提交 10d8493c 编写于 作者: A Arend van Spriel 提交者: John W. Linville

bcma: add support for on-chip OTP memory used for SPROM storage

Wireless Broadcom chips can have either their SPROM data stored
on either external SPROM or on-chip OTP memory. Both are accessed
through the same register space. This patch adds support for the
on-chip OTP memory.

Tested with:
BCM43224 OTP and SPROM
BCM4331 SPROM
BCM4313 OTP

This patch is in response to linux-wireless thread [1].

[1] http://article.gmane.org/gmane.linux.kernel.wireless.general/85426Tested-by: NSaul St. John <saul.stjohn@gmail.com>
Tested-by: NRafal Milecki <zajec5@gmail.com>
Tested-by: NHauke Mehrtens <hauke@hauke-m.de>
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: NArend van Spriel <arend@broadcom.com>
Signed-off-by: NJohn W. Linville <linville@tuxdriver.com>
上级 4ac887cf
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -300,37 +300,128 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
SSB_SROM8_FEM_ANTSWLUT_SHIFT);
}
static bool bcma_is_sprom_available(struct bcma_bus *bus)
/*
* Indicates the presence of external SPROM.
*/
static bool bcma_sprom_ext_available(struct bcma_bus *bus)
{
u32 sromctrl;
u32 chip_status;
u32 srom_control;
u32 present_mask;
if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
return false;
if (bus->drv_cc.core->id.rev >= 31) {
if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
return false;
if (bus->drv_cc.core->id.rev >= 32) {
sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
return sromctrl & BCMA_CC_SROM_CONTROL_PRESENT;
srom_control = bcma_read32(bus->drv_cc.core,
BCMA_CC_SROM_CONTROL);
return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
}
return true;
/* older chipcommon revisions use chip status register */
chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
switch (bus->chipinfo.id) {
case 0x4313:
present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
break;
case 0x4331:
present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
break;
default:
return true;
}
return chip_status & present_mask;
}
/*
* Indicates that on-chip OTP memory is present and enabled.
*/
static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
{
u32 chip_status;
u32 otpsize = 0;
bool present;
chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
switch (bus->chipinfo.id) {
case 0x4313:
present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
break;
case 0x4331:
present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
break;
case 43224:
case 43225:
/* for these chips OTP is always available */
present = true;
break;
default:
present = false;
break;
}
if (present) {
otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
}
return otpsize != 0;
}
/*
* Verify OTP is filled and determine the byte
* offset where SPROM data is located.
*
* On error, returns 0; byte offset otherwise.
*/
static int bcma_sprom_onchip_offset(struct bcma_bus *bus)
{
struct bcma_device *cc = bus->drv_cc.core;
u32 offset;
/* verify OTP status */
if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0)
return 0;
/* obtain bit offset from otplayout register */
offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET);
return BCMA_CC_SPROM + (offset >> 3);
}
int bcma_sprom_get(struct bcma_bus *bus)
{
u16 offset;
u16 offset = BCMA_CC_SPROM;
u16 *sprom;
int err = 0;
if (!bus->drv_cc.core)
return -EOPNOTSUPP;
if (!bcma_is_sprom_available(bus)) {
if (!bcma_sprom_ext_available(bus)) {
/*
* Maybe there is no SPROM on the device?
* Now we ask the arch code if there is some sprom
* available for this device in some other storage.
* External SPROM takes precedence so check
* on-chip OTP only when no external SPROM
* is present.
*/
err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
return err;
if (bcma_sprom_onchip_available(bus)) {
/* determine offset */
offset = bcma_sprom_onchip_offset(bus);
}
if (!offset) {
/*
* Maybe there is no SPROM on the device?
* Now we ask the arch code if there is some sprom
* available for this device in some other storage.
*/
err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
return err;
}
}
sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
......@@ -341,11 +432,6 @@ int bcma_sprom_get(struct bcma_bus *bus)
if (bus->chipinfo.id == 0x4331)
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
* According to brcm80211 this applies to cards with PCIe rev >= 6
* TODO: understand this condition and use it */
offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
BCMA_CC_SPROM_PCIE6;
pr_debug("SPROM offset 0x%x\n", offset);
bcma_sprom_read(bus, offset, sprom);
......
......@@ -56,6 +56,9 @@
#define BCMA_CC_OTPS_HW_PROTECT 0x00000001
#define BCMA_CC_OTPS_SW_PROTECT 0x00000002
#define BCMA_CC_OTPS_CID_PROTECT 0x00000004
#define BCMA_CC_OTPS_GU_PROG_IND 0x00000F00 /* General Use programmed indication */
#define BCMA_CC_OTPS_GU_PROG_IND_SHIFT 8
#define BCMA_CC_OTPS_GU_PROG_HW 0x00000100 /* HW region programmed */
#define BCMA_CC_OTPC 0x0014 /* OTP control */
#define BCMA_CC_OTPC_RECWAIT 0xFF000000
#define BCMA_CC_OTPC_PROGWAIT 0x00FFFF00
......@@ -72,6 +75,8 @@
#define BCMA_CC_OTPP_READ 0x40000000
#define BCMA_CC_OTPP_START 0x80000000
#define BCMA_CC_OTPP_BUSY 0x80000000
#define BCMA_CC_OTPL 0x001C /* OTP layout */
#define BCMA_CC_OTPL_GURGN_OFFSET 0x00000FFF /* offset of general use region */
#define BCMA_CC_IRQSTAT 0x0020
#define BCMA_CC_IRQMASK 0x0024
#define BCMA_CC_IRQ_GPIO 0x00000001 /* gpio intr */
......@@ -79,6 +84,10 @@
#define BCMA_CC_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */
#define BCMA_CC_CHIPCTL 0x0028 /* Rev >= 11 only */
#define BCMA_CC_CHIPSTAT 0x002C /* Rev >= 11 only */
#define BCMA_CC_CHIPST_4313_SPROM_PRESENT 1
#define BCMA_CC_CHIPST_4313_OTP_PRESENT 2
#define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2
#define BCMA_CC_CHIPST_4331_OTP_PRESENT 4
#define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */
#define BCMA_CC_JCMD_START 0x80000000
#define BCMA_CC_JCMD_BUSY 0x80000000
......@@ -256,7 +265,6 @@
#define BCMA_CC_PLLCTL_ADDR 0x0660
#define BCMA_CC_PLLCTL_DATA 0x0664
#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */
#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */
/* Divider allocation in 4716/47162/5356 */
#define BCMA_CC_PMU5_MAINPLL_CPU 1
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部