clk: sunxi: Add muxable AHB clock to fix hstimer issues
Subsystems (4)
cover clk: sunxi: Add muxable AHB clock to fix hstimer issues
Hi everyone,
This series adds support for the muxable ahb clock on sun5/7i. The mux has inputs such as the axi clock, the cpu clock on sun5i, and pll6 with various dividers. The goal is to have ahb muxed to pll6, which should be a fixed rate albeit configurable clock. This fixes issues with cpufreq changing the cpu frequency, which would affect the hstimer clocked from ahb.
This series is a bit large, but should be included as a fix for 4.0.
Patch 1 adds driver support for the muxable ahb clock.
Patch 2 adds the "cpu" clock to the list of protected clocks, as now ahb might be muxed away, leaving cpu clock with no real users, and getting disabled.
Patch 3 rearranges the order in which different types of clocks are registered. Since our goal is to mux ahb (which is a factor clock) to pll6 (which is a divs clock) using clock provider assigned-clocks properties, we must register factor clocks first.
Patch 4 makes divs clocks explicitly specify in the driver which output is the parent clock, instead of always putting it in last. This is done to ensure DT bindings compatibility when we add outputs.
Patch 5 adds the new pll6/4 output, which is used on sun7i as an input to ahb mux.
Patch 6 updates the dtsi files with the new drivers.
The series is also available at https://github.com/wens/linux/commits/sun5i-ahb
Regards
ChenYu
Chen-Yu Tsai (6):
clk: sunxi: Add muxable ahb factors clock for sun5i and sun7i
clk: sunxi: Add "cpu" to list of protected clocks for sun5i
clk: sunxi: Register divs clocks before factor clocks
clk: sunxi: Make divs clocks specify which output is the parent clock
clk: sunxi: Add pll6 / 4 clock output to sun4i-a10-pll6
ARM: dts: sunxi: Update ahb clocks for sun5i and sun7i
Documentation/devicetree/bindings/clock/sunxi.txt | 1 + arch/arm/boot/dts/sun5i.dtsi | 10 ++- arch/arm/boot/dts/sun7i-a20.dtsi | 13 +++- drivers/clk/sunxi/clk-sunxi.c | 91 +++++++++++++++++++---- 4 files changed, 95 insertions(+), 20 deletions(-)
Signature · 1 line
2.1.4
PATCH 1/6 clk: sunxi: Add muxable ahb factors clock for sun5i and sun7i
The AHB clock on sun5i and sun7i are muxable divider clocks. Use a factors clock to support them.
--- Documentation/devicetree/bindings/clock/sunxi.txt | 1 + drivers/clk/sunxi/clk-sunxi.c | 52 +++++++++++++++++++++++ 2 files changed, 53 insertions(+)
Documentation/devicetree/bindings/clock/sunxi.txt +1 -0
@@ -20,6 +20,7 @@ Required properties: "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23 "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates "allwinner,sun4i-a10-ahb-clk" - for the AHB clock + "allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13 "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80 "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10 "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
drivers/clk/sunxi/clk-sunxi.c +52 -0
76 lines not on this page · raw message
Signature · 1 line
2.1.4
Maxime Ripard
AppliedPATCH 1/6 clk: sunxi: Add muxable ahb factors clock for sun5i and sun7i
Quoted 4 lines · Chen-Yu Tsai
The AHB clock on sun5i and sun7i are muxable divider clocks. Use a factors clock to support them.
Signed-off-by Chen-Yu Tsai <[email protected]>
Applied, thanks!
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150321/8c4bda2f/attachment.sig>
PATCH 2/6 clk: sunxi: Add "cpu" to list of protected clocks for sun5i
In reply to Chen-Yu TsaiNow that the ahb clock on sun5i/sun7i is muxable, ahb is no longer guaranteed to be a child of the cpu clock. Add the cpu clock to the list of protected clocks so it doesn't get disabled.
--- drivers/clk/sunxi/clk-sunxi.c | 1 + 1 file changed, 1 insertion(+)
drivers/clk/sunxi/clk-sunxi.c +1 -0
@@ -1349,6 +1349,7 @@ static void __init sun4i_a10_init_clocks(struct device_node *node)CLK_OF_DECLARE (sun4i_a10_clk_init,"allwinner,sun4i-a10" , sun4i_a10_init_clocks);static const char *sun5i_critical_clocks[]__initdata = { +"cpu" ,"pll5_ddr" ,"ahb_sdram" , };
Signature · 1 line
2.1.4
Maxime Ripard
AppliedPATCH 2/6 clk: sunxi: Add "cpu" to list of protected clocks for sun5i
Quoted 5 lines · Chen-Yu Tsai
Now that the ahb clock on sun5i/sun7i is muxable, ahb is no longer guaranteed to be a child of the cpu clock. Add the cpu clock to the list of protected clocks so it doesn't get disabled.
Signed-off-by Chen-Yu Tsai <[email protected]>
Applied, thanks!
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150321/14e20e5c/attachment-0001.sig>
PATCH 3/6 clk: sunxi: Register divs clocks before factor clocks
In reply to Chen-Yu TsaiWe want to reparent AHB clock to PLL6 on sun5i/sun7i using the assigned clocks properties. AHB is a factor clock, while PLL6 is a divs clock.
Register divs clocks before factor clocks so reparenting works. This is only needed because we do the reparenting on the clock provider.
The proper way to fix this is to split out all the old sunxi clocks into separate CLK_OF_DECLARE statements, like we are doing for sun9i.
--- drivers/clk/sunxi/clk-sunxi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/clk/sunxi/clk-sunxi.c +3 -3
@@ -1312,15 +1312,15 @@ static void __init sunxi_init_clocks(const char *clocks[], int nclocks) {unsigned int i; +/* Register divided output clocks */ +of_sunxi_table_clock_setup (clk_divs_match, sunxi_divs_clk_setup); +/* Register factor clocks */ of_sunxi_table_clock_setup (clk_factors_match, sunxi_factors_clk_setup);/* Register divider clocks */ of_sunxi_table_clock_setup (clk_div_match, sunxi_divider_clk_setup); -/* Register divided output clocks */ -of_sunxi_table_clock_setup (clk_divs_match, sunxi_divs_clk_setup); -/* Register mux clocks */ of_sunxi_table_clock_setup (clk_mux_match, sunxi_mux_clk_setup);
Signature · 1 line
2.1.4
Maxime Ripard
AppliedPATCH 3/6 clk: sunxi: Register divs clocks before factor clocks
Quoted 10 lines · Chen-Yu Tsai
We want to reparent AHB clock to PLL6 on sun5i/sun7i using the assigned clocks properties. AHB is a factor clock, while PLL6 is a divs clock.
Register divs clocks before factor clocks so reparenting works. This is only needed because we do the reparenting on the clock provider.
The proper way to fix this is to split out all the old sunxi clocks into separate
CLK_OF_DECLAREstatements, like we are doing for sun9i.Signed-off-by Chen-Yu Tsai <[email protected]>
Applied, thanks!
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150321/1586b51f/attachment.sig>
PATCH 4/6 clk: sunxi: Make divs clocks specify which output is the parent clock
In reply to Chen-Yu TsaiThe current sunxi clock driver has the parent of divs clocks as the last clock output of the clock node. This makes it rather difficult to add new outputs, such as fixed dividers, which were previously unknown.
This patch makes the divs clocks data structure specify which output is the parent clock, and updates all current divs clocks accordingly.
We can then add new outputs after the parent clocks, at least not breaking backward compatibility with regards to the devicetree bindings.
Also replace kzalloc with kcalloc in sunxi_divs_clk_setup().
--- drivers/clk/sunxi/clk-sunxi.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-)
drivers/clk/sunxi/clk-sunxi.c +19 -12
@@ -1046,13 +1046,14 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,* sunxi_divs_clk_setup() helper data */ -#define SUNXI_DIVS_MAX_QTY 2 +#define SUNXI_DIVS_MAX_QTY 4#define SUNXI_DIVISOR_WIDTH 2struct divs_data {const struct factors_data *factors;/* data for the factor clock */ -int ndivs;/* number of children */ +int ndivs;/* number of outputs */ struct { +u8 parent;/* is it the parent? (only one please) */ u8 fixed;/* is it a fixed divisor? if not... */ struct clk_div_table *table;/* is it a table based divisor? */ u8 shift;/* otherwise it's a normal divisor with this shift */
@@ -1075,23 +1076,26 @@ static const struct divs_data pll5_divs_data __initconst = { .div = { { .shift = 0, .pow = 0, }, /* M, DDR */ { .shift = 16, .pow = 1, }, /* P, other */ +/* No output for the parent */ } };static const struct divs_data pll6_divs_data__initconst = { .factors = &sun4i_pll6_data, - .ndivs =2 , + .ndivs =3 , .div = { { .shift =0 , .table = pll6_sata_tbl, .gate =14 },/* M, SATA */ { .fixed =2 },/* P, other */ + { .parent =1 },/* parent, 2x */ } };static const struct divs_data sun6i_a31_pll6_divs_data__initconst = { .factors = &sun6i_a31_pll6_data, - .ndivs =1 , + .ndivs =2 , .div = { { .fixed =2 },/* normal output */ + { .parent =1 },/* parent, 2x */ } };
@@ -1122,6 +1126,10 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,int ndivs =SUNXI_DIVS_MAX_QTY , i =0 ;int flags, clkflags; +/* if number of children known, use it */ +if (data->ndivs) + ndivs = data->ndivs; +/* Set up factor clock that we will be dividing */ pclk =sunxi_factors_clk_setup (node, data->factors); parent =__clk_get_name (pclk);
@@ -1132,7 +1140,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,if (!clk_data)return ; - clks =kzalloc ((SUNXI_DIVS_MAX_QTY +1 ) *sizeof (*clks),GFP_KERNEL ); + clks =kcalloc (ndivs,sizeof (*clks),GFP_KERNEL );if (!clks) goto free_clkdata;
@@ -1142,15 +1150,17 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,* our RAM clock! */ clkflags = !strcmp ("pll5" , parent) ?0 :CLK_SET_RATE_PARENT ; -/* if number of children known, use it */ -if (data->ndivs) - ndivs = data->ndivs; -for (i =0 ; i < ndivs; i++) {if (of_property_read_string_index (node,"clock-output-names" , i, &clk_name) !=0 )break ; +/* If this is the parent, just update clks and skip */ +if (data->div[i].parent) { + clk_data->clks[i] = pclk; +continue ; + } + gate_hw =NULL ; rate_hw =NULL ; rate_ops =NULL ;
@@ -1209,9 +1219,6 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,clk_register_clkdev (clks[i], clk_name,NULL ); } -/* The last clock available on the getter is the parent */ - clks[i++] = pclk; -/* Adjust to the real max */ clk_data->clk_num = i;
Signature · 1 line
2.1.4
PATCH 4/6 clk: sunxi: Make divs clocks specify which output is the parent clock
Quoted 26 lines · Chen-Yu Tsai
The current sunxi clock driver has the parent of divs clocks as the last clock output of the clock node. This makes it rather difficult to add new outputs, such as fixed dividers, which were previously unknown.
This patch makes the divs clocks data structure specify which output is the parent clock, and updates all current divs clocks accordingly.
We can then add new outputs after the parent clocks, at least not breaking backward compatibility with regards to the devicetree bindings.
Also replace kzalloc with kcalloc in
sunxi_divs_clk_setup().Signed-off-by Chen-Yu Tsai <[email protected]>--- drivers/clk/sunxi/clk-sunxi.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-)drivers/clk/sunxi/clk-sunxi.c +0
-0@@ -1046,13 +1046,14 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,* sunxi_divs_clk_setup() helper data */
drivers/clk/sunxi/clk-sunxi.c static void __init sunxi_gates_clk_setup(struct device_node *node, · line 1056
Quoted 10 lines
drivers/clk/sunxi/clk-sunxi.c +3
-2-#define SUNXI_DIVS_MAX_QTY 2 +#define SUNXI_DIVS_MAX_QTY 4#define SUNXI_DIVISOR_WIDTH 2struct divs_data {const struct factors_data *factors;/* data for the factor clock */ -int ndivs;/* number of children */ +int ndivs;/* number of outputs */ struct { +u8 parent;/* is it the parent? (only one please) */
I really don't get what this "parent" is about. Is it a clock passed through to the users.
Do we have even have users for these?
Thanks,
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150321/9cf76127/attachment.sig>
PATCH 4/6 clk: sunxi: Make divs clocks specify which output is the parent clock
Quoted 31 lines · Maxime Ripard
Quoted 30 lines · Chen-Yu Tsai
The current sunxi clock driver has the parent of divs clocks as the last clock output of the clock node. This makes it rather difficult to add new outputs, such as fixed dividers, which were previously unknown.
This patch makes the divs clocks data structure specify which output is the parent clock, and updates all current divs clocks accordingly.
We can then add new outputs after the parent clocks, at least not breaking backward compatibility with regards to the devicetree bindings.
Also replace kzalloc with kcalloc in
sunxi_divs_clk_setup().Signed-off-by Chen-Yu Tsai <[email protected]>--- drivers/clk/sunxi/clk-sunxi.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-)drivers/clk/sunxi/clk-sunxi.c +1
-1@@ -1046,13 +1046,14 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,* sunxi_divs_clk_setup() helper data */ -#define SUNXI_DIVS_MAX_QTY 2 +#define SUNXI_DIVS_MAX_QTY 4#define SUNXI_DIVISOR_WIDTH 2
Quoted 9 lines
drivers/clk/sunxi/clk-sunxi.c static void __init sunxi_gates_clk_setup(struct device_node *node, · line 1056
Quoted 6 lines
drivers/clk/sunxi/clk-sunxi.c +2
-1struct divs_data {const struct factors_data *factors;/* data for the factor clock */ -int ndivs;/* number of children */ +int ndivs;/* number of outputs */ struct { +u8 parent;/* is it the parent? (only one please) */ I really don't get what this "parent" is about. Is it a clock passed through to the users.
It is the PLL itself (the rate doubled one if you will), which then has the separate divided outputs. Or:
sun6i: PLL6x2 -> PLL6
sun7i: PLL6 -> {PLL6 SATA, PLL6 other}Quoted 1 line
Do we have even have users for these?
The mbus clocks use the doubled PLL6 as one of it's inputs. There are no users of the parent PLL5 clock. This can be seen in the .dtsi files, where PLL6 has a clock-output-name for itself, while PLL5 does not. However the clock driver has always exported the parent clock as the last clock for the node.
ChenYu
PATCH 5/6 clk: sunxi: Add pll6 / 4 clock output to sun4i-a10-pll6
In reply to Chen-Yu TsaiThe pll6 has a /4 output that is used as an input to the ahb mux clock.
--- drivers/clk/sunxi/clk-sunxi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/clk/sunxi/clk-sunxi.c +2 -1
@@ -1082,11 +1082,12 @@ static const struct divs_data pll5_divs_data __initconst = {static const struct divs_data pll6_divs_data__initconst = { .factors = &sun4i_pll6_data, - .ndivs =3 , + .ndivs =4 , .div = { { .shift =0 , .table = pll6_sata_tbl, .gate =14 },/* M, SATA */ { .fixed =2 },/* P, other */ { .parent =1 },/* parent, 2x */ + { .fixed =4 },/* pll6 / 4, used as ahb input */ } };
Signature · 1 line
2.1.4
PATCH 6/6 ARM: dts: sunxi: Update ahb clocks for sun5i and sun7i
In reply to Chen-Yu TsaiThe clock driver now supports a muxable ahb clock. Update the dtsi with the proper compatible and add the new parent clocks.
This also adds the new pll6/4 output for pll6 on sun7i-a20. The output is not used on sun4/5i.
Also use assigned-clocks to reparent ahb to pll6. We want ahb to have a stable, non-changing clock rate. cpu/axi clock rate changes as a result of newly added cpufreq support.
--- arch/arm/boot/dts/sun5i.dtsi | 10 ++++++++-- arch/arm/boot/dts/sun7i-a20.dtsi | 13 ++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-)
arch/arm/boot/dts/sun5i.dtsi +8 -2
@@ -150,10 +150,16 @@ ahb: ahb at 01c20054 { #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-ahb-clk"; + compatible = "allwinner,sun5i-a13-ahb-clk"; reg = <0x01c20054 0x4>; - clocks = <&axi>; + clocks = <&axi>, <&cpu>, <&pll6 1>; clock-output-names = "ahb"; + /* + * Use PLL6 as parent, instead of CPU/AXI + * which has rate changes due to cpufreq + */ + assigned-clocks = <&ahb>; + assigned-clock-parents = <&pll6 1>; }; apb0: apb0 at 01c20054 {
arch/arm/boot/dts/sun7i-a20.dtsi +10 -3
@@ -225,7 +225,8 @@ compatible = "allwinner,sun4i-a10-pll6-clk"; reg = <0x01c20028 0x4>; clocks = <&osc24M>; - clock-output-names = "pll6_sata", "pll6_other", "pll6"; + clock-output-names = "pll6_sata", "pll6_other", "pll6", + "pll6_div_4"; }; pll8: clk at 01c20040 {
@@ -254,10 +255,16 @@ ahb: ahb at 01c20054 { #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-ahb-clk"; + compatible = "allwinner,sun5i-a13-ahb-clk"; reg = <0x01c20054 0x4>; - clocks = <&axi>; + clocks = <&axi>, <&pll6 3>, <&pll6 1>; clock-output-names = "ahb"; + /* + * Use PLL6 as parent, instead of CPU/AXI + * which has rate changes due to cpufreq + */ + assigned-clocks = <&ahb>; + assigned-clock-parents = <&pll6 3>; }; ahb_gates: clk at 01c20060 {
Signature · 1 line
2.1.4