From: Arend van Spriel Date: Wed, 11 Mar 2015 16:11:31 +0100 Subject: [PATCH] brcmfmac: extract ram size info from internal memory registers Instead of hard-coded memory sizes it is possible to obtain that information from the internal memory registers. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c @@ -100,9 +100,6 @@ #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 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_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; + if (sr->chip->pub.chiprev < 2) + *srsize = (32 * 1024); break; - case BRCM_CC_4335_CHIP_ID: - ci->pub.ramsize = 0xc0000; - ci->pub.rambase = 0x180000; - 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 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 return -ENODEV; } - brcmf_chip_get_raminfo(ci); - - return brcmf_chip_cores_check(ci); + ret = brcmf_chip_cores_check(ci); + if (ret) + return ret; + + /* 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(voi if (err < 0) goto fail; - /* assure chip is passive for download */ - brcmf_chip_set_passive(&chip->pub); return &chip->pub; fail: --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h @@ -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]; };