提交 7316e106 编写于 作者: E Eric Anholt 提交者: Zheng Zengkai

clk: bcm2835: Allow reparenting leaf clocks while they're running.

raspberrypi inclusion
category: feature
bugzilla: 50432

--------------------------------

This falls under the same "we can reprogram glitch-free as long as we
pause generation" rule as updating the div/frac fields.  This can be
used for runtime reclocking of V3D to manage power leakage.
Signed-off-by: NEric Anholt <eric@anholt.net>
Signed-off-by: NFang Yafen <yafen@iscas.ac.cn>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 30042312
...@@ -1104,8 +1104,10 @@ static int bcm2835_clock_on(struct clk_hw *hw) ...@@ -1104,8 +1104,10 @@ static int bcm2835_clock_on(struct clk_hw *hw)
return 0; return 0;
} }
static int bcm2835_clock_set_rate(struct clk_hw *hw, static int bcm2835_clock_set_rate_and_parent(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate) unsigned long rate,
unsigned long parent_rate,
u8 parent)
{ {
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
struct bcm2835_cprman *cprman = clock->cprman; struct bcm2835_cprman *cprman = clock->cprman;
...@@ -1127,6 +1129,11 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, ...@@ -1127,6 +1129,11 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
bcm2835_clock_wait_busy(clock); bcm2835_clock_wait_busy(clock);
} }
if (parent != 0xff) {
ctl &= ~(CM_SRC_MASK << CM_SRC_SHIFT);
ctl |= parent << CM_SRC_SHIFT;
}
ctl &= ~CM_FRAC; ctl &= ~CM_FRAC;
ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0; ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
cprman_write(cprman, data->ctl_reg, ctl); cprman_write(cprman, data->ctl_reg, ctl);
...@@ -1138,6 +1145,12 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, ...@@ -1138,6 +1145,12 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
return 0; return 0;
} }
static int bcm2835_clock_set_rate(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate)
{
return bcm2835_clock_set_rate_and_parent(hw, rate, parent_rate, 0xff);
}
static bool static bool
bcm2835_clk_is_pllc(struct clk_hw *hw) bcm2835_clk_is_pllc(struct clk_hw *hw)
{ {
...@@ -1321,6 +1334,7 @@ static const struct clk_ops bcm2835_clock_clk_ops = { ...@@ -1321,6 +1334,7 @@ static const struct clk_ops bcm2835_clock_clk_ops = {
.unprepare = bcm2835_clock_off, .unprepare = bcm2835_clock_off,
.recalc_rate = bcm2835_clock_get_rate, .recalc_rate = bcm2835_clock_get_rate,
.set_rate = bcm2835_clock_set_rate, .set_rate = bcm2835_clock_set_rate,
.set_rate_and_parent = bcm2835_clock_set_rate_and_parent,
.determine_rate = bcm2835_clock_determine_rate, .determine_rate = bcm2835_clock_determine_rate,
.set_parent = bcm2835_clock_set_parent, .set_parent = bcm2835_clock_set_parent,
.get_parent = bcm2835_clock_get_parent, .get_parent = bcm2835_clock_get_parent,
...@@ -1503,7 +1517,6 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, ...@@ -1503,7 +1517,6 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
init.ops = &bcm2835_vpu_clock_clk_ops; init.ops = &bcm2835_vpu_clock_clk_ops;
} else { } else {
init.ops = &bcm2835_clock_clk_ops; init.ops = &bcm2835_clock_clk_ops;
init.flags |= CLK_SET_PARENT_GATE;
/* If the clock wasn't actually enabled at boot, it's not /* If the clock wasn't actually enabled at boot, it's not
* critical. * critical.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册