summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSangwook Lee <sangwook.lee@linaro.org>2011-11-28 16:34:55 +0000
committerTushar Behera <tushar.behera@linaro.org>2012-12-13 14:53:38 +0530
commitc21304cd075872620ce93e50fdf7a237eb414e1d (patch)
tree547867d44e16e58e1634359ef5ffbfc87625c67a
parent933d3a10e664f5b3793418e9cf8530add5947eba (diff)
downloadlinux-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.c95
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c11
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);