From 15cec0c18d4989bf364eff587b45507386ef6e4f Mon Sep 17 00:00:00 2001
From: Gaurang Rathod <Gaurang.Rathod@infineon.com>
Date: Thu, 18 May 2023 01:25:28 -0500
Subject: [PATCH 230/296] brcmfmac: New rmmod seq for 43022:secure-mode

In 43022 secured-mode, we can not use pmu_watchdog
sequence for resetting the chip in rmmod path.

In new reset sequence,
1.Set the Card Control(offset 0xf1) 1nd and 2nd bits.
2.Set the IOAbort(0ffset 0x6) 3rd bit IO Card Reset.

Signed-off-by: Gaurang Rathod <Gaurang.Rathod@infineon.com>
---
 .../broadcom/brcm80211/brcmfmac/chip.c        |   6 +-
 .../broadcom/brcm80211/brcmfmac/sdio.c        | 134 ++++++++++++------
 .../broadcom/brcm80211/brcmfmac/sdio.h        |   2 +
 3 files changed, 99 insertions(+), 43 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
index e86e4ed624fe..5f7b5c0188a2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -254,7 +254,7 @@ struct sbsocramregs {
 
 //TODO: original value is 450, check if need assign to specific chip or not.
 #define BRCMF_BLHS_D2H_VALDN_DONE_TIMEOUT		250	/* msec */
-#define BRCMF_BLHS_D2H_MV_NVRAM_DONE_TIMEOUT		100	/* msec */
+#define BRCMF_BLHS_D2H_MV_NVRAM_DONE_TIMEOUT		(100)	/* msec */
 #define BRCMF_BLHS_D2H_BP_CLK_DISABLE_REQ_TIMEOUT	(5 * 1000)	/* msec */
 
 /* Bootloader handshake flags - dongle to host */
@@ -1124,7 +1124,7 @@ static int brcmf_blhs_pre_nvram_download(struct brcmf_chip *pub)
 static int brcmf_blhs_ack_wait_dongle_access(struct brcmf_chip *pub)
 {
 	struct brcmf_chip_priv *chip;
-	u32 addr, base;
+	u32 addr;
 	int err;
 
 	chip = container_of(pub, struct brcmf_chip_priv, pub);
@@ -1229,7 +1229,7 @@ static int brcmf_blhs_post_nvram_download(struct brcmf_chip *pub)
 				  regdata);
 		} else {
 		/* Timeout waiting for the NVRAM to be moved to the end of the RAM. */
-			brcmf_err("Timeout:%dms for BRCMF_BLHS_D2H_MV_NVRAM_DONE regdata 0x%08x\n"
+			brcmf_err("Timeout: %dms for BRCMF_BLHS_D2H_MV_NVRAM_DONE regdata 0x%08x\n",
 				  BRCMF_BLHS_D2H_MV_NVRAM_DONE_TIMEOUT, regdata);
 			return -EPERM;
 		}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 1f1a18b25cec..afb48625b4b9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3154,8 +3154,7 @@ brcmf_sdio_ulp_pre_redownload_check(struct brcmf_sdio *bus, u32 hmb_data)
 			brcmf_dbg(ULP, "wowl_wake_ind: 0x%08x, ulp_wake_ind: 0x%08x\n",
 				  wowl_wake_ind, ulp_wake_ind);
 
-		/* skip setting min resource mask for secure chip */
-		if (bus->ci->chip != CY_CC_43022_CHIP_ID) {
+			/* skip setting min resource mask for secure chip */
 			reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base,
 					       min_res_mask);
 			brcmf_sdiod_writel(sdiod, reg_addr,
@@ -3977,7 +3976,7 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus,
 			err = brcmf_sdiod_ramrw(bus->sdiodev, true, TRX_HDR_START_ADDR,
 						(u8 *)fw->data, sizeof(struct trx_header_le));
 			fw_size -= sizeof(struct trx_header_le);
-			image = fw->data;
+			image = (u8 *)fw->data;
 			image = image + TRX_HDR_SZ;
 		}
 		err = brcmf_sdiod_ramrw(bus->sdiodev, true, address,
@@ -4851,7 +4850,7 @@ int brcmf_get_intr_pending_data(void *ctx)
 	int loop = 0, status = 0, err = 0;
 	u32 reg_val = 0;
 
-	for (loop == 0; loop < LOOP_TO_CHECK_FOR_BP_ENABLE; loop++) {
+	for (loop = 0; loop < LOOP_TO_CHECK_FOR_BP_ENABLE; loop++) {
 		sdio_claim_host(sdiodev->func1);
 		reg_val = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_INTx, &err);
 		sdio_release_host(sdiodev->func1);
@@ -5676,9 +5675,10 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
 void brcmf_sdio_remove(struct brcmf_sdio *bus)
 {
 	struct brcmf_bus *bus_if = bus->sdiodev->bus_if;
+	u32 reg_val, read_reg;
+	int err = 0;
 
 	brcmf_dbg(TRACE, "Enter\n");
-
 	if (bus) {
 		/* Stop watchdog task */
 		if (bus->watchdog_tsk) {
@@ -5721,46 +5721,100 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
 					brcmf_chip_set_passive(bus->ci);
 				}
 
-				if (bus->ci->blhs)
-					bus->ci->blhs->init(bus->ci);
-
-				/* Configure registers to trigger WLAN reset on
-				 * "SDIO Soft Reset", and set RES bit to trigger
-				 *  SDIO as well as WLAN reset
-				 * (instead of using PMU/CC Watchdog register)
-				 */
-				if (bus->ci->ccsec) {
-					struct brcmf_sdio_dev *sdiodev;
-					int err = 0;
-					u32 reg_val = 0;
-
-					sdiodev = bus->sdiodev;
-					/* Set card control so an SDIO card reset
-					 *does a WLAN backplane reset */
-					reg_val = brcmf_sdiod_func0_rb(sdiodev,
+				if (bus->ci->blhs &&
+				    (bus->ci->chip == CY_CC_43012_CHIP_ID ||
+				     bus->ci->chip == CY_CC_43022_CHIP_ID)) {
+					/* Set card control so an SDIO card
+					 * reset does a WLAN backplane reset
+					 */
+					reg_val = brcmf_sdiod_func0_rb(bus->sdiodev,
 								       SDIO_CCCR_BRCM_CARDCTRL,
 								       &err);
-					reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
-
-					if (inf_btsdio_set_bt_reset(bus_if))
-						reg_val |= SDIO_CCCR_BRCM_CARDCTRL_BTRESET;
-
-					brcmf_dbg(SDIO, "Write CARDCTRL = 0x%x\n", reg_val);
-
-					brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL,
-							     reg_val, &err);
-					brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT,
-							    sdiodev->func1->num |\
-								SDIO_IO_CARD_RESET,
-								NULL);
+					if (!err) {
+						/* For 43022 bit 1 and bit 2 are required
+						 * to be set for SDIO reset
+						 */
+						reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
+						if (inf_btsdio_set_bt_reset(bus_if))
+							reg_val |= SDIO_CCCR_BRCM_CARDCTRL_BTRESET;
+						brcmf_sdiod_func0_wb(bus->sdiodev,
+								     SDIO_CCCR_BRCM_CARDCTRL,
+								     reg_val, &err);
+						brcmf_dbg(INFO, "Write CARDCTRL = 0x%x err:%d\n",
+							  reg_val, err);
+						read_reg = brcmf_sdiod_func0_rb(bus->sdiodev,
+										SDIO_CCCR_BRCM_CARDCTRL,
+										&err);
+						brcmf_dbg(INFO, "Card CTRL reg dump [0x%x], read err:%d\n",
+							  read_reg, err);
+					} else {
+						brcmf_err("Failed to read Card CTRL [err = %d]\n",
+							  err);
+					}
+					/* For 43022, bit 3 needs to be set
+					 * for IO Card reset
+					 */
+					reg_val = brcmf_sdiod_func0_rb(bus->sdiodev,
+								       SDIO_CCCR_IO_ABORT,
+								       &err);
+					if (!err) {
+						reg_val |= SDIO_CCCR_IO_ABORT_RES;
+						brcmf_err("Setting IO Card Reset (RES) bit"
+							" in IOAbort register, after this point no"
+							" SDIO access is allowed till full"
+							" SDIO init\n");
+						brcmf_sdiod_func0_wb(bus->sdiodev,
+								     SDIO_CCCR_IO_ABORT,
+								     reg_val, &err);
+					} else {
+						brcmf_err("Failed to read IO Abort [err = %d]\n",
+							  err);
+					}
+					mdelay(20);
 				} else {
-					/* Reset the PMU, backplane and all the
-					 * cores by using the PMUWatchdogCounter.
+					if (bus->ci->blhs)
+						bus->ci->blhs->init(bus->ci);
+
+					/* Configure registers to trigger WLAN reset on
+					 * "SDIO Soft Reset", and set RES bit to trigger
+					 *  SDIO as well as WLAN reset
+					 * (instead of using PMU/CC Watchdog register)
 					 */
-					brcmf_chip_reset_watchdog(bus->ci);
+					if (bus->ci->ccsec) {
+						struct brcmf_sdio_dev *sdiodev;
+						int err = 0;
+						u32 reg_val = 0;
+
+						sdiodev = bus->sdiodev;
+						/* Set card control so an SDIO card reset
+						 * does a WLAN backplane reset
+						 */
+						reg_val = brcmf_sdiod_func0_rb(sdiodev,
+									       SDIO_CCCR_BRCM_CARDCTRL,
+									       &err);
+						reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
+                                                if (inf_btsdio_set_bt_reset(bus_if))
+                                                        reg_val |= SDIO_CCCR_BRCM_CARDCTRL_BTRESET;
+						brcmf_sdiod_func0_wb(sdiodev,
+								     SDIO_CCCR_BRCM_CARDCTRL,
+								     reg_val, &err);
+						brcmf_dbg(INFO, "Write CARDCTRL = 0x%x err:%d\n",
+							  reg_val, err);
+						brcmf_sdiod_func0_wb(sdiodev,
+								     SDIO_CCCR_ABORT,
+								     sdiodev->func1->num |
+								     SDIO_IO_CARD_RESET,
+								     NULL);
+					} else {
+						/* Reset the PMU, backplane and all the
+						 * cores by using the PMUWatchdogCounter.
+						 */
+						brcmf_chip_reset_watchdog(bus->ci);
+					}
+
+					if (bus->ci->blhs)
+						bus->ci->blhs->post_wdreset(bus->ci);
 				}
-				if (bus->ci->blhs)
-					bus->ci->blhs->post_wdreset(bus->ci);
 
 				brcmf_sdio_clkctl(bus, CLK_NONE, false);
 				sdio_release_host(bus->sdiodev->func1);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index fd7f1c9e223d..aad18306f8d6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -50,6 +50,8 @@
 /* function 0 vendor specific CCCR registers */
 
 #define SDIO_CCCR_INTR_PND			0x05
+#define SDIO_CCCR_IO_ABORT			0x06
+#define SDIO_CCCR_IO_ABORT_RES			BIT(3)
 #define SDIO_CCCR_BRCM_CARDCAP			0xf0
 #define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT	BIT(1)
 #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT	BIT(2)
-- 
2.25.1

