[bhnd] Initial bhnd(4) SPROM/NVRAM support.

This adds support for the NVRAM handling and the basic SPROM
hardware used on siba(4) and bcma(4) devices, including:

* SPROM directly attached to the PCI core, accessible via PCI configuration
  space.
* SPROM attached to later ChipCommon cores.
* SPROM variables vended from the parent SoC bus (e.g. via a directly-attached
  flash device).

Additional improvements to the NVRAM/SPROM interface will
be required, but this changeset stands alone as working
checkpoint.

Submitted by:	Landon Fuller <landonf@landonf.org>
Reviewed by:	Michael Zhilin <mizkha@gmail.com> (Broadcom MIPS support)
Differential Revision:	https://reviews.freebsd.org/D6196
This commit is contained in:
Adrian Chadd 2016-05-08 19:14:05 +00:00
parent f74f1a68d5
commit e83ce34035
34 changed files with 4550 additions and 1160 deletions

View file

@ -9,6 +9,16 @@ acpi_quirks.h optional acpi \
compile-with "${AWK} -f $S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \
no-obj no-implicit-rule before-depend \
clean "acpi_quirks.h"
bhnd_nvram_map.h optional bhndbus | bhnd \
dependency "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \
compile-with "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -h" \
no-obj no-implicit-rule before-depend \
clean "bhnd_nvram_map.h"
bhnd_nvram_map_data.h optional bhndbus | bhnd \
dependency "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \
compile-with "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -d" \
no-obj no-implicit-rule before-depend \
clean "bhnd_nvram_map_data.h"
#
# The 'fdt_dtb_file' target covers an actual DTB file name, which is derived
# from the specified source (DTS) file: <platform>.dts -> <platform>.dtb
@ -1121,6 +1131,7 @@ dev/bhnd/bhndb/bhndb_hwdata.c optional bhndbus | bhndb
dev/bhnd/bhndb/bhndb_if.m optional bhndbus | bhndb
dev/bhnd/bhndb/bhndb_pci.c optional bhndbus pci | bhndb pci
dev/bhnd/bhndb/bhndb_pci_hwdata.c optional bhndbus pci | bhndb pci
dev/bhnd/bhndb/bhndb_pci_sprom.c optional bhndbus pci | bhndb pci
dev/bhnd/bhndb/bhndb_subr.c optional bhndbus pci | bhndb
dev/bhnd/bcma/bcma.c optional bhndbus | bcma
dev/bhnd/bcma/bcma_bhndb.c optional bhndbus | bcma bhndb
@ -1132,6 +1143,8 @@ dev/bhnd/cores/pci/bhnd_pci.c optional bhndbus pci | bhnd pci
dev/bhnd/cores/pci/bhnd_pci_hostb.c optional bhndbus pci | bhndb pci
dev/bhnd/cores/pci/bhnd_pcib.c optional bhnd_pcib bhnd pci
dev/bhnd/nvram/bhnd_nvram_if.m optional bhndbus | bhnd
dev/bhnd/nvram/bhnd_sprom.c optional bhndbus | bhnd
dev/bhnd/nvram/nvram_subr.c optional bhndbus | bhnd
dev/bhnd/siba/siba.c optional bhndbus | siba
dev/bhnd/siba/siba_bhndb.c optional bhndbus | siba bhndb
dev/bhnd/siba/siba_nexus.c optional siba_nexus siba

View file

@ -411,6 +411,26 @@ ${_i}devs.h: ${SYSDIR}/tools/${_i}devs2h.awk ${SYSDIR}/dev/${_i}/${_i}devs
.endif
.endfor # _i
.if !empty(SRCS:Mbhnd_nvram_map.h)
CLEANFILES+= bhnd_nvram_map.h
bhnd_nvram_map.h: ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.awk \
${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
${SYSDIR}/dev/bhnd/nvram/nvram_map
bhnd_nvram_map.h:
${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
${SYSDIR}/dev/bhnd/nvram/nvram_map -h
.endif
.if !empty(SRCS:Mbhnd_nvram_map_data.h)
CLEANFILES+= bhnd_nvram_map_data.h
bhnd_nvram_map_data.h: ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.awk \
${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
${SYSDIR}/dev/bhnd/nvram/nvram_map
bhnd_nvram_map_data.h:
${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
${SYSDIR}/dev/bhnd/nvram/nvram_map -d
.endif
.if !empty(SRCS:Musbdevs.h)
CLEANFILES+= usbdevs.h
usbdevs.h: ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs

View file

@ -1,373 +0,0 @@
/*-
* Copyright (c) 2010 Broadcom Corporation
*
* This file is derived from the bcmsrom.h header distributed with Broadcom's
* 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_BCMSROM_FMT_H_
#define _BHND_BCMSROM_FMT_H_
/* Maximum srom: 6 Kilobits == 768 bytes */
#define SROM_MAX 768
#define SROM_MAXW 384
#define VARS_MAX 4096
/* PCI fields */
#define PCI_F0DEVID 48
#define SROM_WORDS 64
#define SROM3_SWRGN_OFF 28 /* s/w region offset in words */
#define SROM_SSID 2
#define SROM_WL1LHMAXP 29
#define SROM_WL1LPAB0 30
#define SROM_WL1LPAB1 31
#define SROM_WL1LPAB2 32
#define SROM_WL1HPAB0 33
#define SROM_WL1HPAB1 34
#define SROM_WL1HPAB2 35
#define SROM_MACHI_IL0 36
#define SROM_MACMID_IL0 37
#define SROM_MACLO_IL0 38
#define SROM_MACHI_ET0 39
#define SROM_MACMID_ET0 40
#define SROM_MACLO_ET0 41
#define SROM_MACHI_ET1 42
#define SROM_MACMID_ET1 43
#define SROM_MACLO_ET1 44
#define SROM3_MACHI 37
#define SROM3_MACMID 38
#define SROM3_MACLO 39
#define SROM_BXARSSI2G 40
#define SROM_BXARSSI5G 41
#define SROM_TRI52G 42
#define SROM_TRI5GHL 43
#define SROM_RXPO52G 45
#define SROM2_ENETPHY 45
#define SROM_AABREV 46
/* Fields in AABREV */
#define SROM_BR_MASK 0x00ff
#define SROM_CC_MASK 0x0f00
#define SROM_CC_SHIFT 8
#define SROM_AA0_MASK 0x3000
#define SROM_AA0_SHIFT 12
#define SROM_AA1_MASK 0xc000
#define SROM_AA1_SHIFT 14
#define SROM_WL0PAB0 47
#define SROM_WL0PAB1 48
#define SROM_WL0PAB2 49
#define SROM_LEDBH10 50
#define SROM_LEDBH32 51
#define SROM_WL10MAXP 52
#define SROM_WL1PAB0 53
#define SROM_WL1PAB1 54
#define SROM_WL1PAB2 55
#define SROM_ITT 56
#define SROM_BFL 57
#define SROM_BFL2 28
#define SROM3_BFL2 61
#define SROM_AG10 58
#define SROM_CCODE 59
#define SROM_OPO 60
#define SROM3_LEDDC 62
#define SROM_CRCREV 63
/* SROM Rev 4: Reallocate the software part of the srom to accommodate
* MIMO features. It assumes up to two PCIE functions and 440 bytes
* of useable srom i.e. the useable storage in chips with OTP that
* implements hardware redundancy.
*/
#define SROM4_WORDS 220
#define SROM4_SIGN 32
#define SROM4_SIGNATURE 0x5372
#define SROM4_BREV 33
#define SROM4_BFL0 34
#define SROM4_BFL1 35
#define SROM4_BFL2 36
#define SROM4_BFL3 37
#define SROM5_BFL0 37
#define SROM5_BFL1 38
#define SROM5_BFL2 39
#define SROM5_BFL3 40
#define SROM4_MACHI 38
#define SROM4_MACMID 39
#define SROM4_MACLO 40
#define SROM5_MACHI 41
#define SROM5_MACMID 42
#define SROM5_MACLO 43
#define SROM4_CCODE 41
#define SROM4_REGREV 42
#define SROM5_CCODE 34
#define SROM5_REGREV 35
#define SROM4_LEDBH10 43
#define SROM4_LEDBH32 44
#define SROM5_LEDBH10 59
#define SROM5_LEDBH32 60
#define SROM4_LEDDC 45
#define SROM5_LEDDC 45
#define SROM4_AA 46
#define SROM4_AA2G_MASK 0x00ff
#define SROM4_AA2G_SHIFT 0
#define SROM4_AA5G_MASK 0xff00
#define SROM4_AA5G_SHIFT 8
#define SROM4_AG10 47
#define SROM4_AG32 48
#define SROM4_TXPID2G 49
#define SROM4_TXPID5G 51
#define SROM4_TXPID5GL 53
#define SROM4_TXPID5GH 55
#define SROM4_TXRXC 61
#define SROM4_TXCHAIN_MASK 0x000f
#define SROM4_TXCHAIN_SHIFT 0
#define SROM4_RXCHAIN_MASK 0x00f0
#define SROM4_RXCHAIN_SHIFT 4
#define SROM4_SWITCH_MASK 0xff00
#define SROM4_SWITCH_SHIFT 8
/* Per-path fields */
#define MAX_PATH_SROM 4
#define SROM4_PATH0 64
#define SROM4_PATH1 87
#define SROM4_PATH2 110
#define SROM4_PATH3 133
#define SROM4_2G_ITT_MAXP 0
#define SROM4_2G_PA 1
#define SROM4_5G_ITT_MAXP 5
#define SROM4_5GLH_MAXP 6
#define SROM4_5G_PA 7
#define SROM4_5GL_PA 11
#define SROM4_5GH_PA 15
/* Fields in the ITT_MAXP and 5GLH_MAXP words */
#define B2G_MAXP_MASK 0xff
#define B2G_ITT_SHIFT 8
#define B5G_MAXP_MASK 0xff
#define B5G_ITT_SHIFT 8
#define B5GH_MAXP_MASK 0xff
#define B5GL_MAXP_SHIFT 8
/* All the miriad power offsets */
#define SROM4_2G_CCKPO 156
#define SROM4_2G_OFDMPO 157
#define SROM4_5G_OFDMPO 159
#define SROM4_5GL_OFDMPO 161
#define SROM4_5GH_OFDMPO 163
#define SROM4_2G_MCSPO 165
#define SROM4_5G_MCSPO 173
#define SROM4_5GL_MCSPO 181
#define SROM4_5GH_MCSPO 189
#define SROM4_CDDPO 197
#define SROM4_STBCPO 198
#define SROM4_BW40PO 199
#define SROM4_BWDUPPO 200
#define SROM4_CRCREV 219
/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
* This is acombined srom for both MIMO and SISO boards, usable in
* the .130 4Kilobit OTP with hardware redundancy.
*/
#define SROM8_SIGN 64
#define SROM8_BREV 65
#define SROM8_BFL0 66
#define SROM8_BFL1 67
#define SROM8_BFL2 68
#define SROM8_BFL3 69
#define SROM8_MACHI 70
#define SROM8_MACMID 71
#define SROM8_MACLO 72
#define SROM8_CCODE 73
#define SROM8_REGREV 74
#define SROM8_LEDBH10 75
#define SROM8_LEDBH32 76
#define SROM8_LEDDC 77
#define SROM8_AA 78
#define SROM8_AG10 79
#define SROM8_AG32 80
#define SROM8_TXRXC 81
#define SROM8_BXARSSI2G 82
#define SROM8_BXARSSI5G 83
#define SROM8_TRI52G 84
#define SROM8_TRI5GHL 85
#define SROM8_RXPO52G 86
#define SROM8_FEM2G 87
#define SROM8_FEM5G 88
#define SROM8_FEM_ANTSWLUT_MASK 0xf800
#define SROM8_FEM_ANTSWLUT_SHIFT 11
#define SROM8_FEM_TR_ISO_MASK 0x0700
#define SROM8_FEM_TR_ISO_SHIFT 8
#define SROM8_FEM_PDET_RANGE_MASK 0x00f8
#define SROM8_FEM_PDET_RANGE_SHIFT 3
#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006
#define SROM8_FEM_EXTPA_GAIN_SHIFT 1
#define SROM8_FEM_TSSIPOS_MASK 0x0001
#define SROM8_FEM_TSSIPOS_SHIFT 0
#define SROM8_THERMAL 89
/* Temp sense related entries */
#define SROM8_MPWR_RAWTS 90
#define SROM8_TS_SLP_OPT_CORRX 91
/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
#define SROM8_FOC_HWIQ_IQSWP 92
/* Temperature delta for PHY calibration */
#define SROM8_PHYCAL_TEMPDELTA 93
/* Per-path offsets & fields */
#define SROM8_PATH0 96
#define SROM8_PATH1 112
#define SROM8_PATH2 128
#define SROM8_PATH3 144
#define SROM8_2G_ITT_MAXP 0
#define SROM8_2G_PA 1
#define SROM8_5G_ITT_MAXP 4
#define SROM8_5GLH_MAXP 5
#define SROM8_5G_PA 6
#define SROM8_5GL_PA 9
#define SROM8_5GH_PA 12
/* All the miriad power offsets */
#define SROM8_2G_CCKPO 160
#define SROM8_2G_OFDMPO 161
#define SROM8_5G_OFDMPO 163
#define SROM8_5GL_OFDMPO 165
#define SROM8_5GH_OFDMPO 167
#define SROM8_2G_MCSPO 169
#define SROM8_5G_MCSPO 177
#define SROM8_5GL_MCSPO 185
#define SROM8_5GH_MCSPO 193
#define SROM8_CDDPO 201
#define SROM8_STBCPO 202
#define SROM8_BW40PO 203
#define SROM8_BWDUPPO 204
/* SISO PA parameters are in the path0 spaces */
#define SROM8_SISO 96
/* Legacy names for SISO PA parameters */
#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP)
#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA)
#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1)
#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2)
#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP)
#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP)
#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA)
#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1)
#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2)
#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA)
#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1)
#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2)
#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA)
#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1)
#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2)
#define SROM8_CRCREV 219
/* SROM REV 9 */
#define SROM9_2GPO_CCKBW20 160
#define SROM9_2GPO_CCKBW20UL 161
#define SROM9_2GPO_LOFDMBW20 162
#define SROM9_2GPO_LOFDMBW20UL 164
#define SROM9_5GLPO_LOFDMBW20 166
#define SROM9_5GLPO_LOFDMBW20UL 168
#define SROM9_5GMPO_LOFDMBW20 170
#define SROM9_5GMPO_LOFDMBW20UL 172
#define SROM9_5GHPO_LOFDMBW20 174
#define SROM9_5GHPO_LOFDMBW20UL 176
#define SROM9_2GPO_MCSBW20 178
#define SROM9_2GPO_MCSBW20UL 180
#define SROM9_2GPO_MCSBW40 182
#define SROM9_5GLPO_MCSBW20 184
#define SROM9_5GLPO_MCSBW20UL 186
#define SROM9_5GLPO_MCSBW40 188
#define SROM9_5GMPO_MCSBW20 190
#define SROM9_5GMPO_MCSBW20UL 192
#define SROM9_5GMPO_MCSBW40 194
#define SROM9_5GHPO_MCSBW20 196
#define SROM9_5GHPO_MCSBW20UL 198
#define SROM9_5GHPO_MCSBW40 200
#define SROM9_PO_MCS32 202
#define SROM9_PO_LOFDM40DUP 203
#define SROM9_REV_CRC 219
typedef struct {
u8 tssipos; /* TSSI positive slope, 1: positive, 0: negative */
u8 extpagain; /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
u8 pdetrange; /* support 32 combinations of different Pdet dynamic ranges */
u8 triso; /* TR switch isolation */
u8 antswctrllut; /* antswctrl lookup table configuration: 32 possible choices */
} srom_fem_t;
#endif /* _BHND_BCMSROM_TBL_H_ */

View file

@ -1,577 +0,0 @@
/*-
* Copyright (c) 2010 Broadcom Corporation
*
* This file is derived from the bcmsrom.h header distributed with Broadcom's
* 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_BCMSROM_TBL_H_
#define _BHND_BCMSROM_TBL_H_
#include "bcmsrom_fmt.h"
typedef struct {
const char *name;
u32 revmask;
u32 flags;
u16 off;
u16 mask;
} sromvar_t;
#define SRFL_MORE 1 /* value continues as described by the next entry */
#define SRFL_NOFFS 2 /* value bits can't be all one's */
#define SRFL_PRHEX 4 /* value is in hexdecimal format */
#define SRFL_PRSIGN 8 /* value is in signed decimal format */
#define SRFL_CCODE 0x10 /* value is in country code format */
#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */
#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */
#define SRFL_NOVAR 0x80 /* do not generate a nvram param, entry is for mfgc */
/* Assumptions:
* - Ethernet address spans across 3 consective words
*
* Table rules:
* - Add multiple entries next to each other if a value spans across multiple words
* (even multiple fields in the same word) with each entry except the last having
* it's SRFL_MORE bit set.
* - Ethernet address entry does not follow above rule and must not have SRFL_MORE
* bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
* - The last entry's name field must be NULL to indicate the end of the table. Other
* entries must have non-NULL name.
*/
static const sromvar_t pci_sromvars[] = {
{"devid", 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, 0xffff},
{"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK},
{"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
{"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
{"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
{"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
{"", 0, 0, SROM_BFL2, 0xffff},
{"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
{"", 0, 0, SROM3_BFL2, 0xffff},
{"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff},
{"", 0, 0, SROM4_BFL1, 0xffff},
{"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff},
{"", 0, 0, SROM5_BFL1, 0xffff},
{"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff},
{"", 0, 0, SROM8_BFL1, 0xffff},
{"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff},
{"", 0, 0, SROM4_BFL3, 0xffff},
{"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff},
{"", 0, 0, SROM5_BFL3, 0xffff},
{"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff},
{"", 0, 0, SROM8_BFL3, 0xffff},
{"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
{"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
{"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff},
{"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff},
{"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff},
{"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff},
{"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
{"regrev", 0x00000008, 0, SROM_OPO, 0xff00},
{"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff},
{"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff},
{"regrev", 0xffffff00, 0, SROM8_REGREV, 0x00ff},
{"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
{"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
{"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
{"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
{"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
{"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
{"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
{"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
{"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
{"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
{"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
{"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
{"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
{"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
{"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
{"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
{"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
{"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
{"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
{"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff},
{"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
{"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
{"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
{"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
{"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
{"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
{"opo", 0x0000000c, 0, SROM_OPO, 0x00ff},
{"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
{"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
{"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff},
{"aa2g", 0xffffff00, 0, SROM8_AA, 0x00ff},
{"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
{"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00},
{"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00},
{"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff},
{"ag1", 0x0000000e, 0, SROM_AG10, 0xff00},
{"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff},
{"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00},
{"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff},
{"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00},
{"ag0", 0xffffff00, 0, SROM8_AG10, 0x00ff},
{"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00},
{"ag2", 0xffffff00, 0, SROM8_AG32, 0x00ff},
{"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00},
{"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
{"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
{"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
{"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
{"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
{"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
{"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
{"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
{"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
{"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00},
{"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
{"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
{"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
{"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
{"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
{"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
{"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
{"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
{"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
{"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
{"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
{"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
{"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
{"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
{"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
{"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
{"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
{"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
{"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
{"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
{"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
{"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
{"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
{"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
{"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
{"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
{"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
{"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
{"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
{"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
{"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
{"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
{"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff},
{"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00},
{"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
{"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00},
{"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
{"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00},
{"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
{"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
{"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
{"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
{"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
{"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
{"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK},
{"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK},
{"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK},
{"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK},
{"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK},
{"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK},
{"tssipos2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK},
{"extpagain2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK},
{"pdetrange2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK},
{"triso2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
{"antswctl2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK},
{"tssipos5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK},
{"extpagain5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK},
{"pdetrange5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK},
{"triso5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
{"antswctl5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK},
{"tempthresh", 0xffffff00, 0, SROM8_THERMAL, 0xff00},
{"tempoffset", 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
{"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
{"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
{"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G+1, 0x00ff},
{"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G+1, 0xff00},
{"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
{"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
{"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G+1, 0x00ff},
{"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G+1, 0xff00},
{"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
{"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
{"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL+1, 0x00ff},
{"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL+1, 0xff00},
{"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
{"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
{"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH+1, 0x00ff},
{"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH+1, 0xff00},
{"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
{"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
{"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
{"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
{"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
{"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
{"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
{"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
{"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff},
{"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff},
{"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff},
{"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff},
{"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff},
{"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff},
{"rawtempsense",0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff},
{"measpower", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00},
{"tempsense_slope",0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x00ff},
{"tempcorrx", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00},
{"tempsense_option",0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x0300},
{"freqoffset_corr",0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x000f},
{"iqcal_swp_dis",0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010},
{"hw_iqcal_en", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020},
{"phycal_tempdelta",0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff},
{"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
{"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
{"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
{"", 0, 0, SROM4_2G_OFDMPO+1, 0xffff},
{"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
{"", 0, 0, SROM4_5G_OFDMPO+1, 0xffff},
{"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
{"", 0, 0, SROM4_5GL_OFDMPO+1, 0xffff},
{"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
{"", 0, 0, SROM4_5GH_OFDMPO+1, 0xffff},
{"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
{"", 0, 0, SROM8_2G_OFDMPO+1, 0xffff},
{"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
{"", 0, 0, SROM8_5G_OFDMPO+1, 0xffff},
{"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
{"", 0, 0, SROM8_5GL_OFDMPO+1, 0xffff},
{"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
{"", 0, 0, SROM8_5GH_OFDMPO+1, 0xffff},
{"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
{"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO+1, 0xffff},
{"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO+2, 0xffff},
{"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO+3, 0xffff},
{"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO+4, 0xffff},
{"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO+5, 0xffff},
{"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO+6, 0xffff},
{"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO+7, 0xffff},
{"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
{"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO+1, 0xffff},
{"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO+2, 0xffff},
{"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO+3, 0xffff},
{"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO+4, 0xffff},
{"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO+5, 0xffff},
{"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO+6, 0xffff},
{"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO+7, 0xffff},
{"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
{"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO+1, 0xffff},
{"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO+2, 0xffff},
{"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO+3, 0xffff},
{"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO+4, 0xffff},
{"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO+5, 0xffff},
{"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO+6, 0xffff},
{"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO+7, 0xffff},
{"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
{"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO+1, 0xffff},
{"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO+2, 0xffff},
{"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO+3, 0xffff},
{"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO+4, 0xffff},
{"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO+5, 0xffff},
{"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO+6, 0xffff},
{"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO+7, 0xffff},
{"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
{"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO+1, 0xffff},
{"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO+2, 0xffff},
{"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO+3, 0xffff},
{"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO+4, 0xffff},
{"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO+5, 0xffff},
{"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO+6, 0xffff},
{"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO+7, 0xffff},
{"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
{"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO+1, 0xffff},
{"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO+2, 0xffff},
{"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO+3, 0xffff},
{"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO+4, 0xffff},
{"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO+5, 0xffff},
{"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO+6, 0xffff},
{"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO+7, 0xffff},
{"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
{"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO+1, 0xffff},
{"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO+2, 0xffff},
{"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO+3, 0xffff},
{"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO+4, 0xffff},
{"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO+5, 0xffff},
{"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO+6, 0xffff},
{"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO+7, 0xffff},
{"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
{"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO+1, 0xffff},
{"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO+2, 0xffff},
{"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO+3, 0xffff},
{"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO+4, 0xffff},
{"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO+5, 0xffff},
{"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO+6, 0xffff},
{"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO+7, 0xffff},
{"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff},
{"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff},
{"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff},
{"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
{"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff},
{"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff},
{"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff},
{"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
/* power per rate from sromrev 9 */
{"cckbw202gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
{"cckbw20ul2gpo",0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
{"legofdmbw202gpo",0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20, 0xffff},
{"", 0, 0, SROM9_2GPO_LOFDMBW20+1, 0xffff},
{"legofdmbw20ul2gpo",0xfffffe00,SRFL_MORE, SROM9_2GPO_LOFDMBW20UL, 0xffff},
{"", 0, 0, SROM9_2GPO_LOFDMBW20UL+1,0xffff},
{"legofdmbw205glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20, 0xffff},
{"", 0, 0, SROM9_5GLPO_LOFDMBW20+1,0xffff},
{"legofdmbw20ul5glpo",0xfffffe00,SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,0xffff},
{"", 0, 0, SROM9_5GLPO_LOFDMBW20UL+1,0xffff},
{"legofdmbw205gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20, 0xffff},
{"", 0, 0, SROM9_5GMPO_LOFDMBW20+1,0xffff},
{"legofdmbw20ul5gmpo",0xfffffe00,SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,0xffff},
{"", 0, 0, SROM9_5GMPO_LOFDMBW20UL+1,0xffff},
{"legofdmbw205ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20, 0xffff},
{"", 0, 0, SROM9_5GHPO_LOFDMBW20+1,0xffff},
{"legofdmbw20ul5ghpo",0xfffffe00,SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,0xffff},
{"", 0, 0, SROM9_5GHPO_LOFDMBW20UL+1,0xffff},
{"mcsbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff},
{"", 0, 0, SROM9_2GPO_MCSBW20+1, 0xffff},
{"mcsbw20ul2gpo",0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff},
{"", 0, 0, SROM9_2GPO_MCSBW20UL+1, 0xffff},
{"mcsbw402gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff},
{"", 0, 0, SROM9_2GPO_MCSBW40+1, 0xffff},
{"mcsbw205glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff},
{"", 0, 0, SROM9_5GLPO_MCSBW20+1, 0xffff},
{"mcsbw20ul5glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20UL, 0xffff},
{"", 0, 0, SROM9_5GLPO_MCSBW20UL+1,0xffff},
{"mcsbw405glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff},
{"", 0, 0, SROM9_5GLPO_MCSBW40+1, 0xffff},
{"mcsbw205gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff},
{"", 0, 0, SROM9_5GMPO_MCSBW20+1, 0xffff},
{"mcsbw20ul5gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20UL, 0xffff},
{"", 0, 0, SROM9_5GMPO_MCSBW20UL+1,0xffff},
{"mcsbw405gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff},
{"", 0, 0, SROM9_5GMPO_MCSBW40+1, 0xffff},
{"mcsbw205ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff},
{"", 0, 0, SROM9_5GHPO_MCSBW20+1, 0xffff},
{"mcsbw20ul5ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20UL, 0xffff},
{"", 0, 0, SROM9_5GHPO_MCSBW20UL+1,0xffff},
{"mcsbw405ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff},
{"", 0, 0, SROM9_5GHPO_MCSBW40+1, 0xffff},
{"mcs32po", 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
{"legofdm40duppo",0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
{NULL, 0, 0, 0, 0}
};
static const sromvar_t perpath_pci_sromvars[] = {
{"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
{"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
{"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
{"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
{"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA+1, 0xffff},
{"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA+2, 0xffff},
{"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA+3, 0xffff},
{"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
{"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
{"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
{"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
{"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA+1, 0xffff},
{"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA+2, 0xffff},
{"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA+3, 0xffff},
{"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
{"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA+1, 0xffff},
{"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA+2, 0xffff},
{"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA+3, 0xffff},
{"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
{"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA+1, 0xffff},
{"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA+2, 0xffff},
{"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA+3, 0xffff},
{"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
{"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
{"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
{"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
{"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA+1, 0xffff},
{"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA+2, 0xffff},
{"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
{"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
{"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
{"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
{"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA+1, 0xffff},
{"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA+2, 0xffff},
{"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
{"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA+1, 0xffff},
{"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA+2, 0xffff},
{"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
{"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA+1, 0xffff},
{"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA+2, 0xffff},
{NULL, 0, 0, 0, 0}
};
#if !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP))
#define PHY_TYPE_N 4 /* N-Phy value */
#define PHY_TYPE_LP 5 /* LP-Phy value */
#endif /* !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */
#if !defined(PHY_TYPE_NULL)
#define PHY_TYPE_NULL 0xf /* Invalid Phy value */
#endif /* !defined(PHY_TYPE_NULL) */
typedef struct {
u16 phy_type;
u16 bandrange;
u16 chain;
const char *vars;
} pavars_t;
static const pavars_t pavars[] = {
/* NPHY */
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
/* LPPHY */
{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"},
{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"},
{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"},
{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"},
{PHY_TYPE_NULL, 0, 0, ""}
};
typedef struct {
u16 phy_type;
u16 bandrange;
const char *vars;
} povars_t;
static const povars_t povars[] = {
/* NPHY */
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,
"mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 "
"mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"},
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL,
"mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 "
"mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"},
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM,
"mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 "
"mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"},
{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH,
"mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 "
"mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"},
{PHY_TYPE_NULL, 0, ""}
};
typedef struct {
u8 tag; /* Broadcom subtag name */
u8 len; /* Length field of the tuple, note that it includes the
* subtag name (1 byte): 1 + tuple content length
*/
const char *params;
} cis_tuple_t;
#define OTP_RAW (0xff - 1) /* Reserved tuple number for wrvar Raw input */
#define OTP_VERS_1 (0xff - 2) /* CISTPL_VERS_1 */
#define OTP_MANFID (0xff - 3) /* CISTPL_MANFID */
#define OTP_RAW1 (0xff - 4) /* Like RAW, but comes first */
static const cis_tuple_t cis_hnbuvars[] = {
{OTP_RAW1, 0, ""}, /* special case */
{OTP_VERS_1, 0, "smanf sproductname"}, /* special case (non BRCM tuple) */
{OTP_MANFID, 4, "2manfid 2prodid"}, /* special case (non BRCM tuple) */
{HNBU_SROMREV, 2, "1sromrev"},
/* NOTE: subdevid is also written to boardtype.
* Need to write HNBU_BOARDTYPE to change it if it is different.
*/
{HNBU_CHIPID, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"},
{HNBU_BOARDREV, 3, "2boardrev"},
{HNBU_PAPARMS, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"},
{HNBU_AA, 3, "1aa2g 1aa5g"},
{HNBU_AA, 3, "1aa0 1aa1"}, /* backward compatibility */
{HNBU_AG, 5, "1ag0 1ag1 1ag2 1ag3"},
{HNBU_BOARDFLAGS, 9, "4boardflags 4boardflags2"},
{HNBU_LEDS, 5, "1ledbh0 1ledbh1 1ledbh2 1ledbh3"},
{HNBU_CCODE, 4, "2ccode 1cctl"},
{HNBU_CCKPO, 3, "2cckpo"},
{HNBU_OFDMPO, 5, "4ofdmpo"},
{HNBU_RDLID, 3, "2rdlid"},
{HNBU_RSSISMBXA2G, 3, "0rssismf2g 0rssismc2g 0rssisav2g 0bxa2g"}, /* special case */
{HNBU_RSSISMBXA5G, 3, "0rssismf5g 0rssismc5g 0rssisav5g 0bxa5g"}, /* special case */
{HNBU_XTALFREQ, 5, "4xtalfreq"},
{HNBU_TRI2G, 2, "1tri2g"},
{HNBU_TRI5G, 4, "1tri5gl 1tri5g 1tri5gh"},
{HNBU_RXPO2G, 2, "1rxpo2g"},
{HNBU_RXPO5G, 2, "1rxpo5g"},
{HNBU_BOARDNUM, 3, "2boardnum"},
{HNBU_MACADDR, 7, "6macaddr"}, /* special case */
{HNBU_RDLSN, 3, "2rdlsn"},
{HNBU_BOARDTYPE, 3, "2boardtype"},
{HNBU_LEDDC, 3, "2leddc"},
{HNBU_RDLRNDIS, 2, "1rdlndis"},
{HNBU_CHAINSWITCH, 5, "1txchain 1rxchain 2antswitch"},
{HNBU_REGREV, 2, "1regrev"},
{HNBU_FEM, 5, "0antswctl2g, 0triso2g, 0pdetrange2g, 0extpagain2g, 0tssipos2g" "0antswctl5g, 0triso5g, 0pdetrange5g, 0extpagain5g, 0tssipos5g"}, /* special case */
{HNBU_PAPARMS_C0, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 "
"2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 "
"2pa5gw1a0 2pa5gw2a0 2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 "
"2pa5ghw1a0 2pa5ghw2a0"},
{HNBU_PAPARMS_C1, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 "
"2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 "
"2pa5gw1a1 2pa5gw2a1 2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 "
"2pa5ghw1a1 2pa5ghw2a1"},
{HNBU_PO_CCKOFDM, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo "
"4ofdm5ghpo"},
{HNBU_PO_MCS2G, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 "
"2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"},
{HNBU_PO_MCS5GM, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 "
"2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"},
{HNBU_PO_MCS5GLH, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 "
"2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 "
"2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 "
"2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"},
{HNBU_CCKFILTTYPE, 2, "1cckdigfilttype"},
{HNBU_PO_CDD, 3, "2cddpo"},
{HNBU_PO_STBC, 3, "2stbcpo"},
{HNBU_PO_40M, 3, "2bw40po"},
{HNBU_PO_40MDUP, 3, "2bwduppo"},
{HNBU_RDLRWU, 2, "1rdlrwu"},
{HNBU_WPS, 3, "1wpsgpio 1wpsled"},
{HNBU_USBFS, 2, "1usbfs"},
{HNBU_CUSTOM1, 5, "4customvar1"},
{OTP_RAW, 0, ""}, /* special case */
{HNBU_OFDMPO5G, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"},
{HNBU_USBEPNUM, 3, "2usbepnum"},
{0xFF, 0, ""}
};
#endif /* _BHND_BCMSROM_TBL_H_ */

View file

@ -58,11 +58,14 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <machine/resource.h>
#include "nvram/bhnd_nvram.h"
#include "bhnd_chipc_if.h"
#include "bhnd_nvram_if.h"
#include "bhnd.h"
#include "bhndvar.h"
#include "bhnd_nvram_if.h"
MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
/**
@ -386,23 +389,27 @@ bhnd_generic_is_region_valid(device_t dev, device_t child,
static device_t
find_nvram_child(device_t dev)
{
device_t chipc, nvram;
device_t chipc, nvram;
/* Look for a directly-attached NVRAM child */
nvram = device_find_child(dev, devclass_get_name(bhnd_nvram_devclass),
-1);
if (nvram == NULL)
return (NULL);
nvram = device_find_child(dev, "bhnd_nvram", 0);
if (nvram != NULL)
return (nvram);
/* Further checks require a bhnd(4) bus */
/* Remaining checks are only applicable when searching a bhnd(4)
* bus. */
if (device_get_devclass(dev) != bhnd_devclass)
return (NULL);
/* Look for a ChipCommon-attached OTP device */
/* Look for a ChipCommon device */
if ((chipc = bhnd_find_child(dev, BHND_DEVCLASS_CC, -1)) != NULL) {
/* Recursively search the ChipCommon device */
if ((nvram = find_nvram_child(chipc)) != NULL)
return (nvram);
bhnd_nvram_src_t src;
/* Query the NVRAM source and determine whether it's
* accessible via the ChipCommon device */
src = BHND_CHIPC_NVRAM_SRC(chipc);
if (BHND_NVRAM_SRC_CC(src))
return (chipc);
}
/* Not found */
@ -410,22 +417,26 @@ find_nvram_child(device_t dev)
}
/**
* Default bhnd(4) bus driver implementation of BHND_BUS_READ_NVRAM_VAR().
* Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR().
*
* This implementation searches @p dev for a valid NVRAM device. If no NVRAM
* child device is found on @p dev, the request is delegated to the
* BHND_BUS_READ_NVRAM_VAR() method on the parent
* of @p dev.
* This implementation searches @p dev for a usable NVRAM child device:
* - The first child device implementing the bhnd_nvram devclass is
* returned, otherwise
* - If @p dev is a bhnd(4) bus, a ChipCommon core that advertises an
* attached NVRAM source.
*
* If no usable child device is found on @p dev, the request is delegated to
* the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
*/
static int
bhnd_generic_read_nvram_var(device_t dev, device_t child, const char *name,
bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
void *buf, size_t *size)
{
device_t nvram;
/* Try to find an NVRAM device applicable to @p child */
if ((nvram = find_nvram_child(dev)) == NULL)
return (BHND_BUS_READ_NVRAM_VAR(device_get_parent(dev), child,
return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
name, buf, size));
return BHND_NVRAM_GETVAR(nvram, name, buf, size);
@ -682,7 +693,7 @@ static device_method_t bhnd_methods[] = {
DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order),
DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid),
DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled),
DEVMETHOD(bhnd_bus_read_nvram_var, bhnd_generic_read_nvram_var),
DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var),
DEVMETHOD(bhnd_bus_read_1, bhnd_read_1),
DEVMETHOD(bhnd_bus_read_2, bhnd_read_2),
DEVMETHOD(bhnd_bus_read_4, bhnd_read_4),

View file

@ -464,6 +464,55 @@ bhnd_get_chipid(device_t dev) {
return (BHND_BUS_GET_CHIPID(device_get_parent(dev), dev));
};
/**
* Determine an NVRAM variable's expected size.
*
* @param dev A bhnd bus child device.
* @param name The variable name.
* @param[out] len On success, the variable's size, in bytes.
*
* @retval 0 success
* @retval ENOENT The requested variable was not found.
* @retval non-zero If reading @p name otherwise fails, a regular unix
* error code will be returned.
*/
static inline int
bhnd_nvram_getvarlen(device_t dev, const char *name, size_t *len)
{
return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, NULL,
len));
}
/**
* Read an NVRAM variable.
*
* @param dev A bhnd bus child device.
* @param name The NVRAM variable name.
* @param buf A buffer large enough to hold @p len bytes. On success,
* the requested value will be written to this buffer.
* @param len The required variable length.
*
* @retval 0 success
* @retval ENOENT The requested variable was not found.
* @retval EINVAL If @p len does not match the actual variable size.
* @retval non-zero If reading @p name otherwise fails, a regular unix
* error code will be returned.
*/
static inline int
bhnd_nvram_getvar(device_t dev, const char *name, void *buf, size_t len)
{
size_t var_len;
int error;
if ((error = bhnd_nvram_getvarlen(dev, name, &var_len)))
return (error);
if (len != var_len)
return (EINVAL);
return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, buf,
&len));
}
/**
* Allocate a resource from a device's parent bhnd(4) bus.

View file

@ -96,7 +96,7 @@ CODE {
}
static int
bhnd_bus_null_read_nvram_var(device_t dev, device_t child,
bhnd_bus_null_get_nvram_var(device_t dev, device_t child,
const char *name, void *buf, size_t *size)
{
return (ENOENT);
@ -403,13 +403,13 @@ METHOD int get_region_addr {
* @retval non-zero If reading @p name otherwise fails, a regular unix
* error code will be returned.
*/
METHOD int read_nvram_var {
METHOD int get_nvram_var {
device_t dev;
device_t child;
const char *name;
void *buf;
size_t *size;
} DEFAULT bhnd_bus_null_read_nvram_var;
} DEFAULT bhnd_bus_null_get_nvram_var;
/** An implementation of bus_read_1() compatible with bhnd_resource */

View file

@ -328,6 +328,7 @@
#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 */
@ -345,6 +346,7 @@
#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 */
@ -433,7 +435,6 @@
#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 */

View file

@ -51,6 +51,10 @@ __FBSDID("$FreeBSD$");
#include <dev/bhnd/bhndreg.h>
#include <dev/bhnd/cores/chipc/chipcreg.h>
#include <dev/bhnd/nvram/bhnd_nvram.h>
#include "bhnd_chipc_if.h"
#include "bhnd_nvram_if.h"
#include "bhndbvar.h"
#include "bhndb_bus_if.h"
@ -609,7 +613,7 @@ bhndb_generic_init_full_config(device_t dev, device_t child,
goto cleanup;
}
if (bootverbose)
if (bootverbose || BHNDB_DEBUG(PRIO))
device_printf(sc->dev, "%s resource configuration\n", hw->name);
/* Release existing resource state */
@ -1298,9 +1302,10 @@ bhndb_retain_dynamic_window(struct bhndb_softc *sc, struct resource *r)
rman_get_size(r));
if (error) {
device_printf(sc->dev, "dynamic window initialization "
"for 0x%llx-0x%llx failed\n",
"for 0x%llx-0x%llx failed: %d\n",
(unsigned long long) r_start,
(unsigned long long) r_start + r_size - 1);
(unsigned long long) r_start + r_size - 1,
error);
return (NULL);
}
@ -1709,6 +1714,26 @@ bhndb_io_resource(struct bhndb_softc *sc, bus_addr_t addr, bus_size_t size,
return (dwa);
}
/**
* Default bhndb(4) implementation of BHND_BUS_GET_NVRAM_VAR().
*/
static int
bhndb_get_nvram_var(device_t dev, device_t child, const char *name,
void *buf, size_t *size)
{
device_t nvram;
/* Look for a directly-attached NVRAM child */
nvram = device_find_child(dev, devclass_get_name(bhnd_nvram_devclass),
0);
if (nvram != NULL)
return (BHND_NVRAM_GETVAR(nvram, name, buf, size));
/* Otherwise, delegate to our parent */
return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
name, buf, size));
}
/*
* BHND_BUS_(READ|WRITE_* implementations
*/
@ -1936,6 +1961,7 @@ static device_method_t bhndb_methods[] = {
DEVMETHOD(bhnd_bus_get_chipid, bhndb_get_chipid),
DEVMETHOD(bhnd_bus_activate_resource, bhndb_activate_bhnd_resource),
DEVMETHOD(bhnd_bus_deactivate_resource, bhndb_deactivate_bhnd_resource),
DEVMETHOD(bhnd_bus_get_nvram_var, bhndb_get_nvram_var),
DEVMETHOD(bhnd_bus_read_1, bhndb_bus_read_1),
DEVMETHOD(bhnd_bus_read_2, bhndb_bus_read_2),
DEVMETHOD(bhnd_bus_read_4, bhndb_bus_read_4),

View file

@ -61,15 +61,19 @@ __FBSDID("$FreeBSD$");
#include "bhndb_pcivar.h"
#include "bhndb_private.h"
static int bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc);
static int bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc);
static int bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc);
static int bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc);
static int bhndb_pci_compat_setregwin(struct bhndb_pci_softc *,
const struct bhndb_regwin *, bhnd_addr_t);
static int bhndb_pci_fast_setregwin(struct bhndb_pci_softc *,
const struct bhndb_regwin *, bhnd_addr_t);
static int bhndb_pci_compat_setregwin(struct bhndb_pci_softc *,
const struct bhndb_regwin *, bhnd_addr_t);
static int bhndb_pci_fast_setregwin(struct bhndb_pci_softc *,
const struct bhndb_regwin *, bhnd_addr_t);
static void bhndb_init_sromless_pci_config(struct bhndb_pci_softc *sc);
static void bhndb_init_sromless_pci_config(
struct bhndb_pci_softc *sc);
static bus_addr_t bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc);
static size_t bhndb_pci_sprom_size(struct bhndb_pci_softc *sc);
/**
* Default bhndb_pci implementation of device_probe().
@ -104,13 +108,14 @@ bhndb_pci_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
sc->parent = device_get_parent(dev);
/* Enable PCI bus mastering */
pci_enable_busmaster(device_get_parent(dev));
pci_enable_busmaster(sc->parent);
/* Determine our bridge device class */
sc->pci_devclass = BHND_DEVCLASS_PCI;
if (pci_find_cap(device_get_parent(dev), PCIY_EXPRESS, &reg) == 0)
if (pci_find_cap(sc->parent, PCIY_EXPRESS, &reg) == 0)
sc->pci_devclass = BHND_DEVCLASS_PCIE;
/* Enable clocks (if supported by this hardware) */
@ -142,6 +147,8 @@ bhndb_pci_init_full_config(device_t dev, device_t child,
const struct bhndb_hw_priority *hw_prio_table)
{
struct bhndb_pci_softc *sc;
device_t nv_dev;
bus_size_t nv_sz;
int error;
sc = device_get_softc(dev);
@ -153,9 +160,126 @@ bhndb_pci_init_full_config(device_t dev, device_t child,
/* Fix-up power on defaults for SROM-less devices. */
bhndb_init_sromless_pci_config(sc);
/* If SPROM is mapped directly into BAR0, add NVRAM device. */
nv_sz = bhndb_pci_sprom_size(sc);
if (nv_sz > 0) {
struct bhndb_devinfo *dinfo;
const char *dname;
if (bootverbose) {
device_printf(dev, "found SPROM (%zu bytes)\n", nv_sz);
}
/* Add sprom device */
dname = "bhnd_nvram";
if ((nv_dev = BUS_ADD_CHILD(dev, 0, dname, -1)) == NULL) {
device_printf(dev, "failed to add sprom device\n");
return (ENXIO);
}
/* Initialize device address space and resource covering the
* BAR0 SPROM shadow. */
dinfo = device_get_ivars(nv_dev);
dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE;
error = bus_set_resource(nv_dev, SYS_RES_MEMORY, 0,
bhndb_pci_sprom_addr(sc), nv_sz);
if (error) {
device_printf(dev,
"failed to register sprom resources\n");
return (error);
}
/* Attach the device */
if ((error = device_probe_and_attach(nv_dev))) {
device_printf(dev, "sprom attach failed\n");
return (error);
}
}
return (0);
}
static const struct bhndb_regwin *
bhndb_pci_sprom_regwin(struct bhndb_pci_softc *sc)
{
struct bhndb_resources *bres;
const struct bhndb_hwcfg *cfg;
const struct bhndb_regwin *sprom_win;
bres = sc->bhndb.bus_res;
cfg = bres->cfg;
sprom_win = bhndb_regwin_find_type(cfg->register_windows,
BHNDB_REGWIN_T_SPROM, BHNDB_PCI_V0_BAR0_SPROM_SIZE);
return (sprom_win);
}
static bus_addr_t
bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc)
{
const struct bhndb_regwin *sprom_win;
struct resource *r;
/* Fetch the SPROM register window */
sprom_win = bhndb_pci_sprom_regwin(sc);
KASSERT(sprom_win != NULL, ("requested sprom address on PCI_V2+"));
/* Fetch the associated resource */
r = bhndb_find_regwin_resource(sc->bhndb.bus_res, sprom_win);
KASSERT(r != NULL, ("missing resource for sprom window\n"));
return (rman_get_start(r) + sprom_win->win_offset);
}
static bus_size_t
bhndb_pci_sprom_size(struct bhndb_pci_softc *sc)
{
const struct bhndb_regwin *sprom_win;
uint32_t sctl;
bus_size_t sprom_sz;
sprom_win = bhndb_pci_sprom_regwin(sc);
/* PCI_V2 and later devices map SPROM/OTP via ChipCommon */
if (sprom_win == NULL)
return (0);
/* Determine SPROM size */
sctl = pci_read_config(sc->parent, BHNDB_PCI_SPROM_CONTROL, 4);
if (sctl & BHNDB_PCI_SPROM_BLANK)
return (0);
switch (sctl & BHNDB_PCI_SPROM_SZ_MASK) {
case BHNDB_PCI_SPROM_SZ_1KB:
sprom_sz = (1 * 1024);
break;
case BHNDB_PCI_SPROM_SZ_4KB:
sprom_sz = (4 * 1024);
break;
case BHNDB_PCI_SPROM_SZ_16KB:
sprom_sz = (16 * 1024);
break;
case BHNDB_PCI_SPROM_SZ_RESERVED:
default:
device_printf(sc->dev, "invalid PCI sprom size 0x%x\n", sctl);
return (0);
}
if (sprom_sz > sprom_win->win_size) {
device_printf(sc->dev,
"PCI sprom size (0x%x) overruns defined register window\n",
sctl);
return (0);
}
return (sprom_sz);
}
/*
* On devices without a SROM, the PCI(e) cores will be initialized with
* their Power-on-Reset defaults; this can leave two of the BAR0 PCI windows
@ -274,7 +398,7 @@ bhndb_pci_detach(device_t dev)
return (error);
/* Disable PCI bus mastering */
pci_disable_busmaster(device_get_parent(dev));
pci_disable_busmaster(sc->parent);
return (0);
}
@ -301,19 +425,18 @@ static int
bhndb_pci_compat_setregwin(struct bhndb_pci_softc *sc,
const struct bhndb_regwin *rw, bhnd_addr_t addr)
{
device_t parent;
int error;
parent = sc->bhndb.parent_dev;
int reg;
if (rw->win_type != BHNDB_REGWIN_T_DYN)
return (ENODEV);
reg = rw->d.dyn.cfg_offset;
for (u_int i = 0; i < BHNDB_PCI_BARCTRL_WRITE_RETRY; i++) {
if ((error = bhndb_pci_fast_setregwin(sc, rw, addr)))
return (error);
if (pci_read_config(parent, rw->d.dyn.cfg_offset, 4) == addr)
if (pci_read_config(sc->parent, reg, 4) == addr)
return (0);
DELAY(10);
@ -330,8 +453,6 @@ static int
bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc,
const struct bhndb_regwin *rw, bhnd_addr_t addr)
{
device_t parent = sc->bhndb.parent_dev;
/* The PCI bridge core only supports 32-bit addressing, regardless
* of the bus' support for 64-bit addressing */
if (addr > UINT32_MAX)
@ -343,7 +464,7 @@ bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc,
if (addr % rw->win_size != 0)
return (EINVAL);
pci_write_config(parent, rw->d.dyn.cfg_offset, addr, 4);
pci_write_config(sc->parent, rw->d.dyn.cfg_offset, addr, 4);
break;
default:
return (ENODEV);
@ -366,7 +487,6 @@ bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc,
static int
bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc)
{
device_t pci_parent;
uint32_t gpio_in, gpio_out, gpio_en;
uint32_t gpio_flags;
uint16_t pci_status;
@ -375,35 +495,33 @@ bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc)
if (sc->pci_devclass != BHND_DEVCLASS_PCI)
return (0);
pci_parent = device_get_parent(sc->dev);
/* Read state of XTAL pin */
gpio_in = pci_read_config(pci_parent, BHNDB_PCI_GPIO_IN, 4);
gpio_in = pci_read_config(sc->parent, BHNDB_PCI_GPIO_IN, 4);
if (gpio_in & BHNDB_PCI_GPIO_XTAL_ON)
return (0); /* already enabled */
/* Fetch current config */
gpio_out = pci_read_config(pci_parent, BHNDB_PCI_GPIO_OUT, 4);
gpio_en = pci_read_config(pci_parent, BHNDB_PCI_GPIO_OUTEN, 4);
gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4);
/* Set PLL_OFF/XTAL_ON pins to HIGH and enable both pins */
gpio_flags = (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON);
gpio_out |= gpio_flags;
gpio_en |= gpio_flags;
pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
DELAY(1000);
/* Reset PLL_OFF */
gpio_out &= ~BHNDB_PCI_GPIO_PLL_OFF;
pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
DELAY(5000);
/* Clear any PCI 'sent target-abort' flag. */
pci_status = pci_read_config(pci_parent, PCIR_STATUS, 2);
pci_status = pci_read_config(sc->parent, PCIR_STATUS, 2);
pci_status &= ~PCIM_STATUS_STABORT;
pci_write_config(pci_parent, PCIR_STATUS, pci_status, 2);
pci_write_config(sc->parent, PCIR_STATUS, pci_status, 2);
return (0);
}
@ -416,31 +534,28 @@ bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc)
static int
bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc)
{
device_t parent_dev;
uint32_t gpio_out, gpio_en;
/* Only supported and required on PCI devices */
if (sc->pci_devclass != BHND_DEVCLASS_PCI)
return (0);
parent_dev = device_get_parent(sc->dev);
// TODO: Check board flags for BFL2_XTALBUFOUTEN?
// TODO: Check PCI core revision?
// TODO: Switch to 'slow' clock?
/* Fetch current config */
gpio_out = pci_read_config(parent_dev, BHNDB_PCI_GPIO_OUT, 4);
gpio_en = pci_read_config(parent_dev, BHNDB_PCI_GPIO_OUTEN, 4);
gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4);
/* Set PLL_OFF to HIGH, XTAL_ON to LOW. */
gpio_out &= ~BHNDB_PCI_GPIO_XTAL_ON;
gpio_out |= BHNDB_PCI_GPIO_PLL_OFF;
pci_write_config(parent_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
/* Enable both output pins */
gpio_en |= (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON);
pci_write_config(parent_dev, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
return (0);
}

View file

@ -0,0 +1,210 @@
/*-
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
* 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,
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* BHNDB PCI SPROM driver.
*
* Provides support for early PCI bridge cores that vend SPROM CSRs
* via PCI configuration space.
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/limits.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/bhnd/bhnd.h>
#include <dev/bhnd/cores/pci/bhnd_pci_hostbvar.h>
#include <dev/bhnd/nvram/bhnd_spromvar.h>
#include "bhnd_nvram_if.h"
#include "bhndb_pcireg.h"
#include "bhndb_pcivar.h"
struct bhndb_pci_sprom_softc {
device_t dev;
struct bhnd_resource *sprom_res; /**< SPROM resource */
int sprom_rid; /**< SPROM RID */
struct bhnd_sprom shadow; /**< SPROM shadow */
struct mtx mtx; /**< SPROM shadow mutex */
};
#define SPROM_LOCK_INIT(sc) \
mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
"BHND PCI SPROM lock", MTX_DEF)
#define SPROM_LOCK(sc) mtx_lock(&(sc)->mtx)
#define SPROM_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
#define SPROM_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what)
#define SPROM_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx)
static int
bhndb_pci_sprom_probe(device_t dev)
{
device_t bridge, bus;
/* Our parent must be a PCI-BHND bridge with an attached bhnd bus */
bridge = device_get_parent(dev);
if (device_get_driver(bridge) != &bhndb_pci_driver)
return (ENXIO);
bus = device_find_child(bridge, devclass_get_name(bhnd_devclass), 0);
if (bus == NULL)
return (ENXIO);
/* Found */
device_set_desc(dev, "PCI-BHNDB SPROM/OTP");
if (!bootverbose)
device_quiet(dev);
/* Refuse wildcard attachments */
return (BUS_PROBE_NOWILDCARD);
}
static int
bhndb_pci_sprom_attach(device_t dev)
{
struct bhndb_pci_sprom_softc *sc;
int error;
sc = device_get_softc(dev);
sc->dev = dev;
/* Allocate SPROM resource */
sc->sprom_rid = 0;
sc->sprom_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->sprom_rid, RF_ACTIVE);
if (sc->sprom_res == NULL) {
device_printf(dev, "failed to allocate resources\n");
return (ENXIO);
}
/* Initialize SPROM shadow */
if ((error = bhnd_sprom_init(&sc->shadow, sc->sprom_res, 0))) {
device_printf(dev, "unrecognized SPROM format\n");
goto failed;
}
/* Initialize mutex */
SPROM_LOCK_INIT(sc);
return (0);
failed:
bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid,
sc->sprom_res);
return (error);
}
static int
bhndb_pci_sprom_resume(device_t dev)
{
return (0);
}
static int
bhndb_pci_sprom_suspend(device_t dev)
{
return (0);
}
static int
bhndb_pci_sprom_detach(device_t dev)
{
struct bhndb_pci_sprom_softc *sc;
sc = device_get_softc(dev);
bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid,
sc->sprom_res);
bhnd_sprom_fini(&sc->shadow);
SPROM_LOCK_DESTROY(sc);
return (0);
}
static int
bhndb_pci_sprom_getvar(device_t dev, const char *name, void *buf, size_t *len)
{
struct bhndb_pci_sprom_softc *sc;
int error;
sc = device_get_softc(dev);
SPROM_LOCK(sc);
error = bhnd_sprom_getvar(&sc->shadow, name, buf, len);
SPROM_UNLOCK(sc);
return (error);
}
static int
bhndb_pci_sprom_setvar(device_t dev, const char *name, const void *buf,
size_t len)
{
struct bhndb_pci_sprom_softc *sc;
int error;
sc = device_get_softc(dev);
SPROM_LOCK(sc);
error = bhnd_sprom_setvar(&sc->shadow, name, buf, len);
SPROM_UNLOCK(sc);
return (error);
}
static device_method_t bhndb_pci_sprom_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, bhndb_pci_sprom_probe),
DEVMETHOD(device_attach, bhndb_pci_sprom_attach),
DEVMETHOD(device_resume, bhndb_pci_sprom_resume),
DEVMETHOD(device_suspend, bhndb_pci_sprom_suspend),
DEVMETHOD(device_detach, bhndb_pci_sprom_detach),
/* NVRAM interface */
DEVMETHOD(bhnd_nvram_getvar, bhndb_pci_sprom_getvar),
DEVMETHOD(bhnd_nvram_setvar, bhndb_pci_sprom_setvar),
DEVMETHOD_END
};
DEFINE_CLASS_0(bhnd_nvram, bhndb_pci_sprom_driver, bhndb_pci_sprom_methods, sizeof(struct bhndb_pci_sprom_softc));
DRIVER_MODULE(bhndb_pci_sprom, bhndb, bhndb_pci_sprom_driver, bhnd_nvram_devclass, NULL, NULL);
MODULE_DEPEND(bhndb_pci_sprom, bhnd, 1, 1, 1);
MODULE_VERSION(bhndb_pci_sprom, 1);

View file

@ -205,13 +205,17 @@
#define BHNDB_PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */
/* BHNDB_PCI_SPROM_CONTROL */
#define BHNDB_PCI_SPROM_SZ_MSK 0x02 /* SPROM Size Mask */
#define BHNDB_PCI_SPROM_LOCKED 0x08 /* SPROM Locked */
#define BHNDB_PCI_SPROM_BLANK 0x04 /* indicating a blank SPROM */
#define BHNDB_PCI_SPROM_WRITEEN 0x10 /* SPROM write enable */
#define BHNDB_PCI_SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */
#define BHNDB_PCI_SPROM_BACKPLANE_EN 0x40 /* Enable indirect backplane access */
#define BHNDB_PCI_SPROM_OTPIN_USE 0x80 /* device OTP In use */
#define BHNDB_PCI_SPROM_SZ_MASK 0x03 /**< sprom size mask */
#define BHNDB_PCI_SPROM_SZ_1KB 0x00 /**< 1KB sprom size */
#define BHNDB_PCI_SPROM_SZ_4KB 0x01 /**< 4KB sprom size */
#define BHNDB_PCI_SPROM_SZ_16KB 0x02 /**< 16KB sprom size */
#define BHNDB_PCI_SPROM_SZ_RESERVED 0x03 /**< unsupported sprom size */
#define BHNDB_PCI_SPROM_LOCKED 0x08 /**< sprom locked */
#define BHNDB_PCI_SPROM_BLANK 0x04 /**< sprom blank */
#define BHNDB_PCI_SPROM_WRITEEN 0x10 /**< sprom write enable */
#define BHNDB_PCI_SPROM_BOOTROM_WE 0x20 /**< external bootrom write enable */
#define BHNDB_PCI_SPROM_BACKPLANE_EN 0x40 /**< enable indirect backplane access (BHNDB_PCI_BACKPLANE_*) */
#define BHNDB_PCI_SPROM_OTPIN_USE 0x80 /**< device OTP in use */
/* PCI (non-PCIe) BHNDB_PCI_GPIO_OUTEN */

View file

@ -51,6 +51,7 @@ typedef int (*bhndb_pci_set_regwin_t)(struct bhndb_pci_softc *sc,
struct bhndb_pci_softc {
struct bhndb_softc bhndb; /**< parent softc */
device_t dev; /**< bridge device */
device_t parent; /**< parent PCI device */
bhnd_devclass_t pci_devclass; /**< PCI core's devclass */
bhndb_pci_set_regwin_t set_regwin; /**< regwin handler */
};

View file

@ -52,6 +52,8 @@ __FBSDID("$FreeBSD$");
#include <dev/bhnd/bhnd.h>
#include "bhnd_nvram_if.h"
#include "chipcreg.h"
#include "chipcvar.h"
@ -73,13 +75,44 @@ static const struct bhnd_device chipc_devices[] = {
/* Device quirks table */
static struct bhnd_device_quirk chipc_quirks[] = {
{ BHND_HWREV_RANGE (0, 21), CHIPC_QUIRK_ALWAYS_HAS_SPROM },
{ BHND_HWREV_EQ (22), CHIPC_QUIRK_SPROM_CHECK_CST_R22 },
{ BHND_HWREV_RANGE (23, 31), CHIPC_QUIRK_SPROM_CHECK_CST_R23 },
{ BHND_HWREV_GTE (35), CHIPC_QUIRK_SUPPORTS_NFLASH },
{ BHND_HWREV_GTE (32), CHIPC_QUIRK_SUPPORTS_SPROM },
{ BHND_HWREV_GTE (35), CHIPC_QUIRK_SUPPORTS_NFLASH },
BHND_DEVICE_QUIRK_END
};
/* Chip-specific quirks table */
static struct bhnd_chip_quirk chipc_chip_quirks[] = {
/* 4331 12x9 packages */
{{ BHND_CHIP_IP(4331, 4331TN) },
CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM
},
{{ BHND_CHIP_IP(4331, 4331TNA0) },
CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM
},
/* 4331 12x12 packages */
{{ BHND_CHIP_IPR(4331, 4331TT, HWREV_GTE(1)) },
CHIPC_QUIRK_4331_EXTPA2_MUX_SPROM
},
/* 4331 (all packages/revisions) */
{{ BHND_CHIP_ID(4331) },
CHIPC_QUIRK_4331_EXTPA_MUX_SPROM
},
/* 4360 family (all revs <= 2) */
{{ BHND_CHIP_IR(4352, HWREV_LTE(2)) },
CHIPC_QUIRK_4360_FEM_MUX_SPROM },
{{ BHND_CHIP_IR(43460, HWREV_LTE(2)) },
CHIPC_QUIRK_4360_FEM_MUX_SPROM },
{{ BHND_CHIP_IR(43462, HWREV_LTE(2)) },
CHIPC_QUIRK_4360_FEM_MUX_SPROM },
{{ BHND_CHIP_IR(43602, HWREV_LTE(2)) },
CHIPC_QUIRK_4360_FEM_MUX_SPROM },
BHND_CHIP_QUIRK_END
};
/* quirk and capability flag convenience macros */
#define CHIPC_QUIRK(_sc, _name) \
((_sc)->quirks & CHIPC_QUIRK_ ## _name)
@ -91,7 +124,13 @@ static struct bhnd_device_quirk chipc_quirks[] = {
KASSERT(CHIPC_QUIRK((_sc), name), ("quirk " __STRING(_name) " not set"))
#define CHIPC_ASSERT_CAP(_sc, name) \
KASSERT(CHIPC_CAP((_sc), name), ("capability " __STRING(_name) " not set"))
KASSERT(CHIPC_CAP((_sc), name), ("capability " __STRING(_name) " not set"))
static bhnd_nvram_src_t chipc_nvram_identify(struct chipc_softc *sc);
static int chipc_sprom_init(struct chipc_softc *);
static int chipc_enable_sprom_pins(struct chipc_softc *);
static int chipc_disable_sprom_pins(struct chipc_softc *);
static int
chipc_probe(device_t dev)
@ -119,6 +158,9 @@ chipc_attach(device_t dev)
sc->dev = dev;
sc->quirks = bhnd_device_quirks(dev, chipc_devices,
sizeof(chipc_devices[0]));
sc->quirks |= bhnd_chip_quirks(dev, chipc_chip_quirks);
CHIPC_LOCK_INIT(sc);
/* Allocate bus resources */
memcpy(sc->rspec, chipc_rspec, sizeof(sc->rspec));
@ -152,22 +194,28 @@ chipc_attach(device_t dev)
sc->caps = bhnd_bus_read_4(sc->core, CHIPC_CAPABILITIES);
sc->cst = bhnd_bus_read_4(sc->core, CHIPC_CHIPST);
// TODO
switch (bhnd_chipc_nvram_src(dev)) {
case BHND_NVRAM_SRC_CIS:
device_printf(dev, "NVRAM source: CIS\n");
break;
case BHND_NVRAM_SRC_SPROM:
device_printf(dev, "NVRAM source: SPROM\n");
break;
/* Identify NVRAM source */
sc->nvram_src = chipc_nvram_identify(sc);
/* Read NVRAM data */
switch (sc->nvram_src) {
case BHND_NVRAM_SRC_OTP:
device_printf(dev, "NVRAM source: OTP\n");
// TODO (requires access to OTP hardware)
device_printf(sc->dev, "NVRAM-OTP unsupported\n");
break;
case BHND_NVRAM_SRC_NFLASH:
device_printf(dev, "NVRAM source: NFLASH\n");
// TODO (requires access to NFLASH hardware)
device_printf(sc->dev, "NVRAM-NFLASH unsupported\n");
break;
case BHND_NVRAM_SRC_NONE:
device_printf(dev, "NVRAM source: NONE\n");
case BHND_NVRAM_SRC_SPROM:
if ((error = chipc_sprom_init(sc)))
goto cleanup;
break;
case BHND_NVRAM_SRC_UNKNOWN:
/* Handled externally */
break;
}
@ -175,6 +223,7 @@ chipc_attach(device_t dev)
cleanup:
bhnd_release_resources(dev, sc->rspec, sc->res);
CHIPC_LOCK_DESTROY(sc);
return (error);
}
@ -185,6 +234,9 @@ chipc_detach(device_t dev)
sc = device_get_softc(dev);
bhnd_release_resources(dev, sc->rspec, sc->res);
bhnd_sprom_fini(&sc->sprom);
CHIPC_LOCK_DESTROY(sc);
return (0);
}
@ -202,68 +254,64 @@ chipc_resume(device_t dev)
}
/**
* Use device-specific ChipStatus flags to determine the preferred NVRAM
* data source.
* Initialize local SPROM shadow, if required.
*
* @param sc chipc driver state.
*/
static bhnd_nvram_src_t
chipc_nvram_src_chipst(struct chipc_softc *sc)
static int
chipc_sprom_init(struct chipc_softc *sc)
{
uint8_t nvram_sel;
int error;
CHIPC_ASSERT_QUIRK(sc, SPROM_CHECK_CHIPST);
KASSERT(sc->nvram_src == BHND_NVRAM_SRC_SPROM,
("non-SPROM source (%u)\n", sc->nvram_src));
if (CHIPC_QUIRK(sc, SPROM_CHECK_CST_R22)) {
// TODO: On these devices, the official driver code always
// assumes SPROM availability if CHIPC_CST_OTP_SEL is not
// set; we must review against the actual behavior of our
// BCM4312 hardware
nvram_sel = CHIPC_GET_ATTR(sc->cst, CST_SPROM_OTP_SEL_R22);
} else if (CHIPC_QUIRK(sc, SPROM_CHECK_CST_R23)) {
nvram_sel = CHIPC_GET_ATTR(sc->cst, CST_SPROM_OTP_SEL_R23);
} else {
panic("invalid CST OTP/SPROM chipc quirk flags");
/* Enable access to the SPROM */
CHIPC_LOCK(sc);
if ((error = chipc_enable_sprom_pins(sc)))
goto failed;
/* Initialize SPROM parser */
error = bhnd_sprom_init(&sc->sprom, sc->core, CHIPC_SPROM_OTP);
if (error) {
device_printf(sc->dev, "SPROM identification failed: %d\n",
error);
chipc_disable_sprom_pins(sc);
goto failed;
}
device_printf(sc->dev, "querying chipst for 0x%x, 0x%x\n", sc->ccid.chip_id, sc->cst);
switch (nvram_sel) {
case CHIPC_CST_DEFCIS_SEL:
return (BHND_NVRAM_SRC_CIS);
case CHIPC_CST_SPROM_SEL:
case CHIPC_CST_OTP_PWRDN:
return (BHND_NVRAM_SRC_SPROM);
case CHIPC_CST_OTP_SEL:
return (BHND_NVRAM_SRC_OTP);
default:
device_printf(sc->dev, "unrecognized OTP/SPROM type 0x%hhx",
nvram_sel);
return (BHND_NVRAM_SRC_NONE);
/* Drop access to the SPROM lines */
if ((error = chipc_disable_sprom_pins(sc))) {
bhnd_sprom_fini(&sc->sprom);
goto failed;
}
CHIPC_UNLOCK(sc);
return (0);
failed:
CHIPC_UNLOCK(sc);
return (error);
}
/**
* Determine the preferred NVRAM data source.
* Determine the NVRAM data source for this device.
*
* @param sc chipc driver state.
*/
static bhnd_nvram_src_t
chipc_nvram_src(device_t dev)
chipc_nvram_identify(struct chipc_softc *sc)
{
struct chipc_softc *sc;
uint32_t srom_ctrl;
sc = device_get_softc(dev);
/* Very early devices always included a SPROM */
if (CHIPC_QUIRK(sc, ALWAYS_HAS_SPROM))
return (BHND_NVRAM_SRC_SPROM);
/* Most other early devices require checking ChipStatus flags */
if (CHIPC_QUIRK(sc, SPROM_CHECK_CHIPST))
return (chipc_nvram_src_chipst(sc));
/* Very early devices vend SPROM/OTP/CIS (if at all) via the
* host bridge interface instead of ChipCommon. */
if (!CHIPC_QUIRK(sc, SUPPORTS_SPROM))
return (BHND_NVRAM_SRC_UNKNOWN);
/*
* Later chipset revisions standardized the NVRAM capability flags and
* Later chipset revisions standardized the SPROM capability flags and
* register interfaces.
*
* We check for hardware presence in order of precedence. For example,
@ -287,7 +335,158 @@ chipc_nvram_src(device_t dev)
return (BHND_NVRAM_SRC_NFLASH);
/* No NVRAM hardware capability declared */
return (BHND_NVRAM_SRC_NONE);
return (BHND_NVRAM_SRC_UNKNOWN);
}
/**
* If required by this device, enable access to the SPROM.
*
* @param sc chipc driver state.
*/
static int
chipc_enable_sprom_pins(struct chipc_softc *sc)
{
uint32_t cctrl;
CHIPC_LOCK_ASSERT(sc, MA_OWNED);
/* Nothing to do? */
if (!CHIPC_QUIRK(sc, MUX_SPROM))
return (0);
cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL);
/* 4331 devices */
if (CHIPC_QUIRK(sc, 4331_EXTPA_MUX_SPROM)) {
cctrl &= ~CHIPC_CCTRL4331_EXTPA_EN;
if (CHIPC_QUIRK(sc, 4331_GPIO2_5_MUX_SPROM))
cctrl &= ~CHIPC_CCTRL4331_EXTPA_ON_GPIO2_5;
if (CHIPC_QUIRK(sc, 4331_EXTPA2_MUX_SPROM))
cctrl &= ~CHIPC_CCTRL4331_EXTPA_EN2;
bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl);
return (0);
}
/* 4360 devices */
if (CHIPC_QUIRK(sc, 4360_FEM_MUX_SPROM)) {
/* Unimplemented */
}
/* Refuse to proceed on unsupported devices with muxed SPROM pins */
device_printf(sc->dev, "muxed sprom lines on unrecognized device\n");
return (ENXIO);
}
/**
* If required by this device, revert any GPIO/pin configuration applied
* to allow SPROM access.
*
* @param sc chipc driver state.
*/
static int
chipc_disable_sprom_pins(struct chipc_softc *sc)
{
uint32_t cctrl;
CHIPC_LOCK_ASSERT(sc, MA_OWNED);
/* Nothing to do? */
if (!CHIPC_QUIRK(sc, MUX_SPROM))
return (0);
cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL);
/* 4331 devices */
if (CHIPC_QUIRK(sc, 4331_EXTPA_MUX_SPROM)) {
cctrl |= CHIPC_CCTRL4331_EXTPA_EN;
if (CHIPC_QUIRK(sc, 4331_GPIO2_5_MUX_SPROM))
cctrl |= CHIPC_CCTRL4331_EXTPA_ON_GPIO2_5;
if (CHIPC_QUIRK(sc, 4331_EXTPA2_MUX_SPROM))
cctrl |= CHIPC_CCTRL4331_EXTPA_EN2;
bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl);
return (0);
}
/* 4360 devices */
if (CHIPC_QUIRK(sc, 4360_FEM_MUX_SPROM)) {
/* Unimplemented */
}
/* Refuse to proceed on unsupported devices with muxed SPROM pins */
device_printf(sc->dev, "muxed sprom lines on unrecognized device\n");
return (ENXIO);
}
static bhnd_nvram_src_t
chipc_nvram_src(device_t dev)
{
struct chipc_softc *sc = device_get_softc(dev);
return (sc->nvram_src);
}
static int
chipc_nvram_getvar(device_t dev, const char *name, void *buf, size_t *len)
{
struct chipc_softc *sc;
int error;
sc = device_get_softc(dev);
switch (sc->nvram_src) {
case BHND_NVRAM_SRC_SPROM:
CHIPC_LOCK(sc);
error = bhnd_sprom_getvar(&sc->sprom, name, buf, len);
CHIPC_UNLOCK(sc);
return (error);
case BHND_NVRAM_SRC_OTP:
case BHND_NVRAM_SRC_NFLASH:
/* Currently unsupported */
return (ENXIO);
case BHND_NVRAM_SRC_UNKNOWN:
return (ENODEV);
}
/* Unknown NVRAM source */
return (ENODEV);
}
static int
chipc_nvram_setvar(device_t dev, const char *name, const void *buf,
size_t len)
{
struct chipc_softc *sc;
int error;
sc = device_get_softc(dev);
switch (sc->nvram_src) {
case BHND_NVRAM_SRC_SPROM:
CHIPC_LOCK(sc);
error = bhnd_sprom_setvar(&sc->sprom, name, buf, len);
CHIPC_UNLOCK(sc);
return (error);
case BHND_NVRAM_SRC_OTP:
case BHND_NVRAM_SRC_NFLASH:
/* Currently unsupported */
return (ENXIO);
case BHND_NVRAM_SRC_UNKNOWN:
default:
return (ENODEV);
}
/* Unknown NVRAM source */
return (ENODEV);
}
static device_method_t chipc_methods[] = {
@ -301,6 +500,10 @@ static device_method_t chipc_methods[] = {
/* ChipCommon interface */
DEVMETHOD(bhnd_chipc_nvram_src, chipc_nvram_src),
/* NVRAM interface */
DEVMETHOD(bhnd_nvram_getvar, chipc_nvram_getvar),
DEVMETHOD(bhnd_nvram_setvar, chipc_nvram_setvar),
DEVMETHOD_END
};

View file

@ -36,26 +36,12 @@
#define CHIPC_GET_ATTR(_entry, _attr) \
((_entry & CHIPC_ ## _attr ## _MASK) >> CHIPC_ ## _attr ## _SHIFT)
#define CHIPC_ID 0x0
#define CHIPC_CAPABILITIES 0x04
#define CHIPC_CHIPST 0x2c
#define CHIPC_EROMPTR 0xfc /**< 32-bit EROM base address
* on BCMA devices */
/** chipid */
#define CHIPC_ID 0x0 /**< identification register */
#define CHIPC_ID_CHIP_MASK 0x0000FFFF /**< chip id */
#define CHIPC_ID_CHIP_SHIFT 0
#define CHIPC_ID_REV_MASK 0x000F0000 /**< chip revision */
#define CHIPC_ID_REV_SHIFT 16
#define CHIPC_ID_PKG_MASK 0x00F00000 /**< physical package ID */
#define CHIPC_ID_PKG_SHIFT 20
#define CHIPC_ID_NUMCORE_MASK 0x0F000000 /**< number of cores on chip (rev >= 4) */
#define CHIPC_ID_NUMCORE_SHIFT 24
#define CHIPC_ID_BUS_MASK 0xF0000000 /**< chip/interconnect type (BHND_CHIPTYPE_*) */
#define CHIPC_ID_BUS_SHIFT 28
#define CHIPC_ID 0x0
#define CHIPC_CAPABILITIES 0x04
#define CHIPC_OTPST 0x10
#define CHIPC_CHIPCTRL 0x28 /**< chip control */
#define CHIPC_CHIPST 0x2c /**< chip status */
#define CHIPC_JTAGCMD 0x30
#define CHIPC_JTAGIR 0x34
#define CHIPC_JTAGDR 0x38
@ -76,6 +62,8 @@
#define CHIPC_CLKC_M3 0xa0
#define CHIPC_CLKDIV 0xa4
#define CHIPC_SYS_CLK_CTL 0xc0
#define CHIPC_EROMPTR 0xfc /**< 32-bit EROM base address
* on BCMA devices */
#define CHIPC_SPROM_CTRL 0x190 /**< SPROM interface (rev >= 32) */
#define CHIPC_SPROM_ADDR 0x194
#define CHIPC_SPROM_DATA 0x198
@ -95,6 +83,19 @@
#define CHIPC_PMU_PLL_CONTROL_DATA 0x664
#define CHIPC_SPROM_OTP 0x800 /* SPROM/OTP address space */
/** chipid */
#define CHIPC_ID 0x0 /**< identification register */
#define CHIPC_ID_CHIP_MASK 0x0000FFFF /**< chip id */
#define CHIPC_ID_CHIP_SHIFT 0
#define CHIPC_ID_REV_MASK 0x000F0000 /**< chip revision */
#define CHIPC_ID_REV_SHIFT 16
#define CHIPC_ID_PKG_MASK 0x00F00000 /**< physical package ID */
#define CHIPC_ID_PKG_SHIFT 20
#define CHIPC_ID_NUMCORE_MASK 0x0F000000 /**< number of cores on chip (rev >= 4) */
#define CHIPC_ID_NUMCORE_SHIFT 24
#define CHIPC_ID_BUS_MASK 0xF0000000 /**< chip/interconnect type (BHND_CHIPTYPE_*) */
#define CHIPC_ID_BUS_SHIFT 28
/* capabilities */
#define CHIPC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */
#define CHIPC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */
@ -1124,6 +1125,7 @@ enum {
#define CHIPC_CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */
#define CHIPC_CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */
#define CHIPC_CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */
#define CHIPC_CCTRL4331_EXTPA_EN2 (1<<12) /* 0 ext pa2 disable, 1 ext pa2 enabled */
#define CHIPC_CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */
#define CHIPC_CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */

View file

@ -32,6 +32,8 @@
#ifndef _BHND_CORES_CHIPC_CHIPCVAR_H_
#define _BHND_CORES_CHIPC_CHIPCVAR_H_
#include <dev/bhnd/nvram/bhnd_spromvar.h>
#include "chipc.h"
DECLARE_CLASS(bhnd_chipc);
@ -45,37 +47,64 @@ extern devclass_t bhnd_chipc_devclass;
*/
enum {
/** No quirks */
CHIPC_QUIRK_NONE = 0,
CHIPC_QUIRK_NONE = 0,
/**
* The device always provides an external SROM.
* ChipCommon-controlled SPROM/OTP is supported, along with the
* CHIPC_CAP_SPROM capability flag.
*/
CHIPC_QUIRK_ALWAYS_HAS_SPROM = (1<<1),
/**
* SROM availability must be determined through chip-specific
* ChipStatus flags.
*/
CHIPC_QUIRK_SPROM_CHECK_CHIPST = (1<<3),
/**
* Use the rev22 chipstatus register format when determining SPROM
* availability.
*/
CHIPC_QUIRK_SPROM_CHECK_CST_R22 = (1<<4)|CHIPC_QUIRK_SPROM_CHECK_CHIPST,
/**
* Use the rev23 chipstatus register format when determining SPROM
* availability.
*/
CHIPC_QUIRK_SPROM_CHECK_CST_R23 = (1<<5)|CHIPC_QUIRK_SPROM_CHECK_CHIPST,
CHIPC_QUIRK_SUPPORTS_SPROM = (1<<1),
/**
* External NAND NVRAM is supported, along with the CHIPC_CAP_NFLASH
* capability flag.
*/
CHIPC_QUIRK_SUPPORTS_NFLASH = (1<<6),
CHIPC_QUIRK_SUPPORTS_NFLASH = (1<<2),
/**
* The SPROM is attached via muxed pins. The pins must be switched
* to allow reading/writing.
*/
CHIPC_QUIRK_MUX_SPROM = (1<<3),
/**
* Access to the SPROM uses pins shared with the 802.11a external PA.
*
* On modules using these 4331 packages, the CCTRL4331_EXTPA_EN flag
* must be cleared to allow SPROM access.
*/
CHIPC_QUIRK_4331_EXTPA_MUX_SPROM = (1<<4) |
CHIPC_QUIRK_MUX_SPROM,
/**
* Access to the SPROM uses pins shared with the 802.11a external PA.
*
* On modules using these 4331 chip packages, the external PA is
* attached via GPIO 2, 5, and sprom_dout pins.
*
* When enabling and disabling EXTPA to allow SPROM access, the
* CCTRL4331_EXTPA_ON_GPIO2_5 flag must also be set or cleared,
* respectively.
*/
CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM = (1<<5) |
CHIPC_QUIRK_4331_EXTPA_MUX_SPROM,
/**
* Access to the SPROM uses pins shared with two 802.11a external PAs.
*
* When enabling and disabling EXTPA, the CCTRL4331_EXTPA_EN2 must also
* be cleared to allow SPROM access.
*/
CHIPC_QUIRK_4331_EXTPA2_MUX_SPROM = (1<<6) |
CHIPC_QUIRK_4331_EXTPA_MUX_SPROM,
/**
* SPROM pins are muxed with the FEM control lines on this 4360-family
* device. The muxed pins must be switched to allow reading/writing
* the SPROM.
*/
CHIPC_QUIRK_4360_FEM_MUX_SPROM = (1<<5) | CHIPC_QUIRK_MUX_SPROM
};
struct chipc_softc {
@ -89,6 +118,19 @@ struct chipc_softc {
uint32_t quirks; /**< CHIPC_QUIRK_* quirk flags */
uint32_t caps; /**< CHIPC_CAP_* capability register flags */
uint32_t cst; /**< CHIPC_CST* status register flags */
bhnd_nvram_src_t nvram_src; /**< NVRAM source */
struct mtx mtx; /**< state mutex. */
struct bhnd_sprom sprom; /**< OTP/SPROM shadow, if any */
};
#define CHIPC_LOCK_INIT(sc) \
mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
"BHND chipc driver lock", MTX_DEF)
#define CHIPC_LOCK(sc) mtx_lock(&(sc)->mtx)
#define CHIPC_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
#define CHIPC_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what)
#define CHIPC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx)
#endif /* _BHND_CORES_CHIPC_CHIPCVAR_H_ */

View file

@ -36,10 +36,6 @@
* NVRAM data sources supported by bhnd(4) devices.
*/
typedef enum {
BHND_NVRAM_SRC_CIS, /**< Default CIS source; this may
* apply, for example, to PCMCIA cards
* vending Broadcom NVRAM data via
* their standard CIS table. */
BHND_NVRAM_SRC_OTP, /**< On-chip one-time-programmable
* memory. */
@ -51,15 +47,36 @@ typedef enum {
* NVRAM. */
BHND_NVRAM_SRC_SPROM, /**< External serial EEPROM. */
BHND_NVRAM_SRC_NONE /**< No NVRAM source is directly
* attached. This is used on devices
* attached via PCI(e) to BHND SoCs,
* where to avoid unnecessary flash
* hardware, NVRAM configuration for
* individual devices is provided by
* hardware attached to the SoC
* itself.
BHND_NVRAM_SRC_UNKNOWN /**< No NVRAM source is directly
* attached.
*
* This will be returned by ChipCommon
* revisions (rev <= 31) used in early
* chipsets that vend SPROM/OTP via the
* native host bridge interface.
*
* For example, PCMCIA cards may vend
* Broadcom NVRAM data via their standard CIS
* table, and earlier PCI(e) devices map
* SPROM statically into PCI BARs, and the
* control registers into PCI config space.
* This will also be returned on later
* devices that are attached via PCI(e) to
* BHND SoCs, but do not include an attached
* SPROM, or programmed OTP. On such SoCs,
* NVRAM configuration for individual devices
* is provided by a common platform NVRAM
* device.
*/
} bhnd_nvram_src_t;
/**
* Evaluates to true if the given NVRAM data source is accessible via
* ChipCommon.
*/
#define BHND_NVRAM_SRC_CC(_src) \
((_src) == BHND_NVRAM_SRC_OTP || (_src) == BHND_NVRAM_SRC_SPROM)
#endif /* _BHND_NVRAM_BHND_NVRAM_H_ */

View file

@ -46,13 +46,16 @@ INTERFACE bhnd_nvram;
* @param[out] buf On success, the requested value will be written
* to this buffer. This argment may be NULL if
* the value is not desired.
* @param[in,out] size The capacity of @p buf. On success, will be set
* to the actual size of the requested value.
* @param[in,out] len The maximum capacity of @p buf. On success,
* will be set to the actual size of the requested
* value.
*
* @retval 0 success
* @retval ENOENT The requested variable was not found.
* @retval ENOMEM If @p buf is non-NULL and a buffer of @p size is too
* @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too
* small to hold the requested value.
* @retval ENODEV If no supported NVRAM hardware is accessible via this
* device.
* @retval non-zero If reading @p name otherwise fails, a regular unix
* error code will be returned.
*/
@ -60,5 +63,30 @@ METHOD int getvar {
device_t dev;
const char *name;
void *buf;
size_t *size;
};
size_t *len;
};
/**
* Set an NVRAM variable's local value.
*
* No changes should be written to non-volatile storage.
*
* @param dev The NVRAM device.
* @param name The NVRAM variable name.
* @param buf The new value.
* @param len The size of @p buf.
*
* @retval 0 success
* @retval ENOENT The specified variable name is not recognized.
* @retval EINVAL If @p len does not match the expected variable size.
* @retval ENODEV If no supported NVRAM hardware is accessible via this
* device.
* @retval non-zero If reading @p name otherwise fails, a regular unix
* error code will be returned.
*/
METHOD int setvar {
device_t dev;
const char *name;
const void *buf;
size_t len;
};

View file

@ -0,0 +1,572 @@
/*-
* Copyright (c) 2015 Landon Fuller <landon@landonf.org>
* 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,
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/rman.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <dev/bhnd/bhndvar.h>
#include "nvramvar.h"
#include "bhnd_spromreg.h"
#include "bhnd_spromvar.h"
/*
* BHND SPROM Parsing
*
* Provides identification and parsing of BHND SPROM data.
*/
static int sprom_direct_read(struct bhnd_sprom *sc, size_t offset,
void *buf, size_t nbytes, uint8_t *crc);
static int sprom_extend_shadow(struct bhnd_sprom *sc, size_t image_size,
uint8_t *crc);
static int sprom_populate_shadow(struct bhnd_sprom *sc);
static int sprom_var_defn(struct bhnd_sprom *sc, const char *name,
const struct bhnd_nvram_var **var,
const struct bhnd_sprom_var **sprom, size_t *size);
/* SPROM revision is always located at the second-to-last byte */
#define SPROM_REV(_sc) SPROM_READ_1((_sc), (_sc)->sp_size - 2)
/* SPROM CRC is always located at the last byte */
#define SPROM_CRC_OFF(_sc) SPROM_CRC_LEN(_sc)
/* SPROM CRC covers all but the final CRC byte */
#define SPROM_CRC_LEN(_sc) ((_sc)->sp_size - 1)
/* SPROM shadow I/O (with byte-order translation) */
#define SPROM_READ_1(_sc, _off) SPROM_READ_ENC_1(_sc, _off)
#define SPROM_READ_2(_sc, _off) le16toh(SPROM_READ_ENC_2(_sc, _off))
#define SPROM_READ_4(_sc, _off) le32toh(SPROM_READ_ENC_4(_sc, _off))
#define SPROM_WRITE_1(_sc, _off, _v) SPROM_WRITE_ENC_1(_sc, _off, (_v))
#define SPROM_WRITE_2(_sc, _off, _v) SPROM_WRITE_ENC_2(_sc, _off, \
htole16(_v))
#define SPROM_WRITE_4(_sc, _off, _v) SPROM_WRITE_ENC_4(_sc, _off, \
htole32(_v))
/* SPROM shadow I/O (without byte-order translation) */
#define SPROM_READ_ENC_1(_sc, _off) (*(uint8_t *)((_sc)->sp_shadow + _off))
#define SPROM_READ_ENC_2(_sc, _off) (*(uint16_t *)((_sc)->sp_shadow + _off))
#define SPROM_READ_ENC_4(_sc, _off) (*(uint32_t *)((_sc)->sp_shadow + _off))
#define SPROM_WRITE_ENC_1(_sc, _off, _v) \
*((uint8_t *)((_sc)->sp_shadow + _off)) = (_v)
#define SPROM_WRITE_ENC_2(_sc, _off, _v) \
*((uint16_t *)((_sc)->sp_shadow + _off)) = (_v)
#define SPROM_WRITE_ENC_4(_sc, _off, _v) \
*((uint32_t *)((_sc)->sp_shadow + _off)) = (_v)
/* Call @p _next macro with the C type, widened (signed or unsigned) C
* type, and width associated with @p _dtype */
#define SPROM_SWITCH_TYPE(_dtype, _next, ...) \
do { \
switch (_dtype) { \
case BHND_NVRAM_DT_UINT8: \
_next (uint8_t, uint32_t, 1, \
## __VA_ARGS__); \
break; \
case BHND_NVRAM_DT_UINT16: \
_next (uint16_t, uint32_t, 2, \
## __VA_ARGS__); \
break; \
case BHND_NVRAM_DT_UINT32: \
_next (uint32_t, uint32_t, 4, \
## __VA_ARGS__); \
break; \
case BHND_NVRAM_DT_INT8: \
_next (int8_t, int32_t, 1, \
## __VA_ARGS__); \
break; \
case BHND_NVRAM_DT_INT16: \
_next (int16_t, int32_t, 2, \
## __VA_ARGS__); \
break; \
case BHND_NVRAM_DT_INT32: \
_next (int32_t, int32_t, 4, \
## __VA_ARGS__); \
break; \
case BHND_NVRAM_DT_CHAR: \
_next (uint8_t, uint32_t, 1, \
## __VA_ARGS__); \
break; \
} \
} while (0)
/*
* Table of supported SPROM image formats, sorted by image size, ascending.
*/
#define SPROM_FMT(_sz, _revmin, _revmax, _sig) \
{ SPROM_SZ_ ## _sz, _revmin, _revmax, \
SPROM_SIG_ ## _sig ## _OFF, \
SPROM_SIG_ ## _sig }
static const struct sprom_fmt {
size_t size;
uint8_t rev_min;
uint8_t rev_max;
size_t sig_offset;
uint16_t sig_req;
} sprom_fmts[] = {
SPROM_FMT(R1_3, 1, 3, NONE),
SPROM_FMT(R4_8_9, 4, 4, R4),
SPROM_FMT(R4_8_9, 8, 9, R8_9),
SPROM_FMT(R10, 10, 10, R10),
SPROM_FMT(R11, 11, 11, R11)
};
/**
* Identify the SPROM format at @p offset within @p r, verify the CRC,
* and allocate a local shadow copy of the SPROM data.
*
* After successful initialization, @p r will not be accessed; any pin
* configuration required for SPROM access may be reset.
*
* @param[out] sprom On success, will be initialized with shadow of the SPROM
* data.
* @param r An active resource mapping the SPROM data.
* @param offset Offset of the SPROM data within @p resource.
*/
int
bhnd_sprom_init(struct bhnd_sprom *sprom, struct bhnd_resource *r,
bus_size_t offset)
{
bus_size_t res_size;
int error;
sprom->dev = rman_get_device(r->res);
sprom->sp_res = r;
sprom->sp_res_off = offset;
/* Determine maximum possible SPROM image size */
res_size = rman_get_size(r->res);
if (offset >= res_size)
return (EINVAL);
sprom->sp_size_max = MIN(res_size - offset, SPROM_SZ_MAX);
/* Allocate and populate SPROM shadow */
sprom->sp_size = 0;
sprom->sp_capacity = sprom->sp_size_max;
sprom->sp_shadow = malloc(sprom->sp_capacity, M_BHND, M_NOWAIT);
if (sprom->sp_shadow == NULL)
return (ENOMEM);
/* Read and identify SPROM image */
if ((error = sprom_populate_shadow(sprom)))
return (error);
return (0);
}
/**
* Release all resources held by @p sprom.
*
* @param sprom A SPROM instance previously initialized via bhnd_sprom_init().
*/
void
bhnd_sprom_fini(struct bhnd_sprom *sprom)
{
free(sprom->sp_shadow, M_BHND);
}
/* Perform a read using a SPROM offset descriptor, safely widening the
* result to its 32-bit representation before assigning it to @p _dest. */
#define SPROM_GETVAR_READ(_type, _widen, _width, _sc, _off, _dest) \
do { \
_type _v = (_type)SPROM_READ_ ## _width(_sc, _off->offset); \
if (_off->shift > 0) { \
_v >>= _off->shift; \
} else if (off->shift < 0) { \
_v <<= -_off->shift; \
} \
_dest = ((uint32_t) (_widen) _v) & _off->mask; \
} while(0)
/* Emit a value read using a SPROM offset descriptor, narrowing the
* result output representation and, if necessary, OR'ing it with the
* previously read value from @p _buf. */
#define SPROM_GETVAR_WRITE(_type, _widen, _width, _off, _src, _buf) \
do { \
_type _v = (_type) (_widen) _src; \
if (_off->cont) \
_v |= *((_type *)_buf); \
*((_type *)_buf) = _v; \
} while(0)
/**
* Read a SPROM variable, performing conversion to host byte order.
*
* @param sc The SPROM parser state.
* @param name The SPROM variable name.
* @param[out] buf On success, the requested value will be written
* to this buffer. This argment may be NULL if
* the value is not desired.
* @param[in,out] len The capacity of @p buf. On success, will be set
* to the actual size of the requested value.
*
* @retval 0 success
* @retval ENOENT The requested variable was not found.
* @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too
* small to hold the requested value.
* @retval non-zero If reading @p name otherwise fails, a regular unix
* error code will be returned.
*/
int
bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf,
size_t *len)
{
const struct bhnd_nvram_var *nv;
const struct bhnd_sprom_var *sv;
size_t all1_offs;
size_t req_size;
int error;
if ((error = sprom_var_defn(sc, name, &nv, &sv, &req_size)))
return (error);
/* Provide required size */
if (buf == NULL) {
*len = req_size;
return (0);
}
/* Check (and update) target buffer len */
if (*len < req_size)
return (ENOMEM);
else
*len = req_size;
/* Read data */
all1_offs = 0;
for (size_t i = 0; i < sv->num_offsets; i++) {
const struct bhnd_sprom_offset *off;
uint32_t val;
off = &sv->offsets[i];
KASSERT(!off->cont || i > 0, ("cont marked on first offset"));
/* If not a continuation, advance the output buffer */
if (i > 0 && !off->cont) {
buf = ((uint8_t *)buf) +
bhnd_nvram_type_width(sv->offsets[i-1].type);
}
/* Read the value, widening to a common uint32
* representation */
SPROM_SWITCH_TYPE(off->type, SPROM_GETVAR_READ, sc, off, val);
/* If IGNALL1, record whether value has all bits set. */
if (nv->flags & BHND_NVRAM_VF_IGNALL1) {
uint32_t all1;
all1 = off->mask;
if (off->shift > 0)
all1 >>= off->shift;
else if (off->shift < 0)
all1 <<= -off->shift;
if ((val & all1) == all1)
all1_offs++;
}
/* Write the value, narrowing to the appropriate output
* width. */
SPROM_SWITCH_TYPE(nv->type, SPROM_GETVAR_WRITE, off, val, buf);
}
/* Should value should be treated as uninitialized? */
if (nv->flags & BHND_NVRAM_VF_IGNALL1 && all1_offs == sv->num_offsets)
return (ENOENT);
return (0);
}
/* Perform a read of a variable offset from _src, safely widening the result
* to its 32-bit representation before assigning it to @p
* _dest. */
#define SPROM_SETVAR_READ(_type, _widen, _width, _off, _src, _dest) \
do { \
_type _v = *(const _type *)_src; \
if (_off->shift > 0) { \
_v <<= _off->shift; \
} else if (off->shift < 0) { \
_v >>= -_off->shift; \
} \
_dest = ((uint32_t) (_widen) _v) & _off->mask; \
} while(0)
/* Emit a value read using a SPROM offset descriptor, narrowing the
* result output representation and, if necessary, OR'ing it with the
* previously read value from @p _buf. */
#define SPROM_SETVAR_WRITE(_type, _widen, _width, _sc, _off, _src) \
do { \
_type _v = (_type) (_widen) _src; \
if (_off->cont) \
_v |= SPROM_READ_ ## _width(_sc, _off->offset); \
SPROM_WRITE_ ## _width(_sc, _off->offset, _v); \
} while(0)
/**
* Set a local value for a SPROM variable, performing conversion to SPROM byte
* order.
*
* The new value will be written to the backing SPROM shadow.
*
* @param sc The SPROM parser state.
* @param name The SPROM variable name.
* @param[out] buf The new value.
* @param[in,out] len The size of @p buf.
*
* @retval 0 success
* @retval ENOENT The requested variable was not found.
* @retval EINVAL If @p len does not match the expected variable size.
*/
int
bhnd_sprom_setvar(struct bhnd_sprom *sc, const char *name, const void *buf,
size_t len)
{
const struct bhnd_nvram_var *nv;
const struct bhnd_sprom_var *sv;
size_t req_size;
int error;
uint8_t crc;
if ((error = sprom_var_defn(sc, name, &nv, &sv, &req_size)))
return (error);
/* Provide required size */
if (len != req_size)
return (EINVAL);
/* Write data */
for (size_t i = 0; i < sv->num_offsets; i++) {
const struct bhnd_sprom_offset *off;
uint32_t val;
off = &sv->offsets[i];
KASSERT(!off->cont || i > 0, ("cont marked on first offset"));
/* If not a continuation, advance the input pointer */
if (i > 0 && !off->cont) {
buf = ((const uint8_t *)buf) +
bhnd_nvram_type_width(sv->offsets[i-1].type);
}
/* Read the value, widening to a common uint32
* representation */
SPROM_SWITCH_TYPE(nv->type, SPROM_SETVAR_READ, off, buf, val);
/* Write the value, narrowing to the appropriate output
* width. */
SPROM_SWITCH_TYPE(off->type, SPROM_SETVAR_WRITE, sc, off, val);
}
/* Update CRC */
crc = ~bhnd_nvram_crc8(sc->sp_shadow, SPROM_CRC_LEN(sc),
BHND_NVRAM_CRC8_INITIAL);
SPROM_WRITE_1(sc, SPROM_CRC_OFF(sc), crc);
return (0);
}
/* Read and identify the SPROM image by incrementally performing
* read + CRC of all supported image formats */
static int
sprom_populate_shadow(struct bhnd_sprom *sc)
{
const struct sprom_fmt *fmt;
int error;
uint16_t sig;
uint8_t srom_rev;
uint8_t crc;
crc = BHND_NVRAM_CRC8_INITIAL;
/* Identify the SPROM revision (and populate the SPROM shadow) */
for (size_t i = 0; i < nitems(sprom_fmts); i++) {
fmt = &sprom_fmts[i];
/* Read image data and check CRC */
if ((error = sprom_extend_shadow(sc, fmt->size, &crc)))
return (error);
/* Skip on invalid CRC */
if (crc != BHND_NVRAM_CRC8_VALID)
continue;
/* Fetch SROM revision */
srom_rev = SPROM_REV(sc);
/* Early sromrev 1 devices (specifically some BCM440x enet
* cards) are reported to have been incorrectly programmed
* with a revision of 0x10. */
if (fmt->size == SPROM_SZ_R1_3 && srom_rev == 0x10)
srom_rev = 0x1;
/* Verify revision range */
if (srom_rev < fmt->rev_min || srom_rev > fmt->rev_max)
continue;
/* Verify signature (if any) */
sig = SPROM_SIG_NONE;
if (fmt->sig_offset != SPROM_SIG_NONE_OFF)
sig = SPROM_READ_2(sc, fmt->sig_offset);
if (sig != fmt->sig_req) {
device_printf(sc->dev,
"invalid sprom %hhu signature: 0x%hx "
"(expected 0x%hx)\n",
srom_rev, sig, fmt->sig_req);
return (EINVAL);
}
/* Identified */
sc->sp_rev = srom_rev;
return (0);
}
/* identification failed */
device_printf(sc->dev, "unrecognized sprom format\n");
return (EINVAL);
}
/*
* Extend the shadowed SPROM buffer to image_size, reading any required
* data from the backing SPROM resource and updating the CRC.
*/
static int
sprom_extend_shadow(struct bhnd_sprom *sc, size_t image_size,
uint8_t *crc)
{
int error;
KASSERT(image_size >= sc->sp_size, (("shadow truncation unsupported")));
/* Verify the request fits within our shadow buffer */
if (image_size > sc->sp_capacity)
return (ENOSPC);
/* Skip no-op requests */
if (sc->sp_size == image_size)
return (0);
/* Populate the extended range */
error = sprom_direct_read(sc, sc->sp_size, sc->sp_shadow + sc->sp_size,
image_size - sc->sp_size, crc);
if (error)
return (error);
sc->sp_size = image_size;
return (0);
}
/**
* Read nbytes at the given offset from the backing SPROM resource, and
* update the CRC.
*/
static int
sprom_direct_read(struct bhnd_sprom *sc, size_t offset, void *buf,
size_t nbytes, uint8_t *crc)
{
bus_size_t res_offset;
size_t nread;
uint16_t *p;
KASSERT(nbytes % sizeof(uint16_t) == 0, ("unaligned sprom size"));
KASSERT(offset % sizeof(uint16_t) == 0, ("unaligned sprom offset"));
/* Check for read overrun */
if (offset >= sc->sp_size_max || sc->sp_size_max - offset < nbytes) {
device_printf(sc->dev, "requested SPROM read would overrun\n");
return (EINVAL);
}
p = (uint16_t *)buf;
res_offset = sc->sp_res_off + offset;
/* Perform read */
for (nread = 0; nread < nbytes; nread += 2) {
*p = bhnd_bus_read_stream_2(sc->sp_res, res_offset+nread);
*crc = bhnd_nvram_crc8(p, sizeof(*p), *crc);
p++;
};
return (0);
}
/**
* Locate the variable and SPROM revision-specific definitions
* for variable with @p name.
*/
static int
sprom_var_defn(struct bhnd_sprom *sc, const char *name,
const struct bhnd_nvram_var **var,
const struct bhnd_sprom_var **sprom,
size_t *size)
{
/* Find variable definition */
*var = bhnd_nvram_var_defn(name);
if (*var == NULL)
return (ENOENT);
/* Find revision-specific SPROM definition */
for (size_t i = 0; i < (*var)->num_sp_descs; i++) {
const struct bhnd_sprom_var *sp = &(*var)->sprom_descs[i];
if (sc->sp_rev < sp->compat.first)
continue;
if (sc->sp_rev > sp->compat.last)
continue;
/* Found */
*sprom = sp;
/* Calculate size in bytes */
*size = bhnd_nvram_type_width((*var)->type) * sp->num_offsets;
return (0);
}
/* Not supported by this SPROM revision */
return (ENOENT);
}

View file

@ -0,0 +1,63 @@
/*-
* Copyright (c) 2016 Landon Fuller <landon@landonf.org>
* 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,
* 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_NVRAM_SPROMREG_H_
#define _BHND_NVRAM_SPROMREG_H_
#define SPROM_SZ_R1_3 128 /**< SPROM image size (rev 1-3) */
#define SPROM_SZ_R4_8_9 440 /**< SPROM image size (rev 4, 8-9) */
#define SPROM_SZ_R10 460 /**< SPROM image size (rev 10) */
#define SPROM_SZ_R11 468 /**< SPROM image size (rev 11) */
/** Maximum supported SPROM image size */
#define SPROM_SZ_MAX SPROM_SZ_R11
#define SPROM_SIG_NONE 0x0
#define SPROM_SIG_NONE_OFF 0x0
/** SPROM signature (rev 4) */
#define SPROM_SIG_R4 0x5372
#define SPROM_SIG_R4_OFF 64 /**< SPROM signature offset (rev 4) */
/** SPROM signature (rev 8, 9) */
#define SPROM_SIG_R8_9 SPROM_SIG_R4
#define SPROM_SIG_R8_9_OFF 128 /**< SPROM signature offset (rev 8-9) */
/** SPROM signature (rev 10) */
#define SPROM_SIG_R10 SPROM_SIG_R4
#define SPROM_SIG_R10_OFF 438 /**< SPROM signature offset (rev 10) */
/** SPROM signature (rev 11) */
#define SPROM_SIG_R11 0x0634
#define SPROM_SIG_R11_OFF 128 /**< SPROM signature offset (rev 11) */
#endif /* _BHND_NVRAM_SPROMREG_H_ */

View file

@ -0,0 +1,58 @@
/*-
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
* 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,
* 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_NVRAM_BHND_SPROM_H_
#define _BHND_NVRAM_BHND_SPROM_H_
struct bhnd_sprom {
device_t dev; /**< sprom parent device */
uint8_t sp_rev; /**< sprom revision */
struct bhnd_resource *sp_res; /**< sprom resource. */
bus_size_t sp_res_off; /**< offset to sprom image */
uint8_t *sp_shadow; /**< sprom shadow */
bus_size_t sp_size_max; /**< maximum possible sprom length */
size_t sp_size; /**< shadow size */
size_t sp_capacity; /**< shadow buffer capacity */
};
int bhnd_sprom_init(struct bhnd_sprom *sprom, struct bhnd_resource *r,
bus_size_t offset);
void bhnd_sprom_fini(struct bhnd_sprom *sprom);
int bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf,
size_t *len);
int bhnd_sprom_setvar(struct bhnd_sprom *sc, const char *name,
const void *buf, size_t len);
#endif /* _BHND_NVRAM_BHND_SPROM_H_ */

1445
sys/dev/bhnd/nvram/nvram_map Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,149 @@
/*-
* Copyright (c) 2016 Landon Fuller <landon@landonf.org>
* 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,
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
#include "bhnd_nvram_map_data.h"
/*
* CRC-8 lookup table used to checksum SPROM and NVRAM data via
* bhnd_nvram_crc8().
*
* Generated with following parameters:
* polynomial: CRC-8 (x^8 + x^7 + x^6 + x^4 + x^2 + 1)
* reflected bits: false
* reversed: true
*/
const uint8_t bhnd_nvram_crc8_tab[] = {
0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b, 0x4a, 0xbd, 0xf3,
0x04, 0x6f, 0x98, 0xd6, 0x21, 0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46,
0x08, 0xff, 0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5, 0x7f,
0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14, 0x35, 0xc2, 0x8c, 0x7b,
0x10, 0xe7, 0xa9, 0x5e, 0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77,
0x80, 0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca, 0xfe, 0x09,
0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95, 0xb4, 0x43, 0x0d, 0xfa, 0x91,
0x66, 0x28, 0xdf, 0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01,
0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b, 0x81, 0x76, 0x38,
0xcf, 0xa4, 0x53, 0x1d, 0xea, 0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19,
0x57, 0xa0, 0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e, 0x5f,
0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34, 0xab, 0x5c, 0x12, 0xe5,
0x8e, 0x79, 0x37, 0xc0, 0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d,
0x8a, 0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54, 0x75, 0x82,
0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e, 0xd4, 0x23, 0x6d, 0x9a, 0xf1,
0x06, 0x48, 0xbf, 0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5,
0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b, 0x0a, 0xfd, 0xb3,
0x44, 0x2f, 0xd8, 0x96, 0x61, 0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87,
0xc9, 0x3e, 0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74, 0xc1,
0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa, 0x8b, 0x7c, 0x32, 0xc5,
0xae, 0x59, 0x17, 0xe0, 0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6,
0x41, 0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b, 0xbe, 0x49,
0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5, 0xf4, 0x03, 0x4d, 0xba, 0xd1,
0x26, 0x68, 0x9f
};
/**
* Return the size of type @p dt.
*
* @param dt NVRAM data type.
* @result the byte width of @p dt.
*/
size_t
bhnd_nvram_type_width(bhnd_nvram_dt dt)
{
switch (dt) {
case BHND_NVRAM_DT_INT8:
case BHND_NVRAM_DT_UINT8:
case BHND_NVRAM_DT_CHAR:
return (sizeof(uint8_t));
case BHND_NVRAM_DT_INT16:
case BHND_NVRAM_DT_UINT16:
return (sizeof(uint16_t));
case BHND_NVRAM_DT_INT32:
case BHND_NVRAM_DT_UINT32:
return (sizeof(uint32_t));
}
/* Quiesce gcc4.2 */
panic("bhnd nvram data type %u unknown", dt);
}
/**
* Return the variable definition for @p varname, if any.
*
* @param varname variable name
*
* @retval bhnd_nvram_var If a valid definition for @p varname is found.
* @retval NULL If no definition for @p varname is found.
*/
const struct bhnd_nvram_var *
bhnd_nvram_var_defn(const char *varname)
{
size_t min, mid, max;
int order;
/*
* Locate the requested variable using a binary search.
*
* The variable table is guaranteed to be sorted in lexicographical
* order (using the 'C' locale for collation rules)
*/
min = 0;
mid = 0;
max = nitems(bhnd_nvram_vars) - 1;
while (max >= min) {
/* Select midpoint */
mid = (min + max) / 2;
/* Determine which side of the partition to search */
order = strcmp(bhnd_nvram_vars[mid].name, varname);
if (order < 0) {
/* Search upper partition */
min = mid + 1;
} else if (order > 0) {
/* Search lower partition */
max = mid - 1;
} else if (order == 0) {
/* Match found */
return (&bhnd_nvram_vars[mid]);
}
}
/* Not found */
return (NULL);
}

View file

@ -0,0 +1,128 @@
/*-
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
* 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,
* 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_NVRAM_BHND_NVRAMVAR_H_
#define _BHND_NVRAM_BHND_NVRAMVAR_H_
/** NVRAM Primitive data types */
typedef enum {
BHND_NVRAM_DT_UINT8 = 0, /**< unsigned 8-bit integer */
BHND_NVRAM_DT_UINT16 = 1, /**< unsigned 16-bit integer */
BHND_NVRAM_DT_UINT32 = 2, /**< unsigned 32-bit integer */
BHND_NVRAM_DT_INT8 = 3, /**< signed 8-bit integer */
BHND_NVRAM_DT_INT16 = 4, /**< signed 16-bit integer */
BHND_NVRAM_DT_INT32 = 5, /**< signed 32-bit integer */
BHND_NVRAM_DT_CHAR = 6, /**< ASCII char */
} bhnd_nvram_dt;
/** NVRAM data type string representations */
typedef enum {
BHND_NVRAM_VFMT_HEX = 1, /**< hex format */
BHND_NVRAM_VFMT_DEC = 2, /**< decimal format */
BHND_NVRAM_VFMT_MACADDR = 3, /**< mac address (canonical form, hex octets,
separated with ':') */
BHND_NVRAM_VFMT_LEDDC = 4, /**< LED PWM duty-cycle (2 bytes -- on/off) */
BHND_NVRAM_VFMT_CCODE = 5 /**< count code format (2-3 ASCII chars, or hex string) */
} bhnd_nvram_fmt;
/** NVRAM variable flags */
enum {
BHND_NVRAM_VF_ARRAY = (1<<0), /**< variable is an array */
BHND_NVRAM_VF_MFGINT = (1<<1), /**< mfg-internal variable; should not be externally visible */
BHND_NVRAM_VF_IGNALL1 = (1<<2) /**< hide variable if its value has all bits set. */
};
#define BHND_SPROMREV_MAX UINT8_MAX /**< maximum supported SPROM revision */
/** SPROM revision compatibility declaration */
struct bhnd_sprom_compat {
uint8_t first; /**< first compatible SPROM revision */
uint8_t last; /**< last compatible SPROM revision, or BHND_SPROMREV_MAX */
};
/** SPROM value descriptor */
struct bhnd_sprom_offset {
uint16_t offset; /**< byte offset within SPROM */
bool cont:1; /**< value should be bitwise OR'd with the
* previous offset descriptor */
bhnd_nvram_dt type:7; /**< data type */
int8_t shift; /**< shift to be applied to the value */
uint32_t mask; /**< mask to be applied to the value(s) */
};
/** SPROM-specific variable definition */
struct bhnd_sprom_var {
struct bhnd_sprom_compat compat; /**< sprom compatibility declaration */
const struct bhnd_sprom_offset *offsets; /**< offset descriptors */
size_t num_offsets; /**< number of offset descriptors */
};
/** NVRAM variable definition */
struct bhnd_nvram_var {
const char *name; /**< variable name */
bhnd_nvram_dt type; /**< base data type */
bhnd_nvram_fmt fmt; /**< string format */
uint32_t flags; /**< BHND_NVRAM_VF_* flags */
const struct bhnd_sprom_var *sprom_descs; /**< SPROM-specific variable descriptors */
size_t num_sp_descs; /**< number of sprom descriptors */
};
size_t bhnd_nvram_type_width(bhnd_nvram_dt dt);
const struct bhnd_nvram_var *bhnd_nvram_var_defn(const char *varname);
/** Initial bhnd_nvram_crc8 value */
#define BHND_NVRAM_CRC8_INITIAL 0xFF
/** Valid CRC-8 checksum */
#define BHND_NVRAM_CRC8_VALID 0x9F
extern const uint8_t bhnd_nvram_crc8_tab[];
/**
* Calculate CRC-8 over @p buf.
*
* @param buf input buffer
* @param size buffer size
* @param crc last computed crc, or BHND_NVRAM_CRC8_INITIAL
*/
static inline uint8_t
bhnd_nvram_crc8(const void *buf, size_t size, uint8_t crc)
{
const uint8_t *p = (const uint8_t *)buf;
while (size--)
crc = bhnd_nvram_crc8_tab[(crc ^ *p++)];
return (crc);
}
#endif /* _BHND_NVRAM_BHND_NVRAMVAR_H_ */

0
sys/dev/bhnd/tools/bus_macro.sh Executable file → Normal file
View file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
#!/bin/sh
# Use C locale to ensure AWK string comparisons always produce
# a stable sort order.
# $FreeBSD$
BHND_TOOLDIR="$(dirname $0)/"
LC_ALL=C; export LC_ALL
"$BHND_TOOLDIR/nvram_map_gen.awk" $@

View file

@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$");
#include <dev/bhnd/bhnd.h>
#include <dev/bhnd/bhnd_ids.h>
#include "bhnd_nvram_map.h"
static const struct resource_spec bwn_rspec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ -1, -1, 0 }
@ -97,6 +99,14 @@ bwn_attach(device_t dev)
r = sc->res[0];
device_printf(dev, "got rid=%d res=%p\n", sc->rspec[0].rid, r);
uint8_t macaddr[6];
error = bhnd_nvram_getvar(dev, BHND_NVAR_MACADDR, macaddr,
sizeof(macaddr));
if (error)
return (error);
device_printf(dev, "got macaddr %6D\n", macaddr, ":");
return (0);
}

View file

@ -1,10 +1,16 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../dev/bhnd
.PATH: ${.CURDIR}/../../dev/bhnd/nvram
KMOD= bhnd
SRCS= bhnd.c bhnd_subr.c \
bhnd_bus_if.c bhnd_bus_if.h bhnd_nvram_if.h
bhnd_sprom.c nvram_subr.c \
bhnd_nvram_map.h bhnd_nvram_map_data.h
SRCS+= bhnd_bus_if.c bhnd_bus_if.h \
bhnd_chipc_if.c bhnd_chipc_if.h \
bhnd_nvram_if.c bhnd_nvram_if.h
SRCS+= device_if.h bus_if.h
@ -13,7 +19,6 @@ SUBDIR= bcma \
bhndb \
bhndb_pci \
cores \
nvram \
siba \
siba_bhndb

View file

@ -5,8 +5,10 @@
KMOD= bhndb
SRCS= bhndb.c bhndb_subr.c bhndb_hwdata.c \
bhndb_bus_if.c bhndb_bus_if.h \
bhndb_if.c bhndb_if.h \
bhnd_bus_if.h
bhndb_if.c bhndb_if.h
SRCS+= bhnd_bus_if.h \
bhnd_chipc_if.h \
bhnd_nvram_if.h
SRCS+= device_if.h bus_if.h pci_if.h

View file

@ -3,8 +3,10 @@
.PATH: ${.CURDIR}/../../../dev/bhnd/bhndb
KMOD= bhndb_pci
SRCS= bhndb_pci.c bhndb_pci_hwdata.c
SRCS= bhndb_pci.c bhndb_pci_hwdata.c \
bhndb_pci_sprom.c
SRCS+= bhnd_bus_if.h bhndb_bus_if.h bhndb_if.h
SRCS+= bhnd_nvram_if.h
SRCS+= device_if.h bus_if.h pci_if.h

View file

@ -3,8 +3,8 @@
.PATH: ${.CURDIR}/../../../../dev/bhnd/cores/chipc
KMOD= bhnd_chipc
SRCS= chipc.c \
bhnd_chipc_if.c bhnd_chipc_if.h
SRCS+= device_if.h bus_if.h bhnd_bus_if.h
SRCS= chipc.c
SRCS+= device_if.h bus_if.h bhnd_bus_if.h \
bhnd_chipc_if.h bhnd_nvram_if.h
.include <bsd.kmod.mk>

View file

@ -1,10 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/bhnd/nvram
KMOD= bhnd_nvram
SRCS= bhnd_nvram_if.c bhnd_nvram_if.h bhnd_bus_if.h
SRCS+= device_if.h bus_if.h
.include <bsd.kmod.mk>

View file

@ -4,8 +4,8 @@
KMOD= if_bwn_pci
SRCS= if_bwn_pci.c bwn_mac.c
SRCS+= bhnd_bus_if.h bhndb_bus_if.h \
bhndb_if.h bhnd_nvram_map.h
SRCS+= device_if.h bus_if.h pci_if.h \
bhnd_bus_if.h bhndb_bus_if.h \
bhndb_if.h
.include <bsd.kmod.mk>