aboutsummaryrefslogtreecommitdiffstats
path: root/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch')
-rw-r--r--package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch139
1 files changed, 139 insertions, 0 deletions
diff --git a/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch b/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch
new file mode 100644
index 0000000000..856dea8de4
--- /dev/null
+++ b/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch
@@ -0,0 +1,139 @@
+When running with DT, we no longer have a board file that can set up the
+platform data for wlcore. Allow this data to be passed from DT.
+
+Since some platforms use a gpio-irq, add support for passing either the
+irq number or the gpio number. For the latter case, the driver will
+request the gpio and convert it to the irq number. If an irq is
+specified, it'll be used as is.
+
+[Arik - the pdev_data pointer does not belong to us and is freed when
+the device is released. Dereference to our private data first.]
+
+Signed-off-by: Ido Yariv <ido@wizery.com>
+Signed-off-by: Arik Nemtsov <arik@wizery.com>
+---
+ drivers/net/wireless/ti/wlcore/sdio.c | 71 ++++++++++++++++++++++++++++++++---
+ include/linux/wl12xx.h | 3 +-
+ 2 files changed, 67 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/wireless/ti/wlcore/sdio.c
++++ b/drivers/net/wireless/ti/wlcore/sdio.c
+@@ -34,6 +34,7 @@
+ #include <linux/wl12xx.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/printk.h>
++#include <linux/of.h>
+
+ #include "wlcore.h"
+ #include "wl12xx_80211.h"
+@@ -214,6 +215,61 @@ static struct wl1271_if_operations sdio_
+ .set_block_size = wl1271_sdio_set_block_size,
+ };
+
++static const struct of_device_id wlcore_of_match[] = {
++ {
++ .compatible = "wlcore",
++ },
++ {}
++};
++MODULE_DEVICE_TABLE(of, wlcore_of_match);
++
++static struct wl12xx_platform_data *get_platform_data(struct device *dev)
++{
++ struct wl12xx_platform_data *pdata;
++ struct device_node *np;
++ u32 gpio;
++
++ pdata = wl12xx_get_platform_data();
++ if (!IS_ERR(pdata))
++ return kmemdup(pdata, sizeof(*pdata), GFP_KERNEL);
++
++ np = of_find_matching_node(NULL, wlcore_of_match);
++ if (!np) {
++ dev_err(dev, "No platform data set\n");
++ return NULL;
++ }
++
++ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
++ if (!pdata) {
++ dev_err(dev, "Can't allocate platform data\n");
++ return NULL;
++ }
++
++ if (of_property_read_u32(np, "irq", &pdata->irq)) {
++ if (!of_property_read_u32(np, "gpio", &gpio) &&
++ !gpio_request_one(gpio, GPIOF_IN, "wlcore_irq")) {
++ pdata->gpio = gpio;
++ pdata->irq = gpio_to_irq(gpio);
++ }
++ }
++
++ /* Optional fields */
++ pdata->use_eeprom = of_property_read_bool(np, "use-eeprom");
++ of_property_read_u32(np, "board-ref-clock", &pdata->board_ref_clock);
++ of_property_read_u32(np, "board-tcxo-clock", &pdata->board_tcxo_clock);
++ of_property_read_u32(np, "platform-quirks", &pdata->platform_quirks);
++
++ return pdata;
++}
++
++static void del_platform_data(struct wl12xx_platform_data *pdata)
++{
++ if (pdata->gpio)
++ gpio_free(pdata->gpio);
++
++ kfree(pdata);
++}
++
+ static int wl1271_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+ {
+@@ -245,10 +301,10 @@ static int wl1271_probe(struct sdio_func
+ /* Use block mode for transferring over one block size of data */
+ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+
+- pdev_data.pdata = wl12xx_get_platform_data();
+- if (IS_ERR(pdev_data.pdata)) {
+- ret = PTR_ERR(pdev_data.pdata);
+- dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
++ pdev_data.pdata = get_platform_data(&func->dev);
++ if (!pdev_data.pdata) {
++ ret = -EINVAL;
++ dev_err(glue->dev, "missing wlan platform data\n");
+ goto out_free_glue;
+ }
+
+@@ -279,7 +335,7 @@ static int wl1271_probe(struct sdio_func
+ if (!glue->core) {
+ dev_err(glue->dev, "can't allocate platform_device");
+ ret = -ENOMEM;
+- goto out_free_glue;
++ goto out_free_pdata;
+ }
+
+ glue->core->dev.parent = &func->dev;
+@@ -313,6 +369,9 @@ static int wl1271_probe(struct sdio_func
+ out_dev_put:
+ platform_device_put(glue->core);
+
++out_free_pdata:
++ del_platform_data(pdev_data->pdata);
++
+ out_free_glue:
+ kfree(glue);
+
+@@ -323,11 +382,14 @@ out:
+ static void wl1271_remove(struct sdio_func *func)
+ {
+ struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
++ struct wlcore_platdev_data *pdev_data = glue->core->dev.platform_data;
++ struct wl12xx_platform_data *pdata = pdev_data->pdata;
+
+ /* Undo decrement done above in wl1271_probe */
+ pm_runtime_get_noresume(&func->dev);
+
+ platform_device_unregister(glue->core);
++ del_platform_data(pdata);
+ kfree(glue);
+ }
+