Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 Mar 2017 22:34:02 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r315090 - head/sys/dev/uart
Message-ID:  <201703112234.v2BMY2Ou095969@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sat Mar 11 22:34:02 2017
New Revision: 315090
URL: https://svnweb.freebsd.org/changeset/base/315090

Log:
  Extend the pl011 small-fifos fix to other SoCs that indicate rev 5
  hardware but lack the larger fifos rev 5 hardware should have.
  
  The linux world (where our FDT data comes from) solved this by adding
  a new property to pl011 nodes, "arm,primecell-periphid".  When this
  property is present, its values override the values in the hardware
  periphid registers.  For pl011 rev 5 hardware with small fifos, they
  override the id so that it appears to be rev 4 hardware.
  
  The driver now uses the new property when present.  It also continues
  to check the device compat string, to handle older fdt data that may
  still be in use on existing systems (on RPi systems it is common to
  update system software without updating fdt data which is part of the
  boot firmware).
  
  Reviewed by:	imp

Modified:
  head/sys/dev/uart/uart_dev_pl011.c

Modified: head/sys/dev/uart/uart_dev_pl011.c
==============================================================================
--- head/sys/dev/uart/uart_dev_pl011.c	Sat Mar 11 22:22:51 2017	(r315089)
+++ head/sys/dev/uart/uart_dev_pl011.c	Sat Mar 11 22:34:02 2017	(r315090)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/uart/uart_cpu.h>
 #ifdef FDT
 #include <dev/uart/uart_cpu_fdt.h>
+#include <dev/ofw/ofw_bus.h>
 #endif
 #include <dev/uart/uart_bus.h>
 #include "uart_if.h"
@@ -449,25 +450,36 @@ static int
 uart_pl011_bus_probe(struct uart_softc *sc)
 {
 	uint8_t hwrev;
-	bool is_bcm2835;
-
-	device_set_desc(sc->sc_dev, "PrimeCell UART (PL011)");
+#ifdef FDT
+	pcell_t node;
+	uint32_t periphid;
 
 	/*
 	 * The FIFO sizes vary depending on hardware; rev 2 and below have 16
-	 * byte FIFOs, rev 3 and up are 32 byte.  We get a bit of drama, as
-	 * always, with the bcm2835 (rpi), which claims to be rev 3, but has 16
-	 * byte FIFOs.  We check for both the old freebsd-historic and the
-	 * proper bindings-defined compatible strings for bcm2835.
+	 * byte FIFOs, rev 3 and up are 32 byte.  The hardware rev is in the
+	 * primecell periphid register, but we get a bit of drama, as always,
+	 * with the bcm2835 (rpi), which claims to be rev 3, but has 16 byte
+	 * FIFOs.  We check for both the old freebsd-historic and the proper
+	 * bindings-defined compatible strings for bcm2835, and also check the
+	 * workaround the linux drivers use for rpi3, which is to override the
+	 * primecell periphid register value with a property.
 	 */
-#ifdef FDT
-	is_bcm2835 = ofw_bus_is_compatible(sc->sc_dev, "brcm,bcm2835-pl011") ||
-	    ofw_bus_is_compatible(sc->sc_dev, "broadcom,bcm2835-uart");
+	if (ofw_bus_is_compatible(sc->sc_dev, "brcm,bcm2835-pl011") ||
+	    ofw_bus_is_compatible(sc->sc_dev, "broadcom,bcm2835-uart")) {
+		hwrev = 2;
+	} else {
+		node = ofw_bus_get_node(sc->sc_dev);
+		if (OF_getencprop(node, "arm,primecell-periphid", &periphid,
+		    sizeof(periphid)) > 0) {
+			hwrev = (periphid >> 20) & 0x0f;
+		} else {
+			hwrev = __uart_getreg(&sc->sc_bas, UART_PIDREG_2) >> 4;
+		}
+	}
 #else
-	is_bcm2835 = false;
-#endif
 	hwrev = __uart_getreg(&sc->sc_bas, UART_PIDREG_2) >> 4;
-	if (hwrev <= 2 || is_bcm2835) {
+#endif
+	if (hwrev <= 2) {
 		sc->sc_rxfifosz = FIFO_RX_SIZE_R2;
 		sc->sc_txfifosz = FIFO_TX_SIZE_R2;
 	} else {
@@ -475,6 +487,8 @@ uart_pl011_bus_probe(struct uart_softc *
 		sc->sc_txfifosz = FIFO_TX_SIZE_R3;
 	}
 
+	device_set_desc(sc->sc_dev, "PrimeCell UART (PL011)");
+
 	return (0);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703112234.v2BMY2Ou095969>