From c005bafc65029805b7205cc8d00ef516d1e768de Mon Sep 17 00:00:00 2001
From: Gaurang Rathod <Gaurang.Rathod@infineon.com>
Date: Wed, 15 Feb 2023 04:14:30 -0600
Subject: [PATCH 224/296] brcmfmac: Bootloader host handshake implementation

This change is required to bring-up 43022 chip in
secure-mode. Here we have introduced new firmware
nvram download flow for security.

skip the modification in pcie.c as of the commit
commit 5d13af8cf77b ("Bootloader host handshake")

Signed-off-by: Gaurang Rathod <Gaurang.Rathod@infineon.com>
---
 .../broadcom/brcm80211/brcmfmac/chip.c        | 109 +++++++++--
 .../broadcom/brcm80211/brcmfmac/chip.h        |   3 +
 .../broadcom/brcm80211/brcmfmac/firmware.c    |  18 +-
 .../broadcom/brcm80211/brcmfmac/firmware.h    |  10 +-
 .../broadcom/brcm80211/brcmfmac/sdio.c        | 179 +++++++++++++++---
 .../broadcom/brcm80211/brcmfmac/sdio.h        |   1 +
 6 files changed, 268 insertions(+), 52 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
index d58cd5ae7b4f..37c345da55e5 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -251,7 +251,11 @@ struct sbsocramregs {
 #define BRCMF_BLHS_POLL_INTERVAL			10	/* msec */
 #define BRCMF_BLHS_D2H_READY_TIMEOUT			100	/* msec */
 #define BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE_TIMEOUT	50	/* msec */
-#define BRCMF_BLHS_D2H_VALDN_DONE_TIMEOUT		450	/* msec */
+
+//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_BP_CLK_DISABLE_REQ_TIMEOUT	(5 * 1000)	/* msec */
 
 /* Bootloader handshake flags - dongle to host */
 #define BRCMF_BLHS_D2H_START			BIT(0)
@@ -261,12 +265,16 @@ struct sbsocramregs {
 #define BRCMF_BLHS_D2H_VALDN_START		BIT(4)
 #define BRCMF_BLHS_D2H_VALDN_RESULT		BIT(5)
 #define BRCMF_BLHS_D2H_VALDN_DONE		BIT(6)
+#define BRCMF_BLHS_D2H_MV_NVRAM_DONE		BIT(7)
+#define BRCMF_BLHS_D2H_BP_CLK_DISABLE_REQ	BIT(8)
 
 /* Bootloader handshake flags - host to dongle */
 #define BRCMF_BLHS_H2D_DL_FW_START		BIT(0)
 #define BRCMF_BLHS_H2D_DL_FW_DONE		BIT(1)
 #define BRCMF_BLHS_H2D_DL_NVRAM_DONE		BIT(2)
 #define BRCMF_BLHS_H2D_BL_RESET_ON_ERROR	BIT(3)
+#define BRCMF_BLHS_H2D_DL_NVRAM_START		BIT(4)
+#define BRCMF_BLHS_H2D_BP_CLK_DISABLE_ACK	BIT(5)
 
 struct brcmf_core_priv {
 	struct brcmf_core pub;
@@ -1079,7 +1087,7 @@ static int brcmf_blhs_is_bootloader_ready(struct brcmf_chip_priv *chip)
 	return 0;
 }
 
-static int brcmf_blhs_prep_fw_download(struct brcmf_chip *pub)
+static int brcmf_blhs_pre_nvram_download(struct brcmf_chip *pub)
 {
 	struct brcmf_chip_priv *chip;
 	u32 addr;
@@ -1093,6 +1101,51 @@ static int brcmf_blhs_prep_fw_download(struct brcmf_chip *pub)
 	if (err)
 		return err;
 
+	/* Host notification about NVRAM download start */
+	addr = pub->blhs->h2d;
+	pub->blhs->write(chip->ctx, addr, BRCMF_BLHS_H2D_DL_NVRAM_START);
+
+	return 0;
+}
+
+static int brcmf_blhs_ack_wait_dongle_access(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	u32 addr, base;
+	int err;
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+
+	addr = pub->blhs->d2h;
+	SPINWAIT_MS((pub->blhs->read(chip->ctx, addr) &
+		     BRCMF_BLHS_D2H_BP_CLK_DISABLE_REQ) == 0,
+		    BRCMF_BLHS_D2H_BP_CLK_DISABLE_REQ_TIMEOUT,
+		    BRCMF_BLHS_POLL_INTERVAL);
+
+	addr = pub->blhs->h2d;
+	pub->blhs->write(chip->ctx, addr, BRCMF_BLHS_H2D_BP_CLK_DISABLE_ACK);
+
+	err = brcmf_get_intr_pending_data(chip->ctx);
+
+	return err;
+}
+
+static int brcmf_blhs_prep_fw_download(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	u32 addr;
+	int err;
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	/* Host indication for bootloader to start the init */
+	if (!(pub->chip == CY_CC_43022_CHIP_ID)) {
+		brcmf_blhs_init(pub);
+
+		chip = container_of(pub, struct brcmf_chip_priv, pub);
+		err = brcmf_blhs_is_bootloader_ready(chip);
+		if (err)
+			return err;
+	}
 	/* Host notification about FW download start */
 	addr = pub->blhs->h2d;
 	pub->blhs->write(chip->ctx, addr, BRCMF_BLHS_H2D_DL_FW_START);
@@ -1105,30 +1158,36 @@ static int brcmf_blhs_post_fw_download(struct brcmf_chip *pub)
 	struct brcmf_chip_priv *chip;
 	u32 addr;
 	u32 regdata;
+	int err = 0;
 
 	chip = container_of(pub, struct brcmf_chip_priv, pub);
 	addr = pub->blhs->h2d;
 	pub->blhs->write(chip->ctx, addr, BRCMF_BLHS_H2D_DL_FW_DONE);
-	addr = pub->blhs->d2h;
-	SPINWAIT_MS((pub->blhs->read(chip->ctx, addr) &
-		     BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE) == 0,
-		    BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE_TIMEOUT,
-		    BRCMF_BLHS_POLL_INTERVAL);
 
-	regdata = pub->blhs->read(chip->ctx, addr);
-	if (!(regdata & BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE)) {
-		brcmf_err("TRX header parsing failed\n");
+	if (pub->chip == CY_CC_43022_CHIP_ID) {
+		err = brcmf_blhs_ack_wait_dongle_access(pub);
+	} else {
+		addr = pub->blhs->d2h;
+		SPINWAIT_MS((pub->blhs->read(chip->ctx, addr) &
+			     BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE) == 0,
+			    BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE_TIMEOUT,
+			    BRCMF_BLHS_POLL_INTERVAL);
 
-		/* Host indication for bootloader to get reset on error */
-		addr = pub->blhs->h2d;
 		regdata = pub->blhs->read(chip->ctx, addr);
-		regdata |= BRCMF_BLHS_H2D_BL_RESET_ON_ERROR;
-		pub->blhs->write(chip->ctx, addr, regdata);
+		if (!(regdata & BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE)) {
+			brcmf_err("TRX header parsing failed\n");
+
+			/* Host indication for bootloader to get reset on error */
+			addr = pub->blhs->h2d;
+			regdata = pub->blhs->read(chip->ctx, addr);
+			regdata |= BRCMF_BLHS_H2D_BL_RESET_ON_ERROR;
+			pub->blhs->write(chip->ctx, addr, regdata);
 
 		return -EPERM;
+		}
 	}
 
-	return 0;
+	return err;
 }
 
 static void brcmf_blhs_post_nvram_download(struct brcmf_chip *pub)
@@ -1139,9 +1198,21 @@ static void brcmf_blhs_post_nvram_download(struct brcmf_chip *pub)
 
 	chip = container_of(pub, struct brcmf_chip_priv, pub);
 	addr = pub->blhs->h2d;
-	regdata = pub->blhs->read(chip->ctx, addr);
-	regdata |= BRCMF_BLHS_H2D_DL_NVRAM_DONE;
-	pub->blhs->write(chip->ctx, addr, regdata);
+	if (pub->chip == CY_CC_43022_CHIP_ID) {
+		regdata = pub->blhs->read(chip->ctx, addr);
+		regdata |= BRCMF_BLHS_H2D_DL_NVRAM_DONE;
+		pub->blhs->write(chip->ctx, addr, regdata);
+
+		addr = pub->blhs->d2h;
+		SPINWAIT_MS((pub->blhs->read(chip->ctx, addr) &
+			     BRCMF_BLHS_D2H_MV_NVRAM_DONE) == 0,
+			    BRCMF_BLHS_D2H_MV_NVRAM_DONE_TIMEOUT,
+			    BRCMF_BLHS_POLL_INTERVAL);
+	} else {
+		regdata = pub->blhs->read(chip->ctx, addr);
+		regdata |= BRCMF_BLHS_H2D_DL_NVRAM_DONE;
+		pub->blhs->write(chip->ctx, addr, regdata);
+	}
 }
 
 static int brcmf_blhs_chk_validation(struct brcmf_chip *pub)
@@ -1390,9 +1461,11 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,
 
 		if (blhs) {
 			blhs->init = brcmf_blhs_init;
+			blhs->pre_nvramdl = brcmf_blhs_pre_nvram_download;
 			blhs->prep_fwdl = brcmf_blhs_prep_fw_download;
 			blhs->post_fwdl = brcmf_blhs_post_fw_download;
 			blhs->post_nvramdl = brcmf_blhs_post_nvram_download;
+			blhs->bp_clk_ack = brcmf_blhs_ack_wait_dongle_access;
 			blhs->chk_validation = brcmf_blhs_chk_validation;
 			blhs->post_wdreset = brcmf_blhs_post_watchdog_reset;
 		}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
index 3d1bf44f2d14..ad0804d7ace1 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
@@ -100,9 +100,11 @@ struct brcmf_blhs {
 	u32 d2h;
 	u32 h2d;
 	void (*init)(struct brcmf_chip *pub);
+	int (*pre_nvramdl)(struct brcmf_chip *pub);
 	int (*prep_fwdl)(struct brcmf_chip *pub);
 	int (*post_fwdl)(struct brcmf_chip *pub);
 	void (*post_nvramdl)(struct brcmf_chip *pub);
+	int (*bp_clk_ack)(struct brcmf_chip *pub);
 	int (*chk_validation)(struct brcmf_chip *pub);
 	int (*post_wdreset)(struct brcmf_chip *pub);
 	u32 (*read)(void *ctx, u32 addr);
@@ -136,5 +138,6 @@ void brcmf_chip_reset_watchdog(struct brcmf_chip *pub);
 void brcmf_chip_ulp_reset_lhl_regs(struct brcmf_chip *pub);
 void brcmf_chip_reset_pmu_regs(struct brcmf_chip *pub);
 void brcmf_chip_set_default_min_res_mask(struct brcmf_chip *pub);
+int brcmf_get_intr_pending_data(void *ctx);
 
 #endif /* BRCMF_AXIDMP_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index 726430338b9f..aa895df4fe74 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -528,6 +528,7 @@ static void brcmf_fw_free_request(struct brcmf_fw_request *req)
 
 	for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
 		if (item->type == BRCMF_FW_TYPE_BINARY ||
+		    item->type == BRCMF_FW_TYPE_TRXS ||
 		    item->type == BRCMF_FW_TYPE_TRXSE)
 			release_firmware(item->binary);
 		else if (item->type == BRCMF_FW_TYPE_NVRAM)
@@ -601,6 +602,7 @@ static int brcmf_fw_complete_request(const struct firmware *fw,
 		break;
 	case BRCMF_FW_TYPE_BINARY:
 	case BRCMF_FW_TYPE_TRXSE:
+	case BRCMF_FW_TYPE_TRXS:
 		if (fw)
 			cur->binary = fw;
 		else
@@ -681,6 +683,14 @@ static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
 	char alt_path[BRCMF_FW_NAME_LEN];
 	int ret;
 
+	if (!fw && cur->type == BRCMF_FW_TYPE_TRXS) {
+		strscpy(alt_path, cur->path, BRCMF_FW_NAME_LEN);
+		/* strip 'se' from .trxse at the end */
+		//alt_path[strlen(alt_path) - ] = 0;
+		ret = request_firmware(&fw, alt_path, fwctx->dev);
+		if (!ret)
+			cur->path = alt_path;
+	}
 	if (!fw && cur->type == BRCMF_FW_TYPE_TRXSE) {
 		strlcpy(alt_path, cur->path, BRCMF_FW_NAME_LEN);
 		/* strip 'se' from .trxse at the end */
@@ -726,9 +736,11 @@ static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx)
 		if (!alt_path)
 			goto fallback;
 
-		ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
-					      fwctx->dev, GFP_KERNEL, fwctx,
-					      brcmf_fw_request_done_alt_path);
+		if (!fw) {
+			ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
+										  fwctx->dev, GFP_KERNEL, fwctx,
+										  brcmf_fw_request_done_alt_path);
+		}
 		kfree(alt_path);
 
 		if (ret < 0)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
index 4e910f325f4a..2a74e4b00347 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
@@ -43,10 +43,15 @@ static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \
 MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw_base ".bin"); \
 MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw_base ".clm_blob")
 
+#define CY_FW_BL_DEF(bl_name, fw_base) \
+static const char BRCM_ ## bl_name ## _FIRMWARE_BASENAME[] = \
+	CY_FW_DEFAULT_PATH fw_base; \
+MODULE_FIRMWARE(CY_FW_DEFAULT_PATH fw_base ".bin")
+
 #define CY_FW_DEF(fw_name, fw_base) \
 static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \
 	CY_FW_DEFAULT_PATH fw_base; \
-MODULE_FIRMWARE(CY_FW_DEFAULT_PATH fw_base ".bin")
+MODULE_FIRMWARE(CY_FW_DEFAULT_PATH fw_base ".trxs")
 
 #define CY_FW_TRXSE_DEF(fw_name, fw_base) \
 static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \
@@ -61,7 +66,8 @@ void brcmf_fw_nvram_free(void *nvram);
 enum brcmf_fw_type {
 	BRCMF_FW_TYPE_BINARY,
 	BRCMF_FW_TYPE_NVRAM,
-	BRCMF_FW_TYPE_TRXSE
+	BRCMF_FW_TYPE_TRXSE,
+	BRCMF_FW_TYPE_TRXS
 };
 
 struct brcmf_fw_item {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 47612b6c6ad7..b71f48bdcbbb 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3926,34 +3926,56 @@ brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr,
 }
 #endif	/* DEBUG */
 
+/* In 43022:secure-mode TRX header should be copied at 512Kb RAM location
+ * Because for CM3 based chip rtecdc.bin(fw) should be at starting of RAM
+ */
+#define TRX_HDR_START_ADDR     0x7fd4c /* TRX header start address */
+#define TRX_HDR_SZ             0x2b4 /* TRX header size */
+
 static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus,
 					 const struct firmware *fw)
 {
 	struct trx_header_le *trx = (struct trx_header_le *)fw->data;
 	u32 fw_size;
 	u32 address;
+	u8 *image = NULL;
 	int err;
 
 	brcmf_dbg(TRACE, "Enter\n");
 
 	address = bus->ci->rambase;
 	fw_size = fw->size;
-	if (trx->magic == cpu_to_le32(TRX_MAGIC)) {
-		address -= sizeof(struct trx_header_le);
-		fw_size = le32_to_cpu(trx->len);
+
+	if (bus->ci->blhs && bus->ci->chip == CY_CC_43022_CHIP_ID) {
+		if (trx->magic == cpu_to_le32(TRX_MAGIC)) {
+			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 = image + TRX_HDR_SZ;
+		}
+	} else {
+		if (trx->magic == cpu_to_le32(TRX_MAGIC)) {
+			address -= sizeof(struct trx_header_le);
+			fw_size = le32_to_cpu(trx->len);
+		}
 	}
+
 	err = brcmf_sdiod_ramrw(bus->sdiodev, true, address,
-				(u8 *)fw->data, fw_size);
+				image, fw_size);
 	if (err)
 		brcmf_err("error %d on writing %d membytes at 0x%08x\n",
 			  err, (int)fw_size, address);
 	else if (!brcmf_sdio_verifymemory(bus->sdiodev, address,
-					  (u8 *)fw->data, fw_size))
+					  image, fw_size))
 		err = -EIO;
 
 	return err;
 }
 
+/* In 43022:secure-mode NVRAM should be copied to 512KB RAM area */
+#define NVRAM_DL_ADDR   0x80000
+
 static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus,
 				     void *vars, u32 varsz)
 {
@@ -3991,7 +4013,50 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
 	rstvec = get_unaligned_le32(fw->data);
 	brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec);
 
-	if (bus->ci->blhs) {
+	if (bus->ci->blhs && bus->ci->chip == CY_CC_43022_CHIP_ID) {
+		bcmerror = bus->ci->blhs->pre_nvramdl(bus->ci);
+		if (bcmerror) {
+			brcmf_err("NVRAM download preparation failed\n");
+			goto err;
+		}
+
+		bcmerror = brcmf_sdio_download_nvram(bus, nvram, nvlen);
+		if (bcmerror) {
+			brcmf_err("dongle nvram file download failed\n");
+			goto err;
+		}
+
+		bus->ci->blhs->post_nvramdl(bus->ci);
+
+		bcmerror = bus->ci->blhs->prep_fwdl(bus->ci);
+
+		bcmerror = brcmf_sdio_download_code_file(bus, fw);
+		release_firmware(fw);
+		if (bcmerror) {
+			brcmf_err("dongle image file download failed\n");
+			brcmf_fw_nvram_free(nvram);
+			goto err;
+		}
+
+		bcmerror = bus->ci->blhs->post_fwdl(bus->ci);
+		if (bcmerror) {
+			brcmf_err("FW download failed, err=%d\n", bcmerror);
+			brcmf_fw_nvram_free(nvram);
+			goto err;
+		}
+
+		bcmerror = bus->ci->blhs->chk_validation(bus->ci);
+		if (bcmerror) {
+			brcmf_err("FW validation failed, err=%d\n", bcmerror);
+			brcmf_fw_nvram_free(nvram);
+			goto err;
+		}
+#ifdef DEBUG
+		brcmf_sdio_bus_sleep(bus, false, false);
+		if (brcmf_sdio_readconsole(bus) < 0)
+			brcmf_err("Console buffer read failed\n");
+#endif /* DEBUG */
+	} else if (bus->ci->blhs) {
 		bcmerror = bus->ci->blhs->prep_fwdl(bus->ci);
 		if (bcmerror) {
 			brcmf_err("FW download preparation failed\n");
@@ -4001,15 +4066,17 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
 		}
 	}
 
-	bcmerror = brcmf_sdio_download_code_file(bus, fw);
-	release_firmware(fw);
-	if (bcmerror) {
-		brcmf_err("dongle image file download failed\n");
-		brcmf_fw_nvram_free(nvram);
-		goto err;
+	if (bus->ci->chip == CY_CC_43022_CHIP_ID && !(bus->ci->blhs)) {
+		bcmerror = brcmf_sdio_download_code_file(bus, fw);
+		release_firmware(fw);
+		if (bcmerror) {
+			brcmf_err("dongle image file download failed\n");
+			brcmf_fw_nvram_free(nvram);
+			goto err;
+		}
 	}
 
-	if (bus->ci->blhs) {
+	if (bus->ci->blhs && (!(bus->ci->chip == CY_CC_43022_CHIP_ID))) {
 		bcmerror = bus->ci->blhs->post_fwdl(bus->ci);
 		if (bcmerror) {
 			brcmf_err("FW download failed, err=%d\n", bcmerror);
@@ -4024,15 +4091,18 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
 			goto err;
 		}
 	}
-
-	bcmerror = brcmf_sdio_download_nvram(bus, nvram, nvlen);
-	brcmf_fw_nvram_free(nvram);
-	if (bcmerror) {
-		brcmf_err("dongle nvram file download failed\n");
-		goto err;
+	if (bus->ci->chip == CY_CC_43022_CHIP_ID && !(bus->ci->blhs)) {
+		bcmerror = brcmf_sdio_download_nvram(bus, nvram, nvlen);
+		brcmf_fw_nvram_free(nvram);
+		if (bcmerror) {
+			brcmf_err("dongle nvram file download failed\n");
+			goto err;
+		}
 	}
 
-	if (bus->ci->blhs) {
+	if (bus->ci->blhs && bus->ci->chip == CY_CC_43022_CHIP_ID) {
+		brcmf_err("Avoid resetting ARM in 43022 secured chip\n");
+	} else if (bus->ci->blhs && (!(bus->ci->chip == CY_CC_43022_CHIP_ID))) {
 		bus->ci->blhs->post_nvramdl(bus->ci);
 	} else {
 		/* Take arm out of reset */
@@ -4041,7 +4111,6 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
 			goto err;
 		}
 	}
-
 err:
 	brcmf_sdio_clkctl(bus, CLK_SDONLY, false);
 	sdio_release_host(bus->sdiodev->func1);
@@ -4667,10 +4736,30 @@ brcmf_sdio_buscore_sec_attach(void *ctx, struct brcmf_blhs **blhs, struct brcmf_
 	u32 reg_addr;
 	u32 regdata;
 	u8 cardcap;
+	int err = 0, secure_mode;
 
-	if (sdiodev->func1->vendor != SDIO_VENDOR_ID_CYPRESS)
+	if (sdiodev->func1->vendor != SDIO_VENDOR_ID_CYPRESS &&
+	    sdiodev->func1->vendor != SDIO_VENDOR_ID_BROADCOM)
 		return 0;
 
+	/* 43022: Secure-mode OTP bit reading */
+	secure_mode = !brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_SECURE_MODE, &err);
+	if (err)
+		brcmf_err("Failed to read SecureModeRegister = %d\n", err);
+
+	if (secure_mode) {
+		blhsh = kzalloc(sizeof(*blhsh), GFP_KERNEL);
+		if (!blhsh)
+			return -ENOMEM;
+		/* TODO : Get the address from si_backplane */
+		blhsh->d2h = BRCMF_SDIO_REG_D2H_MSG_0;
+		blhsh->h2d = BRCMF_SDIO_REG_H2D_MSG_0;
+		blhsh->read = brcmf_sdio_buscore_read32;
+		blhsh->write = brcmf_sdio_buscore_write32;
+
+		*blhs = blhsh;
+	}
+
 	cardcap = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_BRCM_CARDCAP, NULL);
 	if (cardcap & SDIO_CCCR_BRCM_CARDCAP_SECURE_MODE) {
 		blhsh = kzalloc(sizeof(*blhsh), GFP_KERNEL);
@@ -4721,6 +4810,37 @@ static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
 	.sec_attach = brcmf_sdio_buscore_sec_attach,
 };
 
+#define LOOP_TO_CHECK_FOR_BP_ENABLE                     500      /* Wait for 500msec */
+
+int brcmf_get_intr_pending_data(void *ctx)
+{
+	struct brcmf_sdio_dev *sdiodev = (struct brcmf_sdio_dev *)ctx;
+	int loop = 0, status = 0, err = 0;
+	u32 reg_val = 0;
+
+	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);
+		status = reg_val & INTR_STATUS_FUNC1;
+
+		if (status) {
+			brcmf_err("[%d]: Backplane enabled.\n", loop);
+			break;
+		}
+		udelay(10);
+	}
+
+	/* Bootloader hung after backplane disable */
+	if (loop == LOOP_TO_CHECK_FOR_BP_ENABLE) {
+		err = -EBUSY;
+		brcmf_err("Device hung, return failure.\n");
+	}
+
+	brcmf_err("intr pending err= %d\n", err);
+	return 0;
+}
+
 static bool
 brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 {
@@ -5357,14 +5477,11 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
 {
 	struct brcmf_fw_request *fwreq;
 	struct brcmf_fw_name fwnames[] = {
-		{ ".bin", bus->sdiodev->fw_name },
+		{ ".trxs", bus->sdiodev->fw_name },
 		{ ".txt", bus->sdiodev->nvram_name },
 		{ ".clm_blob", bus->sdiodev->clm_name },
 	};
 
-	if (bus->ci->blhs)
-		fwnames[BRCMF_SDIO_FW_CODE].extension = ".trxse";
-
 	fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
 				       brcmf_sdio_fwnames,
 				       ARRAY_SIZE(brcmf_sdio_fwnames),
@@ -5372,10 +5489,14 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
 	if (!fwreq)
 		return NULL;
 
-	if (bus->ci->blhs)
-		fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_TRXSE;
-	else
+	if (bus->ci->blhs) {
+		if (bus->ci->chip == CY_CC_43022_CHIP_ID)
+			fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_TRXS;
+		else
+			fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_TRXSE;
+	} else {
 		fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
+	}
 	fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
 	fwreq->items[BRCMF_SDIO_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
 	fwreq->items[BRCMF_SDIO_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index c79f96ad391f..fd7f1c9e223d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -49,6 +49,7 @@
 
 /* function 0 vendor specific CCCR registers */
 
+#define SDIO_CCCR_INTR_PND			0x05
 #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

