diff options
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.patch | 182 |
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 + |