clk: sunxi: Add peripheral bus clock support for A80
Subsystems (6)
cover clk: sunxi: Add peripheral bus clock support for A80
Hi everyone,
This series adds support for the basic bus (AHB/APB) clocks used by peripherals on the A80 SoC. This series is based on my previous A80 bringup series.
The A80 has 5 peripheral related bus clocks, 1 data bus clock, and 1 CCI bus clock. 2 out of 12 PLLs are used to clock these.
Patch 1 adds support for configurable mux masks in sunxi factors clocks. This was previously hardcoded to a width of 2 bits, or a 0x3 mask.
Patch 2 adds support for the clocks mentioned above.
Patch 3 adds support for the bus gate clocks for the peripheral modules.
Patch 4 selects ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER when building for sun9i so the user does not forget to enable reset controller support.
Patch 5 adds the clocks and reset controls to the dtsi.
CPU and specific purpose (audio/video/gpu) PLLs have been left out. These can be added as the need comes. CPU PLLs (PLL1/2) should probably be added along with cpufreq support.
Cheers
ChenYu
Chen-Yu Tsai (5):
clk: sunxi: make factors clock mux mask configurable
clk: sunxi: Add support for A80 basic bus clocks
clk: sunxi: Add support for bus clock gates on Allwinner A80 SoC
ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for
sun9i
ARM: dts: sun9i: Add basic clocks and reset controls
Documentation/devicetree/bindings/clock/sunxi.txt | 10 + arch/arm/boot/dts/sun9i-a80.dtsi | 177 +++++++++++++- arch/arm/mach-sunxi/Kconfig | 2 + drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk-factors.c | 2 +- drivers/clk/sunxi/clk-factors.h | 3 +- drivers/clk/sunxi/clk-mod0.c | 1 + drivers/clk/sunxi/clk-sun8i-mbus.c | 1 + drivers/clk/sunxi/clk-sun9i-core.c | 272 ++++++++++++++++++++++ drivers/clk/sunxi/clk-sunxi.c | 32 +++ 10 files changed, 492 insertions(+), 9 deletions(-) create mode 100644 drivers/clk/sunxi/clk-sun9i-core.c
Signature · 1 line
2.1.1
PATCH 1/5 clk: sunxi: make factors clock mux mask configurable
Some of the factors-style clocks on the A80 have different widths for the mux values in the registers.
Add a .muxmask field to clk_factors_config to make it configurable. Passing a bitmask instead of a width parameter will allow reuse in case we support table-based muxes in the future.
--- drivers/clk/sunxi/clk-factors.c | 2 +- drivers/clk/sunxi/clk-factors.h | 3 +-- drivers/clk/sunxi/clk-mod0.c | 1 + drivers/clk/sunxi/clk-sun8i-mbus.c | 1 + drivers/clk/sunxi/clk-sunxi.c | 1 + 5 files changed, 5 insertions(+), 3 deletions(-)
drivers/clk/sunxi/clk-factors.c +1 -1
@@ -224,7 +224,7 @@ struct clk * __init sunxi_factors_register(struct device_node *node,/* set up gate properties */ mux->reg = reg; mux->shift = data->mux; - mux->mask =SUNXI_FACTORS_MUX_MASK ; + mux->mask = data->muxmask; mux->lock = factors->lock; mux_hw = &mux->hw; }
drivers/clk/sunxi/clk-factors.h +1 -2
@@ -7,8 +7,6 @@#define SUNXI_FACTORS_NOT_APPLICABLE (0) -#define SUNXI_FACTORS_MUX_MASK 0x3 -struct clk_factors_config {u8 nshift;u8 nwidth;
@@ -24,6 +22,7 @@ struct clk_factors_config {struct factors_data {int enable;int mux; +int muxmask;struct clk_factors_config *table;void (*getter) (u32 *rate,u32 parent_rate,u8 *n,u8 *k,u8 *m,u8 *p);const char *name;
drivers/clk/sunxi/clk-mod0.c +1 -0
@@ -70,6 +70,7 @@ static struct clk_factors_config sun4i_a10_mod0_config = {static const struct factors_data sun4i_a10_mod0_data__initconst = { .enable =31 , .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), .table = &sun4i_a10_mod0_config, .getter = sun4i_a10_get_mod0_factors, };
drivers/clk/sunxi/clk-sun8i-mbus.c +1 -0
@@ -60,6 +60,7 @@ static struct clk_factors_config sun8i_a23_mbus_config = {static const struct factors_data sun8i_a23_mbus_data__initconst = { .enable =31 , .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), .table = &sun8i_a23_mbus_config, .getter = sun8i_a23_get_mbus_factors, };
drivers/clk/sunxi/clk-sunxi.c +1 -0
@@ -514,6 +514,7 @@ static const struct factors_data sun4i_apb1_data __initconst = {static const struct factors_data sun7i_a20_out_data__initconst = { .enable =31 , .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), .table = &sun7i_a20_out_config, .getter = sun7i_a20_get_out_factors, };
Signature · 1 line
2.1.1
PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks
In reply to Chen-Yu TsaiThe A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a new "GT" bus, which I assume is some kind of data bus connecting the processor cores, memory and various busses. Also there is a bus clock for a ARM CCI400 module.
As far as I can tell, the GT bus and CCI400 bus clock must be protected.
This patch adds driver support for peripheral related PLLs and bus clocks on the A80. The GT and CCI400 clocks are added as well as these 2 along with the PLLs they are clocked from must not be disabled.
--- Documentation/devicetree/bindings/clock/sunxi.txt | 5 + drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk-sun9i-core.c | 272 ++++++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 drivers/clk/sunxi/clk-sun9i-core.c
Documentation/devicetree/bindings/clock/sunxi.txt +5 -0
@@ -10,14 +10,17 @@ Required properties: "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 + "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 + "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80 "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-a10-axi-clk" - for the AXI clock "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,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 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
@@ -29,6 +32,7 @@ Required properties: "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23 + "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
@@ -36,6 +40,7 @@ Required properties: "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock + "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
drivers/clk/sunxi/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o obj-y += clk-a20-gmac.o obj-y += clk-mod0.o obj-y += clk-sun8i-mbus.o +obj-y += clk-sun9i-core.o obj-$(CONFIG_MFD_SUN6I_PRCM) += \ clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
drivers/clk/sunxi/clk-sun9i-core.c new file +272 -0
272 lines not on this page · raw message
Signature · 1 line
2.1.1
PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks
Quoted 116 lines · Chen-Yu Tsai
The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a new "GT" bus, which I assume is some kind of data bus connecting the processor cores, memory and various busses. Also there is a bus clock for a ARM CCI400 module.
As far as I can tell, the GT bus and CCI400 bus clock must be protected.
This patch adds driver support for peripheral related PLLs and bus clocks on the A80. The GT and CCI400 clocks are added as well as these 2 along with the PLLs they are clocked from must not be disabled.
Signed-off-by Chen-Yu Tsai <[email protected]>--- Documentation/devicetree/bindings/clock/sunxi.txt | 5 + drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk-sun9i-core.c | 272 ++++++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 drivers/clk/sunxi/clk-sun9i-core.cDocumentation/devicetree/bindings/clock/sunxi.txt +5
-0@@ -10,14 +10,17 @@ Required properties: "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 + "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 + "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80 "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-a10-axi-clk" - for the AXI clock "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,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 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s@@ -29,6 +32,7 @@ Required properties: "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23 + "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s@@ -36,6 +40,7 @@ Required properties: "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock + "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13drivers/clk/sunxi/Makefile +1
-0@@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o obj-y += clk-a20-gmac.o obj-y += clk-mod0.o obj-y += clk-sun8i-mbus.o +obj-y += clk-sun9i-core.o obj-$(CONFIG_MFD_SUN6I_PRCM) += \ clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \drivers/clk/sunxi/clk-sun9i-core.c new file +39
-0@@ -0,0 +1,272 @@ +/* +* Copyright 2014 Chen-Yu Tsai +* +* Chen-Yu Tsai <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/log2.h> + +#include "clk-factors.h" + + +/** +* sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1 +* PLL4 rate is calculated as follows +* rate = (parent_rate * n >> p) / (m + 1); +* parent_rate is always 24Mhz +* +* p and m are named div1 and div2 in Allwinner's SDK +*/ + +static void sun9i_a80_get_pll4_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +int div; +
drivers/clk/sunxi/clk-sun9i-core.c line 49
Quoted 10 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +10
-0+/* Normalize value to a 6M multiple */ + div = *freq /6000000 ; + +/* divs above 256 cannot be odd */ +if (div >256 ) + div &= ~0x1 ; + +/* divs above 512 must be a multiple of 4 */ +if (div >512 ) + div &= ~0x3 ;
round_up / round_down looks more readable.
drivers/clk/sunxi/clk-sun9i-core.c line 51
Quoted 2 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +2
-0+ + *freq =6000000 * div;
and here as well
Quoted 210 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +210
-0+/* we were called to round the frequency, we can now return */ +if (n ==NULL ) +return ; + +/* p will be 1 for divs under 512 */ +if (div <512 ) + *p =1 ; +else + *p =0 ; + +/* m will be 1 if div is odd */ +if (div &1 ) + *m =1 ; +else + *m =0 ; + +/* calculate a suitable n based on m and p */ + *n = div / (*p +1 ) / (*m +1 ); +} + +static struct clk_factors_config sun9i_a80_pll4_config = { + .mshift =18 , + .mwidth =1 , + .nshift =8 , + .nwidth =8 , + .pshift =16 , + .pwidth =1 , +}; + +static const struct factors_data sun9i_a80_pll4_data__initconst = { + .enable =31 , + .table = &sun9i_a80_pll4_config, + .getter = sun9i_a80_get_pll4_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_pll4_lock); + +static void __init sun9i_a80_pll4_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock); +} +CLK_OF_DECLARE (sun9i_a80_pll4,"allwinner,sun9i-a80-pll4-clk" , sun9i_a80_pll4_setup); + + +/** +* sun9i_a80_get_gt_factors() - calculates m factor for GT +* GT rate is calculated as follows +* rate = parent_rate / (m + 1); +*/ + +static void sun9i_a80_get_gt_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 div; + +if (parent_rate < *freq) + *freq = parent_rate; + + div =DIV_ROUND_UP (parent_rate, *freq); + +/* maximum divider is 4 */ +if (div >4 ) + div =4 ; + + *freq = parent_rate / div; + +/* we were called to round the frequency, we can now return */ +if (!m) +return ; + + *m = div; +} + +static struct clk_factors_config sun9i_a80_gt_config = { + .mshift =0 , + .mwidth =2 , +}; + +static const struct factors_data sun9i_a80_gt_data__initconst = { + .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), + .table = &sun9i_a80_gt_config, + .getter = sun9i_a80_get_gt_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_gt_lock); + +static void __init sun9i_a80_gt_setup (struct device_node *node) +{ +struct clk *gt =sunxi_factors_register (node, &sun9i_a80_gt_data, + &sun9i_a80_gt_lock); + +/* The GT bus clock needs to be always enabled */ +__clk_get (gt); +clk_prepare_enable (gt); +} +CLK_OF_DECLARE (sun9i_a80_gt,"allwinner,sun9i-a80-gt-clk" , sun9i_a80_gt_setup); + + +/** +* sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2 +* AHB rate is calculated as follows +* rate = parent_rate >> p; +*/ + +static void sun9i_a80_get_ahb_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 _p; + +if (parent_rate < *freq) + *freq = parent_rate; + + _p =order_base_2 (DIV_ROUND_UP (parent_rate, *freq)); + +/* maximum p is 3 */ +if (_p >3 ) + _p =3 ; + + *freq = parent_rate >> _p; + +/* we were called to round the frequency, we can now return */ +if (!p) +return ; + + *p = _p; +} + +static struct clk_factors_config sun9i_a80_ahb_config = { + .pshift =0 , + .pwidth =2 , +}; + +static const struct factors_data sun9i_a80_ahb_data__initconst = { + .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), + .table = &sun9i_a80_ahb_config, + .getter = sun9i_a80_get_ahb_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_ahb_lock); + +static void __init sun9i_a80_ahb_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock); +} +CLK_OF_DECLARE (sun9i_a80_ahb,"allwinner,sun9i-a80-ahb-clk" , sun9i_a80_ahb_setup); + + +static const struct factors_data sun9i_a80_apb0_data__initconst = { + .mux =24 , + .muxmask =BIT (0 ), + .table = &sun9i_a80_ahb_config, + .getter = sun9i_a80_get_ahb_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_apb0_lock); + +static void __init sun9i_a80_apb0_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock); +} +CLK_OF_DECLARE (sun9i_a80_apb0,"allwinner,sun9i-a80-apb0-clk" , sun9i_a80_apb0_setup); + + +/** +* sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1 +* APB1 rate is calculated as follows +* rate = (parent_rate >> p) / (m + 1); +*/ + +static void sun9i_a80_get_apb1_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 div; +u8 calcm, calcp; + +if (parent_rate < *freq) + *freq = parent_rate; + + div =DIV_ROUND_UP (parent_rate, *freq); + +/* Highest possible divider is 256 (p = 3, m = 31) */ +if (div >256 ) + div =256 ; + + calcp =order_base_2 (div); + calcm = (parent_rate >> calcp) -1 ; + *freq = (parent_rate >> calcp) / (calcm +1 ); + +/* we were called to round the frequency, we can now return */ +if (n ==NULL ) +return ; + + *m = calcm; + *p = calcp; +} + +static struct clk_factors_config sun9i_a80_apb1_config = { + .mshift =0 , + .mwidth =5 , + .pshift =16 , + .pwidth =2 , +}; + +static const struct factors_data sun9i_a80_apb1_data__initconst = { + .mux =24 , + .muxmask =BIT (0 ), + .table = &sun9i_a80_apb1_config, + .getter = sun9i_a80_get_apb1_factors,
drivers/clk/sunxi/clk-sun9i-core.c line 272
Quoted 10 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +10
-0+}; + +static DEFINE_SPINLOCK (sun9i_a80_apb1_lock); + +static void __init sun9i_a80_apb1_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock); +} +CLK_OF_DECLARE (sun9i_a80_apb1,"allwinner,sun9i-a80-apb1-clk" , sun9i_a80_apb1_setup); +
Do these clocks share anything (aside from being for the A80) that require them to be in the same file?
Thanks for your work!
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/20141016/ce48b63c/attachment.sig>
PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks
Quoted 121 lines · Maxime Ripard
Quoted 120 lines · Chen-Yu Tsai
The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a new "GT" bus, which I assume is some kind of data bus connecting the processor cores, memory and various busses. Also there is a bus clock for a ARM CCI400 module.
As far as I can tell, the GT bus and CCI400 bus clock must be protected.
This patch adds driver support for peripheral related PLLs and bus clocks on the A80. The GT and CCI400 clocks are added as well as these 2 along with the PLLs they are clocked from must not be disabled.
Signed-off-by Chen-Yu Tsai <[email protected]>--- Documentation/devicetree/bindings/clock/sunxi.txt | 5 + drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk-sun9i-core.c | 272 ++++++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 drivers/clk/sunxi/clk-sun9i-core.cDocumentation/devicetree/bindings/clock/sunxi.txt +5
-0@@ -10,14 +10,17 @@ Required properties: "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 + "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 + "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80 "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-a10-axi-clk" - for the AXI clock "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,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 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s@@ -29,6 +32,7 @@ Required properties: "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23 + "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s@@ -36,6 +40,7 @@ Required properties: "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock + "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13drivers/clk/sunxi/Makefile +1
-0@@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o obj-y += clk-a20-gmac.o obj-y += clk-mod0.o obj-y += clk-sun8i-mbus.o +obj-y += clk-sun9i-core.o obj-$(CONFIG_MFD_SUN6I_PRCM) += \ clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \drivers/clk/sunxi/clk-sun9i-core.c new file +43
-0@@ -0,0 +1,272 @@ +/* +* Copyright 2014 Chen-Yu Tsai +* +* Chen-Yu Tsai <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/log2.h> + +#include "clk-factors.h" + + +/** +* sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1 +* PLL4 rate is calculated as follows +* rate = (parent_rate * n >> p) / (m + 1); +* parent_rate is always 24Mhz +* +* p and m are named div1 and div2 in Allwinner's SDK +*/ + +static void sun9i_a80_get_pll4_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +int div; + +/* Normalize value to a 6M multiple */ + div = *freq /6000000 ; + +/* divs above 256 cannot be odd */
Quoted 8 lines
drivers/clk/sunxi/clk-sun9i-core.c line 49
Quoted 6 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +6
-0+if (div >256 ) + div &= ~0x1 ; + +/* divs above 512 must be a multiple of 4 */ +if (div >512 ) + div &= ~0x3 ;
round_up/round_downlooks more readable.
OK.
Quoted 4 lines
drivers/clk/sunxi/clk-sun9i-core.c line 51
Quoted 2 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +2
-0+ + *freq =6000000 * div;and here as well
This won't look pretty with round_up/round_down i think. This function is supposed to return the actual closest supported frequency, so it depends on the calculated/rounded divider from the previous section.
Quoted 215 lines
Quoted 215 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +215
-0+/* we were called to round the frequency, we can now return */ +if (n ==NULL ) +return ; + +/* p will be 1 for divs under 512 */ +if (div <512 ) + *p =1 ; +else + *p =0 ; + +/* m will be 1 if div is odd */ +if (div &1 ) + *m =1 ; +else + *m =0 ; + +/* calculate a suitable n based on m and p */ + *n = div / (*p +1 ) / (*m +1 ); +} + +static struct clk_factors_config sun9i_a80_pll4_config = { + .mshift =18 , + .mwidth =1 , + .nshift =8 , + .nwidth =8 , + .pshift =16 , + .pwidth =1 , +}; + +static const struct factors_data sun9i_a80_pll4_data__initconst = { + .enable =31 , + .table = &sun9i_a80_pll4_config, + .getter = sun9i_a80_get_pll4_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_pll4_lock); + +static void __init sun9i_a80_pll4_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock); +} +CLK_OF_DECLARE (sun9i_a80_pll4,"allwinner,sun9i-a80-pll4-clk" , sun9i_a80_pll4_setup); + + +/** +* sun9i_a80_get_gt_factors() - calculates m factor for GT +* GT rate is calculated as follows +* rate = parent_rate / (m + 1); +*/ + +static void sun9i_a80_get_gt_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 div; + +if (parent_rate < *freq) + *freq = parent_rate; + + div =DIV_ROUND_UP (parent_rate, *freq); + +/* maximum divider is 4 */ +if (div >4 ) + div =4 ; + + *freq = parent_rate / div; + +/* we were called to round the frequency, we can now return */ +if (!m) +return ; + + *m = div; +} + +static struct clk_factors_config sun9i_a80_gt_config = { + .mshift =0 , + .mwidth =2 , +}; + +static const struct factors_data sun9i_a80_gt_data__initconst = { + .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), + .table = &sun9i_a80_gt_config, + .getter = sun9i_a80_get_gt_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_gt_lock); + +static void __init sun9i_a80_gt_setup (struct device_node *node) +{ +struct clk *gt =sunxi_factors_register (node, &sun9i_a80_gt_data, + &sun9i_a80_gt_lock); + +/* The GT bus clock needs to be always enabled */ +__clk_get (gt); +clk_prepare_enable (gt); +} +CLK_OF_DECLARE (sun9i_a80_gt,"allwinner,sun9i-a80-gt-clk" , sun9i_a80_gt_setup); + + +/** +* sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2 +* AHB rate is calculated as follows +* rate = parent_rate >> p; +*/ + +static void sun9i_a80_get_ahb_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 _p; + +if (parent_rate < *freq) + *freq = parent_rate; + + _p =order_base_2 (DIV_ROUND_UP (parent_rate, *freq)); + +/* maximum p is 3 */ +if (_p >3 ) + _p =3 ; + + *freq = parent_rate >> _p; + +/* we were called to round the frequency, we can now return */ +if (!p) +return ; + + *p = _p; +} + +static struct clk_factors_config sun9i_a80_ahb_config = { + .pshift =0 , + .pwidth =2 , +}; + +static const struct factors_data sun9i_a80_ahb_data__initconst = { + .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), + .table = &sun9i_a80_ahb_config, + .getter = sun9i_a80_get_ahb_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_ahb_lock); + +static void __init sun9i_a80_ahb_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock); +} +CLK_OF_DECLARE (sun9i_a80_ahb,"allwinner,sun9i-a80-ahb-clk" , sun9i_a80_ahb_setup); + + +static const struct factors_data sun9i_a80_apb0_data__initconst = { + .mux =24 , + .muxmask =BIT (0 ), + .table = &sun9i_a80_ahb_config, + .getter = sun9i_a80_get_ahb_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_apb0_lock); + +static void __init sun9i_a80_apb0_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock); +} +CLK_OF_DECLARE (sun9i_a80_apb0,"allwinner,sun9i-a80-apb0-clk" , sun9i_a80_apb0_setup); + + +/** +* sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1 +* APB1 rate is calculated as follows +* rate = (parent_rate >> p) / (m + 1); +*/ + +static void sun9i_a80_get_apb1_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 div; +u8 calcm, calcp; + +if (parent_rate < *freq) + *freq = parent_rate; + + div =DIV_ROUND_UP (parent_rate, *freq); + +/* Highest possible divider is 256 (p = 3, m = 31) */ +if (div >256 ) + div =256 ; + + calcp =order_base_2 (div); + calcm = (parent_rate >> calcp) -1 ; + *freq = (parent_rate >> calcp) / (calcm +1 ); + +/* we were called to round the frequency, we can now return */ +if (n ==NULL ) +return ; + + *m = calcm; + *p = calcp; +} + +static struct clk_factors_config sun9i_a80_apb1_config = { + .mshift =0 , + .mwidth =5 , + .pshift =16 , + .pwidth =2 , +}; + +static const struct factors_data sun9i_a80_apb1_data__initconst = { + .mux =24 , + .muxmask =BIT (0 ), + .table = &sun9i_a80_apb1_config, + .getter = sun9i_a80_get_apb1_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_apb1_lock); + +static void __init sun9i_a80_apb1_setup (struct device_node *node)
Quoted 8 lines
drivers/clk/sunxi/clk-sun9i-core.c line 272
Quoted 5 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +5
-0+{ +sunxi_factors_register (node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock); +} +CLK_OF_DECLARE (sun9i_a80_apb1,"allwinner,sun9i-a80-apb1-clk" , sun9i_a80_apb1_setup); +Do these clocks share anything (aside from being for the A80) that require them to be in the same file?
They are part of the same tree hierarchy. But otherwise no requirements.
I would put CPU plls and clocks in a different file, module clocks in another, and the remaining (media related) plls in yet another one.
I think having one file per clock is kind of taking it too far.
Quoted 2 lines
Thanks for your work!
Maxime
Thanks!
ChenYu
PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks
Quoted 137 lines · Chen-Yu Tsai
Quoted 121 lines · Maxime Ripard
Quoted 120 lines · Chen-Yu Tsai
The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a new "GT" bus, which I assume is some kind of data bus connecting the processor cores, memory and various busses. Also there is a bus clock for a ARM CCI400 module.
As far as I can tell, the GT bus and CCI400 bus clock must be protected.
This patch adds driver support for peripheral related PLLs and bus clocks on the A80. The GT and CCI400 clocks are added as well as these 2 along with the PLLs they are clocked from must not be disabled.
Signed-off-by Chen-Yu Tsai <[email protected]>--- Documentation/devicetree/bindings/clock/sunxi.txt | 5 + drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk-sun9i-core.c | 272 ++++++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 drivers/clk/sunxi/clk-sun9i-core.cDocumentation/devicetree/bindings/clock/sunxi.txt +5
-0@@ -10,14 +10,17 @@ Required properties: "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 + "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 + "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80 "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-a10-axi-clk" - for the AXI clock "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,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 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s@@ -29,6 +32,7 @@ Required properties: "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23 + "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s@@ -36,6 +40,7 @@ Required properties: "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock + "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13drivers/clk/sunxi/Makefile +1
-0@@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o obj-y += clk-a20-gmac.o obj-y += clk-mod0.o obj-y += clk-sun8i-mbus.o +obj-y += clk-sun9i-core.o obj-$(CONFIG_MFD_SUN6I_PRCM) += \ clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \drivers/clk/sunxi/clk-sun9i-core.c new file +43
-0@@ -0,0 +1,272 @@ +/* +* Copyright 2014 Chen-Yu Tsai +* +* Chen-Yu Tsai <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/log2.h> + +#include "clk-factors.h" + + +/** +* sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1 +* PLL4 rate is calculated as follows +* rate = (parent_rate * n >> p) / (m + 1); +* parent_rate is always 24Mhz +* +* p and m are named div1 and div2 in Allwinner's SDK +*/ + +static void sun9i_a80_get_pll4_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +int div; + +/* Normalize value to a 6M multiple */ + div = *freq /6000000 ; + +/* divs above 256 cannot be odd */ Quoted 8 lines
drivers/clk/sunxi/clk-sun9i-core.c line 49
Quoted 6 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +6
-0+if (div >256 ) + div &= ~0x1 ; + +/* divs above 512 must be a multiple of 4 */ +if (div >512 ) + div &= ~0x3 ;
round_up/round_downlooks more readable.OK.
Quoted 3 lines
Quoted 2 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +2
-0+ + *freq =6000000 * div;
Quoted 6 lines
Quoted 1 line
and here as well
This won't look pretty with round_up/round_down i think. This function is supposed to return the actual closest supported frequency, so it depends on the calculated/rounded divider from the previous section.
Well, if I understood your code correctly, you want to round the frequency to 6MHz multiple if div < 256, 12MHz if div < 512 and 24MHz otherwise right?
I'm confident it can be made prettier.
Quoted 224 lines
Quoted 215 lines
Quoted 215 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +215
-0+/* we were called to round the frequency, we can now return */ +if (n ==NULL ) +return ; + +/* p will be 1 for divs under 512 */ +if (div <512 ) + *p =1 ; +else + *p =0 ; + +/* m will be 1 if div is odd */ +if (div &1 ) + *m =1 ; +else + *m =0 ; + +/* calculate a suitable n based on m and p */ + *n = div / (*p +1 ) / (*m +1 ); +} + +static struct clk_factors_config sun9i_a80_pll4_config = { + .mshift =18 , + .mwidth =1 , + .nshift =8 , + .nwidth =8 , + .pshift =16 , + .pwidth =1 , +}; + +static const struct factors_data sun9i_a80_pll4_data__initconst = { + .enable =31 , + .table = &sun9i_a80_pll4_config, + .getter = sun9i_a80_get_pll4_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_pll4_lock); + +static void __init sun9i_a80_pll4_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock); +} +CLK_OF_DECLARE (sun9i_a80_pll4,"allwinner,sun9i-a80-pll4-clk" , sun9i_a80_pll4_setup); + + +/** +* sun9i_a80_get_gt_factors() - calculates m factor for GT +* GT rate is calculated as follows +* rate = parent_rate / (m + 1); +*/ + +static void sun9i_a80_get_gt_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 div; + +if (parent_rate < *freq) + *freq = parent_rate; + + div =DIV_ROUND_UP (parent_rate, *freq); + +/* maximum divider is 4 */ +if (div >4 ) + div =4 ; + + *freq = parent_rate / div; + +/* we were called to round the frequency, we can now return */ +if (!m) +return ; + + *m = div; +} + +static struct clk_factors_config sun9i_a80_gt_config = { + .mshift =0 , + .mwidth =2 , +}; + +static const struct factors_data sun9i_a80_gt_data__initconst = { + .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), + .table = &sun9i_a80_gt_config, + .getter = sun9i_a80_get_gt_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_gt_lock); + +static void __init sun9i_a80_gt_setup (struct device_node *node) +{ +struct clk *gt =sunxi_factors_register (node, &sun9i_a80_gt_data, + &sun9i_a80_gt_lock); + +/* The GT bus clock needs to be always enabled */ +__clk_get (gt); +clk_prepare_enable (gt); +} +CLK_OF_DECLARE (sun9i_a80_gt,"allwinner,sun9i-a80-gt-clk" , sun9i_a80_gt_setup); + + +/** +* sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2 +* AHB rate is calculated as follows +* rate = parent_rate >> p; +*/ + +static void sun9i_a80_get_ahb_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 _p; + +if (parent_rate < *freq) + *freq = parent_rate; + + _p =order_base_2 (DIV_ROUND_UP (parent_rate, *freq)); + +/* maximum p is 3 */ +if (_p >3 ) + _p =3 ; + + *freq = parent_rate >> _p; + +/* we were called to round the frequency, we can now return */ +if (!p) +return ; + + *p = _p; +} + +static struct clk_factors_config sun9i_a80_ahb_config = { + .pshift =0 , + .pwidth =2 , +}; + +static const struct factors_data sun9i_a80_ahb_data__initconst = { + .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), + .table = &sun9i_a80_ahb_config, + .getter = sun9i_a80_get_ahb_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_ahb_lock); + +static void __init sun9i_a80_ahb_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock); +} +CLK_OF_DECLARE (sun9i_a80_ahb,"allwinner,sun9i-a80-ahb-clk" , sun9i_a80_ahb_setup); + + +static const struct factors_data sun9i_a80_apb0_data__initconst = { + .mux =24 , + .muxmask =BIT (0 ), + .table = &sun9i_a80_ahb_config, + .getter = sun9i_a80_get_ahb_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_apb0_lock); + +static void __init sun9i_a80_apb0_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock); +} +CLK_OF_DECLARE (sun9i_a80_apb0,"allwinner,sun9i-a80-apb0-clk" , sun9i_a80_apb0_setup); + + +/** +* sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1 +* APB1 rate is calculated as follows +* rate = (parent_rate >> p) / (m + 1); +*/ + +static void sun9i_a80_get_apb1_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 div; +u8 calcm, calcp; + +if (parent_rate < *freq) + *freq = parent_rate; + + div =DIV_ROUND_UP (parent_rate, *freq); + +/* Highest possible divider is 256 (p = 3, m = 31) */ +if (div >256 ) + div =256 ; + + calcp =order_base_2 (div); + calcm = (parent_rate >> calcp) -1 ; + *freq = (parent_rate >> calcp) / (calcm +1 ); + +/* we were called to round the frequency, we can now return */ +if (n ==NULL ) +return ; + + *m = calcm; + *p = calcp; +} + +static struct clk_factors_config sun9i_a80_apb1_config = { + .mshift =0 , + .mwidth =5 , + .pshift =16 , + .pwidth =2 , +}; + +static const struct factors_data sun9i_a80_apb1_data__initconst = { + .mux =24 , + .muxmask =BIT (0 ), + .table = &sun9i_a80_apb1_config, + .getter = sun9i_a80_get_apb1_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_apb1_lock); + +static void __init sun9i_a80_apb1_setup (struct device_node *node)Quoted 8 lines
drivers/clk/sunxi/clk-sun9i-core.c line 272
Quoted 5 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +5
-0+{ +sunxi_factors_register (node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock); +} +CLK_OF_DECLARE (sun9i_a80_apb1,"allwinner,sun9i-a80-apb1-clk" , sun9i_a80_apb1_setup); +Do these clocks share anything (aside from being for the A80) that require them to be in the same file?
Quoted 4 lines
They are part of the same tree hierarchy. But otherwise no requirements.
I would put CPU plls and clocks in a different file, module clocks in another, and the remaining (media related) plls in yet another one.
Yep, it looks better.
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/20141017/200b04b3/attachment.sig>
PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks
Quoted 145 lines · Maxime Ripard
Quoted 137 lines · Chen-Yu Tsai
Quoted 121 lines · Maxime Ripard
Quoted 120 lines · Chen-Yu Tsai
The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a new "GT" bus, which I assume is some kind of data bus connecting the processor cores, memory and various busses. Also there is a bus clock for a ARM CCI400 module.
As far as I can tell, the GT bus and CCI400 bus clock must be protected.
This patch adds driver support for peripheral related PLLs and bus clocks on the A80. The GT and CCI400 clocks are added as well as these 2 along with the PLLs they are clocked from must not be disabled.
Signed-off-by Chen-Yu Tsai <[email protected]>--- Documentation/devicetree/bindings/clock/sunxi.txt | 5 + drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk-sun9i-core.c | 272 ++++++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 drivers/clk/sunxi/clk-sun9i-core.cDocumentation/devicetree/bindings/clock/sunxi.txt +5
-0@@ -10,14 +10,17 @@ Required properties: "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 + "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 + "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80 "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-a10-axi-clk" - for the AXI clock "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,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 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s@@ -29,6 +32,7 @@ Required properties: "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23 + "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s@@ -36,6 +40,7 @@ Required properties: "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock + "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13drivers/clk/sunxi/Makefile +1
-0@@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o obj-y += clk-a20-gmac.o obj-y += clk-mod0.o obj-y += clk-sun8i-mbus.o +obj-y += clk-sun9i-core.o obj-$(CONFIG_MFD_SUN6I_PRCM) += \ clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \drivers/clk/sunxi/clk-sun9i-core.c new file +43
-0@@ -0,0 +1,272 @@ +/* +* Copyright 2014 Chen-Yu Tsai +* +* Chen-Yu Tsai <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/log2.h> + +#include "clk-factors.h" + + +/** +* sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1 +* PLL4 rate is calculated as follows +* rate = (parent_rate * n >> p) / (m + 1); +* parent_rate is always 24Mhz +* +* p and m are named div1 and div2 in Allwinner's SDK +*/ + +static void sun9i_a80_get_pll4_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +int div; + +/* Normalize value to a 6M multiple */ + div = *freq /6000000 ; + +/* divs above 256 cannot be odd */ Quoted 8 lines
drivers/clk/sunxi/clk-sun9i-core.c line 49
Quoted 6 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +6
-0+if (div >256 ) + div &= ~0x1 ; + +/* divs above 512 must be a multiple of 4 */ +if (div >512 ) + div &= ~0x3 ;
round_up/round_downlooks more readable.OK.
Quoted 3 lines
Quoted 2 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +2
-0+ + *freq =6000000 * div;Quoted 6 lines
Quoted 1 line
and here as well
This won't look pretty with round_up/round_down i think. This function is supposed to return the actual closest supported frequency, so it depends on the calculated/rounded divider from the previous section.
Quoted 5 lines
Well, if I understood your code correctly, you want to round the frequency to 6MHz multiple if div < 256, 12MHz if div < 512 and 24MHz otherwise right?
I'm confident it can be made prettier.
I seem to have responded incorrectly.
What I meant to say is that i can replace the bitmasking with ROUND_UP/ROUND_DOWN, but the conditionals will still be there.
Is that what you had in mind?
Quoted 224 lines
Quoted 224 lines
Quoted 223 lines
Quoted 210 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +210
-0+/* we were called to round the frequency, we can now return */ +if (n ==NULL ) +return ; + +/* p will be 1 for divs under 512 */ +if (div <512 ) + *p =1 ; +else + *p =0 ; + +/* m will be 1 if div is odd */ +if (div &1 ) + *m =1 ; +else + *m =0 ; + +/* calculate a suitable n based on m and p */ + *n = div / (*p +1 ) / (*m +1 ); +} + +static struct clk_factors_config sun9i_a80_pll4_config = { + .mshift =18 , + .mwidth =1 , + .nshift =8 , + .nwidth =8 , + .pshift =16 , + .pwidth =1 , +}; + +static const struct factors_data sun9i_a80_pll4_data__initconst = { + .enable =31 , + .table = &sun9i_a80_pll4_config, + .getter = sun9i_a80_get_pll4_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_pll4_lock); + +static void __init sun9i_a80_pll4_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock); +} +CLK_OF_DECLARE (sun9i_a80_pll4,"allwinner,sun9i-a80-pll4-clk" , sun9i_a80_pll4_setup); + + +/** +* sun9i_a80_get_gt_factors() - calculates m factor for GT +* GT rate is calculated as follows +* rate = parent_rate / (m + 1); +*/ + +static void sun9i_a80_get_gt_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 div; + +if (parent_rate < *freq) + *freq = parent_rate; + + div =DIV_ROUND_UP (parent_rate, *freq); + +/* maximum divider is 4 */ +if (div >4 ) + div =4 ; + + *freq = parent_rate / div; + +/* we were called to round the frequency, we can now return */ +if (!m) +return ; + + *m = div; +} + +static struct clk_factors_config sun9i_a80_gt_config = { + .mshift =0 , + .mwidth =2 , +}; + +static const struct factors_data sun9i_a80_gt_data__initconst = { + .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), + .table = &sun9i_a80_gt_config, + .getter = sun9i_a80_get_gt_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_gt_lock); + +static void __init sun9i_a80_gt_setup (struct device_node *node) +{ +struct clk *gt =sunxi_factors_register (node, &sun9i_a80_gt_data, + &sun9i_a80_gt_lock); + +/* The GT bus clock needs to be always enabled */ +__clk_get (gt); +clk_prepare_enable (gt); +} +CLK_OF_DECLARE (sun9i_a80_gt,"allwinner,sun9i-a80-gt-clk" , sun9i_a80_gt_setup); + + +/** +* sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2 +* AHB rate is calculated as follows +* rate = parent_rate >> p; +*/ + +static void sun9i_a80_get_ahb_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 _p; + +if (parent_rate < *freq) + *freq = parent_rate; + + _p =order_base_2 (DIV_ROUND_UP (parent_rate, *freq)); + +/* maximum p is 3 */ +if (_p >3 ) + _p =3 ; + + *freq = parent_rate >> _p; + +/* we were called to round the frequency, we can now return */ +if (!p) +return ; + + *p = _p; +} + +static struct clk_factors_config sun9i_a80_ahb_config = { + .pshift =0 , + .pwidth =2 , +}; + +static const struct factors_data sun9i_a80_ahb_data__initconst = { + .mux =24 , + .muxmask =BIT (1 ) |BIT (0 ), + .table = &sun9i_a80_ahb_config, + .getter = sun9i_a80_get_ahb_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_ahb_lock); + +static void __init sun9i_a80_ahb_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock); +} +CLK_OF_DECLARE (sun9i_a80_ahb,"allwinner,sun9i-a80-ahb-clk" , sun9i_a80_ahb_setup); + + +static const struct factors_data sun9i_a80_apb0_data__initconst = { + .mux =24 , + .muxmask =BIT (0 ), + .table = &sun9i_a80_ahb_config, + .getter = sun9i_a80_get_ahb_factors, +}; + +static DEFINE_SPINLOCK (sun9i_a80_apb0_lock); + +static void __init sun9i_a80_apb0_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock); +} +CLK_OF_DECLARE (sun9i_a80_apb0,"allwinner,sun9i-a80-apb0-clk" , sun9i_a80_apb0_setup); + + +/** +* sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1 +* APB1 rate is calculated as follows +* rate = (parent_rate >> p) / (m + 1); +*/ + +static void sun9i_a80_get_apb1_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +u32 div; +u8 calcm, calcp; + +if (parent_rate < *freq) + *freq = parent_rate; + + div =DIV_ROUND_UP (parent_rate, *freq); + +/* Highest possible divider is 256 (p = 3, m = 31) */ +if (div >256 ) + div =256 ; + + calcp =order_base_2 (div); + calcm = (parent_rate >> calcp) -1 ; + *freq = (parent_rate >> calcp) / (calcm +1 ); + +/* we were called to round the frequency, we can now return */ +if (n ==NULL ) +return ; + + *m = calcm; + *p = calcp; +} + +static struct clk_factors_config sun9i_a80_apb1_config = { + .mshift =0 , + .mwidth =5 , + .pshift =16 , + .pwidth =2 , +}; + +static const struct factors_data sun9i_a80_apb1_data__initconst = { + .mux =24 , + .muxmask =BIT (0 ), + .table = &sun9i_a80_apb1_config, + .getter = sun9i_a80_get_apb1_factors,drivers/clk/sunxi/clk-sun9i-core.c line 272
Quoted 10 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +10
-0+}; + +static DEFINE_SPINLOCK (sun9i_a80_apb1_lock); + +static void __init sun9i_a80_apb1_setup (struct device_node *node) +{ +sunxi_factors_register (node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock); +} +CLK_OF_DECLARE (sun9i_a80_apb1,"allwinner,sun9i-a80-apb1-clk" , sun9i_a80_apb1_setup); +Do these clocks share anything (aside from being for the A80) that require them to be in the same file?
Quoted 7 lines
Quoted 4 lines
They are part of the same tree hierarchy. But otherwise no requirements.
I would put CPU plls and clocks in a different file, module clocks in another, and the remaining (media related) plls in yet another one.
Yep, it looks better.
Thanks!
:)
ChenYu
PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks
Quoted 151 lines · Chen-Yu Tsai
Quoted 149 lines · Maxime Ripard
Quoted 137 lines · Chen-Yu Tsai
Quoted 121 lines · Maxime Ripard
Quoted 120 lines · Chen-Yu Tsai
The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a new "GT" bus, which I assume is some kind of data bus connecting the processor cores, memory and various busses. Also there is a bus clock for a ARM CCI400 module.
As far as I can tell, the GT bus and CCI400 bus clock must be protected.
This patch adds driver support for peripheral related PLLs and bus clocks on the A80. The GT and CCI400 clocks are added as well as these 2 along with the PLLs they are clocked from must not be disabled.
Signed-off-by Chen-Yu Tsai <[email protected]>--- Documentation/devicetree/bindings/clock/sunxi.txt | 5 + drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk-sun9i-core.c | 272 ++++++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 drivers/clk/sunxi/clk-sun9i-core.cDocumentation/devicetree/bindings/clock/sunxi.txt +5
-0@@ -10,14 +10,17 @@ Required properties: "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 + "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 + "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80 "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-a10-axi-clk" - for the AXI clock "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,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 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s@@ -29,6 +32,7 @@ Required properties: "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23 + "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s@@ -36,6 +40,7 @@ Required properties: "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock + "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13drivers/clk/sunxi/Makefile +1
-0@@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o obj-y += clk-a20-gmac.o obj-y += clk-mod0.o obj-y += clk-sun8i-mbus.o +obj-y += clk-sun9i-core.o obj-$(CONFIG_MFD_SUN6I_PRCM) += \ clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \drivers/clk/sunxi/clk-sun9i-core.c new file +43
-0@@ -0,0 +1,272 @@ +/* +* Copyright 2014 Chen-Yu Tsai +* +* Chen-Yu Tsai <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/log2.h> + +#include "clk-factors.h" + + +/** +* sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1 +* PLL4 rate is calculated as follows +* rate = (parent_rate * n >> p) / (m + 1); +* parent_rate is always 24Mhz +* +* p and m are named div1 and div2 in Allwinner's SDK +*/ + +static void sun9i_a80_get_pll4_factors (u32 *freq,u32 parent_rate, +u8 *n,u8 *k,u8 *m,u8 *p) +{ +int div; + +/* Normalize value to a 6M multiple */ + div = *freq /6000000 ; + +/* divs above 256 cannot be odd */ Quoted 8 lines
drivers/clk/sunxi/clk-sun9i-core.c line 49
Quoted 6 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +6
-0+if (div >256 ) + div &= ~0x1 ; + +/* divs above 512 must be a multiple of 4 */ +if (div >512 ) + div &= ~0x3 ;
round_up/round_downlooks more readable.OK.
Quoted 3 lines
Quoted 2 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +2
-0+ + *freq =6000000 * div;Quoted 6 lines
Quoted 1 line
and here as well
This won't look pretty with round_up/round_down i think. This function is supposed to return the actual closest supported frequency, so it depends on the calculated/rounded divider from the previous section.
Well, if I understood your code correctly, you want to round the frequency to 6MHz multiple if div < 256, 12MHz if div < 512 and 24MHz otherwise right?
Quoted 8 lines
Quoted 1 line
I'm confident it can be made prettier.
I seem to have responded incorrectly.
What I meant to say is that i can replace the bitmasking with ROUND_UP/ROUND_DOWN, but the conditionals will still be there.
Is that what you had in mind?
Oh, my bad.
Yes, it's definitely something like that I had in mind :)
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/20141020/e4789ad9/attachment.sig>
PATCH 3/5 clk: sunxi: Add support for bus clock gates on Allwinner A80 SoC
In reply to Chen-Yu TsaiThis adds the gate clocks for AHB/APB busses on the A80 SoC.
--- Documentation/devicetree/bindings/clock/sunxi.txt | 5 ++++ drivers/clk/sunxi/clk-sunxi.c | 31 +++++++++++++++++++++++ 2 files changed, 36 insertions(+)
Documentation/devicetree/bindings/clock/sunxi.txt +5 -0
@@ -29,6 +29,9 @@ Required properties: "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23 + "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80 + "allwinner,sun9i-a80-ahb1-gates-clk" - for the AHB1 gates on A80 + "allwinner,sun9i-a80-ahb2-gates-clk" - for the AHB2 gates on A80 "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
@@ -39,6 +42,7 @@ Required properties: "allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31 "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23 + "allwinner,sun9i-a80-apb0-gates-clk" - for the APB0 gates on A80 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
@@ -48,6 +52,7 @@ Required properties: "allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31 "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 "allwinner,sun8i-a23-apb1-gates-clk" - for the APB1 gates on A23 + "allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80 "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
drivers/clk/sunxi/clk-sunxi.c +31 -0
@@ -758,6 +758,18 @@ static const struct gates_data sun8i_a23_ahb1_gates_data __initconst = { .mask = {0x25386742, 0x2505111}, }; +static const struct gates_data sun9i_a80_ahb0_gates_data__initconst = { + .mask = {0xF5F12B }, +}; + +static const struct gates_data sun9i_a80_ahb1_gates_data__initconst = { + .mask = {0x1E20003 }, +}; + +static const struct gates_data sun9i_a80_ahb2_gates_data__initconst = { + .mask = {0x9B7 }, +}; +static const struct gates_data sun4i_apb0_gates_data__initconst = { .mask = {0x4EF }, };
@@ -774,6 +786,10 @@ static const struct gates_data sun7i_a20_apb0_gates_data __initconst = { .mask = { 0x4ff }, }; +static const struct gates_data sun9i_a80_apb0_gates_data__initconst = { + .mask = {0xEB822 }, +}; +static const struct gates_data sun4i_apb1_gates_data__initconst = { .mask = {0xFF00F7 }, };
@@ -802,6 +818,10 @@ static const struct gates_data sun7i_a20_apb1_gates_data __initconst = { .mask = { 0xff80ff }, }; +static const struct gates_data sun9i_a80_apb1_gates_data__initconst = { + .mask = {0x3F001F }, +}; +static const struct gates_data sun8i_a23_apb2_gates_data__initconst = { .mask = {0x1F0007 }, };
@@ -1103,16 +1123,21 @@ static const struct of_device_id clk_gates_match[] __initconst = { {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,}, {.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,}, + {.compatible = "allwinner,sun9i-a80-ahb0-gates-clk", .data = &sun9i_a80_ahb0_gates_data,}, + {.compatible = "allwinner,sun9i-a80-ahb1-gates-clk", .data = &sun9i_a80_ahb1_gates_data,}, + {.compatible = "allwinner,sun9i-a80-ahb2-gates-clk", .data = &sun9i_a80_ahb2_gates_data,}, {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,}, + {.compatible = "allwinner,sun9i-a80-apb0-gates-clk", .data = &sun9i_a80_apb0_gates_data,}, {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,}, {.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,}, + {.compatible = "allwinner,sun9i-a80-apb1-gates-clk", .data = &sun9i_a80_apb1_gates_data,}, {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, {.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,}, {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
@@ -1201,3 +1226,9 @@ static void __init sun6i_init_clocks(struct device_node *node) }CLK_OF_DECLARE (sun6i_a31_clk_init,"allwinner,sun6i-a31" , sun6i_init_clocks);CLK_OF_DECLARE (sun8i_a23_clk_init,"allwinner,sun8i-a23" , sun6i_init_clocks); + +static void __init sun9i_init_clocks (struct device_node *node) +{ +sunxi_init_clocks (NULL ,0 ); +} +CLK_OF_DECLARE (sun9i_a80_clk_init,"allwinner,sun9i-a80" , sun9i_init_clocks);
Signature · 1 line
2.1.1
PATCH 4/5 ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for sun9i
In reply to Chen-Yu TsaiThe A80 SoC has reset controls matching bus clock gates.
--- arch/arm/mach-sunxi/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
arch/arm/mach-sunxi/Kconfig +2 -0
@@ -45,6 +45,8 @@ config MACH_SUN8I config MACH_SUN9I bool "Allwinner (sun9i) SoCs support" default ARCH_SUNXI + select ARCH_HAS_RESET_CONTROLLER select ARM_GIC + select RESET_CONTROLLER endif
Signature · 1 line
2.1.1
Maxime Ripard
AppliedPATCH 4/5 ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for sun9i
Quoted 3 lines · Chen-Yu Tsai
The A80 SoC has reset controls matching bus clock gates.
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/20141016/e62ea9fa/attachment.sig>
PATCH 5/5 ARM: dts: sun9i: Add basic clocks and reset controls
In reply to Chen-Yu TsaiNow that we have driver support for the basic clocks, add them to the dtsi and update existing peripherals. Also add reset controls to match.
--- arch/arm/boot/dts/sun9i-a80.dtsi | 177 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 171 insertions(+), 6 deletions(-)
arch/arm/boot/dts/sun9i-a80.dtsi +171 -6
@@ -142,6 +142,135 @@ clock-frequency = <32768>; clock-output-names = "osc32k"; }; + + pll4: clk at 0600000c { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-pll4-clk"; + reg = <0x0600000c 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll4"; + }; + + pll12: clk at 0600002c { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-pll4-clk"; + reg = <0x0600002c 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll12"; + }; + + gt_clk: clk at 0600005c { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-gt-clk"; + reg = <0x0600005c 0x4>; + clocks = <&osc24M>, <&pll4>, <&pll12>, <&pll12>; + clock-output-names = "gt"; + }; + + ahb0: clk at 06000060 { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-ahb-clk"; + reg = <0x06000060 0x4>; + clocks = <>_clk>, <&pll4>, <&pll12>, <&pll12>; + clock-output-names = "ahb0"; + }; + + ahb1: clk at 06000064 { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-ahb-clk"; + reg = <0x06000064 0x4>; + clocks = <>_clk>, <&pll4>, <&pll12>, <&pll12>; + clock-output-names = "ahb1"; + }; + + ahb2: clk at 06000068 { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-ahb-clk"; + reg = <0x06000068 0x4>; + clocks = <>_clk>, <&pll4>, <&pll12>, <&pll12>; + clock-output-names = "ahb2"; + }; + + apb0: clk at 06000070 { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-apb0-clk"; + reg = <0x06000070 0x4>; + clocks = <&osc24M>, <&pll4>; + clock-output-names = "apb0"; + }; + + apb1: clk at 06000074 { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-apb1-clk"; + reg = <0x06000074 0x4>; + clocks = <&osc24M>, <&pll4>; + clock-output-names = "apb1"; + }; + + cci400_clk: clk at 06000078 { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-gt-clk"; + reg = <0x06000078 0x4>; + clocks = <&osc24M>, <&pll4>, <&pll12>, <&pll12>; + clock-output-names = "cci400"; + }; + + ahb0_gates: clk at 06000580 { + #clock-cells = <1>; + compatible = "allwinner,sun9i-a80-ahb0-gates-clk"; + reg = <0x06000580 0x4>; + clocks = <&ahb0>; + clock-output-names = "ahb0_fd", "ahb0_ve", "ahb0_gpu", + "ahb0_ss", "ahb0_sd", "ahb0_nand1", + "ahb0_nand0", "ahb0_sdram", + "ahb0_mipi_hsi", "ahb0_sata", "ahb0_ts", + "ahb0_spi0","ahb0_spi1", "ahb0_spi2", + "ahb0_spi3"; + }; + + ahb1_gates: clk at 06000584 { + #clock-cells = <1>; + compatible = "allwinner,sun9i-a80-ahb1-gates-clk"; + reg = <0x06000584 0x4>; + clocks = <&ahb1>; + clock-output-names = "ahb1_usbotg", "ahb1_usbhci", + "ahb1_gmac", "ahb1_msgbox", + "ahb1_spinlock", "ahb1_hstimer", + "ahb1_dma"; + }; + + ahb2_gates: clk at 06000588 { + #clock-cells = <1>; + compatible = "allwinner,sun9i-a80-ahb2-gates-clk"; + reg = <0x06000588 0x4>; + clocks = <&ahb2>; + clock-output-names = "ahb2_lcd0", "ahb2_lcd1", + "ahb2_edp", "ahb2_csi", "ahb2_hdmi", + "ahb2_de", "ahb2_mp", "ahb2_mipi_dsi"; + }; + + apb0_gates: clk at 06000590 { + #clock-cells = <1>; + compatible = "allwinner,sun9i-a80-apb0-gates-clk"; + reg = <0x06000590 0x4>; + clocks = <&apb0>; + clock-output-names = "apb0_spdif", "apb0_pio", + "apb0_ac97", "apb0_i2s0", "apb0_i2s1", + "apb0_lradc", "apb0_gpadc", "apb0_twd", + "apb0_cirtx"; + }; + + apb1_gates: clk at 06000594 { + #clock-cells = <1>; + compatible = "allwinner,sun9i-a80-apb1-gates-clk"; + reg = <0x06000594 0x4>; + clocks = <&apb1>; + clock-output-names = "apb1_i2c0", "apb1_i2c1", + "apb1_i2c2", "apb1_i2c3", "apb1_i2c4", + "apb1_uart0", "apb1_uart1", + "apb1_uart2", "apb1_uart3", + "apb1_uart4", "apb1_uart5"; + }; }; soc {
@@ -165,6 +294,36 @@ interrupts = <1 9 0xf04>; }; + ahb0_resets: reset at 060005a0 { + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-clock-reset"; + reg = <0x060005a0 0x4>; + }; + + ahb1_resets: reset at 060005a4 { + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-clock-reset"; + reg = <0x060005a4 0x4>; + }; + + ahb2_resets: reset at 060005a8 { + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-clock-reset"; + reg = <0x060005a8 0x4>; + }; + + apb0_resets: reset at 060005b0 { + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-clock-reset"; + reg = <0x060005b0 0x4>; + }; + + apb1_resets: reset at 060005b4 { + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-clock-reset"; + reg = <0x060005b4 0x4>; + }; + timer at 06000c00 { compatible = "allwinner,sun4i-a10-timer"; reg = <0x06000c00 0xa0>;
@@ -184,7 +343,8 @@ interrupts = <0 0 4>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&osc24M>; + clocks = <&apb1_gates 16>; + resets = <&apb1_resets 16>; status = "disabled"; };
@@ -194,7 +354,8 @@ interrupts = <0 1 4>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&osc24M>; + clocks = <&apb1_gates 17>; + resets = <&apb1_resets 17>; status = "disabled"; };
@@ -204,7 +365,8 @@ interrupts = <0 2 4>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&osc24M>; + clocks = <&apb1_gates 18>; + resets = <&apb1_resets 18>; status = "disabled"; };
@@ -214,7 +376,8 @@ interrupts = <0 3 4>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&osc24M>; + clocks = <&apb1_gates 19>; + resets = <&apb1_resets 19>; status = "disabled"; };
@@ -224,7 +387,8 @@ interrupts = <0 4 4>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&osc24M>; + clocks = <&apb1_gates 20>; + resets = <&apb1_resets 20>; status = "disabled"; };
@@ -234,7 +398,8 @@ interrupts = <0 5 4>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&osc24M>; + clocks = <&apb1_gates 21>; + resets = <&apb1_resets 21>; status = "disabled"; };
Signature · 1 line
2.1.1
cover clk: sunxi: Add peripheral bus clock support for A80
In reply to Chen-Yu TsaiHi ChenYu,
Quoted 5 lines · Chen-Yu Tsai
Hi everyone,
This series adds support for the basic bus (AHB/APB) clocks used by peripherals on the A80 SoC. This series is based on my previous A80 bringup series.
Cool stuff, any chance you could write a quick howto for getting an upstream kernel to run on the Merrii A80 optimus board, for lazy / very busy people like me? Preferably including a link to an sdcard image which already has all the bootloader bits in place ?
Regards,
Hans
cover clk: sunxi: Add peripheral bus clock support for A80
Hi Hans,
Quoted 5 lines · Hans de Goede
Hi ChenYu,
Quoted 2 lines · Chen-Yu Tsai
Hi everyone,
Quoted 8 lines
Quoted 3 lines
This series adds support for the basic bus (AHB/APB) clocks used by peripherals on the A80 SoC. This series is based on my previous A80 bringup series.
Cool stuff, any chance you could write a quick howto for getting an upstream kernel to run on the Merrii A80 optimus board, for lazy / very busy people like me? Preferably including a link to an sdcard image which already has all the bootloader bits in place ?
I keep a short status report and howto on my user page on the linux-sunxi wiki:
http://linux-sunxi.org/User:Wens#A80_Optimus
I will try to expand it this week. Feel free to let me know if something is fuzzy or doesn't make sense.
ChenYu
cover clk: sunxi: Add peripheral bus clock support for A80
Quoted 17 lines · Chen-Yu Tsai
Hi Hans,
Quoted 5 lines · Hans de Goede
Hi ChenYu,
Quoted 2 lines · Chen-Yu Tsai
Hi everyone,
Quoted 8 lines
Quoted 3 lines
This series adds support for the basic bus (AHB/APB) clocks used by peripherals on the A80 SoC. This series is based on my previous A80 bringup series.
Cool stuff, any chance you could write a quick howto for getting an upstream kernel to run on the Merrii A80 optimus board, for lazy / very busy people like me? Preferably including a link to an sdcard image which already has all the bootloader bits in place ?
Quoted 8 lines
I keep a short status report and howto on my user page on the linux-sunxi wiki:
http://linux-sunxi.org/User:Wens#A80_Optimus
I will try to expand it this week. Feel free to let me know if something is fuzzy or doesn't make sense.
Hi ChenYu,
Any update on this? (quick howto to get upstream kernel to boot the A80)
Thanks,
Simos
cover clk: sunxi: Add peripheral bus clock support for A80
Quoted 22 lines · Simos Xenitellis
Quoted 21 lines · Chen-Yu Tsai
Hi Hans,
Quoted 5 lines · Hans de Goede
Hi ChenYu,
Quoted 2 lines · Chen-Yu Tsai
Hi everyone,
Quoted 8 lines
Quoted 3 lines
This series adds support for the basic bus (AHB/APB) clocks used by peripherals on the A80 SoC. This series is based on my previous A80 bringup series.
Cool stuff, any chance you could write a quick howto for getting an upstream kernel to run on the Merrii A80 optimus board, for lazy / very busy people like me? Preferably including a link to an sdcard image which already has all the bootloader bits in place ?
I keep a short status report and howto on my user page on the linux-sunxi wiki:
Quoted 8 lines
Quoted 4 lines
I will try to expand it this week. Feel free to let me know if something is fuzzy or doesn't make sense.
Hi ChenYu,
Any update on this? (quick howto to get upstream kernel to boot the A80)
Nothing has changed for the moment, mainly because I've been busy for the past month, and haven't tried anything else.
ChenYu