[bhnd] Centralize fetching of board information

Centralizes fetching of board information (vendor, type, revision, etc),
and adds support for matching quirks against board identification info.

* Adds a BHND_BUS_READ_BOARD_INFO(), allowing bhnd bus/bus parent(s) to
  handle implementation-specific fetching of board info.
* Integrates board type constants from the latest Broadcom ISC-licensed
  bcmdevs.h included in dd-wrt's Broadcom driver source drops.
* Adds support for matching on chip/board quirks to bhnd_device_quirks()/
  bhnd_chip_quirks().
* Use the new board/chip quirk matching to match Apple devices that failed
  to set BFL2_PCIEWAR_OVR in SROM.

Submitted by:	Landon Fuller <landonf@landonf.org>
Differential Revision:	https://reviews.freebsd.org/D6361
This commit is contained in:
Adrian Chadd 2016-05-17 00:23:46 +00:00
parent 0d2181d9ac
commit d567592b68
15 changed files with 942 additions and 222 deletions

View File

@ -166,6 +166,20 @@ bcma_bhndb_resume_child(device_t dev, device_t child)
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 @@ static device_method_t bcma_bhndb_methods[] = {
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
};

View File

@ -58,11 +58,6 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <machine/resource.h>
#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 @@ static const struct bhnd_nomatch {
{ 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 @@ bhnd_generic_get_probe_order(device_t dev, device_t child)
{
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 */
@ -380,68 +375,6 @@ bhnd_generic_is_region_valid(device_t dev, device_t child,
return (true);
}
/**
* 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().
*
@ -693,7 +626,7 @@ static device_method_t bhnd_methods[] = {
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),

View File

@ -109,6 +109,34 @@ BHND_ACCESSOR(core_unit, CORE_UNIT, int);
#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
*
@ -130,24 +158,11 @@ struct bhnd_chipid {
* not available. */
};
/**
* 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 @@ struct bhnd_hwrev_match {
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 @@ struct bhnd_core_match {
.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 @@ struct bhnd_chip_match {
#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 @@ struct bhnd_device {
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_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, ...) \
_BHND_DEVICE(MIPS, _device, _desc, _quirks, ## __VA_ARGS__, 0)
#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, ...) \
_BHND_DEVICE(ARM, _device, _desc, _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, ...) \
_BHND_DEVICE(BCM, _device, _desc, _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_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_core_matches(
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 @@ int bhnd_bus_generic_read_nvram_var(device_t dev,
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,
@ -471,6 +557,28 @@ bhnd_get_chipid(device_t dev) {
return (BHND_BUS_GET_CHIPID(device_get_parent(dev), dev));
};
/**
* 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.
*
@ -480,6 +588,7 @@ bhnd_get_chipid(device_t dev) {
*
* @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 @@ bhnd_nvram_getvarlen(device_t dev, const char *name, size_t *len)
* @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.
*/

View File

@ -38,10 +38,10 @@ INTERFACE bhnd_bus;
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 @@ CODE {
{
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 @@ CODE {
bhnd_bus_null_get_nvram_var(device_t dev, device_t child,
const char *name, void *buf, size_t *size)
{
return (ENOENT);
return (ENODEV);
}
}
@ -176,6 +183,28 @@ METHOD const struct bhnd_chipid * get_chipid {
device_t child;
} 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.
*
@ -400,6 +429,7 @@ METHOD int get_region_addr {
* @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.
*/

View File

@ -1,10 +1,12 @@
/*-
* Copyright (C) 1999-2013, Broadcom Corporation
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
* 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

View File

@ -41,9 +41,18 @@ __FBSDID("$FreeBSD$");
#include <dev/bhnd/cores/chipc/chipcreg.h>
#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 @@ bhnd_core_matches(const struct bhnd_core_info *core,
* 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 @@ bhnd_core_matches(const struct bhnd_core_info *core,
*/
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_chip_matches(const struct bhnd_chipid *chip,
!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 @@ bhnd_device_lookup(device_t dev, const struct bhnd_device *table,
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 @@ bhnd_device_quirks(device_t dev, const struct bhnd_device *table,
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 @@ bhnd_bus_generic_get_chipid(device_t dev, device_t child)
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().
*

View File

@ -1714,26 +1714,6 @@ bhndb_io_resource(struct bhndb_softc *sc, bus_addr_t addr, bus_size_t size,
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 @@ static device_method_t bhndb_methods[] = {
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),

View File

@ -55,6 +55,13 @@ CODE {
panic("bhndb_get_chipid unimplemented");
}
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)
@ -101,6 +108,21 @@ METHOD const struct bhnd_chipid * get_chipid {
device_t child;
} 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.

View File

@ -474,6 +474,25 @@ bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc,
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 @@ static device_method_t bhndb_pci_methods[] = {
/* 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
};

View File

@ -65,10 +65,11 @@ static const struct resource_spec chipc_rspec[CHIPC_MAX_RSPEC] = {
};
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 @@ chipc_attach(device_t dev)
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);

View File

@ -68,8 +68,8 @@ static struct bhnd_device_quirk bhnd_pcie_quirks[];
#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 {

View File

@ -62,11 +62,12 @@ __FBSDID("$FreeBSD$");
#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 @@ static int bhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc);
* 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 @@ static const struct bhnd_device_quirk bhnd_pcie_quirks[] = {
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

View File

@ -131,20 +131,27 @@ enum {
* 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 @@ enum {
*
* 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 @@ enum {
* 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 @@ enum {
*
* 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),
};
/**

View File

@ -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 @@ u8 aga2 {
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 @@ u16 antswitch {
srom >= 11 u8 0xA8
}
# PCI device id
private u16 devid {
srom >= 8 u16 0x60
}
u8 elna2g {
srom 8-10 0xBB
}
@ -1269,10 +1278,6 @@ u8 sar5g {
srom >= 11 0x1BA
}
u16 subvid {
srom >= 2 0x6
}
u32[5] swctrlmap_2g {
srom 10 u32[4] 0x1B8, u16 0x1C8
}

View File

@ -166,6 +166,20 @@ siba_bhndb_resume_child(device_t dev, device_t child)
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 @@ static device_method_t siba_bhndb_methods[] = {
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
};