summaryrefslogtreecommitdiffstats
path: root/drivers/clk/rockchip/clk-cpu.c
diff options
context:
space:
mode:
authorElaine Zhang <zhangqing@rock-chips.com>2021-03-15 16:56:07 +0800
committerHeiko Stuebner <heiko@sntech.de>2021-03-21 11:10:58 +0100
commita3561e77cf3ca0937227ba13744d84fc46e5eb4b (patch)
tree14bb72f7a1a97dcf5fc532dff1d4beec99bb9bbb /drivers/clk/rockchip/clk-cpu.c
parent0cd74eec54a3ec34416bab6cc640a88230472078 (diff)
downloadlinux-a3561e77cf3ca0937227ba13744d84fc46e5eb4b.tar.bz2
clk: rockchip: support more core div setting
Use arrays to support more core independent div settings. A55 supports each core to work at different frequencies, and each core has an independent divider control. Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com> Reviewed-by: Kever Yang <kever.yang@rock-chips.com> Acked-by: Stephen Boyd <sboyd@kernel.org> Link: https://lore.kernel.org/r/20210315085608.16010-4-zhangqing@rock-chips.com Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Diffstat (limited to 'drivers/clk/rockchip/clk-cpu.c')
-rw-r--r--drivers/clk/rockchip/clk-cpu.c53
1 files changed, 29 insertions, 24 deletions
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
index fa9027fb1920..47288197c9d7 100644
--- a/drivers/clk/rockchip/clk-cpu.c
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -84,10 +84,10 @@ static unsigned long rockchip_cpuclk_recalc_rate(struct clk_hw *hw,
{
struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_hw(hw);
const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
- u32 clksel0 = readl_relaxed(cpuclk->reg_base + reg_data->core_reg);
+ u32 clksel0 = readl_relaxed(cpuclk->reg_base + reg_data->core_reg[0]);
- clksel0 >>= reg_data->div_core_shift;
- clksel0 &= reg_data->div_core_mask;
+ clksel0 >>= reg_data->div_core_shift[0];
+ clksel0 &= reg_data->div_core_mask[0];
return parent_rate / (clksel0 + 1);
}
@@ -120,6 +120,7 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
const struct rockchip_cpuclk_rate_table *rate;
unsigned long alt_prate, alt_div;
unsigned long flags;
+ int i = 0;
/* check validity of the new rate */
rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate);
@@ -142,10 +143,10 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
if (alt_prate > ndata->old_rate) {
/* calculate dividers */
alt_div = DIV_ROUND_UP(alt_prate, ndata->old_rate) - 1;
- if (alt_div > reg_data->div_core_mask) {
+ if (alt_div > reg_data->div_core_mask[0]) {
pr_warn("%s: limiting alt-divider %lu to %d\n",
- __func__, alt_div, reg_data->div_core_mask);
- alt_div = reg_data->div_core_mask;
+ __func__, alt_div, reg_data->div_core_mask[0]);
+ alt_div = reg_data->div_core_mask[0];
}
/*
@@ -158,19 +159,17 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
pr_debug("%s: setting div %lu as alt-rate %lu > old-rate %lu\n",
__func__, alt_div, alt_prate, ndata->old_rate);
- writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask,
- reg_data->div_core_shift) |
- HIWORD_UPDATE(reg_data->mux_core_alt,
- reg_data->mux_core_mask,
- reg_data->mux_core_shift),
- cpuclk->reg_base + reg_data->core_reg);
- } else {
- /* select alternate parent */
- writel(HIWORD_UPDATE(reg_data->mux_core_alt,
- reg_data->mux_core_mask,
- reg_data->mux_core_shift),
- cpuclk->reg_base + reg_data->core_reg);
+ for (i = 0; i < reg_data->num_cores; i++) {
+ writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask[i],
+ reg_data->div_core_shift[i]),
+ cpuclk->reg_base + reg_data->core_reg[i]);
+ }
}
+ /* select alternate parent */
+ writel(HIWORD_UPDATE(reg_data->mux_core_alt,
+ reg_data->mux_core_mask,
+ reg_data->mux_core_shift),
+ cpuclk->reg_base + reg_data->core_reg[0]);
spin_unlock_irqrestore(cpuclk->lock, flags);
return 0;
@@ -182,6 +181,7 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,
const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
const struct rockchip_cpuclk_rate_table *rate;
unsigned long flags;
+ int i = 0;
rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate);
if (!rate) {
@@ -202,12 +202,17 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,
* primary parent by the extra dividers that were needed for the alt.
*/
- writel(HIWORD_UPDATE(0, reg_data->div_core_mask,
- reg_data->div_core_shift) |
- HIWORD_UPDATE(reg_data->mux_core_main,
- reg_data->mux_core_mask,
- reg_data->mux_core_shift),
- cpuclk->reg_base + reg_data->core_reg);
+ writel(HIWORD_UPDATE(reg_data->mux_core_main,
+ reg_data->mux_core_mask,
+ reg_data->mux_core_shift),
+ cpuclk->reg_base + reg_data->core_reg[0]);
+
+ /* remove dividers */
+ for (i = 0; i < reg_data->num_cores; i++) {
+ writel(HIWORD_UPDATE(0, reg_data->div_core_mask[i],
+ reg_data->div_core_shift[i]),
+ cpuclk->reg_base + reg_data->core_reg[i]);
+ }
if (ndata->old_rate > ndata->new_rate)
rockchip_cpuclk_set_dividers(cpuclk, rate);