mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	Targets were build tested and patches are refreshed. Signed-off-by: Luka Perkov <luka@openwrt.org> SVN-Revision: 42463
		
			
				
	
	
		
			176 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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(+)
 | |
| 
 | |
| --- 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
 | |
|  
 | |
| @@ -55,6 +56,9 @@ Additionally, "allwinner,*-gates-clk" cl
 | |
|  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
 | |
| @@ -82,3 +86,29 @@ cpu: cpu@01c20054 {
 | |
|  	reg = <0x01c20054 0x4>;
 | |
|  	clocks = <&osc32k>, <&osc24M>, <&pll1>;
 | |
|  };
 | |
| +
 | |
| +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";
 | |
| +};
 | |
| --- 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(u3
 | |
|  
 | |
|  
 | |
|  /**
 | |
| + * 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
 | |
|   */
 | |
|  
 |