diff options
author | landonf <landonf@FreeBSD.org> | 2016-06-04 19:58:01 +0000 |
---|---|---|
committer | landonf <landonf@FreeBSD.org> | 2016-06-04 19:58:01 +0000 |
commit | e62e1c44622d4598d700c7a031e1b7d7feeb5a5a (patch) | |
tree | 6002f4835ea932547ba68daf77cf7c8a79d020e4 /sys/dev/bhnd/cores/chipc/chipc.c | |
parent | 8c895dab58ab61d3ed5ab876c7254df5894523fe (diff) | |
download | FreeBSD-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.c | 133 |
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), |