diff options
author | Sangwook Lee <sangwook.lee@linaro.org> | 2011-11-28 16:34:55 +0000 |
---|---|---|
committer | Tushar Behera <tushar.behera@linaro.org> | 2012-12-13 14:53:38 +0530 |
commit | c21304cd075872620ce93e50fdf7a237eb414e1d (patch) | |
tree | 547867d44e16e58e1634359ef5ffbfc87625c67a | |
parent | 933d3a10e664f5b3793418e9cf8530add5947eba (diff) | |
download | linux-topics-c21304cd075872620ce93e50fdf7a237eb414e1d.tar.gz |
ath6kl: Add enablements for Samsung Origen WLAN
Origen board will call Platform API to setup power control
Signed-off-by: Sangwook Lee <sangwook.lee@linaro.org>
-rw-r--r-- | arch/arm/mach-exynos/mach-origen.c | 95 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/sdio.c | 11 |
2 files changed, 106 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 520b804be3b..72192e1cda6 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -24,6 +24,8 @@ #include <linux/lcd.h> #include <linux/rfkill-gpio.h> #include <linux/platform_data/s3c-hsotg.h> +#include <linux/ath6kl.h> +#include <linux/delay.h> #include <asm/mach/arch.h> #include <asm/hardware/gic.h> @@ -501,6 +503,95 @@ static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = { .cd_type = S3C_SDHCI_CD_INTERNAL, }; + +/* + * WLAN: SDIO Host will call this func at booting time + */ +static int origen_wifi_status_register(void (*notify_func) + (struct platform_device *, int state)); + +/* WLAN: MMC3-SDIO */ +static struct s3c_sdhci_platdata origen_hsmmc3_pdata __initdata = { + .max_width = 4, + .host_caps = MMC_CAP_4_BIT_DATA | + MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED, + .cd_type = S3C_SDHCI_CD_EXTERNAL, + .ext_cd_init = origen_wifi_status_register, +}; + +/* + * WLAN: Save SDIO Card detect func into this pointer + */ +static void (*wifi_status_cb)(struct platform_device *, int state); + +static int origen_wifi_status_register(void (*notify_func) + (struct platform_device *, int state)) +{ + if (!notify_func) + return -EAGAIN; + else + wifi_status_cb = notify_func; + + return 0; +} + +#define ORIGEN_WLAN_WOW EXYNOS4_GPX2(3) +#define ORIGEN_WLAN_RESET EXYNOS4_GPX2(4) + + +static void origen_wlan_setup_power(bool val) +{ + int err; + + if (val) { + err = gpio_request_one(ORIGEN_WLAN_RESET, + GPIOF_OUT_INIT_LOW, "GPX2_4"); + if (err) { + pr_warning("ORIGEN: Not obtain WIFI gpios\n"); + return; + } + s3c_gpio_cfgpin(ORIGEN_WLAN_RESET, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(ORIGEN_WLAN_RESET, + S3C_GPIO_PULL_NONE); + /* VDD33,I/O Supply must be done */ + gpio_set_value(ORIGEN_WLAN_RESET, 0); + udelay(30); /*Tb */ + gpio_direction_output(ORIGEN_WLAN_RESET, 1); + } else { + gpio_direction_output(ORIGEN_WLAN_RESET, 0); + gpio_free(ORIGEN_WLAN_RESET); + } + + mdelay(100); + + return; +} + +/* + * This will be called at init time of WLAN driver + */ +static int origen_wifi_set_detect(bool val) +{ + if (!wifi_status_cb) { + printk(KERN_WARNING "WLAN: Nobody to notify\n"); + return -EAGAIN; + } + if (true == val) { + origen_wlan_setup_power(true); + wifi_status_cb(&s3c_device_hsmmc3, 1); + } else { + origen_wlan_setup_power(false); + wifi_status_cb(&s3c_device_hsmmc3, 0); + } + + return 0; +} + +struct ath6kl_platform_data origen_wlan_data __initdata = { + .setup_power = origen_wifi_set_detect, +}; + + /* USB EHCI */ static struct s5p_ehci_platdata origen_ehci_pdata; @@ -713,6 +804,7 @@ static struct platform_device origen_device_bluetooth = { static struct platform_device *origen_devices[] __initdata = { &s3c_device_hsmmc2, &s3c_device_hsmmc0, + &s3c_device_hsmmc3, &s3c_device_i2c0, &s3c_device_i2c1, &s3c_device_rtc, @@ -814,6 +906,7 @@ static void __init origen_machine_init(void) */ s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata); s3c_sdhci0_set_platdata(&origen_hsmmc0_pdata); + s3c_sdhci3_set_platdata(&origen_hsmmc3_pdata); origen_ehci_init(); origen_ohci_init(); @@ -836,6 +929,8 @@ static void __init origen_machine_init(void) samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data); origen_bt_setup(); + + ath6kl_set_platform_data(&origen_wlan_data); } MACHINE_START(ORIGEN, "ORIGEN") diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 05b95405f7b..0a80af3ba10 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -23,6 +23,7 @@ #include <linux/mmc/sdio_ids.h> #include <linux/mmc/sdio.h> #include <linux/mmc/sd.h> +#include <linux/ath6kl.h> #include "hif.h" #include "hif-ops.h" #include "target.h" @@ -1423,7 +1424,11 @@ static struct sdio_driver ath6kl_sdio_driver = { static int __init ath6kl_sdio_init(void) { int ret; + const struct ath6kl_platform_data *wlan_data; + wlan_data = ath6kl_get_platform_data(); + if (!IS_ERR(wlan_data)) + wlan_data->setup_power(true); ret = sdio_register_driver(&ath6kl_sdio_driver); if (ret) ath6kl_err("sdio driver registration failed: %d\n", ret); @@ -1433,7 +1438,13 @@ static int __init ath6kl_sdio_init(void) static void __exit ath6kl_sdio_exit(void) { + const struct ath6kl_platform_data *wlan_data; + sdio_unregister_driver(&ath6kl_sdio_driver); + + wlan_data = ath6kl_get_platform_data(); + if (!IS_ERR(wlan_data)) + wlan_data->setup_power(false); } module_init(ath6kl_sdio_init); |