omap: start working on 3.18 support
[openwrt/svn-archive/archive.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