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 <finley.xiao@rock-chips.com>
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
This commit is contained in:
Finley Xiao
2019-09-24 14:49:52 +08:00
committed by Tao Huang
parent 124c0977a0
commit c1a61a70dc
2 changed files with 29 additions and 0 deletions

View File

@@ -3,6 +3,7 @@
* Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/slab.h>
@@ -149,8 +150,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);

View File

@@ -1035,6 +1035,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
@@ -1046,6 +1049,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;