From af616888c86534b0f6a9754b2cf63adf062fdb7d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 8 Mar 2019 15:03:41 +0100 Subject: clk: parent_names should be const Not only the array of pointers should be const, but also the strings they point to. Add missing const. Signed-off-by: Sascha Hauer --- include/linux/clk.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/clk.h b/include/linux/clk.h index ee888dc083..1f20eb2772 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -310,7 +310,7 @@ struct clk { int enable_count; struct list_head list; const char *name; - const char **parent_names; + const char * const *parent_names; int num_parents; struct clk **parents; @@ -384,11 +384,11 @@ struct clk_mux { extern struct clk_ops clk_mux_ops; struct clk *clk_mux_alloc(const char *name, void __iomem *reg, - u8 shift, u8 width, const char **parents, u8 num_parents, + u8 shift, u8 width, const char * const *parents, u8 num_parents, unsigned flags); void clk_mux_free(struct clk *clk_mux); struct clk *clk_mux(const char *name, void __iomem *reg, - u8 shift, u8 width, const char **parents, u8 num_parents, + u8 shift, u8 width, const char * const *parents, u8 num_parents, unsigned flags); struct clk_gate { @@ -429,7 +429,7 @@ struct clk *clk_lookup(const char *name); void clk_dump(int verbose); struct clk *clk_register_composite(const char *name, - const char **parent_names, int num_parents, + const char * const *parent_names, int num_parents, struct clk *mux_clk, struct clk *rate_clk, struct clk *gate_clk, -- cgit v1.2.3 From b9658388d7ffdc7f453c03763e91dba98a81dbda Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 8 Mar 2019 15:04:03 +0100 Subject: clk: export clk_gate_is_enabled() Will be needed by stm32 clk support. Signed-off-by: Sascha Hauer --- drivers/clk/clk-gate.c | 2 +- include/linux/clk.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 89240ff794..b2b160555e 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -56,7 +56,7 @@ static void clk_gate_disable(struct clk *clk) clk_gate_endisable(clk, 0); } -static int clk_gate_is_enabled(struct clk *clk) +int clk_gate_is_enabled(struct clk *clk) { struct clk_gate *g = container_of(clk, struct clk_gate, clk); u32 val; diff --git a/include/linux/clk.h b/include/linux/clk.h index 1f20eb2772..6081a1af87 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -399,6 +399,8 @@ struct clk_gate { unsigned flags; }; +int clk_gate_is_enabled(struct clk *clk); + #define to_clk_gate(_clk) container_of(_clk, struct clk_gate, clk) extern struct clk_ops clk_gate_ops; -- cgit v1.2.3 From 90f70a9825919037729c20ab3c5e8b30d08fe9de Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 11 Mar 2019 08:36:07 +0100 Subject: clk: Make CLK_IGNORE_UNUSED generic barebox will never disable unused clocks, so add CLK_IGNORE_UNUSED as a no-op flag. With this we can keep the changes to the imported kernel code smaller. Signed-off-by: Sascha Hauer --- drivers/clk/rockchip/clk.h | 1 - include/linux/clk.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index aa52638f70..d6798a9055 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -27,7 +27,6 @@ #include /* To keep changes from kernel smaller */ -#define CLK_IGNORE_UNUSED 0 #define CLK_GATE_SET_TO_DISABLE CLK_GATE_INVERTED #define CLK_GET_RATE_NOCACHE 0 diff --git a/include/linux/clk.h b/include/linux/clk.h index 6081a1af87..5b0a93095d 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -285,6 +285,7 @@ static inline void clk_put(struct clk *clk) #include #define CLK_SET_RATE_PARENT (1 << 0) /* propagate rate change up one level */ +#define CLK_IGNORE_UNUSED (1 << 3) /* do not gate even if unused */ /* parents need enable during gate/ungate, set rate and re-parent */ #define CLK_OPS_PARENT_ENABLE (1 << 12) -- cgit v1.2.3 From 1ae7f310d101e2bbba8d0fc80b582aee5e39ab8f Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 11 Mar 2019 08:40:42 +0100 Subject: clk: Support CLK_IS_CRITICAL flag Support CLK_IS_CRITICAL flag. Simply do not disable the clock even when the enable count is zero. Signed-off-by: Sascha Hauer --- drivers/clk/clk.c | 3 +++ include/linux/clk.h | 1 + 2 files changed, 4 insertions(+) (limited to 'include') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 6a2d8ad178..ea3304bc7c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -87,6 +87,9 @@ void clk_disable(struct clk *clk) clk->enable_count--; if (!clk->enable_count) { + if (clk->flags & CLK_IS_CRITICAL) + return; + if (clk->ops->disable) clk->ops->disable(clk); diff --git a/include/linux/clk.h b/include/linux/clk.h index 5b0a93095d..5ad12c571c 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -286,6 +286,7 @@ static inline void clk_put(struct clk *clk) #define CLK_SET_RATE_PARENT (1 << 0) /* propagate rate change up one level */ #define CLK_IGNORE_UNUSED (1 << 3) /* do not gate even if unused */ +#define CLK_IS_CRITICAL (1 << 11) /* do not gate, ever */ /* parents need enable during gate/ungate, set rate and re-parent */ #define CLK_OPS_PARENT_ENABLE (1 << 12) -- cgit v1.2.3 From 9339b5f05484b5e9f4a7e0b08b2c6ca6599aca6d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 11 Mar 2019 09:27:08 +0100 Subject: clk: divider: pass divider flags The generic clk divider needs clock flags and divider flags. Fix prototypes to take both as separate arguments. Signed-off-by: Sascha Hauer --- arch/arm/mach-clps711x/clock.c | 4 ++-- drivers/clk/clk-divider.c | 28 +++++++++++++++++----------- drivers/clk/imx/clk-vf610.c | 2 +- drivers/clk/imx/clk.h | 14 ++++++++------ drivers/clk/rockchip/clk.c | 6 +++--- include/linux/clk.h | 16 ++++++++++------ 6 files changed, 41 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-clps711x/clock.c b/arch/arm/mach-clps711x/clock.c index 4d6403b92e..2c5137c582 100644 --- a/arch/arm/mach-clps711x/clock.c +++ b/arch/arm/mach-clps711x/clock.c @@ -71,9 +71,9 @@ static __init int clps711x_clk_init(void) clks[CLPS711X_CLK_BUS] = clk_fixed("bus", f_bus); clks[CLPS711X_CLK_UART] = clk_fixed("uart", f_uart); clks[CLPS711X_CLK_TIMERREF] = clk_fixed("timer_ref", f_timer_ref); - clks[CLPS711X_CLK_TIMER1] = clk_divider_table("timer1", "timer_ref", + clks[CLPS711X_CLK_TIMER1] = clk_divider_table("timer1", "timer_ref", 0, IOMEM(SYSCON1), 5, 1, tdiv_tbl, ARRAY_SIZE(tdiv_tbl)); - clks[CLPS711X_CLK_TIMER2] = clk_divider_table("timer2", "timer_ref", + clks[CLPS711X_CLK_TIMER2] = clk_divider_table("timer2", "timer_ref", 0, IOMEM(SYSCON1), 7, 1, tdiv_tbl, ARRAY_SIZE(tdiv_tbl)); clkdev_add_physbase(clks[CLPS711X_CLK_UART], UARTDR1, NULL); diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 7b1bdde1ce..407aae78ea 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -249,7 +249,8 @@ struct clk_ops clk_divider_ops = { }; struct clk *clk_divider_alloc(const char *name, const char *parent, - void __iomem *reg, u8 shift, u8 width, unsigned flags) + unsigned clk_flags, void __iomem *reg, u8 shift, + u8 width, unsigned div_flags) { struct clk_divider *div = xzalloc(sizeof(*div)); @@ -257,9 +258,10 @@ struct clk *clk_divider_alloc(const char *name, const char *parent, div->reg = reg; div->width = width; div->parent = parent; + div->flags = div_flags; div->clk.ops = &clk_divider_ops; div->clk.name = name; - div->clk.flags = flags; + div->clk.flags = clk_flags; div->clk.parent_names = &div->parent; div->clk.num_parents = 1; @@ -273,13 +275,14 @@ void clk_divider_free(struct clk *clk) free(d); } -struct clk *clk_divider(const char *name, const char *parent, - void __iomem *reg, u8 shift, u8 width, unsigned flags) +struct clk *clk_divider(const char *name, const char *parent, unsigned clk_flags, + void __iomem *reg, u8 shift, u8 width, unsigned div_flags) { struct clk *d; int ret; - d = clk_divider_alloc(name , parent, reg, shift, width, flags); + d = clk_divider_alloc(name , parent, clk_flags, reg, shift, width, + div_flags); ret = clk_register(d); if (ret) { @@ -291,12 +294,13 @@ struct clk *clk_divider(const char *name, const char *parent, } struct clk *clk_divider_one_based(const char *name, const char *parent, - void __iomem *reg, u8 shift, u8 width, unsigned flags) + unsigned clk_flags, void __iomem *reg, u8 shift, + u8 width, unsigned div_flags) { struct clk_divider *div; struct clk *clk; - clk = clk_divider(name, parent, reg, shift, width, flags); + clk = clk_divider(name, parent, clk_flags, reg, shift, width, div_flags); if (IS_ERR(clk)) return clk; @@ -306,9 +310,10 @@ struct clk *clk_divider_one_based(const char *name, const char *parent, return clk; } -struct clk *clk_divider_table(const char *name, - const char *parent, void __iomem *reg, u8 shift, u8 width, - const struct clk_div_table *table, unsigned flags) +struct clk *clk_divider_table(const char *name, const char *parent, + unsigned clk_flags, void __iomem *reg, u8 shift, + u8 width, const struct clk_div_table *table, + unsigned div_flags) { struct clk_divider *div = xzalloc(sizeof(*div)); const struct clk_div_table *clkt; @@ -318,9 +323,10 @@ struct clk *clk_divider_table(const char *name, div->reg = reg; div->width = width; div->parent = parent; + div->flags = div_flags; div->clk.ops = &clk_divider_ops; div->clk.name = name; - div->clk.flags = flags; + div->clk.flags = clk_flags; div->clk.parent_names = &div->parent; div->clk.num_parents = 1; div->table = table; diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 49d66fb592..1b1b881052 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -252,7 +252,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_IPG_BUS] = imx_clk_divider("ipg_bus", "platform_bus", CCM_CACRR, 11, 2); clk[VF610_CLK_PLL3_MAIN_DIV] = imx_clk_divider("pll3_usb_otg_div", "pll3_usb_otg", CCM_CACRR, 20, 1); - clk[VF610_CLK_PLL4_MAIN_DIV] = clk_divider_table("pll4_audio_div", "pll4_audio", CCM_CACRR, 6, 3, pll4_audio_div_table, 0); + clk[VF610_CLK_PLL4_MAIN_DIV] = clk_divider_table("pll4_audio_div", "pll4_audio", 0, CCM_CACRR, 6, 3, pll4_audio_div_table, 0); clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1); clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", "ddr_sel", CCM_CCGR6, CCM_CCGRx_CGn(14), 0x2); diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 945671cbad..60fe36c6c6 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -7,34 +7,36 @@ struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg, static inline struct clk *imx_clk_divider(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width) { - return clk_divider(name, parent, reg, shift, width, CLK_SET_RATE_PARENT); + return clk_divider(name, parent, CLK_SET_RATE_PARENT, reg, shift, width, + 0); } static inline struct clk *imx_clk_divider_flags(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width, unsigned long flags) { - return clk_divider(name, parent, reg, shift, width, flags); + return clk_divider(name, parent, flags, reg, shift, width, 0); } static inline struct clk *imx_clk_divider_np(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width) { - return clk_divider(name, parent, reg, shift, width, 0); + return clk_divider(name, parent, 0, 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_divider(name, parent, reg, shift, width, CLK_OPS_PARENT_ENABLE); + return clk_divider(name, parent, CLK_OPS_PARENT_ENABLE, reg, shift, + width, 0); } static inline struct clk *imx_clk_divider_table(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width, const struct clk_div_table *table) { - return clk_divider_table(name, parent, reg, shift, width, table, - CLK_SET_RATE_PARENT); + return clk_divider_table(name, parent, CLK_SET_RATE_PARENT, reg, shift, + width, table, 0); } static inline struct clk *imx_clk_fixed_factor(const char *name, diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 3222a4e09e..35729e0cfc 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -64,7 +64,7 @@ static struct clk *rockchip_clk_register_branch(const char *name, } if (div_width > 0) { - div = clk_divider_alloc(name, *parent_names, + div = clk_divider_alloc(name, *parent_names, 0, base + muxdiv_offset, div_shift, div_width, div_flags); if (!div) return ERR_PTR(-ENOMEM); @@ -188,13 +188,13 @@ void __init rockchip_clk_register_branches( case branch_divider: if (list->div_table) clk = clk_divider_table(list->name, - list->parent_names[0], + list->parent_names[0], flags, reg_base + list->muxdiv_offset, list->div_shift, list->div_width, list->div_table, list->div_flags); else clk = clk_divider(list->name, - list->parent_names[0], + list->parent_names[0], flags, reg_base + list->muxdiv_offset, list->div_shift, list->div_width, list->div_flags); diff --git a/include/linux/clk.h b/include/linux/clk.h index 5ad12c571c..65d163c78d 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -352,15 +352,19 @@ unsigned long divider_recalc_rate(struct clk *clk, unsigned long parent_rate, unsigned long flags, unsigned long width); struct clk *clk_divider_alloc(const char *name, const char *parent, - void __iomem *reg, u8 shift, u8 width, unsigned flags); + unsigned clk_flags, void __iomem *reg, + u8 shift, u8 width, unsigned div_flags); void clk_divider_free(struct clk *clk_divider); struct clk *clk_divider(const char *name, const char *parent, - void __iomem *reg, u8 shift, u8 width, unsigned flags); + unsigned clk_flags, void __iomem *reg, u8 shift, + u8 width, unsigned div_flags); struct clk *clk_divider_one_based(const char *name, const char *parent, - void __iomem *reg, u8 shift, u8 width, unsigned flags); -struct clk *clk_divider_table(const char *name, - const char *parent, void __iomem *reg, u8 shift, u8 width, - const struct clk_div_table *table, unsigned flags); + unsigned clk_flags, void __iomem *reg, + u8 shift, u8 width, unsigned div_flags); +struct clk *clk_divider_table(const char *name, const char *parent, + unsigned clk_flags, void __iomem *reg, u8 shift, + u8 width, const struct clk_div_table *table, + unsigned div_flags); struct clk *clk_fixed_factor(const char *name, const char *parent, unsigned int mult, unsigned int div, unsigned flags); -- cgit v1.2.3 From df44d586d0d70c2189103e60807d33f3267e8021 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 11 Mar 2019 09:31:39 +0100 Subject: clk: divider: Support CLK_DIVIDER_READ_ONLY flag To support a readonly divider add the CLK_DIVIDER_READ_ONLY flag. Signed-off-by: Sascha Hauer --- drivers/clk/clk-divider.c | 7 +++++++ drivers/clk/rockchip/clk-rk3188.c | 1 - drivers/clk/rockchip/clk-rk3288.c | 1 - include/linux/clk.h | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 407aae78ea..d9d3407e75 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -203,8 +203,12 @@ static int clk_divider_bestdiv(struct clk *clk, unsigned long rate, static long clk_divider_round_rate(struct clk *clk, unsigned long rate, unsigned long *parent_rate) { + struct clk_divider *divider = container_of(clk, struct clk_divider, clk); int div; + if (divider->flags & CLK_DIVIDER_READ_ONLY) + return clk_divider_recalc_rate(clk, *parent_rate); + div = clk_divider_bestdiv(clk, rate, parent_rate); return *parent_rate / div; @@ -217,6 +221,9 @@ static int clk_divider_set_rate(struct clk *clk, unsigned long rate, unsigned int div, value; u32 val; + if (divider->flags & CLK_DIVIDER_READ_ONLY) + return 0; + if (clk->flags & CLK_SET_RATE_PARENT) { unsigned long best_parent_rate = parent_rate; div = clk_divider_bestdiv(clk, rate, &best_parent_rate); diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 7dda2963e3..8ed3a6d894 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -26,7 +26,6 @@ #define RK3188_GRF_SOC_STATUS 0xac #define CLK_SET_RATE_NO_REPARENT 0 -#define CLK_DIVIDER_READ_ONLY 0 enum rk3188_plls { apll, cpll, dpll, gpll, diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index bb111e1e0b..e7cc9c1b5b 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -26,7 +26,6 @@ #define RK3288_GRF_SOC_STATUS1 0x284 #define CLK_SET_RATE_NO_REPARENT 0 -#define CLK_DIVIDER_READ_ONLY 0 enum rk3288_plls { apll, dpll, cpll, gpll, npll, diff --git a/include/linux/clk.h b/include/linux/clk.h index 65d163c78d..2de963e7e9 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -341,6 +341,7 @@ struct clk_divider { #define CLK_DIVIDER_POWER_OF_TWO (1 << 1) #define CLK_DIVIDER_HIWORD_MASK (1 << 3) +#define CLK_DIVIDER_READ_ONLY (1 << 5) #define CLK_MUX_HIWORD_MASK (1 << 2) -- cgit v1.2.3 From a2fbc210ade163ea3e746f49269b698bd8e5b7ed Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 11 Mar 2019 09:40:18 +0100 Subject: clk: mux: Support mux specific flags We'll need mux specific flags in the future, so add a parameter to the mux initialization functions. Signed-off-by: Sascha Hauer --- drivers/clk/clk-mux.c | 15 +++++++++------ drivers/clk/imx/clk.h | 19 +++++++++++-------- drivers/clk/mxs/clk.h | 2 +- drivers/clk/rockchip/clk-pll.c | 3 ++- drivers/clk/rockchip/clk.c | 10 +++------- drivers/clk/tegra/clk-periph.c | 2 +- include/linux/clk.h | 14 ++++++++------ 7 files changed, 35 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index a108a72d63..ebf736bdff 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -51,18 +51,19 @@ struct clk_ops clk_mux_ops = { .set_parent = clk_mux_set_parent, }; -struct clk *clk_mux_alloc(const char *name, void __iomem *reg, +struct clk *clk_mux_alloc(const char *name, unsigned clk_flags, void __iomem *reg, u8 shift, u8 width, const char * const *parents, u8 num_parents, - unsigned flags) + unsigned mux_flags) { struct clk_mux *m = xzalloc(sizeof(*m)); m->reg = reg; m->shift = shift; m->width = width; + m->flags = mux_flags; m->clk.ops = &clk_mux_ops; m->clk.name = name; - m->clk.flags = flags; + m->clk.flags = clk_flags; m->clk.parent_names = parents; m->clk.num_parents = num_parents; @@ -76,13 +77,15 @@ void clk_mux_free(struct clk *clk_mux) free(m); } -struct clk *clk_mux(const char *name, void __iomem *reg, - u8 shift, u8 width, const char * const *parents, u8 num_parents, unsigned flags) +struct clk *clk_mux(const char *name, unsigned clk_flags, void __iomem *reg, + u8 shift, u8 width, const char * const *parents, + u8 num_parents, unsigned mux_flags) { struct clk *m; int ret; - m = clk_mux_alloc(name, reg, shift, width, parents, num_parents, flags); + m = clk_mux_alloc(name, clk_flags, reg, shift, width, parents, + num_parents, mux_flags); ret = clk_register(m); if (ret) { diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 60fe36c6c6..875c76a8b3 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -48,35 +48,38 @@ static inline struct clk *imx_clk_fixed_factor(const char *name, static inline struct clk *imx_clk_mux_flags(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, u8 num_parents, - unsigned long flags) + unsigned long clk_flags) { - return clk_mux(name, reg, shift, width, parents, num_parents, flags); + return clk_mux(name, clk_flags, reg, shift, width, parents, num_parents, + 0); } static inline struct clk *imx_clk_mux2_flags(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, - int num_parents, unsigned long flags) + int num_parents, unsigned long clk_flags) { - return clk_mux(name, reg, shift, width, parents, num_parents, - flags | CLK_OPS_PARENT_ENABLE); + return clk_mux(name, clk_flags | CLK_OPS_PARENT_ENABLE, reg, shift, + width, parents, num_parents, 0); } static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, u8 num_parents) { - return clk_mux(name, reg, shift, width, parents, num_parents, 0); + return clk_mux(name, 0, reg, shift, width, parents, num_parents, 0); } static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, u8 num_parents) { - return clk_mux(name, reg, shift, width, parents, num_parents, CLK_OPS_PARENT_ENABLE); + return clk_mux(name, CLK_OPS_PARENT_ENABLE, reg, shift, width, parents, + num_parents, 0); } static inline struct clk *imx_clk_mux_p(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, u8 num_parents) { - return clk_mux(name, reg, shift, width, parents, num_parents, CLK_SET_RATE_PARENT); + return clk_mux(name, CLK_SET_RATE_PARENT, reg, shift, width, parents, + num_parents, 0); } static inline struct clk *imx_clk_gate(const char *name, const char *parent, diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h index 7bab7b5e6e..00895de507 100644 --- a/drivers/clk/mxs/clk.h +++ b/drivers/clk/mxs/clk.h @@ -40,7 +40,7 @@ static inline struct clk *mxs_clk_gate(const char *name, static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parent_names, int num_parents) { - return clk_mux(name, reg, shift, width, parent_names, num_parents, 0); + return clk_mux(name, 0, reg, shift, width, parent_names, num_parents, 0); } static inline struct clk *mxs_clk_fixed_factor(const char *name, diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 87a3969c28..39ccf0a226 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -352,7 +352,8 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, pll_parents[1] = pll->pll_name; pll_parents[2] = parent_names[1]; - pll_mux = clk_mux_alloc(name, base + mode_offset, mode_shift, PLL_MODE_MASK, pll_parents, 3, CLK_SET_RATE_PARENT); + pll_mux = clk_mux_alloc(name, CLK_SET_RATE_PARENT, base + mode_offset, mode_shift, + PLL_MODE_MASK, pll_parents, 3, 0); pll->pll_mux_ops = pll_mux->ops; mux_clk = pll_mux; diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 35729e0cfc..9e0cbadd57 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -50,7 +50,7 @@ static struct clk *rockchip_clk_register_branch(const char *name, struct clk *div = NULL; if (num_parents > 1) { - mux = clk_mux_alloc(name, base + muxdiv_offset, mux_shift, + mux = clk_mux_alloc(name, 0, base + muxdiv_offset, mux_shift, mux_width, parent_names, num_parents, mux_flags); if (!mux) return ERR_PTR(-ENOMEM); @@ -176,14 +176,10 @@ void __init rockchip_clk_register_branches( /* catch simple muxes */ switch (list->branch_type) { case branch_mux: - /* - * mux_flags and flags are ored, this is safe, - * since there is no value clash, but isn't that elegant - */ - clk = clk_mux(list->name, + clk = clk_mux(list->name, flags, reg_base + list->muxdiv_offset, list->mux_shift, list->mux_width, list->parent_names, - list->num_parents, list->mux_flags | flags); + list->num_parents, list->mux_flags); break; case branch_divider: if (list->div_table) diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index fd1e2ed2c6..b4182861e7 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -123,7 +123,7 @@ static struct clk *_tegra_clk_register_periph(const char *name, goto out_periph; } - periph->mux = clk_mux_alloc(NULL, clk_base + reg_offset, 32 - mux_size, + periph->mux = clk_mux_alloc(NULL, 0, clk_base + reg_offset, 32 - mux_size, mux_size, parent_names, num_parents, 0); if (!periph->mux) goto out_mux; diff --git a/include/linux/clk.h b/include/linux/clk.h index 2de963e7e9..2e698e2ea6 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -384,19 +384,21 @@ struct clk_mux { void __iomem *reg; int shift; int width; + unsigned flags; }; #define to_clk_mux(_clk) container_of(_clk, struct clk_mux, clk) extern struct clk_ops clk_mux_ops; -struct clk *clk_mux_alloc(const char *name, void __iomem *reg, - u8 shift, u8 width, const char * const *parents, u8 num_parents, - unsigned flags); +struct clk *clk_mux_alloc(const char *name, unsigned clk_flags, + void __iomem *reg, u8 shift, u8 width, + const char * const *parents, u8 num_parents, + unsigned mux_flags); void clk_mux_free(struct clk *clk_mux); -struct clk *clk_mux(const char *name, void __iomem *reg, - u8 shift, u8 width, const char * const *parents, u8 num_parents, - unsigned flags); +struct clk *clk_mux(const char *name, unsigned clk_flags, void __iomem *reg, + u8 shift, u8 width, const char * const *parents, + u8 num_parents, unsigned mux_flags); struct clk_gate { struct clk clk; -- cgit v1.2.3 From c7cc27d006ccca5951b8fecb596d546998181f7c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 11 Mar 2019 09:44:15 +0100 Subject: clk: mux: Support CLK_MUX_READ_ONLY flag Support readonly dividers using the CLK_MUX_READ_ONLY flag. Signed-off-by: Sascha Hauer --- drivers/clk/clk-mux.c | 7 +++++++ include/linux/clk.h | 1 + 2 files changed, 8 insertions(+) (limited to 'include') diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index ebf736bdff..e9cb614005 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -33,6 +33,13 @@ static int clk_mux_set_parent(struct clk *clk, u8 idx) struct clk_mux *m = container_of(clk, struct clk_mux, clk); u32 val; + if (m->flags & CLK_MUX_READ_ONLY) { + if (clk_mux_get_parent(clk) != idx) + return -EPERM; + else + return 0; + } + val = readl(m->reg); val &= ~(((1 << m->width) - 1) << m->shift); val |= idx << m->shift; diff --git a/include/linux/clk.h b/include/linux/clk.h index 2e698e2ea6..2492608a15 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -344,6 +344,7 @@ struct clk_divider { #define CLK_DIVIDER_READ_ONLY (1 << 5) #define CLK_MUX_HIWORD_MASK (1 << 2) +#define CLK_MUX_READ_ONLY (1 << 3) /* mux can't be changed */ extern struct clk_ops clk_divider_ops; -- cgit v1.2.3 From e0e87be220fa4f1182462e772aa77454f799d40d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 11 Mar 2019 09:49:25 +0100 Subject: clk: mux: Support CLK_SET_RATE_NO_REPARENT flag Since barebox doesn't do reparenting on rate changes we only have to define the flag. Signed-off-by: Sascha Hauer --- drivers/clk/rockchip/clk-rk3188.c | 2 -- drivers/clk/rockchip/clk-rk3288.c | 2 -- include/linux/clk.h | 1 + 3 files changed, 1 insertion(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 8ed3a6d894..9340739945 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -25,8 +25,6 @@ #define RK3066_GRF_SOC_STATUS 0x15c #define RK3188_GRF_SOC_STATUS 0xac -#define CLK_SET_RATE_NO_REPARENT 0 - enum rk3188_plls { apll, cpll, dpll, gpll, }; diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index e7cc9c1b5b..dcfaae2407 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -25,8 +25,6 @@ #define RK3288_GRF_SOC_CON(x) (0x244 + x * 4) #define RK3288_GRF_SOC_STATUS1 0x284 -#define CLK_SET_RATE_NO_REPARENT 0 - enum rk3288_plls { apll, dpll, cpll, gpll, npll, }; diff --git a/include/linux/clk.h b/include/linux/clk.h index 2492608a15..b9c5e0ab04 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -286,6 +286,7 @@ static inline void clk_put(struct clk *clk) #define CLK_SET_RATE_PARENT (1 << 0) /* propagate rate change up one level */ #define CLK_IGNORE_UNUSED (1 << 3) /* do not gate even if unused */ +#define CLK_SET_RATE_NO_REPARENT (1 << 7) /* don't re-parent on rate change */ #define CLK_IS_CRITICAL (1 << 11) /* do not gate, ever */ /* parents need enable during gate/ungate, set rate and re-parent */ #define CLK_OPS_PARENT_ENABLE (1 << 12) -- cgit v1.2.3