From 8001749f9c1f59d30932eadaefa0dcb3ef24050e Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 24 Sep 2019 14:49:52 +0800 Subject: [PATCH] clk: composite: Add support to change brother clock rate Some composite clocks may have the same parent clock, if one clock change the parent clock rate, the other clock rate may too large, so add a brother clock in composite that the other clock also can be changed when parent rate is changed. Change-Id: I2c6749e578b76d6780cecdcd9ff1b5fd4f25a0ba Signed-off-by: Finley Xiao --- drivers/clk/clk-composite.c | 24 ++++++++++++++++++++++++ include/linux/clk-provider.h | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 00269de2f390..4ccee4f823f5 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -161,8 +161,32 @@ static int clk_composite_set_rate_and_parent(struct clk_hw *hw, 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_hw *brother_hw = composite->brother_hw; unsigned long temp_rate; + if (brother_hw) { + struct clk_composite *bcomposite = to_clk_composite(brother_hw); + const struct clk_ops *brate_ops = bcomposite->rate_ops; + struct clk_hw *brate_hw = bcomposite->rate_hw; + struct clk_hw *parent_hw = clk_hw_get_parent(brother_hw); + struct clk_hw *new_parent_hw = clk_hw_get_parent(hw); + + __clk_hw_set_clk(brate_hw, brother_hw); + + temp_rate = brate_ops->recalc_rate(brate_hw, parent_rate); + if (temp_rate > rate) + brate_ops->set_rate(brate_hw, rate, parent_rate); + if (clk_hw_is_prepared(brother_hw)) { + clk_prepare_enable(new_parent_hw->clk); + clk_enable(brother_hw->clk); + } + clk_hw_reparent(brother_hw, new_parent_hw); + if (clk_hw_is_prepared(brother_hw)) { + clk_disable(brother_hw->clk); + clk_disable_unprepare(parent_hw->clk); + } + } + __clk_hw_set_clk(rate_hw, hw); __clk_hw_set_clk(mux_hw, hw); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index b4dd6ea524d6..d1d87824e3c8 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -674,6 +674,9 @@ extern const struct clk_ops clk_multiplier_ops; * @mux_hw: handle between composite and hardware-specific mux clock * @rate_hw: handle between composite and hardware-specific rate clock * @gate_hw: handle between composite and hardware-specific gate clock + * @brother_hw: a member of clk_composite who has the common parent clocks + * with another clk_composite, and it's also a handle between + * common and hardware-specific interfaces * @mux_ops: clock ops for mux * @rate_ops: clock ops for rate * @gate_ops: clock ops for gate @@ -685,6 +688,7 @@ struct clk_composite { struct clk_hw *mux_hw; struct clk_hw *rate_hw; struct clk_hw *gate_hw; + struct clk_hw *brother_hw; const struct clk_ops *mux_ops; const struct clk_ops *rate_ops;