1
0
Fork 0

Add support for AP6256 wifi module

- Add sdio chip ID 43455
- Replace formerly used devicetree based wifi module power cycling via SDIO host interface driver with brcmf platform driver power events
ap6256_fix_initial_attempt_before_cleanup
Steinar Bakkemo 2019-01-11 07:38:59 +01:00
parent 7f82abb869
commit fd8872af5d
5 changed files with 91 additions and 20 deletions

View File

@ -22,15 +22,6 @@
reg = <0x80000000 0x20000000>;
};
wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&gpio3 30 GPIO_ACTIVE_LOW>,
<&gpio4 0 GPIO_ACTIVE_LOW>;
clocks = <&clks IMX6SL_CLK_OSC>;
clock-names = "ext_clock";
};
regulators {
compatible = "simple-bus";
#address-cells = <1>;
@ -758,7 +749,6 @@
pinctrl-0 = <&pinctrl_usdhc3>;
pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
mmc-pwrseq = <&wifi_pwrseq>;
bus-width = <4>;
enable-sdio-wakeup;
non-removable;
@ -774,7 +764,6 @@
interrupt-parent = <&gpio4>;
interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "host-wake";
/*resets = <&wifi_reset>;*/
};
};

View File

@ -16,10 +16,77 @@
#include <linux/regmap.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <linux/gpio.h>
#include <config/brcmfmac.h>
#include <linux/delay.h>
#include <linux/platform_data/brcmfmac-sdio.h>
#include "common.h"
#include "hardware.h"
#include "cpuidle.h"
#define WL_PWR_ON IMX_GPIO_NR(3, 30)
#define WL_REG_ON IMX_GPIO_NR(4, 0)
static bool init_wifi_gpio(void)
{
int err;
pr_debug("init_wifi_gpio: enter\n");
pr_debug("init_wifi_gpio: Requesting GPIO_3_30 (PWR_ON) ..\n");
err = gpio_request_one(WL_PWR_ON, GPIOF_OUT_INIT_LOW, "wl_pwr_on");
if (err) {
pr_err("Failed to request power GPIO for wifi: %d\n", err);
return false;
}
pr_debug("init_wifi_gpio: OK !\n");
pr_debug("init_wifi_gpio: Requesting GPIO4_0 (REG_ON) ..\n");
err = gpio_request_one(WL_REG_ON, GPIOF_OUT_INIT_LOW, "wl_reg_on");
if (err) {
pr_err("Failed to request regulator GPIO for wifi: %d\n", err);
return false;
}
pr_debug("init_wifi_gpio: OK !!\n");
return true;
}
static void brcmfmac_power_on(void)
{
pr_debug("brcmfmac_power_on: enter\n");
gpio_set_value(WL_PWR_ON, 1);
gpio_set_value(WL_REG_ON, 1);
}
static void brcmfmac_power_off(void)
{
pr_debug("brcmfmac_power_off: enter\n");
gpio_set_value(WL_PWR_ON, 0);
gpio_set_value(WL_REG_ON, 0);
}
static void brcmfmac_reset(void)
{
pr_debug("brcmfmac_reset: enter\n");
brcmfmac_power_off();
msleep(5);
brcmfmac_power_on();
}
static struct brcmfmac_sdio_platform_data brcmfmac_sdio_pdata = {
.power_on = brcmfmac_power_on,
.power_off = brcmfmac_power_off,
.reset = brcmfmac_reset
};
static struct platform_device brcmfmac_device = {
.name = BRCMFMAC_SDIO_PDATA_NAME,
.id = PLATFORM_DEVID_NONE,
.dev.platform_data = &brcmfmac_sdio_pdata
};
static void __init imx6sl_fec_clk_init(void)
{
struct regmap *gpr;
@ -33,6 +100,10 @@ static void __init imx6sl_fec_clk_init(void)
IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK, 0);
} else
pr_err("failed to find fsl,imx6sl-iomux-gpr regmap\n");
if (init_wifi_gpio()) {
platform_device_register(&brcmfmac_device);
}
}
static inline void imx6sl_fec_init(void)

View File

@ -1028,6 +1028,8 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
uint max_blocks;
int ret = 0;
pr_debug("brcmf_sdiod_probe (enter)\n");
sdiodev->num_funcs = 2;
sdio_claim_host(sdiodev->func[1]);
@ -1111,6 +1113,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455),
{ /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
@ -1125,7 +1128,8 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
struct brcmf_sdio_dev *sdiodev;
struct brcmf_bus *bus_if;
printk("brcmf_ops_sdio_probe\n");
pr_debug("brcmf_ops_sdio_probe (enter)\n");
brcmf_dbg(SDIO, "Enter\n");
brcmf_dbg(SDIO, "Class=%x\n", func->class);
brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);

View File

@ -686,6 +686,8 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
int i;
char end;
printk("brcmf_sdio_get_fwnames: chip id:%lx/%ld, revision:%d\n", ci->chip, ci->chip, ci->chiprev);
for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
if (brcmf_fwname_data[i].chipid == ci->chip &&
brcmf_fwname_data[i].revmsk & BIT(ci->chiprev))
@ -697,6 +699,7 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
return -ENODEV;
}
/* check if firmware path is provided by module parameter */
if (brcmf_firmware_path[0] != '\0') {
strlcpy(sdiodev->fw_name, brcmf_firmware_path,
@ -717,6 +720,9 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
strlcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv,
sizeof(sdiodev->nvram_name));
pr_debug("brcmf_sdio_get_fwnames: fw_name = %s\n", sdiodev->fw_name);
pr_debug("brcmf_sdio_get_fwnames: nvram_name = %s\n", sdiodev->nvram_name);
return 0;
}
@ -1046,7 +1052,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
end:
/* control clocks */
if (sleep) {
if (!bus->sr_enabled)
if (false && !bus->sr_enabled)
brcmf_sdio_clkctl(bus, CLK_NONE, pendok);
} else {
brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok);
@ -4090,7 +4096,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
struct brcmf_sdio *bus;
struct workqueue_struct *wq;
brcmf_dbg(TRACE, "Enter\n");
pr_debug("brcmf_sdio_probe (enter)\n");
/* Allocate private bus interface state */
bus = kzalloc(sizeof(struct brcmf_sdio), GFP_ATOMIC);
@ -4121,7 +4127,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM,
dev_name(&sdiodev->func[1]->dev));
if (!wq) {
brcmf_err("insufficient memory to create txworkqueue\n");
pr_err("brcmf_sdio_probe: insufficient memory to create txworkqueue\n");
goto fail;
}
brcmf_sdiod_freezer_count(sdiodev);
@ -4130,7 +4136,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
/* attempt to attach to the dongle */
if (!(brcmf_sdio_probe_attach(bus))) {
brcmf_err("brcmf_sdio_probe_attach failed\n");
pr_err("brcmf_sdio_probe: brcmf_sdio_probe_attach failed\n");
goto fail;
}
@ -4150,7 +4156,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
bus, "brcmf_wdog/%s",
dev_name(&sdiodev->func[1]->dev));
if (IS_ERR(bus->watchdog_tsk)) {
pr_warn("brcmf_watchdog thread failed to start\n");
pr_err("brcmf_sdio_probe: brcmf_watchdog thread failed to start\n");
bus->watchdog_tsk = NULL;
}
/* Initialize DPC thread */
@ -4169,7 +4175,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
/* Attach to the common layer, reserve hdr space */
ret = brcmf_attach(bus->sdiodev->dev);
if (ret != 0) {
brcmf_err("brcmf_attach failed\n");
pr_err("brcmf_sdio_probe: brcmf_attach failed\n");
goto fail;
}
@ -4185,7 +4191,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
ALIGNMENT) + bus->head_align;
bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
if (!(bus->rxbuf)) {
brcmf_err("rxbuf allocation failed\n");
pr_err("brcmf_sdio_probe: rxbuf allocation failed\n");
goto fail;
}
}
@ -4221,7 +4227,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
sdiodev->fw_name, sdiodev->nvram_name,
brcmf_sdio_firmware_callback);
if (ret != 0) {
brcmf_err("async firmware request failed: %d\n", ret);
pr_err("brcmf_sdio_probe: async firmware request failed: %d\n", ret);
goto fail;
}

View File

@ -35,6 +35,7 @@
#define SDIO_DEVICE_ID_BROADCOM_43362 0xa962
#define SDIO_DEVICE_ID_BROADCOM_43430 0xa9a6
#define SDIO_DEVICE_ID_BROADCOM_4345 0x4345
#define SDIO_DEVICE_ID_BROADCOM_43455 0xa9bf
#define SDIO_DEVICE_ID_BROADCOM_4354 0x4354
#define SDIO_VENDOR_ID_INTEL 0x0089