From c992219825823cad5e11fab3854eb93df2e9ffa1 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 2 Jun 2013 09:53:01 -0400 Subject: cw1200: move platform_data header to correct location. (As suggested by Arnd Bergmann) Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- include/linux/platform_data/cw1200_platform.h | 46 +++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 include/linux/platform_data/cw1200_platform.h (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/cw1200_platform.h b/include/linux/platform_data/cw1200_platform.h new file mode 100644 index 000000000000..c168fa512347 --- /dev/null +++ b/include/linux/platform_data/cw1200_platform.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Dmitry Tarnyagin + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CW1200_PLAT_H_INCLUDED +#define CW1200_PLAT_H_INCLUDED + +struct cw1200_platform_data_spi { + u8 spi_bits_per_word; /* REQUIRED */ + u16 ref_clk; /* REQUIRED (in KHz) */ + + /* All others are optional */ + bool have_5ghz; + const struct resource *reset; /* GPIO to RSTn signal */ + const struct resource *powerup; /* GPIO to POWERUP signal */ + int (*power_ctrl)(const struct cw1200_platform_data_spi *pdata, + bool enable); /* Control 3v3 / 1v8 supply */ + int (*clk_ctrl)(const struct cw1200_platform_data_spi *pdata, + bool enable); /* Control CLK32K */ + const u8 *macaddr; /* if NULL, use cw1200_mac_template module parameter */ + const char *sdd_file; /* if NULL, will use default for detected hw type */ +}; + +struct cw1200_platform_data_sdio { + u16 ref_clk; /* REQUIRED (in KHz) */ + + /* All others are optional */ + const struct resource *irq; /* if using GPIO for IRQ */ + bool have_5ghz; + bool no_nptb; /* SDIO hardware does not support non-power-of-2-blocksizes */ + const struct resource *reset; /* GPIO to RSTn signal */ + const struct resource *powerup; /* GPIO to POWERUP signal */ + int (*power_ctrl)(const struct cw1200_platform_data_sdio *pdata, + bool enable); /* Control 3v3 / 1v8 supply */ + int (*clk_ctrl)(const struct cw1200_platform_data_sdio *pdata, + bool enable); /* Control CLK32K */ + const u8 *macaddr; /* if NULL, use cw1200_mac_template module parameter */ + const char *sdd_file; /* if NULL, will use default for detected hw type */ +}; + +const void *cw1200_get_platform_data(void); + +#endif /* CW1200_PLAT_H_INCLUDED */ -- cgit v1.2.3-71-gd317 From 6dd64a304eff76ca7dd41bf63df55efa965fa9ec Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 2 Jun 2013 09:53:03 -0400 Subject: cw1200: Replace use of 'struct resource' with 'int' for GPIO fields. The only advantage of 'struct resource' is that it lets us assign names as part of the platform data. Unfortunately since we are using platform data, we are already limited to a single instance of each driver, rendering this moot. So, replace the struct resources with ints, resulting in cleaner code. This was based on a suggestion from Arnd Bergmann. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/cw1200_sagrad.c | 49 +++----------------------- drivers/net/wireless/cw1200/cw1200_sdio.c | 50 ++++++++++++--------------- drivers/net/wireless/cw1200/cw1200_spi.c | 33 ++++++++---------- include/linux/platform_data/cw1200_platform.h | 12 +++---- 4 files changed, 47 insertions(+), 97 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/net/wireless/cw1200/cw1200_sagrad.c b/drivers/net/wireless/cw1200/cw1200_sagrad.c index 14c2a186b493..3f884ac96ccc 100644 --- a/drivers/net/wireless/cw1200/cw1200_sagrad.c +++ b/drivers/net/wireless/cw1200/cw1200_sagrad.c @@ -21,29 +21,6 @@ MODULE_LICENSE("GPL"); /* #define SAGRAD_1091_1098_EVK_SPI */ #ifdef SAGRAD_1091_1098_EVK_SDIO -#if 0 -static struct resource cw1200_href_resources[] = { - { - .start = 215, /* fix me as appropriate */ - .end = 215, /* ditto */ - .flags = IORESOURCE_IO, - .name = "cw1200_wlan_reset", - }, - { - .start = 216, /* fix me as appropriate */ - .end = 216, /* ditto */ - .flags = IORESOURCE_IO, - .name = "cw1200_wlan_powerup", - }, - { - .start = NOMADIK_GPIO_TO_IRQ(216), /* fix me as appropriate */ - .end = NOMADIK_GPIO_TO_IRQ(216), /* ditto */ - .flags = IORESOURCE_IRQ, - .name = "cw1200_wlan_irq", - }, -}; -#endif - static int cw1200_power_ctrl(const struct cw1200_platform_data_sdio *pdata, bool enable) { @@ -68,9 +45,9 @@ static struct cw1200_platform_data_sdio cw1200_platform_data = { .ref_clk = 38400, .have_5ghz = false, #if 0 - .reset = &cw1200_href_resources[0], - .powerup = &cw1200_href_resources[1], - .irq = &cw1200_href_resources[2], + .reset = GPIO_RF_RESET, /* Replace as appropriate */ + .powerup = GPIO_RF_POWERUP, /* Replace as appropriate */ + .irq = GPIO_TO_IRQ(GPIO_RF_IRQ), /* Replace as appropriate */ #endif .power_ctrl = cw1200_power_ctrl, .clk_ctrl = cw1200_clk_ctrl, @@ -80,22 +57,6 @@ static struct cw1200_platform_data_sdio cw1200_platform_data = { #endif #ifdef SAGRAD_1091_1098_EVK_SPI -/* Note that this is an example of integrating into your board support file */ -static struct resource cw1200_href_resources[] = { - { - .start = GPIO_RF_RESET, - .end = GPIO_RF_RESET, - .flags = IORESOURCE_IO, - .name = "cw1200_wlan_reset", - }, - { - .start = GPIO_RF_POWERUP, - .end = GPIO_RF_POWERUP, - .flags = IORESOURCE_IO, - .name = "cw1200_wlan_powerup", - }, -}; - static int cw1200_power_ctrl(const struct cw1200_platform_data_spi *pdata, bool enable) { @@ -118,8 +79,8 @@ static int cw1200_clk_ctrl(const struct cw1200_platform_data_spi *pdata, static struct cw1200_platform_data_spi cw1200_platform_data = { .ref_clk = 38400, .spi_bits_per_word = 16, - .reset = &cw1200_href_resources[0], - .powerup = &cw1200_href_resources[1], + .reset = GPIO_RF_RESET, /* Replace as appropriate */ + .powerup = GPIO_RF_POWERUP, /* Replace as appropriate */ .power_ctrl = cw1200_power_ctrl, .clk_ctrl = cw1200_clk_ctrl, /* .macaddr = ??? */ diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index 0a882ca89bbb..574cf727567c 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -105,7 +105,6 @@ static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id) static int cw1200_request_irq(struct hwbus_priv *self) { int ret; - const struct resource *irq = self->pdata->irq; u8 cccr; cccr = sdio_f0_readb(self->func, SDIO_CCCR_IENx, &ret); @@ -122,15 +121,15 @@ static int cw1200_request_irq(struct hwbus_priv *self) if (WARN_ON(ret)) goto err; - ret = enable_irq_wake(irq->start); + ret = enable_irq_wake(self->pdata->irq); if (WARN_ON(ret)) goto err; /* Request the IRQ */ - ret = request_threaded_irq(irq->start, cw1200_gpio_hardirq, + ret = request_threaded_irq(self->pdata->irq, cw1200_gpio_hardirq, cw1200_gpio_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - irq->name, self); + "cw1200_wlan_irq", self); if (WARN_ON(ret)) goto err; @@ -162,8 +161,8 @@ static int cw1200_sdio_irq_unsubscribe(struct hwbus_priv *self) pr_debug("SW IRQ unsubscribe\n"); if (self->pdata->irq) { - disable_irq_wake(self->pdata->irq->start); - free_irq(self->pdata->irq->start, self); + disable_irq_wake(self->pdata->irq); + free_irq(self->pdata->irq, self); } else { sdio_claim_host(self->func); ret = sdio_release_irq(self->func); @@ -174,12 +173,10 @@ static int cw1200_sdio_irq_unsubscribe(struct hwbus_priv *self) static int cw1200_sdio_off(const struct cw1200_platform_data_sdio *pdata) { - const struct resource *reset = pdata->reset; - - if (reset) { - gpio_set_value(reset->start, 0); + if (pdata->reset) { + gpio_set_value(pdata->reset, 0); msleep(30); /* Min is 2 * CLK32K cycles */ - gpio_free(reset->start); + gpio_free(pdata->reset); } if (pdata->power_ctrl) @@ -192,20 +189,17 @@ static int cw1200_sdio_off(const struct cw1200_platform_data_sdio *pdata) static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata) { - const struct resource *reset = pdata->reset; - const struct resource *powerup = pdata->powerup; - /* Ensure I/Os are pulled low */ - if (reset) { - gpio_request(reset->start, reset->name); - gpio_direction_output(reset->start, 0); + if (pdata->reset) { + gpio_request(pdata->reset, "cw1200_wlan_reset"); + gpio_direction_output(pdata->reset, 0); } - if (powerup) { - gpio_request(powerup->start, powerup->name); - gpio_direction_output(powerup->start, 0); + if (pdata->powerup) { + gpio_request(pdata->powerup, "cw1200_wlan_powerup"); + gpio_direction_output(pdata->powerup, 0); } - if (reset || powerup) - msleep(50); /* Settle time */ + if (pdata->reset || pdata->powerup) + msleep(10); /* Settle time? */ /* Enable 3v3 and 1v8 to hardware */ if (pdata->power_ctrl) { @@ -225,13 +219,13 @@ static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata) } /* Enable POWERUP signal */ - if (powerup) { - gpio_set_value(powerup->start, 1); + if (pdata->powerup) { + gpio_set_value(pdata->powerup, 1); msleep(250); /* or more..? */ } /* Enable RSTn signal */ - if (reset) { - gpio_set_value(reset->start, 1); + if (pdata->reset) { + gpio_set_value(pdata->reset, 1); msleep(50); /* Or more..? */ } return 0; @@ -252,7 +246,7 @@ static int cw1200_sdio_pm(struct hwbus_priv *self, bool suspend) int ret = 0; if (self->pdata->irq) - ret = irq_set_irq_wake(self->pdata->irq->start, suspend); + ret = irq_set_irq_wake(self->pdata->irq, suspend); return ret; } @@ -274,7 +268,7 @@ static int cw1200_sdio_probe(struct sdio_func *func, pr_info("cw1200_wlan_sdio: Probe called\n"); - /* We are only able to handle the wlan function */ + /* We are only able to handle the wlan function */ if (func->num != 0x01) return -ENODEV; diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index da5d24cc67db..d8dc7c6bb96d 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -268,12 +268,10 @@ static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self) static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata) { - const struct resource *reset = pdata->reset; - - if (reset) { - gpio_set_value(reset->start, 0); + if (pdata->reset) { + gpio_set_value(pdata->reset, 0); msleep(30); /* Min is 2 * CLK32K cycles */ - gpio_free(reset->start); + gpio_free(pdata->reset); } if (pdata->power_ctrl) @@ -286,19 +284,16 @@ static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata) static int cw1200_spi_on(const struct cw1200_platform_data_spi *pdata) { - const struct resource *reset = pdata->reset; - const struct resource *powerup = pdata->powerup; - /* Ensure I/Os are pulled low */ - if (reset) { - gpio_request(reset->start, reset->name); - gpio_direction_output(reset->start, 0); + if (pdata->reset) { + gpio_request(pdata->reset, "cw1200_wlan_reset"); + gpio_direction_output(pdata->reset, 0); } - if (powerup) { - gpio_request(powerup->start, powerup->name); - gpio_direction_output(powerup->start, 0); + if (pdata->powerup) { + gpio_request(pdata->powerup, "cw1200_wlan_powerup"); + gpio_direction_output(pdata->powerup, 0); } - if (reset || powerup) + if (pdata->reset || pdata->powerup) msleep(10); /* Settle time? */ /* Enable 3v3 and 1v8 to hardware */ @@ -319,13 +314,13 @@ static int cw1200_spi_on(const struct cw1200_platform_data_spi *pdata) } /* Enable POWERUP signal */ - if (powerup) { - gpio_set_value(powerup->start, 1); + if (pdata->powerup) { + gpio_set_value(pdata->powerup, 1); msleep(250); /* or more..? */ } /* Enable RSTn signal */ - if (reset) { - gpio_set_value(reset->start, 1); + if (pdata->reset) { + gpio_set_value(pdata->reset, 1); msleep(50); /* Or more..? */ } return 0; diff --git a/include/linux/platform_data/cw1200_platform.h b/include/linux/platform_data/cw1200_platform.h index c168fa512347..4454c16ea3e5 100644 --- a/include/linux/platform_data/cw1200_platform.h +++ b/include/linux/platform_data/cw1200_platform.h @@ -14,8 +14,8 @@ struct cw1200_platform_data_spi { /* All others are optional */ bool have_5ghz; - const struct resource *reset; /* GPIO to RSTn signal */ - const struct resource *powerup; /* GPIO to POWERUP signal */ + int reset; /* GPIO to RSTn signal (0 disables) */ + int powerup; /* GPIO to POWERUP signal (0 disables) */ int (*power_ctrl)(const struct cw1200_platform_data_spi *pdata, bool enable); /* Control 3v3 / 1v8 supply */ int (*clk_ctrl)(const struct cw1200_platform_data_spi *pdata, @@ -28,11 +28,11 @@ struct cw1200_platform_data_sdio { u16 ref_clk; /* REQUIRED (in KHz) */ /* All others are optional */ - const struct resource *irq; /* if using GPIO for IRQ */ bool have_5ghz; - bool no_nptb; /* SDIO hardware does not support non-power-of-2-blocksizes */ - const struct resource *reset; /* GPIO to RSTn signal */ - const struct resource *powerup; /* GPIO to POWERUP signal */ + bool no_nptb; /* SDIO hardware does not support non-power-of-2-blocksizes */ + int reset; /* GPIO to RSTn signal (0 disables) */ + int powerup; /* GPIO to POWERUP signal (0 disables) */ + int irq; /* IRQ line or 0 to use SDIO IRQ */ int (*power_ctrl)(const struct cw1200_platform_data_sdio *pdata, bool enable); /* Control 3v3 / 1v8 supply */ int (*clk_ctrl)(const struct cw1200_platform_data_sdio *pdata, -- cgit v1.2.3-71-gd317 From 7c0b6f49dbea0b09b1de8aa5c942af9c2ad8b54c Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 2 Jun 2013 11:35:31 -0400 Subject: cw1200: Rework SDIO platform support to prevent build problems. Based on discussions with And Bergmann, this patch changes the SDIO platform code to default to supporting the Sagrad devices, allowing for it to be overridden in board setup code. This renders the cw1200_sagrad module suplerflous, so it is now removed. It also moves the documentation that was in the cw1200_sagrad source to the platform header. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/Kconfig | 17 ++--- drivers/net/wireless/cw1200/Makefile | 2 - drivers/net/wireless/cw1200/cw1200_sagrad.c | 106 -------------------------- drivers/net/wireless/cw1200/cw1200_sdio.c | 26 ++++++- include/linux/platform_data/cw1200_platform.h | 37 ++++++++- 5 files changed, 66 insertions(+), 122 deletions(-) delete mode 100644 drivers/net/wireless/cw1200/cw1200_sagrad.c (limited to 'include/linux/platform_data') diff --git a/drivers/net/wireless/cw1200/Kconfig b/drivers/net/wireless/cw1200/Kconfig index 13e36119ae9f..7a585d4e9c8e 100644 --- a/drivers/net/wireless/cw1200/Kconfig +++ b/drivers/net/wireless/cw1200/Kconfig @@ -13,20 +13,19 @@ config CW1200_WLAN_SDIO depends on CW1200 && MMC help Enable support for the CW1200 connected via an SDIO bus. + By default this driver only supports the Sagrad SG901-1091/1098 EVK + and similar designs that utilize a hardware reset circuit. To + support different CW1200 SDIO designs you will need to override + the default platform data by calling cw1200_sdio_set_platform_data() + in your board setup file. config CW1200_WLAN_SPI tristate "Support SPI platforms" depends on CW1200 && SPI help - Enables support for the CW1200 connected via a SPI bus. - -config CW1200_WLAN_SAGRAD - tristate "Support Sagrad SG901-1091/1098 modules" - depends on CW1200_WLAN_SDIO - help - This provides the platform data glue to support the - Sagrad SG901-1091/1098 modules in their standard SDIO EVK. - It also includes example SPI platform data. + Enables support for the CW1200 connected via a SPI bus. You will + need to add appropriate platform data glue in your board setup + file. menu "Driver debug features" depends on CW1200 && DEBUG_FS diff --git a/drivers/net/wireless/cw1200/Makefile b/drivers/net/wireless/cw1200/Makefile index 1aa3682066e0..bc6cbf91f26e 100644 --- a/drivers/net/wireless/cw1200/Makefile +++ b/drivers/net/wireless/cw1200/Makefile @@ -16,9 +16,7 @@ cw1200_core-$(CONFIG_PM) += pm.o cw1200_wlan_sdio-y := cw1200_sdio.o cw1200_wlan_spi-y := cw1200_spi.o -cw1200_wlan_sagrad-y := cw1200_sagrad.o obj-$(CONFIG_CW1200) += cw1200_core.o obj-$(CONFIG_CW1200_WLAN_SDIO) += cw1200_wlan_sdio.o obj-$(CONFIG_CW1200_WLAN_SPI) += cw1200_wlan_spi.o -obj-$(CONFIG_CW1200_WLAN_SAGRAD) += cw1200_wlan_sagrad.o diff --git a/drivers/net/wireless/cw1200/cw1200_sagrad.c b/drivers/net/wireless/cw1200/cw1200_sagrad.c deleted file mode 100644 index 3f884ac96ccc..000000000000 --- a/drivers/net/wireless/cw1200/cw1200_sagrad.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Platform glue data for ST-Ericsson CW1200 driver - * - * Copyright (c) 2013, Sagrad, Inc - * Author: Solomon Peachy - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include - -MODULE_AUTHOR("Solomon Peachy "); -MODULE_DESCRIPTION("ST-Ericsson CW1200 Platform glue driver"); -MODULE_LICENSE("GPL"); - -/* Define just one of these. Feel free to customize as needed */ -#define SAGRAD_1091_1098_EVK_SDIO -/* #define SAGRAD_1091_1098_EVK_SPI */ - -#ifdef SAGRAD_1091_1098_EVK_SDIO -static int cw1200_power_ctrl(const struct cw1200_platform_data_sdio *pdata, - bool enable) -{ - /* Control 3v3 and 1v8 to hardware as appropriate */ - /* Note this is not needed if it's controlled elsewhere or always on */ - - /* May require delay for power to stabilize */ - return 0; -} - -static int cw1200_clk_ctrl(const struct cw1200_platform_data_sdio *pdata, - bool enable) -{ - /* Turn CLK_32K off and on as appropriate. */ - /* Note this is not needed if it's always on */ - - /* May require delay for clock to stabilize */ - return 0; -} - -static struct cw1200_platform_data_sdio cw1200_platform_data = { - .ref_clk = 38400, - .have_5ghz = false, -#if 0 - .reset = GPIO_RF_RESET, /* Replace as appropriate */ - .powerup = GPIO_RF_POWERUP, /* Replace as appropriate */ - .irq = GPIO_TO_IRQ(GPIO_RF_IRQ), /* Replace as appropriate */ -#endif - .power_ctrl = cw1200_power_ctrl, - .clk_ctrl = cw1200_clk_ctrl, -/* .macaddr = ??? */ - .sdd_file = "sdd_sagrad_1091_1098.bin", -}; -#endif - -#ifdef SAGRAD_1091_1098_EVK_SPI -static int cw1200_power_ctrl(const struct cw1200_platform_data_spi *pdata, - bool enable) -{ - /* Control 3v3 and 1v8 to hardware as appropriate */ - /* Note this is not needed if it's controlled elsewhere or always on */ - - /* May require delay for power to stabilize */ - return 0; -} -static int cw1200_clk_ctrl(const struct cw1200_platform_data_spi *pdata, - bool enable) -{ - /* Turn CLK_32K off and on as appropriate. */ - /* Note this is not needed if it's always on */ - - /* May require delay for clock to stabilize */ - return 0; -} - -static struct cw1200_platform_data_spi cw1200_platform_data = { - .ref_clk = 38400, - .spi_bits_per_word = 16, - .reset = GPIO_RF_RESET, /* Replace as appropriate */ - .powerup = GPIO_RF_POWERUP, /* Replace as appropriate */ - .power_ctrl = cw1200_power_ctrl, - .clk_ctrl = cw1200_clk_ctrl, -/* .macaddr = ??? */ - .sdd_file = "sdd_sagrad_1091_1098.bin", -}; -static struct spi_board_info myboard_spi_devices[] __initdata = { - { - .modalias = "cw1200_wlan_spi", - .max_speed_hz = 10000000, /* 52MHz Max */ - .bus_num = 0, - .irq = WIFI_IRQ, - .platform_data = &cw1200_platform_data, - .chip_select = 0, - }, -}; -#endif - - -const void *cw1200_get_platform_data(void) -{ - return &cw1200_platform_data; -} -EXPORT_SYMBOL_GPL(cw1200_get_platform_data); diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index 574cf727567c..4b3148e47ee7 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -29,6 +29,21 @@ MODULE_LICENSE("GPL"); #define SDIO_BLOCK_SIZE (512) +/* Default platform data for Sagrad modules */ +static struct cw1200_platform_data_sdio sagrad_109x_evk_platform_data = { + .ref_clk = 38400, + .have_5ghz = false, + .sdd_file = "sdd_sagrad_1091_1098.bin", +}; + +/* Allow platform data to be overridden */ +static struct cw1200_platform_data_sdio *global_plat_data = &sagrad_109x_evk_platform_data; + +void __init cw1200_sdio_set_platform_data(struct cw1200_platform_data_sdio *pdata) +{ + global_plat_data = pdata; +} + struct hwbus_priv { struct sdio_func *func; struct cw1200_common *core; @@ -261,7 +276,7 @@ static struct hwbus_ops cw1200_sdio_hwbus_ops = { /* Probe Function to be called by SDIO stack when device is discovered */ static int cw1200_sdio_probe(struct sdio_func *func, - const struct sdio_device_id *id) + const struct sdio_device_id *id) { struct hwbus_priv *self; int status; @@ -280,7 +295,7 @@ static int cw1200_sdio_probe(struct sdio_func *func, func->card->quirks |= MMC_QUIRK_LENIENT_FN0; - self->pdata = cw1200_get_platform_data(); + self->pdata = global_plat_data; /* FIXME */ self->func = func; sdio_set_drvdata(func, self); sdio_claim_host(func); @@ -374,7 +389,8 @@ static int __init cw1200_sdio_init(void) const struct cw1200_platform_data_sdio *pdata; int ret; - pdata = cw1200_get_platform_data(); + /* FIXME -- this won't support multiple devices */ + pdata = global_plat_data; if (cw1200_sdio_on(pdata)) { ret = -1; @@ -396,7 +412,9 @@ err: static void __exit cw1200_sdio_exit(void) { const struct cw1200_platform_data_sdio *pdata; - pdata = cw1200_get_platform_data(); + + /* FIXME -- this won't support multiple devices */ + pdata = global_plat_data; sdio_unregister_driver(&sdio_driver); cw1200_sdio_off(pdata); } diff --git a/include/linux/platform_data/cw1200_platform.h b/include/linux/platform_data/cw1200_platform.h index 4454c16ea3e5..c6fbc3ce4ab0 100644 --- a/include/linux/platform_data/cw1200_platform.h +++ b/include/linux/platform_data/cw1200_platform.h @@ -41,6 +41,41 @@ struct cw1200_platform_data_sdio { const char *sdd_file; /* if NULL, will use default for detected hw type */ }; -const void *cw1200_get_platform_data(void); + +/* An example of SPI support in your board setup file: + + static struct cw1200_platform_data_spi cw1200_platform_data = { + .ref_clk = 38400, + .spi_bits_per_word = 16, + .reset = GPIO_RF_RESET, + .powerup = GPIO_RF_POWERUP, + .macaddr = wifi_mac_addr, + .sdd_file = "sdd_sagrad_1091_1098.bin", + }; + static struct spi_board_info myboard_spi_devices[] __initdata = { + { + .modalias = "cw1200_wlan_spi", + .max_speed_hz = 52000000, + .bus_num = 0, + .irq = WIFI_IRQ, + .platform_data = &cw1200_platform_data, + .chip_select = 0, + }, + }; + + */ + +/* An example of SDIO support in your board setup file: + + static struct cw1200_platform_data_sdio my_cw1200_platform_data = { + .ref_clk = 38400, + .have_5ghz = false, + .sdd_file = "sdd_myplatform.bin", + }; + cw1200_sdio_set_platform_data(&my_cw1200_platform_data); + + */ + +void __init cw1200_sdio_set_platform_data(struct cw1200_platform_data_sdio *pdata); #endif /* CW1200_PLAT_H_INCLUDED */ -- cgit v1.2.3-71-gd317 From 4da2a54a842db6921289e3e25b0739531a594dea Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 2 Jun 2013 11:35:32 -0400 Subject: cw1200: rename the cw1200 platform definition header My previous patch just moved the file, but it also needed to be renamed to conform to proper conventions. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/cw1200_sdio.c | 2 +- drivers/net/wireless/cw1200/cw1200_spi.c | 2 +- include/linux/platform_data/cw1200_platform.h | 81 --------------------------- include/linux/platform_data/net-cw1200.h | 81 +++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 83 deletions(-) delete mode 100644 include/linux/platform_data/cw1200_platform.h create mode 100644 include/linux/platform_data/net-cw1200.h (limited to 'include/linux/platform_data') diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index 4b3148e47ee7..bb1f405315e4 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -20,7 +20,7 @@ #include "cw1200.h" #include "hwbus.h" -#include +#include #include "hwio.h" MODULE_AUTHOR("Dmitry Tarnyagin "); diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index d8dc7c6bb96d..e58f0a5bafa9 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -25,7 +25,7 @@ #include "cw1200.h" #include "hwbus.h" -#include +#include #include "hwio.h" MODULE_AUTHOR("Solomon Peachy "); diff --git a/include/linux/platform_data/cw1200_platform.h b/include/linux/platform_data/cw1200_platform.h deleted file mode 100644 index c6fbc3ce4ab0..000000000000 --- a/include/linux/platform_data/cw1200_platform.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * Author: Dmitry Tarnyagin - * License terms: GNU General Public License (GPL) version 2 - */ - -#ifndef CW1200_PLAT_H_INCLUDED -#define CW1200_PLAT_H_INCLUDED - -struct cw1200_platform_data_spi { - u8 spi_bits_per_word; /* REQUIRED */ - u16 ref_clk; /* REQUIRED (in KHz) */ - - /* All others are optional */ - bool have_5ghz; - int reset; /* GPIO to RSTn signal (0 disables) */ - int powerup; /* GPIO to POWERUP signal (0 disables) */ - int (*power_ctrl)(const struct cw1200_platform_data_spi *pdata, - bool enable); /* Control 3v3 / 1v8 supply */ - int (*clk_ctrl)(const struct cw1200_platform_data_spi *pdata, - bool enable); /* Control CLK32K */ - const u8 *macaddr; /* if NULL, use cw1200_mac_template module parameter */ - const char *sdd_file; /* if NULL, will use default for detected hw type */ -}; - -struct cw1200_platform_data_sdio { - u16 ref_clk; /* REQUIRED (in KHz) */ - - /* All others are optional */ - bool have_5ghz; - bool no_nptb; /* SDIO hardware does not support non-power-of-2-blocksizes */ - int reset; /* GPIO to RSTn signal (0 disables) */ - int powerup; /* GPIO to POWERUP signal (0 disables) */ - int irq; /* IRQ line or 0 to use SDIO IRQ */ - int (*power_ctrl)(const struct cw1200_platform_data_sdio *pdata, - bool enable); /* Control 3v3 / 1v8 supply */ - int (*clk_ctrl)(const struct cw1200_platform_data_sdio *pdata, - bool enable); /* Control CLK32K */ - const u8 *macaddr; /* if NULL, use cw1200_mac_template module parameter */ - const char *sdd_file; /* if NULL, will use default for detected hw type */ -}; - - -/* An example of SPI support in your board setup file: - - static struct cw1200_platform_data_spi cw1200_platform_data = { - .ref_clk = 38400, - .spi_bits_per_word = 16, - .reset = GPIO_RF_RESET, - .powerup = GPIO_RF_POWERUP, - .macaddr = wifi_mac_addr, - .sdd_file = "sdd_sagrad_1091_1098.bin", - }; - static struct spi_board_info myboard_spi_devices[] __initdata = { - { - .modalias = "cw1200_wlan_spi", - .max_speed_hz = 52000000, - .bus_num = 0, - .irq = WIFI_IRQ, - .platform_data = &cw1200_platform_data, - .chip_select = 0, - }, - }; - - */ - -/* An example of SDIO support in your board setup file: - - static struct cw1200_platform_data_sdio my_cw1200_platform_data = { - .ref_clk = 38400, - .have_5ghz = false, - .sdd_file = "sdd_myplatform.bin", - }; - cw1200_sdio_set_platform_data(&my_cw1200_platform_data); - - */ - -void __init cw1200_sdio_set_platform_data(struct cw1200_platform_data_sdio *pdata); - -#endif /* CW1200_PLAT_H_INCLUDED */ diff --git a/include/linux/platform_data/net-cw1200.h b/include/linux/platform_data/net-cw1200.h new file mode 100644 index 000000000000..c6fbc3ce4ab0 --- /dev/null +++ b/include/linux/platform_data/net-cw1200.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Dmitry Tarnyagin + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CW1200_PLAT_H_INCLUDED +#define CW1200_PLAT_H_INCLUDED + +struct cw1200_platform_data_spi { + u8 spi_bits_per_word; /* REQUIRED */ + u16 ref_clk; /* REQUIRED (in KHz) */ + + /* All others are optional */ + bool have_5ghz; + int reset; /* GPIO to RSTn signal (0 disables) */ + int powerup; /* GPIO to POWERUP signal (0 disables) */ + int (*power_ctrl)(const struct cw1200_platform_data_spi *pdata, + bool enable); /* Control 3v3 / 1v8 supply */ + int (*clk_ctrl)(const struct cw1200_platform_data_spi *pdata, + bool enable); /* Control CLK32K */ + const u8 *macaddr; /* if NULL, use cw1200_mac_template module parameter */ + const char *sdd_file; /* if NULL, will use default for detected hw type */ +}; + +struct cw1200_platform_data_sdio { + u16 ref_clk; /* REQUIRED (in KHz) */ + + /* All others are optional */ + bool have_5ghz; + bool no_nptb; /* SDIO hardware does not support non-power-of-2-blocksizes */ + int reset; /* GPIO to RSTn signal (0 disables) */ + int powerup; /* GPIO to POWERUP signal (0 disables) */ + int irq; /* IRQ line or 0 to use SDIO IRQ */ + int (*power_ctrl)(const struct cw1200_platform_data_sdio *pdata, + bool enable); /* Control 3v3 / 1v8 supply */ + int (*clk_ctrl)(const struct cw1200_platform_data_sdio *pdata, + bool enable); /* Control CLK32K */ + const u8 *macaddr; /* if NULL, use cw1200_mac_template module parameter */ + const char *sdd_file; /* if NULL, will use default for detected hw type */ +}; + + +/* An example of SPI support in your board setup file: + + static struct cw1200_platform_data_spi cw1200_platform_data = { + .ref_clk = 38400, + .spi_bits_per_word = 16, + .reset = GPIO_RF_RESET, + .powerup = GPIO_RF_POWERUP, + .macaddr = wifi_mac_addr, + .sdd_file = "sdd_sagrad_1091_1098.bin", + }; + static struct spi_board_info myboard_spi_devices[] __initdata = { + { + .modalias = "cw1200_wlan_spi", + .max_speed_hz = 52000000, + .bus_num = 0, + .irq = WIFI_IRQ, + .platform_data = &cw1200_platform_data, + .chip_select = 0, + }, + }; + + */ + +/* An example of SDIO support in your board setup file: + + static struct cw1200_platform_data_sdio my_cw1200_platform_data = { + .ref_clk = 38400, + .have_5ghz = false, + .sdd_file = "sdd_myplatform.bin", + }; + cw1200_sdio_set_platform_data(&my_cw1200_platform_data); + + */ + +void __init cw1200_sdio_set_platform_data(struct cw1200_platform_data_sdio *pdata); + +#endif /* CW1200_PLAT_H_INCLUDED */ -- cgit v1.2.3-71-gd317 From 3b81a6809480f3fc7d9d06562704c8df18ecec00 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Wed, 26 Jun 2013 14:20:18 +0200 Subject: brcmfmac: add broken scatter-gather DMA support DMA engine of some old SDIO host controllers require block size alignment for data length of each scatterlist item. This patch introduces an intermediate buffer list to support this kind of platform. It decreases the throughput because of an extra memcpy in critical data path. So don't turn this on unless it's necessary. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend van Spriel Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 78 ++++++++++++++++++++---- include/linux/platform_data/brcmfmac-sdio.h | 5 ++ 2 files changed, 72 insertions(+), 11 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 70cd0e9cd52b..e3f3c48f86d4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -331,10 +331,11 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, bool write, u32 addr, struct sk_buff_head *pktlist) { unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset; - unsigned int max_blks, max_req_sz; + unsigned int max_blks, max_req_sz, orig_offset, dst_offset; unsigned short max_seg_sz, seg_sz; - unsigned char *pkt_data; - struct sk_buff *pkt_next = NULL; + unsigned char *pkt_data, *orig_data, *dst_data; + struct sk_buff *pkt_next = NULL, *local_pkt_next; + struct sk_buff_head local_list, *target_list; struct mmc_request mmc_req; struct mmc_command mmc_cmd; struct mmc_data mmc_dat; @@ -371,6 +372,32 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, req_sz); } + target_list = pktlist; + /* for host with broken sg support, prepare a page aligned list */ + __skb_queue_head_init(&local_list); + if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) { + req_sz = 0; + skb_queue_walk(pktlist, pkt_next) + req_sz += pkt_next->len; + req_sz = ALIGN(req_sz, sdiodev->func[fn]->cur_blksize); + while (req_sz > PAGE_SIZE) { + pkt_next = brcmu_pkt_buf_get_skb(PAGE_SIZE); + if (pkt_next == NULL) { + ret = -ENOMEM; + goto exit; + } + __skb_queue_tail(&local_list, pkt_next); + req_sz -= PAGE_SIZE; + } + pkt_next = brcmu_pkt_buf_get_skb(req_sz); + if (pkt_next == NULL) { + ret = -ENOMEM; + goto exit; + } + __skb_queue_tail(&local_list, pkt_next); + target_list = &local_list; + } + host = sdiodev->func[fn]->card->host; func_blk_sz = sdiodev->func[fn]->cur_blksize; /* Blocks per command is limited by host count, host transfer @@ -380,13 +407,15 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, max_req_sz = min_t(unsigned int, host->max_req_size, max_blks * func_blk_sz); max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC); - max_seg_sz = min_t(unsigned short, max_seg_sz, pktlist->qlen); - seg_sz = pktlist->qlen; + max_seg_sz = min_t(unsigned short, max_seg_sz, target_list->qlen); + seg_sz = target_list->qlen; pkt_offset = 0; - pkt_next = pktlist->next; + pkt_next = target_list->next; - if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) - return -ENOMEM; + if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) { + ret = -ENOMEM; + goto exit; + } while (seg_sz) { req_sz = 0; @@ -396,7 +425,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, memset(&mmc_dat, 0, sizeof(struct mmc_data)); sgl = st.sgl; /* prep sg table */ - while (pkt_next != (struct sk_buff *)pktlist) { + while (pkt_next != (struct sk_buff *)target_list) { pkt_data = pkt_next->data + pkt_offset; sg_data_sz = pkt_next->len - pkt_offset; if (sg_data_sz > host->max_seg_size) @@ -423,8 +452,8 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, if (req_sz % func_blk_sz != 0) { brcmf_err("sg request length %u is not %u aligned\n", req_sz, func_blk_sz); - sg_free_table(&st); - return -ENOTBLK; + ret = -ENOTBLK; + goto exit; } mmc_dat.sg = st.sgl; mmc_dat.sg_len = sg_cnt; @@ -457,7 +486,34 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, } } + if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) { + local_pkt_next = local_list.next; + orig_offset = 0; + skb_queue_walk(pktlist, pkt_next) { + dst_offset = 0; + do { + req_sz = local_pkt_next->len - orig_offset; + req_sz = min_t(uint, pkt_next->len - dst_offset, + req_sz); + orig_data = local_pkt_next->data + orig_offset; + dst_data = pkt_next->data + dst_offset; + memcpy(dst_data, orig_data, req_sz); + orig_offset += req_sz; + dst_offset += req_sz; + if (orig_offset == local_pkt_next->len) { + orig_offset = 0; + local_pkt_next = local_pkt_next->next; + } + if (dst_offset == pkt_next->len) + break; + } while (!skb_queue_empty(&local_list)); + } + } + +exit: sg_free_table(&st); + while ((pkt_next = __skb_dequeue(&local_list)) != NULL) + brcmu_pkt_buf_free_skb(pkt_next); return ret; } diff --git a/include/linux/platform_data/brcmfmac-sdio.h b/include/linux/platform_data/brcmfmac-sdio.h index 1ade657d5fc1..b7174998c24a 100644 --- a/include/linux/platform_data/brcmfmac-sdio.h +++ b/include/linux/platform_data/brcmfmac-sdio.h @@ -90,6 +90,10 @@ void __init brcmfmac_init_pdata(void) * oob_irq_nr, oob_irq_flags: the OOB interrupt information. The values are * used for registering the irq using request_irq function. * + * broken_sg_support: flag for broken sg list support of SDIO host controller. + * Set this to true if the SDIO host controller has higher align requirement + * than 32 bytes for each scatterlist item. + * * power_on: This function is called by the brcmfmac when the module gets * loaded. This can be particularly useful for low power devices. The platform * spcific routine may for example decide to power up the complete device. @@ -116,6 +120,7 @@ struct brcmfmac_sdio_platform_data { bool oob_irq_supported; unsigned int oob_irq_nr; unsigned long oob_irq_flags; + bool broken_sg_support; void (*power_on)(void); void (*power_off)(void); void (*reset)(void); -- cgit v1.2.3-71-gd317