linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] bcma: return error in bcma_sprom_get() when fallback fails
@ 2012-03-06 14:50 Arend van Spriel
  2012-03-06 14:50 ` [PATCH v2 2/2] bcma: add support for on-chip OTP memory used for SPROM storage Arend van Spriel
  2012-03-06 23:07 ` [PATCH v2 1/2] bcma: return error in bcma_sprom_get() when fallback fails Hauke Mehrtens
  0 siblings, 2 replies; 3+ messages in thread
From: Arend van Spriel @ 2012-03-06 14:50 UTC (permalink / raw)
  To: John W. Linville
  Cc: Linux Wireless List, Arend van Spriel, Rafal Milecki,
	Hauke Mehrtens

When not SPROM is available a fallback mechanism is used. However,
when that fails the code currently continues. This patch assures
that the bcma_sprom_get() function aborts when that happens.

Cc: Rafal Milecki <zajec5@gmail.com>
Cc: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/bcma/sprom.c |   27 +++++++++++++++++----------
 1 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index 916ae25..fba8066 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -49,10 +49,23 @@ int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus
 static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
 					 struct ssb_sprom *out)
 {
-	if (!get_fallback_sprom)
-		return -ENOENT;
+	int err;
 
-	return get_fallback_sprom(bus, out);
+	if (!get_fallback_sprom) {
+		err = -ENOENT;
+		goto fail;
+	}
+
+	err = get_fallback_sprom(bus, out);
+	if (err)
+		goto fail;
+
+	pr_debug("Using SPROM revision %d provided by"
+		 " platform.\n", bus->sprom.revision);
+	return 0;
+fail:
+	pr_warn("Using fallback SPROM failed (err %d)\n", err);
+	return err;
 }
 
 /**************************************************
@@ -317,13 +330,7 @@ int bcma_sprom_get(struct bcma_bus *bus)
 		 * available for this device in some other storage.
 		 */
 		err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
-		if (err) {
-			pr_warn("Using fallback SPROM failed (err %d)\n", err);
-		} else {
-			pr_debug("Using SPROM revision %d provided by"
-				 " platform.\n", bus->sprom.revision);
-			return 0;
-		}
+		return err;
 	}
 
 	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v2 2/2] bcma: add support for on-chip OTP memory used for SPROM storage
  2012-03-06 14:50 [PATCH v2 1/2] bcma: return error in bcma_sprom_get() when fallback fails Arend van Spriel
@ 2012-03-06 14:50 ` Arend van Spriel
  2012-03-06 23:07 ` [PATCH v2 1/2] bcma: return error in bcma_sprom_get() when fallback fails Hauke Mehrtens
  1 sibling, 0 replies; 3+ messages in thread
From: Arend van Spriel @ 2012-03-06 14:50 UTC (permalink / raw)
  To: John W. Linville; +Cc: Linux Wireless List, Arend van Spriel, Larry Finger

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/85426

Tested-by: Saul St. John <saul.stjohn@gmail.com>
Tested-by: Rafal Milecki <zajec5@gmail.com>
Tested-by: Hauke Mehrtens <hauke@hauke-m.de>
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/bcma/sprom.c                        |  126 ++++++++++++++++++++++----
 include/linux/bcma/bcma_driver_chipcommon.h |   10 ++-
 2 files changed, 115 insertions(+), 21 deletions(-)

diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index fba8066..cdcf75c 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -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);
 
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index e72938b..8bbfe31 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
@@ -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
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2 1/2] bcma: return error in bcma_sprom_get() when fallback fails
  2012-03-06 14:50 [PATCH v2 1/2] bcma: return error in bcma_sprom_get() when fallback fails Arend van Spriel
  2012-03-06 14:50 ` [PATCH v2 2/2] bcma: add support for on-chip OTP memory used for SPROM storage Arend van Spriel
@ 2012-03-06 23:07 ` Hauke Mehrtens
  1 sibling, 0 replies; 3+ messages in thread
From: Hauke Mehrtens @ 2012-03-06 23:07 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: John W. Linville, Linux Wireless List, Rafal Milecki

On 03/06/2012 03:50 PM, Arend van Spriel wrote:
> When not SPROM is available a fallback mechanism is used. However,
> when that fails the code currently continues. This patch assures
> that the bcma_sprom_get() function aborts when that happens.
> 
> Cc: Rafal Milecki <zajec5@gmail.com>
> Cc: Hauke Mehrtens <hauke@hauke-m.de>
> Signed-off-by: Arend van Spriel <arend@broadcom.com>
Acked-by: Hauke Mehrtens <hauke@hauke-m.de>
> ---
>  drivers/bcma/sprom.c |   27 +++++++++++++++++----------
>  1 files changed, 17 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
> index 916ae25..fba8066 100644
> --- a/drivers/bcma/sprom.c
> +++ b/drivers/bcma/sprom.c
> @@ -49,10 +49,23 @@ int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus
>  static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
>  					 struct ssb_sprom *out)
>  {
> -	if (!get_fallback_sprom)
> -		return -ENOENT;
> +	int err;
>  
> -	return get_fallback_sprom(bus, out);
> +	if (!get_fallback_sprom) {
> +		err = -ENOENT;
> +		goto fail;
> +	}
> +
> +	err = get_fallback_sprom(bus, out);
> +	if (err)
> +		goto fail;
> +
> +	pr_debug("Using SPROM revision %d provided by"
> +		 " platform.\n", bus->sprom.revision);
> +	return 0;
> +fail:
> +	pr_warn("Using fallback SPROM failed (err %d)\n", err);
> +	return err;
>  }
>  
>  /**************************************************
> @@ -317,13 +330,7 @@ int bcma_sprom_get(struct bcma_bus *bus)
>  		 * available for this device in some other storage.
>  		 */
>  		err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
> -		if (err) {
> -			pr_warn("Using fallback SPROM failed (err %d)\n", err);
> -		} else {
> -			pr_debug("Using SPROM revision %d provided by"
> -				 " platform.\n", bus->sprom.revision);
> -			return 0;
> -		}
> +		return err;
>  	}
>  
>  	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-03-06 23:07 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-06 14:50 [PATCH v2 1/2] bcma: return error in bcma_sprom_get() when fallback fails Arend van Spriel
2012-03-06 14:50 ` [PATCH v2 2/2] bcma: add support for on-chip OTP memory used for SPROM storage Arend van Spriel
2012-03-06 23:07 ` [PATCH v2 1/2] bcma: return error in bcma_sprom_get() when fallback fails Hauke Mehrtens

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).