]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: brcmfmac: common: Add support for external calibration blobs
authorHector Martin <marcan@marcan.st>
Tue, 14 Feb 2023 09:24:23 +0000 (18:24 +0900)
committerKalle Valo <kvalo@kernel.org>
Mon, 27 Feb 2023 14:59:36 +0000 (16:59 +0200)
The calibration blob for a chip is normally stored in SROM and loaded
internally by the firmware. However, Apple ARM64 platforms instead store
it as part of platform configuration data, and provide it via the Apple
Device Tree. We forward this into the Linux DT in the bootloader.

Add support for taking this blob from the DT and loading it into the
dongle. The loading mechanism is the same as used for the CLM and TxCap
blobs.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230214092423.15175-10-marcan@marcan.st
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c

index 88e81b83af9d682aa7a2582de793a7b4e22de514..a194b0e68eb53a9e650ed4058d84c1f6cd4bc76b 100644 (file)
@@ -246,6 +246,23 @@ static const u8 brcmf_default_mac_address[ETH_ALEN] = {
        0x00, 0x90, 0x4c, 0xc5, 0x12, 0x38
 };
 
+static int brcmf_c_process_cal_blob(struct brcmf_if *ifp)
+{
+       struct brcmf_pub *drvr = ifp->drvr;
+       struct brcmf_mp_device *settings = drvr->settings;
+       s32 err;
+
+       brcmf_dbg(TRACE, "Enter\n");
+
+       if (!settings->cal_blob || !settings->cal_size)
+               return 0;
+
+       brcmf_info("Calibration blob provided by platform, loading\n");
+       err = brcmf_c_download_blob(ifp, settings->cal_blob, settings->cal_size,
+                                   "calload", "calload_status");
+       return err;
+}
+
 int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 {
        struct brcmf_pub *drvr = ifp->drvr;
@@ -336,6 +353,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
                goto done;
        }
 
+       /* Download external calibration blob, if available */
+       err = brcmf_c_process_cal_blob(ifp);
+       if (err < 0) {
+               bphy_err(drvr, "download calibration blob file failed, %d\n", err);
+               goto done;
+       }
+
        /* query for 'ver' to get version info from firmware */
        memset(buf, 0, sizeof(buf));
        err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
index 7167fd4f8c639b83e3d8d574498e790ebe054e5e..2be2986d2110a2c6caa47063c0ab13d5e561e1ae 100644 (file)
@@ -54,6 +54,8 @@ struct brcmf_mp_device {
        const char      *board_type;
        unsigned char   mac[ETH_ALEN];
        const char      *antenna_sku;
+       const void      *cal_blob;
+       int             cal_size;
        union {
                struct brcmfmac_sdio_pd sdio;
        } bus;
index fdd0c9abc1a10dbf109ff68a9f92cec4e37401f2..52527b61341edd1dffddb4029d4944f048e3955b 100644 (file)
@@ -86,6 +86,13 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
        if (!of_property_read_string(np, "apple,antenna-sku", &prop))
                settings->antenna_sku = prop;
 
+       /* The WLAN calibration blob is normally stored in SROM, but Apple
+        * ARM64 platforms pass it via the DT instead.
+        */
+       prop = of_get_property(np, "brcm,cal-blob", &settings->cal_size);
+       if (prop && settings->cal_size)
+               settings->cal_blob = prop;
+
        /* Set board-type to the first string of the machine compatible prop */
        root = of_find_node_by_path("/");
        if (root && err) {