aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/sunxi/patches-3.14/185-clk-sunxi-add-a20-a31-gmac-clock.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/sunxi/patches-3.14/185-clk-sunxi-add-a20-a31-gmac-clock.patch')
-rw-r--r--target/linux/sunxi/patches-3.14/185-clk-sunxi-add-a20-a31-gmac-clock.patch182
1 files changed, 182 insertions, 0 deletions
diff --git a/target/linux/sunxi/patches-3.14/185-clk-sunxi-add-a20-a31-gmac-clock.patch b/target/linux/sunxi/patches-3.14/185-clk-sunxi-add-a20-a31-gmac-clock.patch
new file mode 100644
index 0000000000..e105c25702
--- /dev/null
+++ b/target/linux/sunxi/patches-3.14/185-clk-sunxi-add-a20-a31-gmac-clock.patch
@@ -0,0 +1,182 @@
+From dd91dc4b9c55c8fa24738249214274442e2fcbd3 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 10 Feb 2014 18:35:47 +0800
+Subject: [PATCH] clk: sunxi: Add Allwinner A20/A31 GMAC clock unit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+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>
+---
+ Documentation/devicetree/bindings/clock/sunxi.txt | 30 +++++++
+ drivers/clk/sunxi/clk-sunxi.c | 96 +++++++++++++++++++++++
+ 2 files changed, 126 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
+index c37c764..256a908 100644
+--- a/Documentation/devicetree/bindings/clock/sunxi.txt
++++ b/Documentation/devicetree/bindings/clock/sunxi.txt
+@@ -38,6 +38,7 @@ Required properties:
+ "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
+ "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
+ "allwinner,sun7i-a20-out-clk" - for the external output clocks
++ "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
+ "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
+ "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
+
+@@ -56,6 +57,9 @@ Required properties for all clocks:
+ And "allwinner,*-usb-clk" clocks also require:
+ - reset-cells : shall be set to 1
+
++For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
++dummy clocks at 25 MHz and 125 MHz, respectively. See example.
++
+ Clock consumers should specify the desired clocks they use with a
+ "clocks" phandle cell. Consumers that are using a gated clock should
+ provide an additional ID in their clock property. This ID is the
+@@ -102,3 +106,29 @@ mmc0_clk: clk@01c20088 {
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ clock-output-names = "mmc0";
+ };
++
++mii_phy_tx_clk: clk@2 {
++ #clock-cells = <0>;
++ compatible = "fixed-clock";
++ clock-frequency = <25000000>;
++ clock-output-names = "mii_phy_tx";
++};
++
++gmac_int_tx_clk: clk@3 {
++ #clock-cells = <0>;
++ compatible = "fixed-clock";
++ clock-frequency = <125000000>;
++ clock-output-names = "gmac_int_tx";
++};
++
++gmac_clk: clk@01c20164 {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun7i-a20-gmac-clk";
++ reg = <0x01c20164 0x4>;
++ /*
++ * The first clock must be fixed at 25MHz;
++ * the second clock must be fixed at 125MHz
++ */
++ clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
++ clock-output-names = "gmac";
++};
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index d4cf297..335c987 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,
+
+
+ /**
++ * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
++ *
++ * This clock looks something like this
++ * ________________________
++ * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
++ * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
++ * Ext. 125MHz RGMII TX clk >--|__divider__/ |
++ * |________________________|
++ *
++ * The external 125 MHz reference is optional, i.e. GMAC can use its
++ * internal TX clock just fine. The A31 GMAC clock module does not have
++ * the divider controls for the external reference.
++ *
++ * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
++ * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
++ * select the appropriate source and gate/ungate the output to the PHY.
++ *
++ * Only the GMAC should use this clock. Altering the clock so that it doesn't
++ * match the GMAC's operation parameters will result in the GMAC not being
++ * able to send traffic out. The GMAC driver should set the clock rate and
++ * enable/disable this clock to configure the required state. The clock
++ * driver then responds by auto-reparenting the clock.
++ */
++
++#define SUN7I_A20_GMAC_GPIT 2
++#define SUN7I_A20_GMAC_MASK 0x3
++#define SUN7I_A20_GMAC_PARENTS 2
++
++static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
++{
++ struct clk *clk;
++ struct clk_mux *mux;
++ struct clk_gate *gate;
++ const char *clk_name = node->name;
++ const char *parents[SUN7I_A20_GMAC_PARENTS];
++ void *reg;
++
++ if (of_property_read_string(node, "clock-output-names", &clk_name))
++ return;
++
++ /* allocate mux and gate clock structs */
++ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
++ if (!mux)
++ return;
++
++ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
++ if (!gate)
++ goto free_mux;
++
++ /* gmac clock requires exactly 2 parents */
++ parents[0] = of_clk_get_parent_name(node, 0);
++ parents[1] = of_clk_get_parent_name(node, 1);
++ if (!parents[0] || !parents[1])
++ goto free_gate;
++
++ reg = of_iomap(node, 0);
++ if (!reg)
++ goto free_gate;
++
++ /* set up gate and fixed rate properties */
++ gate->reg = reg;
++ gate->bit_idx = SUN7I_A20_GMAC_GPIT;
++ gate->lock = &clk_lock;
++ mux->reg = reg;
++ mux->mask = SUN7I_A20_GMAC_MASK;
++ mux->flags = CLK_MUX_INDEX_BIT;
++ mux->lock = &clk_lock;
++
++ clk = clk_register_composite(NULL, clk_name,
++ parents, SUN7I_A20_GMAC_PARENTS,
++ &mux->hw, &clk_mux_ops,
++ NULL, NULL,
++ &gate->hw, &clk_gate_ops,
++ 0);
++
++ if (IS_ERR(clk))
++ goto iounmap_reg;
++
++ of_clk_add_provider(node, of_clk_src_simple_get, clk);
++ clk_register_clkdev(clk, clk_name, NULL);
++
++ return;
++
++iounmap_reg:
++ iounmap(reg);
++free_gate:
++ kfree(gate);
++free_mux:
++ kfree(mux);
++}
++CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
++ sun7i_a20_gmac_clk_setup);
++
++
++
++/**
+ * sunxi_factors_clk_setup() - Setup function for factor clocks
+ */
+
+--
+2.0.3
+