diff options
-rw-r--r-- | drivers/clk/clk-mux.c | 2 | ||||
-rw-r--r-- | drivers/clk/clk.c | 13 | ||||
-rw-r--r-- | include/linux/clk-provider.h | 6 |
3 files changed, 20 insertions, 1 deletions
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 0811633fcc4d..2718b1139948 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -143,7 +143,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, init.ops = &clk_mux_ro_ops; else init.ops = &clk_mux_ops; - init.flags = flags | CLK_IS_BASIC; + init.flags = flags | CLK_IS_BASIC | CLK_IS_BASIC_MUX; init.parent_names = parent_names; init.num_parents = num_parents; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 02e75d4e0a77..91894db43c50 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1567,6 +1567,7 @@ void __clk_reparent(struct clk *clk, struct clk *new_parent) */ int clk_set_parent(struct clk *clk, struct clk *parent) { + struct clk *child; int ret = 0; u8 p_index = 0; unsigned long p_rate = 0; @@ -1593,6 +1594,18 @@ int clk_set_parent(struct clk *clk, struct clk *parent) goto out; } + /* check two consecutive basic mux clocks */ + if (clk->flags & CLK_IS_BASIC_MUX) { + hlist_for_each_entry(child, &clk->children, child_node) { + if (child->flags & CLK_IS_BASIC_MUX) { + pr_err("%s: failed to switch parent of %s due to child mux %s\n", + __func__, clk->name, child->name); + ret = -EBUSY; + goto out; + } + } + } + /* try finding the new parent index */ if (parent) { p_index = clk_fetch_parent_index(clk, parent); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 4e9f36a15033..0c71babde4a7 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -28,6 +28,12 @@ #define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ #define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ +/* + * Basic mux clk, can't switch parent while there is another basic mux clk + * being its child. Otherwise, a glitch might be propagated to downstream + * clocks through this child mux. + */ +#define CLK_IS_BASIC_MUX BIT(8) struct clk_hw; |