clk: sunxi: add PLL5 and PLL6 support
Subsystems (4)
Emilio López
maintainerv3 cover clk: sunxi: add PLL5 and PLL6 support
Hi everyone,
This is v3 of the sunxi clock series. For those seeing this for the first time, it adds PLL4, PLL5, PLL6 and mod0 clock support on sun4i, sun5i and sun7i. Additionally, mbus is supported on sun5i and sun7i. I would like to see this merged for 3.14 as clock users are progressing rapidly and will be needing this code, so all feedback is appreciated.
v2 -> v3 changelog:
* clean magic 5 on parent char arrays
* drop special consideration for pll5, as the clock protection function should be enough to keep that clock enabled.
* rework the mod0 and mbus nodes as suggested by Maxime, and add a bit of code to keep the old nodes working.
* add Acked-by tags from Mike
Cheers,
Emilio
Emilio L?pez (13):
clk: sunxi: register factors clocks behind composite
clk: sunxi: clean the magic number of mux parents
clk: sunxi: add gating support to PLL1
ARM: sunxi: add PLL4 support
clk: sunxi: make factors_clk_setup return the clock it registers
clk: sunxi: add PLL5 and PLL6 support
ARM: sunxi: add PLL5 and PLL6 support
clk: sunxi: mod0 support
clk: sunxi: support better factor DT nodes
ARM: sun4i: dt: mod0 clocks
ARM: sun5i: dt: mod0 clocks
ARM: sun7i: dt: mod0 clocks
ARM: sunxi: dt: add nodes for the mbus clock
Documentation/devicetree/bindings/clock/sunxi.txt | 9 +- arch/arm/boot/dts/sun4i-a10.dtsi | 146 ++++++++- arch/arm/boot/dts/sun5i-a10s.dtsi | 122 ++++++- arch/arm/boot/dts/sun5i-a13.dtsi | 122 ++++++- arch/arm/boot/dts/sun7i-a20.dtsi | 161 ++++++++- drivers/clk/sunxi/clk-factors.c | 63 +--- drivers/clk/sunxi/clk-factors.h | 16 +- drivers/clk/sunxi/clk-sunxi.c | 378 +++++++++++++++++++++- 8 files changed, 921 insertions(+), 96 deletions(-)
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 1/13 clk: sunxi: register factors clocks behind composite
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.
--- drivers/clk/sunxi/clk-factors.c | 63 +------------------------------------ drivers/clk/sunxi/clk-factors.h | 16 +++++----- drivers/clk/sunxi/clk-sunxi.c | 70 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 76 insertions(+), 73 deletions(-)
drivers/clk/sunxi/clk-factors.c +1 -62
@@ -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 << (len)) - 1) << (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; -}
drivers/clk/sunxi/clk-factors.h +9 -7
@@ -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
drivers/clk/sunxi/clk-sunxi.c +66 -4
95 lines not on this page · raw message
Signature · 1 line
1.8.5.2
PATCH v3 1/13 clk: sunxi: register factors clocks behind composite
Hello Emilio, Mike,
Quoted 211 lines · Emilio L?pez
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 <[email protected]>Acked-by Maxime Ripard <[email protected]>--- drivers/clk/sunxi/clk-factors.c | 63 +------------------------------------ drivers/clk/sunxi/clk-factors.h | 16 +++++----- drivers/clk/sunxi/clk-sunxi.c | 70 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 76 insertions(+), 73 deletions(-)drivers/clk/sunxi/clk-factors.c +1
-62@@ -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 << (len)) - 1) << (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; -}drivers/clk/sunxi/clk-factors.h +9
-7@@ -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 drivers/clk/sunxi/clk-sunxi.c +60
-2@@ -23,6 +23,9 @@static DEFINE_SPINLOCK (clk_lock); +/* Maximum number of parents our clocks have */ +#define SUNXI_MAX_PARENTS 5 +/** * sun4i_osc_clk_setup() - Setup function for gatable oscillator */ @@ -255,7 +258,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); };@@ -306,16 +313,71 @@ 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 =NULL ; +struct clk_mux *mux =NULL ; +struct clk_hw *gate_hw =NULL ; +struct clk_hw *mux_hw =NULL ;const char *clk_name = node->name; -const char *parent; +const char *parents[SUNXI_MAX_PARENTS ];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 <SUNXI_MAX_PARENTS && + (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; + } + +/* 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;
drivers/clk/sunxi/clk-sunxi.c static void __init sunxi_factors_clk_setup(struct device_node *node, · line 381
Quoted 10 lines
drivers/clk/sunxi/clk-sunxi.c +6
-2- clk =clk_register_factors (NULL , clk_name, parent,0 , reg, - data->table, data->getter, &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 );
I'm currently working on the sunxi NFC (Nand Flash Controller) driver and I need to set the NAND clk (which is a mod0 clk type) rate.
It seems that the composite clk fallbacks to the mux_hw's determine_rate instead of calling the rate_hw's (or factors hw) round_rate, if rate_hw does not implement determine_rate.
In the sunxi specific case, this leads to a DIV by 0 error when later calling set_rate on this composite clk, because the requested freq is set to 0 (result from mux_hw determine_rate):
[ 0.632125] Division by zero in kernel. [ 0.635970] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.13.0-rc1-00005-ge2b2be1-dirty #203 [ 0.644230] [<c00139bc>] (unwind_backtrace+0x0/0xf8) from [<c0010fb8>] (show_stack+0x10/0x14) [ 0.652765] [<c0010fb8>] (show_stack+0x10/0x14) from [<c029276c>] (dump_stack+0x68/0x84) [ 0.660861] [<c029276c>] (dump_stack+0x68/0x84) from [<c015e8b0>] (Ldiv0+0x8/0x10) [ 0.668438] [<c015e8b0>] (Ldiv0+0x8/0x10) from [<c020d63c>] (sun4i_get_mod0_factors+0x6c/0xa8) [ 0.677057] [<c020d63c>] (sun4i_get_mod0_factors+0x6c/0xa8) from [<c020d87c>] (clk_factors_set_rate+0x50/0x138) [ 0.687149] [<c020d87c>] (clk_factors_set_rate+0x50/0x138) from [<c020cf18>] (clk_composite_set_rate+0x20/0x24) [ 0.697241] [<c020cf18>] (clk_composite_set_rate+0x20/0x24) from [<c020b538>] (clk_change_rate+0x5c/0xf8) [ 0.706812] [<c020b538>] (clk_change_rate+0x5c/0xf8) from [<c020b64c>] (clk_set_rate+0x78/0xb0) [ 0.715518] [<c020b64c>] (clk_set_rate+0x78/0xb0) from [<c01cc370>] (sunxi_nfc_probe+0x1ec/0x5e0) [ 0.724383] [<c01cc370>] (sunxi_nfc_probe+0x1ec/0x5e0) from [<c01b50d4>] (platform_drv_probe+0x18/0x48) [ 0.733779] [<c01b50d4>] (platform_drv_probe+0x18/0x48) from [<c01b37f0>] (driver_probe_device+0x100/0x210) [ 0.743521] [<c01b37f0>] (driver_probe_device+0x100/0x210) from [<c01b398c>] (__driver_attach+0x8c/0x90) [ 0.753005] [<c01b398c>] (__driver_attach+0x8c/0x90) from [<c01b2178>] (bus_for_each_dev+0x54/0x88) [ 0.762058] [<c01b2178>] (bus_for_each_dev+0x54/0x88) from [<c01b2fd4>] (bus_add_driver+0xd8/0x1cc) [ 0.771108] [<c01b2fd4>] (bus_add_driver+0xd8/0x1cc) from [<c01b3fc8>] (driver_register+0x78/0xf4) [ 0.780069] [<c01b3fc8>] (driver_register+0x78/0xf4) from [<c00087c8>] (do_one_initcall+0x38/0x160) [ 0.789118] [<c00087c8>] (do_one_initcall+0x38/0x160) from [<c0372bc0>] (kernel_init_freeable+0xfc/0x1c8) [ 0.798688] [<c0372bc0>] (kernel_init_freeable+0xfc/0x1c8) from [<c028fd00>] (kernel_init+0x8/0x110) [ 0.807825] [<c028fd00>] (kernel_init+0x8/0x110) from [<c000e2b8>]
(ret_from_fork+0x14/0x3c)
We should definitely check the requested freq and gracefully handle the 0 case.
But anyway, I think there is a drawback in the way composite clk implement the determine_rate handler.
Mike, shouldn't we choose the best parent (using mux) fullfilling the rate_hw needs ?
I'll post a proposal...
Best Regards,
Boris
Quoted 3 lines
drivers/clk/sunxi/clk-sunxi.c +0
-0if (!IS_ERR (clk)) {of_clk_add_provider (node, of_clk_src_simple_get, clk);
Emilio López
maintainerPATCH v3 1/13 clk: sunxi: register factors clocks behind composite
Hi Boris,
[ Apologies if the email looks weird and for using a link; I'm not using my typical email client ]
Quoted 6 lines
I'm currently working on the sunxi NFC (Nand Flash Controller) driver and I need to set the NAND clk (which is a mod0 clk type) rate.
It seems that the composite clk fallbacks to the mux_hw's
determine_rateinstead of calling the rate_hw's (or factors hw)round_rate, ifrate_hwdoes not implementdetermine_rate.
That is to be expected; if you have a composite clock that has all fixed parents you'd not implement the determine_rate on the rate component but on the mux one.
(...)
Quoted 4 lines
But anyway, I think there is a drawback in the way composite clk implement the
determine_ratehandler.
Mike, shouldn't we choose the best parent (using mux) fullfilling therate_hwneeds ?
Someone using the composite clock may not want their clocks to start changing parents though. I believe it's easier and better to just implement determine_rate as on this patch on my tree (which I haven't sent yet, but it's literally the next in queue.)
http://git.elopez.com.ar/linux/commits/5b4eb3ac406b9c98965714d40e8dd6da943d1ab0
Let me know if that resolves your issue.
Cheers,
Emilio
PATCH v3 1/13 clk: sunxi: register factors clocks behind composite
"Emilio L?pez" <[email protected]> a ?crit?:
Quoted 9 lines
Hi Boris,
[ Apologies if the email looks weird and for using a link; I'm not using my typical email client ]
Quoted 4 lines
I'm currently working on the sunxi NFC (Nand Flash Controller) driver and I need to set the NAND clk (which is a mod0 clk type) rate.
It seems that the composite clk fallbacks to the mux_hw's
Quoted 9 lines
determine_rateQuoted 1 line
instead of calling the rate_hw's (or factors hw)
round_rate, if
rate_hwQuoted 1 line
does not implement
determine_rate.That is to be expected; if you have a composite clock that has all fixed parents you'd not implement the
determine_rateon the rate component but on the mux one.
Right, but this is not the case for mod0
clks, is it ?
Quoted 7 lines
(...)
Quoted 4 lines
But anyway, I think there is a drawback in the way composite clk implement the
determine_ratehandler.
Mike, shouldn't we choose the best parent (using mux) fullfilling therate_hwneeds ?
Quoted 5 lines
Someone using the composite clock may not want their clocks to start changing parents though. I believe it's easier and better to just implement
determine_rateas on this patch on my tree (which I haven't sent yet, but it's literally the next in queue.)
Fair enough (I did pretty much the same thing in my first attempt to fix this bug ;-))
Quoted 3 lines
http://git.elopez.com.ar/linux/commits/5b4eb3ac406b9c98965714d40e8dd6da943d1ab0
Let me know if that resolves your issue.
I'll try it tomorrow.
BTW, I managed to get a working NAND driver (without DMA and hw ECC).
I'll post it on the ML soon (just need to clean it up a little bit).
Best regards,
Boris
Quoted 4 lines
Cheers,
Emilio
PATCH v3 1/13 clk: sunxi: register factors clocks behind composite
In reply to Emilio LópezQuoted 21 lines · Emilio L?pez
Hi Boris,
[ Apologies if the email looks weird and for using a link; I'm not using my typical email client ]
Quoted 6 lines
I'm currently working on the sunxi NFC (Nand Flash Controller) driver and I need to set the NAND clk (which is a mod0 clk type) rate.
It seems that the composite clk fallbacks to the mux_hw's
determine_rateinstead of calling the rate_hw's (or factors hw)round_rate, ifrate_hwdoes not implementdetermine_rate.That is to be expected; if you have a composite clock that has all fixed parents you'd not implement the
determine_rateon the rate component but on the mux one.(...)
Quoted 4 lines
But anyway, I think there is a drawback in the way composite clk implement the
determine_ratehandler.
Mike, shouldn't we choose the best parent (using mux) fullfilling therate_hwneeds ?
Quoted 8 lines
Someone using the composite clock may not want their clocks to start changing parents though. I believe it's easier and better to just implement
determine_rateas on this patch on my tree (which I haven't sent yet, but it's literally the next in queue.)http://git.elopez.com.ar/linux/commits/5b4eb3ac406b9c98965714d40e8dd6da943d1ab0
Let me know if that resolves your issue.
Yes, it works.
Thanks.
Can you submit it on LAKML so that I can state the dependency in my NFC driver series ?
Best Regards,
Boris
Quoted 4 lines
Cheers,
Emilio
RFC PATCH 1/1 clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent
In reply to Emilio LópezIn case the rate_hw does not implement determine_rate, but only round_rate we fallback to best_parent selection if mux_hw is present and support reparenting.
--- drivers/clk/clk-composite.c | 49 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-)
drivers/clk/clk-composite.c +48 -1
@@ -64,11 +64,57 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,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; +struct clk *parent; +unsigned long parent_rate; +long tmp_rate; +unsigned long rate_diff; +unsigned long best_rate_diff =ULONG_MAX ; +int i;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 (rate_hw && rate_ops && rate_ops->round_rate && + mux_hw && mux_ops && mux_ops->set_parent) { + *best_parent_p =NULL ; + +if (__clk_get_flags (hw->clk) &CLK_SET_RATE_NO_REPARENT ) { + *best_parent_p =clk_get_parent (mux_hw->clk); + *best_parent_rate =__clk_get_rate (*best_parent_p); + +return rate_ops->round_rate (rate_hw, rate, + best_parent_rate); + } + +for (i =0 ; i <__clk_get_num_parents (mux_hw->clk); i++) { + parent =clk_get_parent_by_index (mux_hw->clk, i); +if (!parent) +continue ; + + parent_rate =__clk_get_rate (parent); + + tmp_rate = rate_ops->round_rate (rate_hw, rate, + &parent_rate); +if (tmp_rate <0 ) +continue ; + +if (tmp_rate < rate) + rate_diff = rate - tmp_rate; +else + rate_diff = tmp_rate - rate; + +if (!rate_diff || !*best_parent_p || best_rate_diff > rate_diff) { + *best_parent_p = parent; + *best_parent_rate = parent_rate; + best_rate_diff = rate_diff; + } + +if (!rate_diff) +return rate; + } + +return best_rate_diff; }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,
@@ -196,7 +242,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) +if (rate_ops->determine_rate || + (rate_ops->round_rate && clk_composite_ops->set_parent)) clk_composite_ops->determine_rate = clk_composite_determine_rate; }
Signature · 1 line
1.7.9.5
RFC PATCH 1/1 clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent
In reply to Emilio LópezIn case the rate_hw does not implement determine_rate, but only round_rate we fallback to best_parent selection if mux_hw is present and support reparenting.
--- drivers/clk/clk-composite.c | 49 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-)
drivers/clk/clk-composite.c +48 -1
@@ -64,11 +64,57 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,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; +struct clk *parent; +unsigned long parent_rate; +long tmp_rate; +unsigned long rate_diff; +unsigned long best_rate_diff =ULONG_MAX ; +int i;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 (rate_hw && rate_ops && rate_ops->round_rate && + mux_hw && mux_ops && mux_ops->set_parent) { + *best_parent_p =NULL ; + +if (__clk_get_flags (hw->clk) &CLK_SET_RATE_NO_REPARENT ) { + *best_parent_p =clk_get_parent (mux_hw->clk); + *best_parent_rate =__clk_get_rate (*best_parent_p); + +return rate_ops->round_rate (rate_hw, rate, + best_parent_rate); + } + +for (i =0 ; i <__clk_get_num_parents (mux_hw->clk); i++) { + parent =clk_get_parent_by_index (mux_hw->clk, i); +if (!parent) +continue ; + + parent_rate =__clk_get_rate (parent); + + tmp_rate = rate_ops->round_rate (rate_hw, rate, + &parent_rate); +if (tmp_rate <0 ) +continue ; + +if (tmp_rate < rate) + rate_diff = rate - tmp_rate; +else + rate_diff = tmp_rate - rate; + +if (!rate_diff || !*best_parent_p || best_rate_diff > rate_diff) { + *best_parent_p = parent; + *best_parent_rate = parent_rate; + best_rate_diff = rate_diff; + } + +if (!rate_diff) +return rate; + } + +return best_rate_diff; }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,
@@ -196,7 +242,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) +if (rate_ops->determine_rate || + (rate_ops->round_rate && clk_composite_ops->set_parent)) clk_composite_ops->determine_rate = clk_composite_determine_rate; }
Signature · 1 line
1.7.9.5
RFC PATCH 1/1 clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent
Quoting Boris BREZILLON (2014-01-07 09:03:52)
Quoted 5 lines
In case the
rate_hwdoes not implementdetermine_rate, but onlyround_ratewe fallback tobest_parentselection ifmux_hwis present and support reparenting.Signed-off-by Boris BREZILLON <[email protected]>
Hi Boris,
Since this change affects users of the composite clock type I will hold off reviewing/applying this patch until after the merge window.
Thanks,
Mike
Quoted 79 lines
--- drivers/clk/clk-composite.c | 49 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-)drivers/clk/clk-composite.c +48
-1@@ -64,11 +64,57 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,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; +struct clk *parent; +unsigned long parent_rate; +long tmp_rate; +unsigned long rate_diff; +unsigned long best_rate_diff =ULONG_MAX ; +int i;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 (rate_hw && rate_ops && rate_ops->round_rate && + mux_hw && mux_ops && mux_ops->set_parent) { + *best_parent_p =NULL ; + +if (__clk_get_flags (hw->clk) &CLK_SET_RATE_NO_REPARENT ) { + *best_parent_p =clk_get_parent (mux_hw->clk); + *best_parent_rate =__clk_get_rate (*best_parent_p); + +return rate_ops->round_rate (rate_hw, rate, + best_parent_rate); + } + +for (i =0 ; i <__clk_get_num_parents (mux_hw->clk); i++) { + parent =clk_get_parent_by_index (mux_hw->clk, i); +if (!parent) +continue ; + + parent_rate =__clk_get_rate (parent); + + tmp_rate = rate_ops->round_rate (rate_hw, rate, + &parent_rate); +if (tmp_rate <0 ) +continue ; + +if (tmp_rate < rate) + rate_diff = rate - tmp_rate; +else + rate_diff = tmp_rate - rate; + +if (!rate_diff || !*best_parent_p || best_rate_diff > rate_diff) { + *best_parent_p = parent; + *best_parent_rate = parent_rate; + best_rate_diff = rate_diff; + } + +if (!rate_diff) +return rate; + } + +return best_rate_diff; }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,@@ -196,7 +242,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) +if (rate_ops->determine_rate || + (rate_ops->round_rate && clk_composite_ops->set_parent)) clk_composite_ops->determine_rate = clk_composite_determine_rate; }Signature · 1 line
1.7.9.5
RFC PATCH 1/1 clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent
Am Dienstag, 14. Januar 2014, 12:41:46 schrieb Mike Turquette:
Quoted 10 lines
Quoting Boris BREZILLON (2014-01-07 09:03:52)
Quoted 5 lines
In case the
rate_hwdoes not implementdetermine_rate, but onlyround_ratewe fallback tobest_parentselection ifmux_hwis present and support reparenting.Signed-off-by Boris BREZILLON <[email protected]>Since this change affects users of the composite clock type I will hold off reviewing/applying this patch until after the merge window.
sorry for resurrecting this old code, but it looks like it was forgotten somehow and I'm currently hit by a problem that this patch fixes.
When using a composite clk containing both a divider and mux using the standard clock ops, all rate changes ignore the divider completely and only handle the mux. In my case the parents provide 800 and 600MHz while I'm requesting 300MHz. As only mux_ops->determine_rate runs, I get 600MHz instead of anything <= 300 when using the included divider.
Boris' patch fixes this issue for me, so
The patch applies nicely after adapting it according to 5d2043fbe4ddc6cc16ba71b49c2c13f4cb2fe932 ("clk: composite: pass mux_hw into determine_rate")
Heiko
Quoted 100 lines
Quoted 91 lines
---
drivers/clk/clk-composite.c | 49++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-)
drivers/clk/clk-composite.c +13
-0@@ -64,11 +64,57 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,>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; +struct clk *parent; +unsigned long parent_rate; +long tmp_rate; +unsigned long rate_diff; +unsigned long best_rate_diff =ULONG_MAX ; +int i;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 (rate_hw && rate_ops && rate_ops->round_rate && + mux_hw && mux_ops && mux_ops->set_parent) { + *best_parent_p =NULL ; + +if (__clk_get_flags (hw->clk) &CLK_SET_RATE_NO_REPARENT ) { + *best_parent_p =clk_get_parent (mux_hw->clk); + *best_parent_rate =
__clk_get_rate(*best_parent_p);drivers/clk/clk-composite.c +23
-0+ +return rate_ops->round_rate (rate_hw, rate, + best_parent_rate); + } + +for (i =0 ; i <__clk_get_num_parents (mux_hw->clk); i++) { + parent =clk_get_parent_by_index (mux_hw->clk, i); +if (!parent) +continue ; + + parent_rate =__clk_get_rate (parent); + + tmp_rate = rate_ops->round_rate (rate_hw, rate, + &parent_rate); +if (tmp_rate <0 ) +continue ; + +if (tmp_rate < rate) + rate_diff = rate - tmp_rate; +else + rate_diff = tmp_rate - rate; + + if (!rate_diff || !*best_parent_p ||
best_rate_diff>rate_diff) { +*best_parent_p= parent;drivers/clk/clk-composite.c +9
-0+ *best_parent_rate = parent_rate; + best_rate_diff = rate_diff; + } + +if (!rate_diff) +return rate; + } + +return best_rate_diff; }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,@@ -196,7 +242,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;drivers/clk/clk-composite.c +2
-1-if (rate_ops->determine_rate) + if (rate_ops->determine_rate || + (rate_ops->round_rate &&
clk_composite_ops->set_parent))>Quoted 4 lines
clk_composite_ops->determine_rate = clk_composite_determine_rate; }_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Emilio López
maintainerPATCH v3 2/13 clk: sunxi: clean the magic number of mux parents
In reply to Emilio LópezThis was pointed out during the review of the factor patches. Let's indicate what does that magic 5 mean.
--- drivers/clk/sunxi/clk-sunxi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/clk/sunxi/clk-sunxi.c +3 -2
@@ -414,13 +414,14 @@ static void __init sunxi_mux_clk_setup(struct device_node *node, {struct clk *clk;const char *clk_name = node->name; -const char *parents[5 ]; +const char *parents[SUNXI_MAX_PARENTS ];void *reg;int i =0 ; reg =of_iomap (node,0 ); -while (i <5 && (parents[i] =of_clk_get_parent_name (node, i)) !=NULL ) +while (i <SUNXI_MAX_PARENTS && + (parents[i] =of_clk_get_parent_name (node, i)) !=NULL ) i++; clk = clk_register_mux(NULL, clk_name, parents, i,
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 3/13 clk: sunxi: add gating support to PLL1
In reply to Emilio LópezThis commit adds gating support to PLL1 on the clock driver. This makes the PLL1 implementation fully compatible with PLL4 as well.
--- Documentation/devicetree/bindings/clock/sunxi.txt | 2 +- drivers/clk/sunxi/clk-sunxi.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/clock/sunxi.txt +1 -1
@@ -7,7 +7,7 @@ This binding uses the common clock binding[1]. Required properties: - compatible : shall be one of the following: "allwinner,sun4i-osc-clk" - for a gatable oscillator - "allwinner,sun4i-pll1-clk" - for the main PLL clock + "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-axi-clk" - for the AXI clock
drivers/clk/sunxi/clk-sunxi.c +2 -0
@@ -295,11 +295,13 @@ static struct clk_factors_config sun4i_apb1_config = { };static const struct factors_data sun4i_pll1_data__initconst = { + .enable =31 , .table = &sun4i_pll1_config, .getter = sun4i_get_pll1_factors, };static const struct factors_data sun6i_a31_pll1_data__initconst = { + .enable =31 , .table = &sun6i_a31_pll1_config, .getter = sun6i_a31_get_pll1_factors, };
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 4/13 ARM: sunxi: add PLL4 support
In reply to Emilio LópezThis commit adds the PLL4 definition to the sun4i, sun5i and sun7i device trees. PLL4 is compatible with PLL1.
--- arch/arm/boot/dts/sun4i-a10.dtsi | 7 +++++++ arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++++ arch/arm/boot/dts/sun5i-a13.dtsi | 7 +++++++ arch/arm/boot/dts/sun7i-a20.dtsi | 7 +++++++ 4 files changed, 28 insertions(+)
arch/arm/boot/dts/sun4i-a10.dtsi +7 -0
@@ -70,6 +70,13 @@ clocks = <&osc24M>; }; + pll4: pll4 at 01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20018 0x4>; + clocks = <&osc24M>; + }; + /* dummy is 200M */ cpu: cpu at 01c20054 { #clock-cells = <0>;
arch/arm/boot/dts/sun5i-a10s.dtsi +7 -0
@@ -67,6 +67,13 @@ clocks = <&osc24M>; }; + pll4: pll4 at 01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20018 0x4>; + clocks = <&osc24M>; + }; + /* dummy is 200M */ cpu: cpu at 01c20054 { #clock-cells = <0>;
arch/arm/boot/dts/sun5i-a13.dtsi +7 -0
@@ -67,6 +67,13 @@ clocks = <&osc24M>; }; + pll4: pll4 at 01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20018 0x4>; + clocks = <&osc24M>; + }; + /* dummy is 200M */ cpu: cpu at 01c20054 { #clock-cells = <0>;
arch/arm/boot/dts/sun7i-a20.dtsi +7 -0
@@ -66,6 +66,13 @@ clocks = <&osc24M>; }; + pll4: pll4 at 01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20018 0x4>; + clocks = <&osc24M>; + }; + /* * This is a dummy clock, to be used as placeholder on * other mux clocks when a specific parent clock is not
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 5/13 clk: sunxi: make factors_clk_setup return the clock it registers
In reply to Emilio LópezWe will be needing this to register a factor clock as parent with leaf divisors on a single call.
--- drivers/clk/sunxi/clk-sunxi.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
drivers/clk/sunxi/clk-sunxi.c +8 -7
@@ -311,8 +311,8 @@ static const struct factors_data sun4i_apb1_data __initconst = { .getter = sun4i_get_apb1_factors, }; -static void __init sunxi_factors_clk_setup (struct device_node *node, -struct factors_data *data) +static struct clk *__init sunxi_factors_clk_setup (struct device_node *node, +const struct factors_data *data) {struct clk *clk;struct clk_factors *factors;
@@ -334,14 +334,14 @@ static void __init sunxi_factors_clk_setup(struct device_node *node, factors =kzalloc (sizeof (struct clk_factors ),GFP_KERNEL );if (!factors) -return ; +return NULL ;/* 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 ; +return NULL ; }/* set up gate properties */
@@ -357,7 +357,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,if (!mux) {kfree (factors);kfree (gate); -return ; +return NULL ; }/* set up gate properties */
@@ -378,13 +378,14 @@ static void __init sunxi_factors_clk_setup(struct device_node *node, parents, i, mux_hw, &clk_mux_ops, &factors->hw, &clk_factors_ops, - gate_hw, &clk_gate_ops, - i ? 0 : CLK_IS_ROOT); + gate_hw, &clk_gate_ops, 0);if (!IS_ERR (clk)) {of_clk_add_provider (node, of_clk_src_simple_get, clk);clk_register_clkdev (clk, clk_name,NULL ); } + +return clk; }
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 6/13 clk: sunxi: add PLL5 and PLL6 support
In reply to Emilio LópezThis commit implements PLL5 and PLL6 support on the sunxi clock driver. These PLLs use a similar factor clock, but differ on their outputs.
--- Documentation/devicetree/bindings/clock/sunxi.txt | 2 + drivers/clk/sunxi/clk-sunxi.c | 230 ++++++++++++++++++++++ 2 files changed, 232 insertions(+)
Documentation/devicetree/bindings/clock/sunxi.txt +2 -0
@@ -9,6 +9,8 @@ Required properties: "allwinner,sun4i-osc-clk" - for a gatable oscillator "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 + "allwinner,sun4i-pll5-clk" - for the PLL5 clock + "allwinner,sun4i-pll6-clk" - for the PLL6 clock "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-axi-clk" - for the AXI clock "allwinner,sun4i-axi-gates-clk" - for the AXI gates
drivers/clk/sunxi/clk-sunxi.c +230 -0
266 lines not on this page · raw message
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 7/13 ARM: sunxi: add PLL5 and PLL6 support
In reply to Emilio LópezThis commit adds PLL5 and PLL6 nodes to the sun4i, sun5i and sun7i device trees.
--- arch/arm/boot/dts/sun4i-a10.dtsi | 19 +++++++++++++++++-- arch/arm/boot/dts/sun5i-a10s.dtsi | 19 +++++++++++++++++-- arch/arm/boot/dts/sun5i-a13.dtsi | 19 +++++++++++++++++-- arch/arm/boot/dts/sun7i-a20.dtsi | 28 ++++++++++++++++------------ 4 files changed, 67 insertions(+), 18 deletions(-)
arch/arm/boot/dts/sun4i-a10.dtsi +17 -2
@@ -77,6 +77,22 @@ clocks = <&osc24M>; }; + pll5: pll5 at 01c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll5-clk"; + reg = <0x01c20020 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll5_ddr", "pll5_other"; + }; + + pll6: pll6 at 01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll6-clk"; + reg = <0x01c20028 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll6_sata", "pll6_other", "pll6"; + }; + /* dummy is 200M */ cpu: cpu at 01c20054 { #clock-cells = <0>;
@@ -142,12 +158,11 @@ "apb0_ir1", "apb0_keypad"; }; - /* dummy is pll62 */ apb1_mux: apb1_mux at 01c20058 { #clock-cells = <0>; compatible = "allwinner,sun4i-apb1-mux-clk"; reg = <0x01c20058 0x4>; - clocks = <&osc24M>, <&dummy>, <&osc32k>; + clocks = <&osc24M>, <&pll6 1>, <&osc32k>; }; apb1: apb1 at 01c20058 {
arch/arm/boot/dts/sun5i-a10s.dtsi +17 -2
@@ -74,6 +74,22 @@ clocks = <&osc24M>; }; + pll5: pll5 at 01c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll5-clk"; + reg = <0x01c20020 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll5_ddr", "pll5_other"; + }; + + pll6: pll6 at 01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll6-clk"; + reg = <0x01c20028 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll6_sata", "pll6_other", "pll6"; + }; + /* dummy is 200M */ cpu: cpu at 01c20054 { #clock-cells = <0>;
@@ -134,12 +150,11 @@ "apb0_ir", "apb0_keypad"; }; - /* dummy is pll62 */ apb1_mux: apb1_mux at 01c20058 { #clock-cells = <0>; compatible = "allwinner,sun4i-apb1-mux-clk"; reg = <0x01c20058 0x4>; - clocks = <&osc24M>, <&dummy>, <&osc32k>; + clocks = <&osc24M>, <&pll6 1>, <&osc32k>; }; apb1: apb1 at 01c20058 {
arch/arm/boot/dts/sun5i-a13.dtsi +17 -2
@@ -74,6 +74,22 @@ clocks = <&osc24M>; }; + pll5: pll5 at 01c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll5-clk"; + reg = <0x01c20020 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll5_ddr", "pll5_other"; + }; + + pll6: pll6 at 01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll6-clk"; + reg = <0x01c20028 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll6_sata", "pll6_other", "pll6"; + }; + /* dummy is 200M */ cpu: cpu at 01c20054 { #clock-cells = <0>;
@@ -132,12 +148,11 @@ clock-output-names = "apb0_codec", "apb0_pio", "apb0_ir"; }; - /* dummy is pll6 */ apb1_mux: apb1_mux at 01c20058 { #clock-cells = <0>; compatible = "allwinner,sun4i-apb1-mux-clk"; reg = <0x01c20058 0x4>; - clocks = <&osc24M>, <&dummy>, <&osc32k>; + clocks = <&osc24M>, <&pll6 1>, <&osc32k>; }; apb1: apb1 at 01c20058 {
arch/arm/boot/dts/sun7i-a20.dtsi +16 -12
@@ -73,23 +73,27 @@ clocks = <&osc24M>; }; - /* - * This is a dummy clock, to be used as placeholder on - * other mux clocks when a specific parent clock is not - * yet implemented. It should be dropped when the driver - * is complete. - */ - pll6: pll6 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <0>; + pll5: pll5 at 01c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll5-clk"; + reg = <0x01c20020 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll5_ddr", "pll5_other"; + }; + + pll6: pll6 at 01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll6-clk"; + reg = <0x01c20028 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll6_sata", "pll6_other", "pll6"; }; cpu: cpu at 01c20054 { #clock-cells = <0>; compatible = "allwinner,sun4i-cpu-clk"; reg = <0x01c20054 0x4>; - clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll6>; + clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll6 1>; }; axi: axi at 01c20054 {
@@ -148,7 +152,7 @@ #clock-cells = <0>; compatible = "allwinner,sun4i-apb1-mux-clk"; reg = <0x01c20058 0x4>; - clocks = <&osc24M>, <&pll6>, <&osc32k>; + clocks = <&osc24M>, <&pll6 1>, <&osc32k>; }; apb1: apb1 at 01c20058 {
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 8/13 clk: sunxi: mod0 support
In reply to Emilio LópezThis commit implements support for the "module 0" type of clocks, as used by MMC, IR, NAND, SATA and other components.
--- Documentation/devicetree/bindings/clock/sunxi.txt | 5 +- drivers/clk/sunxi/clk-sunxi.c | 57 +++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/clock/sunxi.txt +4 -1
@@ -35,10 +35,13 @@ Required properties: "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 "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,sun4i-mod0-clk" - for the module 0 family of clocks Required properties for all clocks: - reg : shall be the control register address for the clock. -- clocks : shall be the input parent clock(s) phandle for the clock +- clocks : shall be the input parent clock(s) phandle for the clock. For + multiplexed clocks, the list order must match the hardware + programming order. - #clock-cells : from common clock binding; shall be set to 0 except for "allwinner,*-gates-clk" where it shall be set to 1
drivers/clk/sunxi/clk-sunxi.c +57 -0
81 lines not on this page · raw message
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 9/13 clk: sunxi: support better factor DT nodes
In reply to Emilio LópezThe DT nodes should look like
abc_clk: clk at deadbeef {
...
clock-output-names = "abc";
}But our old DT nodes look like
abc: abc at deadbeef {
...
}So, let's support both formats, until we can transition everything to the new, correct one.
--- drivers/clk/sunxi/clk-sunxi.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/clk/sunxi/clk-sunxi.c +9 -0
@@ -435,6 +435,15 @@ static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, (parents[i] = of_clk_get_parent_name(node, i)) != NULL) i++; +/* Nodes should be providing the name via clock-output-names +* but originally our dts didn't, and so we used node->name. +* The new, better nodes look like clk at deadbeef, so we pull the +* name just in this case */ +if (!strcmp ("clk" , clk_name)) { +of_property_read_string_index (node,"clock-output-names" , +0 , &clk_name); + } + factors =kzalloc (sizeof (struct clk_factors ),GFP_KERNEL );if (!factors)return NULL ;
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 10/13 ARM: sun4i: dt: mod0 clocks
In reply to Emilio LópezThis commit adds all the mod0 clocks present on sun4i to its device tree
--- arch/arm/boot/dts/sun4i-a10.dtsi | 120 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+)
arch/arm/boot/dts/sun4i-a10.dtsi +120 -0
@@ -184,6 +184,126 @@ "apb1_uart4", "apb1_uart5", "apb1_uart6", "apb1_uart7"; }; + + nand_clk: clk at 01c20080 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20080 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "nand"; + }; + + ms_clk: clk at 01c20084 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20084 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ms"; + }; + + mmc0_clk: clk at 01c20088 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20088 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc0"; + }; + + mmc1_clk: clk at 01c2008c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c2008c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc1"; + }; + + mmc2_clk: clk at 01c20090 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20090 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc2"; + }; + + mmc3_clk: clk at 01c20094 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20094 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc3"; + }; + + ts_clk: clk at 01c20098 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20098 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ts"; + }; + + ss_clk: clk at 01c2009c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c2009c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ss"; + }; + + spi0_clk: clk at 01c200a0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200a0 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi0"; + }; + + spi1_clk: clk at 01c200a4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200a4 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi1"; + }; + + spi2_clk: clk at 01c200a8 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200a8 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi2"; + }; + + pata_clk: clk at 01c200ac { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200ac 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "pata"; + }; + + ir0_clk: clk at 01c200b0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200b0 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ir0"; + }; + + ir1_clk: clk at 01c200b4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200b4 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ir1"; + }; + + spi3_clk: clk at 01c200d4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200d4 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi3"; + }; }; soc at 01c00000 {
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 11/13 ARM: sun5i: dt: mod0 clocks
In reply to Emilio LópezThis 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.
--- arch/arm/boot/dts/sun5i-a10s.dtsi | 88 +++++++++++++++++++++++++++++++++++++++ arch/arm/boot/dts/sun5i-a13.dtsi | 88 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+)
arch/arm/boot/dts/sun5i-a10s.dtsi +88 -0
@@ -173,6 +173,94 @@ "apb1_i2c2", "apb1_uart0", "apb1_uart1", "apb1_uart2", "apb1_uart3"; }; + + nand_clk: clk at 01c20080 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20080 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "nand"; + }; + + ms_clk: clk at 01c20084 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20084 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ms"; + }; + + mmc0_clk: clk at 01c20088 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20088 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc0"; + }; + + mmc1_clk: clk at 01c2008c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c2008c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc1"; + }; + + mmc2_clk: clk at 01c20090 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20090 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc2"; + }; + + ts_clk: clk at 01c20098 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20098 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ts"; + }; + + ss_clk: clk at 01c2009c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c2009c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ss"; + }; + + spi0_clk: clk at 01c200a0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200a0 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi0"; + }; + + spi1_clk: clk at 01c200a4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200a4 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi1"; + }; + + spi2_clk: clk at 01c200a8 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200a8 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi2"; + }; + + ir0_clk: clk at 01c200b0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200b0 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ir0"; + }; }; soc at 01c00000 {
arch/arm/boot/dts/sun5i-a13.dtsi +88 -0
94 lines not on this page · raw message
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 12/13 ARM: sun7i: dt: mod0 clocks
In reply to Emilio LópezThis commit adds all the mod0 clocks available on A20 to its device tree. This list was created by looking at AW's code release.
--- arch/arm/boot/dts/sun7i-a20.dtsi | 120 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+)
arch/arm/boot/dts/sun7i-a20.dtsi +120 -0
@@ -174,6 +174,126 @@ "apb1_uart2", "apb1_uart3", "apb1_uart4", "apb1_uart5", "apb1_uart6", "apb1_uart7"; }; + + nand_clk: clk at 01c20080 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20080 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "nand"; + }; + + ms_clk: clk at 01c20084 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20084 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ms"; + }; + + mmc0_clk: clk at 01c20088 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20088 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc0"; + }; + + mmc1_clk: clk at 01c2008c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c2008c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc1"; + }; + + mmc2_clk: clk at 01c20090 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20090 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc2"; + }; + + mmc3_clk: clk at 01c20094 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20094 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc3"; + }; + + ts_clk: clk at 01c20098 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c20098 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ts"; + }; + + ss_clk: clk at 01c2009c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c2009c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ss"; + }; + + spi0_clk: clk at 01c200a0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200a0 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi0"; + }; + + spi1_clk: clk at 01c200a4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200a4 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi1"; + }; + + spi2_clk: clk at 01c200a8 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200a8 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi2"; + }; + + pata_clk: clk at 01c200ac { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200ac 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "pata"; + }; + + ir0_clk: clk at 01c200b0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200b0 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ir0"; + }; + + ir1_clk: clk at 01c200b4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200b4 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "ir1"; + }; + + spi3_clk: clk at 01c200d4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c200d4 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi3"; + }; }; soc at 01c00000 {
Signature · 1 line
1.8.5.2
Emilio López
maintainerPATCH v3 13/13 ARM: sunxi: dt: add nodes for the mbus clock
In reply to Emilio Lópezmbus is the memory bus clock, and it is present on both sun5i and sun7i machines. Its register layout is compatible with the mod0 one.
--- arch/arm/boot/dts/sun5i-a10s.dtsi | 8 ++++++++ arch/arm/boot/dts/sun5i-a13.dtsi | 8 ++++++++ arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++ 3 files changed, 24 insertions(+)
arch/arm/boot/dts/sun5i-a10s.dtsi +8 -0
@@ -261,6 +261,14 @@ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; clock-output-names = "ir0"; }; + + mbus_clk: clk at 01c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c2015c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mbus"; + }; }; soc at 01c00000 {
arch/arm/boot/dts/sun5i-a13.dtsi +8 -0
@@ -258,6 +258,14 @@ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; clock-output-names = "ir0"; }; + + mbus_clk: clk at 01c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c2015c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mbus"; + }; }; soc at 01c00000 {
arch/arm/boot/dts/sun7i-a20.dtsi +8 -0
@@ -294,6 +294,14 @@ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; clock-output-names = "spi3"; }; + + mbus_clk: clk at 01c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; + reg = <0x01c2015c 0x4>; + clocks = <&osc24M>, <&pll6 2>, <&pll5 1>; + clock-output-names = "mbus"; + }; }; soc at 01c00000 {
Signature · 1 line
1.8.5.2
A message that is not in the archive (sent off-list or not yet received): 20131223054401.22761.10523@quantum
Emilio López
maintainerv3 cover clk: sunxi: add PLL5 and PLL6 support
Hi Mike,
El 23/12/13 02:44, Mike Turquette escribi?:
Quoted 9 lines
Quoting Emilio L?pez (2013-12-22 19:32:31)
Quoted 7 lines
Hi everyone,
This is v3 of the sunxi clock series. For those seeing this for the first time, it adds PLL4, PLL5, PLL6 and mod0 clock support on sun4i, sun5i and sun7i. Additionally, mbus is supported on sun5i and sun7i. I would like to see this merged for 3.14 as clock users are progressing rapidly and will be needing this code, so all feedback is appreciated.
Quoted 3 lines
For all the clock patches missing my Ack (I think just the first three):
Acked-by Mike Turquette <[email protected]>
Great; if nobody else has any other objection I'd like to get these merged for 3.14. I assume you'll want a pull request as agreed on earlier; do you have a branch I can use as a base? These patches depend on the pull Maxime sent last time and is currently sitting on clk-next.
Cheers!
Emilio
v3 cover clk: sunxi: add PLL5 and PLL6 support
Quoting Emilio L?pez (2013-12-23 05:22:05)
Quoted 12 lines
Hi Mike,
El 23/12/13 02:44, Mike Turquette escribi?:
Quoted 9 lines
Quoting Emilio L?pez (2013-12-22 19:32:31)
Quoted 7 lines
Hi everyone,
This is v3 of the sunxi clock series. For those seeing this for the first time, it adds PLL4, PLL5, PLL6 and mod0 clock support on sun4i, sun5i and sun7i. Additionally, mbus is supported on sun5i and sun7i. I would like to see this merged for 3.14 as clock users are progressing rapidly and will be needing this code, so all feedback is appreciated.
Quoted 8 lines
Quoted 3 lines
For all the clock patches missing my Ack (I think just the first three):
Acked-by Mike Turquette <[email protected]>Great; if nobody else has any other objection I'd like to get these merged for 3.14. I assume you'll want a pull request as agreed on earlier; do you have a branch I can use as a base? These patches depend on the pull Maxime sent last time and is currently sitting on clk-next.
I can assure you that 0903ea60, "clk: add accuracy support for fixed clock" will not change, so feel free to base on that.
Also feel free to roll in "[PATCH 1/4] clk: sunxi: Allwinner A20 output clock support" with your pull request if you like.
Regards,
Mike
Quoted 4 lines
Cheers!
Emilio