[U-Boot] [PATCH 01/16] clk: introduce clk_dev_binded

When support Clock Common Framework, U-Boot use dev for clk tree information, there is no clk->parent. When support composite clk, it contains mux/gate/divider, but the mux/gate/divider is not binded with device. So we could not use dev_get_uclass_priv to get the correct clk_mux/gate/divider. So add clk_dev_binded to let choose the correct method.
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/clk.c | 8 ++++++++ include/clk.h | 9 +++++++++ 2 files changed, 17 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7d748c9fc7..39b3087067 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -55,3 +55,11 @@ const char *clk_hw_get_name(const struct clk *hw) { return hw->dev->name; } + +bool clk_dev_binded(struct clk *clk) +{ + if (clk->dev && (clk->dev->flags & DM_FLAG_BOUND)) + return true; + + return false; +} diff --git a/include/clk.h b/include/clk.h index f8f56d9cf0..2ebc905e04 100644 --- a/include/clk.h +++ b/include/clk.h @@ -356,4 +356,13 @@ static inline bool clk_valid(struct clk *clk) * @return zero on success, or -ENOENT on error */ int clk_get_by_id(ulong id, struct clk **clkp); + +/** + * clk_dev_binded() - Check whether the clk has a device binded + * + * @clk A pointer to the clk + * + * @return true on binded, or false on no + */ +bool clk_dev_binded(struct clk *clk); #endif

Preparing to support composite clk.
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/clk-divider.c | 4 ++-- drivers/clk/clk-mux.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 6921c76a48..2ed9ed6ab8 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -69,8 +69,8 @@ unsigned long divider_recalc_rate(struct clk *hw, unsigned long parent_rate,
static ulong clk_divider_recalc_rate(struct clk *clk) { - struct clk_divider *divider = - to_clk_divider(dev_get_clk_ptr(clk->dev)); + struct clk_divider *divider = to_clk_divider(clk_dev_binded(clk) ? + dev_get_clk_ptr(clk->dev) : clk); unsigned long parent_rate = clk_get_parent_rate(clk); unsigned int val;
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 3c075aa09e..81d1e7ebee 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -35,7 +35,8 @@ int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int flags, unsigned int val) { - struct clk_mux *mux = to_clk_mux(clk); + struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? + dev_get_clk_ptr(clk->dev) : clk); int num_parents = mux->num_parents;
if (table) { @@ -61,7 +62,8 @@ int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int flags,
static u8 clk_mux_get_parent(struct clk *clk) { - struct clk_mux *mux = to_clk_mux(clk); + struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? + dev_get_clk_ptr(clk->dev) : clk); u32 val;
#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)

Add set parent support for clk mux
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/clk-mux.c | 70 ++++++++++++++++++++++++++++++++++++++++++-- include/linux/clk-provider.h | 2 ++ 2 files changed, 70 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 81d1e7ebee..5acc0b8cbd 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -60,7 +60,24 @@ int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int flags, return val; }
-static u8 clk_mux_get_parent(struct clk *clk) +unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index) +{ + unsigned int val = index; + + if (table) { + val = table[index]; + } else { + if (flags & CLK_MUX_INDEX_BIT) + val = 1 << index; + + if (flags & CLK_MUX_INDEX_ONE) + val++; + } + + return val; +} + +u8 clk_mux_get_parent(struct clk *clk) { struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? dev_get_clk_ptr(clk->dev) : clk); @@ -77,8 +94,57 @@ static u8 clk_mux_get_parent(struct clk *clk) return clk_mux_val_to_index(clk, mux->table, mux->flags, val); }
+static int clk_fetch_parent_index(struct clk *clk, + struct clk *parent) +{ + struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? + dev_get_clk_ptr(clk->dev) : clk); + + int i; + + if (!parent) + return -EINVAL; + + for (i = 0; i < mux->num_parents; i++) { + if (!strcmp(parent->dev->name, mux->parent_names[i])) + return i; + } + + return -EINVAL; +} + +static int clk_mux_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? + dev_get_clk_ptr(clk->dev) : clk); + int index; + u32 val; + u32 reg; + + index = clk_fetch_parent_index(clk, parent); + if (index < 0) { + printf("Could not fetch index\n"); + return index; + } + + val = clk_mux_index_to_val(mux->table, mux->flags, index); + + if (mux->flags & CLK_MUX_HIWORD_MASK) { + reg = mux->mask << (mux->shift + 16); + } else { + reg = readl(mux->reg); + reg &= ~(mux->mask << mux->shift); + } + val = val << mux->shift; + reg |= val; + writel(reg, mux->reg); + + return 0; +} + const struct clk_ops clk_mux_ops = { - .get_rate = clk_generic_get_rate, + .get_rate = clk_generic_get_rate, + .set_parent = clk_mux_set_parent, };
struct clk *clk_hw_register_mux_table(struct device *dev, const char *name, diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 43a25e9c6a..7e44045c16 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -66,6 +66,8 @@ struct clk_mux { };
#define to_clk_mux(_clk) container_of(_clk, struct clk_mux, clk) +extern const struct clk_ops clk_mux_ops; +u8 clk_mux_get_parent(struct clk *clk);
struct clk_div_table { unsigned int val;

Export mux/divider ops for composite usage
Signed-off-by: Peng Fan peng.fan@nxp.com --- include/linux/clk-provider.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 7e44045c16..6c6475ea91 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -96,6 +96,7 @@ struct clk_divider { #define CLK_DIVIDER_ROUND_CLOSEST BIT(4) #define CLK_DIVIDER_READ_ONLY BIT(5) #define CLK_DIVIDER_MAX_AT_ZERO BIT(6) +extern const struct clk_ops clk_divider_ops;
struct clk_fixed_factor { struct clk clk;

Import clk-gate support from Linux Kernel 5.1-rc5
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/Makefile | 2 +- drivers/clk/clk-gate.c | 148 +++++++++++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 18 ++++++ 3 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/clk-gate.c
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 37dfd281e9..a17ba6deae 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK) += clk-uclass.o obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_rate.o obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_factor.o -obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk.o clk-divider.o clk-mux.o +obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk.o clk-divider.o clk-mux.o clk-gate.o obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk-fixed-factor.o
obj-y += imx/ diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c new file mode 100644 index 0000000000..a3a1fdd3b2 --- /dev/null +++ b/drivers/clk/clk-gate.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2010-2011 Canonical Ltd jeremy.kerr@canonical.com + * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd mturquette@linaro.org + * Copyright 2019 NXP + * + * Gated clock implementation + */ + +#include <common.h> +#include <asm/io.h> +#include <malloc.h> +#include <clk-uclass.h> +#include <dm/device.h> +#include <linux/clk-provider.h> +#include <clk.h> +#include "clk.h" + +#define UBOOT_DM_CLK_GATE "clk_gate" + +/** + * DOC: basic gatable clock which can gate and ungate it's output + * + * Traits of this clock: + * prepare - clk_(un)prepare only ensures parent is (un)prepared + * enable - clk_enable and clk_disable are functional & control gating + * rate - inherits rate from parent. No clk_set_rate support + * parent - fixed parent. No clk_set_parent support + */ + +/* + * It works on following logic: + * + * For enabling clock, enable = 1 + * set2dis = 1 -> clear bit -> set = 0 + * set2dis = 0 -> set bit -> set = 1 + * + * For disabling clock, enable = 0 + * set2dis = 1 -> set bit -> set = 1 + * set2dis = 0 -> clear bit -> set = 0 + * + * So, result is always: enable xor set2dis. + */ +static void clk_gate_endisable(struct clk *clk, int enable) +{ + struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ? + dev_get_clk_ptr(clk->dev) : clk); + int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; + u32 reg; + + set ^= enable; + + if (gate->flags & CLK_GATE_HIWORD_MASK) { + reg = BIT(gate->bit_idx + 16); + if (set) + reg |= BIT(gate->bit_idx); + } else { + reg = readl(gate->reg); + + if (set) + reg |= BIT(gate->bit_idx); + else + reg &= ~BIT(gate->bit_idx); + } + + writel(reg, gate->reg); +} + +static int clk_gate_enable(struct clk *clk) +{ + clk_gate_endisable(clk, 1); + + return 0; +} + +static int clk_gate_disable(struct clk *clk) +{ + clk_gate_endisable(clk, 0); + + return 0; +} + +int clk_gate_is_enabled(struct clk *clk) +{ + struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ? + dev_get_clk_ptr(clk->dev) : clk); + u32 reg; + + reg = readl(gate->reg); + + /* if a set bit disables this clk, flip it before masking */ + if (gate->flags & CLK_GATE_SET_TO_DISABLE) + reg ^= BIT(gate->bit_idx); + + reg &= BIT(gate->bit_idx); + + return reg ? 1 : 0; +} + +const struct clk_ops clk_gate_ops = { + .enable = clk_gate_enable, + .disable = clk_gate_disable, + .get_rate = clk_generic_get_rate, +}; + +struct clk *clk_register_gate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock) +{ + struct clk_gate *gate; + struct clk *clk; + int ret; + + if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { + if (bit_idx > 15) { + pr_err("gate bit exceeds LOWORD field\n"); + return ERR_PTR(-EINVAL); + } + } + + /* allocate the gate */ + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + /* struct clk_gate assignments */ + gate->reg = reg; + gate->bit_idx = bit_idx; + gate->flags = clk_gate_flags; + + clk = &gate->clk; + + ret = clk_register(clk, UBOOT_DM_CLK_GATE, name, parent_name); + if (ret) { + kfree(gate); + return ERR_PTR(ret); + } + + return clk; +} + +U_BOOT_DRIVER(clk_gate) = { + .name = UBOOT_DM_CLK_GATE, + .id = UCLASS_CLK, + .ops = &clk_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 6c6475ea91..b9568502a1 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -69,6 +69,24 @@ struct clk_mux { extern const struct clk_ops clk_mux_ops; u8 clk_mux_get_parent(struct clk *clk);
+struct clk_gate { + struct clk clk; + void __iomem *reg; + u8 bit_idx; + u8 flags; +}; + +#define to_clk_gate(_clk) container_of(_clk, struct clk_gate, clk) + +#define CLK_GATE_SET_TO_DISABLE BIT(0) +#define CLK_GATE_HIWORD_MASK BIT(1) + +extern const struct clk_ops clk_gate_ops; +struct clk *clk_register_gate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock); + struct clk_div_table { unsigned int val; unsigned int div;

Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/clk-divider.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+)
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 2ed9ed6ab8..822e09b084 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -18,6 +18,7 @@ #include <dm/lists.h> #include <dm/device-internal.h> #include <linux/clk-provider.h> +#include <linux/log2.h> #include <div64.h> #include <clk.h> #include "clk.h" @@ -86,8 +87,95 @@ static ulong clk_divider_recalc_rate(struct clk *clk) divider->flags, divider->width); }
+static bool _is_valid_table_div(const struct clk_div_table *table, + unsigned int div) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->div == div) + return true; + return false; +} + +static bool _is_valid_div(const struct clk_div_table *table, unsigned int div, + unsigned long flags) +{ + if (flags & CLK_DIVIDER_POWER_OF_TWO) + return is_power_of_2(div); + if (table) + return _is_valid_table_div(table, div); + return true; +} + +static unsigned int _get_table_val(const struct clk_div_table *table, + unsigned int div) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->div == div) + return clkt->val; + return 0; +} + +static unsigned int _get_val(const struct clk_div_table *table, + unsigned int div, unsigned long flags, u8 width) +{ + if (flags & CLK_DIVIDER_ONE_BASED) + return div; + if (flags & CLK_DIVIDER_POWER_OF_TWO) + return __ffs(div); + if (flags & CLK_DIVIDER_MAX_AT_ZERO) + return (div == clk_div_mask(width) + 1) ? 0 : div; + if (table) + return _get_table_val(table, div); + return div - 1; +} +int divider_get_val(unsigned long rate, unsigned long parent_rate, + const struct clk_div_table *table, u8 width, + unsigned long flags) +{ + unsigned int div, value; + + div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); + + if (!_is_valid_div(table, div, flags)) + return -EINVAL; + + value = _get_val(table, div, flags, width); + + return min_t(unsigned int, value, clk_div_mask(width)); +} + +static ulong clk_divider_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk_divider *divider = to_clk_divider(clk_dev_binded(clk) ? + dev_get_clk_ptr(clk->dev) : clk); + unsigned long parent_rate = clk_get_parent_rate(clk); + int value; + u32 val; + + value = divider_get_val(rate, parent_rate, divider->table, + divider->width, divider->flags); + if (value < 0) + return value; + + if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { + val = clk_div_mask(divider->width) << (divider->shift + 16); + } else { + val = readl(divider->reg); + val &= ~(clk_div_mask(divider->width) << divider->shift); + } + val |= (u32)value << divider->shift; + writel(val, divider->reg); + + return clk_get_rate(clk); +} + const struct clk_ops clk_divider_ops = { .get_rate = clk_divider_recalc_rate, + .set_rate = clk_divider_set_rate, };
static struct clk *_register_divider(struct device *dev, const char *name,

Export the structure for others to use.
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/clk_fixed_rate.c | 8 +------- include/linux/clk-provider.h | 7 +++++++ 2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c index 1fdf8c4e54..08cce0d79b 100644 --- a/drivers/clk/clk_fixed_rate.c +++ b/drivers/clk/clk_fixed_rate.c @@ -6,13 +6,7 @@ #include <common.h> #include <clk-uclass.h> #include <dm.h> - -struct clk_fixed_rate { - struct clk clk; - unsigned long fixed_rate; -}; - -#define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_platdata(dev)) +#include <linux/clk-provider.h>
static ulong clk_fixed_rate_get_rate(struct clk *clk) { diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index b9568502a1..8b790cb666 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -125,6 +125,13 @@ struct clk_fixed_factor { #define to_clk_fixed_factor(_clk) container_of(_clk, struct clk_fixed_factor,\ clk)
+struct clk_fixed_rate { + struct clk clk; + unsigned long fixed_rate; +}; + +#define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_platdata(dev)) + int clk_register(struct clk *clk, const char *drv_name, const char *name, const char *parent_name);

Import some clk helpers from Linux Kernel for i.MX8MM usage
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/imx/clk.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+)
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index e6d51830e8..1d480d8722 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -36,6 +36,23 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent, shift, 0x3, 0); }
+static inline struct clk *imx_clk_gate4(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return clk_register_gate2(NULL, name, parent, + CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + reg, shift, 0x3, 0); +} + +static inline struct clk *imx_clk_gate4_flags(const char *name, + const char *parent, void __iomem *reg, u8 shift, + unsigned long flags) +{ + return clk_register_gate2(NULL, name, parent, + flags | CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + reg, shift, 0x3, 0); +} + static inline struct clk *imx_clk_fixed_factor(const char *name, const char *parent, unsigned int mult, unsigned int div) { @@ -50,6 +67,14 @@ static inline struct clk *imx_clk_divider(const char *name, const char *parent, reg, shift, width, 0); }
+static inline struct clk *imx_clk_divider2(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width) +{ + return clk_register_divider(NULL, name, parent, + CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + reg, shift, width, 0); +} + struct clk *imx_clk_pfd(const char *name, const char *parent_name, void __iomem *reg, u8 idx);
@@ -57,6 +82,16 @@ struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg, u8 shift, u8 width, const char * const *parents, int num_parents, void (*fixup)(u32 *val));
+static inline struct clk *imx_clk_mux_flags(const char *name, + void __iomem *reg, u8 shift, u8 width, + const char * const *parents, int num_parents, + unsigned long flags) +{ + return clk_register_mux(NULL, name, parents, num_parents, + flags | CLK_SET_RATE_NO_REPARENT, reg, shift, + width, 0); +} + static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg, u8 shift, u8 width, const char * const *parents, int num_parents) @@ -66,4 +101,50 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg, width, 0); }
+static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg, + u8 shift, u8 width, const char * const *parents, + int num_parents) +{ + return clk_register_mux(NULL, name, parents, num_parents, + CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE, + reg, shift, width, 0); +} + +static inline struct clk *imx_clk_gate(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg, + shift, 0, NULL); +} + +static inline struct clk *imx_clk_gate_flags(const char *name, const char *parent, + void __iomem *reg, u8 shift, unsigned long flags) +{ + return clk_register_gate(NULL, name, parent, flags | CLK_SET_RATE_PARENT, reg, + shift, 0, NULL); +} + +static inline struct clk *imx_clk_gate3(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return clk_register_gate(NULL, name, parent, + CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + reg, shift, 0, NULL); +} + +struct clk *imx8m_clk_composite_flags(const char *name, + const char * const *parent_names, + int num_parents, void __iomem *reg, unsigned long flags); + +#define __imx8m_clk_composite(name, parent_names, reg, flags) \ + imx8m_clk_composite_flags(name, parent_names, \ + ARRAY_SIZE(parent_names), reg, \ + flags | CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE) + +#define imx8m_clk_composite(name, parent_names, reg) \ + __imx8m_clk_composite(name, parent_names, reg, 0) + +#define imx8m_clk_composite_critical(name, parent_names, reg) \ + __imx8m_clk_composite(name, parent_names, reg, CLK_IS_CRITICAL) + #endif /* __MACH_IMX_CLK_H */

Add set rate for imx clk-gate2
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/imx/clk-gate2.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index 571be32088..1b9db6e791 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -60,7 +60,18 @@ static int clk_gate2_disable(struct clk *clk) return 0; }
+static ulong clk_gate2_set_rate(struct clk *clk, ulong rate) +{ + struct clk *parent = clk_get_parent(clk); + + if (parent) + return clk_set_rate(parent, rate); + + return -ENODEV; +} + static const struct clk_ops clk_gate2_ops = { + .set_rate = clk_gate2_set_rate, .enable = clk_gate2_enable, .disable = clk_gate2_disable, .get_rate = clk_generic_get_rate,

When the device not binded with a node, we need ignore the parents and rate settings.
Cc: Simon Glass sjg@chromium.org Cc: Jagan Teki jagan@amarulasolutions.com Cc: Philipp Tomsich philipp.tomsich@theobroma-systems.com Cc: Neil Armstrong narmstrong@baylibre.com Cc: Andreas Dannenberg dannenberg@ti.com Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/clk-uclass.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 5acf186b01..39c6a97caa 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -283,6 +283,9 @@ int clk_set_defaults(struct udevice *dev) { int ret;
+ if (!dev_of_valid(dev)) + return 0; + /* If this not in SPL and pre-reloc state, don't take any action. */ if (!(IS_ENABLED(CONFIG_SPL_BUILD) || (gd->flags & GD_FLG_RELOC))) return 0;

Import clk composite clk support from Linux Kernel 5.1-rc5
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/Kconfig | 14 ++++ drivers/clk/Makefile | 1 + drivers/clk/clk-composite.c | 160 +++++++++++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 22 ++++++ 4 files changed, 197 insertions(+) create mode 100644 drivers/clk/clk-composite.c
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 9399bb79e9..0138473ac7 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -53,6 +53,13 @@ config SPL_CLK_CCF Enable this option if you want to (re-)use the Linux kernel's Common Clock Framework [CCF] code in U-Boot's SPL.
+config SPL_CLK_COMPOSITE_CCF + bool "SPL Common Clock Framework [CCF] composite clk support " + depends on SPL_CLK_CCF + help + Enable this option if you want to (re-)use the Linux kernel's Common + Clock Framework [CCF] composite code in U-Boot's SPL. + config CLK_CCF bool "Common Clock Framework [CCF] support " depends on CLK_IMX6Q || SANDBOX_CLK_CCF @@ -60,6 +67,13 @@ config CLK_CCF Enable this option if you want to (re-)use the Linux kernel's Common Clock Framework [CCF] code in U-Boot's clock driver.
+config CLK_COMPOSITE_CCF + bool "Common Clock Framework [CCF] composite clk support " + depends on CLK_CCF + help + Enable this option if you want to (re-)use the Linux kernel's Common + Clock Framework [CCF] composite code in U-Boot's clock driver. + config CLK_STM32F bool "Enable clock driver support for STM32F family" depends on CLK && (STM32F7 || STM32F4) diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index a17ba6deae..681372639d 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_rate.o obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_factor.o obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk.o clk-divider.o clk-mux.o clk-gate.o obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk-fixed-factor.o +obj-$(CONFIG_$(SPL_TPL_)CLK_COMPOSITE_CCF) += clk-composite.o
obj-y += imx/ obj-y += tegra/ diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c new file mode 100644 index 0000000000..a5626c33d1 --- /dev/null +++ b/drivers/clk/clk-composite.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved. + * Copyright 2019 NXP + */ + +#include <common.h> +#include <asm/io.h> +#include <malloc.h> +#include <clk-uclass.h> +#include <dm/device.h> +#include <linux/clk-provider.h> +#include <clk.h> + +#include "clk.h" + +#define UBOOT_DM_CLK_COMPOSITE "clk_composite" + +static u8 clk_composite_get_parent(struct clk *clk) +{ + struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? + (struct clk *)dev_get_clk_ptr(clk->dev) : clk); + struct clk *mux = composite->mux; + + return clk_mux_get_parent(mux); +} + +static int clk_composite_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? + (struct clk *)dev_get_clk_ptr(clk->dev) : clk); + const struct clk_ops *mux_ops = composite->mux_ops; + struct clk *mux = composite->mux; + + return mux_ops->set_parent(mux, parent); +} + +static unsigned long clk_composite_recalc_rate(struct clk *clk) +{ + struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? + (struct clk *)dev_get_clk_ptr(clk->dev) : clk); + const struct clk_ops *rate_ops = composite->rate_ops; + struct clk *rate = composite->rate; + + return rate_ops->get_rate(rate); +} + +static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? + (struct clk *)dev_get_clk_ptr(clk->dev) : clk); + const struct clk_ops *rate_ops = composite->rate_ops; + struct clk *clk_rate = composite->rate; + + return rate_ops->set_rate(clk_rate, rate); +} + +static int clk_composite_enable(struct clk *clk) +{ + struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? + (struct clk *)dev_get_clk_ptr(clk->dev) : clk); + const struct clk_ops *gate_ops = composite->gate_ops; + struct clk *gate = composite->gate; + + return gate_ops->enable(gate); +} + +static int clk_composite_disable(struct clk *clk) +{ + struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? + (struct clk *)dev_get_clk_ptr(clk->dev) : clk); + const struct clk_ops *gate_ops = composite->gate_ops; + struct clk *gate = composite->gate; + + gate_ops->disable(gate); + + return 0; +} + +struct clk_ops clk_composite_ops = { + /* This will be set according to clk_register_composite */ +}; + +struct clk *clk_register_composite(struct device *dev, const char *name, + const char * const *parent_names, + int num_parents, struct clk *mux, + const struct clk_ops *mux_ops, + struct clk *rate, + const struct clk_ops *rate_ops, + struct clk *gate, + const struct clk_ops *gate_ops, + unsigned long flags) +{ + struct clk *clk; + struct clk_composite *composite; + int ret; + struct clk_ops *composite_ops = &clk_composite_ops; + + composite = kzalloc(sizeof(*composite), GFP_KERNEL); + if (!composite) + return ERR_PTR(-ENOMEM); + + if (mux && mux_ops) { + composite->mux = mux; + composite->mux_ops = mux_ops; + if (mux_ops->set_parent) + composite_ops->set_parent = clk_composite_set_parent; + mux->data = (ulong)composite; + } + + if (rate && rate_ops) { + if (!rate_ops->get_rate) { + clk = ERR_PTR(-EINVAL); + goto err; + } + composite_ops->get_rate = clk_composite_recalc_rate; + + /* .set_rate requires either .round_rate or .determine_rate */ + if (rate_ops->set_rate) + composite_ops->set_rate = clk_composite_set_rate; + + composite->rate = rate; + composite->rate_ops = rate_ops; + rate->data = (ulong)composite; + } + + if (gate && gate_ops) { + if (!gate_ops->enable || !gate_ops->disable) { + clk = ERR_PTR(-EINVAL); + goto err; + } + + composite->gate = gate; + composite->gate_ops = gate_ops; + composite_ops->enable = clk_composite_enable; + composite_ops->disable = clk_composite_disable; + gate->data = (ulong)composite; + } + + clk = &composite->clk; + ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name, + parent_names[clk_composite_get_parent(clk)]); + if (ret) { + clk = ERR_PTR(ret); + goto err; + } + + return clk; + +err: + kfree(composite); + return clk; +} + +U_BOOT_DRIVER(clk_composite) = { + .name = UBOOT_DM_CLK_COMPOSITE, + .id = UCLASS_CLK, + .ops = &clk_composite_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 8b790cb666..9c292f555d 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -132,6 +132,28 @@ struct clk_fixed_rate {
#define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_platdata(dev))
+struct clk_composite { + struct clk clk; + struct clk_ops ops; + + struct clk *mux; + struct clk *rate; + struct clk *gate; + + const struct clk_ops *mux_ops; + const struct clk_ops *rate_ops; + const struct clk_ops *gate_ops; +}; + +#define to_clk_composite(_clk) container_of(_clk, struct clk_composite, clk) + +struct clk *clk_register_composite(struct device *dev, const char *name, + const char * const *parent_names, int num_parents, + struct clk *mux_clk, const struct clk_ops *mux_ops, + struct clk *rate_clk, const struct clk_ops *rate_ops, + struct clk *gate_clk, const struct clk_ops *gate_ops, + unsigned long flags); + int clk_register(struct clk *clk, const char *drv_name, const char *name, const char *parent_name);

Because clk-provider use clk_ops, so let's include clk-uclass.h
Signed-off-by: Peng Fan peng.fan@nxp.com --- include/linux/clk-provider.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 9c292f555d..32a777d86c 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -8,6 +8,7 @@ */ #ifndef __LINUX_CLK_PROVIDER_H #define __LINUX_CLK_PROVIDER_H +#include <clk-uclass.h>
static inline void clk_dm(ulong id, struct clk *clk) {

Introduce io_gate_val for sandbox clk gate test usage
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/clk-gate.c | 11 +++++++++++ include/linux/clk-provider.h | 3 +++ 2 files changed, 14 insertions(+)
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index a3a1fdd3b2..70b8794554 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -55,7 +55,11 @@ static void clk_gate_endisable(struct clk *clk, int enable) if (set) reg |= BIT(gate->bit_idx); } else { +#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) + reg = gate->io_gate_val; +#else reg = readl(gate->reg); +#endif
if (set) reg |= BIT(gate->bit_idx); @@ -86,7 +90,11 @@ int clk_gate_is_enabled(struct clk *clk) dev_get_clk_ptr(clk->dev) : clk); u32 reg;
+#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) + reg = gate->io_gate_val; +#else reg = readl(gate->reg); +#endif
/* if a set bit disables this clk, flip it before masking */ if (gate->flags & CLK_GATE_SET_TO_DISABLE) @@ -128,6 +136,9 @@ struct clk *clk_register_gate(struct device *dev, const char *name, gate->reg = reg; gate->bit_idx = bit_idx; gate->flags = clk_gate_flags; +#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) + gate->io_gate_val = *(u32 *)reg; +#endif
clk = &gate->clk;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 32a777d86c..1e8183207d 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -75,6 +75,9 @@ struct clk_gate { void __iomem *reg; u8 bit_idx; u8 flags; +#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) + u32 io_gate_val; +#endif };
#define to_clk_gate(_clk) container_of(_clk, struct clk_gate, clk)

Add composite clk to sandbox driver
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/clk/clk_sandbox_ccf.c | 80 +++++++++++++++++++++++++++++++++++++++++++ include/sandbox-clk.h | 1 + 2 files changed, 81 insertions(+)
diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c index edeb0f2cf3..e126f18d8e 100644 --- a/drivers/clk/clk_sandbox_ccf.c +++ b/drivers/clk/clk_sandbox_ccf.c @@ -130,6 +130,80 @@ U_BOOT_DRIVER(sandbox_clk_gate2) = { .ops = &clk_gate2_ops, };
+static unsigned long sandbox_clk_composite_divider_recalc_rate(struct clk *clk) +{ + struct clk_divider *divider = (struct clk_divider *)to_clk_divider(clk); + struct clk_composite *composite = (struct clk_composite *)clk->data; + ulong parent_rate = clk_get_parent_rate(&composite->clk); + unsigned int val; + + val = divider->io_divider_val; + val >>= divider->shift; + val &= clk_div_mask(divider->width); + + return divider_recalc_rate(clk, parent_rate, val, divider->table, + divider->flags, divider->width); +} + +static const struct clk_ops sandbox_clk_composite_divider_ops = { + .get_rate = sandbox_clk_composite_divider_recalc_rate, +}; + +struct clk *sandbox_clk_composite(const char *name, + const char * const *parent_names, + int num_parents, void __iomem *reg, + unsigned long flags) +{ + struct clk *clk = ERR_PTR(-ENOMEM); + struct clk_divider *div = NULL; + struct clk_gate *gate = NULL; + struct clk_mux *mux = NULL; + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + goto fail; + + mux->reg = reg; + mux->shift = 24; + mux->mask = 0x7; + mux->num_parents = num_parents; + mux->flags = flags; + mux->parent_names = parent_names; + + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) + goto fail; + + div->reg = reg; + div->shift = 16; + div->width = 3; + div->flags = CLK_DIVIDER_ROUND_CLOSEST | flags; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + goto fail; + + gate->reg = reg; + gate->bit_idx = 28; + gate->flags = flags; + + clk = clk_register_composite(NULL, name, + parent_names, num_parents, + &mux->clk, &clk_mux_ops, &div->clk, + &sandbox_clk_composite_divider_ops, + &gate->clk, &clk_gate_ops, flags); + if (IS_ERR(clk)) + goto fail; + + return clk; + +fail: + kfree(gate); + kfree(div); + kfree(mux); + return ERR_CAST(clk); +} + /* --- Sandbox Gate --- */ /* The CCF core driver itself */ static const struct udevice_id sandbox_clk_ccf_test_ids[] = { @@ -138,6 +212,7 @@ static const struct udevice_id sandbox_clk_ccf_test_ids[] = { };
static const char *const usdhc_sels[] = { "pll3_60m", "pll3_80m", }; +static const char *const i2c_sels[] = { "pll3_60m", "pll3_80m", };
static int sandbox_clk_ccf_probe(struct udevice *dev) { @@ -174,6 +249,11 @@ static int sandbox_clk_ccf_probe(struct udevice *dev) sandbox_clk_mux("usdhc2_sel", ®, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)));
+ reg = BIT(28) | BIT(24) | BIT(16); + clk_dm(SANDBOX_CLK_I2C, + sandbox_clk_composite("i2c", i2c_sels, ARRAY_SIZE(i2c_sels), + ®, 0)); + return 0; }
diff --git a/include/sandbox-clk.h b/include/sandbox-clk.h index 37c9838f76..f449de1364 100644 --- a/include/sandbox-clk.h +++ b/include/sandbox-clk.h @@ -19,6 +19,7 @@ enum { SANDBOX_CLK_ECSPI1, SANDBOX_CLK_USDHC1_SEL, SANDBOX_CLK_USDHC2_SEL, + SANDBOX_CLK_I2C, };
enum sandbox_pllv3_type {

Test composite clk with dm ccf
Signed-off-by: Peng Fan peng.fan@nxp.com --- test/dm/clk_ccf.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c index 8d397593a3..bbc4b500e8 100644 --- a/test/dm/clk_ccf.c +++ b/test/dm/clk_ccf.c @@ -56,6 +56,14 @@ static int dm_test_clk_ccf(struct unit_test_state *uts) pclk = clk_get_parent(clk); ut_asserteq_str("pll3_80m", pclk->dev->name);
+ /* Test the composite of CCF */ + ret = clk_get_by_id(SANDBOX_CLK_I2C, &clk); + ut_assertok(ret); + ut_asserteq_str("i2c", clk->dev->name); + + rate = clk_get_rate(clk); + ut_asserteq(rate, 60000000); + return 1; }

Enable composite clk for sandbox test
Signed-off-by: Peng Fan peng.fan@nxp.com --- configs/sandbox_defconfig | 1 + configs/sandbox_flattree_defconfig | 1 + 2 files changed, 2 insertions(+)
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index f9c9b19b6d..402c6d4e19 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -91,6 +91,7 @@ CONFIG_BOOTCOUNT_LIMIT=y CONFIG_DM_BOOTCOUNT=y CONFIG_DM_BOOTCOUNT_RTC=y CONFIG_CLK=y +CONFIG_CLK_COMPOSITE_CCF=y CONFIG_SANDBOX_CLK_CCF=y CONFIG_CPU=y CONFIG_DM_DEMO=y diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index 2429ae4621..610457e0aa 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -66,6 +66,7 @@ CONFIG_DEBUG_DEVRES=y CONFIG_ADC=y CONFIG_ADC_SANDBOX=y CONFIG_CLK=y +CONFIG_CLK_COMPOSITE_CCF=y CONFIG_SANDBOX_CLK_CCF=y CONFIG_CPU=y CONFIG_DM_DEMO=y

Hi Lukasz,
Subject: [PATCH 01/16] clk: introduce clk_dev_binded
Do you have time to review the patchset? Patches were delegated to you.
Thanks, Peng.
When support Clock Common Framework, U-Boot use dev for clk tree information, there is no clk->parent. When support composite clk, it contains mux/gate/divider, but the mux/gate/divider is not binded with device. So we could not use dev_get_uclass_priv to get the correct clk_mux/gate/divider. So add clk_dev_binded to let choose the correct method.
Signed-off-by: Peng Fan peng.fan@nxp.com
drivers/clk/clk.c | 8 ++++++++ include/clk.h | 9 +++++++++ 2 files changed, 17 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7d748c9fc7..39b3087067 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -55,3 +55,11 @@ const char *clk_hw_get_name(const struct clk *hw) { return hw->dev->name; }
+bool clk_dev_binded(struct clk *clk) +{
- if (clk->dev && (clk->dev->flags & DM_FLAG_BOUND))
return true;
- return false;
+} diff --git a/include/clk.h b/include/clk.h index f8f56d9cf0..2ebc905e04 100644 --- a/include/clk.h +++ b/include/clk.h @@ -356,4 +356,13 @@ static inline bool clk_valid(struct clk *clk)
- @return zero on success, or -ENOENT on error
*/ int clk_get_by_id(ulong id, struct clk **clkp);
+/**
- clk_dev_binded() - Check whether the clk has a device binded
- @clk A pointer to the clk
- @return true on binded, or false on no */ bool
+clk_dev_binded(struct clk *clk);
#endif
2.16.4

Hi Peng,
Hi Lukasz,
Subject: [PATCH 01/16] clk: introduce clk_dev_binded
Do you have time to review the patchset? Patches were delegated to you.
The i.MX related PR (with base CCF) has been pulled to mainline just yesteday, so I'm going to rewiew and test your code on top of it (with buildman) today.
I shall send PR for -clk tomorrow.
Thanks for your patches.
Thanks, Peng.
When support Clock Common Framework, U-Boot use dev for clk tree information, there is no clk->parent. When support composite clk, it contains mux/gate/divider, but the mux/gate/divider is not binded with device. So we could not use dev_get_uclass_priv to get the correct clk_mux/gate/divider. So add clk_dev_binded to let choose the correct method.
Signed-off-by: Peng Fan peng.fan@nxp.com
drivers/clk/clk.c | 8 ++++++++ include/clk.h | 9 +++++++++ 2 files changed, 17 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7d748c9fc7..39b3087067 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -55,3 +55,11 @@ const char *clk_hw_get_name(const struct clk *hw) { return hw->dev->name; }
+bool clk_dev_binded(struct clk *clk) +{
- if (clk->dev && (clk->dev->flags & DM_FLAG_BOUND))
return true;
- return false;
+} diff --git a/include/clk.h b/include/clk.h index f8f56d9cf0..2ebc905e04 100644 --- a/include/clk.h +++ b/include/clk.h @@ -356,4 +356,13 @@ static inline bool clk_valid(struct clk *clk)
- @return zero on success, or -ENOENT on error
*/ int clk_get_by_id(ulong id, struct clk **clkp);
+/**
- clk_dev_binded() - Check whether the clk has a device binded
- @clk A pointer to the clk
- @return true on binded, or false on no */ bool
+clk_dev_binded(struct clk *clk);
#endif
2.16.4
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Subject: Re: [PATCH 01/16] clk: introduce clk_dev_binded
Hi Peng,
Hi Lukasz,
Subject: [PATCH 01/16] clk: introduce clk_dev_binded
Do you have time to review the patchset? Patches were delegated to you.
The i.MX related PR (with base CCF) has been pulled to mainline just yesteday, so I'm going to rewiew and test your code on top of it (with buildman) today.
Thanks very much.
Thanks, Peng.
I shall send PR for -clk tomorrow.
Thanks for your patches.
Thanks, Peng.
When support Clock Common Framework, U-Boot use dev for clk tree information, there is no clk->parent. When support composite clk, it contains mux/gate/divider, but the mux/gate/divider is not binded with device. So we could not use dev_get_uclass_priv to get the correct clk_mux/gate/divider. So add clk_dev_binded to let choose the correct method.
Signed-off-by: Peng Fan peng.fan@nxp.com
drivers/clk/clk.c | 8 ++++++++ include/clk.h | 9 +++++++++ 2 files changed, 17 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7d748c9fc7..39b3087067 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -55,3 +55,11 @@ const char *clk_hw_get_name(const struct clk
*hw)
{ return hw->dev->name; }
+bool clk_dev_binded(struct clk *clk) {
- if (clk->dev && (clk->dev->flags & DM_FLAG_BOUND))
return true;
- return false;
+} diff --git a/include/clk.h b/include/clk.h index f8f56d9cf0..2ebc905e04 100644 --- a/include/clk.h +++ b/include/clk.h @@ -356,4 +356,13 @@ static inline bool clk_valid(struct clk *clk)
- @return zero on success, or -ENOENT on error
*/ int clk_get_by_id(ulong id, struct clk **clkp);
+/**
- clk_dev_binded() - Check whether the clk has a device binded
- @clk A pointer to the clk
- @return true on binded, or false on no */ bool
+clk_dev_binded(struct clk *clk);
#endif
2.16.4
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Hi Peng,
Hi Peng,
Hi Lukasz,
Subject: [PATCH 01/16] clk: introduce clk_dev_binded
Do you have time to review the patchset? Patches were delegated to you.
The i.MX related PR (with base CCF) has been pulled to mainline just yesteday, so I'm going to rewiew and test your code on top of it (with buildman) today.
I shall send PR for -clk tomorrow.
The patches from this series causes the sandbox travis-ci to break: https://travis-ci.org/lmajewski/u-boot-dfu/builds/565204559
Please fix those errors.
You can also reproduce this issue with:
./tools/buildman/buildman.py --branch=HEAD sandbox --show_errors --force-build --count=16 --output-dir=../BUILD/
run on this series.
Thanks for your patches.
Thanks, Peng.
When support Clock Common Framework, U-Boot use dev for clk tree information, there is no clk->parent. When support composite clk, it contains mux/gate/divider, but the mux/gate/divider is not binded with device. So we could not use dev_get_uclass_priv to get the correct clk_mux/gate/divider. So add clk_dev_binded to let choose the correct method.
Signed-off-by: Peng Fan peng.fan@nxp.com
drivers/clk/clk.c | 8 ++++++++ include/clk.h | 9 +++++++++ 2 files changed, 17 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7d748c9fc7..39b3087067 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -55,3 +55,11 @@ const char *clk_hw_get_name(const struct clk *hw) { return hw->dev->name; }
+bool clk_dev_binded(struct clk *clk) +{
- if (clk->dev && (clk->dev->flags & DM_FLAG_BOUND))
return true;
- return false;
+} diff --git a/include/clk.h b/include/clk.h index f8f56d9cf0..2ebc905e04 100644 --- a/include/clk.h +++ b/include/clk.h @@ -356,4 +356,13 @@ static inline bool clk_valid(struct clk *clk)
- @return zero on success, or -ENOENT on error
*/ int clk_get_by_id(ulong id, struct clk **clkp);
+/**
- clk_dev_binded() - Check whether the clk has a device binded
- @clk A pointer to the clk
- @return true on binded, or false on no */ bool
+clk_dev_binded(struct clk *clk);
#endif
2.16.4
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Hi Lukasz,
Subject: Re: [PATCH 01/16] clk: introduce clk_dev_binded
Hi Peng,
Hi Peng,
Hi Lukasz,
Subject: [PATCH 01/16] clk: introduce clk_dev_binded
Do you have time to review the patchset? Patches were delegated to you.
The i.MX related PR (with base CCF) has been pulled to mainline just yesteday, so I'm going to rewiew and test your code on top of it (with buildman) today.
I shall send PR for -clk tomorrow.
The patches from this series causes the sandbox travis-ci to break: https://travis-ci.org/lmajewski/u-boot-dfu/builds/565204559
I ran qcheck before posting patches.
Please fix those errors.
You can also reproduce this issue with:
./tools/buildman/buildman.py --branch=HEAD sandbox --show_errors --force-build --count=16 --output-dir=../BUILD/
I'll fix soon.
Thanks, Peng.
run on this series.
Thanks for your patches.
Thanks, Peng.
When support Clock Common Framework, U-Boot use dev for clk tree information, there is no clk->parent. When support composite clk, it contains mux/gate/divider, but the mux/gate/divider is not binded with device. So we could not use dev_get_uclass_priv to get the correct clk_mux/gate/divider. So add clk_dev_binded to let choose the correct method.
Signed-off-by: Peng Fan peng.fan@nxp.com
drivers/clk/clk.c | 8 ++++++++ include/clk.h | 9 +++++++++ 2 files changed, 17 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7d748c9fc7..39b3087067 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -55,3 +55,11 @@ const char *clk_hw_get_name(const struct clk *hw) { return hw->dev->name; }
+bool clk_dev_binded(struct clk *clk) {
- if (clk->dev && (clk->dev->flags & DM_FLAG_BOUND))
return true;
- return false;
+} diff --git a/include/clk.h b/include/clk.h index f8f56d9cf0..2ebc905e04 100644 --- a/include/clk.h +++ b/include/clk.h @@ -356,4 +356,13 @@ static inline bool clk_valid(struct clk *clk)
- @return zero on success, or -ENOENT on error
*/ int clk_get_by_id(ulong id, struct clk **clkp);
+/**
- clk_dev_binded() - Check whether the clk has a device binded
- @clk A pointer to the clk
- @return true on binded, or false on no */ bool
+clk_dev_binded(struct clk *clk);
#endif
2.16.4
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang
Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Hi Lukasz,
Subject: RE: [PATCH 01/16] clk: introduce clk_dev_binded
Hi Lukasz,
Subject: Re: [PATCH 01/16] clk: introduce clk_dev_binded
Hi Peng,
Hi Peng,
Hi Lukasz,
Subject: [PATCH 01/16] clk: introduce clk_dev_binded
Do you have time to review the patchset? Patches were delegated to you.
The i.MX related PR (with base CCF) has been pulled to mainline just yesteday, so I'm going to rewiew and test your code on top of it (with buildman) today.
I shall send PR for -clk tomorrow.
The patches from this series causes the sandbox travis-ci to break: https://travis-ci.org/lmajewski/u-boot-dfu/builds/565204559
I ran qcheck before posting patches.
Missed a build warning when ran qcheck.
It was divider_recalc_rate missed add to clk-provider.h. Just posted out v2.
Thanks, Peng.
Please fix those errors.
You can also reproduce this issue with:
./tools/buildman/buildman.py --branch=HEAD sandbox --show_errors --force-build --count=16 --output-dir=../BUILD/
I'll fix soon.
Thanks, Peng.
run on this series.
Thanks for your patches.
Thanks, Peng.
When support Clock Common Framework, U-Boot use dev for clk tree information, there is no clk->parent. When support composite clk, it contains mux/gate/divider, but the mux/gate/divider is not binded with device. So we could not use dev_get_uclass_priv to get the correct clk_mux/gate/divider. So add clk_dev_binded to let choose the correct method.
Signed-off-by: Peng Fan peng.fan@nxp.com
drivers/clk/clk.c | 8 ++++++++ include/clk.h | 9 +++++++++ 2 files changed, 17 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7d748c9fc7..39b3087067 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -55,3 +55,11 @@ const char *clk_hw_get_name(const struct clk *hw) { return hw->dev->name; }
+bool clk_dev_binded(struct clk *clk) {
- if (clk->dev && (clk->dev->flags & DM_FLAG_BOUND))
return true;
- return false;
+} diff --git a/include/clk.h b/include/clk.h index f8f56d9cf0..2ebc905e04 100644 --- a/include/clk.h +++ b/include/clk.h @@ -356,4 +356,13 @@ static inline bool clk_valid(struct clk *clk)
- @return zero on success, or -ENOENT on error
*/ int clk_get_by_id(ulong id, struct clk **clkp);
+/**
- clk_dev_binded() - Check whether the clk has a device binded
- @clk A pointer to the clk
- @return true on binded, or false on no */ bool
+clk_dev_binded(struct clk *clk);
#endif
2.16.4
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang
Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang
Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
participants (2)
-
Lukasz Majewski
-
Peng Fan