Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0da32ba4 authored by Arend van Spriel's avatar Arend van Spriel Committed by Kalle Valo
Browse files

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: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 38f29e1f
Loading
Loading
Loading
Loading
+214 −46
Original line number Diff line number Diff line
@@ -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 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;
		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 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:
+3 −1
Original line number Diff line number Diff line
@@ -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];
};