* [PATCH v3 01/13] clk: sunxi: register factors clocks behind composite
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
@ 2013-12-23 3:32 ` Emilio López
2014-01-07 16:56 ` boris brezillon
` (2 more replies)
2013-12-23 3:32 ` [PATCH v3 02/13] clk: sunxi: clean the magic number of mux parents Emilio López
` (12 subsequent siblings)
13 siblings, 3 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
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 <emilio@elopez.com.ar>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
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(-)
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index f05207a..9e23264 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 << (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;
-}
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 8fc1375..b823613 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -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;
- 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);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 01/13] clk: sunxi: register factors clocks behind composite
2013-12-23 3:32 ` [PATCH v3 01/13] clk: sunxi: register factors clocks behind composite Emilio López
@ 2014-01-07 16:56 ` boris brezillon
2014-01-07 17:47 ` Emilio López
2014-01-07 17:02 ` [RFC PATCH] clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent Boris BREZILLON
2014-01-07 17:03 ` Boris BREZILLON
2 siblings, 1 reply; 24+ messages in thread
From: boris brezillon @ 2014-01-07 16:56 UTC (permalink / raw)
To: linux-arm-kernel
Hello Emilio, Mike,
On 23/12/2013 04:32, Emilio L?pez wrote:
> 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 <emilio@elopez.com.ar>
> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
> 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(-)
>
> diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
> index f05207a..9e23264 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 << (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;
> -}
> 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 8fc1375..b823613 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c
> @@ -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;
>
> - 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
> if (!IS_ERR(clk)) {
> of_clk_add_provider(node, of_clk_src_simple_get, clk);
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v3 01/13] clk: sunxi: register factors clocks behind composite
2014-01-07 16:56 ` boris brezillon
@ 2014-01-07 17:47 ` Emilio López
2014-01-07 20:46 ` Boris Brezillon
2014-01-08 9:30 ` boris brezillon
0 siblings, 2 replies; 24+ messages in thread
From: Emilio López @ 2014-01-07 17:47 UTC (permalink / raw)
To: linux-arm-kernel
Hi Boris,
[ Apologies if the email looks weird and for using a link; I'm not
using my typical email client ]
> 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.
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.
(...)
> 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 ?
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
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v3 01/13] clk: sunxi: register factors clocks behind composite
2014-01-07 17:47 ` Emilio López
@ 2014-01-07 20:46 ` Boris Brezillon
2014-01-08 9:30 ` boris brezillon
1 sibling, 0 replies; 24+ messages in thread
From: Boris Brezillon @ 2014-01-07 20:46 UTC (permalink / raw)
To: linux-arm-kernel
"Emilio L?pez" <emilio@elopez.com.ar> a ?crit?:
>Hi Boris,
>
>[ Apologies if the email looks weird and for using a link; I'm not
>using my typical email client ]
>
>> 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.
>
>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.
>
Right, but this is not the case for mod0
clks, is it ?
>(...)
>
>> 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 ?
>
>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.)
>
Fair enough (I did pretty much the same thing in my first attempt to fix this bug ;-))
>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
>
>Cheers,
>
>Emilio
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v3 01/13] clk: sunxi: register factors clocks behind composite
2014-01-07 17:47 ` Emilio López
2014-01-07 20:46 ` Boris Brezillon
@ 2014-01-08 9:30 ` boris brezillon
1 sibling, 0 replies; 24+ messages in thread
From: boris brezillon @ 2014-01-08 9:30 UTC (permalink / raw)
To: linux-arm-kernel
On 07/01/2014 18:47, Emilio L?pez wrote:
> Hi Boris,
>
> [ Apologies if the email looks weird and for using a link; I'm not
> using my typical email client ]
>
>> 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.
> 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.
>
> (...)
>
>> 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 ?
> 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.
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
>
> Cheers,
>
> Emilio
^ permalink raw reply [flat|nested] 24+ messages in thread
* [RFC PATCH] clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent
2013-12-23 3:32 ` [PATCH v3 01/13] clk: sunxi: register factors clocks behind composite Emilio López
2014-01-07 16:56 ` boris brezillon
@ 2014-01-07 17:02 ` Boris BREZILLON
2014-01-07 17:03 ` Boris BREZILLON
2 siblings, 0 replies; 24+ messages in thread
From: Boris BREZILLON @ 2014-01-07 17:02 UTC (permalink / raw)
To: linux-arm-kernel
In 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.
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
drivers/clk/clk-composite.c | 49 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 48 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 753d0b7..d3cf49a 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -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;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [RFC PATCH] clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent
2013-12-23 3:32 ` [PATCH v3 01/13] clk: sunxi: register factors clocks behind composite Emilio López
2014-01-07 16:56 ` boris brezillon
2014-01-07 17:02 ` [RFC PATCH] clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent Boris BREZILLON
@ 2014-01-07 17:03 ` Boris BREZILLON
2014-01-14 20:41 ` Mike Turquette
2 siblings, 1 reply; 24+ messages in thread
From: Boris BREZILLON @ 2014-01-07 17:03 UTC (permalink / raw)
To: linux-arm-kernel
In 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.
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
drivers/clk/clk-composite.c | 49 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 48 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 753d0b7..d3cf49a 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -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;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [RFC PATCH] clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent
2014-01-07 17:03 ` Boris BREZILLON
@ 2014-01-14 20:41 ` Mike Turquette
2014-05-18 22:23 ` Heiko Stübner
0 siblings, 1 reply; 24+ messages in thread
From: Mike Turquette @ 2014-01-14 20:41 UTC (permalink / raw)
To: linux-arm-kernel
Quoting Boris BREZILLON (2014-01-07 09:03:52)
> In 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.
>
> Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
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
> ---
> drivers/clk/clk-composite.c | 49 ++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 48 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
> index 753d0b7..d3cf49a 100644
> --- a/drivers/clk/clk-composite.c
> +++ b/drivers/clk/clk-composite.c
> @@ -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;
> }
>
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [RFC PATCH] clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent
2014-01-14 20:41 ` Mike Turquette
@ 2014-05-18 22:23 ` Heiko Stübner
0 siblings, 0 replies; 24+ messages in thread
From: Heiko Stübner @ 2014-05-18 22:23 UTC (permalink / raw)
To: linux-arm-kernel
Am Dienstag, 14. Januar 2014, 12:41:46 schrieb Mike Turquette:
> Quoting Boris BREZILLON (2014-01-07 09:03:52)
>
> > In 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.
> >
> > Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
>
> 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
Tested-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Heiko Stuebner <heiko@sntech.de>
The patch applies nicely after adapting it according to
5d2043fbe4ddc6cc16ba71b49c2c13f4cb2fe932 ("clk: composite: pass mux_hw into
determine_rate")
Heiko
> > ---
> >
> > drivers/clk/clk-composite.c | 49
> > ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48
> > insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
> > index 753d0b7..d3cf49a 100644
> > --- a/drivers/clk/clk-composite.c
> > +++ b/drivers/clk/clk-composite.c
> > @@ -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;
> >
> > }
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v3 02/13] clk: sunxi: clean the magic number of mux parents
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
2013-12-23 3:32 ` [PATCH v3 01/13] clk: sunxi: register factors clocks behind composite Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 03/13] clk: sunxi: add gating support to PLL1 Emilio López
` (11 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
This was pointed out during the review of the factor patches. Let's
indicate what does that magic 5 mean.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
drivers/clk/sunxi/clk-sunxi.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index b823613..ce42c92 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -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,
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 03/13] clk: sunxi: add gating support to PLL1
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
2013-12-23 3:32 ` [PATCH v3 01/13] clk: sunxi: register factors clocks behind composite Emilio López
2013-12-23 3:32 ` [PATCH v3 02/13] clk: sunxi: clean the magic number of mux parents Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 04/13] ARM: sunxi: add PLL4 support Emilio López
` (10 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds gating support to PLL1 on the clock driver. This makes
the PLL1 implementation fully compatible with PLL4 as well.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Mike Turquette <mturquette@linaro.org>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 2 +-
drivers/clk/sunxi/clk-sunxi.c | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 91a748f..b8c6cc4 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -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
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index ce42c92..42e8690 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -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,
};
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 04/13] ARM: sunxi: add PLL4 support
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (2 preceding siblings ...)
2013-12-23 3:32 ` [PATCH v3 03/13] clk: sunxi: add gating support to PLL1 Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 05/13] clk: sunxi: make factors_clk_setup return the clock it registers Emilio López
` (9 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds the PLL4 definition to the sun4i, sun5i and sun7i
device trees. PLL4 is compatible with PLL1.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
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(+)
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 5b158d2..3833c14 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index b4764be..3252aa8 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index ce8ef2a..8c4a9c3 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index d62d693..2b2d3847 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -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
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 05/13] clk: sunxi: make factors_clk_setup return the clock it registers
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (3 preceding siblings ...)
2013-12-23 3:32 ` [PATCH v3 04/13] ARM: sunxi: add PLL4 support Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 06/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (8 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
We will be needing this to register a factor clock as parent with leaf
divisors on a single call.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
Acked-by: Mike Turquette <mturquette@linaro.org>
---
drivers/clk/sunxi/clk-sunxi.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 42e8690..0f23d16 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -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;
}
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 06/13] clk: sunxi: add PLL5 and PLL6 support
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (4 preceding siblings ...)
2013-12-23 3:32 ` [PATCH v3 05/13] clk: sunxi: make factors_clk_setup return the clock it registers Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 07/13] ARM: " Emilio López
` (7 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
This commit implements PLL5 and PLL6 support on the sunxi clock driver.
These PLLs use a similar factor clock, but differ on their outputs.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
Acked-by: Mike Turquette <mturquette@linaro.org>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 2 +
drivers/clk/sunxi/clk-sunxi.c | 230 ++++++++++++++++++++++
2 files changed, 232 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index b8c6cc4..80b2a39 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -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
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 0f23d16..a63efee 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -212,6 +212,40 @@ static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate,
}
/**
+ * sun4i_get_pll5_factors() - calculates n, k factors for PLL5
+ * PLL5 rate is calculated as follows
+ * rate = parent_rate * n * (k + 1)
+ * parent_rate is always 24Mhz
+ */
+
+static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
+ u8 *n, u8 *k, u8 *m, u8 *p)
+{
+ u8 div;
+
+ /* Normalize value to a parent_rate multiple (24M) */
+ div = *freq / parent_rate;
+ *freq = parent_rate * div;
+
+ /* we were called to round the frequency, we can now return */
+ if (n == NULL)
+ return;
+
+ if (div < 31)
+ *k = 0;
+ else if (div / 2 < 31)
+ *k = 1;
+ else if (div / 3 < 31)
+ *k = 2;
+ else
+ *k = 3;
+
+ *n = DIV_ROUND_UP(div, (*k+1));
+}
+
+
+
+/**
* sun4i_get_apb1_factors() - calculates m, p factors for APB1
* APB1 rate is calculated as follows
* rate = (parent_rate >> p) / (m + 1);
@@ -287,6 +321,13 @@ static struct clk_factors_config sun6i_a31_pll1_config = {
.mwidth = 2,
};
+static struct clk_factors_config sun4i_pll5_config = {
+ .nshift = 8,
+ .nwidth = 5,
+ .kshift = 4,
+ .kwidth = 2,
+};
+
static struct clk_factors_config sun4i_apb1_config = {
.mshift = 0,
.mwidth = 5,
@@ -306,6 +347,12 @@ static const struct factors_data sun6i_a31_pll1_data __initconst = {
.getter = sun6i_a31_get_pll1_factors,
};
+static const struct factors_data sun4i_pll5_data __initconst = {
+ .enable = 31,
+ .table = &sun4i_pll5_config,
+ .getter = sun4i_get_pll5_factors,
+};
+
static const struct factors_data sun4i_apb1_data __initconst = {
.table = &sun4i_apb1_config,
.getter = sun4i_get_apb1_factors,
@@ -621,6 +668,179 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
+
+
+/**
+ * sunxi_divs_clk_setup() helper data
+ */
+
+#define SUNXI_DIVS_MAX_QTY 2
+#define SUNXI_DIVISOR_WIDTH 2
+
+struct divs_data {
+ const struct factors_data *factors; /* data for the factor clock */
+ struct {
+ u8 fixed; /* is it a fixed divisor? if not... */
+ struct clk_div_table *table; /* is it a table based divisor? */
+ u8 shift; /* otherwise it's a normal divisor with this shift */
+ 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_tbl[] = {
+ { .val = 0, .div = 6, },
+ { .val = 1, .div = 12, },
+ { .val = 2, .div = 18, },
+ { .val = 3, .div = 24, },
+ { } /* sentinel */
+};
+
+static const struct divs_data pll5_divs_data __initconst = {
+ .factors = &sun4i_pll5_data,
+ .div = {
+ { .shift = 0, .pow = 0, }, /* M, DDR */
+ { .shift = 16, .pow = 1, }, /* P, other */
+ }
+};
+
+static const struct divs_data pll6_divs_data __initconst = {
+ .factors = &sun4i_pll5_data,
+ .div = {
+ { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
+ { .fixed = 2 }, /* P, other */
+ }
+};
+
+/**
+ * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks
+ *
+ * These clocks look something like this
+ * ________________________
+ * | ___divisor 1---|----> to consumer
+ * parent >--| pll___/___divisor 2---|----> to consumer
+ * | \_______________|____> to consumer
+ * |________________________|
+ */
+
+static void __init sunxi_divs_clk_setup(struct device_node *node,
+ struct divs_data *data)
+{
+ struct clk_onecell_data *clk_data;
+ 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;
+
+ /* Set up factor clock that we will be dividing */
+ pclk = sunxi_factors_clk_setup(node, data->factors);
+
+ reg = of_iomap(node, 0);
+
+ clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+ if (!clk_data)
+ return;
+
+ clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL);
+ if (!clks)
+ goto free_clkdata;
+
+ clk_data->clks = clks;
+
+ /* It's not a good idea to have automatic reparenting changing
+ * our RAM clock! */
+ clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT;
+
+ for (i = 0; i < SUNXI_DIVS_MAX_QTY; i++) {
+ if (of_property_read_string_index(node, "clock-output-names",
+ 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) {
+ 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;
+
+ 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);
+ }
+
+ /* The last clock available on the getter is the parent */
+ clks[i++] = pclk;
+
+ /* Adjust to the real max */
+ 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);
+}
+
+
+
/* Matches for factors clocks */
static const struct of_device_id clk_factors_match[] __initconst = {
{.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
@@ -638,6 +858,13 @@ static const struct of_device_id clk_div_match[] __initconst = {
{}
};
+/* Matches for divided outputs */
+static const struct of_device_id clk_divs_match[] __initconst = {
+ {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,},
+ {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,},
+ {}
+};
+
/* Matches for mux clocks */
static const struct of_device_id clk_mux_match[] __initconst = {
{.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,},
@@ -715,6 +942,9 @@ static void __init sunxi_init_clocks(struct device_node *np)
/* Register divider clocks */
of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup);
+ /* Register divided output clocks */
+ of_sunxi_table_clock_setup(clk_divs_match, sunxi_divs_clk_setup);
+
/* Register mux clocks */
of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 07/13] ARM: sunxi: add PLL5 and PLL6 support
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (5 preceding siblings ...)
2013-12-23 3:32 ` [PATCH v3 06/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 08/13] clk: sunxi: mod0 support Emilio López
` (6 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds PLL5 and PLL6 nodes to the sun4i, sun5i and sun7i
device trees.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
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(-)
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 3833c14..ebacb5d 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -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 {
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 3252aa8..86e06e4 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -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 {
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 8c4a9c3..cded3c7 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -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 {
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 2b2d3847..7949028 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -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 {
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 08/13] clk: sunxi: mod0 support
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (6 preceding siblings ...)
2013-12-23 3:32 ` [PATCH v3 07/13] ARM: " Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 09/13] clk: sunxi: support better factor DT nodes Emilio López
` (5 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
This commit implements support for the "module 0" type of clocks, as
used by MMC, IR, NAND, SATA and other components.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
Acked-by: Mike Turquette <mturquette@linaro.org>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 5 +-
drivers/clk/sunxi/clk-sunxi.c | 57 +++++++++++++++++++++++
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 80b2a39..46d8433 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -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
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index a63efee..3497a29 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -289,6 +289,47 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
/**
+ * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
+ * MMC rate is calculated as follows
+ * rate = (parent_rate >> p) / (m + 1);
+ */
+
+static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
+ u8 *n, u8 *k, u8 *m, u8 *p)
+{
+ u8 div, calcm, calcp;
+
+ /* These clocks can only divide, so we will never be able to achieve
+ * frequencies higher than the parent frequency */
+ if (*freq > parent_rate)
+ *freq = parent_rate;
+
+ div = parent_rate / *freq;
+
+ if (div < 16)
+ calcp = 0;
+ else if (div / 2 < 16)
+ calcp = 1;
+ else if (div / 4 < 16)
+ calcp = 2;
+ else
+ calcp = 3;
+
+ calcm = DIV_ROUND_UP(div, 1 << calcp);
+
+ *freq = (parent_rate >> calcp) / calcm;
+
+ /* we were called to round the frequency, we can now return */
+ if (n == NULL)
+ return;
+
+ *m = calcm - 1;
+ *p = calcp;
+}
+
+
+
+/**
* sunxi_factors_clk_setup() - Setup function for factor clocks
*/
@@ -335,6 +376,14 @@ static struct clk_factors_config sun4i_apb1_config = {
.pwidth = 2,
};
+/* user manual says "n" but it's really "p" */
+static struct clk_factors_config sun4i_mod0_config = {
+ .mshift = 0,
+ .mwidth = 4,
+ .pshift = 16,
+ .pwidth = 2,
+};
+
static const struct factors_data sun4i_pll1_data __initconst = {
.enable = 31,
.table = &sun4i_pll1_config,
@@ -358,6 +407,13 @@ static const struct factors_data sun4i_apb1_data __initconst = {
.getter = sun4i_get_apb1_factors,
};
+static const struct factors_data sun4i_mod0_data __initconst = {
+ .enable = 31,
+ .mux = 24,
+ .table = &sun4i_mod0_config,
+ .getter = sun4i_get_mod0_factors,
+};
+
static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
const struct factors_data *data)
{
@@ -846,6 +902,7 @@ 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,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
+ {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
{}
};
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 09/13] clk: sunxi: support better factor DT nodes
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (7 preceding siblings ...)
2013-12-23 3:32 ` [PATCH v3 08/13] clk: sunxi: mod0 support Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 10/13] ARM: sun4i: dt: mod0 clocks Emilio López
` (4 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
The 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.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
drivers/clk/sunxi/clk-sunxi.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 3497a29..2be4e46 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -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;
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 10/13] ARM: sun4i: dt: mod0 clocks
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (8 preceding siblings ...)
2013-12-23 3:32 ` [PATCH v3 09/13] clk: sunxi: support better factor DT nodes Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 11/13] ARM: sun5i: " Emilio López
` (3 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds all the mod0 clocks present on sun4i to its device tree
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 120 +++++++++++++++++++++++++++++++++++++++
1 file changed, 120 insertions(+)
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index ebacb5d..834b37e 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -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 {
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 11/13] ARM: sun5i: dt: mod0 clocks
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (9 preceding siblings ...)
2013-12-23 3:32 ` [PATCH v3 10/13] ARM: sun4i: dt: mod0 clocks Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 12/13] ARM: sun7i: " Emilio López
` (2 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
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 <emilio@elopez.com.ar>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun5i-a10s.dtsi | 88 +++++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/sun5i-a13.dtsi | 88 +++++++++++++++++++++++++++++++++++++++
2 files changed, 176 insertions(+)
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 86e06e4..5012c27 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -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 {
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index cded3c7..c46ac65 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -170,6 +170,94 @@
clock-output-names = "apb1_i2c0", "apb1_i2c1",
"apb1_i2c2", "apb1_uart1", "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 {
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 12/13] ARM: sun7i: dt: mod0 clocks
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (10 preceding siblings ...)
2013-12-23 3:32 ` [PATCH v3 11/13] ARM: sun5i: " Emilio López
@ 2013-12-23 3:32 ` Emilio López
2013-12-23 3:32 ` [PATCH v3 13/13] ARM: sunxi: dt: add nodes for the mbus clock Emilio López
[not found] ` <20131223054401.22761.10523@quantum>
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
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 <emilio@elopez.com.ar>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 120 +++++++++++++++++++++++++++++++++++++++
1 file changed, 120 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 7949028..9a2e356 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -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 {
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 13/13] ARM: sunxi: dt: add nodes for the mbus clock
2013-12-23 3:32 [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (11 preceding siblings ...)
2013-12-23 3:32 ` [PATCH v3 12/13] ARM: sun7i: " Emilio López
@ 2013-12-23 3:32 ` Emilio López
[not found] ` <20131223054401.22761.10523@quantum>
13 siblings, 0 replies; 24+ messages in thread
From: Emilio López @ 2013-12-23 3:32 UTC (permalink / raw)
To: linux-arm-kernel
mbus is the memory bus clock, and it is present on both sun5i and sun7i
machines. Its register layout is compatible with the mod0 one.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
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(+)
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 5012c27..50f34fd 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -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 {
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index c46ac65..227be94 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -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 {
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 9a2e356..1ba8532 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -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 {
--
1.8.5.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
[parent not found: <20131223054401.22761.10523@quantum>]
* [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support
[not found] ` <20131223054401.22761.10523@quantum>
@ 2013-12-23 13:22 ` Emilio López
2013-12-23 19:37 ` Mike Turquette
0 siblings, 1 reply; 24+ messages in thread
From: Emilio López @ 2013-12-23 13:22 UTC (permalink / raw)
To: linux-arm-kernel
Hi Mike,
El 23/12/13 02:44, Mike Turquette escribi?:
> Quoting Emilio L?pez (2013-12-22 19:32:31)
>> 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.
>
> For all the clock patches missing my Ack (I think just the first three):
>
> Acked-by: Mike Turquette <mturquette@linaro.org>
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
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support
2013-12-23 13:22 ` [PATCH v3 00/13] clk: sunxi: add PLL5 and PLL6 support Emilio López
@ 2013-12-23 19:37 ` Mike Turquette
0 siblings, 0 replies; 24+ messages in thread
From: Mike Turquette @ 2013-12-23 19:37 UTC (permalink / raw)
To: linux-arm-kernel
Quoting Emilio L?pez (2013-12-23 05:22:05)
> Hi Mike,
>
> El 23/12/13 02:44, Mike Turquette escribi?:
> > Quoting Emilio L?pez (2013-12-22 19:32:31)
> >> 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.
> >
> > For all the clock patches missing my Ack (I think just the first three):
> >
> > Acked-by: Mike Turquette <mturquette@linaro.org>
>
> 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
>
> Cheers!
>
> Emilio
^ permalink raw reply [flat|nested] 24+ messages in thread