diff options
-rw-r--r-- | Documentation/devicetree/bindings/clock/sunxi.txt | 43 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/mmc/sunxi-mmc.txt | 8 | ||||
-rw-r--r-- | arch/arm/boot/dts/sun4i-a10.dtsi | 72 | ||||
-rw-r--r-- | arch/arm/boot/dts/sun5i-a10s.dtsi | 54 | ||||
-rw-r--r-- | arch/arm/boot/dts/sun5i-a13.dtsi | 44 | ||||
-rw-r--r-- | arch/arm/boot/dts/sun6i-a31.dtsi | 86 | ||||
-rw-r--r-- | arch/arm/boot/dts/sun7i-a20.dtsi | 72 | ||||
-rw-r--r-- | arch/arm/boot/dts/sun8i-a23.dtsi | 96 | ||||
-rw-r--r-- | drivers/clk/sunxi/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-factors.c | 10 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-factors.h | 7 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-mod0.c | 224 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-sun8i-mbus.c | 13 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-sun9i-core.c | 119 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-sun9i-mmc.c | 219 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-sunxi.c | 260 | ||||
-rw-r--r-- | drivers/mmc/host/sunxi-mmc.c | 73 | ||||
-rw-r--r-- | include/linux/clk/sunxi.h | 22 |
18 files changed, 1092 insertions, 331 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 67b2b99f2b33..60b44285250d 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt | |||
@@ -26,7 +26,7 @@ Required properties: | |||
26 | "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s | 26 | "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s |
27 | "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 | 27 | "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 |
28 | "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31 | 28 | "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31 |
29 | "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 | 29 | "allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31 |
30 | "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 | 30 | "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 |
31 | "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23 | 31 | "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23 |
32 | "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80 | 32 | "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80 |
@@ -55,9 +55,11 @@ Required properties: | |||
55 | "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 | 55 | "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 |
56 | "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23 | 56 | "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23 |
57 | "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13 | 57 | "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13 |
58 | "allwinner,sun4i-a10-mmc-output-clk" - for the MMC output clock on A10 | 58 | "allwinner,sun4i-a10-mmc-clk" - for the MMC clock |
59 | "allwinner,sun4i-a10-mmc-sample-clk" - for the MMC sample clock on A10 | 59 | "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80 |
60 | "allwinner,sun9i-a80-mmc-config-clk" - for mmc gates + resets on A80 | ||
60 | "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks | 61 | "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks |
62 | "allwinner,sun9i-a80-mod0-clk" - for module 0 (storage) clocks on A80 | ||
61 | "allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23 | 63 | "allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23 |
62 | "allwinner,sun7i-a20-out-clk" - for the external output clocks | 64 | "allwinner,sun7i-a20-out-clk" - for the external output clocks |
63 | "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 | 65 | "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 |
@@ -73,7 +75,9 @@ Required properties for all clocks: | |||
73 | - #clock-cells : from common clock binding; shall be set to 0 except for | 75 | - #clock-cells : from common clock binding; shall be set to 0 except for |
74 | the following compatibles where it shall be set to 1: | 76 | the following compatibles where it shall be set to 1: |
75 | "allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk", | 77 | "allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk", |
76 | "allwinner,sun4i-pll6-clk", "allwinner,sun6i-a31-pll6-clk" | 78 | "allwinner,sun4i-pll6-clk", "allwinner,sun6i-a31-pll6-clk", |
79 | "allwinner,*-usb-clk", "allwinner,*-mmc-clk", | ||
80 | "allwinner,*-mmc-config-clk" | ||
77 | - clock-output-names : shall be the corresponding names of the outputs. | 81 | - clock-output-names : shall be the corresponding names of the outputs. |
78 | If the clock module only has one output, the name shall be the | 82 | If the clock module only has one output, the name shall be the |
79 | module name. | 83 | module name. |
@@ -81,6 +85,10 @@ Required properties for all clocks: | |||
81 | And "allwinner,*-usb-clk" clocks also require: | 85 | And "allwinner,*-usb-clk" clocks also require: |
82 | - reset-cells : shall be set to 1 | 86 | - reset-cells : shall be set to 1 |
83 | 87 | ||
88 | The "allwinner,sun9i-a80-mmc-config-clk" clock also requires: | ||
89 | - #reset-cells : shall be set to 1 | ||
90 | - resets : shall be the reset control phandle for the mmc block. | ||
91 | |||
84 | For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate | 92 | For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate |
85 | dummy clocks at 25 MHz and 125 MHz, respectively. See example. | 93 | dummy clocks at 25 MHz and 125 MHz, respectively. See example. |
86 | 94 | ||
@@ -95,6 +103,14 @@ For "allwinner,sun6i-a31-pll6-clk", there are 2 outputs. The first output | |||
95 | is the normal PLL6 output, or "pll6". The second output is rate doubled | 103 | is the normal PLL6 output, or "pll6". The second output is rate doubled |
96 | PLL6, or "pll6x2". | 104 | PLL6, or "pll6x2". |
97 | 105 | ||
106 | The "allwinner,*-mmc-clk" clocks have three different outputs: the | ||
107 | main clock, with the ID 0, and the output and sample clocks, with the | ||
108 | IDs 1 and 2, respectively. | ||
109 | |||
110 | The "allwinner,sun9i-a80-mmc-config-clk" clock has one clock/reset output | ||
111 | per mmc controller. The number of outputs is determined by the size of | ||
112 | the address block, which is related to the overall mmc block. | ||
113 | |||
98 | For example: | 114 | For example: |
99 | 115 | ||
100 | osc24M: clk@01c20050 { | 116 | osc24M: clk@01c20050 { |
@@ -138,11 +154,11 @@ cpu: cpu@01c20054 { | |||
138 | }; | 154 | }; |
139 | 155 | ||
140 | mmc0_clk: clk@01c20088 { | 156 | mmc0_clk: clk@01c20088 { |
141 | #clock-cells = <0>; | 157 | #clock-cells = <1>; |
142 | compatible = "allwinner,sun4i-mod0-clk"; | 158 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
143 | reg = <0x01c20088 0x4>; | 159 | reg = <0x01c20088 0x4>; |
144 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 160 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
145 | clock-output-names = "mmc0"; | 161 | clock-output-names = "mmc0", "mmc0_output", "mmc0_sample"; |
146 | }; | 162 | }; |
147 | 163 | ||
148 | mii_phy_tx_clk: clk@2 { | 164 | mii_phy_tx_clk: clk@2 { |
@@ -170,3 +186,16 @@ gmac_clk: clk@01c20164 { | |||
170 | clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>; | 186 | clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>; |
171 | clock-output-names = "gmac"; | 187 | clock-output-names = "gmac"; |
172 | }; | 188 | }; |
189 | |||
190 | mmc_config_clk: clk@01c13000 { | ||
191 | compatible = "allwinner,sun9i-a80-mmc-config-clk"; | ||
192 | reg = <0x01c13000 0x10>; | ||
193 | clocks = <&ahb0_gates 8>; | ||
194 | clock-names = "ahb"; | ||
195 | resets = <&ahb0_resets 8>; | ||
196 | reset-names = "ahb"; | ||
197 | #clock-cells = <1>; | ||
198 | #reset-cells = <1>; | ||
199 | clock-output-names = "mmc0_config", "mmc1_config", | ||
200 | "mmc2_config", "mmc3_config"; | ||
201 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt index 91b3a3467150..4bf41d833804 100644 --- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt +++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt | |||
@@ -10,8 +10,8 @@ Absolute maximum transfer rate is 200MB/s | |||
10 | Required properties: | 10 | Required properties: |
11 | - compatible : "allwinner,sun4i-a10-mmc" or "allwinner,sun5i-a13-mmc" | 11 | - compatible : "allwinner,sun4i-a10-mmc" or "allwinner,sun5i-a13-mmc" |
12 | - reg : mmc controller base registers | 12 | - reg : mmc controller base registers |
13 | - clocks : a list with 2 phandle + clock specifier pairs | 13 | - clocks : a list with 4 phandle + clock specifier pairs |
14 | - clock-names : must contain "ahb" and "mmc" | 14 | - clock-names : must contain "ahb", "mmc", "output" and "sample" |
15 | - interrupts : mmc controller interrupt | 15 | - interrupts : mmc controller interrupt |
16 | 16 | ||
17 | Optional properties: | 17 | Optional properties: |
@@ -25,8 +25,8 @@ Examples: | |||
25 | mmc0: mmc@01c0f000 { | 25 | mmc0: mmc@01c0f000 { |
26 | compatible = "allwinner,sun5i-a13-mmc"; | 26 | compatible = "allwinner,sun5i-a13-mmc"; |
27 | reg = <0x01c0f000 0x1000>; | 27 | reg = <0x01c0f000 0x1000>; |
28 | clocks = <&ahb_gates 8>, <&mmc0_clk>; | 28 | clocks = <&ahb_gates 8>, <&mmc0_clk>, <&mmc0_output_clk>, <&mmc0_sample_clk>; |
29 | clock-names = "ahb", "mod"; | 29 | clock-names = "ahb", "mod", "output", "sample"; |
30 | interrupts = <0 32 4>; | 30 | interrupts = <0 32 4>; |
31 | status = "disabled"; | 31 | status = "disabled"; |
32 | }; | 32 | }; |
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 7b4099fcf817..bb6b6ae95d82 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi | |||
@@ -226,35 +226,43 @@ | |||
226 | }; | 226 | }; |
227 | 227 | ||
228 | mmc0_clk: clk@01c20088 { | 228 | mmc0_clk: clk@01c20088 { |
229 | #clock-cells = <0>; | 229 | #clock-cells = <1>; |
230 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 230 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
231 | reg = <0x01c20088 0x4>; | 231 | reg = <0x01c20088 0x4>; |
232 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 232 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
233 | clock-output-names = "mmc0"; | 233 | clock-output-names = "mmc0", |
234 | "mmc0_output", | ||
235 | "mmc0_sample"; | ||
234 | }; | 236 | }; |
235 | 237 | ||
236 | mmc1_clk: clk@01c2008c { | 238 | mmc1_clk: clk@01c2008c { |
237 | #clock-cells = <0>; | 239 | #clock-cells = <1>; |
238 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 240 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
239 | reg = <0x01c2008c 0x4>; | 241 | reg = <0x01c2008c 0x4>; |
240 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 242 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
241 | clock-output-names = "mmc1"; | 243 | clock-output-names = "mmc1", |
244 | "mmc1_output", | ||
245 | "mmc1_sample"; | ||
242 | }; | 246 | }; |
243 | 247 | ||
244 | mmc2_clk: clk@01c20090 { | 248 | mmc2_clk: clk@01c20090 { |
245 | #clock-cells = <0>; | 249 | #clock-cells = <1>; |
246 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 250 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
247 | reg = <0x01c20090 0x4>; | 251 | reg = <0x01c20090 0x4>; |
248 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 252 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
249 | clock-output-names = "mmc2"; | 253 | clock-output-names = "mmc2", |
254 | "mmc2_output", | ||
255 | "mmc2_sample"; | ||
250 | }; | 256 | }; |
251 | 257 | ||
252 | mmc3_clk: clk@01c20094 { | 258 | mmc3_clk: clk@01c20094 { |
253 | #clock-cells = <0>; | 259 | #clock-cells = <1>; |
254 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 260 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
255 | reg = <0x01c20094 0x4>; | 261 | reg = <0x01c20094 0x4>; |
256 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 262 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
257 | clock-output-names = "mmc3"; | 263 | clock-output-names = "mmc3", |
264 | "mmc3_output", | ||
265 | "mmc3_sample"; | ||
258 | }; | 266 | }; |
259 | 267 | ||
260 | ts_clk: clk@01c20098 { | 268 | ts_clk: clk@01c20098 { |
@@ -398,8 +406,14 @@ | |||
398 | mmc0: mmc@01c0f000 { | 406 | mmc0: mmc@01c0f000 { |
399 | compatible = "allwinner,sun4i-a10-mmc"; | 407 | compatible = "allwinner,sun4i-a10-mmc"; |
400 | reg = <0x01c0f000 0x1000>; | 408 | reg = <0x01c0f000 0x1000>; |
401 | clocks = <&ahb_gates 8>, <&mmc0_clk>; | 409 | clocks = <&ahb_gates 8>, |
402 | clock-names = "ahb", "mmc"; | 410 | <&mmc0_clk 0>, |
411 | <&mmc0_clk 1>, | ||
412 | <&mmc0_clk 2>; | ||
413 | clock-names = "ahb", | ||
414 | "mmc", | ||
415 | "output", | ||
416 | "sample"; | ||
403 | interrupts = <32>; | 417 | interrupts = <32>; |
404 | status = "disabled"; | 418 | status = "disabled"; |
405 | }; | 419 | }; |
@@ -407,8 +421,14 @@ | |||
407 | mmc1: mmc@01c10000 { | 421 | mmc1: mmc@01c10000 { |
408 | compatible = "allwinner,sun4i-a10-mmc"; | 422 | compatible = "allwinner,sun4i-a10-mmc"; |
409 | reg = <0x01c10000 0x1000>; | 423 | reg = <0x01c10000 0x1000>; |
410 | clocks = <&ahb_gates 9>, <&mmc1_clk>; | 424 | clocks = <&ahb_gates 9>, |
411 | clock-names = "ahb", "mmc"; | 425 | <&mmc1_clk 0>, |
426 | <&mmc1_clk 1>, | ||
427 | <&mmc1_clk 2>; | ||
428 | clock-names = "ahb", | ||
429 | "mmc", | ||
430 | "output", | ||
431 | "sample"; | ||
412 | interrupts = <33>; | 432 | interrupts = <33>; |
413 | status = "disabled"; | 433 | status = "disabled"; |
414 | }; | 434 | }; |
@@ -416,8 +436,14 @@ | |||
416 | mmc2: mmc@01c11000 { | 436 | mmc2: mmc@01c11000 { |
417 | compatible = "allwinner,sun4i-a10-mmc"; | 437 | compatible = "allwinner,sun4i-a10-mmc"; |
418 | reg = <0x01c11000 0x1000>; | 438 | reg = <0x01c11000 0x1000>; |
419 | clocks = <&ahb_gates 10>, <&mmc2_clk>; | 439 | clocks = <&ahb_gates 10>, |
420 | clock-names = "ahb", "mmc"; | 440 | <&mmc2_clk 0>, |
441 | <&mmc2_clk 1>, | ||
442 | <&mmc2_clk 2>; | ||
443 | clock-names = "ahb", | ||
444 | "mmc", | ||
445 | "output", | ||
446 | "sample"; | ||
421 | interrupts = <34>; | 447 | interrupts = <34>; |
422 | status = "disabled"; | 448 | status = "disabled"; |
423 | }; | 449 | }; |
@@ -425,8 +451,14 @@ | |||
425 | mmc3: mmc@01c12000 { | 451 | mmc3: mmc@01c12000 { |
426 | compatible = "allwinner,sun4i-a10-mmc"; | 452 | compatible = "allwinner,sun4i-a10-mmc"; |
427 | reg = <0x01c12000 0x1000>; | 453 | reg = <0x01c12000 0x1000>; |
428 | clocks = <&ahb_gates 11>, <&mmc3_clk>; | 454 | clocks = <&ahb_gates 11>, |
429 | clock-names = "ahb", "mmc"; | 455 | <&mmc3_clk 0>, |
456 | <&mmc3_clk 1>, | ||
457 | <&mmc3_clk 2>; | ||
458 | clock-names = "ahb", | ||
459 | "mmc", | ||
460 | "output", | ||
461 | "sample"; | ||
430 | interrupts = <35>; | 462 | interrupts = <35>; |
431 | status = "disabled"; | 463 | status = "disabled"; |
432 | }; | 464 | }; |
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index 1b76667f3182..0e011427615f 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi | |||
@@ -211,27 +211,33 @@ | |||
211 | }; | 211 | }; |
212 | 212 | ||
213 | mmc0_clk: clk@01c20088 { | 213 | mmc0_clk: clk@01c20088 { |
214 | #clock-cells = <0>; | 214 | #clock-cells = <1>; |
215 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 215 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
216 | reg = <0x01c20088 0x4>; | 216 | reg = <0x01c20088 0x4>; |
217 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 217 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
218 | clock-output-names = "mmc0"; | 218 | clock-output-names = "mmc0", |
219 | "mmc0_output", | ||
220 | "mmc0_sample"; | ||
219 | }; | 221 | }; |
220 | 222 | ||
221 | mmc1_clk: clk@01c2008c { | 223 | mmc1_clk: clk@01c2008c { |
222 | #clock-cells = <0>; | 224 | #clock-cells = <1>; |
223 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 225 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
224 | reg = <0x01c2008c 0x4>; | 226 | reg = <0x01c2008c 0x4>; |
225 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 227 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
226 | clock-output-names = "mmc1"; | 228 | clock-output-names = "mmc1", |
229 | "mmc1_output", | ||
230 | "mmc1_sample"; | ||
227 | }; | 231 | }; |
228 | 232 | ||
229 | mmc2_clk: clk@01c20090 { | 233 | mmc2_clk: clk@01c20090 { |
230 | #clock-cells = <0>; | 234 | #clock-cells = <1>; |
231 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 235 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
232 | reg = <0x01c20090 0x4>; | 236 | reg = <0x01c20090 0x4>; |
233 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 237 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
234 | clock-output-names = "mmc2"; | 238 | clock-output-names = "mmc2", |
239 | "mmc2_output", | ||
240 | "mmc2_sample"; | ||
235 | }; | 241 | }; |
236 | 242 | ||
237 | ts_clk: clk@01c20098 { | 243 | ts_clk: clk@01c20098 { |
@@ -359,8 +365,14 @@ | |||
359 | mmc0: mmc@01c0f000 { | 365 | mmc0: mmc@01c0f000 { |
360 | compatible = "allwinner,sun5i-a13-mmc"; | 366 | compatible = "allwinner,sun5i-a13-mmc"; |
361 | reg = <0x01c0f000 0x1000>; | 367 | reg = <0x01c0f000 0x1000>; |
362 | clocks = <&ahb_gates 8>, <&mmc0_clk>; | 368 | clocks = <&ahb_gates 8>, |
363 | clock-names = "ahb", "mmc"; | 369 | <&mmc0_clk 0>, |
370 | <&mmc0_clk 1>, | ||
371 | <&mmc0_clk 2>; | ||
372 | clock-names = "ahb", | ||
373 | "mmc", | ||
374 | "output", | ||
375 | "sample"; | ||
364 | interrupts = <32>; | 376 | interrupts = <32>; |
365 | status = "disabled"; | 377 | status = "disabled"; |
366 | }; | 378 | }; |
@@ -368,8 +380,14 @@ | |||
368 | mmc1: mmc@01c10000 { | 380 | mmc1: mmc@01c10000 { |
369 | compatible = "allwinner,sun5i-a13-mmc"; | 381 | compatible = "allwinner,sun5i-a13-mmc"; |
370 | reg = <0x01c10000 0x1000>; | 382 | reg = <0x01c10000 0x1000>; |
371 | clocks = <&ahb_gates 9>, <&mmc1_clk>; | 383 | clocks = <&ahb_gates 9>, |
372 | clock-names = "ahb", "mmc"; | 384 | <&mmc1_clk 0>, |
385 | <&mmc1_clk 1>, | ||
386 | <&mmc1_clk 2>; | ||
387 | clock-names = "ahb", | ||
388 | "mmc", | ||
389 | "output", | ||
390 | "sample"; | ||
373 | interrupts = <33>; | 391 | interrupts = <33>; |
374 | status = "disabled"; | 392 | status = "disabled"; |
375 | }; | 393 | }; |
@@ -377,8 +395,14 @@ | |||
377 | mmc2: mmc@01c11000 { | 395 | mmc2: mmc@01c11000 { |
378 | compatible = "allwinner,sun5i-a13-mmc"; | 396 | compatible = "allwinner,sun5i-a13-mmc"; |
379 | reg = <0x01c11000 0x1000>; | 397 | reg = <0x01c11000 0x1000>; |
380 | clocks = <&ahb_gates 10>, <&mmc2_clk>; | 398 | clocks = <&ahb_gates 10>, |
381 | clock-names = "ahb", "mmc"; | 399 | <&mmc2_clk 0>, |
400 | <&mmc2_clk 1>, | ||
401 | <&mmc2_clk 2>; | ||
402 | clock-names = "ahb", | ||
403 | "mmc", | ||
404 | "output", | ||
405 | "sample"; | ||
382 | interrupts = <34>; | 406 | interrupts = <34>; |
383 | status = "disabled"; | 407 | status = "disabled"; |
384 | }; | 408 | }; |
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index c35217ea1f64..cbb63b750e08 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi | |||
@@ -195,27 +195,33 @@ | |||
195 | }; | 195 | }; |
196 | 196 | ||
197 | mmc0_clk: clk@01c20088 { | 197 | mmc0_clk: clk@01c20088 { |
198 | #clock-cells = <0>; | 198 | #clock-cells = <1>; |
199 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 199 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
200 | reg = <0x01c20088 0x4>; | 200 | reg = <0x01c20088 0x4>; |
201 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 201 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
202 | clock-output-names = "mmc0"; | 202 | clock-output-names = "mmc0", |
203 | "mmc0_output", | ||
204 | "mmc0_sample"; | ||
203 | }; | 205 | }; |
204 | 206 | ||
205 | mmc1_clk: clk@01c2008c { | 207 | mmc1_clk: clk@01c2008c { |
206 | #clock-cells = <0>; | 208 | #clock-cells = <1>; |
207 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 209 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
208 | reg = <0x01c2008c 0x4>; | 210 | reg = <0x01c2008c 0x4>; |
209 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 211 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
210 | clock-output-names = "mmc1"; | 212 | clock-output-names = "mmc1", |
213 | "mmc1_output", | ||
214 | "mmc1_sample"; | ||
211 | }; | 215 | }; |
212 | 216 | ||
213 | mmc2_clk: clk@01c20090 { | 217 | mmc2_clk: clk@01c20090 { |
214 | #clock-cells = <0>; | 218 | #clock-cells = <1>; |
215 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 219 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
216 | reg = <0x01c20090 0x4>; | 220 | reg = <0x01c20090 0x4>; |
217 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 221 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
218 | clock-output-names = "mmc2"; | 222 | clock-output-names = "mmc2", |
223 | "mmc2_output", | ||
224 | "mmc2_sample"; | ||
219 | }; | 225 | }; |
220 | 226 | ||
221 | ts_clk: clk@01c20098 { | 227 | ts_clk: clk@01c20098 { |
@@ -327,8 +333,14 @@ | |||
327 | mmc0: mmc@01c0f000 { | 333 | mmc0: mmc@01c0f000 { |
328 | compatible = "allwinner,sun5i-a13-mmc"; | 334 | compatible = "allwinner,sun5i-a13-mmc"; |
329 | reg = <0x01c0f000 0x1000>; | 335 | reg = <0x01c0f000 0x1000>; |
330 | clocks = <&ahb_gates 8>, <&mmc0_clk>; | 336 | clocks = <&ahb_gates 8>, |
331 | clock-names = "ahb", "mmc"; | 337 | <&mmc0_clk 0>, |
338 | <&mmc0_clk 1>, | ||
339 | <&mmc0_clk 2>; | ||
340 | clock-names = "ahb", | ||
341 | "mmc", | ||
342 | "output", | ||
343 | "sample"; | ||
332 | interrupts = <32>; | 344 | interrupts = <32>; |
333 | status = "disabled"; | 345 | status = "disabled"; |
334 | }; | 346 | }; |
@@ -336,8 +348,14 @@ | |||
336 | mmc2: mmc@01c11000 { | 348 | mmc2: mmc@01c11000 { |
337 | compatible = "allwinner,sun5i-a13-mmc"; | 349 | compatible = "allwinner,sun5i-a13-mmc"; |
338 | reg = <0x01c11000 0x1000>; | 350 | reg = <0x01c11000 0x1000>; |
339 | clocks = <&ahb_gates 10>, <&mmc2_clk>; | 351 | clocks = <&ahb_gates 10>, |
340 | clock-names = "ahb", "mmc"; | 352 | <&mmc2_clk 0>, |
353 | <&mmc2_clk 1>, | ||
354 | <&mmc2_clk 2>; | ||
355 | clock-names = "ahb", | ||
356 | "mmc", | ||
357 | "output", | ||
358 | "sample"; | ||
341 | interrupts = <34>; | 359 | interrupts = <34>; |
342 | status = "disabled"; | 360 | status = "disabled"; |
343 | }; | 361 | }; |
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index f47156b6572b..3e7db5191516 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi | |||
@@ -174,19 +174,11 @@ | |||
174 | clock-output-names = "axi"; | 174 | clock-output-names = "axi"; |
175 | }; | 175 | }; |
176 | 176 | ||
177 | ahb1_mux: ahb1_mux@01c20054 { | ||
178 | #clock-cells = <0>; | ||
179 | compatible = "allwinner,sun6i-a31-ahb1-mux-clk"; | ||
180 | reg = <0x01c20054 0x4>; | ||
181 | clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; | ||
182 | clock-output-names = "ahb1_mux"; | ||
183 | }; | ||
184 | |||
185 | ahb1: ahb1@01c20054 { | 177 | ahb1: ahb1@01c20054 { |
186 | #clock-cells = <0>; | 178 | #clock-cells = <0>; |
187 | compatible = "allwinner,sun4i-a10-ahb-clk"; | 179 | compatible = "allwinner,sun6i-a31-ahb1-clk"; |
188 | reg = <0x01c20054 0x4>; | 180 | reg = <0x01c20054 0x4>; |
189 | clocks = <&ahb1_mux>; | 181 | clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; |
190 | clock-output-names = "ahb1"; | 182 | clock-output-names = "ahb1"; |
191 | }; | 183 | }; |
192 | 184 | ||
@@ -249,35 +241,43 @@ | |||
249 | }; | 241 | }; |
250 | 242 | ||
251 | mmc0_clk: clk@01c20088 { | 243 | mmc0_clk: clk@01c20088 { |
252 | #clock-cells = <0>; | 244 | #clock-cells = <1>; |
253 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 245 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
254 | reg = <0x01c20088 0x4>; | 246 | reg = <0x01c20088 0x4>; |
255 | clocks = <&osc24M>, <&pll6 0>; | 247 | clocks = <&osc24M>, <&pll6 0>; |
256 | clock-output-names = "mmc0"; | 248 | clock-output-names = "mmc0", |
249 | "mmc0_output", | ||
250 | "mmc0_sample"; | ||
257 | }; | 251 | }; |
258 | 252 | ||
259 | mmc1_clk: clk@01c2008c { | 253 | mmc1_clk: clk@01c2008c { |
260 | #clock-cells = <0>; | 254 | #clock-cells = <1>; |
261 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 255 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
262 | reg = <0x01c2008c 0x4>; | 256 | reg = <0x01c2008c 0x4>; |
263 | clocks = <&osc24M>, <&pll6 0>; | 257 | clocks = <&osc24M>, <&pll6 0>; |
264 | clock-output-names = "mmc1"; | 258 | clock-output-names = "mmc1", |
259 | "mmc1_output", | ||
260 | "mmc1_sample"; | ||
265 | }; | 261 | }; |
266 | 262 | ||
267 | mmc2_clk: clk@01c20090 { | 263 | mmc2_clk: clk@01c20090 { |
268 | #clock-cells = <0>; | 264 | #clock-cells = <1>; |
269 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 265 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
270 | reg = <0x01c20090 0x4>; | 266 | reg = <0x01c20090 0x4>; |
271 | clocks = <&osc24M>, <&pll6 0>; | 267 | clocks = <&osc24M>, <&pll6 0>; |
272 | clock-output-names = "mmc2"; | 268 | clock-output-names = "mmc2", |
269 | "mmc2_output", | ||
270 | "mmc2_sample"; | ||
273 | }; | 271 | }; |
274 | 272 | ||
275 | mmc3_clk: clk@01c20094 { | 273 | mmc3_clk: clk@01c20094 { |
276 | #clock-cells = <0>; | 274 | #clock-cells = <1>; |
277 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 275 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
278 | reg = <0x01c20094 0x4>; | 276 | reg = <0x01c20094 0x4>; |
279 | clocks = <&osc24M>, <&pll6 0>; | 277 | clocks = <&osc24M>, <&pll6 0>; |
280 | clock-output-names = "mmc3"; | 278 | clock-output-names = "mmc3", |
279 | "mmc3_output", | ||
280 | "mmc3_sample"; | ||
281 | }; | 281 | }; |
282 | 282 | ||
283 | spi0_clk: clk@01c200a0 { | 283 | spi0_clk: clk@01c200a0 { |
@@ -367,15 +367,21 @@ | |||
367 | #dma-cells = <1>; | 367 | #dma-cells = <1>; |
368 | 368 | ||
369 | /* DMA controller requires AHB1 clocked from PLL6 */ | 369 | /* DMA controller requires AHB1 clocked from PLL6 */ |
370 | assigned-clocks = <&ahb1_mux>; | 370 | assigned-clocks = <&ahb1>; |
371 | assigned-clock-parents = <&pll6 0>; | 371 | assigned-clock-parents = <&pll6 0>; |
372 | }; | 372 | }; |
373 | 373 | ||
374 | mmc0: mmc@01c0f000 { | 374 | mmc0: mmc@01c0f000 { |
375 | compatible = "allwinner,sun5i-a13-mmc"; | 375 | compatible = "allwinner,sun5i-a13-mmc"; |
376 | reg = <0x01c0f000 0x1000>; | 376 | reg = <0x01c0f000 0x1000>; |
377 | clocks = <&ahb1_gates 8>, <&mmc0_clk>; | 377 | clocks = <&ahb1_gates 8>, |
378 | clock-names = "ahb", "mmc"; | 378 | <&mmc0_clk 0>, |
379 | <&mmc0_clk 1>, | ||
380 | <&mmc0_clk 2>; | ||
381 | clock-names = "ahb", | ||
382 | "mmc", | ||
383 | "output", | ||
384 | "sample"; | ||
379 | resets = <&ahb1_rst 8>; | 385 | resets = <&ahb1_rst 8>; |
380 | reset-names = "ahb"; | 386 | reset-names = "ahb"; |
381 | interrupts = <0 60 4>; | 387 | interrupts = <0 60 4>; |
@@ -385,8 +391,14 @@ | |||
385 | mmc1: mmc@01c10000 { | 391 | mmc1: mmc@01c10000 { |
386 | compatible = "allwinner,sun5i-a13-mmc"; | 392 | compatible = "allwinner,sun5i-a13-mmc"; |
387 | reg = <0x01c10000 0x1000>; | 393 | reg = <0x01c10000 0x1000>; |
388 | clocks = <&ahb1_gates 9>, <&mmc1_clk>; | 394 | clocks = <&ahb1_gates 9>, |
389 | clock-names = "ahb", "mmc"; | 395 | <&mmc1_clk 0>, |
396 | <&mmc1_clk 1>, | ||
397 | <&mmc1_clk 2>; | ||
398 | clock-names = "ahb", | ||
399 | "mmc", | ||
400 | "output", | ||
401 | "sample"; | ||
390 | resets = <&ahb1_rst 9>; | 402 | resets = <&ahb1_rst 9>; |
391 | reset-names = "ahb"; | 403 | reset-names = "ahb"; |
392 | interrupts = <0 61 4>; | 404 | interrupts = <0 61 4>; |
@@ -396,8 +408,14 @@ | |||
396 | mmc2: mmc@01c11000 { | 408 | mmc2: mmc@01c11000 { |
397 | compatible = "allwinner,sun5i-a13-mmc"; | 409 | compatible = "allwinner,sun5i-a13-mmc"; |
398 | reg = <0x01c11000 0x1000>; | 410 | reg = <0x01c11000 0x1000>; |
399 | clocks = <&ahb1_gates 10>, <&mmc2_clk>; | 411 | clocks = <&ahb1_gates 10>, |
400 | clock-names = "ahb", "mmc"; | 412 | <&mmc2_clk 0>, |
413 | <&mmc2_clk 1>, | ||
414 | <&mmc2_clk 2>; | ||
415 | clock-names = "ahb", | ||
416 | "mmc", | ||
417 | "output", | ||
418 | "sample"; | ||
401 | resets = <&ahb1_rst 10>; | 419 | resets = <&ahb1_rst 10>; |
402 | reset-names = "ahb"; | 420 | reset-names = "ahb"; |
403 | interrupts = <0 62 4>; | 421 | interrupts = <0 62 4>; |
@@ -407,8 +425,14 @@ | |||
407 | mmc3: mmc@01c12000 { | 425 | mmc3: mmc@01c12000 { |
408 | compatible = "allwinner,sun5i-a13-mmc"; | 426 | compatible = "allwinner,sun5i-a13-mmc"; |
409 | reg = <0x01c12000 0x1000>; | 427 | reg = <0x01c12000 0x1000>; |
410 | clocks = <&ahb1_gates 11>, <&mmc3_clk>; | 428 | clocks = <&ahb1_gates 11>, |
411 | clock-names = "ahb", "mmc"; | 429 | <&mmc3_clk 0>, |
430 | <&mmc3_clk 1>, | ||
431 | <&mmc3_clk 2>; | ||
432 | clock-names = "ahb", | ||
433 | "mmc", | ||
434 | "output", | ||
435 | "sample"; | ||
412 | resets = <&ahb1_rst 11>; | 436 | resets = <&ahb1_rst 11>; |
413 | reset-names = "ahb"; | 437 | reset-names = "ahb"; |
414 | interrupts = <0 63 4>; | 438 | interrupts = <0 63 4>; |
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index e21ce5992d56..fa51bffcaf1d 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi | |||
@@ -274,35 +274,43 @@ | |||
274 | }; | 274 | }; |
275 | 275 | ||
276 | mmc0_clk: clk@01c20088 { | 276 | mmc0_clk: clk@01c20088 { |
277 | #clock-cells = <0>; | 277 | #clock-cells = <1>; |
278 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 278 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
279 | reg = <0x01c20088 0x4>; | 279 | reg = <0x01c20088 0x4>; |
280 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 280 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
281 | clock-output-names = "mmc0"; | 281 | clock-output-names = "mmc0", |
282 | "mmc0_output", | ||
283 | "mmc0_sample"; | ||
282 | }; | 284 | }; |
283 | 285 | ||
284 | mmc1_clk: clk@01c2008c { | 286 | mmc1_clk: clk@01c2008c { |
285 | #clock-cells = <0>; | 287 | #clock-cells = <1>; |
286 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 288 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
287 | reg = <0x01c2008c 0x4>; | 289 | reg = <0x01c2008c 0x4>; |
288 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 290 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
289 | clock-output-names = "mmc1"; | 291 | clock-output-names = "mmc1", |
292 | "mmc1_output", | ||
293 | "mmc1_sample"; | ||
290 | }; | 294 | }; |
291 | 295 | ||
292 | mmc2_clk: clk@01c20090 { | 296 | mmc2_clk: clk@01c20090 { |
293 | #clock-cells = <0>; | 297 | #clock-cells = <1>; |
294 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 298 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
295 | reg = <0x01c20090 0x4>; | 299 | reg = <0x01c20090 0x4>; |
296 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 300 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
297 | clock-output-names = "mmc2"; | 301 | clock-output-names = "mmc2", |
302 | "mmc2_output", | ||
303 | "mmc2_sample"; | ||
298 | }; | 304 | }; |
299 | 305 | ||
300 | mmc3_clk: clk@01c20094 { | 306 | mmc3_clk: clk@01c20094 { |
301 | #clock-cells = <0>; | 307 | #clock-cells = <1>; |
302 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 308 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
303 | reg = <0x01c20094 0x4>; | 309 | reg = <0x01c20094 0x4>; |
304 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | 310 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; |
305 | clock-output-names = "mmc3"; | 311 | clock-output-names = "mmc3", |
312 | "mmc3_output", | ||
313 | "mmc3_sample"; | ||
306 | }; | 314 | }; |
307 | 315 | ||
308 | ts_clk: clk@01c20098 { | 316 | ts_clk: clk@01c20098 { |
@@ -518,8 +526,14 @@ | |||
518 | mmc0: mmc@01c0f000 { | 526 | mmc0: mmc@01c0f000 { |
519 | compatible = "allwinner,sun5i-a13-mmc"; | 527 | compatible = "allwinner,sun5i-a13-mmc"; |
520 | reg = <0x01c0f000 0x1000>; | 528 | reg = <0x01c0f000 0x1000>; |
521 | clocks = <&ahb_gates 8>, <&mmc0_clk>; | 529 | clocks = <&ahb_gates 8>, |
522 | clock-names = "ahb", "mmc"; | 530 | <&mmc0_clk 0>, |
531 | <&mmc0_clk 1>, | ||
532 | <&mmc0_clk 2>; | ||
533 | clock-names = "ahb", | ||
534 | "mmc", | ||
535 | "output", | ||
536 | "sample"; | ||
523 | interrupts = <0 32 4>; | 537 | interrupts = <0 32 4>; |
524 | status = "disabled"; | 538 | status = "disabled"; |
525 | }; | 539 | }; |
@@ -527,8 +541,14 @@ | |||
527 | mmc1: mmc@01c10000 { | 541 | mmc1: mmc@01c10000 { |
528 | compatible = "allwinner,sun5i-a13-mmc"; | 542 | compatible = "allwinner,sun5i-a13-mmc"; |
529 | reg = <0x01c10000 0x1000>; | 543 | reg = <0x01c10000 0x1000>; |
530 | clocks = <&ahb_gates 9>, <&mmc1_clk>; | 544 | clocks = <&ahb_gates 9>, |
531 | clock-names = "ahb", "mmc"; | 545 | <&mmc1_clk 0>, |
546 | <&mmc1_clk 1>, | ||
547 | <&mmc1_clk 2>; | ||
548 | clock-names = "ahb", | ||
549 | "mmc", | ||
550 | "output", | ||
551 | "sample"; | ||
532 | interrupts = <0 33 4>; | 552 | interrupts = <0 33 4>; |
533 | status = "disabled"; | 553 | status = "disabled"; |
534 | }; | 554 | }; |
@@ -536,8 +556,14 @@ | |||
536 | mmc2: mmc@01c11000 { | 556 | mmc2: mmc@01c11000 { |
537 | compatible = "allwinner,sun5i-a13-mmc"; | 557 | compatible = "allwinner,sun5i-a13-mmc"; |
538 | reg = <0x01c11000 0x1000>; | 558 | reg = <0x01c11000 0x1000>; |
539 | clocks = <&ahb_gates 10>, <&mmc2_clk>; | 559 | clocks = <&ahb_gates 10>, |
540 | clock-names = "ahb", "mmc"; | 560 | <&mmc2_clk 0>, |
561 | <&mmc2_clk 1>, | ||
562 | <&mmc2_clk 2>; | ||
563 | clock-names = "ahb", | ||
564 | "mmc", | ||
565 | "output", | ||
566 | "sample"; | ||
541 | interrupts = <0 34 4>; | 567 | interrupts = <0 34 4>; |
542 | status = "disabled"; | 568 | status = "disabled"; |
543 | }; | 569 | }; |
@@ -545,8 +571,14 @@ | |||
545 | mmc3: mmc@01c12000 { | 571 | mmc3: mmc@01c12000 { |
546 | compatible = "allwinner,sun5i-a13-mmc"; | 572 | compatible = "allwinner,sun5i-a13-mmc"; |
547 | reg = <0x01c12000 0x1000>; | 573 | reg = <0x01c12000 0x1000>; |
548 | clocks = <&ahb_gates 11>, <&mmc3_clk>; | 574 | clocks = <&ahb_gates 11>, |
549 | clock-names = "ahb", "mmc"; | 575 | <&mmc3_clk 0>, |
576 | <&mmc3_clk 1>, | ||
577 | <&mmc3_clk 2>; | ||
578 | clock-names = "ahb", | ||
579 | "mmc", | ||
580 | "output", | ||
581 | "sample"; | ||
550 | interrupts = <0 35 4>; | 582 | interrupts = <0 35 4>; |
551 | status = "disabled"; | 583 | status = "disabled"; |
552 | }; | 584 | }; |
diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi index 0746cd1024d7..43a0688fffa0 100644 --- a/arch/arm/boot/dts/sun8i-a23.dtsi +++ b/arch/arm/boot/dts/sun8i-a23.dtsi | |||
@@ -110,11 +110,19 @@ | |||
110 | }; | 110 | }; |
111 | 111 | ||
112 | /* dummy clock until actually implemented */ | 112 | /* dummy clock until actually implemented */ |
113 | pll6: pll6_clk { | 113 | pll5: pll5_clk { |
114 | #clock-cells = <0>; | 114 | #clock-cells = <0>; |
115 | compatible = "fixed-clock"; | 115 | compatible = "fixed-clock"; |
116 | clock-frequency = <600000000>; | 116 | clock-frequency = <0>; |
117 | clock-output-names = "pll6"; | 117 | clock-output-names = "pll5"; |
118 | }; | ||
119 | |||
120 | pll6: clk@01c20028 { | ||
121 | #clock-cells = <1>; | ||
122 | compatible = "allwinner,sun6i-a31-pll6-clk"; | ||
123 | reg = <0x01c20028 0x4>; | ||
124 | clocks = <&osc24M>; | ||
125 | clock-output-names = "pll6", "pll6x2"; | ||
118 | }; | 126 | }; |
119 | 127 | ||
120 | cpu: cpu_clk@01c20050 { | 128 | cpu: cpu_clk@01c20050 { |
@@ -140,19 +148,11 @@ | |||
140 | clock-output-names = "axi"; | 148 | clock-output-names = "axi"; |
141 | }; | 149 | }; |
142 | 150 | ||
143 | ahb1_mux: ahb1_mux_clk@01c20054 { | ||
144 | #clock-cells = <0>; | ||
145 | compatible = "allwinner,sun6i-a31-ahb1-mux-clk"; | ||
146 | reg = <0x01c20054 0x4>; | ||
147 | clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>; | ||
148 | clock-output-names = "ahb1_mux"; | ||
149 | }; | ||
150 | |||
151 | ahb1: ahb1_clk@01c20054 { | 151 | ahb1: ahb1_clk@01c20054 { |
152 | #clock-cells = <0>; | 152 | #clock-cells = <0>; |
153 | compatible = "allwinner,sun4i-a10-ahb-clk"; | 153 | compatible = "allwinner,sun6i-a31-ahb1-clk"; |
154 | reg = <0x01c20054 0x4>; | 154 | reg = <0x01c20054 0x4>; |
155 | clocks = <&ahb1_mux>; | 155 | clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; |
156 | clock-output-names = "ahb1"; | 156 | clock-output-names = "ahb1"; |
157 | }; | 157 | }; |
158 | 158 | ||
@@ -193,7 +193,7 @@ | |||
193 | #clock-cells = <0>; | 193 | #clock-cells = <0>; |
194 | compatible = "allwinner,sun4i-a10-apb1-clk"; | 194 | compatible = "allwinner,sun4i-a10-apb1-clk"; |
195 | reg = <0x01c20058 0x4>; | 195 | reg = <0x01c20058 0x4>; |
196 | clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>; | 196 | clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>; |
197 | clock-output-names = "apb2"; | 197 | clock-output-names = "apb2"; |
198 | }; | 198 | }; |
199 | 199 | ||
@@ -209,27 +209,41 @@ | |||
209 | }; | 209 | }; |
210 | 210 | ||
211 | mmc0_clk: clk@01c20088 { | 211 | mmc0_clk: clk@01c20088 { |
212 | #clock-cells = <0>; | 212 | #clock-cells = <1>; |
213 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 213 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
214 | reg = <0x01c20088 0x4>; | 214 | reg = <0x01c20088 0x4>; |
215 | clocks = <&osc24M>, <&pll6>; | 215 | clocks = <&osc24M>, <&pll6 0>; |
216 | clock-output-names = "mmc0"; | 216 | clock-output-names = "mmc0", |
217 | "mmc0_output", | ||
218 | "mmc0_sample"; | ||
217 | }; | 219 | }; |
218 | 220 | ||
219 | mmc1_clk: clk@01c2008c { | 221 | mmc1_clk: clk@01c2008c { |
220 | #clock-cells = <0>; | 222 | #clock-cells = <1>; |
221 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 223 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
222 | reg = <0x01c2008c 0x4>; | 224 | reg = <0x01c2008c 0x4>; |
223 | clocks = <&osc24M>, <&pll6>; | 225 | clocks = <&osc24M>, <&pll6 0>; |
224 | clock-output-names = "mmc1"; | 226 | clock-output-names = "mmc1", |
227 | "mmc1_output", | ||
228 | "mmc1_sample"; | ||
225 | }; | 229 | }; |
226 | 230 | ||
227 | mmc2_clk: clk@01c20090 { | 231 | mmc2_clk: clk@01c20090 { |
228 | #clock-cells = <0>; | 232 | #clock-cells = <1>; |
229 | compatible = "allwinner,sun4i-a10-mod0-clk"; | 233 | compatible = "allwinner,sun4i-a10-mmc-clk"; |
230 | reg = <0x01c20090 0x4>; | 234 | reg = <0x01c20090 0x4>; |
231 | clocks = <&osc24M>, <&pll6>; | 235 | clocks = <&osc24M>, <&pll6 0>; |
232 | clock-output-names = "mmc2"; | 236 | clock-output-names = "mmc2", |
237 | "mmc2_output", | ||
238 | "mmc2_sample"; | ||
239 | }; | ||
240 | |||
241 | mbus_clk: clk@01c2015c { | ||
242 | #clock-cells = <0>; | ||
243 | compatible = "allwinner,sun8i-a23-mbus-clk"; | ||
244 | reg = <0x01c2015c 0x4>; | ||
245 | clocks = <&osc24M>, <&pll6 1>, <&pll5>; | ||
246 | clock-output-names = "mbus"; | ||
233 | }; | 247 | }; |
234 | }; | 248 | }; |
235 | 249 | ||
@@ -251,8 +265,14 @@ | |||
251 | mmc0: mmc@01c0f000 { | 265 | mmc0: mmc@01c0f000 { |
252 | compatible = "allwinner,sun5i-a13-mmc"; | 266 | compatible = "allwinner,sun5i-a13-mmc"; |
253 | reg = <0x01c0f000 0x1000>; | 267 | reg = <0x01c0f000 0x1000>; |
254 | clocks = <&ahb1_gates 8>, <&mmc0_clk>; | 268 | clocks = <&ahb1_gates 8>, |
255 | clock-names = "ahb", "mmc"; | 269 | <&mmc0_clk 0>, |
270 | <&mmc0_clk 1>, | ||
271 | <&mmc0_clk 2>; | ||
272 | clock-names = "ahb", | ||
273 | "mmc", | ||
274 | "output", | ||
275 | "sample"; | ||
256 | resets = <&ahb1_rst 8>; | 276 | resets = <&ahb1_rst 8>; |
257 | reset-names = "ahb"; | 277 | reset-names = "ahb"; |
258 | interrupts = <0 60 4>; | 278 | interrupts = <0 60 4>; |
@@ -262,8 +282,14 @@ | |||
262 | mmc1: mmc@01c10000 { | 282 | mmc1: mmc@01c10000 { |
263 | compatible = "allwinner,sun5i-a13-mmc"; | 283 | compatible = "allwinner,sun5i-a13-mmc"; |
264 | reg = <0x01c10000 0x1000>; | 284 | reg = <0x01c10000 0x1000>; |
265 | clocks = <&ahb1_gates 9>, <&mmc1_clk>; | 285 | clocks = <&ahb1_gates 9>, |
266 | clock-names = "ahb", "mmc"; | 286 | <&mmc1_clk 0>, |
287 | <&mmc1_clk 1>, | ||
288 | <&mmc1_clk 2>; | ||
289 | clock-names = "ahb", | ||
290 | "mmc", | ||
291 | "output", | ||
292 | "sample"; | ||
267 | resets = <&ahb1_rst 9>; | 293 | resets = <&ahb1_rst 9>; |
268 | reset-names = "ahb"; | 294 | reset-names = "ahb"; |
269 | interrupts = <0 61 4>; | 295 | interrupts = <0 61 4>; |
@@ -273,8 +299,14 @@ | |||
273 | mmc2: mmc@01c11000 { | 299 | mmc2: mmc@01c11000 { |
274 | compatible = "allwinner,sun5i-a13-mmc"; | 300 | compatible = "allwinner,sun5i-a13-mmc"; |
275 | reg = <0x01c11000 0x1000>; | 301 | reg = <0x01c11000 0x1000>; |
276 | clocks = <&ahb1_gates 10>, <&mmc2_clk>; | 302 | clocks = <&ahb1_gates 10>, |
277 | clock-names = "ahb", "mmc"; | 303 | <&mmc2_clk 0>, |
304 | <&mmc2_clk 1>, | ||
305 | <&mmc2_clk 2>; | ||
306 | clock-names = "ahb", | ||
307 | "mmc", | ||
308 | "output", | ||
309 | "sample"; | ||
278 | resets = <&ahb1_rst 10>; | 310 | resets = <&ahb1_rst 10>; |
279 | reset-names = "ahb"; | 311 | reset-names = "ahb"; |
280 | interrupts = <0 62 4>; | 312 | interrupts = <0 62 4>; |
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index a66953c0f430..3a5292e3fcf8 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile | |||
@@ -8,6 +8,7 @@ obj-y += clk-a20-gmac.o | |||
8 | obj-y += clk-mod0.o | 8 | obj-y += clk-mod0.o |
9 | obj-y += clk-sun8i-mbus.o | 9 | obj-y += clk-sun8i-mbus.o |
10 | obj-y += clk-sun9i-core.o | 10 | obj-y += clk-sun9i-core.o |
11 | obj-y += clk-sun9i-mmc.o | ||
11 | 12 | ||
12 | obj-$(CONFIG_MFD_SUN6I_PRCM) += \ | 13 | obj-$(CONFIG_MFD_SUN6I_PRCM) += \ |
13 | clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \ | 14 | clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \ |
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 62e08fb58554..a9ebbd207d58 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c | |||
@@ -156,9 +156,10 @@ static const struct clk_ops clk_factors_ops = { | |||
156 | .set_rate = clk_factors_set_rate, | 156 | .set_rate = clk_factors_set_rate, |
157 | }; | 157 | }; |
158 | 158 | ||
159 | struct clk * __init sunxi_factors_register(struct device_node *node, | 159 | struct clk *sunxi_factors_register(struct device_node *node, |
160 | const struct factors_data *data, | 160 | const struct factors_data *data, |
161 | spinlock_t *lock) | 161 | spinlock_t *lock, |
162 | void __iomem *reg) | ||
162 | { | 163 | { |
163 | struct clk *clk; | 164 | struct clk *clk; |
164 | struct clk_factors *factors; | 165 | struct clk_factors *factors; |
@@ -168,11 +169,8 @@ struct clk * __init sunxi_factors_register(struct device_node *node, | |||
168 | struct clk_hw *mux_hw = NULL; | 169 | struct clk_hw *mux_hw = NULL; |
169 | const char *clk_name = node->name; | 170 | const char *clk_name = node->name; |
170 | const char *parents[FACTORS_MAX_PARENTS]; | 171 | const char *parents[FACTORS_MAX_PARENTS]; |
171 | void __iomem *reg; | ||
172 | int i = 0; | 172 | int i = 0; |
173 | 173 | ||
174 | reg = of_iomap(node, 0); | ||
175 | |||
176 | /* if we have a mux, we will have >1 parents */ | 174 | /* if we have a mux, we will have >1 parents */ |
177 | while (i < FACTORS_MAX_PARENTS && | 175 | while (i < FACTORS_MAX_PARENTS && |
178 | (parents[i] = of_clk_get_parent_name(node, i)) != NULL) | 176 | (parents[i] = of_clk_get_parent_name(node, i)) != NULL) |
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h index 912238fde132..171085ab5513 100644 --- a/drivers/clk/sunxi/clk-factors.h +++ b/drivers/clk/sunxi/clk-factors.h | |||
@@ -36,8 +36,9 @@ struct clk_factors { | |||
36 | spinlock_t *lock; | 36 | spinlock_t *lock; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct clk * __init sunxi_factors_register(struct device_node *node, | 39 | struct clk *sunxi_factors_register(struct device_node *node, |
40 | const struct factors_data *data, | 40 | const struct factors_data *data, |
41 | spinlock_t *lock); | 41 | spinlock_t *lock, |
42 | void __iomem *reg); | ||
42 | 43 | ||
43 | #endif | 44 | #endif |
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index da0524eaee94..ec8f5a1fca09 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/clk-provider.h> | 17 | #include <linux/clk-provider.h> |
18 | #include <linux/clkdev.h> | 18 | #include <linux/clkdev.h> |
19 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
20 | #include <linux/platform_device.h> | ||
20 | 21 | ||
21 | #include "clk-factors.h" | 22 | #include "clk-factors.h" |
22 | 23 | ||
@@ -67,7 +68,7 @@ static struct clk_factors_config sun4i_a10_mod0_config = { | |||
67 | .pwidth = 2, | 68 | .pwidth = 2, |
68 | }; | 69 | }; |
69 | 70 | ||
70 | static const struct factors_data sun4i_a10_mod0_data __initconst = { | 71 | static const struct factors_data sun4i_a10_mod0_data = { |
71 | .enable = 31, | 72 | .enable = 31, |
72 | .mux = 24, | 73 | .mux = 24, |
73 | .muxmask = BIT(1) | BIT(0), | 74 | .muxmask = BIT(1) | BIT(0), |
@@ -79,15 +80,95 @@ static DEFINE_SPINLOCK(sun4i_a10_mod0_lock); | |||
79 | 80 | ||
80 | static void __init sun4i_a10_mod0_setup(struct device_node *node) | 81 | static void __init sun4i_a10_mod0_setup(struct device_node *node) |
81 | { | 82 | { |
82 | sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock); | 83 | void __iomem *reg; |
84 | |||
85 | reg = of_iomap(node, 0); | ||
86 | if (!reg) { | ||
87 | /* | ||
88 | * This happens with mod0 clk nodes instantiated through | ||
89 | * mfd, as those do not have their resources assigned at | ||
90 | * CLK_OF_DECLARE time yet, so do not print an error. | ||
91 | */ | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | sunxi_factors_register(node, &sun4i_a10_mod0_data, | ||
96 | &sun4i_a10_mod0_lock, reg); | ||
83 | } | 97 | } |
84 | CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup); | 98 | CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup); |
85 | 99 | ||
100 | static int sun4i_a10_mod0_clk_probe(struct platform_device *pdev) | ||
101 | { | ||
102 | struct device_node *np = pdev->dev.of_node; | ||
103 | struct resource *r; | ||
104 | void __iomem *reg; | ||
105 | |||
106 | if (!np) | ||
107 | return -ENODEV; | ||
108 | |||
109 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
110 | reg = devm_ioremap_resource(&pdev->dev, r); | ||
111 | if (IS_ERR(reg)) | ||
112 | return PTR_ERR(reg); | ||
113 | |||
114 | sunxi_factors_register(np, &sun4i_a10_mod0_data, | ||
115 | &sun4i_a10_mod0_lock, reg); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static const struct of_device_id sun4i_a10_mod0_clk_dt_ids[] = { | ||
120 | { .compatible = "allwinner,sun4i-a10-mod0-clk" }, | ||
121 | { /* sentinel */ } | ||
122 | }; | ||
123 | |||
124 | static struct platform_driver sun4i_a10_mod0_clk_driver = { | ||
125 | .driver = { | ||
126 | .name = "sun4i-a10-mod0-clk", | ||
127 | .of_match_table = sun4i_a10_mod0_clk_dt_ids, | ||
128 | }, | ||
129 | .probe = sun4i_a10_mod0_clk_probe, | ||
130 | }; | ||
131 | module_platform_driver(sun4i_a10_mod0_clk_driver); | ||
132 | |||
133 | static const struct factors_data sun9i_a80_mod0_data __initconst = { | ||
134 | .enable = 31, | ||
135 | .mux = 24, | ||
136 | .muxmask = BIT(3) | BIT(2) | BIT(1) | BIT(0), | ||
137 | .table = &sun4i_a10_mod0_config, | ||
138 | .getter = sun4i_a10_get_mod0_factors, | ||
139 | }; | ||
140 | |||
141 | static void __init sun9i_a80_mod0_setup(struct device_node *node) | ||
142 | { | ||
143 | void __iomem *reg; | ||
144 | |||
145 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
146 | if (IS_ERR(reg)) { | ||
147 | pr_err("Could not get registers for mod0-clk: %s\n", | ||
148 | node->name); | ||
149 | return; | ||
150 | } | ||
151 | |||
152 | sunxi_factors_register(node, &sun9i_a80_mod0_data, | ||
153 | &sun4i_a10_mod0_lock, reg); | ||
154 | } | ||
155 | CLK_OF_DECLARE(sun9i_a80_mod0, "allwinner,sun9i-a80-mod0-clk", sun9i_a80_mod0_setup); | ||
156 | |||
86 | static DEFINE_SPINLOCK(sun5i_a13_mbus_lock); | 157 | static DEFINE_SPINLOCK(sun5i_a13_mbus_lock); |
87 | 158 | ||
88 | static void __init sun5i_a13_mbus_setup(struct device_node *node) | 159 | static void __init sun5i_a13_mbus_setup(struct device_node *node) |
89 | { | 160 | { |
90 | struct clk *mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun5i_a13_mbus_lock); | 161 | struct clk *mbus; |
162 | void __iomem *reg; | ||
163 | |||
164 | reg = of_iomap(node, 0); | ||
165 | if (!reg) { | ||
166 | pr_err("Could not get registers for a13-mbus-clk\n"); | ||
167 | return; | ||
168 | } | ||
169 | |||
170 | mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data, | ||
171 | &sun5i_a13_mbus_lock, reg); | ||
91 | 172 | ||
92 | /* The MBUS clocks needs to be always enabled */ | 173 | /* The MBUS clocks needs to be always enabled */ |
93 | __clk_get(mbus); | 174 | __clk_get(mbus); |
@@ -95,14 +176,10 @@ static void __init sun5i_a13_mbus_setup(struct device_node *node) | |||
95 | } | 176 | } |
96 | CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup); | 177 | CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup); |
97 | 178 | ||
98 | struct mmc_phase_data { | ||
99 | u8 offset; | ||
100 | }; | ||
101 | |||
102 | struct mmc_phase { | 179 | struct mmc_phase { |
103 | struct clk_hw hw; | 180 | struct clk_hw hw; |
181 | u8 offset; | ||
104 | void __iomem *reg; | 182 | void __iomem *reg; |
105 | struct mmc_phase_data *data; | ||
106 | spinlock_t *lock; | 183 | spinlock_t *lock; |
107 | }; | 184 | }; |
108 | 185 | ||
@@ -118,7 +195,7 @@ static int mmc_get_phase(struct clk_hw *hw) | |||
118 | u8 delay; | 195 | u8 delay; |
119 | 196 | ||
120 | value = readl(phase->reg); | 197 | value = readl(phase->reg); |
121 | delay = (value >> phase->data->offset) & 0x3; | 198 | delay = (value >> phase->offset) & 0x3; |
122 | 199 | ||
123 | if (!delay) | 200 | if (!delay) |
124 | return 180; | 201 | return 180; |
@@ -206,8 +283,8 @@ static int mmc_set_phase(struct clk_hw *hw, int degrees) | |||
206 | 283 | ||
207 | spin_lock_irqsave(phase->lock, flags); | 284 | spin_lock_irqsave(phase->lock, flags); |
208 | value = readl(phase->reg); | 285 | value = readl(phase->reg); |
209 | value &= ~GENMASK(phase->data->offset + 3, phase->data->offset); | 286 | value &= ~GENMASK(phase->offset + 3, phase->offset); |
210 | value |= delay << phase->data->offset; | 287 | value |= delay << phase->offset; |
211 | writel(value, phase->reg); | 288 | writel(value, phase->reg); |
212 | spin_unlock_irqrestore(phase->lock, flags); | 289 | spin_unlock_irqrestore(phase->lock, flags); |
213 | 290 | ||
@@ -219,66 +296,97 @@ static const struct clk_ops mmc_clk_ops = { | |||
219 | .set_phase = mmc_set_phase, | 296 | .set_phase = mmc_set_phase, |
220 | }; | 297 | }; |
221 | 298 | ||
222 | static void __init sun4i_a10_mmc_phase_setup(struct device_node *node, | 299 | /* |
223 | struct mmc_phase_data *data) | 300 | * sunxi_mmc_setup - Common setup function for mmc module clocks |
301 | * | ||
302 | * The only difference between module clocks on different platforms is the | ||
303 | * width of the mux register bits and the valid values, which are passed in | ||
304 | * through struct factors_data. The phase clocks parts are identical. | ||
305 | */ | ||
306 | static void __init sunxi_mmc_setup(struct device_node *node, | ||
307 | const struct factors_data *data, | ||
308 | spinlock_t *lock) | ||
224 | { | 309 | { |
225 | const char *parent_names[1] = { of_clk_get_parent_name(node, 0) }; | 310 | struct clk_onecell_data *clk_data; |
226 | struct clk_init_data init = { | 311 | const char *parent; |
227 | .num_parents = 1, | 312 | void __iomem *reg; |
228 | .parent_names = parent_names, | 313 | int i; |
229 | .ops = &mmc_clk_ops, | 314 | |
230 | }; | 315 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
231 | 316 | if (IS_ERR(reg)) { | |
232 | struct mmc_phase *phase; | 317 | pr_err("Couldn't map the %s clock registers\n", node->name); |
233 | struct clk *clk; | ||
234 | |||
235 | phase = kmalloc(sizeof(*phase), GFP_KERNEL); | ||
236 | if (!phase) | ||
237 | return; | 318 | return; |
319 | } | ||
238 | 320 | ||
239 | phase->hw.init = &init; | 321 | clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL); |
240 | 322 | if (!clk_data) | |
241 | phase->reg = of_iomap(node, 0); | 323 | return; |
242 | if (!phase->reg) | ||
243 | goto err_free; | ||
244 | |||
245 | phase->data = data; | ||
246 | phase->lock = &sun4i_a10_mod0_lock; | ||
247 | |||
248 | if (of_property_read_string(node, "clock-output-names", &init.name)) | ||
249 | init.name = node->name; | ||
250 | 324 | ||
251 | clk = clk_register(NULL, &phase->hw); | 325 | clk_data->clks = kcalloc(3, sizeof(*clk_data->clks), GFP_KERNEL); |
252 | if (IS_ERR(clk)) | 326 | if (!clk_data->clks) |
253 | goto err_unmap; | 327 | goto err_free_data; |
328 | |||
329 | clk_data->clk_num = 3; | ||
330 | clk_data->clks[0] = sunxi_factors_register(node, data, lock, reg); | ||
331 | if (!clk_data->clks[0]) | ||
332 | goto err_free_clks; | ||
333 | |||
334 | parent = __clk_get_name(clk_data->clks[0]); | ||
335 | |||
336 | for (i = 1; i < 3; i++) { | ||
337 | struct clk_init_data init = { | ||
338 | .num_parents = 1, | ||
339 | .parent_names = &parent, | ||
340 | .ops = &mmc_clk_ops, | ||
341 | }; | ||
342 | struct mmc_phase *phase; | ||
343 | |||
344 | phase = kmalloc(sizeof(*phase), GFP_KERNEL); | ||
345 | if (!phase) | ||
346 | continue; | ||
347 | |||
348 | phase->hw.init = &init; | ||
349 | phase->reg = reg; | ||
350 | phase->lock = lock; | ||
351 | |||
352 | if (i == 1) | ||
353 | phase->offset = 8; | ||
354 | else | ||
355 | phase->offset = 20; | ||
356 | |||
357 | if (of_property_read_string_index(node, "clock-output-names", | ||
358 | i, &init.name)) | ||
359 | init.name = node->name; | ||
360 | |||
361 | clk_data->clks[i] = clk_register(NULL, &phase->hw); | ||
362 | if (IS_ERR(clk_data->clks[i])) { | ||
363 | kfree(phase); | ||
364 | continue; | ||
365 | } | ||
366 | } | ||
254 | 367 | ||
255 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | 368 | of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); |
256 | 369 | ||
257 | return; | 370 | return; |
258 | 371 | ||
259 | err_unmap: | 372 | err_free_clks: |
260 | iounmap(phase->reg); | 373 | kfree(clk_data->clks); |
261 | err_free: | 374 | err_free_data: |
262 | kfree(phase); | 375 | kfree(clk_data); |
263 | } | 376 | } |
264 | 377 | ||
378 | static DEFINE_SPINLOCK(sun4i_a10_mmc_lock); | ||
265 | 379 | ||
266 | static struct mmc_phase_data mmc_output_clk = { | 380 | static void __init sun4i_a10_mmc_setup(struct device_node *node) |
267 | .offset = 8, | ||
268 | }; | ||
269 | |||
270 | static struct mmc_phase_data mmc_sample_clk = { | ||
271 | .offset = 20, | ||
272 | }; | ||
273 | |||
274 | static void __init sun4i_a10_mmc_output_setup(struct device_node *node) | ||
275 | { | 381 | { |
276 | sun4i_a10_mmc_phase_setup(node, &mmc_output_clk); | 382 | sunxi_mmc_setup(node, &sun4i_a10_mod0_data, &sun4i_a10_mmc_lock); |
277 | } | 383 | } |
278 | CLK_OF_DECLARE(sun4i_a10_mmc_output, "allwinner,sun4i-a10-mmc-output-clk", sun4i_a10_mmc_output_setup); | 384 | CLK_OF_DECLARE(sun4i_a10_mmc, "allwinner,sun4i-a10-mmc-clk", sun4i_a10_mmc_setup); |
385 | |||
386 | static DEFINE_SPINLOCK(sun9i_a80_mmc_lock); | ||
279 | 387 | ||
280 | static void __init sun4i_a10_mmc_sample_setup(struct device_node *node) | 388 | static void __init sun9i_a80_mmc_setup(struct device_node *node) |
281 | { | 389 | { |
282 | sun4i_a10_mmc_phase_setup(node, &mmc_sample_clk); | 390 | sunxi_mmc_setup(node, &sun9i_a80_mod0_data, &sun9i_a80_mmc_lock); |
283 | } | 391 | } |
284 | CLK_OF_DECLARE(sun4i_a10_mmc_sample, "allwinner,sun4i-a10-mmc-sample-clk", sun4i_a10_mmc_sample_setup); | 392 | CLK_OF_DECLARE(sun9i_a80_mmc, "allwinner,sun9i-a80-mmc-clk", sun9i_a80_mmc_setup); |
diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c b/drivers/clk/sunxi/clk-sun8i-mbus.c index ef49786eefd3..14cd026064bf 100644 --- a/drivers/clk/sunxi/clk-sun8i-mbus.c +++ b/drivers/clk/sunxi/clk-sun8i-mbus.c | |||
@@ -69,8 +69,17 @@ static DEFINE_SPINLOCK(sun8i_a23_mbus_lock); | |||
69 | 69 | ||
70 | static void __init sun8i_a23_mbus_setup(struct device_node *node) | 70 | static void __init sun8i_a23_mbus_setup(struct device_node *node) |
71 | { | 71 | { |
72 | struct clk *mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data, | 72 | struct clk *mbus; |
73 | &sun8i_a23_mbus_lock); | 73 | void __iomem *reg; |
74 | |||
75 | reg = of_iomap(node, 0); | ||
76 | if (!reg) { | ||
77 | pr_err("Could not get registers for a23-mbus-clk\n"); | ||
78 | return; | ||
79 | } | ||
80 | |||
81 | mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data, | ||
82 | &sun8i_a23_mbus_lock, reg); | ||
74 | 83 | ||
75 | /* The MBUS clocks needs to be always enabled */ | 84 | /* The MBUS clocks needs to be always enabled */ |
76 | __clk_get(mbus); | 85 | __clk_get(mbus); |
diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c index 3cb9036d91bb..d8da77d72861 100644 --- a/drivers/clk/sunxi/clk-sun9i-core.c +++ b/drivers/clk/sunxi/clk-sun9i-core.c | |||
@@ -24,50 +24,51 @@ | |||
24 | 24 | ||
25 | 25 | ||
26 | /** | 26 | /** |
27 | * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1 | 27 | * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL4 |
28 | * PLL4 rate is calculated as follows | 28 | * PLL4 rate is calculated as follows |
29 | * rate = (parent_rate * n >> p) / (m + 1); | 29 | * rate = (parent_rate * n >> p) / (m + 1); |
30 | * parent_rate is always 24Mhz | 30 | * parent_rate is always 24MHz |
31 | * | 31 | * |
32 | * p and m are named div1 and div2 in Allwinner's SDK | 32 | * p and m are named div1 and div2 in Allwinner's SDK |
33 | */ | 33 | */ |
34 | 34 | ||
35 | static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate, | 35 | static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate, |
36 | u8 *n, u8 *k, u8 *m, u8 *p) | 36 | u8 *n_ret, u8 *k, u8 *m_ret, u8 *p_ret) |
37 | { | 37 | { |
38 | int div; | 38 | int n; |
39 | int m = 1; | ||
40 | int p = 1; | ||
39 | 41 | ||
40 | /* Normalize value to a 6M multiple */ | 42 | /* Normalize value to a 6 MHz multiple (24 MHz / 4) */ |
41 | div = DIV_ROUND_UP(*freq, 6000000); | 43 | n = DIV_ROUND_UP(*freq, 6000000); |
42 | 44 | ||
43 | /* divs above 256 cannot be odd */ | 45 | /* If n is too large switch to steps of 12 MHz */ |
44 | if (div > 256) | 46 | if (n > 255) { |
45 | div = round_up(div, 2); | 47 | m = 0; |
48 | n = (n + 1) / 2; | ||
49 | } | ||
50 | |||
51 | /* If n is still too large switch to steps of 24 MHz */ | ||
52 | if (n > 255) { | ||
53 | p = 0; | ||
54 | n = (n + 1) / 2; | ||
55 | } | ||
46 | 56 | ||
47 | /* divs above 512 must be a multiple of 4 */ | 57 | /* n must be between 12 and 255 */ |
48 | if (div > 512) | 58 | if (n > 255) |
49 | div = round_up(div, 4); | 59 | n = 255; |
60 | else if (n < 12) | ||
61 | n = 12; | ||
50 | 62 | ||
51 | *freq = 6000000 * div; | 63 | *freq = ((24000000 * n) >> p) / (m + 1); |
52 | 64 | ||
53 | /* we were called to round the frequency, we can now return */ | 65 | /* we were called to round the frequency, we can now return */ |
54 | if (n == NULL) | 66 | if (n_ret == NULL) |
55 | return; | 67 | return; |
56 | 68 | ||
57 | /* p will be 1 for divs under 512 */ | 69 | *n_ret = n; |
58 | if (div < 512) | 70 | *m_ret = m; |
59 | *p = 1; | 71 | *p_ret = p; |
60 | else | ||
61 | *p = 0; | ||
62 | |||
63 | /* m will be 1 if div is odd */ | ||
64 | if (div & 1) | ||
65 | *m = 1; | ||
66 | else | ||
67 | *m = 0; | ||
68 | |||
69 | /* calculate a suitable n based on m and p */ | ||
70 | *n = div / (*p + 1) / (*m + 1); | ||
71 | } | 72 | } |
72 | 73 | ||
73 | static struct clk_factors_config sun9i_a80_pll4_config = { | 74 | static struct clk_factors_config sun9i_a80_pll4_config = { |
@@ -89,7 +90,17 @@ static DEFINE_SPINLOCK(sun9i_a80_pll4_lock); | |||
89 | 90 | ||
90 | static void __init sun9i_a80_pll4_setup(struct device_node *node) | 91 | static void __init sun9i_a80_pll4_setup(struct device_node *node) |
91 | { | 92 | { |
92 | sunxi_factors_register(node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock); | 93 | void __iomem *reg; |
94 | |||
95 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
96 | if (!reg) { | ||
97 | pr_err("Could not get registers for a80-pll4-clk: %s\n", | ||
98 | node->name); | ||
99 | return; | ||
100 | } | ||
101 | |||
102 | sunxi_factors_register(node, &sun9i_a80_pll4_data, | ||
103 | &sun9i_a80_pll4_lock, reg); | ||
93 | } | 104 | } |
94 | CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup); | 105 | CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup); |
95 | 106 | ||
@@ -139,8 +150,18 @@ static DEFINE_SPINLOCK(sun9i_a80_gt_lock); | |||
139 | 150 | ||
140 | static void __init sun9i_a80_gt_setup(struct device_node *node) | 151 | static void __init sun9i_a80_gt_setup(struct device_node *node) |
141 | { | 152 | { |
142 | struct clk *gt = sunxi_factors_register(node, &sun9i_a80_gt_data, | 153 | void __iomem *reg; |
143 | &sun9i_a80_gt_lock); | 154 | struct clk *gt; |
155 | |||
156 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
157 | if (!reg) { | ||
158 | pr_err("Could not get registers for a80-gt-clk: %s\n", | ||
159 | node->name); | ||
160 | return; | ||
161 | } | ||
162 | |||
163 | gt = sunxi_factors_register(node, &sun9i_a80_gt_data, | ||
164 | &sun9i_a80_gt_lock, reg); | ||
144 | 165 | ||
145 | /* The GT bus clock needs to be always enabled */ | 166 | /* The GT bus clock needs to be always enabled */ |
146 | __clk_get(gt); | 167 | __clk_get(gt); |
@@ -194,7 +215,17 @@ static DEFINE_SPINLOCK(sun9i_a80_ahb_lock); | |||
194 | 215 | ||
195 | static void __init sun9i_a80_ahb_setup(struct device_node *node) | 216 | static void __init sun9i_a80_ahb_setup(struct device_node *node) |
196 | { | 217 | { |
197 | sunxi_factors_register(node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock); | 218 | void __iomem *reg; |
219 | |||
220 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
221 | if (!reg) { | ||
222 | pr_err("Could not get registers for a80-ahb-clk: %s\n", | ||
223 | node->name); | ||
224 | return; | ||
225 | } | ||
226 | |||
227 | sunxi_factors_register(node, &sun9i_a80_ahb_data, | ||
228 | &sun9i_a80_ahb_lock, reg); | ||
198 | } | 229 | } |
199 | CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup); | 230 | CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup); |
200 | 231 | ||
@@ -210,7 +241,17 @@ static DEFINE_SPINLOCK(sun9i_a80_apb0_lock); | |||
210 | 241 | ||
211 | static void __init sun9i_a80_apb0_setup(struct device_node *node) | 242 | static void __init sun9i_a80_apb0_setup(struct device_node *node) |
212 | { | 243 | { |
213 | sunxi_factors_register(node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock); | 244 | void __iomem *reg; |
245 | |||
246 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
247 | if (!reg) { | ||
248 | pr_err("Could not get registers for a80-apb0-clk: %s\n", | ||
249 | node->name); | ||
250 | return; | ||
251 | } | ||
252 | |||
253 | sunxi_factors_register(node, &sun9i_a80_apb0_data, | ||
254 | &sun9i_a80_apb0_lock, reg); | ||
214 | } | 255 | } |
215 | CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup); | 256 | CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup); |
216 | 257 | ||
@@ -266,6 +307,16 @@ static DEFINE_SPINLOCK(sun9i_a80_apb1_lock); | |||
266 | 307 | ||
267 | static void __init sun9i_a80_apb1_setup(struct device_node *node) | 308 | static void __init sun9i_a80_apb1_setup(struct device_node *node) |
268 | { | 309 | { |
269 | sunxi_factors_register(node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock); | 310 | void __iomem *reg; |
311 | |||
312 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
313 | if (!reg) { | ||
314 | pr_err("Could not get registers for a80-apb1-clk: %s\n", | ||
315 | node->name); | ||
316 | return; | ||
317 | } | ||
318 | |||
319 | sunxi_factors_register(node, &sun9i_a80_apb1_data, | ||
320 | &sun9i_a80_apb1_lock, reg); | ||
270 | } | 321 | } |
271 | CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup); | 322 | CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup); |
diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c new file mode 100644 index 000000000000..710c273648d7 --- /dev/null +++ b/drivers/clk/sunxi/clk-sun9i-mmc.c | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Chen-Yu Tsai | ||
3 | * | ||
4 | * Chen-Yu Tsai <wens@csie.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk-provider.h> | ||
18 | #include <linux/clkdev.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <linux/of_device.h> | ||
22 | #include <linux/reset.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/reset-controller.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | |||
27 | #define SUN9I_MMC_WIDTH 4 | ||
28 | |||
29 | #define SUN9I_MMC_GATE_BIT 16 | ||
30 | #define SUN9I_MMC_RESET_BIT 18 | ||
31 | |||
32 | struct sun9i_mmc_clk_data { | ||
33 | spinlock_t lock; | ||
34 | void __iomem *membase; | ||
35 | struct clk *clk; | ||
36 | struct reset_control *reset; | ||
37 | struct clk_onecell_data clk_data; | ||
38 | struct reset_controller_dev rcdev; | ||
39 | }; | ||
40 | |||
41 | static int sun9i_mmc_reset_assert(struct reset_controller_dev *rcdev, | ||
42 | unsigned long id) | ||
43 | { | ||
44 | struct sun9i_mmc_clk_data *data = container_of(rcdev, | ||
45 | struct sun9i_mmc_clk_data, | ||
46 | rcdev); | ||
47 | unsigned long flags; | ||
48 | void __iomem *reg = data->membase + SUN9I_MMC_WIDTH * id; | ||
49 | u32 val; | ||
50 | |||
51 | clk_prepare_enable(data->clk); | ||
52 | spin_lock_irqsave(&data->lock, flags); | ||
53 | |||
54 | val = readl(reg); | ||
55 | writel(val & ~BIT(SUN9I_MMC_RESET_BIT), reg); | ||
56 | |||
57 | spin_unlock_irqrestore(&data->lock, flags); | ||
58 | clk_disable_unprepare(data->clk); | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int sun9i_mmc_reset_deassert(struct reset_controller_dev *rcdev, | ||
64 | unsigned long id) | ||
65 | { | ||
66 | struct sun9i_mmc_clk_data *data = container_of(rcdev, | ||
67 | struct sun9i_mmc_clk_data, | ||
68 | rcdev); | ||
69 | unsigned long flags; | ||
70 | void __iomem *reg = data->membase + SUN9I_MMC_WIDTH * id; | ||
71 | u32 val; | ||
72 | |||
73 | clk_prepare_enable(data->clk); | ||
74 | spin_lock_irqsave(&data->lock, flags); | ||
75 | |||
76 | val = readl(reg); | ||
77 | writel(val | BIT(SUN9I_MMC_RESET_BIT), reg); | ||
78 | |||
79 | spin_unlock_irqrestore(&data->lock, flags); | ||
80 | clk_disable_unprepare(data->clk); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static struct reset_control_ops sun9i_mmc_reset_ops = { | ||
86 | .assert = sun9i_mmc_reset_assert, | ||
87 | .deassert = sun9i_mmc_reset_deassert, | ||
88 | }; | ||
89 | |||
90 | static int sun9i_a80_mmc_config_clk_probe(struct platform_device *pdev) | ||
91 | { | ||
92 | struct device_node *np = pdev->dev.of_node; | ||
93 | struct sun9i_mmc_clk_data *data; | ||
94 | struct clk_onecell_data *clk_data; | ||
95 | const char *clk_name = np->name; | ||
96 | const char *clk_parent; | ||
97 | struct resource *r; | ||
98 | int count, i, ret; | ||
99 | |||
100 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
101 | if (!data) | ||
102 | return -ENOMEM; | ||
103 | |||
104 | spin_lock_init(&data->lock); | ||
105 | |||
106 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
107 | /* one clock/reset pair per word */ | ||
108 | count = DIV_ROUND_UP((r->end - r->start + 1), SUN9I_MMC_WIDTH); | ||
109 | data->membase = devm_ioremap_resource(&pdev->dev, r); | ||
110 | if (IS_ERR(data->membase)) | ||
111 | return PTR_ERR(data->membase); | ||
112 | |||
113 | clk_data = &data->clk_data; | ||
114 | clk_data->clk_num = count; | ||
115 | clk_data->clks = devm_kcalloc(&pdev->dev, count, sizeof(struct clk *), | ||
116 | GFP_KERNEL); | ||
117 | if (!clk_data->clks) | ||
118 | return -ENOMEM; | ||
119 | |||
120 | data->clk = devm_clk_get(&pdev->dev, NULL); | ||
121 | if (IS_ERR(data->clk)) { | ||
122 | dev_err(&pdev->dev, "Could not get clock\n"); | ||
123 | return PTR_ERR(data->clk); | ||
124 | } | ||
125 | |||
126 | data->reset = devm_reset_control_get(&pdev->dev, NULL); | ||
127 | if (IS_ERR(data->reset)) { | ||
128 | dev_err(&pdev->dev, "Could not get reset control\n"); | ||
129 | return PTR_ERR(data->reset); | ||
130 | } | ||
131 | |||
132 | ret = reset_control_deassert(data->reset); | ||
133 | if (ret) { | ||
134 | dev_err(&pdev->dev, "Reset deassert err %d\n", ret); | ||
135 | return ret; | ||
136 | } | ||
137 | |||
138 | clk_parent = __clk_get_name(data->clk); | ||
139 | for (i = 0; i < count; i++) { | ||
140 | of_property_read_string_index(np, "clock-output-names", | ||
141 | i, &clk_name); | ||
142 | |||
143 | clk_data->clks[i] = clk_register_gate(&pdev->dev, clk_name, | ||
144 | clk_parent, 0, | ||
145 | data->membase + SUN9I_MMC_WIDTH * i, | ||
146 | SUN9I_MMC_GATE_BIT, 0, | ||
147 | &data->lock); | ||
148 | |||
149 | if (IS_ERR(clk_data->clks[i])) { | ||
150 | ret = PTR_ERR(clk_data->clks[i]); | ||
151 | goto err_clk_register; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); | ||
156 | if (ret) | ||
157 | goto err_clk_provider; | ||
158 | |||
159 | data->rcdev.owner = THIS_MODULE; | ||
160 | data->rcdev.nr_resets = count; | ||
161 | data->rcdev.ops = &sun9i_mmc_reset_ops; | ||
162 | data->rcdev.of_node = pdev->dev.of_node; | ||
163 | |||
164 | ret = reset_controller_register(&data->rcdev); | ||
165 | if (ret) | ||
166 | goto err_rc_reg; | ||
167 | |||
168 | platform_set_drvdata(pdev, data); | ||
169 | |||
170 | return 0; | ||
171 | |||
172 | err_rc_reg: | ||
173 | of_clk_del_provider(np); | ||
174 | |||
175 | err_clk_provider: | ||
176 | for (i = 0; i < count; i++) | ||
177 | clk_unregister(clk_data->clks[i]); | ||
178 | |||
179 | err_clk_register: | ||
180 | reset_control_assert(data->reset); | ||
181 | |||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | static int sun9i_a80_mmc_config_clk_remove(struct platform_device *pdev) | ||
186 | { | ||
187 | struct device_node *np = pdev->dev.of_node; | ||
188 | struct sun9i_mmc_clk_data *data = platform_get_drvdata(pdev); | ||
189 | struct clk_onecell_data *clk_data = &data->clk_data; | ||
190 | int i; | ||
191 | |||
192 | reset_controller_unregister(&data->rcdev); | ||
193 | of_clk_del_provider(np); | ||
194 | for (i = 0; i < clk_data->clk_num; i++) | ||
195 | clk_unregister(clk_data->clks[i]); | ||
196 | |||
197 | reset_control_assert(data->reset); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static const struct of_device_id sun9i_a80_mmc_config_clk_dt_ids[] = { | ||
203 | { .compatible = "allwinner,sun9i-a80-mmc-config-clk" }, | ||
204 | { /* sentinel */ } | ||
205 | }; | ||
206 | |||
207 | static struct platform_driver sun9i_a80_mmc_config_clk_driver = { | ||
208 | .driver = { | ||
209 | .name = "sun9i-a80-mmc-config-clk", | ||
210 | .of_match_table = sun9i_a80_mmc_config_clk_dt_ids, | ||
211 | }, | ||
212 | .probe = sun9i_a80_mmc_config_clk_probe, | ||
213 | .remove = sun9i_a80_mmc_config_clk_remove, | ||
214 | }; | ||
215 | module_platform_driver(sun9i_a80_mmc_config_clk_driver); | ||
216 | |||
217 | MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); | ||
218 | MODULE_DESCRIPTION("Allwinner A80 MMC clock/reset Driver"); | ||
219 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 570202582dcf..9b79f8907cc5 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
@@ -20,11 +20,219 @@ | |||
20 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
21 | #include <linux/reset-controller.h> | 21 | #include <linux/reset-controller.h> |
22 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
23 | #include <linux/log2.h> | ||
23 | 24 | ||
24 | #include "clk-factors.h" | 25 | #include "clk-factors.h" |
25 | 26 | ||
26 | static DEFINE_SPINLOCK(clk_lock); | 27 | static DEFINE_SPINLOCK(clk_lock); |
27 | 28 | ||
29 | /** | ||
30 | * sun6i_a31_ahb1_clk_setup() - Setup function for a31 ahb1 composite clk | ||
31 | */ | ||
32 | |||
33 | #define SUN6I_AHB1_MAX_PARENTS 4 | ||
34 | #define SUN6I_AHB1_MUX_PARENT_PLL6 3 | ||
35 | #define SUN6I_AHB1_MUX_SHIFT 12 | ||
36 | /* un-shifted mask is what mux_clk expects */ | ||
37 | #define SUN6I_AHB1_MUX_MASK 0x3 | ||
38 | #define SUN6I_AHB1_MUX_GET_PARENT(reg) ((reg >> SUN6I_AHB1_MUX_SHIFT) & \ | ||
39 | SUN6I_AHB1_MUX_MASK) | ||
40 | |||
41 | #define SUN6I_AHB1_DIV_SHIFT 4 | ||
42 | #define SUN6I_AHB1_DIV_MASK (0x3 << SUN6I_AHB1_DIV_SHIFT) | ||
43 | #define SUN6I_AHB1_DIV_GET(reg) ((reg & SUN6I_AHB1_DIV_MASK) >> \ | ||
44 | SUN6I_AHB1_DIV_SHIFT) | ||
45 | #define SUN6I_AHB1_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_DIV_MASK) | \ | ||
46 | (div << SUN6I_AHB1_DIV_SHIFT)) | ||
47 | #define SUN6I_AHB1_PLL6_DIV_SHIFT 6 | ||
48 | #define SUN6I_AHB1_PLL6_DIV_MASK (0x3 << SUN6I_AHB1_PLL6_DIV_SHIFT) | ||
49 | #define SUN6I_AHB1_PLL6_DIV_GET(reg) ((reg & SUN6I_AHB1_PLL6_DIV_MASK) >> \ | ||
50 | SUN6I_AHB1_PLL6_DIV_SHIFT) | ||
51 | #define SUN6I_AHB1_PLL6_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_PLL6_DIV_MASK) | \ | ||
52 | (div << SUN6I_AHB1_PLL6_DIV_SHIFT)) | ||
53 | |||
54 | struct sun6i_ahb1_clk { | ||
55 | struct clk_hw hw; | ||
56 | void __iomem *reg; | ||
57 | }; | ||
58 | |||
59 | #define to_sun6i_ahb1_clk(_hw) container_of(_hw, struct sun6i_ahb1_clk, hw) | ||
60 | |||
61 | static unsigned long sun6i_ahb1_clk_recalc_rate(struct clk_hw *hw, | ||
62 | unsigned long parent_rate) | ||
63 | { | ||
64 | struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw); | ||
65 | unsigned long rate; | ||
66 | u32 reg; | ||
67 | |||
68 | /* Fetch the register value */ | ||
69 | reg = readl(ahb1->reg); | ||
70 | |||
71 | /* apply pre-divider first if parent is pll6 */ | ||
72 | if (SUN6I_AHB1_MUX_GET_PARENT(reg) == SUN6I_AHB1_MUX_PARENT_PLL6) | ||
73 | parent_rate /= SUN6I_AHB1_PLL6_DIV_GET(reg) + 1; | ||
74 | |||
75 | /* clk divider */ | ||
76 | rate = parent_rate >> SUN6I_AHB1_DIV_GET(reg); | ||
77 | |||
78 | return rate; | ||
79 | } | ||
80 | |||
81 | static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp, | ||
82 | u8 parent, unsigned long parent_rate) | ||
83 | { | ||
84 | u8 div, calcp, calcm = 1; | ||
85 | |||
86 | /* | ||
87 | * clock can only divide, so we will never be able to achieve | ||
88 | * frequencies higher than the parent frequency | ||
89 | */ | ||
90 | if (parent_rate && rate > parent_rate) | ||
91 | rate = parent_rate; | ||
92 | |||
93 | div = DIV_ROUND_UP(parent_rate, rate); | ||
94 | |||
95 | /* calculate pre-divider if parent is pll6 */ | ||
96 | if (parent == SUN6I_AHB1_MUX_PARENT_PLL6) { | ||
97 | if (div < 4) | ||
98 | calcp = 0; | ||
99 | else if (div / 2 < 4) | ||
100 | calcp = 1; | ||
101 | else if (div / 4 < 4) | ||
102 | calcp = 2; | ||
103 | else | ||
104 | calcp = 3; | ||
105 | |||
106 | calcm = DIV_ROUND_UP(div, 1 << calcp); | ||
107 | } else { | ||
108 | calcp = __roundup_pow_of_two(div); | ||
109 | calcp = calcp > 3 ? 3 : calcp; | ||
110 | } | ||
111 | |||
112 | /* we were asked to pass back divider values */ | ||
113 | if (divp) { | ||
114 | *divp = calcp; | ||
115 | *pre_divp = calcm - 1; | ||
116 | } | ||
117 | |||
118 | return (parent_rate / calcm) >> calcp; | ||
119 | } | ||
120 | |||
121 | static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate, | ||
122 | unsigned long *best_parent_rate, | ||
123 | struct clk_hw **best_parent_clk) | ||
124 | { | ||
125 | struct clk *clk = hw->clk, *parent, *best_parent = NULL; | ||
126 | int i, num_parents; | ||
127 | unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0; | ||
128 | |||
129 | /* find the parent that can help provide the fastest rate <= rate */ | ||
130 | num_parents = __clk_get_num_parents(clk); | ||
131 | for (i = 0; i < num_parents; i++) { | ||
132 | parent = clk_get_parent_by_index(clk, i); | ||
133 | if (!parent) | ||
134 | continue; | ||
135 | if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT) | ||
136 | parent_rate = __clk_round_rate(parent, rate); | ||
137 | else | ||
138 | parent_rate = __clk_get_rate(parent); | ||
139 | |||
140 | child_rate = sun6i_ahb1_clk_round(rate, NULL, NULL, i, | ||
141 | parent_rate); | ||
142 | |||
143 | if (child_rate <= rate && child_rate > best_child_rate) { | ||
144 | best_parent = parent; | ||
145 | best = parent_rate; | ||
146 | best_child_rate = child_rate; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | if (best_parent) | ||
151 | *best_parent_clk = __clk_get_hw(best_parent); | ||
152 | *best_parent_rate = best; | ||
153 | |||
154 | return best_child_rate; | ||
155 | } | ||
156 | |||
157 | static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
158 | unsigned long parent_rate) | ||
159 | { | ||
160 | struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw); | ||
161 | unsigned long flags; | ||
162 | u8 div, pre_div, parent; | ||
163 | u32 reg; | ||
164 | |||
165 | spin_lock_irqsave(&clk_lock, flags); | ||
166 | |||
167 | reg = readl(ahb1->reg); | ||
168 | |||
169 | /* need to know which parent is used to apply pre-divider */ | ||
170 | parent = SUN6I_AHB1_MUX_GET_PARENT(reg); | ||
171 | sun6i_ahb1_clk_round(rate, &div, &pre_div, parent, parent_rate); | ||
172 | |||
173 | reg = SUN6I_AHB1_DIV_SET(reg, div); | ||
174 | reg = SUN6I_AHB1_PLL6_DIV_SET(reg, pre_div); | ||
175 | writel(reg, ahb1->reg); | ||
176 | |||
177 | spin_unlock_irqrestore(&clk_lock, flags); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static const struct clk_ops sun6i_ahb1_clk_ops = { | ||
183 | .determine_rate = sun6i_ahb1_clk_determine_rate, | ||
184 | .recalc_rate = sun6i_ahb1_clk_recalc_rate, | ||
185 | .set_rate = sun6i_ahb1_clk_set_rate, | ||
186 | }; | ||
187 | |||
188 | static void __init sun6i_ahb1_clk_setup(struct device_node *node) | ||
189 | { | ||
190 | struct clk *clk; | ||
191 | struct sun6i_ahb1_clk *ahb1; | ||
192 | struct clk_mux *mux; | ||
193 | const char *clk_name = node->name; | ||
194 | const char *parents[SUN6I_AHB1_MAX_PARENTS]; | ||
195 | void __iomem *reg; | ||
196 | int i = 0; | ||
197 | |||
198 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
199 | |||
200 | /* we have a mux, we will have >1 parents */ | ||
201 | while (i < SUN6I_AHB1_MAX_PARENTS && | ||
202 | (parents[i] = of_clk_get_parent_name(node, i)) != NULL) | ||
203 | i++; | ||
204 | |||
205 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
206 | |||
207 | ahb1 = kzalloc(sizeof(struct sun6i_ahb1_clk), GFP_KERNEL); | ||
208 | if (!ahb1) | ||
209 | return; | ||
210 | |||
211 | mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); | ||
212 | if (!mux) { | ||
213 | kfree(ahb1); | ||
214 | return; | ||
215 | } | ||
216 | |||
217 | /* set up clock properties */ | ||
218 | mux->reg = reg; | ||
219 | mux->shift = SUN6I_AHB1_MUX_SHIFT; | ||
220 | mux->mask = SUN6I_AHB1_MUX_MASK; | ||
221 | mux->lock = &clk_lock; | ||
222 | ahb1->reg = reg; | ||
223 | |||
224 | clk = clk_register_composite(NULL, clk_name, parents, i, | ||
225 | &mux->hw, &clk_mux_ops, | ||
226 | &ahb1->hw, &sun6i_ahb1_clk_ops, | ||
227 | NULL, NULL, 0); | ||
228 | |||
229 | if (!IS_ERR(clk)) { | ||
230 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
231 | clk_register_clkdev(clk, clk_name, NULL); | ||
232 | } | ||
233 | } | ||
234 | CLK_OF_DECLARE(sun6i_a31_ahb1, "allwinner,sun6i-a31-ahb1-clk", sun6i_ahb1_clk_setup); | ||
235 | |||
28 | /* Maximum number of parents our clocks have */ | 236 | /* Maximum number of parents our clocks have */ |
29 | #define SUNXI_MAX_PARENTS 5 | 237 | #define SUNXI_MAX_PARENTS 5 |
30 | 238 | ||
@@ -355,43 +563,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, | |||
355 | } | 563 | } |
356 | 564 | ||
357 | /** | 565 | /** |
358 | * clk_sunxi_mmc_phase_control() - configures MMC clock phase control | ||
359 | */ | ||
360 | |||
361 | void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output) | ||
362 | { | ||
363 | #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw) | ||
364 | #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) | ||
365 | |||
366 | struct clk_hw *hw = __clk_get_hw(clk); | ||
367 | struct clk_composite *composite = to_clk_composite(hw); | ||
368 | struct clk_hw *rate_hw = composite->rate_hw; | ||
369 | struct clk_factors *factors = to_clk_factors(rate_hw); | ||
370 | unsigned long flags = 0; | ||
371 | u32 reg; | ||
372 | |||
373 | if (factors->lock) | ||
374 | spin_lock_irqsave(factors->lock, flags); | ||
375 | |||
376 | reg = readl(factors->reg); | ||
377 | |||
378 | /* set sample clock phase control */ | ||
379 | reg &= ~(0x7 << 20); | ||
380 | reg |= ((sample & 0x7) << 20); | ||
381 | |||
382 | /* set output clock phase control */ | ||
383 | reg &= ~(0x7 << 8); | ||
384 | reg |= ((output & 0x7) << 8); | ||
385 | |||
386 | writel(reg, factors->reg); | ||
387 | |||
388 | if (factors->lock) | ||
389 | spin_unlock_irqrestore(factors->lock, flags); | ||
390 | } | ||
391 | EXPORT_SYMBOL(clk_sunxi_mmc_phase_control); | ||
392 | |||
393 | |||
394 | /** | ||
395 | * sunxi_factors_clk_setup() - Setup function for factor clocks | 566 | * sunxi_factors_clk_setup() - Setup function for factor clocks |
396 | */ | 567 | */ |
397 | 568 | ||
@@ -413,6 +584,7 @@ static struct clk_factors_config sun6i_a31_pll1_config = { | |||
413 | .kwidth = 2, | 584 | .kwidth = 2, |
414 | .mshift = 0, | 585 | .mshift = 0, |
415 | .mwidth = 2, | 586 | .mwidth = 2, |
587 | .n_start = 1, | ||
416 | }; | 588 | }; |
417 | 589 | ||
418 | static struct clk_factors_config sun8i_a23_pll1_config = { | 590 | static struct clk_factors_config sun8i_a23_pll1_config = { |
@@ -520,7 +692,16 @@ static const struct factors_data sun7i_a20_out_data __initconst = { | |||
520 | static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, | 692 | static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, |
521 | const struct factors_data *data) | 693 | const struct factors_data *data) |
522 | { | 694 | { |
523 | return sunxi_factors_register(node, data, &clk_lock); | 695 | void __iomem *reg; |
696 | |||
697 | reg = of_iomap(node, 0); | ||
698 | if (!reg) { | ||
699 | pr_err("Could not get registers for factors-clk: %s\n", | ||
700 | node->name); | ||
701 | return NULL; | ||
702 | } | ||
703 | |||
704 | return sunxi_factors_register(node, data, &clk_lock, reg); | ||
524 | } | 705 | } |
525 | 706 | ||
526 | 707 | ||
@@ -561,7 +742,7 @@ static void __init sunxi_mux_clk_setup(struct device_node *node, | |||
561 | of_property_read_string(node, "clock-output-names", &clk_name); | 742 | of_property_read_string(node, "clock-output-names", &clk_name); |
562 | 743 | ||
563 | clk = clk_register_mux(NULL, clk_name, parents, i, | 744 | clk = clk_register_mux(NULL, clk_name, parents, i, |
564 | CLK_SET_RATE_NO_REPARENT, reg, | 745 | CLK_SET_RATE_PARENT, reg, |
565 | data->shift, SUNXI_MUX_GATE_WIDTH, | 746 | data->shift, SUNXI_MUX_GATE_WIDTH, |
566 | 0, &clk_lock); | 747 | 0, &clk_lock); |
567 | 748 | ||
@@ -1217,7 +1398,6 @@ CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks); | |||
1217 | 1398 | ||
1218 | static const char *sun6i_critical_clocks[] __initdata = { | 1399 | static const char *sun6i_critical_clocks[] __initdata = { |
1219 | "cpu", | 1400 | "cpu", |
1220 | "ahb1_sdram", | ||
1221 | }; | 1401 | }; |
1222 | 1402 | ||
1223 | static void __init sun6i_init_clocks(struct device_node *node) | 1403 | static void __init sun6i_init_clocks(struct device_node *node) |
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 15cb8b7ffc34..c9a6fc0eaa35 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c | |||
@@ -21,8 +21,6 @@ | |||
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | 22 | ||
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/clk/sunxi.h> | ||
25 | |||
26 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
27 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
28 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
@@ -229,6 +227,8 @@ struct sunxi_mmc_host { | |||
229 | /* clock management */ | 227 | /* clock management */ |
230 | struct clk *clk_ahb; | 228 | struct clk *clk_ahb; |
231 | struct clk *clk_mmc; | 229 | struct clk *clk_mmc; |
230 | struct clk *clk_sample; | ||
231 | struct clk *clk_output; | ||
232 | 232 | ||
233 | /* irq */ | 233 | /* irq */ |
234 | spinlock_t lock; | 234 | spinlock_t lock; |
@@ -616,7 +616,7 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) | |||
616 | static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, | 616 | static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, |
617 | struct mmc_ios *ios) | 617 | struct mmc_ios *ios) |
618 | { | 618 | { |
619 | u32 rate, oclk_dly, rval, sclk_dly, src_clk; | 619 | u32 rate, oclk_dly, rval, sclk_dly; |
620 | int ret; | 620 | int ret; |
621 | 621 | ||
622 | rate = clk_round_rate(host->clk_mmc, ios->clock); | 622 | rate = clk_round_rate(host->clk_mmc, ios->clock); |
@@ -642,34 +642,31 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, | |||
642 | 642 | ||
643 | /* determine delays */ | 643 | /* determine delays */ |
644 | if (rate <= 400000) { | 644 | if (rate <= 400000) { |
645 | oclk_dly = 0; | 645 | oclk_dly = 180; |
646 | sclk_dly = 7; | 646 | sclk_dly = 42; |
647 | } else if (rate <= 25000000) { | 647 | } else if (rate <= 25000000) { |
648 | oclk_dly = 0; | 648 | oclk_dly = 180; |
649 | sclk_dly = 5; | 649 | sclk_dly = 75; |
650 | } else if (rate <= 50000000) { | 650 | } else if (rate <= 50000000) { |
651 | if (ios->timing == MMC_TIMING_UHS_DDR50) { | 651 | if (ios->timing == MMC_TIMING_UHS_DDR50) { |
652 | oclk_dly = 2; | 652 | oclk_dly = 60; |
653 | sclk_dly = 4; | 653 | sclk_dly = 120; |
654 | } else { | 654 | } else { |
655 | oclk_dly = 3; | 655 | oclk_dly = 90; |
656 | sclk_dly = 5; | 656 | sclk_dly = 150; |
657 | } | 657 | } |
658 | } else if (rate <= 100000000) { | ||
659 | oclk_dly = 6; | ||
660 | sclk_dly = 24; | ||
661 | } else if (rate <= 200000000) { | ||
662 | oclk_dly = 3; | ||
663 | sclk_dly = 12; | ||
658 | } else { | 664 | } else { |
659 | /* rate > 50000000 */ | 665 | return -EINVAL; |
660 | oclk_dly = 2; | ||
661 | sclk_dly = 4; | ||
662 | } | ||
663 | |||
664 | src_clk = clk_get_rate(clk_get_parent(host->clk_mmc)); | ||
665 | if (src_clk >= 300000000 && src_clk <= 400000000) { | ||
666 | if (oclk_dly) | ||
667 | oclk_dly--; | ||
668 | if (sclk_dly) | ||
669 | sclk_dly--; | ||
670 | } | 666 | } |
671 | 667 | ||
672 | clk_sunxi_mmc_phase_control(host->clk_mmc, sclk_dly, oclk_dly); | 668 | clk_set_phase(host->clk_sample, sclk_dly); |
669 | clk_set_phase(host->clk_output, oclk_dly); | ||
673 | 670 | ||
674 | return sunxi_mmc_oclk_onoff(host, 1); | 671 | return sunxi_mmc_oclk_onoff(host, 1); |
675 | } | 672 | } |
@@ -908,6 +905,18 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, | |||
908 | return PTR_ERR(host->clk_mmc); | 905 | return PTR_ERR(host->clk_mmc); |
909 | } | 906 | } |
910 | 907 | ||
908 | host->clk_output = devm_clk_get(&pdev->dev, "output"); | ||
909 | if (IS_ERR(host->clk_output)) { | ||
910 | dev_err(&pdev->dev, "Could not get output clock\n"); | ||
911 | return PTR_ERR(host->clk_output); | ||
912 | } | ||
913 | |||
914 | host->clk_sample = devm_clk_get(&pdev->dev, "sample"); | ||
915 | if (IS_ERR(host->clk_sample)) { | ||
916 | dev_err(&pdev->dev, "Could not get sample clock\n"); | ||
917 | return PTR_ERR(host->clk_sample); | ||
918 | } | ||
919 | |||
911 | host->reset = devm_reset_control_get(&pdev->dev, "ahb"); | 920 | host->reset = devm_reset_control_get(&pdev->dev, "ahb"); |
912 | 921 | ||
913 | ret = clk_prepare_enable(host->clk_ahb); | 922 | ret = clk_prepare_enable(host->clk_ahb); |
@@ -922,11 +931,23 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, | |||
922 | goto error_disable_clk_ahb; | 931 | goto error_disable_clk_ahb; |
923 | } | 932 | } |
924 | 933 | ||
934 | ret = clk_prepare_enable(host->clk_output); | ||
935 | if (ret) { | ||
936 | dev_err(&pdev->dev, "Enable output clk err %d\n", ret); | ||
937 | goto error_disable_clk_mmc; | ||
938 | } | ||
939 | |||
940 | ret = clk_prepare_enable(host->clk_sample); | ||
941 | if (ret) { | ||
942 | dev_err(&pdev->dev, "Enable sample clk err %d\n", ret); | ||
943 | goto error_disable_clk_output; | ||
944 | } | ||
945 | |||
925 | if (!IS_ERR(host->reset)) { | 946 | if (!IS_ERR(host->reset)) { |
926 | ret = reset_control_deassert(host->reset); | 947 | ret = reset_control_deassert(host->reset); |
927 | if (ret) { | 948 | if (ret) { |
928 | dev_err(&pdev->dev, "reset err %d\n", ret); | 949 | dev_err(&pdev->dev, "reset err %d\n", ret); |
929 | goto error_disable_clk_mmc; | 950 | goto error_disable_clk_sample; |
930 | } | 951 | } |
931 | } | 952 | } |
932 | 953 | ||
@@ -945,6 +966,10 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, | |||
945 | error_assert_reset: | 966 | error_assert_reset: |
946 | if (!IS_ERR(host->reset)) | 967 | if (!IS_ERR(host->reset)) |
947 | reset_control_assert(host->reset); | 968 | reset_control_assert(host->reset); |
969 | error_disable_clk_sample: | ||
970 | clk_disable_unprepare(host->clk_sample); | ||
971 | error_disable_clk_output: | ||
972 | clk_disable_unprepare(host->clk_output); | ||
948 | error_disable_clk_mmc: | 973 | error_disable_clk_mmc: |
949 | clk_disable_unprepare(host->clk_mmc); | 974 | clk_disable_unprepare(host->clk_mmc); |
950 | error_disable_clk_ahb: | 975 | error_disable_clk_ahb: |
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h deleted file mode 100644 index aed28c4451d9..000000000000 --- a/include/linux/clk/sunxi.h +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2013 - Hans de Goede <hdegoede@redhat.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef __LINUX_CLK_SUNXI_H_ | ||
16 | #define __LINUX_CLK_SUNXI_H_ | ||
17 | |||
18 | #include <linux/clk.h> | ||
19 | |||
20 | void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output); | ||
21 | |||
22 | #endif | ||