sunxi: initial 3.14 patchset
[openwrt/svn-archive/archive.git] / target / linux / sunxi / patches-3.14 / 185-clk-sunxi-add-a20-a31-gmac-clock.patch
1 From dd91dc4b9c55c8fa24738249214274442e2fcbd3 Mon Sep 17 00:00:00 2001
2 From: Chen-Yu Tsai <wens@csie.org>
3 Date: Mon, 10 Feb 2014 18:35:47 +0800
4 Subject: [PATCH] clk: sunxi: Add Allwinner A20/A31 GMAC clock unit
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 The Allwinner A20/A31 clock module controls the transmit clock source
10 and interface type of the GMAC ethernet controller. Model this as
11 a single clock for GMAC drivers to use.
12
13 Signed-off-by: Chen-Yu Tsai <wens@csie.org>
14 Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
15 Signed-off-by: Emilio López <emilio@elopez.com.ar>
16 ---
17 Documentation/devicetree/bindings/clock/sunxi.txt | 30 +++++++
18 drivers/clk/sunxi/clk-sunxi.c | 96 +++++++++++++++++++++++
19 2 files changed, 126 insertions(+)
20
21 diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
22 index c37c764..256a908 100644
23 --- a/Documentation/devicetree/bindings/clock/sunxi.txt
24 +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
25 @@ -38,6 +38,7 @@ Required properties:
26 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
27 "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
28 "allwinner,sun7i-a20-out-clk" - for the external output clocks
29 + "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
30 "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
31 "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
32
33 @@ -56,6 +57,9 @@ Required properties for all clocks:
34 And "allwinner,*-usb-clk" clocks also require:
35 - reset-cells : shall be set to 1
36
37 +For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
38 +dummy clocks at 25 MHz and 125 MHz, respectively. See example.
39 +
40 Clock consumers should specify the desired clocks they use with a
41 "clocks" phandle cell. Consumers that are using a gated clock should
42 provide an additional ID in their clock property. This ID is the
43 @@ -102,3 +106,29 @@ mmc0_clk: clk@01c20088 {
44 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
45 clock-output-names = "mmc0";
46 };
47 +
48 +mii_phy_tx_clk: clk@2 {
49 + #clock-cells = <0>;
50 + compatible = "fixed-clock";
51 + clock-frequency = <25000000>;
52 + clock-output-names = "mii_phy_tx";
53 +};
54 +
55 +gmac_int_tx_clk: clk@3 {
56 + #clock-cells = <0>;
57 + compatible = "fixed-clock";
58 + clock-frequency = <125000000>;
59 + clock-output-names = "gmac_int_tx";
60 +};
61 +
62 +gmac_clk: clk@01c20164 {
63 + #clock-cells = <0>;
64 + compatible = "allwinner,sun7i-a20-gmac-clk";
65 + reg = <0x01c20164 0x4>;
66 + /*
67 + * The first clock must be fixed at 25MHz;
68 + * the second clock must be fixed at 125MHz
69 + */
70 + clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
71 + clock-output-names = "gmac";
72 +};
73 diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
74 index d4cf297..335c987 100644
75 --- a/drivers/clk/sunxi/clk-sunxi.c
76 +++ b/drivers/clk/sunxi/clk-sunxi.c
77 @@ -411,6 +411,102 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
78
79
80 /**
81 + * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
82 + *
83 + * This clock looks something like this
84 + * ________________________
85 + * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
86 + * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
87 + * Ext. 125MHz RGMII TX clk >--|__divider__/ |
88 + * |________________________|
89 + *
90 + * The external 125 MHz reference is optional, i.e. GMAC can use its
91 + * internal TX clock just fine. The A31 GMAC clock module does not have
92 + * the divider controls for the external reference.
93 + *
94 + * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
95 + * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
96 + * select the appropriate source and gate/ungate the output to the PHY.
97 + *
98 + * Only the GMAC should use this clock. Altering the clock so that it doesn't
99 + * match the GMAC's operation parameters will result in the GMAC not being
100 + * able to send traffic out. The GMAC driver should set the clock rate and
101 + * enable/disable this clock to configure the required state. The clock
102 + * driver then responds by auto-reparenting the clock.
103 + */
104 +
105 +#define SUN7I_A20_GMAC_GPIT 2
106 +#define SUN7I_A20_GMAC_MASK 0x3
107 +#define SUN7I_A20_GMAC_PARENTS 2
108 +
109 +static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
110 +{
111 + struct clk *clk;
112 + struct clk_mux *mux;
113 + struct clk_gate *gate;
114 + const char *clk_name = node->name;
115 + const char *parents[SUN7I_A20_GMAC_PARENTS];
116 + void *reg;
117 +
118 + if (of_property_read_string(node, "clock-output-names", &clk_name))
119 + return;
120 +
121 + /* allocate mux and gate clock structs */
122 + mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
123 + if (!mux)
124 + return;
125 +
126 + gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
127 + if (!gate)
128 + goto free_mux;
129 +
130 + /* gmac clock requires exactly 2 parents */
131 + parents[0] = of_clk_get_parent_name(node, 0);
132 + parents[1] = of_clk_get_parent_name(node, 1);
133 + if (!parents[0] || !parents[1])
134 + goto free_gate;
135 +
136 + reg = of_iomap(node, 0);
137 + if (!reg)
138 + goto free_gate;
139 +
140 + /* set up gate and fixed rate properties */
141 + gate->reg = reg;
142 + gate->bit_idx = SUN7I_A20_GMAC_GPIT;
143 + gate->lock = &clk_lock;
144 + mux->reg = reg;
145 + mux->mask = SUN7I_A20_GMAC_MASK;
146 + mux->flags = CLK_MUX_INDEX_BIT;
147 + mux->lock = &clk_lock;
148 +
149 + clk = clk_register_composite(NULL, clk_name,
150 + parents, SUN7I_A20_GMAC_PARENTS,
151 + &mux->hw, &clk_mux_ops,
152 + NULL, NULL,
153 + &gate->hw, &clk_gate_ops,
154 + 0);
155 +
156 + if (IS_ERR(clk))
157 + goto iounmap_reg;
158 +
159 + of_clk_add_provider(node, of_clk_src_simple_get, clk);
160 + clk_register_clkdev(clk, clk_name, NULL);
161 +
162 + return;
163 +
164 +iounmap_reg:
165 + iounmap(reg);
166 +free_gate:
167 + kfree(gate);
168 +free_mux:
169 + kfree(mux);
170 +}
171 +CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
172 + sun7i_a20_gmac_clk_setup);
173 +
174 +
175 +
176 +/**
177 * sunxi_factors_clk_setup() - Setup function for factor clocks
178 */
179
180 --
181 2.0.3
182