Index: head/sys/dev/bhnd/bcma/bcma_bhndb.c =================================================================== --- head/sys/dev/bhnd/bcma/bcma_bhndb.c +++ head/sys/dev/bhnd/bcma/bcma_bhndb.c @@ -166,6 +166,20 @@ return (0); } +static int +bcma_bhndb_read_board_info(device_t dev, device_t child, + struct bhnd_board_info *info) +{ + int error; + + /* Initialize with NVRAM-derived values */ + if ((error = bhnd_bus_generic_read_board_info(dev, child, info))) + return (error); + + /* Let the bridge fill in any additional data */ + return (BHNDB_POPULATE_BOARD_INFO(device_get_parent(dev), dev, info)); +} + static device_method_t bcma_bhndb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bcma_bhndb_probe), @@ -175,6 +189,9 @@ DEVMETHOD(bus_suspend_child, bcma_bhndb_suspend_child), DEVMETHOD(bus_resume_child, bcma_bhndb_resume_child), + /* BHND interface */ + DEVMETHOD(bhnd_bus_read_board_info, bcma_bhndb_read_board_info), + DEVMETHOD_END }; Index: head/sys/dev/bhnd/bhnd.h =================================================================== --- head/sys/dev/bhnd/bhnd.h +++ head/sys/dev/bhnd/bhnd.h @@ -110,6 +110,34 @@ #undef BHND_ACCESSOR /** + * A bhnd(4) board descriptor. + */ +struct bhnd_board_info { + uint16_t board_vendor; /**< PCI-SIG vendor ID (even on non-PCI + * devices). + * + * On PCI devices, this will generally + * be the subsystem vendor ID, but the + * value may be overridden in device + * NVRAM. + */ + uint16_t board_type; /**< Board type (See BHND_BOARD_*) + * + * On PCI devices, this will generally + * be the subsystem device ID, but the + * value may be overridden in device + * NVRAM. + */ + uint16_t board_rev; /**< Board revision. */ + uint8_t board_srom_rev; /**< Board SROM format revision */ + + uint32_t board_flags; /**< Board flags (see BHND_BFL_*) */ + uint32_t board_flags2; /**< Board flags 2 (see BHND_BFL2_*) */ + uint32_t board_flags3; /**< Board flags 3 (see BHND_BFL3_*) */ +}; + + +/** * Chip Identification * * This is read from the ChipCommon ID register; on earlier bhnd(4) devices @@ -131,23 +159,10 @@ }; /** -* A bhnd(4) bus resource. -* -* This provides an abstract interface to per-core resources that may require -* bus-level remapping of address windows prior to access. -*/ -struct bhnd_resource { - struct resource *res; /**< the system resource. */ - bool direct; /**< false if the resource requires - * bus window remapping before it - * is MMIO accessible. */ -}; - -/** * A bhnd(4) core descriptor. */ struct bhnd_core_info { - uint16_t vendor; /**< vendor */ + uint16_t vendor; /**< JEP-106 vendor (BHND_MFGID_*) */ uint16_t device; /**< device */ uint16_t hwrev; /**< hardware revision */ u_int core_idx; /**< bus-assigned core index */ @@ -165,6 +180,19 @@ to match on any revision. */ }; +/** +* A bhnd(4) bus resource. +* +* This provides an abstract interface to per-core resources that may require +* bus-level remapping of address windows prior to access. +*/ +struct bhnd_resource { + struct resource *res; /**< the system resource. */ + bool direct; /**< false if the resource requires + * bus window remapping before it + * is MMIO accessible. */ +}; + /** * Wildcard hardware revision match descriptor. */ @@ -233,31 +261,51 @@ .unit = -1 \ } -/** A chipset match descriptor. */ +/** + * A chipset match descriptor. + * + * @warning Matching on board/nvram attributes relies on NVRAM access, and will + * fail if a valid NVRAM device cannot be found, or is not yet attached. + */ struct bhnd_chip_match { /** Select fields to be matched */ - uint8_t + uint16_t match_id:1, match_rev:1, match_pkg:1, - match_flags_unused:5; + match_bvendor:1, + match_btype:1, + match_brev:1, + match_srom_rev:1, + match_any:1, + match_flags_unused:8; uint16_t chip_id; /**< required chip id */ struct bhnd_hwrev_match chip_rev; /**< matching chip revisions */ uint8_t chip_pkg; /**< required package */ + + uint16_t board_vendor; /**< required board vendor */ + uint16_t board_type; /**< required board type */ + struct bhnd_hwrev_match board_rev; /**< matching board revisions */ + + struct bhnd_hwrev_match board_srom_rev; /**< matching board srom revisions */ }; #define BHND_CHIP_MATCH_ANY \ - { .match_id = 0, .match_rev = 0, .match_pkg = 0 } + { .match_any = 1 } #define BHND_CHIP_MATCH_IS_ANY(_m) \ - ((_m)->match_id == 0 && (_m)->match_rev == 0 && (_m)->match_pkg == 0) + ((_m)->match_any == 1) + +#define BHND_CHIP_MATCH_REQ_BOARD_INFO(_m) \ + ((_m)->match_srom_rev || (_m)->match_bvendor || \ + (_m)->match_btype || (_m)->match_brev) /** Set the required chip ID within a bhnd_chip_match instance */ #define BHND_CHIP_ID(_cid) \ .match_id = 1, .chip_id = BHND_CHIPID_BCM ## _cid -/** Set the required revision range within a bhnd_chip_match instance */ +/** Set the required chip revision range within a bhnd_chip_match instance */ #define BHND_CHIP_REV(_rev) \ .match_rev = 1, .chip_rev = BHND_ ## _rev @@ -265,6 +313,31 @@ #define BHND_CHIP_PKG(_pkg) \ .match_pkg = 1, .chip_pkg = BHND_PKGID_BCM ## _pkg +/** Set the required board vendor within a bhnd_chip_match instance */ +#define BHND_CHIP_BVENDOR(_vend) \ + .match_bvendor = 1, .board_vendor = _vend + +/** Set the required board type within a bhnd_chip_match instance */ +#define BHND_CHIP_BT(_btype) \ + .match_btype = 1, .board_type = BHND_BOARD_BCM ## _btype + +/** Set the required SROM revision range within a bhnd_chip_match instance */ +#define BHND_CHIP_SROMREV(_rev) \ + .match_srom_rev = 1, .board_srom_rev = BHND_ ## _rev + +/** Set the required board revision range within a bhnd_chip_match instance */ +#define BHND_CHIP_BREV(_rev) \ + .match_brev = 1, .board_rev = BHND_ ## _rev + +/** Set the required board vendor and type within a bhnd_chip_match instance */ +#define BHND_CHIP_BVT(_vend, _type) \ + BHND_CHIP_BVEND(_vend), BHND_CHIP_BTYPE(_type) + +/** Set the required board vendor, type, and revision within a bhnd_chip_match + * instance */ +#define BHND_CHIP_BVTR(_vend, _type, _rev) \ + BHND_CHIP_BVT(_vend, _type), BHND_CHIP_BREV(_rev) + /** Set the required chip and package ID within a bhnd_chip_match instance */ #define BHND_CHIP_IP(_cid, _pkg) \ BHND_CHIP_ID(_cid), BHND_CHIP_PKG(_pkg) @@ -314,23 +387,29 @@ const struct bhnd_core_match core; /**< core match descriptor */ const char *desc; /**< device description, or NULL. */ const struct bhnd_device_quirk *quirks_table; /**< quirks table for this device, or NULL */ + const struct bhnd_chip_quirk *chip_quirks_table; /**< chipset-specific quirks for this device, or NULL */ uint32_t device_flags; /**< required BHND_DF_* flags */ }; -#define _BHND_DEVICE(_vendor, _device, _desc, _quirks, _flags, ...) \ - { BHND_CORE_MATCH(BHND_MFGID_ ## _vendor, BHND_COREID_ ## _device, \ - BHND_HWREV_ANY), _desc, _quirks, _flags } - -#define BHND_MIPS_DEVICE(_device, _desc, _quirks, ...) \ - _BHND_DEVICE(MIPS, _device, _desc, _quirks, ## __VA_ARGS__, 0) - -#define BHND_ARM_DEVICE(_device, _desc, _quirks, ...) \ - _BHND_DEVICE(ARM, _device, _desc, _quirks, ## __VA_ARGS__, 0) +#define _BHND_DEVICE(_vendor, _device, _desc, _quirks, _chip_quirks, \ + _flags, ...) \ + { BHND_CORE_MATCH(BHND_MFGID_ ## _vendor, \ + BHND_COREID_ ## _device, BHND_HWREV_ANY), _desc, _quirks, \ + _chip_quirks, _flags } + +#define BHND_MIPS_DEVICE(_device, _desc, _quirks, _chip_quirks, ...) \ + _BHND_DEVICE(MIPS, _device, _desc, _quirks, _chip_quirks, \ + ## __VA_ARGS__, 0) + +#define BHND_ARM_DEVICE(_device, _desc, _quirks, _chip_quirks, ...) \ + _BHND_DEVICE(ARM, _device, _desc, _quirks, _chip_quirks, \ + ## __VA_ARGS__, 0) + +#define BHND_DEVICE(_device, _desc, _quirks, _chip_quirks, ...) \ + _BHND_DEVICE(BCM, _device, _desc, _quirks, _chip_quirks, \ + ## __VA_ARGS__, 0) -#define BHND_DEVICE(_device, _desc, _quirks, ...) \ - _BHND_DEVICE(BCM, _device, _desc, _quirks, ## __VA_ARGS__, 0) - -#define BHND_DEVICE_END { BHND_CORE_MATCH_ANY, NULL, NULL, 0 } +#define BHND_DEVICE_END { BHND_CORE_MATCH_ANY, NULL, NULL, NULL, 0 } const char *bhnd_vendor_name(uint16_t vendor); const char *bhnd_port_type_name(bhnd_port_type port_type); @@ -365,6 +444,7 @@ bool bhnd_chip_matches( const struct bhnd_chipid *chipid, + const struct bhnd_board_info *binfo, const struct bhnd_chip_match *desc); bool bhnd_hwrev_matches(uint16_t hwrev, @@ -418,6 +498,12 @@ void *buf, size_t *size); const struct bhnd_chipid *bhnd_bus_generic_get_chipid(device_t dev, device_t child); +int bhnd_bus_generic_read_board_info(device_t dev, + device_t child, + struct bhnd_board_info *info); +int bhnd_bus_generic_get_nvram_var(device_t dev, + device_t child, const char *name, + void *buf, size_t *size); struct bhnd_resource *bhnd_bus_generic_alloc_resource (device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, @@ -472,6 +558,28 @@ }; /** + * Attempt to read the BHND board identification from the bhnd bus. + * + * This relies on NVRAM access, and will fail if a valid NVRAM device cannot + * be found, or is not yet attached. + * + * @param dev The parent of @p child. + * @param child The bhnd device requesting board info. + * @param[out] info On success, will be populated with the bhnd(4) device's + * board information. + * + * @retval 0 success + * @retval ENODEV No valid NVRAM source could be found. + * @retval non-zero If reading @p name otherwise fails, a regular unix + * error code will be returned. + */ +static inline int +bhnd_read_board_info(device_t dev, struct bhnd_board_info *info) +{ + return (BHND_BUS_READ_BOARD_INFO(device_get_parent(dev), dev, info)); +} + +/** * Determine an NVRAM variable's expected size. * * @param dev A bhnd bus child device. @@ -480,6 +588,7 @@ * * @retval 0 success * @retval ENOENT The requested variable was not found. + * @retval ENODEV No valid NVRAM source could be found. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ @@ -502,6 +611,7 @@ * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval EINVAL If @p len does not match the actual variable size. + * @retval ENODEV No valid NVRAM source could be found. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ Index: head/sys/dev/bhnd/bhnd.c =================================================================== --- head/sys/dev/bhnd/bhnd.c +++ head/sys/dev/bhnd/bhnd.c @@ -58,11 +58,6 @@ #include #include -#include "nvram/bhnd_nvram.h" - -#include "bhnd_chipc_if.h" -#include "bhnd_nvram_if.h" - #include "bhnd.h" #include "bhndvar.h" @@ -85,8 +80,6 @@ { BHND_MFGID_INVALID, BHND_COREID_INVALID, false } }; -static device_t find_nvram_child(device_t dev); - static int compare_ascending_probe_order(const void *lhs, const void *rhs); static int compare_descending_probe_order(const void *lhs, @@ -314,7 +307,9 @@ { switch (bhnd_get_class(child)) { case BHND_DEVCLASS_CC: - return (BHND_PROBE_BUS + BHND_PROBE_ORDER_FIRST); + /* Must be early enough to provide NVRAM access to the + * host bridge */ + return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_FIRST); case BHND_DEVCLASS_CC_B: /* fall through */ @@ -381,68 +376,6 @@ } /** - * Find an NVRAM child device on @p dev, if any. - * - * @retval device_t An NVRAM device. - * @retval NULL If no NVRAM device is found. - */ -static device_t -find_nvram_child(device_t dev) -{ - device_t chipc, nvram; - - /* Look for a directly-attached NVRAM child */ - nvram = device_find_child(dev, "bhnd_nvram", 0); - if (nvram != NULL) - return (nvram); - - /* Remaining checks are only applicable when searching a bhnd(4) - * bus. */ - if (device_get_devclass(dev) != bhnd_devclass) - return (NULL); - - /* Look for a ChipCommon device */ - if ((chipc = bhnd_find_child(dev, BHND_DEVCLASS_CC, -1)) != NULL) { - bhnd_nvram_src_t src; - - /* Query the NVRAM source and determine whether it's - * accessible via the ChipCommon device */ - src = BHND_CHIPC_NVRAM_SRC(chipc); - if (BHND_NVRAM_SRC_CC(src)) - return (chipc); - } - - /* Not found */ - return (NULL); -} - -/** - * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR(). - * - * This implementation searches @p dev for a usable NVRAM child device: - * - The first child device implementing the bhnd_nvram devclass is - * returned, otherwise - * - If @p dev is a bhnd(4) bus, a ChipCommon core that advertises an - * attached NVRAM source. - * - * If no usable child device is found on @p dev, the request is delegated to - * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. - */ -static int -bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name, - void *buf, size_t *size) -{ - device_t nvram; - - /* Try to find an NVRAM device applicable to @p child */ - if ((nvram = find_nvram_child(dev)) == NULL) - return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, - name, buf, size)); - - return BHND_NVRAM_GETVAR(nvram, name, buf, size); -} - -/** * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD(). * * This implementation requests the device's struct resource_list via @@ -693,7 +626,7 @@ DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order), DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid), DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled), - DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var), + DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_bus_generic_get_nvram_var), DEVMETHOD(bhnd_bus_read_1, bhnd_read_1), DEVMETHOD(bhnd_bus_read_2, bhnd_read_2), DEVMETHOD(bhnd_bus_read_4, bhnd_read_4), Index: head/sys/dev/bhnd/bhnd_bus_if.m =================================================================== --- head/sys/dev/bhnd/bhnd_bus_if.m +++ head/sys/dev/bhnd/bhnd_bus_if.m @@ -38,10 +38,10 @@ HEADER { /* forward declarations */ + struct bhnd_board_info; struct bhnd_core_info; struct bhnd_chipid; struct bhnd_resource; - struct bhnd_bus_ctx; } CODE { @@ -54,7 +54,14 @@ { panic("bhnd_bus_get_chipid unimplemented"); } - + + static int + bhnd_bus_null_read_board_info(device_t dev, device_t child, + struct bhnd_board_info *info) + { + panic("bhnd_bus_read_boardinfo unimplemented"); + } + static device_t bhnd_bus_null_find_hostb_device(device_t dev) { @@ -99,7 +106,7 @@ bhnd_bus_null_get_nvram_var(device_t dev, device_t child, const char *name, void *buf, size_t *size) { - return (ENOENT); + return (ENODEV); } } @@ -177,6 +184,28 @@ } DEFAULT bhnd_bus_null_get_chipid; /** + * Attempt to read the BHND board identification from the parent bus. + * + * This relies on NVRAM access, and will fail if a valid NVRAM device cannot + * be found, or is not yet attached. + * + * @param dev The parent of @p child. + * @param child The bhnd device requesting board info. + * @param[out] info On success, will be populated with the bhnd(4) device's + * board information. + * + * @retval 0 success + * @retval ENODEV No valid NVRAM source could be found. + * @retval non-zero If reading @p name otherwise fails, a regular unix + * error code will be returned. + */ +METHOD int read_board_info { + device_t dev; + device_t child; + struct bhnd_board_info *info; +} DEFAULT bhnd_bus_null_read_board_info; + +/** * Reset the device's hardware core. * * @param dev The parent of @p child. @@ -400,6 +429,7 @@ * @retval ENOENT The requested variable was not found. * @retval ENOMEM If @p buf is non-NULL and a buffer of @p size is too * small to hold the requested value. + * @retval ENODEV No valid NVRAM source could be found. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ Index: head/sys/dev/bhnd/bhnd_ids.h =================================================================== --- head/sys/dev/bhnd/bhnd_ids.h +++ head/sys/dev/bhnd/bhnd_ids.h @@ -1,10 +1,12 @@ /*- - * Copyright (C) 1999-2013, Broadcom Corporation + * Copyright (c) 2015-2016 Landon Fuller + * Copyright (c) 1999-2015, Broadcom Corporation * * This file is derived from the bcmdevs.h header contributed by Broadcom - * to Android's bcmdhd driver module, and the hndsoc.h header distributed with - * with Broadcom's initial brcm80211 Linux driver release, as contributed to - * the Linux staging repository. + * to Android's bcmdhd driver module, later revisions of bcmdevs.h distributed + * with the dd-wrt project, and the hndsoc.h header distributed with Broadcom's + * initial brcm80211 Linux driver release as contributed to the Linux staging + * repository. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,8 +20,6 @@ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: bcmdevs.h 387183 2013-02-24 07:42:07Z $ - * * $FreeBSD$ */ @@ -669,22 +669,22 @@ /* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ -#define BHND_BOARD_GPIO_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */ -#define BHND_BOARD_GPIO_BTC3W_OUT 0x020 /* bit 5 is TX_CONF */ -#define BHND_BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistence Input */ -#define BHND_BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistence Out */ -#define BHND_BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistence Input */ -#define BHND_BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistence Out */ -#define BHND_BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ -#define BHND_BOARD_GPIO_12 0x1000 /* gpio 12 */ -#define BHND_BOARD_GPIO_13 0x2000 /* gpio 13 */ -#define BHND_BOARD_GPIO_BTC4_IN 0x0800 /* gpio 11, coex4, in */ -#define BHND_BOARD_GPIO_BTC4_BT 0x2000 /* gpio 12, coex4, bt active */ -#define BHND_BOARD_GPIO_BTC4_STAT 0x4000 /* gpio 14, coex4, status */ -#define BHND_BOARD_GPIO_BTC4_WLAN 0x8000 /* gpio 15, coex4, wlan active */ -#define BHND_BOARD_GPIO_1_WLAN_PWR 0x02 /* throttle WLAN power on X21 board */ -#define BHND_BOARD_GPIO_3_WLAN_PWR 0x08 /* throttle WLAN power on X28 board */ -#define BHND_BOARD_GPIO_4_WLAN_PWR 0x10 /* throttle WLAN power on X19 board */ +#define BHND_GPIO_BOARD_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */ +#define BHND_GPIO_BOARD_BTC3W_OUT 0x020 /* bit 5 is TX_CONF */ +#define BHND_GPIO_BOARD_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistence Input */ +#define BHND_GPIO_BOARD_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistence Out */ +#define BHND_GPIO_BOARD_BTC_IN 0x080 /* bit 7 is BT Coexistence Input */ +#define BHND_GPIO_BOARD_BTC_OUT 0x100 /* bit 8 is BT Coexistence Out */ +#define BHND_GPIO_BOARD_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ +#define BHND_GPIO_BOARD_12 0x1000 /* gpio 12 */ +#define BHND_GPIO_BOARD_13 0x2000 /* gpio 13 */ +#define BHND_GPIO_BOARD_BTC4_IN 0x0800 /* gpio 11, coex4, in */ +#define BHND_GPIO_BOARD_BTC4_BT 0x2000 /* gpio 12, coex4, bt active */ +#define BHND_GPIO_BOARD_BTC4_STAT 0x4000 /* gpio 14, coex4, status */ +#define BHND_GPIO_BOARD_BTC4_WLAN 0x8000 /* gpio 15, coex4, wlan active */ +#define BHND_GPIO_BOARD_1_WLAN_PWR 0x02 /* throttle WLAN power on X21 board */ +#define BHND_GPIO_BOARD_3_WLAN_PWR 0x08 /* throttle WLAN power on X28 board */ +#define BHND_GPIO_BOARD_4_WLAN_PWR 0x10 /* throttle WLAN power on X19 board */ #define BHND_GPIO_BTC4W_OUT_4312 0x010 /* bit 4 is BT_IODISABLE */ #define BHND_GPIO_BTC4W_OUT_43224 0x020 /* bit 5 is BT_IODISABLE */ @@ -700,11 +700,385 @@ #define BHND_CHIPC_MIN_SLOW_CLK 32 /* us Slow clock period */ #define BHND_CHIPC_XTAL_ON_DELAY 1000 /* us crystal power-on delay */ +/* Board Types */ +#define BHND_BOARD_BU4710 0x0400 +#define BHND_BOARD_VSIM4710 0x0401 +#define BHND_BOARD_QT4710 0x0402 + +#define BHND_BOARD_BU4309 0x040a +#define BHND_BOARD_BCM94309CB 0x040b +#define BHND_BOARD_BCM94309MP 0x040c +#define BHND_BOARD_BCM4309AP 0x040d + +#define BHND_BOARD_BCM94302MP 0x040e + +#define BHND_BOARD_BU4306 0x0416 +#define BHND_BOARD_BCM94306CB 0x0417 +#define BHND_BOARD_BCM94306MP 0x0418 + +#define BHND_BOARD_BCM94710D 0x041a +#define BHND_BOARD_BCM94710R1 0x041b +#define BHND_BOARD_BCM94710R4 0x041c +#define BHND_BOARD_BCM94710AP 0x041d + +#define BHND_BOARD_BU2050 0x041f + + +#define BHND_BOARD_BCM94309G 0x0421 + +#define BHND_BOARD_BU4704 0x0423 +#define BHND_BOARD_BU4702 0x0424 + +#define BHND_BOARD_BCM94306PC 0x0425 /* pcmcia 3.3v 4306 card */ + + +#define BHND_BOARD_BCM94702MN 0x0428 + +/* BCM4702 1U CompactPCI Board */ +#define BHND_BOARD_BCM94702CPCI 0x0429 + +/* BCM4702 with BCM95380 VLAN Router */ +#define BHND_BOARD_BCM95380RR 0x042a + +/* cb4306 with SiGe PA */ +#define BHND_BOARD_BCM94306CBSG 0x042b + +/* cb4306 with SiGe PA */ +#define BHND_BOARD_PCSG94306 0x042d + +/* bu4704 with sdram */ +#define BHND_BOARD_BU4704SD 0x042e + +/* Dual 11a/11g Router */ +#define BHND_BOARD_BCM94704AGR 0x042f + +/* 11a-only minipci */ +#define BHND_BOARD_BCM94308MP 0x0430 + + + +#define BHND_BOARD_BU4712 0x0444 +#define BHND_BOARD_BU4712SD 0x045d +#define BHND_BOARD_BU4712L 0x045f + +/* BCM4712 boards */ +#define BHND_BOARD_BCM94712AP 0x0445 +#define BHND_BOARD_BCM94712P 0x0446 + +/* BCM4318 boards */ +#define BHND_BOARD_BU4318 0x0447 +#define BHND_BOARD_CB4318 0x0448 +#define BHND_BOARD_MPG4318 0x0449 +#define BHND_BOARD_MP4318 0x044a +#define BHND_BOARD_SD4318 0x044b + +/* BCM4313 boards */ +#define BHND_BOARD_BCM94313BU 0x050f +#define BHND_BOARD_BCM94313HM 0x0510 +#define BHND_BOARD_BCM94313EPA 0x0511 +#define BHND_BOARD_BCM94313HMG 0x051C + +/* BCM63XX boards */ +#define BHND_BOARD_BCM96338 0x6338 +#define BHND_BOARD_BCM96348 0x6348 +#define BHND_BOARD_BCM96358 0x6358 +#define BHND_BOARD_BCM96368 0x6368 + +/* Another mp4306 with SiGe */ +#define BHND_BOARD_BCM94306P 0x044c + +/* mp4303 */ +#define BHND_BOARD_BCM94303MP 0x044e + +/* mpsgh4306 */ +#define BHND_BOARD_BCM94306MPSGH 0x044f + +/* BRCM 4306 w/ Front End Modules */ +#define BHND_BOARD_BCM94306MPM 0x0450 +#define BHND_BOARD_BCM94306MPL 0x0453 + +/* 4712agr */ +#define BHND_BOARD_BCM94712AGR 0x0451 + +/* pcmcia 4303 */ +#define BHND_BOARD_PC4303 0x0454 + +/* 5350K */ +#define BHND_BOARD_BCM95350K 0x0455 + +/* 5350R */ +#define BHND_BOARD_BCM95350R 0x0456 + +/* 4306mplna */ +#define BHND_BOARD_BCM94306MPLNA 0x0457 + +/* 4320 boards */ +#define BHND_BOARD_BU4320 0x0458 +#define BHND_BOARD_BU4320S 0x0459 +#define BHND_BOARD_BCM94320PH 0x045a + +/* 4306mph */ +#define BHND_BOARD_BCM94306MPH 0x045b + +/* 4306pciv */ +#define BHND_BOARD_BCM94306PCIV 0x045c + +#define BHND_BOARD_BU4712SD 0x045d + +#define BHND_BOARD_BCM94320PFLSH 0x045e + +#define BHND_BOARD_BU4712L 0x045f +#define BHND_BOARD_BCM94712LGR 0x0460 +#define BHND_BOARD_BCM94320R 0x0461 + +#define BHND_BOARD_BU5352 0x0462 + +#define BHND_BOARD_BCM94318MPGH 0x0463 + +#define BHND_BOARD_BU4311 0x0464 +#define BHND_BOARD_BCM94311MC 0x0465 +#define BHND_BOARD_BCM94311MCAG 0x0466 + +#define BHND_BOARD_BCM95352GR 0x0467 + +/* bcm95351agr */ +#define BHND_BOARD_BCM95351AGR 0x0470 + +/* bcm94704mpcb */ +#define BHND_BOARD_BCM94704MPCB 0x0472 + +/* 4785 boards */ +#define BHND_BOARD_BU4785 0x0478 + +/* 4321 boards */ +#define BHND_BOARD_BU4321 0x046b +#define BHND_BOARD_BU4321E 0x047c +#define BHND_BOARD_MP4321 0x046c +#define BHND_BOARD_CB2_4321 0x046d +#define BHND_BOARD_CB2_4321_AG 0x0066 +#define BHND_BOARD_MC4321 0x046e + +/* 4328 boards */ +#define BHND_BOARD_BU4328 0x0481 +#define BHND_BOARD_BCM4328SDG 0x0482 +#define BHND_BOARD_BCM4328SDAG 0x0483 +#define BHND_BOARD_BCM4328UG 0x0484 +#define BHND_BOARD_BCM4328UAG 0x0485 +#define BHND_BOARD_BCM4328PC 0x0486 +#define BHND_BOARD_BCM4328CF 0x0487 + +/* 4325 boards */ +#define BHND_BOARD_BCM94325DEVBU 0x0490 +#define BHND_BOARD_BCM94325BGABU 0x0491 + +#define BHND_BOARD_BCM94325SDGWB 0x0492 + +#define BHND_BOARD_BCM94325SDGMDL 0x04aa +#define BHND_BOARD_BCM94325SDGMDL2 0x04c6 +#define BHND_BOARD_BCM94325SDGMDL3 0x04c9 + +#define BHND_BOARD_BCM94325SDABGWBA 0x04e1 + +/* 4322 boards */ +#define BHND_BOARD_BCM94322MC 0x04a4 +#define BHND_BOARD_BCM94322USB 0x04a8 /* dualband */ +#define BHND_BOARD_BCM94322HM 0x04b0 +#define BHND_BOARD_BCM94322USB2D 0x04bf /* single band discrete front end */ + +/* 4312 boards */ +#define BHND_BOARD_BCM4312MCGSG 0x04b5 + +/* 4315 boards */ +#define BHND_BOARD_BCM94315DEVBU 0x04c2 +#define BHND_BOARD_BCM94315USBGP 0x04c7 +#define BHND_BOARD_BCM94315BGABU 0x04ca +#define BHND_BOARD_BCM94315USBGP41 0x04cb + +/* 4319 boards */ +#define BHND_BOARD_BCM94319DEVBU 0X04e5 +#define BHND_BOARD_BCM94319USB 0X04e6 +#define BHND_BOARD_BCM94319SD 0X04e7 + +/* 4716 boards */ +#define BHND_BOARD_BCM94716NR2 0x04cd + +/* 4319 boards */ +#define BHND_BOARD_BCM94319DEVBU 0X04e5 +#define BHND_BOARD_BCM94319USBNP4L 0X04e6 +#define BHND_BOARD_BCM94319WLUSBN4L 0X04e7 +#define BHND_BOARD_BCM94319SDG 0X04ea +#define BHND_BOARD_BCM94319LCUSBSDN4L 0X04eb +#define BHND_BOARD_BCM94319USBB 0x04ee +#define BHND_BOARD_BCM94319LCSDN4L 0X0507 +#define BHND_BOARD_BCM94319LSUSBN4L 0X0508 +#define BHND_BOARD_BCM94319SDNA4L 0X0517 +#define BHND_BOARD_BCM94319SDELNA4L 0X0518 +#define BHND_BOARD_BCM94319SDELNA6L 0X0539 +#define BHND_BOARD_BCM94319ARCADYAN 0X0546 +#define BHND_BOARD_BCM94319WINDSOR 0x0561 +#define BHND_BOARD_BCM94319MLAP 0x0562 +#define BHND_BOARD_BCM94319SDNA 0x058b +#define BHND_BOARD_BCM94319BHEMU3 0x0563 +#define BHND_BOARD_BCM94319SDHMB 0x058c +#define BHND_BOARD_BCM94319SDBREF 0x05a1 +#define BHND_BOARD_BCM94319USBSDB 0x05a2 + +/* 4329 boards */ +#define BHND_BOARD_BCM94329AGB 0X04b9 +#define BHND_BOARD_BCM94329TDKMDL1 0X04ba +#define BHND_BOARD_BCM94329TDKMDL11 0X04fc +#define BHND_BOARD_BCM94329OLYMPICN18 0X04fd +#define BHND_BOARD_BCM94329OLYMPICN90 0X04fe +#define BHND_BOARD_BCM94329OLYMPICN90U 0X050c +#define BHND_BOARD_BCM94329OLYMPICN90M 0X050b +#define BHND_BOARD_BCM94329AGBF 0X04ff +#define BHND_BOARD_BCM94329OLYMPICX17 0X0504 +#define BHND_BOARD_BCM94329OLYMPICX17M 0X050a +#define BHND_BOARD_BCM94329OLYMPICX17U 0X0509 +#define BHND_BOARD_BCM94329OLYMPICUNO 0X0564 +#define BHND_BOARD_BCM94329MOTOROLA 0X0565 +#define BHND_BOARD_BCM94329OLYMPICLOCO 0X0568 + +/* 4336 SDIO board types */ +#define BHND_BOARD_BCM94336SD_WLBGABU 0x0511 +#define BHND_BOARD_BCM94336SD_WLBGAREF 0x0519 +#define BHND_BOARD_BCM94336SDGP 0x0538 +#define BHND_BOARD_BCM94336SDG 0x0519 +#define BHND_BOARD_BCM94336SDGN 0x0538 +#define BHND_BOARD_BCM94336SDGFC 0x056B + +/* 4330 SDIO board types */ +#define BHND_BOARD_BCM94330SDG 0x0528 +#define BHND_BOARD_BCM94330SD_FCBGABU 0x052e +#define BHND_BOARD_BCM94330SD_WLBGABU 0x052f +#define BHND_BOARD_BCM94330SD_FCBGA 0x0530 +#define BHND_BOARD_BCM94330FCSDAGB 0x0532 +#define BHND_BOARD_BCM94330OLYMPICAMG 0x0549 +#define BHND_BOARD_BCM94330OLYMPICAMGEPA 0x054F +#define BHND_BOARD_BCM94330OLYMPICUNO3 0x0551 +#define BHND_BOARD_BCM94330WLSDAGB 0x0547 +#define BHND_BOARD_BCM94330CSPSDAGBB 0x054A + +/* 43224 boards */ +#define BHND_BOARD_BCM943224X21 0x056e +#define BHND_BOARD_BCM943224X21_FCC 0x00d1 +#define BHND_BOARD_BCM943224X21B 0x00e9 +#define BHND_BOARD_BCM943224M93 0x008b +#define BHND_BOARD_BCM943224M93A 0x0090 +#define BHND_BOARD_BCM943224X16 0x0093 +#define BHND_BOARD_BCM94322X9 0x008d +#define BHND_BOARD_BCM94322M35e 0x008e + +/* 43228 Boards */ +#define BHND_BOARD_BCM943228BU8 0x0540 +#define BHND_BOARD_BCM943228BU9 0x0541 +#define BHND_BOARD_BCM943228BU 0x0542 +#define BHND_BOARD_BCM943227HM4L 0x0543 +#define BHND_BOARD_BCM943227HMB 0x0544 +#define BHND_BOARD_BCM943228HM4L 0x0545 +#define BHND_BOARD_BCM943228SD 0x0573 + +/* 43239 Boards */ +#define BHND_BOARD_BCM943239MOD 0x05ac +#define BHND_BOARD_BCM943239REF 0x05aa + +/* 4331 boards */ +#define BHND_BOARD_BCM94331X19 0x00D6 /* X19B */ +#define BHND_BOARD_BCM94331X28 0x00E4 /* X28 */ +#define BHND_BOARD_BCM94331X28B 0x010E /* X28B */ +#define BHND_BOARD_BCM94331PCIEBT3Ax BCM94331X28 +#define BHND_BOARD_BCM94331X12_2G 0x00EC /* X12 2G */ +#define BHND_BOARD_BCM94331X12_5G 0x00ED /* X12 5G */ +#define BHND_BOARD_BCM94331X29B 0x00EF /* X29B */ +#define BHND_BOARD_BCM94331X29D 0x010F /* X29D */ +#define BHND_BOARD_BCM94331CSAX BCM94331X29B +#define BHND_BOARD_BCM94331X19C 0x00F5 /* X19C */ +#define BHND_BOARD_BCM94331X33 0x00F4 /* X33 */ +#define BHND_BOARD_BCM94331BU 0x0523 +#define BHND_BOARD_BCM94331S9BU 0x0524 +#define BHND_BOARD_BCM94331MC 0x0525 +#define BHND_BOARD_BCM94331MCI 0x0526 +#define BHND_BOARD_BCM94331PCIEBT4 0x0527 +#define BHND_BOARD_BCM94331HM 0x0574 +#define BHND_BOARD_BCM94331PCIEDUAL 0x059B +#define BHND_BOARD_BCM94331MCH5 0x05A9 +#define BHND_BOARD_BCM94331CS 0x05C6 +#define BHND_BOARD_BCM94331CD 0x05DA + +/* 4314 Boards */ +#define BHND_BOARD_BCM94314BU 0x05b1 + +/* 53572 Boards */ +#define BHND_BOARD_BCM953572BU 0x058D +#define BHND_BOARD_BCM953572NR2 0x058E +#define BHND_BOARD_BCM947188NR2 0x058F +#define BHND_BOARD_BCM953572SDRNR2 0x0590 + +/* 43236 boards */ +#define BHND_BOARD_BCM943236OLYMPICSULLEY 0x594 +#define BHND_BOARD_BCM943236PREPROTOBLU2O3 0x5b9 +#define BHND_BOARD_BCM943236USBELNA 0x5f8 + +/* 4314 Boards */ +#define BHND_BOARD_BCM94314BUSDIO 0x05c8 +#define BHND_BOARD_BCM94314BGABU 0x05c9 +#define BHND_BOARD_BCM94314HMEPA 0x05ca +#define BHND_BOARD_BCM94314HMEPABK 0x05cb +#define BHND_BOARD_BCM94314SUHMEPA 0x05cc +#define BHND_BOARD_BCM94314SUHM 0x05cd +#define BHND_BOARD_BCM94314HM 0x05d1 + +/* 4334 Boards */ +#define BHND_BOARD_BCM94334FCAGBI 0x05df +#define BHND_BOARD_BCM94334WLAGBI 0x05dd + +/* 4335 Boards */ +#define BHND_BOARD_BCM94335X52 0x0114 + +/* 4345 Boards */ +#define BHND_BOARD_BCM94345 0x0687 + +/* 4360 Boards */ +#define BHND_BOARD_BCM94360X52C 0X0117 +#define BHND_BOARD_BCM94360X52D 0X0137 +#define BHND_BOARD_BCM94360X29C 0X0112 +#define BHND_BOARD_BCM94360X29CP2 0X0134 +#define BHND_BOARD_BCM94360X51 0x0111 +#define BHND_BOARD_BCM94360X51P2 0x0129 +#define BHND_BOARD_BCM94360X51A 0x0135 +#define BHND_BOARD_BCM94360X51B 0x0136 +#define BHND_BOARD_BCM94360CS 0x061B +#define BHND_BOARD_BCM94360J28_D11AC2G 0x0c00 +#define BHND_BOARD_BCM94360J28_D11AC5G 0x0c01 +#define BHND_BOARD_BCM94360USBH5_D11AC5G 0x06aa + +/* 4350 Boards */ +#define BHND_BOARD_BCM94350X52B 0X0116 +#define BHND_BOARD_BCM94350X14 0X0131 + +/* 43217 Boards */ +#define BHND_BOARD_BCM943217BU 0x05d5 +#define BHND_BOARD_BCM943217HM2L 0x05d6 +#define BHND_BOARD_BCM943217HMITR2L 0x05d7 + +/* 43142 Boards */ +#define BHND_BOARD_BCM943142HM 0x05e0 + /* 43341 Boards */ -#define BCM943341WLABGS_SSID 0x062d +#define BHND_BOARD_BCM943341WLABGS 0x062d /* 43342 Boards */ -#define BCM943342FCAGBI_SSID 0x0641 +#define BHND_BOARD_BCM943342FCAGBI 0x0641 + +/* 43602 Boards, unclear yet what boards will be created. */ +#define BHND_BOARD_BCM943602RSVD1 0x06a5 +#define BHND_BOARD_BCM943602RSVD2 0x06a6 +#define BHND_BOARD_BCM943602X87 0X0133 +#define BHND_BOARD_BCM943602X238 0X0132 + +/* 4354 board types */ +#define BHND_BOARD_BCM94354WLSAGBI 0x06db +#define BHND_BOARD_BCM94354Z 0x0707 /* # of GPIO pins */ #define BHND_BCM43XX_GPIO_NUMPINS 32 Index: head/sys/dev/bhnd/bhnd_subr.c =================================================================== --- head/sys/dev/bhnd/bhnd_subr.c +++ head/sys/dev/bhnd/bhnd_subr.c @@ -41,9 +41,18 @@ #include +#include "nvram/bhnd_nvram.h" + +#include "bhnd_chipc_if.h" + +#include "bhnd_nvram_if.h" +#include "bhnd_nvram_map.h" + #include "bhndreg.h" #include "bhndvar.h" +static device_t find_nvram_child(device_t dev); + /* BHND core device description table. */ static const struct bhnd_core_desc { uint16_t vendor; @@ -427,6 +436,7 @@ * Return true if the @p chip matches @p desc. * * @param chip A bhnd chip identifier. + * @param board The bhnd board info, or NULL if unavailable. * @param desc A match descriptor to compare against @p chip. * * @retval true if @p chip matches @p match @@ -434,8 +444,19 @@ */ bool bhnd_chip_matches(const struct bhnd_chipid *chip, + const struct bhnd_board_info *board, const struct bhnd_chip_match *desc) { + /* Explicit wildcard match */ + if (desc->match_any) + return (true); + + /* If board_info is missing, but required, we cannot match. */ + if (BHND_CHIP_MATCH_REQ_BOARD_INFO(desc) && board == NULL) + return (false); + + + /* Chip matching */ if (desc->match_id && chip->chip_id != desc->chip_id) return (false); @@ -446,6 +467,23 @@ !bhnd_hwrev_matches(chip->chip_rev, &desc->chip_rev)) return (false); + + /* Board info matching */ + if (desc->match_srom_rev && + !bhnd_hwrev_matches(board->board_srom_rev, &desc->board_srom_rev)) + return (false); + + if (desc->match_bvendor && board->board_vendor != desc->board_vendor) + return (false); + + if (desc->match_btype && board->board_type != desc->board_type) + return (false); + + if (desc->match_brev && + !bhnd_hwrev_matches(board->board_rev, &desc->board_rev)) + return (false); + + return (true); } @@ -547,15 +585,43 @@ uint32_t bhnd_chip_quirks(device_t dev, const struct bhnd_chip_quirk *table) { + struct bhnd_board_info bi, *board; const struct bhnd_chipid *cid; const struct bhnd_chip_quirk *qent; uint32_t quirks; - + int error; + bool need_boardinfo; + cid = bhnd_get_chipid(dev); quirks = 0; + need_boardinfo = 0; + board = NULL; + /* Determine whether quirk matching requires board_info; we want to + * avoid fetching board_info for early devices (e.g. ChipCommon) + * that are brought up prior to NVRAM being readable. */ for (qent = table; !BHND_CHIP_QUIRK_IS_END(qent); qent++) { - if (bhnd_chip_matches(cid, &qent->chip)) + if (!BHND_CHIP_MATCH_REQ_BOARD_INFO(&qent->chip)) + continue; + + need_boardinfo = true; + break; + } + + /* If required, fetch board info */ + if (need_boardinfo) { + error = bhnd_read_board_info(dev, &bi); + if (!error) { + board = &bi; + } else { + device_printf(dev, "failed to read required board info " + "during quirk matching: %d\n", error); + } + } + + /* Apply all matching quirk flags */ + for (qent = table; !BHND_CHIP_QUIRK_IS_END(qent); qent++) { + if (bhnd_chip_matches(cid, board, &qent->chip)) quirks |= qent->quirks; } @@ -590,16 +656,18 @@ return (0); } - /* Quirks aren't a mandatory field */ - if ((qtable = dent->quirks_table) == NULL) - return (0); - - /* Collect matching quirk entries */ - for (qent = qtable; !BHND_DEVICE_QUIRK_IS_END(qent); qent++) { - if (bhnd_hwrev_matches(hwrev, &qent->hwrev)) - quirks |= qent->quirks; + /* Collect matching device quirk entries */ + if ((qtable = dent->quirks_table) != NULL) { + for (qent = qtable; !BHND_DEVICE_QUIRK_IS_END(qent); qent++) { + if (bhnd_hwrev_matches(hwrev, &qent->hwrev)) + quirks |= qent->quirks; + } } + /* Collect matching chip quirk entries */ + if (dent->chip_quirks_table != NULL) + quirks |= bhnd_chip_quirks(dev, dent->chip_quirks_table); + return (quirks); } @@ -824,6 +892,130 @@ panic("missing BHND_BUS_GET_CHIPID()"); } +/* nvram board_info population macros for bhnd_bus_generic_read_board_info() */ +#define BHND_GV(_dest, _name) \ + bhnd_nvram_getvar(child, BHND_NVAR_ ## _name, &_dest, sizeof(_dest)) + +#define REQ_BHND_GV(_dest, _name) do { \ + if ((error = BHND_GV(_dest, _name))) { \ + device_printf(dev, \ + "error reading " __STRING(_name) ": %d\n", error); \ + return (error); \ + } \ +} while(0) + +#define OPT_BHND_GV(_dest, _name, _default) do { \ + if ((error = BHND_GV(_dest, _name))) { \ + if (error != ENOENT) { \ + device_printf(dev, \ + "error reading " \ + __STRING(_name) ": %d\n", error); \ + return (error); \ + } \ + _dest = _default; \ + } \ +} while(0) + +/** + * Helper function for implementing BHND_BUS_READ_BOARDINFO(). + * + * This implementation populates @p info with information from NVRAM, + * defaulting board_vendor and board_type fields to 0 if the + * requested variables cannot be found. + * + * This behavior is correct for most SoCs, but must be overridden on + * bridged (PCI, PCMCIA, etc) devices to produce a complete bhnd_board_info + * result. + */ +int +bhnd_bus_generic_read_board_info(device_t dev, device_t child, + struct bhnd_board_info *info) +{ + int error; + + OPT_BHND_GV(info->board_vendor, BOARDVENDOR, 0); + OPT_BHND_GV(info->board_type, BOARDTYPE, 0); /* srom >= 2 */ + REQ_BHND_GV(info->board_rev, BOARDREV); + REQ_BHND_GV(info->board_srom_rev,SROMREV); + REQ_BHND_GV(info->board_flags, BOARDFLAGS); + OPT_BHND_GV(info->board_flags2, BOARDFLAGS2, 0); /* srom >= 4 */ + OPT_BHND_GV(info->board_flags3, BOARDFLAGS3, 0); /* srom >= 11 */ + + return (0); +} + +#undef BHND_GV +#undef BHND_GV_REQ +#undef BHND_GV_OPT + + +/** + * Find an NVRAM child device on @p dev, if any. + * + * @retval device_t An NVRAM device. + * @retval NULL If no NVRAM device is found. + */ +static device_t +find_nvram_child(device_t dev) +{ + device_t chipc, nvram; + + /* Look for a directly-attached NVRAM child */ + nvram = device_find_child(dev, "bhnd_nvram", 0); + if (nvram != NULL) + return (nvram); + + /* Remaining checks are only applicable when searching a bhnd(4) + * bus. */ + if (device_get_devclass(dev) != bhnd_devclass) + return (NULL); + + /* Look for a ChipCommon device */ + if ((chipc = bhnd_find_child(dev, BHND_DEVCLASS_CC, -1)) != NULL) { + bhnd_nvram_src_t src; + + /* Query the NVRAM source and determine whether it's + * accessible via the ChipCommon device */ + src = BHND_CHIPC_NVRAM_SRC(chipc); + if (BHND_NVRAM_SRC_CC(src)) + return (chipc); + } + + /* Not found */ + return (NULL); +} + +/** + * Helper function for implementing BHND_BUS_GET_NVRAM_VAR(). + * + * This implementation searches @p dev for a usable NVRAM child device: + * - The first child device implementing the bhnd_nvram devclass is + * returned, otherwise + * - If @p dev is a bhnd(4) bus, a ChipCommon core that advertises an + * attached NVRAM source. + * + * If no usable child device is found on @p dev, the request is delegated to + * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. + */ +int +bhnd_bus_generic_get_nvram_var(device_t dev, device_t child, const char *name, + void *buf, size_t *size) +{ + device_t nvram; + device_t parent; + + /* Try to find an NVRAM device applicable to @p child */ + if ((nvram = find_nvram_child(dev)) != NULL) + return BHND_NVRAM_GETVAR(nvram, name, buf, size); + + /* Try to delegate to parent */ + if ((parent = device_get_parent(dev)) == NULL) + return (ENODEV); + + return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, + name, buf, size)); +} + /** * Helper function for implementing BHND_BUS_ALLOC_RESOURCE(). * Index: head/sys/dev/bhnd/bhndb/bhndb.c =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb.c +++ head/sys/dev/bhnd/bhndb/bhndb.c @@ -1714,26 +1714,6 @@ return (dwa); } -/** - * Default bhndb(4) implementation of BHND_BUS_GET_NVRAM_VAR(). - */ -static int -bhndb_get_nvram_var(device_t dev, device_t child, const char *name, - void *buf, size_t *size) -{ - device_t nvram; - - /* Look for a directly-attached NVRAM child */ - nvram = device_find_child(dev, devclass_get_name(bhnd_nvram_devclass), - 0); - if (nvram != NULL) - return (BHND_NVRAM_GETVAR(nvram, name, buf, size)); - - /* Otherwise, delegate to our parent */ - return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, - name, buf, size)); -} - /* * BHND_BUS_(READ|WRITE_* implementations */ @@ -1961,7 +1941,7 @@ DEVMETHOD(bhnd_bus_get_chipid, bhndb_get_chipid), DEVMETHOD(bhnd_bus_activate_resource, bhndb_activate_bhnd_resource), DEVMETHOD(bhnd_bus_deactivate_resource, bhndb_deactivate_bhnd_resource), - DEVMETHOD(bhnd_bus_get_nvram_var, bhndb_get_nvram_var), + DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_bus_generic_get_nvram_var), DEVMETHOD(bhnd_bus_read_1, bhndb_bus_read_1), DEVMETHOD(bhnd_bus_read_2, bhndb_bus_read_2), DEVMETHOD(bhnd_bus_read_4, bhndb_bus_read_4), Index: head/sys/dev/bhnd/bhndb/bhndb_if.m =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb_if.m +++ head/sys/dev/bhnd/bhndb/bhndb_if.m @@ -56,6 +56,13 @@ } static int + bhndb_null_populate_board_info(device_t dev, device_t child, + struct bhnd_board_info *info) + { + panic("bhndb_populate_board_info unimplemented"); + } + + static int bhndb_null_init_full_config(device_t dev, device_t child, const struct bhndb_hw_priority *priority_table) { @@ -102,6 +109,21 @@ } DEFAULT bhndb_null_get_chipid; /** + * Populate @p info with board info known only to the bridge, + * deferring to any existing initialized fields in @p info. + * + * @param dev The parent device of @p child. + * @param child The bhndb-attached device. + * @param[in,out] info A board info structure previously initialized with any + * information available from NVRAM. + */ +METHOD int populate_board_info { + device_t dev; + device_t child; + struct bhnd_board_info *info; +} DEFAULT bhndb_null_populate_board_info; + +/** * Perform final bridge hardware configuration after @p child has fully * enumerated its children. * Index: head/sys/dev/bhnd/bhndb/bhndb_pci.c =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb_pci.c +++ head/sys/dev/bhnd/bhndb/bhndb_pci.c @@ -474,6 +474,25 @@ return (0); } +static int +bhndb_pci_populate_board_info(device_t dev, device_t child, + struct bhnd_board_info *info) +{ + struct bhndb_pci_softc *sc; + + sc = device_get_softc(dev); + + /* If NVRAM did not supply vendor/type info, provide the PCI + * subvendor/subdevice values. */ + if (info->board_vendor == 0) + info->board_vendor = pci_get_subvendor(sc->parent); + + if (info->board_type == 0) + info->board_type = pci_get_subdevice(sc->parent); + + return (0); +} + /** * Enable externally managed clocks, if required. * @@ -572,6 +591,7 @@ /* BHNDB interface */ DEVMETHOD(bhndb_init_full_config, bhndb_pci_init_full_config), DEVMETHOD(bhndb_set_window_addr, bhndb_pci_set_window_addr), + DEVMETHOD(bhndb_populate_board_info, bhndb_pci_populate_board_info), DEVMETHOD_END }; Index: head/sys/dev/bhnd/cores/chipc/chipc.c =================================================================== --- head/sys/dev/bhnd/cores/chipc/chipc.c +++ head/sys/dev/bhnd/cores/chipc/chipc.c @@ -65,10 +65,11 @@ }; static struct bhnd_device_quirk chipc_quirks[]; +static struct bhnd_chip_quirk chipc_chip_quirks[]; /* Supported device identifiers */ static const struct bhnd_device chipc_devices[] = { - BHND_DEVICE(CC, "CC", chipc_quirks), + BHND_DEVICE(CC, "CC", chipc_quirks, chipc_chip_quirks), BHND_DEVICE_END }; @@ -158,7 +159,6 @@ sc->dev = dev; sc->quirks = bhnd_device_quirks(dev, chipc_devices, sizeof(chipc_devices[0])); - sc->quirks |= bhnd_chip_quirks(dev, chipc_chip_quirks); CHIPC_LOCK_INIT(sc); Index: head/sys/dev/bhnd/cores/pci/bhnd_pci.c =================================================================== --- head/sys/dev/bhnd/cores/pci/bhnd_pci.c +++ head/sys/dev/bhnd/cores/pci/bhnd_pci.c @@ -68,8 +68,8 @@ #define BHND_PCI_QUIRKS bhnd_pci_quirks #define BHND_PCIE_QUIRKS bhnd_pcie_quirks -#define BHND_PCI_DEV(_core, _desc, ...) \ - { BHND_DEVICE(_core, _desc, BHND_ ## _core ## _QUIRKS, \ +#define BHND_PCI_DEV(_core, _desc, ...) \ + { BHND_DEVICE(_core, _desc, BHND_ ## _core ## _QUIRKS, NULL, \ ## __VA_ARGS__), BHND_PCI_REGFMT_ ## _core } static const struct bhnd_pci_device { Index: head/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c =================================================================== --- head/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c +++ head/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c @@ -62,11 +62,12 @@ #define BHND_PCI_ASSERT_QUIRK(_sc, _name) \ KASSERT((_sc)->quirks & (_name), ("quirk " __STRING(_name) " not set")) -#define BHND_PCI_DEV(_core, _quirks) \ - BHND_DEVICE(_core, "", _quirks, BHND_DF_HOSTB) +#define BHND_PCI_DEV(_core, _quirks, _chip_quirks) \ + BHND_DEVICE(_core, "", _quirks, _chip_quirks, BHND_DF_HOSTB) static const struct bhnd_device_quirk bhnd_pci_quirks[]; static const struct bhnd_device_quirk bhnd_pcie_quirks[]; +static const struct bhnd_chip_quirk bhnd_pcie_chip_quirks[]; static int bhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc); static int bhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc); @@ -76,8 +77,8 @@ * device/quirk tables */ static const struct bhnd_device bhnd_pci_devs[] = { - BHND_PCI_DEV(PCI, bhnd_pci_quirks), - BHND_PCI_DEV(PCIE, bhnd_pcie_quirks), + BHND_PCI_DEV(PCI, bhnd_pci_quirks, NULL), + BHND_PCI_DEV(PCIE, bhnd_pcie_quirks, bhnd_pcie_chip_quirks), BHND_DEVICE_END }; @@ -105,9 +106,21 @@ BHND_DEVICE_QUIRK_END }; +static const struct bhnd_chip_quirk bhnd_pcie_chip_quirks[] = { + /* Apple boards on which BHND_BFL2_PCIEWAR_OVR should be assumed + * to be set. */ + {{ BHND_CHIP_BVENDOR (PCI_VENDOR_APPLE), + BHND_CHIP_SROMREV (HWREV_EQ(4)), + BHND_CHIP_BREV (HWREV_LTE(0x71)) }, + BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN }, + + BHND_CHIP_QUIRK_END +}; + // Quirk handling TODO // WARs for the following are not yet implemented: // - BHND_PCIE_QUIRK_ASPM_OVR +// - BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN // - BHND_PCIE_QUIRK_SERDES_NOPLLDOWN // Quirks (and WARs) for the following are not yet defined: // - Power savings via MDIO BLK1/PWR_MGMT3 on PCIe hwrev 15-20, 21-22 Index: head/sys/dev/bhnd/cores/pci/bhnd_pci_hostbvar.h =================================================================== --- head/sys/dev/bhnd/cores/pci/bhnd_pci_hostbvar.h +++ head/sys/dev/bhnd/cores/pci/bhnd_pci_hostbvar.h @@ -131,20 +131,27 @@ * clear ASPM L1 in the PCIER_LINK_CTL register. */ BHND_PCIE_QUIRK_ASPM_OVR = (1<<9), - + + /** + * A subset of Apple devices did not set the BHND_BFL2_PCIEWAR_OVR + * flag in SPROM; on these devices, the BHND_BFL2_PCIEWAR_OVR flag + * should always be treated as if set. + */ + BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN = (1<<10), + /** * Fix SerDes polarity on SerDes <= rev9 devices. * * The SerDes polarity must be saved at device attachment, and * restored on suspend/resume. */ - BHND_PCIE_QUIRK_SDR9_POLARITY = (1<<10), + BHND_PCIE_QUIRK_SDR9_POLARITY = (1<<11), /** * SerDes PLL down flag must be manually disabled (by ChipCommon) on * resume. */ - BHND_PCIE_QUIRK_SERDES_NOPLLDOWN = (1<<11), + BHND_PCIE_QUIRK_SERDES_NOPLLDOWN = (1<<12), /** * On attach and resume, consult the SPROM to determine whether @@ -152,7 +159,7 @@ * * If L23READY_EXIT_NOPRST is not already set in the SPROM, set it */ - BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET = (1<<12), + BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET = (1<<13), /** * The PCIe SerDes supports non-standard extended MDIO register access. @@ -160,7 +167,7 @@ * The PCIe SerDes supports access to extended MDIO registers via * a non-standard Clause 22 address extension mechanism. */ - BHND_PCIE_QUIRK_SD_C22_EXTADDR = (1<<13), + BHND_PCIE_QUIRK_SD_C22_EXTADDR = (1<<14), /** * The PCIe SerDes PLL must be configured to not retry the startup @@ -168,7 +175,7 @@ * * The issue this workaround resolves has not be determined. */ - BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY = (1<<14), + BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY = (1<<15), }; /** Index: head/sys/dev/bhnd/nvram/nvram_map =================================================================== --- head/sys/dev/bhnd/nvram/nvram_map +++ head/sys/dev/bhnd/nvram/nvram_map @@ -30,6 +30,60 @@ # available ISC-licensed CIS and SROM code and associated headers. # +# Board Info +# + +u16 boardvendor {} # PCI vendor ID (SoC NVRAM-only) +u16 subvid { srom >= 2 0x6 } # PCI subvendor ID +u16 devid { srom >= 8 0x60 } # PCI device ID + +u32 boardflags { + srom 1 u16 0x72 + srom 2 u16 0x72 | u16 0x38 (<<16) + srom 3 u16 0x72 | u16 0x7A (<<16) + srom 4 0x44 + srom 5-7 0x4A + srom >= 8 0x84 +} +u32 boardflags2 { + srom 4 0x48 + srom 5-7 0x4E + srom >= 8 0x88 +} +u32 boardflags3 { + srom >= 11 0x8C +} + +# Board serial number, independent of mac addr +u16 boardnum { + srom 1-2 0x4C + srom 3 0x4E + srom 4 0x50 + srom 5-7 0x56 + srom 8-10 0x90 + srom >= 11 0x94 +} + +# Board revision +u16 boardrev { + srom 1-3 u8 0x5D + srom 4-7 0x42 + srom >= 8 0x82 +} + +# Board type +u16 boardtype { + srom >= 2 0x4 +} + +# SROM revision +u8 sromrev { + srom 1-3 0x74 + srom 4-9 0x1B6 + srom 10 0x1CA + srom 11 0x1D2 +} + # Antennas available u8 aa2g { srom 1-3 0x5C (&0x30, >>4) @@ -184,46 +238,6 @@ srom >= 11 0xA7 } -# board flags -u32 boardflags { - srom 1 u16 0x72 - srom 2 u16 0x72 | u16 0x38 (<<16) - srom 3 u16 0x72 | u16 0x7A (<<16) - srom 4 0x44 - srom 5-7 0x4A - srom >= 8 0x84 -} -u32 boardflags2 { - srom 4 0x48 - srom 5-7 0x4E - srom >= 8 0x88 -} -u32 boardflags3 { - srom >= 11 0x8C -} - -# board serial number, independent of mac addr -u16 boardnum { - srom 1-2 0x4C - srom 3 0x4E - srom 4 0x50 - srom 5-7 0x56 - srom 8-10 0x90 - srom >= 11 0x94 -} - -# One byte board revision -u16 boardrev { - srom 1-3 u8 0x5D - srom 4-7 0x42 - srom >= 8 0x82 -} - -# 2 bytes; boardtype -u16 boardtype { - srom >= 2 0x4 -} - # Default country code (sromrev == 1) u8 cc { srom 1 0x5C (&0xF) @@ -274,11 +288,6 @@ srom >= 11 u8 0xA8 } -# PCI device id -private u16 devid { - srom >= 8 u16 0x60 -} - u8 elna2g { srom 8-10 0xBB } @@ -1269,10 +1278,6 @@ srom >= 11 0x1BA } -u16 subvid { - srom >= 2 0x6 -} - u32[5] swctrlmap_2g { srom 10 u32[4] 0x1B8, u16 0x1C8 } Index: head/sys/dev/bhnd/siba/siba_bhndb.c =================================================================== --- head/sys/dev/bhnd/siba/siba_bhndb.c +++ head/sys/dev/bhnd/siba/siba_bhndb.c @@ -166,6 +166,20 @@ return (0); } +static int +siba_bhndb_read_board_info(device_t dev, device_t child, + struct bhnd_board_info *info) +{ + int error; + + /* Initialize with NVRAM-derived values */ + if ((error = bhnd_bus_generic_read_board_info(dev, child, info))) + return (error); + + /* Let the bridge fill in any additional data */ + return (BHNDB_POPULATE_BOARD_INFO(device_get_parent(dev), dev, info)); +} + static device_method_t siba_bhndb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, siba_bhndb_probe), @@ -175,6 +189,9 @@ DEVMETHOD(bus_suspend_child, siba_bhndb_suspend_child), DEVMETHOD(bus_resume_child, siba_bhndb_resume_child), + /* BHND interface */ + DEVMETHOD(bhnd_bus_read_board_info, siba_bhndb_read_board_info), + DEVMETHOD_END };