add device tree based initialization to wl12xx
[openwrt.git] / target / linux / omap / patches-3.12 / 904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch
1 If platform data is not available, try to get the required information
2 from the device tree.  Register an OF match table and parse the
3 appropriate device tree nodes.
4
5 Parse interrupt property only, for now.
6
7 Signed-off-by: Luciano Coelho <coelho@ti.com>
8 Reviewed-by: Felipe Balbi <balbi@ti.com>
9
10 ---
11  drivers/net/wireless/ti/wlcore/sdio.c | 69 ++++++++++++++++++++++++++++++++---
12  1 file changed, 63 insertions(+), 6 deletions(-)
13
14 --- a/drivers/net/wireless/ti/wlcore/sdio.c
15 +++ b/drivers/net/wireless/ti/wlcore/sdio.c
16 @@ -30,7 +30,7 @@
17  #include <linux/mmc/sdio_ids.h>
18  #include <linux/mmc/card.h>
19  #include <linux/mmc/host.h>
20 -#include <linux/gpio.h>
21 +#include <linux/of_irq.h>
22  #include <linux/wl12xx.h>
23  #include <linux/pm_runtime.h>
24  #include <linux/printk.h>
25 @@ -214,6 +214,43 @@ static struct wl1271_if_operations sdio_
26         .set_block_size = wl1271_sdio_set_block_size,
27  };
28  
29 +static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
30 +{
31 +       struct wl12xx_platform_data *pdata;
32 +       struct device_node *np = dev->of_node;
33 +
34 +       if (!np) {
35 +               np = of_find_matching_node(NULL, dev->driver->of_match_table);
36 +               if (!np) {
37 +                       dev_notice(dev, "device tree node not available\n");
38 +                       pdata = ERR_PTR(-ENODEV);
39 +                       goto out;
40 +               }
41 +       }
42 +
43 +       pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
44 +       if (!pdata) {
45 +               dev_err(dev, "can't allocate platform data\n");
46 +               pdata = ERR_PTR(-ENODEV);
47 +               goto out;
48 +       }
49 +
50 +       pdata->irq = irq_of_parse_and_map(np, 0);
51 +       if (pdata->irq < 0) {
52 +               dev_err(dev, "can't get interrupt gpio from the device tree\n");
53 +               goto out_free;
54 +       }
55 +
56 +       goto out;
57 +
58 +out_free:
59 +       kfree(pdata);
60 +       pdata = ERR_PTR(-ENODEV);
61 +
62 +out:
63 +       return pdata;
64 +}
65 +
66  static int wl1271_probe(struct sdio_func *func,
67                                   const struct sdio_device_id *id)
68  {
69 @@ -248,11 +285,22 @@ static int wl1271_probe(struct sdio_func
70         /* Use block mode for transferring over one block size of data */
71         func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
72  
73 +       /* The pdata allocated here is freed when the device is freed,
74 +        * so we don't need an additional out label to free it in case
75 +        * of error further on.
76 +        */
77 +
78 +       /* Try to get legacy platform data from the board file */
79         pdev_data->pdata = wl12xx_get_platform_data();
80         if (IS_ERR(pdev_data->pdata)) {
81 -               ret = PTR_ERR(pdev_data->pdata);
82 -               dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
83 -               goto out_free_glue;
84 +               dev_info(&func->dev,
85 +                        "legacy platform data not found, trying device tree\n");
86 +
87 +               pdev_data->pdata = wlcore_get_pdata_from_of(&func->dev);
88 +               if (IS_ERR(pdev_data->pdata)) {
89 +                       dev_err(&func->dev, "can't get platform data\n");
90 +                       goto out_free_glue;
91 +               }
92         }
93  
94         /* if sdio can keep power while host is suspended, enable wow */
95 @@ -386,16 +434,25 @@ static const struct dev_pm_ops wl1271_sd
96  };
97  #endif
98  
99 +static const struct of_device_id wlcore_sdio_of_match_table[] = {
100 +       { .compatible = "ti,wilink6" },
101 +       { .compatible = "ti,wilink7" },
102 +       { .compatible = "ti,wilink8" },
103 +       { }
104 +};
105 +MODULE_DEVICE_TABLE(of, wlcore_sdio_of_match_table);
106 +
107  static struct sdio_driver wl1271_sdio_driver = {
108         .name           = "wl1271_sdio",
109         .id_table       = wl1271_devices,
110         .probe          = wl1271_probe,
111         .remove         = wl1271_remove,
112 -#ifdef CONFIG_PM
113         .drv = {
114 +#ifdef CONFIG_PM
115                 .pm = &wl1271_sdio_pm_ops,
116 -       },
117  #endif
118 +               .of_match_table = of_match_ptr(wlcore_sdio_of_match_table),
119 +       },
120  };
121  
122  static int __init wl1271_init(void)