clk: renesas: Update R-Car Gen3 driver Gen4 support

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>
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
index d58e897..b51837a 100644
--- a/drivers/clk/renesas/Kconfig
+++ b/drivers/clk/renesas/Kconfig
@@ -45,13 +45,13 @@
 	  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"
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index 1697867..c8a5512 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -35,10 +35,16 @@
 #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 @@
 	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 @@
 
 	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 @@
 
 	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 @@
 
 	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 @@
 
 	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, 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, pll_config->pll1_mult,
-						pll_config->pll1_div,
-						"V3U_PLL1");
+						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 @@
 		      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 @@
 						     gen3_clk_get_rate64(&parent),
 						     priv->base + CPG_RPCCKCR,
 						     CPG_RPCCKCR_DIV_POST_MASK,
+						     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,
-						     cpg_rpcsrc_div_table, "RPCSRC");
+						     gen4_cpg_rpcsrc_div_table,
+						     "RPCSRC");
 
 	case CLK_TYPE_GEN3_D3_RPCSRC:
 	case CLK_TYPE_GEN3_E3_RPCSRC:
@@ -409,6 +458,7 @@
 	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 @@
 
 	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;
 	}
diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
index a9c941b..6b7ec36 100644
--- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
@@ -232,11 +232,10 @@
 /*
  * 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 @@
  */
 #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 @@
 	.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[] = {
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h
index 894e376..06318c8 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.h
+++ b/drivers/clk/renesas/rcar-gen3-cpg.h
@@ -34,8 +34,13 @@
 
 	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 @@
 	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 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);
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index e0895d2..10bd54d 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -128,7 +128,7 @@
 				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),
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h
index 519f885..71e409f 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.h
+++ b/drivers/clk/renesas/renesas-cpg-mssr.h
@@ -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 @@
  * 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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__ */