diff options
author | Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> | 2011-05-18 23:16:54 +0200 |
---|---|---|
committer | Philippe LANGLAIS <philippe.langlais@stericsson.com> | 2011-05-23 08:29:23 +0200 |
commit | 0119664ee6eb134c26ccd78fc0885741f0f1c036 (patch) | |
tree | e9386a0ca0cfbfe97fff610e178fa69d51a26864 | |
parent | 4f4ef8517117b92f596da8482a55d67a34384817 (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/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500-wlan.c | 108 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500-wlan.h | 17 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500.c | 2 | ||||
-rw-r--r-- | drivers/staging/cw1200/cw1200_plat.h | 19 | ||||
-rw-r--r-- | drivers/staging/cw1200/cw1200_sdio.c | 135 |
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()); } |