aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bus
diff options
context:
space:
mode:
authorAlexander Shiyan <shc_work@mail.ru>2013-06-29 00:27:54 -0400
committerShawn Guo <shawn.guo@linaro.org>2013-08-16 00:59:44 -0400
commit3f98b6baad63b181da4e859d81953e88ce8a50ec (patch)
tree6e6c227c95f3955044558dbe9d65da3beb1edb80 /drivers/bus
parentfc608c745cf71a7abb673d891104597120042f21 (diff)
drivers: bus: imx-weim: Add support for i.MX1/21/25/27/31/35/50/51/53
This patch adds WEIM support for all i.MX CPUs supported by the kernel. Signed-off-by: Alexander Shiyan <shc_work@mail.ru> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Diffstat (limited to 'drivers/bus')
-rw-r--r--drivers/bus/Kconfig3
-rw-r--r--drivers/bus/imx-weim.c69
2 files changed, 54 insertions, 18 deletions
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 dc860a411343..3ef58c8dbf11 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -12,46 +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_devtype {
16 unsigned int cs_count;
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,
43};
44
15static const struct of_device_id weim_id_table[] = { 45static const struct of_device_id weim_id_table[] = {
16 { .compatible = "fsl,imx6q-weim", }, 46 /* i.MX1/21 */
17 {} 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 { }
18}; 56};
19MODULE_DEVICE_TABLE(of, weim_id_table); 57MODULE_DEVICE_TABLE(of, weim_id_table);
20 58
21#define CS_TIMING_LEN 6
22#define CS_REG_RANGE 0x18
23
24/* Parse and set the timing for this device. */ 59/* Parse and set the timing for this device. */
25static int __init weim_timing_setup(struct device_node *np, void __iomem *base) 60static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
61 const struct imx_weim_devtype *devtype)
26{ 62{
27 u32 value[CS_TIMING_LEN]; 63 u32 cs_idx, value[devtype->cs_regs_count];
28 u32 cs_idx; 64 int i, ret;
29 int ret;
30 int i;
31 65
32 /* get the CS index from this child node's "reg" property. */ 66 /* get the CS index from this child node's "reg" property. */
33 ret = of_property_read_u32(np, "reg", &cs_idx); 67 ret = of_property_read_u32(np, "reg", &cs_idx);
34 if (ret) 68 if (ret)
35 return ret; 69 return ret;
36 70
37 /* The weim has four chip selects. */ 71 if (cs_idx >= devtype->cs_count)
38 if (cs_idx > 3)
39 return -EINVAL; 72 return -EINVAL;
40 73
41 ret = of_property_read_u32_array(np, "fsl,weim-cs-timing", 74 ret = of_property_read_u32_array(np, "fsl,weim-cs-timing",
42 value, CS_TIMING_LEN); 75 value, devtype->cs_regs_count);
43 if (ret) 76 if (ret)
44 return ret; 77 return ret;
45 78
46 /* set the timing for WEIM */ 79 /* set the timing for WEIM */
47 for (i = 0; i < CS_TIMING_LEN; i++) 80 for (i = 0; i < devtype->cs_regs_count; i++)
48 writel(value[i], base + cs_idx * CS_REG_RANGE + i * 4); 81 writel(value[i], base + cs_idx * devtype->cs_stride + i * 4);
82
49 return 0; 83 return 0;
50} 84}
51 85
52static int __init weim_parse_dt(struct platform_device *pdev, 86static int __init weim_parse_dt(struct platform_device *pdev,
53 void __iomem *base) 87 void __iomem *base)
54{ 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;
55 struct device_node *child; 92 struct device_node *child;
56 int ret; 93 int ret;
57 94
@@ -59,7 +96,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
59 if (!child->name) 96 if (!child->name)
60 continue; 97 continue;
61 98
62 ret = weim_timing_setup(child, base); 99 ret = weim_timing_setup(child, base, devtype);
63 if (ret) { 100 if (ret) {
64 dev_err(&pdev->dev, "%s set timing failed.\n", 101 dev_err(&pdev->dev, "%s set timing failed.\n",
65 child->full_name); 102 child->full_name);