From: Zoltan Herpai Date: Sat, 4 Jan 2014 09:47:50 +0000 (+0000) Subject: sunxi: refresh clock framework X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=6b61e7786cb628939f7ee7c464eb186d525e0ab0;p=openwrt%2Fstaging%2Fmans0n.git sunxi: refresh clock framework Signed-off-by: Zoltan HERPAI SVN-Revision: 39186 --- diff --git a/target/linux/sunxi/patches-3.12/100-1-clk-sunxi_register_factors.patch b/target/linux/sunxi/patches-3.12/100-1-clk-sunxi_register_factors.patch new file mode 100644 index 0000000000..c949eeb69f --- /dev/null +++ b/target/linux/sunxi/patches-3.12/100-1-clk-sunxi_register_factors.patch @@ -0,0 +1,220 @@ +From 337d479970b0c8493ee3e8b8d89fb80ee39333a6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Sun, 5 May 2013 21:26:23 -0300 +Subject: [PATCH] clk: sunxi: register factors clocks behind composite +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit reworks factors clock registration to be done behind a +composite clock. This allows us to additionally add a gate, mux or +divisors, as it will be needed by some future PLLs. + +Signed-off-by: Emilio López +--- + drivers/clk/sunxi/clk-factors.c | 63 +-------------------------------------- + drivers/clk/sunxi/clk-factors.h | 16 +++++----- + drivers/clk/sunxi/clk-sunxi.c | 66 ++++++++++++++++++++++++++++++++++++++--- + 3 files changed, 72 insertions(+), 73 deletions(-) + +diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c +index 88523f9..6e3926c 100644 +--- a/drivers/clk/sunxi/clk-factors.c ++++ b/drivers/clk/sunxi/clk-factors.c +@@ -30,14 +30,6 @@ + * parent - fixed parent. No clk_set_parent support + */ + +-struct clk_factors { +- struct clk_hw hw; +- void __iomem *reg; +- struct clk_factors_config *config; +- void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); +- spinlock_t *lock; +-}; +- + #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) + + #define SETMASK(len, pos) (((-1U) >> (31-len)) << (pos)) +@@ -120,61 +112,8 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, + return 0; + } + +-static const struct clk_ops clk_factors_ops = { ++const struct clk_ops clk_factors_ops = { + .recalc_rate = clk_factors_recalc_rate, + .round_rate = clk_factors_round_rate, + .set_rate = clk_factors_set_rate, + }; +- +-/** +- * clk_register_factors - register a factors clock with +- * the clock framework +- * @dev: device registering this clock +- * @name: name of this clock +- * @parent_name: name of clock's parent +- * @flags: framework-specific flags +- * @reg: register address to adjust factors +- * @config: shift and width of factors n, k, m and p +- * @get_factors: function to calculate the factors for a given frequency +- * @lock: shared register lock for this clock +- */ +-struct clk *clk_register_factors(struct device *dev, const char *name, +- const char *parent_name, +- unsigned long flags, void __iomem *reg, +- struct clk_factors_config *config, +- void (*get_factors)(u32 *rate, u32 parent, +- u8 *n, u8 *k, u8 *m, u8 *p), +- spinlock_t *lock) +-{ +- struct clk_factors *factors; +- struct clk *clk; +- struct clk_init_data init; +- +- /* allocate the factors */ +- factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); +- if (!factors) { +- pr_err("%s: could not allocate factors clk\n", __func__); +- return ERR_PTR(-ENOMEM); +- } +- +- init.name = name; +- init.ops = &clk_factors_ops; +- init.flags = flags; +- init.parent_names = (parent_name ? &parent_name : NULL); +- init.num_parents = (parent_name ? 1 : 0); +- +- /* struct clk_factors assignments */ +- factors->reg = reg; +- factors->config = config; +- factors->lock = lock; +- factors->hw.init = &init; +- factors->get_factors = get_factors; +- +- /* register the clock */ +- clk = clk_register(dev, &factors->hw); +- +- if (IS_ERR(clk)) +- kfree(factors); +- +- return clk; +-} +diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h +index f49851c..02e1a43 100644 +--- a/drivers/clk/sunxi/clk-factors.h ++++ b/drivers/clk/sunxi/clk-factors.h +@@ -17,11 +17,13 @@ struct clk_factors_config { + u8 pwidth; + }; + +-struct clk *clk_register_factors(struct device *dev, const char *name, +- const char *parent_name, +- unsigned long flags, void __iomem *reg, +- struct clk_factors_config *config, +- void (*get_factors) (u32 *rate, u32 parent_rate, +- u8 *n, u8 *k, u8 *m, u8 *p), +- spinlock_t *lock); ++struct clk_factors { ++ struct clk_hw hw; ++ void __iomem *reg; ++ struct clk_factors_config *config; ++ void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); ++ spinlock_t *lock; ++}; ++ ++extern const struct clk_ops clk_factors_ops; + #endif +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 34ee69f..6aed57f 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -256,7 +256,11 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate, + * sunxi_factors_clk_setup() - Setup function for factor clocks + */ + ++#define SUNXI_FACTORS_MUX_MASK 0x3 ++ + struct factors_data { ++ int enable; ++ int mux; + struct clk_factors_config *table; + void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); + }; +@@ -307,16 +311,70 @@ static void __init sunxi_factors_clk_setup(struct device_node *node, + struct factors_data *data) + { + struct clk *clk; ++ struct clk_factors *factors; ++ struct clk_gate *gate; ++ struct clk_mux *mux; ++ struct clk_hw *gate_hw = NULL; ++ struct clk_hw *mux_hw = NULL; + const char *clk_name = node->name; +- const char *parent; ++ const char *parents[5]; + void *reg; ++ int i = 0; + + reg = of_iomap(node, 0); + +- parent = of_clk_get_parent_name(node, 0); ++ /* if we have a mux, we will have >1 parents */ ++ while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL) ++ i++; ++ ++ factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); ++ if (!factors) ++ return; ++ ++ /* Add a gate if this factor clock can be gated */ ++ if (data->enable) { ++ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); ++ if (!gate) { ++ kfree(factors); ++ return; ++ } ++ ++ /* set up gate properties */ ++ gate->reg = reg; ++ gate->bit_idx = data->enable; ++ gate->lock = &clk_lock; ++ gate_hw = &gate->hw; ++ } + +- clk = clk_register_factors(NULL, clk_name, parent, 0, reg, +- data->table, data->getter, &clk_lock); ++ /* Add a mux if this factor clock can be muxed */ ++ if (data->mux) { ++ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); ++ if (!mux) { ++ kfree(factors); ++ kfree(gate); ++ return; ++ } ++ ++ /* set up gate properties */ ++ mux->reg = reg; ++ mux->shift = data->mux; ++ mux->mask = SUNXI_FACTORS_MUX_MASK; ++ mux->lock = &clk_lock; ++ mux_hw = &mux->hw; ++ } ++ ++ /* set up factors properties */ ++ factors->reg = reg; ++ factors->config = data->table; ++ factors->get_factors = data->getter; ++ factors->lock = &clk_lock; ++ ++ clk = clk_register_composite(NULL, clk_name, ++ parents, i, ++ mux_hw, &clk_mux_ops, ++ &factors->hw, &clk_factors_ops, ++ gate_hw, &clk_gate_ops, ++ i ? 0 : CLK_IS_ROOT); + + if (!IS_ERR(clk)) { + of_clk_add_provider(node, of_clk_src_simple_get, clk); +-- +1.8.4 + diff --git a/target/linux/sunxi/patches-3.12/100-2-fix-off-by-one-masks.patch b/target/linux/sunxi/patches-3.12/100-2-fix-off-by-one-masks.patch new file mode 100644 index 0000000000..4dba064375 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/100-2-fix-off-by-one-masks.patch @@ -0,0 +1,33 @@ +From 04609953e11377c0705b0aba5c25ebdcbb9e4aa7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Thu, 5 Sep 2013 19:47:20 -0300 +Subject: [PATCH] clk: sunxi: factors: fix off-by-one masks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The previous code would generate one bit too long masks, and was +needlessly complicated. This patch replaces it by simpler code that can +generate the masks correctly. + +Signed-off-by: Emilio López +--- + drivers/clk/sunxi/clk-factors.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c +index 88523f9..5687ac9 100644 +--- a/drivers/clk/sunxi/clk-factors.c ++++ b/drivers/clk/sunxi/clk-factors.c +@@ -40,7 +40,7 @@ struct clk_factors { + + #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) + +-#define SETMASK(len, pos) (((-1U) >> (31-len)) << (pos)) ++#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos)) + #define CLRMASK(len, pos) (~(SETMASK(len, pos))) + #define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit)) + +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/100-3-clk-factors-clear-vars.patch b/target/linux/sunxi/patches-3.12/100-3-clk-factors-clear-vars.patch new file mode 100644 index 0000000000..a1323ea02d --- /dev/null +++ b/target/linux/sunxi/patches-3.12/100-3-clk-factors-clear-vars.patch @@ -0,0 +1,31 @@ +From 29aef2f23ca8c91bce0a356fd5f120404389125a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Thu, 5 Sep 2013 19:50:46 -0300 +Subject: [PATCH] clk: sunxi: factors: clear variables before using them +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Random bits may get into our factors if we don't clear n, k, m and p. + +Signed-off-by: Emilio López +--- + drivers/clk/sunxi/clk-factors.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c +index 5687ac9..f05207a 100644 +--- a/drivers/clk/sunxi/clk-factors.c ++++ b/drivers/clk/sunxi/clk-factors.c +@@ -88,7 +88,7 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, + static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) + { +- u8 n, k, m, p; ++ u8 n = 0, k = 0, m = 0, p = 0; + u32 reg; + struct clk_factors *factors = to_clk_factors(hw); + struct clk_factors_config *config = factors->config; +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/100-clk-sunxi_register_factors.patch b/target/linux/sunxi/patches-3.12/100-clk-sunxi_register_factors.patch deleted file mode 100644 index c949eeb69f..0000000000 --- a/target/linux/sunxi/patches-3.12/100-clk-sunxi_register_factors.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 337d479970b0c8493ee3e8b8d89fb80ee39333a6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Emilio=20L=C3=B3pez?= -Date: Sun, 5 May 2013 21:26:23 -0300 -Subject: [PATCH] clk: sunxi: register factors clocks behind composite -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This commit reworks factors clock registration to be done behind a -composite clock. This allows us to additionally add a gate, mux or -divisors, as it will be needed by some future PLLs. - -Signed-off-by: Emilio López ---- - drivers/clk/sunxi/clk-factors.c | 63 +-------------------------------------- - drivers/clk/sunxi/clk-factors.h | 16 +++++----- - drivers/clk/sunxi/clk-sunxi.c | 66 ++++++++++++++++++++++++++++++++++++++--- - 3 files changed, 72 insertions(+), 73 deletions(-) - -diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c -index 88523f9..6e3926c 100644 ---- a/drivers/clk/sunxi/clk-factors.c -+++ b/drivers/clk/sunxi/clk-factors.c -@@ -30,14 +30,6 @@ - * parent - fixed parent. No clk_set_parent support - */ - --struct clk_factors { -- struct clk_hw hw; -- void __iomem *reg; -- struct clk_factors_config *config; -- void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); -- spinlock_t *lock; --}; -- - #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) - - #define SETMASK(len, pos) (((-1U) >> (31-len)) << (pos)) -@@ -120,61 +112,8 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, - return 0; - } - --static const struct clk_ops clk_factors_ops = { -+const struct clk_ops clk_factors_ops = { - .recalc_rate = clk_factors_recalc_rate, - .round_rate = clk_factors_round_rate, - .set_rate = clk_factors_set_rate, - }; -- --/** -- * clk_register_factors - register a factors clock with -- * the clock framework -- * @dev: device registering this clock -- * @name: name of this clock -- * @parent_name: name of clock's parent -- * @flags: framework-specific flags -- * @reg: register address to adjust factors -- * @config: shift and width of factors n, k, m and p -- * @get_factors: function to calculate the factors for a given frequency -- * @lock: shared register lock for this clock -- */ --struct clk *clk_register_factors(struct device *dev, const char *name, -- const char *parent_name, -- unsigned long flags, void __iomem *reg, -- struct clk_factors_config *config, -- void (*get_factors)(u32 *rate, u32 parent, -- u8 *n, u8 *k, u8 *m, u8 *p), -- spinlock_t *lock) --{ -- struct clk_factors *factors; -- struct clk *clk; -- struct clk_init_data init; -- -- /* allocate the factors */ -- factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); -- if (!factors) { -- pr_err("%s: could not allocate factors clk\n", __func__); -- return ERR_PTR(-ENOMEM); -- } -- -- init.name = name; -- init.ops = &clk_factors_ops; -- init.flags = flags; -- init.parent_names = (parent_name ? &parent_name : NULL); -- init.num_parents = (parent_name ? 1 : 0); -- -- /* struct clk_factors assignments */ -- factors->reg = reg; -- factors->config = config; -- factors->lock = lock; -- factors->hw.init = &init; -- factors->get_factors = get_factors; -- -- /* register the clock */ -- clk = clk_register(dev, &factors->hw); -- -- if (IS_ERR(clk)) -- kfree(factors); -- -- return clk; --} -diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h -index f49851c..02e1a43 100644 ---- a/drivers/clk/sunxi/clk-factors.h -+++ b/drivers/clk/sunxi/clk-factors.h -@@ -17,11 +17,13 @@ struct clk_factors_config { - u8 pwidth; - }; - --struct clk *clk_register_factors(struct device *dev, const char *name, -- const char *parent_name, -- unsigned long flags, void __iomem *reg, -- struct clk_factors_config *config, -- void (*get_factors) (u32 *rate, u32 parent_rate, -- u8 *n, u8 *k, u8 *m, u8 *p), -- spinlock_t *lock); -+struct clk_factors { -+ struct clk_hw hw; -+ void __iomem *reg; -+ struct clk_factors_config *config; -+ void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); -+ spinlock_t *lock; -+}; -+ -+extern const struct clk_ops clk_factors_ops; - #endif -diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c -index 34ee69f..6aed57f 100644 ---- a/drivers/clk/sunxi/clk-sunxi.c -+++ b/drivers/clk/sunxi/clk-sunxi.c -@@ -256,7 +256,11 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate, - * sunxi_factors_clk_setup() - Setup function for factor clocks - */ - -+#define SUNXI_FACTORS_MUX_MASK 0x3 -+ - struct factors_data { -+ int enable; -+ int mux; - struct clk_factors_config *table; - void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); - }; -@@ -307,16 +311,70 @@ static void __init sunxi_factors_clk_setup(struct device_node *node, - struct factors_data *data) - { - struct clk *clk; -+ struct clk_factors *factors; -+ struct clk_gate *gate; -+ struct clk_mux *mux; -+ struct clk_hw *gate_hw = NULL; -+ struct clk_hw *mux_hw = NULL; - const char *clk_name = node->name; -- const char *parent; -+ const char *parents[5]; - void *reg; -+ int i = 0; - - reg = of_iomap(node, 0); - -- parent = of_clk_get_parent_name(node, 0); -+ /* if we have a mux, we will have >1 parents */ -+ while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL) -+ i++; -+ -+ factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); -+ if (!factors) -+ return; -+ -+ /* Add a gate if this factor clock can be gated */ -+ if (data->enable) { -+ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); -+ if (!gate) { -+ kfree(factors); -+ return; -+ } -+ -+ /* set up gate properties */ -+ gate->reg = reg; -+ gate->bit_idx = data->enable; -+ gate->lock = &clk_lock; -+ gate_hw = &gate->hw; -+ } - -- clk = clk_register_factors(NULL, clk_name, parent, 0, reg, -- data->table, data->getter, &clk_lock); -+ /* Add a mux if this factor clock can be muxed */ -+ if (data->mux) { -+ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); -+ if (!mux) { -+ kfree(factors); -+ kfree(gate); -+ return; -+ } -+ -+ /* set up gate properties */ -+ mux->reg = reg; -+ mux->shift = data->mux; -+ mux->mask = SUNXI_FACTORS_MUX_MASK; -+ mux->lock = &clk_lock; -+ mux_hw = &mux->hw; -+ } -+ -+ /* set up factors properties */ -+ factors->reg = reg; -+ factors->config = data->table; -+ factors->get_factors = data->getter; -+ factors->lock = &clk_lock; -+ -+ clk = clk_register_composite(NULL, clk_name, -+ parents, i, -+ mux_hw, &clk_mux_ops, -+ &factors->hw, &clk_factors_ops, -+ gate_hw, &clk_gate_ops, -+ i ? 0 : CLK_IS_ROOT); - - if (!IS_ERR(clk)) { - of_clk_add_provider(node, of_clk_src_simple_get, clk); --- -1.8.4 - diff --git a/target/linux/sunxi/patches-3.12/106-dt-sun7i-add-mod0-clk.patch b/target/linux/sunxi/patches-3.12/106-dt-sun7i-add-mod0-clk.patch new file mode 100644 index 0000000000..fbd30c65e7 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/106-dt-sun7i-add-mod0-clk.patch @@ -0,0 +1,136 @@ +From 8cf7164b32f2ce228b0c8116fd712484f67c65b5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Wed, 4 Sep 2013 21:28:49 -0300 +Subject: [PATCH] ARM: sun7i: dt: mod0 clocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit adds all the mod0 clocks available on A20 to its device +tree. This list was created by looking at AW's code release. + +Signed-off-by: Emilio López +Acked-by: Maxime Ripard +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 105 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 105 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 0af287e..0596e82 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -174,6 +174,111 @@ + "apb1_uart2", "apb1_uart3", "apb1_uart4", + "apb1_uart5", "apb1_uart6", "apb1_uart7"; + }; ++ ++ nand: nand@01c20080 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20080 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ms: ms@01c20084 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20084 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc0: mmc0@01c20088 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20088 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc1: mmc1@01c2008c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c2008c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc2: mmc2@01c20090 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20090 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc3: mmc3@01c20094 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20094 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ts: ts@01c20098 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20098 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ss: ss@01c2009c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c2009c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi0: spi0@01c200a0 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a0 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi1: spi1@01c200a4 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a4 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi2: spi2@01c200a8 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a8 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ pata: pata@01c200ac { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200ac 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ir0: ir0@01c200b0 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200b0 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ir1: ir1@01c200b4 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200b4 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi3: spi3@01c200d4 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200d4 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; + }; + + soc@01c00000 { +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/107-dt-sun5i-add-mod0-clk.patch b/target/linux/sunxi/patches-3.12/107-dt-sun5i-add-mod0-clk.patch new file mode 100644 index 0000000000..63fbdd1c70 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/107-dt-sun5i-add-mod0-clk.patch @@ -0,0 +1,198 @@ +From 0ae543fe8ae8b9ea7166c39b00e977506eccdf4b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Wed, 4 Sep 2013 21:21:16 -0300 +Subject: [PATCH] ARM: sun5i: dt: mod0 clocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit adds all the mod0 clocks available on A10 and A13. The list +has been constructed by looking at the Allwinner code release for A10S +and A13. + +Signed-off-by: Emilio López +Acked-by: Maxime Ripard +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 77 +++++++++++++++++++++++++++++++++++++++ + arch/arm/boot/dts/sun5i-a13.dtsi | 77 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 154 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 86e06e4..82b5ce6 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -173,6 +173,83 @@ + "apb1_i2c2", "apb1_uart0", "apb1_uart1", + "apb1_uart2", "apb1_uart3"; + }; ++ ++ nand: nand@01c20080 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20080 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ms: ms@01c20084 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20084 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc0: mmc0@01c20088 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20088 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc1: mmc1@01c2008c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c2008c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc2: mmc2@01c20090 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20090 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ts: ts@01c20098 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20098 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ss: ss@01c2009c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c2009c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi0: spi0@01c200a0 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a0 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi1: spi1@01c200a4 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a4 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi2: spi2@01c200a8 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a8 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ir0: ir0@01c200b0 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200b0 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; + }; + + soc@01c00000 { +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index cded3c7..938e6d3 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -170,6 +170,83 @@ + clock-output-names = "apb1_i2c0", "apb1_i2c1", + "apb1_i2c2", "apb1_uart1", "apb1_uart3"; + }; ++ ++ nand: nand@01c20080 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20080 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ms: ms@01c20084 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20084 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc0: mmc0@01c20088 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20088 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc1: mmc1@01c2008c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c2008c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc2: mmc2@01c20090 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20090 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ts: ts@01c20098 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20098 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ss: ss@01c2009c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c2009c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi0: spi0@01c200a0 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a0 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi1: spi1@01c200a4 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a4 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi2: spi2@01c200a8 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a8 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ir0: ir0@01c200b0 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200b0 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; + }; + + soc@01c00000 { +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/108-dt-sun4i-add-mod0-clk.patch b/target/linux/sunxi/patches-3.12/108-dt-sun4i-add-mod0-clk.patch new file mode 100644 index 0000000000..d72335bbad --- /dev/null +++ b/target/linux/sunxi/patches-3.12/108-dt-sun4i-add-mod0-clk.patch @@ -0,0 +1,135 @@ +From 5f554ea6757748c2fc45228030a20e08f6053ff7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Tue, 21 May 2013 21:28:32 -0300 +Subject: [PATCH] ARM: sun4i: dt: mod0 clocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit adds all the mod0 clocks present on sun4i to its device tree + +Signed-off-by: Emilio López +Acked-by: Maxime Ripard +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 105 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 105 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index ebacb5d..2828427e 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -184,6 +184,111 @@ + "apb1_uart4", "apb1_uart5", "apb1_uart6", + "apb1_uart7"; + }; ++ ++ nand: nand@01c20080 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20080 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ms: ms@01c20084 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20084 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc0: mmc0@01c20088 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20088 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc1: mmc1@01c2008c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c2008c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc2: mmc2@01c20090 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20090 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ mmc3: mmc3@01c20094 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20094 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ts: ts@01c20098 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c20098 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ss: ss@01c2009c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c2009c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi0: spi0@01c200a0 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a0 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi1: spi1@01c200a4 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a4 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi2: spi2@01c200a8 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a8 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ pata: pata@01c200ac { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200ac 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ir0: ir0@01c200b0 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200b0 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ ir1: ir1@01c200b4 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200b4 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; ++ ++ spi3: spi3@01c200d4 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200d4 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ }; + }; + + soc@01c00000 { +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/109-mach-sunxi-add-clkprovider.patch b/target/linux/sunxi/patches-3.12/109-mach-sunxi-add-clkprovider.patch new file mode 100644 index 0000000000..7ef6ea25d2 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/109-mach-sunxi-add-clkprovider.patch @@ -0,0 +1,11 @@ +diff -ruN old/arch/arm/mach-sunxi/sunxi.c new/arch/arm/mach-sunxi/sunxi.c +--- old/arch/arm/mach-sunxi/sunxi.c 2014-01-04 01:57:31.000000000 +0100 ++++ new/arch/arm/mach-sunxi/sunxi.c 2014-01-04 01:11:47.000000000 +0100 +@@ -10,6 +10,7 @@ + * warranty of any kind, whether express or implied. + */ + ++#include + #include + #include + #include diff --git a/target/linux/sunxi/patches-3.12/110-clk-sunxi-fix-pll5-6.patch b/target/linux/sunxi/patches-3.12/110-clk-sunxi-fix-pll5-6.patch new file mode 100644 index 0000000000..ad5935c89f --- /dev/null +++ b/target/linux/sunxi/patches-3.12/110-clk-sunxi-fix-pll5-6.patch @@ -0,0 +1,149 @@ +From 11e7ff129807394d87c937b880bb58972dc91fc0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Thu, 28 Nov 2013 09:00:47 -0300 +Subject: [PATCH] fixup! clk: sunxi: add PLL5 and PLL6 support + +--- + drivers/clk/sunxi/clk-sunxi.c | 83 +++++++++++++++++++++++++++++++++++-------- + 1 file changed, 69 insertions(+), 14 deletions(-) + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index d2b8d3c..3ce33b8 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -807,10 +807,11 @@ struct divs_data { + struct clk_div_table *table; /* is it a table based divisor? */ + u8 shift; /* otherwise it's a normal divisor with this shift */ + u8 pow; /* is it power-of-two based? */ ++ u8 gate; /* is it independently gateable? */ + } div[SUNXI_DIVS_MAX_QTY]; + }; + +-static struct clk_div_table pll6_sata_table[] = { ++static struct clk_div_table pll6_sata_tbl[] = { + { .val = 0, .div = 6, }, + { .val = 1, .div = 12, }, + { .val = 2, .div = 18, }, +@@ -829,7 +830,7 @@ struct divs_data { + static const struct divs_data pll6_divs_data __initconst = { + .factors = &sun4i_pll5_data, + .div = { +- { .shift = 0, .table = pll6_sata_table }, /* M, SATA */ ++ { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ + { .fixed = 2 }, /* P, other */ + } + }; +@@ -852,6 +853,11 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + const char *parent = node->name; + const char *clk_name; + struct clk **clks, *pclk; ++ struct clk_hw *gate_hw, *rate_hw; ++ const struct clk_ops *rate_ops; ++ struct clk_gate *gate = NULL; ++ struct clk_fixed_factor *fix_factor; ++ struct clk_divider *divider; + void *reg; + int i = 0; + int flags, clkflags; +@@ -866,10 +872,9 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + return; + + clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL); +- if (!clks) { +- kfree(clk_data); +- return; +- } ++ if (!clks) ++ goto free_clkdata; ++ + clk_data->clks = clks; + + /* It's not a good idea to have automatic reparenting changing +@@ -881,19 +886,60 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + i, &clk_name) != 0) + break; + ++ gate_hw = NULL; ++ rate_hw = NULL; ++ rate_ops = NULL; ++ ++ /* If this leaf clock can be gated, create a gate */ ++ if (data->div[i].gate) { ++ gate = kzalloc(sizeof(*gate), GFP_KERNEL); ++ if (!gate) ++ goto free_clks; ++ ++ gate->reg = reg; ++ gate->bit_idx = data->div[i].gate; ++ gate->lock = &clk_lock; ++ ++ gate_hw = &gate->hw; ++ } ++ ++ /* Leaves can be fixed or configurable divisors */ + if (data->div[i].fixed) { +- clks[i] = clk_register_fixed_factor(NULL, clk_name, +- parent, clkflags, +- 1, data->div[i].fixed); ++ fix_factor = kzalloc(sizeof(*fix_factor), GFP_KERNEL); ++ if (!fix_factor) ++ goto free_gate; ++ ++ fix_factor->mult = 1; ++ fix_factor->div = data->div[i].fixed; ++ ++ rate_hw = &fix_factor->hw; ++ rate_ops = &clk_fixed_factor_ops; + } else { ++ divider = kzalloc(sizeof(*divider), GFP_KERNEL); ++ if (!divider) ++ goto free_gate; ++ + flags = data->div[i].pow ? CLK_DIVIDER_POWER_OF_TWO : 0; +- clks[i] = clk_register_divider_table(NULL, clk_name, +- parent, clkflags, reg, +- data->div[i].shift, +- SUNXI_DIVISOR_WIDTH, flags, +- data->div[i].table, &clk_lock); ++ ++ divider->reg = reg; ++ divider->shift = data->div[i].shift; ++ divider->width = SUNXI_DIVISOR_WIDTH; ++ divider->flags = flags; ++ divider->lock = &clk_lock; ++ divider->table = data->div[i].table; ++ ++ rate_hw = ÷r->hw; ++ rate_ops = &clk_divider_ops; + } + ++ /* Wrap the (potential) gate and the divisor on a composite ++ * clock to unify them */ ++ clks[i] = clk_register_composite(NULL, clk_name, &parent, 1, ++ NULL, NULL, ++ rate_hw, rate_ops, ++ gate_hw, &clk_gate_ops, ++ clkflags); ++ + WARN_ON(IS_ERR(clk_data->clks[i])); + clk_register_clkdev(clks[i], clk_name, NULL); + } +@@ -905,6 +951,15 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + clk_data->clk_num = i; + + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ return; ++ ++free_gate: ++ kfree(gate); ++free_clks: ++ kfree(clks); ++free_clkdata: ++ kfree(clk_data); + } + + +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/111-clk-composite-determine-rate.patch b/target/linux/sunxi/patches-3.12/111-clk-composite-determine-rate.patch new file mode 100644 index 0000000000..0b4697a605 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/111-clk-composite-determine-rate.patch @@ -0,0 +1,74 @@ +From de7bfadd1022613ab2c7eeca124bb1e4a6f4c072 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Thu, 5 Sep 2013 19:43:33 -0300 +Subject: [PATCH] clk: composite: .determine_rate support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit adds .determine_rate support to the composite clock. It will +use the .determine_rate callback from the rate component if available, +and fall back on the mux component otherwise. This allows composite +clocks to enjoy the benefits of automatic clock reparenting. + +Signed-off-by: Emilio López +--- + drivers/clk/clk-composite.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c +index a33f46f..753d0b7 100644 +--- a/drivers/clk/clk-composite.c ++++ b/drivers/clk/clk-composite.c +@@ -55,6 +55,30 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, + return rate_ops->recalc_rate(rate_hw, parent_rate); + } + ++static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *best_parent_rate, ++ struct clk **best_parent_p) ++{ ++ struct clk_composite *composite = to_clk_composite(hw); ++ const struct clk_ops *rate_ops = composite->rate_ops; ++ const struct clk_ops *mux_ops = composite->mux_ops; ++ struct clk_hw *rate_hw = composite->rate_hw; ++ struct clk_hw *mux_hw = composite->mux_hw; ++ ++ if (rate_hw && rate_ops && rate_ops->determine_rate) { ++ rate_hw->clk = hw->clk; ++ return rate_ops->determine_rate(rate_hw, rate, best_parent_rate, ++ best_parent_p); ++ } else if (mux_hw && mux_ops && mux_ops->determine_rate) { ++ mux_hw->clk = hw->clk; ++ return mux_ops->determine_rate(rate_hw, rate, best_parent_rate, ++ best_parent_p); ++ } else { ++ pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n"); ++ return 0; ++ } ++} ++ + static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) + { +@@ -147,6 +171,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name, + composite->mux_ops = mux_ops; + clk_composite_ops->get_parent = clk_composite_get_parent; + clk_composite_ops->set_parent = clk_composite_set_parent; ++ if (mux_ops->determine_rate) ++ clk_composite_ops->determine_rate = clk_composite_determine_rate; + } + + if (rate_hw && rate_ops) { +@@ -170,6 +196,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name, + composite->rate_hw = rate_hw; + composite->rate_ops = rate_ops; + clk_composite_ops->recalc_rate = clk_composite_recalc_rate; ++ if (rate_ops->determine_rate) ++ clk_composite_ops->determine_rate = clk_composite_determine_rate; + } + + if (gate_hw && gate_ops) { +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/112-clk-sunxi-automatic-reparenting.patch b/target/linux/sunxi/patches-3.12/112-clk-sunxi-automatic-reparenting.patch new file mode 100644 index 0000000000..1ed5754b50 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/112-clk-sunxi-automatic-reparenting.patch @@ -0,0 +1,73 @@ +From 679e8db359d0c1994e88f3a4a2aa0697ce001ad4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Thu, 5 Sep 2013 19:52:41 -0300 +Subject: [PATCH] clk: sunxi: factors: automatic reparenting support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit implements .determine_rate, so that our factor clocks can be +reparented when needed. + +Signed-off-by: Emilio López +--- + drivers/clk/sunxi/clk-factors.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c +index 9e23264..3806d97 100644 +--- a/drivers/clk/sunxi/clk-factors.c ++++ b/drivers/clk/sunxi/clk-factors.c +@@ -77,6 +77,41 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, + return rate; + } + ++static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *best_parent_rate, ++ struct clk **best_parent_p) ++{ ++ struct clk *clk = hw->clk, *parent, *best_parent = NULL; ++ int i, num_parents; ++ unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0; ++ ++ /* find the parent that can help provide the fastest rate <= rate */ ++ num_parents = __clk_get_num_parents(clk); ++ for (i = 0; i < num_parents; i++) { ++ parent = clk_get_parent_by_index(clk, i); ++ if (!parent) ++ continue; ++ if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT) ++ parent_rate = __clk_round_rate(parent, rate); ++ else ++ parent_rate = __clk_get_rate(parent); ++ ++ child_rate = clk_factors_round_rate(hw, rate, &parent_rate); ++ ++ if (child_rate <= rate && child_rate > best_child_rate) { ++ best_parent = parent; ++ best = parent_rate; ++ best_child_rate = child_rate; ++ } ++ } ++ ++ if (best_parent) ++ *best_parent_p = best_parent; ++ *best_parent_rate = best; ++ ++ return best_child_rate; ++} ++ + static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) + { +@@ -113,6 +148,7 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, + } + + const struct clk_ops clk_factors_ops = { ++ .determine_rate = clk_factors_determine_rate, + .recalc_rate = clk_factors_recalc_rate, + .round_rate = clk_factors_round_rate, + .set_rate = clk_factors_set_rate, +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/113-clk-sunxi-unify-apb1.patch b/target/linux/sunxi/patches-3.12/113-clk-sunxi-unify-apb1.patch new file mode 100644 index 0000000000..951eaffa3d --- /dev/null +++ b/target/linux/sunxi/patches-3.12/113-clk-sunxi-unify-apb1.patch @@ -0,0 +1,63 @@ +From 75d3fa72634a4943f0f03146916094b6f4908552 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Sun, 8 Sep 2013 18:14:52 -0300 +Subject: [PATCH] clk: sunxi: unify APB1 clock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit unifies the APB1 mux with the APB1 clock, using the new +factors infrastructure. + +Signed-off-by: Emilio López +--- + Documentation/devicetree/bindings/clock/sunxi.txt | 1 - + drivers/clk/sunxi/clk-sunxi.c | 6 +----- + 2 files changed, 1 insertion(+), 6 deletions(-) + +diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt +index 46d8433..e840cb2 100644 +--- a/Documentation/devicetree/bindings/clock/sunxi.txt ++++ b/Documentation/devicetree/bindings/clock/sunxi.txt +@@ -27,7 +27,6 @@ Required properties: + "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s + "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 + "allwinner,sun4i-apb1-clk" - for the APB1 clock +- "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing + "allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10 + "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13 + "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 06c4f01..0ecaa18 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -400,6 +400,7 @@ struct factors_data { + }; + + static const struct factors_data sun4i_apb1_data __initconst = { ++ .mux = 24, + .table = &sun4i_apb1_config, + .getter = sun4i_get_apb1_factors, + }; +@@ -511,10 +512,6 @@ struct mux_data { + .shift = 12, + }; + +-static const struct mux_data sun4i_apb1_mux_data __initconst = { +- .shift = 24, +-}; +- + static void __init sunxi_mux_clk_setup(struct device_node *node, + struct mux_data *data) + { +@@ -869,7 +866,6 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + /* Matches for mux clocks */ + static const struct of_device_id clk_mux_match[] __initconst = { + {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,}, +- {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,}, + {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, + {} + }; +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/114-dt-unify-apb1.patch b/target/linux/sunxi/patches-3.12/114-dt-unify-apb1.patch new file mode 100644 index 0000000000..7652391cf3 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/114-dt-unify-apb1.patch @@ -0,0 +1,118 @@ +From f3443f6d43a69a520ae1e636d69a71c4a6bee21e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Sun, 8 Sep 2013 18:12:28 -0300 +Subject: [PATCH] ARM: sunxi: dt: unify APB1 clock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With the new factors infrastructure in place, we can unify apb1 and +apb1_mux as a single clock now. + +Signed-off-by: Emilio López +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 9 +-------- + arch/arm/boot/dts/sun5i-a10s.dtsi | 9 +-------- + arch/arm/boot/dts/sun5i-a13.dtsi | 9 +-------- + arch/arm/boot/dts/sun7i-a20.dtsi | 9 +-------- + 4 files changed, 4 insertions(+), 32 deletions(-) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 2828427e..4dccdb0 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -158,18 +158,11 @@ + "apb0_ir1", "apb0_keypad"; + }; + +- apb1_mux: apb1_mux@01c20058 { +- #clock-cells = <0>; +- compatible = "allwinner,sun4i-apb1-mux-clk"; +- reg = <0x01c20058 0x4>; +- clocks = <&osc24M>, <&pll6 1>, <&osc32k>; +- }; +- + apb1: apb1@01c20058 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-apb1-clk"; + reg = <0x01c20058 0x4>; +- clocks = <&apb1_mux>; ++ clocks = <&osc24M>, <&pll6 1>, <&osc32k>; + }; + + apb1_gates: apb1_gates@01c2006c { +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 60bd3f7..9cb1b14 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -150,18 +150,11 @@ + "apb0_ir", "apb0_keypad"; + }; + +- apb1_mux: apb1_mux@01c20058 { +- #clock-cells = <0>; +- compatible = "allwinner,sun4i-apb1-mux-clk"; +- reg = <0x01c20058 0x4>; +- clocks = <&osc24M>, <&pll6 1>, <&osc32k>; +- }; +- + apb1: apb1@01c20058 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-apb1-clk"; + reg = <0x01c20058 0x4>; +- clocks = <&apb1_mux>; ++ clocks = <&osc24M>, <&pll6 1>, <&osc32k>; + }; + + apb1_gates: apb1_gates@01c2006c { +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index 3e616a0..6b74dd0 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -148,18 +148,11 @@ + clock-output-names = "apb0_codec", "apb0_pio", "apb0_ir"; + }; + +- apb1_mux: apb1_mux@01c20058 { +- #clock-cells = <0>; +- compatible = "allwinner,sun4i-apb1-mux-clk"; +- reg = <0x01c20058 0x4>; +- clocks = <&osc24M>, <&pll6 1>, <&osc32k>; +- }; +- + apb1: apb1@01c20058 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-apb1-clk"; + reg = <0x01c20058 0x4>; +- clocks = <&apb1_mux>; ++ clocks = <&osc24M>, <&pll6 1>, <&osc32k>; + }; + + apb1_gates: apb1_gates@01c2006c { +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 0bf5d07..55d3e14 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -148,18 +148,11 @@ + "apb0_iis2", "apb0_keypad"; + }; + +- apb1_mux: apb1_mux@01c20058 { +- #clock-cells = <0>; +- compatible = "allwinner,sun4i-apb1-mux-clk"; +- reg = <0x01c20058 0x4>; +- clocks = <&osc24M>, <&pll6 1>, <&osc32k>; +- }; +- + apb1: apb1@01c20058 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-apb1-clk"; + reg = <0x01c20058 0x4>; +- clocks = <&apb1_mux>; ++ clocks = <&osc24M>, <&pll6 1>, <&osc32k>; + }; + + apb1_gates: apb1_gates@01c2006c { +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/115-clk-sunxi-muxable-ahb-clock.patch b/target/linux/sunxi/patches-3.12/115-clk-sunxi-muxable-ahb-clock.patch new file mode 100644 index 0000000000..3446b37c4d --- /dev/null +++ b/target/linux/sunxi/patches-3.12/115-clk-sunxi-muxable-ahb-clock.patch @@ -0,0 +1,102 @@ +From 147a46beeb49c6baabb85126d570f330a2ba7cad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Sat, 14 Sep 2013 20:48:40 -0300 +Subject: [PATCH] clk: sunxi: Implement muxable AHB clock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +sun5i and sun7i have a mux to change the AHB clock parent, this commit +adds support for it on the driver. + +Signed-off-by: Emilio López +--- + Documentation/devicetree/bindings/clock/sunxi.txt | 1 + + drivers/clk/sunxi/clk-sunxi.c | 37 +++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt +index e840cb2..941bd93 100644 +--- a/Documentation/devicetree/bindings/clock/sunxi.txt ++++ b/Documentation/devicetree/bindings/clock/sunxi.txt +@@ -15,6 +15,7 @@ Required properties: + "allwinner,sun4i-axi-clk" - for the AXI clock + "allwinner,sun4i-axi-gates-clk" - for the AXI gates + "allwinner,sun4i-ahb-clk" - for the AHB clock ++ "allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13 + "allwinner,sun4i-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 +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 0ecaa18..360d705 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -240,7 +240,32 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate, + *n = DIV_ROUND_UP(div, (*k+1)); + } + ++/** ++ * sun5i_get_ahb_factors() - calculates p factor for AHB ++ * AHB rate is calculated as follows ++ * rate = parent_rate >> p ++ */ + ++static void sun5i_a13_get_ahb_factors(u32 *freq, u32 parent_rate, ++ u8 *n, u8 *k, u8 *m, u8 *p) ++{ ++ u8 div; ++ ++ /* This clock can only divide, so we will never achieve a higher ++ * rate than the parent's */ ++ if (*freq > parent_rate) ++ *freq = parent_rate; ++ ++ /* Normalize value to a parent multiple */ ++ div = *freq / parent_rate; ++ *freq = parent_rate * div; ++ ++ /* we were called to round the frequency, we can now return */ ++ if (n == NULL) ++ return; ++ ++ *p = div; ++} + + /** + * sun4i_get_apb1_factors() - calculates m, p factors for APB1 +@@ -366,6 +391,11 @@ struct factors_data { + .kwidth = 2, + }; + ++static struct clk_factors_config sun5i_a13_ahb_config = { ++ .pshift = 4, ++ .pwidth = 2, ++}; ++ + static struct clk_factors_config sun4i_apb1_config = { + .mshift = 0, + .mwidth = 5, +@@ -399,6 +429,12 @@ struct factors_data { + .getter = sun4i_get_pll5_factors, + }; + ++static const struct factors_data sun5i_a13_ahb_data __initconst = { ++ .mux = 6, ++ .table = &sun5i_a13_ahb_config, ++ .getter = sun5i_a13_get_ahb_factors, ++}; ++ + static const struct factors_data sun4i_apb1_data __initconst = { + .mux = 24, + .table = &sun4i_apb1_config, +@@ -842,6 +878,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + static const struct of_device_id clk_factors_match[] __initconst = { + {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, + {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, ++ {.compatible = "allwinner,sun5i-a13-ahb-clk", .data = &sun5i_a13_ahb_data,}, + {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, + {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,}, + {} +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/116-dt-update-ahb-clock.patch b/target/linux/sunxi/patches-3.12/116-dt-update-ahb-clock.patch new file mode 100644 index 0000000000..3d48a608de --- /dev/null +++ b/target/linux/sunxi/patches-3.12/116-dt-update-ahb-clock.patch @@ -0,0 +1,69 @@ +From 051f43def45e53d93b9998728e398a68c4948114 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Sat, 14 Sep 2013 20:44:03 -0300 +Subject: [PATCH] ARM: sunxi: dt: Update AHB clock to be muxable on sun[57]i +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +sun5i and sun7i have a mux to select the parent clock for AHB. This +commit implements the required changes on the device trees. + +Signed-off-by: Emilio López +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 4 ++-- + arch/arm/boot/dts/sun5i-a13.dtsi | 4 ++-- + arch/arm/boot/dts/sun7i-a20.dtsi | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 9cb1b14..83e183c 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -115,9 +115,9 @@ + + ahb: ahb@01c20054 { + #clock-cells = <0>; +- compatible = "allwinner,sun4i-ahb-clk"; ++ compatible = "allwinner,sun5i-a13-ahb-clk"; + reg = <0x01c20054 0x4>; +- clocks = <&axi>; ++ clocks = <&axi>, <&cpu>, <&pll6 1>; + }; + + ahb_gates: ahb_gates@01c20060 { +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index 6b74dd0..0bb4300 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -115,9 +115,9 @@ + + ahb: ahb@01c20054 { + #clock-cells = <0>; +- compatible = "allwinner,sun4i-ahb-clk"; ++ compatible = "allwinner,sun5i-a13-ahb-clk"; + reg = <0x01c20054 0x4>; +- clocks = <&axi>; ++ clocks = <&axi>, <&cpu>, <&pll6 1>; + }; + + ahb_gates: ahb_gates@01c20060 { +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 55d3e14..63757c5 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -105,9 +105,9 @@ + + ahb: ahb@01c20054 { + #clock-cells = <0>; +- compatible = "allwinner,sun4i-ahb-clk"; ++ compatible = "allwinner,sun5i-a13-ahb-clk"; + reg = <0x01c20054 0x4>; +- clocks = <&axi>; ++ clocks = <&axi>, <&pll6 1>, <&pll6 2>; + }; + + ahb_gates: ahb_gates@01c20060 { +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/117-clk-sunxi-declare-OF-provider.patch b/target/linux/sunxi/patches-3.12/117-clk-sunxi-declare-OF-provider.patch new file mode 100644 index 0000000000..296e0e478d --- /dev/null +++ b/target/linux/sunxi/patches-3.12/117-clk-sunxi-declare-OF-provider.patch @@ -0,0 +1,108 @@ +From be0804513a506de96925f9ed1aa8dc1facd4c180 Mon Sep 17 00:00:00 2001 +From: Sebastian Hesselbarth +Date: Fri, 6 Sep 2013 14:59:57 +0200 +Subject: [PATCH] clk: sunxi: declare OF clock provider + +Common clock framework allows to register clock providers to get called +on of_clk_init() by using CLK_OF_DECLARE. This converts sunxi clock +providers to make use of it and get rid of the mach specific clk init +call. As sunxi has a bunch of independent clk provider nodes, we hook +current clock init to board compatible to make it called once. + +Signed-off-by: Sebastian Hesselbarth +Acked-by: Maxime Ripard +Acked-by: Mike Turquette +--- + arch/arm/mach-sunxi/sunxi.c | 4 +--- + drivers/clk/sunxi/clk-sunxi.c | 11 ++++++----- + include/linux/clk/sunxi.h | 22 ---------------------- + 3 files changed, 7 insertions(+), 30 deletions(-) + delete mode 100644 include/linux/clk/sunxi.h + +diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c +index e79fb34..e5a6975 100644 +--- a/arch/arm/mach-sunxi/sunxi.c ++++ b/arch/arm/mach-sunxi/sunxi.c +@@ -20,8 +20,6 @@ + #include + #include + +-#include +- + #include + #include + #include +@@ -118,7 +116,7 @@ static void sunxi_setup_restart(void) + + static void __init sunxi_timer_init(void) + { +- sunxi_init_clocks(); ++ of_clk_init(NULL); + clocksource_of_init(); + } + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 34ee69f..9bbd035 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -16,7 +16,6 @@ + + #include + #include +-#include + #include + #include + +@@ -617,11 +616,8 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat + } + } + +-void __init sunxi_init_clocks(void) ++static void __init sunxi_init_clocks(struct device_node *np) + { +- /* Register all the simple and basic clocks on DT */ +- of_clk_init(NULL); +- + /* Register factor clocks */ + of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); + +@@ -634,3 +630,8 @@ void __init sunxi_init_clocks(void) + /* Register gate clocks */ + of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup); + } ++CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks); ++CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks); ++CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sunxi_init_clocks); ++CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sunxi_init_clocks); ++CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sunxi_init_clocks); +diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h +deleted file mode 100644 +index e074fdd..0000000 +--- a/include/linux/clk/sunxi.h ++++ /dev/null +@@ -1,22 +0,0 @@ +-/* +- * Copyright 2012 Maxime Ripard +- * +- * Maxime Ripard +- * +- * 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. +- */ +- +-#ifndef __LINUX_CLK_SUNXI_H_ +-#define __LINUX_CLK_SUNXI_H_ +- +-void __init sunxi_init_clocks(void); +- +-#endif +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/118-sunxi-clk-core-clock-protect.patch b/target/linux/sunxi/patches-3.12/118-sunxi-clk-core-clock-protect.patch new file mode 100644 index 0000000000..50536d1a1e --- /dev/null +++ b/target/linux/sunxi/patches-3.12/118-sunxi-clk-core-clock-protect.patch @@ -0,0 +1,67 @@ +From d1bcc34ce6cb7601ce27f3090aee0e8a3e8076e3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Sat, 14 Sep 2013 20:54:42 -0300 +Subject: [PATCH] clk: sunxi: protect core clocks from accidental shutdown +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some important clocks may get disabled as a side effect of another clock +being disabled, because they have no consumers. This patch implements a +mechanism so those clocks can be claimed by the driver and therefore +remain enabled at all times. + +Signed-off-by: Emilio López +--- + drivers/clk/sunxi/clk-sunxi.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 9bbd035..8fc1375 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -616,6 +616,31 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat + } + } + ++/** ++ * System clock protection ++ * ++ * By enabling these critical clocks, we prevent their accidental gating ++ * by the framework ++ */ ++static void __init sunxi_clock_protect(void) ++{ ++ struct clk *clk; ++ ++ /* memory bus clock - sun5i+ */ ++ clk = clk_get(NULL, "mbus"); ++ if (!IS_ERR(clk)) { ++ clk_prepare_enable(clk); ++ clk_put(clk); ++ } ++ ++ /* DDR clock - sun4i+ */ ++ clk = clk_get(NULL, "pll5_ddr"); ++ if (!IS_ERR(clk)) { ++ clk_prepare_enable(clk); ++ clk_put(clk); ++ } ++} ++ + static void __init sunxi_init_clocks(struct device_node *np) + { + /* Register factor clocks */ +@@ -629,6 +654,9 @@ static void __init sunxi_init_clocks(struct device_node *np) + + /* Register gate clocks */ + of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup); ++ ++ /* Enable core system clocks */ ++ sunxi_clock_protect(); + } + CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks); + CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks); +-- +1.8.5.1 +