diff options
-rw-r--r-- | Documentation/devicetree/bindings/bus/imx-weim.txt | 28 | ||||
-rw-r--r-- | drivers/bus/imx-weim.c | 58 |
2 files changed, 85 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/bus/imx-weim.txt b/Documentation/devicetree/bindings/bus/imx-weim.txt index 0fd76c405208..6630d842c7a3 100644 --- a/Documentation/devicetree/bindings/bus/imx-weim.txt +++ b/Documentation/devicetree/bindings/bus/imx-weim.txt | |||
@@ -8,7 +8,12 @@ The actual devices are instantiated from the child nodes of a WEIM node. | |||
8 | 8 | ||
9 | Required properties: | 9 | Required properties: |
10 | 10 | ||
11 | - compatible: Should be set to "fsl,<soc>-weim" | 11 | - compatible: Should contain one of the following: |
12 | "fsl,imx1-weim" | ||
13 | "fsl,imx27-weim" | ||
14 | "fsl,imx51-weim" | ||
15 | "fsl,imx50-weim" | ||
16 | "fsl,imx6q-weim" | ||
12 | - reg: A resource specifier for the register space | 17 | - reg: A resource specifier for the register space |
13 | (see the example below) | 18 | (see the example below) |
14 | - clocks: the clock, see the example below. | 19 | - clocks: the clock, see the example below. |
@@ -19,6 +24,26 @@ Required properties: | |||
19 | 24 | ||
20 | <cs-number> 0 <physical address of mapping> <size> | 25 | <cs-number> 0 <physical address of mapping> <size> |
21 | 26 | ||
27 | Optional properties: | ||
28 | |||
29 | - fsl,weim-cs-gpr: For "fsl,imx50-weim" and "fsl,imx6q-weim" type of | ||
30 | devices, it should be the phandle to the system General | ||
31 | Purpose Register controller that contains WEIM CS GPR | ||
32 | register, e.g. IOMUXC_GPR1 on i.MX6Q. IOMUXC_GPR1[11:0] | ||
33 | should be set up as one of the following 4 possible | ||
34 | values depending on the CS space configuration. | ||
35 | |||
36 | IOMUXC_GPR1[11:0] CS0 CS1 CS2 CS3 | ||
37 | --------------------------------------------- | ||
38 | 05 128M 0M 0M 0M | ||
39 | 033 64M 64M 0M 0M | ||
40 | 0113 64M 32M 32M 0M | ||
41 | 01111 32M 32M 32M 32M | ||
42 | |||
43 | In case that the property is absent, the reset value or | ||
44 | what bootloader sets up in IOMUXC_GPR1[11:0] will be | ||
45 | used. | ||
46 | |||
22 | Timing property for child nodes. It is mandatory, not optional. | 47 | Timing property for child nodes. It is mandatory, not optional. |
23 | 48 | ||
24 | - fsl,weim-cs-timing: The timing array, contains timing values for the | 49 | - fsl,weim-cs-timing: The timing array, contains timing values for the |
@@ -43,6 +68,7 @@ Example for an imx6q-sabreauto board, the NOR flash connected to the WEIM: | |||
43 | #address-cells = <2>; | 68 | #address-cells = <2>; |
44 | #size-cells = <1>; | 69 | #size-cells = <1>; |
45 | ranges = <0 0 0x08000000 0x08000000>; | 70 | ranges = <0 0 0x08000000 0x08000000>; |
71 | fsl,weim-cs-gpr = <&gpr>; | ||
46 | 72 | ||
47 | nor@0,0 { | 73 | nor@0,0 { |
48 | compatible = "cfi-flash"; | 74 | compatible = "cfi-flash"; |
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c index 3ef58c8dbf11..f8ee13c7bf7b 100644 --- a/drivers/bus/imx-weim.c +++ b/drivers/bus/imx-weim.c | |||
@@ -11,6 +11,9 @@ | |||
11 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
13 | #include <linux/of_device.h> | 13 | #include <linux/of_device.h> |
14 | #include <linux/mfd/syscon.h> | ||
15 | #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> | ||
16 | #include <linux/regmap.h> | ||
14 | 17 | ||
15 | struct imx_weim_devtype { | 18 | struct imx_weim_devtype { |
16 | unsigned int cs_count; | 19 | unsigned int cs_count; |
@@ -56,6 +59,55 @@ static const struct of_device_id weim_id_table[] = { | |||
56 | }; | 59 | }; |
57 | MODULE_DEVICE_TABLE(of, weim_id_table); | 60 | MODULE_DEVICE_TABLE(of, weim_id_table); |
58 | 61 | ||
62 | static int __init imx_weim_gpr_setup(struct platform_device *pdev) | ||
63 | { | ||
64 | struct device_node *np = pdev->dev.of_node; | ||
65 | struct property *prop; | ||
66 | const __be32 *p; | ||
67 | struct regmap *gpr; | ||
68 | u32 gprvals[4] = { | ||
69 | 05, /* CS0(128M) CS1(0M) CS2(0M) CS3(0M) */ | ||
70 | 033, /* CS0(64M) CS1(64M) CS2(0M) CS3(0M) */ | ||
71 | 0113, /* CS0(64M) CS1(32M) CS2(32M) CS3(0M) */ | ||
72 | 01111, /* CS0(32M) CS1(32M) CS2(32M) CS3(32M) */ | ||
73 | }; | ||
74 | u32 gprval = 0; | ||
75 | u32 val; | ||
76 | int cs = 0; | ||
77 | int i = 0; | ||
78 | |||
79 | gpr = syscon_regmap_lookup_by_phandle(np, "fsl,weim-cs-gpr"); | ||
80 | if (IS_ERR(gpr)) { | ||
81 | dev_dbg(&pdev->dev, "failed to find weim-cs-gpr\n"); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | of_property_for_each_u32(np, "ranges", prop, p, val) { | ||
86 | if (i % 4 == 0) { | ||
87 | cs = val; | ||
88 | } else if (i % 4 == 3 && val) { | ||
89 | val = (val / SZ_32M) | 1; | ||
90 | gprval |= val << cs * 3; | ||
91 | } | ||
92 | i++; | ||
93 | } | ||
94 | |||
95 | if (i == 0 || i % 4) | ||
96 | goto err; | ||
97 | |||
98 | for (i = 0; i < ARRAY_SIZE(gprvals); i++) { | ||
99 | if (gprval == gprvals[i]) { | ||
100 | /* Found it. Set up IOMUXC_GPR1[11:0] with it. */ | ||
101 | regmap_update_bits(gpr, IOMUXC_GPR1, 0xfff, gprval); | ||
102 | return 0; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | err: | ||
107 | dev_err(&pdev->dev, "Invalid 'ranges' configuration\n"); | ||
108 | return -EINVAL; | ||
109 | } | ||
110 | |||
59 | /* Parse and set the timing for this device. */ | 111 | /* Parse and set the timing for this device. */ |
60 | static int __init weim_timing_setup(struct device_node *np, void __iomem *base, | 112 | static int __init weim_timing_setup(struct device_node *np, void __iomem *base, |
61 | const struct imx_weim_devtype *devtype) | 113 | const struct imx_weim_devtype *devtype) |
@@ -92,6 +144,12 @@ static int __init weim_parse_dt(struct platform_device *pdev, | |||
92 | struct device_node *child; | 144 | struct device_node *child; |
93 | int ret; | 145 | int ret; |
94 | 146 | ||
147 | if (devtype == &imx50_weim_devtype) { | ||
148 | ret = imx_weim_gpr_setup(pdev); | ||
149 | if (ret) | ||
150 | return ret; | ||
151 | } | ||
152 | |||
95 | for_each_child_of_node(pdev->dev.of_node, child) { | 153 | for_each_child_of_node(pdev->dev.of_node, child) { |
96 | if (!child->name) | 154 | if (!child->name) |
97 | continue; | 155 | continue; |