summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>2011-05-18 23:16:54 +0200
committerPhilippe LANGLAIS <philippe.langlais@stericsson.com>2011-05-23 08:29:23 +0200
commit0119664ee6eb134c26ccd78fc0885741f0f1c036 (patch)
treee9386a0ca0cfbfe97fff610e178fa69d51a26864
parent4f4ef8517117b92f596da8482a55d67a34384817 (diff)
cw1200: Integration with mach-ux500
CW1200 platform data is defined and set in arch/arm/mach-ux500. TODO: WLAN regulators are defined but not handled. Waiting for support in mach-ux500. Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> Change-Id: If368398af1ca22366bb44c3bb8c7e3b1484cab1b Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23353 Reviewed-by: Janusz DZIEDZIC <janusz.dziedzic@tieto.com> Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
-rw-r--r--arch/arm/mach-ux500/Makefile3
-rw-r--r--arch/arm/mach-ux500/board-mop500-wlan.c108
-rw-r--r--arch/arm/mach-ux500/board-mop500-wlan.h17
-rw-r--r--arch/arm/mach-ux500/board-mop500.c2
-rw-r--r--drivers/staging/cw1200/cw1200_plat.h19
-rw-r--r--drivers/staging/cw1200/cw1200_sdio.c135
6 files changed, 194 insertions, 90 deletions
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index caef1fc3fc0..e76ac44a440 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -17,7 +17,8 @@ obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \
board-mop500-uib.o board-mop500-stuib.o \
board-mop500-u8500uib.o board-mop500-pins.o \
board-mop500-mcde.o \
- board-mop500-msp.o board-mop500-bm.o
+ board-mop500-msp.o board-mop500-bm.o \
+ board-mop500-wlan.o
obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o \
board-u5500-mcde.o board-u5500-regulators.o \
board-u5500-pins.o
diff --git a/arch/arm/mach-ux500/board-mop500-wlan.c b/arch/arm/mach-ux500/board-mop500-wlan.c
new file mode 100644
index 00000000000..c24069600ca
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-wlan.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <asm/mach-types.h>
+#include <mach/irqs-board-mop500.h>
+#include "../drivers/staging/cw1200/cw1200_plat.h"
+
+static void cw1200_release(struct device *dev);
+
+static struct resource cw1200_href_resources[] = {
+ {
+ .start = 215,
+ .end = 215,
+ .flags = IORESOURCE_IO,
+ .name = "cw1200_reset",
+ },
+#ifdef CONFIG_CW1200_USE_GPIO_IRQ
+ {
+ .start = NOMADIK_GPIO_TO_IRQ(216),
+ .end = NOMADIK_GPIO_TO_IRQ(216),
+ .flags = IORESOURCE_IRQ,
+ .name = "cw1200_irq",
+ },
+#endif /* CONFIG_CW1200_USE_GPIO_IRQ */
+};
+
+static struct resource cw1200_href60_resources[] = {
+ {
+ .start = 85,
+ .end = 85,
+ .flags = IORESOURCE_IO,
+ .name = "cw1200_reset",
+ },
+#ifdef CONFIG_CW1200_USE_GPIO_IRQ
+ {
+ .start = NOMADIK_GPIO_TO_IRQ(4),
+ .end = NOMADIK_GPIO_TO_IRQ(4),
+ .flags = IORESOURCE_IRQ,
+ .name = "cw1200_irq",
+ },
+#endif /* CONFIG_CW1200_USE_GPIO_IRQ */
+};
+
+static struct cw1200_platform_data cw1200_platform_data = {
+ .regulator_vdd = "vdd",
+ .regulator_vio = "vio",
+};
+
+static struct platform_device cw1200_device = {
+ .name = "cw1200",
+ .dev = {
+ .platform_data = &cw1200_platform_data,
+ .release = cw1200_release,
+ },
+};
+
+const struct cw1200_platform_data *cw1200_get_platform_data(void)
+{
+ return &cw1200_platform_data;
+}
+EXPORT_SYMBOL_GPL(cw1200_get_platform_data);
+
+int __init mop500_wlan_init(void)
+{
+ if (machine_is_snowball() ||
+ machine_is_u8500() ||
+ machine_is_u5500() ||
+ machine_is_nomadik()) {
+ cw1200_device.num_resources =
+ ARRAY_SIZE(cw1200_href_resources);
+ cw1200_device.resource = cw1200_href_resources;
+ } else if (machine_is_hrefv60()) {
+ cw1200_device.num_resources =
+ ARRAY_SIZE(cw1200_href60_resources);
+ cw1200_device.resource = cw1200_href60_resources;
+ } else {
+ dev_err(&cw1200_device.dev,
+ "Unsupported mach type %d "
+ "(check mach-types.h)\n",
+ __machine_arch_type);
+ return -ENOTSUPP;
+ }
+
+ if (machine_is_snowball())
+ cw1200_platform_data.mmc_id = "mmc2";
+ else
+ cw1200_platform_data.mmc_id = "mmc3";
+
+ cw1200_platform_data.reset = &cw1200_device.resource[0];
+#ifdef CONFIG_CW1200_USE_GPIO_IRQ
+ cw1200_platform_data.irq = &cw1200_device.resource[1];
+#endif /* #ifdef CONFIG_CW1200_USE_GPIO_IRQ */
+
+ cw1200_device.dev.release = cw1200_release;
+
+ return platform_device_register(&cw1200_device);
+}
+
+static void cw1200_release(struct device *dev)
+{
+ /* Do nothing: release is handled by SDIO stack */
+}
diff --git a/arch/arm/mach-ux500/board-mop500-wlan.h b/arch/arm/mach-ux500/board-mop500-wlan.h
new file mode 100644
index 00000000000..c6788adc46f
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-wlan.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * U8500 board specific cw1200 (WLAN device) initialization.
+ *
+ * Author: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>
+ *
+ */
+
+#ifndef __BOARD_MOP500_WLAN_H
+#define __BOARD_MOP500_WLAN_H
+
+int mop500_wlan_init(void);
+
+#endif
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index e4a1da9c568..780b6537a1f 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -54,6 +54,7 @@
#include "board-mop500.h"
#include "board-mop500-regulators.h"
#include "board-mop500-bm.h"
+#include "board-mop500-wlan.h"
#ifdef CONFIG_AB8500_DENC
static struct ab8500_denc_platform_data ab8500_denc_pdata = {
@@ -842,6 +843,7 @@ static void __init mop500_init_machine(void)
mop500_msp_init();
mop500_spi_init();
mop500_uart_init();
+ mop500_wlan_init();
i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
if (machine_is_hrefv60())
diff --git a/drivers/staging/cw1200/cw1200_plat.h b/drivers/staging/cw1200/cw1200_plat.h
new file mode 100644
index 00000000000..3b6acaff305
--- /dev/null
+++ b/drivers/staging/cw1200/cw1200_plat.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/ioport.h>
+
+struct cw1200_platform_data {
+ const char *regulator_vdd;
+ const char *regulator_vio;
+ const char *mmc_id;
+ const struct resource *irq;
+ const struct resource *reset;
+};
+
+/* Declaration only. Should be implemented in arch/xxx/mach-yyy */
+const struct cw1200_platform_data *cw1200_get_platform_data(void);
diff --git a/drivers/staging/cw1200/cw1200_sdio.c b/drivers/staging/cw1200/cw1200_sdio.c
index 5c84975b361..2b7d0a1eaf7 100644
--- a/drivers/staging/cw1200/cw1200_sdio.c
+++ b/drivers/staging/cw1200/cw1200_sdio.c
@@ -19,43 +19,24 @@
#include <linux/mmc/sdio.h>
#include <linux/spinlock.h>
#include <asm/mach-types.h>
-
#include <net/mac80211.h>
#include "cw1200.h"
#include "sbus.h"
+#include "cw1200_plat.h"
MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>");
MODULE_DESCRIPTION("mac80211 ST-Ericsson CW1200 SDIO driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("cw1200_wlan");
-
-/* Module parameter for MMC interface to probe the driver on. */
-static char device_name[10] = "mmc3";
-module_param_string(device, device_name, sizeof(device_name), S_IRUGO);
-MODULE_PARM_DESC(device, "SDIO interface device is connected to");
-
-#define CW1200_GPIO_LOW (0)
-#define CW1200_GPIO_HIGH (1)
-
-enum cw1200_plat_t {
- cw1200_plat_href = 0,
- cw1200_plat_hrefv60,
- cw1200_plat_snowball,
-};
-
-struct cw1200_gpio {
- int reset;
- int irq;
-};
+MODULE_ALIAS("cw1200");
struct sbus_priv {
struct sdio_func *func;
struct cw1200_common *core;
+ const struct cw1200_platform_data *pdata;
spinlock_t lock;
sbus_irq_handler irq_handler;
void *irq_priv;
- enum cw1200_plat_t plat;
};
static const struct sdio_device_id if_sdio_ids[] = {
@@ -63,22 +44,6 @@ static const struct sdio_device_id if_sdio_ids[] = {
{ /* end: all zeroes */ },
};
-/* TODO: Move to the platform data */
-static const struct cw1200_gpio cw1200_gpio_table[] = {
- [cw1200_plat_href] = {
- .reset = 215,
- .irq = 216,
- },
- [cw1200_plat_hrefv60] = {
- .reset = 85,
- .irq = 4,
- },
- [cw1200_plat_snowball] = {
- .reset = 215,
- .irq = 216,
- },
-};
-
/* sbus_ops implemetation */
static int cw1200_sdio_memcpy_fromio(struct sbus_priv *self,
@@ -138,24 +103,15 @@ static int cw1200_request_irq(struct sbus_priv *self,
{
int ret;
int func_num;
- int gpio = cw1200_gpio_table[self->plat].irq;
- int irq = gpio_to_irq(gpio);
+ const struct resource *irq = self->pdata->irq;
u8 cccr;
- ret = gpio_request(gpio, "cw1200_irq");
- if (WARN_ON(ret))
- goto exit;
-
- ret = gpio_direction_input(gpio);
- if (WARN_ON(ret))
- goto free_gpio;
-
- ret = request_any_context_irq(irq, handler,
- IRQF_TRIGGER_RISING, "cw1200_irq", self);
+ ret = request_any_context_irq(irq->start, handler,
+ IRQF_TRIGGER_RISING, irq->name, self);
if (WARN_ON(ret < 0))
- goto free_gpio;
+ goto exit;
- ret = enable_irq_wake(irq);
+ ret = enable_irq_wake(irq->start);
if (WARN_ON(ret))
goto free_irq;
@@ -183,11 +139,9 @@ static int cw1200_request_irq(struct sbus_priv *self,
set_func:
self->func->num = func_num;
- disable_irq_wake(irq);
+ disable_irq_wake(irq->start);
free_irq:
- free_irq(irq, self);
-free_gpio:
- gpio_free(gpio);
+ free_irq(irq->start, self);
exit:
return ret;
}
@@ -224,8 +178,7 @@ static int cw1200_sdio_irq_unsubscribe(struct sbus_priv *self)
int ret = 0;
unsigned long flags;
#ifdef CONFIG_CW1200_USE_GPIO_IRQ
- int gpio = cw1200_gpio_table[self->plat].irq;
- int irq = gpio_to_irq(gpio);
+ const struct resource *irq = self->pdata->irq;
#endif
WARN_ON(!self->irq_handler);
@@ -238,9 +191,8 @@ static int cw1200_sdio_irq_unsubscribe(struct sbus_priv *self)
ret = sdio_release_irq(self->func);
sdio_release_host(self->func);
#else
- disable_irq_wake(irq);
- free_irq(irq, self);
- gpio_free(gpio);
+ disable_irq_wake(irq->start);
+ free_irq(irq->start, self);
#endif
spin_lock_irqsave(&self->lock, flags);
@@ -251,7 +203,7 @@ static int cw1200_sdio_irq_unsubscribe(struct sbus_priv *self)
return ret;
}
-static int cw1200_detect_card(void)
+static int cw1200_detect_card(const struct cw1200_platform_data *pdata)
{
/* HACK!!!
* Rely on mmc->class_dev.class set in mmc_alloc_host
@@ -273,8 +225,8 @@ static int cw1200_detect_card(void)
for (;;) {
dev = class_dev_iter_next(&iter);
if (!dev) {
- printk(KERN_ERR "CW1200: %s is not found.\n",
- device_name);
+ printk(KERN_ERR "cw1200: %s is not found.\n",
+ pdata->mmc_id);
break;
} else {
struct mmc_host *host = container_of(dev,
@@ -282,7 +234,7 @@ static int cw1200_detect_card(void)
if (dev_name(&host->class_dev) &&
strcmp(dev_name(&host->class_dev),
- device_name))
+ pdata->mmc_id))
continue;
mmc_detect_change(host, 10);
@@ -293,28 +245,30 @@ static int cw1200_detect_card(void)
return 0;
}
-static int cw1200_sdio_off(void)
+static int cw1200_sdio_off(const struct cw1200_platform_data *pdata)
{
- gpio_set_value(215, CW1200_GPIO_LOW);
- cw1200_detect_card();
- gpio_free(215);
+ const struct resource *reset = pdata->reset;
+ gpio_set_value(reset->start, 0);
+ cw1200_detect_card(pdata);
+ gpio_free(reset->start);
return 0;
}
-static int cw1200_sdio_on(void)
+static int cw1200_sdio_on(const struct cw1200_platform_data *pdata)
{
- gpio_request(215, "cw1200_sdio");
- gpio_direction_output(215, 1);
- gpio_set_value(215, CW1200_GPIO_HIGH);
- cw1200_detect_card();
+ const struct resource *reset = pdata->reset;
+ gpio_request(reset->start, reset->name);
+ gpio_direction_output(reset->start, 1);
+ gpio_set_value(reset->start, 1);
+ cw1200_detect_card(pdata);
return 0;
}
static int cw1200_sdio_reset(struct sbus_priv *self)
{
- cw1200_sdio_off();
+ cw1200_sdio_off(self->pdata);
mdelay(1000);
- cw1200_sdio_on();
+ cw1200_sdio_on(self->pdata);
return 0;
}
@@ -356,14 +310,8 @@ static int cw1200_sdio_probe(struct sdio_func *func,
return -ENOMEM;
}
- if (machine_is_snowball())
- self->plat = cw1200_plat_snowball;
- else if (machine_is_hrefv60())
- self->plat = cw1200_plat_hrefv60;
- else
- self->plat = cw1200_plat_href;
-
spin_lock_init(&self->lock);
+ self->pdata = cw1200_get_platform_data();
self->func = func;
sdio_set_drvdata(func, self);
sdio_claim_host(func);
@@ -402,7 +350,7 @@ static void cw1200_sdio_disconnect(struct sdio_func *func)
}
static struct sdio_driver sdio_driver = {
- .name = "cw1200_wlan",
+ .name = "cw1200",
.id_table = if_sdio_ids,
.probe = cw1200_sdio_probe,
.remove = cw1200_sdio_disconnect,
@@ -411,12 +359,21 @@ static struct sdio_driver sdio_driver = {
/* Init Module function -> Called by insmod */
static int __init cw1200_sdio_init(void)
{
- int ret = sdio_register_driver(&sdio_driver);
+ int ret;
+
+ ret = sdio_register_driver(&sdio_driver);
if (ret)
- return ret;
- ret = cw1200_sdio_on();
+ goto err_reg;
+
+ ret = cw1200_sdio_on(cw1200_get_platform_data());
if (ret)
- sdio_unregister_driver(&sdio_driver);
+ goto err_on;
+
+ return 0;
+
+err_on:
+ sdio_unregister_driver(&sdio_driver);
+err_reg:
return ret;
}
@@ -424,7 +381,7 @@ static int __init cw1200_sdio_init(void)
static void __exit cw1200_sdio_exit(void)
{
sdio_unregister_driver(&sdio_driver);
- cw1200_sdio_off();
+ cw1200_sdio_off(cw1200_get_platform_data());
}