Message ID | 1310303679-17936-7-git-send-email-ido@wizery.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Sun, Jul 10, 2011 at 18:44:39, Ido Yariv wrote: > The wl1271 daughter card for AM18x EVMs is a combo wireless connectivity > add-on card, based on the LS Research TiWi module with Texas > Instruments' wl1271 solution. > It is a 4-wire, 1.8V, embedded SDIO WLAN device with an external IRQ > line and is power-controlled by a GPIO-based fixed regulator. > > This patch adds support for the WLAN capabilities of this expansion > board. > > Signed-off-by: Ido Yariv <ido@wizery.com> > --- > diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c > index a7b41bf..2dae1a1 100644 > --- a/arch/arm/mach-davinci/board-da850-evm.c > +++ b/arch/arm/mach-davinci/board-da850-evm.c > @@ -31,6 +31,8 @@ > +#ifdef CONFIG_DA850_WL12XX > + > +static int da850_wl12xx_fref = WL12XX_REFCLOCK_38; > + > +static int __init setup_da850_wl12xx_fref(char *fref) > +{ > + if (!strcmp(fref, "19.2")) > + da850_wl12xx_fref = WL12XX_REFCLOCK_19; > + else if (!strcmp(fref, "26")) > + da850_wl12xx_fref = WL12XX_REFCLOCK_26; > + else if (!strcmp(fref, "38.4")) > + da850_wl12xx_fref = WL12XX_REFCLOCK_38; > + else if (!strcmp(fref, "52")) > + da850_wl12xx_fref = WL12XX_REFCLOCK_52; > + else if (!strcmp(fref, "XTAL26")) > + da850_wl12xx_fref = WL12XX_REFCLOCK_26_XTAL; > + else if (!strcmp(fref, "XTAL38.4")) > + da850_wl12xx_fref = WL12XX_REFCLOCK_38_XTAL; > + else > + pr_info("da850_wl12xx_fref is invalid. Valid options: " > + "19.2, 26, 38.4, 52, XTAL26 or XTAL38.4\n"); > + return 0; > +} > +__setup("da850_wl12xx_fref=", setup_da850_wl12xx_fref); Adding a new kernel parameter requires update to Documentation/kernel-parameters.txt as well. I am Ccing a couple of folks in case they have ideas on whether there is a better way to pass this information to the kernel. I assume there is no way to detect this from hardware. > +static struct davinci_mmc_config da850_mmc_wl12xx_config = { > + .get_ro = NULL, > + .get_cd = NULL, You can get rid of these NULL initializers. > + .set_power = wl12xx_set_power, > + .wires = 4, > + .max_freq = 25000000, > + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NONREMOVABLE | > + MMC_CAP_POWER_OFF_CARD, > + .version = MMC_CTLR_VERSION_2, > +}; > +static void da850_wl12xx_init(void) > +{ > + int ret; > + > + ret = davinci_cfg_reg_list(da850_evm_mmc_wl12xx_pins); > + if (ret) { > + pr_warning("da850_evm_init: wl12xx/mmc mux setup failed:" > + " %d\n", ret); > + return; > + } > + > + ret = da850_register_mmcsd1(&da850_mmc_wl12xx_config); > + if (ret) { > + pr_warning("da850_evm_init: wl12xx/mmc registration failed:" > + " %d\n", ret); > + return; > + } > + > + ret = gpio_request_one(DA850_WLAN_EN, GPIOF_OUT_INIT_LOW, "wl12xx_en"); > + if (ret) { > + pr_err("Error initializing the wl12xx enable gpio: %d\n", ret); > + return; > + } > + > + ret = gpio_request_one(DA850_WLAN_IRQ, GPIOF_IN, "wl12xx_irq"); > + if (ret) { > + pr_err("Error initializing the wl12xx irq gpio: %d\n", ret); > + gpio_free(DA850_WLAN_EN); > + return; > + } > + > + da850_wl12xx_wlan_data.irq = gpio_to_irq(DA850_WLAN_IRQ); > + da850_wl12xx_wlan_data.board_ref_clock = da850_wl12xx_fref; > + > + ret = wl12xx_set_platform_data(&da850_wl12xx_wlan_data); > + if (ret) { > + pr_err("Error setting wl12xx data: %d\n", ret); > + gpio_free(DA850_WLAN_IRQ); > + gpio_free(DA850_WLAN_EN); Why not just use the traditional goto based bail out mechanism? You will avoid the multiple gpio_free() calls. Thanks, Sekhar
Hi Sekhar, On Mon, Jul 25, 2011 at 11:10:55PM +0530, Nori, Sekhar wrote: > Adding a new kernel parameter requires update to > Documentation/kernel-parameters.txt as well. > > I am Ccing a couple of folks in case they have ideas on > whether there is a better way to pass this information > to the kernel. I assume there is no way to detect > this from hardware. Unfortunately, auto-detection of the reference clock is not currently possible. However, it might be a better idea to have the ability to override this value with a wl12xx module parameter instead of a kernel parameter. I'll drop this kernel parameter. > > +static struct davinci_mmc_config da850_mmc_wl12xx_config = { > > + .get_ro = NULL, > > + .get_cd = NULL, > > You can get rid of these NULL initializers. Sure. > > + .set_power = wl12xx_set_power, > > + .wires = 4, > > + .max_freq = 25000000, > > + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NONREMOVABLE | > > + MMC_CAP_POWER_OFF_CARD, > > + .version = MMC_CTLR_VERSION_2, > > +}; [...] > > + ret = gpio_request_one(DA850_WLAN_EN, GPIOF_OUT_INIT_LOW, "wl12xx_en"); > > + if (ret) { > > + pr_err("Error initializing the wl12xx enable gpio: %d\n", ret); > > + return; > > + } > > + > > + ret = gpio_request_one(DA850_WLAN_IRQ, GPIOF_IN, "wl12xx_irq"); > > + if (ret) { > > + pr_err("Error initializing the wl12xx irq gpio: %d\n", ret); > > + gpio_free(DA850_WLAN_EN); > > + return; > > + } > > + > > + da850_wl12xx_wlan_data.irq = gpio_to_irq(DA850_WLAN_IRQ); > > + da850_wl12xx_wlan_data.board_ref_clock = da850_wl12xx_fref; > > + > > + ret = wl12xx_set_platform_data(&da850_wl12xx_wlan_data); > > + if (ret) { > > + pr_err("Error setting wl12xx data: %d\n", ret); > > + gpio_free(DA850_WLAN_IRQ); > > + gpio_free(DA850_WLAN_EN); > > Why not just use the traditional goto based bail out > mechanism? You will avoid the multiple gpio_free() calls. Sure. Thanks for your review, Ido.
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index c0deaca..32d837d 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -192,6 +192,16 @@ config DA850_UI_RMII endchoice +config DA850_WL12XX + bool "AM18x wl1271 daughter board" + depends on MACH_DAVINCI_DA850_EVM + help + The wl1271 daughter card for AM18x EVMs is a combo wireless + connectivity add-on card, based on the LS Research TiWi module with + Texas Instruments' wl1271 solution. + Say Y if you want to use a wl1271 expansion card connected to the + AM18x EVM. + config GPIO_PCA953X default MACH_DAVINCI_DA850_EVM diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index a7b41bf..2dae1a1 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -31,6 +31,8 @@ #include <linux/input/tps6507x-ts.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> +#include <linux/delay.h> +#include <linux/wl12xx.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -49,6 +51,9 @@ #define DA850_MMCSD_CD_PIN GPIO_TO_PIN(4, 0) #define DA850_MMCSD_WP_PIN GPIO_TO_PIN(4, 1) +#define DA850_WLAN_EN GPIO_TO_PIN(6, 9) +#define DA850_WLAN_IRQ GPIO_TO_PIN(6, 10) + #define DA850_MII_MDIO_CLKEN_PIN GPIO_TO_PIN(2, 6) static struct mtd_partition da850evm_spiflash_part[] = { @@ -1117,6 +1122,126 @@ static __init int da850_evm_init_cpufreq(void) static __init int da850_evm_init_cpufreq(void) { return 0; } #endif +#ifdef CONFIG_DA850_WL12XX + +static int da850_wl12xx_fref = WL12XX_REFCLOCK_38; + +static int __init setup_da850_wl12xx_fref(char *fref) +{ + if (!strcmp(fref, "19.2")) + da850_wl12xx_fref = WL12XX_REFCLOCK_19; + else if (!strcmp(fref, "26")) + da850_wl12xx_fref = WL12XX_REFCLOCK_26; + else if (!strcmp(fref, "38.4")) + da850_wl12xx_fref = WL12XX_REFCLOCK_38; + else if (!strcmp(fref, "52")) + da850_wl12xx_fref = WL12XX_REFCLOCK_52; + else if (!strcmp(fref, "XTAL26")) + da850_wl12xx_fref = WL12XX_REFCLOCK_26_XTAL; + else if (!strcmp(fref, "XTAL38.4")) + da850_wl12xx_fref = WL12XX_REFCLOCK_38_XTAL; + else + pr_info("da850_wl12xx_fref is invalid. Valid options: " + "19.2, 26, 38.4, 52, XTAL26 or XTAL38.4\n"); + return 0; +} +__setup("da850_wl12xx_fref=", setup_da850_wl12xx_fref); + +static void wl12xx_set_power(int slot, bool power_on) +{ + static bool power_state; + + pr_debug("Powering %s wl12xx", power_on ? "on" : "off"); + + if (power_on == power_state) + return; + power_state = power_on; + + if (power_on) { + /* Power up sequence required for wl127x devices */ + gpio_set_value(DA850_WLAN_EN, 1); + usleep_range(15000, 15000); + gpio_set_value(DA850_WLAN_EN, 0); + usleep_range(1000, 1000); + gpio_set_value(DA850_WLAN_EN, 1); + msleep(70); + } else { + gpio_set_value(DA850_WLAN_EN, 0); + } +} + +static struct davinci_mmc_config da850_mmc_wl12xx_config = { + .get_ro = NULL, + .get_cd = NULL, + .set_power = wl12xx_set_power, + .wires = 4, + .max_freq = 25000000, + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NONREMOVABLE | + MMC_CAP_POWER_OFF_CARD, + .version = MMC_CTLR_VERSION_2, +}; + +static const short da850_evm_mmc_wl12xx_pins[] __initconst = { + DA850_MMCSD1_DAT_0, DA850_MMCSD1_DAT_1, DA850_MMCSD1_DAT_2, + DA850_MMCSD1_DAT_3, DA850_MMCSD1_CLK, DA850_MMCSD1_CMD, + DA850_GPIO6_9, DA850_GPIO6_10, + -1 +}; + +static struct wl12xx_platform_data da850_wl12xx_wlan_data __initdata = { + .irq = -1, + .board_ref_clock = -1, + .platform_quirks = WL12XX_PLATFORM_QUIRK_EDGE_IRQ, +}; + +static void da850_wl12xx_init(void) +{ + int ret; + + ret = davinci_cfg_reg_list(da850_evm_mmc_wl12xx_pins); + if (ret) { + pr_warning("da850_evm_init: wl12xx/mmc mux setup failed:" + " %d\n", ret); + return; + } + + ret = da850_register_mmcsd1(&da850_mmc_wl12xx_config); + if (ret) { + pr_warning("da850_evm_init: wl12xx/mmc registration failed:" + " %d\n", ret); + return; + } + + ret = gpio_request_one(DA850_WLAN_EN, GPIOF_OUT_INIT_LOW, "wl12xx_en"); + if (ret) { + pr_err("Error initializing the wl12xx enable gpio: %d\n", ret); + return; + } + + ret = gpio_request_one(DA850_WLAN_IRQ, GPIOF_IN, "wl12xx_irq"); + if (ret) { + pr_err("Error initializing the wl12xx irq gpio: %d\n", ret); + gpio_free(DA850_WLAN_EN); + return; + } + + da850_wl12xx_wlan_data.irq = gpio_to_irq(DA850_WLAN_IRQ); + da850_wl12xx_wlan_data.board_ref_clock = da850_wl12xx_fref; + + ret = wl12xx_set_platform_data(&da850_wl12xx_wlan_data); + if (ret) { + pr_err("Error setting wl12xx data: %d\n", ret); + gpio_free(DA850_WLAN_IRQ); + gpio_free(DA850_WLAN_EN); + } +} + +#else /* CONFIG_DA850_WL12XX */ + +static void da850_wl12xx_init(void) { } + +#endif /* CONFIG_DA850_WL12XX */ + static __init void da850_evm_init(void) { int ret; @@ -1169,6 +1294,8 @@ static __init void da850_evm_init(void) if (ret) pr_warning("da850_evm_init: mmcsd0 registration failed:" " %d\n", ret); + + da850_wl12xx_init(); } davinci_serial_init(&da850_evm_uart_config);
The wl1271 daughter card for AM18x EVMs is a combo wireless connectivity add-on card, based on the LS Research TiWi module with Texas Instruments' wl1271 solution. It is a 4-wire, 1.8V, embedded SDIO WLAN device with an external IRQ line and is power-controlled by a GPIO-based fixed regulator. This patch adds support for the WLAN capabilities of this expansion board. Signed-off-by: Ido Yariv <ido@wizery.com> --- arch/arm/mach-davinci/Kconfig | 10 +++ arch/arm/mach-davinci/board-da850-evm.c | 127 +++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 0 deletions(-)