brcmfmac: extract ram size info from internal memory registers
authorArend van Spriel <arend@broadcom.com>
Wed, 11 Mar 2015 15:11:31 +0000 (16:11 +0100)
committerKalle Valo <kvalo@codeaurora.org>
Fri, 13 Mar 2015 14:10:33 +0000 (16:10 +0200)
Instead of hard-coded memory sizes it is possible to obtain that
information from the internal memory registers.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/brcm80211/brcmfmac/chip.c
drivers/net/wireless/brcm80211/brcmfmac/chip.h

index c11137e..7341725 100644 (file)
 #define BCM4329_CORE_SOCRAM_BASE       0x18003000
 /* ARM Cortex M3 core, ID 0x82a */
 #define BCM4329_CORE_ARM_BASE          0x18002000
-#define BCM4329_RAMSIZE                        0x48000
-/* bcm43143 */
-#define BCM43143_RAMSIZE               0x70000
 
 #define CORE_SB(base, field) \
                (base + SBCONFIGOFF + offsetof(struct sbconfig, field))
@@ -150,6 +147,78 @@ struct sbconfig {
        u32 sbidhigh;   /* identification */
 };
 
+/* bankidx and bankinfo reg defines corerev >= 8 */
+#define SOCRAM_BANKINFO_RETNTRAM_MASK  0x00010000
+#define SOCRAM_BANKINFO_SZMASK         0x0000007f
+#define SOCRAM_BANKIDX_ROM_MASK                0x00000100
+
+#define SOCRAM_BANKIDX_MEMTYPE_SHIFT   8
+/* socram bankinfo memtype */
+#define SOCRAM_MEMTYPE_RAM             0
+#define SOCRAM_MEMTYPE_R0M             1
+#define SOCRAM_MEMTYPE_DEVRAM          2
+
+#define SOCRAM_BANKINFO_SZBASE         8192
+#define SRCI_LSS_MASK          0x00f00000
+#define SRCI_LSS_SHIFT         20
+#define        SRCI_SRNB_MASK          0xf0
+#define        SRCI_SRNB_SHIFT         4
+#define        SRCI_SRBSZ_MASK         0xf
+#define        SRCI_SRBSZ_SHIFT        0
+#define SR_BSZ_BASE            14
+
+struct sbsocramregs {
+       u32 coreinfo;
+       u32 bwalloc;
+       u32 extracoreinfo;
+       u32 biststat;
+       u32 bankidx;
+       u32 standbyctrl;
+
+       u32 errlogstatus;       /* rev 6 */
+       u32 errlogaddr; /* rev 6 */
+       /* used for patching rev 3 & 5 */
+       u32 cambankidx;
+       u32 cambankstandbyctrl;
+       u32 cambankpatchctrl;
+       u32 cambankpatchtblbaseaddr;
+       u32 cambankcmdreg;
+       u32 cambankdatareg;
+       u32 cambankmaskreg;
+       u32 PAD[1];
+       u32 bankinfo;   /* corev 8 */
+       u32 bankpda;
+       u32 PAD[14];
+       u32 extmemconfig;
+       u32 extmemparitycsr;
+       u32 extmemparityerrdata;
+       u32 extmemparityerrcnt;
+       u32 extmemwrctrlandsize;
+       u32 PAD[84];
+       u32 workaround;
+       u32 pwrctl;             /* corerev >= 2 */
+       u32 PAD[133];
+       u32 sr_control;     /* corerev >= 15 */
+       u32 sr_status;      /* corerev >= 15 */
+       u32 sr_address;     /* corerev >= 15 */
+       u32 sr_data;        /* corerev >= 15 */
+};
+
+#define SOCRAMREGOFFS(_f)      offsetof(struct sbsocramregs, _f)
+
+#define ARMCR4_CAP             (0x04)
+#define ARMCR4_BANKIDX         (0x40)
+#define ARMCR4_BANKINFO                (0x44)
+#define ARMCR4_BANKPDA         (0x4C)
+
+#define        ARMCR4_TCBBNB_MASK      0xf0
+#define        ARMCR4_TCBBNB_SHIFT     4
+#define        ARMCR4_TCBANB_MASK      0xf
+#define        ARMCR4_TCBANB_SHIFT     0
+
+#define        ARMCR4_BSZ_MASK         0x3f
+#define        ARMCR4_BSZ_MULT         8192
+
 struct brcmf_core_priv {
        struct brcmf_core pub;
        u32 wrapbase;
@@ -443,10 +512,6 @@ static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
                        break;
                case BCMA_CORE_ARM_CR4:
                        cpu_found = true;
-                       if (ci->pub.rambase == 0) {
-                               brcmf_err("RAM base not provided with ARM CR4 core\n");
-                               return -ENOMEM;
-                       }
                        break;
                default:
                        break;
@@ -462,60 +527,160 @@ static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
                brcmf_err("RAM core not provided with ARM CM3 core\n");
                return -ENODEV;
        }
-       if (!ci->pub.ramsize) {
-               brcmf_err("RAM size is undetermined\n");
-               return -ENOMEM;
-       }
        return 0;
 }
 
-static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
+static u32 brcmf_chip_core_read32(struct brcmf_core_priv *core, u16 reg)
 {
-       switch (ci->pub.chip) {
-       case BRCM_CC_4329_CHIP_ID:
-               ci->pub.ramsize = BCM4329_RAMSIZE;
-               break;
-       case BRCM_CC_43143_CHIP_ID:
-               ci->pub.ramsize = BCM43143_RAMSIZE;
-               break;
-       case BRCM_CC_43241_CHIP_ID:
-               ci->pub.ramsize = 0x90000;
-               break;
-       case BRCM_CC_4330_CHIP_ID:
-               ci->pub.ramsize = 0x48000;
-               break;
+       return core->chip->ops->read32(core->chip->ctx, core->pub.base + reg);
+}
+
+static void brcmf_chip_core_write32(struct brcmf_core_priv *core,
+                                   u16 reg, u32 val)
+{
+       core->chip->ops->write32(core->chip->ctx, core->pub.base + reg, val);
+}
+
+static bool brcmf_chip_socram_banksize(struct brcmf_core_priv *core, u8 idx,
+                                      u32 *banksize)
+{
+       u32 bankinfo;
+       u32 bankidx = (SOCRAM_MEMTYPE_RAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
+
+       bankidx |= idx;
+       brcmf_chip_core_write32(core, SOCRAMREGOFFS(bankidx), bankidx);
+       bankinfo = brcmf_chip_core_read32(core, SOCRAMREGOFFS(bankinfo));
+       *banksize = (bankinfo & SOCRAM_BANKINFO_SZMASK) + 1;
+       *banksize *= SOCRAM_BANKINFO_SZBASE;
+       return !!(bankinfo & SOCRAM_BANKINFO_RETNTRAM_MASK);
+}
+
+static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize,
+                                     u32 *srsize)
+{
+       u32 coreinfo;
+       uint nb, banksize, lss;
+       bool retent;
+       int i;
+
+       *ramsize = 0;
+       *srsize = 0;
+
+       if (WARN_ON(sr->pub.rev < 4))
+               return;
+
+       if (!brcmf_chip_iscoreup(&sr->pub))
+               brcmf_chip_resetcore(&sr->pub, 0, 0, 0);
+
+       /* Get info for determining size */
+       coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo));
+       nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+
+       if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) {
+               banksize = (coreinfo & SRCI_SRBSZ_MASK);
+               lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
+               if (lss != 0)
+                       nb--;
+               *ramsize = nb * (1 << (banksize + SR_BSZ_BASE));
+               if (lss != 0)
+                       *ramsize += (1 << ((lss - 1) + SR_BSZ_BASE));
+       } else {
+               nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+               for (i = 0; i < nb; i++) {
+                       retent = brcmf_chip_socram_banksize(sr, i, &banksize);
+                       *ramsize += banksize;
+                       if (retent)
+                               *srsize += banksize;
+               }
+       }
+
+       /* hardcoded save&restore memory sizes */
+       switch (sr->chip->pub.chip) {
        case BRCM_CC_4334_CHIP_ID:
-       case BRCM_CC_43340_CHIP_ID:
-               ci->pub.ramsize = 0x80000;
-               break;
-       case BRCM_CC_4335_CHIP_ID:
-               ci->pub.ramsize = 0xc0000;
-               ci->pub.rambase = 0x180000;
+               if (sr->chip->pub.chiprev < 2)
+                       *srsize = (32 * 1024);
                break;
-       case BRCM_CC_43362_CHIP_ID:
-               ci->pub.ramsize = 0x3c000;
+       default:
                break;
+       }
+}
+
+/** Return the TCM-RAM size of the ARMCR4 core. */
+static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)
+{
+       u32 corecap;
+       u32 memsize = 0;
+       u32 nab;
+       u32 nbb;
+       u32 totb;
+       u32 bxinfo;
+       u32 idx;
+
+       corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP);
+
+       nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;
+       nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;
+       totb = nab + nbb;
+
+       for (idx = 0; idx < totb; idx++) {
+               brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx);
+               bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO);
+               memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT;
+       }
+
+       return memsize;
+}
+
+static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
+{
+       switch (ci->pub.chip) {
        case BRCM_CC_4345_CHIP_ID:
-               ci->pub.ramsize = 0xc8000;
-               ci->pub.rambase = 0x198000;
-               break;
+               return 0x198000;
+       case BRCM_CC_4335_CHIP_ID:
        case BRCM_CC_4339_CHIP_ID:
        case BRCM_CC_4354_CHIP_ID:
        case BRCM_CC_4356_CHIP_ID:
        case BRCM_CC_43567_CHIP_ID:
        case BRCM_CC_43569_CHIP_ID:
        case BRCM_CC_43570_CHIP_ID:
-               ci->pub.ramsize = 0xc0000;
-               ci->pub.rambase = 0x180000;
-               break;
        case BRCM_CC_43602_CHIP_ID:
-               ci->pub.ramsize = 0xf0000;
-               ci->pub.rambase = 0x180000;
-               break;
+               return 0x180000;
        default:
                brcmf_err("unknown chip: %s\n", ci->pub.name);
                break;
        }
+       return 0;
+}
+
+static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
+{
+       struct brcmf_core_priv *mem_core;
+       struct brcmf_core *mem;
+
+       mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4);
+       if (mem) {
+               mem_core = container_of(mem, struct brcmf_core_priv, pub);
+               ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core);
+               ci->pub.rambase = brcmf_chip_tcm_rambase(ci);
+               if (!ci->pub.rambase) {
+                       brcmf_err("RAM base not provided with ARM CR4 core\n");
+                       return -EINVAL;
+               }
+       } else {
+               mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_INTERNAL_MEM);
+               mem_core = container_of(mem, struct brcmf_core_priv, pub);
+               brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize,
+                                         &ci->pub.srsize);
+       }
+       brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n",
+                 ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize,
+                 ci->pub.srsize, ci->pub.srsize);
+
+       if (!ci->pub.ramsize) {
+               brcmf_err("RAM size is undetermined\n");
+               return -ENOMEM;
+       }
+       return 0;
 }
 
 static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr,
@@ -668,6 +833,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
        struct brcmf_core *core;
        u32 regdata;
        u32 socitype;
+       int ret;
 
        /* Get CC core rev
         * Chipid is assume to be at offset 0 from SI_ENUM_BASE
@@ -720,9 +886,13 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
                return -ENODEV;
        }
 
-       brcmf_chip_get_raminfo(ci);
+       ret = brcmf_chip_cores_check(ci);
+       if (ret)
+               return ret;
 
-       return brcmf_chip_cores_check(ci);
+       /* assure chip is passive for core access */
+       brcmf_chip_set_passive(&ci->pub);
+       return brcmf_chip_get_raminfo(ci);
 }
 
 static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)
@@ -827,8 +997,6 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx,
        if (err < 0)
                goto fail;
 
-       /* assure chip is passive for download */
-       brcmf_chip_set_passive(&chip->pub);
        return &chip->pub;
 
 fail:
index 7b7b629..60dcb38 100644 (file)
@@ -30,7 +30,8 @@
  * @pmucaps: PMU capabilities.
  * @pmurev: PMU revision.
  * @rambase: RAM base address (only applicable for ARM CR4 chips).
- * @ramsize: amount of RAM on chip.
+ * @ramsize: amount of RAM on chip including retention.
+ * @srsize: amount of retention RAM on chip.
  * @name: string representation of the chip identifier.
  */
 struct brcmf_chip {
@@ -41,6 +42,7 @@ struct brcmf_chip {
        u32 pmurev;
        u32 rambase;
        u32 ramsize;
+       u32 srsize;
        char name[8];
 };