aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi.txt43
-rw-r--r--Documentation/devicetree/bindings/mmc/sunxi-mmc.txt8
-rw-r--r--arch/arm/boot/dts/sun4i-a10.dtsi72
-rw-r--r--arch/arm/boot/dts/sun5i-a10s.dtsi54
-rw-r--r--arch/arm/boot/dts/sun5i-a13.dtsi44
-rw-r--r--arch/arm/boot/dts/sun6i-a31.dtsi86
-rw-r--r--arch/arm/boot/dts/sun7i-a20.dtsi72
-rw-r--r--arch/arm/boot/dts/sun8i-a23.dtsi96
-rw-r--r--drivers/clk/sunxi/Makefile1
-rw-r--r--drivers/clk/sunxi/clk-factors.c10
-rw-r--r--drivers/clk/sunxi/clk-factors.h7
-rw-r--r--drivers/clk/sunxi/clk-mod0.c224
-rw-r--r--drivers/clk/sunxi/clk-sun8i-mbus.c13
-rw-r--r--drivers/clk/sunxi/clk-sun9i-core.c119
-rw-r--r--drivers/clk/sunxi/clk-sun9i-mmc.c219
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c260
-rw-r--r--drivers/mmc/host/sunxi-mmc.c73
-rw-r--r--include/linux/clk/sunxi.h22
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:
81And "allwinner,*-usb-clk" clocks also require: 85And "allwinner,*-usb-clk" clocks also require:
82- reset-cells : shall be set to 1 86- reset-cells : shall be set to 1
83 87
88The "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
84For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate 92For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
85dummy clocks at 25 MHz and 125 MHz, respectively. See example. 93dummy 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
95is the normal PLL6 output, or "pll6". The second output is rate doubled 103is the normal PLL6 output, or "pll6". The second output is rate doubled
96PLL6, or "pll6x2". 104PLL6, or "pll6x2".
97 105
106The "allwinner,*-mmc-clk" clocks have three different outputs: the
107main clock, with the ID 0, and the output and sample clocks, with the
108IDs 1 and 2, respectively.
109
110The "allwinner,sun9i-a80-mmc-config-clk" clock has one clock/reset output
111per mmc controller. The number of outputs is determined by the size of
112the address block, which is related to the overall mmc block.
113
98For example: 114For example:
99 115
100osc24M: clk@01c20050 { 116osc24M: clk@01c20050 {
@@ -138,11 +154,11 @@ cpu: cpu@01c20054 {
138}; 154};
139 155
140mmc0_clk: clk@01c20088 { 156mmc0_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
148mii_phy_tx_clk: clk@2 { 164mii_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
190mmc_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
10Required properties: 10Required 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
17Optional properties: 17Optional 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
8obj-y += clk-mod0.o 8obj-y += clk-mod0.o
9obj-y += clk-sun8i-mbus.o 9obj-y += clk-sun8i-mbus.o
10obj-y += clk-sun9i-core.o 10obj-y += clk-sun9i-core.o
11obj-y += clk-sun9i-mmc.o
11 12
12obj-$(CONFIG_MFD_SUN6I_PRCM) += \ 13obj-$(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
159struct clk * __init sunxi_factors_register(struct device_node *node, 159struct 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
39struct clk * __init sunxi_factors_register(struct device_node *node, 39struct 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
70static const struct factors_data sun4i_a10_mod0_data __initconst = { 71static 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
80static void __init sun4i_a10_mod0_setup(struct device_node *node) 81static 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}
84CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup); 98CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup);
85 99
100static 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
119static const struct of_device_id sun4i_a10_mod0_clk_dt_ids[] = {
120 { .compatible = "allwinner,sun4i-a10-mod0-clk" },
121 { /* sentinel */ }
122};
123
124static 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};
131module_platform_driver(sun4i_a10_mod0_clk_driver);
132
133static 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
141static 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}
155CLK_OF_DECLARE(sun9i_a80_mod0, "allwinner,sun9i-a80-mod0-clk", sun9i_a80_mod0_setup);
156
86static DEFINE_SPINLOCK(sun5i_a13_mbus_lock); 157static DEFINE_SPINLOCK(sun5i_a13_mbus_lock);
87 158
88static void __init sun5i_a13_mbus_setup(struct device_node *node) 159static 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}
96CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup); 177CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
97 178
98struct mmc_phase_data {
99 u8 offset;
100};
101
102struct mmc_phase { 179struct 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
222static 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 */
306static 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
259err_unmap: 372err_free_clks:
260 iounmap(phase->reg); 373 kfree(clk_data->clks);
261err_free: 374err_free_data:
262 kfree(phase); 375 kfree(clk_data);
263} 376}
264 377
378static DEFINE_SPINLOCK(sun4i_a10_mmc_lock);
265 379
266static struct mmc_phase_data mmc_output_clk = { 380static void __init sun4i_a10_mmc_setup(struct device_node *node)
267 .offset = 8,
268};
269
270static struct mmc_phase_data mmc_sample_clk = {
271 .offset = 20,
272};
273
274static 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}
278CLK_OF_DECLARE(sun4i_a10_mmc_output, "allwinner,sun4i-a10-mmc-output-clk", sun4i_a10_mmc_output_setup); 384CLK_OF_DECLARE(sun4i_a10_mmc, "allwinner,sun4i-a10-mmc-clk", sun4i_a10_mmc_setup);
385
386static DEFINE_SPINLOCK(sun9i_a80_mmc_lock);
279 387
280static void __init sun4i_a10_mmc_sample_setup(struct device_node *node) 388static 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}
284CLK_OF_DECLARE(sun4i_a10_mmc_sample, "allwinner,sun4i-a10-mmc-sample-clk", sun4i_a10_mmc_sample_setup); 392CLK_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
70static void __init sun8i_a23_mbus_setup(struct device_node *node) 70static 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
35static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate, 35static 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
73static struct clk_factors_config sun9i_a80_pll4_config = { 74static struct clk_factors_config sun9i_a80_pll4_config = {
@@ -89,7 +90,17 @@ static DEFINE_SPINLOCK(sun9i_a80_pll4_lock);
89 90
90static void __init sun9i_a80_pll4_setup(struct device_node *node) 91static 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}
94CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup); 105CLK_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
140static void __init sun9i_a80_gt_setup(struct device_node *node) 151static 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
195static void __init sun9i_a80_ahb_setup(struct device_node *node) 216static 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}
199CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup); 230CLK_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
211static void __init sun9i_a80_apb0_setup(struct device_node *node) 242static 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}
215CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup); 256CLK_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
267static void __init sun9i_a80_apb1_setup(struct device_node *node) 308static 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}
271CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup); 322CLK_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
32struct 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
41static 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
63static 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
85static struct reset_control_ops sun9i_mmc_reset_ops = {
86 .assert = sun9i_mmc_reset_assert,
87 .deassert = sun9i_mmc_reset_deassert,
88};
89
90static 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
172err_rc_reg:
173 of_clk_del_provider(np);
174
175err_clk_provider:
176 for (i = 0; i < count; i++)
177 clk_unregister(clk_data->clks[i]);
178
179err_clk_register:
180 reset_control_assert(data->reset);
181
182 return ret;
183}
184
185static 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
202static const struct of_device_id sun9i_a80_mmc_config_clk_dt_ids[] = {
203 { .compatible = "allwinner,sun9i-a80-mmc-config-clk" },
204 { /* sentinel */ }
205};
206
207static 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};
215module_platform_driver(sun9i_a80_mmc_config_clk_driver);
216
217MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
218MODULE_DESCRIPTION("Allwinner A80 MMC clock/reset Driver");
219MODULE_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
26static DEFINE_SPINLOCK(clk_lock); 27static 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
54struct 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
61static 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
81static 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
121static 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
157static 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
182static 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
188static 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}
234CLK_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
361void 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}
391EXPORT_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
418static struct clk_factors_config sun8i_a23_pll1_config = { 590static struct clk_factors_config sun8i_a23_pll1_config = {
@@ -520,7 +692,16 @@ static const struct factors_data sun7i_a20_out_data __initconst = {
520static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, 692static 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
1218static const char *sun6i_critical_clocks[] __initdata = { 1399static const char *sun6i_critical_clocks[] __initdata = {
1219 "cpu", 1400 "cpu",
1220 "ahb1_sdram",
1221}; 1401};
1222 1402
1223static void __init sun6i_init_clocks(struct device_node *node) 1403static 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)
616static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, 616static 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,
945error_assert_reset: 966error_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);
969error_disable_clk_sample:
970 clk_disable_unprepare(host->clk_sample);
971error_disable_clk_output:
972 clk_disable_unprepare(host->clk_output);
948error_disable_clk_mmc: 973error_disable_clk_mmc:
949 clk_disable_unprepare(host->clk_mmc); 974 clk_disable_unprepare(host->clk_mmc);
950error_disable_clk_ahb: 975error_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
20void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output);
21
22#endif