summaryrefslogtreecommitdiffstats
path: root/sys/dev/bhnd/cores/chipc/chipc.c
diff options
context:
space:
mode:
authorlandonf <landonf@FreeBSD.org>2016-06-04 19:58:01 +0000
committerlandonf <landonf@FreeBSD.org>2016-06-04 19:58:01 +0000
commite62e1c44622d4598d700c7a031e1b7d7feeb5a5a (patch)
tree6002f4835ea932547ba68daf77cf7c8a79d020e4 /sys/dev/bhnd/cores/chipc/chipc.c
parent8c895dab58ab61d3ed5ab876c7254df5894523fe (diff)
downloadFreeBSD-src-e62e1c44622d4598d700c7a031e1b7d7feeb5a5a.zip
FreeBSD-src-e62e1c44622d4598d700c7a031e1b7d7feeb5a5a.tar.gz
bhnd(4): support IPX OTP NVRAM/SPROM data source
Add support for fetching SPROM data from OTP on chipsets with an IPX OTP controller (including the BCM43225). This integrates the NVRAM data source into the chipc_caps capability structure, and adds a sprom_offset field that can be used with OTP to locate the SPROM image data (found within the general use region, H/W subregion). This also removes one of two duplicate parse error messages reported by both the bhnd_sprom driver and the underlying SPROM parsing API. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D6729
Diffstat (limited to 'sys/dev/bhnd/cores/chipc/chipc.c')
-rw-r--r--sys/dev/bhnd/cores/chipc/chipc.c133
1 files changed, 82 insertions, 51 deletions
diff --git a/sys/dev/bhnd/cores/chipc/chipc.c b/sys/dev/bhnd/cores/chipc/chipc.c
index 2de0dc8..b30cec1 100644
--- a/sys/dev/bhnd/cores/chipc/chipc.c
+++ b/sys/dev/bhnd/cores/chipc/chipc.c
@@ -91,10 +91,18 @@ static const struct bhnd_device chipc_devices[] = {
/* Device quirks table */
static struct bhnd_device_quirk chipc_quirks[] = {
- /* core revision quirks */
+ /* HND OTP controller revisions */
+ BHND_CORE_QUIRK (HWREV_EQ (12), CHIPC_QUIRK_OTP_HND), /* (?) */
+ BHND_CORE_QUIRK (HWREV_EQ (17), CHIPC_QUIRK_OTP_HND), /* BCM4311 */
+ BHND_CORE_QUIRK (HWREV_EQ (22), CHIPC_QUIRK_OTP_HND), /* BCM4312 */
+
+ /* IPX OTP controller revisions */
+ BHND_CORE_QUIRK (HWREV_EQ (21), CHIPC_QUIRK_OTP_IPX),
+ BHND_CORE_QUIRK (HWREV_GTE(23), CHIPC_QUIRK_OTP_IPX),
+
BHND_CORE_QUIRK (HWREV_GTE(32), CHIPC_QUIRK_SUPPORTS_SPROM),
BHND_CORE_QUIRK (HWREV_GTE(35), CHIPC_QUIRK_SUPPORTS_CAP_EXT),
- BHND_CORE_QUIRK (HWREV_GTE(49), CHIPC_QUIRK_IPX_OTPLAYOUT_SIZE),
+ BHND_CORE_QUIRK (HWREV_GTE(49), CHIPC_QUIRK_IPX_OTPL_SIZE),
/* 4706 variant quirks */
BHND_CORE_QUIRK (HWREV_EQ (38), CHIPC_QUIRK_4706_NFLASH), /* BCM5357? */
@@ -159,10 +167,11 @@ static int chipc_try_activate_resource(
int type, int rid, struct resource *r,
bool req_direct);
+static bhnd_nvram_src chipc_find_nvram_src(struct chipc_softc *sc,
+ struct chipc_caps *caps);
static int chipc_read_caps(struct chipc_softc *sc,
struct chipc_caps *caps);
-static bhnd_nvram_src_t chipc_nvram_identify(struct chipc_softc *sc);
static bool chipc_should_enable_sprom(
struct chipc_softc *sc);
@@ -265,9 +274,6 @@ chipc_attach(device_t dev)
if (bootverbose)
chipc_print_caps(sc->dev, &sc->caps);
- /* Identify NVRAM source */
- sc->nvram_src = chipc_nvram_identify(sc);
-
/* Probe and attach children */
bus_generic_probe(dev);
if ((error = bus_generic_attach(dev)))
@@ -305,6 +311,60 @@ chipc_detach(device_t dev)
return (0);
}
+/**
+ * Determine the NVRAM data source for this device.
+ *
+ * The SPROM, OTP, and flash capability flags must be fully populated in
+ * @p caps.
+ *
+ * @param sc chipc driver state.
+ * @param caps capability flags to be used to derive NVRAM configuration.
+ */
+static bhnd_nvram_src
+chipc_find_nvram_src(struct chipc_softc *sc, struct chipc_caps *caps)
+{
+ uint32_t otp_st, srom_ctrl;
+
+ /* Very early devices vend SPROM/OTP/CIS (if at all) via the
+ * host bridge interface instead of ChipCommon. */
+ if (!CHIPC_QUIRK(sc, SUPPORTS_SPROM))
+ return (BHND_NVRAM_SRC_UNKNOWN);
+
+ /*
+ * Later chipset revisions standardized the SPROM capability flags and
+ * register interfaces.
+ *
+ * We check for hardware presence in order of precedence. For example,
+ * SPROM is is always used in preference to internal OTP if found.
+ */
+ if (caps->sprom) {
+ srom_ctrl = bhnd_bus_read_4(sc->core, CHIPC_SPROM_CTRL);
+ if (srom_ctrl & CHIPC_SRC_PRESENT)
+ return (BHND_NVRAM_SRC_SPROM);
+ }
+
+ /* Check for programmed OTP H/W subregion (contains SROM data) */
+ if (CHIPC_QUIRK(sc, SUPPORTS_OTP) && caps->otp_size > 0) {
+ /* TODO: need access to HND-OTP device */
+ if (!CHIPC_QUIRK(sc, OTP_HND)) {
+ device_printf(sc->dev,
+ "NVRAM unavailable: unsupported OTP controller.\n");
+ return (BHND_NVRAM_SRC_UNKNOWN);
+ }
+
+ otp_st = bhnd_bus_read_4(sc->core, CHIPC_OTPST);
+ if (otp_st & CHIPC_OTPS_GUP_HW)
+ return (BHND_NVRAM_SRC_OTP);
+ }
+
+ /* Check for flash */
+ if (caps->flash_type != CHIPC_FLASH_NONE)
+ return (BHND_NVRAM_SRC_FLASH);
+
+ /* No NVRAM hardware capability declared */
+ return (BHND_NVRAM_SRC_UNKNOWN);
+}
+
/* Read and parse chipc capabilities */
static int
chipc_read_caps(struct chipc_softc *sc, struct chipc_caps *caps)
@@ -342,7 +402,7 @@ chipc_read_caps(struct chipc_softc *sc, struct chipc_caps *caps)
caps->aob = CHIPC_GET_FLAG(cap_ext_reg, CHIPC_CAP2_AOB);
/* Fetch OTP size for later IPX controller revisions */
- if (CHIPC_QUIRK(sc, IPX_OTPLAYOUT_SIZE)) {
+ if (CHIPC_QUIRK(sc, IPX_OTPL_SIZE)) {
regval = bhnd_bus_read_4(sc->core, CHIPC_OTPLAYOUT);
caps->otp_size = CHIPC_GET_BITS(regval, CHIPC_OTPL_SIZE);
}
@@ -384,47 +444,26 @@ chipc_read_caps(struct chipc_softc *sc, struct chipc_caps *caps)
caps->flash_type = CHIPC_NFLASH_4706;
}
- return (0);
-}
-
-/**
- * Determine the NVRAM data source for this device.
- *
- * @param sc chipc driver state.
- */
-static bhnd_nvram_src_t
-chipc_nvram_identify(struct chipc_softc *sc)
-{
- uint32_t srom_ctrl;
- /* Very early devices vend SPROM/OTP/CIS (if at all) via the
- * host bridge interface instead of ChipCommon. */
- if (!CHIPC_QUIRK(sc, SUPPORTS_SPROM))
- return (BHND_NVRAM_SRC_UNKNOWN);
+ /* Determine NVRAM source. Must occur after the SPROM/OTP/flash
+ * capability flags have been populated. */
+ caps->nvram_src = chipc_find_nvram_src(sc, caps);
- /*
- * Later chipset revisions standardized the SPROM capability flags and
- * register interfaces.
- *
- * We check for hardware presence in order of precedence. For example,
- * SPROM is is always used in preference to internal OTP if found.
- */
- if (CHIPC_CAP(sc, sprom)) {
- srom_ctrl = bhnd_bus_read_4(sc->core, CHIPC_SPROM_CTRL);
- if (srom_ctrl & CHIPC_SRC_PRESENT)
- return (BHND_NVRAM_SRC_SPROM);
- }
+ /* Determine the SPROM offset within OTP (if any). SPROM-formatted
+ * data is placed within the OTP general use region. */
+ caps->sprom_offset = 0;
+ if (caps->nvram_src == BHND_NVRAM_SRC_OTP) {
+ CHIPC_ASSERT_QUIRK(sc, OTP_IPX);
- /* Check for OTP */
- if (CHIPC_CAP(sc, otp_size) != 0)
- return (BHND_NVRAM_SRC_OTP);
+ /* Bit offset to GUP HW subregion containing SPROM data */
+ regval = bhnd_bus_read_4(sc->core, CHIPC_OTPLAYOUT);
+ caps->sprom_offset = CHIPC_GET_BITS(regval, CHIPC_OTPL_GUP);
- /* Check for flash */
- if (CHIPC_CAP(sc, flash_type) != CHIPC_FLASH_NONE)
- return (BHND_NVRAM_SRC_FLASH);
+ /* Convert to bytes */
+ caps->sprom_offset /= 8;
+ }
- /* No NVRAM hardware capability declared */
- return (BHND_NVRAM_SRC_UNKNOWN);
+ return (0);
}
static int
@@ -1284,13 +1323,6 @@ finished:
CHIPC_UNLOCK(sc);
}
-static bhnd_nvram_src_t
-chipc_nvram_src(device_t dev)
-{
- struct chipc_softc *sc = device_get_softc(dev);
- return (sc->nvram_src);
-}
-
static void
chipc_write_chipctrl(device_t dev, uint32_t value, uint32_t mask)
{
@@ -1363,7 +1395,6 @@ static device_method_t chipc_methods[] = {
DEVMETHOD(bhnd_bus_activate_resource, chipc_activate_bhnd_resource),
/* ChipCommon interface */
- DEVMETHOD(bhnd_chipc_nvram_src, chipc_nvram_src),
DEVMETHOD(bhnd_chipc_write_chipctrl, chipc_write_chipctrl),
DEVMETHOD(bhnd_chipc_enable_sprom, chipc_enable_sprom_pins),
DEVMETHOD(bhnd_chipc_disable_sprom, chipc_disable_sprom_pins),
OpenPOWER on IntegriCloud