omap: start working on 3.18 support
[openwrt.git] / target / linux / omap / patches-3.18 / 900-wlcore-Add-support-for-DT-platform-data.patch
1 When running with DT, we no longer have a board file that can set up the
2 platform data for wlcore. Allow this data to be passed from DT.
3
4 Since some platforms use a gpio-irq, add support for passing either the
5 irq number or the gpio number. For the latter case, the driver will
6 request the gpio and convert it to the irq number. If an irq is
7 specified, it'll be used as is.
8
9 [Arik - the pdev_data pointer does not belong to us and is freed when
10 the device is released. Dereference to our private data first.]
11
12 Signed-off-by: Ido Yariv <ido@wizery.com>
13 Signed-off-by: Arik Nemtsov <arik@wizery.com>
14 ---
15  drivers/net/wireless/ti/wlcore/sdio.c | 71 ++++++++++++++++++++++++++++++++---
16  include/linux/wl12xx.h                |  3 +-
17  2 files changed, 67 insertions(+), 7 deletions(-)
18
19 --- a/drivers/net/wireless/ti/wlcore/sdio.c
20 +++ b/drivers/net/wireless/ti/wlcore/sdio.c
21 @@ -34,6 +34,7 @@
22  #include <linux/wl12xx.h>
23  #include <linux/pm_runtime.h>
24  #include <linux/printk.h>
25 +#include <linux/of.h>
26  
27  #include "wlcore.h"
28  #include "wl12xx_80211.h"
29 @@ -214,6 +215,61 @@ static struct wl1271_if_operations sdio_
30         .set_block_size = wl1271_sdio_set_block_size,
31  };
32  
33 +static const struct of_device_id wlcore_of_match[] = {
34 +       {
35 +               .compatible = "wlcore",
36 +       },
37 +       {}
38 +};
39 +MODULE_DEVICE_TABLE(of, wlcore_of_match);
40 +
41 +static struct wl12xx_platform_data *get_platform_data(struct device *dev)
42 +{
43 +       struct wl12xx_platform_data *pdata;
44 +       struct device_node *np;
45 +       u32 gpio;
46 +
47 +       pdata = wl12xx_get_platform_data();
48 +       if (!IS_ERR(pdata))
49 +               return kmemdup(pdata, sizeof(*pdata), GFP_KERNEL);
50 +
51 +       np = of_find_matching_node(NULL, wlcore_of_match);
52 +       if (!np) {
53 +               dev_err(dev, "No platform data set\n");
54 +               return NULL;
55 +       }
56 +
57 +       pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
58 +       if (!pdata) {
59 +               dev_err(dev, "Can't allocate platform data\n");
60 +               return NULL;
61 +       }
62 +
63 +       if (of_property_read_u32(np, "irq", &pdata->irq)) {
64 +               if (!of_property_read_u32(np, "gpio", &gpio) &&
65 +                   !gpio_request_one(gpio, GPIOF_IN, "wlcore_irq")) {
66 +                       pdata->gpio = gpio;
67 +                       pdata->irq = gpio_to_irq(gpio);
68 +               }
69 +       }
70 +
71 +       /* Optional fields */
72 +       pdata->use_eeprom = of_property_read_bool(np, "use-eeprom");
73 +       of_property_read_u32(np, "board-ref-clock", &pdata->board_ref_clock);
74 +       of_property_read_u32(np, "board-tcxo-clock", &pdata->board_tcxo_clock);
75 +       of_property_read_u32(np, "platform-quirks", &pdata->platform_quirks);
76 +
77 +       return pdata;
78 +}
79 +
80 +static void del_platform_data(struct wl12xx_platform_data *pdata)
81 +{
82 +       if (pdata->gpio)
83 +               gpio_free(pdata->gpio);
84 +
85 +       kfree(pdata);
86 +}
87 +
88  static int wl1271_probe(struct sdio_func *func,
89                                   const struct sdio_device_id *id)
90  {
91 @@ -248,12 +304,9 @@ static int wl1271_probe(struct sdio_func
92         /* Use block mode for transferring over one block size of data */
93         func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
94  
95 -       pdev_data->pdata = wl12xx_get_platform_data();
96 -       if (IS_ERR(pdev_data->pdata)) {
97 -               ret = PTR_ERR(pdev_data->pdata);
98 -               dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
99 +       pdev_data->pdata = get_platform_data(&func->dev);
100 +       if (!(pdev_data->pdata))
101                 goto out_free_glue;
102 -       }
103  
104         /* if sdio can keep power while host is suspended, enable wow */
105         mmcflags = sdio_get_host_pm_caps(func);
106 @@ -282,7 +335,7 @@ static int wl1271_probe(struct sdio_func
107         if (!glue->core) {
108                 dev_err(glue->dev, "can't allocate platform_device");
109                 ret = -ENOMEM;
110 -               goto out_free_glue;
111 +               goto out_free_pdata;
112         }
113  
114         glue->core->dev.parent = &func->dev;
115 @@ -316,6 +369,9 @@ static int wl1271_probe(struct sdio_func
116  out_dev_put:
117         platform_device_put(glue->core);
118  
119 +out_free_pdata:
120 +       del_platform_data(pdev_data->pdata);
121 +
122  out_free_glue:
123         kfree(glue);
124  
125 @@ -329,11 +385,14 @@ out:
126  static void wl1271_remove(struct sdio_func *func)
127  {
128         struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
129 +       struct wlcore_platdev_data *pdev_data = glue->core->dev.platform_data;
130 +       struct wl12xx_platform_data *pdata = pdev_data->pdata;
131  
132         /* Undo decrement done above in wl1271_probe */
133         pm_runtime_get_noresume(&func->dev);
134  
135         platform_device_unregister(glue->core);
136 +       del_platform_data(pdata);
137         kfree(glue);
138  }
139  
140 --- a/include/linux/wl12xx.h
141 +++ b/include/linux/wl12xx.h
142 @@ -51,11 +51,12 @@ enum {
143  struct wl12xx_platform_data {
144         void (*set_power)(bool enable);
145         /* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */
146 +       int gpio;
147         int irq;
148         bool use_eeprom;
149         int board_ref_clock;
150         int board_tcxo_clock;
151 -       unsigned long platform_quirks;
152 +       u32 platform_quirks;
153         bool pwr_in_suspend;
154  };
155