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