1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-02-15 04:42:02 +00:00
openmptcprouter/6.1/target/linux/bcm27xx/patches-6.1/950-0445-brcmfmac-Read-alternative-firmware-names-from-DT.patch
Ycarus (Yannick Chabanois) 3743692973 Fix RPI5 support
2023-11-17 17:31:36 +01:00

185 lines
5.4 KiB
Diff

From 4cb2a6e42361d4121dc993b9d0edd857c5e61ac1 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 | 52 +++++++++++++++++--
3 files changed, 91 insertions(+), 4 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,
@@ -136,3 +137,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,16 @@
#ifdef CONFIG_OF
void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings);
+struct brcmf_firmware_mapping *
+brcmf_of_fwnames(struct device *dev, u32 *map_count);
#else
static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings)
{
}
+static struct brcmf_firmware_mapping *
+brcmf_of_fwnames(struct device *dev, u32 *map_count)
+{
+ return NULL;
+}
#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)
@@ -4408,7 +4409,9 @@ fail:
}
static struct brcmf_fw_request *
-brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
+brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus,
+ const struct brcmf_firmware_mapping *fwmap,
+ int fwmap_count)
{
struct brcmf_fw_request *fwreq;
struct brcmf_fw_name fwnames[] = {
@@ -4418,8 +4421,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),
+ fwmap, fwmap_count,
fwnames, ARRAY_SIZE(fwnames));
if (!fwreq)
return NULL;
@@ -4433,12 +4435,44 @@ brcmf_sdio_prepare_fw_request(struct brc
return fwreq;
}
+static void brcmf_sdio_of_firmware_callback(struct device *dev, int err,
+ struct brcmf_fw_request *fwreq)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_sdio_dev *sdiod = bus_if->bus_priv.sdio;
+ struct brcmf_sdio *bus = sdiod->bus;
+
+ brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
+
+ if (err) {
+ /* Try again with the standard firmware names */
+ kfree(fwreq);
+ fwreq = brcmf_sdio_prepare_fw_request(bus,
+ brcmf_sdio_fwnames,
+ ARRAY_SIZE(brcmf_sdio_fwnames));
+ if (!fwreq) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ err = brcmf_fw_get_firmwares(sdiod->dev, fwreq,
+ brcmf_sdio_firmware_callback);
+ if (!err)
+ return;
+ }
+
+fail:
+ brcmf_sdio_firmware_callback(dev, err, fwreq);
+}
+
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
{
int ret;
struct brcmf_sdio *bus;
struct workqueue_struct *wq;
struct brcmf_fw_request *fwreq;
+ struct brcmf_firmware_mapping *of_fwnames;
+ u32 of_fwcount;
brcmf_dbg(TRACE, "Enter\n");
@@ -4521,13 +4555,23 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
brcmf_dbg(INFO, "completed!!\n");
- fwreq = brcmf_sdio_prepare_fw_request(bus);
+ of_fwnames = brcmf_of_fwnames(sdiodev->dev, &of_fwcount);
+
+ if (of_fwnames)
+ fwreq = brcmf_sdio_prepare_fw_request(bus, of_fwnames,
+ of_fwcount);
+ else
+ fwreq = brcmf_sdio_prepare_fw_request(bus, brcmf_sdio_fwnames,
+ ARRAY_SIZE(brcmf_sdio_fwnames));
+
if (!fwreq) {
ret = -ENOMEM;
goto fail;
}
ret = brcmf_fw_get_firmwares(sdiodev->dev, fwreq,
+ of_fwnames ?
+ brcmf_sdio_of_firmware_callback :
brcmf_sdio_firmware_callback);
if (ret != 0) {
brcmf_err("async firmware request failed: %d\n", ret);