diff options
author | Rakesh Kumar <krakesh@nvidia.com> | 2010-10-28 13:57:00 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:52:11 -0800 |
commit | ff955eaa11756ce5884670b8455f347c6ad7ab39 (patch) | |
tree | 0e75485d57511841d657c8a61e32ec6d9bc25557 /arch/arm/mach-tegra/board-ventana-sdhci.c | |
parent | ea4fdb48af589698e2215cdb10ac69131e987a2a (diff) |
[arm/tegra/ventana] provide wifi power/carddetect abstraction
When user switches on wifi, wifi driver need to poweron wifi card and
ask sdhci stack to enumerate the card. Sdhci stack does not provide any
interface to do so. BCM4329 depend on platform to provide wifi
poweron/reset/carddetect abstraction functions
bug 724105
Original-Change-Id: Ib82ac12cd0a3c33c8406434e64872c4cda3c2cc7
Reviewed-on: http://git-master/r/9883
Reviewed-by: Rakesh Kumar <krakesh@nvidia.com>
Tested-by: Rakesh Kumar <krakesh@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Rebase-Id: Rbf9f008102990bd125f6ce4d4ed781a9beac02af
Diffstat (limited to 'arch/arm/mach-tegra/board-ventana-sdhci.c')
-rw-r--r-- | arch/arm/mach-tegra/board-ventana-sdhci.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/board-ventana-sdhci.c b/arch/arm/mach-tegra/board-ventana-sdhci.c index 0396b70935e9..5e4ddf971c58 100644 --- a/arch/arm/mach-tegra/board-ventana-sdhci.c +++ b/arch/arm/mach-tegra/board-ventana-sdhci.c @@ -16,8 +16,12 @@ #include <linux/resource.h> #include <linux/platform_device.h> +#include <linux/wlan_plat.h> #include <linux/delay.h> #include <linux/gpio.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/mmc/host.h> #include <asm/mach-types.h> #include <mach/irqs.h> @@ -27,6 +31,32 @@ #include "gpio-names.h" #include "board.h" +#define VENTANA_WLAN_PWR TEGRA_GPIO_PK5 +#define VENTANA_WLAN_RST TEGRA_GPIO_PK6 + +static void (*wifi_status_cb)(int card_present, void *dev_id); +static void *wifi_status_cb_devid; +static int ventana_wifi_status_register(void (*callback)(int , void *), void *); +static struct clk *wifi_32k_clk; + +static int ventana_wifi_reset(int on); +static int ventana_wifi_power(int on); +static int ventana_wifi_set_carddetect(int val); + +static struct wifi_platform_data ventana_wifi_control = { + .set_power = ventana_wifi_power, + .set_reset = ventana_wifi_reset, + .set_carddetect = ventana_wifi_set_carddetect, +}; + +static struct platform_device ventana_wifi_device = { + .name = "bcm4329_wlan", + .id = 1, + .dev = { + .platform_data = &ventana_wifi_control, + }, +}; + static struct resource sdhci_resource0[] = { [0] = { .start = INT_SDMMC1, @@ -66,7 +96,21 @@ static struct resource sdhci_resource3[] = { }, }; + static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = { + .register_status_notify = ventana_wifi_status_register, + .cccr = { + .sdio_vsn = 2, + .multi_block = 1, + .low_speed = 0, + .wide_bus = 0, + .high_power = 1, + .high_speed = 1, + }, + .cis = { + .vendor = 0x02d0, + .device = 0x4329, + }, .cd_gpio = -1, .wp_gpio = -1, .power_gpio = -1, @@ -114,6 +158,70 @@ static struct platform_device tegra_sdhci_device3 = { }, }; +static int ventana_wifi_status_register( + void (*callback)(int card_present, void *dev_id), + void *dev_id) +{ + if (wifi_status_cb) + return -EAGAIN; + wifi_status_cb = callback; + wifi_status_cb_devid = dev_id; + return 0; +} + +static int ventana_wifi_set_carddetect(int val) +{ + pr_debug("%s: %d\n", __func__, val); + if (wifi_status_cb) + wifi_status_cb(val, wifi_status_cb_devid); + else + pr_warning("%s: Nobody to notify\n", __func__); + return 0; +} + +static int ventana_wifi_power(int on) +{ + pr_debug("%s: %d\n", __func__, on); + + gpio_set_value(VENTANA_WLAN_PWR, on); + mdelay(100); + gpio_set_value(VENTANA_WLAN_RST, on); + mdelay(200); + + if (on) + clk_enable(wifi_32k_clk); + else + clk_disable(wifi_32k_clk); + + return 0; +} + +static int ventana_wifi_reset(int on) +{ + pr_debug("%s: do nothing\n", __func__); + return 0; +} + +static int __init ventana_wifi_init(void) +{ + wifi_32k_clk = clk_get_sys(NULL, "blink"); + if (IS_ERR(wifi_32k_clk)) { + pr_err("%s: unable to get blink clock\n", __func__); + return PTR_ERR(wifi_32k_clk); + } + + gpio_request(VENTANA_WLAN_PWR, "wlan_power"); + gpio_request(VENTANA_WLAN_RST, "wlan_rst"); + + tegra_gpio_enable(VENTANA_WLAN_PWR); + tegra_gpio_enable(VENTANA_WLAN_RST); + + gpio_direction_output(VENTANA_WLAN_PWR, 0); + gpio_direction_output(VENTANA_WLAN_RST, 0); + + platform_device_register(&ventana_wifi_device); + return 0; +} int __init ventana_sdhci_init(void) { tegra_gpio_enable(tegra_sdhci_platform_data2.power_gpio); @@ -125,5 +233,6 @@ int __init ventana_sdhci_init(void) platform_device_register(&tegra_sdhci_device2); platform_device_register(&tegra_sdhci_device0); + ventana_wifi_init(); return 0; } |