]> Git Repo - linux.git/commitdiff
clk: Support bypassing dividers
authorPaul Cercueil <[email protected]>
Sun, 30 May 2021 16:49:19 +0000 (17:49 +0100)
committerStephen Boyd <[email protected]>
Mon, 28 Jun 2021 02:49:17 +0000 (19:49 -0700)
When a clock is declared as both CGU_CLK_DIV and CGU_CLK_MUX, the CGU
code expects the mux to be applied first, the divider second.

On the JZ4760, and maybe on some other SoCs, some clocks also have a mux
setting and a divider, but the divider is not applied to all parents
selectable from the mux.

This could be solved by creating two clocks, one with CGU_CLK_DIV and
one with CGU_CLK_MUX, but that would increase the number of clocks.

Instead, add a 8-bit mask to CGU_CLK_DIV clocks. If the bit
corresponding to the parent clock's index is set, the divider is
bypassed.

Signed-off-by: Paul Cercueil <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Stephen Boyd <[email protected]>
drivers/clk/ingenic/cgu.c
drivers/clk/ingenic/cgu.h
drivers/clk/ingenic/jz4725b-cgu.c
drivers/clk/ingenic/jz4740-cgu.c
drivers/clk/ingenic/jz4770-cgu.c

index c8e9cb6c8e39cc8f27f99990e8053f764d07869e..0619d45a950c0f2d3899696e4e9e74b56f0349a6 100644 (file)
@@ -369,18 +369,23 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        struct ingenic_cgu *cgu = ingenic_clk->cgu;
        unsigned long rate = parent_rate;
        u32 div_reg, div;
+       u8 parent;
 
        if (clk_info->type & CGU_CLK_DIV) {
-               div_reg = readl(cgu->base + clk_info->div.reg);
-               div = (div_reg >> clk_info->div.shift) &
-                     GENMASK(clk_info->div.bits - 1, 0);
+               parent = ingenic_clk_get_parent(hw);
 
-               if (clk_info->div.div_table)
-                       div = clk_info->div.div_table[div];
-               else
-                       div = (div + 1) * clk_info->div.div;
+               if (!(clk_info->div.bypass_mask & BIT(parent))) {
+                       div_reg = readl(cgu->base + clk_info->div.reg);
+                       div = (div_reg >> clk_info->div.shift) &
+                             GENMASK(clk_info->div.bits - 1, 0);
+
+                       if (clk_info->div.div_table)
+                               div = clk_info->div.div_table[div];
+                       else
+                               div = (div + 1) * clk_info->div.div;
 
-               rate /= div;
+                       rate /= div;
+               }
        } else if (clk_info->type & CGU_CLK_FIXDIV) {
                rate /= clk_info->fixdiv.div;
        }
@@ -410,10 +415,16 @@ ingenic_clk_calc_hw_div(const struct ingenic_cgu_clk_info *clk_info,
 }
 
 static unsigned
-ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info,
+ingenic_clk_calc_div(struct clk_hw *hw,
+                    const struct ingenic_cgu_clk_info *clk_info,
                     unsigned long parent_rate, unsigned long req_rate)
 {
        unsigned int div, hw_div;
+       u8 parent;
+
+       parent = ingenic_clk_get_parent(hw);
+       if (clk_info->div.bypass_mask & BIT(parent))
+               return 1;
 
        /* calculate the divide */
        div = DIV_ROUND_UP(parent_rate, req_rate);
@@ -448,7 +459,7 @@ ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate,
        unsigned int div = 1;
 
        if (clk_info->type & CGU_CLK_DIV)
-               div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate);
+               div = ingenic_clk_calc_div(hw, clk_info, *parent_rate, req_rate);
        else if (clk_info->type & CGU_CLK_FIXDIV)
                div = clk_info->fixdiv.div;
        else if (clk_hw_can_set_rate_parent(hw))
@@ -480,7 +491,7 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
        int ret = 0;
 
        if (clk_info->type & CGU_CLK_DIV) {
-               div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate);
+               div = ingenic_clk_calc_div(hw, clk_info, parent_rate, req_rate);
                rate = DIV_ROUND_UP(parent_rate, div);
 
                if (rate != req_rate)
index 2c75ef4a36f5c9c68a46c04d0b265dd5e7c4dd25..44d97a259692bdd65360b865d8ad5798f63ac707 100644 (file)
@@ -84,6 +84,7 @@ struct ingenic_cgu_mux_info {
  *          isn't one
  * @busy_bit: the index of the busy bit within reg, or -1 if there isn't one
  * @stop_bit: the index of the stop bit within reg, or -1 if there isn't one
+ * @bypass_mask: mask of parent clocks for which the divider does not apply
  * @div_table: optional table to map the value read from the register to the
  *             actual divider value
  */
@@ -95,6 +96,7 @@ struct ingenic_cgu_div_info {
        s8 ce_bit;
        s8 busy_bit;
        s8 stop_bit;
+       u8 bypass_mask;
        const u8 *div_table;
 };
 
index 8c38e72d14a79919f51569ee226f4b94558f6722..5154b0cf8ad6cdad5b157544cedca052cd56e833 100644 (file)
@@ -80,7 +80,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
                "pll half", CGU_CLK_DIV,
                .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1,
+                       CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,
                        jz4725b_cgu_pll_half_div_table,
                },
        },
@@ -89,7 +89,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
                "cclk", CGU_CLK_DIV,
                .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
                        jz4725b_cgu_cpccr_div_table,
                },
        },
@@ -98,7 +98,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
                "hclk", CGU_CLK_DIV,
                .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
                        jz4725b_cgu_cpccr_div_table,
                },
        },
@@ -107,7 +107,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
                "pclk", CGU_CLK_DIV,
                .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
                        jz4725b_cgu_cpccr_div_table,
                },
        },
@@ -116,7 +116,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
                "mclk", CGU_CLK_DIV,
                .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
                        jz4725b_cgu_cpccr_div_table,
                },
        },
@@ -125,7 +125,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
                "ipu", CGU_CLK_DIV | CGU_CLK_GATE,
                .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
                        jz4725b_cgu_cpccr_div_table,
                },
                .gate = { CGU_REG_CLKGR, 13 },
index c0ac9196a5819b94ff2b1b97b18bcaf893114334..cd878f08aca3ed845dbf5d2a963cf16d3968e193 100644 (file)
@@ -95,7 +95,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
                "pll half", CGU_CLK_DIV,
                .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1,
+                       CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,
                        jz4740_cgu_pll_half_div_table,
                },
        },
@@ -104,7 +104,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
                "cclk", CGU_CLK_DIV,
                .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
                        jz4740_cgu_cpccr_div_table,
                },
        },
@@ -113,7 +113,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
                "hclk", CGU_CLK_DIV,
                .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
                        jz4740_cgu_cpccr_div_table,
                },
        },
@@ -122,7 +122,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
                "pclk", CGU_CLK_DIV,
                .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
                        jz4740_cgu_cpccr_div_table,
                },
        },
@@ -131,7 +131,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
                "mclk", CGU_CLK_DIV,
                .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
                        jz4740_cgu_cpccr_div_table,
                },
        },
@@ -140,7 +140,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
                "lcd", CGU_CLK_DIV | CGU_CLK_GATE,
                .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
                .div = {
-                       CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1,
+                       CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1, 0,
                        jz4740_cgu_cpccr_div_table,
                },
                .gate = { CGU_REG_CLKGR, 10 },
index 9ea4490ecb7f181e23e6f02976fd3eff16d1177e..381a27f20b516f47f6b35c58cb64b2560d25f7f3 100644 (file)
@@ -152,7 +152,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
                "cclk", CGU_CLK_DIV,
                .parents = { JZ4770_CLK_PLL0, },
                .div = {
-                       CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
                        jz4770_cgu_cpccr_div_table,
                },
        },
@@ -160,7 +160,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
                "h0clk", CGU_CLK_DIV,
                .parents = { JZ4770_CLK_PLL0, },
                .div = {
-                       CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
                        jz4770_cgu_cpccr_div_table,
                },
        },
@@ -168,7 +168,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
                "h1clk", CGU_CLK_DIV | CGU_CLK_GATE,
                .parents = { JZ4770_CLK_PLL0, },
                .div = {
-                       CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0,
                        jz4770_cgu_cpccr_div_table,
                },
                .gate = { CGU_REG_CLKGR1, 7 },
@@ -177,7 +177,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
                "h2clk", CGU_CLK_DIV,
                .parents = { JZ4770_CLK_PLL0, },
                .div = {
-                       CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
                        jz4770_cgu_cpccr_div_table,
                },
        },
@@ -185,7 +185,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
                "c1clk", CGU_CLK_DIV | CGU_CLK_GATE,
                .parents = { JZ4770_CLK_PLL0, },
                .div = {
-                       CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
                        jz4770_cgu_cpccr_div_table,
                },
                .gate = { CGU_REG_OPCR, 31, true }, // disable CCLK stop on idle
@@ -194,7 +194,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
                "pclk", CGU_CLK_DIV,
                .parents = { JZ4770_CLK_PLL0, },
                .div = {
-                       CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1,
+                       CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
                        jz4770_cgu_cpccr_div_table,
                },
        },
This page took 0.071081 seconds and 4 git commands to generate.