+++ /dev/null
-From 4e32024cbb14230af3048e249e84f8c2b25ce45a Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.com>
-Date: Thu, 28 Oct 2021 15:03:16 +0100
-Subject: [PATCH] brcmfmac: Read alternative firmware names from DT
-
-Add the ability to load the names of alternative firmwares from the
-Device Tree node. This permits separate firmwares for 43436s and 43438
-and allows downstream firmwares to coexist with upstream.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.com>
----
- .../wireless/broadcom/brcm80211/brcmfmac/of.c | 36 ++++++++++++++
- .../wireless/broadcom/brcm80211/brcmfmac/of.h | 7 +++
- .../broadcom/brcm80211/brcmfmac/sdio.c | 47 +++++++++++++++++--
- 3 files changed, 87 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
-@@ -11,6 +11,7 @@
- #include "debug.h"
- #include "core.h"
- #include "common.h"
-+#include "firmware.h"
- #include "of.h"
-
- static int brcmf_of_get_country_codes(struct device *dev,
-@@ -175,3 +176,38 @@ void brcmf_of_probe(struct device *dev,
- sdio->oob_irq_nr = irq;
- sdio->oob_irq_flags = irqf;
- }
-+
-+struct brcmf_firmware_mapping *
-+brcmf_of_fwnames(struct device *dev, u32 *fwname_count)
-+{
-+ struct device_node *np = dev->of_node;
-+ struct brcmf_firmware_mapping *fwnames;
-+ struct device_node *map_np, *fw_np;
-+ int of_count;
-+ int count = 0;
-+
-+ map_np = of_get_child_by_name(np, "firmwares");
-+ of_count = of_get_child_count(map_np);
-+ if (!of_count)
-+ return NULL;
-+
-+ fwnames = devm_kcalloc(dev, of_count,
-+ sizeof(struct brcmf_firmware_mapping),
-+ GFP_KERNEL);
-+
-+ for_each_child_of_node(map_np, fw_np)
-+ {
-+ struct brcmf_firmware_mapping *cur = &fwnames[count];
-+
-+ if (of_property_read_u32(fw_np, "chipid", &cur->chipid) ||
-+ of_property_read_u32(fw_np, "revmask", &cur->revmask))
-+ continue;
-+ cur->fw_base = of_get_property(fw_np, "fw_base", NULL);
-+ if (cur->fw_base)
-+ count++;
-+ }
-+
-+ *fwname_count = count;
-+
-+ return count ? fwnames : NULL;
-+}
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
-@@ -5,9 +5,20 @@
- #ifdef CONFIG_OF
- void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
- struct brcmf_mp_device *settings);
-+#ifdef CPTCFG_BRCMFMAC_SDIO
-+struct brcmf_firmware_mapping *
-+brcmf_of_fwnames(struct device *dev, u32 *map_count);
-+#endif
- #else
- static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
- struct brcmf_mp_device *settings)
- {
- }
-+#ifdef CPTCFG_BRCMFMAC_SDIO
-+static struct brcmf_firmware_mapping *
-+brcmf_of_fwnames(struct device *dev, u32 *map_count)
-+{
-+ return NULL;
-+}
-+#endif
- #endif /* CONFIG_OF */
---- 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 "of.h"
-
- #define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500)
- #define CTL_DONE_TIMEOUT msecs_to_jiffies(2500)
-@@ -632,7 +633,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "b
- /* per-board firmware binaries */
- MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.bin");
-
--static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
-+static const struct brcmf_firmware_mapping sdio_fwnames[] = {
- BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
- BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
- BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
-@@ -660,6 +661,9 @@ static const struct brcmf_firmware_mappi
- BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752)
- };
-
-+static const struct brcmf_firmware_mapping *brcmf_sdio_fwnames = sdio_fwnames;
-+static u32 brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames);
-+
- #define TXCTL_CREDITS 2
-
- static void pkt_align(struct sk_buff *p, int len, int align)
-@@ -4201,6 +4205,9 @@ static const struct brcmf_bus_ops brcmf_
- #define BRCMF_SDIO_FW_NVRAM 1
- #define BRCMF_SDIO_FW_CLM 2
-
-+static struct brcmf_fw_request *
-+brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus);
-+
- static void brcmf_sdio_firmware_callback(struct device *dev, int err,
- struct brcmf_fw_request *fwreq)
- {
-@@ -4216,6 +4223,22 @@ static void brcmf_sdio_firmware_callback
-
- brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
-
-+ if (err && brcmf_sdio_fwnames != sdio_fwnames) {
-+ /* Try again with the standard firmware names */
-+ brcmf_sdio_fwnames = sdio_fwnames;
-+ brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames);
-+ kfree(fwreq);
-+ fwreq = brcmf_sdio_prepare_fw_request(bus);
-+ if (!fwreq) {
-+ err = -ENOMEM;
-+ goto fail;
-+ }
-+ err = brcmf_fw_get_firmwares(dev, fwreq,
-+ brcmf_sdio_firmware_callback);
-+ if (!err)
-+ return;
-+ }
-+
- if (err)
- goto fail;
-
-@@ -4426,7 +4449,7 @@ brcmf_sdio_prepare_fw_request(struct brc
-
- fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
- brcmf_sdio_fwnames,
-- ARRAY_SIZE(brcmf_sdio_fwnames),
-+ brcmf_sdio_fwnames_count,
- fwnames, ARRAY_SIZE(fwnames));
- if (!fwreq)
- return NULL;
-@@ -4446,6 +4469,9 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- struct brcmf_sdio *bus;
- struct workqueue_struct *wq;
- struct brcmf_fw_request *fwreq;
-+ struct brcmf_firmware_mapping *of_fwnames, *fwnames = NULL;
-+ const int fwname_size = sizeof(struct brcmf_firmware_mapping);
-+ u32 of_fw_count;
-
- brcmf_dbg(TRACE, "Enter\n");
-
-@@ -4528,6 +4554,21 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
-
- brcmf_dbg(INFO, "completed!!\n");
-
-+ of_fwnames = brcmf_of_fwnames(sdiodev->dev, &of_fw_count);
-+ if (of_fwnames)
-+ fwnames = devm_kcalloc(sdiodev->dev,
-+ of_fw_count + brcmf_sdio_fwnames_count,
-+ fwname_size, GFP_KERNEL);
-+
-+ if (fwnames) {
-+ /* The array is scanned in order, so overrides come first */
-+ memcpy(fwnames, of_fwnames, of_fw_count * fwname_size);
-+ memcpy(fwnames + of_fw_count, sdio_fwnames,
-+ brcmf_sdio_fwnames_count * fwname_size);
-+ brcmf_sdio_fwnames = fwnames;
-+ brcmf_sdio_fwnames_count += of_fw_count;
-+ }
-+
- fwreq = brcmf_sdio_prepare_fw_request(bus);
- if (!fwreq) {
- ret = -ENOMEM;