summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Konovalov <andrey.konovalov@linaro.org>2012-05-22 20:39:11 +0400
committerAndrey Konovalov <andrey.konovalov@linaro.org>2012-05-22 20:39:11 +0400
commit0801288cee8791cf441e9a3ce8e93937960f5a6e (patch)
tree854cbec5a3025096c28d17b389a420c8739346de
parent28489b18693b5b551c61d1aa84f6c8713b2ad869 (diff)
parent06115973bcc339b55bc156c97a8bb7b6918afb68 (diff)
downloadlinux-topics-0801288cee8791cf441e9a3ce8e93937960f5a6e.tar.gz
Automatically merging rebase-samslt-wlan into merge-linux-linaro
Conflicting files:
-rw-r--r--arch/arm/configs/exynos4_defconfig5
-rw-r--r--arch/arm/mach-exynos/Kconfig1
-rw-r--r--arch/arm/mach-exynos/mach-origen.c100
-rw-r--r--configs/origen.conf2
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/mmc/core/sdio_irq.c2
-rw-r--r--drivers/mmc/core/sdio_ops.c40
-rw-r--r--drivers/mmc/core/sdio_ops.h1
-rw-r--r--drivers/mmc/host/sdhci.c4
-rw-r--r--drivers/net/wireless/ath/Makefile2
-rw-r--r--drivers/net/wireless/ath/ath6kl/Kconfig12
-rw-r--r--drivers/net/wireless/ath/ath6kl/Makefile26
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c11
-rw-r--r--drivers/net/wireless/ath/platform_data.c26
-rw-r--r--include/linux/ath6kl.h38
15 files changed, 256 insertions, 16 deletions
diff --git a/arch/arm/configs/exynos4_defconfig b/arch/arm/configs/exynos4_defconfig
index 6a19e5b567b..5ccb3561338 100644
--- a/arch/arm/configs/exynos4_defconfig
+++ b/arch/arm/configs/exynos4_defconfig
@@ -53,6 +53,11 @@ CONFIG_USB_PEGASUS=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_DM9601=y
CONFIG_USB_NET_MCS7830=y
+CONFIG_ATH_COMMON=y
+CONFIG_ATH_DEBUG=y
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_PLATFORM_DATA=y
+CONFIG_ATH6KL_POLL=y
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
# CONFIG_INPUT_MOUSE is not set
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index b07c346f3c5..ee0b6c3caa1 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -326,6 +326,7 @@ config MACH_ORIGEN
select S3C_DEV_WDT
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC2
+ select S3C_DEV_HSMMC3
select S3C_DEV_USB_HSOTG
select S5P_DEV_FIMC0
select S5P_DEV_FIMC1
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 70ddf1087a7..7e473e0017e 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -22,6 +22,8 @@
#include <linux/mfd/max8997.h>
#include <linux/lcd.h>
#include <linux/rfkill-gpio.h>
+#include <linux/ath6kl.h>
+#include <linux/delay.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
@@ -485,6 +487,100 @@ 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,
+ .pm_caps = MMC_PM_KEEP_POWER,
+ .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))
+{
+ /* Assign sdhci_s3c_notify_change to wifi_status_cb */
+ 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) {
+ pr_warning("ORIGEN: WLAN: No callback \n"
+ "ORIGEN: WLAN: MMC should boot earlier than net \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;
@@ -671,6 +767,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_rtc,
&s3c_device_wdt,
@@ -759,6 +856,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();
@@ -775,6 +873,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/configs/origen.conf b/configs/origen.conf
index 1b2fdb2e62c..374884cf4c2 100644
--- a/configs/origen.conf
+++ b/configs/origen.conf
@@ -33,6 +33,8 @@ CONFIG_USB_NET_MCS7830=y
CONFIG_ATH_COMMON=y
CONFIG_ATH_DEBUG=y
CONFIG_ATH6KL=y
+CONFIG_ATH6KL_PLATFORM_DATA=y
+CONFIG_ATH6KL_POLL=y
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_TOUCHSCREEN=y
diff --git a/drivers/Makefile b/drivers/Makefile
index 4f7acbf9c2b..b3347860c6f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_TARGET_CORE) += target/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
obj-y += hsi/
+obj-y += mmc/
obj-y += net/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_FUSION) += message/
@@ -97,7 +98,6 @@ obj-$(CONFIG_EISA) += eisa/
obj-y += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_CPU_IDLE) += cpuidle/
-obj-y += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-y += leds/
obj-$(CONFIG_SWITCH) += switch/
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index f573e7f9f74..2a07aed6e59 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -44,7 +44,7 @@ static int process_sdio_pending_irqs(struct mmc_card *card)
return 1;
}
- ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending);
+ ret = mmc_io_rw_direct_irq(card, &pending);
if (ret) {
pr_debug("%s: error %d reading SDIO_CCCR_INTx\n",
mmc_card_id(card), ret);
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index d29e20630ee..2fcb53e678c 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -111,6 +111,46 @@ static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn,
return 0;
}
+static struct mmc_command sdio_intx_cmd = {
+ .opcode = SD_IO_RW_DIRECT,
+ .arg = SDIO_CCCR_INTx << 9,
+ .flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC,
+};
+
+int mmc_io_rw_direct_irq(struct mmc_card *card, u8 *out)
+{
+ int err;
+ struct mmc_host *host ;
+
+ BUG_ON(!card);
+ host = card->host;
+ BUG_ON(!host);
+
+ err = mmc_wait_for_cmd(host, &sdio_intx_cmd, 0);
+ if (err)
+ return err;
+
+ if (mmc_host_is_spi(host)) {
+ /* host driver already reported errors */
+ } else {
+ if (sdio_intx_cmd.resp[0] & R5_ERROR)
+ return -EIO;
+ if (sdio_intx_cmd.resp[0] & R5_FUNCTION_NUMBER)
+ return -EINVAL;
+ if (sdio_intx_cmd.resp[0] & R5_OUT_OF_RANGE)
+ return -ERANGE;
+ }
+
+ if (out) {
+ if (mmc_host_is_spi(host))
+ *out = (sdio_intx_cmd.resp[0] >> 8) & 0xFF;
+ else
+ *out = sdio_intx_cmd.resp[0] & 0xFF;
+ }
+
+ return 0;
+}
+
int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
unsigned addr, u8 in, u8 *out)
{
diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h
index 12a4d3ab174..5fe8ad66745 100644
--- a/drivers/mmc/core/sdio_ops.h
+++ b/drivers/mmc/core/sdio_ops.h
@@ -15,6 +15,7 @@
int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
unsigned addr, u8 in, u8* out);
+int mmc_io_rw_direct_irq(struct mmc_card *card, u8 *out);
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
int sdio_reset(struct mmc_host *host);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 37601ec6a95..2ebe589a616 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2747,7 +2747,11 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+#if defined(CONFIG_MACH_ORIGEN) && defined(CONFIG_ATH6KL_POLL)
+ mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
+#else
mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
+#endif
if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
host->flags |= SDHCI_AUTO_CMD12;
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index d716b748e57..fc2851e2b7c 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_ATH5K) += ath5k/
obj-$(CONFIG_ATH9K_HW) += ath9k/
obj-$(CONFIG_CARL9170) += carl9170/
obj-$(CONFIG_ATH6KL) += ath6kl/
-
+obj-$(CONFIG_ATH6KL_PLATFORM_DATA) += platform_data.o
obj-$(CONFIG_ATH_COMMON) += ath.o
ath-objs := main.o \
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig
index d755a5e7ed2..734a6ef3d08 100644
--- a/drivers/net/wireless/ath/ath6kl/Kconfig
+++ b/drivers/net/wireless/ath/ath6kl/Kconfig
@@ -30,3 +30,15 @@ config ATH6KL_DEBUG
depends on ATH6KL
---help---
Enables debug support
+
+config ATH6KL_PLATFORM_DATA
+ bool "Atheros ath6kl Platform data support"
+ depends on ATH6KL
+ ---help---
+ Enables ath6kl platform data
+
+config ATH6KL_POLL
+ bool "Atheros ath6kl Polling support"
+ depends on ATH6KL
+ ---help---
+ Enables workaround for ar6003 hw2.0
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index 85746c3eb02..9e8f15b7de6 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -22,21 +22,21 @@
# Author(s): ="Atheros"
#------------------------------------------------------------------------------
-obj-$(CONFIG_ATH6KL) += ath6kl_core.o
-ath6kl_core-y += debug.o
-ath6kl_core-y += hif.o
-ath6kl_core-y += htc.o
-ath6kl_core-y += bmi.o
-ath6kl_core-y += cfg80211.o
-ath6kl_core-y += init.o
-ath6kl_core-y += main.o
-ath6kl_core-y += txrx.o
-ath6kl_core-y += wmi.o
-ath6kl_core-y += core.o
-ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
+obj-$(CONFIG_ATH6KL) += ath6kl.o
+ath6kl-y += debug.o
+ath6kl-y += hif.o
+ath6kl-y += htc.o
+ath6kl-y += bmi.o
+ath6kl-y += cfg80211.o
+ath6kl-y += init.o
+ath6kl-y += main.o
+ath6kl-y += txrx.o
+ath6kl-y += wmi.o
+ath6kl-y += core.o
+ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o
obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o
-ath6kl_sdio-y += sdio.o
+ath6kl-y += sdio.o
obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o
ath6kl_usb-y += usb.o
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 53528648b42..7c7e12fe58f 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"
@@ -1421,7 +1422,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);
@@ -1431,7 +1436,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);
diff --git a/drivers/net/wireless/ath/platform_data.c b/drivers/net/wireless/ath/platform_data.c
new file mode 100644
index 00000000000..dddffe409b0
--- /dev/null
+++ b/drivers/net/wireless/ath/platform_data.c
@@ -0,0 +1,26 @@
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/ath6kl.h>
+
+static const struct ath6kl_platform_data *platform_data;
+
+int __init ath6kl_set_platform_data(const struct ath6kl_platform_data *data)
+{
+ if (platform_data)
+ return -EBUSY;
+ if (!data)
+ return -EINVAL;
+
+ platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
+ if (!platform_data)
+ return -ENOMEM;
+ return 0;
+}
+
+const struct ath6kl_platform_data *ath6kl_get_platform_data(void)
+{
+ if (!platform_data)
+ return ERR_PTR(-ENODEV);
+ return platform_data;
+}
+EXPORT_SYMBOL(ath6kl_get_platform_data);
diff --git a/include/linux/ath6kl.h b/include/linux/ath6kl.h
new file mode 100644
index 00000000000..0e0ff495481
--- /dev/null
+++ b/include/linux/ath6kl.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LINUX_ATH6KL_PLATFORM_H
+#define _LINUX_ATH6KL_PLATFORM_H
+
+struct ath6kl_platform_data {
+ int (*setup_power)(bool);
+};
+
+#ifdef CONFIG_ATH6KL_PLATFORM_DATA
+int ath6kl_set_platform_data(const struct ath6kl_platform_data *data);
+#else
+static inline
+int ath6kl_set_platform_data(const struct ath6kl_platform_data *data)
+{
+ return -ENOSYS;
+}
+#endif
+
+const struct ath6kl_platform_data *ath6kl_get_platform_data(void);
+
+#endif /* _LINUX_ATH6KL_PLATFORM_H */