aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Turquette <mturquette@linaro.org>2014-03-19 15:14:11 -0400
committerMike Turquette <mturquette@linaro.org>2014-03-19 15:14:11 -0400
commitdf21f62bbb8d5e2e115cf331c2a74351e4e73153 (patch)
treee47c4abdcf97fc2be0a7983459aea42512025f0a
parent95bb9f515f5d8428a447b3afc131a99ddbdf4e8b (diff)
parentfd1b22f6fb3b31980b80505ac9d86521569ed2ee (diff)
Merge tag 'sunxi-clk-for-3.15' of https://bitbucket.org/emiliolopez/linux into clk-next-sunxi
Allwinner sunXi SoCs clock changes This adds support for the new, more correct clock node naming and gets the A10 compatibles in line with the rest of the other SoCs. It also adds support for the USB, GMAC and A31's PLL6 clocks. Some of these changes also require DT modifications that will be merged via arm-soc.
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi.txt102
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c290
2 files changed, 344 insertions, 48 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index c2cb7621ad2d..a5160d8cbb5f 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -6,37 +6,41 @@ This binding uses the common clock binding[1].
6 6
7Required properties: 7Required properties:
8- compatible : shall be one of the following: 8- compatible : shall be one of the following:
9 "allwinner,sun4i-osc-clk" - for a gatable oscillator 9 "allwinner,sun4i-a10-osc-clk" - for a gatable oscillator
10 "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4 10 "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
11 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 11 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
12 "allwinner,sun4i-pll5-clk" - for the PLL5 clock 12 "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
13 "allwinner,sun4i-pll6-clk" - for the PLL6 clock 13 "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
14 "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock 14 "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
15 "allwinner,sun4i-axi-clk" - for the AXI clock 15 "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
16 "allwinner,sun4i-axi-gates-clk" - for the AXI gates 16 "allwinner,sun4i-a10-axi-clk" - for the AXI clock
17 "allwinner,sun4i-ahb-clk" - for the AHB clock 17 "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
18 "allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10 18 "allwinner,sun4i-a10-ahb-clk" - for the AHB clock
19 "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
19 "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 20 "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
20 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s 21 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
21 "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 22 "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
22 "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 23 "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
23 "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 24 "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
24 "allwinner,sun4i-apb0-clk" - for the APB0 clock 25 "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
25 "allwinner,sun4i-apb0-gates-clk" - for the APB0 gates on A10 26 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
26 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 27 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
27 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s 28 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
28 "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 29 "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
29 "allwinner,sun4i-apb1-clk" - for the APB1 clock 30 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
30 "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing 31 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
31 "allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10 32 "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
32 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13 33 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
33 "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s 34 "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s
34 "allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31 35 "allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31
35 "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 36 "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
36 "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 37 "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
37 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 38 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
38 "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks 39 "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
39 "allwinner,sun7i-a20-out-clk" - for the external output clocks 40 "allwinner,sun7i-a20-out-clk" - for the external output clocks
41 "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
42 "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
43 "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
40 44
41Required properties for all clocks: 45Required properties for all clocks:
42- reg : shall be the control register address for the clock. 46- reg : shall be the control register address for the clock.
@@ -44,10 +48,17 @@ Required properties for all clocks:
44 multiplexed clocks, the list order must match the hardware 48 multiplexed clocks, the list order must match the hardware
45 programming order. 49 programming order.
46- #clock-cells : from common clock binding; shall be set to 0 except for 50- #clock-cells : from common clock binding; shall be set to 0 except for
47 "allwinner,*-gates-clk" where it shall be set to 1 51 "allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk" and
52 "allwinner,sun4i-pll6-clk" where it shall be set to 1
53- clock-output-names : shall be the corresponding names of the outputs.
54 If the clock module only has one output, the name shall be the
55 module name.
48 56
49Additionally, "allwinner,*-gates-clk" clocks require: 57And "allwinner,*-usb-clk" clocks also require:
50- clock-output-names : the corresponding gate names that the clock controls 58- reset-cells : shall be set to 1
59
60For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
61dummy clocks at 25 MHz and 125 MHz, respectively. See example.
51 62
52Clock consumers should specify the desired clocks they use with a 63Clock consumers should specify the desired clocks they use with a
53"clocks" phandle cell. Consumers that are using a gated clock should 64"clocks" phandle cell. Consumers that are using a gated clock should
@@ -56,23 +67,68 @@ offset of the bit controlling this particular gate in the register.
56 67
57For example: 68For example:
58 69
59osc24M: osc24M@01c20050 { 70osc24M: clk@01c20050 {
60 #clock-cells = <0>; 71 #clock-cells = <0>;
61 compatible = "allwinner,sun4i-osc-clk"; 72 compatible = "allwinner,sun4i-a10-osc-clk";
62 reg = <0x01c20050 0x4>; 73 reg = <0x01c20050 0x4>;
63 clocks = <&osc24M_fixed>; 74 clocks = <&osc24M_fixed>;
75 clock-output-names = "osc24M";
64}; 76};
65 77
66pll1: pll1@01c20000 { 78pll1: clk@01c20000 {
67 #clock-cells = <0>; 79 #clock-cells = <0>;
68 compatible = "allwinner,sun4i-pll1-clk"; 80 compatible = "allwinner,sun4i-a10-pll1-clk";
69 reg = <0x01c20000 0x4>; 81 reg = <0x01c20000 0x4>;
70 clocks = <&osc24M>; 82 clocks = <&osc24M>;
83 clock-output-names = "pll1";
84};
85
86pll5: clk@01c20020 {
87 #clock-cells = <1>;
88 compatible = "allwinner,sun4i-pll5-clk";
89 reg = <0x01c20020 0x4>;
90 clocks = <&osc24M>;
91 clock-output-names = "pll5_ddr", "pll5_other";
71}; 92};
72 93
73cpu: cpu@01c20054 { 94cpu: cpu@01c20054 {
74 #clock-cells = <0>; 95 #clock-cells = <0>;
75 compatible = "allwinner,sun4i-cpu-clk"; 96 compatible = "allwinner,sun4i-a10-cpu-clk";
76 reg = <0x01c20054 0x4>; 97 reg = <0x01c20054 0x4>;
77 clocks = <&osc32k>, <&osc24M>, <&pll1>; 98 clocks = <&osc32k>, <&osc24M>, <&pll1>;
99 clock-output-names = "cpu";
100};
101
102mmc0_clk: clk@01c20088 {
103 #clock-cells = <0>;
104 compatible = "allwinner,sun4i-mod0-clk";
105 reg = <0x01c20088 0x4>;
106 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
107 clock-output-names = "mmc0";
108};
109
110mii_phy_tx_clk: clk@2 {
111 #clock-cells = <0>;
112 compatible = "fixed-clock";
113 clock-frequency = <25000000>;
114 clock-output-names = "mii_phy_tx";
115};
116
117gmac_int_tx_clk: clk@3 {
118 #clock-cells = <0>;
119 compatible = "fixed-clock";
120 clock-frequency = <125000000>;
121 clock-output-names = "gmac_int_tx";
122};
123
124gmac_clk: clk@01c20164 {
125 #clock-cells = <0>;
126 compatible = "allwinner,sun7i-a20-gmac-clk";
127 reg = <0x01c20164 0x4>;
128 /*
129 * The first clock must be fixed at 25MHz;
130 * the second clock must be fixed at 125MHz
131 */
132 clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
133 clock-output-names = "gmac";
78}; 134};
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index abb6c5ac8a10..23baad9d934a 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -18,6 +18,7 @@
18#include <linux/clkdev.h> 18#include <linux/clkdev.h>
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_address.h> 20#include <linux/of_address.h>
21#include <linux/reset-controller.h>
21 22
22#include "clk-factors.h" 23#include "clk-factors.h"
23 24
@@ -51,6 +52,8 @@ static void __init sun4i_osc_clk_setup(struct device_node *node)
51 if (!gate) 52 if (!gate)
52 goto err_free_fixed; 53 goto err_free_fixed;
53 54
55 of_property_read_string(node, "clock-output-names", &clk_name);
56
54 /* set up gate and fixed rate properties */ 57 /* set up gate and fixed rate properties */
55 gate->reg = of_iomap(node, 0); 58 gate->reg = of_iomap(node, 0);
56 gate->bit_idx = SUNXI_OSC24M_GATE; 59 gate->bit_idx = SUNXI_OSC24M_GATE;
@@ -77,7 +80,7 @@ err_free_gate:
77err_free_fixed: 80err_free_fixed:
78 kfree(fixed); 81 kfree(fixed);
79} 82}
80CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup); 83CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup);
81 84
82 85
83 86
@@ -249,7 +252,38 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
249 *n = DIV_ROUND_UP(div, (*k+1)); 252 *n = DIV_ROUND_UP(div, (*k+1));
250} 253}
251 254
255/**
256 * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6
257 * PLL6 rate is calculated as follows
258 * rate = parent_rate * n * (k + 1) / 2
259 * parent_rate is always 24Mhz
260 */
261
262static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
263 u8 *n, u8 *k, u8 *m, u8 *p)
264{
265 u8 div;
266
267 /*
268 * We always have 24MHz / 2, so we can just say that our
269 * parent clock is 12MHz.
270 */
271 parent_rate = parent_rate / 2;
272
273 /* Normalize value to a parent_rate multiple (24M / 2) */
274 div = *freq / parent_rate;
275 *freq = parent_rate * div;
276
277 /* we were called to round the frequency, we can now return */
278 if (n == NULL)
279 return;
280
281 *k = div / 32;
282 if (*k > 3)
283 *k = 3;
252 284
285 *n = DIV_ROUND_UP(div, (*k+1));
286}
253 287
254/** 288/**
255 * sun4i_get_apb1_factors() - calculates m, p factors for APB1 289 * sun4i_get_apb1_factors() - calculates m, p factors for APB1
@@ -377,6 +411,102 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
377 411
378 412
379/** 413/**
414 * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
415 *
416 * This clock looks something like this
417 * ________________________
418 * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
419 * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
420 * Ext. 125MHz RGMII TX clk >--|__divider__/ |
421 * |________________________|
422 *
423 * The external 125 MHz reference is optional, i.e. GMAC can use its
424 * internal TX clock just fine. The A31 GMAC clock module does not have
425 * the divider controls for the external reference.
426 *
427 * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
428 * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
429 * select the appropriate source and gate/ungate the output to the PHY.
430 *
431 * Only the GMAC should use this clock. Altering the clock so that it doesn't
432 * match the GMAC's operation parameters will result in the GMAC not being
433 * able to send traffic out. The GMAC driver should set the clock rate and
434 * enable/disable this clock to configure the required state. The clock
435 * driver then responds by auto-reparenting the clock.
436 */
437
438#define SUN7I_A20_GMAC_GPIT 2
439#define SUN7I_A20_GMAC_MASK 0x3
440#define SUN7I_A20_GMAC_PARENTS 2
441
442static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
443{
444 struct clk *clk;
445 struct clk_mux *mux;
446 struct clk_gate *gate;
447 const char *clk_name = node->name;
448 const char *parents[SUN7I_A20_GMAC_PARENTS];
449 void *reg;
450
451 if (of_property_read_string(node, "clock-output-names", &clk_name))
452 return;
453
454 /* allocate mux and gate clock structs */
455 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
456 if (!mux)
457 return;
458
459 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
460 if (!gate)
461 goto free_mux;
462
463 /* gmac clock requires exactly 2 parents */
464 parents[0] = of_clk_get_parent_name(node, 0);
465 parents[1] = of_clk_get_parent_name(node, 1);
466 if (!parents[0] || !parents[1])
467 goto free_gate;
468
469 reg = of_iomap(node, 0);
470 if (!reg)
471 goto free_gate;
472
473 /* set up gate and fixed rate properties */
474 gate->reg = reg;
475 gate->bit_idx = SUN7I_A20_GMAC_GPIT;
476 gate->lock = &clk_lock;
477 mux->reg = reg;
478 mux->mask = SUN7I_A20_GMAC_MASK;
479 mux->flags = CLK_MUX_INDEX_BIT;
480 mux->lock = &clk_lock;
481
482 clk = clk_register_composite(NULL, clk_name,
483 parents, SUN7I_A20_GMAC_PARENTS,
484 &mux->hw, &clk_mux_ops,
485 NULL, NULL,
486 &gate->hw, &clk_gate_ops,
487 0);
488
489 if (IS_ERR(clk))
490 goto iounmap_reg;
491
492 of_clk_add_provider(node, of_clk_src_simple_get, clk);
493 clk_register_clkdev(clk, clk_name, NULL);
494
495 return;
496
497iounmap_reg:
498 iounmap(reg);
499free_gate:
500 kfree(gate);
501free_mux:
502 kfree(mux);
503}
504CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
505 sun7i_a20_gmac_clk_setup);
506
507
508
509/**
380 * sunxi_factors_clk_setup() - Setup function for factor clocks 510 * sunxi_factors_clk_setup() - Setup function for factor clocks
381 */ 511 */
382 512
@@ -387,6 +517,7 @@ struct factors_data {
387 int mux; 517 int mux;
388 struct clk_factors_config *table; 518 struct clk_factors_config *table;
389 void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); 519 void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
520 const char *name;
390}; 521};
391 522
392static struct clk_factors_config sun4i_pll1_config = { 523static struct clk_factors_config sun4i_pll1_config = {
@@ -416,6 +547,13 @@ static struct clk_factors_config sun4i_pll5_config = {
416 .kwidth = 2, 547 .kwidth = 2,
417}; 548};
418 549
550static struct clk_factors_config sun6i_a31_pll6_config = {
551 .nshift = 8,
552 .nwidth = 5,
553 .kshift = 4,
554 .kwidth = 2,
555};
556
419static struct clk_factors_config sun4i_apb1_config = { 557static struct clk_factors_config sun4i_apb1_config = {
420 .mshift = 0, 558 .mshift = 0,
421 .mwidth = 5, 559 .mwidth = 5,
@@ -455,6 +593,20 @@ static const struct factors_data sun4i_pll5_data __initconst = {
455 .enable = 31, 593 .enable = 31,
456 .table = &sun4i_pll5_config, 594 .table = &sun4i_pll5_config,
457 .getter = sun4i_get_pll5_factors, 595 .getter = sun4i_get_pll5_factors,
596 .name = "pll5",
597};
598
599static const struct factors_data sun4i_pll6_data __initconst = {
600 .enable = 31,
601 .table = &sun4i_pll5_config,
602 .getter = sun4i_get_pll5_factors,
603 .name = "pll6",
604};
605
606static const struct factors_data sun6i_a31_pll6_data __initconst = {
607 .enable = 31,
608 .table = &sun6i_a31_pll6_config,
609 .getter = sun6i_a31_get_pll6_factors,
458}; 610};
459 611
460static const struct factors_data sun4i_apb1_data __initconst = { 612static const struct factors_data sun4i_apb1_data __initconst = {
@@ -497,14 +649,14 @@ static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
497 (parents[i] = of_clk_get_parent_name(node, i)) != NULL) 649 (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
498 i++; 650 i++;
499 651
500 /* Nodes should be providing the name via clock-output-names 652 /*
501 * but originally our dts didn't, and so we used node->name. 653 * some factor clocks, such as pll5 and pll6, may have multiple
502 * The new, better nodes look like clk@deadbeef, so we pull the 654 * outputs, and have their name designated in factors_data
503 * name just in this case */ 655 */
504 if (!strcmp("clk", clk_name)) { 656 if (data->name)
505 of_property_read_string_index(node, "clock-output-names", 657 clk_name = data->name;
506 0, &clk_name); 658 else
507 } 659 of_property_read_string(node, "clock-output-names", &clk_name);
508 660
509 factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); 661 factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
510 if (!factors) 662 if (!factors)
@@ -601,6 +753,8 @@ static void __init sunxi_mux_clk_setup(struct device_node *node,
601 (parents[i] = of_clk_get_parent_name(node, i)) != NULL) 753 (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
602 i++; 754 i++;
603 755
756 of_property_read_string(node, "clock-output-names", &clk_name);
757
604 clk = clk_register_mux(NULL, clk_name, parents, i, 758 clk = clk_register_mux(NULL, clk_name, parents, i,
605 CLK_SET_RATE_NO_REPARENT, reg, 759 CLK_SET_RATE_NO_REPARENT, reg,
606 data->shift, SUNXI_MUX_GATE_WIDTH, 760 data->shift, SUNXI_MUX_GATE_WIDTH,
@@ -660,6 +814,8 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
660 814
661 clk_parent = of_clk_get_parent_name(node, 0); 815 clk_parent = of_clk_get_parent_name(node, 0);
662 816
817 of_property_read_string(node, "clock-output-names", &clk_name);
818
663 clk = clk_register_divider(NULL, clk_name, clk_parent, 0, 819 clk = clk_register_divider(NULL, clk_name, clk_parent, 0,
664 reg, data->shift, data->width, 820 reg, data->shift, data->width,
665 data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, 821 data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
@@ -673,6 +829,59 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
673 829
674 830
675/** 831/**
832 * sunxi_gates_reset... - reset bits in leaf gate clk registers handling
833 */
834
835struct gates_reset_data {
836 void __iomem *reg;
837 spinlock_t *lock;
838 struct reset_controller_dev rcdev;
839};
840
841static int sunxi_gates_reset_assert(struct reset_controller_dev *rcdev,
842 unsigned long id)
843{
844 struct gates_reset_data *data = container_of(rcdev,
845 struct gates_reset_data,
846 rcdev);
847 unsigned long flags;
848 u32 reg;
849
850 spin_lock_irqsave(data->lock, flags);
851
852 reg = readl(data->reg);
853 writel(reg & ~BIT(id), data->reg);
854
855 spin_unlock_irqrestore(data->lock, flags);
856
857 return 0;
858}
859
860static int sunxi_gates_reset_deassert(struct reset_controller_dev *rcdev,
861 unsigned long id)
862{
863 struct gates_reset_data *data = container_of(rcdev,
864 struct gates_reset_data,
865 rcdev);
866 unsigned long flags;
867 u32 reg;
868
869 spin_lock_irqsave(data->lock, flags);
870
871 reg = readl(data->reg);
872 writel(reg | BIT(id), data->reg);
873
874 spin_unlock_irqrestore(data->lock, flags);
875
876 return 0;
877}
878
879static struct reset_control_ops sunxi_gates_reset_ops = {
880 .assert = sunxi_gates_reset_assert,
881 .deassert = sunxi_gates_reset_deassert,
882};
883
884/**
676 * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks 885 * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
677 */ 886 */
678 887
@@ -680,6 +889,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
680 889
681struct gates_data { 890struct gates_data {
682 DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); 891 DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
892 u32 reset_mask;
683}; 893};
684 894
685static const struct gates_data sun4i_axi_gates_data __initconst = { 895static const struct gates_data sun4i_axi_gates_data __initconst = {
@@ -746,10 +956,21 @@ static const struct gates_data sun7i_a20_apb1_gates_data __initconst = {
746 .mask = { 0xff80ff }, 956 .mask = { 0xff80ff },
747}; 957};
748 958
959static const struct gates_data sun4i_a10_usb_gates_data __initconst = {
960 .mask = {0x1C0},
961 .reset_mask = 0x07,
962};
963
964static const struct gates_data sun5i_a13_usb_gates_data __initconst = {
965 .mask = {0x140},
966 .reset_mask = 0x03,
967};
968
749static void __init sunxi_gates_clk_setup(struct device_node *node, 969static void __init sunxi_gates_clk_setup(struct device_node *node,
750 struct gates_data *data) 970 struct gates_data *data)
751{ 971{
752 struct clk_onecell_data *clk_data; 972 struct clk_onecell_data *clk_data;
973 struct gates_reset_data *reset_data;
753 const char *clk_parent; 974 const char *clk_parent;
754 const char *clk_name; 975 const char *clk_name;
755 void *reg; 976 void *reg;
@@ -793,6 +1014,21 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
793 clk_data->clk_num = i; 1014 clk_data->clk_num = i;
794 1015
795 of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); 1016 of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
1017
1018 /* Register a reset controler for gates with reset bits */
1019 if (data->reset_mask == 0)
1020 return;
1021
1022 reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
1023 if (!reset_data)
1024 return;
1025
1026 reset_data->reg = reg;
1027 reset_data->lock = &clk_lock;
1028 reset_data->rcdev.nr_resets = __fls(data->reset_mask) + 1;
1029 reset_data->rcdev.ops = &sunxi_gates_reset_ops;
1030 reset_data->rcdev.of_node = node;
1031 reset_controller_register(&reset_data->rcdev);
796} 1032}
797 1033
798 1034
@@ -832,7 +1068,7 @@ static const struct divs_data pll5_divs_data __initconst = {
832}; 1068};
833 1069
834static const struct divs_data pll6_divs_data __initconst = { 1070static const struct divs_data pll6_divs_data __initconst = {
835 .factors = &sun4i_pll5_data, 1071 .factors = &sun4i_pll6_data,
836 .div = { 1072 .div = {
837 { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ 1073 { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
838 { .fixed = 2 }, /* P, other */ 1074 { .fixed = 2 }, /* P, other */
@@ -854,7 +1090,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
854 struct divs_data *data) 1090 struct divs_data *data)
855{ 1091{
856 struct clk_onecell_data *clk_data; 1092 struct clk_onecell_data *clk_data;
857 const char *parent = node->name; 1093 const char *parent;
858 const char *clk_name; 1094 const char *clk_name;
859 struct clk **clks, *pclk; 1095 struct clk **clks, *pclk;
860 struct clk_hw *gate_hw, *rate_hw; 1096 struct clk_hw *gate_hw, *rate_hw;
@@ -868,6 +1104,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
868 1104
869 /* Set up factor clock that we will be dividing */ 1105 /* Set up factor clock that we will be dividing */
870 pclk = sunxi_factors_clk_setup(node, data->factors); 1106 pclk = sunxi_factors_clk_setup(node, data->factors);
1107 parent = __clk_get_name(pclk);
871 1108
872 reg = of_iomap(node, 0); 1109 reg = of_iomap(node, 0);
873 1110
@@ -970,56 +1207,59 @@ free_clkdata:
970 1207
971/* Matches for factors clocks */ 1208/* Matches for factors clocks */
972static const struct of_device_id clk_factors_match[] __initconst = { 1209static const struct of_device_id clk_factors_match[] __initconst = {
973 {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, 1210 {.compatible = "allwinner,sun4i-a10-pll1-clk", .data = &sun4i_pll1_data,},
974 {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, 1211 {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
975 {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, 1212 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
976 {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,}, 1213 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
1214 {.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,},
977 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, 1215 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
978 {} 1216 {}
979}; 1217};
980 1218
981/* Matches for divider clocks */ 1219/* Matches for divider clocks */
982static const struct of_device_id clk_div_match[] __initconst = { 1220static const struct of_device_id clk_div_match[] __initconst = {
983 {.compatible = "allwinner,sun4i-axi-clk", .data = &sun4i_axi_data,}, 1221 {.compatible = "allwinner,sun4i-a10-axi-clk", .data = &sun4i_axi_data,},
984 {.compatible = "allwinner,sun4i-ahb-clk", .data = &sun4i_ahb_data,}, 1222 {.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,},
985 {.compatible = "allwinner,sun4i-apb0-clk", .data = &sun4i_apb0_data,}, 1223 {.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,},
986 {.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,}, 1224 {.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,},
987 {} 1225 {}
988}; 1226};
989 1227
990/* Matches for divided outputs */ 1228/* Matches for divided outputs */
991static const struct of_device_id clk_divs_match[] __initconst = { 1229static const struct of_device_id clk_divs_match[] __initconst = {
992 {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,}, 1230 {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,},
993 {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,}, 1231 {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,},
994 {} 1232 {}
995}; 1233};
996 1234
997/* Matches for mux clocks */ 1235/* Matches for mux clocks */
998static const struct of_device_id clk_mux_match[] __initconst = { 1236static const struct of_device_id clk_mux_match[] __initconst = {
999 {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,}, 1237 {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,},
1000 {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,}, 1238 {.compatible = "allwinner,sun4i-a10-apb1-mux-clk", .data = &sun4i_apb1_mux_data,},
1001 {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, 1239 {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
1002 {} 1240 {}
1003}; 1241};
1004 1242
1005/* Matches for gate clocks */ 1243/* Matches for gate clocks */
1006static const struct of_device_id clk_gates_match[] __initconst = { 1244static const struct of_device_id clk_gates_match[] __initconst = {
1007 {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,}, 1245 {.compatible = "allwinner,sun4i-a10-axi-gates-clk", .data = &sun4i_axi_gates_data,},
1008 {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,}, 1246 {.compatible = "allwinner,sun4i-a10-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
1009 {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,}, 1247 {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
1010 {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,}, 1248 {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
1011 {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, 1249 {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
1012 {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,}, 1250 {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
1013 {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, 1251 {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
1014 {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, 1252 {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
1015 {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, 1253 {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
1016 {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,}, 1254 {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,},
1017 {.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, 1255 {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
1018 {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, 1256 {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,},
1019 {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, 1257 {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
1020 {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, 1258 {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
1021 {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,}, 1259 {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
1022 {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, 1260 {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
1261 {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
1262 {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
1023 {} 1263 {}
1024}; 1264};
1025 1265