Index: head/share/man/man9/bhnd.9 =================================================================== --- head/share/man/man9/bhnd.9 (revision 328182) +++ head/share/man/man9/bhnd.9 (revision 328183) @@ -1,2665 +1,2667 @@ .\" Copyright (c) 2015-2016 Landon Fuller .\" Copyright (c) 2017 The FreeBSD Foundation .\" All rights reserved. .\" .\" Portions of this documentation were written by Landon Fuller .\" under sponsorship from the FreeBSD Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd November 9, 2017 +.Dd January 19, 2018 .Dt BHND 9 .Os .Sh NAME .Nm bhnd .Nd BHND driver programming interface .Sh SYNOPSIS .In dev/bhnd/bhnd.h .\" .Ss Bus Resource Functions .Ft int .Fo bhnd_activate_resource .Fa "device_t dev" "int type" "int rid" "struct bhnd_resource *r" .Fc .Ft "struct bhnd_resource *" .Fo bhnd_alloc_resource .Fa "device_t dev" "int type" "int *rid" "rman_res_t start" "rman_res_t end" .Fa "rman_res_t count" "u_int flags" .Fc .Ft "struct bhnd_resource *" .Fo bhnd_alloc_resource_any .Fa "device_t dev" "int type" "int *rid" "u_int flags" .Fc .Ft int .Fo bhnd_alloc_resources .Fa "device_t dev" "struct resource_spec *rs" "struct bhnd_resource **res" .Fc .Ft int .Fo bhnd_deactivate_resource .Fa "device_t dev" "int type" "int rid" "struct bhnd_resource *r" .Fc .Ft int .Fo bhnd_release_resource .Fa "device_t dev" "int type" "int rid" "struct bhnd_resource *r" .Fc .Ft void .Fo bhnd_release_resources .Fa "device_t dev" "const struct resource_spec *rs" .Fa "struct bhnd_resource **res" .Fc .\" .Ss "Bus Space Functions" .Ft void .Fo bhnd_bus_barrier .Fa "struct bhnd_resource *r" "bus_size_t offset" .Fa "bus_size_t length" "int flags" .Fc .Ft uint8_t .Fn bhnd_bus_read_1 "struct bhnd_resource *r" "bus_size_t offset" .Ft uint16_t .Fn bhnd_bus_read_2 "struct bhnd_resource *r" "bus_size_t offset" .Ft uint32_t .Fn bhnd_bus_read_4 "struct bhnd_resource *r" "bus_size_t offset" .Ft void .Fo bhnd_bus_read_multi_1 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_multi_2 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_multi_4 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_multi_stream_1 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_multi_stream_2 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_multi_stream_4 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_region_1 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_region_2 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_region_4 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_region_stream_1 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_region_stream_2 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_read_region_stream_4 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fn bhnd_bus_read_stream_1 "struct bhnd_resource *r" "bus_size_t offset" .Ft void .Fn bhnd_bus_read_stream_2 "struct bhnd_resource *r" "bus_size_t offset" .Ft uint32_t .Fn bhnd_bus_read_stream_4 "struct bhnd_resource *r" "bus_size_t offset" .Ft void .Fo bhnd_bus_set_multi_1 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint8_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_set_multi_2 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint16_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_set_multi_4 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint32_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_set_region_1 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint8_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_set_region_2 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint16_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_set_region_4 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint32_t value" .Fa "bus_size_t count" .Fc .Ft void .Fn bhnd_bus_write_1 "struct bhnd_resource *r" "uint8_t value" .Ft void .Fn bhnd_bus_write_2 "struct bhnd_resource *r" "uint16_t value" .Ft void .Fn bhnd_bus_write_4 "struct bhnd_resource *r" "uint32_t value" .Ft void .Fo bhnd_bus_write_multi_1 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_multi_2 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_multi_4 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_multi_stream_1 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_multi_stream_2 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_multi_stream_4 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_region_1 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_region_2 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_region_4 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_region_stream_1 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_region_stream_2 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bhnd_bus_write_region_stream_4 .Fa "struct bhnd_resource *r" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fn bhnd_bus_write_stream_1 "struct bhnd_resource *r" "uint8_t value" .Ft void .Fn bhnd_bus_write_stream_2 "struct bhnd_resource *r" "uint16_t value" .Ft void .Fn bhnd_bus_write_stream_4 "struct bhnd_resource *r" "uint32_t value" .\" .Ss "Device Configuration Functions" .Ft int .Fn bhnd_read_ioctl "device_t dev" "uint16_t *ioctl" .Ft int .Fn bhnd_write_ioctl "device_t dev" "uint16_t value" "uint16_t mask" .Ft int .Fn bhnd_read_iost "device_t dev" "uint16_t *iost" .Ft uint32_t .Fo bhnd_read_config .Fa "device_t dev" "bus_size_t offset" "void *value" "u_int width" .Fc .Ft int .Fo bhnd_write_config .Fa "device_t dev" "bus_size_t offset" "const void *value" "u_int width" .Fc .Ft int .Fn bhnd_reset_hw "device_t dev" "uint16_t ioctl" "uint16_t reset_ioctl" .Ft int .Fn bhnd_suspend_hw "device_t dev" "uint16_t ioctl" .Ft bool .Fn bhnd_is_hw_suspended "device_t dev" .\" .Ss "Device Information Functions" .Ft bhnd_attach_type .Fo bhnd_get_attach_type .Fa "device_t dev" .Fc .Ft "const struct bhnd_chipid *" .Fo bhnd_get_chipid .Fa "device_t dev" .Fc .Ft bhnd_devclass_t .Fo bhnd_get_class .Fa "device_t dev" .Fc .Ft u_int .Fo bhnd_get_core_index .Fa "device_t dev" .Fc .Ft "struct bhnd_core_info" .Fo bhnd_get_core_info .Fa "device_t dev" .Fc .Ft int .Fo bhnd_get_core_unit .Fa "device_t dev" .Fc .Ft uint16_t .Fo bhnd_get_device .Fa "device_t dev" .Fc .Ft const char * .Fo bhnd_get_device_name .Fa "device_t dev" .Fc .Ft uint8_t .Fo bhnd_get_hwrev .Fa "device_t dev" .Fc .Ft uint16_t .Fo bhnd_get_vendor .Fa "device_t dev" .Fc .Ft const char * .Fo bhnd_get_vendor_name .Fa "device_t dev" .Fc .Ft int .Fo bhnd_read_board_info .Fa "device_t dev" "struct bhnd_board_info *info" .Fc .\" .Ss "Device Matching Functions" .Ft bool .Fo bhnd_board_matches .Fa "const struct bhnd_board_info *board" "const struct bhnd_board_match *desc" .Fc .Ft device_t .Fo bhnd_bus_match_child .Fa "device_t bus" "const struct bhnd_core_match *desc" .Fc .Ft bool .Fo bhnd_chip_matches .Fa "const struct bhnd_chipid *chip" "const struct bhnd_chip_match *desc" .Fc .Ft "struct bhnd_core_match" .Fo bhnd_core_get_match_desc .Fa "const struct bhnd_core_info *core" .Fc .Ft bool .Fo bhnd_core_matches .Fa "const struct bhnd_core_info *core" "const struct bhnd_core_match *desc" .Fc .Ft bool .Fo bhnd_cores_equal .Fa "const struct bhnd_core_info *lhs" "const struct bhnd_core_info *rhs" .Fc .Ft bool .Fo bhnd_hwrev_matches .Fa "uint16_t hwrev" "const struct bhnd_hwrev_match *desc" .Fc .Ft "const struct bhnd_core_info *" .Fo bhnd_match_core .Fa "const struct bhnd_core_info *cores" "u_int num_cores" .Fa "const struct bhnd_core_match *desc" .Fc .\" .Ss "Device Table Functions" .Ft "const struct bhnd_device *" .Fo bhnd_device_lookup .Fa "device_t dev" "const struct bhnd_device *table" "size_t entry_size" .Fc .Ft bool .Fo bhnd_device_matches .Fa "device_t dev" "const struct bhnd_device_match *desc" .Fc .Ft uint32_t .Fo bhnd_device_quirks .Fa "device_t dev" "const struct bhnd_device *table" "size_t entry_size" .Fc .Fo BHND_BOARD_QUIRK .Fa "board" "flags" .Fc .Fo BHND_CHIP_QUIRK .Fa "chip" "hwrev" "flags" .Fc .Fo BHND_CORE_QUIRK .Fa "hwrev" "flags" .Fc .Fo BHND_DEVICE .Fa "vendor" "device" "desc" "quirks" "..." .Fc .Fo BHND_DEVICE_IS_END .Fa "struct bhnd_device *d" .Fc .Fo BHND_DEVICE_QUIRK_IS_END .Fa "struct bhnd_device_quirk *q" .Fc .Fo BHND_PKG_QUIRK .Fa "chip" "pkg" "flags" .Fc .Bd -literal struct bhnd_device_quirk { struct bhnd_device_match desc; uint32_t quirks; }; .Ed .Bd -literal struct bhnd_device { const struct bhnd_device_match core; const char *desc; const struct bhnd_device_quirk *quirks_table; uint32_t device_flags; }; .Ed .Bd -literal enum { BHND_DF_ANY = 0, BHND_DF_HOSTB = (1 << 0), BHND_DF_SOC = (1 << 1), BHND_DF_ADAPTER = (1 << 2) }; .Ed .Bd -literal #define BHND_DEVICE_END { { BHND_MATCH_ANY }, NULL, NULL, 0 } .Ed .Bd -literal #define BHND_DEVICE_QUIRK_END { { BHND_MATCH_ANY }, 0 } .Ed .\" .Ss "DMA Address Translation Functions" .Ft int .Fo bhnd_get_dma_translation .Fa "device_t dev" "u_int width" "uint32_t flags" "bus_dma_tag_t *dmat" .Fa "struct bhnd_dma_translation *translation" .Fc .Bd -literal struct bhnd_dma_translation { bhnd_addr_t base_addr; bhnd_addr_t addr_mask; bhnd_addr_t addrext_mask; uint32_t flags; }; .Ed .Bd -literal typedef enum { BHND_DMA_ADDR_30BIT = 30, BHND_DMA_ADDR_32BIT = 32, BHND_DMA_ADDR_64BIT = 64 } bhnd_dma_addrwidth; .Ed .Bd -literal enum bhnd_dma_translation_flags { BHND_DMA_TRANSLATION_PHYSMAP = (1<<0), BHND_DMA_TRANSLATION_BYTESWAPPED = (1<<1) }; .Ed .\" .Ss "Interrupt Functions" .Ft u_int .Fo bhnd_get_intr_count .Fa "device_t dev" .Fc .Ft int .Fo bhnd_get_intr_ivec .Fa "device_t dev" "u_int intr" "u_int *ivec" .Fc .Ft int .Fo bhnd_map_intr .Fa "device_t dev" "u_int intr" "rman_res_t *irq" .Fc .Ft void .Fo bhnd_unmap_intr .Fa "device_t dev" "rman_res_t irq" .Fc .\" .Ss "NVRAM Functions" .Ft int .Fo bhnd_nvram_getvar .Fa "device_t dev" "const char *name" "void *buf" "size_t *len" .Fa "bhnd_nvram_type type" .Fc .Ft int .Fo bhnd_nvram_getvar_array .Fa "device_t dev" "const char *name" "void *buf" "size_t size" .Fa "bhnd_nvram_type type" .Fc .Ft int .Fo bhnd_nvram_getvar_int .Fa "device_t dev" "const char *name" "void *value" "int width" .Fc .Ft int .Fn bhnd_nvram_getvar_int8 "device_t dev" "const char *name" "int8_t *value" .Ft int .Fn bhnd_nvram_getvar_int16 "device_t dev" "const char *name" "int16_t *value" .Ft int .Fn bhnd_nvram_getvar_int32 "device_t dev" "const char *name" "int32_t *value" .Ft int .Fo bhnd_nvram_getvar_uint .Fa "device_t dev" "const char *name" "void *value" "int width" .Fc .Ft int .Fo bhnd_nvram_getvar_uint8 .Fa "device_t dev" "const char *name" "uint8_t *value" .Fc .Ft int .Fo bhnd_nvram_getvar_uint16 .Fa "device_t dev" "const char *name" "uint16_t *value" .Fc .Ft int .Fo bhnd_nvram_getvar_uint32 .Fa "device_t dev" "const char *name" "uint32_t *value" .Fc .Ft int .Fo bhnd_nvram_getvar_str .Fa "device_t dev" "const char *name" "char *buf" "size_t len" "size_t *rlen" .Fc .Ft "const char *" .Fo bhnd_nvram_string_array_next .Fa "const char *inp" "size_t ilen" "const char *prev" "size_t *olen" .Fc .Bd -literal typedef enum { BHND_NVRAM_TYPE_UINT8 = 0, BHND_NVRAM_TYPE_UINT16 = 1, BHND_NVRAM_TYPE_UINT32 = 2, BHND_NVRAM_TYPE_UINT64 = 3, BHND_NVRAM_TYPE_INT8 = 4, BHND_NVRAM_TYPE_INT16 = 5, BHND_NVRAM_TYPE_INT32 = 6, BHND_NVRAM_TYPE_INT64 = 7, BHND_NVRAM_TYPE_CHAR = 8, BHND_NVRAM_TYPE_STRING = 9, BHND_NVRAM_TYPE_BOOL = 10, BHND_NVRAM_TYPE_NULL = 11, BHND_NVRAM_TYPE_DATA = 12 BHND_NVRAM_TYPE_UINT8_ARRAY = 16, BHND_NVRAM_TYPE_UINT16_ARRAY = 17, BHND_NVRAM_TYPE_UINT32_ARRAY = 18, BHND_NVRAM_TYPE_UINT64_ARRAY = 19, BHND_NVRAM_TYPE_INT8_ARRAY = 20, BHND_NVRAM_TYPE_INT16_ARRAY = 21, BHND_NVRAM_TYPE_INT32_ARRAY = 22, BHND_NVRAM_TYPE_INT64_ARRAY = 23, BHND_NVRAM_TYPE_CHAR_ARRAY = 24, BHND_NVRAM_TYPE_STRING_ARRAY = 25, BHND_NVRAM_TYPE_BOOL_ARRAY = 26 } bhnd_nvram_type; .Ed .\" .Ss "Port/Region Functions" .Ft int .Fo bhnd_decode_port_rid .Fa "device_t dev" "int type" "int rid" "bhnd_port_type *port_type" .Fa "u_int *port" "u_int *region" .Fc .Ft u_int .Fo bhnd_get_port_count .Fa "device_t dev" "bhnd_port_type type" .Fc .Ft int .Fo bhnd_get_port_rid .Fa "device_t dev" "bhnd_port_type type" "u_int port" "u_int region" .Fc .Ft int .Fo bhnd_get_region_addr .Fa "device_t dev" "bhnd_port_type port_type" "u_int port" "u_int region" .Fa "bhnd_addr_t *region_addr" "bhnd_size_t *region_size" .Fc .Ft u_int .Fo bhnd_get_region_count .Fa "device_t dev" "bhnd_port_type type" "u_int port" .Fc .Ft bool .Fo bhnd_is_region_valid .Fa "device_t dev" "bhnd_port_type type" "u_int port" "u_int region" .Fc .Bd -literal typedef enum { BHND_PORT_DEVICE = 0, BHND_PORT_BRIDGE = 1, BHND_PORT_AGENT = 2 } bhnd_port_type; .Ed .\" .Ss "Power Management Functions" .Ft int .Fo bhnd_alloc_pmu .Fa "device_t dev" .Fc .Ft int .Fo bhnd_release_pmu .Fa "device_t dev" .Fc .Ft int .Fo bhnd_enable_clocks .Fa "device_t dev" "uint32_t clocks" .Fc .Ft int .Fo bhnd_request_clock .Fa "device_t dev" "bhnd_clock clock" .Fc .Ft int .Fo bhnd_get_clock_freq .Fa "device_t dev" "bhnd_clock clock" "u_int *freq" .Fc .Ft int .Fo bhnd_get_clock_latency .Fa "device_t dev" "bhnd_clock clock" "u_int *latency" .Fc .Ft int .Fo bhnd_request_ext_rsrc .Fa "device_t dev" "u_int rsrc" .Fc .Ft int .Fo bhnd_release_ext_rsrc .Fa "device_t dev" "u_int rsrc" .Fc .Bd -literal typedef enum { BHND_CLOCK_DYN = (1 << 0), BHND_CLOCK_ILP = (1 << 1), BHND_CLOCK_ALP = (1 << 2), BHND_CLOCK_HT = (1 << 3) } bhnd_clock; .Ed .\" .Ss "Service Provider Functions" .Ft int .Fo bhnd_register_provider .Fa "device_t dev" "bhnd_service_t service" .Fc .Ft int .Fo bhnd_deregister_provider .Fa "device_t dev" "bhnd_service_t service" .Fc .Ft device_t .Fo bhnd_retain_provider .Fa "device_t dev" "bhnd_service_t service" .Fc .Ft void .Fo bhnd_release_provider .Fa "device_t dev" "device_t provider" "bhnd_service_t service" .Fc .Bd -literal typedef enum { BHND_SERVICE_CHIPC, BHND_SERVICE_PWRCTL, BHND_SERVICE_PMU, BHND_SERVICE_NVRAM, BHND_SERVICE_GPIO, BHND_SERVICE_ANY = 1000 } bhnd_service_t; .Ed .\" .Ss "Utility Functions" .Ft "bhnd_erom_class_t *" .Fo bhnd_driver_get_erom_class .Fa "driver_t *driver" .Fc .Ft bhnd_devclass_t .Fo bhnd_find_core_class .Fa "uint16_t vendor" "uint16_t device" .Fc .Ft "const char *" .Fo bhnd_find_core_name .Fa "uint16_t vendor" "uint16_t device" .Fc .Ft bhnd_devclass_t .Fo bhnd_core_class .Fa "const struct bhnd_core_info *ci" .Fc .Ft "const char *" .Fo bhnd_core_name .Fa "const struct bhnd_core_info *ci" .Fc .Ft int .Fo bhnd_format_chip_id .Fa "char *buffer" "size_t size" "uint16_t chip_id" .Fc .Ft void .Fo bhnd_set_custom_core_desc .Fa "device_t dev" "const char *dev_name" .Fc .Ft void .Fo bhnd_set_default_core_desc .Fa "device_t dev" .Fc .Ft "const char *" .Fo bhnd_vendor_name .Fa "uint16_t vendor" .Fc .Bd -literal #define BHND_CHIPID_MAX_NAMELEN 32 .Ed .\" .Sh DESCRIPTION .Nm provides a unified bus and driver programming interface for the on-chip interconnects and IP cores found in Broadcom Home Networking Division (BHND) devices. .Pp The BHND device family consists of MIPS/ARM SoCs (System On a Chip) and host-connected chipsets based on a common library of Broadcom IP cores, connected via one of two on-chip backplane (hardware bus) architectures. .Pp Hardware designed prior to 2009 used Broadcom's .Dq SSB backplane architecture, based on Sonics Silicon's interconnect IP. Each core on the Sonics backplane vends a 4 KiB register block, containing both device-specific CSRs, and SSB-specific per-core device management (enable/reset/etc) registers. .Pp Subsequent hardware is based on Broadcom's .Dq BCMA backplane, based on ARM's AMBA IP. The IP cores used in earlier SSB-based devices were adapted for compatibility with the new backplane, with additional .Dq wrapper cores providing per-core device management functions in place of the SSB per-core management registers. .Pp When BHND hardware is used as a host-connected peripheral (e.g., in a PCI Wi-Fi card), the on-chip peripheral controller core is configured to operate as an endpoint device, bridging access to the SoC hardware: .Pp .Bl -dash -offset indent .It Host access to SoC address space is provided via a set of register windows (e.g., a set of configurable windows into SoC address space mapped via PCI BARs) .It DMA is supported by the bridge core's sparse mapping of host address space into the backplane address space. These address regions may be used as a target for the on-chip DMA engine. .It Any backplane interrupt vectors routed to the bridge core may be mapped by the bridge to host interrupts (e.g., PCI INTx/MSI/MSI-X). .El .Pp The .Nm driver programming interface \(em and .Xr bhndb 4 host bridge drivers \(em support the implementation of common drivers for Broadcom IP cores, whether attached via a BHND host bridge, or via the native SoC backplane. .\" .Ss "Bus Resource Functions" The bhnd_resource functions are wrappers for the standard .Vt "struct resource" bus APIs, providing support for .Vt SYS_RES_MEMORY resources that, on .Xr bhndb 4 bridged chipsets, may require on-demand remapping of address windows prior to accessing bus memory. .Pp These functions are primarily used in the implementation of BHND platform device drivers that, on host-connected peripherals, must share a small set of register windows during initial setup and teardown. .Pp BHND peripherals are designed to not require register window remapping during normal operation, and most drivers may safely use the standard .Vt struct resource APIs directly. .Pp The .Fn bhnd_activate_resource function activates a previously allocated resource. .Pp The arguments are as follows: .Bl -tag -width indent .It Fa dev The device holding ownership of the allocated resource. .It Fa type The type of the resource. .It Fa rid The bus-specific handle that identifies the resource being activated. .It Fa r A pointer to the resource returned by .Fn bhnd_alloc_resource . .El .Pp The .Fn bhnd_alloc_resource function allocates a resource from a device's parent .Xr bhnd 4 bus. .Pp The arguments are as follows: .Bl -tag -width indent .It Fa dev The device requesting resource ownership. .It Fa type The type of resource to allocate. This may be any type supported by the standard .Xr bus_alloc_resource 9 function. .It Fa rid The bus-specific handle identifying the resource being allocated. .It Fa start The start address of the resource. .It Fa end The end address of the resource. .It Fa count The size of the resource. .It Fa flags The flags for the resource to be allocated. These may be any values supported by the standard .Xr bus_alloc_resource 9 function. .El .Pp To request that the bus supply the resource's default .Fa start , .Fa end , and .Fa count values, pass .Fa start and .Fa end values of 0ul and ~0ul respectively, and a .Fa count of 1. .Pp The .Fn bhnd_alloc_resource_any function is a convenience wrapper for .Fn bhnd_alloc_resource , using the resource's default .Fa start , .Fa end , and .Fa count values. .Pp The arguments are as follows: .Bl -tag -width indent .It Fa dev The device requesting resource ownership. .It Fa type The type of resource to allocate. This may be any type supported by the standard .Xr bus_alloc_resource 9 function. .It Fa rid The bus-specific handle identifying the resource being allocated. .It Fa flags The flags for the resource to be allocated. These may be any values supported by the standard .Xr bus_alloc_resource 9 function. .El .Pp The .Fn bhnd_alloc_resources function allocates resources defined in resource specification from a device's parent .Xr bhnd 4 bus. .Pp The arguments are as follows: .Bl -tag -width indent .It Fa dev The device requesting ownership of the resources. .It Fa rs A standard bus resource specification. If all requested resources, are successfully allocated, this will be updated with the allocated resource identifiers. .It Fa res If all requested resources are successfully allocated, this will be populated with the allocated .Vt "struct bhnd_resource" instances. .El .Pp The .Fn bhnd_deactivate_resource function deactivates a resource previously activated by. .Fn bhnd_activate_resource . The arguments are as follows: .Bl -tag -width indent .It Fa dev The device holding ownership of the activated resource. .It Fa type The type of the resource. .It Fa rid The bus-specific handle identifying the resource. .It Fa r A pointer to the resource returned by bhnd_alloc_resource. .El .Pp The .Fn bhnd_release_resource function frees a resource previously returned by .Fn bhnd_alloc_resource . The arguments are as follows: .Bl -tag -width indent .It Fa dev The device holding ownership of the resource. .It Fa type The type of the resource. .It Fa rid The bus-specific handle identifying the resource. .It Fa r A pointer to the resource returned by bhnd_alloc_resource. .El .Pp The .Fn bhnd_release_resources function frees resources previously returned by .Fn bhnd_alloc_resources . The arguments are as follows: .Bl -tag -width indent .It Fa dev The device that owns the resources. .It Fa rs A standard bus resource specification previously initialized by .Fn bhnd_alloc_resources . .It Fa res The resources to be released. .El .Pp The .Vt bhnd_resource structure contains the following fields: .Bl -tag -width "direct" .It Fa res A pointer to the bus .Vt struct resource . .It Fa direct If true, the resource requires bus window remapping before it is MMIO accessible. .El .Pp .\" .Ss "Bus Space Functions" The bhnd_bus_space functions wrap their equivalent .Xr bus_space 9 counterparts, and provide support for accessing bus memory via .Vt "struct bhnd_resource". .Pp .Bl -ohang -offset indent -compact .It Fn bhnd_bus_barrier .It Fn bhnd_bus_[read|write]_[1|2|4] .It Fn bhnd_bus_[read_multi|write_multi]_[1|2|4] .It Fn bhnd_bus_[read_multi_stream|write_multi_stream]_[1|2|4] .It Fn bhnd_bus_[read_region|write_region]_[1|2|4] .It Fn bhnd_bus_[read_region_stream|write_region_stream]_[1|2|4] .It Fn bhnd_bus_[read_stream|write_stream]_[1|2|4] .It Fn bhnd_bus_[set_multi|set_stream]_[1|2|4] .El .Pp Drivers that do not rely on .Vt "struct bhnd_resource" should use the standard .Vt struct resource and .Xr bus_space 9 APIs directly. .\" .Ss "Device Configuration Functions" The .Fn bhnd_read_ioctl function is used to read the I/O control register value of device .Fa dev , returning the current value in .Fa ioctl . .Pp The .Fn bhnd_write_ioctl function is used to modify the I/O control register of .Fa dev . The new value of the register is computed by updating any bits set in .Fa mask to .Fa value . The following I/O control flags are supported: .Bl -tag -width ".Dv BHND_IOCTL_CLK_FORCE" -offset indent .It Dv BHND_IOCTL_BIST Initiate a built-in self-test (BIST). Must be cleared after BIST results are read via the IOST (I/O Status) register. .It Dv BHND_IOCTL_PME Enable posting of power management events by the core. .It Dv BHND_IOCTL_CLK_FORCE Force disable of clock gating, resulting in all clocks being distributed within the core. Should be set when asserting/deasserting reset to ensure the reset signal fully propagates to the entire core. .It Dv BHND_IOCTL_CLK_EN If cleared, the core clock will be disabled. Should be set during normal operation, and cleared when the core is held in reset. .It Dv BHND_IOCTL_CFLAGS The mask of IOCTL bits reserved for additional core-specific I/O control flags. .El .Pp The .Fn bhnd_read_iost function is used to read the I/O status register of device .Fa dev , returning the current value in .Fa iost . The following I/O status flags are supported: .Bl -tag -width ".Dv BHND_IOST_BIST_DONE" -offset indent .It Dv BHND_IOST_BIST_DONE Set upon BIST completion. Will be cleared when the .Dv BHND_IOCTL_BIST flag of the I/O control register is cleared using .Fn bhnd_write_ioctl . .It Dv BHND_IOST_BIST_FAIL Set upon detection of a BIST error; the value is unspecified if BIST has not completed and .Dv BHND_IOST_BIST_DONE is not also set. .It Dv BHND_IOST_CLK Set if the core has required that clocked be ungated, or cleared otherwise. The value is undefined if a core does not support clock gating. .It Dv BHND_IOST_DMA64 Set if this core supports 64-bit DMA. .It Dv BHND_IOST_CFLAGS The mask of IOST bits reserved for additional core-specific I/O status flags. .El .Pp The .Fn bhnd_read_config function is used to read a data item of .Fa width bytes at .Fa offset from the backplane-specific agent/config space of the device .Fa dev . .Pp The .Fn bhnd_write_config function is used to write a data item of .Fa width bytes with .Fa value at .Fa offset from the backplane-specific agent/config space of the device .Fa dev . The requested .Fa width must be one of 1, 2, or 4 bytes. .Pp The agent/config space accessible via .Fn bhnd_read_config and .Fn bhnd_write_config is backplane-specific, and these functions should only be used for functionality that is not available via another .Nm function. .Pp The .Fn bhnd_suspend_hw function transitions the device .Fa dev to a low power .Dq RESET state, writing .Fa ioctl to the I/O control flags of .Fa dev . The hardware may be brought out of this state using .Fn bhnd_reset_hw . .Pp The .Fn bhnd_reset_hw function first transitions the device .Fa dev to a low power RESET state, writing .Fa ioctl_reset to the I/O control flags of .Fa dev , and then brings the device out of RESET, writing .Fa ioctl to the device's I/O control flags. .Pp The .Fn bhnd_is_hw_suspended function returns .Dv true if the device .Fa dev is currently held in a RESET state, or is otherwise not clocked. Otherwise, it returns .Dv false . .Pp Any outstanding per-device PMU requests made using .Fn bhnd_enable_clocks , .Fn bhnd_request_clock , or .Fn bhnd_request_ext_rsrc will be released automatically upon placing a device into a RESET state. .Ss "Device Information Functions" The .Fn bhnd_get_attach_type function returns the attachment type of the parent .Xr bhnd 4 bus of device .Fa dev . .Pp The following attachment types are supported: .Bl -hang -width ".Dv BHND_ATTACH_ADAPTER" -offset indent .It Dv BHND_ATTACH_ADAPTER The bus is resident on a bridged adapter, such as a PCI Wi-Fi device. .It Dv BHND_ATTACH_NATIVE The bus is resident on the native host, such as the primary or secondary bus of an embedded SoC. .El .Pp The .Fn bhnd_get_chipid function returns chip information from the parent .Xr bhnd 4 bus of device .Fa dev . The returned .Vt bhnd_chipid struct contains the following fields: .Pp .Bl -tag -width "enum_addr" -offset indent .It Fa chip_id The chip identifier. .It Fa chip_rev The chip's hardware revision. .It Fa chip_pkg The chip's semiconductor package identifier. .Pp Several different physical semiconductor package variants may exist for a given chip, each of which may require driver workarounds for hardware errata, unpopulated components, etc. .It Fa chip_type The interconnect architecture used by this chip. .It Fa enum_addr The backplane enumeration address. On SSB devices, this will be the base address of the first SSB core. On BCMA devices, this will be the address of the enumeration ROM (EROM) core. .It Fa ncores The number of cores on the chip backplane, or 0 if unknown. .El .Pp The following constants are defined for known .Fa chip_type values: .Bl -tag -width ".Dv BHND_CHIPTYPE_BCMA_ALT" -offset indent -compact .It Dv BHND_CHIPTYPE_SIBA SSB interconnect. .It Dv BHND_CHIPTYPE_BCMA BCMA interconnect. .It Dv BHND_CHIPTYPE_BCMA_ALT BCMA-compatible variant found in Broadcom Northstar ARM SoCs. .It Dv BHND_CHIPTYPE_UBUS UBUS interconnect. This BCMA-derived interconnect is found in Broadcom BCM33xx DOCSIS SoCs, and BCM63xx xDSL SoCs. UBUS is not currently supported by .Xr bhnd 4 . .El .Pp Additional symbolic constants for known .Fa chip_id , .Fa chip_pkg , and .Fa chip_type values are defined in .In dev/bhnd/bhnd_ids.h . .Pp The .Fn bhnd_get_class function returns the BHND class of device .Fa dev , if the device's .Em vendor and .Em device identifiers are recognized. Otherwise, returns .Dv BHND_DEVCLASS_OTHER . .Pp One of the following device classes will be returned: .Pp .Bl -tag -width ".Dv BHND_DEVCLASS_SOC_ROUTER" -offset indent -compact .It Dv BHND_DEVCLASS_CC ChipCommon I/O Controller .It Dv BHND_DEVCLASS_CC_B ChipCommon Auxiliary Controller .It Dv BHND_DEVCLASS_PMU PMU Controller .It Dv BHND_DEVCLASS_PCI PCI Host/Device Bridge .It Dv BHND_DEVCLASS_PCIE PCIe Host/Device Bridge .It Dv BHND_DEVCLASS_PCCARD PCMCIA Host/Device Bridge .It Dv BHND_DEVCLASS_RAM Internal RAM/SRAM .It Dv BHND_DEVCLASS_MEMC Memory Controller .It Dv BHND_DEVCLASS_ENET IEEE 802.3 MAC/PHY .It Dv BHND_DEVCLASS_ENET_MAC IEEE 802.3 MAC .It Dv BHND_DEVCLASS_ENET_PHY IEEE 802.3 PHY .It Dv BHND_DEVCLASS_WLAN IEEE 802.11 MAC/PHY/Radio .It Dv BHND_DEVCLASS_WLAN_MAC IEEE 802.11 MAC .It Dv BHND_DEVCLASS_WLAN_PHY IEEE 802.11 PHY .It Dv BHND_DEVCLASS_CPU CPU Core .It Dv BHND_DEVCLASS_SOC_ROUTER Interconnect Router .It Dv BHND_DEVCLASS_SOC_BRIDGE Interconnect Host Bridge .It Dv BHND_DEVCLASS_EROM Device Enumeration ROM .It Dv BHND_DEVCLASS_NVRAM NVRAM/Flash Controller +.It Dv BHND_DEVCLASS_SOFTMODEM +Analog/PSTN SoftModem Codec .It Dv BHND_DEVCLASS_USB_HOST USB Host Controller .It Dv BHND_DEVCLASS_USB_DEV USB Device Controller .It Dv BHND_DEVCLASS_USB_DUAL USB Host/Device Controller .It Dv BHND_DEVCLASS_OTHER Other / Unknown .It Dv BHND_DEVCLASS_INVALID Invalid Class .El .Pp The .Fn bhnd_get_core_info function returns the core information for device .Fa dev . The returned .Vt bhnd_core_info structure contains the following fields: .Pp .Bl -tag -width "core_idx" -offset indent -compact .It Fa vendor Vendor identifier (JEP-106, ARM 4-bit continuation encoded) .It Fa device Device identifier .It Fa hwrev Hardware revision .It Fa core_idx Core index .It Fa unit Core unit .El .Pp Symbolic constants for common vendor and device identifiers are defined in .In dev/bhnd/bhnd_ids.h . Common vendor identifiers include: .Pp .Bl -tag -width ".Dv BHND_MFGID_MIPS" -offset indent -compact .It Dv BHND_MFGID_ARM ARM .It Dv BHND_MFGID_BCM Broadcom .It Dv BHND_MFGID_MIPS MIPS .El .Pp The .Fn bhnd_get_core_index , .Fn bhnd_get_core_unit , .Fn bhnd_get_device , .Fn bhnd_get_hwrev , and .Fn bhnd_get_vendor functions are convenience wrappers for .Fn bhnd_get_core_info , returning, respect the .Fa core_idx , .Fa core_unit , .Fa device , .Fa hwrev , or .Fa vendor field from the .Vt bhnd_core_info structure. .Pp The .Fn bhnd_get_device_name function returns a human readable name for device .Fa dev . .Pp The .Fn bhnd_get_vendor_name function returns a human readable name for the vendor of device .Fa dev . .Pp The .Fn bhnd_read_board_info function attempts to read the board information for device .Fa dev . The board information will be returned in the location pointed to by .Fa info on success. .Pp The .Vt bhnd_board_info structure contains the following fields: .Pp .Bl -tag -width "board_srom_rev" -offset indent .It Fa board_vendor Vendor ID of the board manufacturer (PCI-SIG assigned). .It Fa board_type Board ID. .It Fa board_devid Device ID. .It Fa board_rev Board revision. .It Fa board_srom_rev Board SROM format revision. .It Fa board_flags Board flags (1) .It Fa board_flags2 Board flags (2) .It Fa board_flags3 Board flags (3) .El .Pp The .Fa board_devid field is the Broadcom PCI device ID that most closely matches the capabilities of the BHND device (if any). .Pp On PCI devices, the .Fa board_vendor , .Fa board_type , and .Fa board_devid fields default to the PCI Subsystem Vendor ID, PCI Subsystem ID, and PCI device ID, unless overridden in device NVRAM. .Pp On other devices, including SoCs, the .Fa board_vendor , .Fa board_type , and .Fa board_devid fields will be populated from device NVRAM. .Pp Symbolic constants for common board flags are defined in .In dev/bhnd/bhnd_ids.h . .Pp .Ss "Device Matching Functions" The bhnd device matching functions are used to match against core, chip, and board-level device attributes. Match requirements are specified using the .Vt "struct bhnd_board_match" , .Vt "struct bhnd_chip_match" , .Vt "struct bhnd_core_match" , .Vt "struct bhnd_device_match" , and .Vt "struct bhnd_hwrev_match" match descriptor structures. .Pp The .Fn bhnd_board_matches function returns .Dv true if .Fa board matches the board match descriptor .Fa desc . Otherwise, it returns .Dv false . .Pp The .Fn bhnd_chip_matches function returns .Dv true if .Fa chip matches the chip match descriptor .Fa desc . Otherwise, it returns .Dv false . .Pp The .Fn bhnd_core_matches function returns .Dv true if .Fa core matches the core match descriptor .Fa desc . Otherwise, it returns .Dv false . .Pp The .Fn bhnd_device_matches function returns .Dv true if the device .Fa dev matches the device match descriptor .Fa desc . Otherwise, it returns .Dv false . .Pp The .Fn bhnd_hwrev_matches function returns .Dv true if .Fa hwrev matches the hwrev match descriptor .Fa desc . Otherwise, it returns .Dv false . .Pp The .Fn bhnd_bus_match_child function returns the first child device of .Fa bus that matches the device match descriptor .Fa desc . If no matching child is found, .Dv NULL is returned. .Pp The .Fn bhnd_core_get_match_desc function returns an equality match descriptor for the core info in .Fa core . The returned descriptor will match only on core attributes identical to those defined by .Fa core . .Pp The .Fn bhnd_cores_equal function is a convenience wrapper for .Fn bhnd_core_matches and .Fn bhnd_core_get_match_desc . This function returns .Dv true if the .Vt bhnd_core_info structures .Fa lhs and .Fa rhs are equal. Otherwise, it returns .Dv false . .Pp The .Fn bhnd_match_core function returns a pointer to the first entry in the array .Fa cores of length .Fa num_cores that matches .Fa desc . If no matching core is found, .Dv NULL is returned. .Pp A .Vt bhnd_board_match match descriptor may be initialized using one or more of the following macros: .Pp .Bl -tag -width "Fn BHND_MATCH_BOARD_VENDOR vendor" -offset indent .It Fn BHND_MATCH_BOARD_VENDOR "vendor" Match on boards with a vendor equal to .Fa vendor . .It Fn BHND_MATCH_BOARD_TYPE "type" Match on boards with a type equal to .Dv "BHND_BOARD_ ##" .Fa type .It Fn BHND_MATCH_SROMREV "sromrev" Match on boards with a sromrev that matches .Dv "BHND_HWREV_ ##" .Fa sromrev . .It Fn BHND_MATCH_BOARD_REV "hwrev" Match on boards with hardware revisions that match .Dv "BHND_ ##" .Fa hwrev . .It Fn BHND_MATCH_BOARD "vendor" "type" A convenience wrapper for .Fn BHND_MATCH_BOARD_VENDOR and .Fn BHND_MATCH_BOARD_TYPE . .El .Pp For example: .Bd -literal -offset indent struct bhnd_board_match board_desc = { BHND_MATCH_BOARD_VENDOR(BHND_MFGID_BROADCOM), BHND_MATCH_BOARD_TYPE(BCM94360X52C), BHND_MATCH_BOARD_REV(HWREV_ANY), BHND_MATCH_SROMREV(RANGE(0, 10)) }; .Ed .Pp A .Vt bhnd_chip_match match descriptor may be initialized using one or more of the following macros: .Pp .Bl -tag -width "Fn BHND_MATCH_CHIP_IPR id pkg hwrev" -offset indent .It Fn BHND_MATCH_CHIP_ID "id" Match on chips with an ID equal to .Dv "BHND_CHIPID_ ##" .Fa id .It Fn BHND_MATCH_CHIP_REV "hwrev" Match on chips with hardware revisions that match .Dv "BHND_ ##" .Fa hwrev . .It Fn BHND_MATCH_CHIP_PKG "pkg" Match on chips with a package ID equal to .Dv "BHND_PKGID_ ##" .Fa pkg .It Fn BHND_MATCH_CHIP_TYPE "type" Match on chips with a chip type equal to .Dv "BHND_CHIPTYPE_ ##" .Fa type .It Fn BHND_MATCH_CHIP_IP "id" "pkg" A convenience wrapper for .Fn BHND_MATCH_CHIP_ID and .Fn BHND_MATCH_CHIP_PKG . .It Fn BHND_MATCH_CHIP_IPR "id" "pkg" "hwrev" A convenience wrapper for .Fn BHND_MATCH_CHIP_ID , .Fn BHND_MATCH_CHIP_PKG , and .Fn BHND_MATCH_CHIP_REV . .It Fn BHND_MATCH_CHIP_IR "id" "hwrev" A convenience wrapper for .Fn BHND_MATCH_CHIP_ID and .Fn BHND_MATCH_CHIP_REV . .El .Pp For example: .Bd -literal -offset indent struct bhnd_chip_match chip_desc = { BHND_MATCH_CHIP_IP(BCM4329, BCM4329_289PIN), BHND_MATCH_CHIP_TYPE(SIBA) }; .Ed .Pp A .Vt bhnd_core_match match descriptor may be initialized using one or more of the following macros: .Pp .Bl -tag -width "Fn BHND_MATCH_CORE_VENDOR vendor" -offset indent .It Fn BHND_MATCH_CORE_VENDOR "vendor" Match on cores with a vendor ID equal to .Fa vendor .It Fn BHND_MATCH_CORE_ID "id" Match on cores with a device ID equal to .Fa id .It Fn BHND_MATCH_CORE_REV "hwrev" Match on cores with hardware revisions that match .Dv "BHND_ ##" .Fa hwrev . .It Fn BHND_MATCH_CORE_CLASS "class" Match on cores with a core device class equal to .Fa class .It Fn BHND_MATCH_CORE_IDX "idx" Match on cores with a core index equal to .Fa idx .It Fn BHND_MATCH_CORE_UNIT "unit" Match on cores with a core unit equal to .Fa unit .It Fn BHND_MATCH_CORE "vendor" "id" A convenience wrapper for .Fn BHND_MATCH_CORE_VENDOR and .Fn BHND_MATCH_CORE_ID . .El .Pp For example: .Bd -literal -offset indent struct bhnd_core_match core_desc = { BHND_MATCH_CORE(BHND_MFGID_BROADCOM, BHND_COREID_CC), BHND_MATCH_CORE_REV(HWREV_RANGE(0, 10)) }; .Ed .Pp The .Vt bhnd_device_match match descriptor supports matching on all board, chip, and core attributes, and may be initialized using any of the .Vt bhnd_board_match , .Vt bhnd_chip_match , or .Vt bhnd_core_match macros. .Pp For example: .Bd -literal -offset indent struct bhnd_device_match device_desc = { BHND_MATCH_CHIP_IP(BCM4329, BCM4329_289PIN), BHND_MATCH_BOARD_VENDOR(BHND_MFGID_BROADCOM), BHND_MATCH_BOARD_TYPE(BCM94329AGB), BHND_MATCH_CORE(BHND_MFGID_BROADCOM, BHND_COREID_CC), }; .Ed .Pp A .Vt bhnd_hwrev_match match descriptor may be initialized using one of the following macros: .Pp .Bl -tag -width "Fn BHND_HWREV_RANGE start end" -offset indent -compact .It Dv BHND_HWREV_ANY Matches any hardware revision. .It Fn BHND_HWREV_EQ "hwrev" Matches any hardware revision equal to .Fa hwrev .It Fn BHND_HWREV_GTE "hwrev" Matches any hardware revision greater than or equal to .Fa hwrev .It Fn BHND_HWREV_LTE "hwrev" Matches any hardware revision less than or equal to .Fa hwrev .It Fn BHND_HWREV_RANGE "start" "end" Matches any hardware revision within an inclusive range. If .Dv BHND_HWREV_INVALID is specified as the .Fa end value, will match on any revision equal to or greater than .Fa start .El .\" .Ss "Device Table Functions" The bhnd device table functions are used to query device and quirk tables. .Pp The .Fn bhnd_device_lookup function returns a pointer to the first entry in device table .Fa table that matches the device .Fa dev . The table entry size is specified by .Fa entry_size . .Pp The .Fn bhnd_device_quirks function scan the device table .Fa table for all quirk entries that match the device .Fa dev , returning the bitwise OR of all matching quirk flags. The table entry size is specified by .Fa entry_size . .Pp The .Vt bhnd_device structure contains the following fields: .Bl -tag -width "quirks_table" -offset indent -compact .It Fa core A .Vt bhnd_device_match descriptor. .It Fa desc A verbose device description suitable for use with .Xr device_set_desc 9 , or .Dv NULL . .It Fa quirks_table The quirks table for this device, or .Dv NULL . .It Fa device_flags The device flags required when matching this entry. .El .Pp The following device flags are supported: .Bl -tag -width ".Dv BHND_DF_ADAPTER" -offset indent -compact .It Dv BHND_DF_ANY Match on any device. .It Dv BHND_DF_HOSTB Match only if the device is the .Xr bhndb 4 host bridge. Implies .Dv BHND_DF_ADAPTER . .It Dv BHND_DF_SOC Match only if the device is attached to a native SoC backplane. .It Dv BHND_DF_ADAPTER Match only if the device is attached to a .Xr bhndb 4 bridged backplane. .El .Pp A .Vt bhnd_device table entry may be initialized using one of the following macros: .Pp .Bl -ohang -offset indent .It Fn BHND_DEVICE "vendor" "device" "desc" "quirks" "flags" Match on devices with a vendor ID equal to .Dv BHND_MFGID_ ## .Fa vendor and a core device ID equal to .Dv BHND_COREID_ ## .Fa device . .Pp The device's verbose description is specified by the .Fa desc argument, a pointer to the device-specific quirks table is specified by the .Fa quirks argument, and any required device flags may be provided in .Fa flags . The optional .Fa flags argument defaults to .Dv BHND_DF_ANY if omitted. .It Dv BHND_DEVICE_END Terminate the .Vt bhnd_device table. .El .Pp For example: .Bd -literal -offset indent struct bhnd_device bhnd_usb11_devices[] = { BHND_DEVICE(BCM, USB, "Broadcom USB1.1 Controller", bhnd_usb11_quirks), BHND_DEVICE_END }; .Ed .Pp The .Vt bhnd_device_quirk structure contains the following fields: .Bl -tag -width "quirks_table" -offset indent -compact .It Fa desc A .Vt bhnd_device_match descriptor. .It Fa quirks Applicable quirk flags. .El .Pp A bhnd_device_quirk table entry may be initialized using one of the following convenience macros: .Bl -tag -width "Fn BHND_CHIP_QUIRK chip hwrev flags" -offset indent .It Fn BHND_BOARD_QUIRK "board" "flags" Set quirk flags .Fa flags on devices with a board type equal to .Dv BHND_BOARD_ ## .Fa board . .It Fn BHND_CHIP_QUIRK "chip" "hwrev" "flags" Set quirk flags .Fa flags on devices with a chip ID equal to .Dv BHND_CHIPID_BCM ## .Fa chip and chip hardware revision that matches .Dv BHND_ ## .Fa hwrev . .It Fn BHND_PKG_QUIRK "chip" "pkg" flags" Set quirk flags .Fa flags on devices with a chip ID equal to .Dv BHND_CHIPID_BCM ## .Fa chip and chip package equal to .Dv BHND_ ## chip ## .Fa pkg . .It Fn BHND_CORE_QUIRK "hwrev" flags" Set quirk flags .Fa flags on devices with a core hardware revision that matches .Dv BHND_ ## .Fa hwrev . .El For example: .Bd -literal -offset indent struct bhnd_device_quirk bhnd_usb11_quirks[] = { BHND_DEVICE(BCM, USB, "Broadcom USB1.1 Controller", bhnd_usb11_quirks), BHND_DEVICE_END }; .Ed .Ss "DMA Address Translation Functions" The .Fn bhnd_get_dma_translation function is used to request a DMA address translation descriptor suitable for use with a maximum DMA address width of .Fa width , with support for the requested translation .Fa flags . .Pp If a suitable DMA address translation descriptor is found, it will be stored in .Fa translation , and a bus DMA tag specifying the DMA translation's address restrictions will be stored in .Fa dmat . The .Fa translation and .Fa dmat arguments may be .Dv NULL if the translation descriptor or DMA tag are not desired. .Pp The following DMA translation flags are supported: .Bl -ohang -width ".Dv BHND_DMA_TRANSLATION_BYTESWAPPED" -offset indent .It Dv BHND_DMA_TRANSLATION_PHYSMAP The translation remaps the device's physical address space. .Pp This is used in conjunction with .Dv BHND_DMA_TRANSLATION_BYTESWAPPED to define a DMA translation that provides byteswapped access to physical memory on big-endian MIPS SoCs. .It Dv BHND_DMA_TRANSLATION_BYTESWAPPED The translation provides a byte-swapped mapping; write requests will be byte-swapped before being written to memory, and read requests will be byte-swapped before being returned. .Pp This is primarily used to perform efficient byte swapping of DMA data on embedded MIPS SoCs executing in big-endian mode. .El .Pp The following symbolic constants are defined for common DMA address widths: .Pp .Bl -tag -width ".Dv BHND_DMA_ADDR_64BIT" -offset indent -compact .It Dv BHND_DMA_ADDR_30BIT 30-bit DMA .It Dv BHND_DMA_ADDR_32BIT 32-bit DMA .It Dv BHND_DMA_ADDR_64BIT 64-bit DMA .El .Pp The .Vt bhnd_dma_translation structure contains the following fields: .Bl -tag -width "addrext_mask" .It Fa base_addr Host-to-device physical address translation. This may be added to a host physical address to produce a device DMA address. .It Fa addr_mask Device-addressable address mask. This defines the device DMA address range, and excludes any bits reserved for mapping the address within the translation window at .Fa base_addr . .It Fa addrext_mask Device-addressable extended address mask. If a the per-core BHND DMA engine supports the 'addrext' control field, it can be used to provide address bits excluded by .Fa addr_mask . .Pp Support for DMA extended address changes \(em including coordination with the core providing device-to-host DMA address translation \(em is handled transparently by the DMA engine. .Pp For example, on PCI Wi-Fi devices, the Wi-Fi core's DMA engine will (in effect) update the PCI host bridge core's DMA .Dv sbtopcitranslation base address to map the target address prior to performing a DMA transaction. .It Fa flags Translation flags. .El .\" .Ss "Interrupt Functions" The .Fn bhnd_get_intr_count function is used to determine the number of backplane interrupt lines assigned to the device .Fa dev . Interrupt line identifiers are allocated in monotonically increasing order, starting with 0. .Pp The .Fn bhnd_get_intr_ivec function is used to determine the backplane interrupt vector assigned to interrupt line .Fa intr on the device .Fa dev , writing the result to .Fa ivec . Interrupt vector assignments are backplane-specific: On BCMA devices, this function returns the OOB bus line assigned to the interrupt. On SIBA devices, it returns the target OCP slave flag number assigned to the interrupt. .Pp The .Fn bhnd_map_intr function is used to map interrupt line .Fa intr assigned to device .Fa dev to an IRQ number, writing the result to .Fa irq . Until unmapped, this IRQ may be used when allocating a resource of type SYS_RES_IRQ. .Pp Ownership of the interrupt mapping is assumed by the caller, and must be explicitly released using .Fa bhnd_unmap_intr . .Pp The .Fn bhnd_unmap_intr function is used to unmap bus IRQ .Fa irq previously mapped using .Fn bhnd_map_intr by the device .Fa dev . .\" .Ss "NVRAM Functions" The .Fn bhnd_nvram_getvar function is used to read the value of NVRAM variable .Fa name from the NVRAM provider(s) registered with the parent .Xr bhnd 4 bus of device .Fa dev , coerced to the desired data representation .Fa type , written to the buffer specified by .Fa buf . .Pp Before the call, the maximum capacity of .Fa buf is specified by .Fa len . After a successful call \(em or if .Er ENOMEM is returned \(em the size of the available data will be written to .Fa len . The size of the desired data representation can be determined by calling .Fn bhnd_nvram_getvar with a .Dv NULL argument for .Fa buf . .Pp The following NVRAM data types are supported: .Pp .Bl -tag -width ".Dv BHND_NVRAM_TYPE_UINT64_ARRAY" -offset indent -compact .It Dv BHND_NVRAM_TYPE_UINT8 unsigned 8-bit integer .It Dv BHND_NVRAM_TYPE_UINT16 unsigned 16-bit integer .It Dv BHND_NVRAM_TYPE_UINT32 unsigned 32-bit integer .It Dv BHND_NVRAM_TYPE_UINT64 signed 64-bit integer .It Dv BHND_NVRAM_TYPE_INT8 signed 8-bit integer .It Dv BHND_NVRAM_TYPE_INT16 signed 16-bit integer .It Dv BHND_NVRAM_TYPE_INT32 signed 32-bit integer .It Dv BHND_NVRAM_TYPE_INT64 signed 64-bit integer .It Dv BHND_NVRAM_TYPE_CHAR UTF-8 character .It Dv BHND_NVRAM_TYPE_STRING UTF-8 NUL-terminated string .It Dv BHND_NVRAM_TYPE_BOOL uint8 boolean value .It Dv BHND_NVRAM_TYPE_NULL NULL (empty) value .It Dv BHND_NVRAM_TYPE_DATA opaque octet string .It Dv BHND_NVRAM_TYPE_UINT8_ARRAY array of uint8 integers .It Dv BHND_NVRAM_TYPE_UINT16_ARRAY array of uint16 integers .It Dv BHND_NVRAM_TYPE_UINT32_ARRAY array of uint32 integers .It Dv BHND_NVRAM_TYPE_UINT64_ARRAY array of uint64 integers .It Dv BHND_NVRAM_TYPE_INT8_ARRAY array of int8 integers .It Dv BHND_NVRAM_TYPE_INT16_ARRAY array of int16 integers .It Dv BHND_NVRAM_TYPE_INT32_ARRAY array of int32 integers .It Dv BHND_NVRAM_TYPE_INT64_ARRAY array of int64 integers .It Dv BHND_NVRAM_TYPE_CHAR_ARRAY array of UTF-8 characters .It Dv BHND_NVRAM_TYPE_STRING_ARRAY array of UTF-8 NUL-terminated strings .It Dv BHND_NVRAM_TYPE_BOOL_ARRAY array of uint8 boolean values .El .Pp The .Fn bhnd_nvram_getvar_array , .Fn bhnd_nvram_getvar_int , .Fn bhnd_nvram_getvar_int8 , .Fn bhnd_nvram_getvar_int16 , .Fn bhnd_nvram_getvar_int32 , .Fn bhnd_nvram_getvar_uint , .Fn bhnd_nvram_getvar_uint8 , .Fn bhnd_nvram_getvar_uint16 , .Fn bhnd_nvram_getvar_uint32 , and .Fn bhnd_nvram_getvar_str functions are convenience wrappers for .Fn bhnd_nvram_getvar . .Pp The .Fn bhnd_nvram_getvar_array function returns either a value of exactly .Fa size in .Fa buf , or returns an error code of .Er ENXIO if the data representation is not exactly .Fa size in length. .Pp The .Fn bhnd_nvram_getvar_int and .Fn bhnd_nvram_getvar_uint functions return the value of NVRAM variable .Fa name , coerced to a signed or unsigned integer type of .Fa width (1, 2, or 4 bytes). .Pp The .Fn bhnd_nvram_getvar_int8 , .Fn bhnd_nvram_getvar_int16 , .Fn bhnd_nvram_getvar_int32 , .Fn bhnd_nvram_getvar_uint , .Fn bhnd_nvram_getvar_uint8 , .Fn bhnd_nvram_getvar_uint16 , and .Fn bhnd_nvram_getvar_uint32 functions return the value of NVRAM variable .Fa name , coerced to a signed or unsigned 8, 16, or 32-bit integer type. .Pp The .Fn bhnd_nvram_getvar_str functions return the value of NVRAM variable .Fa name , coerced to a NUL-terminated string. .Pp The .Fn bhnd_nvram_string_array_next function iterates over all strings in the .Fa inp .Dv BHND_NVRAM_TYPE_STRING_ARRAY value. The size of .Fa inp , including any terminating NUL character(s), is specified using the .Fa ilen argument. The .Fa prev argument should be either a string pointer previously returned by .Fn bhnd_nvram_string_array_next , or .Dv NULL to begin iteration. If .Fa prev is not .Dv NULL , the .Fa olen argument must be a pointer to the length previously returned by .Fn bhnd_nvram_string_array_next . On success, the next string element's length will be written to this pointer. .\" .Ss "Port/Region Functions" Per-device interconnect memory mappings are identified by a combination of .Em port type , .Em port number , and .Em region number . Port and memory region identifiers are allocated in monotonically increasing order for each .Em port type , starting with 0. .Pp The following port types are supported: .Bl -tag -width ".Dv BHND_PORT_DEVICE" -offset indent .It Dv BHND_PORT_DEVICE Device memory. The device's control/status registers are always mapped by the first device port and region, and will be assigned a .Dv SYS_RES_MEMORY resource ID of 0. .It Dv BHND_PORT_BRIDGE Bridge memory. .It Dv BHND_PORT_AGENT Interconnect agent/wrapper. .El .Pp The .Fn bhnd_decode_port_rid function is used to decode the resource ID .Fa rid assigned to device .Fa dev , of resource type .Fa type , writing the port type to .Fa port_type , port number to .Fa port , and region number to .Fa region . .Pp The .Fn bhnd_get_port_count function returns the number of ports of type .Fa type assigned to device .Fa dev . .Pp The .Fn bhnd_get_port_rid function returns the resource ID for the .Dv SYS_RES_MEMORY resource mapping the .Fa port of .Fa type and .Fa region on device .Fa dev , or -1 if the port or region are invalid, or do not have an assigned resource ID. .Pp The .Fn bhnd_get_region_addr function is used to determine the base address and size of the memory .Fa region on .Fa port of .Fa type assigned to .Fa dev . The region's base device address will be written to .Fa region_addr , and the region size to .Fa region_size . .Pp The .Fn bhnd_get_region_count function returns the number of memory regions mapped to .Fa port of .Fa type on device .Fa dev . .Pp The .Fn bhnd_is_region_valid function returns .Dv true if .Fa region is a valid region mapped by .Fa port of .Fa type on device .Fa dev . .\" .Ss "Power Management Functions" Drivers must ask the parent .Xr bhnd 4 bus to allocate device PMU state using .Fn bhnd_alloc_pmu before calling any another bhnd PMU functions. .Pp The .Fn bhnd_alloc_pmu function is used to allocate per-device PMU state and enable PMU request handling for device .Fa dev . The memory region containing the device's PMU register block must be allocated using .Xr bus_alloc_resource 9 or .Fn bhnd_alloc_resource before calling .Fn bhnd_alloc_pmu , and must not be released until after calling .Fn bhnd_release_pmu . .Pp On all supported BHND hardware, the PMU register block is mapped by the device's control/status registers in the first device port and region. .Pp The .Fn bhnd_release_pmu function releases the per-device PMU state previously allocated for device .Fa dev using .Fn bhnd_alloc_pmu . Any outstanding clock and external resource requests will be discarded upon release of the device PMU state. .Pp The .Fn bhnd_enable_clocks function is used to request that .Fa clocks be powered up and routed to the backplane on behalf of device .Fa dev . This will power any clock sources required (e.g., XTAL, PLL, etc) and wait until the requested clocks are stable. If the request succeeds, any previous clock requests issued by .Fa dev will be discarded. .Pp The following clocks are supported, and may be combined using bitwise OR to request multiple clocks: .Pp .Bl -tag -width ".Dv BHND_CLOCK_DYN" -offset indent .It BHND_CLOCK_DYN Dynamically select an appropriate clock source based on all outstanding clock requests by any device attached to the parent .Xr bhnd 4 bus. .It BHND_CLOCK_ILP Idle Low-Power (ILP) Clock. May be used if no register access is required, or long request latency is acceptable. .It BHND_CLOCK_ALP Active Low-Power (ALP) Clock. Supports low-latency register access and low-rate DMA. .It BHND_CLOCK_HT High Throughput (HT) Clock. Supports high bus throughput and lowest-latency register access. .El .Pp The .Fn bhnd_request_clock function is used to request that .Fa clock (or faster) be powered up and routed to device .Fa dev . .Pp The .Fn bhnd_get_clock_freq function is used to request the current clock frequency of .Fa clock , writing the frequency in Hz to .Fa freq . .Pp The .Fn bhnd_get_clock_latency function is used to determine the transition latency required for .Fa clock , writing the latency in microseconds to .Fa latency . The .Dv BHND_CLOCK_HT latency value is suitable for use as the D11 Wi-Fi core .Em fastpwrup_dly value. .Pp The .Fn bhnd_request_ext_rsrc function is used to request that the external PMU-managed resource assigned to device .Fa dev , identified by device-specific identifier .Fa rsrc , be powered up. .Pp The .Fn bhnd_release_ext_rsrc function releases any outstanding requests by device .Fa dev for the PMU-managed resource identified by device-specific identifier .Fa rsrc . If an external resource is shared by multiple devices, it will not be powered down until all device requests are released. .\" .Ss "Service Provider Functions" The .Fn bhnd_register_provider function is used to register device .Fa dev as a provider for platform .Fa service with the parent .Xr bhnd 4 bus. .Pp The following service types are supported: .Bl -tag -width ".Dv BHND_SERVICE_INVALID" -offset indent .It Dv BHND_SERVICE_CHIPC ChipCommon service. The providing device must implement the bhnd_chipc interface. .It Dv BHND_SERVICE_PWRCTL Legacy PWRCTL service. The providing device must implement the bhnd_pwrctl interface. .It Dv BHND_SERVICE_PMU PMU service. The providing device must implement the bhnd_pmu interface. .It Dv BHND_SERVICE_NVRAM NVRAM service. The providing device must implement the bhnd_nvram interface. .It Dv BHND_SERVICE_GPIO GPIO service. The providing device must implement the standard .Xr gpio 4 interface. .It Dv BHND_SERVICE_ANY Matches on any service type. May be used with .Fn bhnd_deregister_provider to remove all service provider registrations for a device. .El .Pp The .Fn bhnd_deregister_provider function attempts to remove provider registration for the device .Fa dev and .Fa service . If a .Fa service argument of .Dv BHND_SERVICE_ANY is specified, this function will attempt to remove .Em all service provider registrations for .Fa dev . .Pp The .Fn bhnd_retain_provider function retains and returns a reference to the provider registered for .Fa service with the parent .Xr bhnd 4 bus of devce .Fa dev , if available. On success, the caller is responsible for releasing this provider reference using .Fn bhnd_release_provider . The service provider is guaranteed to remain available until the provider reference is released. .Pp The .Fn bhnd_release_provider function releases a reference to a .Fa provider for .Fa service , previously retained by device .Fa dev using .Fn bhnd_retain_provider . .\" .Ss "Utility Functions" The .Fn bhnd_driver_get_erom_class function returns the .Xr bhnd_erom 9 class for the device enumeration table format used by .Xr bhnd 4 bus driver instance .Fa driver . If the driver does not support .Xr bhnd_erom 9 device enumeration, .Dv NULL is returned. .Pp The .Fn bhnd_find_core_class function looks up the BHND class, if known, for the BHND vendor ID .Fa vendor and device ID .Fa device . .Pp The .Fn bhnd_find_core_name function is used to fetch the human-readable name, if known, for the BHND core with a vendor ID of .Fa vendor and device ID of .Fa device . .Pp The .Fn bhnd_core_class and .Fn bhnd_core_name functions are convenience wrappers for .Fn bhnd_find_core_class and .Fn bhnd_find_core_name , that use the .Fa vendor and .Fa device fields of the core info structure .Fa ci . .Pp The .Fn bhnd_format_chip_id function writes a NUL-terminated human-readable representation of the BHND .Fa chip_id value to the specified .Fa buffer with a capacity of .Fa size . No more than .Fa size-1 characters will be written, with the .Fa size'th character set to '\\0'. A buffer size of .Dv BHND_CHIPID_MAX_NAMELEN is sufficient for any string representation produced using .Fn bhnd_format_chip_id . .Pp The .Fn bhnd_set_custom_core_desc function uses the .Xr bhnd 4 device identification of .Fa dev , overriding the core name with the specified .Fa dev_name , to populate the device's verbose description using .Xr device_set_desc . .Pp The .Fn bhnd_set_default_core_desc function uses the .Xr bhnd 4 device identification of .Fa dev to populate the device's verbose description using .Xr device_set_desc . .Pp The .Fn bhnd_vendor_name function returns the human-readable name for the JEP-106, ARM 4-bit continuation encoded manufacturer ID .Fa vendor , if known. .\" .Sh RETURN VALUES .Ss Bus Resource Functions The .Fn bhnd_activate_resource , .Fn bhnd_alloc_resources , .Fn bhnd_deactivate_resource , and .Fn bhnd_release_resource functions return 0 on success, otherwise an appropriate error code is returned. .Pp The .Fn bhnd_alloc_resource and .Fn bhnd_alloc_resource_any functions return a pointer to .Vt "struct resource" on success, a null pointer otherwise. .\" .Ss "Device Configuration Functions" .Pp The .Fn bhnd_read_config and .Fn bhnd_write_config functions return 0 on success, or one of the following values on error: .Bl -tag -width Er .It Bq Er EINVAL The device is not a direct child of the .Xr bhnd 4 bus .It Bq Er EINVAL The requested width is not one of 1, 2, or 4 bytes. .It Bq Er ENODEV Accessing agent/config space for the device is unsupported. .It Bq Er EFAULT The requested offset or width exceeds the bounds of the mapped agent/config space. .El .Pp The .Fn bhnd_read_ioctl , .Fn bhnd_write_ioctl , .Fn bhnd_read_iost , .Fn bhnd_reset_hw , and .Fn bhnd_suspend_hw functions return 0 on success, otherwise an appropriate error code is returned. .\" .Ss "Device Information Functions" .Pp The .Fn bhnd_read_board_info function returns 0 on success, otherwise an appropriate error code is returned. .\" .Ss "DMA Address Translation Functions" The .Fn bhnd_get_dma_translation function returns 0 on success, or one of the following values on error: .Bl -tag -width Er .It Bq Er ENODEV DMA is not supported. .It Bq Er ENOENT No DMA translation matching the requested address width and translation flags is available. .El .Pp If fetching the requested DMA address translation otherwise fails, an appropriate error code will be returned. .\" .Ss "Interrupt Functions" .Pp The .Fn bhnd_get_intr_ivec function returns 0 on success, or .Er ENXIO if the requested interrupt line exceeds the number of interrupt lines assigned to the device. .Pp The .Fn bhnd_map_intr function returns 0 on success, otherwise an appropriate error code is returned. .\" .Ss "NVRAM Functions" The .Fn bhnd_nvram_getvar , .Fn bhnd_nvram_getvar_array , .Fn bhnd_nvram_getvar_int , .Fn bhnd_nvram_getvar_int8 , .Fn bhnd_nvram_getvar_int16 , .Fn bhnd_nvram_getvar_int32 , .Fn bhnd_nvram_getvar_uint , .Fn bhnd_nvram_getvar_uint8 , .Fn bhnd_nvram_getvar_uint16 , and .Fn bhnd_nvram_getvar_uint32 functions return 0 on success, or one of the following values on error: .Bl -tag -width Er .It Bq Er ENODEV If an NVRAM provider has not been registered with the bus. .It Bq Er ENOENT The requested variable was not found. .It Bq Er ENOMEM If the buffer of size is too small to hold the requested value. .It Bq Er EOPNOTSUPP If the value's native type is incompatible with and cannot be coerced to the requested type. .It Bq Er ERANGE If value coercion would overflow (or underflow) the requested type .El .Pp If reading the variable otherwise fails, an appropriate error code will be returned. .\" .Ss "Port/Region Functions" The .Fn bhnd_decode_port_rid function returns 0 on success, or an appropriate error code if no matching port/region is found. .Pp The .Fn bhnd_get_port_rid function returns the resource ID for the requested port and region, or -1 if the port or region are invalid, or do not have an assigned resource ID. .Pp The .Fn bhnd_get_region_addr function returns 0 on success, or an appropriate error code if no matching port/region is found. .\" .Ss "PMU Functions" The .Fn bhnd_alloc_pmu function returns 0 on success, otherwise an appropriate error code is returned. .Pp The .Fn bhnd_release_pmu function returns 0 on success, otherwise an appropriate error code is returned, and the core state will be left unmodified. .Pp The .Fn bhnd_enable_clocks and .Fn bhnd_request_clock functions return 0 on success, or one of the following values on error: .Bl -tag -width Er .It Bq Er ENODEV An unsupported clock was requested. .It Bq Er ENXIO No PMU or PWRCTL provider has been registered with the bus. .El .Pp The .Fn bhnd_get_clock_freq function returns 0 on success, or .Er ENODEV if the frequency for the specified clock is not available. .Pp The .Fn bhnd_get_clock_latency function returns 0 on success, or .Er ENODEV if the transition latency for the specified clock is not available. .Pp The .Fn bhnd_request_ext_rsrc and .Fn bhnd_release_ext_rsrc functions return 0 on success, otherwise an appropriate error code is returned. .Pp .\" .Ss "Service Provider Functions" The .Fn bhnd_register_provider function returns 0 on success, .Er EEXIST if an entry for service already exists, or an appropriate error code if service registration otherwise fails. .Pp The .Fn bhnd_deregister_provider function returns 0 on success, or .Er EBUSY if active references to the service provider exist. .Pp The .Fn bhnd_retain_provider function returns a pointer to .Vt "device_t" on success, a null pointer if the requested provider is not registered. .\" .Ss "Utility Functions" .Pp The .Fn bhnd_format_chip_id function returns the total number of bytes written on success, or a negative integer on failure. .\" .Sh SEE ALSO .Xr bhnd 4 .Xr bhnd_erom 9 .Sh AUTHORS .An -nosplit The .Nm driver programming interface and this manual page were written by .An Landon Fuller Aq Mt landonf@FreeBSD.org . Index: head/sys/dev/bhnd/bhnd_ids.h =================================================================== --- head/sys/dev/bhnd/bhnd_ids.h (revision 328182) +++ head/sys/dev/bhnd/bhnd_ids.h (revision 328183) @@ -1,1133 +1,1133 @@ /*- * SPDX-License-Identifier: ISC * * 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, 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 * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $FreeBSD$ */ #ifndef _BHND_BHND_IDS_H_ #define _BHND_BHND_IDS_H_ /* * JEDEC JEP-106 Core Vendor IDs * * These are the JEDEC JEP-106 manufacturer ID representions (with ARM's * non-standard 4-bit continutation code), as used in ARM's PrimeCell * identification registers, bcma(4) EROM core descriptors, etc. * * @note * Bus implementations that predate the adoption of ARM IP * will need to convert bus-specific vendor IDs to their BHND_MFGID * JEP-106 equivalents. * * @par ARM 4-bit Continuation Code * * BHND MFGIDs are encoded using ARM's non-standard 4-bit continuation code * format: * * @code{.unparsed} * [11:8 ][7:0 ] * [cont code][mfg id] * @endcode * * The 4-bit continuation code field specifies the number of JEP-106 * continuation codes that prefix the manufacturer's ID code. In the case of * ARM's JEP-106 ID of `0x7F 0x7F 0x7F 0x7F 0x3B`, the four 0x7F continuations * are encoded as '4' in the 4-bit continuation code field (i.e. 0x43B). */ #define BHND_MFGID_ARM 0x043b /**< arm JEP-106 vendor id */ #define BHND_MFGID_BCM 0x04bf /**< broadcom JEP-106 vendor id */ #define BHND_MFGID_MIPS 0x04a7 /**< mips JEP-106 vendor id */ #define BHND_MFGID_INVALID 0x0000 /**< invalid JEP-106 vendor id */ /* * OCP (Open Core Protocol) Vendor IDs. * * OCP-IP assigned vendor codes are used by siba(4) */ #define OCP_VENDOR_BCM 0x4243 /**< Broadcom OCP vendor id */ /* PCI vendor IDs */ #define PCI_VENDOR_EPIGRAM 0xfeda #define PCI_VENDOR_BROADCOM 0x14e4 #define PCI_VENDOR_3COM 0x10b7 #define PCI_VENDOR_NETGEAR 0x1385 #define PCI_VENDOR_DIAMOND 0x1092 #define PCI_VENDOR_INTEL 0x8086 #define PCI_VENDOR_DELL 0x1028 #define PCI_VENDOR_HP 0x103c #define PCI_VENDOR_HP_COMPAQ 0x0e11 #define PCI_VENDOR_APPLE 0x106b #define PCI_VENDOR_SI_IMAGE 0x1095 /* Silicon Image, used by Arasan SDIO Host */ #define PCI_VENDOR_BUFFALO 0x1154 /* Buffalo vendor id */ #define PCI_VENDOR_TI 0x104c /* Texas Instruments */ #define PCI_VENDOR_RICOH 0x1180 /* Ricoh */ #define PCI_VENDOR_JMICRON 0x197b /* PCMCIA vendor IDs */ #define PCMCIA_VENDOR_BROADCOM 0x02d0 /* SDIO vendor IDs */ #define SDIO_VENDOR_BROADCOM 0x00BF /* USB dongle VID/PIDs */ #define USB_VID_BROADCOM 0x0a5c #define USB_PID_BCM4328 0xbd12 #define USB_PID_BCM4322 0xbd13 #define USB_PID_BCM4319 0xbd16 #define USB_PID_BCM43236 0xbd17 #define USB_PID_BCM4332 0xbd18 #define USB_PID_BCM4330 0xbd19 #define USB_PID_BCM4334 0xbd1a #define USB_PID_BCM43239 0xbd1b #define USB_PID_BCM4324 0xbd1c #define USB_PID_BCM4360 0xbd1d #define USB_PID_BCM43143 0xbd1e #define USB_PID_BCM43242 0xbd1f #define USB_PID_BCM43342 0xbd21 #define USB_PID_BCM4335 0xbd20 #define USB_PID_BCM4350 0xbd23 #define USB_PID_BCM43341 0xbd22 #define USB_PID_BCM_DNGL_BDC 0x0bdc /* BDC USB device controller IP? */ #define USB_PID_BCM_DNGL_JTAG 0x4a44 /* HW USB BLOCK [CPULESS USB] PIDs */ #define USB_PID_CCM_HWUSB_43239 43239 /* PCI Device IDs */ #define PCI_DEVID_BCM4210 0x1072 /* never used */ #define PCI_DEVID_BCM4230 0x1086 /* never used */ #define PCI_DEVID_BCM4401_ENET 0x170c /* 4401b0 production enet cards */ #define PCI_DEVID_BCM3352 0x3352 /* bcm3352 device id */ #define PCI_DEVID_BCM3360 0x3360 /* bcm3360 device id */ #define PCI_DEVID_BCM4211 0x4211 #define PCI_DEVID_BCM4231 0x4231 #define PCI_DEVID_BCM4301 0x4301 /* 4031 802.11b */ #define PCI_DEVID_BCM4303_D11B 0x4303 /* 4303 802.11b */ #define PCI_DEVID_BCM4306 0x4306 /* 4306 802.11b/g */ #define PCI_DEVID_BCM4307 0x4307 /* 4307 802.11b, 10/100 ethernet, V.92 modem */ #define PCI_DEVID_BCM4311_D11G 0x4311 /* 4311 802.11b/g id */ #define PCI_DEVID_BCM4311_D11DUAL 0x4312 /* 4311 802.11a/b/g id */ #define PCI_DEVID_BCM4311_D11A 0x4313 /* 4311 802.11a id */ #define PCI_DEVID_BCM4328_D11DUAL 0x4314 /* 4328/4312 802.11a/g id */ #define PCI_DEVID_BCM4328_D11G 0x4315 /* 4328/4312 802.11g id */ #define PCI_DEVID_BCM4328_D11A 0x4316 /* 4328/4312 802.11a id */ #define PCI_DEVID_BCM4318_D11G 0x4318 /* 4318 802.11b/g id */ #define PCI_DEVID_BCM4318_D11DUAL 0x4319 /* 4318 802.11a/b/g id */ #define PCI_DEVID_BCM4318_D11A 0x431a /* 4318 802.11a id */ #define PCI_DEVID_BCM4325_D11DUAL 0x431b /* 4325 802.11a/g id */ #define PCI_DEVID_BCM4325_D11G 0x431c /* 4325 802.11g id */ #define PCI_DEVID_BCM4325_D11A 0x431d /* 4325 802.11a id */ #define PCI_DEVID_BCM4306_D11G 0x4320 /* 4306 802.11g */ #define PCI_DEVID_BCM4306_D11A 0x4321 /* 4306 802.11a */ #define PCI_DEVID_BCM4306_UART 0x4322 /* 4306 uart */ #define PCI_DEVID_BCM4306_V90 0x4323 /* 4306 v90 codec */ #define PCI_DEVID_BCM4306_D11DUAL 0x4324 /* 4306 dual A+B */ #define PCI_DEVID_BCM4306_D11G_ID2 0x4325 /* BCM4306_D11G; INF w/loose binding war */ #define PCI_DEVID_BCM4321_D11N 0x4328 /* 4321 802.11n dualband id */ #define PCI_DEVID_BCM4321_D11N2G 0x4329 /* 4321 802.11n 2.4Ghz band id */ #define PCI_DEVID_BCM4321_D11N5G 0x432a /* 4321 802.11n 5Ghz band id */ #define PCI_DEVID_BCM4322_D11N 0x432b /* 4322 802.11n dualband device */ #define PCI_DEVID_BCM4322_D11N2G 0x432c /* 4322 802.11n 2.4GHz device */ #define PCI_DEVID_BCM4322_D11N5G 0x432d /* 4322 802.11n 5GHz device */ #define PCI_DEVID_BCM4329_D11N 0x432e /* 4329 802.11n dualband device */ #define PCI_DEVID_BCM4329_D11N2G 0x432f /* 4329 802.11n 2.4G device */ #define PCI_DEVID_BCM4329_D11N5G 0x4330 /* 4329 802.11n 5G device */ #define PCI_DEVID_BCM4315_D11DUAL 0x4334 /* 4315 802.11a/g id */ #define PCI_DEVID_BCM4315_D11G 0x4335 /* 4315 802.11g id */ #define PCI_DEVID_BCM4315_D11A 0x4336 /* 4315 802.11a id */ #define PCI_DEVID_BCM4319_D11N 0x4337 /* 4319 802.11n dualband device */ #define PCI_DEVID_BCM4319_D11N2G 0x4338 /* 4319 802.11n 2.4G device */ #define PCI_DEVID_BCM4319_D11N5G 0x4339 /* 4319 802.11n 5G device */ #define PCI_DEVID_BCM43231_D11N2G 0x4340 /* 43231 802.11n 2.4GHz device */ #define PCI_DEVID_BCM43221_D11N2G 0x4341 /* 43221 802.11n 2.4GHz device */ #define PCI_DEVID_BCM43222_D11N 0x4350 /* 43222 802.11n dualband device */ #define PCI_DEVID_BCM43222_D11N2G 0x4351 /* 43222 802.11n 2.4GHz device */ #define PCI_DEVID_BCM43222_D11N5G 0x4352 /* 43222 802.11n 5GHz device */ #define PCI_DEVID_BCM43224_D11N 0x4353 /* 43224 802.11n dualband device */ #define PCI_DEVID_BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db device */ #define PCI_DEVID_BCM43226_D11N 0x4354 /* 43226 802.11n dualband device */ #define PCI_DEVID_BCM43236_D11N 0x4346 /* 43236 802.11n dualband device */ #define PCI_DEVID_BCM43236_D11N2G 0x4347 /* 43236 802.11n 2.4GHz device */ #define PCI_DEVID_BCM43236_D11N5G 0x4348 /* 43236 802.11n 5GHz device */ #define PCI_DEVID_BCM43225_D11N2G 0x4357 /* 43225 802.11n 2.4GHz device */ #define PCI_DEVID_BCM43421_D11N 0xA99D /* 43421 802.11n dualband device */ #define PCI_DEVID_BCM4313_D11N2G 0x4727 /* 4313 802.11n 2.4G device */ #define PCI_DEVID_BCM4330_D11N 0x4360 /* 4330 802.11n dualband device */ #define PCI_DEVID_BCM4330_D11N2G 0x4361 /* 4330 802.11n 2.4G device */ #define PCI_DEVID_BCM4330_D11N5G 0x4362 /* 4330 802.11n 5G device */ #define PCI_DEVID_BCM4336_D11N 0x4343 /* 4336 802.11n 2.4GHz device */ #define PCI_DEVID_BCM6362_D11N 0x435f /* 6362 802.11n dualband device */ #define PCI_DEVID_BCM6362_D11N2G 0x433f /* 6362 802.11n 2.4Ghz band id */ #define PCI_DEVID_BCM6362_D11N5G 0x434f /* 6362 802.11n 5Ghz band id */ #define PCI_DEVID_BCM4331_D11N 0x4331 /* 4331 802.11n dualband id */ #define PCI_DEVID_BCM4331_D11N2G 0x4332 /* 4331 802.11n 2.4Ghz band id */ #define PCI_DEVID_BCM4331_D11N5G 0x4333 /* 4331 802.11n 5Ghz band id */ #define PCI_DEVID_BCM43237_D11N 0x4355 /* 43237 802.11n dualband device */ #define PCI_DEVID_BCM43237_D11N5G 0x4356 /* 43237 802.11n 5GHz device */ #define PCI_DEVID_BCM43227_D11N2G 0x4358 /* 43228 802.11n 2.4GHz device */ #define PCI_DEVID_BCM43228_D11N 0x4359 /* 43228 802.11n DualBand device */ #define PCI_DEVID_BCM43228_D11N5G 0x435a /* 43228 802.11n 5GHz device */ #define PCI_DEVID_BCM43362_D11N 0x4363 /* 43362 802.11n 2.4GHz device */ #define PCI_DEVID_BCM43239_D11N 0x4370 /* 43239 802.11n dualband device */ #define PCI_DEVID_BCM4324_D11N 0x4374 /* 4324 802.11n dualband device */ #define PCI_DEVID_BCM43217_D11N2G 0x43a9 /* 43217 802.11n 2.4GHz device */ #define PCI_DEVID_BCM43131_D11N2G 0x43aa /* 43131 802.11n 2.4GHz device */ #define PCI_DEVID_BCM4314_D11N2G 0x4364 /* 4314 802.11n 2.4G device */ #define PCI_DEVID_BCM43142_D11N2G 0x4365 /* 43142 802.11n 2.4G device */ #define PCI_DEVID_BCM43143_D11N2G 0x4366 /* 43143 802.11n 2.4G device */ #define PCI_DEVID_BCM4334_D11N 0x4380 /* 4334 802.11n dualband device */ #define PCI_DEVID_BCM4334_D11N2G 0x4381 /* 4334 802.11n 2.4G device */ #define PCI_DEVID_BCM4334_D11N5G 0x4382 /* 4334 802.11n 5G device */ #define PCI_DEVID_BCM43342_D11N 0x4383 /* 43342 802.11n dualband device */ #define PCI_DEVID_BCM43342_D11N2G 0x4384 /* 43342 802.11n 2.4G device */ #define PCI_DEVID_BCM43342_D11N5G 0x4385 /* 43342 802.11n 5G device */ #define PCI_DEVID_BCM43341_D11N 0x4386 /* 43341 802.11n dualband device */ #define PCI_DEVID_BCM43341_D11N2G 0x4387 /* 43341 802.11n 2.4G device */ #define PCI_DEVID_BCM43341_D11N5G 0x4388 /* 43341 802.11n 5G device */ #define PCI_DEVID_BCM4360_D11AC 0x43a0 #define PCI_DEVID_BCM4360_D11AC2G 0x43a1 #define PCI_DEVID_BCM4360_D11AC5G 0x43a2 #define PCI_DEVID_BCM4335_D11AC 0x43ae #define PCI_DEVID_BCM4335_D11AC2G 0x43af #define PCI_DEVID_BCM4335_D11AC5G 0x43b0 #define PCI_DEVID_BCM4352_D11AC 0x43b1 /* 4352 802.11ac dualband device */ #define PCI_DEVID_BCM4352_D11AC2G 0x43b2 /* 4352 802.11ac 2.4G device */ #define PCI_DEVID_BCM4352_D11AC5G 0x43b3 /* 4352 802.11ac 5G device */ #define PCI_DEVID_PCIXX21_FLASHMEDIA0 0x8033 /* TI PCI xx21 Standard Host Controller */ #define PCI_DEVID_PCIXX21_SDIOH0 0x8034 /* TI PCI xx21 Standard Host Controller */ /* PCI Subsystem Vendor IDs */ #define PCI_SUBVENDOR_BCM943228HMB 0x0607 #define PCI_SUBVENDOR_BCM94313HMGBL 0x0608 #define PCI_SUBVENDOR_BCM94313HMG 0x0609 #define PCI_SUBVENDOR_BCM943142HM 0x0611 /* PCI Subsystem Device IDs */ #define PCI_SUBDEVID_BCM43143_D11N2G 0x4366 /* 43143 802.11n 2.4G device */ #define PCI_SUBDEVID_BCM43242_D11N 0x4367 /* 43242 802.11n dualband device */ #define PCI_SUBDEVID_BCM43242_D11N2G 0x4368 /* 43242 802.11n 2.4G device */ #define PCI_SUBDEVID_BCM43242_D11N5G 0x4369 /* 43242 802.11n 5G device */ #define PCI_SUBDEVID_BCM4350_D11AC 0x43a3 #define PCI_SUBDEVID_BCM4350_D11AC2G 0x43a4 #define PCI_SUBDEVID_BCM4350_D11AC5G 0x43a5 #define PCI_SUBDEVID_BCMGPRS_UART 0x4333 /* Uart id used by 4306/gprs card */ #define PCI_SUBDEVID_BCMGPRS2_UART 0x4344 /* Uart id used by 4306/gprs card */ #define PCI_SUBDEVID_BCM_FPGA_JTAGM 0x43f0 /* FPGA jtagm device id */ #define PCI_SUBDEVID_BCM_JTAGM 0x43f1 /* BCM jtagm device id */ #define PCI_SUBDEVID_BCM_SDIOH_FPGA 0x43f2 /* sdio host fpga */ #define PCI_SUBDEVID_BCM_SDIOH 0x43f3 /* BCM sdio host id */ #define PCI_SUBDEVID_BCM_SDIOD_FPGA 0x43f4 /* sdio device fpga */ #define PCI_SUBDEVID_BCM_SPIH_FPGA 0x43f5 /* PCI SPI Host Controller FPGA */ #define PCI_SUBDEVID_BCM_SPIH 0x43f6 /* Synopsis SPI Host Controller */ #define PCI_SUBDEVID_BCM_MIMO_FPGA 0x43f8 /* FPGA mimo minimacphy device id */ #define PCI_SUBDEVID_BCM_JTAGM2 0x43f9 /* PCI_SUBDEVID_BCM alternate jtagm device id */ #define PCI_SUBDEVID_BCM_SDHCI_FPGA 0x43fa /* Standard SDIO Host Controller FPGA */ #define PCI_SUBDEVID_BCM4402_ENET 0x4402 /* 4402 enet */ #define PCI_SUBDEVID_BCM4402_V90 0x4403 /* 4402 v90 codec */ #define PCI_SUBDEVID_BCM4410 0x4410 /* bcm44xx family pci iline */ #define PCI_SUBDEVID_BCM4412 0x4412 /* bcm44xx family pci enet */ #define PCI_SUBDEVID_BCM4430 0x4430 /* bcm44xx family cardbus iline */ #define PCI_SUBDEVID_BCM4432 0x4432 /* bcm44xx family cardbus enet */ #define PCI_SUBDEVID_BCM4704_ENET 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ #define PCI_SUBDEVID_BCM4710 0x4710 /* 4710 primary function 0 */ #define PCI_SUBDEVID_BCM47XX_AUDIO 0x4711 /* 47xx audio codec */ #define PCI_SUBDEVID_BCM47XX_V90 0x4712 /* 47xx v90 codec */ #define PCI_SUBDEVID_BCM47XX_ENET 0x4713 /* 47xx enet */ #define PCI_SUBDEVID_BCM47XX_EXT 0x4714 /* 47xx external i/f */ #define PCI_SUBDEVID_BCM47XX_GMAC 0x4715 /* 47xx Unimac based GbE */ #define PCI_SUBDEVID_BCM47XX_USBH 0x4716 /* 47xx usb host */ #define PCI_SUBDEVID_BCM47XX_USBD 0x4717 /* 47xx usb device */ #define PCI_SUBDEVID_BCM47XX_IPSEC 0x4718 /* 47xx ipsec */ #define PCI_SUBDEVID_BCM47XX_ROBO 0x4719 /* 47xx/53xx roboswitch core */ #define PCI_SUBDEVID_BCM47XX_USB20H 0x471a /* 47xx usb 2.0 host */ #define PCI_SUBDEVID_BCM47XX_USB20D 0x471b /* 47xx usb 2.0 device */ #define PCI_SUBDEVID_BCM47XX_ATA100 0x471d /* 47xx parallel ATA */ #define PCI_SUBDEVID_BCM47XX_SATAXOR 0x471e /* 47xx serial ATA & XOR DMA */ #define PCI_SUBDEVID_BCM47XX_GIGETH 0x471f /* 47xx GbE (5700) */ #define PCI_SUBDEVID_BCM4712_MIPS 0x4720 /* 4712 base devid */ #define PCI_SUBDEVID_BCM4716 0x4722 /* 4716 base devid */ #define PCI_SUBDEVID_BCM47XX_USB30H 0x472a /* 47xx usb 3.0 host */ #define PCI_SUBDEVID_BCM47XX_USB30D 0x472b /* 47xx usb 3.0 device */ #define PCI_SUBDEVID_BCM47XX_SMBUS_EMU 0x47fe /* 47xx emulated SMBus device */ #define PCI_SUBDEVID_BCM47XX_XOR_EMU 0x47ff /* 47xx emulated XOR engine */ #define PCI_SUBDEVID_BCM_EPI41210 0xa0fa /* bcm4210 */ #define PCI_SUBDEVID_BCM_EPI41230 0xa10e /* bcm4230 */ #define PCI_SUBDEVID_BCM_JINVANI_SDIOH 0x4743 /* Jinvani SDIO Gold Host */ #define PCI_SUBDEVID_BCM27XX_SDIOH 0x2702 /* PCI_SUBDEVID_BCM27xx Standard SDIO Host */ #define PCI_SUBDEVID_BCM_PCIXX21_FLASHMEDIA 0x803b /* TI PCI xx21 Standard Host Controller */ #define PCI_SUBDEVID_BCM_PCIXX21_SDIOH 0x803c /* TI PCI xx21 Standard Host Controller */ #define PCI_SUBDEVID_BCM_R5C822_SDIOH 0x0822 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host */ #define PCI_SUBDEVID_BCM_JMICRON_SDIOH 0x2381 /* JMicron Standard SDIO Host Controller */ /* Broadcom ChipCommon Chip IDs */ #define BHND_CHIPID_BCM4306 0x4306 /* 4306 chipcommon chipid */ #define BHND_CHIPID_BCM4311 0x4311 /* 4311 PCIe 802.11a/b/g */ #define BHND_CHIPID_BCM43111 43111 /* 43111 chipcommon chipid (OTP chipid) */ #define BHND_CHIPID_BCM43112 43112 /* 43112 chipcommon chipid (OTP chipid) */ #define BHND_CHIPID_BCM4312 0x4312 /* 4312 chipcommon chipid */ #define BHND_CHIPID_BCM4313 0x4313 /* 4313 chip id */ #define BHND_CHIPID_BCM43131 43131 /* 43131 chip id (OTP chipid) */ #define BHND_CHIPID_BCM4315 0x4315 /* 4315 chip id */ #define BHND_CHIPID_BCM4318 0x4318 /* 4318 chipcommon chipid */ #define BHND_CHIPID_BCM4319 0x4319 /* 4319 chip id */ #define BHND_CHIPID_BCM4320 0x4320 /* 4320 chipcommon chipid */ #define BHND_CHIPID_BCM4321 0x4321 /* 4321 chipcommon chipid */ #define BHND_CHIPID_BCM43217 43217 /* 43217 chip id (OTP chipid) */ #define BHND_CHIPID_BCM4322 0x4322 /* 4322 chipcommon chipid */ #define BHND_CHIPID_BCM43221 43221 /* 43221 chipcommon chipid (OTP chipid) */ #define BHND_CHIPID_BCM43222 43222 /* 43222 chipcommon chipid */ #define BHND_CHIPID_BCM43224 43224 /* 43224 chipcommon chipid */ #define BHND_CHIPID_BCM43225 43225 /* 43225 chipcommon chipid */ #define BHND_CHIPID_BCM43227 43227 /* 43227 chipcommon chipid */ #define BHND_CHIPID_BCM43228 43228 /* 43228 chipcommon chipid */ #define BHND_CHIPID_BCM43226 43226 /* 43226 chipcommon chipid */ #define BHND_CHIPID_BCM43231 43231 /* 43231 chipcommon chipid (OTP chipid) */ #define BHND_CHIPID_BCM43234 43234 /* 43234 chipcommon chipid */ #define BHND_CHIPID_BCM43235 43235 /* 43235 chipcommon chipid */ #define BHND_CHIPID_BCM43236 43236 /* 43236 chipcommon chipid */ #define BHND_CHIPID_BCM43237 43237 /* 43237 chipcommon chipid */ #define BHND_CHIPID_BCM43238 43238 /* 43238 chipcommon chipid */ #define BHND_CHIPID_BCM43239 43239 /* 43239 chipcommon chipid */ #define BHND_CHIPID_BCM43420 43420 /* 43222 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM43421 43421 /* 43224 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM43428 43428 /* 43228 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM43431 43431 /* 4331 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM43460 43460 /* 4360 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM43462 0xA9C6 /* 43462 chipcommon chipid */ #define BHND_CHIPID_BCM4325 0x4325 /* 4325 chip id */ #define BHND_CHIPID_BCM4328 0x4328 /* 4328 chip id */ #define BHND_CHIPID_BCM4329 0x4329 /* 4329 chipcommon chipid */ #define BHND_CHIPID_BCM4331 0x4331 /* 4331 chipcommon chipid */ #define BHND_CHIPID_BCM4336 0x4336 /* 4336 chipcommon chipid */ #define BHND_CHIPID_BCM43362 43362 /* 43362 chipcommon chipid */ #define BHND_CHIPID_BCM4330 0x4330 /* 4330 chipcommon chipid */ #define BHND_CHIPID_BCM6362 0x6362 /* 6362 chipcommon chipid */ #define BHND_CHIPID_BCM4314 0x4314 /* 4314 chipcommon chipid */ #define BHND_CHIPID_BCM43142 43142 /* 43142 chipcommon chipid */ #define BHND_CHIPID_BCM43143 43143 /* 43143 chipcommon chipid */ #define BHND_CHIPID_BCM4324 0x4324 /* 4324 chipcommon chipid */ #define BHND_CHIPID_BCM43242 43242 /* 43242 chipcommon chipid */ #define BHND_CHIPID_BCM43243 43243 /* 43243 chipcommon chipid */ #define BHND_CHIPID_BCM4334 0x4334 /* 4334 chipcommon chipid */ #define BHND_CHIPID_BCM4335 0x4335 /* 4335 chipcommon chipid */ #define BHND_CHIPID_BCM4360 0x4360 /* 4360 chipcommon chipid */ #define BHND_CHIPID_BCM43602 0xaa52 /* 43602 chipcommon chipid */ #define BHND_CHIPID_BCM4352 0x4352 /* 4352 chipcommon chipid */ #define BHND_CHIPID_BCM43526 0xAA06 #define BHND_CHIPID_BCM43341 43341 /* 43341 chipcommon chipid */ #define BHND_CHIPID_BCM43342 43342 /* 43342 chipcommon chipid */ #define BHND_CHIPID_BCM4335 0x4335 #define BHND_CHIPID_BCM4350 0x4350 /* 4350 chipcommon chipid */ #define BHND_CHIPID_BCM4342 4342 /* 4342 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM4402 0x4402 /* 4402 chipid */ #define BHND_CHIPID_BCM4704 0x4704 /* 4704 chipcommon chipid */ #define BHND_CHIPID_BCM4706 0x5300 /* 4706 chipcommon chipid */ #define BHND_CHIPID_BCM4707 53010 /* 4707 chipcommon chipid */ #define BHND_CHIPID_BCM53018 53018 /* 53018 chipcommon chipid */ #define BHND_CHIPID_IS_BCM4707(chipid) \ (((chipid) == BHND_CHIPID_BCM4707) || \ ((chipid) == BHND_CHIPID_BCM53018)) #define BHND_CHIPID_BCM4710 0x4710 /* 4710 chipid */ #define BHND_CHIPID_BCM4712 0x4712 /* 4712 chipcommon chipid */ #define BHND_CHIPID_BCM4716 0x4716 /* 4716 chipcommon chipid */ #define BHND_CHIPID_BCM47162 47162 /* 47162 chipcommon chipid */ #define BHND_CHIPID_BCM4748 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM4749 0x4749 /* 5357 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM4785 0x4785 /* 4785 chipcommon chipid */ #define BHND_CHIPID_BCM5350 0x5350 /* 5350 chipcommon chipid */ #define BHND_CHIPID_BCM5352 0x5352 /* 5352 chipcommon chipid */ #define BHND_CHIPID_BCM5354 0x5354 /* 5354 chipcommon chipid */ #define BHND_CHIPID_BCM5365 0x5365 /* 5365 chipcommon chipid */ #define BHND_CHIPID_BCM5356 0x5356 /* 5356 chipcommon chipid */ #define BHND_CHIPID_BCM5357 0x5357 /* 5357 chipcommon chipid */ #define BHND_CHIPID_BCM53572 53572 /* 53572 chipcommon chipid */ /* Broadcom ChipCommon Package IDs */ #define BHND_PKGID_BCM4303 2 /* 4303 package id */ #define BHND_PKGID_BCM4309 1 /* 4309 package id */ #define BHND_PKGID_BCM4712LARGE 0 /* 340pin 4712 package id */ #define BHND_PKGID_BCM4712SMALL 1 /* 200pin 4712 package id */ #define BHND_PKGID_BCM4712MID 2 /* 225pin 4712 package id */ #define BHND_PKGID_BCM4328USBD11G 2 /* 4328 802.11g USB package id */ #define BHND_PKGID_BCM4328USBDUAL 3 /* 4328 802.11a/g USB package id */ #define BHND_PKGID_BCM4328SDIOD11G 4 /* 4328 802.11g SDIO package id */ #define BHND_PKGID_BCM4328SDIODUAL 5 /* 4328 802.11a/g SDIO package id */ #define BHND_PKGID_BCM4329_289PIN 0 /* 4329 289-pin package id */ #define BHND_PKGID_BCM4329_182PIN 1 /* 4329N 182-pin package id */ #define BHND_PKGID_BCM5354E 1 /* 5354E package id */ #define BHND_PKGID_BCM4716 8 /* 4716 package id */ #define BHND_PKGID_BCM4717 9 /* 4717 package id */ #define BHND_PKGID_BCM4718 10 /* 4718 package id */ #define BHND_PKGID_BCM5356_NONMODE 1 /* 5356 package without nmode suppport */ #define BHND_PKGID_BCM5358U 8 /* 5358U package id */ #define BHND_PKGID_BCM5358 9 /* 5358 package id */ #define BHND_PKGID_BCM47186 10 /* 47186 package id */ #define BHND_PKGID_BCM5357 11 /* 5357 package id */ #define BHND_PKGID_BCM5356U 12 /* 5356U package id */ #define BHND_PKGID_BCM53572 8 /* 53572 package id */ #define BHND_PKGID_BCM5357C0 8 /* 5357c0 package id (the same as 53572) */ #define BHND_PKGID_BCM47188 9 /* 47188 package id */ #define BHND_PKGID_BCM5358C0 0xa /* 5358c0 package id */ #define BHND_PKGID_BCM5356C0 0xb /* 5356c0 package id */ #define BHND_PKGID_BCM4331TT 8 /* 4331 12x12 package id */ #define BHND_PKGID_BCM4331TN 9 /* 4331 12x9 package id */ #define BHND_PKGID_BCM4331TNA0 0xb /* 4331 12x9 package id */ #define BHND_PKGID_BCM4706L 1 /* 4706L package id */ #define BHND_PKGID_HDLSIM5350 1 /* HDL simulator package id for a 5350 */ #define BHND_PKGID_HDLSIM 14 /* HDL simulator package id */ #define BHND_PKGID_HWSIM 15 /* Hardware simulator package id */ #define BHND_PKGID_BCM43224_FAB_CSM 0x8 /* the chip is manufactured by CSM */ #define BHND_PKGID_BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ #define BHND_PKGID_BCM4336_WLBGA 0x8 #define BHND_PKGID_BCM4330_WLBGA 0x0 #define BHND_PKGID_BCM4314PCIE_ARM (8 | 0) /* 4314 QFN PCI package id, bit 3 tie high */ #define BHND_PKGID_BCM4314SDIO (8 | 1) /* 4314 QFN SDIO package id */ #define BHND_PKGID_BCM4314PCIE (8 | 2) /* 4314 QFN PCI (ARM-less) package id */ #define BHND_PKGID_BCM4314SDIO_ARM (8 | 3) /* 4314 QFN SDIO (ARM-less) package id */ #define BHND_PKGID_BCM4314SDIO_FPBGA (8 | 4) /* 4314 FpBGA SDIO package id */ #define BHND_PKGID_BCM4314DEV (8 | 6) /* 4314 Development package id */ #define BHND_PKGID_BCM4707 1 /* 4707 package id */ #define BHND_PKGID_BCM4708 2 /* 4708 package id */ #define BHND_PKGID_BCM4709 0 /* 4709 package id */ #define BHND_PKGID_BCM4335_WLCSP (0x0) /* WLCSP Module/Mobile SDIO/HSIC. */ #define BHND_PKGID_BCM4335_FCBGA (0x1) /* FCBGA PC/Embedded/Media PCIE/SDIO */ #define BHND_PKGID_BCM4335_WLBGA (0x2) /* WLBGA COB/Mobile SDIO/HSIC. */ #define BHND_PKGID_BCM4335_FCBGAD (0x3) /* FCBGA Debug Debug/Dev All if's. */ #define BHND_PKGID_PKG_MASK_BCM4335 (0x3) /* Broadcom Core IDs */ #define BHND_COREID_INVALID 0x700 /* Invalid coreid */ #define BHND_COREID_CC 0x800 /* chipcommon core */ #define BHND_COREID_ILINE20 0x801 /* iline20 core */ #define BHND_COREID_SRAM 0x802 /* sram core */ #define BHND_COREID_SDRAM 0x803 /* sdram core */ #define BHND_COREID_PCI 0x804 /* pci core */ #define BHND_COREID_MIPS 0x805 /* mips core */ #define BHND_COREID_ENET 0x806 /* enet mac core */ -#define BHND_COREID_CODEC 0x807 /* v90 codec core */ +#define BHND_COREID_V90_CODEC 0x807 /* v90 codec core */ #define BHND_COREID_USB 0x808 /* usb 1.1 host/device core */ #define BHND_COREID_ADSL 0x809 /* ADSL core */ #define BHND_COREID_ILINE100 0x80a /* iline100 core */ #define BHND_COREID_IPSEC 0x80b /* ipsec core */ #define BHND_COREID_UTOPIA 0x80c /* utopia core */ #define BHND_COREID_PCMCIA 0x80d /* pcmcia core */ #define BHND_COREID_SOCRAM 0x80e /* internal memory core */ #define BHND_COREID_MEMC 0x80f /* memc sdram core */ #define BHND_COREID_OFDM 0x810 /* OFDM phy core */ #define BHND_COREID_EXTIF 0x811 /* external interface core */ #define BHND_COREID_D11 0x812 /* 802.11 MAC core */ #define BHND_COREID_APHY 0x813 /* 802.11a phy core */ #define BHND_COREID_BPHY 0x814 /* 802.11b phy core */ #define BHND_COREID_GPHY 0x815 /* 802.11g phy core */ #define BHND_COREID_MIPS33 0x816 /* mips3302 core */ #define BHND_COREID_USB11H 0x817 /* usb 1.1 host core */ #define BHND_COREID_USB11D 0x818 /* usb 1.1 device core */ #define BHND_COREID_USB20H 0x819 /* usb 2.0 host core */ #define BHND_COREID_USB20D 0x81a /* usb 2.0 device core */ #define BHND_COREID_SDIOH 0x81b /* sdio host core */ #define BHND_COREID_ROBO 0x81c /* roboswitch core */ #define BHND_COREID_ATA100 0x81d /* parallel ATA core */ #define BHND_COREID_SATAXOR 0x81e /* serial ATA & XOR DMA core */ #define BHND_COREID_GIGETH 0x81f /* gigabit ethernet core */ #define BHND_COREID_PCIE 0x820 /* pci express core */ #define BHND_COREID_NPHY 0x821 /* 802.11n 2x2 phy core */ #define BHND_COREID_SRAMC 0x822 /* SRAM controller core */ #define BHND_COREID_MINIMAC 0x823 /* MINI MAC/phy core */ #define BHND_COREID_ARM11 0x824 /* ARM 1176 core */ #define BHND_COREID_ARM7S 0x825 /* ARM7tdmi-s core */ #define BHND_COREID_LPPHY 0x826 /* 802.11a/b/g phy core */ #define BHND_COREID_PMU 0x827 /* PMU core */ #define BHND_COREID_SSNPHY 0x828 /* 802.11n single-stream phy core */ #define BHND_COREID_SDIOD 0x829 /* SDIO device core */ #define BHND_COREID_ARMCM3 0x82a /* ARM Cortex M3 core */ #define BHND_COREID_HTPHY 0x82b /* 802.11n 4x4 phy core */ #define BHND_COREID_MIPS74K 0x82c /* mips 74k core */ #define BHND_COREID_GMAC 0x82d /* Gigabit MAC core */ #define BHND_COREID_DMEMC 0x82e /* DDR1/2 memory controller core */ #define BHND_COREID_PCIERC 0x82f /* PCIE Root Complex core */ #define BHND_COREID_OCP 0x830 /* OCP2OCP bridge core */ #define BHND_COREID_SC 0x831 /* shared common core */ #define BHND_COREID_AHB 0x832 /* OCP2AHB bridge core */ #define BHND_COREID_SPIH 0x833 /* SPI host core */ #define BHND_COREID_I2S 0x834 /* I2S core */ #define BHND_COREID_DMEMS 0x835 /* SDR/DDR1 memory controller core */ #define BHND_COREID_UBUS_SHIM 0x837 /* SHIM component in ubus/6362 */ #define BHND_COREID_PCIE2 0x83c /* pci express (gen2) core */ /* ARM/AMBA Core IDs */ #define BHND_COREID_APB_BRIDGE 0x135 /* BP135 AMBA AXI-APB bridge */ #define BHND_COREID_PL301 0x301 /* PL301 AMBA AXI Interconnect */ #define BHND_COREID_EROM 0x366 /* Enumeration ROM */ #define BHND_COREID_OOB_ROUTER 0x367 /* OOB router core ID */ #define BHND_COREID_AXI_UNMAPPED 0xfff /* AXI "Default Slave"; maps all unused address * ranges, returning DECERR on read or write. */ /* Northstar Plus and BCM4706 Core IDs */ #define BHND_COREID_4706_CC 0x500 /* chipcommon core */ #define BHND_COREID_NS_PCIE2 0x501 /* pci express (gen2) core */ #define BHND_COREID_NS_DMA 0x502 /* dma core */ #define BHND_COREID_NS_SDIO 0x503 /* sdio host core */ #define BHND_COREID_NS_USB20H 0x504 /* usb 2.0 host core */ #define BHND_COREID_NS_USB30H 0x505 /* usb 3.0 host core */ #define BHND_COREID_NS_A9JTAG 0x506 /* ARM Cortex A9 JTAG core */ #define BHND_COREID_NS_DDR23_MEMC 0x507 /* DDR2/3 cadence/denali memory controller core () */ #define BHND_COREID_NS_ROM 0x508 /* device ROM core */ #define BHND_COREID_NS_NAND 0x509 /* NAND flash controller core */ #define BHND_COREID_NS_QSPI 0x50a /* QSPI flash controller core */ #define BHND_COREID_NS_CC_B 0x50b /* chipcommon `b' (auxiliary) core */ #define BHND_COREID_4706_SOCRAM 0x50e /* internal memory core */ #define BHND_COREID_IHOST_ARMCA9 0x510 /* ARM Cortex A9 core */ #define BHND_COREID_4706_GMAC_CMN 0x5dc /* Gigabit MAC common core */ #define BHND_COREID_4706_GMAC 0x52d /* Gigabit MAC core */ #define BHND_COREID_AMEMC 0x52e /* DDR1/2 cadence/denali memory controller core */ /* ARM PrimeCell Peripherial IDs. These were derived from inspection of the * PrimeCell-compatible BCM4331 cores, but due to lack of documentation, the * surmised core name/description may be incorrect. */ #define BHND_PRIMEID_EROM 0x364 /* Enumeration ROM's primecell ID */ #define BHND_PRIMEID_SWRAP 0x368 /* PL368 Device Management Interface (Slave) */ #define BHND_PRIMEID_MWRAP 0x369 /* PL369 Device Management Interface (Master) */ /* Core HW Revision Numbers */ #define BHND_HWREV_INVALID 0xFF /* Invalid hardware revision ID */ /* Chip Types */ #define BHND_CHIPTYPE_SIBA 0 /**< siba(4) interconnect */ #define BHND_CHIPTYPE_BCMA 1 /**< bcma(4) interconnect */ #define BHND_CHIPTYPE_UBUS 2 /**< ubus interconnect found in bcm63xx devices */ #define BHND_CHIPTYPE_BCMA_ALT 3 /**< bcma(4) interconnect */ /** Evaluates to true if @p _type is a BCMA or BCMA-compatible interconenct */ #define BHND_CHIPTYPE_IS_BCMA_COMPATIBLE(_type) \ ((_type) == BHND_CHIPTYPE_BCMA || \ (_type) == BHND_CHIPTYPE_BCMA_ALT || \ (_type) == BHND_CHIPTYPE_UBUS) /** Evaluates to true if @p _type uses a BCMA EROM table */ #define BHND_CHIPTYPE_HAS_EROM(_type) \ BHND_CHIPTYPE_IS_BCMA_COMPATIBLE(_type) /* Boardflags */ #define BHND_BFL_BTC2WIRE 0x00000001 /* old 2wire Bluetooth coexistence, OBSOLETE */ #define BHND_BFL_BTCOEX 0x00000001 /* Board supports BTCOEX */ #define BHND_BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */ #define BHND_BFL_AIRLINEMODE 0x00000004 /* Board implements gpio 13 radio disable indication, UNUSED */ #define BHND_BFL_ADCDIV 0x00000008 /* Board has the rssi ADC divider */ #define BHND_BFL_DIS_256QAM 0x00000008 #define BHND_BFL_ENETROBO 0x00000010 /* Board has robo switch or core */ #define BHND_BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */ #define BHND_BFL_CCKHIPWR 0x00000040 /* Can do high-power CCK transmission */ #define BHND_BFL_ENETADM 0x00000080 /* Board has ADMtek switch */ #define BHND_BFL_ENETVLAN 0x00000100 /* Board has VLAN capability */ #define BHND_BFL_LTECOEX 0x00000200 /* Board has LTE coex capability */ #define BHND_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ #define BHND_BFL_FEM 0x00000800 /* Board supports the Front End Module */ #define BHND_BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */ #define BHND_BFL_HGPA 0x00002000 /* Board has a high gain PA */ #define BHND_BFL_BTC2WIRE_ALTGPIO 0x00004000 /* Board's BTC 2wire is in the alternate gpios OBSLETE */ #define BHND_BFL_ALTIQ 0x00008000 /* Alternate I/Q settings */ #define BHND_BFL_NOPA 0x00010000 /* Board has no PA */ #define BHND_BFL_RSSIINV 0x00020000 /* Board's RSSI uses positive slope(not TSSI) */ #define BHND_BFL_PAREF 0x00040000 /* Board uses the PARef LDO */ #define BHND_BFL_3TSWITCH 0x00080000 /* Board uses a triple throw switch shared with BT */ #define BHND_BFL_PHASESHIFT 0x00100000 /* Board can support phase shifter */ #define BHND_BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */ #define BHND_BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */ #define BHND_BFL_RXCHAIN_OFF_BT 0x00400000 /* one rxchain is to be shut off when BT is active */ #define BHND_BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */ #define BHND_BFL_CCKFAVOREVM 0x01000000 /* Favor CCK EVM over spectral mask */ #define BHND_BFL_PALDO 0x02000000 /* Power topology uses PALDO */ #define BHND_BFL_LNLDO2_2P5 0x04000000 /* Select 2.5V as LNLDO2 output voltage */ #define BHND_BFL_FASTPWR 0x08000000 #define BHND_BFL_UCPWRCTL_MININDX 0x08000000 /* Enforce min power index to avoid FEM damage */ #define BHND_BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */ #define BHND_BFL_TRSW_1by2 0x20000000 /* Board has 2 TRSW's in 1by2 designs */ #define BHND_BFL_GAINBOOSTA01 0x20000000 /* 5g Gainboost for core0 and core1 */ #define BHND_BFL_LO_TRSW_R_5GHz 0x40000000 /* In 5G do not throw TRSW to T for clipLO gain */ #define BHND_BFL_ELNA_GAINDEF 0x80000000 /* Backoff InitGain based on elna_2g/5g field * when this flag is set */ #define BHND_BFL_EXTLNA_TX 0x20000000 /* Temp boardflag to indicate to */ /* Boardflags2 */ #define BHND_BFL2_RXBB_INT_REG_DIS 0x00000001 /* Board has an external rxbb regulator */ #define BHND_BFL2_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */ #define BHND_BFL2_TXPWRCTRL_EN 0x00000004 /* Board permits enabling TX Power Control */ #define BHND_BFL2_2X4_DIV 0x00000008 /* Board supports the 2X4 diversity switch */ #define BHND_BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */ #define BHND_BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */ #define BHND_BFL2_CAESERS_BRD 0x00000040 /* Board is Caesers brd (unused by sw) */ #define BHND_BFL2_BTC3WIRE 0x00000080 /* Board support legacy 3 wire or 4 wire */ #define BHND_BFL2_BTCLEGACY 0x00000080 /* Board support legacy 3/4 wire, to replace * BHND_BFL2_BTC3WIRE */ #define BHND_BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */ #define BHND_BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */ #define BHND_BFL2_GPLL_WAR 0x00000400 /* Flag to narrow G-band PLL loop b/w */ #define BHND_BFL2_TRISTATE_LED 0x00000800 /* Tri-state the LED */ #define BHND_BFL2_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */ #define BHND_BFL2_2G_SPUR_WAR 0x00002000 /* WAR to reduce and avoid clock-harmonic spurs in 2G */ #define BHND_BFL2_BPHY_ALL_TXCORES 0x00004000 /* Transmit bphy frames using all tx cores */ #define BHND_BFL2_FCC_BANDEDGE_WAR 0x00008000 /* Activates WAR to improve FCC bandedge performance */ #define BHND_BFL2_GPLL_WAR2 0x00010000 /* Flag to widen G-band PLL loop b/w */ #define BHND_BFL2_IPALVLSHIFT_3P3 0x00020000 #define BHND_BFL2_INTERNDET_TXIQCAL 0x00040000 /* Use internal envelope detector for TX IQCAL */ #define BHND_BFL2_XTALBUFOUTEN 0x00080000 /* Keep the buffered Xtal output from radio on */ /* Most drivers will turn it off without this flag */ /* to save power. */ #define BHND_BFL2_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are controlled by analog PA ctrl lines */ #define BHND_BFL2_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are controlled by analog PA ctrl lines */ #define BHND_BFL2_ELNACTRL_TRSW_2G 0x00400000 /* AZW4329: 2G gmode_elna_gain controls TR Switch */ #define BHND_BFL2_BT_SHARE_ANT0 0x00800000 /* WLAN/BT share antenna 0 */ #define BHND_BFL2_BT_SHARE_BM_BIT0 0x00800000 /* bit 0 of WLAN/BT shared core bitmap */ #define BHND_BFL2_TEMPSENSE_HIGHER 0x01000000 /* The tempsense threshold can sustain higher value * than programmed. The exact delta is decided by * driver per chip/boardtype. This can be used * when tempsense qualification happens after shipment */ #define BHND_BFL2_BTC3WIREONLY 0x02000000 /* standard 3 wire btc only. 4 wire not supported */ #define BHND_BFL2_PWR_NOMINAL 0x04000000 /* 0: power reduction on, 1: no power reduction */ #define BHND_BFL2_EXTLNA_PWRSAVE 0x08000000 /* boardflag to enable ucode to apply power save * ucode control of eLNA during Tx */ #define BHND_BFL2_4313_RADIOREG 0x10000000 /* board rework */ #define BHND_BFL2_DYNAMIC_VMID 0x10000000 /* boardflag to enable dynamic Vmid idle TSSI CAL */ #define BHND_BFL2_SDR_EN 0x20000000 /* SDR enabled or disabled */ #define BHND_BFL2_LNA1BYPFORTR2G 0x40000000 /* acphy, enable lna1 bypass for clip gain, 2g */ #define BHND_BFL2_LNA1BYPFORTR5G 0x80000000 /* acphy, enable lna1 bypass for clip gain, 5g */ /* SROM 11 - 11ac boardflag definitions */ #define BHND_BFL_SROM11_BTCOEX 0x00000001 /* Board supports BTCOEX */ #define BHND_BFL_SROM11_WLAN_BT_SH_XTL 0x00000002 /* bluetooth and wlan share same crystal */ #define BHND_BFL_SROM11_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */ #define BHND_BFL_SROM11_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */ #define BHND_BFL_SROM11_GAINBOOSTA01 0x20000000 /* 5g Gainboost for core0 and core1 */ #define BHND_BFL2_SROM11_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */ #define BHND_BFL2_SROM11_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are ctrl-ed by analog PA ctrl lines */ #define BHND_BFL2_SROM11_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are ctrl-ed by analog PA ctrl lines */ /* Boardflags3 */ #define BHND_BFL3_FEMCTRL_SUB 0x00000007 /* acphy, subrevs of femctrl on top of srom_femctrl */ #define BHND_BFL3_RCAL_WAR 0x00000008 /* acphy, rcal war active on this board (4335a0) */ #define BHND_BFL3_TXGAINTBLID 0x00000070 /* acphy, txgain table id */ #define BHND_BFL3_TXGAINTBLID_SHIFT 0x4 /* acphy, txgain table id shift bit */ #define BHND_BFL3_TSSI_DIV_WAR 0x00000080 /* acphy, Separate paparam for 20/40/80 */ #define BHND_BFL3_TSSI_DIV_WAR_SHIFT 0x7 /* acphy, Separate paparam for 20/40/80 shift bit */ #define BHND_BFL3_FEMTBL_FROM_NVRAM 0x00000100 /* acphy, femctrl table is read from nvram */ #define BHND_BFL3_FEMTBL_FROM_NVRAM_SHIFT 0x8 /* acphy, femctrl table is read from nvram */ #define BHND_BFL3_AGC_CFG_2G 0x00000200 /* acphy, gain control configuration for 2G */ #define BHND_BFL3_AGC_CFG_5G 0x00000400 /* acphy, gain control configuration for 5G */ #define BHND_BFL3_PPR_BIT_EXT 0x00000800 /* acphy, bit position for 1bit extension for ppr */ #define BHND_BFL3_PPR_BIT_EXT_SHIFT 11 /* acphy, bit shift for 1bit extension for ppr */ #define BHND_BFL3_BBPLL_SPR_MODE_DIS 0x00001000 /* acphy, disables bbpll spur modes */ #define BHND_BFL3_RCAL_OTP_VAL_EN 0x00002000 /* acphy, to read rcal_trim value from otp */ #define BHND_BFL3_2GTXGAINTBL_BLANK 0x00004000 /* acphy, blank the first X ticks of 2g gaintbl */ #define BHND_BFL3_2GTXGAINTBL_BLANK_SHIFT 14 /* acphy, blank the first X ticks of 2g gaintbl */ #define BHND_BFL3_5GTXGAINTBL_BLANK 0x00008000 /* acphy, blank the first X ticks of 5g gaintbl */ #define BHND_BFL3_5GTXGAINTBL_BLANK_SHIFT 15 /* acphy, blank the first X ticks of 5g gaintbl */ #define BHND_BFL3_BT_SHARE_BM_BIT1 0x40000000 /* bit 1 of WLAN/BT shared core bitmap */ #define BHND_BFL3_PHASETRACK_MAX_ALPHABETA 0x00010000 /* acphy, to max out alpha,beta to 511 */ #define BHND_BFL3_PHASETRACK_MAX_ALPHABETA_SHIFT 16 /* acphy, to max out alpha,beta to 511 */ #define BHND_BFL3_BT_SHARE_BM_BIT1 0x40000000 /* bit 1 of WLAN/BT shared core bitmap */ #define BHND_BFL3_EN_NONBRCM_TXBF 0x10000000 /* acphy, enable non-brcm TXBF */ #define BHND_BFL3_EN_P2PLINK_TXBF 0x20000000 /* acphy, enable TXBF in p2p links */ /* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ #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 */ #define BHND_GPIO_BTC4W_OUT_43224_SHARED 0x0e0 /* bit 5 is BT_IODISABLE */ #define BHND_GPIO_BTC4W_OUT_43225 0x0e0 /* bit 5 BT_IODISABLE, bit 6 SW_BT, bit 7 SW_WL */ #define BHND_GPIO_BTC4W_OUT_43421 0x020 /* bit 5 is BT_IODISABLE */ #define BHND_GPIO_BTC4W_OUT_4313 0x060 /* bit 5 SW_BT, bit 6 SW_WL */ #define BHND_GPIO_BTC4W_OUT_4331_SHARED 0x010 /* GPIO 4 */ /* 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_BCM4321BU 0x046b #define BHND_BOARD_BCM4321BUE 0x047c #define BHND_BOARD_BCM4321MP 0x046c #define BHND_BOARD_BCM4321CB2 0x046d #define BHND_BOARD_BCM4321CB2_AG 0x0066 #define BHND_BOARD_BCM4321MC 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 BHND_BOARD_BCM943341WLABGS 0x062d /* 43342 Boards */ #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 /* These values are used by dhd USB host driver. */ #define BHND_USB_RDL_RAM_BASE_4319 0x60000000 #define BHND_USB_RDL_RAM_BASE_4329 0x60000000 #define BHND_USB_RDL_RAM_SIZE_4319 0x48000 #define BHND_USB_RDL_RAM_SIZE_4329 0x48000 #define BHND_USB_RDL_RAM_SIZE_43236 0x70000 #define BHND_USB_RDL_RAM_BASE_43236 0x60000000 #define BHND_USB_RDL_RAM_SIZE_4328 0x60000 #define BHND_USB_RDL_RAM_BASE_4328 0x80000000 #define BHND_USB_RDL_RAM_SIZE_4322 0x60000 #define BHND_USB_RDL_RAM_BASE_4322 0x60000000 #define BHND_USB_RDL_RAM_SIZE_4360 0xA0000 #define BHND_USB_RDL_RAM_BASE_4360 0x60000000 #define BHND_USB_RDL_RAM_SIZE_43242 0x90000 #define BHND_USB_RDL_RAM_BASE_43242 0x60000000 #define BHND_USB_RDL_RAM_SIZE_43143 0x70000 #define BHND_USB_RDL_RAM_BASE_43143 0x60000000 #define BHND_USB_RDL_RAM_SIZE_4350 0xC0000 #define BHND_USB_RDL_RAM_BASE_4350 0x180800 /* generic defs for nvram "muxenab" bits * Note: these differ for 4335a0. refer bcmchipc.h for specific mux options. */ #define BHND_NVRAM_MUXENAB_UART 0x00000001 #define BHND_NVRAM_MUXENAB_GPIO 0x00000002 #define BHND_NVRAM_MUXENAB_ERCX 0x00000004 /* External Radio BT coex */ #define BHND_NVRAM_MUXENAB_JTAG 0x00000008 #define BHND_NVRAM_MUXENAB_HOST_WAKE 0x00000010 /* configure GPIO for SDIO host_wake */ #define BHND_NVRAM_MUXENAB_I2S_EN 0x00000020 #define BHND_NVRAM_MUXENAB_I2S_MASTER 0x00000040 #define BHND_NVRAM_MUXENAB_I2S_FULL 0x00000080 #define BHND_NVRAM_MUXENAB_SFLASH 0x00000100 #define BHND_NVRAM_MUXENAB_RFSWCTRL0 0x00000200 #define BHND_NVRAM_MUXENAB_RFSWCTRL1 0x00000400 #define BHND_NVRAM_MUXENAB_RFSWCTRL2 0x00000800 #define BHND_NVRAM_MUXENAB_SECI 0x00001000 #define BHND_NVRAM_MUXENAB_BT_LEGACY 0x00002000 #define BHND_NVRAM_MUXENAB_HOST_WAKE1 0x00004000 /* configure alternative GPIO for SDIO host_wake */ /* Boot flags */ #define BHND_BOOTFLAG_FLASH_KERNEL_NFLASH 0x00000001 #define BHND_BOOTFLAG_FLASH_BOOT_NFLASH 0x00000002 #endif /* _BHND_BHND_IDS_H_ */ Index: head/sys/dev/bhnd/bhnd_subr.c =================================================================== --- head/sys/dev/bhnd/bhnd_subr.c (revision 328182) +++ head/sys/dev/bhnd/bhnd_subr.c (revision 328183) @@ -1,2515 +1,2515 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2015-2016 Landon Fuller * Copyright (c) 2017 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by Landon Fuller * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #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" #include "bhnd_private.h" static void bhnd_service_registry_free_entry( struct bhnd_service_entry *entry); static int compare_ascending_probe_order(const void *lhs, const void *rhs); static int compare_descending_probe_order(const void *lhs, const void *rhs); /* BHND core device description table. */ static const struct bhnd_core_desc { uint16_t vendor; uint16_t device; bhnd_devclass_t class; const char *desc; } bhnd_core_descs[] = { #define BHND_CDESC(_mfg, _cid, _cls, _desc) \ { BHND_MFGID_ ## _mfg, BHND_COREID_ ## _cid, \ BHND_DEVCLASS_ ## _cls, _desc } BHND_CDESC(BCM, CC, CC, "ChipCommon I/O Controller"), BHND_CDESC(BCM, ILINE20, OTHER, "iLine20 HPNA"), BHND_CDESC(BCM, SRAM, RAM, "SRAM"), BHND_CDESC(BCM, SDRAM, RAM, "SDRAM"), BHND_CDESC(BCM, PCI, PCI, "PCI Bridge"), BHND_CDESC(BCM, MIPS, CPU, "BMIPS CPU"), BHND_CDESC(BCM, ENET, ENET_MAC, "Fast Ethernet MAC"), - BHND_CDESC(BCM, CODEC, OTHER, "V.90 Modem Codec"), + BHND_CDESC(BCM, V90_CODEC, SOFTMODEM, "V.90 SoftModem Codec"), BHND_CDESC(BCM, USB, USB_DUAL, "USB 1.1 Device/Host Controller"), BHND_CDESC(BCM, ADSL, OTHER, "ADSL Core"), BHND_CDESC(BCM, ILINE100, OTHER, "iLine100 HPNA"), BHND_CDESC(BCM, IPSEC, OTHER, "IPsec Accelerator"), BHND_CDESC(BCM, UTOPIA, OTHER, "UTOPIA ATM Core"), BHND_CDESC(BCM, PCMCIA, PCCARD, "PCMCIA Bridge"), BHND_CDESC(BCM, SOCRAM, RAM, "Internal Memory"), BHND_CDESC(BCM, MEMC, MEMC, "MEMC SDRAM Controller"), BHND_CDESC(BCM, OFDM, OTHER, "OFDM PHY"), BHND_CDESC(BCM, EXTIF, OTHER, "External Interface"), BHND_CDESC(BCM, D11, WLAN, "802.11 MAC/PHY/Radio"), BHND_CDESC(BCM, APHY, WLAN_PHY, "802.11a PHY"), BHND_CDESC(BCM, BPHY, WLAN_PHY, "802.11b PHY"), BHND_CDESC(BCM, GPHY, WLAN_PHY, "802.11g PHY"), BHND_CDESC(BCM, MIPS33, CPU, "BMIPS33 CPU"), BHND_CDESC(BCM, USB11H, USB_HOST, "USB 1.1 Host Controller"), BHND_CDESC(BCM, USB11D, USB_DEV, "USB 1.1 Device Controller"), BHND_CDESC(BCM, USB20H, USB_HOST, "USB 2.0 Host Controller"), BHND_CDESC(BCM, USB20D, USB_DEV, "USB 2.0 Device Controller"), BHND_CDESC(BCM, SDIOH, OTHER, "SDIO Host Controller"), BHND_CDESC(BCM, ROBO, OTHER, "RoboSwitch"), BHND_CDESC(BCM, ATA100, OTHER, "Parallel ATA Controller"), BHND_CDESC(BCM, SATAXOR, OTHER, "SATA DMA/XOR Controller"), BHND_CDESC(BCM, GIGETH, ENET_MAC, "Gigabit Ethernet MAC"), BHND_CDESC(BCM, PCIE, PCIE, "PCIe Bridge"), BHND_CDESC(BCM, NPHY, WLAN_PHY, "802.11n 2x2 PHY"), BHND_CDESC(BCM, SRAMC, MEMC, "SRAM Controller"), BHND_CDESC(BCM, MINIMAC, OTHER, "MINI MAC/PHY"), BHND_CDESC(BCM, ARM11, CPU, "ARM1176 CPU"), BHND_CDESC(BCM, ARM7S, CPU, "ARM7TDMI-S CPU"), BHND_CDESC(BCM, LPPHY, WLAN_PHY, "802.11a/b/g PHY"), BHND_CDESC(BCM, PMU, PMU, "PMU"), BHND_CDESC(BCM, SSNPHY, WLAN_PHY, "802.11n Single-Stream PHY"), BHND_CDESC(BCM, SDIOD, OTHER, "SDIO Device Core"), BHND_CDESC(BCM, ARMCM3, CPU, "ARM Cortex-M3 CPU"), BHND_CDESC(BCM, HTPHY, WLAN_PHY, "802.11n 4x4 PHY"), BHND_CDESC(MIPS,MIPS74K, CPU, "MIPS74k CPU"), BHND_CDESC(BCM, GMAC, ENET_MAC, "Gigabit MAC core"), BHND_CDESC(BCM, DMEMC, MEMC, "DDR1/DDR2 Memory Controller"), BHND_CDESC(BCM, PCIERC, OTHER, "PCIe Root Complex"), BHND_CDESC(BCM, OCP, SOC_BRIDGE, "OCP to OCP Bridge"), BHND_CDESC(BCM, SC, OTHER, "Shared Common Core"), BHND_CDESC(BCM, AHB, SOC_BRIDGE, "OCP to AHB Bridge"), BHND_CDESC(BCM, SPIH, OTHER, "SPI Host Controller"), BHND_CDESC(BCM, I2S, OTHER, "I2S Digital Audio Interface"), BHND_CDESC(BCM, DMEMS, MEMC, "SDR/DDR1 Memory Controller"), BHND_CDESC(BCM, UBUS_SHIM, OTHER, "BCM6362/UBUS WLAN SHIM"), BHND_CDESC(BCM, PCIE2, PCIE, "PCIe Bridge (Gen2)"), BHND_CDESC(ARM, APB_BRIDGE, SOC_BRIDGE, "BP135 AMBA3 AXI to APB Bridge"), BHND_CDESC(ARM, PL301, SOC_ROUTER, "PL301 AMBA3 Interconnect"), BHND_CDESC(ARM, EROM, EROM, "PL366 Device Enumeration ROM"), BHND_CDESC(ARM, OOB_ROUTER, OTHER, "PL367 OOB Interrupt Router"), BHND_CDESC(ARM, AXI_UNMAPPED, OTHER, "Unmapped Address Ranges"), BHND_CDESC(BCM, 4706_CC, CC, "ChipCommon I/O Controller"), BHND_CDESC(BCM, NS_PCIE2, PCIE, "PCIe Bridge (Gen2)"), BHND_CDESC(BCM, NS_DMA, OTHER, "DMA engine"), BHND_CDESC(BCM, NS_SDIO, OTHER, "SDIO 3.0 Host Controller"), BHND_CDESC(BCM, NS_USB20H, USB_HOST, "USB 2.0 Host Controller"), BHND_CDESC(BCM, NS_USB30H, USB_HOST, "USB 3.0 Host Controller"), BHND_CDESC(BCM, NS_A9JTAG, OTHER, "ARM Cortex A9 JTAG Interface"), BHND_CDESC(BCM, NS_DDR23_MEMC, MEMC, "Denali DDR2/DD3 Memory Controller"), BHND_CDESC(BCM, NS_ROM, NVRAM, "System ROM"), BHND_CDESC(BCM, NS_NAND, NVRAM, "NAND Flash Controller"), BHND_CDESC(BCM, NS_QSPI, NVRAM, "QSPI Flash Controller"), BHND_CDESC(BCM, NS_CC_B, CC_B, "ChipCommon B Auxiliary I/O Controller"), BHND_CDESC(BCM, 4706_SOCRAM, RAM, "Internal Memory"), BHND_CDESC(BCM, IHOST_ARMCA9, CPU, "ARM Cortex A9 CPU"), BHND_CDESC(BCM, 4706_GMAC_CMN, ENET, "Gigabit MAC (Common)"), BHND_CDESC(BCM, 4706_GMAC, ENET_MAC, "Gigabit MAC"), BHND_CDESC(BCM, AMEMC, MEMC, "Denali DDR1/DDR2 Memory Controller"), #undef BHND_CDESC /* Derived from inspection of the BCM4331 cores that provide PrimeCell * IDs. Due to lack of documentation, the surmised device name/purpose * provided here may be incorrect. */ { BHND_MFGID_ARM, BHND_PRIMEID_EROM, BHND_DEVCLASS_OTHER, "PL364 Device Enumeration ROM" }, { BHND_MFGID_ARM, BHND_PRIMEID_SWRAP, BHND_DEVCLASS_OTHER, "PL368 Device Management Interface" }, { BHND_MFGID_ARM, BHND_PRIMEID_MWRAP, BHND_DEVCLASS_OTHER, "PL369 Device Management Interface" }, { 0, 0, 0, NULL } }; static const struct bhnd_device_quirk bhnd_chipc_clkctl_quirks[]; static const struct bhnd_device_quirk bhnd_pcmcia_clkctl_quirks[]; /** * Device table entries for core-specific CLKCTL quirk lookup. */ static const struct bhnd_device bhnd_clkctl_devices[] = { BHND_DEVICE(BCM, CC, NULL, bhnd_chipc_clkctl_quirks), BHND_DEVICE(BCM, PCMCIA, NULL, bhnd_pcmcia_clkctl_quirks), BHND_DEVICE_END, }; /** ChipCommon CLKCTL quirks */ static const struct bhnd_device_quirk bhnd_chipc_clkctl_quirks[] = { /* HTAVAIL/ALPAVAIL are bitswapped in chipc's CLKCTL */ BHND_CHIP_QUIRK(4328, HWREV_ANY, BHND_CLKCTL_QUIRK_CCS0), BHND_CHIP_QUIRK(5354, HWREV_ANY, BHND_CLKCTL_QUIRK_CCS0), BHND_DEVICE_QUIRK_END }; /** PCMCIA CLKCTL quirks */ static const struct bhnd_device_quirk bhnd_pcmcia_clkctl_quirks[] = { /* HTAVAIL/ALPAVAIL are bitswapped in pcmcia's CLKCTL */ BHND_CHIP_QUIRK(4328, HWREV_ANY, BHND_CLKCTL_QUIRK_CCS0), BHND_CHIP_QUIRK(5354, HWREV_ANY, BHND_CLKCTL_QUIRK_CCS0), BHND_DEVICE_QUIRK_END }; /** * Return the name for a given JEP106 manufacturer ID. * * @param vendor A JEP106 Manufacturer ID, including the non-standard ARM 4-bit * JEP106 continuation code. */ const char * bhnd_vendor_name(uint16_t vendor) { switch (vendor) { case BHND_MFGID_ARM: return "ARM"; case BHND_MFGID_BCM: return "Broadcom"; case BHND_MFGID_MIPS: return "MIPS"; default: return "unknown"; } } /** * Return the name of a port type. * * @param port_type The port type to look up. */ const char * bhnd_port_type_name(bhnd_port_type port_type) { switch (port_type) { case BHND_PORT_DEVICE: return ("device"); case BHND_PORT_BRIDGE: return ("bridge"); case BHND_PORT_AGENT: return ("agent"); default: return "unknown"; } } /** * Return the name of an NVRAM source. * * @param nvram_src The NVRAM source type to look up. */ const char * bhnd_nvram_src_name(bhnd_nvram_src nvram_src) { switch (nvram_src) { case BHND_NVRAM_SRC_FLASH: return ("flash"); case BHND_NVRAM_SRC_OTP: return ("OTP"); case BHND_NVRAM_SRC_SPROM: return ("SPROM"); case BHND_NVRAM_SRC_UNKNOWN: return ("none"); default: return ("unknown"); } } static const struct bhnd_core_desc * bhnd_find_core_desc(uint16_t vendor, uint16_t device) { for (u_int i = 0; bhnd_core_descs[i].desc != NULL; i++) { if (bhnd_core_descs[i].vendor != vendor) continue; if (bhnd_core_descs[i].device != device) continue; return (&bhnd_core_descs[i]); } return (NULL); } /** * Return a human-readable name for a BHND core. * * @param vendor The core designer's JEDEC-106 Manufacturer ID. * @param device The core identifier. */ const char * bhnd_find_core_name(uint16_t vendor, uint16_t device) { const struct bhnd_core_desc *desc; if ((desc = bhnd_find_core_desc(vendor, device)) == NULL) return ("unknown"); return desc->desc; } /** * Return the device class for a BHND core. * * @param vendor The core designer's JEDEC-106 Manufacturer ID. * @param device The core identifier. */ bhnd_devclass_t bhnd_find_core_class(uint16_t vendor, uint16_t device) { const struct bhnd_core_desc *desc; if ((desc = bhnd_find_core_desc(vendor, device)) == NULL) return (BHND_DEVCLASS_OTHER); return desc->class; } /** * Return a human-readable name for a BHND core. * * @param ci The core's info record. */ const char * bhnd_core_name(const struct bhnd_core_info *ci) { return bhnd_find_core_name(ci->vendor, ci->device); } /** * Return the device class for a BHND core. * * @param ci The core's info record. */ bhnd_devclass_t bhnd_core_class(const struct bhnd_core_info *ci) { return bhnd_find_core_class(ci->vendor, ci->device); } /** * Write a human readable name representation of the given * BHND_CHIPID_* constant to @p buffer. * * @param buffer Output buffer, or NULL to compute the required size. * @param size Capacity of @p buffer, in bytes. * @param chip_id Chip ID to be formatted. * * @return The required number of bytes on success, or a negative integer on * failure. No more than @p size-1 characters be written, with the @p size'th * set to '\0'. * * @sa BHND_CHIPID_MAX_NAMELEN */ int bhnd_format_chip_id(char *buffer, size_t size, uint16_t chip_id) { /* All hex formatted IDs are within the range of 0x4000-0x9C3F (40000-1) */ if (chip_id >= 0x4000 && chip_id <= 0x9C3F) return (snprintf(buffer, size, "BCM%hX", chip_id)); else return (snprintf(buffer, size, "BCM%hu", chip_id)); } /** * Return a core info record populated from a bhnd-attached @p dev. * * @param dev A bhnd device. * * @return A core info record for @p dev. */ struct bhnd_core_info bhnd_get_core_info(device_t dev) { return (struct bhnd_core_info) { .vendor = bhnd_get_vendor(dev), .device = bhnd_get_device(dev), .hwrev = bhnd_get_hwrev(dev), .core_idx = bhnd_get_core_index(dev), .unit = bhnd_get_core_unit(dev) }; } /** * Find a @p class child device with @p unit on @p bus. * * @param bus The bhnd-compatible bus to be searched. * @param class The device class to match on. * @param unit The core unit number; specify -1 to return the first match * regardless of unit number. * * @retval device_t if a matching child device is found. * @retval NULL if no matching child device is found. */ device_t bhnd_bus_find_child(device_t bus, bhnd_devclass_t class, int unit) { struct bhnd_core_match md = { BHND_MATCH_CORE_CLASS(class), BHND_MATCH_CORE_UNIT(unit) }; if (unit == -1) md.m.match.core_unit = 0; return bhnd_bus_match_child(bus, &md); } /** * Find the first child device on @p bus that matches @p desc. * * @param bus The bhnd-compatible bus to be searched. * @param desc A match descriptor. * * @retval device_t if a matching child device is found. * @retval NULL if no matching child device is found. */ device_t bhnd_bus_match_child(device_t bus, const struct bhnd_core_match *desc) { device_t *devlistp; device_t match; int devcnt; int error; error = device_get_children(bus, &devlistp, &devcnt); if (error != 0) return (NULL); match = NULL; for (int i = 0; i < devcnt; i++) { struct bhnd_core_info ci = bhnd_get_core_info(devlistp[i]); if (bhnd_core_matches(&ci, desc)) { match = devlistp[i]; goto done; } } done: free(devlistp, M_TEMP); return match; } /** * Retrieve an ordered list of all device instances currently connected to * @p bus, returning a pointer to the array in @p devlistp and the count * in @p ndevs. * * The memory allocated for the table must be freed via * bhnd_bus_free_children(). * * @param bus The bhnd-compatible bus to be queried. * @param[out] devlist The array of devices. * @param[out] devcount The number of devices in @p devlistp * @param order The order in which devices will be returned * in @p devlist. * * @retval 0 success * @retval non-zero if an error occurs, a regular unix error code will * be returned. */ int bhnd_bus_get_children(device_t bus, device_t **devlist, int *devcount, bhnd_device_order order) { int error; /* Fetch device array */ if ((error = device_get_children(bus, devlist, devcount))) return (error); /* Perform requested sorting */ if ((error = bhnd_sort_devices(*devlist, *devcount, order))) { bhnd_bus_free_children(*devlist); return (error); } return (0); } /** * Free any memory allocated in a previous call to bhnd_bus_get_children(). * * @param devlist The device array returned by bhnd_bus_get_children(). */ void bhnd_bus_free_children(device_t *devlist) { free(devlist, M_TEMP); } /** * Perform in-place sorting of an array of bhnd device instances. * * @param devlist An array of bhnd devices. * @param devcount The number of devices in @p devs. * @param order The sort order to be used. * * @retval 0 success * @retval EINVAL if the sort order is unknown. */ int bhnd_sort_devices(device_t *devlist, size_t devcount, bhnd_device_order order) { int (*compare)(const void *, const void *); switch (order) { case BHND_DEVICE_ORDER_ATTACH: compare = compare_ascending_probe_order; break; case BHND_DEVICE_ORDER_DETACH: compare = compare_descending_probe_order; break; default: printf("unknown sort order: %d\n", order); return (EINVAL); } qsort(devlist, devcount, sizeof(*devlist), compare); return (0); } /* * Ascending comparison of bhnd device's probe order. */ static int compare_ascending_probe_order(const void *lhs, const void *rhs) { device_t ldev, rdev; int lorder, rorder; ldev = (*(const device_t *) lhs); rdev = (*(const device_t *) rhs); lorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(ldev), ldev); rorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(rdev), rdev); if (lorder < rorder) { return (-1); } else if (lorder > rorder) { return (1); } else { return (0); } } /* * Descending comparison of bhnd device's probe order. */ static int compare_descending_probe_order(const void *lhs, const void *rhs) { return (compare_ascending_probe_order(rhs, lhs)); } /** * Call device_probe_and_attach() for each of the bhnd bus device's * children, in bhnd attach order. * * @param bus The bhnd-compatible bus for which all children should be probed * and attached. */ int bhnd_bus_probe_children(device_t bus) { device_t *devs; int ndevs; int error; /* Fetch children in attach order */ error = bhnd_bus_get_children(bus, &devs, &ndevs, BHND_DEVICE_ORDER_ATTACH); if (error) return (error); /* Probe and attach all children */ for (int i = 0; i < ndevs; i++) { device_t child = devs[i]; device_probe_and_attach(child); } bhnd_bus_free_children(devs); return (0); } /** * Walk up the bhnd device hierarchy to locate the root device * to which the bhndb bridge is attached. * * This can be used from within bhnd host bridge drivers to locate the * actual upstream host device. * * @param dev A bhnd device. * @param bus_class The expected bus (e.g. "pci") to which the bridge root * should be attached. * * @retval device_t if a matching parent device is found. * @retval NULL if @p dev is not attached via a bhndb bus. * @retval NULL if no parent device is attached via @p bus_class. */ device_t bhnd_find_bridge_root(device_t dev, devclass_t bus_class) { devclass_t bhndb_class; device_t parent; KASSERT(device_get_devclass(device_get_parent(dev)) == bhnd_devclass, ("%s not a bhnd device", device_get_nameunit(dev))); bhndb_class = devclass_find("bhndb"); /* Walk the device tree until we hit a bridge */ parent = dev; while ((parent = device_get_parent(parent)) != NULL) { if (device_get_devclass(parent) == bhndb_class) break; } /* No bridge? */ if (parent == NULL) return (NULL); /* Search for a parent attached to the expected bus class */ while ((parent = device_get_parent(parent)) != NULL) { device_t bus; bus = device_get_parent(parent); if (bus != NULL && device_get_devclass(bus) == bus_class) return (parent); } /* Not found */ return (NULL); } /** * Find the first core in @p cores that matches @p desc. * * @param cores The table to search. * @param num_cores The length of @p cores. * @param desc A match descriptor. * * @retval bhnd_core_info if a matching core is found. * @retval NULL if no matching core is found. */ const struct bhnd_core_info * bhnd_match_core(const struct bhnd_core_info *cores, u_int num_cores, const struct bhnd_core_match *desc) { for (u_int i = 0; i < num_cores; i++) { if (bhnd_core_matches(&cores[i], desc)) return &cores[i]; } return (NULL); } /** * Find the first core in @p cores with the given @p class. * * @param cores The table to search. * @param num_cores The length of @p cores. * @param class The device class to match on. * * @retval non-NULL if a matching core is found. * @retval NULL if no matching core is found. */ const struct bhnd_core_info * bhnd_find_core(const struct bhnd_core_info *cores, u_int num_cores, bhnd_devclass_t class) { struct bhnd_core_match md = { BHND_MATCH_CORE_CLASS(class) }; return bhnd_match_core(cores, num_cores, &md); } /** * Create an equality match descriptor for @p core. * * @param core The core info to be matched on. * * @return an equality match descriptor for @p core. */ struct bhnd_core_match bhnd_core_get_match_desc(const struct bhnd_core_info *core) { return ((struct bhnd_core_match) { BHND_MATCH_CORE_VENDOR(core->vendor), BHND_MATCH_CORE_ID(core->device), BHND_MATCH_CORE_REV(HWREV_EQ(core->hwrev)), BHND_MATCH_CORE_CLASS(bhnd_core_class(core)), BHND_MATCH_CORE_IDX(core->core_idx), BHND_MATCH_CORE_UNIT(core->unit) }); } /** * Return true if the @p lhs is equal to @p rhs. * * @param lhs The first bhnd core descriptor to compare. * @param rhs The second bhnd core descriptor to compare. * * @retval true if @p lhs is equal to @p rhs * @retval false if @p lhs is not equal to @p rhs */ bool bhnd_cores_equal(const struct bhnd_core_info *lhs, const struct bhnd_core_info *rhs) { struct bhnd_core_match md; /* Use an equality match descriptor to perform the comparison */ md = bhnd_core_get_match_desc(rhs); return (bhnd_core_matches(lhs, &md)); } /** * Return true if the @p core matches @p desc. * * @param core A bhnd core descriptor. * @param desc A match descriptor to compare against @p core. * * @retval true if @p core matches @p match. * @retval false if @p core does not match @p match. */ bool bhnd_core_matches(const struct bhnd_core_info *core, const struct bhnd_core_match *desc) { if (desc->m.match.core_vendor && desc->core_vendor != core->vendor) return (false); if (desc->m.match.core_id && desc->core_id != core->device) return (false); if (desc->m.match.core_unit && desc->core_unit != core->unit) return (false); if (desc->m.match.core_rev && !bhnd_hwrev_matches(core->hwrev, &desc->core_rev)) return (false); if (desc->m.match.core_idx && desc->core_idx != core->core_idx) return (false); if (desc->m.match.core_class && desc->core_class != bhnd_core_class(core)) return (false); return true; } /** * Return true if the @p chip matches @p desc. * * @param chip A bhnd chip identifier. * @param desc A match descriptor to compare against @p chip. * * @retval true if @p chip matches @p match. * @retval false if @p chip does not match @p match. */ bool bhnd_chip_matches(const struct bhnd_chipid *chip, const struct bhnd_chip_match *desc) { if (desc->m.match.chip_id && chip->chip_id != desc->chip_id) return (false); if (desc->m.match.chip_pkg && chip->chip_pkg != desc->chip_pkg) return (false); if (desc->m.match.chip_rev && !bhnd_hwrev_matches(chip->chip_rev, &desc->chip_rev)) return (false); if (desc->m.match.chip_type && chip->chip_type != desc->chip_type) return (false); return (true); } /** * Return true if the @p board matches @p desc. * * @param board The bhnd board info. * @param desc A match descriptor to compare against @p board. * * @retval true if @p chip matches @p match. * @retval false if @p chip does not match @p match. */ bool bhnd_board_matches(const struct bhnd_board_info *board, const struct bhnd_board_match *desc) { if (desc->m.match.board_srom_rev && !bhnd_hwrev_matches(board->board_srom_rev, &desc->board_srom_rev)) return (false); if (desc->m.match.board_vendor && board->board_vendor != desc->board_vendor) return (false); if (desc->m.match.board_type && board->board_type != desc->board_type) return (false); if (desc->m.match.board_devid && board->board_devid != desc->board_devid) return (false); if (desc->m.match.board_rev && !bhnd_hwrev_matches(board->board_rev, &desc->board_rev)) return (false); return (true); } /** * Return true if the @p hwrev matches @p desc. * * @param hwrev A bhnd hardware revision. * @param desc A match descriptor to compare against @p core. * * @retval true if @p hwrev matches @p match. * @retval false if @p hwrev does not match @p match. */ bool bhnd_hwrev_matches(uint16_t hwrev, const struct bhnd_hwrev_match *desc) { if (desc->start != BHND_HWREV_INVALID && desc->start > hwrev) return false; if (desc->end != BHND_HWREV_INVALID && desc->end < hwrev) return false; return true; } /** * Return true if the @p dev matches @p desc. * * @param dev A bhnd device. * @param desc A match descriptor to compare against @p dev. * * @retval true if @p dev matches @p match. * @retval false if @p dev does not match @p match. */ bool bhnd_device_matches(device_t dev, const struct bhnd_device_match *desc) { struct bhnd_core_info core; const struct bhnd_chipid *chip; struct bhnd_board_info board; device_t parent; int error; /* Construct individual match descriptors */ struct bhnd_core_match m_core = { _BHND_CORE_MATCH_COPY(desc) }; struct bhnd_chip_match m_chip = { _BHND_CHIP_MATCH_COPY(desc) }; struct bhnd_board_match m_board = { _BHND_BOARD_MATCH_COPY(desc) }; /* Fetch and match core info */ if (m_core.m.match_flags) { /* Only applicable to bhnd-attached cores */ parent = device_get_parent(dev); if (device_get_devclass(parent) != bhnd_devclass) { device_printf(dev, "attempting to match core " "attributes against non-core device\n"); return (false); } core = bhnd_get_core_info(dev); if (!bhnd_core_matches(&core, &m_core)) return (false); } /* Fetch and match chip info */ if (m_chip.m.match_flags) { chip = bhnd_get_chipid(dev); if (!bhnd_chip_matches(chip, &m_chip)) return (false); } /* Fetch and match board info. * * This is not available until after NVRAM is up; earlier device * matches should not include board requirements */ if (m_board.m.match_flags) { if ((error = bhnd_read_board_info(dev, &board))) { device_printf(dev, "failed to read required board info " "during device matching: %d\n", error); return (false); } if (!bhnd_board_matches(&board, &m_board)) return (false); } /* All matched */ return (true); } /** * Search @p table for an entry matching @p dev. * * @param dev A bhnd device to match against @p table. * @param table The device table to search. * @param entry_size The @p table entry size, in bytes. * * @retval non-NULL the first matching device, if any. * @retval NULL if no matching device is found in @p table. */ const struct bhnd_device * bhnd_device_lookup(device_t dev, const struct bhnd_device *table, size_t entry_size) { const struct bhnd_device *entry; device_t hostb, parent; bhnd_attach_type attach_type; uint32_t dflags; parent = device_get_parent(dev); hostb = bhnd_bus_find_hostb_device(parent); attach_type = bhnd_get_attach_type(dev); for (entry = table; !BHND_DEVICE_IS_END(entry); entry = (const struct bhnd_device *) ((const char *) entry + entry_size)) { /* match core info */ if (!bhnd_device_matches(dev, &entry->core)) continue; /* match device flags */ dflags = entry->device_flags; /* hostb implies BHND_ATTACH_ADAPTER requirement */ if (dflags & BHND_DF_HOSTB) dflags |= BHND_DF_ADAPTER; if (dflags & BHND_DF_ADAPTER) if (attach_type != BHND_ATTACH_ADAPTER) continue; if (dflags & BHND_DF_HOSTB) if (dev != hostb) continue; if (dflags & BHND_DF_SOC) if (attach_type != BHND_ATTACH_NATIVE) continue; /* device found */ return (entry); } /* not found */ return (NULL); } /** * Scan the device @p table for all quirk flags applicable to @p dev. * * @param dev A bhnd device to match against @p table. * @param table The device table to search. * @param entry_size The @p table entry size, in bytes. * * @return all matching quirk flags. */ uint32_t bhnd_device_quirks(device_t dev, const struct bhnd_device *table, size_t entry_size) { const struct bhnd_device *dent; const struct bhnd_device_quirk *qent, *qtable; uint32_t quirks; /* Locate the device entry */ if ((dent = bhnd_device_lookup(dev, table, entry_size)) == NULL) return (0); /* Quirks table is optional */ qtable = dent->quirks_table; if (qtable == NULL) return (0); /* Collect matching device quirk entries */ quirks = 0; for (qent = qtable; !BHND_DEVICE_QUIRK_IS_END(qent); qent++) { if (bhnd_device_matches(dev, &qent->desc)) quirks |= qent->quirks; } return (quirks); } /** * Allocate bhnd(4) resources defined in @p rs from a parent bus. * * @param dev The device requesting ownership of the resources. * @param rs A standard bus resource specification. This will be updated * with the allocated resource's RIDs. * @param res On success, the allocated bhnd resources. * * @retval 0 success * @retval non-zero if allocation of any non-RF_OPTIONAL resource fails, * all allocated resources will be released and a regular * unix error code will be returned. */ int bhnd_alloc_resources(device_t dev, struct resource_spec *rs, struct bhnd_resource **res) { /* Initialize output array */ for (u_int i = 0; rs[i].type != -1; i++) res[i] = NULL; for (u_int i = 0; rs[i].type != -1; i++) { res[i] = bhnd_alloc_resource_any(dev, rs[i].type, &rs[i].rid, rs[i].flags); /* Clean up all allocations on failure */ if (res[i] == NULL && !(rs[i].flags & RF_OPTIONAL)) { bhnd_release_resources(dev, rs, res); return (ENXIO); } } return (0); } /** * Release bhnd(4) resources defined in @p rs from a parent bus. * * @param dev The device that owns the resources. * @param rs A standard bus resource specification previously initialized * by @p bhnd_alloc_resources. * @param res The bhnd resources to be released. */ void bhnd_release_resources(device_t dev, const struct resource_spec *rs, struct bhnd_resource **res) { for (u_int i = 0; rs[i].type != -1; i++) { if (res[i] == NULL) continue; bhnd_release_resource(dev, rs[i].type, rs[i].rid, res[i]); res[i] = NULL; } } /** * Parse the CHIPC_ID_* fields from the ChipCommon CHIPC_ID * register, returning its bhnd_chipid representation. * * @param idreg The CHIPC_ID register value. * @param enum_addr The enumeration address to include in the result. * * @warning * On early siba(4) devices, the ChipCommon core does not provide * a valid CHIPC_ID_NUMCORE field. On these ChipCommon revisions * (see CHIPC_NCORES_MIN_HWREV()), this function will parse and return * an invalid `ncores` value. */ struct bhnd_chipid bhnd_parse_chipid(uint32_t idreg, bhnd_addr_t enum_addr) { struct bhnd_chipid result; /* Fetch the basic chip info */ result.chip_id = CHIPC_GET_BITS(idreg, CHIPC_ID_CHIP); result.chip_pkg = CHIPC_GET_BITS(idreg, CHIPC_ID_PKG); result.chip_rev = CHIPC_GET_BITS(idreg, CHIPC_ID_REV); result.chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS); result.ncores = CHIPC_GET_BITS(idreg, CHIPC_ID_NUMCORE); result.enum_addr = enum_addr; return (result); } /** * Determine the correct core count for a chip identification value that * may contain an invalid core count. * * On some early siba(4) devices (see CHIPC_NCORES_MIN_HWREV()), the ChipCommon * core does not provide a valid CHIPC_ID_NUMCORE field. * * @param cid The chip identification to be queried. * @param chipc_hwrev The hardware revision of the ChipCommon core from which * @p cid was parsed. * @param[out] ncores On success, will be set to the correct core count. * * @retval 0 If the core count is already correct, or was mapped to a * a correct value. * @retval EINVAL If the core count is incorrect, but the chip was not * recognized. */ int bhnd_chipid_fixed_ncores(const struct bhnd_chipid *cid, uint16_t chipc_hwrev, uint8_t *ncores) { /* bcma(4), and most siba(4) devices */ if (CHIPC_NCORES_MIN_HWREV(chipc_hwrev)) { *ncores = cid->ncores; return (0); } /* broken siba(4) chipsets */ switch (cid->chip_id) { case BHND_CHIPID_BCM4306: *ncores = 6; break; case BHND_CHIPID_BCM4704: *ncores = 9; break; case BHND_CHIPID_BCM5365: /* * BCM5365 does support ID_NUMCORE in at least * some of its revisions, but for unknown * reasons, Broadcom's drivers always exclude * the ChipCommon revision (0x5) used by BCM5365 * from the set of revisions supporting * ID_NUMCORE, and instead supply a fixed value. * * Presumably, at least some of these devices * shipped with a broken ID_NUMCORE value. */ *ncores = 7; break; default: return (EINVAL); } return (0); } /** * Allocate the resource defined by @p rs via @p dev, use it * to read the ChipCommon ID register relative to @p chipc_offset, * then release the resource. * * @param dev The device owning @p rs. * @param rs A resource spec that encompasses the ChipCommon register block. * @param chipc_offset The offset of the ChipCommon registers within @p rs. * @param[out] result The chip identification data. * * @retval 0 success * @retval non-zero if the ChipCommon identification data could not be read. */ int bhnd_read_chipid(device_t dev, struct resource_spec *rs, bus_size_t chipc_offset, struct bhnd_chipid *result) { struct resource *res; bhnd_addr_t enum_addr; uint32_t reg; uint8_t chip_type; int error, rid, rtype; rid = rs->rid; rtype = rs->type; error = 0; /* Allocate the ChipCommon window resource and fetch the chipid data */ res = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE); if (res == NULL) { device_printf(dev, "failed to allocate bhnd chipc resource\n"); return (ENXIO); } /* Fetch the basic chip info */ reg = bus_read_4(res, chipc_offset + CHIPC_ID); chip_type = CHIPC_GET_BITS(reg, CHIPC_ID_BUS); /* Fetch the EROMPTR */ if (BHND_CHIPTYPE_HAS_EROM(chip_type)) { enum_addr = bus_read_4(res, chipc_offset + CHIPC_EROMPTR); } else if (chip_type == BHND_CHIPTYPE_SIBA) { /* siba(4) uses the ChipCommon base address as the enumeration * address */ enum_addr = BHND_DEFAULT_CHIPC_ADDR; } else { device_printf(dev, "unknown chip type %hhu\n", chip_type); error = ENODEV; goto cleanup; } *result = bhnd_parse_chipid(reg, enum_addr); /* Fix the core count on early siba(4) devices */ if (chip_type == BHND_CHIPTYPE_SIBA) { uint32_t idh; uint16_t chipc_hwrev; /* * We need the ChipCommon revision to determine whether * the ncore field is valid. * * We can safely assume the siba IDHIGH register is mapped * within the chipc register block. */ idh = bus_read_4(res, SB0_REG_ABS(SIBA_CFG0_IDHIGH)); chipc_hwrev = SIBA_IDH_CORE_REV(idh); error = bhnd_chipid_fixed_ncores(result, chipc_hwrev, &result->ncores); if (error) goto cleanup; } cleanup: /* Clean up */ bus_release_resource(dev, rtype, rid, res); return (error); } /** * Allocate and return a new per-core PMU clock control/status (clkctl) * instance for @p dev. * * @param dev The bhnd(4) core device mapped by @p r. * @param pmu_dev The bhnd(4) PMU device, implmenting the bhnd_pmu_if * interface. The caller is responsible for ensuring that * this reference remains valid for the lifetime of the * returned clkctl instance. * @param r A resource mapping the core's clock control register * (see BHND_CLK_CTL_ST). The caller is responsible for * ensuring that this resource remains valid for the * lifetime of the returned clkctl instance. * @param offset The offset to the clock control register within @p r. * @param max_latency The PMU's maximum state transition latency in * microseconds; this upper bound will be used to busy-wait * on PMU state transitions. * * @retval non-NULL success * @retval NULL if allocation fails. * */ struct bhnd_core_clkctl * bhnd_alloc_core_clkctl(device_t dev, device_t pmu_dev, struct bhnd_resource *r, bus_size_t offset, u_int max_latency) { struct bhnd_core_clkctl *clkctl; clkctl = malloc(sizeof(*clkctl), M_BHND, M_ZERO | M_NOWAIT); if (clkctl == NULL) return (NULL); clkctl->cc_dev = dev; clkctl->cc_pmu_dev = pmu_dev; clkctl->cc_res = r; clkctl->cc_res_offset = offset; clkctl->cc_max_latency = max_latency; clkctl->cc_quirks = bhnd_device_quirks(dev, bhnd_clkctl_devices, sizeof(bhnd_clkctl_devices[0])); BHND_CLKCTL_LOCK_INIT(clkctl); return (clkctl); } /** * Free a clkctl instance previously allocated via bhnd_alloc_core_clkctl(). * * @param clkctl The clkctl instance to be freed. */ void bhnd_free_core_clkctl(struct bhnd_core_clkctl *clkctl) { BHND_CLKCTL_LOCK_DESTROY(clkctl); free(clkctl, M_BHND); } /** * Wait for the per-core clock status to be equal to @p value after * applying @p mask, timing out after the maximum transition latency is reached. * * @param clkctl Per-core clkctl state to be queryied. * @param value Value to wait for. * @param mask Mask to apply prior to value comparison. * * @retval 0 success * @retval ETIMEDOUT if the PMU's maximum transition delay is reached before * the clock status matches @p value and @p mask. */ int bhnd_core_clkctl_wait(struct bhnd_core_clkctl *clkctl, uint32_t value, uint32_t mask) { uint32_t clkst; BHND_CLKCTL_LOCK_ASSERT(clkctl, MA_OWNED); /* Bitswapped HTAVAIL/ALPAVAIL work-around */ if (clkctl->cc_quirks & BHND_CLKCTL_QUIRK_CCS0) { uint32_t fmask, fval; fmask = mask & ~(BHND_CCS_HTAVAIL | BHND_CCS_ALPAVAIL); fval = value & ~(BHND_CCS_HTAVAIL | BHND_CCS_ALPAVAIL); if (mask & BHND_CCS_HTAVAIL) fmask |= BHND_CCS0_HTAVAIL; if (value & BHND_CCS_HTAVAIL) fval |= BHND_CCS0_HTAVAIL; if (mask & BHND_CCS_ALPAVAIL) fmask |= BHND_CCS0_ALPAVAIL; if (value & BHND_CCS_ALPAVAIL) fval |= BHND_CCS0_ALPAVAIL; mask = fmask; value = fval; } for (u_int i = 0; i < clkctl->cc_max_latency; i += 10) { clkst = bhnd_bus_read_4(clkctl->cc_res, clkctl->cc_res_offset); if ((clkst & mask) == (value & mask)) return (0); DELAY(10); } device_printf(clkctl->cc_dev, "clkst wait timeout (value=%#x, " "mask=%#x)\n", value, mask); return (ETIMEDOUT); } /** * Read an NVRAM variable's NUL-terminated string value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] buf A buffer large enough to hold @p len bytes. On * success, the NUL-terminated string value will be * written to this buffer. This argment may be NULL if * the value is not desired. * @param len The maximum capacity of @p buf. * @param[out] rlen On success, will be set to the actual size of * the requested value (including NUL termination). This * argment may be NULL if the size is not desired. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too * small to hold the requested value. * @retval EFTYPE If the variable data cannot be coerced to a valid * string representation. * @retval ERANGE If value coercion would overflow @p type. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_str(device_t dev, const char *name, char *buf, size_t len, size_t *rlen) { size_t larg; int error; larg = len; error = bhnd_nvram_getvar(dev, name, buf, &larg, BHND_NVRAM_TYPE_STRING); if (rlen != NULL) *rlen = larg; return (error); } /** * Read an NVRAM variable's unsigned integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * @param width The output integer type width (1, 2, or * 4 bytes). * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid unsigned integer representation. * @retval ERANGE If value coercion would overflow (or underflow) an * unsigned representation of the given @p width. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_uint(device_t dev, const char *name, void *value, int width) { bhnd_nvram_type type; size_t len; switch (width) { case 1: type = BHND_NVRAM_TYPE_UINT8; break; case 2: type = BHND_NVRAM_TYPE_UINT16; break; case 4: type = BHND_NVRAM_TYPE_UINT32; break; default: device_printf(dev, "unsupported NVRAM integer width: %d\n", width); return (EINVAL); } len = width; return (bhnd_nvram_getvar(dev, name, value, &len, type)); } /** * Read an NVRAM variable's unsigned 8-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid unsigned integer representation. * @retval ERANGE If value coercion would overflow (or underflow) uint8_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_uint8(device_t dev, const char *name, uint8_t *value) { return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's unsigned 16-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid unsigned integer representation. * @retval ERANGE If value coercion would overflow (or underflow) * uint16_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_uint16(device_t dev, const char *name, uint16_t *value) { return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's unsigned 32-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid unsigned integer representation. * @retval ERANGE If value coercion would overflow (or underflow) * uint32_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_uint32(device_t dev, const char *name, uint32_t *value) { return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's signed integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * @param width The output integer type width (1, 2, or * 4 bytes). * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid integer representation. * @retval ERANGE If value coercion would overflow (or underflow) an * signed representation of the given @p width. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_int(device_t dev, const char *name, void *value, int width) { bhnd_nvram_type type; size_t len; switch (width) { case 1: type = BHND_NVRAM_TYPE_INT8; break; case 2: type = BHND_NVRAM_TYPE_INT16; break; case 4: type = BHND_NVRAM_TYPE_INT32; break; default: device_printf(dev, "unsupported NVRAM integer width: %d\n", width); return (EINVAL); } len = width; return (bhnd_nvram_getvar(dev, name, value, &len, type)); } /** * Read an NVRAM variable's signed 8-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid integer representation. * @retval ERANGE If value coercion would overflow (or underflow) int8_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_int8(device_t dev, const char *name, int8_t *value) { return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's signed 16-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid integer representation. * @retval ERANGE If value coercion would overflow (or underflow) * int16_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_int16(device_t dev, const char *name, int16_t *value) { return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's signed 32-bit integer value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] value On success, the requested value will be written * to this pointer. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval EFTYPE If the variable data cannot be coerced to a * a valid integer representation. * @retval ERANGE If value coercion would overflow (or underflow) * int32_t. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_int32(device_t dev, const char *name, int32_t *value) { return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); } /** * Read an NVRAM variable's array value. * * @param dev A bhnd bus child device. * @param name The NVRAM variable name. * @param[out] buf A buffer large enough to hold @p size bytes. * On success, the requested value will be written * to this buffer. * @param[in,out] size The required number of bytes to write to * @p buf. * @param type The desired array element data representation. * * @retval 0 success * @retval ENOENT The requested variable was not found. * @retval ENODEV No valid NVRAM source could be found. * @retval ENXIO If less than @p size bytes are available. * @retval ENOMEM If a buffer of @p size is too small to hold the * requested value. * @retval EFTYPE If the variable data cannot be coerced to a * a valid instance of @p type. * @retval ERANGE If value coercion would overflow (or underflow) a * representation of @p type. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ int bhnd_nvram_getvar_array(device_t dev, const char *name, void *buf, size_t size, bhnd_nvram_type type) { size_t nbytes; int error; /* Attempt read */ nbytes = size; if ((error = bhnd_nvram_getvar(dev, name, buf, &nbytes, type))) return (error); /* Verify that the expected number of bytes were fetched */ if (nbytes < size) return (ENXIO); return (0); } /** * Initialize a service provider registry. * * @param bsr The service registry to initialize. * * @retval 0 success * @retval non-zero if an error occurs initializing the service registry, * a regular unix error code will be returned. */ int bhnd_service_registry_init(struct bhnd_service_registry *bsr) { STAILQ_INIT(&bsr->entries); mtx_init(&bsr->lock, "bhnd_service_registry lock", NULL, MTX_DEF); return (0); } /** * Release all resources held by @p bsr. * * @param bsr A service registry instance previously successfully * initialized via bhnd_service_registry_init(). * * @retval 0 success * @retval EBUSY if active references to service providers registered * with @p bsr exist. */ int bhnd_service_registry_fini(struct bhnd_service_registry *bsr) { struct bhnd_service_entry *entry, *enext; /* Remove everthing we can */ mtx_lock(&bsr->lock); STAILQ_FOREACH_SAFE(entry, &bsr->entries, link, enext) { if (entry->refs > 0) continue; STAILQ_REMOVE(&bsr->entries, entry, bhnd_service_entry, link); free(entry, M_BHND); } if (!STAILQ_EMPTY(&bsr->entries)) { mtx_unlock(&bsr->lock); return (EBUSY); } mtx_unlock(&bsr->lock); mtx_destroy(&bsr->lock); return (0); } /** * Register a @p provider for the given @p service. * * @param bsr Service registry to be modified. * @param provider Service provider to register. * @param service Service for which @p provider will be registered. * @param flags Service provider flags (see BHND_SPF_*). * * @retval 0 success * @retval EEXIST if an entry for @p service already exists. * @retval EINVAL if @p service is BHND_SERVICE_ANY. * @retval non-zero if registering @p provider otherwise fails, a regular * unix error code will be returned. */ int bhnd_service_registry_add(struct bhnd_service_registry *bsr, device_t provider, bhnd_service_t service, uint32_t flags) { struct bhnd_service_entry *entry; if (service == BHND_SERVICE_ANY) return (EINVAL); mtx_lock(&bsr->lock); /* Is a service provider already registered? */ STAILQ_FOREACH(entry, &bsr->entries, link) { if (entry->service == service) { mtx_unlock(&bsr->lock); return (EEXIST); } } /* Initialize and insert our new entry */ entry = malloc(sizeof(*entry), M_BHND, M_NOWAIT); if (entry == NULL) { mtx_unlock(&bsr->lock); return (ENOMEM); } entry->provider = provider; entry->service = service; entry->flags = flags; refcount_init(&entry->refs, 0); STAILQ_INSERT_HEAD(&bsr->entries, entry, link); mtx_unlock(&bsr->lock); return (0); } /** * Free an unreferenced registry entry. * * @param entry The entry to be deallocated. */ static void bhnd_service_registry_free_entry(struct bhnd_service_entry *entry) { KASSERT(entry->refs == 0, ("provider has active references")); free(entry, M_BHND); } /** * Attempt to remove the @p service provider registration for @p provider. * * @param bsr The service registry to be modified. * @param provider The service provider to be deregistered. * @param service The service for which @p provider will be deregistered, * or BHND_SERVICE_ANY to remove all service * registrations for @p provider. * * @retval 0 success * @retval EBUSY if active references to @p provider exist; see * bhnd_service_registry_retain() and * bhnd_service_registry_release(). */ int bhnd_service_registry_remove(struct bhnd_service_registry *bsr, device_t provider, bhnd_service_t service) { struct bhnd_service_entry *entry, *enext; mtx_lock(&bsr->lock); #define BHND_PROV_MATCH(_e) \ ((_e)->provider == provider && \ (service == BHND_SERVICE_ANY || (_e)->service == service)) /* Validate matching provider entries before making any * modifications */ STAILQ_FOREACH(entry, &bsr->entries, link) { /* Skip non-matching entries */ if (!BHND_PROV_MATCH(entry)) continue; /* Entry is in use? */ if (entry->refs > 0) { mtx_unlock(&bsr->lock); return (EBUSY); } } /* We can now safely remove matching entries */ STAILQ_FOREACH_SAFE(entry, &bsr->entries, link, enext) { /* Skip non-matching entries */ if (!BHND_PROV_MATCH(entry)) continue; /* Remove from list */ STAILQ_REMOVE(&bsr->entries, entry, bhnd_service_entry, link); /* Free provider entry */ bhnd_service_registry_free_entry(entry); } #undef BHND_PROV_MATCH mtx_unlock(&bsr->lock); return (0); } /** * Retain and return a reference to a registered @p service provider, if any. * * @param bsr The service registry to be queried. * @param service The service for which a provider should be returned. * * On success, the caller assumes ownership the returned provider, and * is responsible for releasing this reference via * bhnd_service_registry_release(). * * @retval device_t success * @retval NULL if no provider is registered for @p service. */ device_t bhnd_service_registry_retain(struct bhnd_service_registry *bsr, bhnd_service_t service) { struct bhnd_service_entry *entry; mtx_lock(&bsr->lock); STAILQ_FOREACH(entry, &bsr->entries, link) { if (entry->service != service) continue; /* With a live refcount, entry is gauranteed to remain alive * after we release our lock */ refcount_acquire(&entry->refs); mtx_unlock(&bsr->lock); return (entry->provider); } mtx_unlock(&bsr->lock); /* Not found */ return (NULL); } /** * Release a reference to a service provider previously returned by * bhnd_service_registry_retain(). * * If this is the last reference to an inherited service provider registration * (see BHND_SPF_INHERITED), the registration will also be removed, and * true will be returned. * * @param bsr The service registry from which @p provider * was returned. * @param provider The provider to be released. * @param service The service for which @p provider was previously * retained. * @retval true The inherited service provider registration was removed; * the caller should release its own reference to the * provider. * @retval false The service provider was not inherited, or active * references to the provider remain. * * @see BHND_SPF_INHERITED */ bool bhnd_service_registry_release(struct bhnd_service_registry *bsr, device_t provider, bhnd_service_t service) { struct bhnd_service_entry *entry; /* Exclusive lock, as we need to prevent any new references to the * entry from being taken if it's to be removed */ mtx_lock(&bsr->lock); STAILQ_FOREACH(entry, &bsr->entries, link) { bool removed; if (entry->provider != provider) continue; if (entry->service != service) continue; if (refcount_release(&entry->refs) && (entry->flags & BHND_SPF_INHERITED)) { /* If an inherited entry is no longer actively * referenced, remove the local registration and inform * the caller. */ STAILQ_REMOVE(&bsr->entries, entry, bhnd_service_entry, link); bhnd_service_registry_free_entry(entry); removed = true; } else { removed = false; } mtx_unlock(&bsr->lock); return (removed); } /* Caller owns a reference, but no such provider is registered? */ panic("invalid service provider reference"); } /** * Using the bhnd(4) bus-level core information and a custom core name, * populate @p dev's device description. * * @param dev A bhnd-bus attached device. * @param dev_name The core's name (e.g. "SDIO Device Core"). */ void bhnd_set_custom_core_desc(device_t dev, const char *dev_name) { const char *vendor_name; char *desc; vendor_name = bhnd_get_vendor_name(dev); asprintf(&desc, M_BHND, "%s %s, rev %hhu", vendor_name, dev_name, bhnd_get_hwrev(dev)); if (desc != NULL) { device_set_desc_copy(dev, desc); free(desc, M_BHND); } else { device_set_desc(dev, dev_name); } } /** * Using the bhnd(4) bus-level core information, populate @p dev's device * description. * * @param dev A bhnd-bus attached device. */ void bhnd_set_default_core_desc(device_t dev) { bhnd_set_custom_core_desc(dev, bhnd_get_device_name(dev)); } /** * Using the bhnd @p chip_id, populate the bhnd(4) bus @p dev's device * description. * * @param dev A bhnd-bus attached device. * @param chip_id The chip identification. */ void bhnd_set_default_bus_desc(device_t dev, const struct bhnd_chipid *chip_id) { const char *bus_name; char *desc; char chip_name[BHND_CHIPID_MAX_NAMELEN]; /* Determine chip type's bus name */ switch (chip_id->chip_type) { case BHND_CHIPTYPE_SIBA: bus_name = "SIBA bus"; break; case BHND_CHIPTYPE_BCMA: case BHND_CHIPTYPE_BCMA_ALT: bus_name = "BCMA bus"; break; case BHND_CHIPTYPE_UBUS: bus_name = "UBUS bus"; break; default: bus_name = "Unknown Type"; break; } /* Format chip name */ bhnd_format_chip_id(chip_name, sizeof(chip_name), chip_id->chip_id); /* Format and set device description */ asprintf(&desc, M_BHND, "%s %s", chip_name, bus_name); if (desc != NULL) { device_set_desc_copy(dev, desc); free(desc, M_BHND); } else { device_set_desc(dev, bus_name); } } /** * Helper function for implementing BHND_BUS_REGISTER_PROVIDER(). * * This implementation delegates the request to the BHND_BUS_REGISTER_PROVIDER() * method on the parent of @p dev. If no parent exists, the implementation * will return an error. */ int bhnd_bus_generic_register_provider(device_t dev, device_t child, device_t provider, bhnd_service_t service) { device_t parent = device_get_parent(dev); if (parent != NULL) { return (BHND_BUS_REGISTER_PROVIDER(parent, child, provider, service)); } return (ENXIO); } /** * Helper function for implementing BHND_BUS_DEREGISTER_PROVIDER(). * * This implementation delegates the request to the * BHND_BUS_DEREGISTER_PROVIDER() method on the parent of @p dev. If no parent * exists, the implementation will panic. */ int bhnd_bus_generic_deregister_provider(device_t dev, device_t child, device_t provider, bhnd_service_t service) { device_t parent = device_get_parent(dev); if (parent != NULL) { return (BHND_BUS_DEREGISTER_PROVIDER(parent, child, provider, service)); } panic("missing BHND_BUS_DEREGISTER_PROVIDER()"); } /** * Helper function for implementing BHND_BUS_RETAIN_PROVIDER(). * * This implementation delegates the request to the * BHND_BUS_DEREGISTER_PROVIDER() method on the parent of @p dev. If no parent * exists, the implementation will return NULL. */ device_t bhnd_bus_generic_retain_provider(device_t dev, device_t child, bhnd_service_t service) { device_t parent = device_get_parent(dev); if (parent != NULL) { return (BHND_BUS_RETAIN_PROVIDER(parent, child, service)); } return (NULL); } /** * Helper function for implementing BHND_BUS_RELEASE_PROVIDER(). * * This implementation delegates the request to the * BHND_BUS_DEREGISTER_PROVIDER() method on the parent of @p dev. If no parent * exists, the implementation will panic. */ void bhnd_bus_generic_release_provider(device_t dev, device_t child, device_t provider, bhnd_service_t service) { device_t parent = device_get_parent(dev); if (parent != NULL) { return (BHND_BUS_RELEASE_PROVIDER(parent, child, provider, service)); } panic("missing BHND_BUS_RELEASE_PROVIDER()"); } /** * Helper function for implementing BHND_BUS_REGISTER_PROVIDER(). * * This implementation uses the bhnd_service_registry_add() function to * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find * a suitable service registry to edit. */ int bhnd_bus_generic_sr_register_provider(device_t dev, device_t child, device_t provider, bhnd_service_t service) { struct bhnd_service_registry *bsr; bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child); KASSERT(bsr != NULL, ("NULL service registry")); return (bhnd_service_registry_add(bsr, provider, service, 0)); } /** * Helper function for implementing BHND_BUS_DEREGISTER_PROVIDER(). * * This implementation uses the bhnd_service_registry_remove() function to * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find * a suitable service registry to edit. */ int bhnd_bus_generic_sr_deregister_provider(device_t dev, device_t child, device_t provider, bhnd_service_t service) { struct bhnd_service_registry *bsr; bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child); KASSERT(bsr != NULL, ("NULL service registry")); return (bhnd_service_registry_remove(bsr, provider, service)); } /** * Helper function for implementing BHND_BUS_RETAIN_PROVIDER(). * * This implementation uses the bhnd_service_registry_retain() function to * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find * a suitable service registry. * * If a local provider for the service is not available, and a parent device is * available, this implementation will attempt to fetch and locally register * a service provider reference from the parent of @p dev. */ device_t bhnd_bus_generic_sr_retain_provider(device_t dev, device_t child, bhnd_service_t service) { struct bhnd_service_registry *bsr; device_t parent, provider; int error; bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child); KASSERT(bsr != NULL, ("NULL service registry")); /* * Attempt to fetch a service provider reference from either the local * service registry, or if not found, from our parent. * * If we fetch a provider from our parent, we register the provider * with the local service registry to prevent conflicting local * registrations from being added. */ while (1) { /* Check the local service registry first */ provider = bhnd_service_registry_retain(bsr, service); if (provider != NULL) return (provider); /* Otherwise, try to delegate to our parent (if any) */ if ((parent = device_get_parent(dev)) == NULL) return (NULL); provider = BHND_BUS_RETAIN_PROVIDER(parent, dev, service); if (provider == NULL) return (NULL); /* Register the inherited service registration with the local * registry */ error = bhnd_service_registry_add(bsr, provider, service, BHND_SPF_INHERITED); if (error) { BHND_BUS_RELEASE_PROVIDER(parent, dev, provider, service); if (error == EEXIST) { /* A valid service provider was registered * concurrently; retry fetching from the local * registry */ continue; } device_printf(dev, "failed to register service " "provider: %d\n", error); return (NULL); } } } /** * Helper function for implementing BHND_BUS_RELEASE_PROVIDER(). * * This implementation uses the bhnd_service_registry_release() function to * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find * a suitable service registry. */ void bhnd_bus_generic_sr_release_provider(device_t dev, device_t child, device_t provider, bhnd_service_t service) { struct bhnd_service_registry *bsr; bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child); KASSERT(bsr != NULL, ("NULL service registry")); /* Release the provider reference; if the refcount hits zero on an * inherited reference, true will be returned, and we need to drop * our own bus reference to the provider */ if (!bhnd_service_registry_release(bsr, provider, service)) return; /* Drop our reference to the borrowed provider */ BHND_BUS_RELEASE_PROVIDER(device_get_parent(dev), dev, provider, service); } /** * Helper function for implementing BHND_BUS_IS_HW_DISABLED(). * * If a parent device is available, this implementation delegates the * request to the BHND_BUS_IS_HW_DISABLED() method on the parent of @p dev. * * If no parent device is available (i.e. on a the bus root), the hardware * is assumed to be usable and false is returned. */ bool bhnd_bus_generic_is_hw_disabled(device_t dev, device_t child) { if (device_get_parent(dev) != NULL) return (BHND_BUS_IS_HW_DISABLED(device_get_parent(dev), child)); return (false); } /** * Helper function for implementing BHND_BUS_GET_CHIPID(). * * This implementation delegates the request to the BHND_BUS_GET_CHIPID() * method on the parent of @p dev. If no parent exists, the implementation * will panic. */ const struct bhnd_chipid * bhnd_bus_generic_get_chipid(device_t dev, device_t child) { if (device_get_parent(dev) != NULL) return (BHND_BUS_GET_CHIPID(device_get_parent(dev), child)); panic("missing BHND_BUS_GET_CHIPID()"); } /** * Helper function for implementing BHND_BUS_GET_DMA_TRANSLATION(). * * If a parent device is available, this implementation delegates the * request to the BHND_BUS_GET_DMA_TRANSLATION() method on the parent of @p dev. * * If no parent device is available, this implementation will panic. */ int bhnd_bus_generic_get_dma_translation(device_t dev, device_t child, u_int width, uint32_t flags, bus_dma_tag_t *dmat, struct bhnd_dma_translation *translation) { if (device_get_parent(dev) != NULL) { return (BHND_BUS_GET_DMA_TRANSLATION(device_get_parent(dev), child, width, flags, dmat, translation)); } panic("missing BHND_BUS_GET_DMA_TRANSLATION()"); } /* nvram board_info population macros for bhnd_bus_generic_read_board_info() */ #define BHND_GV(_dest, _name) \ bhnd_nvram_getvar_uint(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 */ OPT_BHND_GV(info->board_devid, DEVID, 0); /* srom >= 8 */ REQ_BHND_GV(info->board_rev, BOARDREV); OPT_BHND_GV(info->board_srom_rev,SROMREV, 0); /* missing in some SoC NVRAM */ 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 /** * Helper function for implementing BHND_BUS_GET_NVRAM_VAR(). * * This implementation searches @p dev for a usable NVRAM child device. * * 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, bhnd_nvram_type type) { device_t nvram; device_t parent; /* Make sure we're holding Giant for newbus */ GIANT_REQUIRED; /* Look for a directly-attached NVRAM child */ if ((nvram = device_find_child(dev, "bhnd_nvram", -1)) != NULL) return BHND_NVRAM_GETVAR(nvram, name, buf, size, type); /* 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, type)); } /** * Helper function for implementing BHND_BUS_ALLOC_RESOURCE(). * * This implementation of BHND_BUS_ALLOC_RESOURCE() delegates allocation * of the underlying resource to BUS_ALLOC_RESOURCE(), and activation * to @p dev's BHND_BUS_ACTIVATE_RESOURCE(). */ 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, rman_res_t count, u_int flags) { struct bhnd_resource *br; struct resource *res; int error; br = NULL; res = NULL; /* Allocate the real bus resource (without activating it) */ res = BUS_ALLOC_RESOURCE(dev, child, type, rid, start, end, count, (flags & ~RF_ACTIVE)); if (res == NULL) return (NULL); /* Allocate our bhnd resource wrapper. */ br = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT); if (br == NULL) goto failed; br->direct = false; br->res = res; /* Attempt activation */ if (flags & RF_ACTIVE) { error = BHND_BUS_ACTIVATE_RESOURCE(dev, child, type, *rid, br); if (error) goto failed; } return (br); failed: if (res != NULL) BUS_RELEASE_RESOURCE(dev, child, type, *rid, res); free(br, M_BHND); return (NULL); } /** * Helper function for implementing BHND_BUS_RELEASE_RESOURCE(). * * This implementation of BHND_BUS_RELEASE_RESOURCE() delegates release of * the backing resource to BUS_RELEASE_RESOURCE(). */ int bhnd_bus_generic_release_resource(device_t dev, device_t child, int type, int rid, struct bhnd_resource *r) { int error; if ((error = BUS_RELEASE_RESOURCE(dev, child, type, rid, r->res))) return (error); free(r, M_BHND); return (0); } /** * Helper function for implementing BHND_BUS_ACTIVATE_RESOURCE(). * * This implementation of BHND_BUS_ACTIVATE_RESOURCE() first calls the * BHND_BUS_ACTIVATE_RESOURCE() method of the parent of @p dev. * * If this fails, and if @p dev is the direct parent of @p child, standard * resource activation is attempted via bus_activate_resource(). This enables * direct use of the bhnd(4) resource APIs on devices that may not be attached * to a parent bhnd bus or bridge. */ int bhnd_bus_generic_activate_resource(device_t dev, device_t child, int type, int rid, struct bhnd_resource *r) { int error; bool passthrough; passthrough = (device_get_parent(child) != dev); /* Try to delegate to the parent */ if (device_get_parent(dev) != NULL) { error = BHND_BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, type, rid, r); } else { error = ENODEV; } /* If bhnd(4) activation has failed and we're the child's direct * parent, try falling back on standard resource activation. */ if (error && !passthrough) { error = bus_activate_resource(child, type, rid, r->res); if (!error) r->direct = true; } return (error); } /** * Helper function for implementing BHND_BUS_DEACTIVATE_RESOURCE(). * * This implementation of BHND_BUS_ACTIVATE_RESOURCE() simply calls the * BHND_BUS_ACTIVATE_RESOURCE() method of the parent of @p dev. */ int bhnd_bus_generic_deactivate_resource(device_t dev, device_t child, int type, int rid, struct bhnd_resource *r) { if (device_get_parent(dev) != NULL) return (BHND_BUS_DEACTIVATE_RESOURCE(device_get_parent(dev), child, type, rid, r)); return (EINVAL); } /** * Helper function for implementing BHND_BUS_GET_INTR_DOMAIN(). * * This implementation simply returns the address of nearest bhnd(4) bus, * which may be @p dev; this behavior may be incompatible with FDT/OFW targets. */ uintptr_t bhnd_bus_generic_get_intr_domain(device_t dev, device_t child, bool self) { return ((uintptr_t)dev); } Index: head/sys/dev/bhnd/bhnd_types.h =================================================================== --- head/sys/dev/bhnd/bhnd_types.h (revision 328182) +++ head/sys/dev/bhnd/bhnd_types.h (revision 328183) @@ -1,187 +1,188 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2015-2016 Landon Fuller * Copyright (c) 2017 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by Landon Fuller * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ #ifndef _BHND_BHND_TYPES_H_ #define _BHND_BHND_TYPES_H_ #include #include "nvram/bhnd_nvram.h" /** bhnd(4) device classes. */ typedef enum { BHND_DEVCLASS_CC, /**< chipcommon i/o controller */ BHND_DEVCLASS_CC_B, /**< chipcommon auxiliary controller */ BHND_DEVCLASS_PMU, /**< pmu controller */ BHND_DEVCLASS_PCI, /**< pci host/device bridge */ BHND_DEVCLASS_PCIE, /**< pcie host/device bridge */ BHND_DEVCLASS_PCCARD, /**< pcmcia host/device bridge */ BHND_DEVCLASS_RAM, /**< internal RAM/SRAM */ BHND_DEVCLASS_MEMC, /**< memory controller */ BHND_DEVCLASS_ENET, /**< 802.3 MAC/PHY */ BHND_DEVCLASS_ENET_MAC, /**< 802.3 MAC */ BHND_DEVCLASS_ENET_PHY, /**< 802.3 PHY */ BHND_DEVCLASS_WLAN, /**< 802.11 MAC/PHY/Radio */ BHND_DEVCLASS_WLAN_MAC, /**< 802.11 MAC */ BHND_DEVCLASS_WLAN_PHY, /**< 802.11 PHY */ BHND_DEVCLASS_CPU, /**< cpu core */ BHND_DEVCLASS_SOC_ROUTER, /**< interconnect router */ BHND_DEVCLASS_SOC_BRIDGE, /**< interconnect host bridge */ BHND_DEVCLASS_EROM, /**< bus device enumeration ROM */ BHND_DEVCLASS_NVRAM, /**< nvram/flash controller */ BHND_DEVCLASS_USB_HOST, /**< USB host controller */ BHND_DEVCLASS_USB_DEV, /**< USB device controller */ BHND_DEVCLASS_USB_DUAL, /**< USB host/device controller */ + BHND_DEVCLASS_SOFTMODEM, /**< analog/PSTN softmodem codec */ BHND_DEVCLASS_OTHER = 1000, /**< other / unknown */ BHND_DEVCLASS_INVALID /**< no/invalid class */ } bhnd_devclass_t; /** bhnd(4) platform services. */ typedef enum { BHND_SERVICE_CHIPC, /**< chipcommon service; implements the bhnd_chipc interface */ BHND_SERVICE_PWRCTL, /**< legacy pwrctl service; implements the bhnd_pwrctl interface */ BHND_SERVICE_PMU, /**< pmu service; implements the bhnd_pmu interface */ BHND_SERVICE_NVRAM, /**< nvram service; implements the bhnd_nvram interface */ BHND_SERVICE_GPIO, /**< gpio service; implements the standard gpio interface */ BHND_SERVICE_ANY = 1000, /**< match on any service type */ } bhnd_service_t; /** * bhnd(4) port types. * * Only BHND_PORT_DEVICE is guaranteed to be supported by all bhnd(4) bus * implementations. */ typedef enum { BHND_PORT_DEVICE = 0, /**< device memory */ BHND_PORT_BRIDGE = 1, /**< bridge memory */ BHND_PORT_AGENT = 2, /**< interconnect agent/wrapper */ } bhnd_port_type; /** * bhnd(4) attachment types. */ typedef enum { BHND_ATTACH_ADAPTER = 0, /**< A bridged card, such as a PCI WiFi chipset */ BHND_ATTACH_NATIVE = 1 /**< A bus resident on the native host, such as * the primary or secondary bus of an embedded * SoC */ } bhnd_attach_type; /** * bhnd(4) clock types. */ typedef enum { /** * Dynamically select an appropriate clock source based on all * outstanding clock requests. */ BHND_CLOCK_DYN = (1 << 0), /** * Idle Low-Power (ILP). * * No register access is required, or long request latency is * acceptable. */ BHND_CLOCK_ILP = (1 << 1), /** * Active Low-Power (ALP). * * Low-latency register access and low-rate DMA. */ BHND_CLOCK_ALP = (1 << 2), /** * High Throughput (HT). * * High bus throughput and lowest-latency register access. */ BHND_CLOCK_HT = (1 << 3) } bhnd_clock; /** * Given two clock types, return the type with the highest precedence. */ static inline bhnd_clock bhnd_clock_max(bhnd_clock a, bhnd_clock b) { return (a > b ? a : b); } /** * bhnd(4) clock sources. */ typedef enum { /** * Clock is provided by the PCI bus clock */ BHND_CLKSRC_PCI = 0, /** Clock is provided by a crystal. */ BHND_CLKSRC_XTAL = 1, /** Clock is provided by a low power oscillator. */ BHND_CLKSRC_LPO = 2, /** Clock source is unknown */ BHND_CLKSRC_UNKNOWN = 3 } bhnd_clksrc; /** Evaluates to true if @p cls is a device class that can be configured * as a host bridge device. */ #define BHND_DEVCLASS_SUPPORTS_HOSTB(cls) \ ((cls) == BHND_DEVCLASS_PCI || (cls) == BHND_DEVCLASS_PCIE || \ (cls) == BHND_DEVCLASS_PCCARD) /** * BHND bus address. * * @note While the interconnect may support 64-bit addressing, not * all bridges and SoC CPUs will. */ typedef uint64_t bhnd_addr_t; #define BHND_ADDR_MAX UINT64_MAX /**< Maximum bhnd_addr_t value */ /** BHND bus size. */ typedef uint64_t bhnd_size_t; #define BHND_SIZE_MAX UINT64_MAX /**< Maximum bhnd_size_t value */ #endif /* _BHND_BHND_TYPES_H_ */ Index: head/sys/dev/bwn/if_bwn_pci.c =================================================================== --- head/sys/dev/bwn/if_bwn_pci.c (revision 328182) +++ head/sys/dev/bwn/if_bwn_pci.c (revision 328183) @@ -1,311 +1,317 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2015-2016 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_bwn.h" #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include "bhndb_bus_if.h" #include "if_bwn_pcivar.h" /* If non-zero, enable attachment of BWN_QUIRK_UNTESTED devices */ static int attach_untested = 0; TUNABLE_INT("hw.bwn_pci.attach_untested", &attach_untested); /* If non-zero, probe at a higher priority than the stable if_bwn driver. */ static int prefer_new_driver = 1; TUNABLE_INT("hw.bwn_pci.preferred", &prefer_new_driver); /* SIBA Devices */ static const struct bwn_pci_device siba_devices[] = { BWN_BCM_DEV(BCM4306_D11A, "BCM4306 802.11a", - BWN_QUIRK_WLAN_DUALCORE), - BWN_BCM_DEV(BCM4306_D11G, "BCM4306 802.11b/g", 0), - BWN_BCM_DEV(BCM4306_D11G_ID2, "BCM4306 802.11b/g", 0), - BWN_BCM_DEV(BCM4306_D11DUAL, "BCM4306 802.11a/b/g", 0), + BWN_QUIRK_WLAN_DUALCORE|BWN_QUIRK_SOFTMODEM_UNPOPULATED), + BWN_BCM_DEV(BCM4306_D11G, "BCM4306 802.11b/g", + BWN_QUIRK_SOFTMODEM_UNPOPULATED), + BWN_BCM_DEV(BCM4306_D11G_ID2, "BCM4306 802.11b/g", + BWN_QUIRK_SOFTMODEM_UNPOPULATED), + BWN_BCM_DEV(BCM4306_D11DUAL, "BCM4306 802.11a/b/g", + BWN_QUIRK_SOFTMODEM_UNPOPULATED), BWN_BCM_DEV(BCM4307, "BCM4307 802.11b", 0), BWN_BCM_DEV(BCM4311_D11G, "BCM4311 802.11b/g", 0), BWN_BCM_DEV(BCM4311_D11DUAL, "BCM4311 802.11a/b/g", 0), BWN_BCM_DEV(BCM4311_D11A, "BCM4311 802.11a", BWN_QUIRK_UNTESTED|BWN_QUIRK_WLAN_DUALCORE), BWN_BCM_DEV(BCM4318_D11G, "BCM4318 802.11b/g", 0), BWN_BCM_DEV(BCM4318_D11DUAL, "BCM4318 802.11a/b/g", 0), BWN_BCM_DEV(BCM4318_D11A, "BCM4318 802.11a", BWN_QUIRK_UNTESTED|BWN_QUIRK_WLAN_DUALCORE), BWN_BCM_DEV(BCM4321_D11N, "BCM4321 802.11n Dual-Band", BWN_QUIRK_USBH_UNPOPULATED), BWN_BCM_DEV(BCM4321_D11N2G, "BCM4321 802.11n 2GHz", BWN_QUIRK_USBH_UNPOPULATED), BWN_BCM_DEV(BCM4321_D11N5G, "BCM4321 802.11n 5GHz", BWN_QUIRK_UNTESTED|BWN_QUIRK_USBH_UNPOPULATED), BWN_BCM_DEV(BCM4322_D11N, "BCM4322 802.11n Dual-Band", 0), BWN_BCM_DEV(BCM4322_D11N2G, "BCM4322 802.11n 2GHz", BWN_QUIRK_UNTESTED), BWN_BCM_DEV(BCM4322_D11N5G, "BCM4322 802.11n 5GHz", BWN_QUIRK_UNTESTED), BWN_BCM_DEV(BCM4328_D11G, "BCM4328/4312 802.11g", 0), { 0, 0, NULL, 0 } }; /** BCMA Devices */ static const struct bwn_pci_device bcma_devices[] = { BWN_BCM_DEV(BCM4331_D11N, "BCM4331 802.11n Dual-Band", 0), BWN_BCM_DEV(BCM4331_D11N2G, "BCM4331 802.11n 2GHz", 0), BWN_BCM_DEV(BCM4331_D11N5G, "BCM4331 802.11n 5GHz", 0), BWN_BCM_DEV(BCM43224_D11N, "BCM43224 802.11n Dual-Band", 0), BWN_BCM_DEV(BCM43224_D11N_ID_VEN1, "BCM43224 802.11n Dual-Band",0), BWN_BCM_DEV(BCM43225_D11N2G, "BCM43225 802.11n 2GHz", 0), { 0, 0, NULL, 0} }; /** Device configuration table */ static const struct bwn_pci_devcfg bwn_pci_devcfgs[] = { /* SIBA devices */ { .bridge_hwcfg = &bhndb_pci_siba_generic_hwcfg, .bridge_hwtable = bhndb_pci_generic_hw_table, .bridge_hwprio = bhndb_siba_priority_table, .devices = siba_devices }, /* BCMA devices */ { .bridge_hwcfg = &bhndb_pci_bcma_generic_hwcfg, .bridge_hwtable = bhndb_pci_generic_hw_table, .bridge_hwprio = bhndb_bcma_priority_table, .devices = bcma_devices }, { NULL, NULL, NULL } }; /** Search the device configuration table for an entry matching @p dev. */ static int bwn_pci_find_devcfg(device_t dev, const struct bwn_pci_devcfg **cfg, const struct bwn_pci_device **device) { const struct bwn_pci_devcfg *dvc; const struct bwn_pci_device *dv; for (dvc = bwn_pci_devcfgs; dvc->devices != NULL; dvc++) { for (dv = dvc->devices; dv->device != 0; dv++) { if (pci_get_vendor(dev) == dv->vendor && pci_get_device(dev) == dv->device) { if (cfg != NULL) *cfg = dvc; if (device != NULL) *device = dv; return (0); } } } return (ENOENT); } static int bwn_pci_probe(device_t dev) { const struct bwn_pci_device *ident; if (bwn_pci_find_devcfg(dev, NULL, &ident)) return (ENXIO); /* Skip untested devices */ if (ident->quirks & BWN_QUIRK_UNTESTED && !attach_untested) return (ENXIO); device_set_desc(dev, ident->desc); /* Until this driver is complete, require explicit opt-in before * superceding if_bwn/siba_bwn. */ if (prefer_new_driver) return (BUS_PROBE_DEFAULT+1); else return (BUS_PROBE_LOW_PRIORITY); // return (BUS_PROBE_DEFAULT); } static int bwn_pci_attach(device_t dev) { struct bwn_pci_softc *sc; const struct bwn_pci_device *ident; int error; sc = device_get_softc(dev); sc->dev = dev; /* Find our hardware config */ if (bwn_pci_find_devcfg(dev, &sc->devcfg, &ident)) return (ENXIO); /* Save quirk flags */ sc->quirks = ident->quirks; /* Attach bridge device */ if ((error = bhndb_attach_bridge(dev, &sc->bhndb_dev, -1))) return (ENXIO); /* Success */ return (0); } static int bwn_pci_detach(device_t dev) { int error; if ((error = bus_generic_detach(dev))) return (error); return (device_delete_children(dev)); } static void bwn_pci_probe_nomatch(device_t dev, device_t child) { const char *name; name = device_get_name(child); if (name == NULL) name = "unknown device"; device_printf(dev, "<%s> (no driver attached)\n", name); } static const struct bhndb_hwcfg * bwn_pci_get_generic_hwcfg(device_t dev, device_t child) { struct bwn_pci_softc *sc = device_get_softc(dev); return (sc->devcfg->bridge_hwcfg); } static const struct bhndb_hw * bwn_pci_get_bhndb_hwtable(device_t dev, device_t child) { struct bwn_pci_softc *sc = device_get_softc(dev); return (sc->devcfg->bridge_hwtable); } static const struct bhndb_hw_priority * bwn_pci_get_bhndb_hwprio(device_t dev, device_t child) { struct bwn_pci_softc *sc = device_get_softc(dev); return (sc->devcfg->bridge_hwprio); } static bool bwn_pci_is_core_disabled(device_t dev, device_t child, struct bhnd_core_info *core) { struct bwn_pci_softc *sc; sc = device_get_softc(dev); switch (bhnd_core_class(core)) { case BHND_DEVCLASS_WLAN: if (core->unit > 0 && !(sc->quirks & BWN_QUIRK_WLAN_DUALCORE)) return (true); return (false); case BHND_DEVCLASS_ENET: case BHND_DEVCLASS_ENET_MAC: case BHND_DEVCLASS_ENET_PHY: return ((sc->quirks & BWN_QUIRK_ENET_HW_UNPOPULATED) != 0); case BHND_DEVCLASS_USB_HOST: return ((sc->quirks & BWN_QUIRK_USBH_UNPOPULATED) != 0); + + case BHND_DEVCLASS_SOFTMODEM: + return ((sc->quirks & BWN_QUIRK_SOFTMODEM_UNPOPULATED) != 0); default: return (false); } } static device_method_t bwn_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bwn_pci_probe), DEVMETHOD(device_attach, bwn_pci_attach), DEVMETHOD(device_detach, bwn_pci_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_probe_nomatch, bwn_pci_probe_nomatch), /* BHNDB_BUS Interface */ DEVMETHOD(bhndb_bus_get_generic_hwcfg, bwn_pci_get_generic_hwcfg), DEVMETHOD(bhndb_bus_get_hardware_table, bwn_pci_get_bhndb_hwtable), DEVMETHOD(bhndb_bus_get_hardware_prio, bwn_pci_get_bhndb_hwprio), DEVMETHOD(bhndb_bus_is_core_disabled, bwn_pci_is_core_disabled), DEVMETHOD_END }; static devclass_t bwn_pci_devclass; DEFINE_CLASS_0(bwn_pci, bwn_pci_driver, bwn_pci_methods, sizeof(struct bwn_pci_softc)); DRIVER_MODULE_ORDERED(bwn_pci, pci, bwn_pci_driver, bwn_pci_devclass, NULL, NULL, SI_ORDER_ANY); DRIVER_MODULE(bhndb, bwn_pci, bhndb_pci_driver, bhndb_devclass, NULL, NULL); MODULE_DEPEND(bwn_pci, bhnd, 1, 1, 1); MODULE_DEPEND(bwn_pci, bhndb, 1, 1, 1); MODULE_DEPEND(bwn_pci, bhndb_pci, 1, 1, 1); MODULE_DEPEND(bwn_pci, bcma_bhndb, 1, 1, 1); MODULE_DEPEND(bwn_pci, siba_bhndb, 1, 1, 1); MODULE_VERSION(bwn_pci, 1); Index: head/sys/dev/bwn/if_bwn_pcivar.h =================================================================== --- head/sys/dev/bwn/if_bwn_pcivar.h (revision 328182) +++ head/sys/dev/bwn/if_bwn_pcivar.h (revision 328183) @@ -1,100 +1,107 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2015-2016 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _IF_BWN_PCIVAR_H_ #define _IF_BWN_PCIVAR_H_ struct bwn_pci_devcfg; /** bwn_pci per-instance state. */ struct bwn_pci_softc { device_t dev; /**< device */ device_t bhndb_dev; /**< bhnd bridge device */ const struct bwn_pci_devcfg *devcfg; /**< bwn device config */ uint32_t quirks; /**< quirk flags */ }; /* bwn device quirks */ enum { /** No quirks */ BWN_QUIRK_NONE = 0, /** * This model/revision has not been tested and may not work. */ BWN_QUIRK_UNTESTED = 1<<0, /** * Early dual-band devices did not support accessing multiple PHYs * from a single WLAN core, and instead used separate 2GHz and 5GHz * WLAN cores. * * However, not all cards with two WLAN cores are fully populated; * we must whitelist the boards on which a second WLAN core is actually * usable. */ BWN_QUIRK_WLAN_DUALCORE = 1<<1, /** * Some early devices shipped with unconnected ethernet cores; set * this quirk to treat these cores as unpopulated. */ BWN_QUIRK_ENET_HW_UNPOPULATED = 1<<2, /** * Some PCI/PCIe "Intensi-fi" chipsets shipped with floating USB * host controller cores; set this quirk to treat these cores as * unpopulated. */ BWN_QUIRK_USBH_UNPOPULATED = 1<<3, + + /** + * Some early devices (including all BCM4306 chipsets) shipped with + * floating analog softmodem codec cores; set this quirk to treat these + * cores as unpopulated. + */ + BWN_QUIRK_SOFTMODEM_UNPOPULATED = 1<<4, }; /* PCI device descriptor */ struct bwn_pci_device { uint16_t vendor; uint16_t device; const char *desc; uint32_t quirks; }; #define BWN_BCM_DEV(_devid, _desc, _quirks) \ { PCI_VENDOR_BROADCOM, PCI_DEVID_ ## _devid, \ "Broadcom " _desc " Wireless", _quirks } /* Supported device table */ struct bwn_pci_devcfg { const struct bhndb_hwcfg *bridge_hwcfg; const struct bhndb_hw *bridge_hwtable; const struct bhndb_hw_priority *bridge_hwprio; const struct bwn_pci_device *devices; }; #endif /* _IF_BWN_PCIVAR_H_ */