From: "Arend van Spriel" <arend@broadcom.com>
To: linux-wireless@vger.kernel.org
Cc: "Arend van Spriel" <arend@broadcom.com>,
"Saul St. John" <saul.stjohn@gmail.com>,
"Rafal Milecki" <zajec5@gmail.com>,
"Hauke Mehrtens" <hauke@hauke-m.de>,
"Larry Finger" <Larry.Finger@lwfinger.net>
Subject: [RFC] bcma: add support for on-chip OTP memory used for SPROM storage
Date: Thu, 23 Feb 2012 22:52:57 +0100 [thread overview]
Message-ID: <1330033977-5741-1-git-send-email-arend@broadcom.com> (raw)
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 so gmane article [1].
[1] http://article.gmane.org/gmane.linux.kernel.wireless.general/85426
Cc: Saul St. John <saul.stjohn@gmail.com>
Cc: Rafal Milecki <zajec5@gmail.com>
Cc: Hauke Mehrtens <hauke@hauke-m.de>
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
Determining the offset for OTP sprom data turned out to be
easier as it boils down to reading a register. This change
collides with patch posted by Hauke:
bcma: add support for sprom not found on the device.
Now working on changes in brcmsmac to start using the sprom
data stored in struct bcma_bus. Feel free to comment this patch.
Gr. AvS
---
drivers/bcma/sprom.c | 118 ++++++++++++++++++++++++---
include/linux/bcma/bcma_driver_chipcommon.h | 9 ++
2 files changed, 115 insertions(+), 12 deletions(-)
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index ca77525..4dd537c 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -246,22 +246,121 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
SSB_SROM8_FEM_ANTSWLUT_SHIFT);
}
+/*
+ * Indicates the presence of external SPROM.
+ */
+static bool bcma_sprom_ext_available(struct bcma_bus *bus)
+{
+ u32 chip_status;
+ u32 srom_control;
+ u32 present_mask;
+
+ if (bus->drv_cc.core->id.rev >= 31) {
+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
+ return false;
+
+ srom_control = bcma_read32(bus->drv_cc.core,
+ BCMA_CC_SROM_CONTROL);
+ return !!(srom_control & BCMA_CC_SROM_CONTROL_PRESENT);
+ }
+
+ /* 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) == 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;
- u32 sromctrl;
int err = 0;
if (!bus->drv_cc.core)
return -EOPNOTSUPP;
- if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
- return -ENOENT;
+ if (!bcma_sprom_ext_available(bus)) {
+ /*
+ * External SPROM takes precedence so check
+ * on-chip OTP only when no external SPROM
+ * is present.
+ */
+ if (!bcma_sprom_onchip_available(bus))
+ return -ENOENT;
- if (bus->drv_cc.core->id.rev >= 32) {
- sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
- if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT))
+ /* determine offset */
+ offset = bcma_sprom_onchip_offset(bus);
+ if (!offset)
return -ENOENT;
}
@@ -273,11 +372,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);
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index e72938b..d963510 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -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
--
1.7.5.4
next reply other threads:[~2012-02-23 21:53 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-23 21:52 Arend van Spriel [this message]
2012-02-24 2:42 ` [RFC] bcma: add support for on-chip OTP memory used for SPROM storage Saul St. John
2012-02-24 9:55 ` Arend van Spriel
2012-02-24 7:52 ` Rafał Miłecki
2012-02-24 10:15 ` Arend van Spriel
2012-02-24 10:39 ` Arend van Spriel
2012-02-24 10:58 ` Johannes Berg
2012-02-24 11:18 ` Arend van Spriel
2012-02-25 12:52 ` Hauke Mehrtens
2012-02-25 14:29 ` Rafał Miłecki
2012-02-27 10:12 ` Arend van Spriel
2012-02-28 20:11 ` Hauke Mehrtens
2012-03-01 14:12 ` Arend van Spriel
2012-03-01 14:35 ` Hauke Mehrtens
2012-03-01 15:16 ` Arend van Spriel
2012-03-01 16:14 ` Hauke Mehrtens
2012-03-03 22:44 ` Rafał Miłecki
2012-03-05 9:16 ` Arend van Spriel
2012-03-06 8:52 ` Rafał Miłecki
2012-03-06 12:26 ` Arend van Spriel
2012-03-01 21:26 ` Arend van Spriel
2012-03-01 21:42 ` Larry Finger
2012-03-01 21:56 ` Hauke Mehrtens
2012-03-02 10:39 ` Arend van Spriel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1330033977-5741-1-git-send-email-arend@broadcom.com \
--to=arend@broadcom.com \
--cc=Larry.Finger@lwfinger.net \
--cc=hauke@hauke-m.de \
--cc=linux-wireless@vger.kernel.org \
--cc=saul.stjohn@gmail.com \
--cc=zajec5@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).