aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChen-Yu Tsai <wens@csie.org>2014-02-10 05:35:47 -0500
committerEmilio López <emilio@elopez.com.ar>2014-02-18 08:34:28 -0500
commite4c6d6c11bee5ff11feb837a0a76103b3eba252f (patch)
treede46fbc31e9fa56f85dcf2182a44d383fc7176da
parent92ef67c53ad92487c3c8de75e7940384c2edd793 (diff)
clk: sunxi: Add Allwinner A20/A31 GMAC clock unit
The Allwinner A20/A31 clock module controls the transmit clock source and interface type of the GMAC ethernet controller. Model this as a single clock for GMAC drivers to use. Signed-off-by: Chen-Yu Tsai <wens@csie.org> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Emilio López <emilio@elopez.com.ar>
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi.txt30
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c96
2 files changed, 126 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index c37c764cbbc5..256a9089f677 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -38,6 +38,7 @@ Required properties:
38 "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
39 "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks 39 "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
40 "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
41 "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 42 "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
42 "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 43 "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
43 44
@@ -56,6 +57,9 @@ Required properties for all clocks:
56And "allwinner,*-usb-clk" clocks also require: 57And "allwinner,*-usb-clk" clocks also require:
57- reset-cells : shall be set to 1 58- reset-cells : shall be set to 1
58 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.
62
59Clock consumers should specify the desired clocks they use with a 63Clock consumers should specify the desired clocks they use with a
60"clocks" phandle cell. Consumers that are using a gated clock should 64"clocks" phandle cell. Consumers that are using a gated clock should
61provide an additional ID in their clock property. This ID is the 65provide an additional ID in their clock property. This ID is the
@@ -102,3 +106,29 @@ mmc0_clk: clk@01c20088 {
102 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 106 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
103 clock-output-names = "mmc0"; 107 clock-output-names = "mmc0";
104}; 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";
134};
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index d4cf297e8fac..335c98721218 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -411,6 +411,102 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
411 411
412 412
413/** 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/**
414 * sunxi_factors_clk_setup() - Setup function for factor clocks 510 * sunxi_factors_clk_setup() - Setup function for factor clocks
415 */ 511 */
416 512