linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] wifi: brcmfmac: add support for TRX firmware download
@ 2024-09-09 20:31 Marek Vasut
  2024-09-09 20:31 ` [PATCH v2 2/2] wifi: brcmfmac: add support for CYW55572 PCIe chipset Marek Vasut
  2024-09-14  6:24 ` [PATCH v2 1/2] wifi: brcmfmac: add support for TRX firmware download Arend van Spriel
  0 siblings, 2 replies; 4+ messages in thread
From: Marek Vasut @ 2024-09-09 20:31 UTC (permalink / raw)
  To: linux-wireless
  Cc: Chung-Hsien Hsu, Chung-Hsien Hsu, Marek Vasut,
	Dr. David Alan Gilbert, Gustavo A. R. Silva,
	Rafał Miłecki, Arend van Spriel, Bjorn Helgaas,
	Carter Chen, Double Lo, Duoming Zhou, Erick Archer, Kalle Valo,
	Kees Cook, Krzysztof Kozlowski, Mathias Krause, Matthias Brugger,
	Owen Huang, Ulf Hansson, brcm80211-dev-list.pdl, brcm80211

From: Chung-Hsien Hsu <stanley.hsu@cypress.com>

Add support to download TRX firmware for PCIe and SDIO.

Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com>
Signed-off-by: Chung-Hsien Hsu <chung-hsien.hsu@infineon.com>
Signed-off-by: Marek Vasut <marex@denx.de> # Upport to current linux-next
---
NOTE: This is downstream upport from
      https://github.com/Infineon/ifx-wireless-drivers/
      branch RTM/v5.15.58-Indrik / tag release-v5.15.58-2024_0514
- ba34bf4816f9 ("brcmfmac: add support for TRX firmware download")
---
Cc: "Dr. David Alan Gilbert" <linux@treblig.org>
Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: "Rafał Miłecki" <zajec5@gmail.com>
Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Carter Chen <carter.chen@infineon.com>
Cc: Chung-Hsien Hsu <stanley.hsu@cypress.com>
Cc: Double Lo <Double.Lo@infineon.com>
Cc: Duoming Zhou <duoming@zju.edu.cn>
Cc: Erick Archer <erick.archer@outlook.com>
Cc: Kalle Valo <kvalo@kernel.org>
Cc: Kees Cook <kees@kernel.org>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Cc: Mathias Krause <minipli@grsecurity.net>
Cc: Matthias Brugger <mbrugger@suse.com>
Cc: Owen Huang <Owen.Huang@infineon.com>
Cc: Ulf Hansson <ulf.hansson@linaro.org>
Cc: brcm80211-dev-list.pdl@broadcom.com
Cc: brcm80211@lists.linux.dev
Cc: linux-wireless@vger.kernel.org
---
V2: Include SoB line from Chung-Hsien with both cypress and infineon address
---
 .../broadcom/brcm80211/brcmfmac/pcie.c        | 12 +++++-
 .../broadcom/brcm80211/brcmfmac/sdio.c        | 20 +++++++---
 .../broadcom/brcm80211/brcmfmac/trxhdr.h      | 38 +++++++++++++++++++
 3 files changed, 63 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/wireless/broadcom/brcm80211/brcmfmac/trxhdr.h

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index ce482a3877e90..058a742d17eda 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -42,6 +42,7 @@
 #include "chip.h"
 #include "core.h"
 #include "common.h"
+#include "trxhdr.h"
 
 
 enum brcmf_pcie_state {
@@ -1684,6 +1685,8 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
 					u32 nvram_len)
 {
 	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
+	struct trx_header_le *trx = (struct trx_header_le *)fw->data;
+	u32 fw_size;
 	u32 sharedram_addr;
 	u32 sharedram_addr_written;
 	u32 loop_counter;
@@ -1697,8 +1700,13 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
 		return err;
 
 	brcmf_dbg(PCIE, "Download FW %s\n", devinfo->fw_name);
-	memcpy_toio(devinfo->tcm + devinfo->ci->rambase,
-		    (void *)fw->data, fw->size);
+	address = devinfo->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);
+	}
+	memcpy_toio(devinfo->tcm + address, (void *)fw->data, fw_size);
 
 	resetintr = get_unaligned_le32(fw->data);
 	release_firmware(fw);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 1461dc453ac22..08881e366cae2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -35,6 +35,7 @@
 #include "core.h"
 #include "common.h"
 #include "bcdc.h"
+#include "trxhdr.h"
 
 #define DCMD_RESP_TIMEOUT	msecs_to_jiffies(2500)
 #define CTL_DONE_TIMEOUT	msecs_to_jiffies(2500)
@@ -3346,17 +3347,26 @@ brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr,
 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;
 	int err;
 
 	brcmf_dbg(TRACE, "Enter\n");
 
-	err = brcmf_sdiod_ramrw(bus->sdiodev, true, bus->ci->rambase,
-				(u8 *)fw->data, fw->size);
+	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);
+	}
+	err = brcmf_sdiod_ramrw(bus->sdiodev, true, address,
+				(u8 *)fw->data, fw_size);
 	if (err)
 		brcmf_err("error %d on writing %d membytes at 0x%08x\n",
-			  err, (int)fw->size, bus->ci->rambase);
-	else if (!brcmf_sdio_verifymemory(bus->sdiodev, bus->ci->rambase,
-					  (u8 *)fw->data, fw->size))
+			  err, (int)fw_size, address);
+	else if (!brcmf_sdio_verifymemory(bus->sdiodev, address,
+					  (u8 *)fw->data, fw_size))
 		err = -EIO;
 
 	return err;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/trxhdr.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/trxhdr.h
new file mode 100644
index 0000000000000..0411c7c7ffb99
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/trxhdr.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: ISC */
+/* Copyright (c) 2020 Cypress Semiconductor Corporation */
+
+#ifndef BRCMFMAC_TRXHDR_H
+#define BRCMFMAC_TRXHDR_H
+
+/* Bootloader makes special use of trx header "offsets" array */
+enum {
+	TRX_OFFSET_SIGN_INFO_IDX		= 0,
+	TRX_OFFSET_DATA_FOR_SIGN1_IDX		= 1,
+	TRX_OFFSET_DATA_FOR_SIGN2_IDX		= 2,
+	TRX_OFFSET_ROOT_MODULUS_IDX		= 3,
+	TRX_OFFSET_ROOT_EXPONENT_IDX		= 67,
+	TRX_OFFSET_CONT_MODULUS_IDX		= 68,
+	TRX_OFFSET_CONT_EXPONENT_IDX		= 132,
+	TRX_OFFSET_HASH_FW_IDX			= 133,
+	TRX_OFFSET_FW_LEN_IDX			= 149,
+	TRX_OFFSET_TR_RST_IDX			= 150,
+	TRX_OFFSET_FW_VER_FOR_ANTIROOLBACK_IDX	= 151,
+	TRX_OFFSET_IV_IDX			= 152,
+	TRX_OFFSET_NONCE_IDX			= 160,
+	TRX_OFFSET_SIGN_INFO2_IDX		= 168,
+	TRX_OFFSET_MAX_IDX
+};
+
+#define TRX_MAGIC	0x30524448		/* "HDR0" */
+#define TRX_VERSION	4			/* Version 4 */
+#define TRX_MAX_OFFSET	TRX_OFFSET_MAX_IDX	/* Max number of file offsets */
+
+struct trx_header_le {
+	__le32 magic;		/* "HDR0" */
+	__le32 len;		/* Length of file including header */
+	__le32 crc32;		/* CRC from flag_version to end of file */
+	__le32 flag_version;	/* 0:15 flags, 16:31 version */
+	__le32 offsets[TRX_MAX_OFFSET];	/* Offsets of partitions */
+};
+
+#endif /* BRCMFMAC_TRXHDR_H */
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/2] wifi: brcmfmac: add support for CYW55572 PCIe chipset
  2024-09-09 20:31 [PATCH v2 1/2] wifi: brcmfmac: add support for TRX firmware download Marek Vasut
@ 2024-09-09 20:31 ` Marek Vasut
  2024-09-14 12:04   ` Arend van Spriel
  2024-09-14  6:24 ` [PATCH v2 1/2] wifi: brcmfmac: add support for TRX firmware download Arend van Spriel
  1 sibling, 1 reply; 4+ messages in thread
From: Marek Vasut @ 2024-09-09 20:31 UTC (permalink / raw)
  To: linux-wireless
  Cc: Chung-Hsien Hsu, Chung-Hsien Hsu, Carter Chen, Owen Huang,
	Marek Vasut, Dr. David Alan Gilbert, Gustavo A. R. Silva,
	Rafał Miłecki, Arend van Spriel, Bjorn Helgaas,
	Double Lo, Duoming Zhou, Erick Archer, Kalle Valo, Kees Cook,
	Krzysztof Kozlowski, Mathias Krause, Matthias Brugger,
	Ulf Hansson, brcm80211-dev-list.pdl, brcm80211

From: Chung-Hsien Hsu <stanley.hsu@cypress.com>

CYW55572 is a 2x2 dual-band 802.11a/b/g/n/ac/ax chipset with 20/40/80MHz
channel support. It is a WLAN+BT combo device with WLAN secure boot support.
The CYW55572 used to be labeled CYW55560.

Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com>
Signed-off-by: Chung-Hsien Hsu <chung-hsien.hsu@infineon.com>
Signed-off-by: Carter Chen <carter.chen@infineon.com>
Signed-off-by: Owen Huang <Owen.Huang@infineon.com>
Signed-off-by: Marek Vasut <marex@denx.de> # Upport to current linux-next
---
NOTE: This is squashed from downstream upports from
      https://github.com/Infineon/ifx-wireless-drivers/
      branch RTM/v5.15.58-Indrik / tag release-v5.15.58-2024_0514
- 8a41d39f6290 ("brcmfmac: add Cypress PCIe vendor ID")
- 12f74eba2569 ("brcmfmac: add support for CYW55560 PCIe chipset")
- ea4e4056a3f8 ("brcmfmac: update firmware loading name for CY5557x")
- ee322201fe11 ("brcmfmac: use SR core id to decide SR capability for CY55572")
- 0a47ed7f3678 ("brcmfmac: Fix invalid RAM address warning for PCIE platforms")
---
Cc: "Dr. David Alan Gilbert" <linux@treblig.org>
Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: "Rafał Miłecki" <zajec5@gmail.com>
Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Carter Chen <carter.chen@infineon.com>
Cc: Chung-Hsien Hsu <stanley.hsu@cypress.com>
Cc: Double Lo <Double.Lo@infineon.com>
Cc: Duoming Zhou <duoming@zju.edu.cn>
Cc: Erick Archer <erick.archer@outlook.com>
Cc: Kalle Valo <kvalo@kernel.org>
Cc: Kees Cook <kees@kernel.org>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Cc: Mathias Krause <minipli@grsecurity.net>
Cc: Matthias Brugger <mbrugger@suse.com>
Cc: Owen Huang <Owen.Huang@infineon.com>
Cc: Ulf Hansson <ulf.hansson@linaro.org>
Cc: brcm80211-dev-list.pdl@broadcom.com
Cc: brcm80211@lists.linux.dev
Cc: linux-wireless@vger.kernel.org
---
V2: - Fix up build warnings related to use of u32 instead of __le32
    - Include SoB line from Chung-Hsien with both cypress and infineon address
---
 .../broadcom/brcm80211/brcmfmac/bcmsdh.c      |   6 +
 .../broadcom/brcm80211/brcmfmac/chip.c        | 214 +++++++++++++++++-
 .../broadcom/brcm80211/brcmfmac/chip.h        |  34 +++
 .../broadcom/brcm80211/brcmfmac/firmware.c    |  15 +-
 .../broadcom/brcm80211/brcmfmac/firmware.h    |   8 +-
 .../broadcom/brcm80211/brcmfmac/pcie.c        | 192 +++++++++++++++-
 .../broadcom/brcm80211/brcmfmac/sdio.c        |  27 ++-
 .../broadcom/brcm80211/include/brcm_hw_ids.h  |   3 +
 .../broadcom/brcm80211/include/brcmu_utils.h  |  13 ++
 include/linux/bcma/bcma.h                     |   1 +
 include/linux/mmc/sdio_ids.h                  |   1 +
 11 files changed, 497 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index d35262335eaf7..ae89d73eefb87 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -46,6 +46,8 @@
 #define SDIO_4373_FUNC2_BLOCKSIZE	256
 #define SDIO_435X_FUNC2_BLOCKSIZE	256
 #define SDIO_4329_FUNC2_BLOCKSIZE	128
+#define SDIO_CYW55572_FUNC2_BLOCKSIZE	256
+
 /* Maximum milliseconds to wait for F2 to come up */
 #define SDIO_WAIT_F2RDY	3000
 
@@ -917,6 +919,9 @@ int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
 	case SDIO_DEVICE_ID_BROADCOM_4329:
 		f2_blksz = SDIO_4329_FUNC2_BLOCKSIZE;
 		break;
+	case SDIO_DEVICE_ID_CYPRESS_55572:
+		f2_blksz = SDIO_CYW55572_FUNC2_BLOCKSIZE;
+		break;
 	default:
 		break;
 	}
@@ -996,6 +1001,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752, CYW),
 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359, CYW),
 	CYW_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439, CYW),
+	CYW_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_55572, CYW),
 	{ /* end: all zeroes */ }
 };
 MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
index 2ef92ef25517e..c5188a31c9efb 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -216,6 +216,32 @@ struct sbsocramregs {
 #define	ARMCR4_BSZ_MULT		8192
 #define	ARMCR4_BLK_1K_MASK	0x200
 
+/* CYW55572 dedicated space and RAM base */
+#define CYW55572_TCAM_SIZE	0x800
+#define CYW55572_TRXHDR_SIZE	0x2b4
+#define CYW55572_RAM_BASE	(0x370000 + \
+				 CYW55572_TCAM_SIZE + CYW55572_TRXHDR_SIZE)
+
+#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		250	/* msec */
+
+/* Bootloader handshake flags - dongle to host */
+#define BRCMF_BLHS_D2H_START			BIT(0)
+#define BRCMF_BLHS_D2H_READY			BIT(1)
+#define BRCMF_BLHS_D2H_STEADY			BIT(2)
+#define BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE	BIT(3)
+#define BRCMF_BLHS_D2H_VALDN_START		BIT(4)
+#define BRCMF_BLHS_D2H_VALDN_RESULT		BIT(5)
+#define BRCMF_BLHS_D2H_VALDN_DONE		BIT(6)
+
+/* 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)
+
 struct brcmf_core_priv {
 	struct brcmf_core pub;
 	u32 wrapbase;
@@ -501,6 +527,21 @@ char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len)
 	return buf;
 }
 
+static bool brcmf_chip_find_coreid(struct brcmf_chip_priv *ci, u16 coreid)
+{
+	struct brcmf_core_priv *core;
+
+	list_for_each_entry(core, &ci->cores, list) {
+		brcmf_dbg(TRACE, " core 0x%x:%-2d base 0x%08x wrap 0x%08x\n",
+			  core->pub.id, core->pub.rev, core->pub.base,
+			  core->wrapbase);
+		if (core->pub.id == coreid)
+			return true;
+	}
+
+	return false;
+}
+
 static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci,
 					      u16 coreid, u32 base,
 					      u32 wrapbase)
@@ -745,6 +786,8 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
 		return 0x352000;
 	case BRCM_CC_4387_CHIP_ID:
 		return 0x740000;
+	case CY_CC_55572_CHIP_ID:
+		return CYW55572_RAM_BASE;
 	default:
 		brcmf_err("unknown chip: %s\n", ci->pub.name);
 		break;
@@ -763,6 +806,9 @@ int brcmf_chip_get_raminfo(struct brcmf_chip *pub)
 	if (mem) {
 		mem_core = container_of(mem, struct brcmf_core_priv, pub);
 		ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core);
+		if (ci->pub.chip == CY_CC_55572_CHIP_ID)
+			ci->pub.ramsize -= (CYW55572_TCAM_SIZE +
+					    CYW55572_TRXHDR_SIZE);
 		ci->pub.rambase = brcmf_chip_tcm_rambase(ci);
 		if (ci->pub.rambase == INVALID_RAMBASE) {
 			brcmf_err("RAM base not provided with ARM CR4 core\n");
@@ -942,7 +988,8 @@ int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci)
 		/* need core with ports */
 		if (nmw + nsw == 0 &&
 		    id != BCMA_CORE_PMU &&
-		    id != BCMA_CORE_GCI)
+		    id != BCMA_CORE_GCI &&
+			id != BCMA_CORE_SR)
 			continue;
 
 		/* try to obtain register address info */
@@ -966,6 +1013,144 @@ u32 brcmf_chip_enum_base(u16 devid)
 	return SI_ENUM_BASE_DEFAULT;
 }
 
+static void brcmf_blhs_init(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	u32 addr;
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	addr = pub->blhs->h2d;
+	pub->blhs->write(chip->ctx, addr, 0);
+}
+
+static int brcmf_blhs_is_bootloader_ready(struct brcmf_chip_priv *chip)
+{
+	u32 regdata;
+	u32 addr;
+
+	addr = chip->pub.blhs->d2h;
+	SPINWAIT_MS((chip->pub.blhs->read(chip->ctx, addr) &
+		     BRCMF_BLHS_D2H_READY) == 0,
+		    BRCMF_BLHS_D2H_READY_TIMEOUT, BRCMF_BLHS_POLL_INTERVAL);
+
+	regdata = chip->pub.blhs->read(chip->ctx, addr);
+	if (!(regdata & BRCMF_BLHS_D2H_READY)) {
+		brcmf_err("Timeout waiting for bootloader ready\n");
+		return -EPERM;
+	}
+
+	return 0;
+}
+
+static int brcmf_blhs_prep_fw_download(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	u32 addr;
+	int err;
+
+	/* Host indication for bootloader to start the init */
+	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);
+
+	return 0;
+}
+
+static int brcmf_blhs_post_fw_download(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	u32 addr;
+	u32 regdata;
+
+	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");
+
+		/* 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;
+}
+
+static void brcmf_blhs_post_nvram_download(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	u32 addr;
+	u32 regdata;
+
+	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);
+}
+
+static int brcmf_blhs_chk_validation(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	u32 addr;
+	u32 regdata;
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	addr = pub->blhs->d2h;
+	SPINWAIT_MS((pub->blhs->read(chip->ctx, addr) &
+		     BRCMF_BLHS_D2H_VALDN_DONE) == 0,
+		    BRCMF_BLHS_D2H_VALDN_DONE_TIMEOUT,
+		    BRCMF_BLHS_POLL_INTERVAL);
+
+	regdata = pub->blhs->read(chip->ctx, addr);
+	if (!(regdata & BRCMF_BLHS_D2H_VALDN_DONE) ||
+	    !(regdata & BRCMF_BLHS_D2H_VALDN_RESULT)) {
+		brcmf_err("TRX image validation check failed\n");
+
+		/* Host notification 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;
+}
+
+static int brcmf_blhs_post_watchdog_reset(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	int err;
+
+	/* Host indication for bootloader to start the init */
+	brcmf_blhs_init(pub);
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	err = brcmf_blhs_is_bootloader_ready(chip);
+
+	return err;
+}
+
 static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
 {
 	struct brcmf_core *core;
@@ -1123,6 +1308,7 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,
 				     const struct brcmf_buscore_ops *ops)
 {
 	struct brcmf_chip_priv *chip;
+	struct brcmf_blhs *blhs;
 	int err = 0;
 
 	if (WARN_ON(!ops->read32))
@@ -1150,6 +1336,26 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,
 	if (err < 0)
 		goto fail;
 
+	blhs = NULL;
+	if (chip->ops->blhs_attach) {
+		err = chip->ops->blhs_attach(chip->ctx, &blhs,
+					     BRCMF_BLHS_D2H_READY,
+					     BRCMF_BLHS_D2H_READY_TIMEOUT,
+					     BRCMF_BLHS_POLL_INTERVAL);
+		if (err < 0)
+			goto fail;
+
+		if (blhs) {
+			blhs->init = brcmf_blhs_init;
+			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->chk_validation = brcmf_blhs_chk_validation;
+			blhs->post_wdreset = brcmf_blhs_post_watchdog_reset;
+		}
+	}
+	chip->pub.blhs = blhs;
+
 	err = brcmf_chip_recognition(chip);
 	if (err < 0)
 		goto fail;
@@ -1176,6 +1382,7 @@ void brcmf_chip_detach(struct brcmf_chip *pub)
 		list_del(&core->list);
 		kfree(core);
 	}
+	kfree(pub->blhs);
 	kfree(chip);
 }
 
@@ -1309,7 +1516,8 @@ brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip)
 	int i;
 	struct brcmf_core *core;
 
-	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
+	if (!chip->pub.blhs)
+		brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
 
 	/* Disable the cores only and let the firmware enable them.
 	 * Releasing reset ourselves breaks BCM4387 in weird ways.
@@ -1456,6 +1664,8 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
 		reg = chip->ops->read32(chip->ctx, addr);
 		return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
 			       PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
+	case CY_CC_55572_CHIP_ID:
+		return brcmf_chip_find_coreid(chip, BCMA_CORE_SR);
 	default:
 		addr = CORE_CC_REG(pmu->base, pmucapabilities_ext);
 		reg = chip->ops->read32(chip->ctx, addr);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
index d69f101f58344..0a00fb9d7632e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
@@ -10,6 +10,8 @@
 #define CORE_CC_REG(base, field) \
 		(base + offsetof(struct chipcregs, field))
 
+struct brcmf_blhs;
+
 /**
  * struct brcmf_chip - chip level information.
  *
@@ -24,6 +26,7 @@
  * @ramsize: amount of RAM on chip including retention.
  * @srsize: amount of retention RAM on chip.
  * @name: string representation of the chip identifier.
+ * @blhs: bootlooder handshake handle.
  */
 struct brcmf_chip {
 	u32 chip;
@@ -37,6 +40,7 @@ struct brcmf_chip {
 	u32 ramsize;
 	u32 srsize;
 	char name[12];
+	struct brcmf_blhs *blhs;
 };
 
 /**
@@ -61,6 +65,7 @@ struct brcmf_core {
  * @setup: bus-specific core setup.
  * @active: chip becomes active.
  *	The callback should use the provided @rstvec when non-zero.
+ * @blhs_attach: attach bootloader handshake handle
  */
 struct brcmf_buscore_ops {
 	u32 (*read32)(void *ctx, u32 addr);
@@ -69,6 +74,35 @@ 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);
+};
+
+/**
+ * struct brcmf_blhs - bootloader handshake handle related information.
+ *
+ * @d2h: offset of dongle to host register for the handshake.
+ * @h2d: offset of host to dongle register for the handshake.
+ * @init: bootloader handshake initialization.
+ * @prep_fwdl: handshake before firmware download.
+ * @post_fwdl: handshake after firmware download.
+ * @post_nvramdl: handshake after nvram download.
+ * @chk_validation: handshake for firmware validation check.
+ * @post_wdreset: handshake after watchdog reset.
+ * @read: read value with register offset for the handshake.
+ * @write: write value with register offset for the handshake.
+ */
+struct brcmf_blhs {
+	u32 d2h;
+	u32 h2d;
+	void (*init)(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 (*chk_validation)(struct brcmf_chip *pub);
+	int (*post_wdreset)(struct brcmf_chip *pub);
+	u32 (*read)(void *ctx, u32 addr);
+	void (*write)(void *ctx, u32 addr, u32 value);
 };
 
 int brcmf_chip_get_raminfo(struct brcmf_chip *pub);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index 83f8ed7d00f96..1d5be3ce51ccf 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -527,7 +527,8 @@ static void brcmf_fw_free_request(struct brcmf_fw_request *req)
 	int i;
 
 	for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
-		if (item->type == BRCMF_FW_TYPE_BINARY)
+		if (item->type == BRCMF_FW_TYPE_BINARY ||
+		    item->type == BRCMF_FW_TYPE_TRXSE)
 			release_firmware(item->binary);
 		else if (item->type == BRCMF_FW_TYPE_NVRAM)
 			brcmf_fw_nvram_free(item->nv_data.data);
@@ -599,6 +600,7 @@ static int brcmf_fw_complete_request(const struct firmware *fw,
 		ret = brcmf_fw_request_nvram_done(fw, fwctx);
 		break;
 	case BRCMF_FW_TYPE_BINARY:
+	case BRCMF_FW_TYPE_TRXSE:
 		if (fw)
 			cur->binary = fw;
 		else
@@ -672,8 +674,19 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,
 static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
 {
 	struct brcmf_fw *fwctx = ctx;
+	struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos];
+	char alt_path[BRCMF_FW_NAME_LEN];
 	int ret;
 
+	if (!fw && cur->type == BRCMF_FW_TYPE_TRXSE) {
+		strscpy(alt_path, cur->path, BRCMF_FW_NAME_LEN);
+		/* strip 'se' from .trxse at the end */
+		alt_path[strlen(alt_path) - 2] = 0;
+		ret = request_firmware(&fw, alt_path, fwctx->dev);
+		if (!ret)
+			cur->path = alt_path;
+	}
+
 	ret = brcmf_fw_complete_request(fw, fwctx);
 
 	while (ret == 0 && ++fwctx->curpos < fwctx->req->n_items) {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
index 4002d326fd21b..ab709babd649a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
@@ -41,6 +41,11 @@ 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_TRXSE_DEF(fw_name, fw_base) \
+static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \
+	BRCMF_FW_DEFAULT_PATH fw_base; \
+MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw_base ".trxse")
+
 #define BRCMF_FW_ENTRY(chipid, mask, name) \
 	{ chipid, mask, BRCM_ ## name ## _FIRMWARE_BASENAME }
 
@@ -48,7 +53,8 @@ void brcmf_fw_nvram_free(void *nvram);
 
 enum brcmf_fw_type {
 	BRCMF_FW_TYPE_BINARY,
-	BRCMF_FW_TYPE_NVRAM
+	BRCMF_FW_TYPE_NVRAM,
+	BRCMF_FW_TYPE_TRXSE
 };
 
 struct brcmf_fw_item {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 058a742d17eda..15b045ab477ca 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -71,6 +71,7 @@ BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie");
 BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");
 BRCMF_FW_CLM_DEF(4378B3, "brcmfmac4378b3-pcie");
 BRCMF_FW_CLM_DEF(4387C2, "brcmfmac4387c2-pcie");
+CY_FW_TRXSE_DEF(55572, "cyfmac55572-pcie");
 
 /* firmware config files */
 MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");
@@ -109,6 +110,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
 	BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0x0000000F, 4378B1), /* revision ID 3 */
 	BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFE0, 4378B3), /* revision ID 5 */
 	BRCMF_FW_ENTRY(BRCM_CC_4387_CHIP_ID, 0xFFFFFFFF, 4387C2), /* revision ID 7 */
+	BRCMF_FW_ENTRY(CY_CC_55572_CHIP_ID, 0xFFFFFFFF, 55572),
 };
 
 #define BRCMF_PCIE_FW_UP_TIMEOUT		5000 /* msec */
@@ -121,7 +123,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
 #define	BRCMF_PCIE_BAR0_WRAPPERBASE		0x70
 
 #define BRCMF_PCIE_BAR0_WRAPBASE_DMP_OFFSET	0x1000
-#define BRCMF_PCIE_BARO_PCIE_ENUM_OFFSET	0x2000
+#define BRCMF_PCIE_BAR0_PCIE_ENUM_OFFSET	0x2000
+#define BRCMF_CYW55572_PCIE_BAR0_PCIE_ENUM_OFFSET	0x3000
 
 #define BRCMF_PCIE_ARMCR4REG_BANKIDX		0x40
 #define BRCMF_PCIE_ARMCR4REG_BANKPDA		0x4C
@@ -139,6 +142,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
 #define BRCMF_PCIE_PCIE2REG_CONFIGDATA		0x124
 #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0	0x140
 #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1	0x144
+#define BRCMF_PCIE_PCIE2REG_DAR_D2H_MSG_0	0xA80
+#define BRCMF_PCIE_PCIE2REG_DAR_H2D_MSG_0	0xA90
 
 #define BRCMF_PCIE_64_PCIE2REG_INTMASK		0xC14
 #define BRCMF_PCIE_64_PCIE2REG_MAILBOXINT	0xC30
@@ -271,18 +276,32 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
 #define BRCMF_PCIE_CFGREG_MSI_ADDR_L		0x5C
 #define BRCMF_PCIE_CFGREG_MSI_ADDR_H		0x60
 #define BRCMF_PCIE_CFGREG_MSI_DATA		0x64
+#define BRCMF_PCIE_CFGREG_REVID			0x6C
 #define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL	0xBC
 #define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2	0xDC
 #define BRCMF_PCIE_CFGREG_RBAR_CTRL		0x228
 #define BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1	0x248
 #define BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG	0x4E0
 #define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG	0x4F4
+#define BRCMF_PCIE_CFGREG_REVID_SECURE_MODE	BIT(31)
 #define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB	3
 
 /* Magic number at a magic location to find RAM size */
 #define BRCMF_RAMSIZE_MAGIC			0x534d4152	/* SMAR */
 #define BRCMF_RAMSIZE_OFFSET			0x6c
 
+#define BRCMF_ENTROPY_SEED_LEN		64u
+#define BRCMF_ENTROPY_NONCE_LEN		16u
+#define BRCMF_ENTROPY_HOST_LEN		(BRCMF_ENTROPY_SEED_LEN + \
+					 BRCMF_ENTROPY_NONCE_LEN)
+#define BRCMF_NVRAM_OFFSET_TCM		4u
+#define BRCMF_NVRAM_COMPRS_FACTOR	4u
+#define BRCMF_NVRAM_RNG_SIGNATURE	0xFEEDC0DEu
+
+struct brcmf_rand_metadata {
+	__le32 signature;
+	__le32 count;
+};
 
 struct brcmf_pcie_console {
 	u32 base_addr;
@@ -679,9 +698,15 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
 			       val);
 
 	/* Watchdog reset */
+	if (devinfo->ci->blhs)
+		devinfo->ci->blhs->init(devinfo->ci);
 	brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
 	WRITECC32(devinfo, watchdog, 4);
 	msleep(100);
+	if (devinfo->ci->blhs)
+		if (devinfo->ci->blhs->post_wdreset(devinfo->ci))
+			return;
+
 
 	/* Restore ASPM */
 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
@@ -722,6 +747,9 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
 
 static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)
 {
+	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
+	int err = 0;
+
 	if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
 		brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4);
 		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
@@ -733,7 +761,14 @@ static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)
 		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,
 				       0);
 	}
-	return 0;
+
+	if (devinfo->ci->blhs) {
+		err = devinfo->ci->blhs->prep_fwdl(devinfo->ci);
+		if (err)
+			brcmf_err(bus, "FW download preparation failed");
+	}
+
+	return err;
 }
 
 
@@ -747,8 +782,13 @@ static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo,
 		brcmf_chip_resetcore(core, 0, 0, 0);
 	}
 
-	if (!brcmf_chip_set_active(devinfo->ci, resetintr))
-		return -EIO;
+	if (devinfo->ci->blhs) {
+		devinfo->ci->blhs->post_nvramdl(devinfo->ci);
+	} else {
+		if (!brcmf_chip_set_active(devinfo->ci, resetintr))
+			return -EIO;
+	}
+
 	return 0;
 }
 
@@ -1608,6 +1648,27 @@ brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info *devinfo, u8 *data,
 }
 
 
+static void
+brcmf_pcie_write_rand(struct brcmf_pciedev_info *devinfo, u32 nvram_csm)
+{
+	struct brcmf_rand_metadata rand_data;
+	u8 rand_buf[BRCMF_ENTROPY_HOST_LEN];
+	u32 count = BRCMF_ENTROPY_HOST_LEN;
+	u32 address;
+
+	address = devinfo->ci->rambase +
+		  (devinfo->ci->ramsize - BRCMF_NVRAM_OFFSET_TCM) -
+		  ((nvram_csm & 0xffff) * BRCMF_NVRAM_COMPRS_FACTOR) -
+		  sizeof(rand_data);
+	memset(rand_buf, 0, BRCMF_ENTROPY_HOST_LEN);
+	rand_data.signature = cpu_to_le32(BRCMF_NVRAM_RNG_SIGNATURE);
+	rand_data.count = cpu_to_le32(count);
+	memcpy_toio(devinfo->tcm + address, &rand_data, sizeof(rand_data));
+	address -= count;
+	get_random_bytes(rand_buf, count);
+	memcpy_toio(devinfo->tcm + address, rand_buf, count);
+}
+
 static int
 brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
 			       u32 sharedram_addr)
@@ -1693,6 +1754,8 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
 	int err;
 	u32 address;
 	u32 resetintr;
+	u32 nvram_lenw;
+	u32 nvram_csm;
 
 	brcmf_dbg(PCIE, "Halt ARM.\n");
 	err = brcmf_pcie_enter_download_state(devinfo);
@@ -1711,16 +1774,40 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
 	resetintr = get_unaligned_le32(fw->data);
 	release_firmware(fw);
 
-	/* reset last 4 bytes of RAM address. to be used for shared
-	 * area. This identifies when FW is running
-	 */
-	brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);
+	if (devinfo->ci->blhs) {
+		err = devinfo->ci->blhs->post_fwdl(devinfo->ci);
+		if (err) {
+			brcmf_err(bus, "FW download failed, err=%d\n", err);
+			return err;
+		}
+
+		err = devinfo->ci->blhs->chk_validation(devinfo->ci);
+		if (err) {
+			brcmf_err(bus, "FW valication failed, err=%d\n", err);
+			return err;
+		}
+	} else {
+		/* reset last 4 bytes of RAM address. to be used for shared
+		 * area. This identifies when FW is running
+		 */
+		brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);
+	}
 
 	if (nvram) {
 		brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);
 		address = devinfo->ci->rambase + devinfo->ci->ramsize -
 			  nvram_len;
+
+		if (devinfo->ci->blhs)
+			address -= 4;
 		memcpy_toio(devinfo->tcm + address, nvram, nvram_len);
+
+		/* Convert nvram_len to words to determine the length token */
+		nvram_lenw = nvram_len / 4;
+		/* subtract word used to store the token itself on non-blhs devices */
+		if (!devinfo->ci->blhs)
+			nvram_lenw -= 1;
+		nvram_csm = (~nvram_lenw << 16) | (nvram_lenw & 0x0000FFFF);
 		brcmf_fw_nvram_free(nvram);
 
 		if (devinfo->otp.valid) {
@@ -1743,10 +1830,20 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
 			brcmf_pcie_provide_random_bytes(devinfo, address);
 		}
 	} else {
+		nvram_csm = 0;
 		brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
 			  devinfo->nvram_name);
 	}
 
+	if (devinfo->ci->chip == CY_CC_55572_CHIP_ID) {
+		/* Write the length token to the last word of RAM address */
+		brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4,
+				       (u32)cpu_to_le32(nvram_csm));
+
+		/* Write random numbers to TCM for randomizing heap address */
+		brcmf_pcie_write_rand(devinfo, nvram_csm);
+	}
+
 	sharedram_addr_written = brcmf_pcie_read_ram32(devinfo,
 						       devinfo->ci->ramsize -
 						       4);
@@ -1837,6 +1934,21 @@ static void brcmf_pcie_release_resource(struct brcmf_pciedev_info *devinfo)
 	pci_disable_device(devinfo->pdev);
 }
 
+static u32 brcmf_pcie_buscore_blhs_read(void *ctx, u32 reg_offset)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	return brcmf_pcie_read_reg32(devinfo, reg_offset);
+}
+
+static void brcmf_pcie_buscore_blhs_write(void *ctx, u32 reg_offset, u32 value)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	brcmf_pcie_write_reg32(devinfo, reg_offset, value);
+}
 
 static u32 brcmf_pcie_buscore_prep_addr(const struct pci_dev *pdev, u32 addr)
 {
@@ -1907,12 +2019,63 @@ 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)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
+	struct brcmf_blhs *blhsh;
+	u32 regdata;
+	u32 pcie_enum;
+	u32 addr;
+
+	if (devinfo->pdev->vendor != CY_PCIE_VENDOR_ID_CYPRESS)
+		return 0;
+
+	pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_CFGREG_REVID, &regdata);
+	if (regdata & BRCMF_PCIE_CFGREG_REVID_SECURE_MODE) {
+		blhsh = kzalloc(sizeof(*blhsh), GFP_KERNEL);
+		if (!blhsh)
+			return -ENOMEM;
+
+		blhsh->d2h = BRCMF_PCIE_PCIE2REG_DAR_D2H_MSG_0;
+		blhsh->h2d = BRCMF_PCIE_PCIE2REG_DAR_H2D_MSG_0;
+		blhsh->read = brcmf_pcie_buscore_blhs_read;
+		blhsh->write = brcmf_pcie_buscore_blhs_write;
+
+		/* Host indication for bootloarder to start the init */
+		if (devinfo->pdev->device == CY_PCIE_55572_DEVICE_ID)
+			pcie_enum = BRCMF_CYW55572_PCIE_BAR0_PCIE_ENUM_OFFSET;
+		else
+			pcie_enum = BRCMF_PCIE_BAR0_PCIE_ENUM_OFFSET;
+
+		pci_read_config_dword(devinfo->pdev, PCI_BASE_ADDRESS_0,
+				      &regdata);
+		addr = regdata + pcie_enum + blhsh->h2d;
+		brcmf_pcie_buscore_write32(ctx, addr, 0);
+
+		addr = regdata + pcie_enum + blhsh->d2h;
+		SPINWAIT_MS((brcmf_pcie_buscore_read32(ctx, addr) & flag) == 0,
+			    timeout, interval);
+		regdata = brcmf_pcie_buscore_read32(ctx, addr);
+		if (!(regdata & flag)) {
+			brcmf_err(bus, "Timeout waiting for bootloader ready\n");
+			kfree(blhsh);
+			return -EPERM;
+		}
+		*blhs = blhsh;
+	}
+
+	return 0;
+}
+
 static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
 	.prepare = brcmf_pcie_buscoreprep,
 	.reset = brcmf_pcie_buscore_reset,
 	.activate = brcmf_pcie_buscore_activate,
 	.read32 = brcmf_pcie_buscore_read32,
 	.write32 = brcmf_pcie_buscore_write32,
+	.blhs_attach = brcmf_pcie_buscore_blhs_attach,
 };
 
 #define BRCMF_OTP_SYS_VENDOR	0x15
@@ -2243,6 +2406,9 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
 		{ ".txcap_blob", devinfo->txcap_name },
 	};
 
+	if (devinfo->ci->blhs)
+		fwnames[BRCMF_PCIE_FW_CODE].extension = ".trxse";
+
 	fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
 				       brcmf_pcie_fwnames,
 				       ARRAY_SIZE(brcmf_pcie_fwnames),
@@ -2250,7 +2416,10 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
 	if (!fwreq)
 		return NULL;
 
-	fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
+	if (devinfo->ci->blhs)
+		fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_TRXSE;
+	else
+		fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
 	fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
 	fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
 	fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
@@ -2678,6 +2847,9 @@ static const struct dev_pm_ops brcmf_pciedrvr_pm = {
 		BRCMF_FWVENDOR_ ## fw_vend \
 	}
 
+#define BRCMF_PCIE_DEVICE_CY(dev_id)	{ CY_PCIE_VENDOR_ID_CYPRESS, dev_id,\
+	PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
+
 static const struct pci_device_id brcmf_pcie_devid_table[] = {
 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID, WCC),
 	BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355, WCC),
@@ -2706,7 +2878,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = {
 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC),
 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC),
 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC),
-
+	BRCMF_PCIE_DEVICE_CY(CY_PCIE_55572_DEVICE_ID),
 	{ /* end: all zeroes */ }
 };
 
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 08881e366cae2..3bb03de1c2d29 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -59,6 +59,10 @@
 #define CY_435X_F2_WATERMARK	0x40
 #define CY_435X_F1_MESBUSYCTRL	(CY_435X_F2_WATERMARK | \
 				 SBSDIO_MESBUSYCTRL_ENAB)
+#define CYW55572_F2_WATERMARK	0x40
+#define CYW55572_MES_WATERMARK	0x40
+#define CYW55572_F1_MESBUSYCTRL	(CYW55572_MES_WATERMARK | \
+				 SBSDIO_MESBUSYCTRL_ENAB)
 
 #ifdef DEBUG
 
@@ -626,6 +630,7 @@ BRCMF_FW_DEF(4359, "brcmfmac4359-sdio");
 BRCMF_FW_CLM_DEF(4373, "brcmfmac4373-sdio");
 BRCMF_FW_CLM_DEF(43012, "brcmfmac43012-sdio");
 BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-sdio");
+CY_FW_TRXSE_DEF(55572, "cyfmac55572-sdio");
 
 /* firmware config files */
 MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.txt");
@@ -658,7 +663,8 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
 	BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373),
 	BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012),
 	BRCMF_FW_ENTRY(CY_CC_43439_CHIP_ID, 0xFFFFFFFF, 43439),
-	BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752)
+	BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752),
+	BRCMF_FW_ENTRY(CY_CC_55572_CHIP_ID, 0xFFFFFFFF, 55572)
 };
 
 #define TXCTL_CREDITS	2
@@ -719,7 +725,8 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 	 * fail. Thereby just bailing out immediately after clearing KSO
 	 * bit, to avoid polling of KSO bit.
 	 */
-	if (!on && bus->ci->chip == CY_CC_43012_CHIP_ID)
+	if (!on && (bus->ci->chip == CY_CC_43012_CHIP_ID ||
+		    bus->ci->chip == CY_CC_55572_CHIP_ID))
 		return err;
 
 	if (on) {
@@ -3435,7 +3442,8 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
 static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus)
 {
 	if (bus->ci->chip == CY_CC_43012_CHIP_ID ||
-	    bus->ci->chip == CY_CC_43752_CHIP_ID)
+	    bus->ci->chip == CY_CC_43752_CHIP_ID ||
+	    bus->ci->chip == CY_CC_55572_CHIP_ID)
 		return true;
 	else
 		return false;
@@ -4352,6 +4360,19 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
 			brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
 					   CY_435X_F1_MESBUSYCTRL, &err);
 			break;
+		case SDIO_DEVICE_ID_CYPRESS_55572:
+			brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
+				  CYW55572_F2_WATERMARK);
+			brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
+					   CYW55572_F2_WATERMARK, &err);
+			devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
+						   &err);
+			devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
+			brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
+					   &err);
+			brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
+					   CYW55572_F1_MESBUSYCTRL, &err);
+			break;
 		default:
 			brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
 					   DEFAULT_F2_WATERMARK, &err);
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
index 44684bf1b9acc..fc1757c505312 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
@@ -14,6 +14,7 @@
 #define BRCM_USB_VENDOR_ID_LINKSYS	0x13b1
 #define CY_USB_VENDOR_ID_CYPRESS	0x04b4
 #define BRCM_PCIE_VENDOR_ID_BROADCOM	PCI_VENDOR_ID_BROADCOM
+#define CY_PCIE_VENDOR_ID_CYPRESS	0x12be
 
 /* Chipcommon Core Chip IDs */
 #define BRCM_CC_43143_CHIP_ID		43143
@@ -59,6 +60,7 @@
 #define CY_CC_43012_CHIP_ID		43012
 #define CY_CC_43439_CHIP_ID		43439
 #define CY_CC_43752_CHIP_ID		43752
+#define CY_CC_55572_CHIP_ID		0xd908
 
 /* USB Device IDs */
 #define BRCM_USB_43143_DEVICE_ID	0xbd1e
@@ -97,6 +99,7 @@
 #define BRCM_PCIE_4377_DEVICE_ID	0x4488
 #define BRCM_PCIE_4378_DEVICE_ID	0x4425
 #define BRCM_PCIE_4387_DEVICE_ID	0x4433
+#define CY_PCIE_55572_DEVICE_ID		0xbd31
 
 /* brcmsmac IDs */
 #define BCM4313_D11N2G_ID	0x4727	/* 4313 802.11n 2.4G device */
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h
index 9465323286673..48791ac87496d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h
@@ -21,6 +21,19 @@
 	} \
 }
 
+/* Spin at most 'ms' milliseconds with polling interval 'interval' milliseconds
+ * while 'exp' is true. Caller should explicitly test 'exp' when this completes
+ * and take appropriate error action if 'exp' is still true.
+ */
+#define SPINWAIT_MS(exp, ms, interval) { \
+	typeof(interval) interval_ = (interval); \
+	uint countdown = (ms) + (interval_ - 1U); \
+	while ((exp) && (countdown >= interval_)) { \
+		msleep(interval_); \
+		countdown -= interval_; \
+	} \
+}
+
 /* osl multi-precedence packet queue */
 #define PKTQ_LEN_DEFAULT        128	/* Max 128 packets */
 #define PKTQ_MAX_PREC           16	/* Maximum precedence levels */
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 60b94b944e9f1..fe1cb2aeaef38 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -154,6 +154,7 @@ struct bcma_host_ops {
 #define BCMA_CORE_USB30_DEV		0x83D
 #define BCMA_CORE_ARM_CR4		0x83E
 #define BCMA_CORE_GCI			0x840
+#define BCMA_CORE_SR			0x841
 #define BCMA_CORE_CMEM			0x846	/* CNDS DDR2/3 memory controller */
 #define BCMA_CORE_ARM_CA7		0x847
 #define BCMA_CORE_SYS_MEM		0x849
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index 7cddfdac2f576..8ba3f25217a21 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -80,6 +80,7 @@
 
 #define SDIO_VENDOR_ID_CYPRESS			0x04b4
 #define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439	0xbd3d
+#define SDIO_DEVICE_ID_CYPRESS_55572		0xbd31
 
 #define SDIO_VENDOR_ID_MARVELL			0x02df
 #define SDIO_DEVICE_ID_MARVELL_LIBERTAS		0x9103
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 1/2] wifi: brcmfmac: add support for TRX firmware download
  2024-09-09 20:31 [PATCH v2 1/2] wifi: brcmfmac: add support for TRX firmware download Marek Vasut
  2024-09-09 20:31 ` [PATCH v2 2/2] wifi: brcmfmac: add support for CYW55572 PCIe chipset Marek Vasut
@ 2024-09-14  6:24 ` Arend van Spriel
  1 sibling, 0 replies; 4+ messages in thread
From: Arend van Spriel @ 2024-09-14  6:24 UTC (permalink / raw)
  To: Marek Vasut, linux-wireless
  Cc: Chung-Hsien Hsu, Chung-Hsien Hsu, Dr. David Alan Gilbert,
	Gustavo A. R. Silva, Rafał Miłecki, Bjorn Helgaas,
	Carter Chen, Double Lo, Duoming Zhou, Erick Archer, Kalle Valo,
	Kees Cook, Krzysztof Kozlowski, Mathias Krause, Matthias Brugger,
	Owen Huang, Ulf Hansson, brcm80211-dev-list.pdl, brcm80211

On 9/9/2024 10:31 PM, Marek Vasut wrote:
> From: Chung-Hsien Hsu <stanley.hsu@cypress.com>
> 
> Add support to download TRX firmware for PCIe and SDIO.

Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com>

The sob tag is a certification by that person so strictly speaking you 
can not add this line. Don't know what is best here. I will leave it to 
Kalle to decide.

> Signed-off-by: Chung-Hsien Hsu <chung-hsien.hsu@infineon.com>
> Signed-off-by: Marek Vasut <marex@denx.de> # Upport to current linux-next
> ---
> NOTE: This is downstream upport from
>        https://github.com/Infineon/ifx-wireless-drivers/
>        branch RTM/v5.15.58-Indrik / tag release-v5.15.58-2024_0514
> - ba34bf4816f9 ("brcmfmac: add support for TRX firmware download")
> ---
> Cc: "Dr. David Alan Gilbert" <linux@treblig.org>
> Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
> Cc: "Rafał Miłecki" <zajec5@gmail.com>
> Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Carter Chen <carter.chen@infineon.com>
> Cc: Chung-Hsien Hsu <stanley.hsu@cypress.com>
> Cc: Double Lo <Double.Lo@infineon.com>
> Cc: Duoming Zhou <duoming@zju.edu.cn>
> Cc: Erick Archer <erick.archer@outlook.com>
> Cc: Kalle Valo <kvalo@kernel.org>
> Cc: Kees Cook <kees@kernel.org>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Cc: Mathias Krause <minipli@grsecurity.net>
> Cc: Matthias Brugger <mbrugger@suse.com>
> Cc: Owen Huang <Owen.Huang@infineon.com>
> Cc: Ulf Hansson <ulf.hansson@linaro.org>
> Cc: brcm80211-dev-list.pdl@broadcom.com
> Cc: brcm80211@lists.linux.dev
> Cc: linux-wireless@vger.kernel.org
> ---
> V2: Include SoB line from Chung-Hsien with both cypress and infineon address
> ---
>   .../broadcom/brcm80211/brcmfmac/pcie.c        | 12 +++++-
>   .../broadcom/brcm80211/brcmfmac/sdio.c        | 20 +++++++---
>   .../broadcom/brcm80211/brcmfmac/trxhdr.h      | 38 +++++++++++++++++++
>   3 files changed, 63 insertions(+), 7 deletions(-)
>   create mode 100644 drivers/net/wireless/broadcom/brcm80211/brcmfmac/trxhdr.h
> 
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
> index ce482a3877e90..058a742d17eda 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
> @@ -42,6 +42,7 @@
>   #include "chip.h"
>   #include "core.h"
>   #include "common.h"
> +#include "trxhdr.h"

Maybe the definitions can simply be put in firmware.h as it is closely 
related.

>   
>   enum brcmf_pcie_state {
> @@ -1684,6 +1685,8 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
>   					u32 nvram_len)
>   {
>   	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
> +	struct trx_header_le *trx = (struct trx_header_le *)fw->data;
> +	u32 fw_size;
>   	u32 sharedram_addr;
>   	u32 sharedram_addr_written;
>   	u32 loop_counter;
> @@ -1697,8 +1700,13 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
>   		return err;
>   
>   	brcmf_dbg(PCIE, "Download FW %s\n", devinfo->fw_name);
> -	memcpy_toio(devinfo->tcm + devinfo->ci->rambase,
> -		    (void *)fw->data, fw->size);
> +	address = devinfo->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);

trx->len needs to be validated against fw->size and return an error, eg. 
-EINVAL, if it fails.

> +	}
> +	memcpy_toio(devinfo->tcm + address, (void *)fw->data, fw_size);
>   
>   	resetintr = get_unaligned_le32(fw->data);
>   	release_firmware(fw);
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> index 1461dc453ac22..08881e366cae2 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> @@ -35,6 +35,7 @@
>   #include "core.h"
>   #include "common.h"
>   #include "bcdc.h"
> +#include "trxhdr.h"
>   
>   #define DCMD_RESP_TIMEOUT	msecs_to_jiffies(2500)
>   #define CTL_DONE_TIMEOUT	msecs_to_jiffies(2500)
> @@ -3346,17 +3347,26 @@ brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr,
>   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;
>   	int err;
>   
>   	brcmf_dbg(TRACE, "Enter\n");
>   
> -	err = brcmf_sdiod_ramrw(bus->sdiodev, true, bus->ci->rambase,
> -				(u8 *)fw->data, fw->size);
> +	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);

same here.

> +	}
> +	err = brcmf_sdiod_ramrw(bus->sdiodev, true, address,
> +				(u8 *)fw->data, fw_size);
>   	if (err)
>   		brcmf_err("error %d on writing %d membytes at 0x%08x\n",
> -			  err, (int)fw->size, bus->ci->rambase);
> -	else if (!brcmf_sdio_verifymemory(bus->sdiodev, bus->ci->rambase,
> -					  (u8 *)fw->data, fw->size))
> +			  err, (int)fw_size, address);
> +	else if (!brcmf_sdio_verifymemory(bus->sdiodev, address,
> +					  (u8 *)fw->data, fw_size))
>   		err = -EIO;
>   
>   	return err;
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/trxhdr.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/trxhdr.h
> new file mode 100644
> index 0000000000000..0411c7c7ffb99
> --- /dev/null
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/trxhdr.h
> @@ -0,0 +1,38 @@

[...]

> +struct trx_header_le {
> +	__le32 magic;		/* "HDR0" */
> +	__le32 len;		/* Length of file including header */
> +	__le32 crc32;		/* CRC from flag_version to end of file */
> +	__le32 flag_version;	/* 0:15 flags, 16:31 version */

Let's make this two separate __le16 fields as the comment does.

> +	__le32 offsets[TRX_MAX_OFFSET];	/* Offsets of partitions */
> +};
> +
> +#endif /* BRCMFMAC_TRXHDR_H */


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 2/2] wifi: brcmfmac: add support for CYW55572 PCIe chipset
  2024-09-09 20:31 ` [PATCH v2 2/2] wifi: brcmfmac: add support for CYW55572 PCIe chipset Marek Vasut
@ 2024-09-14 12:04   ` Arend van Spriel
  0 siblings, 0 replies; 4+ messages in thread
From: Arend van Spriel @ 2024-09-14 12:04 UTC (permalink / raw)
  To: Marek Vasut, linux-wireless
  Cc: Chung-Hsien Hsu, Chung-Hsien Hsu, Carter Chen, Owen Huang,
	Dr. David Alan Gilbert, Gustavo A. R. Silva,
	Rafał Miłecki, Bjorn Helgaas, Double Lo, Duoming Zhou,
	Erick Archer, Kalle Valo, Kees Cook, Krzysztof Kozlowski,
	Mathias Krause, Matthias Brugger, Ulf Hansson,
	brcm80211-dev-list.pdl, brcm80211

On 9/9/2024 10:31 PM, Marek Vasut wrote:
> From: Chung-Hsien Hsu <stanley.hsu@cypress.com>
> 
> CYW55572 is a 2x2 dual-band 802.11a/b/g/n/ac/ax chipset with 20/40/80MHz
> channel support. It is a WLAN+BT combo device with WLAN secure boot support.
> The CYW55572 used to be labeled CYW55560.

Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com>

Same remark here as in the first patch of this series.

> Signed-off-by: Chung-Hsien Hsu <chung-hsien.hsu@infineon.com>
> Signed-off-by: Carter Chen <carter.chen@infineon.com>
> Signed-off-by: Owen Huang <Owen.Huang@infineon.com>
> Signed-off-by: Marek Vasut <marex@denx.de> # Upport to current linux-next
> ---
> NOTE: This is squashed from downstream upports from
>        https://github.com/Infineon/ifx-wireless-drivers/
>        branch RTM/v5.15.58-Indrik / tag release-v5.15.58-2024_0514
> - 8a41d39f6290 ("brcmfmac: add Cypress PCIe vendor ID")
> - 12f74eba2569 ("brcmfmac: add support for CYW55560 PCIe chipset")
> - ea4e4056a3f8 ("brcmfmac: update firmware loading name for CY5557x")
> - ee322201fe11 ("brcmfmac: use SR core id to decide SR capability for CY55572")
> - 0a47ed7f3678 ("brcmfmac: Fix invalid RAM address warning for PCIE platforms")

This patch is a bit large and covering multiple concepts. At least the 
bootloader handshake implementation is worth a separate patch I would 
say. I skipped the related stuff for now.

> ---
> Cc: "Dr. David Alan Gilbert" <linux@treblig.org>
> Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
> Cc: "Rafał Miłecki" <zajec5@gmail.com>
> Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Carter Chen <carter.chen@infineon.com>
> Cc: Chung-Hsien Hsu <stanley.hsu@cypress.com>
> Cc: Double Lo <Double.Lo@infineon.com>
> Cc: Duoming Zhou <duoming@zju.edu.cn>
> Cc: Erick Archer <erick.archer@outlook.com>
> Cc: Kalle Valo <kvalo@kernel.org>
> Cc: Kees Cook <kees@kernel.org>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Cc: Mathias Krause <minipli@grsecurity.net>
> Cc: Matthias Brugger <mbrugger@suse.com>
> Cc: Owen Huang <Owen.Huang@infineon.com>
> Cc: Ulf Hansson <ulf.hansson@linaro.org>
> Cc: brcm80211-dev-list.pdl@broadcom.com
> Cc: brcm80211@lists.linux.dev
> Cc: linux-wireless@vger.kernel.org
> ---
> V2: - Fix up build warnings related to use of u32 instead of __le32
>      - Include SoB line from Chung-Hsien with both cypress and infineon address
> ---
>   .../broadcom/brcm80211/brcmfmac/bcmsdh.c      |   6 +
>   .../broadcom/brcm80211/brcmfmac/chip.c        | 214 +++++++++++++++++-
>   .../broadcom/brcm80211/brcmfmac/chip.h        |  34 +++
>   .../broadcom/brcm80211/brcmfmac/firmware.c    |  15 +-
>   .../broadcom/brcm80211/brcmfmac/firmware.h    |   8 +-
>   .../broadcom/brcm80211/brcmfmac/pcie.c        | 192 +++++++++++++++-
>   .../broadcom/brcm80211/brcmfmac/sdio.c        |  27 ++-
>   .../broadcom/brcm80211/include/brcm_hw_ids.h  |   3 +
>   .../broadcom/brcm80211/include/brcmu_utils.h  |  13 ++
>   include/linux/bcma/bcma.h                     |   1 +
>   include/linux/mmc/sdio_ids.h                  |   1 +
>   11 files changed, 497 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
> index d35262335eaf7..ae89d73eefb87 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
> @@ -46,6 +46,8 @@
>   #define SDIO_4373_FUNC2_BLOCKSIZE	256
>   #define SDIO_435X_FUNC2_BLOCKSIZE	256
>   #define SDIO_4329_FUNC2_BLOCKSIZE	128
> +#define SDIO_CYW55572_FUNC2_BLOCKSIZE	256
> +
>   /* Maximum milliseconds to wait for F2 to come up */
>   #define SDIO_WAIT_F2RDY	3000
>   
> @@ -917,6 +919,9 @@ int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
>   	case SDIO_DEVICE_ID_BROADCOM_4329:
>   		f2_blksz = SDIO_4329_FUNC2_BLOCKSIZE;
>   		break;
> +	case SDIO_DEVICE_ID_CYPRESS_55572:
> +		f2_blksz = SDIO_CYW55572_FUNC2_BLOCKSIZE;
> +		break;
>   	default:
>   		break;
>   	}
> @@ -996,6 +1001,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
>   	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752, CYW),
>   	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359, CYW),
>   	CYW_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439, CYW),
> +	CYW_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_55572, CYW),
>   	{ /* end: all zeroes */ }
>   };
>   MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
> index 2ef92ef25517e..c5188a31c9efb 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
> @@ -216,6 +216,32 @@ struct sbsocramregs {
>   #define	ARMCR4_BSZ_MULT		8192
>   #define	ARMCR4_BLK_1K_MASK	0x200
>   
> +/* CYW55572 dedicated space and RAM base */
> +#define CYW55572_TCAM_SIZE	0x800
> +#define CYW55572_TRXHDR_SIZE	0x2b4

Please use sizeof(struct trxhdr_le) instead of hard value 0x2b4 (they 
are the same).

> +#define CYW55572_RAM_BASE	(0x370000 + \
> +				 CYW55572_TCAM_SIZE + CYW55572_TRXHDR_SIZE)
> +
> +#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		250	/* msec */
> +
> +/* Bootloader handshake flags - dongle to host */
> +#define BRCMF_BLHS_D2H_START			BIT(0)
> +#define BRCMF_BLHS_D2H_READY			BIT(1)
> +#define BRCMF_BLHS_D2H_STEADY			BIT(2)
> +#define BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE	BIT(3)
> +#define BRCMF_BLHS_D2H_VALDN_START		BIT(4)
> +#define BRCMF_BLHS_D2H_VALDN_RESULT		BIT(5)
> +#define BRCMF_BLHS_D2H_VALDN_DONE		BIT(6)
> +
> +/* 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)
> +
>   struct brcmf_core_priv {
>   	struct brcmf_core pub;
>   	u32 wrapbase;
> @@ -501,6 +527,21 @@ char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len)
>   	return buf;
>   }
>   
> +static bool brcmf_chip_find_coreid(struct brcmf_chip_priv *ci, u16 coreid)

No need for this function. Simply use brcmf_chip_get_core().

> +{
> +	struct brcmf_core_priv *core;
> +
> +	list_for_each_entry(core, &ci->cores, list) {
> +		brcmf_dbg(TRACE, " core 0x%x:%-2d base 0x%08x wrap 0x%08x\n",
> +			  core->pub.id, core->pub.rev, core->pub.base,
> +			  core->wrapbase);
> +		if (core->pub.id == coreid)
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
>   static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci,
>   					      u16 coreid, u32 base,
>   					      u32 wrapbase)
> @@ -745,6 +786,8 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
>   		return 0x352000;
>   	case BRCM_CC_4387_CHIP_ID:
>   		return 0x740000;
> +	case CY_CC_55572_CHIP_ID:
> +		return CYW55572_RAM_BASE;
>   	default:
>   		brcmf_err("unknown chip: %s\n", ci->pub.name);
>   		break;
> @@ -763,6 +806,9 @@ int brcmf_chip_get_raminfo(struct brcmf_chip *pub)
>   	if (mem) {
>   		mem_core = container_of(mem, struct brcmf_core_priv, pub);
>   		ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core);
> +		if (ci->pub.chip == CY_CC_55572_CHIP_ID)
> +			ci->pub.ramsize -= (CYW55572_TCAM_SIZE +
> +					    CYW55572_TRXHDR_SIZE);

Please move this to the end of the function just before the debug print 
and use switch statement instead.

>   		ci->pub.rambase = brcmf_chip_tcm_rambase(ci);
>   		if (ci->pub.rambase == INVALID_RAMBASE) {
>   			brcmf_err("RAM base not provided with ARM CR4 core\n");
> @@ -942,7 +988,8 @@ int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci)
>   		/* need core with ports */
>   		if (nmw + nsw == 0 &&
>   		    id != BCMA_CORE_PMU &&
> -		    id != BCMA_CORE_GCI)
> +		    id != BCMA_CORE_GCI &&
> +			id != BCMA_CORE_SR)

indentation wrong(?)
>   			continue;
>   
>   		/* try to obtain register address info */
> @@ -966,6 +1013,144 @@ u32 brcmf_chip_enum_base(u16 devid)
>   	return SI_ENUM_BASE_DEFAULT;
>   }

[...] as mentioned skipped blhs stuff for now.

>   static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
>   {
>   	struct brcmf_core *core;
> @@ -1123,6 +1308,7 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,
>   				     const struct brcmf_buscore_ops *ops)
>   {
>   	struct brcmf_chip_priv *chip;
> +	struct brcmf_blhs *blhs;
>   	int err = 0;
>   
>   	if (WARN_ON(!ops->read32))
> @@ -1150,6 +1336,26 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid,
>   	if (err < 0)
>   		goto fail;
>   
> +	blhs = NULL;
> +	if (chip->ops->blhs_attach) {
> +		err = chip->ops->blhs_attach(chip->ctx, &blhs,
> +					     BRCMF_BLHS_D2H_READY,
> +					     BRCMF_BLHS_D2H_READY_TIMEOUT,
> +					     BRCMF_BLHS_POLL_INTERVAL);
> +		if (err < 0)
> +			goto fail;
> +
> +		if (blhs) {
> +			blhs->init = brcmf_blhs_init;
> +			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->chk_validation = brcmf_blhs_chk_validation;
> +			blhs->post_wdreset = brcmf_blhs_post_watchdog_reset;
> +		}
> +	}
> +	chip->pub.blhs = blhs;
> +
>   	err = brcmf_chip_recognition(chip);
>   	if (err < 0)
>   		goto fail;
> @@ -1176,6 +1382,7 @@ void brcmf_chip_detach(struct brcmf_chip *pub)
>   		list_del(&core->list);
>   		kfree(core);
>   	}
> +	kfree(pub->blhs);
>   	kfree(chip);
>   }
>   
> @@ -1309,7 +1516,8 @@ brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip)
>   	int i;
>   	struct brcmf_core *core;
>   
> -	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
> +	if (!chip->pub.blhs)
> +		brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
>   
>   	/* Disable the cores only and let the firmware enable them.
>   	 * Releasing reset ourselves breaks BCM4387 in weird ways.
> @@ -1456,6 +1664,8 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
>   		reg = chip->ops->read32(chip->ctx, addr);
>   		return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
>   			       PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
> +	case CY_CC_55572_CHIP_ID:
> +		return brcmf_chip_find_coreid(chip, BCMA_CORE_SR);

Simply use !!brcmf_chip_get_core(chip, BCMA_CORE_SR) here although I am 
surprised the presence is sufficient here. I would suggest reading 
control0 register (offset 0x4):

sr = brcmf_chip_get_core(chip, BCMA_CORE_SR);
if (sr) {
	reg = chip->ops->read32(chip->ctx, sr->base + 0x4);
	return (reg & CC_SR_CTL0_ENABLE_MASK) != 0;
}
return false;

>   	default:
>   		addr = CORE_CC_REG(pmu->base, pmucapabilities_ext);
>   		reg = chip->ops->read32(chip->ctx, addr);
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
> index d69f101f58344..0a00fb9d7632e 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
> @@ -10,6 +10,8 @@
>   #define CORE_CC_REG(base, field) \
>   		(base + offsetof(struct chipcregs, field))
>   
> +struct brcmf_blhs;
> +

Just put the struct brcmf_blhs here and drop the forward declaration.

>   /**
>    * struct brcmf_chip - chip level information.
>    *
> @@ -24,6 +26,7 @@
>    * @ramsize: amount of RAM on chip including retention.
>    * @srsize: amount of retention RAM on chip.
>    * @name: string representation of the chip identifier.
> + * @blhs: bootlooder handshake handle.
>    */
>   struct brcmf_chip {
>   	u32 chip;
> @@ -37,6 +40,7 @@ struct brcmf_chip {
>   	u32 ramsize;
>   	u32 srsize;
>   	char name[12];
> +	struct brcmf_blhs *blhs;
>   };
>   
>   /**
> @@ -61,6 +65,7 @@ struct brcmf_core {
>    * @setup: bus-specific core setup.
>    * @active: chip becomes active.
>    *	The callback should use the provided @rstvec when non-zero.
> + * @blhs_attach: attach bootloader handshake handle
>    */
>   struct brcmf_buscore_ops {
>   	u32 (*read32)(void *ctx, u32 addr);
> @@ -69,6 +74,35 @@ 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);
> +};
> +
> +/**
> + * struct brcmf_blhs - bootloader handshake handle related information.
> + *
> + * @d2h: offset of dongle to host register for the handshake.
> + * @h2d: offset of host to dongle register for the handshake.
> + * @init: bootloader handshake initialization.
> + * @prep_fwdl: handshake before firmware download.
> + * @post_fwdl: handshake after firmware download.
> + * @post_nvramdl: handshake after nvram download.
> + * @chk_validation: handshake for firmware validation check.
> + * @post_wdreset: handshake after watchdog reset.
> + * @read: read value with register offset for the handshake.
> + * @write: write value with register offset for the handshake.
> + */
> +struct brcmf_blhs {
> +	u32 d2h;
> +	u32 h2d;
> +	void (*init)(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 (*chk_validation)(struct brcmf_chip *pub);
> +	int (*post_wdreset)(struct brcmf_chip *pub);
> +	u32 (*read)(void *ctx, u32 addr);
> +	void (*write)(void *ctx, u32 addr, u32 value);
>   };
>   
>   int brcmf_chip_get_raminfo(struct brcmf_chip *pub);
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
> index 83f8ed7d00f96..1d5be3ce51ccf 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
> @@ -527,7 +527,8 @@ static void brcmf_fw_free_request(struct brcmf_fw_request *req)
>   	int i;
>   
>   	for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
> -		if (item->type == BRCMF_FW_TYPE_BINARY)
> +		if (item->type == BRCMF_FW_TYPE_BINARY ||
> +		    item->type == BRCMF_FW_TYPE_TRXSE)
>   			release_firmware(item->binary);
>   		else if (item->type == BRCMF_FW_TYPE_NVRAM)
>   			brcmf_fw_nvram_free(item->nv_data.data);
> @@ -599,6 +600,7 @@ static int brcmf_fw_complete_request(const struct firmware *fw,
>   		ret = brcmf_fw_request_nvram_done(fw, fwctx);
>   		break;
>   	case BRCMF_FW_TYPE_BINARY:
> +	case BRCMF_FW_TYPE_TRXSE:
>   		if (fw)
>   			cur->binary = fw;
>   		else
> @@ -672,8 +674,19 @@ static int brcmf_fw_request_firmware(const struct firmware **fw,
>   static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
>   {
>   	struct brcmf_fw *fwctx = ctx;
> +	struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos];
> +	char alt_path[BRCMF_FW_NAME_LEN];
>   	int ret;
>   
> +	if (!fw && cur->type == BRCMF_FW_TYPE_TRXSE) {
> +		strscpy(alt_path, cur->path, BRCMF_FW_NAME_LEN);
> +		/* strip 'se' from .trxse at the end */
> +		alt_path[strlen(alt_path) - 2] = 0;
> +		ret = request_firmware(&fw, alt_path, fwctx->dev);

What is the reason for stripping the 'se'. Just keep it.

> +		if (!ret)
> +			cur->path = alt_path;
> +	}
> +
>   	ret = brcmf_fw_complete_request(fw, fwctx);
>   
>   	while (ret == 0 && ++fwctx->curpos < fwctx->req->n_items) {
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
> index 4002d326fd21b..ab709babd649a 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
> @@ -41,6 +41,11 @@ 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_TRXSE_DEF(fw_name, fw_base) \
> +static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \
> +	BRCMF_FW_DEFAULT_PATH fw_base; \
> +MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw_base ".trxse")
> +
>   #define BRCMF_FW_ENTRY(chipid, mask, name) \
>   	{ chipid, mask, BRCM_ ## name ## _FIRMWARE_BASENAME }
>   
> @@ -48,7 +53,8 @@ void brcmf_fw_nvram_free(void *nvram);
>   
>   enum brcmf_fw_type {
>   	BRCMF_FW_TYPE_BINARY,
> -	BRCMF_FW_TYPE_NVRAM
> +	BRCMF_FW_TYPE_NVRAM,
> +	BRCMF_FW_TYPE_TRXSE
>   };
>   
>   struct brcmf_fw_item {
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
> index 058a742d17eda..15b045ab477ca 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
> @@ -71,6 +71,7 @@ BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie");
>   BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");
>   BRCMF_FW_CLM_DEF(4378B3, "brcmfmac4378b3-pcie");
>   BRCMF_FW_CLM_DEF(4387C2, "brcmfmac4387c2-pcie");
> +CY_FW_TRXSE_DEF(55572, "cyfmac55572-pcie");
>   
>   /* firmware config files */
>   MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");
> @@ -109,6 +110,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
>   	BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0x0000000F, 4378B1), /* revision ID 3 */
>   	BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFE0, 4378B3), /* revision ID 5 */
>   	BRCMF_FW_ENTRY(BRCM_CC_4387_CHIP_ID, 0xFFFFFFFF, 4387C2), /* revision ID 7 */
> +	BRCMF_FW_ENTRY(CY_CC_55572_CHIP_ID, 0xFFFFFFFF, 55572),

What chip revisions did you come across? We can keep the revmask as 
above for now, but I would like to know what is out there.

>   };
>   
>   #define BRCMF_PCIE_FW_UP_TIMEOUT		5000 /* msec */
> @@ -121,7 +123,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
>   #define	BRCMF_PCIE_BAR0_WRAPPERBASE		0x70
>   
>   #define BRCMF_PCIE_BAR0_WRAPBASE_DMP_OFFSET	0x1000
> -#define BRCMF_PCIE_BARO_PCIE_ENUM_OFFSET	0x2000
> +#define BRCMF_PCIE_BAR0_PCIE_ENUM_OFFSET	0x2000
> +#define BRCMF_CYW55572_PCIE_BAR0_PCIE_ENUM_OFFSET	0x3000
>   
>   #define BRCMF_PCIE_ARMCR4REG_BANKIDX		0x40
>   #define BRCMF_PCIE_ARMCR4REG_BANKPDA		0x4C
> @@ -139,6 +142,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
>   #define BRCMF_PCIE_PCIE2REG_CONFIGDATA		0x124
>   #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0	0x140
>   #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1	0x144
> +#define BRCMF_PCIE_PCIE2REG_DAR_D2H_MSG_0	0xA80
> +#define BRCMF_PCIE_PCIE2REG_DAR_H2D_MSG_0	0xA90
>   
>   #define BRCMF_PCIE_64_PCIE2REG_INTMASK		0xC14
>   #define BRCMF_PCIE_64_PCIE2REG_MAILBOXINT	0xC30
> @@ -271,18 +276,32 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
>   #define BRCMF_PCIE_CFGREG_MSI_ADDR_L		0x5C
>   #define BRCMF_PCIE_CFGREG_MSI_ADDR_H		0x60
>   #define BRCMF_PCIE_CFGREG_MSI_DATA		0x64
> +#define BRCMF_PCIE_CFGREG_REVID			0x6C
>   #define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL	0xBC
>   #define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2	0xDC
>   #define BRCMF_PCIE_CFGREG_RBAR_CTRL		0x228
>   #define BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1	0x248
>   #define BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG	0x4E0
>   #define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG	0x4F4
> +#define BRCMF_PCIE_CFGREG_REVID_SECURE_MODE	BIT(31)
>   #define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB	3
>   
>   /* Magic number at a magic location to find RAM size */
>   #define BRCMF_RAMSIZE_MAGIC			0x534d4152	/* SMAR */
>   #define BRCMF_RAMSIZE_OFFSET			0x6c
>   
> +#define BRCMF_ENTROPY_SEED_LEN		64u
> +#define BRCMF_ENTROPY_NONCE_LEN		16u
> +#define BRCMF_ENTROPY_HOST_LEN		(BRCMF_ENTROPY_SEED_LEN + \
> +					 BRCMF_ENTROPY_NONCE_LEN)
> +#define BRCMF_NVRAM_OFFSET_TCM		4u
> +#define BRCMF_NVRAM_COMPRS_FACTOR	4u
> +#define BRCMF_NVRAM_RNG_SIGNATURE	0xFEEDC0DEu
> +
> +struct brcmf_rand_metadata {
> +	__le32 signature;
> +	__le32 count;
> +};
>   
>   struct brcmf_pcie_console {
>   	u32 base_addr;
> @@ -679,9 +698,15 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
>   			       val);
>   
>   	/* Watchdog reset */
> +	if (devinfo->ci->blhs)
> +		devinfo->ci->blhs->init(devinfo->ci);
>   	brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
>   	WRITECC32(devinfo, watchdog, 4);
>   	msleep(100);
> +	if (devinfo->ci->blhs)
> +		if (devinfo->ci->blhs->post_wdreset(devinfo->ci))
> +			return;

use single if statement and-ing the two conditions.

> +
>   
>   	/* Restore ASPM */
>   	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
> @@ -722,6 +747,9 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
>   
>   static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)
>   {
> +	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
> +	int err = 0;
> +
>   	if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
>   		brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4);
>   		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
> @@ -733,7 +761,14 @@ static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)
>   		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,
>   				       0);
>   	}
> -	return 0;
> +
> +	if (devinfo->ci->blhs) {
> +		err = devinfo->ci->blhs->prep_fwdl(devinfo->ci);
> +		if (err)
> +			brcmf_err(bus, "FW download preparation failed");
> +	}
> +
> +	return err;
>   }
>   
>   
> @@ -747,8 +782,13 @@ static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo,
>   		brcmf_chip_resetcore(core, 0, 0, 0);
>   	}
>   
> -	if (!brcmf_chip_set_active(devinfo->ci, resetintr))
> -		return -EIO;
> +	if (devinfo->ci->blhs) {
> +		devinfo->ci->blhs->post_nvramdl(devinfo->ci);
> +	} else {
> +		if (!brcmf_chip_set_active(devinfo->ci, resetintr))
> +			return -EIO;
> +	}
> +
>   	return 0;
>   }
>   
> @@ -1608,6 +1648,27 @@ brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info *devinfo, u8 *data,
>   }
>   
>   
> +static void
> +brcmf_pcie_write_rand(struct brcmf_pciedev_info *devinfo, u32 nvram_csm)

I mentioned in v1 that there is already a (probably incompatible) 
mechinism for providing random seed to firmware. Prefer to explore 
possible reuse or at least align code flow if possible.

> +{
> +	struct brcmf_rand_metadata rand_data;
> +	u8 rand_buf[BRCMF_ENTROPY_HOST_LEN];
> +	u32 count = BRCMF_ENTROPY_HOST_LEN;
> +	u32 address;
> +
> +	address = devinfo->ci->rambase +
> +		  (devinfo->ci->ramsize - BRCMF_NVRAM_OFFSET_TCM) -
> +		  ((nvram_csm & 0xffff) * BRCMF_NVRAM_COMPRS_FACTOR) -
> +		  sizeof(rand_data);
> +	memset(rand_buf, 0, BRCMF_ENTROPY_HOST_LEN);
> +	rand_data.signature = cpu_to_le32(BRCMF_NVRAM_RNG_SIGNATURE);
> +	rand_data.count = cpu_to_le32(count);
> +	memcpy_toio(devinfo->tcm + address, &rand_data, sizeof(rand_data));
> +	address -= count;
> +	get_random_bytes(rand_buf, count);
> +	memcpy_toio(devinfo->tcm + address, rand_buf, count);
> +}
> +
>   static int
>   brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
>   			       u32 sharedram_addr)
> @@ -1693,6 +1754,8 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
>   	int err;
>   	u32 address;
>   	u32 resetintr;
> +	u32 nvram_lenw;
> +	u32 nvram_csm;
>   
>   	brcmf_dbg(PCIE, "Halt ARM.\n");
>   	err = brcmf_pcie_enter_download_state(devinfo);
> @@ -1711,16 +1774,40 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
>   	resetintr = get_unaligned_le32(fw->data);
>   	release_firmware(fw);
>   
> -	/* reset last 4 bytes of RAM address. to be used for shared
> -	 * area. This identifies when FW is running
> -	 */
> -	brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);
> +	if (devinfo->ci->blhs) {
> +		err = devinfo->ci->blhs->post_fwdl(devinfo->ci);
> +		if (err) {
> +			brcmf_err(bus, "FW download failed, err=%d\n", err);
> +			return err;
> +		}
> +
> +		err = devinfo->ci->blhs->chk_validation(devinfo->ci);
> +		if (err) {
> +			brcmf_err(bus, "FW valication failed, err=%d\n", err);

typo

> +			return err;
> +		}
> +	} else {
> +		/* reset last 4 bytes of RAM address. to be used for shared
> +		 * area. This identifies when FW is running
> +		 */
> +		brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);
> +	}
>   
>   	if (nvram) {
>   		brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);
>   		address = devinfo->ci->rambase + devinfo->ci->ramsize -
>   			  nvram_len;
> +
> +		if (devinfo->ci->blhs)
> +			address -= 4;
>   		memcpy_toio(devinfo->tcm + address, nvram, nvram_len);
> +
> +		/* Convert nvram_len to words to determine the length token */
> +		nvram_lenw = nvram_len / 4;
> +		/* subtract word used to store the token itself on non-blhs devices */
> +		if (!devinfo->ci->blhs)
> +			nvram_lenw -= 1;
> +		nvram_csm = (~nvram_lenw << 16) | (nvram_lenw & 0x0000FFFF);
>   		brcmf_fw_nvram_free(nvram);
>   
>   		if (devinfo->otp.valid) {
> @@ -1743,10 +1830,20 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
>   			brcmf_pcie_provide_random_bytes(devinfo, address);
>   		}
>   	} else {
> +		nvram_csm = 0;
>   		brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
>   			  devinfo->nvram_name);
>   	}
>   
> +	if (devinfo->ci->chip == CY_CC_55572_CHIP_ID) {
> +		/* Write the length token to the last word of RAM address */
> +		brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4,
> +				       (u32)cpu_to_le32(nvram_csm));
> +
> +		/* Write random numbers to TCM for randomizing heap address */
> +		brcmf_pcie_write_rand(devinfo, nvram_csm);
> +	}
> +
>   	sharedram_addr_written = brcmf_pcie_read_ram32(devinfo,
>   						       devinfo->ci->ramsize -
>   						       4);
> @@ -1837,6 +1934,21 @@ static void brcmf_pcie_release_resource(struct brcmf_pciedev_info *devinfo)
>   	pci_disable_device(devinfo->pdev);
>   }
>   
> +static u32 brcmf_pcie_buscore_blhs_read(void *ctx, u32 reg_offset)
> +{
> +	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
> +
> +	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
> +	return brcmf_pcie_read_reg32(devinfo, reg_offset);
> +}
> +
> +static void brcmf_pcie_buscore_blhs_write(void *ctx, u32 reg_offset, u32 value)
> +{
> +	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
> +
> +	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
> +	brcmf_pcie_write_reg32(devinfo, reg_offset, value);
> +}
>   
>   static u32 brcmf_pcie_buscore_prep_addr(const struct pci_dev *pdev, u32 addr)
>   {
> @@ -1907,12 +2019,63 @@ 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)
> +{
> +	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
> +	struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
> +	struct brcmf_blhs *blhsh;
> +	u32 regdata;
> +	u32 pcie_enum;
> +	u32 addr;
> +
> +	if (devinfo->pdev->vendor != CY_PCIE_VENDOR_ID_CYPRESS)
> +		return 0;
> +
> +	pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_CFGREG_REVID, &regdata);
> +	if (regdata & BRCMF_PCIE_CFGREG_REVID_SECURE_MODE) {
> +		blhsh = kzalloc(sizeof(*blhsh), GFP_KERNEL);
> +		if (!blhsh)
> +			return -ENOMEM;
> +
> +		blhsh->d2h = BRCMF_PCIE_PCIE2REG_DAR_D2H_MSG_0;
> +		blhsh->h2d = BRCMF_PCIE_PCIE2REG_DAR_H2D_MSG_0;
> +		blhsh->read = brcmf_pcie_buscore_blhs_read;
> +		blhsh->write = brcmf_pcie_buscore_blhs_write;
> +
> +		/* Host indication for bootloarder to start the init */
> +		if (devinfo->pdev->device == CY_PCIE_55572_DEVICE_ID)
> +			pcie_enum = BRCMF_CYW55572_PCIE_BAR0_PCIE_ENUM_OFFSET;
> +		else
> +			pcie_enum = BRCMF_PCIE_BAR0_PCIE_ENUM_OFFSET;
> +
> +		pci_read_config_dword(devinfo->pdev, PCI_BASE_ADDRESS_0,
> +				      &regdata);
> +		addr = regdata + pcie_enum + blhsh->h2d;
> +		brcmf_pcie_buscore_write32(ctx, addr, 0);
> +
> +		addr = regdata + pcie_enum + blhsh->d2h;
> +		SPINWAIT_MS((brcmf_pcie_buscore_read32(ctx, addr) & flag) == 0,
> +			    timeout, interval);
> +		regdata = brcmf_pcie_buscore_read32(ctx, addr);
> +		if (!(regdata & flag)) {
> +			brcmf_err(bus, "Timeout waiting for bootloader ready\n");
> +			kfree(blhsh);
> +			return -EPERM;
> +		}
> +		*blhs = blhsh;
> +	}
> +
> +	return 0;
> +}
> +
>   static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
>   	.prepare = brcmf_pcie_buscoreprep,
>   	.reset = brcmf_pcie_buscore_reset,
>   	.activate = brcmf_pcie_buscore_activate,
>   	.read32 = brcmf_pcie_buscore_read32,
>   	.write32 = brcmf_pcie_buscore_write32,
> +	.blhs_attach = brcmf_pcie_buscore_blhs_attach,
>   };
>   
>   #define BRCMF_OTP_SYS_VENDOR	0x15
> @@ -2243,6 +2406,9 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
>   		{ ".txcap_blob", devinfo->txcap_name },
>   	};
>   
> +	if (devinfo->ci->blhs)
> +		fwnames[BRCMF_PCIE_FW_CODE].extension = ".trxse";
> +
>   	fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
>   				       brcmf_pcie_fwnames,
>   				       ARRAY_SIZE(brcmf_pcie_fwnames),
> @@ -2250,7 +2416,10 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
>   	if (!fwreq)
>   		return NULL;
>   
> -	fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
> +	if (devinfo->ci->blhs)
> +		fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_TRXSE;
> +	else
> +		fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
>   	fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
>   	fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
>   	fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
> @@ -2678,6 +2847,9 @@ static const struct dev_pm_ops brcmf_pciedrvr_pm = {
>   		BRCMF_FWVENDOR_ ## fw_vend \
>   	}
>   
> +#define BRCMF_PCIE_DEVICE_CY(dev_id)	{ CY_PCIE_VENDOR_ID_CYPRESS, dev_id,\
> +	PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
> +
>   static const struct pci_device_id brcmf_pcie_devid_table[] = {
>   	BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID, WCC),
>   	BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355, WCC),
> @@ -2706,7 +2878,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = {
>   	BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC),
>   	BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC),
>   	BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC),
> -
> +	BRCMF_PCIE_DEVICE_CY(CY_PCIE_55572_DEVICE_ID),
>   	{ /* end: all zeroes */ }
>   };
>   
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> index 08881e366cae2..3bb03de1c2d29 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> @@ -59,6 +59,10 @@
>   #define CY_435X_F2_WATERMARK	0x40
>   #define CY_435X_F1_MESBUSYCTRL	(CY_435X_F2_WATERMARK | \
>   				 SBSDIO_MESBUSYCTRL_ENAB)
> +#define CYW55572_F2_WATERMARK	0x40
> +#define CYW55572_MES_WATERMARK	0x40
> +#define CYW55572_F1_MESBUSYCTRL	(CYW55572_MES_WATERMARK | \
> +				 SBSDIO_MESBUSYCTRL_ENAB)
>   
>   #ifdef DEBUG
>   
> @@ -626,6 +630,7 @@ BRCMF_FW_DEF(4359, "brcmfmac4359-sdio");
>   BRCMF_FW_CLM_DEF(4373, "brcmfmac4373-sdio");
>   BRCMF_FW_CLM_DEF(43012, "brcmfmac43012-sdio");
>   BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-sdio");
> +CY_FW_TRXSE_DEF(55572, "cyfmac55572-sdio");
>   
>   /* firmware config files */
>   MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.txt");
> @@ -658,7 +663,8 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
>   	BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373),
>   	BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012),
>   	BRCMF_FW_ENTRY(CY_CC_43439_CHIP_ID, 0xFFFFFFFF, 43439),
> -	BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752)
> +	BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752),
> +	BRCMF_FW_ENTRY(CY_CC_55572_CHIP_ID, 0xFFFFFFFF, 55572)
>   };
>   
>   #define TXCTL_CREDITS	2
> @@ -719,7 +725,8 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
>   	 * fail. Thereby just bailing out immediately after clearing KSO
>   	 * bit, to avoid polling of KSO bit.
>   	 */
> -	if (!on && bus->ci->chip == CY_CC_43012_CHIP_ID)
> +	if (!on && (bus->ci->chip == CY_CC_43012_CHIP_ID ||
> +		    bus->ci->chip == CY_CC_55572_CHIP_ID))
>   		return err;
>   
>   	if (on) {
> @@ -3435,7 +3442,8 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
>   static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus)
>   {
>   	if (bus->ci->chip == CY_CC_43012_CHIP_ID ||
> -	    bus->ci->chip == CY_CC_43752_CHIP_ID)
> +	    bus->ci->chip == CY_CC_43752_CHIP_ID ||
> +	    bus->ci->chip == CY_CC_55572_CHIP_ID)
>   		return true;
>   	else
>   		return false;
> @@ -4352,6 +4360,19 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
>   			brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
>   					   CY_435X_F1_MESBUSYCTRL, &err);
>   			break;
> +		case SDIO_DEVICE_ID_CYPRESS_55572:
> +			brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
> +				  CYW55572_F2_WATERMARK);
> +			brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
> +					   CYW55572_F2_WATERMARK, &err);
> +			devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
> +						   &err);
> +			devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
> +			brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
> +					   &err);
> +			brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
> +					   CYW55572_F1_MESBUSYCTRL, &err);
> +			break;
>   		default:
>   			brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
>   					   DEFAULT_F2_WATERMARK, &err);
> diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
> index 44684bf1b9acc..fc1757c505312 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
> +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
> @@ -14,6 +14,7 @@
>   #define BRCM_USB_VENDOR_ID_LINKSYS	0x13b1
>   #define CY_USB_VENDOR_ID_CYPRESS	0x04b4
>   #define BRCM_PCIE_VENDOR_ID_BROADCOM	PCI_VENDOR_ID_BROADCOM
> +#define CY_PCIE_VENDOR_ID_CYPRESS	0x12be

Looked up this vendor id and it is registered to Anchor Chips Inc. which 
apparently was acquired by Cypress in 1999. Maybe good to add a 
definition in include/linux/pci_ids for this, but not sure whether to 
call it PCI_VENDOR_ID_CYPRESS or PCI_VENDOR_ID_INFINEON. 
PCI_VENDOR_ID_ANCHOR_CHIPS seems a bit stale to choose.

>   /* Chipcommon Core Chip IDs */
>   #define BRCM_CC_43143_CHIP_ID		43143
> @@ -59,6 +60,7 @@
>   #define CY_CC_43012_CHIP_ID		43012
>   #define CY_CC_43439_CHIP_ID		43439
>   #define CY_CC_43752_CHIP_ID		43752
> +#define CY_CC_55572_CHIP_ID		0xd908
>   
>   /* USB Device IDs */
>   #define BRCM_USB_43143_DEVICE_ID	0xbd1e
> @@ -97,6 +99,7 @@
>   #define BRCM_PCIE_4377_DEVICE_ID	0x4488
>   #define BRCM_PCIE_4378_DEVICE_ID	0x4425
>   #define BRCM_PCIE_4387_DEVICE_ID	0x4433
> +#define CY_PCIE_55572_DEVICE_ID		0xbd31
>   
>   /* brcmsmac IDs */
>   #define BCM4313_D11N2G_ID	0x4727	/* 4313 802.11n 2.4G device */
> diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h
> index 9465323286673..48791ac87496d 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h
> +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h
> @@ -21,6 +21,19 @@
>   	} \
>   }
>   
> +/* Spin at most 'ms' milliseconds with polling interval 'interval' milliseconds
> + * while 'exp' is true. Caller should explicitly test 'exp' when this completes
> + * and take appropriate error action if 'exp' is still true.
> + */
> +#define SPINWAIT_MS(exp, ms, interval) { \
> +	typeof(interval) interval_ = (interval); \
> +	uint countdown = (ms) + (interval_ - 1U); \
> +	while ((exp) && (countdown >= interval_)) { \
> +		msleep(interval_); \
> +		countdown -= interval_; \
> +	} \
> +}

Don't like this construct and it seems unnecessary. wait_event() and/or 
friends can probably do the trick. The exp/condition usage in 
wait_event() is also bit more intuitive.

>   /* osl multi-precedence packet queue */
>   #define PKTQ_LEN_DEFAULT        128	/* Max 128 packets */
>   #define PKTQ_MAX_PREC           16	/* Maximum precedence levels */
> diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
> index 60b94b944e9f1..fe1cb2aeaef38 100644
> --- a/include/linux/bcma/bcma.h
> +++ b/include/linux/bcma/bcma.h
> @@ -154,6 +154,7 @@ struct bcma_host_ops {
>   #define BCMA_CORE_USB30_DEV		0x83D
>   #define BCMA_CORE_ARM_CR4		0x83E
>   #define BCMA_CORE_GCI			0x840
> +#define BCMA_CORE_SR			0x841
>   #define BCMA_CORE_CMEM			0x846	/* CNDS DDR2/3 memory controller */
>   #define BCMA_CORE_ARM_CA7		0x847
>   #define BCMA_CORE_SYS_MEM		0x849
> diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
> index 7cddfdac2f576..8ba3f25217a21 100644
> --- a/include/linux/mmc/sdio_ids.h
> +++ b/include/linux/mmc/sdio_ids.h
> @@ -80,6 +80,7 @@
>   
>   #define SDIO_VENDOR_ID_CYPRESS			0x04b4
>   #define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439	0xbd3d
> +#define SDIO_DEVICE_ID_CYPRESS_55572		0xbd31
>   
>   #define SDIO_VENDOR_ID_MARVELL			0x02df
>   #define SDIO_DEVICE_ID_MARVELL_LIBERTAS		0x9103


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-09-14 12:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-09 20:31 [PATCH v2 1/2] wifi: brcmfmac: add support for TRX firmware download Marek Vasut
2024-09-09 20:31 ` [PATCH v2 2/2] wifi: brcmfmac: add support for CYW55572 PCIe chipset Marek Vasut
2024-09-14 12:04   ` Arend van Spriel
2024-09-14  6:24 ` [PATCH v2 1/2] wifi: brcmfmac: add support for TRX firmware download Arend van Spriel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).