Commit 8bd6f53af54b7dbf13625479ae673e73f61ff46a

Authored by Kevin Hilman

Merge tag 'imx-weim-3.12' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/soc

From Shawn Guo:
This is a patch series that updates imx-weim bus driver to have it
support more i.MX SoCs.  Because there is no maintainer for
drivers/bus so far, I'm forwarding it through IMX tree for 3.12 merge
window.

* tag 'imx-weim-3.12' of git://git.linaro.org/people/shawnguo/linux-2.6:
  drivers: bus: imx-weim: Add support for i.MX1/21/25/27/31/35/50/51/53
  drivers: bus: imx-weim: Add missing platform_driver.owner field
  drivers: bus: imx-weim: use module_platform_driver_probe()
  drivers: bus: imx-weim: Simplify error path
  drivers: bus: imx-weim: Remove private driver data

Showing 3 changed files Side-by-side Diff

Documentation/devicetree/bindings/bus/imx-weim.txt
... ... @@ -8,7 +8,7 @@
8 8  
9 9 Required properties:
10 10  
11   - - compatible: Should be set to "fsl,imx6q-weim"
  11 + - compatible: Should be set to "fsl,<soc>-weim"
12 12 - reg: A resource specifier for the register space
13 13 (see the example below)
14 14 - clocks: the clock, see the example below.
15 15  
... ... @@ -21,11 +21,18 @@
21 21  
22 22 Timing property for child nodes. It is mandatory, not optional.
23 23  
24   - - fsl,weim-cs-timing: The timing array, contains 6 timing values for the
  24 + - fsl,weim-cs-timing: The timing array, contains timing values for the
25 25 child node. We can get the CS index from the child
26   - node's "reg" property. This property contains the values
27   - for the registers EIM_CSnGCR1, EIM_CSnGCR2, EIM_CSnRCR1,
28   - EIM_CSnRCR2, EIM_CSnWCR1, EIM_CSnWCR2 in this order.
  26 + node's "reg" property. The number of registers depends
  27 + on the selected chip.
  28 + For i.MX1, i.MX21 ("fsl,imx1-weim") there are two
  29 + registers: CSxU, CSxL.
  30 + For i.MX25, i.MX27, i.MX31 and i.MX35 ("fsl,imx27-weim")
  31 + there are three registers: CSCRxU, CSCRxL, CSCRxA.
  32 + For i.MX50, i.MX53 ("fsl,imx50-weim"),
  33 + i.MX51 ("fsl,imx51-weim") and i.MX6Q ("fsl,imx6q-weim")
  34 + there are six registers: CSxGCR1, CSxGCR2, CSxRCR1,
  35 + CSxRCR2, CSxWCR1, CSxWCR2.
29 36  
30 37 Example for an imx6q-sabreauto board, the NOR flash connected to the WEIM:
31 38  
... ... @@ -8,10 +8,9 @@
8 8 bool "Freescale EIM DRIVER"
9 9 depends on ARCH_MXC
10 10 help
11   - Driver for i.MX6 WEIM controller.
  11 + Driver for i.MX WEIM controller.
12 12 The WEIM(Wireless External Interface Module) works like a bus.
13 13 You can attach many different devices on it, such as NOR, onenand.
14   - But now, we only support the Parallel NOR.
15 14  
16 15 config MVEBU_MBUS
17 16 bool
drivers/bus/imx-weim.c
... ... @@ -12,52 +12,83 @@
12 12 #include <linux/io.h>
13 13 #include <linux/of_device.h>
14 14  
15   -struct imx_weim {
16   - void __iomem *base;
17   - struct clk *clk;
  15 +struct imx_weim_devtype {
  16 + unsigned int cs_count;
  17 + unsigned int cs_regs_count;
  18 + unsigned int cs_stride;
18 19 };
19 20  
  21 +static const struct imx_weim_devtype imx1_weim_devtype = {
  22 + .cs_count = 6,
  23 + .cs_regs_count = 2,
  24 + .cs_stride = 0x08,
  25 +};
  26 +
  27 +static const struct imx_weim_devtype imx27_weim_devtype = {
  28 + .cs_count = 6,
  29 + .cs_regs_count = 3,
  30 + .cs_stride = 0x10,
  31 +};
  32 +
  33 +static const struct imx_weim_devtype imx50_weim_devtype = {
  34 + .cs_count = 4,
  35 + .cs_regs_count = 6,
  36 + .cs_stride = 0x18,
  37 +};
  38 +
  39 +static const struct imx_weim_devtype imx51_weim_devtype = {
  40 + .cs_count = 6,
  41 + .cs_regs_count = 6,
  42 + .cs_stride = 0x18,
  43 +};
  44 +
20 45 static const struct of_device_id weim_id_table[] = {
21   - { .compatible = "fsl,imx6q-weim", },
22   - {}
  46 + /* i.MX1/21 */
  47 + { .compatible = "fsl,imx1-weim", .data = &imx1_weim_devtype, },
  48 + /* i.MX25/27/31/35 */
  49 + { .compatible = "fsl,imx27-weim", .data = &imx27_weim_devtype, },
  50 + /* i.MX50/53/6Q */
  51 + { .compatible = "fsl,imx50-weim", .data = &imx50_weim_devtype, },
  52 + { .compatible = "fsl,imx6q-weim", .data = &imx50_weim_devtype, },
  53 + /* i.MX51 */
  54 + { .compatible = "fsl,imx51-weim", .data = &imx51_weim_devtype, },
  55 + { }
23 56 };
24 57 MODULE_DEVICE_TABLE(of, weim_id_table);
25 58  
26   -#define CS_TIMING_LEN 6
27   -#define CS_REG_RANGE 0x18
28   -
29 59 /* Parse and set the timing for this device. */
30   -static int
31   -weim_timing_setup(struct platform_device *pdev, struct device_node *np)
  60 +static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
  61 + const struct imx_weim_devtype *devtype)
32 62 {
33   - struct imx_weim *weim = platform_get_drvdata(pdev);
34   - u32 value[CS_TIMING_LEN];
35   - u32 cs_idx;
36   - int ret;
37   - int i;
  63 + u32 cs_idx, value[devtype->cs_regs_count];
  64 + int i, ret;
38 65  
39 66 /* get the CS index from this child node's "reg" property. */
40 67 ret = of_property_read_u32(np, "reg", &cs_idx);
41 68 if (ret)
42 69 return ret;
43 70  
44   - /* The weim has four chip selects. */
45   - if (cs_idx > 3)
  71 + if (cs_idx >= devtype->cs_count)
46 72 return -EINVAL;
47 73  
48 74 ret = of_property_read_u32_array(np, "fsl,weim-cs-timing",
49   - value, CS_TIMING_LEN);
  75 + value, devtype->cs_regs_count);
50 76 if (ret)
51 77 return ret;
52 78  
53 79 /* set the timing for WEIM */
54   - for (i = 0; i < CS_TIMING_LEN; i++)
55   - writel(value[i], weim->base + cs_idx * CS_REG_RANGE + i * 4);
  80 + for (i = 0; i < devtype->cs_regs_count; i++)
  81 + writel(value[i], base + cs_idx * devtype->cs_stride + i * 4);
  82 +
56 83 return 0;
57 84 }
58 85  
59   -static int weim_parse_dt(struct platform_device *pdev)
  86 +static int __init weim_parse_dt(struct platform_device *pdev,
  87 + void __iomem *base)
60 88 {
  89 + const struct of_device_id *of_id = of_match_device(weim_id_table,
  90 + &pdev->dev);
  91 + const struct imx_weim_devtype *devtype = of_id->data;
61 92 struct device_node *child;
62 93 int ret;
63 94  
... ... @@ -65,7 +96,7 @@
65 96 if (!child->name)
66 97 continue;
67 98  
68   - ret = weim_timing_setup(pdev, child);
  99 + ret = weim_timing_setup(child, base, devtype);
69 100 if (ret) {
70 101 dev_err(&pdev->dev, "%s set timing failed.\n",
71 102 child->full_name);
72 103  
73 104  
74 105  
75 106  
76 107  
77 108  
78 109  
79 110  
80 111  
81 112  
82 113  
83 114  
84 115  
... ... @@ -80,59 +111,47 @@
80 111 return ret;
81 112 }
82 113  
83   -static int weim_probe(struct platform_device *pdev)
  114 +static int __init weim_probe(struct platform_device *pdev)
84 115 {
85   - struct imx_weim *weim;
86 116 struct resource *res;
87   - int ret = -EINVAL;
  117 + struct clk *clk;
  118 + void __iomem *base;
  119 + int ret;
88 120  
89   - weim = devm_kzalloc(&pdev->dev, sizeof(*weim), GFP_KERNEL);
90   - if (!weim) {
91   - ret = -ENOMEM;
92   - goto weim_err;
93   - }
94   - platform_set_drvdata(pdev, weim);
95   -
96 121 /* get the resource */
97 122 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
98   - weim->base = devm_ioremap_resource(&pdev->dev, res);
99   - if (IS_ERR(weim->base)) {
100   - ret = PTR_ERR(weim->base);
101   - goto weim_err;
102   - }
  123 + base = devm_ioremap_resource(&pdev->dev, res);
  124 + if (IS_ERR(base))
  125 + return PTR_ERR(base);
103 126  
104 127 /* get the clock */
105   - weim->clk = devm_clk_get(&pdev->dev, NULL);
106   - if (IS_ERR(weim->clk))
107   - goto weim_err;
  128 + clk = devm_clk_get(&pdev->dev, NULL);
  129 + if (IS_ERR(clk))
  130 + return PTR_ERR(clk);
108 131  
109   - ret = clk_prepare_enable(weim->clk);
  132 + ret = clk_prepare_enable(clk);
110 133 if (ret)
111   - goto weim_err;
  134 + return ret;
112 135  
113 136 /* parse the device node */
114   - ret = weim_parse_dt(pdev);
115   - if (ret) {
116   - clk_disable_unprepare(weim->clk);
117   - goto weim_err;
118   - }
  137 + ret = weim_parse_dt(pdev, base);
  138 + if (ret)
  139 + clk_disable_unprepare(clk);
  140 + else
  141 + dev_info(&pdev->dev, "Driver registered.\n");
119 142  
120   - dev_info(&pdev->dev, "WEIM driver registered.\n");
121   - return 0;
122   -
123   -weim_err:
124 143 return ret;
125 144 }
126 145  
127 146 static struct platform_driver weim_driver = {
128 147 .driver = {
129   - .name = "imx-weim",
130   - .of_match_table = weim_id_table,
  148 + .name = "imx-weim",
  149 + .owner = THIS_MODULE,
  150 + .of_match_table = weim_id_table,
131 151 },
132   - .probe = weim_probe,
133 152 };
  153 +module_platform_driver_probe(weim_driver, weim_probe);
134 154  
135   -module_platform_driver(weim_driver);
136 155 MODULE_AUTHOR("Freescale Semiconductor Inc.");
137 156 MODULE_DESCRIPTION("i.MX EIM Controller Driver");
138 157 MODULE_LICENSE("GPL");