From c3a0d829681948746f2838eef80621e19a56dc3d Mon Sep 17 00:00:00 2001
From: Wright Feng <wright.feng@infineon.com>
Date: Tue, 19 Apr 2022 05:51:42 +0000
Subject: [PATCH 150/296] brcmfmac: get chip info from SDIOD if chip common
 space is protected


---
 .../broadcom/brcm80211/brcmfmac/chip.c        | 25 ++++++--
 .../broadcom/brcm80211/brcmfmac/chip.h        | 11 +++-
 .../broadcom/brcm80211/brcmfmac/pcie.c        |  7 ++-
 .../broadcom/brcm80211/brcmfmac/sdio.c        | 62 ++++++++++++++++---
 .../broadcom/brcm80211/brcmfmac/sdio.h        |  7 ++-
 5 files changed, 94 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
index 1ee07c25c844..71addd8957ba 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -976,7 +976,10 @@ int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci)
 	u32 base, wrap;
 	int err;
 
-	eromaddr = ci->ops->read32(ci->ctx,
+	if (ci->pub.ccsec)
+		eromaddr = ci->pub.ccsec->erombase;
+	else
+		eromaddr = ci->ops->read32(ci->ctx,
 				   CORE_CC_REG(ci->pub.enum_base, eromptr));
 
 	while (desc_type != DMP_DESC_EOT) {
@@ -1178,11 +1181,15 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
 	const u32 READ_FAILED = 0xFFFFFFFF;
 
 	/* Get CC core rev
-	 * Chipid is assume to be at offset 0 from SI_ENUM_BASE
+	 * Chipid is in bus core if CC space is protected or
+	 * it is assume to be at offset 0 from SI_ENUM_BASE
 	 * For different chiptypes or old sdio hosts w/o chipcommon,
 	 * other ways of recognition should be added here.
 	 */
-	regdata = ci->ops->read32(ci->ctx,
+	if (ci->pub.ccsec)
+		regdata = ci->pub.ccsec->chipid;
+	else
+		regdata = ci->ops->read32(ci->ctx,
 				  CORE_CC_REG(ci->pub.enum_base, chipid));
 	if (regdata == READ_FAILED) {
 		brcmf_err("MMIO read failed: 0x%08x\n", regdata);
@@ -1292,6 +1299,9 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip)
 	u32 val;
 	int ret = 0;
 
+	if (chip->pub.ccsec)
+		return 0;
+
 	pub = &chip->pub;
 	cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);
 	base = cc->pub.base;
@@ -1327,6 +1337,7 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,
 {
 	struct brcmf_chip_priv *chip;
 	struct brcmf_blhs *blhs;
+	struct brcmf_ccsec *ccsec;
 	int err = 0;
 
 	if (WARN_ON(!ops->read32))
@@ -1355,8 +1366,9 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,
 		goto fail;
 
 	blhs = NULL;
-	if (chip->ops->blhs_attach) {
-		err = chip->ops->blhs_attach(chip->ctx, &blhs,
+	ccsec = NULL;
+	if (chip->ops->sec_attach) {
+		err = chip->ops->sec_attach(chip->ctx, &blhs, &ccsec,
 					     BRCMF_BLHS_D2H_READY,
 					     BRCMF_BLHS_D2H_READY_TIMEOUT,
 					     BRCMF_BLHS_POLL_INTERVAL);
@@ -1373,6 +1385,7 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,
 		}
 	}
 	chip->pub.blhs = blhs;
+	chip->pub.ccsec = ccsec;
 
 	err = brcmf_chip_recognition(chip);
 	if (err < 0)
@@ -1400,7 +1413,9 @@ void brcmf_chip_detach(struct brcmf_chip *pub)
 		list_del(&core->list);
 		kfree(core);
 	}
+
 	kfree(pub->blhs);
+	kfree(pub->ccsec);
 	kfree(chip);
 }
 
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
index 4629201de715..3d1bf44f2d14 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
@@ -44,6 +44,7 @@ struct brcmf_chip {
 	u32 srsize;
 	char name[12];
 	struct brcmf_blhs *blhs;
+	struct brcmf_ccsec *ccsec;
 };
 
 /**
@@ -77,8 +78,8 @@ struct brcmf_buscore_ops {
 	int (*reset)(void *ctx, struct brcmf_chip *chip);
 	int (*setup)(void *ctx, struct brcmf_chip *chip);
 	void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
-	int (*blhs_attach)(void *ctx, struct brcmf_blhs **blhs, u32 flag,
-			   uint timeout, uint interval);
+	int (*sec_attach)(void *ctx, struct brcmf_blhs **blhs, struct brcmf_ccsec **ccsec,
+			  u32 flag, uint timeout, uint interval);
 };
 
 /**
@@ -108,6 +109,12 @@ struct brcmf_blhs {
 	void (*write)(void *ctx, u32 addr, u32 value);
 };
 
+struct brcmf_ccsec {
+	u32	bus_corebase;
+	u32 erombase;
+	u32 chipid;
+};
+
 int brcmf_chip_get_raminfo(struct brcmf_chip *pub);
 struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,
 				     const struct brcmf_buscore_ops *ops);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 032593d99fec..1a1726d63528 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -2399,8 +2399,9 @@ static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,
 }
 
 
-static int brcmf_pcie_buscore_blhs_attach(void *ctx, struct brcmf_blhs **blhs,
-					  u32 flag, uint timeout, uint interval)
+static int
+brcmf_pcie_buscore_sec_attach(void *ctx, struct brcmf_blhs **blhs, struct brcmf_ccsec **ccsec,
+			      u32 flag, uint timeout, uint interval)
 {
 	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
 	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
@@ -2455,7 +2456,7 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
 	.activate = brcmf_pcie_buscore_activate,
 	.read32 = brcmf_pcie_buscore_read32,
 	.write32 = brcmf_pcie_buscore_write32,
-	.blhs_attach = brcmf_pcie_buscore_blhs_attach,
+	.sec_attach = brcmf_pcie_buscore_sec_attach,
 };
 
 #define BRCMF_OTP_SYS_VENDOR	0x15
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 0be1d60b5eb9..464e55e89062 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -173,6 +173,8 @@ struct rte_console {
 #define SBSDIO_DEVCTL_RST_BPRESET	0x10
 /*   Force no backplane reset */
 #define SBSDIO_DEVCTL_RST_NOBPRESET	0x20
+/* Reset SB Address to default value */
+#define SBSDIO_DEVCTL_ADDR_RESET    0x40
 
 /* direct(mapped) cis space */
 
@@ -551,6 +553,7 @@ struct brcmf_sdio {
 	u16 head_align;		/* buffer pointer alignment */
 	u16 sgentry_align;	/* scatter-gather buffer alignment */
 	struct mutex sdsem;
+	bool chipid_preset;
 };
 
 /* clkstate */
@@ -4229,6 +4232,33 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
 	}
 }
 
+static u32
+brcmf_sdio_ccsec_get_buscorebase(struct brcmf_sdio_dev *sdiodev)
+{
+	u8 devctl = 0;
+	u32 addr = 0;
+	int err = 0;
+
+	devctl = brcmf_sdiod_readb(sdiodev, SBSDIO_DEVICE_CTL, NULL);
+	brcmf_sdiod_writeb(sdiodev, SBSDIO_DEVICE_CTL, devctl | SBSDIO_DEVCTL_ADDR_RESET, &err);
+	if (err)
+		goto exit;
+
+	addr |= (brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_SBADDRLOW, NULL) << 8) |
+			(brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_SBADDRMID, NULL) << 16) |
+			(brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_SBADDRHIGH, NULL) << 24);
+
+	brcmf_dbg(INFO, "sdiod core address is 0x%x\n", addr);
+exit:
+	if (err) {
+		brcmf_err("Get SDIO core base address failed, err=%d", err);
+		addr = 0;
+	}
+	brcmf_sdiod_writeb(sdiodev, SBSDIO_DEVICE_CTL, devctl, &err);
+
+	return addr;
+}
+
 static u32 brcmf_sdio_buscore_blhs_read(void *ctx, u32 reg_offset)
 {
 	struct brcmf_sdio_dev *sdiodev = (struct brcmf_sdio_dev *)ctx;
@@ -4339,11 +4369,14 @@ static void brcmf_sdio_buscore_write32(void *ctx, u32 addr, u32 val)
 	brcmf_sdiod_writel(sdiodev, addr, val, NULL);
 }
 
-static int brcmf_sdio_buscore_blhs_attach(void *ctx, struct brcmf_blhs **blhs,
-					  u32 flag, uint timeout, uint interval)
+static int
+brcmf_sdio_buscore_sec_attach(void *ctx, struct brcmf_blhs **blhs, struct brcmf_ccsec **ccsec,
+			      u32 flag, uint timeout, uint interval)
 {
 	struct brcmf_sdio_dev *sdiodev = (struct brcmf_sdio_dev *)ctx;
-	struct brcmf_blhs *blhsh;
+	struct brcmf_blhs *blhsh = NULL;
+	struct brcmf_ccsec *ccsech = NULL;
+	u32 reg_addr;
 	u8 cardcap;
 
 	if (sdiodev->func1->vendor != SDIO_VENDOR_ID_CYPRESS)
@@ -4363,6 +4396,20 @@ static int brcmf_sdio_buscore_blhs_attach(void *ctx, struct brcmf_blhs **blhs,
 		*blhs = blhsh;
 	}
 
+	if (cardcap & SDIO_CCCR_BRCM_CARDCAP_CHIPID_PRESENT) {
+		ccsech = kzalloc(sizeof(*ccsech), GFP_KERNEL);
+		if (!ccsech) {
+			kfree(blhsh);
+			return -ENOMEM;
+		}
+		ccsech->bus_corebase = brcmf_sdio_ccsec_get_buscorebase(sdiodev);
+		reg_addr = ccsech->bus_corebase + SD_REG(eromptr);
+		ccsech->erombase = brcmf_sdio_buscore_read32(ctx, reg_addr);
+		reg_addr = ccsech->bus_corebase + SD_REG(chipid);
+		ccsech->chipid = brcmf_sdio_buscore_read32(ctx, reg_addr);
+		*ccsec = ccsech;
+	}
+
 	return 0;
 }
 
@@ -4371,7 +4418,7 @@ static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
 	.activate = brcmf_sdio_buscore_activate,
 	.read32 = brcmf_sdio_buscore_read32,
 	.write32 = brcmf_sdio_buscore_write32,
-	.blhs_attach = brcmf_sdio_buscore_blhs_attach,
+	.sec_attach = brcmf_sdio_buscore_sec_attach,
 };
 
 static bool
@@ -4390,9 +4437,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 
 	enum_base = brcmf_chip_enum_base(sdiodev->func1->device);
 
-	pr_debug("F1 signature read @0x%08x=0x%4x\n", enum_base,
-		 brcmf_sdiod_readl(sdiodev, enum_base, NULL));
-
 	/*
 	 * Force PLL off until brcmf_chip_attach()
 	 * programs PLL control regs
@@ -4418,6 +4462,10 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 		goto fail;
 	}
 
+	if (!bus->ci->ccsec)
+		pr_debug("F1 signature read @0x18000000=0x%4x\n",
+			 brcmf_sdiod_readl(sdiodev, enum_base, NULL));
+
 	/* Pick up the SDIO core info struct from chip.c */
 	bus->sdio_core   = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
 	if (!bus->sdio_core)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index 330c8cdfcae7..67c962045a36 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -37,6 +37,7 @@
 #define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT	BIT(1)
 #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT	BIT(2)
 #define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC	BIT(3)
+#define SDIO_CCCR_BRCM_CARDCAP_CHIPID_PRESENT	BIT(6)
 #define SDIO_CCCR_BRCM_CARDCAP_SECURE_MODE	BIT(7)
 
 /* Interrupt enable bits for each function */
@@ -301,7 +302,11 @@ struct sdpcmd_regs {
 	u32 clockctlstatus;		/* rev8 */
 	u32 PAD[7];
 
-	u32 PAD[128];			/* DMA engines */
+	u32 PAD[76];			/* DMA engines */
+
+	u32 chipid;			/* SDIO ChipID Register, 0x330, rev31 */
+	u32 eromptr;			/* SDIO EromPtrOffset Register, 0x334, rev31 */
+	u32 PAD[50];
 
 	/* SDIO/PCMCIA CIS region */
 	char cis[512];			/* 0x400-0x5ff, rev6 */
-- 
2.25.1

