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>
This commit is contained in:
Elaine Zhang 2021-03-15 16:56:07 +08:00 committed by Heiko Stuebner
parent 0cd74eec54
commit a3561e77cf
13 changed files with 98 additions and 77 deletions

View File

@ -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);

View File

@ -124,9 +124,10 @@ static struct rockchip_cpuclk_rate_table px30_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data px30_cpuclk_data = {
.core_reg = PX30_CLKSEL_CON(0),
.div_core_shift = 0,
.div_core_mask = 0xf,
.core_reg[0] = PX30_CLKSEL_CON(0),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0xf,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 0,
.mux_core_shift = 7,

View File

@ -102,9 +102,10 @@ static struct rockchip_cpuclk_rate_table rk3036_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = {
.core_reg = RK2928_CLKSEL_CON(0),
.div_core_shift = 0,
.div_core_mask = 0x1f,
.core_reg[0] = RK2928_CLKSEL_CON(0),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 0,
.mux_core_shift = 7,

View File

@ -117,9 +117,10 @@ static struct rockchip_cpuclk_rate_table rk3128_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3128_cpuclk_data = {
.core_reg = RK2928_CLKSEL_CON(0),
.div_core_shift = 0,
.div_core_mask = 0x1f,
.core_reg[0] = RK2928_CLKSEL_CON(0),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 0,
.mux_core_shift = 7,

View File

@ -145,9 +145,10 @@ static struct rockchip_cpuclk_rate_table rk3066_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3066_cpuclk_data = {
.core_reg = RK2928_CLKSEL_CON(0),
.div_core_shift = 0,
.div_core_mask = 0x1f,
.core_reg[0] = RK2928_CLKSEL_CON(0),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 0,
.mux_core_shift = 8,
@ -184,9 +185,10 @@ static struct rockchip_cpuclk_rate_table rk3188_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3188_cpuclk_data = {
.core_reg = RK2928_CLKSEL_CON(0),
.div_core_shift = 9,
.div_core_mask = 0x1f,
.core_reg[0] = RK2928_CLKSEL_CON(0),
.div_core_shift[0] = 9,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 0,
.mux_core_shift = 8,

View File

@ -119,9 +119,10 @@ static struct rockchip_cpuclk_rate_table rk3228_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = {
.core_reg = RK2928_CLKSEL_CON(0),
.div_core_shift = 0,
.div_core_mask = 0x1f,
.core_reg[0] = RK2928_CLKSEL_CON(0),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 0,
.mux_core_shift = 6,

View File

@ -179,9 +179,10 @@ static struct rockchip_cpuclk_rate_table rk3288_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3288_cpuclk_data = {
.core_reg = RK3288_CLKSEL_CON(0),
.div_core_shift = 8,
.div_core_mask = 0x1f,
.core_reg[0] = RK3288_CLKSEL_CON(0),
.div_core_shift[0] = 8,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 0,
.mux_core_shift = 15,

View File

@ -109,9 +109,10 @@ static struct rockchip_cpuclk_rate_table rk3308_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3308_cpuclk_data = {
.core_reg = RK3308_CLKSEL_CON(0),
.div_core_shift = 0,
.div_core_mask = 0xf,
.core_reg[0] = RK3308_CLKSEL_CON(0),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0xf,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 0,
.mux_core_shift = 6,

View File

@ -130,9 +130,10 @@ static struct rockchip_cpuclk_rate_table rk3328_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3328_cpuclk_data = {
.core_reg = RK3328_CLKSEL_CON(0),
.div_core_shift = 0,
.div_core_mask = 0x1f,
.core_reg[0] = RK3328_CLKSEL_CON(0),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 3,
.mux_core_shift = 6,

View File

@ -154,9 +154,10 @@ static struct clk_div_table div_ddrphy_t[] = {
#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = {
.core_reg = RK3368_CLKSEL_CON(0),
.div_core_shift = 0,
.div_core_mask = 0x1f,
.core_reg[0] = RK3368_CLKSEL_CON(0),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 0,
.mux_core_shift = 7,
@ -164,11 +165,12 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = {
};
static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
.core_reg = RK3368_CLKSEL_CON(2),
.div_core_shift = 0,
.core_reg[0] = RK3368_CLKSEL_CON(2),
.div_core_shift[0] = 0,
.mux_core_alt = 1,
.num_cores = 1,
.mux_core_main = 0,
.div_core_mask = 0x1f,
.div_core_mask[0] = 0x1f,
.mux_core_shift = 7,
.mux_core_mask = 0x1,
};

View File

@ -291,9 +291,10 @@ static struct rockchip_clk_branch rk3399_pmuclk_wifi_fracmux __initdata =
RK3399_PMU_CLKSEL_CON(1), 14, 1, MFLAGS);
static const struct rockchip_cpuclk_reg_data rk3399_cpuclkl_data = {
.core_reg = RK3399_CLKSEL_CON(0),
.div_core_shift = 0,
.div_core_mask = 0x1f,
.core_reg[0] = RK3399_CLKSEL_CON(0),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 3,
.mux_core_main = 0,
.mux_core_shift = 6,
@ -301,9 +302,10 @@ static const struct rockchip_cpuclk_reg_data rk3399_cpuclkl_data = {
};
static const struct rockchip_cpuclk_reg_data rk3399_cpuclkb_data = {
.core_reg = RK3399_CLKSEL_CON(2),
.div_core_shift = 0,
.div_core_mask = 0x1f,
.core_reg[0] = RK3399_CLKSEL_CON(2),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 3,
.mux_core_main = 1,
.mux_core_shift = 6,

View File

@ -106,9 +106,10 @@ static struct rockchip_cpuclk_rate_table rv1108_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = {
.core_reg = RV1108_CLKSEL_CON(0),
.div_core_shift = 0,
.div_core_mask = 0x1f,
.core_reg[0] = RV1108_CLKSEL_CON(0),
.div_core_shift[0] = 0,
.div_core_mask[0] = 0x1f,
.num_cores = 1,
.mux_core_alt = 1,
.mux_core_main = 0,
.mux_core_shift = 8,

View File

@ -323,6 +323,7 @@ struct rockchip_cpuclk_clksel {
};
#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2
#define ROCKCHIP_CPUCLK_MAX_CORES 4
struct rockchip_cpuclk_rate_table {
unsigned long prate;
struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
@ -330,22 +331,23 @@ struct rockchip_cpuclk_rate_table {
/**
* struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock
* @core_reg: register offset of the core settings register
* @div_core_shift: core divider offset used to divide the pll value
* @div_core_mask: core divider mask
* @mux_core_alt: mux value to select alternate parent
* @core_reg[]: register offset of the cores setting register
* @div_core_shift[]: cores divider offset used to divide the pll value
* @div_core_mask[]: cores divider mask
* @num_cores: number of cpu cores
* @mux_core_main: mux value to select main parent of core
* @mux_core_shift: offset of the core multiplexer
* @mux_core_mask: core multiplexer mask
*/
struct rockchip_cpuclk_reg_data {
int core_reg;
u8 div_core_shift;
u32 div_core_mask;
u8 mux_core_alt;
u8 mux_core_main;
u8 mux_core_shift;
u32 mux_core_mask;
int core_reg[ROCKCHIP_CPUCLK_MAX_CORES];
u8 div_core_shift[ROCKCHIP_CPUCLK_MAX_CORES];
u32 div_core_mask[ROCKCHIP_CPUCLK_MAX_CORES];
int num_cores;
u8 mux_core_alt;
u8 mux_core_main;
u8 mux_core_shift;
u32 mux_core_mask;
};
struct clk *rockchip_clk_register_cpuclk(const char *name,