clk: rockchip: support more core div setting
authorElaine Zhang <zhangqing@rock-chips.com>
Mon, 15 Mar 2021 08:56:07 +0000 (16:56 +0800)
committerHeiko Stuebner <heiko@sntech.de>
Sun, 21 Mar 2021 10:10:58 +0000 (11:10 +0100)
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>
13 files changed:
drivers/clk/rockchip/clk-cpu.c
drivers/clk/rockchip/clk-px30.c
drivers/clk/rockchip/clk-rk3036.c
drivers/clk/rockchip/clk-rk3128.c
drivers/clk/rockchip/clk-rk3188.c
drivers/clk/rockchip/clk-rk3228.c
drivers/clk/rockchip/clk-rk3288.c
drivers/clk/rockchip/clk-rk3308.c
drivers/clk/rockchip/clk-rk3328.c
drivers/clk/rockchip/clk-rk3368.c
drivers/clk/rockchip/clk-rk3399.c
drivers/clk/rockchip/clk-rv1108.c
drivers/clk/rockchip/clk.h

index fa9027fb1920ac260f7bcf6d14c75584daca50b8..47288197c9d7ef21b83300e0ea451681b9450bd5 100644 (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);
index 6fb9c98b7d2430607c8689969754f7fa0371deb8..b58619eb412bbc98da86f1a30cfdea11134dd8f1 100644 (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,
index 6a46f85ad8372e51584ad94f7c9f697a5c643849..91d56ad458172247c59566bdc825cf4169337349 100644 (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,
index 4b1122e98e167b0e45423a17e4b11f0de606be4e..aa53797dbfc145b2e921e9d2007e129485df7b29 100644 (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,
index 0b76ad34de00082a0a280b9d7e6ef51132aa29cb..9c8af4d1dae04fd6986e9384da3ab2d0b6a5f740 100644 (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,
index 47d6482dda9dfd8a84db7029dc9b329e436afad6..a24a35553e13499f3b4b0d98cd2968c0080a49cc 100644 (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,
index 93c794695c469bd1d6282aedc2365fcfdc3d9d2f..baa5aebd32771af9ec0cd4238c05c6501740538f 100644 (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,
index 5bf15f2a44b702f2ae3adae4d52e14fccd6d9cac..2c3bd0c749f266edb26c9dad2a9372943f4af53a 100644 (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,
index 2429b7c2a8b31f359a570fa57dd0bca25778bf5f..267ab54937d3dfda57afd5a6a98961155bf96654 100644 (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,
index 9a0dab9448db37d3d40d1b286a17cd20f9c5396b..2c50cc2cc6dbb5efd38c7fde17730334522383be 100644 (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,
 };
index 7df2f1e00347ef34261bcd833036991ba7408cb5..311ffb3308a89aa2990ae43b12e5b40c4763e6c3 100644 (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,
index 5947d319286682b6777318433e1f365bdbaa838b..5f49af3c970a0ef6f601ecc331c095926f4ee205 100644 (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,
index 2271a84124b07fab1d9602853f383341360f2413..7e60ac810101fe852556f18b98c8518f44a7d388 100644 (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,