Commit 4aa2c47c authored by Arend van Spriel's avatar Arend van Spriel Committed by John W. Linville
Browse files

brcmfmac: get chip core information from the device



Instead of instantiating core info structs based upon the
chip identifier it is now done parsing information provided
on the device.

Reviewed-by: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: default avatarDaniel (Deognyoun) Kim <dekim@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c5a9f3c1
Loading
Loading
Loading
Loading
+203 −104
Original line number Diff line number Diff line
@@ -32,6 +32,55 @@
#define SOCI_SB		0
#define SOCI_AI		1

/* PL-368 DMP definitions */
#define DMP_DESC_TYPE_MSK	0x0000000F
#define  DMP_DESC_EMPTY		0x00000000
#define  DMP_DESC_VALID		0x00000001
#define  DMP_DESC_COMPONENT	0x00000001
#define  DMP_DESC_MASTER_PORT	0x00000003
#define  DMP_DESC_ADDRESS	0x00000005
#define  DMP_DESC_ADDRSIZE_GT32	0x00000008
#define  DMP_DESC_EOT		0x0000000F

#define DMP_COMP_DESIGNER	0xFFF00000
#define DMP_COMP_DESIGNER_S	20
#define DMP_COMP_PARTNUM	0x000FFF00
#define DMP_COMP_PARTNUM_S	8
#define DMP_COMP_CLASS		0x000000F0
#define DMP_COMP_CLASS_S	4
#define DMP_COMP_REVISION	0xFF000000
#define DMP_COMP_REVISION_S	24
#define DMP_COMP_NUM_SWRAP	0x00F80000
#define DMP_COMP_NUM_SWRAP_S	19
#define DMP_COMP_NUM_MWRAP	0x0007C000
#define DMP_COMP_NUM_MWRAP_S	14
#define DMP_COMP_NUM_SPORT	0x00003E00
#define DMP_COMP_NUM_SPORT_S	9
#define DMP_COMP_NUM_MPORT	0x000001F0
#define DMP_COMP_NUM_MPORT_S	4

#define DMP_MASTER_PORT_UID	0x0000FF00
#define DMP_MASTER_PORT_UID_S	8
#define DMP_MASTER_PORT_NUM	0x000000F0
#define DMP_MASTER_PORT_NUM_S	4

#define DMP_SLAVE_ADDR_BASE	0xFFFFF000
#define DMP_SLAVE_ADDR_BASE_S	12
#define DMP_SLAVE_PORT_NUM	0x00000F00
#define DMP_SLAVE_PORT_NUM_S	8
#define DMP_SLAVE_TYPE		0x000000C0
#define DMP_SLAVE_TYPE_S	6
#define  DMP_SLAVE_TYPE_SLAVE	0
#define  DMP_SLAVE_TYPE_BRIDGE	1
#define  DMP_SLAVE_TYPE_SWRAP	2
#define  DMP_SLAVE_TYPE_MWRAP	3
#define DMP_SLAVE_SIZE_TYPE	0x00000030
#define DMP_SLAVE_SIZE_TYPE_S	4
#define  DMP_SLAVE_SIZE_4K	0
#define  DMP_SLAVE_SIZE_8K	1
#define  DMP_SLAVE_SIZE_16K	2
#define  DMP_SLAVE_SIZE_DESC	3

/* EROM CompIdentB */
#define CIB_REV_MASK		0xff000000
#define CIB_REV_SHIFT		24
@@ -393,8 +442,9 @@ static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
	int idx = 1;

	list_for_each_entry(core, &ci->cores, list) {
		brcmf_dbg(INFO, " [%-2d] core 0x%x rev %-2d base 0x%08x\n",
			  idx++, core->pub.id, core->pub.rev, core->pub.base);
		brcmf_dbg(INFO, " [%-2d] core 0x%x:%-2d base 0x%08x wrap 0x%08x\n",
			  idx++, core->pub.id, core->pub.rev, core->pub.base,
			  core->wrapbase);

		switch (core->pub.id) {
		case BCMA_CORE_ARM_CM3:
@@ -463,6 +513,151 @@ static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
	}
}

static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr,
				   u8 *type)
{
	u32 val;

	/* read next descriptor */
	val = ci->ops->read32(ci->ctx, *eromaddr);
	*eromaddr += 4;

	if (!type)
		return val;

	/* determine descriptor type */
	*type = (val & DMP_DESC_TYPE_MSK);
	if ((*type & ~DMP_DESC_ADDRSIZE_GT32) == DMP_DESC_ADDRESS)
		*type = DMP_DESC_ADDRESS;

	return val;
}

static int brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv *ci, u32 *eromaddr,
				      u32 *regbase, u32 *wrapbase)
{
	u8 desc;
	u32 val;
	u8 mpnum = 0;
	u8 stype, sztype, wraptype;

	*regbase = 0;
	*wrapbase = 0;

	val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
	if (desc == DMP_DESC_MASTER_PORT) {
		mpnum = (val & DMP_MASTER_PORT_NUM) >> DMP_MASTER_PORT_NUM_S;
		wraptype = DMP_SLAVE_TYPE_MWRAP;
	} else if (desc == DMP_DESC_ADDRESS) {
		/* revert erom address */
		*eromaddr -= 4;
		wraptype = DMP_SLAVE_TYPE_SWRAP;
	} else {
		*eromaddr -= 4;
		return -EILSEQ;
	}

	do {
		/* locate address descriptor */
		do {
			val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
			/* unexpected table end */
			if (desc == DMP_DESC_EOT) {
				*eromaddr -= 4;
				return -EFAULT;
			}
		} while (desc != DMP_DESC_ADDRESS);

		/* skip upper 32-bit address descriptor */
		if (val & DMP_DESC_ADDRSIZE_GT32)
			brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);

		sztype = (val & DMP_SLAVE_SIZE_TYPE) >> DMP_SLAVE_SIZE_TYPE_S;

		/* next size descriptor can be skipped */
		if (sztype == DMP_SLAVE_SIZE_DESC) {
			val = brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
			/* skip upper size descriptor if present */
			if (val & DMP_DESC_ADDRSIZE_GT32)
				brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
		}

		/* only look for 4K register regions */
		if (sztype != DMP_SLAVE_SIZE_4K)
			continue;

		stype = (val & DMP_SLAVE_TYPE) >> DMP_SLAVE_TYPE_S;

		/* only regular slave and wrapper */
		if (*regbase == 0 && stype == DMP_SLAVE_TYPE_SLAVE)
			*regbase = val & DMP_SLAVE_ADDR_BASE;
		if (*wrapbase == 0 && stype == wraptype)
			*wrapbase = val & DMP_SLAVE_ADDR_BASE;
	} while (*regbase == 0 || *wrapbase == 0);

	return 0;
}

static
int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci)
{
	struct brcmf_core *core;
	u32 eromaddr;
	u8 desc_type = 0;
	u32 val;
	u16 id;
	u8 nmp, nsp, nmw, nsw, rev;
	u32 base, wrap;
	int err;

	eromaddr = ci->ops->read32(ci->ctx, CORE_CC_REG(SI_ENUM_BASE, eromptr));

	while (desc_type != DMP_DESC_EOT) {
		val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);
		if (!(val & DMP_DESC_VALID))
			continue;

		if (desc_type == DMP_DESC_EMPTY)
			continue;

		/* need a component descriptor */
		if (desc_type != DMP_DESC_COMPONENT)
			continue;

		id = (val & DMP_COMP_PARTNUM) >> DMP_COMP_PARTNUM_S;

		/* next descriptor must be component as well */
		val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);
		if (WARN_ON((val & DMP_DESC_TYPE_MSK) != DMP_DESC_COMPONENT))
			return -EFAULT;

		/* only look at cores with master port(s) */
		nmp = (val & DMP_COMP_NUM_MPORT) >> DMP_COMP_NUM_MPORT_S;
		nsp = (val & DMP_COMP_NUM_SPORT) >> DMP_COMP_NUM_SPORT_S;
		nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S;
		nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S;
		rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S;

		/* need core with ports */
		if (nmw + nsw == 0)
			continue;

		/* try to obtain register address info */
		err = brcmf_chip_dmp_get_regaddr(ci, &eromaddr, &base, &wrap);
		if (err)
			continue;

		/* finally a core to be added */
		core = brcmf_chip_add_core(ci, id, base, wrap);
		if (IS_ERR(core))
			return PTR_ERR(core);

		core->rev = rev;
	}

	return 0;
}

static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
{
	struct brcmf_core *core;
@@ -505,114 +700,21 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
		core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
					   BCM4329_CORE_ARM_BASE, 0);
		brcmf_chip_sb_corerev(ci, core);

		core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0);
		brcmf_chip_sb_corerev(ci, core);
	} else if (socitype == SOCI_AI) {
		ci->iscoreup = brcmf_chip_ai_iscoreup;
		ci->coredisable = brcmf_chip_ai_coredisable;
		ci->resetcore = brcmf_chip_ai_resetcore;

		core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON,
					   SI_ENUM_BASE,
					   SI_ENUM_BASE + 0x100000);

		/* Address of cores for new chips should be added here */
		switch (ci->pub.chip) {
		case BCM43143_CHIP_ID:
			core->rev = 43;
			core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
						   BCM43143_CORE_BUS_BASE,
						   BCM43143_CORE_BUS_BASE +
						   0x100000);
			core->rev = 24;
			core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
						   BCM43143_CORE_SOCRAM_BASE,
						   BCM43143_CORE_SOCRAM_BASE +
						   0x100000);
			core->rev = 20;
			core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
						   BCM43143_CORE_ARM_BASE,
						   BCM43143_CORE_ARM_BASE +
						   0x100000);
			core->rev = 7;
			break;
		case BCM43241_CHIP_ID:
			core->rev = 42;
			core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
						   0x18002000, 0x18102000);
			core->rev = 14;
			core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
						   0x18004000, 0x18104000);
			core->rev = 20;
			core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
						   0x18003000, 0x18103000);
			core->rev = 7;
			break;
		case BCM4330_CHIP_ID:
			core->rev = 39;
			core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
						   0x18002000, 0x18102000);
			core->rev = 7;
			core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
						   0x18004000, 0x18104000);
			core->rev = 13;
			core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
						   0x18003000, 0x18103000);
			core->rev = 3;
			break;
		case BCM4334_CHIP_ID:
			core->rev = 41;
			core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
						   0x18002000, 0x18102000);
			core->rev = 13;
			core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
						   0x18004000, 0x18104000);
			core->rev = 19;
			core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
						   0x18003000, 0x18103000);
			core->rev = 7;
			break;
		case BCM4335_CHIP_ID:
			core->rev = 43;
			core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
						   0x18005000, 0x18105000);
			core->rev = 15;
			core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CR4,
						   0x18002000, 0x18102000);
			core->rev = 1;
			break;
		case BCM43362_CHIP_ID:
			core->rev = 39;
			core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
						   0x18002000, 0x18102000);
			core->rev = 10;
			core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
						   0x18004000, 0x18104000);
			core->rev = 8;
			core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
						   0x18003000, 0x18103000);
			core->rev = 3;
			break;
		case BCM4339_CHIP_ID:
			core->rev = 46;
			core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
						   0x18005000, 0x18105000);
			core->rev = 21;
			core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CR4,
						   0x18002000, 0x18102000);
			core->rev = 4;
			break;
		default:
			brcmf_err("AXI chip is not supported\n");
			return -ENODEV;
		}
		brcmf_chip_dmp_erom_scan(ci);
	} else {
		brcmf_err("chip backplane type %u is not supported\n",
			  socitype);
		return -ENODEV;
	}

	/* add 802.11 core for all chips on same backplane address */
	core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0x18101000);

	brcmf_chip_get_raminfo(ci);

	return brcmf_chip_cores_check(ci);
@@ -652,7 +754,6 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip)
{
	struct brcmf_chip *pub;
	struct brcmf_core_priv *cc;
	struct brcmf_core_priv *bus;
	u32 base;
	u32 val;
	int ret = 0;
@@ -673,10 +774,8 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip)
		pub->pmucaps = val;
	}

	bus = list_next_entry(cc, list);

	brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
		  cc->pub.rev, pub->pmurev, bus->pub.rev, bus->pub.id);
	brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, pmucaps=0x%x\n",
		  cc->pub.rev, pub->pmurev, pub->pmucaps);

	/* execute bus core specific setup */
	if (chip->ops->setup)