1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

wifi: brcmfmac: Add optional lpo clock enable support

WiFi modules often require 32kHz clock to function. Add support to
enable the clock to PCIe driver and move "brcm,bcm4329-fmac" check
to the top of brcmf_of_probe. Change function prototypes from void
to int and add appropriate errno's for return values that will be
send to bus when error occurred.

Co-developed-by: Ondrej Jirman <megi@xff.cz>
Signed-off-by: Ondrej Jirman <megi@xff.cz>
Co-developed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Reviewed-by: Sai Krishna <saikrishnag@marvell.com>
Signed-off-by: Jacobe Zang <jacobe.zang@wesion.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Tested-by: Sebastian Reichel <sebastian.reichel@collabora.com> # On RK3588 EVB1
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://patch.msgid.link/20240910-wireless-mainline-v14-3-9d80fea5326d@wesion.com
This commit is contained in:
Jacobe Zang 2024-09-10 11:04:13 +08:00 committed by Kalle Valo
parent 7ca3fac195
commit 0ff0843310
7 changed files with 47 additions and 22 deletions

View file

@ -947,8 +947,8 @@ int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
/* try to attach to the target device */ /* try to attach to the target device */
sdiodev->bus = brcmf_sdio_probe(sdiodev); sdiodev->bus = brcmf_sdio_probe(sdiodev);
if (!sdiodev->bus) { if (IS_ERR(sdiodev->bus)) {
ret = -ENODEV; ret = PTR_ERR(sdiodev->bus);
goto out; goto out;
} }
brcmf_sdiod_host_fixup(sdiodev->func2->card->host); brcmf_sdiod_host_fixup(sdiodev->func2->card->host);

View file

@ -561,7 +561,8 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
if (!found) { if (!found) {
/* No platform data for this device, try OF and DMI data */ /* No platform data for this device, try OF and DMI data */
brcmf_dmi_probe(settings, chip, chiprev); brcmf_dmi_probe(settings, chip, chiprev);
brcmf_of_probe(dev, bus_type, settings); if (brcmf_of_probe(dev, bus_type, settings) == -EPROBE_DEFER)
return ERR_PTR(-EPROBE_DEFER);
brcmf_acpi_probe(dev, bus_type, settings); brcmf_acpi_probe(dev, bus_type, settings);
} }
return settings; return settings;

View file

@ -6,6 +6,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_net.h> #include <linux/of_net.h>
#include <linux/clk.h>
#include <defs.h> #include <defs.h>
#include "debug.h" #include "debug.h"
@ -65,12 +66,13 @@ static int brcmf_of_get_country_codes(struct device *dev,
return 0; return 0;
} }
void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings) struct brcmf_mp_device *settings)
{ {
struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio; struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio;
struct device_node *root, *np = dev->of_node; struct device_node *root, *np = dev->of_node;
struct of_phandle_args oirq; struct of_phandle_args oirq;
struct clk *clk;
const char *prop; const char *prop;
int irq; int irq;
int err; int err;
@ -106,7 +108,7 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
board_type = devm_kstrdup(dev, tmp, GFP_KERNEL); board_type = devm_kstrdup(dev, tmp, GFP_KERNEL);
if (!board_type) { if (!board_type) {
of_node_put(root); of_node_put(root);
return; return 0;
} }
strreplace(board_type, '/', '-'); strreplace(board_type, '/', '-');
settings->board_type = board_type; settings->board_type = board_type;
@ -114,8 +116,15 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
of_node_put(root); of_node_put(root);
} }
clk = devm_clk_get_optional_enabled(dev, "lpo");
if (IS_ERR(clk))
return PTR_ERR(clk);
brcmf_dbg(INFO, "%s LPO clock\n", clk ? "enable" : "no");
clk_set_rate(clk, 32768);
if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac")) if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
return; return 0;
err = brcmf_of_get_country_codes(dev, settings); err = brcmf_of_get_country_codes(dev, settings);
if (err) if (err)
@ -124,23 +133,25 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
of_get_mac_address(np, settings->mac); of_get_mac_address(np, settings->mac);
if (bus_type != BRCMF_BUSTYPE_SDIO) if (bus_type != BRCMF_BUSTYPE_SDIO)
return; return 0;
if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0) if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
sdio->drive_strength = val; sdio->drive_strength = val;
/* make sure there are interrupts defined in the node */ /* make sure there are interrupts defined in the node */
if (of_irq_parse_one(np, 0, &oirq)) if (of_irq_parse_one(np, 0, &oirq))
return; return 0;
irq = irq_create_of_mapping(&oirq); irq = irq_create_of_mapping(&oirq);
if (!irq) { if (!irq) {
brcmf_err("interrupt could not be mapped\n"); brcmf_err("interrupt could not be mapped\n");
return; return 0;
} }
irqf = irq_get_trigger_type(irq); irqf = irq_get_trigger_type(irq);
sdio->oob_irq_supported = true; sdio->oob_irq_supported = true;
sdio->oob_irq_nr = irq; sdio->oob_irq_nr = irq;
sdio->oob_irq_flags = irqf; sdio->oob_irq_flags = irqf;
return 0;
} }

View file

@ -3,11 +3,12 @@
* Copyright (c) 2014 Broadcom Corporation * Copyright (c) 2014 Broadcom Corporation
*/ */
#ifdef CONFIG_OF #ifdef CONFIG_OF
void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings); struct brcmf_mp_device *settings);
#else #else
static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, static int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings) struct brcmf_mp_device *settings)
{ {
return 0;
} }
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */

View file

@ -2452,6 +2452,9 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ret = -ENOMEM; ret = -ENOMEM;
goto fail; goto fail;
} }
ret = PTR_ERR_OR_ZERO(devinfo->settings);
if (ret < 0)
goto fail;
bus = kzalloc(sizeof(*bus), GFP_KERNEL); bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (!bus) { if (!bus) {

View file

@ -3943,7 +3943,7 @@ static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
.write32 = brcmf_sdio_buscore_write32, .write32 = brcmf_sdio_buscore_write32,
}; };
static bool static int
brcmf_sdio_probe_attach(struct brcmf_sdio *bus) brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
{ {
struct brcmf_sdio_dev *sdiodev; struct brcmf_sdio_dev *sdiodev;
@ -3953,6 +3953,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
u32 reg_val; u32 reg_val;
u32 drivestrength; u32 drivestrength;
u32 enum_base; u32 enum_base;
int ret = -EBADE;
sdiodev = bus->sdiodev; sdiodev = bus->sdiodev;
sdio_claim_host(sdiodev->func1); sdio_claim_host(sdiodev->func1);
@ -4001,8 +4002,9 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
BRCMF_BUSTYPE_SDIO, BRCMF_BUSTYPE_SDIO,
bus->ci->chip, bus->ci->chip,
bus->ci->chiprev); bus->ci->chiprev);
if (!sdiodev->settings) { if (IS_ERR_OR_NULL(sdiodev->settings)) {
brcmf_err("Failed to get device parameters\n"); brcmf_err("Failed to get device parameters\n");
ret = PTR_ERR_OR_ZERO(sdiodev->settings);
goto fail; goto fail;
} }
/* platform specific configuration: /* platform specific configuration:
@ -4071,7 +4073,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
/* allocate header buffer */ /* allocate header buffer */
bus->hdrbuf = kzalloc(MAX_HDR_READ + bus->head_align, GFP_KERNEL); bus->hdrbuf = kzalloc(MAX_HDR_READ + bus->head_align, GFP_KERNEL);
if (!bus->hdrbuf) if (!bus->hdrbuf)
return false; return -ENOMEM;
/* Locate an appropriately-aligned portion of hdrbuf */ /* Locate an appropriately-aligned portion of hdrbuf */
bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
bus->head_align); bus->head_align);
@ -4082,11 +4084,11 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
if (bus->poll) if (bus->poll)
bus->pollrate = 1; bus->pollrate = 1;
return true; return 0;
fail: fail:
sdio_release_host(sdiodev->func1); sdio_release_host(sdiodev->func1);
return false; return ret;
} }
static int static int
@ -4451,8 +4453,10 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
/* Allocate private bus interface state */ /* Allocate private bus interface state */
bus = kzalloc(sizeof(*bus), GFP_ATOMIC); bus = kzalloc(sizeof(*bus), GFP_ATOMIC);
if (!bus) if (!bus) {
ret = -ENOMEM;
goto fail; goto fail;
}
bus->sdiodev = sdiodev; bus->sdiodev = sdiodev;
sdiodev->bus = bus; sdiodev->bus = bus;
@ -4467,6 +4471,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
dev_name(&sdiodev->func1->dev)); dev_name(&sdiodev->func1->dev));
if (!wq) { if (!wq) {
brcmf_err("insufficient memory to create txworkqueue\n"); brcmf_err("insufficient memory to create txworkqueue\n");
ret = -ENOMEM;
goto fail; goto fail;
} }
brcmf_sdiod_freezer_count(sdiodev); brcmf_sdiod_freezer_count(sdiodev);
@ -4474,7 +4479,8 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
bus->brcmf_wq = wq; bus->brcmf_wq = wq;
/* attempt to attach to the dongle */ /* attempt to attach to the dongle */
if (!(brcmf_sdio_probe_attach(bus))) { ret = brcmf_sdio_probe_attach(bus);
if (ret < 0) {
brcmf_err("brcmf_sdio_probe_attach failed\n"); brcmf_err("brcmf_sdio_probe_attach failed\n");
goto fail; goto fail;
} }
@ -4546,7 +4552,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
fail: fail:
brcmf_sdio_remove(bus); brcmf_sdio_remove(bus);
return NULL; return ERR_PTR(ret);
} }
/* Detach and free everything */ /* Detach and free everything */

View file

@ -1272,6 +1272,9 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
ret = -ENOMEM; ret = -ENOMEM;
goto fail; goto fail;
} }
ret = PTR_ERR_OR_ZERO(devinfo->settings);
if (ret < 0)
goto fail;
if (!brcmf_usb_dlneeded(devinfo)) { if (!brcmf_usb_dlneeded(devinfo)) {
ret = brcmf_alloc(devinfo->dev, devinfo->settings); ret = brcmf_alloc(devinfo->dev, devinfo->settings);