clk: renesas: Update R-Car Gen3 driver Gen4 support
authorMarek Vasut <marek.vasut+renesas@mailbox.org>
Tue, 28 Feb 2023 21:34:38 +0000 (22:34 +0100)
committerMarek Vasut <marek.vasut+renesas@mailbox.org>
Fri, 7 Apr 2023 15:13:28 +0000 (17:13 +0200)
Update R-Car Gen4 support in Gen3 clock driver. This patch renames the
V3U clock parts to Gen4 and extends them by new PLL2, PLL3, PLL4, PLL6
as well as SDSRC clock which use undocumented bits so far, and RPCSRC
clock which uses its own more capable divider table. The Gen4 module
standby and reset tables are also updated.

This patch makes use of union to alias Gen3 and more extensive Gen4
PLL tables, as the driver cannot ever be instantiated on hardware
that would identify itself as both Gen3 and Gen4.

The V3U clock driver is updated to match Gen4 clock driver behavior,
it is augmented with a more extensive PLL table and a valid MODEMR
register offset.

This supersedes "clk: renesas: Introduce R-Car Gen4 CPG driver"
from Hai Pham as the R-Car Gen3 and Gen4 clock core drivers are
extremely similar. That implementation was in turn based on Linux
commit 470e3f0d0b15 ("clk: renesas: rcar-gen4: Introduce R-Car Gen4 CPG driver")
by Yoshihiro Shimoda .

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
drivers/clk/renesas/Kconfig
drivers/clk/renesas/clk-rcar-gen3.c
drivers/clk/renesas/r8a779a0-cpg-mssr.c
drivers/clk/renesas/rcar-gen3-cpg.h
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/renesas/renesas-cpg-mssr.h

index d58e897..b51837a 100644 (file)
@@ -45,13 +45,13 @@ config CLK_R8A7794
          Enable this to support the clocks on Renesas R8A7794 SoC.
 
 config CLK_RCAR_GEN3
-       bool "Renesas RCar Gen3 clock driver"
-       def_bool y if RCAR_GEN3
+       bool "Renesas RCar Gen3 and Gen4 clock driver"
+       def_bool y if RCAR_64
        depends on CLK_RENESAS
        select CLK_RCAR_CPG_LIB
        select DM_RESET
        help
-         Enable this to support the clocks on Renesas RCar Gen3 SoC.
+         Enable this to support the clocks on Renesas RCar Gen3 and Gen4 SoCs.
 
 config CLK_R8A774A1
         bool "Renesas R8A774A1 clock driver"
index 1697867..c8a5512 100644 (file)
 #define CPG_PLL2CR             0x002c
 #define CPG_PLL4CR             0x01f4
 
-static const struct clk_div_table cpg_rpcsrc_div_table[] = {
+#define SD0CKCR1               0x08a4
+
+static const struct clk_div_table gen3_cpg_rpcsrc_div_table[] = {
        { 2, 5 }, { 3, 6 }, { 0, 0 },
 };
 
+static const struct clk_div_table gen4_cpg_rpcsrc_div_table[] = {
+       { 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 },
+};
+
 static const struct clk_div_table r8a77970_cpg_sd0h_div_table[] = {
        {  0,  2 }, {  1,  3 }, {  2,  4 }, {  3,  6 },
        {  4,  8 }, {  5, 12 }, {  6, 16 }, {  7, 18 },
@@ -181,8 +187,10 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
        struct cpg_mssr_info *info = priv->info;
        struct clk parent;
        const struct cpg_core_clk *core;
-       const struct rcar_gen3_cpg_pll_config *pll_config =
-                                       priv->cpg_pll_config;
+       const struct rcar_gen3_cpg_pll_config *gen3_pll_config =
+                                       priv->gen3_cpg_pll_config;
+       const struct rcar_gen4_cpg_pll_config *gen4_pll_config =
+                                       priv->gen4_cpg_pll_config;
        u32 value, div;
        u64 rate = 0;
        u8 shift;
@@ -227,7 +235,7 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
 
        case CLK_TYPE_GEN3_MAIN:
                return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
-                                               0, 1, pll_config->extal_div,
+                                               0, 1, gen3_pll_config->extal_div,
                                                "MAIN");
 
        case CLK_TYPE_GEN3_PLL0:
@@ -236,8 +244,9 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
 
        case CLK_TYPE_GEN3_PLL1:
                return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
-                                               0, pll_config->pll1_mult,
-                                               pll_config->pll1_div, "PLL1");
+                                               0, gen3_pll_config->pll1_mult,
+                                               gen3_pll_config->pll1_div,
+                                               "PLL1");
 
        case CLK_TYPE_GEN3_PLL2:
                return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
@@ -245,8 +254,9 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
 
        case CLK_TYPE_GEN3_PLL3:
                return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
-                                               0, pll_config->pll3_mult,
-                                               pll_config->pll3_div, "PLL3");
+                                               0, gen3_pll_config->pll3_mult,
+                                               gen3_pll_config->pll3_div,
+                                               "PLL3");
 
        case CLK_TYPE_GEN3_PLL4:
                return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
@@ -254,25 +264,48 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
 
        case CLK_TYPE_GEN4_MAIN:
                return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
-                                               0, 1, pll_config->extal_div,
-                                               "V3U_MAIN");
+                                               0, 1, gen4_pll_config->extal_div,
+                                               "MAIN");
 
        case CLK_TYPE_GEN4_PLL1:
                return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
-                                               0, pll_config->pll1_mult,
-                                               pll_config->pll1_div,
-                                               "V3U_PLL1");
+                                               0, gen4_pll_config->pll1_mult,
+                                               gen4_pll_config->pll1_div,
+                                               "PLL1");
+
+       case CLK_TYPE_GEN4_PLL2:
+               return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
+                                               0, gen4_pll_config->pll2_mult,
+                                               gen4_pll_config->pll2_div,
+                                               "PLL2");
 
        case CLK_TYPE_GEN4_PLL2X_3X:
                return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
-                                               core->offset, 0, 0,
-                                               "V3U_PLL2X_3X");
+                                               core->offset, 0, 0, "PLL2X_3X");
+
+       case CLK_TYPE_GEN4_PLL3:
+               return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
+                                               0, gen4_pll_config->pll3_mult,
+                                               gen4_pll_config->pll3_div,
+                                               "PLL3");
+
+       case CLK_TYPE_GEN4_PLL4:
+               return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
+                                               0, gen4_pll_config->pll4_mult,
+                                               gen4_pll_config->pll4_div,
+                                               "PLL4");
 
        case CLK_TYPE_GEN4_PLL5:
                return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
-                                               0, pll_config->pll5_mult,
-                                               pll_config->pll5_div,
-                                               "V3U_PLL5");
+                                               0, gen4_pll_config->pll5_mult,
+                                               gen4_pll_config->pll5_div,
+                                               "PLL5");
+
+       case CLK_TYPE_GEN4_PLL6:
+               return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
+                                               0, gen4_pll_config->pll6_mult,
+                                               gen4_pll_config->pll6_div,
+                                               "PLL6");
 
        case CLK_TYPE_FF:
                return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
@@ -288,6 +321,13 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
                      div, rate);
                return rate;
 
+       case CLK_TYPE_GEN4_SDSRC:
+               div = ((readl(priv->base + SD0CKCR1) >> 29) & 0x03) + 4;
+               rate = gen3_clk_get_rate64(&parent) / div;
+               debug("%s[%i] SDSRC clk: parent=%i div=%u => rate=%llu\n",
+                     __func__, __LINE__, core->parent, div, rate);
+               return rate;
+
        case CLK_TYPE_GEN3_SDH: /* Fixed factor 1:1 */
                fallthrough;
        case CLK_TYPE_GEN4_SDH: /* Fixed factor 1:1 */
@@ -321,7 +361,16 @@ static u64 gen3_clk_get_rate64(struct clk *clk)
                                                     gen3_clk_get_rate64(&parent),
                                                     priv->base + CPG_RPCCKCR,
                                                     CPG_RPCCKCR_DIV_POST_MASK,
-                                                    cpg_rpcsrc_div_table, "RPCSRC");
+                                                    gen3_cpg_rpcsrc_div_table,
+                                                    "RPCSRC");
+
+       case CLK_TYPE_GEN4_RPCSRC:
+               return rcar_clk_get_rate64_div_table(core->parent,
+                                                    gen3_clk_get_rate64(&parent),
+                                                    priv->base + CPG_RPCCKCR,
+                                                    CPG_RPCCKCR_DIV_POST_MASK,
+                                                    gen4_cpg_rpcsrc_div_table,
+                                                    "RPCSRC");
 
        case CLK_TYPE_GEN3_D3_RPCSRC:
        case CLK_TYPE_GEN3_E3_RPCSRC:
@@ -409,6 +458,7 @@ static int gen3_clk_probe(struct udevice *dev)
        struct gen3_clk_priv *priv = dev_get_priv(dev);
        struct cpg_mssr_info *info =
                (struct cpg_mssr_info *)dev_get_driver_data(dev);
+       const void *pll_config;
        fdt_addr_t rst_base;
        int ret;
 
@@ -427,21 +477,24 @@ static int gen3_clk_probe(struct udevice *dev)
 
        priv->cpg_mode = readl(rst_base + info->reset_modemr_offset);
 
-       priv->cpg_pll_config =
-               (struct rcar_gen3_cpg_pll_config *)info->get_pll_config(priv->cpg_mode);
-       if (!priv->cpg_pll_config->extal_div)
-               return -EINVAL;
+       pll_config = info->get_pll_config(priv->cpg_mode);
 
        if (info->reg_layout == CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3) {
                priv->info->status_regs = mstpsr;
                priv->info->control_regs = smstpcr;
                priv->info->reset_regs = srcr;
                priv->info->reset_clear_regs = srstclr;
-       } else if (info->reg_layout == CLK_REG_LAYOUT_RCAR_V3U) {
-               priv->info->status_regs = mstpsr_for_v3u;
-               priv->info->control_regs = mstpcr_for_v3u;
-               priv->info->reset_regs = srcr_for_v3u;
-               priv->info->reset_clear_regs = srstclr_for_v3u;
+               priv->gen3_cpg_pll_config = pll_config;
+               if (!priv->gen3_cpg_pll_config->extal_div)
+                       return -EINVAL;
+       } else if (info->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4) {
+               priv->info->status_regs = mstpsr_for_gen4;
+               priv->info->control_regs = mstpcr_for_gen4;
+               priv->info->reset_regs = srcr_for_gen4;
+               priv->info->reset_clear_regs = srstclr_for_gen4;
+               priv->gen4_cpg_pll_config = pll_config;
+               if (!priv->gen4_cpg_pll_config->extal_div)
+                       return -EINVAL;
        } else {
                return -EINVAL;
        }
index a9c941b..6b7ec36 100644 (file)
@@ -232,11 +232,10 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] = {
 /*
  * CPG Clock Data
  */
-
 /*
  *   MD         EXTAL          PLL1    PLL20   PLL30   PLL4    PLL5    OSC
  * 14 13 (MHz)                    21      31
- * --------------------------------------------------------
+ * ----------------------------------------------------------------
  * 0  0         16.66 x 1      x128    x216    x128    x144    x192    /16
  * 0  1         20    x 1      x106    x180    x106    x120    x160    /19
  * 1  0         Prohibited setting
@@ -244,13 +243,12 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] = {
  */
 #define CPG_PLL_CONFIG_INDEX(md)       ((((md) & BIT(14)) >> 13) | \
                                         (((md) & BIT(13)) >> 13))
-
-static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[4] = {
-       /* EXTAL div    PLL1 mult/div   Not used     OSC prediv PLL5 mult/div */
-       { 1,            128,    1,      128,    1,      16,     192,    1, },
-       { 1,            106,    1,      106,    1,      19,     160,    1, },
-       { 0,            0,      0,      0,      0,      0,      0,      0, },
-       { 2,            128,    1,      128,    1,      32,     192,    1, },
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = {
+       /* EXTAL div    PLL1 mult/div   PLL2 mult/div   PLL3 mult/div   PLL4 mult/div   PLL5 mult/div   PLL6 mult/div   OSC prediv */
+       { 1,            128,    1,      0,      0,      0,      0,      144,    1,      192,    1,      0,      0,      16,     },
+       { 1,            106,    1,      0,      0,      0,      0,      120,    1,      160,    1,      0,      0,      19,     },
+       { 0,            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      },
+       { 2,            128,    1,      0,      0,      0,      0,      144,    1,      192,    1,      0,      0,      32,     },
 };
 
 /*
@@ -292,13 +290,13 @@ static const struct cpg_mssr_info r8a779a0_cpg_mssr_info = {
        .mstp_table             = r8a779a0_mstp_table,
        .mstp_table_size        = ARRAY_SIZE(r8a779a0_mstp_table),
        .reset_node             = "renesas,r8a779a0-rst",
-       .reset_modemr_offset    = 0x00,
+       .reset_modemr_offset    = CPG_RST_MODEMR0,
        .extalr_node            = "extalr",
        .mod_clk_base           = MOD_CLK_BASE,
        .clk_extal_id           = CLK_EXTAL,
        .clk_extalr_id          = CLK_EXTALR,
        .get_pll_config         = r8a779a0_get_pll_config,
-       .reg_layout             = CLK_REG_LAYOUT_RCAR_V3U,
+       .reg_layout             = CLK_REG_LAYOUT_RCAR_GEN4,
 };
 
 static const struct udevice_id r8a779a0_cpg_ids[] = {
index 894e376..06318c8 100644 (file)
@@ -34,8 +34,13 @@ enum rcar_gen3_clk_types {
 
        CLK_TYPE_GEN4_MAIN,
        CLK_TYPE_GEN4_PLL1,
-       CLK_TYPE_GEN4_PLL2X_3X, /* PLL[23][01] */
+       CLK_TYPE_GEN4_PLL2,
+       CLK_TYPE_GEN4_PLL2X_3X, /* R8A779A0 only */
+       CLK_TYPE_GEN4_PLL3,
        CLK_TYPE_GEN4_PLL5,
+       CLK_TYPE_GEN4_PLL4,
+       CLK_TYPE_GEN4_PLL6,
+       CLK_TYPE_GEN4_SDSRC,
        CLK_TYPE_GEN4_SDH,
        CLK_TYPE_GEN4_SD,
        CLK_TYPE_GEN4_MDSEL,    /* Select parent/divider using mode pin */
@@ -107,11 +112,27 @@ struct rcar_gen3_cpg_pll_config {
        u8 pll3_mult;
        u8 pll3_div;
        u8 osc_prediv;
+};
+
+struct rcar_gen4_cpg_pll_config {
+       u8 extal_div;
+       u8 pll1_mult;
+       u8 pll1_div;
+       u8 pll2_mult;
+       u8 pll2_div;
+       u8 pll3_mult;
+       u8 pll3_div;
+       u8 pll4_mult;
+       u8 pll4_div;
        u8 pll5_mult;
        u8 pll5_div;
+       u8 pll6_mult;
+       u8 pll6_div;
+       u8 osc_prediv;
 };
 
 #define CPG_RST_MODEMR 0x060
+#define CPG_RST_MODEMR0        0x000
 
 #define CPG_SDCKCR_STPnHCK             BIT(9)
 #define CPG_SDCKCR_STPnCK              BIT(8)
@@ -133,7 +154,10 @@ struct gen3_clk_priv {
        struct clk              clk_extal;
        struct clk              clk_extalr;
        u32                     cpg_mode;
-       const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+       union {
+               const struct rcar_gen3_cpg_pll_config *gen3_cpg_pll_config;
+               const struct rcar_gen4_cpg_pll_config *gen4_cpg_pll_config;
+       };
 };
 
 int gen3_cpg_bind(struct udevice *parent);
index e0895d2..10bd54d 100644 (file)
@@ -128,7 +128,7 @@ int renesas_clk_remove(void __iomem *base, struct cpg_mssr_info *info)
                                info->mstp_table[i].sdis,
                                info->mstp_table[i].sen);
 
-               if (info->reg_layout == CLK_REG_LAYOUT_RCAR_V3U)
+               if (info->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4)
                        continue;
 
                clrsetbits_le32(base + RMSTPCR(i),
index 519f885..71e409f 100644 (file)
@@ -17,7 +17,7 @@
 
 enum clk_reg_layout {
        CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3 = 0,
-       CLK_REG_LAYOUT_RCAR_V3U,
+       CLK_REG_LAYOUT_RCAR_GEN4,
 };
 
 struct cpg_mssr_info {
@@ -134,7 +134,7 @@ int renesas_clk_remove(void __iomem *base, struct cpg_mssr_info *info);
  * Module Standby and Software Reset register offets.
  *
  * If the registers exist, these are valid for SH-Mobile, R-Mobile,
- * R-Car Gen2, R-Car Gen3, and RZ/G1.
+ * R-Car Gen2, R-Car Gen3, R-Car Gen4 and RZ/G1.
  * These are NOT valid for R-Car Gen1 and RZ/A1!
  */
 
@@ -147,9 +147,11 @@ static const u16 mstpsr[] = {
        0x9A0, 0x9A4, 0x9A8, 0x9AC,
 };
 
-static const u16 mstpsr_for_v3u[] = {
+static const u16 mstpsr_for_gen4[] = {
        0x2E00, 0x2E04, 0x2E08, 0x2E0C, 0x2E10, 0x2E14, 0x2E18, 0x2E1C,
-       0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38,
+       0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38, 0x2E3C,
+       0x2E40, 0x2E44, 0x2E48, 0x2E4C, 0x2E50, 0x2E54, 0x2E58, 0x2E5C,
+       0x2E60, 0x2E64, 0x2E68, 0x2E6C,
 };
 
 /*
@@ -161,9 +163,11 @@ static const u16 smstpcr[] = {
        0x990, 0x994, 0x998, 0x99C,
 };
 
-static const u16 mstpcr_for_v3u[] = {
+static const u16 mstpcr_for_gen4[] = {
        0x2D00, 0x2D04, 0x2D08, 0x2D0C, 0x2D10, 0x2D14, 0x2D18, 0x2D1C,
-       0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38,
+       0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38, 0x2D3C,
+       0x2D40, 0x2D44, 0x2D48, 0x2D4C, 0x2D50, 0x2D54, 0x2D58, 0x2D5C,
+       0x2D60, 0x2D64, 0x2D68, 0x2D6C,
 };
 
 /*
@@ -175,9 +179,11 @@ static const u16 srcr[] = {
        0x920, 0x924, 0x928, 0x92C,
 };
 
-static const u16 srcr_for_v3u[] = {
+static const u16 srcr_for_gen4[] = {
        0x2C00, 0x2C04, 0x2C08, 0x2C0C, 0x2C10, 0x2C14, 0x2C18, 0x2C1C,
-       0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38,
+       0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38, 0x2C3C,
+       0x2C40, 0x2C44, 0x2C48, 0x2C4C, 0x2C50, 0x2C54, 0x2C58, 0x2C5C,
+       0x2C60, 0x2C64, 0x2C68, 0x2C6C,
 };
 
 /* Realtime Module Stop Control Register offsets */
@@ -193,9 +199,11 @@ static const u16 srstclr[] = {
        0x960, 0x964, 0x968, 0x96C,
 };
 
-static const u16 srstclr_for_v3u[] = {
+static const u16 srstclr_for_gen4[] = {
        0x2C80, 0x2C84, 0x2C88, 0x2C8C, 0x2C90, 0x2C94, 0x2C98, 0x2C9C,
-       0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8,
+       0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8, 0x2CBC,
+       0x2CC0, 0x2CC4, 0x2CC8, 0x2CCC, 0x2CD0, 0x2CD4, 0x2CD8, 0x2CDC,
+       0x2CE0, 0x2CE4, 0x2CE8, 0x2CEC,
 };
 
 #endif /* __DRIVERS_CLK_RENESAS_CPG_MSSR__ */