summaryrefslogtreecommitdiffstats
path: root/drivers/clk/renesas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/renesas')
-rw-r--r--drivers/clk/renesas/Kconfig281
-rw-r--r--drivers/clk/renesas/Makefile61
-rw-r--r--drivers/clk/renesas/clk-div6.c370
-rw-r--r--drivers/clk/renesas/clk-div6.h9
-rw-r--r--drivers/clk/renesas/clk-emev2.c95
-rw-r--r--drivers/clk/renesas/clk-mstp.c346
-rw-r--r--drivers/clk/renesas/clk-r8a73a4.c237
-rw-r--r--drivers/clk/renesas/clk-r8a7740.c196
-rw-r--r--drivers/clk/renesas/clk-r8a7778.c128
-rw-r--r--drivers/clk/renesas/clk-r8a7779.c166
-rw-r--r--drivers/clk/renesas/clk-rz.c121
-rw-r--r--drivers/clk/renesas/clk-sh73a0.c214
-rw-r--r--drivers/clk/renesas/clk-vbattb.c204
-rw-r--r--drivers/clk/renesas/r7s9210-cpg-mssr.c225
-rw-r--r--drivers/clk/renesas/r8a7742-cpg-mssr.c276
-rw-r--r--drivers/clk/renesas/r8a7743-cpg-mssr.c280
-rw-r--r--drivers/clk/renesas/r8a7745-cpg-mssr.c246
-rw-r--r--drivers/clk/renesas/r8a77470-cpg-mssr.c229
-rw-r--r--drivers/clk/renesas/r8a774a1-cpg-mssr.c346
-rw-r--r--drivers/clk/renesas/r8a774b1-cpg-mssr.c342
-rw-r--r--drivers/clk/renesas/r8a774c0-cpg-mssr.c308
-rw-r--r--drivers/clk/renesas/r8a774e1-cpg-mssr.c354
-rw-r--r--drivers/clk/renesas/r8a7790-cpg-mssr.c277
-rw-r--r--drivers/clk/renesas/r8a7791-cpg-mssr.c285
-rw-r--r--drivers/clk/renesas/r8a7792-cpg-mssr.c227
-rw-r--r--drivers/clk/renesas/r8a7794-cpg-mssr.c254
-rw-r--r--drivers/clk/renesas/r8a7795-cpg-mssr.c398
-rw-r--r--drivers/clk/renesas/r8a7796-cpg-mssr.c383
-rw-r--r--drivers/clk/renesas/r8a77965-cpg-mssr.c371
-rw-r--r--drivers/clk/renesas/r8a77970-cpg-mssr.c272
-rw-r--r--drivers/clk/renesas/r8a77980-cpg-mssr.c264
-rw-r--r--drivers/clk/renesas/r8a77990-cpg-mssr.c322
-rw-r--r--drivers/clk/renesas/r8a77995-cpg-mssr.c258
-rw-r--r--drivers/clk/renesas/r8a779a0-cpg-mssr.c318
-rw-r--r--drivers/clk/renesas/r8a779f0-cpg-mssr.c238
-rw-r--r--drivers/clk/renesas/r8a779g0-cpg-mssr.c312
-rw-r--r--drivers/clk/renesas/r8a779h0-cpg-mssr.c307
-rw-r--r--drivers/clk/renesas/r9a06g032-clocks.c1428
-rw-r--r--drivers/clk/renesas/r9a07g043-cpg.c433
-rw-r--r--drivers/clk/renesas/r9a07g044-cpg.c566
-rw-r--r--drivers/clk/renesas/r9a08g045-cpg.c391
-rw-r--r--drivers/clk/renesas/r9a08g046-cpg.c508
-rw-r--r--drivers/clk/renesas/r9a09g011-cpg.c263
-rw-r--r--drivers/clk/renesas/r9a09g047-cpg.c645
-rw-r--r--drivers/clk/renesas/r9a09g056-cpg.c658
-rw-r--r--drivers/clk/renesas/r9a09g057-cpg.c693
-rw-r--r--drivers/clk/renesas/r9a09g077-cpg.c519
-rw-r--r--drivers/clk/renesas/rcar-cpg-lib.c208
-rw-r--r--drivers/clk/renesas/rcar-cpg-lib.h43
-rw-r--r--drivers/clk/renesas/rcar-gen2-cpg.c392
-rw-r--r--drivers/clk/renesas/rcar-gen2-cpg.h39
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.c551
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.h88
-rw-r--r--drivers/clk/renesas/rcar-gen4-cpg.c546
-rw-r--r--drivers/clk/renesas/rcar-gen4-cpg.h85
-rw-r--r--drivers/clk/renesas/rcar-usb2-clock-sel.c220
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.c1435
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.h222
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.c2246
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.h329
-rw-r--r--drivers/clk/renesas/rzv2h-cpg.c1874
-rw-r--r--drivers/clk/renesas/rzv2h-cpg.h380
62 files changed, 24282 insertions, 0 deletions
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
new file mode 100644
index 000000000..0203ecbb3
--- /dev/null
+++ b/drivers/clk/renesas/Kconfig
@@ -0,0 +1,281 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config CLK_RENESAS
+ bool "Renesas SoC clock support" if COMPILE_TEST && !ARCH_RENESAS
+ default y if ARCH_RENESAS
+ select CLK_EMEV2 if ARCH_EMEV2
+ select CLK_RZA1 if ARCH_R7S72100
+ select CLK_R7S9210 if ARCH_R7S9210
+ select CLK_R8A73A4 if ARCH_R8A73A4
+ select CLK_R8A7740 if ARCH_R8A7740
+ select CLK_R8A7742 if ARCH_R8A7742
+ select CLK_R8A7743 if ARCH_R8A7743 || ARCH_R8A7744
+ select CLK_R8A7745 if ARCH_R8A7745
+ select CLK_R8A77470 if ARCH_R8A77470
+ select CLK_R8A774A1 if ARCH_R8A774A1
+ select CLK_R8A774B1 if ARCH_R8A774B1
+ select CLK_R8A774C0 if ARCH_R8A774C0
+ select CLK_R8A774E1 if ARCH_R8A774E1
+ select CLK_R8A7778 if ARCH_R8A7778
+ select CLK_R8A7779 if ARCH_R8A7779
+ select CLK_R8A7790 if ARCH_R8A7790
+ select CLK_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793
+ select CLK_R8A7792 if ARCH_R8A7792
+ select CLK_R8A7794 if ARCH_R8A7794
+ select CLK_R8A7795 if ARCH_R8A77951
+ select CLK_R8A77960 if ARCH_R8A77960
+ select CLK_R8A77961 if ARCH_R8A77961
+ select CLK_R8A77965 if ARCH_R8A77965
+ select CLK_R8A77970 if ARCH_R8A77970
+ select CLK_R8A77980 if ARCH_R8A77980
+ select CLK_R8A77990 if ARCH_R8A77990
+ select CLK_R8A77995 if ARCH_R8A77995
+ select CLK_R8A779A0 if ARCH_R8A779A0
+ select CLK_R8A779F0 if ARCH_R8A779F0
+ select CLK_R8A779G0 if ARCH_R8A779G0
+ select CLK_R8A779H0 if ARCH_R8A779H0
+ select CLK_R9A06G032 if ARCH_R9A06G032
+ select CLK_R9A07G043 if ARCH_R9A07G043
+ select CLK_R9A07G044 if ARCH_R9A07G044
+ select CLK_R9A07G054 if ARCH_R9A07G054
+ select CLK_R9A08G045 if ARCH_R9A08G045
+ select CLK_R9A08G046 if ARCH_R9A08G046
+ select CLK_R9A09G011 if ARCH_R9A09G011
+ select CLK_R9A09G047 if ARCH_R9A09G047
+ select CLK_R9A09G056 if ARCH_R9A09G056
+ select CLK_R9A09G057 if ARCH_R9A09G057
+ select CLK_R9A09G077 if ARCH_R9A09G077
+ select CLK_R9A09G087 if ARCH_R9A09G087
+ select CLK_SH73A0 if ARCH_SH73A0
+
+if CLK_RENESAS
+
+# SoC
+config CLK_EMEV2
+ bool "Emma Mobile EV2 clock support" if COMPILE_TEST
+
+config CLK_RZA1
+ bool "RZ/A1H clock support" if COMPILE_TEST
+ select CLK_RENESAS_CPG_MSTP
+
+config CLK_R7S9210
+ bool "RZ/A2 clock support" if COMPILE_TEST
+ select CLK_RENESAS_CPG_MSSR
+
+config CLK_R8A73A4
+ bool "R-Mobile APE6 clock support" if COMPILE_TEST
+ select CLK_RENESAS_CPG_MSTP
+ select CLK_RENESAS_DIV6
+
+config CLK_R8A7740
+ bool "R-Mobile A1 clock support" if COMPILE_TEST
+ select CLK_RENESAS_CPG_MSTP
+ select CLK_RENESAS_DIV6
+
+config CLK_R8A7742
+ bool "RZ/G1H clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A7743
+ bool "RZ/G1M clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A7745
+ bool "RZ/G1E clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A77470
+ bool "RZ/G1C clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A774A1
+ bool "RZ/G2M clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A774B1
+ bool "RZ/G2N clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A774C0
+ bool "RZ/G2E clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A774E1
+ bool "RZ/G2H clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A7778
+ bool "R-Car M1A clock support" if COMPILE_TEST
+ select CLK_RENESAS_CPG_MSTP
+
+config CLK_R8A7779
+ bool "R-Car H1 clock support" if COMPILE_TEST
+ select CLK_RENESAS_CPG_MSTP
+
+config CLK_R8A7790
+ bool "R-Car H2 clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A7791
+ bool "R-Car M2-W/N clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A7792
+ bool "R-Car V2H clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A7794
+ bool "R-Car E2 clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A7795
+ bool "R-Car H3 clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A77960
+ bool "R-Car M3-W clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A77961
+ bool "R-Car M3-W+ clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A77965
+ bool "R-Car M3-N clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A77970
+ bool "R-Car V3M clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A77980
+ bool "R-Car V3H clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A77990
+ bool "R-Car E3 clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A77995
+ bool "R-Car D3 clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A779A0
+ bool "R-Car V3U clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN4_CPG
+
+config CLK_R8A779F0
+ bool "R-Car S4-8 clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN4_CPG
+
+config CLK_R8A779G0
+ bool "R-Car V4H clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN4_CPG
+
+config CLK_R8A779H0
+ bool "R-Car V4M clock support" if COMPILE_TEST
+ select CLK_RCAR_GEN4_CPG
+
+config CLK_R9A06G032
+ bool "RZ/N1D clock support" if COMPILE_TEST
+
+config CLK_R9A07G043
+ bool "RZ/G2UL clock support" if COMPILE_TEST
+ select CLK_RZG2L
+
+config CLK_R9A07G044
+ bool "RZ/G2L clock support" if COMPILE_TEST
+ select CLK_RZG2L
+
+config CLK_R9A07G054
+ bool "RZ/V2L clock support" if COMPILE_TEST
+ select CLK_RZG2L
+
+config CLK_R9A08G045
+ bool "RZ/G3S clock support" if COMPILE_TEST
+ select CLK_RZG2L
+
+config CLK_R9A08G046
+ bool "RZ/G3L clock support" if COMPILE_TEST
+ select CLK_RZG2L
+
+config CLK_R9A09G011
+ bool "RZ/V2M clock support" if COMPILE_TEST
+ select CLK_RZG2L
+
+config CLK_R9A09G047
+ bool "RZ/G3E clock support" if COMPILE_TEST
+ select CLK_RZV2H
+
+config CLK_R9A09G056
+ bool "RZ/V2N clock support" if COMPILE_TEST
+ select CLK_RZV2H
+
+config CLK_R9A09G057
+ bool "RZ/V2H(P) clock support" if COMPILE_TEST
+ select CLK_RZV2H
+
+config CLK_R9A09G077
+ bool "RZ/T2H clock support" if COMPILE_TEST
+ select CLK_RENESAS_CPG_MSSR
+
+config CLK_R9A09G087
+ bool "RZ/N2H clock support" if COMPILE_TEST
+ select CLK_RENESAS_CPG_MSSR
+
+config CLK_SH73A0
+ bool "SH-Mobile AG5 clock support" if COMPILE_TEST
+ select CLK_RENESAS_CPG_MSTP
+ select CLK_RENESAS_DIV6
+
+
+# Family
+config CLK_RCAR_CPG_LIB
+ bool "CPG/MSSR library functions" if COMPILE_TEST
+
+config CLK_RCAR_GEN2_CPG
+ bool "R-Car Gen2 CPG clock support" if COMPILE_TEST
+ select CLK_RENESAS_CPG_MSSR
+
+config CLK_RCAR_GEN3_CPG
+ bool "R-Car Gen3 and RZ/G2 CPG clock support" if COMPILE_TEST
+ select CLK_RCAR_CPG_LIB
+ select CLK_RENESAS_CPG_MSSR
+
+config CLK_RCAR_GEN4_CPG
+ bool "R-Car Gen4 clock support" if COMPILE_TEST
+ select CLK_RCAR_CPG_LIB
+ select CLK_RENESAS_CPG_MSSR
+
+config CLK_RCAR_USB2_CLOCK_SEL
+ bool "R-Car USB2 clock selector support"
+ depends on ARCH_RENESAS || COMPILE_TEST
+ select RESET_CONTROLLER
+ help
+ This is a driver for R-Car USB2 clock selector
+
+config CLK_RZG2L
+ bool "RZ/{G2{L,UL},G3{S,L},V2L} family clock support" if COMPILE_TEST
+ select RESET_CONTROLLER
+
+config CLK_RZV2H
+ bool "RZ/{G3E,V2H(P)} family clock support" if COMPILE_TEST
+ select RESET_CONTROLLER
+
+config CLK_RENESAS_VBATTB
+ tristate "Renesas VBATTB clock controller"
+ depends on ARCH_RZG2L || COMPILE_TEST
+ select RESET_CONTROLLER
+
+# Generic
+config CLK_RENESAS_CPG_MSSR
+ bool "CPG/MSSR clock support" if COMPILE_TEST
+ select CLK_RENESAS_DIV6
+
+config CLK_RENESAS_CPG_MSTP
+ bool "MSTP clock support" if COMPILE_TEST
+
+config CLK_RENESAS_DIV6
+ bool "DIV6 clock support" if COMPILE_TEST
+
+endif # CLK_RENESAS
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
new file mode 100644
index 000000000..bd2bed91a
--- /dev/null
+++ b/drivers/clk/renesas/Makefile
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0
+# SoC
+obj-$(CONFIG_CLK_EMEV2) += clk-emev2.o
+obj-$(CONFIG_CLK_RZA1) += clk-rz.o
+obj-$(CONFIG_CLK_R7S9210) += r7s9210-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A73A4) += clk-r8a73a4.o
+obj-$(CONFIG_CLK_R8A7740) += clk-r8a7740.o
+obj-$(CONFIG_CLK_R8A7742) += r8a7742-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7743) += r8a7743-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7745) += r8a7745-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A77470) += r8a77470-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A774A1) += r8a774a1-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A774B1) += r8a774b1-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A774C0) += r8a774c0-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A774E1) += r8a774e1-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7778) += clk-r8a7778.o
+obj-$(CONFIG_CLK_R8A7779) += clk-r8a7779.o
+obj-$(CONFIG_CLK_R8A7790) += r8a7790-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7791) += r8a7791-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7792) += r8a7792-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7794) += r8a7794-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7795) += r8a7795-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A77960) += r8a7796-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A77961) += r8a7796-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A77965) += r8a77965-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A77970) += r8a77970-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A77980) += r8a77980-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A77990) += r8a77990-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A779F0) += r8a779f0-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A779G0) += r8a779g0-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A779H0) += r8a779h0-cpg-mssr.o
+obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o
+obj-$(CONFIG_CLK_R9A07G043) += r9a07g043-cpg.o
+obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o
+obj-$(CONFIG_CLK_R9A07G054) += r9a07g044-cpg.o
+obj-$(CONFIG_CLK_R9A08G045) += r9a08g045-cpg.o
+obj-$(CONFIG_CLK_R9A08G046) += r9a08g046-cpg.o
+obj-$(CONFIG_CLK_R9A09G011) += r9a09g011-cpg.o
+obj-$(CONFIG_CLK_R9A09G047) += r9a09g047-cpg.o
+obj-$(CONFIG_CLK_R9A09G056) += r9a09g056-cpg.o
+obj-$(CONFIG_CLK_R9A09G057) += r9a09g057-cpg.o
+obj-$(CONFIG_CLK_R9A09G077) += r9a09g077-cpg.o
+obj-$(CONFIG_CLK_R9A09G087) += r9a09g077-cpg.o
+obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o
+
+# Family
+obj-$(CONFIG_CLK_RCAR_CPG_LIB) += rcar-cpg-lib.o
+obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o
+obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o
+obj-$(CONFIG_CLK_RCAR_GEN4_CPG) += rcar-gen4-cpg.o
+obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o
+obj-$(CONFIG_CLK_RZG2L) += rzg2l-cpg.o
+obj-$(CONFIG_CLK_RZV2H) += rzv2h-cpg.o
+
+# Generic
+obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o
+obj-$(CONFIG_CLK_RENESAS_CPG_MSTP) += clk-mstp.o
+obj-$(CONFIG_CLK_RENESAS_DIV6) += clk-div6.o
+obj-$(CONFIG_CLK_RENESAS_VBATTB) += clk-vbattb.o
diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c
new file mode 100644
index 000000000..c23489900
--- /dev/null
+++ b/drivers/clk/renesas/clk-div6.c
@@ -0,0 +1,370 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7790 Common Clock Framework support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+
+#include "clk-div6.h"
+
+#define CPG_DIV6_CKSTP BIT(8)
+#define CPG_DIV6_DIV(d) ((d) & 0x3f)
+#define CPG_DIV6_DIV_MASK 0x3f
+
+/**
+ * struct div6_clock - CPG 6 bit divider clock
+ * @hw: handle between common and hardware-specific interfaces
+ * @reg: IO-remapped register
+ * @div: divisor value (1-64)
+ * @src_mask: Bitmask covering the register bits to select the parent clock
+ * @nb: Notifier block to save/restore clock state for system resume
+ * @parents: Array to map from valid parent clocks indices to hardware indices
+ */
+struct div6_clock {
+ struct clk_hw hw;
+ void __iomem *reg;
+ unsigned int div;
+ u32 src_mask;
+ struct notifier_block nb;
+ u8 parents[];
+};
+
+#define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw)
+
+static int cpg_div6_clock_enable(struct clk_hw *hw)
+{
+ struct div6_clock *clock = to_div6_clock(hw);
+ u32 val;
+
+ val = (readl(clock->reg) & ~(CPG_DIV6_DIV_MASK | CPG_DIV6_CKSTP))
+ | CPG_DIV6_DIV(clock->div - 1);
+ writel(val, clock->reg);
+
+ return 0;
+}
+
+static void cpg_div6_clock_disable(struct clk_hw *hw)
+{
+ struct div6_clock *clock = to_div6_clock(hw);
+ u32 val;
+
+ val = readl(clock->reg);
+ val |= CPG_DIV6_CKSTP;
+ /*
+ * DIV6 clocks require the divisor field to be non-zero when stopping
+ * the clock. However, some clocks (e.g. ZB on sh73a0) fail to be
+ * re-enabled later if the divisor field is changed when stopping the
+ * clock
+ */
+ if (!(val & CPG_DIV6_DIV_MASK))
+ val |= CPG_DIV6_DIV_MASK;
+ writel(val, clock->reg);
+}
+
+static int cpg_div6_clock_is_enabled(struct clk_hw *hw)
+{
+ struct div6_clock *clock = to_div6_clock(hw);
+
+ return !(readl(clock->reg) & CPG_DIV6_CKSTP);
+}
+
+static unsigned long cpg_div6_clock_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct div6_clock *clock = to_div6_clock(hw);
+
+ return parent_rate / clock->div;
+}
+
+static unsigned int cpg_div6_clock_calc_div(unsigned long rate,
+ unsigned long parent_rate)
+{
+ unsigned int div;
+
+ if (!rate)
+ rate = 1;
+
+ div = DIV_ROUND_CLOSEST(parent_rate, rate);
+ return clamp(div, 1U, 64U);
+}
+
+static int cpg_div6_clock_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ unsigned long prate, calc_rate, diff, best_rate, best_prate;
+ unsigned int num_parents = clk_hw_get_num_parents(hw);
+ struct clk_hw *parent, *best_parent = NULL;
+ unsigned int i, min_div, max_div, div;
+ unsigned long min_diff = ULONG_MAX;
+
+ for (i = 0; i < num_parents; i++) {
+ parent = clk_hw_get_parent_by_index(hw, i);
+ if (!parent)
+ continue;
+
+ prate = clk_hw_get_rate(parent);
+ if (!prate)
+ continue;
+
+ min_div = max(DIV_ROUND_UP(prate, req->max_rate), 1UL);
+ max_div = req->min_rate ? min(prate / req->min_rate, 64UL) : 64;
+ if (max_div < min_div)
+ continue;
+
+ div = cpg_div6_clock_calc_div(req->rate, prate);
+ div = clamp(div, min_div, max_div);
+ calc_rate = prate / div;
+ diff = calc_rate > req->rate ? calc_rate - req->rate
+ : req->rate - calc_rate;
+ if (diff < min_diff) {
+ best_rate = calc_rate;
+ best_parent = parent;
+ best_prate = prate;
+ min_diff = diff;
+ }
+ }
+
+ if (!best_parent)
+ return -EINVAL;
+
+ req->best_parent_rate = best_prate;
+ req->best_parent_hw = best_parent;
+ req->rate = best_rate;
+ return 0;
+}
+
+static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct div6_clock *clock = to_div6_clock(hw);
+ unsigned int div = cpg_div6_clock_calc_div(rate, parent_rate);
+ u32 val;
+
+ clock->div = div;
+
+ val = readl(clock->reg) & ~CPG_DIV6_DIV_MASK;
+ /* Only program the new divisor if the clock isn't stopped. */
+ if (!(val & CPG_DIV6_CKSTP))
+ writel(val | CPG_DIV6_DIV(clock->div - 1), clock->reg);
+
+ return 0;
+}
+
+static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
+{
+ struct div6_clock *clock = to_div6_clock(hw);
+ unsigned int i;
+ u8 hw_index;
+
+ if (clock->src_mask == 0)
+ return 0;
+
+ hw_index = field_get(clock->src_mask, readl(clock->reg));
+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+ if (clock->parents[i] == hw_index)
+ return i;
+ }
+
+ pr_err("%s: %s DIV6 clock set to invalid parent %u\n",
+ __func__, clk_hw_get_name(hw), hw_index);
+ return 0;
+}
+
+static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct div6_clock *clock = to_div6_clock(hw);
+ u32 src;
+
+ if (index >= clk_hw_get_num_parents(hw))
+ return -EINVAL;
+
+ src = field_prep(clock->src_mask, clock->parents[index]);
+ writel((readl(clock->reg) & ~clock->src_mask) | src, clock->reg);
+ return 0;
+}
+
+static const struct clk_ops cpg_div6_clock_ops = {
+ .enable = cpg_div6_clock_enable,
+ .disable = cpg_div6_clock_disable,
+ .is_enabled = cpg_div6_clock_is_enabled,
+ .get_parent = cpg_div6_clock_get_parent,
+ .set_parent = cpg_div6_clock_set_parent,
+ .recalc_rate = cpg_div6_clock_recalc_rate,
+ .determine_rate = cpg_div6_clock_determine_rate,
+ .set_rate = cpg_div6_clock_set_rate,
+};
+
+static int cpg_div6_clock_notifier_call(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct div6_clock *clock = container_of(nb, struct div6_clock, nb);
+
+ switch (action) {
+ case PM_EVENT_RESUME:
+ /*
+ * TODO: This does not yet support DIV6 clocks with multiple
+ * parents, as the parent selection bits are not restored.
+ * Fortunately so far such DIV6 clocks are found only on
+ * R/SH-Mobile SoCs, while the resume functionality is only
+ * needed on R-Car Gen3.
+ */
+ if (__clk_get_enable_count(clock->hw.clk))
+ cpg_div6_clock_enable(&clock->hw);
+ else
+ cpg_div6_clock_disable(&clock->hw);
+ return NOTIFY_OK;
+ }
+
+ return NOTIFY_DONE;
+}
+
+/**
+ * cpg_div6_register - Register a DIV6 clock
+ * @name: Name of the DIV6 clock
+ * @num_parents: Number of parent clocks of the DIV6 clock (1, 4, or 8)
+ * @parent_names: Array containing the names of the parent clocks
+ * @reg: Mapped register used to control the DIV6 clock
+ * @notifiers: Optional notifier chain to save/restore state for system resume
+ */
+struct clk * __init cpg_div6_register(const char *name,
+ unsigned int num_parents,
+ const char **parent_names,
+ void __iomem *reg,
+ struct raw_notifier_head *notifiers)
+{
+ unsigned int valid_parents;
+ struct clk_init_data init = {};
+ struct div6_clock *clock;
+ struct clk *clk;
+ unsigned int i;
+
+ clock = kzalloc_flex(*clock, parents, num_parents);
+ if (!clock)
+ return ERR_PTR(-ENOMEM);
+
+ clock->reg = reg;
+
+ /*
+ * Read the divisor. Disabling the clock overwrites the divisor, so we
+ * need to cache its value for the enable operation.
+ */
+ clock->div = (readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1;
+
+ switch (num_parents) {
+ case 1:
+ /* fixed parent clock */
+ clock->src_mask = 0;
+ break;
+ case 4:
+ /* clock with EXSRC bits 6-7 */
+ clock->src_mask = GENMASK(7, 6);
+ break;
+ case 8:
+ /* VCLK with EXSRC bits 12-14 */
+ clock->src_mask = GENMASK(14, 12);
+ break;
+ default:
+ pr_err("%s: invalid number of parents for DIV6 clock %s\n",
+ __func__, name);
+ clk = ERR_PTR(-EINVAL);
+ goto free_clock;
+ }
+
+ /* Filter out invalid parents */
+ for (i = 0, valid_parents = 0; i < num_parents; i++) {
+ if (parent_names[i]) {
+ parent_names[valid_parents] = parent_names[i];
+ clock->parents[valid_parents] = i;
+ valid_parents++;
+ }
+ }
+
+ /* Register the clock. */
+ init.name = name;
+ init.ops = &cpg_div6_clock_ops;
+ init.parent_names = parent_names;
+ init.num_parents = valid_parents;
+
+ clock->hw.init = &init;
+
+ clk = clk_register(NULL, &clock->hw);
+ if (IS_ERR(clk))
+ goto free_clock;
+
+ if (notifiers) {
+ clock->nb.notifier_call = cpg_div6_clock_notifier_call;
+ raw_notifier_chain_register(notifiers, &clock->nb);
+ }
+
+ return clk;
+
+free_clock:
+ kfree(clock);
+ return clk;
+}
+
+static void __init cpg_div6_clock_init(struct device_node *np)
+{
+ unsigned int num_parents;
+ const char **parent_names;
+ const char *clk_name = np->name;
+ void __iomem *reg;
+ struct clk *clk;
+ unsigned int i;
+
+ num_parents = of_clk_get_parent_count(np);
+ if (num_parents < 1) {
+ pr_err("%s: no parent found for %pOFn DIV6 clock\n",
+ __func__, np);
+ return;
+ }
+
+ parent_names = kmalloc_array(num_parents, sizeof(*parent_names),
+ GFP_KERNEL);
+ if (!parent_names)
+ return;
+
+ reg = of_iomap(np, 0);
+ if (reg == NULL) {
+ pr_err("%s: failed to map %pOFn DIV6 clock register\n",
+ __func__, np);
+ goto error;
+ }
+
+ /* Parse the DT properties. */
+ of_property_read_string(np, "clock-output-names", &clk_name);
+
+ for (i = 0; i < num_parents; i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+
+ clk = cpg_div6_register(clk_name, num_parents, parent_names, reg, NULL);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register %pOFn DIV6 clock (%ld)\n",
+ __func__, np, PTR_ERR(clk));
+ goto error;
+ }
+
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+ kfree(parent_names);
+ return;
+
+error:
+ if (reg)
+ iounmap(reg);
+ kfree(parent_names);
+}
+CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init);
diff --git a/drivers/clk/renesas/clk-div6.h b/drivers/clk/renesas/clk-div6.h
new file mode 100644
index 000000000..3af640a0b
--- /dev/null
+++ b/drivers/clk/renesas/clk-div6.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __RENESAS_CLK_DIV6_H__
+#define __RENESAS_CLK_DIV6_H__
+
+struct clk *cpg_div6_register(const char *name, unsigned int num_parents,
+ const char **parent_names, void __iomem *reg,
+ struct raw_notifier_head *notifiers);
+
+#endif
diff --git a/drivers/clk/renesas/clk-emev2.c b/drivers/clk/renesas/clk-emev2.c
new file mode 100644
index 000000000..37c6f9be5
--- /dev/null
+++ b/drivers/clk/renesas/clk-emev2.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * EMMA Mobile EV2 common clock framework support
+ *
+ * Copyright (C) 2013 Takashi Yoshii <takashi.yoshii.ze@renesas.com>
+ * Copyright (C) 2012 Magnus Damm
+ */
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+/* EMEV2 SMU registers */
+#define USIAU0_RSTCTRL 0x094
+#define USIBU1_RSTCTRL 0x0ac
+#define USIBU2_RSTCTRL 0x0b0
+#define USIBU3_RSTCTRL 0x0b4
+#define IIC0_RSTCTRL 0x0dc
+#define IIC1_RSTCTRL 0x0e0
+#define STI_RSTCTRL 0x124
+#define STI_CLKSEL 0x688
+
+static DEFINE_SPINLOCK(lock);
+
+/* not pretty, but hey */
+static void __iomem *smu_base;
+
+static void __init emev2_smu_write(unsigned long value, int offs)
+{
+ BUG_ON(!smu_base || (offs >= PAGE_SIZE));
+ writel_relaxed(value, smu_base + offs);
+}
+
+static const struct of_device_id smu_id[] __initconst = {
+ { .compatible = "renesas,emev2-smu", },
+ {},
+};
+
+static void __init emev2_smu_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, smu_id);
+ BUG_ON(!np);
+ smu_base = of_iomap(np, 0);
+ BUG_ON(!smu_base);
+ of_node_put(np);
+
+ /* setup STI timer to run on 32.768 kHz and deassert reset */
+ emev2_smu_write(0, STI_CLKSEL);
+ emev2_smu_write(1, STI_RSTCTRL);
+
+ /* deassert reset for UART0->UART3 */
+ emev2_smu_write(2, USIAU0_RSTCTRL);
+ emev2_smu_write(2, USIBU1_RSTCTRL);
+ emev2_smu_write(2, USIBU2_RSTCTRL);
+ emev2_smu_write(2, USIBU3_RSTCTRL);
+
+ /* deassert reset for IIC0->IIC1 */
+ emev2_smu_write(1, IIC0_RSTCTRL);
+ emev2_smu_write(1, IIC1_RSTCTRL);
+}
+
+static void __init emev2_smu_clkdiv_init(struct device_node *np)
+{
+ u32 reg[2];
+ struct clk *clk;
+ const char *parent_name = of_clk_get_parent_name(np, 0);
+ if (WARN_ON(of_property_read_u32_array(np, "reg", reg, 2)))
+ return;
+ if (!smu_base)
+ emev2_smu_init();
+ clk = clk_register_divider(NULL, np->name, parent_name, 0,
+ smu_base + reg[0], reg[1], 8, 0, &lock);
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ pr_debug("## %s %pOFn %p\n", __func__, np, clk);
+}
+CLK_OF_DECLARE(emev2_smu_clkdiv, "renesas,emev2-smu-clkdiv",
+ emev2_smu_clkdiv_init);
+
+static void __init emev2_smu_gclk_init(struct device_node *np)
+{
+ u32 reg[2];
+ struct clk *clk;
+ const char *parent_name = of_clk_get_parent_name(np, 0);
+ if (WARN_ON(of_property_read_u32_array(np, "reg", reg, 2)))
+ return;
+ if (!smu_base)
+ emev2_smu_init();
+ clk = clk_register_gate(NULL, np->name, parent_name, 0,
+ smu_base + reg[0], reg[1], 0, &lock);
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ pr_debug("## %s %pOFn %p\n", __func__, np, clk);
+}
+CLK_OF_DECLARE(emev2_smu_gclk, "renesas,emev2-smu-gclk", emev2_smu_gclk_init);
diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c
new file mode 100644
index 000000000..f57f23428
--- /dev/null
+++ b/drivers/clk/renesas/clk-mstp.c
@@ -0,0 +1,346 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car MSTP clocks
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ * Copyright (C) 2015 Glider bvba
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+/*
+ * MSTP clocks. We can't use standard gate clocks as we need to poll on the
+ * status register when enabling the clock.
+ */
+
+#define MSTP_MAX_CLOCKS 32
+
+/**
+ * struct mstp_clock_group - MSTP gating clocks group
+ *
+ * @data: clock specifier translation for clocks in this group
+ * @smstpcr: module stop control register
+ * @mstpsr: module stop status register (optional)
+ * @lock: protects writes to SMSTPCR
+ * @width_8bit: registers are 8-bit, not 32-bit
+ * @clks: clocks in this group
+ */
+struct mstp_clock_group {
+ struct clk_onecell_data data;
+ void __iomem *smstpcr;
+ void __iomem *mstpsr;
+ spinlock_t lock;
+ bool width_8bit;
+ struct clk *clks[];
+};
+
+/**
+ * struct mstp_clock - MSTP gating clock
+ * @hw: handle between common and hardware-specific interfaces
+ * @bit_index: control bit index
+ * @group: MSTP clocks group
+ */
+struct mstp_clock {
+ struct clk_hw hw;
+ u32 bit_index;
+ struct mstp_clock_group *group;
+};
+
+#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)
+
+static inline u32 cpg_mstp_read(struct mstp_clock_group *group,
+ u32 __iomem *reg)
+{
+ return group->width_8bit ? readb(reg) : readl(reg);
+}
+
+static inline void cpg_mstp_write(struct mstp_clock_group *group, u32 val,
+ u32 __iomem *reg)
+{
+ group->width_8bit ? writeb(val, reg) : writel(val, reg);
+}
+
+static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
+{
+ struct mstp_clock *clock = to_mstp_clock(hw);
+ struct mstp_clock_group *group = clock->group;
+ u32 bitmask = BIT(clock->bit_index);
+ unsigned long flags;
+ u32 value;
+ int ret;
+
+ spin_lock_irqsave(&group->lock, flags);
+
+ value = cpg_mstp_read(group, group->smstpcr);
+ if (enable)
+ value &= ~bitmask;
+ else
+ value |= bitmask;
+ cpg_mstp_write(group, value, group->smstpcr);
+
+ if (!group->mstpsr) {
+ /* dummy read to ensure write has completed */
+ cpg_mstp_read(group, group->smstpcr);
+ barrier_data(group->smstpcr);
+ }
+
+ spin_unlock_irqrestore(&group->lock, flags);
+
+ if (!enable || !group->mstpsr)
+ return 0;
+
+ /* group->width_8bit is always false if group->mstpsr is present */
+ ret = readl_poll_timeout_atomic(group->mstpsr, value,
+ !(value & bitmask), 0, 10);
+ if (ret)
+ pr_err("%s: failed to enable %p[%d]\n", __func__,
+ group->smstpcr, clock->bit_index);
+
+ return ret;
+}
+
+static int cpg_mstp_clock_enable(struct clk_hw *hw)
+{
+ return cpg_mstp_clock_endisable(hw, true);
+}
+
+static void cpg_mstp_clock_disable(struct clk_hw *hw)
+{
+ cpg_mstp_clock_endisable(hw, false);
+}
+
+static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
+{
+ struct mstp_clock *clock = to_mstp_clock(hw);
+ struct mstp_clock_group *group = clock->group;
+ u32 value;
+
+ if (group->mstpsr)
+ value = cpg_mstp_read(group, group->mstpsr);
+ else
+ value = cpg_mstp_read(group, group->smstpcr);
+
+ return !(value & BIT(clock->bit_index));
+}
+
+static const struct clk_ops cpg_mstp_clock_ops = {
+ .enable = cpg_mstp_clock_enable,
+ .disable = cpg_mstp_clock_disable,
+ .is_enabled = cpg_mstp_clock_is_enabled,
+};
+
+static struct clk * __init cpg_mstp_clock_register(const char *name,
+ const char *parent_name, unsigned int index,
+ struct mstp_clock_group *group)
+{
+ struct clk_init_data init = {};
+ struct mstp_clock *clock;
+ struct clk *clk;
+
+ clock = kzalloc_obj(*clock);
+ if (!clock)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_mstp_clock_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ /* INTC-SYS is the module clock of the GIC, and must not be disabled */
+ if (!strcmp(name, "intc-sys")) {
+ pr_debug("MSTP %s setting CLK_IS_CRITICAL\n", name);
+ init.flags |= CLK_IS_CRITICAL;
+ }
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clock->bit_index = index;
+ clock->group = group;
+ clock->hw.init = &init;
+
+ clk = clk_register(NULL, &clock->hw);
+
+ if (IS_ERR(clk))
+ kfree(clock);
+
+ return clk;
+}
+
+static void __init cpg_mstp_clocks_init(struct device_node *np)
+{
+ struct mstp_clock_group *group;
+ const char *idxname;
+ struct clk **clks;
+ unsigned int i;
+
+ group = kzalloc_flex(*group, clks, MSTP_MAX_CLOCKS);
+ if (!group)
+ return;
+
+ clks = group->clks;
+ spin_lock_init(&group->lock);
+ group->data.clks = clks;
+
+ group->smstpcr = of_iomap(np, 0);
+ group->mstpsr = of_iomap(np, 1);
+
+ if (group->smstpcr == NULL) {
+ pr_err("%s: failed to remap SMSTPCR\n", __func__);
+ kfree(group);
+ return;
+ }
+
+ if (of_device_is_compatible(np, "renesas,r7s72100-mstp-clocks"))
+ group->width_8bit = true;
+
+ for (i = 0; i < MSTP_MAX_CLOCKS; ++i)
+ clks[i] = ERR_PTR(-ENOENT);
+
+ if (of_property_present(np, "clock-indices"))
+ idxname = "clock-indices";
+ else
+ idxname = "renesas,clock-indices";
+
+ for (i = 0; i < MSTP_MAX_CLOCKS; ++i) {
+ const char *parent_name;
+ const char *name;
+ u32 clkidx;
+ int ret;
+
+ /* Skip clocks with no name. */
+ ret = of_property_read_string_index(np, "clock-output-names",
+ i, &name);
+ if (ret < 0 || strlen(name) == 0)
+ continue;
+
+ parent_name = of_clk_get_parent_name(np, i);
+ ret = of_property_read_u32_index(np, idxname, i, &clkidx);
+ if (parent_name == NULL || ret < 0)
+ break;
+
+ if (clkidx >= MSTP_MAX_CLOCKS) {
+ pr_err("%s: invalid clock %pOFn %s index %u\n",
+ __func__, np, name, clkidx);
+ continue;
+ }
+
+ clks[clkidx] = cpg_mstp_clock_register(name, parent_name,
+ clkidx, group);
+ if (!IS_ERR(clks[clkidx]))
+ group->data.clk_num = max(group->data.clk_num,
+ clkidx + 1);
+ else
+ pr_err("%s: failed to register %pOFn %s clock (%ld)\n",
+ __func__, np, name, PTR_ERR(clks[clkidx]));
+ }
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, &group->data);
+}
+CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init);
+
+int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct of_phandle_args clkspec;
+ struct clk *clk;
+ int i = 0;
+ int error;
+
+ while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
+ &clkspec)) {
+ if (of_device_is_compatible(clkspec.np,
+ "renesas,cpg-mstp-clocks"))
+ goto found;
+
+ /* BSC on r8a73a4/sh73a0 uses zb_clk instead of an mstp clock */
+ if (of_node_name_eq(clkspec.np, "zb_clk"))
+ goto found;
+
+ of_node_put(clkspec.np);
+ i++;
+ }
+
+ return 0;
+
+found:
+ clk = of_clk_get_from_provider(&clkspec);
+ of_node_put(clkspec.np);
+
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ error = pm_clk_create(dev);
+ if (error)
+ goto fail_put;
+
+ error = pm_clk_add_clk(dev, clk);
+ if (error)
+ goto fail_destroy;
+
+ return 0;
+
+fail_destroy:
+ pm_clk_destroy(dev);
+fail_put:
+ clk_put(clk);
+ return error;
+}
+
+void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev)
+{
+ if (!pm_clk_no_clocks(dev))
+ pm_clk_destroy(dev);
+}
+
+static struct device_node *cpg_mstp_pd_np __initdata = NULL;
+static struct generic_pm_domain *cpg_mstp_pd_genpd __initdata = NULL;
+
+void __init cpg_mstp_add_clk_domain(struct device_node *np)
+{
+ struct generic_pm_domain *pd;
+ u32 ncells;
+
+ if (of_property_read_u32(np, "#power-domain-cells", &ncells)) {
+ pr_warn("%pOF lacks #power-domain-cells\n", np);
+ return;
+ }
+
+ pd = kzalloc_obj(*pd);
+ if (!pd)
+ return;
+
+ pd->name = np->name;
+ pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON |
+ GENPD_FLAG_ACTIVE_WAKEUP;
+ pd->attach_dev = cpg_mstp_attach_dev;
+ pd->detach_dev = cpg_mstp_detach_dev;
+ pm_genpd_init(pd, &pm_domain_always_on_gov, false);
+
+ cpg_mstp_pd_np = of_node_get(np);
+ cpg_mstp_pd_genpd = pd;
+}
+
+static int __init cpg_mstp_pd_init_provider(void)
+{
+ int error;
+
+ if (!cpg_mstp_pd_np)
+ return -ENODEV;
+
+ error = of_genpd_add_provider_simple(cpg_mstp_pd_np, cpg_mstp_pd_genpd);
+
+ of_node_put(cpg_mstp_pd_np);
+ return error;
+}
+postcore_initcall(cpg_mstp_pd_init_provider);
diff --git a/drivers/clk/renesas/clk-r8a73a4.c b/drivers/clk/renesas/clk-r8a73a4.c
new file mode 100644
index 000000000..1a2bbc5e9
--- /dev/null
+++ b/drivers/clk/renesas/clk-r8a73a4.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a73a4 Core CPG Clocks
+ *
+ * Copyright (C) 2014 Ulrich Hecht
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/spinlock.h>
+
+struct r8a73a4_cpg {
+ struct clk_onecell_data data;
+ spinlock_t lock;
+};
+
+#define CPG_CKSCR 0xc0
+#define CPG_FRQCRA 0x00
+#define CPG_FRQCRB 0x04
+#define CPG_FRQCRC 0xe0
+#define CPG_PLL0CR 0xd8
+#define CPG_PLL1CR 0x28
+#define CPG_PLL2CR 0x2c
+#define CPG_PLL2HCR 0xe4
+#define CPG_PLL2SCR 0xf4
+
+struct div4_clk {
+ const char *name;
+ unsigned int reg;
+ unsigned int shift;
+};
+
+static struct div4_clk div4_clks[] = {
+ { "i", CPG_FRQCRA, 20 },
+ { "m3", CPG_FRQCRA, 12 },
+ { "b", CPG_FRQCRA, 8 },
+ { "m1", CPG_FRQCRA, 4 },
+ { "m2", CPG_FRQCRA, 0 },
+ { "ztr", CPG_FRQCRB, 20 },
+ { "zt", CPG_FRQCRB, 16 },
+ { "zx", CPG_FRQCRB, 12 },
+ { "zs", CPG_FRQCRB, 8 },
+ { "hp", CPG_FRQCRB, 4 },
+ { NULL, 0, 0 },
+};
+
+static const struct clk_div_table div4_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 },
+ { 6, 16 }, { 7, 18 }, { 8, 24 }, { 10, 36 }, { 11, 48 },
+ { 12, 10 }, { 0, 0 }
+};
+
+static struct clk * __init
+r8a73a4_cpg_register_clock(struct device_node *np, struct r8a73a4_cpg *cpg,
+ void __iomem *base, const char *name)
+{
+ const struct clk_div_table *table = NULL;
+ const char *parent_name;
+ unsigned int shift, reg;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+
+ if (!strcmp(name, "main")) {
+ u32 ckscr = readl(base + CPG_CKSCR);
+
+ switch ((ckscr >> 28) & 3) {
+ case 0: /* extal1 */
+ parent_name = of_clk_get_parent_name(np, 0);
+ break;
+ case 1: /* extal1 / 2 */
+ parent_name = of_clk_get_parent_name(np, 0);
+ div = 2;
+ break;
+ case 2: /* extal2 */
+ parent_name = of_clk_get_parent_name(np, 1);
+ break;
+ case 3: /* extal2 / 2 */
+ parent_name = of_clk_get_parent_name(np, 1);
+ div = 2;
+ break;
+ }
+ } else if (!strcmp(name, "pll0")) {
+ /* PLL0/1 are configurable multiplier clocks. Register them as
+ * fixed factor clocks for now as there's no generic multiplier
+ * clock implementation and we currently have no need to change
+ * the multiplier value.
+ */
+ u32 value = readl(base + CPG_PLL0CR);
+
+ parent_name = "main";
+ mult = ((value >> 24) & 0x7f) + 1;
+ if (value & BIT(20))
+ div = 2;
+ } else if (!strcmp(name, "pll1")) {
+ u32 value = readl(base + CPG_PLL1CR);
+
+ parent_name = "main";
+ /* XXX: enable bit? */
+ mult = ((value >> 24) & 0x7f) + 1;
+ if (value & BIT(7))
+ div = 2;
+ } else if (!strncmp(name, "pll2", 4)) {
+ u32 value, cr;
+
+ switch (name[4]) {
+ case 0:
+ cr = CPG_PLL2CR;
+ break;
+ case 's':
+ cr = CPG_PLL2SCR;
+ break;
+ case 'h':
+ cr = CPG_PLL2HCR;
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+ value = readl(base + cr);
+ switch ((value >> 5) & 7) {
+ case 0:
+ parent_name = "main";
+ div = 2;
+ break;
+ case 1:
+ parent_name = "extal2";
+ div = 2;
+ break;
+ case 3:
+ parent_name = "extal2";
+ div = 4;
+ break;
+ case 4:
+ parent_name = "main";
+ break;
+ case 5:
+ parent_name = "extal2";
+ break;
+ default:
+ pr_warn("%s: unexpected parent of %s\n", __func__,
+ name);
+ return ERR_PTR(-EINVAL);
+ }
+ /* XXX: enable bit? */
+ mult = ((value >> 24) & 0x7f) + 1;
+ } else if (!strcmp(name, "z") || !strcmp(name, "z2")) {
+ u32 shift = 8;
+
+ parent_name = "pll0";
+ if (name[1] == '2') {
+ div = 2;
+ shift = 0;
+ }
+ div *= 32;
+ mult = 0x20 - ((readl(base + CPG_FRQCRC) >> shift) & 0x1f);
+ } else {
+ struct div4_clk *c;
+
+ for (c = div4_clks; c->name; c++) {
+ if (!strcmp(name, c->name))
+ break;
+ }
+ if (!c->name)
+ return ERR_PTR(-EINVAL);
+
+ parent_name = "pll1";
+ table = div4_div_table;
+ reg = c->reg;
+ shift = c->shift;
+ }
+
+ if (!table) {
+ return clk_register_fixed_factor(NULL, name, parent_name, 0,
+ mult, div);
+ } else {
+ return clk_register_divider_table(NULL, name, parent_name, 0,
+ base + reg, shift, 4, 0,
+ table, &cpg->lock);
+ }
+}
+
+static void __init r8a73a4_cpg_clocks_init(struct device_node *np)
+{
+ struct r8a73a4_cpg *cpg;
+ void __iomem *base;
+ struct clk **clks;
+ unsigned int i;
+ int num_clks;
+
+ num_clks = of_property_count_strings(np, "clock-output-names");
+ if (num_clks < 0) {
+ pr_err("%s: failed to count clocks\n", __func__);
+ return;
+ }
+
+ cpg = kzalloc_obj(*cpg);
+ clks = kzalloc_objs(*clks, num_clks);
+ if (cpg == NULL || clks == NULL) {
+ /* We're leaking memory on purpose, there's no point in cleaning
+ * up as the system won't boot anyway.
+ */
+ return;
+ }
+
+ spin_lock_init(&cpg->lock);
+
+ cpg->data.clks = clks;
+ cpg->data.clk_num = num_clks;
+
+ base = of_iomap(np, 0);
+ if (WARN_ON(base == NULL))
+ return;
+
+ for (i = 0; i < num_clks; ++i) {
+ const char *name;
+ struct clk *clk;
+
+ of_property_read_string_index(np, "clock-output-names", i,
+ &name);
+
+ clk = r8a73a4_cpg_register_clock(np, cpg, base, name);
+ if (IS_ERR(clk))
+ pr_err("%s: failed to register %pOFn %s clock (%ld)\n",
+ __func__, np, name, PTR_ERR(clk));
+ else
+ cpg->data.clks[i] = clk;
+ }
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
+}
+CLK_OF_DECLARE(r8a73a4_cpg_clks, "renesas,r8a73a4-cpg-clocks",
+ r8a73a4_cpg_clocks_init);
diff --git a/drivers/clk/renesas/clk-r8a7740.c b/drivers/clk/renesas/clk-r8a7740.c
new file mode 100644
index 000000000..31a796745
--- /dev/null
+++ b/drivers/clk/renesas/clk-r8a7740.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7740 Core CPG Clocks
+ *
+ * Copyright (C) 2014 Ulrich Hecht
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/spinlock.h>
+
+struct r8a7740_cpg {
+ struct clk_onecell_data data;
+ spinlock_t lock;
+};
+
+#define CPG_FRQCRA 0x00
+#define CPG_FRQCRB 0x04
+#define CPG_PLLC2CR 0x2c
+#define CPG_USBCKCR 0x8c
+#define CPG_FRQCRC 0xe0
+
+struct div4_clk {
+ const char *name;
+ unsigned int reg;
+ unsigned int shift;
+};
+
+static struct div4_clk div4_clks[] = {
+ { "i", CPG_FRQCRA, 20 },
+ { "zg", CPG_FRQCRA, 16 },
+ { "b", CPG_FRQCRA, 8 },
+ { "m1", CPG_FRQCRA, 4 },
+ { "ztr", CPG_FRQCRB, 20 },
+ { "zt", CPG_FRQCRB, 16 },
+ { "hp", CPG_FRQCRB, 4 },
+ { "hpp", CPG_FRQCRC, 20 },
+ { "usbp", CPG_FRQCRC, 16 },
+ { "s", CPG_FRQCRC, 12 },
+ { "zb", CPG_FRQCRC, 8 },
+ { "m3", CPG_FRQCRC, 4 },
+ { "cp", CPG_FRQCRC, 0 },
+ { NULL, 0, 0 },
+};
+
+static const struct clk_div_table div4_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 },
+ { 6, 16 }, { 7, 18 }, { 8, 24 }, { 9, 32 }, { 10, 36 }, { 11, 48 },
+ { 13, 72 }, { 14, 96 }, { 0, 0 }
+};
+
+static u32 cpg_mode __initdata;
+
+static struct clk * __init
+r8a7740_cpg_register_clock(struct device_node *np, struct r8a7740_cpg *cpg,
+ void __iomem *base, const char *name)
+{
+ const struct clk_div_table *table = NULL;
+ const char *parent_name;
+ unsigned int shift, reg;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+
+ if (!strcmp(name, "r")) {
+ switch (cpg_mode & (BIT(2) | BIT(1))) {
+ case BIT(1) | BIT(2):
+ /* extal1 */
+ parent_name = of_clk_get_parent_name(np, 0);
+ div = 2048;
+ break;
+ case BIT(2):
+ /* extal1 */
+ parent_name = of_clk_get_parent_name(np, 0);
+ div = 1024;
+ break;
+ default:
+ /* extalr */
+ parent_name = of_clk_get_parent_name(np, 2);
+ break;
+ }
+ } else if (!strcmp(name, "system")) {
+ parent_name = of_clk_get_parent_name(np, 0);
+ if (cpg_mode & BIT(1))
+ div = 2;
+ } else if (!strcmp(name, "pllc0")) {
+ /* PLLC0/1 are configurable multiplier clocks. Register them as
+ * fixed factor clocks for now as there's no generic multiplier
+ * clock implementation and we currently have no need to change
+ * the multiplier value.
+ */
+ u32 value = readl(base + CPG_FRQCRC);
+ parent_name = "system";
+ mult = ((value >> 24) & 0x7f) + 1;
+ } else if (!strcmp(name, "pllc1")) {
+ u32 value = readl(base + CPG_FRQCRA);
+ parent_name = "system";
+ mult = ((value >> 24) & 0x7f) + 1;
+ div = 2;
+ } else if (!strcmp(name, "pllc2")) {
+ u32 value = readl(base + CPG_PLLC2CR);
+ parent_name = "system";
+ mult = ((value >> 24) & 0x3f) + 1;
+ } else if (!strcmp(name, "usb24s")) {
+ u32 value = readl(base + CPG_USBCKCR);
+ if (value & BIT(7))
+ /* extal2 */
+ parent_name = of_clk_get_parent_name(np, 1);
+ else
+ parent_name = "system";
+ if (!(value & BIT(6)))
+ div = 2;
+ } else {
+ struct div4_clk *c;
+ for (c = div4_clks; c->name; c++) {
+ if (!strcmp(name, c->name)) {
+ parent_name = "pllc1";
+ table = div4_div_table;
+ reg = c->reg;
+ shift = c->shift;
+ break;
+ }
+ }
+ if (!c->name)
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!table) {
+ return clk_register_fixed_factor(NULL, name, parent_name, 0,
+ mult, div);
+ } else {
+ return clk_register_divider_table(NULL, name, parent_name, 0,
+ base + reg, shift, 4, 0,
+ table, &cpg->lock);
+ }
+}
+
+static void __init r8a7740_cpg_clocks_init(struct device_node *np)
+{
+ struct r8a7740_cpg *cpg;
+ void __iomem *base;
+ struct clk **clks;
+ unsigned int i;
+ int num_clks;
+
+ if (of_property_read_u32(np, "renesas,mode", &cpg_mode))
+ pr_warn("%s: missing renesas,mode property\n", __func__);
+
+ num_clks = of_property_count_strings(np, "clock-output-names");
+ if (num_clks < 0) {
+ pr_err("%s: failed to count clocks\n", __func__);
+ return;
+ }
+
+ cpg = kzalloc_obj(*cpg);
+ clks = kzalloc_objs(*clks, num_clks);
+ if (cpg == NULL || clks == NULL) {
+ /* We're leaking memory on purpose, there's no point in cleaning
+ * up as the system won't boot anyway.
+ */
+ return;
+ }
+
+ spin_lock_init(&cpg->lock);
+
+ cpg->data.clks = clks;
+ cpg->data.clk_num = num_clks;
+
+ base = of_iomap(np, 0);
+ if (WARN_ON(base == NULL))
+ return;
+
+ for (i = 0; i < num_clks; ++i) {
+ const char *name;
+ struct clk *clk;
+
+ of_property_read_string_index(np, "clock-output-names", i,
+ &name);
+
+ clk = r8a7740_cpg_register_clock(np, cpg, base, name);
+ if (IS_ERR(clk))
+ pr_err("%s: failed to register %pOFn %s clock (%ld)\n",
+ __func__, np, name, PTR_ERR(clk));
+ else
+ cpg->data.clks[i] = clk;
+ }
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
+}
+CLK_OF_DECLARE(r8a7740_cpg_clks, "renesas,r8a7740-cpg-clocks",
+ r8a7740_cpg_clocks_init);
diff --git a/drivers/clk/renesas/clk-r8a7778.c b/drivers/clk/renesas/clk-r8a7778.c
new file mode 100644
index 000000000..9120f86fc
--- /dev/null
+++ b/drivers/clk/renesas/clk-r8a7778.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7778 Core CPG Clocks
+ *
+ * Copyright (C) 2014 Ulrich Hecht
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+/* PLL multipliers per bits 11, 12, and 18 of MODEMR */
+static const struct {
+ unsigned long plla_mult;
+ unsigned long pllb_mult;
+} r8a7778_rates[] __initconst = {
+ [0] = { 21, 21 },
+ [1] = { 24, 24 },
+ [2] = { 28, 28 },
+ [3] = { 32, 32 },
+ [5] = { 24, 21 },
+ [6] = { 28, 21 },
+ [7] = { 32, 24 },
+};
+
+/* Clock dividers per bits 1 and 2 of MODEMR */
+static const struct {
+ const char *name;
+ unsigned int div[4];
+} r8a7778_divs[6] __initconst = {
+ { "b", { 12, 12, 16, 18 } },
+ { "out", { 12, 12, 16, 18 } },
+ { "p", { 16, 12, 16, 12 } },
+ { "s", { 4, 3, 4, 3 } },
+ { "s1", { 8, 6, 8, 6 } },
+};
+
+static u32 cpg_mode_rates __initdata;
+static u32 cpg_mode_divs __initdata;
+
+static struct clk * __init
+r8a7778_cpg_register_clock(struct device_node *np, const char *name)
+{
+ if (!strcmp(name, "plla")) {
+ return clk_register_fixed_factor(NULL, "plla",
+ of_clk_get_parent_name(np, 0), 0,
+ r8a7778_rates[cpg_mode_rates].plla_mult, 1);
+ } else if (!strcmp(name, "pllb")) {
+ return clk_register_fixed_factor(NULL, "pllb",
+ of_clk_get_parent_name(np, 0), 0,
+ r8a7778_rates[cpg_mode_rates].pllb_mult, 1);
+ } else {
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(r8a7778_divs); i++) {
+ if (!strcmp(name, r8a7778_divs[i].name)) {
+ return clk_register_fixed_factor(NULL,
+ r8a7778_divs[i].name,
+ "plla", 0, 1,
+ r8a7778_divs[i].div[cpg_mode_divs]);
+ }
+ }
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static void __init r8a7778_cpg_clocks_init(struct device_node *np)
+{
+ struct clk_onecell_data *data;
+ struct clk **clks;
+ unsigned int i;
+ int num_clks;
+ u32 mode;
+
+ if (rcar_rst_read_mode_pins(&mode))
+ return;
+
+ BUG_ON(!(mode & BIT(19)));
+
+ cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
+ (!!(mode & BIT(12)) << 1) |
+ (!!(mode & BIT(11)));
+ cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
+ (!!(mode & BIT(1)));
+
+ num_clks = of_property_count_strings(np, "clock-output-names");
+ if (num_clks < 0) {
+ pr_err("%s: failed to count clocks\n", __func__);
+ return;
+ }
+
+ data = kzalloc_obj(*data);
+ clks = kzalloc_objs(*clks, num_clks);
+ if (data == NULL || clks == NULL) {
+ /* We're leaking memory on purpose, there's no point in cleaning
+ * up as the system won't boot anyway.
+ */
+ return;
+ }
+
+ data->clks = clks;
+ data->clk_num = num_clks;
+
+ for (i = 0; i < num_clks; ++i) {
+ const char *name;
+ struct clk *clk;
+
+ of_property_read_string_index(np, "clock-output-names", i,
+ &name);
+
+ clk = r8a7778_cpg_register_clock(np, name);
+ if (IS_ERR(clk))
+ pr_err("%s: failed to register %pOFn %s clock (%ld)\n",
+ __func__, np, name, PTR_ERR(clk));
+ else
+ data->clks[i] = clk;
+ }
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, data);
+
+ cpg_mstp_add_clk_domain(np);
+}
+
+CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks",
+ r8a7778_cpg_clocks_init);
diff --git a/drivers/clk/renesas/clk-r8a7779.c b/drivers/clk/renesas/clk-r8a7779.c
new file mode 100644
index 000000000..f2d6cbaf6
--- /dev/null
+++ b/drivers/clk/renesas/clk-r8a7779.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7779 Core CPG Clocks
+ *
+ * Copyright (C) 2013, 2014 Horms Solutions Ltd.
+ *
+ * Contact: Simon Horman <horms@verge.net.au>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7779-clock.h>
+
+#define CPG_NUM_CLOCKS (R8A7779_CLK_OUT + 1)
+
+/* -----------------------------------------------------------------------------
+ * CPG Clock Data
+ */
+
+/*
+ * MD1 = 1 MD1 = 0
+ * (PLLA = 1500) (PLLA = 1600)
+ * (MHz) (MHz)
+ *------------------------------------------------+--------------------
+ * clkz 1000 (2/3) 800 (1/2)
+ * clkzs 250 (1/6) 200 (1/8)
+ * clki 750 (1/2) 800 (1/2)
+ * clks 250 (1/6) 200 (1/8)
+ * clks1 125 (1/12) 100 (1/16)
+ * clks3 187.5 (1/8) 200 (1/8)
+ * clks4 93.7 (1/16) 100 (1/16)
+ * clkp 62.5 (1/24) 50 (1/32)
+ * clkg 62.5 (1/24) 66.6 (1/24)
+ * clkb, CLKOUT
+ * (MD2 = 0) 62.5 (1/24) 66.6 (1/24)
+ * (MD2 = 1) 41.6 (1/36) 50 (1/32)
+ */
+
+#define CPG_CLK_CONFIG_INDEX(md) (((md) & (BIT(2)|BIT(1))) >> 1)
+
+struct cpg_clk_config {
+ unsigned int z_mult;
+ unsigned int z_div;
+ unsigned int zs_and_s_div;
+ unsigned int s1_div;
+ unsigned int p_div;
+ unsigned int b_and_out_div;
+};
+
+static const struct cpg_clk_config cpg_clk_configs[4] __initconst = {
+ { 1, 2, 8, 16, 32, 24 },
+ { 2, 3, 6, 12, 24, 24 },
+ { 1, 2, 8, 16, 32, 32 },
+ { 2, 3, 6, 12, 24, 36 },
+};
+
+/*
+ * MD PLLA Ratio
+ * 12 11
+ *------------------------
+ * 0 0 x42
+ * 0 1 x48
+ * 1 0 x56
+ * 1 1 x64
+ */
+
+#define CPG_PLLA_MULT_INDEX(md) (((md) & (BIT(12)|BIT(11))) >> 11)
+
+static const unsigned int cpg_plla_mult[4] __initconst = { 42, 48, 56, 64 };
+
+/* -----------------------------------------------------------------------------
+ * Initialization
+ */
+
+static struct clk * __init
+r8a7779_cpg_register_clock(struct device_node *np,
+ const struct cpg_clk_config *config,
+ unsigned int plla_mult, const char *name)
+{
+ const char *parent_name = "plla";
+ unsigned int mult = 1;
+ unsigned int div = 1;
+
+ if (!strcmp(name, "plla")) {
+ parent_name = of_clk_get_parent_name(np, 0);
+ mult = plla_mult;
+ } else if (!strcmp(name, "z")) {
+ div = config->z_div;
+ mult = config->z_mult;
+ } else if (!strcmp(name, "zs") || !strcmp(name, "s")) {
+ div = config->zs_and_s_div;
+ } else if (!strcmp(name, "s1")) {
+ div = config->s1_div;
+ } else if (!strcmp(name, "p")) {
+ div = config->p_div;
+ } else if (!strcmp(name, "b") || !strcmp(name, "out")) {
+ div = config->b_and_out_div;
+ } else {
+ return ERR_PTR(-EINVAL);
+ }
+
+ return clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div);
+}
+
+static void __init r8a7779_cpg_clocks_init(struct device_node *np)
+{
+ const struct cpg_clk_config *config;
+ struct clk_onecell_data *data;
+ struct clk **clks;
+ unsigned int i, plla_mult;
+ int num_clks;
+ u32 mode;
+
+ if (rcar_rst_read_mode_pins(&mode))
+ return;
+
+ num_clks = of_property_count_strings(np, "clock-output-names");
+ if (num_clks < 0) {
+ pr_err("%s: failed to count clocks\n", __func__);
+ return;
+ }
+
+ data = kzalloc_obj(*data);
+ clks = kzalloc_objs(*clks, CPG_NUM_CLOCKS);
+ if (data == NULL || clks == NULL) {
+ /* We're leaking memory on purpose, there's no point in cleaning
+ * up as the system won't boot anyway.
+ */
+ return;
+ }
+
+ data->clks = clks;
+ data->clk_num = num_clks;
+
+ config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(mode)];
+ plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(mode)];
+
+ for (i = 0; i < num_clks; ++i) {
+ const char *name;
+ struct clk *clk;
+
+ of_property_read_string_index(np, "clock-output-names", i,
+ &name);
+
+ clk = r8a7779_cpg_register_clock(np, config, plla_mult, name);
+ if (IS_ERR(clk))
+ pr_err("%s: failed to register %pOFn %s clock (%ld)\n",
+ __func__, np, name, PTR_ERR(clk));
+ else
+ data->clks[i] = clk;
+ }
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, data);
+
+ cpg_mstp_add_clk_domain(np);
+}
+CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks",
+ r8a7779_cpg_clocks_init);
diff --git a/drivers/clk/renesas/clk-rz.c b/drivers/clk/renesas/clk-rz.c
new file mode 100644
index 000000000..5347c067e
--- /dev/null
+++ b/drivers/clk/renesas/clk-rz.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/A1 Core CPG Clocks
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ * Copyright (C) 2014 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#define CPG_FRQCR 0x10
+#define CPG_FRQCR2 0x14
+
+#define PPR0 0xFCFE3200
+#define PIBC0 0xFCFE7000
+
+#define MD_CLK(x) ((x >> 2) & 1) /* P0_2 */
+
+/* -----------------------------------------------------------------------------
+ * Initialization
+ */
+
+static u16 __init rz_cpg_read_mode_pins(void)
+{
+ void __iomem *ppr0, *pibc0;
+ u16 modes;
+
+ ppr0 = ioremap(PPR0, 2);
+ pibc0 = ioremap(PIBC0, 2);
+ BUG_ON(!ppr0 || !pibc0);
+ iowrite16(4, pibc0); /* enable input buffer */
+ modes = ioread16(ppr0);
+ iounmap(ppr0);
+ iounmap(pibc0);
+
+ return modes;
+}
+
+static struct clk * __init
+rz_cpg_register_clock(struct device_node *np, void __iomem *base,
+ const char *name)
+{
+ u32 val;
+ unsigned mult;
+ static const unsigned frqcr_tab[4] = { 3, 2, 0, 1 };
+
+ if (strcmp(name, "pll") == 0) {
+ unsigned int cpg_mode = MD_CLK(rz_cpg_read_mode_pins());
+ const char *parent_name = of_clk_get_parent_name(np, cpg_mode);
+
+ mult = cpg_mode ? (32 / 4) : 30;
+
+ return clk_register_fixed_factor(NULL, name, parent_name, 0, mult, 1);
+ }
+
+ /* If mapping regs failed, skip non-pll clocks. System will boot anyhow */
+ if (!base)
+ return ERR_PTR(-ENXIO);
+
+ /* FIXME:"i" and "g" are variable clocks with non-integer dividers (e.g. 2/3)
+ * and the constraint that always g <= i. To get the rz platform started,
+ * let them run at fixed current speed and implement the details later.
+ */
+ if (strcmp(name, "i") == 0)
+ val = (readl(base + CPG_FRQCR) >> 8) & 3;
+ else if (strcmp(name, "g") == 0)
+ val = readl(base + CPG_FRQCR2) & 3;
+ else
+ return ERR_PTR(-EINVAL);
+
+ mult = frqcr_tab[val];
+ return clk_register_fixed_factor(NULL, name, "pll", 0, mult, 3);
+}
+
+static void __init rz_cpg_clocks_init(struct device_node *np)
+{
+ struct clk_onecell_data *data;
+ struct clk **clks;
+ void __iomem *base;
+ unsigned i;
+ int num_clks;
+
+ num_clks = of_property_count_strings(np, "clock-output-names");
+ if (WARN(num_clks <= 0, "can't count CPG clocks\n"))
+ return;
+
+ data = kzalloc_obj(*data);
+ clks = kzalloc_objs(*clks, num_clks);
+ BUG_ON(!data || !clks);
+
+ data->clks = clks;
+ data->clk_num = num_clks;
+
+ base = of_iomap(np, 0);
+
+ for (i = 0; i < num_clks; ++i) {
+ const char *name;
+ struct clk *clk;
+
+ of_property_read_string_index(np, "clock-output-names", i, &name);
+
+ clk = rz_cpg_register_clock(np, base, name);
+ if (IS_ERR(clk))
+ pr_err("%s: failed to register %pOFn %s clock (%ld)\n",
+ __func__, np, name, PTR_ERR(clk));
+ else
+ data->clks[i] = clk;
+ }
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, data);
+
+ cpg_mstp_add_clk_domain(np);
+}
+CLK_OF_DECLARE(rz_cpg_clks, "renesas,rz-cpg-clocks", rz_cpg_clocks_init);
diff --git a/drivers/clk/renesas/clk-sh73a0.c b/drivers/clk/renesas/clk-sh73a0.c
new file mode 100644
index 000000000..efae041ac
--- /dev/null
+++ b/drivers/clk/renesas/clk-sh73a0.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * sh73a0 Core CPG Clocks
+ *
+ * Copyright (C) 2014 Ulrich Hecht
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+struct sh73a0_cpg {
+ struct clk_onecell_data data;
+ spinlock_t lock;
+};
+
+#define CPG_FRQCRA 0x00
+#define CPG_FRQCRB 0x04
+#define CPG_SD0CKCR 0x74
+#define CPG_SD1CKCR 0x78
+#define CPG_SD2CKCR 0x7c
+#define CPG_PLLECR 0xd0
+#define CPG_PLL0CR 0xd8
+#define CPG_PLL1CR 0x28
+#define CPG_PLL2CR 0x2c
+#define CPG_PLL3CR 0xdc
+#define CPG_CKSCR 0xc0
+#define CPG_DSI0PHYCR 0x6c
+#define CPG_DSI1PHYCR 0x70
+
+struct div4_clk {
+ const char *name;
+ const char *parent;
+ unsigned int reg;
+ unsigned int shift;
+};
+
+static const struct div4_clk div4_clks[] = {
+ { "zg", "pll0", CPG_FRQCRA, 16 },
+ { "m3", "pll1", CPG_FRQCRA, 12 },
+ { "b", "pll1", CPG_FRQCRA, 8 },
+ { "m1", "pll1", CPG_FRQCRA, 4 },
+ { "m2", "pll1", CPG_FRQCRA, 0 },
+ { "zx", "pll1", CPG_FRQCRB, 12 },
+ { "hp", "pll1", CPG_FRQCRB, 4 },
+ { NULL, NULL, 0, 0 },
+};
+
+static const struct clk_div_table div4_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 },
+ { 6, 16 }, { 7, 18 }, { 8, 24 }, { 10, 36 }, { 11, 48 },
+ { 12, 7 }, { 0, 0 }
+};
+
+static const struct clk_div_table z_div_table[] = {
+ /* ZSEL == 0 */
+ { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 1 },
+ { 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 10, 1 }, { 11, 1 },
+ { 12, 1 }, { 13, 1 }, { 14, 1 }, { 15, 1 },
+ /* ZSEL == 1 */
+ { 16, 2 }, { 17, 3 }, { 18, 4 }, { 19, 6 }, { 20, 8 }, { 21, 12 },
+ { 22, 16 }, { 24, 24 }, { 27, 48 }, { 0, 0 }
+};
+
+static struct clk * __init
+sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg,
+ void __iomem *base, const char *name)
+{
+ const struct clk_div_table *table = NULL;
+ unsigned int shift, reg, width;
+ const char *parent_name = NULL;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+
+ if (!strcmp(name, "main")) {
+ /* extal1, extal1_div2, extal2, extal2_div2 */
+ u32 parent_idx = (readl(base + CPG_CKSCR) >> 28) & 3;
+
+ parent_name = of_clk_get_parent_name(np, parent_idx >> 1);
+ div = (parent_idx & 1) + 1;
+ } else if (!strncmp(name, "pll", 3)) {
+ void __iomem *enable_reg = base;
+ u32 enable_bit = name[3] - '0';
+
+ parent_name = "main";
+ switch (enable_bit) {
+ case 0:
+ enable_reg += CPG_PLL0CR;
+ break;
+ case 1:
+ enable_reg += CPG_PLL1CR;
+ break;
+ case 2:
+ enable_reg += CPG_PLL2CR;
+ break;
+ case 3:
+ enable_reg += CPG_PLL3CR;
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+ if (readl(base + CPG_PLLECR) & BIT(enable_bit)) {
+ mult = ((readl(enable_reg) >> 24) & 0x3f) + 1;
+ /* handle CFG bit for PLL1 and PLL2 */
+ if (enable_bit == 1 || enable_bit == 2)
+ if (readl(enable_reg) & BIT(20))
+ mult *= 2;
+ }
+ } else if (!strcmp(name, "dsi0phy") || !strcmp(name, "dsi1phy")) {
+ u32 phy_no = name[3] - '0';
+ void __iomem *dsi_reg = base +
+ (phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR);
+
+ parent_name = phy_no ? "dsi1pck" : "dsi0pck";
+ mult = readl(dsi_reg);
+ if (!(mult & 0x8000))
+ mult = 1;
+ else
+ mult = (mult & 0x3f) + 1;
+ } else if (!strcmp(name, "z")) {
+ parent_name = "pll0";
+ table = z_div_table;
+ reg = CPG_FRQCRB;
+ shift = 24;
+ width = 5;
+ } else {
+ const struct div4_clk *c;
+
+ for (c = div4_clks; c->name; c++) {
+ if (!strcmp(name, c->name)) {
+ parent_name = c->parent;
+ table = div4_div_table;
+ reg = c->reg;
+ shift = c->shift;
+ width = 4;
+ break;
+ }
+ }
+ if (!c->name)
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!table) {
+ return clk_register_fixed_factor(NULL, name, parent_name, 0,
+ mult, div);
+ } else {
+ return clk_register_divider_table(NULL, name, parent_name, 0,
+ base + reg, shift, width, 0,
+ table, &cpg->lock);
+ }
+}
+
+static void __init sh73a0_cpg_clocks_init(struct device_node *np)
+{
+ struct sh73a0_cpg *cpg;
+ void __iomem *base;
+ struct clk **clks;
+ unsigned int i;
+ int num_clks;
+
+ num_clks = of_property_count_strings(np, "clock-output-names");
+ if (num_clks < 0) {
+ pr_err("%s: failed to count clocks\n", __func__);
+ return;
+ }
+
+ cpg = kzalloc_obj(*cpg);
+ clks = kzalloc_objs(*clks, num_clks);
+ if (cpg == NULL || clks == NULL) {
+ /* We're leaking memory on purpose, there's no point in cleaning
+ * up as the system won't boot anyway.
+ */
+ return;
+ }
+
+ spin_lock_init(&cpg->lock);
+
+ cpg->data.clks = clks;
+ cpg->data.clk_num = num_clks;
+
+ base = of_iomap(np, 0);
+ if (WARN_ON(base == NULL))
+ return;
+
+ /* Set SDHI clocks to a known state */
+ writel(0x108, base + CPG_SD0CKCR);
+ writel(0x108, base + CPG_SD1CKCR);
+ writel(0x108, base + CPG_SD2CKCR);
+
+ for (i = 0; i < num_clks; ++i) {
+ const char *name;
+ struct clk *clk;
+
+ of_property_read_string_index(np, "clock-output-names", i,
+ &name);
+
+ clk = sh73a0_cpg_register_clock(np, cpg, base, name);
+ if (IS_ERR(clk))
+ pr_err("%s: failed to register %pOFn %s clock (%ld)\n",
+ __func__, np, name, PTR_ERR(clk));
+ else
+ cpg->data.clks[i] = clk;
+ }
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
+}
+CLK_OF_DECLARE(sh73a0_cpg_clks, "renesas,sh73a0-cpg-clocks",
+ sh73a0_cpg_clocks_init);
diff --git a/drivers/clk/renesas/clk-vbattb.c b/drivers/clk/renesas/clk-vbattb.c
new file mode 100644
index 000000000..bd97a68be
--- /dev/null
+++ b/drivers/clk/renesas/clk-vbattb.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VBATTB clock driver
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+
+#include <linux/cleanup.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#include <dt-bindings/clock/renesas,r9a08g045-vbattb.h>
+
+#define VBATTB_BKSCCR 0x1c
+#define VBATTB_BKSCCR_SOSEL 6
+#define VBATTB_SOSCCR2 0x24
+#define VBATTB_SOSCCR2_SOSTP2 0
+#define VBATTB_XOSCCR 0x30
+#define VBATTB_XOSCCR_OUTEN 16
+#define VBATTB_XOSCCR_XSEL GENMASK(1, 0)
+#define VBATTB_XOSCCR_XSEL_4_PF 0x0
+#define VBATTB_XOSCCR_XSEL_7_PF 0x1
+#define VBATTB_XOSCCR_XSEL_9_PF 0x2
+#define VBATTB_XOSCCR_XSEL_12_5_PF 0x3
+
+/**
+ * struct vbattb_clk - VBATTB clock data structure
+ * @base: base address
+ * @lock: lock
+ */
+struct vbattb_clk {
+ void __iomem *base;
+ spinlock_t lock;
+};
+
+static int vbattb_clk_validate_load_capacitance(u32 *reg_lc, u32 of_lc)
+{
+ switch (of_lc) {
+ case 4000:
+ *reg_lc = VBATTB_XOSCCR_XSEL_4_PF;
+ break;
+ case 7000:
+ *reg_lc = VBATTB_XOSCCR_XSEL_7_PF;
+ break;
+ case 9000:
+ *reg_lc = VBATTB_XOSCCR_XSEL_9_PF;
+ break;
+ case 12500:
+ *reg_lc = VBATTB_XOSCCR_XSEL_12_5_PF;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void vbattb_clk_action(void *data)
+{
+ struct device *dev = data;
+ struct reset_control *rstc = dev_get_drvdata(dev);
+ int ret;
+
+ ret = reset_control_assert(rstc);
+ if (ret)
+ dev_err(dev, "Failed to de-assert reset!\n");
+
+ ret = pm_runtime_put_sync(dev);
+ if (ret < 0)
+ dev_err(dev, "Failed to runtime suspend!\n");
+
+ of_clk_del_provider(dev->of_node);
+}
+
+static int vbattb_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct clk_parent_data parent_data = {};
+ struct clk_hw_onecell_data *clk_data;
+ const struct clk_hw *parent_hws[2];
+ struct device *dev = &pdev->dev;
+ struct reset_control *rstc;
+ struct vbattb_clk *vbclk;
+ u32 of_lc, reg_lc;
+ struct clk_hw *hw;
+ /* 4 clocks are exported: VBATTB_XC, VBATTB_XBYP, VBATTB_MUX, VBATTB_VBATTCLK. */
+ u8 num_clks = 4;
+ int ret;
+
+ /* Default to 4pF as this is not needed if external clock device is connected. */
+ of_lc = 4000;
+ of_property_read_u32(np, "quartz-load-femtofarads", &of_lc);
+
+ ret = vbattb_clk_validate_load_capacitance(&reg_lc, of_lc);
+ if (ret)
+ return ret;
+
+ vbclk = devm_kzalloc(dev, sizeof(*vbclk), GFP_KERNEL);
+ if (!vbclk)
+ return -ENOMEM;
+
+ clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, num_clks), GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+ clk_data->num = num_clks;
+
+ vbclk->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(vbclk->base))
+ return PTR_ERR(vbclk->base);
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ rstc = devm_reset_control_get_shared(dev, NULL);
+ if (IS_ERR(rstc))
+ return PTR_ERR(rstc);
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(rstc);
+ if (ret) {
+ pm_runtime_put_sync(dev);
+ return ret;
+ }
+
+ dev_set_drvdata(dev, rstc);
+ ret = devm_add_action_or_reset(dev, vbattb_clk_action, dev);
+ if (ret)
+ return ret;
+
+ spin_lock_init(&vbclk->lock);
+
+ parent_data.fw_name = "rtx";
+ hw = devm_clk_hw_register_gate_parent_data(dev, "xc", &parent_data, 0,
+ vbclk->base + VBATTB_SOSCCR2,
+ VBATTB_SOSCCR2_SOSTP2,
+ CLK_GATE_SET_TO_DISABLE, &vbclk->lock);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+ clk_data->hws[VBATTB_XC] = hw;
+
+ hw = devm_clk_hw_register_fixed_factor_fwname(dev, np, "xbyp", "rtx", 0, 1, 1);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+ clk_data->hws[VBATTB_XBYP] = hw;
+
+ parent_hws[0] = clk_data->hws[VBATTB_XC];
+ parent_hws[1] = clk_data->hws[VBATTB_XBYP];
+ hw = devm_clk_hw_register_mux_parent_hws(dev, "mux", parent_hws, 2, 0,
+ vbclk->base + VBATTB_BKSCCR,
+ VBATTB_BKSCCR_SOSEL,
+ 1, 0, &vbclk->lock);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+ clk_data->hws[VBATTB_MUX] = hw;
+
+ /* Set load capacitance before registering the VBATTCLK clock. */
+ scoped_guard(spinlock, &vbclk->lock) {
+ u32 val = readl_relaxed(vbclk->base + VBATTB_XOSCCR);
+
+ val &= ~VBATTB_XOSCCR_XSEL;
+ val |= reg_lc;
+ writel_relaxed(val, vbclk->base + VBATTB_XOSCCR);
+ }
+
+ /* This feeds the RTC counter clock and it needs to stay on. */
+ hw = devm_clk_hw_register_gate_parent_hw(dev, "vbattclk", hw, CLK_IS_CRITICAL,
+ vbclk->base + VBATTB_XOSCCR,
+ VBATTB_XOSCCR_OUTEN, 0,
+ &vbclk->lock);
+
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+ clk_data->hws[VBATTB_VBATTCLK] = hw;
+
+ return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+}
+
+static const struct of_device_id vbattb_clk_match[] = {
+ { .compatible = "renesas,r9a08g045-vbattb" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, vbattb_clk_match);
+
+static struct platform_driver vbattb_clk_driver = {
+ .driver = {
+ .name = "renesas-vbattb-clk",
+ .of_match_table = vbattb_clk_match,
+ },
+ .probe = vbattb_clk_probe,
+};
+module_platform_driver(vbattb_clk_driver);
+
+MODULE_DESCRIPTION("Renesas VBATTB Clock Driver");
+MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/renesas/r7s9210-cpg-mssr.c b/drivers/clk/renesas/r7s9210-cpg-mssr.c
new file mode 100644
index 000000000..a8ed87c11
--- /dev/null
+++ b/drivers/clk/renesas/r7s9210-cpg-mssr.c
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R7S9210 Clock Pulse Generator / Module Standby
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2018 Chris Brandt
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <dt-bindings/clock/r7s9210-cpg-mssr.h>
+#include "renesas-cpg-mssr.h"
+
+#define CPG_FRQCR 0x00
+
+static u8 cpg_mode;
+
+/* Internal Clock ratio table */
+static const struct {
+ unsigned int i;
+ unsigned int g;
+ unsigned int b;
+ unsigned int p1;
+ /* p0 is always 32 */;
+} ratio_tab[5] = { /* I, G, B, P1 */
+ { 2, 4, 8, 16}, /* FRQCR = 0x012 */
+ { 4, 4, 8, 16}, /* FRQCR = 0x112 */
+ { 8, 4, 8, 16}, /* FRQCR = 0x212 */
+ { 16, 8, 16, 16}, /* FRQCR = 0x322 */
+ { 16, 16, 32, 32}, /* FRQCR = 0x333 */
+ };
+
+enum rz_clk_types {
+ CLK_TYPE_RZA_MAIN = CLK_TYPE_CUSTOM,
+ CLK_TYPE_RZA_PLL,
+};
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R7S9210_CLK_P0,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static struct cpg_core_clk r7s9210_early_core_clks[] = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_RZA_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll", CLK_PLL, CLK_TYPE_RZA_PLL, CLK_MAIN),
+
+ /* Core Clock Outputs */
+ DEF_FIXED("p1c", R7S9210_CLK_P1C, CLK_PLL, 16, 1),
+};
+
+static const struct mssr_mod_clk r7s9210_early_mod_clks[] __initconst = {
+ DEF_MOD_STB("ostm2", 34, R7S9210_CLK_P1C),
+ DEF_MOD_STB("ostm1", 35, R7S9210_CLK_P1C),
+ DEF_MOD_STB("ostm0", 36, R7S9210_CLK_P1C),
+};
+
+static struct cpg_core_clk r7s9210_core_clks[] = {
+ /* Core Clock Outputs */
+ DEF_FIXED("i", R7S9210_CLK_I, CLK_PLL, 2, 1),
+ DEF_FIXED("g", R7S9210_CLK_G, CLK_PLL, 4, 1),
+ DEF_FIXED("b", R7S9210_CLK_B, CLK_PLL, 8, 1),
+ DEF_FIXED("p1", R7S9210_CLK_P1, CLK_PLL, 16, 1),
+ DEF_FIXED("p0", R7S9210_CLK_P0, CLK_PLL, 32, 1),
+};
+
+static const struct mssr_mod_clk r7s9210_mod_clks[] __initconst = {
+ DEF_MOD_STB("scif4", 43, R7S9210_CLK_P1C),
+ DEF_MOD_STB("scif3", 44, R7S9210_CLK_P1C),
+ DEF_MOD_STB("scif2", 45, R7S9210_CLK_P1C),
+ DEF_MOD_STB("scif1", 46, R7S9210_CLK_P1C),
+ DEF_MOD_STB("scif0", 47, R7S9210_CLK_P1C),
+
+ DEF_MOD_STB("usb1", 60, R7S9210_CLK_B),
+ DEF_MOD_STB("usb0", 61, R7S9210_CLK_B),
+ DEF_MOD_STB("ether1", 64, R7S9210_CLK_B),
+ DEF_MOD_STB("ether0", 65, R7S9210_CLK_B),
+
+ DEF_MOD_STB("spibsc", 83, R7S9210_CLK_P1),
+ DEF_MOD_STB("i2c3", 84, R7S9210_CLK_P1),
+ DEF_MOD_STB("i2c2", 85, R7S9210_CLK_P1),
+ DEF_MOD_STB("i2c1", 86, R7S9210_CLK_P1),
+ DEF_MOD_STB("i2c0", 87, R7S9210_CLK_P1),
+
+ DEF_MOD_STB("spi2", 95, R7S9210_CLK_P1),
+ DEF_MOD_STB("spi1", 96, R7S9210_CLK_P1),
+ DEF_MOD_STB("spi0", 97, R7S9210_CLK_P1),
+
+ DEF_MOD_STB("sdhi11", 100, R7S9210_CLK_B),
+ DEF_MOD_STB("sdhi10", 101, R7S9210_CLK_B),
+ DEF_MOD_STB("sdhi01", 102, R7S9210_CLK_B),
+ DEF_MOD_STB("sdhi00", 103, R7S9210_CLK_B),
+};
+
+/* The clock dividers in the table vary based on DT and register settings */
+static void __init r7s9210_update_clk_table(struct clk *extal_clk,
+ void __iomem *base)
+{
+ int i;
+ u16 frqcr;
+ u8 index;
+
+ /* If EXTAL is above 12MHz, then we know it is Mode 1 */
+ if (clk_get_rate(extal_clk) > 12000000)
+ cpg_mode = 1;
+
+ frqcr = readl(base + CPG_FRQCR) & 0xFFF;
+ if (frqcr == 0x012)
+ index = 0;
+ else if (frqcr == 0x112)
+ index = 1;
+ else if (frqcr == 0x212)
+ index = 2;
+ else if (frqcr == 0x322)
+ index = 3;
+ else if (frqcr == 0x333)
+ index = 4;
+ else
+ BUG_ON(1); /* Illegal FRQCR value */
+
+ for (i = 0; i < ARRAY_SIZE(r7s9210_core_clks); i++) {
+ switch (r7s9210_core_clks[i].id) {
+ case R7S9210_CLK_I:
+ r7s9210_core_clks[i].div = ratio_tab[index].i;
+ break;
+ case R7S9210_CLK_G:
+ r7s9210_core_clks[i].div = ratio_tab[index].g;
+ break;
+ case R7S9210_CLK_B:
+ r7s9210_core_clks[i].div = ratio_tab[index].b;
+ break;
+ case R7S9210_CLK_P1:
+ case R7S9210_CLK_P1C:
+ r7s9210_core_clks[i].div = ratio_tab[index].p1;
+ break;
+ case R7S9210_CLK_P0:
+ r7s9210_core_clks[i].div = 32;
+ break;
+ }
+ }
+}
+
+static struct clk * __init rza2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+ struct cpg_mssr_pub *pub)
+{
+ void __iomem *base = pub->base0;
+ struct clk **clks = pub->clks;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+ struct clk *parent;
+
+ parent = clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ switch (core->type) {
+ case CLK_TYPE_RZA_MAIN:
+ r7s9210_update_clk_table(parent, base);
+ break;
+
+ case CLK_TYPE_RZA_PLL:
+ if (cpg_mode)
+ mult = 44; /* Divider 1 is 1/2 */
+ else
+ mult = 88; /* Divider 1 is 1 */
+ break;
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ return clk_register_fixed_factor(NULL, core->name,
+ __clk_get_name(parent), 0, mult, div);
+}
+
+const struct cpg_mssr_info r7s9210_cpg_mssr_info __initconst = {
+ /* Early Clocks */
+ .early_core_clks = r7s9210_early_core_clks,
+ .num_early_core_clks = ARRAY_SIZE(r7s9210_early_core_clks),
+ .early_mod_clks = r7s9210_early_mod_clks,
+ .num_early_mod_clks = ARRAY_SIZE(r7s9210_early_mod_clks),
+
+ /* Core Clocks */
+ .core_clks = r7s9210_core_clks,
+ .num_core_clks = ARRAY_SIZE(r7s9210_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r7s9210_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r7s9210_mod_clks),
+ .num_hw_mod_clks = 11 * 32, /* includes STBCR0 which doesn't exist */
+
+ /* Callbacks */
+ .cpg_clk_register = rza2_cpg_clk_register,
+
+ /* RZ/A2 has Standby Control Registers */
+ .reg_layout = CLK_REG_LAYOUT_RZ_A,
+};
+
+static void __init r7s9210_cpg_mssr_early_init(struct device_node *np)
+{
+ cpg_mssr_early_init(np, &r7s9210_cpg_mssr_info);
+}
+
+CLK_OF_DECLARE_DRIVER(cpg_mstp_clks, "renesas,r7s9210-cpg-mssr",
+ r7s9210_cpg_mssr_early_init);
diff --git a/drivers/clk/renesas/r8a7742-cpg-mssr.c b/drivers/clk/renesas/r8a7742-cpg-mssr.c
new file mode 100644
index 000000000..e541489bd
--- /dev/null
+++ b/drivers/clk/renesas/r8a7742-cpg-mssr.c
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7742 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7742-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7742_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_USB_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7742_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("z", R8A7742_CLK_Z, CLK_TYPE_GEN2_Z, CLK_PLL0),
+ DEF_BASE("lb", R8A7742_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1),
+ DEF_BASE("sdh", R8A7742_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
+ DEF_BASE("sd0", R8A7742_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
+ DEF_BASE("sd1", R8A7742_CLK_SD1, CLK_TYPE_GEN2_SD1, CLK_PLL1),
+ DEF_BASE("qspi", R8A7742_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+ DEF_BASE("rcan", R8A7742_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+ DEF_FIXED("z2", R8A7742_CLK_Z2, CLK_PLL1, 2, 1),
+ DEF_FIXED("zg", R8A7742_CLK_ZG, CLK_PLL1, 3, 1),
+ DEF_FIXED("zx", R8A7742_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A7742_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A7742_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("b", R8A7742_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("p", R8A7742_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A7742_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A7742_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("zb3", R8A7742_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("zb3d2", R8A7742_CLK_ZB3D2, CLK_PLL3, 8, 1),
+ DEF_FIXED("ddr", R8A7742_CLK_DDR, CLK_PLL3, 8, 1),
+ DEF_FIXED("mp", R8A7742_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cp", R8A7742_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("r", R8A7742_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A7742_CLK_OSC, CLK_PLL1, 12288, 1),
+
+ DEF_DIV6P1("sd2", R8A7742_CLK_SD2, CLK_PLL1_DIV2, 0x078),
+ DEF_DIV6P1("sd3", R8A7742_CLK_SD3, CLK_PLL1_DIV2, 0x26c),
+ DEF_DIV6P1("mmc0", R8A7742_CLK_MMC0, CLK_PLL1_DIV2, 0x240),
+ DEF_DIV6P1("mmc1", R8A7742_CLK_MMC1, CLK_PLL1_DIV2, 0x244),
+};
+
+static const struct mssr_mod_clk r8a7742_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A7742_CLK_MP),
+ DEF_MOD("vcp1", 100, R8A7742_CLK_ZS),
+ DEF_MOD("vcp0", 101, R8A7742_CLK_ZS),
+ DEF_MOD("vpc1", 102, R8A7742_CLK_ZS),
+ DEF_MOD("vpc0", 103, R8A7742_CLK_ZS),
+ DEF_MOD("tmu1", 111, R8A7742_CLK_P),
+ DEF_MOD("3dg", 112, R8A7742_CLK_ZG),
+ DEF_MOD("2d-dmac", 115, R8A7742_CLK_ZS),
+ DEF_MOD("fdp1-2", 117, R8A7742_CLK_ZS),
+ DEF_MOD("fdp1-1", 118, R8A7742_CLK_ZS),
+ DEF_MOD("fdp1-0", 119, R8A7742_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A7742_CLK_P),
+ DEF_MOD("tmu2", 122, R8A7742_CLK_P),
+ DEF_MOD("cmt0", 124, R8A7742_CLK_R),
+ DEF_MOD("tmu0", 125, R8A7742_CLK_CP),
+ DEF_MOD("vsp1du1", 127, R8A7742_CLK_ZS),
+ DEF_MOD("vsp1du0", 128, R8A7742_CLK_ZS),
+ DEF_MOD("vspr", 130, R8A7742_CLK_ZS),
+ DEF_MOD("vsps", 131, R8A7742_CLK_ZS),
+ DEF_MOD("scifa2", 202, R8A7742_CLK_MP),
+ DEF_MOD("scifa1", 203, R8A7742_CLK_MP),
+ DEF_MOD("scifa0", 204, R8A7742_CLK_MP),
+ DEF_MOD("msiof2", 205, R8A7742_CLK_MP),
+ DEF_MOD("scifb0", 206, R8A7742_CLK_MP),
+ DEF_MOD("scifb1", 207, R8A7742_CLK_MP),
+ DEF_MOD("msiof1", 208, R8A7742_CLK_MP),
+ DEF_MOD("msiof3", 215, R8A7742_CLK_MP),
+ DEF_MOD("scifb2", 216, R8A7742_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A7742_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A7742_CLK_ZS),
+ DEF_MOD("iic2", 300, R8A7742_CLK_HP),
+ DEF_MOD("tpu0", 304, R8A7742_CLK_CP),
+ DEF_MOD("mmcif1", 305, R8A7742_CLK_MMC1),
+ DEF_MOD("scif2", 310, R8A7742_CLK_P),
+ DEF_MOD("sdhi3", 311, R8A7742_CLK_SD3),
+ DEF_MOD("sdhi2", 312, R8A7742_CLK_SD2),
+ DEF_MOD("sdhi1", 313, R8A7742_CLK_SD1),
+ DEF_MOD("sdhi0", 314, R8A7742_CLK_SD0),
+ DEF_MOD("mmcif0", 315, R8A7742_CLK_MMC0),
+ DEF_MOD("iic0", 318, R8A7742_CLK_HP),
+ DEF_MOD("pciec", 319, R8A7742_CLK_MP),
+ DEF_MOD("iic1", 323, R8A7742_CLK_HP),
+ DEF_MOD("usb3.0", 328, R8A7742_CLK_MP),
+ DEF_MOD("cmt1", 329, R8A7742_CLK_R),
+ DEF_MOD("usbhs-dmac0", 330, R8A7742_CLK_HP),
+ DEF_MOD("usbhs-dmac1", 331, R8A7742_CLK_HP),
+ DEF_MOD("rwdt", 402, R8A7742_CLK_R),
+ DEF_MOD("irqc", 407, R8A7742_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A7742_CLK_ZS),
+ DEF_MOD("audio-dmac1", 501, R8A7742_CLK_HP),
+ DEF_MOD("audio-dmac0", 502, R8A7742_CLK_HP),
+ DEF_MOD("thermal", 522, CLK_EXTAL),
+ DEF_MOD("pwm", 523, R8A7742_CLK_P),
+ DEF_MOD("usb-ehci", 703, R8A7742_CLK_MP),
+ DEF_MOD("usbhs", 704, R8A7742_CLK_HP),
+ DEF_MOD("hscif1", 716, R8A7742_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A7742_CLK_ZS),
+ DEF_MOD("scif1", 720, R8A7742_CLK_P),
+ DEF_MOD("scif0", 721, R8A7742_CLK_P),
+ DEF_MOD("du2", 722, R8A7742_CLK_ZX),
+ DEF_MOD("du1", 723, R8A7742_CLK_ZX),
+ DEF_MOD("du0", 724, R8A7742_CLK_ZX),
+ DEF_MOD("lvds1", 725, R8A7742_CLK_ZX),
+ DEF_MOD("lvds0", 726, R8A7742_CLK_ZX),
+ DEF_MOD("r-gp2d", 807, R8A7742_CLK_ZX),
+ DEF_MOD("vin3", 808, R8A7742_CLK_ZG),
+ DEF_MOD("vin2", 809, R8A7742_CLK_ZG),
+ DEF_MOD("vin1", 810, R8A7742_CLK_ZG),
+ DEF_MOD("vin0", 811, R8A7742_CLK_ZG),
+ DEF_MOD("etheravb", 812, R8A7742_CLK_HP),
+ DEF_MOD("ether", 813, R8A7742_CLK_P),
+ DEF_MOD("sata1", 814, R8A7742_CLK_ZS),
+ DEF_MOD("sata0", 815, R8A7742_CLK_ZS),
+ DEF_MOD("imr-x2-1", 820, R8A7742_CLK_ZG),
+ DEF_MOD("imr-x2-0", 821, R8A7742_CLK_HP),
+ DEF_MOD("imr-lsx2-1", 822, R8A7742_CLK_P),
+ DEF_MOD("imr-lsx2-0", 823, R8A7742_CLK_ZS),
+ DEF_MOD("gpio5", 907, R8A7742_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A7742_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A7742_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A7742_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A7742_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A7742_CLK_CP),
+ DEF_MOD("can1", 915, R8A7742_CLK_P),
+ DEF_MOD("can0", 916, R8A7742_CLK_P),
+ DEF_MOD("qspi_mod", 917, R8A7742_CLK_QSPI),
+ DEF_MOD("iicdvfs", 926, R8A7742_CLK_CP),
+ DEF_MOD("i2c3", 928, R8A7742_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A7742_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A7742_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A7742_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A7742_CLK_P),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7742_CLK_P),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a7742_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz) *1 *1
+ *---------------------------------------------------
+ * 0 0 0 15 x172/2 x208/2 x106
+ * 0 0 1 15 x172/2 x208/2 x88
+ * 0 1 0 20 x130/2 x156/2 x80
+ * 0 1 1 20 x130/2 x156/2 x66
+ * 1 0 0 26 / 2 x200/2 x240/2 x122
+ * 1 0 1 26 / 2 x200/2 x240/2 x102
+ * 1 1 0 30 / 2 x172/2 x208/2 x106
+ * 1 1 1 30 / 2 x172/2 x208/2 x88
+ *
+ * *1 : Table 7.5a indicates VCO output (PLLx = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
+ (((md) & BIT(13)) >> 12) | \
+ (((md) & BIT(19)) >> 19))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+ /* EXTAL div PLL1 mult PLL3 mult */
+ { 1, 208, 106, },
+ { 1, 208, 88, },
+ { 1, 156, 80, },
+ { 1, 156, 66, },
+ { 2, 240, 122, },
+ { 2, 240, 102, },
+ { 2, 208, 106, },
+ { 2, 208, 88, },
+};
+
+static int __init r8a7742_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7742_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7742_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7742_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7742_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7742_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7742_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7742_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7742_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7743-cpg-mssr.c b/drivers/clk/renesas/r8a7743-cpg-mssr.c
new file mode 100644
index 000000000..0bba12a48
--- /dev/null
+++ b/drivers/clk/renesas/r8a7743-cpg-mssr.c
@@ -0,0 +1,280 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7743 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7743-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7743_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_USB_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static struct cpg_core_clk r8a7743_core_clks[] __initdata = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("z", R8A7743_CLK_Z, CLK_TYPE_GEN2_Z, CLK_PLL0),
+ DEF_BASE("sdh", R8A7743_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
+ DEF_BASE("sd0", R8A7743_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
+ DEF_BASE("qspi", R8A7743_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+ DEF_BASE("rcan", R8A7743_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+ DEF_FIXED("zg", R8A7743_CLK_ZG, CLK_PLL1, 3, 1),
+ DEF_FIXED("zx", R8A7743_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A7743_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A7743_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("b", R8A7743_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("lb", R8A7743_CLK_LB, CLK_PLL1, 24, 1),
+ DEF_FIXED("p", R8A7743_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A7743_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A7743_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("zb3", R8A7743_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("zb3d2", R8A7743_CLK_ZB3D2, CLK_PLL3, 8, 1),
+ DEF_FIXED("ddr", R8A7743_CLK_DDR, CLK_PLL3, 8, 1),
+ DEF_FIXED("mp", R8A7743_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cp", R8A7743_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("r", R8A7743_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A7743_CLK_OSC, CLK_PLL1, 12288, 1),
+
+ DEF_DIV6P1("sd2", R8A7743_CLK_SD2, CLK_PLL1_DIV2, 0x078),
+ DEF_DIV6P1("sd3", R8A7743_CLK_SD3, CLK_PLL1_DIV2, 0x26c),
+ DEF_DIV6P1("mmc0", R8A7743_CLK_MMC0, CLK_PLL1_DIV2, 0x240),
+};
+
+static const struct mssr_mod_clk r8a7743_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A7743_CLK_MP),
+ DEF_MOD("vcp0", 101, R8A7743_CLK_ZS),
+ DEF_MOD("vpc0", 103, R8A7743_CLK_ZS),
+ DEF_MOD("tmu1", 111, R8A7743_CLK_P),
+ DEF_MOD("3dg", 112, R8A7743_CLK_ZG),
+ DEF_MOD("2d-dmac", 115, R8A7743_CLK_ZS),
+ DEF_MOD("fdp1-1", 118, R8A7743_CLK_ZS),
+ DEF_MOD("fdp1-0", 119, R8A7743_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A7743_CLK_P),
+ DEF_MOD("tmu2", 122, R8A7743_CLK_P),
+ DEF_MOD("cmt0", 124, R8A7743_CLK_R),
+ DEF_MOD("tmu0", 125, R8A7743_CLK_CP),
+ DEF_MOD("vsp1du1", 127, R8A7743_CLK_ZS),
+ DEF_MOD("vsp1du0", 128, R8A7743_CLK_ZS),
+ DEF_MOD("vsps", 131, R8A7743_CLK_ZS),
+ DEF_MOD("scifa2", 202, R8A7743_CLK_MP),
+ DEF_MOD("scifa1", 203, R8A7743_CLK_MP),
+ DEF_MOD("scifa0", 204, R8A7743_CLK_MP),
+ DEF_MOD("msiof2", 205, R8A7743_CLK_MP),
+ DEF_MOD("scifb0", 206, R8A7743_CLK_MP),
+ DEF_MOD("scifb1", 207, R8A7743_CLK_MP),
+ DEF_MOD("msiof1", 208, R8A7743_CLK_MP),
+ DEF_MOD("scifb2", 216, R8A7743_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A7743_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A7743_CLK_ZS),
+ DEF_MOD("tpu0", 304, R8A7743_CLK_CP),
+ DEF_MOD("sdhi3", 311, R8A7743_CLK_SD3),
+ DEF_MOD("sdhi2", 312, R8A7743_CLK_SD2),
+ DEF_MOD("sdhi0", 314, R8A7743_CLK_SD0),
+ DEF_MOD("mmcif0", 315, R8A7743_CLK_MMC0),
+ DEF_MOD("iic0", 318, R8A7743_CLK_HP),
+ DEF_MOD("pciec", 319, R8A7743_CLK_MP),
+ DEF_MOD("iic1", 323, R8A7743_CLK_HP),
+ DEF_MOD("usb3.0", 328, R8A7743_CLK_MP),
+ DEF_MOD("cmt1", 329, R8A7743_CLK_R),
+ DEF_MOD("usbhs-dmac0", 330, R8A7743_CLK_HP),
+ DEF_MOD("usbhs-dmac1", 331, R8A7743_CLK_HP),
+ DEF_MOD("rwdt", 402, R8A7743_CLK_R),
+ DEF_MOD("irqc", 407, R8A7743_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A7743_CLK_ZS),
+ DEF_MOD("audio-dmac1", 501, R8A7743_CLK_HP),
+ DEF_MOD("audio-dmac0", 502, R8A7743_CLK_HP),
+ DEF_MOD("thermal", 522, CLK_EXTAL),
+ DEF_MOD("pwm", 523, R8A7743_CLK_P),
+ DEF_MOD("usb-ehci", 703, R8A7743_CLK_MP),
+ DEF_MOD("usbhs", 704, R8A7743_CLK_HP),
+ DEF_MOD("hscif2", 713, R8A7743_CLK_ZS),
+ DEF_MOD("scif5", 714, R8A7743_CLK_P),
+ DEF_MOD("scif4", 715, R8A7743_CLK_P),
+ DEF_MOD("hscif1", 716, R8A7743_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A7743_CLK_ZS),
+ DEF_MOD("scif3", 718, R8A7743_CLK_P),
+ DEF_MOD("scif2", 719, R8A7743_CLK_P),
+ DEF_MOD("scif1", 720, R8A7743_CLK_P),
+ DEF_MOD("scif0", 721, R8A7743_CLK_P),
+ DEF_MOD("du1", 723, R8A7743_CLK_ZX),
+ DEF_MOD("du0", 724, R8A7743_CLK_ZX),
+ DEF_MOD("lvds0", 726, R8A7743_CLK_ZX),
+ DEF_MOD("ipmmu-sgx", 800, R8A7743_CLK_ZX),
+ DEF_MOD("vin2", 809, R8A7743_CLK_ZG),
+ DEF_MOD("vin1", 810, R8A7743_CLK_ZG),
+ DEF_MOD("vin0", 811, R8A7743_CLK_ZG),
+ DEF_MOD("etheravb", 812, R8A7743_CLK_HP),
+ DEF_MOD("ether", 813, R8A7743_CLK_P),
+ DEF_MOD("sata1", 814, R8A7743_CLK_ZS),
+ DEF_MOD("sata0", 815, R8A7743_CLK_ZS),
+ DEF_MOD("gpio7", 904, R8A7743_CLK_CP),
+ DEF_MOD("gpio6", 905, R8A7743_CLK_CP),
+ DEF_MOD("gpio5", 907, R8A7743_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A7743_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A7743_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A7743_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A7743_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A7743_CLK_CP),
+ DEF_MOD("can1", 915, R8A7743_CLK_P),
+ DEF_MOD("can0", 916, R8A7743_CLK_P),
+ DEF_MOD("qspi_mod", 917, R8A7743_CLK_QSPI),
+ DEF_MOD("i2c5", 925, R8A7743_CLK_HP),
+ DEF_MOD("iicdvfs", 926, R8A7743_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A7743_CLK_HP),
+ DEF_MOD("i2c3", 928, R8A7743_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A7743_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A7743_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A7743_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A7743_CLK_P),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7743_CLK_P),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+ DEF_MOD("scifa3", 1106, R8A7743_CLK_MP),
+ DEF_MOD("scifa4", 1107, R8A7743_CLK_MP),
+ DEF_MOD("scifa5", 1108, R8A7743_CLK_MP),
+};
+
+static const unsigned int r8a7743_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz) *1 *1
+ *---------------------------------------------------
+ * 0 0 0 15 x172/2 x208/2 x106
+ * 0 0 1 15 x172/2 x208/2 x88
+ * 0 1 0 20 x130/2 x156/2 x80
+ * 0 1 1 20 x130/2 x156/2 x66
+ * 1 0 0 26 / 2 x200/2 x240/2 x122
+ * 1 0 1 26 / 2 x200/2 x240/2 x102
+ * 1 1 0 30 / 2 x172/2 x208/2 x106
+ * 1 1 1 30 / 2 x172/2 x208/2 x88
+ *
+ * *1 : Table 7.5a indicates VCO output (PLLx = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
+ (((md) & BIT(13)) >> 12) | \
+ (((md) & BIT(19)) >> 19))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+ /* EXTAL div PLL1 mult PLL3 mult */
+ { 1, 208, 106, },
+ { 1, 208, 88, },
+ { 1, 156, 80, },
+ { 1, 156, 66, },
+ { 2, 240, 122, },
+ { 2, 240, 102, },
+ { 2, 208, 106, },
+ { 2, 208, 88, },
+};
+
+static int __init r8a7743_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ struct device_node *np = dev->of_node;
+ unsigned int i;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ if (of_device_is_compatible(np, "renesas,r8a7744-cpg-mssr")) {
+ /* RZ/G1N uses a 1/5 divider for ZG */
+ for (i = 0; i < ARRAY_SIZE(r8a7743_core_clks); i++)
+ if (r8a7743_core_clks[i].id == R8A7743_CLK_ZG) {
+ r8a7743_core_clks[i].div = 5;
+ break;
+ }
+ }
+ return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7743_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7743_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7743_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7743_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7743_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7743_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7743_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7743_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7745-cpg-mssr.c b/drivers/clk/renesas/r8a7745-cpg-mssr.c
new file mode 100644
index 000000000..dc4a64e8d
--- /dev/null
+++ b/drivers/clk/renesas/r8a7745-cpg-mssr.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7745 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7745-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7745_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_USB_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7745_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("sdh", R8A7745_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
+ DEF_BASE("sd0", R8A7745_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
+ DEF_BASE("qspi", R8A7745_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+ DEF_BASE("rcan", R8A7745_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+ DEF_FIXED("z2", R8A7745_CLK_Z2, CLK_PLL0, 1, 1),
+ DEF_FIXED("zg", R8A7745_CLK_ZG, CLK_PLL1, 6, 1),
+ DEF_FIXED("zx", R8A7745_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A7745_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A7745_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("b", R8A7745_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("lb", R8A7745_CLK_LB, CLK_PLL1, 24, 1),
+ DEF_FIXED("p", R8A7745_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A7745_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("cp", R8A7745_CLK_CP, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A7745_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("zb3", R8A7745_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("zb3d2", R8A7745_CLK_ZB3D2, CLK_PLL3, 8, 1),
+ DEF_FIXED("ddr", R8A7745_CLK_DDR, CLK_PLL3, 8, 1),
+ DEF_FIXED("mp", R8A7745_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cpex", R8A7745_CLK_CPEX, CLK_EXTAL, 2, 1),
+ DEF_FIXED("r", R8A7745_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A7745_CLK_OSC, CLK_PLL1, 12288, 1),
+
+ DEF_DIV6P1("sd2", R8A7745_CLK_SD2, CLK_PLL1_DIV2, 0x078),
+ DEF_DIV6P1("sd3", R8A7745_CLK_SD3, CLK_PLL1_DIV2, 0x26c),
+ DEF_DIV6P1("mmc0", R8A7745_CLK_MMC0, CLK_PLL1_DIV2, 0x240),
+};
+
+static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A7745_CLK_MP),
+ DEF_MOD("vcp0", 101, R8A7745_CLK_ZS),
+ DEF_MOD("vpc0", 103, R8A7745_CLK_ZS),
+ DEF_MOD("tmu1", 111, R8A7745_CLK_P),
+ DEF_MOD("3dg", 112, R8A7745_CLK_ZG),
+ DEF_MOD("2d-dmac", 115, R8A7745_CLK_ZS),
+ DEF_MOD("fdp1-0", 119, R8A7745_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A7745_CLK_P),
+ DEF_MOD("tmu2", 122, R8A7745_CLK_P),
+ DEF_MOD("cmt0", 124, R8A7745_CLK_R),
+ DEF_MOD("tmu0", 125, R8A7745_CLK_CP),
+ DEF_MOD("vsp1du0", 128, R8A7745_CLK_ZS),
+ DEF_MOD("vsps", 131, R8A7745_CLK_ZS),
+ DEF_MOD("scifa2", 202, R8A7745_CLK_MP),
+ DEF_MOD("scifa1", 203, R8A7745_CLK_MP),
+ DEF_MOD("scifa0", 204, R8A7745_CLK_MP),
+ DEF_MOD("msiof2", 205, R8A7745_CLK_MP),
+ DEF_MOD("scifb0", 206, R8A7745_CLK_MP),
+ DEF_MOD("scifb1", 207, R8A7745_CLK_MP),
+ DEF_MOD("msiof1", 208, R8A7745_CLK_MP),
+ DEF_MOD("scifb2", 216, R8A7745_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A7745_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A7745_CLK_ZS),
+ DEF_MOD("tpu0", 304, R8A7745_CLK_CP),
+ DEF_MOD("sdhi3", 311, R8A7745_CLK_SD3),
+ DEF_MOD("sdhi2", 312, R8A7745_CLK_SD2),
+ DEF_MOD("sdhi0", 314, R8A7745_CLK_SD0),
+ DEF_MOD("mmcif0", 315, R8A7745_CLK_MMC0),
+ DEF_MOD("iic0", 318, R8A7745_CLK_HP),
+ DEF_MOD("iic1", 323, R8A7745_CLK_HP),
+ DEF_MOD("cmt1", 329, R8A7745_CLK_R),
+ DEF_MOD("usbhs-dmac0", 330, R8A7745_CLK_HP),
+ DEF_MOD("usbhs-dmac1", 331, R8A7745_CLK_HP),
+ DEF_MOD("rwdt", 402, R8A7745_CLK_R),
+ DEF_MOD("irqc", 407, R8A7745_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A7745_CLK_ZS),
+ DEF_MOD("audio-dmac0", 502, R8A7745_CLK_HP),
+ DEF_MOD("pwm", 523, R8A7745_CLK_P),
+ DEF_MOD("usb-ehci", 703, R8A7745_CLK_MP),
+ DEF_MOD("usbhs", 704, R8A7745_CLK_HP),
+ DEF_MOD("hscif2", 713, R8A7745_CLK_ZS),
+ DEF_MOD("scif5", 714, R8A7745_CLK_P),
+ DEF_MOD("scif4", 715, R8A7745_CLK_P),
+ DEF_MOD("hscif1", 716, R8A7745_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A7745_CLK_ZS),
+ DEF_MOD("scif3", 718, R8A7745_CLK_P),
+ DEF_MOD("scif2", 719, R8A7745_CLK_P),
+ DEF_MOD("scif1", 720, R8A7745_CLK_P),
+ DEF_MOD("scif0", 721, R8A7745_CLK_P),
+ DEF_MOD("du1", 723, R8A7745_CLK_ZX),
+ DEF_MOD("du0", 724, R8A7745_CLK_ZX),
+ DEF_MOD("ipmmu-sgx", 800, R8A7745_CLK_ZX),
+ DEF_MOD("vin1", 810, R8A7745_CLK_ZG),
+ DEF_MOD("vin0", 811, R8A7745_CLK_ZG),
+ DEF_MOD("etheravb", 812, R8A7745_CLK_HP),
+ DEF_MOD("ether", 813, R8A7745_CLK_P),
+ DEF_MOD("gpio6", 905, R8A7745_CLK_CP),
+ DEF_MOD("gpio5", 907, R8A7745_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A7745_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A7745_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A7745_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A7745_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A7745_CLK_CP),
+ DEF_MOD("can1", 915, R8A7745_CLK_P),
+ DEF_MOD("can0", 916, R8A7745_CLK_P),
+ DEF_MOD("qspi_mod", 917, R8A7745_CLK_QSPI),
+ DEF_MOD("i2c5", 925, R8A7745_CLK_HP),
+ DEF_MOD("i2c4", 927, R8A7745_CLK_HP),
+ DEF_MOD("i2c3", 928, R8A7745_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A7745_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A7745_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A7745_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A7745_CLK_P),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7745_CLK_P),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scifa3", 1106, R8A7745_CLK_MP),
+ DEF_MOD("scifa4", 1107, R8A7745_CLK_MP),
+ DEF_MOD("scifa5", 1108, R8A7745_CLK_MP),
+};
+
+static const unsigned int r8a7745_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz) *1 *2
+ *---------------------------------------------------
+ * 0 0 1 15 x200/3 x208/2 x88
+ * 0 1 1 20 x150/3 x156/2 x66
+ * 1 0 1 26 / 2 x230/3 x240/2 x102
+ * 1 1 1 30 / 2 x200/3 x208/2 x88
+ *
+ * *1 : Table 7.5b indicates VCO output (PLL0 = VCO/3)
+ * *2 : Table 7.5b indicates VCO output (PLL1 = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
+ (((md) & BIT(13)) >> 13))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+ /* EXTAL div PLL1 mult PLL3 mult PLL0 mult */
+ { 1, 208, 88, 200 },
+ { 1, 156, 66, 150 },
+ { 2, 240, 102, 230 },
+ { 2, 208, 88, 200 },
+};
+
+static int __init r8a7745_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen2_cpg_init(cpg_pll_config, 3, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7745_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7745_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7745_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7745_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7745_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7745_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7745_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7745_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a77470-cpg-mssr.c b/drivers/clk/renesas/r8a77470-cpg-mssr.c
new file mode 100644
index 000000000..f3d6e6501
--- /dev/null
+++ b/drivers/clk/renesas/r8a77470-cpg-mssr.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a77470 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a77470-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A77470_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_USB_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a77470_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("sdh", R8A77470_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
+ DEF_BASE("sd0", R8A77470_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
+ DEF_BASE("sd1", R8A77470_CLK_SD1, CLK_TYPE_GEN2_SD1, CLK_PLL1),
+ DEF_BASE("qspi", R8A77470_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+ DEF_BASE("rcan", R8A77470_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+ DEF_FIXED("z2", R8A77470_CLK_Z2, CLK_PLL0, 1, 1),
+ DEF_FIXED("zx", R8A77470_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A77470_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A77470_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("b", R8A77470_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("lb", R8A77470_CLK_LB, CLK_PLL1, 24, 1),
+ DEF_FIXED("p", R8A77470_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A77470_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("cp", R8A77470_CLK_CP, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A77470_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("zb3", R8A77470_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("mp", R8A77470_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cpex", R8A77470_CLK_CPEX, CLK_EXTAL, 2, 1),
+ DEF_FIXED("r", R8A77470_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A77470_CLK_OSC, CLK_PLL1, 12288, 1),
+
+ DEF_DIV6P1("sd2", R8A77470_CLK_SD2, CLK_PLL1_DIV2, 0x078),
+};
+
+static const struct mssr_mod_clk r8a77470_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A77470_CLK_MP),
+ DEF_MOD("vcp0", 101, R8A77470_CLK_ZS),
+ DEF_MOD("vpc0", 103, R8A77470_CLK_ZS),
+ DEF_MOD("tmu1", 111, R8A77470_CLK_P),
+ DEF_MOD("3dg", 112, R8A77470_CLK_ZS),
+ DEF_MOD("2d-dmac", 115, R8A77470_CLK_ZS),
+ DEF_MOD("fdp1-0", 119, R8A77470_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A77470_CLK_P),
+ DEF_MOD("tmu2", 122, R8A77470_CLK_P),
+ DEF_MOD("cmt0", 124, R8A77470_CLK_R),
+ DEF_MOD("vsp1du0", 128, R8A77470_CLK_ZS),
+ DEF_MOD("vsps", 131, R8A77470_CLK_ZS),
+ DEF_MOD("msiof2", 205, R8A77470_CLK_MP),
+ DEF_MOD("msiof1", 208, R8A77470_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A77470_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A77470_CLK_ZS),
+ DEF_MOD("sdhi2", 312, R8A77470_CLK_SD2),
+ DEF_MOD("sdhi1", 313, R8A77470_CLK_SD1),
+ DEF_MOD("sdhi0", 314, R8A77470_CLK_SD0),
+ DEF_MOD("usbhs-dmac0-ch1", 326, R8A77470_CLK_HP),
+ DEF_MOD("usbhs-dmac1-ch1", 327, R8A77470_CLK_HP),
+ DEF_MOD("cmt1", 329, R8A77470_CLK_R),
+ DEF_MOD("usbhs-dmac0-ch0", 330, R8A77470_CLK_HP),
+ DEF_MOD("usbhs-dmac1-ch0", 331, R8A77470_CLK_HP),
+ DEF_MOD("rwdt", 402, R8A77470_CLK_R),
+ DEF_MOD("irqc", 407, R8A77470_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A77470_CLK_ZS),
+ DEF_MOD("audio-dmac0", 502, R8A77470_CLK_HP),
+ DEF_MOD("pwm", 523, R8A77470_CLK_P),
+ DEF_MOD("usb-ehci-0", 703, R8A77470_CLK_MP),
+ DEF_MOD("usbhs-0", 704, R8A77470_CLK_HP),
+ DEF_MOD("usb-ehci-1", 705, R8A77470_CLK_MP),
+ DEF_MOD("usbhs-1", 706, R8A77470_CLK_HP),
+ DEF_MOD("hscif2", 713, R8A77470_CLK_ZS),
+ DEF_MOD("scif5", 714, R8A77470_CLK_P),
+ DEF_MOD("scif4", 715, R8A77470_CLK_P),
+ DEF_MOD("hscif1", 716, R8A77470_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A77470_CLK_ZS),
+ DEF_MOD("scif3", 718, R8A77470_CLK_P),
+ DEF_MOD("scif2", 719, R8A77470_CLK_P),
+ DEF_MOD("scif1", 720, R8A77470_CLK_P),
+ DEF_MOD("scif0", 721, R8A77470_CLK_P),
+ DEF_MOD("du1", 723, R8A77470_CLK_ZX),
+ DEF_MOD("du0", 724, R8A77470_CLK_ZX),
+ DEF_MOD("ipmmu-sgx", 800, R8A77470_CLK_ZX),
+ DEF_MOD("etheravb", 812, R8A77470_CLK_HP),
+ DEF_MOD("ether", 813, R8A77470_CLK_P),
+ DEF_MOD("gpio5", 907, R8A77470_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A77470_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A77470_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A77470_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A77470_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A77470_CLK_CP),
+ DEF_MOD("can1", 915, R8A77470_CLK_P),
+ DEF_MOD("can0", 916, R8A77470_CLK_P),
+ DEF_MOD("qspi_mod-1", 917, R8A77470_CLK_QSPI),
+ DEF_MOD("qspi_mod-0", 918, R8A77470_CLK_QSPI),
+ DEF_MOD("i2c4", 927, R8A77470_CLK_HP),
+ DEF_MOD("i2c3", 928, R8A77470_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A77470_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A77470_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A77470_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A77470_CLK_P),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A77470_CLK_P),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a77470_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 (MHz) *1 *2
+ *---------------------------------------------------
+ * 0 0 20 x80 x78 x50
+ * 0 1 26 x60 x60 x56
+ * 1 0 Prohibited setting
+ * 1 1 30 x52 x52 x50
+ *
+ * *1 : Table 7.4 indicates VCO output (PLL0 = VCO)
+ * *2 : Table 7.4 indicates VCO output (PLL1 = VCO)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
+ (((md) & BIT(13)) >> 13))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[4] __initconst = {
+ /* EXTAL div PLL1 mult x2 PLL3 mult */
+ { 1, 156, 50, },
+ { 1, 120, 56, },
+ { /* Invalid*/ },
+ { 1, 104, 50, },
+};
+
+static int __init r8a77470_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a77470_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a77470_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a77470_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a77470_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a77470_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a77470_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a77470_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a77470_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c
new file mode 100644
index 000000000..aba043f99
--- /dev/null
+++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c
@@ -0,0 +1,346 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a774a1 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ *
+ * Based on r8a7796-cpg-mssr.c
+ *
+ * Copyright (C) 2016 Glider bvba
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a774a1-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A774A1_CLK_CANFD,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL3,
+ CLK_PLL4,
+ CLK_PLL1_DIV2,
+ CLK_PLL1_DIV4,
+ CLK_S0,
+ CLK_S1,
+ CLK_S2,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_RINT,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+ DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1),
+ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
+
+ DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32),
+
+ /* Core Clock Outputs */
+ DEF_GEN3_Z("z", R8A774A1_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8),
+ DEF_GEN3_Z("z2", R8A774A1_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL2, 2, 0),
+ DEF_GEN3_Z("zg", R8A774A1_CLK_ZG, CLK_TYPE_GEN3_ZG, CLK_PLL4, 4, 24),
+ DEF_FIXED("ztr", R8A774A1_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED("ztrd2", R8A774A1_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+ DEF_FIXED("zt", R8A774A1_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED("zx", R8A774A1_CLK_ZX, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED("s0d1", R8A774A1_CLK_S0D1, CLK_S0, 1, 1),
+ DEF_FIXED("s0d2", R8A774A1_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A774A1_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A774A1_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6", R8A774A1_CLK_S0D6, CLK_S0, 6, 1),
+ DEF_FIXED("s0d8", R8A774A1_CLK_S0D8, CLK_S0, 8, 1),
+ DEF_FIXED("s0d12", R8A774A1_CLK_S0D12, CLK_S0, 12, 1),
+ DEF_FIXED("s1d2", R8A774A1_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A774A1_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s2d1", R8A774A1_CLK_S2D1, CLK_S2, 1, 1),
+ DEF_FIXED("s2d2", R8A774A1_CLK_S2D2, CLK_S2, 2, 1),
+ DEF_FIXED("s2d4", R8A774A1_CLK_S2D4, CLK_S2, 4, 1),
+ DEF_FIXED("s3d1", R8A774A1_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A774A1_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A774A1_CLK_S3D4, CLK_S3, 4, 1),
+
+ DEF_GEN3_SDH("sd0h", R8A774A1_CLK_SD0H, CLK_SDSRC, 0x074),
+ DEF_GEN3_SDH("sd1h", R8A774A1_CLK_SD1H, CLK_SDSRC, 0x078),
+ DEF_GEN3_SDH("sd2h", R8A774A1_CLK_SD2H, CLK_SDSRC, 0x268),
+ DEF_GEN3_SDH("sd3h", R8A774A1_CLK_SD3H, CLK_SDSRC, 0x26c),
+ DEF_GEN3_SD("sd0", R8A774A1_CLK_SD0, R8A774A1_CLK_SD0H, 0x074),
+ DEF_GEN3_SD("sd1", R8A774A1_CLK_SD1, R8A774A1_CLK_SD1H, 0x078),
+ DEF_GEN3_SD("sd2", R8A774A1_CLK_SD2, R8A774A1_CLK_SD2H, 0x268),
+ DEF_GEN3_SD("sd3", R8A774A1_CLK_SD3, R8A774A1_CLK_SD3H, 0x26c),
+
+ DEF_BASE("rpc", R8A774A1_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A774A1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A774A1_CLK_RPC),
+
+ DEF_FIXED("cl", R8A774A1_CLK_CL, CLK_PLL1_DIV2, 48, 1),
+ DEF_FIXED("cp", R8A774A1_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A774A1_CLK_CPEX, CLK_EXTAL, 2, 1),
+
+ DEF_DIV6P1("canfd", R8A774A1_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+ DEF_DIV6P1("csi0", R8A774A1_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
+ DEF_DIV6P1("mso", R8A774A1_CLK_MSO, CLK_PLL1_DIV4, 0x014),
+ DEF_DIV6P1("hdmi", R8A774A1_CLK_HDMI, CLK_PLL1_DIV4, 0x250),
+
+ DEF_GEN3_OSC("osc", R8A774A1_CLK_OSC, CLK_EXTAL, 8),
+
+ DEF_BASE("r", R8A774A1_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
+};
+
+static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
+ DEF_MOD("3dge", 112, R8A774A1_CLK_ZG),
+ DEF_MOD("tmu4", 121, R8A774A1_CLK_S0D6),
+ DEF_MOD("tmu3", 122, R8A774A1_CLK_S3D2),
+ DEF_MOD("tmu2", 123, R8A774A1_CLK_S3D2),
+ DEF_MOD("tmu1", 124, R8A774A1_CLK_S3D2),
+ DEF_MOD("tmu0", 125, R8A774A1_CLK_CP),
+ DEF_MOD("fdp1-0", 119, R8A774A1_CLK_S0D1),
+ DEF_MOD("scif5", 202, R8A774A1_CLK_S3D4),
+ DEF_MOD("scif4", 203, R8A774A1_CLK_S3D4),
+ DEF_MOD("scif3", 204, R8A774A1_CLK_S3D4),
+ DEF_MOD("scif1", 206, R8A774A1_CLK_S3D4),
+ DEF_MOD("scif0", 207, R8A774A1_CLK_S3D4),
+ DEF_MOD("msiof3", 208, R8A774A1_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A774A1_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A774A1_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A774A1_CLK_MSO),
+ DEF_MOD("sys-dmac2", 217, R8A774A1_CLK_S3D1),
+ DEF_MOD("sys-dmac1", 218, R8A774A1_CLK_S3D1),
+ DEF_MOD("sys-dmac0", 219, R8A774A1_CLK_S0D3),
+ DEF_MOD("cmt3", 300, R8A774A1_CLK_R),
+ DEF_MOD("cmt2", 301, R8A774A1_CLK_R),
+ DEF_MOD("cmt1", 302, R8A774A1_CLK_R),
+ DEF_MOD("cmt0", 303, R8A774A1_CLK_R),
+ DEF_MOD("scif2", 310, R8A774A1_CLK_S3D4),
+ DEF_MOD("sdif3", 311, R8A774A1_CLK_SD3),
+ DEF_MOD("sdif2", 312, R8A774A1_CLK_SD2),
+ DEF_MOD("sdif1", 313, R8A774A1_CLK_SD1),
+ DEF_MOD("sdif0", 314, R8A774A1_CLK_SD0),
+ DEF_MOD("pcie1", 318, R8A774A1_CLK_S3D1),
+ DEF_MOD("pcie0", 319, R8A774A1_CLK_S3D1),
+ DEF_MOD("usb3-if0", 328, R8A774A1_CLK_S3D1),
+ DEF_MOD("usb-dmac0", 330, R8A774A1_CLK_S3D1),
+ DEF_MOD("usb-dmac1", 331, R8A774A1_CLK_S3D1),
+ DEF_MOD("rwdt", 402, R8A774A1_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A774A1_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A774A1_CLK_S0D3),
+ DEF_MOD("audmac1", 501, R8A774A1_CLK_S1D2),
+ DEF_MOD("audmac0", 502, R8A774A1_CLK_S1D2),
+ DEF_MOD("hscif4", 516, R8A774A1_CLK_S3D1),
+ DEF_MOD("hscif3", 517, R8A774A1_CLK_S3D1),
+ DEF_MOD("hscif2", 518, R8A774A1_CLK_S3D1),
+ DEF_MOD("hscif1", 519, R8A774A1_CLK_S3D1),
+ DEF_MOD("hscif0", 520, R8A774A1_CLK_S3D1),
+ DEF_MOD("thermal", 522, R8A774A1_CLK_CP),
+ DEF_MOD("pwm", 523, R8A774A1_CLK_S0D12),
+ DEF_MOD("fcpvd2", 601, R8A774A1_CLK_S0D2),
+ DEF_MOD("fcpvd1", 602, R8A774A1_CLK_S0D2),
+ DEF_MOD("fcpvd0", 603, R8A774A1_CLK_S0D2),
+ DEF_MOD("fcpvb0", 607, R8A774A1_CLK_S0D1),
+ DEF_MOD("fcpvi0", 611, R8A774A1_CLK_S0D1),
+ DEF_MOD("fcpf0", 615, R8A774A1_CLK_S0D1),
+ DEF_MOD("fcpci0", 617, R8A774A1_CLK_S0D2),
+ DEF_MOD("fcpcs", 619, R8A774A1_CLK_S0D2),
+ DEF_MOD("vspd2", 621, R8A774A1_CLK_S0D2),
+ DEF_MOD("vspd1", 622, R8A774A1_CLK_S0D2),
+ DEF_MOD("vspd0", 623, R8A774A1_CLK_S0D2),
+ DEF_MOD("vspb", 626, R8A774A1_CLK_S0D1),
+ DEF_MOD("vspi0", 631, R8A774A1_CLK_S0D1),
+ DEF_MOD("ehci1", 702, R8A774A1_CLK_S3D2),
+ DEF_MOD("ehci0", 703, R8A774A1_CLK_S3D2),
+ DEF_MOD("hsusb", 704, R8A774A1_CLK_S3D2),
+ DEF_MOD("csi20", 714, R8A774A1_CLK_CSI0),
+ DEF_MOD("csi40", 716, R8A774A1_CLK_CSI0),
+ DEF_MOD("du2", 722, R8A774A1_CLK_S2D1),
+ DEF_MOD("du1", 723, R8A774A1_CLK_S2D1),
+ DEF_MOD("du0", 724, R8A774A1_CLK_S2D1),
+ DEF_MOD("lvds", 727, R8A774A1_CLK_S2D1),
+ DEF_MOD("hdmi0", 729, R8A774A1_CLK_HDMI),
+ DEF_MOD("vin7", 804, R8A774A1_CLK_S0D2),
+ DEF_MOD("vin6", 805, R8A774A1_CLK_S0D2),
+ DEF_MOD("vin5", 806, R8A774A1_CLK_S0D2),
+ DEF_MOD("vin4", 807, R8A774A1_CLK_S0D2),
+ DEF_MOD("vin3", 808, R8A774A1_CLK_S0D2),
+ DEF_MOD("vin2", 809, R8A774A1_CLK_S0D2),
+ DEF_MOD("vin1", 810, R8A774A1_CLK_S0D2),
+ DEF_MOD("vin0", 811, R8A774A1_CLK_S0D2),
+ DEF_MOD("etheravb", 812, R8A774A1_CLK_S0D6),
+ DEF_MOD("gpio7", 905, R8A774A1_CLK_S3D4),
+ DEF_MOD("gpio6", 906, R8A774A1_CLK_S3D4),
+ DEF_MOD("gpio5", 907, R8A774A1_CLK_S3D4),
+ DEF_MOD("gpio4", 908, R8A774A1_CLK_S3D4),
+ DEF_MOD("gpio3", 909, R8A774A1_CLK_S3D4),
+ DEF_MOD("gpio2", 910, R8A774A1_CLK_S3D4),
+ DEF_MOD("gpio1", 911, R8A774A1_CLK_S3D4),
+ DEF_MOD("gpio0", 912, R8A774A1_CLK_S3D4),
+ DEF_MOD("can-fd", 914, R8A774A1_CLK_S3D2),
+ DEF_MOD("can-if1", 915, R8A774A1_CLK_S3D4),
+ DEF_MOD("can-if0", 916, R8A774A1_CLK_S3D4),
+ DEF_MOD("rpc-if", 917, R8A774A1_CLK_RPCD2),
+ DEF_MOD("i2c6", 918, R8A774A1_CLK_S0D6),
+ DEF_MOD("i2c5", 919, R8A774A1_CLK_S0D6),
+ DEF_MOD("adg", 922, R8A774A1_CLK_S0D4),
+ DEF_MOD("iic-pmic", 926, R8A774A1_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A774A1_CLK_S0D6),
+ DEF_MOD("i2c3", 928, R8A774A1_CLK_S0D6),
+ DEF_MOD("i2c2", 929, R8A774A1_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A774A1_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A774A1_CLK_S3D2),
+ DEF_MOD("ssi-all", 1005, R8A774A1_CLK_S3D4),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A774A1_CLK_S3D4),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a774a1_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4 OSC
+ * 14 13 19 17 (MHz)
+ *-------------------------------------------------------------------------
+ * 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144 /16
+ * 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144 /16
+ * 0 0 1 0 Prohibited setting
+ * 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144 /16
+ * 0 1 0 0 20 x 1 x150 x160 x120 x160 x120 /19
+ * 0 1 0 1 20 x 1 x150 x160 x120 x106 x120 /19
+ * 0 1 1 0 Prohibited setting
+ * 0 1 1 1 20 x 1 x150 x160 x120 x160 x120 /19
+ * 1 0 0 0 25 x 1 x120 x128 x96 x128 x96 /24
+ * 1 0 0 1 25 x 1 x120 x128 x96 x84 x96 /24
+ * 1 0 1 0 Prohibited setting
+ * 1 0 1 1 25 x 1 x120 x128 x96 x128 x96 /24
+ * 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144 /32
+ * 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144 /32
+ * 1 1 1 0 Prohibited setting
+ * 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144 /32
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \
+ (((md) & BIT(13)) >> 11) | \
+ (((md) & BIT(19)) >> 18) | \
+ (((md) & BIT(17)) >> 17))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 192, 1, 128, 1, 16, },
+ { 0, /* Prohibited setting */ },
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 160, 1, 106, 1, 19, },
+ { 0, /* Prohibited setting */ },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 128, 1, 128, 1, 24, },
+ { 1, 128, 1, 84, 1, 24, },
+ { 0, /* Prohibited setting */ },
+ { 1, 128, 1, 128, 1, 24, },
+ { 2, 192, 1, 192, 1, 32, },
+ { 2, 192, 1, 128, 1, 32, },
+ { 0, /* Prohibited setting */ },
+ { 2, 192, 1, 192, 1, 32, },
+};
+
+static int __init r8a774a1_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+ if (!cpg_pll_config->extal_div) {
+ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+ return -EINVAL;
+ }
+
+ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a774a1_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a774a1_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a774a1_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a774a1_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a774a1_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a774a1_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a774a1_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a774a1_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a774b1-cpg-mssr.c b/drivers/clk/renesas/r8a774b1-cpg-mssr.c
new file mode 100644
index 000000000..a3244e76f
--- /dev/null
+++ b/drivers/clk/renesas/r8a774b1-cpg-mssr.c
@@ -0,0 +1,342 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a774b1 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ *
+ * Based on r8a7796-cpg-mssr.c
+ *
+ * Copyright (C) 2016 Glider bvba
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a774b1-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A774B1_CLK_CANFD,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL4,
+ CLK_PLL1_DIV2,
+ CLK_PLL1_DIV4,
+ CLK_S0,
+ CLK_S1,
+ CLK_S2,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_RINT,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a774b1_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+ DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1),
+ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
+
+ DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32),
+
+ /* Core Clock Outputs */
+ DEF_GEN3_Z("z", R8A774B1_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8),
+ DEF_GEN3_Z("zg", R8A774B1_CLK_ZG, CLK_TYPE_GEN3_ZG, CLK_PLL4, 4, 24),
+ DEF_FIXED("ztr", R8A774B1_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED("ztrd2", R8A774B1_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+ DEF_FIXED("zt", R8A774B1_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED("zx", R8A774B1_CLK_ZX, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED("s0d1", R8A774B1_CLK_S0D1, CLK_S0, 1, 1),
+ DEF_FIXED("s0d2", R8A774B1_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A774B1_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A774B1_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6", R8A774B1_CLK_S0D6, CLK_S0, 6, 1),
+ DEF_FIXED("s0d8", R8A774B1_CLK_S0D8, CLK_S0, 8, 1),
+ DEF_FIXED("s0d12", R8A774B1_CLK_S0D12, CLK_S0, 12, 1),
+ DEF_FIXED("s1d2", R8A774B1_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A774B1_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s2d1", R8A774B1_CLK_S2D1, CLK_S2, 1, 1),
+ DEF_FIXED("s2d2", R8A774B1_CLK_S2D2, CLK_S2, 2, 1),
+ DEF_FIXED("s2d4", R8A774B1_CLK_S2D4, CLK_S2, 4, 1),
+ DEF_FIXED("s3d1", R8A774B1_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A774B1_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A774B1_CLK_S3D4, CLK_S3, 4, 1),
+
+ DEF_GEN3_SDH("sd0h", R8A774B1_CLK_SD0H, CLK_SDSRC, 0x074),
+ DEF_GEN3_SDH("sd1h", R8A774B1_CLK_SD1H, CLK_SDSRC, 0x078),
+ DEF_GEN3_SDH("sd2h", R8A774B1_CLK_SD2H, CLK_SDSRC, 0x268),
+ DEF_GEN3_SDH("sd3h", R8A774B1_CLK_SD3H, CLK_SDSRC, 0x26c),
+ DEF_GEN3_SD("sd0", R8A774B1_CLK_SD0, R8A774B1_CLK_SD0H, 0x074),
+ DEF_GEN3_SD("sd1", R8A774B1_CLK_SD1, R8A774B1_CLK_SD1H, 0x078),
+ DEF_GEN3_SD("sd2", R8A774B1_CLK_SD2, R8A774B1_CLK_SD2H, 0x268),
+ DEF_GEN3_SD("sd3", R8A774B1_CLK_SD3, R8A774B1_CLK_SD3H, 0x26c),
+
+ DEF_BASE("rpc", R8A774B1_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A774B1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A774B1_CLK_RPC),
+
+ DEF_FIXED("cl", R8A774B1_CLK_CL, CLK_PLL1_DIV2, 48, 1),
+ DEF_FIXED("cp", R8A774B1_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A774B1_CLK_CPEX, CLK_EXTAL, 2, 1),
+
+ DEF_DIV6P1("canfd", R8A774B1_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+ DEF_DIV6P1("csi0", R8A774B1_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
+ DEF_DIV6P1("mso", R8A774B1_CLK_MSO, CLK_PLL1_DIV4, 0x014),
+ DEF_DIV6P1("hdmi", R8A774B1_CLK_HDMI, CLK_PLL1_DIV4, 0x250),
+
+ DEF_GEN3_OSC("osc", R8A774B1_CLK_OSC, CLK_EXTAL, 8),
+
+ DEF_BASE("r", R8A774B1_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
+};
+
+static const struct mssr_mod_clk r8a774b1_mod_clks[] __initconst = {
+ DEF_MOD("3dge", 112, R8A774B1_CLK_ZG),
+ DEF_MOD("tmu4", 121, R8A774B1_CLK_S0D6),
+ DEF_MOD("tmu3", 122, R8A774B1_CLK_S3D2),
+ DEF_MOD("tmu2", 123, R8A774B1_CLK_S3D2),
+ DEF_MOD("tmu1", 124, R8A774B1_CLK_S3D2),
+ DEF_MOD("tmu0", 125, R8A774B1_CLK_CP),
+ DEF_MOD("fdp1-0", 119, R8A774B1_CLK_S0D1),
+ DEF_MOD("scif5", 202, R8A774B1_CLK_S3D4),
+ DEF_MOD("scif4", 203, R8A774B1_CLK_S3D4),
+ DEF_MOD("scif3", 204, R8A774B1_CLK_S3D4),
+ DEF_MOD("scif1", 206, R8A774B1_CLK_S3D4),
+ DEF_MOD("scif0", 207, R8A774B1_CLK_S3D4),
+ DEF_MOD("msiof3", 208, R8A774B1_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A774B1_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A774B1_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A774B1_CLK_MSO),
+ DEF_MOD("sys-dmac2", 217, R8A774B1_CLK_S3D1),
+ DEF_MOD("sys-dmac1", 218, R8A774B1_CLK_S3D1),
+ DEF_MOD("sys-dmac0", 219, R8A774B1_CLK_S0D3),
+ DEF_MOD("cmt3", 300, R8A774B1_CLK_R),
+ DEF_MOD("cmt2", 301, R8A774B1_CLK_R),
+ DEF_MOD("cmt1", 302, R8A774B1_CLK_R),
+ DEF_MOD("cmt0", 303, R8A774B1_CLK_R),
+ DEF_MOD("tpu0", 304, R8A774B1_CLK_S3D4),
+ DEF_MOD("scif2", 310, R8A774B1_CLK_S3D4),
+ DEF_MOD("sdif3", 311, R8A774B1_CLK_SD3),
+ DEF_MOD("sdif2", 312, R8A774B1_CLK_SD2),
+ DEF_MOD("sdif1", 313, R8A774B1_CLK_SD1),
+ DEF_MOD("sdif0", 314, R8A774B1_CLK_SD0),
+ DEF_MOD("pcie1", 318, R8A774B1_CLK_S3D1),
+ DEF_MOD("pcie0", 319, R8A774B1_CLK_S3D1),
+ DEF_MOD("usb3-if0", 328, R8A774B1_CLK_S3D1),
+ DEF_MOD("usb-dmac0", 330, R8A774B1_CLK_S3D1),
+ DEF_MOD("usb-dmac1", 331, R8A774B1_CLK_S3D1),
+ DEF_MOD("rwdt", 402, R8A774B1_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A774B1_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A774B1_CLK_S0D3),
+ DEF_MOD("audmac1", 501, R8A774B1_CLK_S1D2),
+ DEF_MOD("audmac0", 502, R8A774B1_CLK_S1D2),
+ DEF_MOD("hscif4", 516, R8A774B1_CLK_S3D1),
+ DEF_MOD("hscif3", 517, R8A774B1_CLK_S3D1),
+ DEF_MOD("hscif2", 518, R8A774B1_CLK_S3D1),
+ DEF_MOD("hscif1", 519, R8A774B1_CLK_S3D1),
+ DEF_MOD("hscif0", 520, R8A774B1_CLK_S3D1),
+ DEF_MOD("thermal", 522, R8A774B1_CLK_CP),
+ DEF_MOD("pwm", 523, R8A774B1_CLK_S0D12),
+ DEF_MOD("fcpvd1", 602, R8A774B1_CLK_S0D2),
+ DEF_MOD("fcpvd0", 603, R8A774B1_CLK_S0D2),
+ DEF_MOD("fcpvb0", 607, R8A774B1_CLK_S0D1),
+ DEF_MOD("fcpvi0", 611, R8A774B1_CLK_S0D1),
+ DEF_MOD("fcpf0", 615, R8A774B1_CLK_S0D1),
+ DEF_MOD("fcpcs", 619, R8A774B1_CLK_S0D2),
+ DEF_MOD("vspd1", 622, R8A774B1_CLK_S0D2),
+ DEF_MOD("vspd0", 623, R8A774B1_CLK_S0D2),
+ DEF_MOD("vspb", 626, R8A774B1_CLK_S0D1),
+ DEF_MOD("vspi0", 631, R8A774B1_CLK_S0D1),
+ DEF_MOD("ehci1", 702, R8A774B1_CLK_S3D2),
+ DEF_MOD("ehci0", 703, R8A774B1_CLK_S3D2),
+ DEF_MOD("hsusb", 704, R8A774B1_CLK_S3D2),
+ DEF_MOD("csi20", 714, R8A774B1_CLK_CSI0),
+ DEF_MOD("csi40", 716, R8A774B1_CLK_CSI0),
+ DEF_MOD("du3", 721, R8A774B1_CLK_S2D1),
+ DEF_MOD("du1", 723, R8A774B1_CLK_S2D1),
+ DEF_MOD("du0", 724, R8A774B1_CLK_S2D1),
+ DEF_MOD("lvds", 727, R8A774B1_CLK_S2D1),
+ DEF_MOD("hdmi0", 729, R8A774B1_CLK_HDMI),
+ DEF_MOD("vin7", 804, R8A774B1_CLK_S0D2),
+ DEF_MOD("vin6", 805, R8A774B1_CLK_S0D2),
+ DEF_MOD("vin5", 806, R8A774B1_CLK_S0D2),
+ DEF_MOD("vin4", 807, R8A774B1_CLK_S0D2),
+ DEF_MOD("vin3", 808, R8A774B1_CLK_S0D2),
+ DEF_MOD("vin2", 809, R8A774B1_CLK_S0D2),
+ DEF_MOD("vin1", 810, R8A774B1_CLK_S0D2),
+ DEF_MOD("vin0", 811, R8A774B1_CLK_S0D2),
+ DEF_MOD("etheravb", 812, R8A774B1_CLK_S0D6),
+ DEF_MOD("sata0", 815, R8A774B1_CLK_S3D2),
+ DEF_MOD("gpio7", 905, R8A774B1_CLK_S3D4),
+ DEF_MOD("gpio6", 906, R8A774B1_CLK_S3D4),
+ DEF_MOD("gpio5", 907, R8A774B1_CLK_S3D4),
+ DEF_MOD("gpio4", 908, R8A774B1_CLK_S3D4),
+ DEF_MOD("gpio3", 909, R8A774B1_CLK_S3D4),
+ DEF_MOD("gpio2", 910, R8A774B1_CLK_S3D4),
+ DEF_MOD("gpio1", 911, R8A774B1_CLK_S3D4),
+ DEF_MOD("gpio0", 912, R8A774B1_CLK_S3D4),
+ DEF_MOD("can-fd", 914, R8A774B1_CLK_S3D2),
+ DEF_MOD("can-if1", 915, R8A774B1_CLK_S3D4),
+ DEF_MOD("can-if0", 916, R8A774B1_CLK_S3D4),
+ DEF_MOD("rpc-if", 917, R8A774B1_CLK_RPCD2),
+ DEF_MOD("i2c6", 918, R8A774B1_CLK_S0D6),
+ DEF_MOD("i2c5", 919, R8A774B1_CLK_S0D6),
+ DEF_MOD("adg", 922, R8A774B1_CLK_S0D4),
+ DEF_MOD("iic-pmic", 926, R8A774B1_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A774B1_CLK_S0D6),
+ DEF_MOD("i2c3", 928, R8A774B1_CLK_S0D6),
+ DEF_MOD("i2c2", 929, R8A774B1_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A774B1_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A774B1_CLK_S3D2),
+ DEF_MOD("ssi-all", 1005, R8A774B1_CLK_S3D4),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A774B1_CLK_S3D4),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a774b1_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3 PLL4 OSC
+ * 14 13 19 17 (MHz)
+ *-----------------------------------------------------------------
+ * 0 0 0 0 16.66 x 1 x180 x192 x192 x144 /16
+ * 0 0 0 1 16.66 x 1 x180 x192 x128 x144 /16
+ * 0 0 1 0 Prohibited setting
+ * 0 0 1 1 16.66 x 1 x180 x192 x192 x144 /16
+ * 0 1 0 0 20 x 1 x150 x160 x160 x120 /19
+ * 0 1 0 1 20 x 1 x150 x160 x106 x120 /19
+ * 0 1 1 0 Prohibited setting
+ * 0 1 1 1 20 x 1 x150 x160 x160 x120 /19
+ * 1 0 0 0 25 x 1 x120 x128 x128 x96 /24
+ * 1 0 0 1 25 x 1 x120 x128 x84 x96 /24
+ * 1 0 1 0 Prohibited setting
+ * 1 0 1 1 25 x 1 x120 x128 x128 x96 /24
+ * 1 1 0 0 33.33 / 2 x180 x192 x192 x144 /32
+ * 1 1 0 1 33.33 / 2 x180 x192 x128 x144 /32
+ * 1 1 1 0 Prohibited setting
+ * 1 1 1 1 33.33 / 2 x180 x192 x192 x144 /32
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \
+ (((md) & BIT(13)) >> 11) | \
+ (((md) & BIT(19)) >> 18) | \
+ (((md) & BIT(17)) >> 17))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 192, 1, 128, 1, 16, },
+ { 0, /* Prohibited setting */ },
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 160, 1, 106, 1, 19, },
+ { 0, /* Prohibited setting */ },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 128, 1, 128, 1, 24, },
+ { 1, 128, 1, 84, 1, 24, },
+ { 0, /* Prohibited setting */ },
+ { 1, 128, 1, 128, 1, 24, },
+ { 2, 192, 1, 192, 1, 32, },
+ { 2, 192, 1, 128, 1, 32, },
+ { 0, /* Prohibited setting */ },
+ { 2, 192, 1, 192, 1, 32, },
+};
+
+static int __init r8a774b1_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+ if (!cpg_pll_config->extal_div) {
+ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+ return -EINVAL;
+ }
+
+ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a774b1_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a774b1_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a774b1_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a774b1_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a774b1_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a774b1_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a774b1_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a774b1_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a774c0-cpg-mssr.c b/drivers/clk/renesas/r8a774c0-cpg-mssr.c
new file mode 100644
index 000000000..870f8c55e
--- /dev/null
+++ b/drivers/clk/renesas/r8a774c0-cpg-mssr.c
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a774c0 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ *
+ * Based on r8a77990-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a774c0-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A774C0_CLK_CANFD,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL0D4,
+ CLK_PLL0D6,
+ CLK_PLL0D8,
+ CLK_PLL0D20,
+ CLK_PLL0D24,
+ CLK_PLL1D2,
+ CLK_PE,
+ CLK_S0,
+ CLK_S1,
+ CLK_S2,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_RINT,
+ CLK_OCO,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll0", CLK_PLL0, CLK_MAIN, 1, 100),
+ DEF_FIXED(".pll0d4", CLK_PLL0D4, CLK_PLL0, 4, 1),
+ DEF_FIXED(".pll0d6", CLK_PLL0D6, CLK_PLL0, 6, 1),
+ DEF_FIXED(".pll0d8", CLK_PLL0D8, CLK_PLL0, 8, 1),
+ DEF_FIXED(".pll0d20", CLK_PLL0D20, CLK_PLL0, 20, 1),
+ DEF_FIXED(".pll0d24", CLK_PLL0D24, CLK_PLL0, 24, 1),
+ DEF_FIXED(".pll1d2", CLK_PLL1D2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pe", CLK_PE, CLK_PLL0D20, 1, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1, 3, 1),
+ DEF_FIXED(".s2", CLK_S2, CLK_PLL1, 4, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1),
+
+ DEF_FIXED_RPCSRC_E3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1),
+
+ DEF_DIV6_RO(".r", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32),
+
+ DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000),
+
+ /* Core Clock Outputs */
+ DEF_FIXED("za2", R8A774C0_CLK_ZA2, CLK_PLL0D24, 1, 1),
+ DEF_FIXED("za8", R8A774C0_CLK_ZA8, CLK_PLL0D8, 1, 1),
+ DEF_GEN3_Z("z2", R8A774C0_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL0, 4, 8),
+ DEF_FIXED("ztr", R8A774C0_CLK_ZTR, CLK_PLL1, 6, 1),
+ DEF_FIXED("zt", R8A774C0_CLK_ZT, CLK_PLL1, 4, 1),
+ DEF_FIXED("zx", R8A774C0_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("s0d1", R8A774C0_CLK_S0D1, CLK_S0, 1, 1),
+ DEF_FIXED("s0d3", R8A774C0_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d6", R8A774C0_CLK_S0D6, CLK_S0, 6, 1),
+ DEF_FIXED("s0d12", R8A774C0_CLK_S0D12, CLK_S0, 12, 1),
+ DEF_FIXED("s0d24", R8A774C0_CLK_S0D24, CLK_S0, 24, 1),
+ DEF_FIXED("s1d1", R8A774C0_CLK_S1D1, CLK_S1, 1, 1),
+ DEF_FIXED("s1d2", R8A774C0_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A774C0_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s2d1", R8A774C0_CLK_S2D1, CLK_S2, 1, 1),
+ DEF_FIXED("s2d2", R8A774C0_CLK_S2D2, CLK_S2, 2, 1),
+ DEF_FIXED("s2d4", R8A774C0_CLK_S2D4, CLK_S2, 4, 1),
+ DEF_FIXED("s3d1", R8A774C0_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A774C0_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A774C0_CLK_S3D4, CLK_S3, 4, 1),
+
+ DEF_BASE("rpc", R8A774C0_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A774C0_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A774C0_CLK_RPC),
+
+ DEF_GEN3_SDH("sd0h", R8A774C0_CLK_SD0H, CLK_SDSRC, 0x0074),
+ DEF_GEN3_SDH("sd1h", R8A774C0_CLK_SD1H, CLK_SDSRC, 0x0078),
+ DEF_GEN3_SDH("sd3h", R8A774C0_CLK_SD3H, CLK_SDSRC, 0x026c),
+ DEF_GEN3_SD("sd0", R8A774C0_CLK_SD0, R8A774C0_CLK_SD0H, 0x0074),
+ DEF_GEN3_SD("sd1", R8A774C0_CLK_SD1, R8A774C0_CLK_SD1H, 0x0078),
+ DEF_GEN3_SD("sd3", R8A774C0_CLK_SD3, R8A774C0_CLK_SD3H, 0x026c),
+
+ DEF_FIXED("cl", R8A774C0_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("cp", R8A774C0_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A774C0_CLK_CPEX, CLK_EXTAL, 4, 1),
+
+ DEF_DIV6_RO("osc", R8A774C0_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8),
+
+ DEF_GEN3_PE("s0d6c", R8A774C0_CLK_S0D6C, CLK_S0, 6, CLK_PE, 2),
+ DEF_GEN3_PE("s3d1c", R8A774C0_CLK_S3D1C, CLK_S3, 1, CLK_PE, 1),
+ DEF_GEN3_PE("s3d2c", R8A774C0_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2),
+ DEF_GEN3_PE("s3d4c", R8A774C0_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4),
+
+ DEF_DIV6P1("canfd", R8A774C0_CLK_CANFD, CLK_PLL0D6, 0x244),
+ DEF_DIV6P1("csi0", R8A774C0_CLK_CSI0, CLK_PLL1D2, 0x00c),
+ DEF_DIV6P1("mso", R8A774C0_CLK_MSO, CLK_PLL1D2, 0x014),
+
+ DEF_GEN3_RCKSEL("r", R8A774C0_CLK_R, CLK_RINT, 1, CLK_OCO, 61 * 4),
+};
+
+static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
+ DEF_MOD("tmu4", 121, R8A774C0_CLK_S0D6C),
+ DEF_MOD("tmu3", 122, R8A774C0_CLK_S3D2C),
+ DEF_MOD("tmu2", 123, R8A774C0_CLK_S3D2C),
+ DEF_MOD("tmu1", 124, R8A774C0_CLK_S3D2C),
+ DEF_MOD("tmu0", 125, R8A774C0_CLK_CP),
+ DEF_MOD("scif5", 202, R8A774C0_CLK_S3D4C),
+ DEF_MOD("scif4", 203, R8A774C0_CLK_S3D4C),
+ DEF_MOD("scif3", 204, R8A774C0_CLK_S3D4C),
+ DEF_MOD("scif1", 206, R8A774C0_CLK_S3D4C),
+ DEF_MOD("scif0", 207, R8A774C0_CLK_S3D4C),
+ DEF_MOD("msiof3", 208, R8A774C0_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A774C0_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A774C0_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A774C0_CLK_MSO),
+ DEF_MOD("sys-dmac2", 217, R8A774C0_CLK_S3D1),
+ DEF_MOD("sys-dmac1", 218, R8A774C0_CLK_S3D1),
+ DEF_MOD("sys-dmac0", 219, R8A774C0_CLK_S3D1),
+
+ DEF_MOD("cmt3", 300, R8A774C0_CLK_R),
+ DEF_MOD("cmt2", 301, R8A774C0_CLK_R),
+ DEF_MOD("cmt1", 302, R8A774C0_CLK_R),
+ DEF_MOD("cmt0", 303, R8A774C0_CLK_R),
+ DEF_MOD("scif2", 310, R8A774C0_CLK_S3D4C),
+ DEF_MOD("sdif3", 311, R8A774C0_CLK_SD3),
+ DEF_MOD("sdif1", 313, R8A774C0_CLK_SD1),
+ DEF_MOD("sdif0", 314, R8A774C0_CLK_SD0),
+ DEF_MOD("pcie0", 319, R8A774C0_CLK_S3D1),
+ DEF_MOD("usb3-if0", 328, R8A774C0_CLK_S3D1),
+ DEF_MOD("usb-dmac0", 330, R8A774C0_CLK_S3D1),
+ DEF_MOD("usb-dmac1", 331, R8A774C0_CLK_S3D1),
+
+ DEF_MOD("rwdt", 402, R8A774C0_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A774C0_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A774C0_CLK_S0D3),
+
+ DEF_MOD("audmac0", 502, R8A774C0_CLK_S1D2),
+ DEF_MOD("hscif4", 516, R8A774C0_CLK_S3D1C),
+ DEF_MOD("hscif3", 517, R8A774C0_CLK_S3D1C),
+ DEF_MOD("hscif2", 518, R8A774C0_CLK_S3D1C),
+ DEF_MOD("hscif1", 519, R8A774C0_CLK_S3D1C),
+ DEF_MOD("hscif0", 520, R8A774C0_CLK_S3D1C),
+ DEF_MOD("thermal", 522, R8A774C0_CLK_CP),
+ DEF_MOD("pwm", 523, R8A774C0_CLK_S3D4C),
+
+ DEF_MOD("fcpvd1", 602, R8A774C0_CLK_S1D2),
+ DEF_MOD("fcpvd0", 603, R8A774C0_CLK_S1D2),
+ DEF_MOD("fcpvb0", 607, R8A774C0_CLK_S0D1),
+ DEF_MOD("fcpvi0", 611, R8A774C0_CLK_S0D1),
+ DEF_MOD("fcpf0", 615, R8A774C0_CLK_S0D1),
+ DEF_MOD("fcpcs", 619, R8A774C0_CLK_S0D1),
+ DEF_MOD("vspd1", 622, R8A774C0_CLK_S1D2),
+ DEF_MOD("vspd0", 623, R8A774C0_CLK_S1D2),
+ DEF_MOD("vspb", 626, R8A774C0_CLK_S0D1),
+ DEF_MOD("vspi0", 631, R8A774C0_CLK_S0D1),
+
+ DEF_MOD("ehci0", 703, R8A774C0_CLK_S3D2),
+ DEF_MOD("hsusb", 704, R8A774C0_CLK_S3D2),
+ DEF_MOD("csi40", 716, R8A774C0_CLK_CSI0),
+ DEF_MOD("du1", 723, R8A774C0_CLK_S1D1),
+ DEF_MOD("du0", 724, R8A774C0_CLK_S1D1),
+ DEF_MOD("lvds", 727, R8A774C0_CLK_S2D1),
+
+ DEF_MOD("vin5", 806, R8A774C0_CLK_S1D2),
+ DEF_MOD("vin4", 807, R8A774C0_CLK_S1D2),
+ DEF_MOD("etheravb", 812, R8A774C0_CLK_S3D2),
+
+ DEF_MOD("gpio6", 906, R8A774C0_CLK_S3D4),
+ DEF_MOD("gpio5", 907, R8A774C0_CLK_S3D4),
+ DEF_MOD("gpio4", 908, R8A774C0_CLK_S3D4),
+ DEF_MOD("gpio3", 909, R8A774C0_CLK_S3D4),
+ DEF_MOD("gpio2", 910, R8A774C0_CLK_S3D4),
+ DEF_MOD("gpio1", 911, R8A774C0_CLK_S3D4),
+ DEF_MOD("gpio0", 912, R8A774C0_CLK_S3D4),
+ DEF_MOD("can-fd", 914, R8A774C0_CLK_S3D2),
+ DEF_MOD("can-if1", 915, R8A774C0_CLK_S3D4),
+ DEF_MOD("can-if0", 916, R8A774C0_CLK_S3D4),
+ DEF_MOD("rpc-if", 917, R8A774C0_CLK_RPCD2),
+ DEF_MOD("i2c6", 918, R8A774C0_CLK_S3D2),
+ DEF_MOD("i2c5", 919, R8A774C0_CLK_S3D2),
+ DEF_MOD("adg", 922, R8A774C0_CLK_ZA2),
+ DEF_MOD("iic-pmic", 926, R8A774C0_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A774C0_CLK_S3D2),
+ DEF_MOD("i2c3", 928, R8A774C0_CLK_S3D2),
+ DEF_MOD("i2c2", 929, R8A774C0_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A774C0_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A774C0_CLK_S3D2),
+
+ DEF_MOD("i2c7", 1003, R8A774C0_CLK_S3D2),
+ DEF_MOD("ssi-all", 1005, R8A774C0_CLK_S3D4),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A774C0_CLK_S3D4),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a774c0_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD19 EXTAL (MHz) PLL0 PLL1 PLL3
+ *--------------------------------------------------------------------
+ * 0 48 x 1 x100/1 x100/3 x100/3
+ * 1 48 x 1 x100/1 x100/3 x58/3
+ */
+#define CPG_PLL_CONFIG_INDEX(md) (((md) & BIT(19)) >> 19)
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[2] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div */
+ { 1, 100, 3, 100, 3, },
+ { 1, 100, 3, 58, 3, },
+};
+
+static int __init r8a774c0_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen3_cpg_init(cpg_pll_config, 0, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a774c0_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a774c0_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a774c0_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a774c0_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a774c0_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a774c0_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a774c0_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a774c0_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a774e1-cpg-mssr.c b/drivers/clk/renesas/r8a774e1-cpg-mssr.c
new file mode 100644
index 000000000..7158464c8
--- /dev/null
+++ b/drivers/clk/renesas/r8a774e1-cpg-mssr.c
@@ -0,0 +1,354 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a774e1 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a774e1-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A774E1_CLK_CANFD,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL3,
+ CLK_PLL4,
+ CLK_PLL1_DIV2,
+ CLK_PLL1_DIV4,
+ CLK_S0,
+ CLK_S1,
+ CLK_S2,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_RINT,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a774e1_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+ DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1),
+ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
+
+ DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32),
+
+ /* Core Clock Outputs */
+ DEF_GEN3_Z("z", R8A774E1_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8),
+ DEF_GEN3_Z("z2", R8A774E1_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL2, 2, 0),
+ DEF_GEN3_Z("zg", R8A774E1_CLK_ZG, CLK_TYPE_GEN3_ZG, CLK_PLL4, 4, 24),
+ DEF_FIXED("ztr", R8A774E1_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED("ztrd2", R8A774E1_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+ DEF_FIXED("zt", R8A774E1_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED("zx", R8A774E1_CLK_ZX, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED("s0d1", R8A774E1_CLK_S0D1, CLK_S0, 1, 1),
+ DEF_FIXED("s0d2", R8A774E1_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A774E1_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A774E1_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6", R8A774E1_CLK_S0D6, CLK_S0, 6, 1),
+ DEF_FIXED("s0d8", R8A774E1_CLK_S0D8, CLK_S0, 8, 1),
+ DEF_FIXED("s0d12", R8A774E1_CLK_S0D12, CLK_S0, 12, 1),
+ DEF_FIXED("s1d2", R8A774E1_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A774E1_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s2d1", R8A774E1_CLK_S2D1, CLK_S2, 1, 1),
+ DEF_FIXED("s2d2", R8A774E1_CLK_S2D2, CLK_S2, 2, 1),
+ DEF_FIXED("s2d4", R8A774E1_CLK_S2D4, CLK_S2, 4, 1),
+ DEF_FIXED("s3d1", R8A774E1_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A774E1_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A774E1_CLK_S3D4, CLK_S3, 4, 1),
+
+ DEF_GEN3_SDH("sd0h", R8A774E1_CLK_SD0H, CLK_SDSRC, 0x074),
+ DEF_GEN3_SDH("sd1h", R8A774E1_CLK_SD1H, CLK_SDSRC, 0x078),
+ DEF_GEN3_SDH("sd2h", R8A774E1_CLK_SD2H, CLK_SDSRC, 0x268),
+ DEF_GEN3_SDH("sd3h", R8A774E1_CLK_SD3H, CLK_SDSRC, 0x26c),
+ DEF_GEN3_SD("sd0", R8A774E1_CLK_SD0, R8A774E1_CLK_SD0H, 0x074),
+ DEF_GEN3_SD("sd1", R8A774E1_CLK_SD1, R8A774E1_CLK_SD1H, 0x078),
+ DEF_GEN3_SD("sd2", R8A774E1_CLK_SD2, R8A774E1_CLK_SD2H, 0x268),
+ DEF_GEN3_SD("sd3", R8A774E1_CLK_SD3, R8A774E1_CLK_SD3H, 0x26c),
+
+ DEF_BASE("rpc", R8A774E1_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A774E1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A774E1_CLK_RPC),
+
+ DEF_FIXED("cl", R8A774E1_CLK_CL, CLK_PLL1_DIV2, 48, 1),
+ DEF_FIXED("cr", R8A774E1_CLK_CR, CLK_PLL1_DIV4, 2, 1),
+ DEF_FIXED("cp", R8A774E1_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A774E1_CLK_CPEX, CLK_EXTAL, 2, 1),
+
+ DEF_DIV6P1("canfd", R8A774E1_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+ DEF_DIV6P1("csi0", R8A774E1_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
+ DEF_DIV6P1("mso", R8A774E1_CLK_MSO, CLK_PLL1_DIV4, 0x014),
+ DEF_DIV6P1("hdmi", R8A774E1_CLK_HDMI, CLK_PLL1_DIV4, 0x250),
+
+ DEF_GEN3_OSC("osc", R8A774E1_CLK_OSC, CLK_EXTAL, 8),
+
+ DEF_BASE("r", R8A774E1_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
+};
+
+static const struct mssr_mod_clk r8a774e1_mod_clks[] __initconst = {
+ DEF_MOD("3dge", 112, R8A774E1_CLK_ZG),
+ DEF_MOD("fdp1-1", 118, R8A774E1_CLK_S0D1),
+ DEF_MOD("fdp1-0", 119, R8A774E1_CLK_S0D1),
+ DEF_MOD("tmu4", 121, R8A774E1_CLK_S0D6),
+ DEF_MOD("tmu3", 122, R8A774E1_CLK_S3D2),
+ DEF_MOD("tmu2", 123, R8A774E1_CLK_S3D2),
+ DEF_MOD("tmu1", 124, R8A774E1_CLK_S3D2),
+ DEF_MOD("tmu0", 125, R8A774E1_CLK_CP),
+ DEF_MOD("vcplf", 130, R8A774E1_CLK_S2D1),
+ DEF_MOD("vdpb", 131, R8A774E1_CLK_S2D1),
+ DEF_MOD("scif5", 202, R8A774E1_CLK_S3D4),
+ DEF_MOD("scif4", 203, R8A774E1_CLK_S3D4),
+ DEF_MOD("scif3", 204, R8A774E1_CLK_S3D4),
+ DEF_MOD("scif1", 206, R8A774E1_CLK_S3D4),
+ DEF_MOD("scif0", 207, R8A774E1_CLK_S3D4),
+ DEF_MOD("msiof3", 208, R8A774E1_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A774E1_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A774E1_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A774E1_CLK_MSO),
+ DEF_MOD("sys-dmac2", 217, R8A774E1_CLK_S3D1),
+ DEF_MOD("sys-dmac1", 218, R8A774E1_CLK_S3D1),
+ DEF_MOD("sys-dmac0", 219, R8A774E1_CLK_S0D3),
+ DEF_MOD("cmt3", 300, R8A774E1_CLK_R),
+ DEF_MOD("cmt2", 301, R8A774E1_CLK_R),
+ DEF_MOD("cmt1", 302, R8A774E1_CLK_R),
+ DEF_MOD("cmt0", 303, R8A774E1_CLK_R),
+ DEF_MOD("tpu0", 304, R8A774E1_CLK_S3D4),
+ DEF_MOD("scif2", 310, R8A774E1_CLK_S3D4),
+ DEF_MOD("sdif3", 311, R8A774E1_CLK_SD3),
+ DEF_MOD("sdif2", 312, R8A774E1_CLK_SD2),
+ DEF_MOD("sdif1", 313, R8A774E1_CLK_SD1),
+ DEF_MOD("sdif0", 314, R8A774E1_CLK_SD0),
+ DEF_MOD("pcie1", 318, R8A774E1_CLK_S3D1),
+ DEF_MOD("pcie0", 319, R8A774E1_CLK_S3D1),
+ DEF_MOD("usb3-if0", 328, R8A774E1_CLK_S3D1),
+ DEF_MOD("usb-dmac0", 330, R8A774E1_CLK_S3D1),
+ DEF_MOD("usb-dmac1", 331, R8A774E1_CLK_S3D1),
+ DEF_MOD("rwdt", 402, R8A774E1_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A774E1_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A774E1_CLK_S0D3),
+ DEF_MOD("audmac1", 501, R8A774E1_CLK_S1D2),
+ DEF_MOD("audmac0", 502, R8A774E1_CLK_S1D2),
+ DEF_MOD("hscif4", 516, R8A774E1_CLK_S3D1),
+ DEF_MOD("hscif3", 517, R8A774E1_CLK_S3D1),
+ DEF_MOD("hscif2", 518, R8A774E1_CLK_S3D1),
+ DEF_MOD("hscif1", 519, R8A774E1_CLK_S3D1),
+ DEF_MOD("hscif0", 520, R8A774E1_CLK_S3D1),
+ DEF_MOD("thermal", 522, R8A774E1_CLK_CP),
+ DEF_MOD("pwm", 523, R8A774E1_CLK_S0D12),
+ DEF_MOD("fcpvd1", 602, R8A774E1_CLK_S0D2),
+ DEF_MOD("fcpvd0", 603, R8A774E1_CLK_S0D2),
+ DEF_MOD("fcpvb1", 606, R8A774E1_CLK_S0D1),
+ DEF_MOD("fcpvb0", 607, R8A774E1_CLK_S0D1),
+ DEF_MOD("fcpvi1", 610, R8A774E1_CLK_S0D1),
+ DEF_MOD("fcpvi0", 611, R8A774E1_CLK_S0D1),
+ DEF_MOD("fcpf1", 614, R8A774E1_CLK_S0D1),
+ DEF_MOD("fcpf0", 615, R8A774E1_CLK_S0D1),
+ DEF_MOD("fcpcs", 619, R8A774E1_CLK_S0D1),
+ DEF_MOD("vspd1", 622, R8A774E1_CLK_S0D2),
+ DEF_MOD("vspd0", 623, R8A774E1_CLK_S0D2),
+ DEF_MOD("vspbc", 624, R8A774E1_CLK_S0D1),
+ DEF_MOD("vspbd", 626, R8A774E1_CLK_S0D1),
+ DEF_MOD("vspi1", 630, R8A774E1_CLK_S0D1),
+ DEF_MOD("vspi0", 631, R8A774E1_CLK_S0D1),
+ DEF_MOD("ehci1", 702, R8A774E1_CLK_S3D2),
+ DEF_MOD("ehci0", 703, R8A774E1_CLK_S3D2),
+ DEF_MOD("hsusb", 704, R8A774E1_CLK_S3D2),
+ DEF_MOD("csi20", 714, R8A774E1_CLK_CSI0),
+ DEF_MOD("csi40", 716, R8A774E1_CLK_CSI0),
+ DEF_MOD("du3", 721, R8A774E1_CLK_S2D1),
+ DEF_MOD("du1", 723, R8A774E1_CLK_S2D1),
+ DEF_MOD("du0", 724, R8A774E1_CLK_S2D1),
+ DEF_MOD("lvds", 727, R8A774E1_CLK_S0D4),
+ DEF_MOD("hdmi0", 729, R8A774E1_CLK_HDMI),
+ DEF_MOD("vin7", 804, R8A774E1_CLK_S0D2),
+ DEF_MOD("vin6", 805, R8A774E1_CLK_S0D2),
+ DEF_MOD("vin5", 806, R8A774E1_CLK_S0D2),
+ DEF_MOD("vin4", 807, R8A774E1_CLK_S0D2),
+ DEF_MOD("vin3", 808, R8A774E1_CLK_S0D2),
+ DEF_MOD("vin2", 809, R8A774E1_CLK_S0D2),
+ DEF_MOD("vin1", 810, R8A774E1_CLK_S0D2),
+ DEF_MOD("vin0", 811, R8A774E1_CLK_S0D2),
+ DEF_MOD("etheravb", 812, R8A774E1_CLK_S0D6),
+ DEF_MOD("sata0", 815, R8A774E1_CLK_S3D2),
+ DEF_MOD("gpio7", 905, R8A774E1_CLK_S3D4),
+ DEF_MOD("gpio6", 906, R8A774E1_CLK_S3D4),
+ DEF_MOD("gpio5", 907, R8A774E1_CLK_S3D4),
+ DEF_MOD("gpio4", 908, R8A774E1_CLK_S3D4),
+ DEF_MOD("gpio3", 909, R8A774E1_CLK_S3D4),
+ DEF_MOD("gpio2", 910, R8A774E1_CLK_S3D4),
+ DEF_MOD("gpio1", 911, R8A774E1_CLK_S3D4),
+ DEF_MOD("gpio0", 912, R8A774E1_CLK_S3D4),
+ DEF_MOD("can-fd", 914, R8A774E1_CLK_S3D2),
+ DEF_MOD("can-if1", 915, R8A774E1_CLK_S3D4),
+ DEF_MOD("can-if0", 916, R8A774E1_CLK_S3D4),
+ DEF_MOD("rpc-if", 917, R8A774E1_CLK_RPCD2),
+ DEF_MOD("i2c6", 918, R8A774E1_CLK_S0D6),
+ DEF_MOD("i2c5", 919, R8A774E1_CLK_S0D6),
+ DEF_MOD("adg", 922, R8A774E1_CLK_S0D4),
+ DEF_MOD("iic-pmic", 926, R8A774E1_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A774E1_CLK_S0D6),
+ DEF_MOD("i2c3", 928, R8A774E1_CLK_S0D6),
+ DEF_MOD("i2c2", 929, R8A774E1_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A774E1_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A774E1_CLK_S3D2),
+ DEF_MOD("ssi-all", 1005, R8A774E1_CLK_S3D4),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A774E1_CLK_S3D4),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a774e1_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4 OSC
+ * 14 13 19 17 (MHz)
+ *-------------------------------------------------------------------------
+ * 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144 /16
+ * 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144 /16
+ * 0 0 1 0 Prohibited setting
+ * 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144 /16
+ * 0 1 0 0 20 x 1 x150 x160 x120 x160 x120 /19
+ * 0 1 0 1 20 x 1 x150 x160 x120 x106 x120 /19
+ * 0 1 1 0 Prohibited setting
+ * 0 1 1 1 20 x 1 x150 x160 x120 x160 x120 /19
+ * 1 0 0 0 25 x 1 x120 x128 x96 x128 x96 /24
+ * 1 0 0 1 25 x 1 x120 x128 x96 x84 x96 /24
+ * 1 0 1 0 Prohibited setting
+ * 1 0 1 1 25 x 1 x120 x128 x96 x128 x96 /24
+ * 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144 /32
+ * 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144 /32
+ * 1 1 1 0 Prohibited setting
+ * 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144 /32
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \
+ (((md) & BIT(13)) >> 11) | \
+ (((md) & BIT(19)) >> 18) | \
+ (((md) & BIT(17)) >> 17))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 192, 1, 128, 1, 16, },
+ { 0, /* Prohibited setting */ },
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 160, 1, 106, 1, 19, },
+ { 0, /* Prohibited setting */ },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 128, 1, 128, 1, 24, },
+ { 1, 128, 1, 84, 1, 24, },
+ { 0, /* Prohibited setting */ },
+ { 1, 128, 1, 128, 1, 24, },
+ { 2, 192, 1, 192, 1, 32, },
+ { 2, 192, 1, 128, 1, 32, },
+ { 0, /* Prohibited setting */ },
+ { 2, 192, 1, 192, 1, 32, },
+};
+
+static int __init r8a774e1_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+ if (!cpg_pll_config->extal_div) {
+ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+ return -EINVAL;
+ }
+
+ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a774e1_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a774e1_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a774e1_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a774e1_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a774e1_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a774e1_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a774e1_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a774e1_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7790-cpg-mssr.c b/drivers/clk/renesas/r8a7790-cpg-mssr.c
new file mode 100644
index 000000000..f7d233e0c
--- /dev/null
+++ b/drivers/clk/renesas/r8a7790-cpg-mssr.c
@@ -0,0 +1,277 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7790 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2017 Glider bvba
+ *
+ * Based on clk-rcar-gen2.c
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7790-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7790_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_USB_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7790_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("z", R8A7790_CLK_Z, CLK_TYPE_GEN2_Z, CLK_PLL0),
+ DEF_BASE("lb", R8A7790_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1),
+ DEF_BASE("adsp", R8A7790_CLK_ADSP, CLK_TYPE_GEN2_ADSP, CLK_PLL1),
+ DEF_BASE("sdh", R8A7790_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
+ DEF_BASE("sd0", R8A7790_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
+ DEF_BASE("sd1", R8A7790_CLK_SD1, CLK_TYPE_GEN2_SD1, CLK_PLL1),
+ DEF_BASE("qspi", R8A7790_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+ DEF_BASE("rcan", R8A7790_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+ DEF_FIXED("z2", R8A7790_CLK_Z2, CLK_PLL1, 2, 1),
+ DEF_FIXED("zg", R8A7790_CLK_ZG, CLK_PLL1, 3, 1),
+ DEF_FIXED("zx", R8A7790_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A7790_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A7790_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("i", R8A7790_CLK_I, CLK_PLL1, 2, 1),
+ DEF_FIXED("b", R8A7790_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("p", R8A7790_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A7790_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A7790_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("imp", R8A7790_CLK_IMP, CLK_PLL1, 4, 1),
+ DEF_FIXED("zb3", R8A7790_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("zb3d2", R8A7790_CLK_ZB3D2, CLK_PLL3, 8, 1),
+ DEF_FIXED("ddr", R8A7790_CLK_DDR, CLK_PLL3, 8, 1),
+ DEF_FIXED("mp", R8A7790_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cp", R8A7790_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("r", R8A7790_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A7790_CLK_OSC, CLK_PLL1, 12288, 1),
+
+ DEF_DIV6P1("sd2", R8A7790_CLK_SD2, CLK_PLL1_DIV2, 0x078),
+ DEF_DIV6P1("sd3", R8A7790_CLK_SD3, CLK_PLL1_DIV2, 0x26c),
+ DEF_DIV6P1("mmc0", R8A7790_CLK_MMC0, CLK_PLL1_DIV2, 0x240),
+ DEF_DIV6P1("mmc1", R8A7790_CLK_MMC1, CLK_PLL1_DIV2, 0x244),
+ DEF_DIV6P1("ssp", R8A7790_CLK_SSP, CLK_PLL1_DIV2, 0x248),
+ DEF_DIV6P1("ssprs", R8A7790_CLK_SSPRS, CLK_PLL1_DIV2, 0x24c),
+};
+
+static const struct mssr_mod_clk r8a7790_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A7790_CLK_MP),
+ DEF_MOD("vcp1", 100, R8A7790_CLK_ZS),
+ DEF_MOD("vcp0", 101, R8A7790_CLK_ZS),
+ DEF_MOD("vpc1", 102, R8A7790_CLK_ZS),
+ DEF_MOD("vpc0", 103, R8A7790_CLK_ZS),
+ DEF_MOD("jpu", 106, R8A7790_CLK_M2),
+ DEF_MOD("ssp1", 109, R8A7790_CLK_ZS),
+ DEF_MOD("tmu1", 111, R8A7790_CLK_P),
+ DEF_MOD("3dg", 112, R8A7790_CLK_ZG),
+ DEF_MOD("2d-dmac", 115, R8A7790_CLK_ZS),
+ DEF_MOD("fdp1-2", 117, R8A7790_CLK_ZS),
+ DEF_MOD("fdp1-1", 118, R8A7790_CLK_ZS),
+ DEF_MOD("fdp1-0", 119, R8A7790_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A7790_CLK_P),
+ DEF_MOD("tmu2", 122, R8A7790_CLK_P),
+ DEF_MOD("cmt0", 124, R8A7790_CLK_R),
+ DEF_MOD("tmu0", 125, R8A7790_CLK_CP),
+ DEF_MOD("vsp1du1", 127, R8A7790_CLK_ZS),
+ DEF_MOD("vsp1du0", 128, R8A7790_CLK_ZS),
+ DEF_MOD("vspr", 130, R8A7790_CLK_ZS),
+ DEF_MOD("vsps", 131, R8A7790_CLK_ZS),
+ DEF_MOD("scifa2", 202, R8A7790_CLK_MP),
+ DEF_MOD("scifa1", 203, R8A7790_CLK_MP),
+ DEF_MOD("scifa0", 204, R8A7790_CLK_MP),
+ DEF_MOD("msiof2", 205, R8A7790_CLK_MP),
+ DEF_MOD("scifb0", 206, R8A7790_CLK_MP),
+ DEF_MOD("scifb1", 207, R8A7790_CLK_MP),
+ DEF_MOD("msiof1", 208, R8A7790_CLK_MP),
+ DEF_MOD("msiof3", 215, R8A7790_CLK_MP),
+ DEF_MOD("scifb2", 216, R8A7790_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A7790_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A7790_CLK_ZS),
+ DEF_MOD("iic2", 300, R8A7790_CLK_HP),
+ DEF_MOD("tpu0", 304, R8A7790_CLK_CP),
+ DEF_MOD("mmcif1", 305, R8A7790_CLK_MMC1),
+ DEF_MOD("scif2", 310, R8A7790_CLK_P),
+ DEF_MOD("sdhi3", 311, R8A7790_CLK_SD3),
+ DEF_MOD("sdhi2", 312, R8A7790_CLK_SD2),
+ DEF_MOD("sdhi1", 313, R8A7790_CLK_SD1),
+ DEF_MOD("sdhi0", 314, R8A7790_CLK_SD0),
+ DEF_MOD("mmcif0", 315, R8A7790_CLK_MMC0),
+ DEF_MOD("iic0", 318, R8A7790_CLK_HP),
+ DEF_MOD("pciec", 319, R8A7790_CLK_MP),
+ DEF_MOD("iic1", 323, R8A7790_CLK_HP),
+ DEF_MOD("usb3.0", 328, R8A7790_CLK_MP),
+ DEF_MOD("cmt1", 329, R8A7790_CLK_R),
+ DEF_MOD("usbhs-dmac0", 330, R8A7790_CLK_HP),
+ DEF_MOD("usbhs-dmac1", 331, R8A7790_CLK_HP),
+ DEF_MOD("rwdt", 402, R8A7790_CLK_R),
+ DEF_MOD("irqc", 407, R8A7790_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A7790_CLK_ZS),
+ DEF_MOD("audio-dmac1", 501, R8A7790_CLK_HP),
+ DEF_MOD("audio-dmac0", 502, R8A7790_CLK_HP),
+ DEF_MOD("adsp_mod", 506, R8A7790_CLK_ADSP),
+ DEF_MOD("thermal", 522, CLK_EXTAL),
+ DEF_MOD("pwm", 523, R8A7790_CLK_P),
+ DEF_MOD("usb-ehci", 703, R8A7790_CLK_MP),
+ DEF_MOD("usbhs", 704, R8A7790_CLK_HP),
+ DEF_MOD("hscif1", 716, R8A7790_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A7790_CLK_ZS),
+ DEF_MOD("scif1", 720, R8A7790_CLK_P),
+ DEF_MOD("scif0", 721, R8A7790_CLK_P),
+ DEF_MOD("du2", 722, R8A7790_CLK_ZX),
+ DEF_MOD("du1", 723, R8A7790_CLK_ZX),
+ DEF_MOD("du0", 724, R8A7790_CLK_ZX),
+ DEF_MOD("lvds1", 725, R8A7790_CLK_ZX),
+ DEF_MOD("lvds0", 726, R8A7790_CLK_ZX),
+ DEF_MOD("mlb", 802, R8A7790_CLK_HP),
+ DEF_MOD("vin3", 808, R8A7790_CLK_ZG),
+ DEF_MOD("vin2", 809, R8A7790_CLK_ZG),
+ DEF_MOD("vin1", 810, R8A7790_CLK_ZG),
+ DEF_MOD("vin0", 811, R8A7790_CLK_ZG),
+ DEF_MOD("etheravb", 812, R8A7790_CLK_HP),
+ DEF_MOD("ether", 813, R8A7790_CLK_P),
+ DEF_MOD("sata1", 814, R8A7790_CLK_ZS),
+ DEF_MOD("sata0", 815, R8A7790_CLK_ZS),
+ DEF_MOD("gyro-adc", 901, R8A7790_CLK_P),
+ DEF_MOD("gpio5", 907, R8A7790_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A7790_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A7790_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A7790_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A7790_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A7790_CLK_CP),
+ DEF_MOD("can1", 915, R8A7790_CLK_P),
+ DEF_MOD("can0", 916, R8A7790_CLK_P),
+ DEF_MOD("qspi_mod", 917, R8A7790_CLK_QSPI),
+ DEF_MOD("iicdvfs", 926, R8A7790_CLK_CP),
+ DEF_MOD("i2c3", 928, R8A7790_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A7790_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A7790_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A7790_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A7790_CLK_P),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7790_CLK_P),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a7790_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz) *1 *1
+ *---------------------------------------------------
+ * 0 0 0 15 x172/2 x208/2 x106
+ * 0 0 1 15 x172/2 x208/2 x88
+ * 0 1 0 20 x130/2 x156/2 x80
+ * 0 1 1 20 x130/2 x156/2 x66
+ * 1 0 0 26 / 2 x200/2 x240/2 x122
+ * 1 0 1 26 / 2 x200/2 x240/2 x102
+ * 1 1 0 30 / 2 x172/2 x208/2 x106
+ * 1 1 1 30 / 2 x172/2 x208/2 x88
+ *
+ * *1 : Table 7.5a indicates VCO output (PLLx = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
+ (((md) & BIT(13)) >> 12) | \
+ (((md) & BIT(19)) >> 19))
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+ { 1, 208, 106 }, { 1, 208, 88 }, { 1, 156, 80 }, { 1, 156, 66 },
+ { 2, 240, 122 }, { 2, 240, 102 }, { 2, 208, 106 }, { 2, 208, 88 },
+};
+
+static int __init r8a7790_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7790_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7790_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7790_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7790_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7790_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7790_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7790_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7790_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7791-cpg-mssr.c b/drivers/clk/renesas/r8a7791-cpg-mssr.c
new file mode 100644
index 000000000..a0de78486
--- /dev/null
+++ b/drivers/clk/renesas/r8a7791-cpg-mssr.c
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7791 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2015-2017 Glider bvba
+ *
+ * Based on clk-rcar-gen2.c
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7791-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7791_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_USB_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static struct cpg_core_clk r8a7791_core_clks[] __initdata = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("z", R8A7791_CLK_Z, CLK_TYPE_GEN2_Z, CLK_PLL0),
+ DEF_BASE("adsp", R8A7791_CLK_ADSP, CLK_TYPE_GEN2_ADSP, CLK_PLL1),
+ DEF_BASE("sdh", R8A7791_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
+ DEF_BASE("sd0", R8A7791_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
+ DEF_BASE("qspi", R8A7791_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+ DEF_BASE("rcan", R8A7791_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+ DEF_FIXED("zg", R8A7791_CLK_ZG, CLK_PLL1, 3, 1),
+ DEF_FIXED("zx", R8A7791_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A7791_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A7791_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("i", R8A7791_CLK_I, CLK_PLL1, 2, 1),
+ DEF_FIXED("b", R8A7791_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("lb", R8A7791_CLK_LB, CLK_PLL1, 24, 1),
+ DEF_FIXED("p", R8A7791_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A7791_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A7791_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("zb3", R8A7791_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("zb3d2", R8A7791_CLK_ZB3D2, CLK_PLL3, 8, 1),
+ DEF_FIXED("ddr", R8A7791_CLK_DDR, CLK_PLL3, 8, 1),
+ DEF_FIXED("mp", R8A7791_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cp", R8A7791_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("r", R8A7791_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A7791_CLK_OSC, CLK_PLL1, 12288, 1),
+
+ DEF_DIV6P1("sd2", R8A7791_CLK_SD2, CLK_PLL1_DIV2, 0x078),
+ DEF_DIV6P1("sd3", R8A7791_CLK_SD3, CLK_PLL1_DIV2, 0x26c),
+ DEF_DIV6P1("mmc0", R8A7791_CLK_MMC0, CLK_PLL1_DIV2, 0x240),
+ DEF_DIV6P1("ssp", R8A7791_CLK_SSP, CLK_PLL1_DIV2, 0x248),
+ DEF_DIV6P1("ssprs", R8A7791_CLK_SSPRS, CLK_PLL1_DIV2, 0x24c),
+};
+
+static const struct mssr_mod_clk r8a7791_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A7791_CLK_MP),
+ DEF_MOD("vcp0", 101, R8A7791_CLK_ZS),
+ DEF_MOD("vpc0", 103, R8A7791_CLK_ZS),
+ DEF_MOD("jpu", 106, R8A7791_CLK_M2),
+ DEF_MOD("ssp1", 109, R8A7791_CLK_ZS),
+ DEF_MOD("tmu1", 111, R8A7791_CLK_P),
+ DEF_MOD("3dg", 112, R8A7791_CLK_ZG),
+ DEF_MOD("2d-dmac", 115, R8A7791_CLK_ZS),
+ DEF_MOD("fdp1-1", 118, R8A7791_CLK_ZS),
+ DEF_MOD("fdp1-0", 119, R8A7791_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A7791_CLK_P),
+ DEF_MOD("tmu2", 122, R8A7791_CLK_P),
+ DEF_MOD("cmt0", 124, R8A7791_CLK_R),
+ DEF_MOD("tmu0", 125, R8A7791_CLK_CP),
+ DEF_MOD("vsp1du1", 127, R8A7791_CLK_ZS),
+ DEF_MOD("vsp1du0", 128, R8A7791_CLK_ZS),
+ DEF_MOD("vsps", 131, R8A7791_CLK_ZS),
+ DEF_MOD("scifa2", 202, R8A7791_CLK_MP),
+ DEF_MOD("scifa1", 203, R8A7791_CLK_MP),
+ DEF_MOD("scifa0", 204, R8A7791_CLK_MP),
+ DEF_MOD("msiof2", 205, R8A7791_CLK_MP),
+ DEF_MOD("scifb0", 206, R8A7791_CLK_MP),
+ DEF_MOD("scifb1", 207, R8A7791_CLK_MP),
+ DEF_MOD("msiof1", 208, R8A7791_CLK_MP),
+ DEF_MOD("scifb2", 216, R8A7791_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A7791_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A7791_CLK_ZS),
+ DEF_MOD("tpu0", 304, R8A7791_CLK_CP),
+ DEF_MOD("sdhi3", 311, R8A7791_CLK_SD3),
+ DEF_MOD("sdhi2", 312, R8A7791_CLK_SD2),
+ DEF_MOD("sdhi0", 314, R8A7791_CLK_SD0),
+ DEF_MOD("mmcif0", 315, R8A7791_CLK_MMC0),
+ DEF_MOD("iic0", 318, R8A7791_CLK_HP),
+ DEF_MOD("pciec", 319, R8A7791_CLK_MP),
+ DEF_MOD("iic1", 323, R8A7791_CLK_HP),
+ DEF_MOD("usb3.0", 328, R8A7791_CLK_MP),
+ DEF_MOD("cmt1", 329, R8A7791_CLK_R),
+ DEF_MOD("usbhs-dmac0", 330, R8A7791_CLK_HP),
+ DEF_MOD("usbhs-dmac1", 331, R8A7791_CLK_HP),
+ DEF_MOD("rwdt", 402, R8A7791_CLK_R),
+ DEF_MOD("irqc", 407, R8A7791_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A7791_CLK_ZS),
+ DEF_MOD("audio-dmac1", 501, R8A7791_CLK_HP),
+ DEF_MOD("audio-dmac0", 502, R8A7791_CLK_HP),
+ DEF_MOD("adsp_mod", 506, R8A7791_CLK_ADSP),
+ DEF_MOD("thermal", 522, CLK_EXTAL),
+ DEF_MOD("pwm", 523, R8A7791_CLK_P),
+ DEF_MOD("usb-ehci", 703, R8A7791_CLK_MP),
+ DEF_MOD("usbhs", 704, R8A7791_CLK_HP),
+ DEF_MOD("hscif2", 713, R8A7791_CLK_ZS),
+ DEF_MOD("scif5", 714, R8A7791_CLK_P),
+ DEF_MOD("scif4", 715, R8A7791_CLK_P),
+ DEF_MOD("hscif1", 716, R8A7791_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A7791_CLK_ZS),
+ DEF_MOD("scif3", 718, R8A7791_CLK_P),
+ DEF_MOD("scif2", 719, R8A7791_CLK_P),
+ DEF_MOD("scif1", 720, R8A7791_CLK_P),
+ DEF_MOD("scif0", 721, R8A7791_CLK_P),
+ DEF_MOD("du1", 723, R8A7791_CLK_ZX),
+ DEF_MOD("du0", 724, R8A7791_CLK_ZX),
+ DEF_MOD("lvds0", 726, R8A7791_CLK_ZX),
+ DEF_MOD("ipmmu-sgx", 800, R8A7791_CLK_ZX),
+ DEF_MOD("mlb", 802, R8A7791_CLK_HP),
+ DEF_MOD("vin2", 809, R8A7791_CLK_ZG),
+ DEF_MOD("vin1", 810, R8A7791_CLK_ZG),
+ DEF_MOD("vin0", 811, R8A7791_CLK_ZG),
+ DEF_MOD("etheravb", 812, R8A7791_CLK_HP),
+ DEF_MOD("ether", 813, R8A7791_CLK_P),
+ DEF_MOD("sata1", 814, R8A7791_CLK_ZS),
+ DEF_MOD("sata0", 815, R8A7791_CLK_ZS),
+ DEF_MOD("gyro-adc", 901, R8A7791_CLK_P),
+ DEF_MOD("gpio7", 904, R8A7791_CLK_CP),
+ DEF_MOD("gpio6", 905, R8A7791_CLK_CP),
+ DEF_MOD("gpio5", 907, R8A7791_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A7791_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A7791_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A7791_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A7791_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A7791_CLK_CP),
+ DEF_MOD("can1", 915, R8A7791_CLK_P),
+ DEF_MOD("can0", 916, R8A7791_CLK_P),
+ DEF_MOD("qspi_mod", 917, R8A7791_CLK_QSPI),
+ DEF_MOD("i2c5", 925, R8A7791_CLK_HP),
+ DEF_MOD("iicdvfs", 926, R8A7791_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A7791_CLK_HP),
+ DEF_MOD("i2c3", 928, R8A7791_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A7791_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A7791_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A7791_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A7791_CLK_P),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7791_CLK_P),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+ DEF_MOD("scifa3", 1106, R8A7791_CLK_MP),
+ DEF_MOD("scifa4", 1107, R8A7791_CLK_MP),
+ DEF_MOD("scifa5", 1108, R8A7791_CLK_MP),
+};
+
+static const unsigned int r8a7791_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz) *1 *1
+ *---------------------------------------------------
+ * 0 0 0 15 x172/2 x208/2 x106
+ * 0 0 1 15 x172/2 x208/2 x88
+ * 0 1 0 20 x130/2 x156/2 x80
+ * 0 1 1 20 x130/2 x156/2 x66
+ * 1 0 0 26 / 2 x200/2 x240/2 x122
+ * 1 0 1 26 / 2 x200/2 x240/2 x102
+ * 1 1 0 30 / 2 x172/2 x208/2 x106
+ * 1 1 1 30 / 2 x172/2 x208/2 x88
+ *
+ * *1 : Table 7.5a indicates VCO output (PLLx = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
+ (((md) & BIT(13)) >> 12) | \
+ (((md) & BIT(19)) >> 19))
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+ { 1, 208, 106 }, { 1, 208, 88 }, { 1, 156, 80 }, { 1, 156, 66 },
+ { 2, 240, 122 }, { 2, 240, 102 }, { 2, 208, 106 }, { 2, 208, 88 },
+};
+
+static int __init r8a7791_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ struct device_node *np = dev->of_node;
+ unsigned int i;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ if (of_device_is_compatible(np, "renesas,r8a7793-cpg-mssr")) {
+ /* R-Car M2-N uses a 1/5 divider for ZG */
+ for (i = 0; i < ARRAY_SIZE(r8a7791_core_clks); i++)
+ if (r8a7791_core_clks[i].id == R8A7791_CLK_ZG) {
+ r8a7791_core_clks[i].div = 5;
+ break;
+ }
+ }
+ return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7791_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7791_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7791_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7791_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7791_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7791_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7791_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7791_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7792-cpg-mssr.c b/drivers/clk/renesas/r8a7792-cpg-mssr.c
new file mode 100644
index 000000000..77af25087
--- /dev/null
+++ b/drivers/clk/renesas/r8a7792-cpg-mssr.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7792 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2017 Glider bvba
+ *
+ * Based on clk-rcar-gen2.c
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7792-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7792_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7792_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("qspi", R8A7792_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+
+ DEF_FIXED("z", R8A7792_CLK_Z, CLK_PLL0, 1, 1),
+ DEF_FIXED("zg", R8A7792_CLK_ZG, CLK_PLL1, 5, 1),
+ DEF_FIXED("zx", R8A7792_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A7792_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A7792_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("i", R8A7792_CLK_I, CLK_PLL1, 3, 1),
+ DEF_FIXED("b", R8A7792_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("lb", R8A7792_CLK_LB, CLK_PLL1, 24, 1),
+ DEF_FIXED("p", R8A7792_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A7792_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A7792_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("imp", R8A7792_CLK_IMP, CLK_PLL1, 4, 1),
+ DEF_FIXED("zb3", R8A7792_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("zb3d2", R8A7792_CLK_ZB3D2, CLK_PLL3, 8, 1),
+ DEF_FIXED("ddr", R8A7792_CLK_DDR, CLK_PLL3, 8, 1),
+ DEF_FIXED("sd", R8A7792_CLK_SD, CLK_PLL1_DIV2, 8, 1),
+ DEF_FIXED("mp", R8A7792_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cp", R8A7792_CLK_CP, CLK_PLL1, 48, 1),
+ DEF_FIXED("cpex", R8A7792_CLK_CPEX, CLK_EXTAL, 2, 1),
+ DEF_FIXED("rcan", R8A7792_CLK_RCAN, CLK_PLL1_DIV2, 49, 1),
+ DEF_FIXED("r", R8A7792_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A7792_CLK_OSC, CLK_PLL1, 12288, 1),
+};
+
+static const struct mssr_mod_clk r8a7792_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A7792_CLK_MP),
+ DEF_MOD("jpu", 106, R8A7792_CLK_M2),
+ DEF_MOD("tmu1", 111, R8A7792_CLK_P),
+ DEF_MOD("3dg", 112, R8A7792_CLK_ZG),
+ DEF_MOD("2d-dmac", 115, R8A7792_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A7792_CLK_P),
+ DEF_MOD("tmu2", 122, R8A7792_CLK_P),
+ DEF_MOD("cmt0", 124, R8A7792_CLK_R),
+ DEF_MOD("tmu0", 125, R8A7792_CLK_CP),
+ DEF_MOD("vsp1du1", 127, R8A7792_CLK_ZS),
+ DEF_MOD("vsp1du0", 128, R8A7792_CLK_ZS),
+ DEF_MOD("vsps", 131, R8A7792_CLK_ZS),
+ DEF_MOD("msiof1", 208, R8A7792_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A7792_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A7792_CLK_ZS),
+ DEF_MOD("tpu0", 304, R8A7792_CLK_CP),
+ DEF_MOD("sdhi0", 314, R8A7792_CLK_SD),
+ DEF_MOD("cmt1", 329, R8A7792_CLK_R),
+ DEF_MOD("rwdt", 402, R8A7792_CLK_R),
+ DEF_MOD("irqc", 407, R8A7792_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A7792_CLK_ZS),
+ DEF_MOD("audio-dmac0", 502, R8A7792_CLK_HP),
+ DEF_MOD("thermal", 522, CLK_EXTAL),
+ DEF_MOD("pwm", 523, R8A7792_CLK_P),
+ DEF_MOD("hscif1", 716, R8A7792_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A7792_CLK_ZS),
+ DEF_MOD("scif3", 718, R8A7792_CLK_P),
+ DEF_MOD("scif2", 719, R8A7792_CLK_P),
+ DEF_MOD("scif1", 720, R8A7792_CLK_P),
+ DEF_MOD("scif0", 721, R8A7792_CLK_P),
+ DEF_MOD("du1", 723, R8A7792_CLK_ZX),
+ DEF_MOD("du0", 724, R8A7792_CLK_ZX),
+ DEF_MOD("vin5", 804, R8A7792_CLK_ZG),
+ DEF_MOD("vin4", 805, R8A7792_CLK_ZG),
+ DEF_MOD("vin3", 808, R8A7792_CLK_ZG),
+ DEF_MOD("vin2", 809, R8A7792_CLK_ZG),
+ DEF_MOD("vin1", 810, R8A7792_CLK_ZG),
+ DEF_MOD("vin0", 811, R8A7792_CLK_ZG),
+ DEF_MOD("etheravb", 812, R8A7792_CLK_HP),
+ DEF_MOD("imr-lx3", 821, R8A7792_CLK_ZG),
+ DEF_MOD("imr-lsx3-1", 822, R8A7792_CLK_ZG),
+ DEF_MOD("imr-lsx3-0", 823, R8A7792_CLK_ZG),
+ DEF_MOD("imr-lsx3-5", 825, R8A7792_CLK_ZG),
+ DEF_MOD("imr-lsx3-4", 826, R8A7792_CLK_ZG),
+ DEF_MOD("imr-lsx3-3", 827, R8A7792_CLK_ZG),
+ DEF_MOD("imr-lsx3-2", 828, R8A7792_CLK_ZG),
+ DEF_MOD("gyro-adc", 901, R8A7792_CLK_P),
+ DEF_MOD("gpio7", 904, R8A7792_CLK_CP),
+ DEF_MOD("gpio6", 905, R8A7792_CLK_CP),
+ DEF_MOD("gpio5", 907, R8A7792_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A7792_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A7792_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A7792_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A7792_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A7792_CLK_CP),
+ DEF_MOD("gpio11", 913, R8A7792_CLK_CP),
+ DEF_MOD("gpio10", 914, R8A7792_CLK_CP),
+ DEF_MOD("can1", 915, R8A7792_CLK_P),
+ DEF_MOD("can0", 916, R8A7792_CLK_P),
+ DEF_MOD("qspi_mod", 917, R8A7792_CLK_QSPI),
+ DEF_MOD("gpio9", 919, R8A7792_CLK_CP),
+ DEF_MOD("gpio8", 921, R8A7792_CLK_CP),
+ DEF_MOD("i2c5", 925, R8A7792_CLK_HP),
+ DEF_MOD("iicdvfs", 926, R8A7792_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A7792_CLK_HP),
+ DEF_MOD("i2c3", 928, R8A7792_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A7792_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A7792_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A7792_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A7792_CLK_P),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+};
+
+static const unsigned int r8a7792_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz) *1 *2
+ *---------------------------------------------------
+ * 0 0 0 15 x200/3 x208/2 x106
+ * 0 0 1 15 x200/3 x208/2 x88
+ * 0 1 0 20 x150/3 x156/2 x80
+ * 0 1 1 20 x150/3 x156/2 x66
+ * 1 0 0 26 / 2 x230/3 x240/2 x122
+ * 1 0 1 26 / 2 x230/3 x240/2 x102
+ * 1 1 0 30 / 2 x200/3 x208/2 x106
+ * 1 1 1 30 / 2 x200/3 x208/2 x88
+ *
+ * *1 : Table 7.5b indicates VCO output (PLL0 = VCO/3)
+ * *2 : Table 7.5b indicates VCO output (PLL1 = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
+ (((md) & BIT(13)) >> 12) | \
+ (((md) & BIT(19)) >> 19))
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+ { 1, 208, 106, 200 },
+ { 1, 208, 88, 200 },
+ { 1, 156, 80, 150 },
+ { 1, 156, 66, 150 },
+ { 2, 240, 122, 230 },
+ { 2, 240, 102, 230 },
+ { 2, 208, 106, 200 },
+ { 2, 208, 88, 200 },
+};
+
+static int __init r8a7792_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen2_cpg_init(cpg_pll_config, 3, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7792_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7792_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7792_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7792_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7792_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7792_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7792_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7792_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7794-cpg-mssr.c b/drivers/clk/renesas/r8a7794-cpg-mssr.c
new file mode 100644
index 000000000..4d7fa26a7
--- /dev/null
+++ b/drivers/clk/renesas/r8a7794-cpg-mssr.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7794 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2017 Glider bvba
+ *
+ * Based on clk-rcar-gen2.c
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7794-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7794_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_USB_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7794_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_BASE("adsp", R8A7794_CLK_ADSP, CLK_TYPE_GEN2_ADSP, CLK_PLL1),
+ DEF_BASE("sdh", R8A7794_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
+ DEF_BASE("sd0", R8A7794_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
+ DEF_BASE("qspi", R8A7794_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+ DEF_BASE("rcan", R8A7794_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+ DEF_FIXED("z2", R8A7794_CLK_Z2, CLK_PLL0, 1, 1),
+ DEF_FIXED("zg", R8A7794_CLK_ZG, CLK_PLL1, 6, 1),
+ DEF_FIXED("zx", R8A7794_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("zs", R8A7794_CLK_ZS, CLK_PLL1, 6, 1),
+ DEF_FIXED("hp", R8A7794_CLK_HP, CLK_PLL1, 12, 1),
+ DEF_FIXED("i", R8A7794_CLK_I, CLK_PLL1, 2, 1),
+ DEF_FIXED("b", R8A7794_CLK_B, CLK_PLL1, 12, 1),
+ DEF_FIXED("lb", R8A7794_CLK_LB, CLK_PLL1, 24, 1),
+ DEF_FIXED("p", R8A7794_CLK_P, CLK_PLL1, 24, 1),
+ DEF_FIXED("cl", R8A7794_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("cp", R8A7794_CLK_CP, CLK_PLL1, 48, 1),
+ DEF_FIXED("m2", R8A7794_CLK_M2, CLK_PLL1, 8, 1),
+ DEF_FIXED("zb3", R8A7794_CLK_ZB3, CLK_PLL3, 4, 1),
+ DEF_FIXED("zb3d2", R8A7794_CLK_ZB3D2, CLK_PLL3, 8, 1),
+ DEF_FIXED("ddr", R8A7794_CLK_DDR, CLK_PLL3, 8, 1),
+ DEF_FIXED("mp", R8A7794_CLK_MP, CLK_PLL1_DIV2, 15, 1),
+ DEF_FIXED("cpex", R8A7794_CLK_CPEX, CLK_EXTAL, 2, 1),
+ DEF_FIXED("r", R8A7794_CLK_R, CLK_PLL1, 49152, 1),
+ DEF_FIXED("osc", R8A7794_CLK_OSC, CLK_PLL1, 12288, 1),
+
+ DEF_DIV6P1("sd2", R8A7794_CLK_SD2, CLK_PLL1_DIV2, 0x078),
+ DEF_DIV6P1("sd3", R8A7794_CLK_SD3, CLK_PLL1_DIV2, 0x26c),
+ DEF_DIV6P1("mmc0", R8A7794_CLK_MMC0, CLK_PLL1_DIV2, 0x240),
+};
+
+static const struct mssr_mod_clk r8a7794_mod_clks[] __initconst = {
+ DEF_MOD("msiof0", 0, R8A7794_CLK_MP),
+ DEF_MOD("vcp0", 101, R8A7794_CLK_ZS),
+ DEF_MOD("vpc0", 103, R8A7794_CLK_ZS),
+ DEF_MOD("jpu", 106, R8A7794_CLK_M2),
+ DEF_MOD("tmu1", 111, R8A7794_CLK_P),
+ DEF_MOD("3dg", 112, R8A7794_CLK_ZG),
+ DEF_MOD("2d-dmac", 115, R8A7794_CLK_ZS),
+ DEF_MOD("fdp1-0", 119, R8A7794_CLK_ZS),
+ DEF_MOD("tmu3", 121, R8A7794_CLK_P),
+ DEF_MOD("tmu2", 122, R8A7794_CLK_P),
+ DEF_MOD("cmt0", 124, R8A7794_CLK_R),
+ DEF_MOD("tmu0", 125, R8A7794_CLK_CP),
+ DEF_MOD("vsp1du0", 128, R8A7794_CLK_ZS),
+ DEF_MOD("vsps", 131, R8A7794_CLK_ZS),
+ DEF_MOD("scifa2", 202, R8A7794_CLK_MP),
+ DEF_MOD("scifa1", 203, R8A7794_CLK_MP),
+ DEF_MOD("scifa0", 204, R8A7794_CLK_MP),
+ DEF_MOD("msiof2", 205, R8A7794_CLK_MP),
+ DEF_MOD("scifb0", 206, R8A7794_CLK_MP),
+ DEF_MOD("scifb1", 207, R8A7794_CLK_MP),
+ DEF_MOD("msiof1", 208, R8A7794_CLK_MP),
+ DEF_MOD("scifb2", 216, R8A7794_CLK_MP),
+ DEF_MOD("sys-dmac1", 218, R8A7794_CLK_ZS),
+ DEF_MOD("sys-dmac0", 219, R8A7794_CLK_ZS),
+ DEF_MOD("tpu0", 304, R8A7794_CLK_CP),
+ DEF_MOD("sdhi3", 311, R8A7794_CLK_SD3),
+ DEF_MOD("sdhi2", 312, R8A7794_CLK_SD2),
+ DEF_MOD("sdhi0", 314, R8A7794_CLK_SD0),
+ DEF_MOD("mmcif0", 315, R8A7794_CLK_MMC0),
+ DEF_MOD("iic0", 318, R8A7794_CLK_HP),
+ DEF_MOD("iic1", 323, R8A7794_CLK_HP),
+ DEF_MOD("cmt1", 329, R8A7794_CLK_R),
+ DEF_MOD("usbhs-dmac0", 330, R8A7794_CLK_HP),
+ DEF_MOD("usbhs-dmac1", 331, R8A7794_CLK_HP),
+ DEF_MOD("rwdt", 402, R8A7794_CLK_R),
+ DEF_MOD("irqc", 407, R8A7794_CLK_CP),
+ DEF_MOD("intc-sys", 408, R8A7794_CLK_ZS),
+ DEF_MOD("audio-dmac0", 502, R8A7794_CLK_HP),
+ DEF_MOD("adsp_mod", 506, R8A7794_CLK_ADSP),
+ DEF_MOD("pwm", 523, R8A7794_CLK_P),
+ DEF_MOD("usb-ehci", 703, R8A7794_CLK_MP),
+ DEF_MOD("usbhs", 704, R8A7794_CLK_HP),
+ DEF_MOD("hscif2", 713, R8A7794_CLK_ZS),
+ DEF_MOD("scif5", 714, R8A7794_CLK_P),
+ DEF_MOD("scif4", 715, R8A7794_CLK_P),
+ DEF_MOD("hscif1", 716, R8A7794_CLK_ZS),
+ DEF_MOD("hscif0", 717, R8A7794_CLK_ZS),
+ DEF_MOD("scif3", 718, R8A7794_CLK_P),
+ DEF_MOD("scif2", 719, R8A7794_CLK_P),
+ DEF_MOD("scif1", 720, R8A7794_CLK_P),
+ DEF_MOD("scif0", 721, R8A7794_CLK_P),
+ DEF_MOD("du1", 723, R8A7794_CLK_ZX),
+ DEF_MOD("du0", 724, R8A7794_CLK_ZX),
+ DEF_MOD("ipmmu-sgx", 800, R8A7794_CLK_ZX),
+ DEF_MOD("mlb", 802, R8A7794_CLK_HP),
+ DEF_MOD("vin1", 810, R8A7794_CLK_ZG),
+ DEF_MOD("vin0", 811, R8A7794_CLK_ZG),
+ DEF_MOD("etheravb", 812, R8A7794_CLK_HP),
+ DEF_MOD("ether", 813, R8A7794_CLK_P),
+ DEF_MOD("gyro-adc", 901, R8A7794_CLK_P),
+ DEF_MOD("gpio6", 905, R8A7794_CLK_CP),
+ DEF_MOD("gpio5", 907, R8A7794_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A7794_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A7794_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A7794_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A7794_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A7794_CLK_CP),
+ DEF_MOD("can1", 915, R8A7794_CLK_P),
+ DEF_MOD("can0", 916, R8A7794_CLK_P),
+ DEF_MOD("qspi_mod", 917, R8A7794_CLK_QSPI),
+ DEF_MOD("i2c5", 925, R8A7794_CLK_HP),
+ DEF_MOD("i2c4", 927, R8A7794_CLK_HP),
+ DEF_MOD("i2c3", 928, R8A7794_CLK_HP),
+ DEF_MOD("i2c2", 929, R8A7794_CLK_HP),
+ DEF_MOD("i2c1", 930, R8A7794_CLK_HP),
+ DEF_MOD("i2c0", 931, R8A7794_CLK_HP),
+ DEF_MOD("ssi-all", 1005, R8A7794_CLK_P),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7794_CLK_P),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scifa3", 1106, R8A7794_CLK_MP),
+ DEF_MOD("scifa4", 1107, R8A7794_CLK_MP),
+ DEF_MOD("scifa5", 1108, R8A7794_CLK_MP),
+};
+
+static const unsigned int r8a7794_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz) *1 *2
+ *---------------------------------------------------
+ * 0 0 1 15 x200/3 x208/2 x88
+ * 0 1 1 20 x150/3 x156/2 x66
+ * 1 0 1 26 / 2 x230/3 x240/2 x102
+ * 1 1 1 30 / 2 x200/3 x208/2 x88
+ *
+ * *1 : Table 7.5c indicates VCO output (PLL0 = VCO/3)
+ * *2 : Table 7.5c indicates VCO output (PLL1 = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
+ (((md) & BIT(13)) >> 13))
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[4] __initconst = {
+ { 1, 208, 88, 200 },
+ { 1, 156, 66, 150 },
+ { 2, 240, 102, 230 },
+ { 2, 208, 88, 200 },
+};
+
+static int __init r8a7794_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen2_cpg_init(cpg_pll_config, 3, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7794_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7794_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7794_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7794_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7794_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7794_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7794_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7794_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c
new file mode 100644
index 000000000..e47d9b1fc
--- /dev/null
+++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c
@@ -0,0 +1,398 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7795 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2018-2019 Renesas Electronics Corp.
+ *
+ * Based on clk-rcar-gen3.c
+ *
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+#include <linux/sys_soc.h>
+
+#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7795_CLK_S0D12,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL3,
+ CLK_PLL4,
+ CLK_PLL1_DIV2,
+ CLK_PLL1_DIV4,
+ CLK_S0,
+ CLK_S1,
+ CLK_S2,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_SSPSRC,
+ CLK_RPCSRC,
+ CLK_RINT,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+ DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1),
+ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
+
+ DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32),
+
+ /* Core Clock Outputs */
+ DEF_GEN3_Z("z", R8A7795_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8),
+ DEF_GEN3_Z("z2", R8A7795_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL2, 2, 0),
+ DEF_GEN3_Z("zg", R8A7795_CLK_ZG, CLK_TYPE_GEN3_ZG, CLK_PLL4, 4, 24),
+ DEF_FIXED("ztr", R8A7795_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED("ztrd2", R8A7795_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+ DEF_FIXED("zt", R8A7795_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED("zx", R8A7795_CLK_ZX, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED("s0d1", R8A7795_CLK_S0D1, CLK_S0, 1, 1),
+ DEF_FIXED("s0d2", R8A7795_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A7795_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A7795_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6", R8A7795_CLK_S0D6, CLK_S0, 6, 1),
+ DEF_FIXED("s0d8", R8A7795_CLK_S0D8, CLK_S0, 8, 1),
+ DEF_FIXED("s0d12", R8A7795_CLK_S0D12, CLK_S0, 12, 1),
+ DEF_FIXED("s1d1", R8A7795_CLK_S1D1, CLK_S1, 1, 1),
+ DEF_FIXED("s1d2", R8A7795_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A7795_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s2d1", R8A7795_CLK_S2D1, CLK_S2, 1, 1),
+ DEF_FIXED("s2d2", R8A7795_CLK_S2D2, CLK_S2, 2, 1),
+ DEF_FIXED("s2d4", R8A7795_CLK_S2D4, CLK_S2, 4, 1),
+ DEF_FIXED("s3d1", R8A7795_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1),
+
+ DEF_GEN3_SDH("sd0h", R8A7795_CLK_SD0H, CLK_SDSRC, 0x074),
+ DEF_GEN3_SDH("sd1h", R8A7795_CLK_SD1H, CLK_SDSRC, 0x078),
+ DEF_GEN3_SDH("sd2h", R8A7795_CLK_SD2H, CLK_SDSRC, 0x268),
+ DEF_GEN3_SDH("sd3h", R8A7795_CLK_SD3H, CLK_SDSRC, 0x26c),
+ DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, R8A7795_CLK_SD0H, 0x074),
+ DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, R8A7795_CLK_SD1H, 0x078),
+ DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, R8A7795_CLK_SD2H, 0x268),
+ DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, R8A7795_CLK_SD3H, 0x26c),
+
+ DEF_BASE("rpc", R8A7795_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A7795_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A7795_CLK_RPC),
+
+ DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1),
+ DEF_FIXED("cr", R8A7795_CLK_CR, CLK_PLL1_DIV4, 2, 1),
+ DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A7795_CLK_CPEX, CLK_EXTAL, 2, 1),
+
+ DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+ DEF_DIV6P1("csi0", R8A7795_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
+ DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014),
+ DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV4, 0x250),
+
+ DEF_GEN3_OSC("osc", R8A7795_CLK_OSC, CLK_EXTAL, 8),
+
+ DEF_BASE("r", R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
+};
+
+static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
+ DEF_MOD("3dge", 112, R8A7795_CLK_ZG),
+ DEF_MOD("fdp1-1", 118, R8A7795_CLK_S0D1),
+ DEF_MOD("fdp1-0", 119, R8A7795_CLK_S0D1),
+ DEF_MOD("tmu4", 121, R8A7795_CLK_S0D6),
+ DEF_MOD("tmu3", 122, R8A7795_CLK_S3D2),
+ DEF_MOD("tmu2", 123, R8A7795_CLK_S3D2),
+ DEF_MOD("tmu1", 124, R8A7795_CLK_S3D2),
+ DEF_MOD("tmu0", 125, R8A7795_CLK_CP),
+ DEF_MOD("scif5", 202, R8A7795_CLK_S3D4),
+ DEF_MOD("scif4", 203, R8A7795_CLK_S3D4),
+ DEF_MOD("scif3", 204, R8A7795_CLK_S3D4),
+ DEF_MOD("scif1", 206, R8A7795_CLK_S3D4),
+ DEF_MOD("scif0", 207, R8A7795_CLK_S3D4),
+ DEF_MOD("msiof3", 208, R8A7795_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A7795_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A7795_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A7795_CLK_MSO),
+ DEF_MOD("sys-dmac2", 217, R8A7795_CLK_S3D1),
+ DEF_MOD("sys-dmac1", 218, R8A7795_CLK_S3D1),
+ DEF_MOD("sys-dmac0", 219, R8A7795_CLK_S0D3),
+ DEF_MOD("sceg-pub", 229, R8A7795_CLK_CR),
+ DEF_MOD("cmt3", 300, R8A7795_CLK_R),
+ DEF_MOD("cmt2", 301, R8A7795_CLK_R),
+ DEF_MOD("cmt1", 302, R8A7795_CLK_R),
+ DEF_MOD("cmt0", 303, R8A7795_CLK_R),
+ DEF_MOD("tpu0", 304, R8A7795_CLK_S3D4),
+ DEF_MOD("scif2", 310, R8A7795_CLK_S3D4),
+ DEF_MOD("sdif3", 311, R8A7795_CLK_SD3),
+ DEF_MOD("sdif2", 312, R8A7795_CLK_SD2),
+ DEF_MOD("sdif1", 313, R8A7795_CLK_SD1),
+ DEF_MOD("sdif0", 314, R8A7795_CLK_SD0),
+ DEF_MOD("pcie1", 318, R8A7795_CLK_S3D1),
+ DEF_MOD("pcie0", 319, R8A7795_CLK_S3D1),
+ DEF_MOD("usb-dmac30", 326, R8A7795_CLK_S3D1),
+ DEF_MOD("usb3-if0", 328, R8A7795_CLK_S3D1),
+ DEF_MOD("usb-dmac31", 329, R8A7795_CLK_S3D1),
+ DEF_MOD("usb-dmac0", 330, R8A7795_CLK_S3D1),
+ DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1),
+ DEF_MOD("rwdt", 402, R8A7795_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A7795_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A7795_CLK_S0D3),
+ DEF_MOD("audmac1", 501, R8A7795_CLK_S1D2),
+ DEF_MOD("audmac0", 502, R8A7795_CLK_S1D2),
+ DEF_MOD("drif31", 508, R8A7795_CLK_S3D2),
+ DEF_MOD("drif30", 509, R8A7795_CLK_S3D2),
+ DEF_MOD("drif21", 510, R8A7795_CLK_S3D2),
+ DEF_MOD("drif20", 511, R8A7795_CLK_S3D2),
+ DEF_MOD("drif11", 512, R8A7795_CLK_S3D2),
+ DEF_MOD("drif10", 513, R8A7795_CLK_S3D2),
+ DEF_MOD("drif01", 514, R8A7795_CLK_S3D2),
+ DEF_MOD("drif00", 515, R8A7795_CLK_S3D2),
+ DEF_MOD("hscif4", 516, R8A7795_CLK_S3D1),
+ DEF_MOD("hscif3", 517, R8A7795_CLK_S3D1),
+ DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1),
+ DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1),
+ DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1),
+ DEF_MOD("thermal", 522, R8A7795_CLK_CP),
+ DEF_MOD("pwm", 523, R8A7795_CLK_S0D12),
+ DEF_MOD("fcpvd2", 601, R8A7795_CLK_S0D2),
+ DEF_MOD("fcpvd1", 602, R8A7795_CLK_S0D2),
+ DEF_MOD("fcpvd0", 603, R8A7795_CLK_S0D2),
+ DEF_MOD("fcpvb1", 606, R8A7795_CLK_S0D1),
+ DEF_MOD("fcpvb0", 607, R8A7795_CLK_S0D1),
+ DEF_MOD("fcpvi1", 610, R8A7795_CLK_S0D1),
+ DEF_MOD("fcpvi0", 611, R8A7795_CLK_S0D1),
+ DEF_MOD("fcpf1", 614, R8A7795_CLK_S0D1),
+ DEF_MOD("fcpf0", 615, R8A7795_CLK_S0D1),
+ DEF_MOD("fcpcs", 619, R8A7795_CLK_S0D1),
+ DEF_MOD("vspd2", 621, R8A7795_CLK_S0D2),
+ DEF_MOD("vspd1", 622, R8A7795_CLK_S0D2),
+ DEF_MOD("vspd0", 623, R8A7795_CLK_S0D2),
+ DEF_MOD("vspbc", 624, R8A7795_CLK_S0D1),
+ DEF_MOD("vspbd", 626, R8A7795_CLK_S0D1),
+ DEF_MOD("vspi1", 630, R8A7795_CLK_S0D1),
+ DEF_MOD("vspi0", 631, R8A7795_CLK_S0D1),
+ DEF_MOD("ehci3", 700, R8A7795_CLK_S3D2),
+ DEF_MOD("ehci2", 701, R8A7795_CLK_S3D2),
+ DEF_MOD("ehci1", 702, R8A7795_CLK_S3D2),
+ DEF_MOD("ehci0", 703, R8A7795_CLK_S3D2),
+ DEF_MOD("hsusb", 704, R8A7795_CLK_S3D2),
+ DEF_MOD("hsusb3", 705, R8A7795_CLK_S3D2),
+ DEF_MOD("cmm3", 708, R8A7795_CLK_S2D1),
+ DEF_MOD("cmm2", 709, R8A7795_CLK_S2D1),
+ DEF_MOD("cmm1", 710, R8A7795_CLK_S2D1),
+ DEF_MOD("cmm0", 711, R8A7795_CLK_S2D1),
+ DEF_MOD("csi20", 714, R8A7795_CLK_CSI0),
+ DEF_MOD("csi41", 715, R8A7795_CLK_CSI0),
+ DEF_MOD("csi40", 716, R8A7795_CLK_CSI0),
+ DEF_MOD("du3", 721, R8A7795_CLK_S2D1),
+ DEF_MOD("du2", 722, R8A7795_CLK_S2D1),
+ DEF_MOD("du1", 723, R8A7795_CLK_S2D1),
+ DEF_MOD("du0", 724, R8A7795_CLK_S2D1),
+ DEF_MOD("lvds", 727, R8A7795_CLK_S0D4),
+ DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI),
+ DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI),
+ DEF_MOD("mlp", 802, R8A7795_CLK_S2D1),
+ DEF_MOD("vin7", 804, R8A7795_CLK_S0D2),
+ DEF_MOD("vin6", 805, R8A7795_CLK_S0D2),
+ DEF_MOD("vin5", 806, R8A7795_CLK_S0D2),
+ DEF_MOD("vin4", 807, R8A7795_CLK_S0D2),
+ DEF_MOD("vin3", 808, R8A7795_CLK_S0D2),
+ DEF_MOD("vin2", 809, R8A7795_CLK_S0D2),
+ DEF_MOD("vin1", 810, R8A7795_CLK_S0D2),
+ DEF_MOD("vin0", 811, R8A7795_CLK_S0D2),
+ DEF_MOD("etheravb", 812, R8A7795_CLK_S0D6),
+ DEF_MOD("sata0", 815, R8A7795_CLK_S3D2),
+ DEF_MOD("imr3", 820, R8A7795_CLK_S0D2),
+ DEF_MOD("imr2", 821, R8A7795_CLK_S0D2),
+ DEF_MOD("imr1", 822, R8A7795_CLK_S0D2),
+ DEF_MOD("imr0", 823, R8A7795_CLK_S0D2),
+ DEF_MOD("gpio7", 905, R8A7795_CLK_S3D4),
+ DEF_MOD("gpio6", 906, R8A7795_CLK_S3D4),
+ DEF_MOD("gpio5", 907, R8A7795_CLK_S3D4),
+ DEF_MOD("gpio4", 908, R8A7795_CLK_S3D4),
+ DEF_MOD("gpio3", 909, R8A7795_CLK_S3D4),
+ DEF_MOD("gpio2", 910, R8A7795_CLK_S3D4),
+ DEF_MOD("gpio1", 911, R8A7795_CLK_S3D4),
+ DEF_MOD("gpio0", 912, R8A7795_CLK_S3D4),
+ DEF_MOD("can-fd", 914, R8A7795_CLK_S3D2),
+ DEF_MOD("can-if1", 915, R8A7795_CLK_S3D4),
+ DEF_MOD("can-if0", 916, R8A7795_CLK_S3D4),
+ DEF_MOD("rpc-if", 917, R8A7795_CLK_RPCD2),
+ DEF_MOD("i2c6", 918, R8A7795_CLK_S0D6),
+ DEF_MOD("i2c5", 919, R8A7795_CLK_S0D6),
+ DEF_MOD("adg", 922, R8A7795_CLK_S0D4),
+ DEF_MOD("i2c-dvfs", 926, R8A7795_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A7795_CLK_S0D6),
+ DEF_MOD("i2c3", 928, R8A7795_CLK_S0D6),
+ DEF_MOD("i2c2", 929, R8A7795_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A7795_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A7795_CLK_S3D2),
+ DEF_MOD("ssi-all", 1005, R8A7795_CLK_S3D4),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7795_CLK_S3D4),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a7795_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4 OSC
+ * 14 13 19 17 (MHz)
+ *-------------------------------------------------------------------------
+ * 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144 /16
+ * 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144 /16
+ * 0 0 1 0 Prohibited setting
+ * 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144 /16
+ * 0 1 0 0 20 x 1 x150 x160 x120 x160 x120 /19
+ * 0 1 0 1 20 x 1 x150 x160 x120 x106 x120 /19
+ * 0 1 1 0 Prohibited setting
+ * 0 1 1 1 20 x 1 x150 x160 x120 x160 x120 /19
+ * 1 0 0 0 25 x 1 x120 x128 x96 x128 x96 /24
+ * 1 0 0 1 25 x 1 x120 x128 x96 x84 x96 /24
+ * 1 0 1 0 Prohibited setting
+ * 1 0 1 1 25 x 1 x120 x128 x96 x128 x96 /24
+ * 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144 /32
+ * 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144 /32
+ * 1 1 1 0 Prohibited setting
+ * 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144 /32
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \
+ (((md) & BIT(13)) >> 11) | \
+ (((md) & BIT(19)) >> 18) | \
+ (((md) & BIT(17)) >> 17))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 192, 1, 128, 1, 16, },
+ { 0, /* Prohibited setting */ },
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 160, 1, 106, 1, 19, },
+ { 0, /* Prohibited setting */ },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 128, 1, 128, 1, 24, },
+ { 1, 128, 1, 84, 1, 24, },
+ { 0, /* Prohibited setting */ },
+ { 1, 128, 1, 128, 1, 24, },
+ { 2, 192, 1, 192, 1, 32, },
+ { 2, 192, 1, 128, 1, 32, },
+ { 0, /* Prohibited setting */ },
+ { 2, 192, 1, 192, 1, 32, },
+};
+
+static const struct soc_device_attribute r8a7795_denylist[] __initconst = {
+ { .soc_id = "r8a7795", .revision = "ES1.*" },
+ { /* sentinel */ }
+};
+
+static int __init r8a7795_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ /*
+ * We panic here to ensure removed SoCs and clk updates are always in
+ * sync to avoid overclocking damages. The panic can only be seen with
+ * commandline args 'earlycon keep_bootcon'. But these SoCs were for
+ * developers only anyhow.
+ */
+ if (soc_device_match(r8a7795_denylist))
+ panic("SoC not supported anymore!\n");
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+ if (!cpg_pll_config->extal_div) {
+ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+ return -EINVAL;
+ }
+
+ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7795_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7795_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7795_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7795_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7795_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7795_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7795_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c
new file mode 100644
index 000000000..e5f9e3e74
--- /dev/null
+++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c
@@ -0,0 +1,383 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a7796 (R-Car M3-W/W+) Clock Pulse Generator / Module Standby and Software
+ * Reset
+ *
+ * Copyright (C) 2016-2019 Glider bvba
+ * Copyright (C) 2018-2019 Renesas Electronics Corp.
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A7796_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL3,
+ CLK_PLL4,
+ CLK_PLL1_DIV2,
+ CLK_PLL1_DIV4,
+ CLK_S0,
+ CLK_S1,
+ CLK_S2,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_SSPSRC,
+ CLK_RPCSRC,
+ CLK_RINT,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+ DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1),
+ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
+
+ DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32),
+
+ /* Core Clock Outputs */
+ DEF_GEN3_Z("z", R8A7796_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8),
+ DEF_GEN3_Z("z2", R8A7796_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL2, 2, 0),
+ DEF_GEN3_Z("zg", R8A7796_CLK_ZG, CLK_TYPE_GEN3_ZG, CLK_PLL4, 4, 24),
+ DEF_FIXED("ztr", R8A7796_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED("ztrd2", R8A7796_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+ DEF_FIXED("zt", R8A7796_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED("zx", R8A7796_CLK_ZX, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED("s0d1", R8A7796_CLK_S0D1, CLK_S0, 1, 1),
+ DEF_FIXED("s0d2", R8A7796_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A7796_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A7796_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6", R8A7796_CLK_S0D6, CLK_S0, 6, 1),
+ DEF_FIXED("s0d8", R8A7796_CLK_S0D8, CLK_S0, 8, 1),
+ DEF_FIXED("s0d12", R8A7796_CLK_S0D12, CLK_S0, 12, 1),
+ DEF_FIXED("s1d1", R8A7796_CLK_S1D1, CLK_S1, 1, 1),
+ DEF_FIXED("s1d2", R8A7796_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A7796_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s2d1", R8A7796_CLK_S2D1, CLK_S2, 1, 1),
+ DEF_FIXED("s2d2", R8A7796_CLK_S2D2, CLK_S2, 2, 1),
+ DEF_FIXED("s2d4", R8A7796_CLK_S2D4, CLK_S2, 4, 1),
+ DEF_FIXED("s3d1", R8A7796_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A7796_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A7796_CLK_S3D4, CLK_S3, 4, 1),
+
+ DEF_GEN3_SDH("sd0h", R8A7796_CLK_SD0H, CLK_SDSRC, 0x074),
+ DEF_GEN3_SDH("sd1h", R8A7796_CLK_SD1H, CLK_SDSRC, 0x078),
+ DEF_GEN3_SDH("sd2h", R8A7796_CLK_SD2H, CLK_SDSRC, 0x268),
+ DEF_GEN3_SDH("sd3h", R8A7796_CLK_SD3H, CLK_SDSRC, 0x26c),
+ DEF_GEN3_SD("sd0", R8A7796_CLK_SD0, R8A7796_CLK_SD0H, 0x074),
+ DEF_GEN3_SD("sd1", R8A7796_CLK_SD1, R8A7796_CLK_SD1H, 0x078),
+ DEF_GEN3_SD("sd2", R8A7796_CLK_SD2, R8A7796_CLK_SD2H, 0x268),
+ DEF_GEN3_SD("sd3", R8A7796_CLK_SD3, R8A7796_CLK_SD3H, 0x26c),
+
+ DEF_BASE("rpc", R8A7796_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A7796_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A7796_CLK_RPC),
+
+ DEF_FIXED("cl", R8A7796_CLK_CL, CLK_PLL1_DIV2, 48, 1),
+ DEF_FIXED("cr", R8A7796_CLK_CR, CLK_PLL1_DIV4, 2, 1),
+ DEF_FIXED("cp", R8A7796_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A7796_CLK_CPEX, CLK_EXTAL, 2, 1),
+
+ DEF_DIV6P1("canfd", R8A7796_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+ DEF_DIV6P1("csi0", R8A7796_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
+ DEF_DIV6P1("mso", R8A7796_CLK_MSO, CLK_PLL1_DIV4, 0x014),
+ DEF_DIV6P1("hdmi", R8A7796_CLK_HDMI, CLK_PLL1_DIV4, 0x250),
+
+ DEF_GEN3_OSC("osc", R8A7796_CLK_OSC, CLK_EXTAL, 8),
+
+ DEF_BASE("r", R8A7796_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
+};
+
+static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = {
+ DEF_MOD("3dge", 112, R8A7796_CLK_ZG),
+ DEF_MOD("fdp1-0", 119, R8A7796_CLK_S0D1),
+ DEF_MOD("tmu4", 121, R8A7796_CLK_S0D6),
+ DEF_MOD("tmu3", 122, R8A7796_CLK_S3D2),
+ DEF_MOD("tmu2", 123, R8A7796_CLK_S3D2),
+ DEF_MOD("tmu1", 124, R8A7796_CLK_S3D2),
+ DEF_MOD("tmu0", 125, R8A7796_CLK_CP),
+ DEF_MOD("scif5", 202, R8A7796_CLK_S3D4),
+ DEF_MOD("scif4", 203, R8A7796_CLK_S3D4),
+ DEF_MOD("scif3", 204, R8A7796_CLK_S3D4),
+ DEF_MOD("scif1", 206, R8A7796_CLK_S3D4),
+ DEF_MOD("scif0", 207, R8A7796_CLK_S3D4),
+ DEF_MOD("msiof3", 208, R8A7796_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A7796_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A7796_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A7796_CLK_MSO),
+ DEF_MOD("sys-dmac2", 217, R8A7796_CLK_S3D1),
+ DEF_MOD("sys-dmac1", 218, R8A7796_CLK_S3D1),
+ DEF_MOD("sys-dmac0", 219, R8A7796_CLK_S0D3),
+ DEF_MOD("sceg-pub", 229, R8A7796_CLK_CR),
+ DEF_MOD("cmt3", 300, R8A7796_CLK_R),
+ DEF_MOD("cmt2", 301, R8A7796_CLK_R),
+ DEF_MOD("cmt1", 302, R8A7796_CLK_R),
+ DEF_MOD("cmt0", 303, R8A7796_CLK_R),
+ DEF_MOD("tpu0", 304, R8A7796_CLK_S3D4),
+ DEF_MOD("scif2", 310, R8A7796_CLK_S3D4),
+ DEF_MOD("sdif3", 311, R8A7796_CLK_SD3),
+ DEF_MOD("sdif2", 312, R8A7796_CLK_SD2),
+ DEF_MOD("sdif1", 313, R8A7796_CLK_SD1),
+ DEF_MOD("sdif0", 314, R8A7796_CLK_SD0),
+ DEF_MOD("pcie1", 318, R8A7796_CLK_S3D1),
+ DEF_MOD("pcie0", 319, R8A7796_CLK_S3D1),
+ DEF_MOD("usb3-if0", 328, R8A7796_CLK_S3D1),
+ DEF_MOD("usb-dmac0", 330, R8A7796_CLK_S3D1),
+ DEF_MOD("usb-dmac1", 331, R8A7796_CLK_S3D1),
+ DEF_MOD("rwdt", 402, R8A7796_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A7796_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A7796_CLK_S0D3),
+ DEF_MOD("audmac1", 501, R8A7796_CLK_S1D2),
+ DEF_MOD("audmac0", 502, R8A7796_CLK_S1D2),
+ DEF_MOD("drif31", 508, R8A7796_CLK_S3D2),
+ DEF_MOD("drif30", 509, R8A7796_CLK_S3D2),
+ DEF_MOD("drif21", 510, R8A7796_CLK_S3D2),
+ DEF_MOD("drif20", 511, R8A7796_CLK_S3D2),
+ DEF_MOD("drif11", 512, R8A7796_CLK_S3D2),
+ DEF_MOD("drif10", 513, R8A7796_CLK_S3D2),
+ DEF_MOD("drif01", 514, R8A7796_CLK_S3D2),
+ DEF_MOD("drif00", 515, R8A7796_CLK_S3D2),
+ DEF_MOD("hscif4", 516, R8A7796_CLK_S3D1),
+ DEF_MOD("hscif3", 517, R8A7796_CLK_S3D1),
+ DEF_MOD("hscif2", 518, R8A7796_CLK_S3D1),
+ DEF_MOD("hscif1", 519, R8A7796_CLK_S3D1),
+ DEF_MOD("hscif0", 520, R8A7796_CLK_S3D1),
+ DEF_MOD("thermal", 522, R8A7796_CLK_CP),
+ DEF_MOD("pwm", 523, R8A7796_CLK_S0D12),
+ DEF_MOD("fcpvd2", 601, R8A7796_CLK_S0D2),
+ DEF_MOD("fcpvd1", 602, R8A7796_CLK_S0D2),
+ DEF_MOD("fcpvd0", 603, R8A7796_CLK_S0D2),
+ DEF_MOD("fcpvb0", 607, R8A7796_CLK_S0D1),
+ DEF_MOD("fcpvi0", 611, R8A7796_CLK_S0D1),
+ DEF_MOD("fcpf0", 615, R8A7796_CLK_S0D1),
+ DEF_MOD("fcpci0", 617, R8A7796_CLK_S0D2),
+ DEF_MOD("fcpcs", 619, R8A7796_CLK_S0D2),
+ DEF_MOD("vspd2", 621, R8A7796_CLK_S0D2),
+ DEF_MOD("vspd1", 622, R8A7796_CLK_S0D2),
+ DEF_MOD("vspd0", 623, R8A7796_CLK_S0D2),
+ DEF_MOD("vspb", 626, R8A7796_CLK_S0D1),
+ DEF_MOD("vspi0", 631, R8A7796_CLK_S0D1),
+ DEF_MOD("ehci1", 702, R8A7796_CLK_S3D2),
+ DEF_MOD("ehci0", 703, R8A7796_CLK_S3D2),
+ DEF_MOD("hsusb", 704, R8A7796_CLK_S3D2),
+ DEF_MOD("cmm2", 709, R8A7796_CLK_S2D1),
+ DEF_MOD("cmm1", 710, R8A7796_CLK_S2D1),
+ DEF_MOD("cmm0", 711, R8A7796_CLK_S2D1),
+ DEF_MOD("csi20", 714, R8A7796_CLK_CSI0),
+ DEF_MOD("csi40", 716, R8A7796_CLK_CSI0),
+ DEF_MOD("du2", 722, R8A7796_CLK_S2D1),
+ DEF_MOD("du1", 723, R8A7796_CLK_S2D1),
+ DEF_MOD("du0", 724, R8A7796_CLK_S2D1),
+ DEF_MOD("lvds", 727, R8A7796_CLK_S2D1),
+ DEF_MOD("hdmi0", 729, R8A7796_CLK_HDMI),
+ DEF_MOD("mlp", 802, R8A7796_CLK_S2D1),
+ DEF_MOD("vin7", 804, R8A7796_CLK_S0D2),
+ DEF_MOD("vin6", 805, R8A7796_CLK_S0D2),
+ DEF_MOD("vin5", 806, R8A7796_CLK_S0D2),
+ DEF_MOD("vin4", 807, R8A7796_CLK_S0D2),
+ DEF_MOD("vin3", 808, R8A7796_CLK_S0D2),
+ DEF_MOD("vin2", 809, R8A7796_CLK_S0D2),
+ DEF_MOD("vin1", 810, R8A7796_CLK_S0D2),
+ DEF_MOD("vin0", 811, R8A7796_CLK_S0D2),
+ DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6),
+ DEF_MOD("imr1", 822, R8A7796_CLK_S0D2),
+ DEF_MOD("imr0", 823, R8A7796_CLK_S0D2),
+ DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4),
+ DEF_MOD("gpio6", 906, R8A7796_CLK_S3D4),
+ DEF_MOD("gpio5", 907, R8A7796_CLK_S3D4),
+ DEF_MOD("gpio4", 908, R8A7796_CLK_S3D4),
+ DEF_MOD("gpio3", 909, R8A7796_CLK_S3D4),
+ DEF_MOD("gpio2", 910, R8A7796_CLK_S3D4),
+ DEF_MOD("gpio1", 911, R8A7796_CLK_S3D4),
+ DEF_MOD("gpio0", 912, R8A7796_CLK_S3D4),
+ DEF_MOD("can-fd", 914, R8A7796_CLK_S3D2),
+ DEF_MOD("can-if1", 915, R8A7796_CLK_S3D4),
+ DEF_MOD("can-if0", 916, R8A7796_CLK_S3D4),
+ DEF_MOD("rpc-if", 917, R8A7796_CLK_RPCD2),
+ DEF_MOD("i2c6", 918, R8A7796_CLK_S0D6),
+ DEF_MOD("i2c5", 919, R8A7796_CLK_S0D6),
+ DEF_MOD("adg", 922, R8A7796_CLK_S0D4),
+ DEF_MOD("i2c-dvfs", 926, R8A7796_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A7796_CLK_S0D6),
+ DEF_MOD("i2c3", 928, R8A7796_CLK_S0D6),
+ DEF_MOD("i2c2", 929, R8A7796_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A7796_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A7796_CLK_S3D2),
+ DEF_MOD("ssi-all", 1005, R8A7796_CLK_S3D4),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A7796_CLK_S3D4),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a7796_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4 OSC
+ * 14 13 19 17 (MHz)
+ *-------------------------------------------------------------------------
+ * 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144 /16
+ * 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144 /16
+ * 0 0 1 0 Prohibited setting
+ * 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144 /16
+ * 0 1 0 0 20 x 1 x150 x160 x120 x160 x120 /19
+ * 0 1 0 1 20 x 1 x150 x160 x120 x106 x120 /19
+ * 0 1 1 0 Prohibited setting
+ * 0 1 1 1 20 x 1 x150 x160 x120 x160 x120 /19
+ * 1 0 0 0 25 x 1 x120 x128 x96 x128 x96 /24
+ * 1 0 0 1 25 x 1 x120 x128 x96 x84 x96 /24
+ * 1 0 1 0 Prohibited setting
+ * 1 0 1 1 25 x 1 x120 x128 x96 x128 x96 /24
+ * 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144 /32
+ * 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144 /32
+ * 1 1 1 0 Prohibited setting
+ * 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144 /32
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \
+ (((md) & BIT(13)) >> 11) | \
+ (((md) & BIT(19)) >> 18) | \
+ (((md) & BIT(17)) >> 17))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 192, 1, 128, 1, 16, },
+ { 0, /* Prohibited setting */ },
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 160, 1, 106, 1, 19, },
+ { 0, /* Prohibited setting */ },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 128, 1, 128, 1, 24, },
+ { 1, 128, 1, 84, 1, 24, },
+ { 0, /* Prohibited setting */ },
+ { 1, 128, 1, 128, 1, 24, },
+ { 2, 192, 1, 192, 1, 32, },
+ { 2, 192, 1, 128, 1, 32, },
+ { 0, /* Prohibited setting */ },
+ { 2, 192, 1, 192, 1, 32, },
+};
+
+ /*
+ * Fixups for R-Car M3-W+
+ */
+
+static const unsigned int r8a77961_mod_nullify[] __initconst = {
+ MOD_CLK_ID(617), /* FCPCI0 */
+};
+
+static int __init r8a7796_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+ if (!cpg_pll_config->extal_div) {
+ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+ return -EINVAL;
+ }
+
+ if (of_device_is_compatible(dev->of_node, "renesas,r8a77961-cpg-mssr"))
+ mssr_mod_nullify(r8a7796_mod_clks,
+ ARRAY_SIZE(r8a7796_mod_clks),
+ r8a77961_mod_nullify,
+ ARRAY_SIZE(r8a77961_mod_nullify));
+
+ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7796_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a7796_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a7796_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a7796_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a7796_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a7796_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a7796_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a7796_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c
new file mode 100644
index 000000000..219e41abb
--- /dev/null
+++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c
@@ -0,0 +1,371 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a77965 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a77965-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A77965_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL4,
+ CLK_PLL1_DIV2,
+ CLK_PLL1_DIV4,
+ CLK_S0,
+ CLK_S1,
+ CLK_S2,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_SSPSRC,
+ CLK_RPCSRC,
+ CLK_RINT,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a77965_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+ DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1),
+ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
+
+ DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32),
+
+ /* Core Clock Outputs */
+ DEF_GEN3_Z("z", R8A77965_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8),
+ DEF_GEN3_Z("zg", R8A77965_CLK_ZG, CLK_TYPE_GEN3_ZG, CLK_PLL4, 4, 24),
+ DEF_FIXED("ztr", R8A77965_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED("ztrd2", R8A77965_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+ DEF_FIXED("zt", R8A77965_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED("zx", R8A77965_CLK_ZX, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED("s0d1", R8A77965_CLK_S0D1, CLK_S0, 1, 1),
+ DEF_FIXED("s0d2", R8A77965_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A77965_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A77965_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6", R8A77965_CLK_S0D6, CLK_S0, 6, 1),
+ DEF_FIXED("s0d8", R8A77965_CLK_S0D8, CLK_S0, 8, 1),
+ DEF_FIXED("s0d12", R8A77965_CLK_S0D12, CLK_S0, 12, 1),
+ DEF_FIXED("s1d1", R8A77965_CLK_S1D1, CLK_S1, 1, 1),
+ DEF_FIXED("s1d2", R8A77965_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A77965_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s2d1", R8A77965_CLK_S2D1, CLK_S2, 1, 1),
+ DEF_FIXED("s2d2", R8A77965_CLK_S2D2, CLK_S2, 2, 1),
+ DEF_FIXED("s2d4", R8A77965_CLK_S2D4, CLK_S2, 4, 1),
+ DEF_FIXED("s3d1", R8A77965_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A77965_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A77965_CLK_S3D4, CLK_S3, 4, 1),
+
+ DEF_GEN3_SDH("sd0h", R8A77965_CLK_SD0H, CLK_SDSRC, 0x074),
+ DEF_GEN3_SDH("sd1h", R8A77965_CLK_SD1H, CLK_SDSRC, 0x078),
+ DEF_GEN3_SDH("sd2h", R8A77965_CLK_SD2H, CLK_SDSRC, 0x268),
+ DEF_GEN3_SDH("sd3h", R8A77965_CLK_SD3H, CLK_SDSRC, 0x26c),
+ DEF_GEN3_SD("sd0", R8A77965_CLK_SD0, R8A77965_CLK_SD0H, 0x074),
+ DEF_GEN3_SD("sd1", R8A77965_CLK_SD1, R8A77965_CLK_SD1H, 0x078),
+ DEF_GEN3_SD("sd2", R8A77965_CLK_SD2, R8A77965_CLK_SD2H, 0x268),
+ DEF_GEN3_SD("sd3", R8A77965_CLK_SD3, R8A77965_CLK_SD3H, 0x26c),
+
+ DEF_BASE("rpc", R8A77965_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A77965_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A77965_CLK_RPC),
+
+ DEF_FIXED("cl", R8A77965_CLK_CL, CLK_PLL1_DIV2, 48, 1),
+ DEF_FIXED("cr", R8A77965_CLK_CR, CLK_PLL1_DIV4, 2, 1),
+ DEF_FIXED("cp", R8A77965_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A77965_CLK_CPEX, CLK_EXTAL, 2, 1),
+
+ DEF_DIV6P1("canfd", R8A77965_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+ DEF_DIV6P1("csi0", R8A77965_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
+ DEF_DIV6P1("mso", R8A77965_CLK_MSO, CLK_PLL1_DIV4, 0x014),
+ DEF_DIV6P1("hdmi", R8A77965_CLK_HDMI, CLK_PLL1_DIV4, 0x250),
+
+ DEF_GEN3_OSC("osc", R8A77965_CLK_OSC, CLK_EXTAL, 8),
+
+ DEF_BASE("r", R8A77965_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
+};
+
+static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
+ DEF_MOD("3dge", 112, R8A77965_CLK_ZG),
+ DEF_MOD("fdp1-0", 119, R8A77965_CLK_S0D1),
+ DEF_MOD("tmu4", 121, R8A77965_CLK_S0D6),
+ DEF_MOD("tmu3", 122, R8A77965_CLK_S3D2),
+ DEF_MOD("tmu2", 123, R8A77965_CLK_S3D2),
+ DEF_MOD("tmu1", 124, R8A77965_CLK_S3D2),
+ DEF_MOD("tmu0", 125, R8A77965_CLK_CP),
+ DEF_MOD("scif5", 202, R8A77965_CLK_S3D4),
+ DEF_MOD("scif4", 203, R8A77965_CLK_S3D4),
+ DEF_MOD("scif3", 204, R8A77965_CLK_S3D4),
+ DEF_MOD("scif1", 206, R8A77965_CLK_S3D4),
+ DEF_MOD("scif0", 207, R8A77965_CLK_S3D4),
+ DEF_MOD("msiof3", 208, R8A77965_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A77965_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A77965_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A77965_CLK_MSO),
+ DEF_MOD("sys-dmac2", 217, R8A77965_CLK_S3D1),
+ DEF_MOD("sys-dmac1", 218, R8A77965_CLK_S3D1),
+ DEF_MOD("sys-dmac0", 219, R8A77965_CLK_S0D3),
+ DEF_MOD("sceg-pub", 229, R8A77965_CLK_CR),
+
+ DEF_MOD("cmt3", 300, R8A77965_CLK_R),
+ DEF_MOD("cmt2", 301, R8A77965_CLK_R),
+ DEF_MOD("cmt1", 302, R8A77965_CLK_R),
+ DEF_MOD("cmt0", 303, R8A77965_CLK_R),
+ DEF_MOD("tpu0", 304, R8A77965_CLK_S3D4),
+ DEF_MOD("scif2", 310, R8A77965_CLK_S3D4),
+ DEF_MOD("sdif3", 311, R8A77965_CLK_SD3),
+ DEF_MOD("sdif2", 312, R8A77965_CLK_SD2),
+ DEF_MOD("sdif1", 313, R8A77965_CLK_SD1),
+ DEF_MOD("sdif0", 314, R8A77965_CLK_SD0),
+ DEF_MOD("pcie1", 318, R8A77965_CLK_S3D1),
+ DEF_MOD("pcie0", 319, R8A77965_CLK_S3D1),
+ DEF_MOD("usb3-if0", 328, R8A77965_CLK_S3D1),
+ DEF_MOD("usb-dmac0", 330, R8A77965_CLK_S3D1),
+ DEF_MOD("usb-dmac1", 331, R8A77965_CLK_S3D1),
+
+ DEF_MOD("rwdt", 402, R8A77965_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A77965_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A77965_CLK_S0D3),
+
+ DEF_MOD("audmac1", 501, R8A77965_CLK_S1D2),
+ DEF_MOD("audmac0", 502, R8A77965_CLK_S1D2),
+ DEF_MOD("drif31", 508, R8A77965_CLK_S3D2),
+ DEF_MOD("drif30", 509, R8A77965_CLK_S3D2),
+ DEF_MOD("drif21", 510, R8A77965_CLK_S3D2),
+ DEF_MOD("drif20", 511, R8A77965_CLK_S3D2),
+ DEF_MOD("drif11", 512, R8A77965_CLK_S3D2),
+ DEF_MOD("drif10", 513, R8A77965_CLK_S3D2),
+ DEF_MOD("drif01", 514, R8A77965_CLK_S3D2),
+ DEF_MOD("drif00", 515, R8A77965_CLK_S3D2),
+ DEF_MOD("hscif4", 516, R8A77965_CLK_S3D1),
+ DEF_MOD("hscif3", 517, R8A77965_CLK_S3D1),
+ DEF_MOD("hscif2", 518, R8A77965_CLK_S3D1),
+ DEF_MOD("hscif1", 519, R8A77965_CLK_S3D1),
+ DEF_MOD("hscif0", 520, R8A77965_CLK_S3D1),
+ DEF_MOD("thermal", 522, R8A77965_CLK_CP),
+ DEF_MOD("pwm", 523, R8A77965_CLK_S0D12),
+
+ DEF_MOD("fcpvd1", 602, R8A77965_CLK_S0D2),
+ DEF_MOD("fcpvd0", 603, R8A77965_CLK_S0D2),
+ DEF_MOD("fcpvb0", 607, R8A77965_CLK_S0D1),
+ DEF_MOD("fcpvi0", 611, R8A77965_CLK_S0D1),
+ DEF_MOD("fcpf0", 615, R8A77965_CLK_S0D1),
+ DEF_MOD("fcpcs", 619, R8A77965_CLK_S0D2),
+ DEF_MOD("vspd1", 622, R8A77965_CLK_S0D2),
+ DEF_MOD("vspd0", 623, R8A77965_CLK_S0D2),
+ DEF_MOD("vspb", 626, R8A77965_CLK_S0D1),
+ DEF_MOD("vspi0", 631, R8A77965_CLK_S0D1),
+
+ DEF_MOD("ehci1", 702, R8A77965_CLK_S3D2),
+ DEF_MOD("ehci0", 703, R8A77965_CLK_S3D2),
+ DEF_MOD("hsusb", 704, R8A77965_CLK_S3D2),
+ DEF_MOD("cmm3", 708, R8A77965_CLK_S2D1),
+ DEF_MOD("cmm1", 710, R8A77965_CLK_S2D1),
+ DEF_MOD("cmm0", 711, R8A77965_CLK_S2D1),
+ DEF_MOD("csi20", 714, R8A77965_CLK_CSI0),
+ DEF_MOD("csi40", 716, R8A77965_CLK_CSI0),
+ DEF_MOD("du3", 721, R8A77965_CLK_S2D1),
+ DEF_MOD("du1", 723, R8A77965_CLK_S2D1),
+ DEF_MOD("du0", 724, R8A77965_CLK_S2D1),
+ DEF_MOD("lvds", 727, R8A77965_CLK_S2D1),
+ DEF_MOD("hdmi0", 729, R8A77965_CLK_HDMI),
+
+ DEF_MOD("mlp", 802, R8A77965_CLK_S2D1),
+ DEF_MOD("vin7", 804, R8A77965_CLK_S0D2),
+ DEF_MOD("vin6", 805, R8A77965_CLK_S0D2),
+ DEF_MOD("vin5", 806, R8A77965_CLK_S0D2),
+ DEF_MOD("vin4", 807, R8A77965_CLK_S0D2),
+ DEF_MOD("vin3", 808, R8A77965_CLK_S0D2),
+ DEF_MOD("vin2", 809, R8A77965_CLK_S0D2),
+ DEF_MOD("vin1", 810, R8A77965_CLK_S0D2),
+ DEF_MOD("vin0", 811, R8A77965_CLK_S0D2),
+ DEF_MOD("etheravb", 812, R8A77965_CLK_S0D6),
+ DEF_MOD("sata0", 815, R8A77965_CLK_S3D2),
+ DEF_MOD("imr1", 822, R8A77965_CLK_S0D2),
+ DEF_MOD("imr0", 823, R8A77965_CLK_S0D2),
+
+ DEF_MOD("gpio7", 905, R8A77965_CLK_S3D4),
+ DEF_MOD("gpio6", 906, R8A77965_CLK_S3D4),
+ DEF_MOD("gpio5", 907, R8A77965_CLK_S3D4),
+ DEF_MOD("gpio4", 908, R8A77965_CLK_S3D4),
+ DEF_MOD("gpio3", 909, R8A77965_CLK_S3D4),
+ DEF_MOD("gpio2", 910, R8A77965_CLK_S3D4),
+ DEF_MOD("gpio1", 911, R8A77965_CLK_S3D4),
+ DEF_MOD("gpio0", 912, R8A77965_CLK_S3D4),
+ DEF_MOD("can-fd", 914, R8A77965_CLK_S3D2),
+ DEF_MOD("can-if1", 915, R8A77965_CLK_S3D4),
+ DEF_MOD("can-if0", 916, R8A77965_CLK_S3D4),
+ DEF_MOD("rpc-if", 917, R8A77965_CLK_RPCD2),
+ DEF_MOD("i2c6", 918, R8A77965_CLK_S0D6),
+ DEF_MOD("i2c5", 919, R8A77965_CLK_S0D6),
+ DEF_MOD("adg", 922, R8A77965_CLK_S0D4),
+ DEF_MOD("i2c-dvfs", 926, R8A77965_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A77965_CLK_S0D6),
+ DEF_MOD("i2c3", 928, R8A77965_CLK_S0D6),
+ DEF_MOD("i2c2", 929, R8A77965_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A77965_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A77965_CLK_S3D2),
+
+ DEF_MOD("ssi-all", 1005, R8A77965_CLK_S3D4),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("dab", 1016, R8A77965_CLK_S0D6),
+ DEF_MOD("scu-all", 1017, R8A77965_CLK_S3D4),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a77965_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3 PLL4 OSC
+ * 14 13 19 17 (MHz)
+ *-----------------------------------------------------------------
+ * 0 0 0 0 16.66 x 1 x180 x192 x192 x144 /16
+ * 0 0 0 1 16.66 x 1 x180 x192 x128 x144 /16
+ * 0 0 1 0 Prohibited setting
+ * 0 0 1 1 16.66 x 1 x180 x192 x192 x144 /16
+ * 0 1 0 0 20 x 1 x150 x160 x160 x120 /19
+ * 0 1 0 1 20 x 1 x150 x160 x106 x120 /19
+ * 0 1 1 0 Prohibited setting
+ * 0 1 1 1 20 x 1 x150 x160 x160 x120 /19
+ * 1 0 0 0 25 x 1 x120 x128 x128 x96 /24
+ * 1 0 0 1 25 x 1 x120 x128 x84 x96 /24
+ * 1 0 1 0 Prohibited setting
+ * 1 0 1 1 25 x 1 x120 x128 x128 x96 /24
+ * 1 1 0 0 33.33 / 2 x180 x192 x192 x144 /32
+ * 1 1 0 1 33.33 / 2 x180 x192 x128 x144 /32
+ * 1 1 1 0 Prohibited setting
+ * 1 1 1 1 33.33 / 2 x180 x192 x192 x144 /32
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \
+ (((md) & BIT(13)) >> 11) | \
+ (((md) & BIT(19)) >> 18) | \
+ (((md) & BIT(17)) >> 17))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 192, 1, 128, 1, 16, },
+ { 0, /* Prohibited setting */ },
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 160, 1, 106, 1, 19, },
+ { 0, /* Prohibited setting */ },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 128, 1, 128, 1, 24, },
+ { 1, 128, 1, 84, 1, 24, },
+ { 0, /* Prohibited setting */ },
+ { 1, 128, 1, 128, 1, 24, },
+ { 2, 192, 1, 192, 1, 32, },
+ { 2, 192, 1, 128, 1, 32, },
+ { 0, /* Prohibited setting */ },
+ { 2, 192, 1, 192, 1, 32, },
+};
+
+static int __init r8a77965_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+ if (!cpg_pll_config->extal_div) {
+ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+ return -EINVAL;
+ }
+
+ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a77965_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a77965_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a77965_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a77965_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a77965_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a77965_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a77965_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a77965_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c
new file mode 100644
index 000000000..e2bda2c10
--- /dev/null
+++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a77970 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2017-2018 Cogent Embedded Inc.
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a77970-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-cpg-lib.h"
+#include "rcar-gen3-cpg.h"
+
+#define CPG_SD0CKCR 0x0074
+
+enum r8a77970_clk_types {
+ CLK_TYPE_R8A77970_SD0H = CLK_TYPE_GEN3_SOC_BASE,
+ CLK_TYPE_R8A77970_SD0,
+};
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A77970_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+ CLK_PLL1_DIV4,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct clk_div_table cpg_sd0h_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static const struct clk_div_table cpg_sd0_div_table[] = {
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },
+ { 0, 0 },
+};
+
+static const struct cpg_core_clk r8a77970_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
+
+ /* Core Clock Outputs */
+ DEF_FIXED("z2", R8A77970_CLK_Z2, CLK_PLL1_DIV4, 1, 1),
+ DEF_FIXED("ztr", R8A77970_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED("ztrd2", R8A77970_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+ DEF_FIXED("zt", R8A77970_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED("zx", R8A77970_CLK_ZX, CLK_PLL1_DIV2, 3, 1),
+ DEF_FIXED("s1d1", R8A77970_CLK_S1D1, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED("s1d2", R8A77970_CLK_S1D2, CLK_PLL1_DIV2, 8, 1),
+ DEF_FIXED("s1d4", R8A77970_CLK_S1D4, CLK_PLL1_DIV2, 16, 1),
+ DEF_FIXED("s2d1", R8A77970_CLK_S2D1, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED("s2d2", R8A77970_CLK_S2D2, CLK_PLL1_DIV2, 12, 1),
+ DEF_FIXED("s2d4", R8A77970_CLK_S2D4, CLK_PLL1_DIV2, 24, 1),
+
+ DEF_BASE("sd0h", R8A77970_CLK_SD0H, CLK_TYPE_R8A77970_SD0H,
+ CLK_PLL1_DIV2),
+ DEF_BASE("sd0", R8A77970_CLK_SD0, CLK_TYPE_R8A77970_SD0, CLK_PLL1_DIV2),
+
+ DEF_FIXED("rpc", R8A77970_CLK_RPC, CLK_PLL1_DIV2, 5, 1),
+ DEF_FIXED("rpcd2", R8A77970_CLK_RPCD2, CLK_PLL1_DIV2, 10, 1),
+
+ DEF_FIXED("cl", R8A77970_CLK_CL, CLK_PLL1_DIV2, 48, 1),
+ DEF_FIXED("cp", R8A77970_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A77970_CLK_CPEX, CLK_EXTAL, 2, 1),
+
+ DEF_DIV6P1("canfd", R8A77970_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+ DEF_DIV6P1("mso", R8A77970_CLK_MSO, CLK_PLL1_DIV4, 0x014),
+ DEF_DIV6P1("csi0", R8A77970_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
+
+ DEF_FIXED("osc", R8A77970_CLK_OSC, CLK_PLL1_DIV2, 12*1024, 1),
+ DEF_FIXED("r", R8A77970_CLK_R, CLK_EXTALR, 1, 1),
+};
+
+static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = {
+ DEF_MOD("tmu4", 121, R8A77970_CLK_S2D2),
+ DEF_MOD("tmu3", 122, R8A77970_CLK_S2D2),
+ DEF_MOD("tmu2", 123, R8A77970_CLK_S2D2),
+ DEF_MOD("tmu1", 124, R8A77970_CLK_S2D2),
+ DEF_MOD("tmu0", 125, R8A77970_CLK_CP),
+ DEF_MOD("ivcp1e", 127, R8A77970_CLK_S2D1),
+ DEF_MOD("scif4", 203, R8A77970_CLK_S2D4),
+ DEF_MOD("scif3", 204, R8A77970_CLK_S2D4),
+ DEF_MOD("scif1", 206, R8A77970_CLK_S2D4),
+ DEF_MOD("scif0", 207, R8A77970_CLK_S2D4),
+ DEF_MOD("msiof3", 208, R8A77970_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A77970_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A77970_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A77970_CLK_MSO),
+ DEF_MOD("mfis", 213, R8A77970_CLK_S2D2),
+ DEF_MOD("sys-dmac2", 217, R8A77970_CLK_S2D1),
+ DEF_MOD("sys-dmac1", 218, R8A77970_CLK_S2D1),
+ DEF_MOD("cmt3", 300, R8A77970_CLK_R),
+ DEF_MOD("cmt2", 301, R8A77970_CLK_R),
+ DEF_MOD("cmt1", 302, R8A77970_CLK_R),
+ DEF_MOD("cmt0", 303, R8A77970_CLK_R),
+ DEF_MOD("tpu0", 304, R8A77970_CLK_S2D4),
+ DEF_MOD("sd-if", 314, R8A77970_CLK_SD0),
+ DEF_MOD("rwdt", 402, R8A77970_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A77970_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A77970_CLK_S2D1),
+ DEF_MOD("hscif3", 517, R8A77970_CLK_S2D1),
+ DEF_MOD("hscif2", 518, R8A77970_CLK_S2D1),
+ DEF_MOD("hscif1", 519, R8A77970_CLK_S2D1),
+ DEF_MOD("hscif0", 520, R8A77970_CLK_S2D1),
+ DEF_MOD("thermal", 522, R8A77970_CLK_CP),
+ DEF_MOD("pwm", 523, R8A77970_CLK_S2D4),
+ DEF_MOD("fcpvd0", 603, R8A77970_CLK_S2D1),
+ DEF_MOD("vspd0", 623, R8A77970_CLK_S2D1),
+ DEF_MOD("csi40", 716, R8A77970_CLK_CSI0),
+ DEF_MOD("du0", 724, R8A77970_CLK_S2D1),
+ DEF_MOD("lvds", 727, R8A77970_CLK_S2D1),
+ DEF_MOD("vin3", 808, R8A77970_CLK_S2D1),
+ DEF_MOD("vin2", 809, R8A77970_CLK_S2D1),
+ DEF_MOD("vin1", 810, R8A77970_CLK_S2D1),
+ DEF_MOD("vin0", 811, R8A77970_CLK_S2D1),
+ DEF_MOD("etheravb", 812, R8A77970_CLK_S2D2),
+ DEF_MOD("gpio5", 907, R8A77970_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A77970_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A77970_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A77970_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A77970_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A77970_CLK_CP),
+ DEF_MOD("can-fd", 914, R8A77970_CLK_S2D2),
+ DEF_MOD("rpc-if", 917, R8A77970_CLK_RPC),
+ DEF_MOD("i2c4", 927, R8A77970_CLK_S2D2),
+ DEF_MOD("i2c3", 928, R8A77970_CLK_S2D2),
+ DEF_MOD("i2c2", 929, R8A77970_CLK_S2D2),
+ DEF_MOD("i2c1", 930, R8A77970_CLK_S2D2),
+ DEF_MOD("i2c0", 931, R8A77970_CLK_S2D2),
+};
+
+static const unsigned int r8a77970_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz)
+ *-------------------------------------------------
+ * 0 0 0 16.66 x 1 x192 x192 x96
+ * 0 0 1 16.66 x 1 x192 x192 x80
+ * 0 1 0 20 x 1 x160 x160 x80
+ * 0 1 1 20 x 1 x160 x160 x66
+ * 1 0 0 27 / 2 x236 x236 x118
+ * 1 0 1 27 / 2 x236 x236 x98
+ * 1 1 0 33.33 / 2 x192 x192 x96
+ * 1 1 1 33.33 / 2 x192 x192 x80
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
+ (((md) & BIT(13)) >> 12) | \
+ (((md) & BIT(19)) >> 19))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[8] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div */
+ { 1, 192, 1, 96, 1, },
+ { 1, 192, 1, 80, 1, },
+ { 1, 160, 1, 80, 1, },
+ { 1, 160, 1, 66, 1, },
+ { 2, 236, 1, 118, 1, },
+ { 2, 236, 1, 98, 1, },
+ { 2, 192, 1, 96, 1, },
+ { 2, 192, 1, 80, 1, },
+};
+
+static int __init r8a77970_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+static struct clk * __init r8a77970_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+ struct cpg_mssr_pub *pub)
+{
+ const struct clk_div_table *table;
+ void __iomem *base = pub->base0;
+ struct clk **clks = pub->clks;
+ const struct clk *parent;
+ unsigned int shift;
+
+ switch (core->type) {
+ case CLK_TYPE_R8A77970_SD0H:
+ table = cpg_sd0h_div_table;
+ shift = 8;
+ break;
+ case CLK_TYPE_R8A77970_SD0:
+ table = cpg_sd0_div_table;
+ shift = 4;
+ break;
+ default:
+ return rcar_gen3_cpg_clk_register(dev, core, info, pub);
+ }
+
+ parent = clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ return clk_register_divider_table(NULL, core->name,
+ __clk_get_name(parent), 0,
+ base + CPG_SD0CKCR,
+ shift, 4, 0, table, &cpg_lock);
+}
+
+const struct cpg_mssr_info r8a77970_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a77970_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a77970_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a77970_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a77970_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a77970_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a77970_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a77970_cpg_mssr_init,
+ .cpg_clk_register = r8a77970_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c
new file mode 100644
index 000000000..aaa685ec3
--- /dev/null
+++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a77980 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ * Copyright (C) 2018 Cogent Embedded, Inc.
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+#include <linux/sys_soc.h>
+
+#include <dt-bindings/clock/r8a77980-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A77980_CLK_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL3,
+ CLK_PLL1_DIV2,
+ CLK_PLL1_DIV4,
+ CLK_S0,
+ CLK_S1,
+ CLK_S2,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_OCO,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a77980_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1),
+ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
+
+ DEF_RATE(".oco", CLK_OCO, 32768),
+
+ /* Core Clock Outputs */
+ DEF_FIXED("z2", R8A77980_CLK_Z2, CLK_PLL2, 4, 1),
+ DEF_FIXED("ztr", R8A77980_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
+ DEF_FIXED("ztrd2", R8A77980_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+ DEF_FIXED("zt", R8A77980_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED("zx", R8A77980_CLK_ZX, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED("s0d1", R8A77980_CLK_S0D1, CLK_S0, 1, 1),
+ DEF_FIXED("s0d2", R8A77980_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A77980_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A77980_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6", R8A77980_CLK_S0D6, CLK_S0, 6, 1),
+ DEF_FIXED("s0d12", R8A77980_CLK_S0D12, CLK_S0, 12, 1),
+ DEF_FIXED("s0d24", R8A77980_CLK_S0D24, CLK_S0, 24, 1),
+ DEF_FIXED("s1d1", R8A77980_CLK_S1D1, CLK_S1, 1, 1),
+ DEF_FIXED("s1d2", R8A77980_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A77980_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s2d1", R8A77980_CLK_S2D1, CLK_S2, 1, 1),
+ DEF_FIXED("s2d2", R8A77980_CLK_S2D2, CLK_S2, 2, 1),
+ DEF_FIXED("s2d4", R8A77980_CLK_S2D4, CLK_S2, 4, 1),
+ DEF_FIXED("s3d1", R8A77980_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A77980_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A77980_CLK_S3D4, CLK_S3, 4, 1),
+
+ DEF_GEN3_SDH("sd0h", R8A77980_CLK_SD0H, CLK_SDSRC, 0x0074),
+ DEF_GEN3_SD("sd0", R8A77980_CLK_SD0, R8A77980_CLK_SD0H, 0x0074),
+
+ DEF_BASE("rpc", R8A77980_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A77980_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A77980_CLK_RPC),
+
+ DEF_FIXED("cl", R8A77980_CLK_CL, CLK_PLL1_DIV2, 48, 1),
+ DEF_FIXED("cp", R8A77980_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A77980_CLK_CPEX, CLK_EXTAL, 2, 1),
+
+ DEF_DIV6P1("canfd", R8A77980_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+ DEF_DIV6P1("csi0", R8A77980_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
+ DEF_DIV6P1("mso", R8A77980_CLK_MSO, CLK_PLL1_DIV4, 0x014),
+
+ DEF_GEN3_OSC("osc", R8A77980_CLK_OSC, CLK_EXTAL, 8),
+ DEF_GEN3_MDSEL("r", R8A77980_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+};
+
+static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = {
+ DEF_MOD("tmu4", 121, R8A77980_CLK_S0D6),
+ DEF_MOD("tmu3", 122, R8A77980_CLK_S0D6),
+ DEF_MOD("tmu2", 123, R8A77980_CLK_S0D6),
+ DEF_MOD("tmu1", 124, R8A77980_CLK_S0D6),
+ DEF_MOD("tmu0", 125, R8A77980_CLK_CP),
+ DEF_MOD("scif4", 203, R8A77980_CLK_S3D4),
+ DEF_MOD("scif3", 204, R8A77980_CLK_S3D4),
+ DEF_MOD("scif1", 206, R8A77980_CLK_S3D4),
+ DEF_MOD("scif0", 207, R8A77980_CLK_S3D4),
+ DEF_MOD("msiof3", 208, R8A77980_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A77980_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A77980_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A77980_CLK_MSO),
+ DEF_MOD("sys-dmac2", 217, R8A77980_CLK_S0D3),
+ DEF_MOD("sys-dmac1", 218, R8A77980_CLK_S0D3),
+ DEF_MOD("cmt3", 300, R8A77980_CLK_R),
+ DEF_MOD("cmt2", 301, R8A77980_CLK_R),
+ DEF_MOD("cmt1", 302, R8A77980_CLK_R),
+ DEF_MOD("cmt0", 303, R8A77980_CLK_R),
+ DEF_MOD("tpu0", 304, R8A77980_CLK_S3D4),
+ DEF_MOD("sdif", 314, R8A77980_CLK_SD0),
+ DEF_MOD("pciec0", 319, R8A77980_CLK_S2D2),
+ DEF_MOD("rwdt", 402, R8A77980_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A77980_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A77980_CLK_S0D3),
+ DEF_MOD("hscif3", 517, R8A77980_CLK_S3D1),
+ DEF_MOD("hscif2", 518, R8A77980_CLK_S3D1),
+ DEF_MOD("hscif1", 519, R8A77980_CLK_S3D1),
+ DEF_MOD("hscif0", 520, R8A77980_CLK_S3D1),
+ DEF_MOD("imp4", 521, R8A77980_CLK_S1D1),
+ DEF_MOD("thermal", 522, R8A77980_CLK_CP),
+ DEF_MOD("pwm", 523, R8A77980_CLK_S0D12),
+ DEF_MOD("impdma1", 526, R8A77980_CLK_S1D1),
+ DEF_MOD("impdma0", 527, R8A77980_CLK_S1D1),
+ DEF_MOD("imp-ocv4", 528, R8A77980_CLK_S1D1),
+ DEF_MOD("imp-ocv3", 529, R8A77980_CLK_S1D1),
+ DEF_MOD("imp-ocv2", 531, R8A77980_CLK_S1D1),
+ DEF_MOD("fcpvd0", 603, R8A77980_CLK_S3D1),
+ DEF_MOD("vin15", 604, R8A77980_CLK_S2D1),
+ DEF_MOD("vin14", 605, R8A77980_CLK_S2D1),
+ DEF_MOD("vin13", 608, R8A77980_CLK_S2D1),
+ DEF_MOD("vin12", 612, R8A77980_CLK_S2D1),
+ DEF_MOD("vin11", 618, R8A77980_CLK_S2D1),
+ DEF_MOD("vspd0", 623, R8A77980_CLK_S3D1),
+ DEF_MOD("vin10", 625, R8A77980_CLK_S2D1),
+ DEF_MOD("vin9", 627, R8A77980_CLK_S2D1),
+ DEF_MOD("vin8", 628, R8A77980_CLK_S2D1),
+ DEF_MOD("csi41", 715, R8A77980_CLK_CSI0),
+ DEF_MOD("csi40", 716, R8A77980_CLK_CSI0),
+ DEF_MOD("du0", 724, R8A77980_CLK_S2D1),
+ DEF_MOD("lvds", 727, R8A77980_CLK_S2D1),
+ DEF_MOD("vin7", 804, R8A77980_CLK_S2D1),
+ DEF_MOD("vin6", 805, R8A77980_CLK_S2D1),
+ DEF_MOD("vin5", 806, R8A77980_CLK_S2D1),
+ DEF_MOD("vin4", 807, R8A77980_CLK_S2D1),
+ DEF_MOD("vin3", 808, R8A77980_CLK_S2D1),
+ DEF_MOD("vin2", 809, R8A77980_CLK_S2D1),
+ DEF_MOD("vin1", 810, R8A77980_CLK_S2D1),
+ DEF_MOD("vin0", 811, R8A77980_CLK_S2D1),
+ DEF_MOD("etheravb", 812, R8A77980_CLK_S3D2),
+ DEF_MOD("gether", 813, R8A77980_CLK_S3D2),
+ DEF_MOD("imp3", 824, R8A77980_CLK_S1D1),
+ DEF_MOD("imp2", 825, R8A77980_CLK_S1D1),
+ DEF_MOD("imp1", 826, R8A77980_CLK_S1D1),
+ DEF_MOD("imp0", 827, R8A77980_CLK_S1D1),
+ DEF_MOD("imp-ocv1", 828, R8A77980_CLK_S1D1),
+ DEF_MOD("imp-ocv0", 829, R8A77980_CLK_S1D1),
+ DEF_MOD("impram", 830, R8A77980_CLK_S1D1),
+ DEF_MOD("impcnn", 831, R8A77980_CLK_S1D1),
+ DEF_MOD("gpio5", 907, R8A77980_CLK_CP),
+ DEF_MOD("gpio4", 908, R8A77980_CLK_CP),
+ DEF_MOD("gpio3", 909, R8A77980_CLK_CP),
+ DEF_MOD("gpio2", 910, R8A77980_CLK_CP),
+ DEF_MOD("gpio1", 911, R8A77980_CLK_CP),
+ DEF_MOD("gpio0", 912, R8A77980_CLK_CP),
+ DEF_MOD("can-fd", 914, R8A77980_CLK_S3D2),
+ DEF_MOD("rpc-if", 917, R8A77980_CLK_RPCD2),
+ DEF_MOD("i2c5", 919, R8A77980_CLK_S0D6),
+ DEF_MOD("i2c4", 927, R8A77980_CLK_S0D6),
+ DEF_MOD("i2c3", 928, R8A77980_CLK_S0D6),
+ DEF_MOD("i2c2", 929, R8A77980_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A77980_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A77980_CLK_S3D2),
+};
+
+static const unsigned int r8a77980_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD EXTAL PLL2 PLL1 PLL3 OSC
+ * 14 13 (MHz)
+ * --------------------------------------------------------
+ * 0 0 16.66 x 1 x240 x192 x192 /16
+ * 0 1 20 x 1 x200 x160 x160 /19
+ * 1 0 27 x 1 x148 x118 x118 /26
+ * 1 1 33.33 / 2 x240 x192 x192 /32
+ */
+#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] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 160, 1, 160, 1, 19, },
+ { 1, 118, 1, 118, 1, 26, },
+ { 2, 192, 1, 192, 1, 32, },
+};
+
+static int __init r8a77980_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a77980_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a77980_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a77980_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a77980_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a77980_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a77980_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a77980_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a77980_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a77990-cpg-mssr.c b/drivers/clk/renesas/r8a77990-cpg-mssr.c
new file mode 100644
index 000000000..b2f82c594
--- /dev/null
+++ b/drivers/clk/renesas/r8a77990-cpg-mssr.c
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a77990 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2018-2019 Renesas Electronics Corp.
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a77990-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A77990_CLK_CPEX,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL0D4,
+ CLK_PLL0D6,
+ CLK_PLL0D8,
+ CLK_PLL0D20,
+ CLK_PLL0D24,
+ CLK_PLL1D2,
+ CLK_PE,
+ CLK_S0,
+ CLK_S1,
+ CLK_S2,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_RINT,
+ CLK_OCO,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a77990_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll0", CLK_PLL0, CLK_MAIN, 1, 100),
+ DEF_FIXED(".pll0d4", CLK_PLL0D4, CLK_PLL0, 4, 1),
+ DEF_FIXED(".pll0d6", CLK_PLL0D6, CLK_PLL0, 6, 1),
+ DEF_FIXED(".pll0d8", CLK_PLL0D8, CLK_PLL0, 8, 1),
+ DEF_FIXED(".pll0d20", CLK_PLL0D20, CLK_PLL0, 20, 1),
+ DEF_FIXED(".pll0d24", CLK_PLL0D24, CLK_PLL0, 24, 1),
+ DEF_FIXED(".pll1d2", CLK_PLL1D2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pe", CLK_PE, CLK_PLL0D20, 1, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1, 3, 1),
+ DEF_FIXED(".s2", CLK_S2, CLK_PLL1, 4, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1),
+
+ DEF_FIXED_RPCSRC_E3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1),
+
+ DEF_DIV6_RO(".r", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32),
+
+ DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000),
+
+ /* Core Clock Outputs */
+ DEF_FIXED("za2", R8A77990_CLK_ZA2, CLK_PLL0D24, 1, 1),
+ DEF_FIXED("za8", R8A77990_CLK_ZA8, CLK_PLL0D8, 1, 1),
+ DEF_GEN3_Z("z2", R8A77990_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL0, 4, 8),
+ DEF_FIXED("ztr", R8A77990_CLK_ZTR, CLK_PLL1, 6, 1),
+ DEF_FIXED("zt", R8A77990_CLK_ZT, CLK_PLL1, 4, 1),
+ DEF_FIXED("zx", R8A77990_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("s0d1", R8A77990_CLK_S0D1, CLK_S0, 1, 1),
+ DEF_FIXED("s0d3", R8A77990_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d6", R8A77990_CLK_S0D6, CLK_S0, 6, 1),
+ DEF_FIXED("s0d12", R8A77990_CLK_S0D12, CLK_S0, 12, 1),
+ DEF_FIXED("s0d24", R8A77990_CLK_S0D24, CLK_S0, 24, 1),
+ DEF_FIXED("s1d1", R8A77990_CLK_S1D1, CLK_S1, 1, 1),
+ DEF_FIXED("s1d2", R8A77990_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A77990_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s2d1", R8A77990_CLK_S2D1, CLK_S2, 1, 1),
+ DEF_FIXED("s2d2", R8A77990_CLK_S2D2, CLK_S2, 2, 1),
+ DEF_FIXED("s2d4", R8A77990_CLK_S2D4, CLK_S2, 4, 1),
+ DEF_FIXED("s3d1", R8A77990_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A77990_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A77990_CLK_S3D4, CLK_S3, 4, 1),
+
+ DEF_GEN3_SDH("sd0h", R8A77990_CLK_SD0H, CLK_SDSRC, 0x0074),
+ DEF_GEN3_SDH("sd1h", R8A77990_CLK_SD1H, CLK_SDSRC, 0x0078),
+ DEF_GEN3_SDH("sd3h", R8A77990_CLK_SD3H, CLK_SDSRC, 0x026c),
+ DEF_GEN3_SD("sd0", R8A77990_CLK_SD0, R8A77990_CLK_SD0H, 0x0074),
+ DEF_GEN3_SD("sd1", R8A77990_CLK_SD1, R8A77990_CLK_SD1H, 0x0078),
+ DEF_GEN3_SD("sd3", R8A77990_CLK_SD3, R8A77990_CLK_SD3H, 0x026c),
+
+ DEF_BASE("rpc", R8A77990_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A77990_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A77990_CLK_RPC),
+
+ DEF_FIXED("cl", R8A77990_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("cr", R8A77990_CLK_CR, CLK_PLL1D2, 2, 1),
+ DEF_FIXED("cp", R8A77990_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A77990_CLK_CPEX, CLK_EXTAL, 4, 1),
+
+ DEF_DIV6_RO("osc", R8A77990_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8),
+
+ DEF_GEN3_PE("s0d6c", R8A77990_CLK_S0D6C, CLK_S0, 6, CLK_PE, 2),
+ DEF_GEN3_PE("s3d1c", R8A77990_CLK_S3D1C, CLK_S3, 1, CLK_PE, 1),
+ DEF_GEN3_PE("s3d2c", R8A77990_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2),
+ DEF_GEN3_PE("s3d4c", R8A77990_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4),
+
+ DEF_DIV6P1("canfd", R8A77990_CLK_CANFD, CLK_PLL0D6, 0x244),
+ DEF_DIV6P1("csi0", R8A77990_CLK_CSI0, CLK_PLL1D2, 0x00c),
+ DEF_DIV6P1("mso", R8A77990_CLK_MSO, CLK_PLL1D2, 0x014),
+
+ DEF_GEN3_RCKSEL("r", R8A77990_CLK_R, CLK_RINT, 1, CLK_OCO, 61 * 4),
+};
+
+static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = {
+ DEF_MOD("tmu4", 121, R8A77990_CLK_S0D6C),
+ DEF_MOD("tmu3", 122, R8A77990_CLK_S3D2C),
+ DEF_MOD("tmu2", 123, R8A77990_CLK_S3D2C),
+ DEF_MOD("tmu1", 124, R8A77990_CLK_S3D2C),
+ DEF_MOD("tmu0", 125, R8A77990_CLK_CP),
+ DEF_MOD("scif5", 202, R8A77990_CLK_S3D4C),
+ DEF_MOD("scif4", 203, R8A77990_CLK_S3D4C),
+ DEF_MOD("scif3", 204, R8A77990_CLK_S3D4C),
+ DEF_MOD("scif1", 206, R8A77990_CLK_S3D4C),
+ DEF_MOD("scif0", 207, R8A77990_CLK_S3D4C),
+ DEF_MOD("msiof3", 208, R8A77990_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A77990_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A77990_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A77990_CLK_MSO),
+ DEF_MOD("sys-dmac2", 217, R8A77990_CLK_S3D1),
+ DEF_MOD("sys-dmac1", 218, R8A77990_CLK_S3D1),
+ DEF_MOD("sys-dmac0", 219, R8A77990_CLK_S3D1),
+ DEF_MOD("sceg-pub", 229, R8A77990_CLK_CR),
+
+ DEF_MOD("cmt3", 300, R8A77990_CLK_R),
+ DEF_MOD("cmt2", 301, R8A77990_CLK_R),
+ DEF_MOD("cmt1", 302, R8A77990_CLK_R),
+ DEF_MOD("cmt0", 303, R8A77990_CLK_R),
+ DEF_MOD("scif2", 310, R8A77990_CLK_S3D4C),
+ DEF_MOD("sdif3", 311, R8A77990_CLK_SD3),
+ DEF_MOD("sdif1", 313, R8A77990_CLK_SD1),
+ DEF_MOD("sdif0", 314, R8A77990_CLK_SD0),
+ DEF_MOD("pcie0", 319, R8A77990_CLK_S3D1),
+ DEF_MOD("usb3-if0", 328, R8A77990_CLK_S3D1),
+ DEF_MOD("usb-dmac0", 330, R8A77990_CLK_S3D1),
+ DEF_MOD("usb-dmac1", 331, R8A77990_CLK_S3D1),
+
+ DEF_MOD("rwdt", 402, R8A77990_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A77990_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A77990_CLK_S0D3),
+
+ DEF_MOD("audmac0", 502, R8A77990_CLK_S1D2),
+ DEF_MOD("drif31", 508, R8A77990_CLK_S3D2),
+ DEF_MOD("drif30", 509, R8A77990_CLK_S3D2),
+ DEF_MOD("drif21", 510, R8A77990_CLK_S3D2),
+ DEF_MOD("drif20", 511, R8A77990_CLK_S3D2),
+ DEF_MOD("drif11", 512, R8A77990_CLK_S3D2),
+ DEF_MOD("drif10", 513, R8A77990_CLK_S3D2),
+ DEF_MOD("drif01", 514, R8A77990_CLK_S3D2),
+ DEF_MOD("drif00", 515, R8A77990_CLK_S3D2),
+ DEF_MOD("hscif4", 516, R8A77990_CLK_S3D1C),
+ DEF_MOD("hscif3", 517, R8A77990_CLK_S3D1C),
+ DEF_MOD("hscif2", 518, R8A77990_CLK_S3D1C),
+ DEF_MOD("hscif1", 519, R8A77990_CLK_S3D1C),
+ DEF_MOD("hscif0", 520, R8A77990_CLK_S3D1C),
+ DEF_MOD("thermal", 522, R8A77990_CLK_CP),
+ DEF_MOD("pwm", 523, R8A77990_CLK_S3D4C),
+
+ DEF_MOD("fcpvd1", 602, R8A77990_CLK_S1D2),
+ DEF_MOD("fcpvd0", 603, R8A77990_CLK_S1D2),
+ DEF_MOD("fcpvb0", 607, R8A77990_CLK_S0D1),
+ DEF_MOD("fcpvi0", 611, R8A77990_CLK_S0D1),
+ DEF_MOD("fcpf0", 615, R8A77990_CLK_S0D1),
+ DEF_MOD("fcpcs", 619, R8A77990_CLK_S0D1),
+ DEF_MOD("vspd1", 622, R8A77990_CLK_S1D2),
+ DEF_MOD("vspd0", 623, R8A77990_CLK_S1D2),
+ DEF_MOD("vspb", 626, R8A77990_CLK_S0D1),
+ DEF_MOD("vspi0", 631, R8A77990_CLK_S0D1),
+
+ DEF_MOD("ehci0", 703, R8A77990_CLK_S3D2),
+ DEF_MOD("hsusb", 704, R8A77990_CLK_S3D2),
+ DEF_MOD("cmm1", 710, R8A77990_CLK_S1D1),
+ DEF_MOD("cmm0", 711, R8A77990_CLK_S1D1),
+ DEF_MOD("csi40", 716, R8A77990_CLK_CSI0),
+ DEF_MOD("du1", 723, R8A77990_CLK_S1D1),
+ DEF_MOD("du0", 724, R8A77990_CLK_S1D1),
+ DEF_MOD("lvds", 727, R8A77990_CLK_S2D1),
+
+ DEF_MOD("mlp", 802, R8A77990_CLK_S2D1),
+ DEF_MOD("vin5", 806, R8A77990_CLK_S1D2),
+ DEF_MOD("vin4", 807, R8A77990_CLK_S1D2),
+ DEF_MOD("etheravb", 812, R8A77990_CLK_S3D2),
+
+ DEF_MOD("gpio6", 906, R8A77990_CLK_S3D4),
+ DEF_MOD("gpio5", 907, R8A77990_CLK_S3D4),
+ DEF_MOD("gpio4", 908, R8A77990_CLK_S3D4),
+ DEF_MOD("gpio3", 909, R8A77990_CLK_S3D4),
+ DEF_MOD("gpio2", 910, R8A77990_CLK_S3D4),
+ DEF_MOD("gpio1", 911, R8A77990_CLK_S3D4),
+ DEF_MOD("gpio0", 912, R8A77990_CLK_S3D4),
+ DEF_MOD("can-fd", 914, R8A77990_CLK_S3D2),
+ DEF_MOD("can-if1", 915, R8A77990_CLK_S3D4),
+ DEF_MOD("can-if0", 916, R8A77990_CLK_S3D4),
+ DEF_MOD("rpc-if", 917, R8A77990_CLK_RPCD2),
+ DEF_MOD("i2c6", 918, R8A77990_CLK_S3D2),
+ DEF_MOD("i2c5", 919, R8A77990_CLK_S3D2),
+ DEF_MOD("adg", 922, R8A77990_CLK_ZA2),
+ DEF_MOD("i2c-dvfs", 926, R8A77990_CLK_CP),
+ DEF_MOD("i2c4", 927, R8A77990_CLK_S3D2),
+ DEF_MOD("i2c3", 928, R8A77990_CLK_S3D2),
+ DEF_MOD("i2c2", 929, R8A77990_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A77990_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A77990_CLK_S3D2),
+
+ DEF_MOD("i2c7", 1003, R8A77990_CLK_S3D2),
+ DEF_MOD("ssi-all", 1005, R8A77990_CLK_S3D4),
+ DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
+ DEF_MOD("dab", 1016, R8A77990_CLK_S3D1),
+ DEF_MOD("scu-all", 1017, R8A77990_CLK_S3D4),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a77990_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD19 EXTAL (MHz) PLL0 PLL1 PLL3
+ *--------------------------------------------------------------------
+ * 0 48 x 1 x100/1 x100/3 x100/3
+ * 1 48 x 1 x100/1 x100/3 x58/3
+ */
+#define CPG_PLL_CONFIG_INDEX(md) (((md) & BIT(19)) >> 19)
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[2] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div */
+ { 1, 100, 3, 100, 3, },
+ { 1, 100, 3, 58, 3, },
+};
+
+static int __init r8a77990_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen3_cpg_init(cpg_pll_config, 0, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a77990_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a77990_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a77990_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a77990_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a77990_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a77990_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a77990_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a77990_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c
new file mode 100644
index 000000000..162fa86c8
--- /dev/null
+++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a77995 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2017 Glider bvba
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a77995-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A77995_CLK_CPEX,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL3,
+ CLK_PLL0D2,
+ CLK_PLL0D3,
+ CLK_PLL0D5,
+ CLK_PLL1D2,
+ CLK_PE,
+ CLK_S0,
+ CLK_S1,
+ CLK_S2,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_RINT,
+ CLK_OCO,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a77995_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+
+ DEF_FIXED(".pll0", CLK_PLL0, CLK_MAIN, 4, 250),
+ DEF_FIXED(".pll0d2", CLK_PLL0D2, CLK_PLL0, 2, 1),
+ DEF_FIXED(".pll0d3", CLK_PLL0D3, CLK_PLL0, 3, 1),
+ DEF_FIXED(".pll0d5", CLK_PLL0D5, CLK_PLL0, 5, 1),
+ DEF_FIXED(".pll1d2", CLK_PLL1D2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pe", CLK_PE, CLK_PLL0D3, 4, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1, 3, 1),
+ DEF_FIXED(".s2", CLK_S2, CLK_PLL1, 4, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1),
+
+ DEF_FIXED_RPCSRC_D3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1),
+
+ DEF_DIV6_RO(".r", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32),
+
+ DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000),
+
+ /* Core Clock Outputs */
+ DEF_FIXED("za2", R8A77995_CLK_ZA2, CLK_PLL0D3, 2, 1),
+ DEF_FIXED("z2", R8A77995_CLK_Z2, CLK_PLL0D3, 1, 1),
+ DEF_FIXED("ztr", R8A77995_CLK_ZTR, CLK_PLL1, 6, 1),
+ DEF_FIXED("zt", R8A77995_CLK_ZT, CLK_PLL1, 4, 1),
+ DEF_FIXED("zx", R8A77995_CLK_ZX, CLK_PLL1, 3, 1),
+ DEF_FIXED("s0d1", R8A77995_CLK_S0D1, CLK_S0, 1, 1),
+ DEF_FIXED("s1d1", R8A77995_CLK_S1D1, CLK_S1, 1, 1),
+ DEF_FIXED("s1d2", R8A77995_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A77995_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s2d1", R8A77995_CLK_S2D1, CLK_S2, 1, 1),
+ DEF_FIXED("s2d2", R8A77995_CLK_S2D2, CLK_S2, 2, 1),
+ DEF_FIXED("s2d4", R8A77995_CLK_S2D4, CLK_S2, 4, 1),
+ DEF_FIXED("s3d1", R8A77995_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A77995_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A77995_CLK_S3D4, CLK_S3, 4, 1),
+
+ DEF_FIXED("cl", R8A77995_CLK_CL, CLK_PLL1, 48, 1),
+ DEF_FIXED("cr", R8A77995_CLK_CR, CLK_PLL1D2, 2, 1),
+ DEF_FIXED("cp", R8A77995_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A77995_CLK_CPEX, CLK_EXTAL, 4, 1),
+
+ DEF_DIV6_RO("osc", R8A77995_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8),
+
+ DEF_GEN3_PE("s1d4c", R8A77995_CLK_S1D4C, CLK_S1, 4, CLK_PE, 2),
+ DEF_GEN3_PE("s3d1c", R8A77995_CLK_S3D1C, CLK_S3, 1, CLK_PE, 1),
+ DEF_GEN3_PE("s3d2c", R8A77995_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2),
+ DEF_GEN3_PE("s3d4c", R8A77995_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4),
+
+ DEF_GEN3_SDH("sd0h", R8A77995_CLK_SD0H, CLK_SDSRC, 0x268),
+ DEF_GEN3_SD("sd0", R8A77995_CLK_SD0, R8A77995_CLK_SD0H, 0x268),
+
+ DEF_BASE("rpc", R8A77995_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A77995_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A77995_CLK_RPC),
+
+ DEF_DIV6P1("canfd", R8A77995_CLK_CANFD, CLK_PLL0D3, 0x244),
+ DEF_DIV6P1("mso", R8A77995_CLK_MSO, CLK_PLL1D2, 0x014),
+
+ DEF_GEN3_RCKSEL("r", R8A77995_CLK_R, CLK_RINT, 1, CLK_OCO, 61 * 4),
+};
+
+static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = {
+ DEF_MOD("tmu4", 121, R8A77995_CLK_S1D4C),
+ DEF_MOD("tmu3", 122, R8A77995_CLK_S3D2C),
+ DEF_MOD("tmu2", 123, R8A77995_CLK_S3D2C),
+ DEF_MOD("tmu1", 124, R8A77995_CLK_S3D2C),
+ DEF_MOD("tmu0", 125, R8A77995_CLK_CP),
+ DEF_MOD("scif5", 202, R8A77995_CLK_S3D4C),
+ DEF_MOD("scif4", 203, R8A77995_CLK_S3D4C),
+ DEF_MOD("scif3", 204, R8A77995_CLK_S3D4C),
+ DEF_MOD("scif1", 206, R8A77995_CLK_S3D4C),
+ DEF_MOD("scif0", 207, R8A77995_CLK_S3D4C),
+ DEF_MOD("msiof3", 208, R8A77995_CLK_MSO),
+ DEF_MOD("msiof2", 209, R8A77995_CLK_MSO),
+ DEF_MOD("msiof1", 210, R8A77995_CLK_MSO),
+ DEF_MOD("msiof0", 211, R8A77995_CLK_MSO),
+ DEF_MOD("sys-dmac2", 217, R8A77995_CLK_S3D1),
+ DEF_MOD("sys-dmac1", 218, R8A77995_CLK_S3D1),
+ DEF_MOD("sys-dmac0", 219, R8A77995_CLK_S3D1),
+ DEF_MOD("sceg-pub", 229, R8A77995_CLK_CR),
+ DEF_MOD("cmt3", 300, R8A77995_CLK_R),
+ DEF_MOD("cmt2", 301, R8A77995_CLK_R),
+ DEF_MOD("cmt1", 302, R8A77995_CLK_R),
+ DEF_MOD("cmt0", 303, R8A77995_CLK_R),
+ DEF_MOD("scif2", 310, R8A77995_CLK_S3D4C),
+ DEF_MOD("emmc0", 312, R8A77995_CLK_SD0),
+ DEF_MOD("usb-dmac0", 330, R8A77995_CLK_S3D1),
+ DEF_MOD("usb-dmac1", 331, R8A77995_CLK_S3D1),
+ DEF_MOD("rwdt", 402, R8A77995_CLK_R),
+ DEF_MOD("intc-ex", 407, R8A77995_CLK_CP),
+ DEF_MOD("intc-ap", 408, R8A77995_CLK_S1D2),
+ DEF_MOD("audmac0", 502, R8A77995_CLK_S1D2),
+ DEF_MOD("hscif3", 517, R8A77995_CLK_S3D1C),
+ DEF_MOD("hscif0", 520, R8A77995_CLK_S3D1C),
+ DEF_MOD("thermal", 522, R8A77995_CLK_CP),
+ DEF_MOD("pwm", 523, R8A77995_CLK_S3D4C),
+ DEF_MOD("fcpvd1", 602, R8A77995_CLK_S1D2),
+ DEF_MOD("fcpvd0", 603, R8A77995_CLK_S1D2),
+ DEF_MOD("fcpvbs", 607, R8A77995_CLK_S0D1),
+ DEF_MOD("vspd1", 622, R8A77995_CLK_S1D2),
+ DEF_MOD("vspd0", 623, R8A77995_CLK_S1D2),
+ DEF_MOD("vspbs", 627, R8A77995_CLK_S0D1),
+ DEF_MOD("ehci0", 703, R8A77995_CLK_S3D2),
+ DEF_MOD("hsusb", 704, R8A77995_CLK_S3D2),
+ DEF_MOD("cmm1", 710, R8A77995_CLK_S1D1),
+ DEF_MOD("cmm0", 711, R8A77995_CLK_S1D1),
+ DEF_MOD("du1", 723, R8A77995_CLK_S1D1),
+ DEF_MOD("du0", 724, R8A77995_CLK_S1D1),
+ DEF_MOD("lvds", 727, R8A77995_CLK_S2D1),
+ DEF_MOD("mlp", 802, R8A77995_CLK_S2D1),
+ DEF_MOD("vin4", 807, R8A77995_CLK_S3D1),
+ DEF_MOD("etheravb", 812, R8A77995_CLK_S3D2),
+ DEF_MOD("imr0", 823, R8A77995_CLK_S1D2),
+ DEF_MOD("gpio6", 906, R8A77995_CLK_S3D4),
+ DEF_MOD("gpio5", 907, R8A77995_CLK_S3D4),
+ DEF_MOD("gpio4", 908, R8A77995_CLK_S3D4),
+ DEF_MOD("gpio3", 909, R8A77995_CLK_S3D4),
+ DEF_MOD("gpio2", 910, R8A77995_CLK_S3D4),
+ DEF_MOD("gpio1", 911, R8A77995_CLK_S3D4),
+ DEF_MOD("gpio0", 912, R8A77995_CLK_S3D4),
+ DEF_MOD("can-fd", 914, R8A77995_CLK_S3D2),
+ DEF_MOD("can-if1", 915, R8A77995_CLK_S3D4),
+ DEF_MOD("can-if0", 916, R8A77995_CLK_S3D4),
+ DEF_MOD("rpc-if", 917, R8A77995_CLK_RPCD2),
+ DEF_MOD("adg", 922, R8A77995_CLK_ZA2),
+ DEF_MOD("i2c3", 928, R8A77995_CLK_S3D2),
+ DEF_MOD("i2c2", 929, R8A77995_CLK_S3D2),
+ DEF_MOD("i2c1", 930, R8A77995_CLK_S3D2),
+ DEF_MOD("i2c0", 931, R8A77995_CLK_S3D2),
+ DEF_MOD("ssi-all", 1005, R8A77995_CLK_S3D4),
+ DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
+ DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
+ DEF_MOD("scu-all", 1017, R8A77995_CLK_S3D4),
+ DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
+ DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a77995_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
+ MOD_CLK_ID(408), /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ * MD19 EXTAL (MHz) PLL0 PLL1 PLL3
+ *--------------------------------------------------------------------
+ * 0 48 x 1 x250/4 x100/3 x100/3
+ * 1 48 x 1 x250/4 x100/3 x58/3
+ */
+#define CPG_PLL_CONFIG_INDEX(md) (((md) & BIT(19)) >> 19)
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[2] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL3 mult/div */
+ { 1, 100, 3, 100, 3, },
+ { 1, 100, 3, 58, 3, },
+};
+
+static int __init r8a77995_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen3_cpg_init(cpg_pll_config, 0, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a77995_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a77995_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a77995_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a77995_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a77995_mod_clks),
+ .num_hw_mod_clks = 12 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a77995_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a77995_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a77995_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
new file mode 100644
index 000000000..d67dff05d
--- /dev/null
+++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
@@ -0,0 +1,318 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a779a0 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen4-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A779A0_CLK_ZG,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL1,
+ CLK_PLL20,
+ CLK_PLL21,
+ CLK_PLL30,
+ CLK_PLL31,
+ CLK_PLL4,
+ CLK_PLL5,
+ CLK_PLL1_DIV2,
+ CLK_PLL20_DIV2,
+ CLK_PLL21_DIV2,
+ CLK_PLL30_DIV2,
+ CLK_PLL31_DIV2,
+ CLK_PLL5_DIV2,
+ CLK_PLL5_DIV4,
+ CLK_S1,
+ CLK_S3,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_OCO,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+#define DEF_PLL(_name, _id, _offset) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN4_PLL2X_3X, CLK_MAIN, \
+ .offset = _offset)
+
+#define CPG_PLL20CR 0x0834 /* PLL20 Control Register */
+#define CPG_PLL21CR 0x0838 /* PLL21 Control Register */
+#define CPG_PLL30CR 0x083c /* PLL30 Control Register */
+#define CPG_PLL31CR 0x0840 /* PLL31 Control Register */
+#define CPG_PLL4CR 0x0844 /* PLL4 Control Register */
+
+static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
+ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN4_PLL1, CLK_MAIN),
+ DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN),
+ DEF_PLL(".pll20", CLK_PLL20, CPG_PLL20CR),
+ DEF_PLL(".pll21", CLK_PLL21, CPG_PLL21CR),
+ DEF_PLL(".pll30", CLK_PLL30, CPG_PLL30CR),
+ DEF_PLL(".pll31", CLK_PLL31, CPG_PLL31CR),
+ DEF_PLL(".pll4", CLK_PLL4, CPG_PLL4CR),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll20_div2", CLK_PLL20_DIV2, CLK_PLL20, 2, 1),
+ DEF_FIXED(".pll21_div2", CLK_PLL21_DIV2, CLK_PLL21, 2, 1),
+ DEF_FIXED(".pll30_div2", CLK_PLL30_DIV2, CLK_PLL30, 2, 1),
+ DEF_FIXED(".pll31_div2", CLK_PLL31_DIV2, CLK_PLL31, 2, 1),
+ DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2, CLK_PLL5, 2, 1),
+ DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1),
+ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL5_DIV4, 1, 1),
+
+ DEF_RATE(".oco", CLK_OCO, 32768),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+
+ /* Core Clock Outputs */
+ DEF_GEN4_Z("z0", R8A779A0_CLK_Z0, CLK_TYPE_GEN4_Z, CLK_PLL20, 2, 0),
+ DEF_GEN4_Z("z1", R8A779A0_CLK_Z1, CLK_TYPE_GEN4_Z, CLK_PLL21, 2, 8),
+ DEF_GEN4_Z("zg", R8A779A0_CLK_ZG, CLK_TYPE_GEN4_Z, CLK_PLL4, 2, 88),
+ DEF_FIXED("zx", R8A779A0_CLK_ZX, CLK_PLL20_DIV2, 2, 1),
+ DEF_FIXED("s1d1", R8A779A0_CLK_S1D1, CLK_S1, 1, 1),
+ DEF_FIXED("s1d2", R8A779A0_CLK_S1D2, CLK_S1, 2, 1),
+ DEF_FIXED("s1d4", R8A779A0_CLK_S1D4, CLK_S1, 4, 1),
+ DEF_FIXED("s1d8", R8A779A0_CLK_S1D8, CLK_S1, 8, 1),
+ DEF_FIXED("s1d12", R8A779A0_CLK_S1D12, CLK_S1, 12, 1),
+ DEF_FIXED("s3d1", R8A779A0_CLK_S3D1, CLK_S3, 1, 1),
+ DEF_FIXED("s3d2", R8A779A0_CLK_S3D2, CLK_S3, 2, 1),
+ DEF_FIXED("s3d4", R8A779A0_CLK_S3D4, CLK_S3, 4, 1),
+ DEF_FIXED("zs", R8A779A0_CLK_ZS, CLK_PLL1_DIV2, 4, 1),
+ DEF_FIXED("zt", R8A779A0_CLK_ZT, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED("ztr", R8A779A0_CLK_ZTR, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED("zr", R8A779A0_CLK_ZR, CLK_PLL1_DIV2, 1, 1),
+ DEF_FIXED("cnndsp", R8A779A0_CLK_CNNDSP, CLK_PLL5_DIV4, 1, 1),
+ DEF_FIXED("vip", R8A779A0_CLK_VIP, CLK_PLL5, 5, 1),
+ DEF_FIXED("adgh", R8A779A0_CLK_ADGH, CLK_PLL5_DIV4, 1, 1),
+ DEF_FIXED("icu", R8A779A0_CLK_ICU, CLK_PLL5_DIV4, 2, 1),
+ DEF_FIXED("icud2", R8A779A0_CLK_ICUD2, CLK_PLL5_DIV4, 4, 1),
+ DEF_FIXED("vcbus", R8A779A0_CLK_VCBUS, CLK_PLL5_DIV4, 1, 1),
+ DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cp", R8A779A0_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cl16mck", R8A779A0_CLK_CL16MCK, CLK_PLL1_DIV2, 64, 1),
+
+ DEF_GEN4_SDH("sd0h", R8A779A0_CLK_SD0H, CLK_SDSRC, CPG_SD0CKCR),
+ DEF_GEN4_SD("sd0", R8A779A0_CLK_SD0, R8A779A0_CLK_SD0H, CPG_SD0CKCR),
+
+ DEF_BASE("rpc", R8A779A0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A779A0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2,
+ R8A779A0_CLK_RPC),
+
+ DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, CPG_MSOCKCR),
+ DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, CPG_CANFDCKCR),
+ DEF_DIV6P1("csi0", R8A779A0_CLK_CSI0, CLK_PLL5_DIV4, CPG_CSICKCR),
+ DEF_DIV6P1("dsi", R8A779A0_CLK_DSI, CLK_PLL5_DIV4, CPG_DSIEXTCKCR),
+
+ DEF_GEN4_OSC("osc", R8A779A0_CLK_OSC, CLK_EXTAL, 8),
+ DEF_GEN4_MDSEL("r", R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+};
+
+static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
+ DEF_MOD("3dge", 0, R8A779A0_CLK_ZG),
+ DEF_MOD("isp0", 16, R8A779A0_CLK_S1D1),
+ DEF_MOD("isp1", 17, R8A779A0_CLK_S1D1),
+ DEF_MOD("isp2", 18, R8A779A0_CLK_S1D1),
+ DEF_MOD("isp3", 19, R8A779A0_CLK_S1D1),
+ DEF_MOD("avb0", 211, R8A779A0_CLK_S3D2),
+ DEF_MOD("avb1", 212, R8A779A0_CLK_S3D2),
+ DEF_MOD("avb2", 213, R8A779A0_CLK_S3D2),
+ DEF_MOD("avb3", 214, R8A779A0_CLK_S3D2),
+ DEF_MOD("avb4", 215, R8A779A0_CLK_S3D2),
+ DEF_MOD("avb5", 216, R8A779A0_CLK_S3D2),
+ DEF_MOD("canfd0", 328, R8A779A0_CLK_S3D2),
+ DEF_MOD("csi40", 331, R8A779A0_CLK_CSI0),
+ DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0),
+ DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0),
+ DEF_MOD("csi43", 402, R8A779A0_CLK_CSI0),
+ DEF_MOD("du", 411, R8A779A0_CLK_S3D1),
+ DEF_MOD("dsi0", 415, R8A779A0_CLK_DSI),
+ DEF_MOD("dsi1", 416, R8A779A0_CLK_DSI),
+ DEF_MOD("fcpvd0", 508, R8A779A0_CLK_S3D1),
+ DEF_MOD("fcpvd1", 509, R8A779A0_CLK_S3D1),
+ DEF_MOD("hscif0", 514, R8A779A0_CLK_S1D2),
+ DEF_MOD("hscif1", 515, R8A779A0_CLK_S1D2),
+ DEF_MOD("hscif2", 516, R8A779A0_CLK_S1D2),
+ DEF_MOD("hscif3", 517, R8A779A0_CLK_S1D2),
+ DEF_MOD("i2c0", 518, R8A779A0_CLK_S1D4),
+ DEF_MOD("i2c1", 519, R8A779A0_CLK_S1D4),
+ DEF_MOD("i2c2", 520, R8A779A0_CLK_S1D4),
+ DEF_MOD("i2c3", 521, R8A779A0_CLK_S1D4),
+ DEF_MOD("i2c4", 522, R8A779A0_CLK_S1D4),
+ DEF_MOD("i2c5", 523, R8A779A0_CLK_S1D4),
+ DEF_MOD("i2c6", 524, R8A779A0_CLK_S1D4),
+ DEF_MOD("ispcs0", 612, R8A779A0_CLK_S1D1),
+ DEF_MOD("ispcs1", 613, R8A779A0_CLK_S1D1),
+ DEF_MOD("ispcs2", 614, R8A779A0_CLK_S1D1),
+ DEF_MOD("ispcs3", 615, R8A779A0_CLK_S1D1),
+ DEF_MOD("msi0", 618, R8A779A0_CLK_MSO),
+ DEF_MOD("msi1", 619, R8A779A0_CLK_MSO),
+ DEF_MOD("msi2", 620, R8A779A0_CLK_MSO),
+ DEF_MOD("msi3", 621, R8A779A0_CLK_MSO),
+ DEF_MOD("msi4", 622, R8A779A0_CLK_MSO),
+ DEF_MOD("msi5", 623, R8A779A0_CLK_MSO),
+ DEF_MOD("pwm0", 628, R8A779A0_CLK_S1D8),
+ DEF_MOD("rpc-if", 629, R8A779A0_CLK_RPCD2),
+ DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8),
+ DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8),
+ DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8),
+ DEF_MOD("scif4", 705, R8A779A0_CLK_S1D8),
+ DEF_MOD("sdhi0", 706, R8A779A0_CLK_SD0),
+ DEF_MOD("sys-dmac1", 709, R8A779A0_CLK_S1D2),
+ DEF_MOD("sys-dmac2", 710, R8A779A0_CLK_S1D2),
+ DEF_MOD("tmu0", 713, R8A779A0_CLK_CL16MCK),
+ DEF_MOD("tmu1", 714, R8A779A0_CLK_S1D4),
+ DEF_MOD("tmu2", 715, R8A779A0_CLK_S1D4),
+ DEF_MOD("tmu3", 716, R8A779A0_CLK_S1D4),
+ DEF_MOD("tmu4", 717, R8A779A0_CLK_S1D4),
+ DEF_MOD("tpu0", 718, R8A779A0_CLK_S1D8),
+ DEF_MOD("vin00", 730, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin01", 731, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin02", 800, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin03", 801, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin04", 802, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin05", 803, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin06", 804, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin07", 805, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin10", 806, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin11", 807, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin12", 808, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin13", 809, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin14", 810, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin15", 811, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin16", 812, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin17", 813, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin20", 814, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin21", 815, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin22", 816, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin23", 817, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin24", 818, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin25", 819, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin26", 820, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin27", 821, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin30", 822, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin31", 823, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin32", 824, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin33", 825, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin34", 826, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin35", 827, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin36", 828, R8A779A0_CLK_S1D1),
+ DEF_MOD("vin37", 829, R8A779A0_CLK_S1D1),
+ DEF_MOD("vspd0", 830, R8A779A0_CLK_S3D1),
+ DEF_MOD("vspd1", 831, R8A779A0_CLK_S3D1),
+ DEF_MOD("rwdt", 907, R8A779A0_CLK_R),
+ DEF_MOD("cmt0", 910, R8A779A0_CLK_R),
+ DEF_MOD("cmt1", 911, R8A779A0_CLK_R),
+ DEF_MOD("cmt2", 912, R8A779A0_CLK_R),
+ DEF_MOD("cmt3", 913, R8A779A0_CLK_R),
+ DEF_MOD("pfc0", 915, R8A779A0_CLK_CP),
+ DEF_MOD("pfc1", 916, R8A779A0_CLK_CP),
+ DEF_MOD("pfc2", 917, R8A779A0_CLK_CP),
+ DEF_MOD("pfc3", 918, R8A779A0_CLK_CP),
+ DEF_MOD("tsc", 919, R8A779A0_CLK_CL16MCK),
+ DEF_MOD("vspx0", 1028, R8A779A0_CLK_S1D1),
+ DEF_MOD("vspx1", 1029, R8A779A0_CLK_S1D1),
+ DEF_MOD("vspx2", 1030, R8A779A0_CLK_S1D1),
+ DEF_MOD("vspx3", 1031, R8A779A0_CLK_S1D1),
+ DEF_MOD("fcpvx0", 1100, R8A779A0_CLK_S1D1),
+ DEF_MOD("fcpvx1", 1101, R8A779A0_CLK_S1D1),
+ DEF_MOD("fcpvx2", 1102, R8A779A0_CLK_S1D1),
+ DEF_MOD("fcpvx3", 1103, R8A779A0_CLK_S1D1),
+};
+
+static const unsigned int r8a779a0_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(907), /* RWDT */
+};
+
+/*
+ * 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
+ * 1 1 33.33 / 2 x128 x216 x128 x144 x192 /32
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
+ (((md) & BIT(13)) >> 13))
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL5 mult/div OSC prediv */
+ { 1, 128, 1, 192, 1, 16, },
+ { 1, 106, 1, 160, 1, 19, },
+ { 0, 0, 0, 0, 0, 0, },
+ { 2, 128, 1, 192, 1, 32, },
+};
+
+static int __init r8a779a0_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+ return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a779a0_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a779a0_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a779a0_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a779a0_mod_clks),
+ .num_hw_mod_clks = 15 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a779a0_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a779a0_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a779a0_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen4_cpg_clk_register,
+
+ .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
+};
diff --git a/drivers/clk/renesas/r8a779f0-cpg-mssr.c b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
new file mode 100644
index 000000000..f33342314
--- /dev/null
+++ b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a779f0 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ * Based on r8a779a0-cpg-mssr.c
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen4-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A779F0_CLK_R,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL3,
+ CLK_PLL5,
+ CLK_PLL6,
+ CLK_PLL1_DIV2,
+ CLK_PLL2_DIV2,
+ CLK_PLL3_DIV2,
+ CLK_PLL5_DIV2,
+ CLK_PLL5_DIV4,
+ CLK_PLL6_DIV2,
+ CLK_S0,
+ CLK_SASYNCPER,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_OCO,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
+ DEF_GEN4_PLL_F9_24(".pll1", 1, CLK_PLL1, CLK_MAIN),
+ DEF_GEN4_PLL_V9_24(".pll2", 2, CLK_PLL2, CLK_MAIN),
+ DEF_GEN4_PLL_V9_24(".pll3", 3, CLK_PLL3, CLK_MAIN),
+ DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN),
+ DEF_GEN4_PLL_V9_24(".pll6", 6, CLK_PLL6, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 2, 1),
+ DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 2, 1),
+ DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2, CLK_PLL5, 2, 1),
+ DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1),
+ DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+
+ DEF_FIXED(".sasyncper", CLK_SASYNCPER, CLK_PLL5_DIV4, 3, 1),
+ DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
+ DEF_RATE(".oco", CLK_OCO, 32768),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+
+ /* Core Clock Outputs */
+ DEF_GEN4_Z("z0", R8A779F0_CLK_Z0, CLK_TYPE_GEN4_Z, CLK_PLL2, 2, 0),
+ DEF_GEN4_Z("z1", R8A779F0_CLK_Z1, CLK_TYPE_GEN4_Z, CLK_PLL2, 2, 8),
+ DEF_FIXED("s0d2", R8A779F0_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A779F0_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A779F0_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("cl16m", R8A779F0_CLK_CL16M, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_mm", R8A779F0_CLK_S0D2_MM, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_mm", R8A779F0_CLK_S0D3_MM, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_mm", R8A779F0_CLK_S0D4_MM, CLK_S0, 4, 1),
+ DEF_FIXED("cl16m_mm", R8A779F0_CLK_CL16M_MM, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_rt", R8A779F0_CLK_S0D2_RT, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_rt", R8A779F0_CLK_S0D3_RT, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_rt", R8A779F0_CLK_S0D4_RT, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6_rt", R8A779F0_CLK_S0D6_RT, CLK_S0, 6, 1),
+ DEF_FIXED("cl16m_rt", R8A779F0_CLK_CL16M_RT, CLK_S0, 48, 1),
+ DEF_FIXED("s0d3_per", R8A779F0_CLK_S0D3_PER, CLK_S0, 3, 1),
+ DEF_FIXED("s0d6_per", R8A779F0_CLK_S0D6_PER, CLK_S0, 6, 1),
+ DEF_FIXED("s0d12_per", R8A779F0_CLK_S0D12_PER, CLK_S0, 12, 1),
+ DEF_FIXED("s0d24_per", R8A779F0_CLK_S0D24_PER, CLK_S0, 24, 1),
+ DEF_FIXED("cl16m_per", R8A779F0_CLK_CL16M_PER, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_hsc", R8A779F0_CLK_S0D2_HSC, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_hsc", R8A779F0_CLK_S0D3_HSC, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_hsc", R8A779F0_CLK_S0D4_HSC, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6_hsc", R8A779F0_CLK_S0D6_HSC, CLK_S0, 6, 1),
+ DEF_FIXED("s0d12_hsc", R8A779F0_CLK_S0D12_HSC, CLK_S0, 12, 1),
+ DEF_FIXED("cl16m_hsc", R8A779F0_CLK_CL16M_HSC, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_cc", R8A779F0_CLK_S0D2_CC, CLK_S0, 2, 1),
+ DEF_FIXED("rsw2", R8A779F0_CLK_RSW2, CLK_PLL5_DIV2, 5, 1),
+ DEF_FIXED("cbfusa", R8A779F0_CLK_CBFUSA, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A779F0_CLK_CPEX, CLK_EXTAL, 2, 1),
+
+ DEF_FIXED("sasyncrt", R8A779F0_CLK_SASYNCRT, CLK_PLL5_DIV4, 48, 1),
+ DEF_FIXED("sasyncperd1",R8A779F0_CLK_SASYNCPERD1, CLK_SASYNCPER,1, 1),
+ DEF_FIXED("sasyncperd2",R8A779F0_CLK_SASYNCPERD2, CLK_SASYNCPER,2, 1),
+ DEF_FIXED("sasyncperd4",R8A779F0_CLK_SASYNCPERD4, CLK_SASYNCPER,4, 1),
+
+ DEF_GEN4_SDH("sd0h", R8A779F0_CLK_SD0H, CLK_SDSRC, CPG_SD0CKCR),
+ DEF_GEN4_SD("sd0", R8A779F0_CLK_SD0, R8A779F0_CLK_SD0H, CPG_SD0CKCR),
+
+ DEF_BASE("rpc", R8A779F0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A779F0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, R8A779F0_CLK_RPC),
+
+ DEF_DIV6P1("mso", R8A779F0_CLK_MSO, CLK_PLL5_DIV4, CPG_MSOCKCR),
+
+ DEF_GEN4_OSC("osc", R8A779F0_CLK_OSC, CLK_EXTAL, 8),
+ DEF_GEN4_MDSEL("r", R8A779F0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+};
+
+static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = {
+ DEF_MOD("hscif0", 514, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif1", 515, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif2", 516, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif3", 517, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("i2c0", 518, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("i2c1", 519, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("i2c2", 520, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("i2c3", 521, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("i2c4", 522, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("i2c5", 523, R8A779F0_CLK_S0D6_PER),
+ DEF_MOD("msiof0", 618, R8A779F0_CLK_MSO),
+ DEF_MOD("msiof1", 619, R8A779F0_CLK_MSO),
+ DEF_MOD("msiof2", 620, R8A779F0_CLK_MSO),
+ DEF_MOD("msiof3", 621, R8A779F0_CLK_MSO),
+ DEF_MOD("pcie0", 624, R8A779F0_CLK_S0D2),
+ DEF_MOD("pcie1", 625, R8A779F0_CLK_S0D2),
+ DEF_MOD("scif0", 702, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("scif1", 703, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("scif3", 704, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("scif4", 705, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("sdhi0", 706, R8A779F0_CLK_SD0),
+ DEF_MOD("sys-dmac0", 709, R8A779F0_CLK_S0D3_PER),
+ DEF_MOD("sys-dmac1", 710, R8A779F0_CLK_S0D3_PER),
+ DEF_MOD("tmu0", 713, R8A779F0_CLK_SASYNCRT),
+ DEF_MOD("tmu1", 714, R8A779F0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu2", 715, R8A779F0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu3", 716, R8A779F0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu4", 717, R8A779F0_CLK_SASYNCPERD2),
+ DEF_MOD("wdt", 907, R8A779F0_CLK_R),
+ DEF_MOD("cmt0", 910, R8A779F0_CLK_R),
+ DEF_MOD("cmt1", 911, R8A779F0_CLK_R),
+ DEF_MOD("cmt2", 912, R8A779F0_CLK_R),
+ DEF_MOD("cmt3", 913, R8A779F0_CLK_R),
+ DEF_MOD("pfc0", 915, R8A779F0_CLK_CPEX),
+ DEF_MOD("tsc", 919, R8A779F0_CLK_CL16M),
+ DEF_MOD("rswitch2", 1505, R8A779F0_CLK_RSW2),
+ DEF_MOD("ether-serdes", 1506, R8A779F0_CLK_S0D2_HSC),
+ DEF_MOD("ufs", 1514, R8A779F0_CLK_S0D4_HSC),
+};
+
+static const unsigned int r8a779f0_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(907), /* WDT */
+};
+
+/*
+ * CPG Clock Data
+ */
+/*
+ * MD EXTAL PLL1 PLL2 PLL3 PLL4 PLL5 PLL6 OSC
+ * 14 13 (MHz)
+ * ------------------------------------------------------------------------
+ * 0 0 16 / 1 x200 x150 x200 n/a x200 x134 /15
+ * 0 1 20 / 1 x160 x120 x160 n/a x160 x106 /19
+ * 1 0 Prohibited setting
+ * 1 1 40 / 2 x160 x120 x160 n/a x160 x106 /38
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
+ (((md) & BIT(13)) >> 13))
+
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL5 mult/div OSC prediv */
+ { 1, 200, 1, 200, 1, 15, },
+ { 1, 160, 1, 160, 1, 19, },
+ { 0, 0, 0, 0, 0, 0, },
+ { 2, 160, 1, 160, 1, 38, },
+};
+
+static int __init r8a779f0_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+ if (!cpg_pll_config->extal_div) {
+ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+ return -EINVAL;
+ }
+
+ return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a779f0_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a779f0_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a779f0_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a779f0_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a779f0_mod_clks),
+ .num_hw_mod_clks = 28 * 32,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r8a779f0_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r8a779f0_crit_mod_clks),
+
+ /* Callbacks */
+ .init = r8a779f0_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen4_cpg_clk_register,
+
+ .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
+};
diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
new file mode 100644
index 000000000..54ba76ff5
--- /dev/null
+++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a779g0 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2022 Renesas Electronics Corp.
+ *
+ * Based on r8a779f0-cpg-mssr.c
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a779g0-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen4-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A779G0_CLK_CP,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL3,
+ CLK_PLL4,
+ CLK_PLL5,
+ CLK_PLL6,
+ CLK_PLL1_DIV2,
+ CLK_PLL2_DIV2,
+ CLK_PLL3_DIV2,
+ CLK_PLL4_DIV2,
+ CLK_PLL5_DIV2,
+ CLK_PLL5_DIV4,
+ CLK_PLL6_DIV2,
+ CLK_S0,
+ CLK_S0_VIO,
+ CLK_S0_VC,
+ CLK_S0_HSC,
+ CLK_SASYNCPER,
+ CLK_SV_VIP,
+ CLK_SV_IR,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_VIO,
+ CLK_VC,
+ CLK_OCO,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
+ DEF_GEN4_PLL_F8_25(".pll1", 1, CLK_PLL1, CLK_MAIN),
+ DEF_GEN4_PLL_V8_25(".pll2", 2, CLK_PLL2, CLK_MAIN),
+ DEF_GEN4_PLL_V8_25(".pll3", 3, CLK_PLL3, CLK_MAIN),
+ DEF_GEN4_PLL_V8_25(".pll4", 4, CLK_PLL4, CLK_MAIN),
+ DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN),
+ DEF_GEN4_PLL_V8_25(".pll6", 6, CLK_PLL6, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 2, 1),
+ DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 2, 1),
+ DEF_FIXED(".pll4_div2", CLK_PLL4_DIV2, CLK_PLL4, 2, 1),
+ DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2, CLK_PLL5, 2, 1),
+ DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1),
+ DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_vio", CLK_S0_VIO, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_vc", CLK_S0_VC, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_hsc", CLK_S0_HSC, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".sasyncper", CLK_SASYNCPER, CLK_PLL5_DIV4, 3, 1),
+ DEF_FIXED(".sv_vip", CLK_SV_VIP, CLK_PLL1, 5, 1),
+ DEF_FIXED(".sv_ir", CLK_SV_IR, CLK_PLL1, 5, 1),
+ DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
+ DEF_RATE(".oco", CLK_OCO, 32768),
+
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+ DEF_FIXED(".vio", CLK_VIO, CLK_PLL5_DIV2, 3, 1),
+ DEF_FIXED(".vc", CLK_VC, CLK_PLL5_DIV2, 3, 1),
+
+ /* Core Clock Outputs */
+ DEF_GEN4_Z("z0", R8A779G0_CLK_Z0, CLK_TYPE_GEN4_Z, CLK_PLL2, 2, 0),
+ DEF_FIXED("s0d2", R8A779G0_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A779G0_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A779G0_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("cl16m", R8A779G0_CLK_CL16M, CLK_S0, 48, 1),
+ DEF_FIXED("s0d1_vio", R8A779G0_CLK_S0D1_VIO, CLK_S0_VIO, 1, 1),
+ DEF_FIXED("s0d2_vio", R8A779G0_CLK_S0D2_VIO, CLK_S0_VIO, 2, 1),
+ DEF_FIXED("s0d4_vio", R8A779G0_CLK_S0D4_VIO, CLK_S0_VIO, 4, 1),
+ DEF_FIXED("s0d8_vio", R8A779G0_CLK_S0D8_VIO, CLK_S0_VIO, 8, 1),
+ DEF_FIXED("s0d1_vc", R8A779G0_CLK_S0D1_VC, CLK_S0_VC, 1, 1),
+ DEF_FIXED("s0d2_vc", R8A779G0_CLK_S0D2_VC, CLK_S0_VC, 2, 1),
+ DEF_FIXED("s0d4_vc", R8A779G0_CLK_S0D4_VC, CLK_S0_VC, 4, 1),
+ DEF_FIXED("s0d2_mm", R8A779G0_CLK_S0D2_MM, CLK_S0, 2, 1),
+ DEF_FIXED("s0d4_mm", R8A779G0_CLK_S0D4_MM, CLK_S0, 4, 1),
+ DEF_FIXED("cl16m_mm", R8A779G0_CLK_CL16M_MM, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_u3dg", R8A779G0_CLK_S0D2_U3DG, CLK_S0, 2, 1),
+ DEF_FIXED("s0d4_u3dg", R8A779G0_CLK_S0D4_U3DG, CLK_S0, 4, 1),
+ DEF_FIXED("s0d2_rt", R8A779G0_CLK_S0D2_RT, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_rt", R8A779G0_CLK_S0D3_RT, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_rt", R8A779G0_CLK_S0D4_RT, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6_rt", R8A779G0_CLK_S0D6_RT, CLK_S0, 6, 1),
+ DEF_FIXED("s0d24_rt", R8A779G0_CLK_S0D24_RT, CLK_S0, 24, 1),
+ DEF_FIXED("cl16m_rt", R8A779G0_CLK_CL16M_RT, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_per", R8A779G0_CLK_S0D2_PER, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_per", R8A779G0_CLK_S0D3_PER, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_per", R8A779G0_CLK_S0D4_PER, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6_per", R8A779G0_CLK_S0D6_PER, CLK_S0, 6, 1),
+ DEF_FIXED("s0d12_per", R8A779G0_CLK_S0D12_PER, CLK_S0, 12, 1),
+ DEF_FIXED("s0d24_per", R8A779G0_CLK_S0D24_PER, CLK_S0, 24, 1),
+ DEF_FIXED("cl16m_per", R8A779G0_CLK_CL16M_PER, CLK_S0, 48, 1),
+ DEF_FIXED("s0d1_hsc", R8A779G0_CLK_S0D1_HSC, CLK_S0_HSC, 1, 1),
+ DEF_FIXED("s0d2_hsc", R8A779G0_CLK_S0D2_HSC, CLK_S0_HSC, 2, 1),
+ DEF_FIXED("s0d4_hsc", R8A779G0_CLK_S0D4_HSC, CLK_S0_HSC, 4, 1),
+ DEF_FIXED("cl16m_hsc", R8A779G0_CLK_CL16M_HSC, CLK_S0_HSC, 48, 1),
+ DEF_FIXED("s0d2_cc", R8A779G0_CLK_S0D2_CC, CLK_S0, 2, 1),
+ DEF_FIXED("sasyncrt", R8A779G0_CLK_SASYNCRT, CLK_PLL5_DIV4, 48, 1),
+ DEF_FIXED("sasyncperd1",R8A779G0_CLK_SASYNCPERD1, CLK_SASYNCPER,1, 1),
+ DEF_FIXED("sasyncperd2",R8A779G0_CLK_SASYNCPERD2, CLK_SASYNCPER,2, 1),
+ DEF_FIXED("sasyncperd4",R8A779G0_CLK_SASYNCPERD4, CLK_SASYNCPER,4, 1),
+ DEF_FIXED("svd1_ir", R8A779G0_CLK_SVD1_IR, CLK_SV_IR, 1, 1),
+ DEF_FIXED("svd2_ir", R8A779G0_CLK_SVD2_IR, CLK_SV_IR, 2, 1),
+ DEF_FIXED("svd1_vip", R8A779G0_CLK_SVD1_VIP, CLK_SV_VIP, 1, 1),
+ DEF_FIXED("svd2_vip", R8A779G0_CLK_SVD2_VIP, CLK_SV_VIP, 2, 1),
+ DEF_FIXED("cbfusa", R8A779G0_CLK_CBFUSA, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A779G0_CLK_CPEX, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cp", R8A779G0_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("viobus", R8A779G0_CLK_VIOBUS, CLK_VIO, 1, 1),
+ DEF_FIXED("viobusd2", R8A779G0_CLK_VIOBUSD2, CLK_VIO, 2, 1),
+ DEF_FIXED("vcbus", R8A779G0_CLK_VCBUS, CLK_VC, 1, 1),
+ DEF_FIXED("vcbusd2", R8A779G0_CLK_VCBUSD2, CLK_VC, 2, 1),
+ DEF_DIV6P1("canfd", R8A779G0_CLK_CANFD, CLK_PLL5_DIV4, CPG_CANFDCKCR),
+ DEF_DIV6P1("csi", R8A779G0_CLK_CSI, CLK_PLL5_DIV4, CPG_CSICKCR),
+ DEF_FIXED("dsiref", R8A779G0_CLK_DSIREF, CLK_PLL5_DIV4, 48, 1),
+ DEF_DIV6P1("dsiext", R8A779G0_CLK_DSIEXT, CLK_PLL5_DIV4, CPG_DSIEXTCKCR),
+
+ DEF_GEN4_SDH("sd0h", R8A779G0_CLK_SD0H, CLK_SDSRC, CPG_SD0CKCR),
+ DEF_GEN4_SD("sd0", R8A779G0_CLK_SD0, R8A779G0_CLK_SD0H, CPG_SD0CKCR),
+ DEF_DIV6P1("mso", R8A779G0_CLK_MSO, CLK_PLL5_DIV4, CPG_MSOCKCR),
+
+ DEF_BASE("rpc", R8A779G0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A779G0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, R8A779G0_CLK_RPC),
+
+ DEF_GEN4_OSC("osc", R8A779G0_CLK_OSC, CLK_EXTAL, 8),
+ DEF_GEN4_MDSEL("r", R8A779G0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+};
+
+static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = {
+ DEF_MOD("isp0", 16, R8A779G0_CLK_S0D2_VIO),
+ DEF_MOD("isp1", 17, R8A779G0_CLK_S0D2_VIO),
+ DEF_MOD("avb0", 211, R8A779G0_CLK_S0D4_HSC),
+ DEF_MOD("avb1", 212, R8A779G0_CLK_S0D4_HSC),
+ DEF_MOD("avb2", 213, R8A779G0_CLK_S0D4_HSC),
+ DEF_MOD("canfd0", 328, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("csi40", 331, R8A779G0_CLK_CSI),
+ DEF_MOD("csi41", 400, R8A779G0_CLK_CSI),
+ DEF_MOD("dis0", 411, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("dsitxlink0", 415, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("dsitxlink1", 416, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("fcpvd0", 508, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("fcpvd1", 509, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("hscif0", 514, R8A779G0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif1", 515, R8A779G0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif2", 516, R8A779G0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif3", 517, R8A779G0_CLK_SASYNCPERD1),
+ DEF_MOD("i2c0", 518, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("i2c1", 519, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("i2c2", 520, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("i2c3", 521, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("i2c4", 522, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("i2c5", 523, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("irqc", 611, R8A779G0_CLK_CL16M),
+ DEF_MOD("ispcs0", 612, R8A779G0_CLK_S0D2_VIO),
+ DEF_MOD("ispcs1", 613, R8A779G0_CLK_S0D2_VIO),
+ DEF_MOD("msi0", 618, R8A779G0_CLK_MSO),
+ DEF_MOD("msi1", 619, R8A779G0_CLK_MSO),
+ DEF_MOD("msi2", 620, R8A779G0_CLK_MSO),
+ DEF_MOD("msi3", 621, R8A779G0_CLK_MSO),
+ DEF_MOD("msi4", 622, R8A779G0_CLK_MSO),
+ DEF_MOD("msi5", 623, R8A779G0_CLK_MSO),
+ DEF_MOD("pciec0", 624, R8A779G0_CLK_S0D2_HSC),
+ DEF_MOD("pciec1", 625, R8A779G0_CLK_S0D2_HSC),
+ DEF_MOD("pwm", 628, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("rpc-if", 629, R8A779G0_CLK_RPCD2),
+ DEF_MOD("scif0", 702, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("scif1", 703, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("scif3", 704, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("scif4", 705, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("sdhi", 706, R8A779G0_CLK_SD0),
+ DEF_MOD("sys-dmac0", 709, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("sys-dmac1", 710, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("tmu0", 713, R8A779G0_CLK_SASYNCRT),
+ DEF_MOD("tmu1", 714, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu2", 715, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu3", 716, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu4", 717, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tpu0", 718, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("vin00", 730, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin01", 731, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin02", 800, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin03", 801, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin04", 802, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin05", 803, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin06", 804, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin07", 805, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin10", 806, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin11", 807, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin12", 808, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin13", 809, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin14", 810, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin15", 811, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin16", 812, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vin17", 813, R8A779G0_CLK_S0D4_VIO),
+ DEF_MOD("vspd0", 830, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("vspd1", 831, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("wdt1:wdt0", 907, R8A779G0_CLK_R),
+ DEF_MOD("cmt0", 910, R8A779G0_CLK_R),
+ DEF_MOD("cmt1", 911, R8A779G0_CLK_R),
+ DEF_MOD("cmt2", 912, R8A779G0_CLK_R),
+ DEF_MOD("cmt3", 913, R8A779G0_CLK_R),
+ DEF_MOD("pfc0", 915, R8A779G0_CLK_CP),
+ DEF_MOD("pfc1", 916, R8A779G0_CLK_CP),
+ DEF_MOD("pfc2", 917, R8A779G0_CLK_CP),
+ DEF_MOD("pfc3", 918, R8A779G0_CLK_CP),
+ DEF_MOD("tsc", 919, R8A779G0_CLK_CL16M),
+ DEF_MOD("vspx0", 1028, R8A779G0_CLK_S0D1_VIO),
+ DEF_MOD("vspx1", 1029, R8A779G0_CLK_S0D1_VIO),
+ DEF_MOD("fcpvx0", 1100, R8A779G0_CLK_S0D1_VIO),
+ DEF_MOD("fcpvx1", 1101, R8A779G0_CLK_S0D1_VIO),
+ DEF_MOD("tsn", 2723, R8A779G0_CLK_S0D4_HSC),
+ DEF_MOD("dsc", 2819, R8A779G0_CLK_VIOBUSD2),
+ DEF_MOD("ssiu", 2926, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("ssi", 2927, R8A779G0_CLK_S0D6_PER),
+};
+
+/*
+ * CPG Clock Data
+ */
+/*
+ * MD EXTAL PLL1 PLL2 PLL3 PLL4 PLL5 PLL6 OSC
+ * 14 13 (MHz)
+ * ------------------------------------------------------------------------
+ * 0 0 16.66 / 1 x192 x204 x192 x144 x192 x168 /16
+ * 0 1 20 / 1 x160 x170 x160 x120 x160 x140 /19
+ * 1 0 Prohibited setting
+ * 1 1 33.33 / 2 x192 x204 x192 x144 x192 x168 /32
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
+ (((md) & BIT(13)) >> 13))
+
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL5 mult/div OSC prediv */
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 160, 1, 160, 1, 19, },
+ { 0, 0, 0, 0, 0, 0, },
+ { 2, 192, 1, 192, 1, 32, },
+};
+
+static int __init r8a779g0_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+ if (!cpg_pll_config->extal_div) {
+ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+ return -EINVAL;
+ }
+
+ return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a779g0_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a779g0_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a779g0_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a779g0_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a779g0_mod_clks),
+ .num_hw_mod_clks = 30 * 32,
+
+ /* Callbacks */
+ .init = r8a779g0_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen4_cpg_clk_register,
+
+ .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
+};
diff --git a/drivers/clk/renesas/r8a779h0-cpg-mssr.c b/drivers/clk/renesas/r8a779h0-cpg-mssr.c
new file mode 100644
index 000000000..ffea06d77
--- /dev/null
+++ b/drivers/clk/renesas/r8a779h0-cpg-mssr.c
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a779h0 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ *
+ * Based on r8a779g0-cpg-mssr.c
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/renesas,r8a779h0-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen4-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R8A779H0_CLK_R,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL3,
+ CLK_PLL4,
+ CLK_PLL5,
+ CLK_PLL6,
+ CLK_PLL1_DIV2,
+ CLK_PLL3_DIV2,
+ CLK_PLL4_DIV2,
+ CLK_PLL4_DIV5,
+ CLK_PLL5_DIV2,
+ CLK_PLL5_DIV4,
+ CLK_PLL6_DIV2,
+ CLK_S0,
+ CLK_S0_VIO,
+ CLK_S0_VC,
+ CLK_S0_HSC,
+ CLK_SASYNCPER,
+ CLK_SV_VIP,
+ CLK_SV_IR,
+ CLK_IMPASRC,
+ CLK_IMPBSRC,
+ CLK_VIOSRC,
+ CLK_VCSRC,
+ CLK_SDSRC,
+ CLK_RPCSRC,
+ CLK_OCO,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a779h0_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("extalr", CLK_EXTALR),
+
+ /* Internal Core Clocks */
+ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
+ DEF_GEN4_PLL_F8_25(".pll1", 1, CLK_PLL1, CLK_MAIN),
+ DEF_GEN4_PLL_V8_25(".pll2", 2, CLK_PLL2, CLK_MAIN),
+ DEF_GEN4_PLL_V8_25(".pll3", 3, CLK_PLL3, CLK_MAIN),
+ DEF_GEN4_PLL_V8_25(".pll4", 4, CLK_PLL4, CLK_MAIN),
+ DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN),
+ DEF_GEN4_PLL_V8_25(".pll6", 6, CLK_PLL6, CLK_MAIN),
+
+ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+ DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 2, 1),
+ DEF_FIXED(".pll4_div2", CLK_PLL4_DIV2, CLK_PLL4, 2, 1),
+ DEF_FIXED(".pll4_div5", CLK_PLL4_DIV5, CLK_PLL4, 5, 1),
+ DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2, CLK_PLL5, 2, 1),
+ DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1),
+ DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 2, 1),
+ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_vio", CLK_S0_VIO, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_vc", CLK_S0_VC, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_hsc", CLK_S0_HSC, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".sasyncper", CLK_SASYNCPER, CLK_PLL5_DIV4, 3, 1),
+ DEF_FIXED(".sv_vip", CLK_SV_VIP, CLK_PLL1, 5, 1),
+ DEF_FIXED(".sv_ir", CLK_SV_IR, CLK_PLL1, 5, 1),
+ DEF_FIXED(".impasrc", CLK_IMPASRC, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".impbsrc", CLK_IMPBSRC, CLK_PLL1, 4, 1),
+ DEF_FIXED(".viosrc", CLK_VIOSRC, CLK_PLL1, 6, 1),
+ DEF_FIXED(".vcsrc", CLK_VCSRC, CLK_PLL1, 6, 1),
+ DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+ DEF_RATE(".oco", CLK_OCO, 32768),
+
+ /* Core Clock Outputs */
+ DEF_GEN4_Z("zc0", R8A779H0_CLK_ZC0, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 0),
+ DEF_GEN4_Z("zc1", R8A779H0_CLK_ZC1, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 8),
+ DEF_GEN4_Z("zc2", R8A779H0_CLK_ZC2, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 32),
+ DEF_GEN4_Z("zc3", R8A779H0_CLK_ZC3, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 40),
+ DEF_FIXED("s0d2", R8A779H0_CLK_S0D2, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3", R8A779H0_CLK_S0D3, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4", R8A779H0_CLK_S0D4, CLK_S0, 4, 1),
+ DEF_FIXED("cl16m", R8A779H0_CLK_CL16M, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_rt", R8A779H0_CLK_S0D2_RT, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_rt", R8A779H0_CLK_S0D3_RT, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_rt", R8A779H0_CLK_S0D4_RT, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6_rt", R8A779H0_CLK_S0D6_RT, CLK_S0, 6, 1),
+ DEF_FIXED("cl16m_rt", R8A779H0_CLK_CL16M_RT, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_per", R8A779H0_CLK_S0D2_PER, CLK_S0, 2, 1),
+ DEF_FIXED("s0d3_per", R8A779H0_CLK_S0D3_PER, CLK_S0, 3, 1),
+ DEF_FIXED("s0d4_per", R8A779H0_CLK_S0D4_PER, CLK_S0, 4, 1),
+ DEF_FIXED("s0d6_per", R8A779H0_CLK_S0D6_PER, CLK_S0, 6, 1),
+ DEF_FIXED("s0d12_per", R8A779H0_CLK_S0D12_PER, CLK_S0, 12, 1),
+ DEF_FIXED("s0d24_per", R8A779H0_CLK_S0D24_PER, CLK_S0, 24, 1),
+ DEF_FIXED("cl16m_per", R8A779H0_CLK_CL16M_PER, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_mm", R8A779H0_CLK_S0D2_MM, CLK_S0, 2, 1),
+ DEF_FIXED("s0d4_mm", R8A779H0_CLK_S0D4_MM, CLK_S0, 4, 1),
+ DEF_FIXED("cl16m_mm", R8A779H0_CLK_CL16M_MM, CLK_S0, 48, 1),
+ DEF_FIXED("s0d2_u3dg", R8A779H0_CLK_S0D2_U3DG, CLK_S0, 2, 1),
+ DEF_FIXED("s0d4_u3dg", R8A779H0_CLK_S0D4_U3DG, CLK_S0, 4, 1),
+ DEF_FIXED("s0d1_vio", R8A779H0_CLK_S0D1_VIO, CLK_S0_VIO, 1, 1),
+ DEF_FIXED("s0d2_vio", R8A779H0_CLK_S0D2_VIO, CLK_S0_VIO, 2, 1),
+ DEF_FIXED("s0d4_vio", R8A779H0_CLK_S0D4_VIO, CLK_S0_VIO, 4, 1),
+ DEF_FIXED("s0d8_vio", R8A779H0_CLK_S0D8_VIO, CLK_S0_VIO, 8, 1),
+ DEF_FIXED("s0d1_vc", R8A779H0_CLK_S0D1_VC, CLK_S0_VC, 1, 1),
+ DEF_FIXED("s0d2_vc", R8A779H0_CLK_S0D2_VC, CLK_S0_VC, 2, 1),
+ DEF_FIXED("s0d4_vc", R8A779H0_CLK_S0D4_VC, CLK_S0_VC, 4, 1),
+ DEF_FIXED("s0d1_hsc", R8A779H0_CLK_S0D1_HSC, CLK_S0_HSC, 1, 1),
+ DEF_FIXED("s0d2_hsc", R8A779H0_CLK_S0D2_HSC, CLK_S0_HSC, 2, 1),
+ DEF_FIXED("s0d4_hsc", R8A779H0_CLK_S0D4_HSC, CLK_S0_HSC, 4, 1),
+ DEF_FIXED("s0d8_hsc", R8A779H0_CLK_S0D8_HSC, CLK_S0_HSC, 8, 1),
+ DEF_FIXED("cl16m_hsc", R8A779H0_CLK_CL16M_HSC, CLK_S0_HSC, 48, 1),
+ DEF_FIXED("sasyncrt", R8A779H0_CLK_SASYNCRT, CLK_PLL5_DIV4, 48, 1),
+ DEF_FIXED("sasyncperd1", R8A779H0_CLK_SASYNCPERD1, CLK_SASYNCPER, 1, 1),
+ DEF_FIXED("sasyncperd2", R8A779H0_CLK_SASYNCPERD2, CLK_SASYNCPER, 2, 1),
+ DEF_FIXED("sasyncperd4", R8A779H0_CLK_SASYNCPERD4, CLK_SASYNCPER, 4, 1),
+ DEF_FIXED("svd1_vip", R8A779H0_CLK_SVD1_VIP, CLK_SV_VIP, 1, 1),
+ DEF_FIXED("svd2_vip", R8A779H0_CLK_SVD2_VIP, CLK_SV_VIP, 2, 1),
+ DEF_FIXED("svd1_ir", R8A779H0_CLK_SVD1_IR, CLK_SV_IR, 1, 1),
+ DEF_FIXED("svd2_ir", R8A779H0_CLK_SVD2_IR, CLK_SV_IR, 2, 1),
+ DEF_FIXED("cbfusa", R8A779H0_CLK_CBFUSA, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A779H0_CLK_CPEX, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cp", R8A779H0_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("impad1", R8A779H0_CLK_IMPAD1, CLK_IMPASRC, 1, 1),
+ DEF_FIXED("impad4", R8A779H0_CLK_IMPAD4, CLK_IMPASRC, 4, 1),
+ DEF_FIXED("impb", R8A779H0_CLK_IMPB, CLK_IMPBSRC, 1, 1),
+ DEF_FIXED("viobusd1", R8A779H0_CLK_VIOBUSD1, CLK_VIOSRC, 1, 1),
+ DEF_FIXED("viobusd2", R8A779H0_CLK_VIOBUSD2, CLK_VIOSRC, 2, 1),
+ DEF_FIXED("vcbusd1", R8A779H0_CLK_VCBUSD1, CLK_VCSRC, 1, 1),
+ DEF_FIXED("vcbusd2", R8A779H0_CLK_VCBUSD2, CLK_VCSRC, 2, 1),
+ DEF_DIV6P1("canfd", R8A779H0_CLK_CANFD, CLK_PLL5_DIV4, CPG_CANFDCKCR),
+ DEF_DIV6P1("csi", R8A779H0_CLK_CSI, CLK_PLL5_DIV4, CPG_CSICKCR),
+ DEF_FIXED("dsiref", R8A779H0_CLK_DSIREF, CLK_PLL5_DIV4, 48, 1),
+ DEF_DIV6P1("dsiext", R8A779H0_CLK_DSIEXT, CLK_PLL5_DIV4, CPG_DSIEXTCKCR),
+ DEF_DIV6P1("mso", R8A779H0_CLK_MSO, CLK_PLL5_DIV4, CPG_MSOCKCR),
+
+ DEF_GEN4_SDH("sd0h", R8A779H0_CLK_SD0H, CLK_SDSRC, CPG_SD0CKCR),
+ DEF_GEN4_SD("sd0", R8A779H0_CLK_SD0, R8A779H0_CLK_SD0H, CPG_SD0CKCR),
+
+ DEF_BASE("rpc", R8A779H0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
+ DEF_BASE("rpcd2", R8A779H0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, R8A779H0_CLK_RPC),
+
+ DEF_GEN4_OSC("osc", R8A779H0_CLK_OSC, CLK_EXTAL, 8),
+ DEF_GEN4_MDSEL("r", R8A779H0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+};
+
+static const struct mssr_mod_clk r8a779h0_mod_clks[] __initconst = {
+ DEF_MOD("isp0", 16, R8A779H0_CLK_S0D2_VIO),
+ DEF_MOD("avb0:rgmii0", 211, R8A779H0_CLK_S0D8_HSC),
+ DEF_MOD("avb1:rgmii1", 212, R8A779H0_CLK_S0D8_HSC),
+ DEF_MOD("avb2:rgmii2", 213, R8A779H0_CLK_S0D8_HSC),
+ DEF_MOD("canfd0", 328, R8A779H0_CLK_SASYNCPERD2),
+ DEF_MOD("csi40", 331, R8A779H0_CLK_CSI),
+ DEF_MOD("csi41", 400, R8A779H0_CLK_CSI),
+ DEF_MOD("dis0", 411, R8A779H0_CLK_VIOBUSD2),
+ DEF_MOD("dsitxlink0", 415, R8A779H0_CLK_VIOBUSD2),
+ DEF_MOD("fcpvd0", 508, R8A779H0_CLK_VIOBUSD2),
+ DEF_MOD("hscif0", 514, R8A779H0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif1", 515, R8A779H0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif2", 516, R8A779H0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif3", 517, R8A779H0_CLK_SASYNCPERD1),
+ DEF_MOD("i2c0", 518, R8A779H0_CLK_S0D6_PER),
+ DEF_MOD("i2c1", 519, R8A779H0_CLK_S0D6_PER),
+ DEF_MOD("i2c2", 520, R8A779H0_CLK_S0D6_PER),
+ DEF_MOD("i2c3", 521, R8A779H0_CLK_S0D6_PER),
+ DEF_MOD("irqc", 611, R8A779H0_CLK_CL16M),
+ DEF_MOD("ispcs0", 612, R8A779H0_CLK_S0D2_VIO),
+ DEF_MOD("ispcs1", 613, R8A779H0_CLK_S0D2_VIO),
+ DEF_MOD("msi0", 618, R8A779H0_CLK_MSO),
+ DEF_MOD("msi1", 619, R8A779H0_CLK_MSO),
+ DEF_MOD("msi2", 620, R8A779H0_CLK_MSO),
+ DEF_MOD("msi3", 621, R8A779H0_CLK_MSO),
+ DEF_MOD("msi4", 622, R8A779H0_CLK_MSO),
+ DEF_MOD("msi5", 623, R8A779H0_CLK_MSO),
+ DEF_MOD("pcie0", 624, R8A779H0_CLK_S0D2_HSC),
+ DEF_MOD("pwm", 628, R8A779H0_CLK_SASYNCPERD4),
+ DEF_MOD("rpc-if", 629, R8A779H0_CLK_RPCD2),
+ DEF_MOD("scif0", 702, R8A779H0_CLK_SASYNCPERD4),
+ DEF_MOD("scif1", 703, R8A779H0_CLK_SASYNCPERD4),
+ DEF_MOD("scif3", 704, R8A779H0_CLK_SASYNCPERD4),
+ DEF_MOD("scif4", 705, R8A779H0_CLK_SASYNCPERD4),
+ DEF_MOD("sdhi0", 706, R8A779H0_CLK_SD0),
+ DEF_MOD("sydm1", 709, R8A779H0_CLK_S0D6_PER),
+ DEF_MOD("sydm2", 710, R8A779H0_CLK_S0D6_PER),
+ DEF_MOD("tmu0", 713, R8A779H0_CLK_SASYNCRT),
+ DEF_MOD("tmu1", 714, R8A779H0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu2", 715, R8A779H0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu3", 716, R8A779H0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu4", 717, R8A779H0_CLK_SASYNCPERD2),
+ DEF_MOD("vin00", 730, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin01", 731, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin02", 800, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin03", 801, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin04", 802, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin05", 803, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin06", 804, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin07", 805, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin10", 806, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin11", 807, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin12", 808, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin13", 809, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin14", 810, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin15", 811, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin16", 812, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vin17", 813, R8A779H0_CLK_S0D4_VIO),
+ DEF_MOD("vspd0", 830, R8A779H0_CLK_VIOBUSD2),
+ DEF_MOD("wdt1:wdt0", 907, R8A779H0_CLK_R),
+ DEF_MOD("cmt0", 910, R8A779H0_CLK_R),
+ DEF_MOD("cmt1", 911, R8A779H0_CLK_R),
+ DEF_MOD("cmt2", 912, R8A779H0_CLK_R),
+ DEF_MOD("cmt3", 913, R8A779H0_CLK_R),
+ DEF_MOD("pfc0", 915, R8A779H0_CLK_CP),
+ DEF_MOD("pfc1", 916, R8A779H0_CLK_CP),
+ DEF_MOD("pfc2", 917, R8A779H0_CLK_CP),
+ DEF_MOD("tsc2:tsc1", 919, R8A779H0_CLK_CL16M),
+ DEF_MOD("vspx0", 1028, R8A779H0_CLK_S0D1_VIO),
+ DEF_MOD("fcpvx0", 1100, R8A779H0_CLK_S0D1_VIO),
+ DEF_MOD("ssiu", 2926, R8A779H0_CLK_S0D6_PER),
+ DEF_MOD("ssi", 2927, R8A779H0_CLK_S0D6_PER),
+};
+
+/*
+ * CPG Clock Data
+ */
+/*
+ * MD EXTAL PLL1 PLL2 PLL3 PLL4 PLL5 PLL6 OSC
+ * 14 13 (MHz)
+ * ------------------------------------------------------------------------
+ * 0 0 16.66 / 1 x192 x240 x192 x240 x192 x168 /16
+ * 0 1 20 / 1 x160 x200 x160 x200 x160 x140 /19
+ * 1 0 Prohibited setting
+ * 1 1 33.33 / 2 x192 x240 x192 x240 x192 x168 /32
+ */
+#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
+ (((md) & BIT(13)) >> 13))
+
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] __initconst = {
+ /* EXTAL div PLL1 mult/div PLL5 mult/div OSC prediv */
+ { 1, 192, 1, 192, 1, 16, },
+ { 1, 160, 1, 160, 1, 19, },
+ { 0, 0, 0, 0, 0, 0, },
+ { 2, 192, 1, 192, 1, 32, },
+};
+
+static int __init r8a779h0_cpg_mssr_init(struct device *dev)
+{
+ const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
+ u32 cpg_mode;
+ int error;
+
+ error = rcar_rst_read_mode_pins(&cpg_mode);
+ if (error)
+ return error;
+
+ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+ if (!cpg_pll_config->extal_div) {
+ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+ return -EINVAL;
+ }
+
+ return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a779h0_cpg_mssr_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r8a779h0_core_clks,
+ .num_core_clks = ARRAY_SIZE(r8a779h0_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r8a779h0_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r8a779h0_mod_clks),
+ .num_hw_mod_clks = 30 * 32,
+
+ /* Callbacks */
+ .init = r8a779h0_cpg_mssr_init,
+ .cpg_clk_register = rcar_gen4_cpg_clk_register,
+
+ .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
+};
diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c
new file mode 100644
index 000000000..076f587df
--- /dev/null
+++ b/drivers/clk/renesas/r9a06g032-clocks.c
@@ -0,0 +1,1428 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R9A06G032 clock driver
+ *
+ * Copyright (C) 2018 Renesas Electronics Europe Limited
+ *
+ * Michel Pollet <michel.pollet@bp.renesas.com>, <buserror@gmail.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/soc/renesas/r9a06g032-sysctrl.h>
+#include <linux/spinlock.h>
+#include <dt-bindings/clock/r9a06g032-sysctrl.h>
+
+#define R9A06G032_SYSCTRL_USB 0x00
+#define R9A06G032_SYSCTRL_USB_H2MODE BIT(1)
+#define R9A06G032_SYSCTRL_DMAMUX 0xA0
+
+#define R9A06G032_SYSCTRL_RSTEN 0x120
+#define R9A06G032_SYSCTRL_RSTEN_MRESET_EN BIT(0)
+#define R9A06G032_SYSCTRL_RSTCTRL 0x198
+/* These work for both reset registers */
+#define R9A06G032_SYSCTRL_SWRST BIT(6)
+#define R9A06G032_SYSCTRL_WDA7RST_1 BIT(2)
+#define R9A06G032_SYSCTRL_WDA7RST_0 BIT(1)
+
+/**
+ * struct regbit - describe one bit in a register
+ * @reg: offset of register relative to base address,
+ * expressed in units of 32-bit words (not bytes),
+ * @bit: which bit (0 to 31) in the register
+ *
+ * This structure is used to compactly encode the location
+ * of a single bit in a register. Five bits are needed to
+ * encode the bit number. With uint16_t data type, this
+ * leaves 11 bits to encode a register offset up to 2047.
+ *
+ * Since registers are aligned on 32-bit boundaries, the
+ * offset will be specified in 32-bit words rather than bytes.
+ * This allows encoding an offset up to 0x1FFC (8188) bytes.
+ *
+ * Helper macro RB() takes care of converting the register
+ * offset from bytes to 32-bit words.
+ */
+struct regbit {
+ u16 bit:5;
+ u16 reg:11;
+};
+
+#define RB(_reg, _bit) ((struct regbit) { \
+ .reg = (_reg) / 4, \
+ .bit = (_bit) \
+})
+
+/**
+ * struct r9a06g032_gate - clock-related control bits
+ * @gate: clock enable/disable
+ * @reset: clock module reset (active low)
+ * @ready: enables NoC forwarding of read/write requests to device,
+ * (eg. device is ready to handle read/write requests)
+ * @midle: request to idle the NoC interconnect
+ *
+ * Each of these fields describes a single bit in a register,
+ * which controls some aspect of clock gating. The @gate field
+ * is mandatory, this one enables/disables the clock. The
+ * other fields are optional, with zero indicating "not used".
+ *
+ * In most cases there is a @reset bit which needs to be
+ * de-asserted to bring the module out of reset.
+ *
+ * Modules may also need to signal when they are @ready to
+ * handle requests (read/writes) from the NoC interconnect.
+ *
+ * Similarly, the @midle bit is used to idle the master.
+ */
+struct r9a06g032_gate {
+ struct regbit gate, reset, ready, midle;
+ /* Unused fields omitted to save space */
+ /* struct regbit scon, mirack, mistat */;
+};
+
+enum gate_type {
+ K_GATE = 0, /* gate which enable/disable */
+ K_FFC, /* fixed factor clock */
+ K_DIV, /* divisor */
+ K_BITSEL, /* special for UARTs */
+ K_DUALGATE /* special for UARTs */
+};
+
+/**
+ * struct r9a06g032_clkdesc - describe a single clock
+ * @name: string describing this clock
+ * @managed: boolean indicating if this clock should be
+ * started/stopped as part of power management
+ * @type: see enum @gate_type
+ * @index: the ID of this clock element
+ * @source: the ID+1 of the parent clock element.
+ * Root clock uses ID of ~0 (PARENT_ID);
+ * @gate: clock enable/disable
+ * @div: substructure for clock divider
+ * @div.min: smallest permitted clock divider
+ * @div.max: largest permitted clock divider
+ * @div.reg: clock divider register offset, in 32-bit words
+ * @div.table: optional list of fixed clock divider values;
+ * must be in ascending order, zero for unused
+ * @ffc: substructure for fixed-factor clocks
+ * @ffc.div: divisor for fixed-factor clock
+ * @ffc.mul: multiplier for fixed-factor clock
+ * @dual: substructure for dual clock gates
+ * @dual.group: UART group, 0=UART0/1/2, 1=UART3/4/5/6/7
+ * @dual.sel: select either g1/r1 or g2/r2 as clock source
+ * @dual.g1: 1st source gate (clock enable/disable)
+ * @dual.r1: 1st source reset (module reset)
+ * @dual.g2: 2nd source gate (clock enable/disable)
+ * @dual.r2: 2nd source reset (module reset)
+ *
+ * Describes a single element in the clock tree hierarchy.
+ * As there are quite a large number of clock elements, this
+ * structure is packed tightly to conserve space.
+ */
+struct r9a06g032_clkdesc {
+ const char *name;
+ uint32_t managed:1;
+ enum gate_type type:3;
+ uint32_t index:8;
+ uint32_t source:8; /* source index + 1 (0 == none) */
+ union {
+ /* type = K_GATE */
+ struct r9a06g032_gate gate;
+ /* type = K_DIV */
+ struct {
+ unsigned int min:10, max:10, reg:10;
+ u16 table[4];
+ } div;
+ /* type = K_FFC */
+ struct {
+ u16 div, mul;
+ } ffc;
+ /* type = K_DUALGATE */
+ struct {
+ uint16_t group:1;
+ struct regbit sel, g1, r1, g2, r2;
+ } dual;
+ };
+};
+
+/*
+ * The last three arguments are not currently used,
+ * but are kept in the r9a06g032_clocks table below.
+ */
+#define I_GATE(_clk, _rst, _rdy, _midle, _scon, _mirack, _mistat) { \
+ .gate = _clk, \
+ .reset = _rst, \
+ .ready = _rdy, \
+ .midle = _midle, \
+ /* .scon = _scon, */ \
+ /* .mirack = _mirack, */ \
+ /* .mistat = _mistat */ \
+}
+#define D_GATE(_idx, _n, _src, ...) { \
+ .type = K_GATE, \
+ .index = R9A06G032_##_idx, \
+ .source = 1 + R9A06G032_##_src, \
+ .name = _n, \
+ .gate = I_GATE(__VA_ARGS__) \
+}
+#define D_MODULE(_idx, _n, _src, ...) { \
+ .type = K_GATE, \
+ .index = R9A06G032_##_idx, \
+ .source = 1 + R9A06G032_##_src, \
+ .name = _n, \
+ .managed = 1, \
+ .gate = I_GATE(__VA_ARGS__) \
+}
+#define D_ROOT(_idx, _n, _mul, _div) { \
+ .type = K_FFC, \
+ .index = R9A06G032_##_idx, \
+ .name = _n, \
+ .ffc.div = _div, \
+ .ffc.mul = _mul \
+}
+#define D_FFC(_idx, _n, _src, _div) { \
+ .type = K_FFC, \
+ .index = R9A06G032_##_idx, \
+ .source = 1 + R9A06G032_##_src, \
+ .name = _n, \
+ .ffc.div = _div, \
+ .ffc.mul = 1 \
+}
+#define D_DIV(_idx, _n, _src, _reg, _min, _max, ...) { \
+ .type = K_DIV, \
+ .index = R9A06G032_##_idx, \
+ .source = 1 + R9A06G032_##_src, \
+ .name = _n, \
+ .div.reg = _reg, \
+ .div.min = _min, \
+ .div.max = _max, \
+ .div.table = { __VA_ARGS__ } \
+}
+#define D_UGATE(_idx, _n, _src, _g, _g1, _r1, _g2, _r2) { \
+ .type = K_DUALGATE, \
+ .index = R9A06G032_##_idx, \
+ .source = 1 + R9A06G032_##_src, \
+ .name = _n, \
+ .dual = { \
+ .group = _g, \
+ .g1 = _g1, \
+ .r1 = _r1, \
+ .g2 = _g2, \
+ .r2 = _r2 \
+ }, \
+}
+
+/* Internal clock IDs */
+#define R9A06G032_CLKOUT 0
+#define R9A06G032_CLKOUT_D10 2
+#define R9A06G032_CLKOUT_D16 3
+#define R9A06G032_CLKOUT_D160 4
+#define R9A06G032_CLKOUT_D1OR2 5
+#define R9A06G032_CLKOUT_D20 6
+#define R9A06G032_CLKOUT_D40 7
+#define R9A06G032_CLKOUT_D5 8
+#define R9A06G032_CLKOUT_D8 9
+#define R9A06G032_DIV_ADC 10
+#define R9A06G032_DIV_I2C 11
+#define R9A06G032_DIV_NAND 12
+#define R9A06G032_DIV_P1_PG 13
+#define R9A06G032_DIV_P2_PG 14
+#define R9A06G032_DIV_P3_PG 15
+#define R9A06G032_DIV_P4_PG 16
+#define R9A06G032_DIV_P5_PG 17
+#define R9A06G032_DIV_P6_PG 18
+#define R9A06G032_DIV_QSPI0 19
+#define R9A06G032_DIV_QSPI1 20
+#define R9A06G032_DIV_REF_SYNC 21
+#define R9A06G032_DIV_SDIO0 22
+#define R9A06G032_DIV_SDIO1 23
+#define R9A06G032_DIV_SWITCH 24
+#define R9A06G032_DIV_UART 25
+#define R9A06G032_DIV_MOTOR 64
+#define R9A06G032_CLK_DDRPHY_PLLCLK_D4 78
+#define R9A06G032_CLK_ECAT100_D4 79
+#define R9A06G032_CLK_HSR100_D2 80
+#define R9A06G032_CLK_REF_SYNC_D4 81
+#define R9A06G032_CLK_REF_SYNC_D8 82
+#define R9A06G032_CLK_SERCOS100_D2 83
+#define R9A06G032_DIV_CA7 84
+
+#define R9A06G032_UART_GROUP_012 154
+#define R9A06G032_UART_GROUP_34567 155
+
+#define R9A06G032_CLOCK_COUNT (R9A06G032_UART_GROUP_34567 + 1)
+
+static const struct r9a06g032_clkdesc r9a06g032_clocks[] = {
+ D_ROOT(CLKOUT, "clkout", 25, 1),
+ D_ROOT(CLK_PLL_USB, "clk_pll_usb", 12, 10),
+ D_FFC(CLKOUT_D10, "clkout_d10", CLKOUT, 10),
+ D_FFC(CLKOUT_D16, "clkout_d16", CLKOUT, 16),
+ D_FFC(CLKOUT_D160, "clkout_d160", CLKOUT, 160),
+ D_DIV(CLKOUT_D1OR2, "clkout_d1or2", CLKOUT, 0, 1, 2),
+ D_FFC(CLKOUT_D20, "clkout_d20", CLKOUT, 20),
+ D_FFC(CLKOUT_D40, "clkout_d40", CLKOUT, 40),
+ D_FFC(CLKOUT_D5, "clkout_d5", CLKOUT, 5),
+ D_FFC(CLKOUT_D8, "clkout_d8", CLKOUT, 8),
+ D_DIV(DIV_ADC, "div_adc", CLKOUT, 77, 50, 250),
+ D_DIV(DIV_I2C, "div_i2c", CLKOUT, 78, 12, 16),
+ D_DIV(DIV_NAND, "div_nand", CLKOUT, 82, 12, 32),
+ D_DIV(DIV_P1_PG, "div_p1_pg", CLKOUT, 68, 12, 200),
+ D_DIV(DIV_P2_PG, "div_p2_pg", CLKOUT, 62, 12, 128),
+ D_DIV(DIV_P3_PG, "div_p3_pg", CLKOUT, 64, 8, 128),
+ D_DIV(DIV_P4_PG, "div_p4_pg", CLKOUT, 66, 8, 128),
+ D_DIV(DIV_P5_PG, "div_p5_pg", CLKOUT, 71, 10, 40),
+ D_DIV(DIV_P6_PG, "div_p6_pg", CLKOUT, 18, 12, 64),
+ D_DIV(DIV_QSPI0, "div_qspi0", CLKOUT, 73, 3, 7),
+ D_DIV(DIV_QSPI1, "div_qspi1", CLKOUT, 25, 3, 7),
+ D_DIV(DIV_REF_SYNC, "div_ref_sync", CLKOUT, 56, 2, 16, 2, 4, 8, 16),
+ D_DIV(DIV_SDIO0, "div_sdio0", CLKOUT, 74, 20, 128),
+ D_DIV(DIV_SDIO1, "div_sdio1", CLKOUT, 75, 20, 128),
+ D_DIV(DIV_SWITCH, "div_switch", CLKOUT, 37, 5, 40),
+ D_DIV(DIV_UART, "div_uart", CLKOUT, 79, 12, 128),
+ D_GATE(CLK_25_PG4, "clk_25_pg4", CLKOUT_D40, RB(0xe8, 9),
+ RB(0xe8, 10), RB(0xe8, 11), RB(0x00, 0),
+ RB(0x15c, 3), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_25_PG5, "clk_25_pg5", CLKOUT_D40, RB(0xe8, 12),
+ RB(0xe8, 13), RB(0xe8, 14), RB(0x00, 0),
+ RB(0x15c, 4), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_25_PG6, "clk_25_pg6", CLKOUT_D40, RB(0xe8, 15),
+ RB(0xe8, 16), RB(0xe8, 17), RB(0x00, 0),
+ RB(0x15c, 5), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_25_PG7, "clk_25_pg7", CLKOUT_D40, RB(0xe8, 18),
+ RB(0xe8, 19), RB(0xe8, 20), RB(0x00, 0),
+ RB(0x15c, 6), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_25_PG8, "clk_25_pg8", CLKOUT_D40, RB(0xe8, 21),
+ RB(0xe8, 22), RB(0xe8, 23), RB(0x00, 0),
+ RB(0x15c, 7), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_ADC, "clk_adc", DIV_ADC, RB(0x3c, 10),
+ RB(0x3c, 11), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_ECAT100, "clk_ecat100", CLKOUT_D10, RB(0x80, 5),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_HSR100, "clk_hsr100", CLKOUT_D10, RB(0x90, 3),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_I2C0, "clk_i2c0", DIV_I2C, RB(0x3c, 6),
+ RB(0x3c, 7), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_I2C1, "clk_i2c1", DIV_I2C, RB(0x3c, 8),
+ RB(0x3c, 9), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_MII_REF, "clk_mii_ref", CLKOUT_D40, RB(0x68, 2),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_NAND, "clk_nand", DIV_NAND, RB(0x50, 4),
+ RB(0x50, 5), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_NOUSBP2_PG6, "clk_nousbp2_pg6", DIV_P2_PG, RB(0xec, 20),
+ RB(0xec, 21), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_P1_PG2, "clk_p1_pg2", DIV_P1_PG, RB(0x10c, 2),
+ RB(0x10c, 3), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_P1_PG3, "clk_p1_pg3", DIV_P1_PG, RB(0x10c, 4),
+ RB(0x10c, 5), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_P1_PG4, "clk_p1_pg4", DIV_P1_PG, RB(0x10c, 6),
+ RB(0x10c, 7), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_P4_PG3, "clk_p4_pg3", DIV_P4_PG, RB(0x104, 4),
+ RB(0x104, 5), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_P4_PG4, "clk_p4_pg4", DIV_P4_PG, RB(0x104, 6),
+ RB(0x104, 7), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_P6_PG1, "clk_p6_pg1", DIV_P6_PG, RB(0x114, 0),
+ RB(0x114, 1), RB(0x114, 2), RB(0x00, 0),
+ RB(0x16c, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_P6_PG2, "clk_p6_pg2", DIV_P6_PG, RB(0x114, 3),
+ RB(0x114, 4), RB(0x114, 5), RB(0x00, 0),
+ RB(0x16c, 1), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_P6_PG3, "clk_p6_pg3", DIV_P6_PG, RB(0x114, 6),
+ RB(0x114, 7), RB(0x114, 8), RB(0x00, 0),
+ RB(0x16c, 2), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_P6_PG4, "clk_p6_pg4", DIV_P6_PG, RB(0x114, 9),
+ RB(0x114, 10), RB(0x114, 11), RB(0x00, 0),
+ RB(0x16c, 3), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(CLK_PCI_USB, "clk_pci_usb", CLKOUT_D40, RB(0x1c, 6),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_QSPI0, "clk_qspi0", DIV_QSPI0, RB(0x54, 4),
+ RB(0x54, 5), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_QSPI1, "clk_qspi1", DIV_QSPI1, RB(0x90, 4),
+ RB(0x90, 5), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_RGMII_REF, "clk_rgmii_ref", CLKOUT_D8, RB(0x68, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_RMII_REF, "clk_rmii_ref", CLKOUT_D20, RB(0x68, 1),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SDIO0, "clk_sdio0", DIV_SDIO0, RB(0x0c, 4),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SDIO1, "clk_sdio1", DIV_SDIO1, RB(0xc8, 4),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SERCOS100, "clk_sercos100", CLKOUT_D10, RB(0x84, 5),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SLCD, "clk_slcd", DIV_P1_PG, RB(0x10c, 0),
+ RB(0x10c, 1), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SPI0, "clk_spi0", DIV_P3_PG, RB(0xfc, 0),
+ RB(0xfc, 1), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SPI1, "clk_spi1", DIV_P3_PG, RB(0xfc, 2),
+ RB(0xfc, 3), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SPI2, "clk_spi2", DIV_P3_PG, RB(0xfc, 4),
+ RB(0xfc, 5), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SPI3, "clk_spi3", DIV_P3_PG, RB(0xfc, 6),
+ RB(0xfc, 7), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SPI4, "clk_spi4", DIV_P4_PG, RB(0x104, 0),
+ RB(0x104, 1), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SPI5, "clk_spi5", DIV_P4_PG, RB(0x104, 2),
+ RB(0x104, 3), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SWITCH, "clk_switch", DIV_SWITCH, RB(0x130, 2),
+ RB(0x130, 3), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_DIV(DIV_MOTOR, "div_motor", CLKOUT_D5, 84, 2, 8),
+ D_MODULE(HCLK_ECAT125, "hclk_ecat125", CLKOUT_D8, RB(0x80, 0),
+ RB(0x80, 1), RB(0x00, 0), RB(0x80, 2),
+ RB(0x00, 0), RB(0x88, 0), RB(0x88, 1)),
+ D_MODULE(HCLK_PINCONFIG, "hclk_pinconfig", CLKOUT_D40, RB(0xe8, 0),
+ RB(0xe8, 1), RB(0xe8, 2), RB(0x00, 0),
+ RB(0x15c, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SERCOS, "hclk_sercos", CLKOUT_D10, RB(0x84, 0),
+ RB(0x84, 2), RB(0x00, 0), RB(0x84, 1),
+ RB(0x00, 0), RB(0x8c, 0), RB(0x8c, 1)),
+ D_MODULE(HCLK_SGPIO2, "hclk_sgpio2", DIV_P5_PG, RB(0x118, 3),
+ RB(0x118, 4), RB(0x118, 5), RB(0x00, 0),
+ RB(0x168, 1), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SGPIO3, "hclk_sgpio3", DIV_P5_PG, RB(0x118, 6),
+ RB(0x118, 7), RB(0x118, 8), RB(0x00, 0),
+ RB(0x168, 2), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SGPIO4, "hclk_sgpio4", DIV_P5_PG, RB(0x118, 9),
+ RB(0x118, 10), RB(0x118, 11), RB(0x00, 0),
+ RB(0x168, 3), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_TIMER0, "hclk_timer0", CLKOUT_D40, RB(0xe8, 3),
+ RB(0xe8, 4), RB(0xe8, 5), RB(0x00, 0),
+ RB(0x15c, 1), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_TIMER1, "hclk_timer1", CLKOUT_D40, RB(0xe8, 6),
+ RB(0xe8, 7), RB(0xe8, 8), RB(0x00, 0),
+ RB(0x15c, 2), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_USBF, "hclk_usbf", CLKOUT_D8, RB(0x1c, 3),
+ RB(0x00, 0), RB(0x00, 0), RB(0x1c, 4),
+ RB(0x00, 0), RB(0x20, 2), RB(0x20, 3)),
+ D_MODULE(HCLK_USBH, "hclk_usbh", CLKOUT_D8, RB(0x1c, 0),
+ RB(0x1c, 1), RB(0x00, 0), RB(0x1c, 2),
+ RB(0x00, 0), RB(0x20, 0), RB(0x20, 1)),
+ D_MODULE(HCLK_USBPM, "hclk_usbpm", CLKOUT_D8, RB(0x1c, 5),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_48_PG_F, "clk_48_pg_f", CLK_48, RB(0xf0, 12),
+ RB(0xf0, 13), RB(0x00, 0), RB(0xf0, 14),
+ RB(0x00, 0), RB(0x160, 4), RB(0x160, 5)),
+ D_GATE(CLK_48_PG4, "clk_48_pg4", CLK_48, RB(0xf0, 9),
+ RB(0xf0, 10), RB(0xf0, 11), RB(0x00, 0),
+ RB(0x160, 3), RB(0x00, 0), RB(0x00, 0)),
+ D_FFC(CLK_DDRPHY_PLLCLK_D4, "clk_ddrphy_pllclk_d4", CLK_DDRPHY_PLLCLK, 4),
+ D_FFC(CLK_ECAT100_D4, "clk_ecat100_d4", CLK_ECAT100, 4),
+ D_FFC(CLK_HSR100_D2, "clk_hsr100_d2", CLK_HSR100, 2),
+ D_FFC(CLK_REF_SYNC_D4, "clk_ref_sync_d4", CLK_REF_SYNC, 4),
+ D_FFC(CLK_REF_SYNC_D8, "clk_ref_sync_d8", CLK_REF_SYNC, 8),
+ D_FFC(CLK_SERCOS100_D2, "clk_sercos100_d2", CLK_SERCOS100, 2),
+ D_DIV(DIV_CA7, "div_ca7", CLK_REF_SYNC, 57, 1, 4, 1, 2, 4),
+ D_MODULE(HCLK_CAN0, "hclk_can0", CLK_48, RB(0xf0, 3),
+ RB(0xf0, 4), RB(0xf0, 5), RB(0x00, 0),
+ RB(0x160, 1), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_CAN1, "hclk_can1", CLK_48, RB(0xf0, 6),
+ RB(0xf0, 7), RB(0xf0, 8), RB(0x00, 0),
+ RB(0x160, 2), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_DELTASIGMA, "hclk_deltasigma", DIV_MOTOR, RB(0x3c, 15),
+ RB(0x3c, 16), RB(0x3c, 17), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_PWMPTO, "hclk_pwmpto", DIV_MOTOR, RB(0x3c, 12),
+ RB(0x3c, 13), RB(0x3c, 14), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_RSV, "hclk_rsv", CLK_48, RB(0xf0, 0),
+ RB(0xf0, 1), RB(0xf0, 2), RB(0x00, 0),
+ RB(0x160, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SGPIO0, "hclk_sgpio0", DIV_MOTOR, RB(0x3c, 0),
+ RB(0x3c, 1), RB(0x3c, 2), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SGPIO1, "hclk_sgpio1", DIV_MOTOR, RB(0x3c, 3),
+ RB(0x3c, 4), RB(0x3c, 5), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_DIV(RTOS_MDC, "rtos_mdc", CLK_REF_SYNC, 100, 80, 640, 80, 160, 320, 640),
+ D_GATE(CLK_CM3, "clk_cm3", CLK_REF_SYNC_D4, RB(0x174, 0),
+ RB(0x174, 1), RB(0x00, 0), RB(0x174, 2),
+ RB(0x00, 0), RB(0x178, 0), RB(0x178, 1)),
+ D_GATE(CLK_DDRC, "clk_ddrc", CLK_DDRPHY_PLLCLK_D4, RB(0x64, 3),
+ RB(0x64, 4), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_ECAT25, "clk_ecat25", CLK_ECAT100_D4, RB(0x80, 3),
+ RB(0x80, 4), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_HSR50, "clk_hsr50", CLK_HSR100_D2, RB(0x90, 4),
+ RB(0x90, 5), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_HW_RTOS, "clk_hw_rtos", CLK_REF_SYNC_D4, RB(0x18c, 0),
+ RB(0x18c, 1), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_GATE(CLK_SERCOS50, "clk_sercos50", CLK_SERCOS100_D2, RB(0x84, 4),
+ RB(0x84, 3), RB(0x00, 0), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_ADC, "hclk_adc", CLK_REF_SYNC_D8, RB(0x34, 15),
+ RB(0x34, 16), RB(0x34, 17), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_CM3, "hclk_cm3", CLK_REF_SYNC_D4, RB(0x184, 0),
+ RB(0x184, 1), RB(0x184, 2), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_CRYPTO_EIP150, "hclk_crypto_eip150", CLK_REF_SYNC_D4, RB(0x24, 3),
+ RB(0x24, 4), RB(0x24, 5), RB(0x00, 0),
+ RB(0x28, 2), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_CRYPTO_EIP93, "hclk_crypto_eip93", CLK_REF_SYNC_D4, RB(0x24, 0),
+ RB(0x24, 1), RB(0x00, 0), RB(0x24, 2),
+ RB(0x00, 0), RB(0x28, 0), RB(0x28, 1)),
+ D_MODULE(HCLK_DDRC, "hclk_ddrc", CLK_REF_SYNC_D4, RB(0x64, 0),
+ RB(0x64, 2), RB(0x00, 0), RB(0x64, 1),
+ RB(0x00, 0), RB(0x74, 0), RB(0x74, 1)),
+ D_MODULE(HCLK_DMA0, "hclk_dma0", CLK_REF_SYNC_D4, RB(0x4c, 0),
+ RB(0x4c, 1), RB(0x4c, 2), RB(0x4c, 3),
+ RB(0x58, 0), RB(0x58, 1), RB(0x58, 2)),
+ D_MODULE(HCLK_DMA1, "hclk_dma1", CLK_REF_SYNC_D4, RB(0x4c, 4),
+ RB(0x4c, 5), RB(0x4c, 6), RB(0x4c, 7),
+ RB(0x58, 3), RB(0x58, 4), RB(0x58, 5)),
+ D_MODULE(HCLK_GMAC0, "hclk_gmac0", CLK_REF_SYNC_D4, RB(0x6c, 0),
+ RB(0x6c, 1), RB(0x6c, 2), RB(0x6c, 3),
+ RB(0x78, 0), RB(0x78, 1), RB(0x78, 2)),
+ D_MODULE(HCLK_GMAC1, "hclk_gmac1", CLK_REF_SYNC_D4, RB(0x70, 0),
+ RB(0x70, 1), RB(0x70, 2), RB(0x70, 3),
+ RB(0x7c, 0), RB(0x7c, 1), RB(0x7c, 2)),
+ D_MODULE(HCLK_GPIO0, "hclk_gpio0", CLK_REF_SYNC_D4, RB(0x40, 18),
+ RB(0x40, 19), RB(0x40, 20), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_GPIO1, "hclk_gpio1", CLK_REF_SYNC_D4, RB(0x40, 21),
+ RB(0x40, 22), RB(0x40, 23), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_GPIO2, "hclk_gpio2", CLK_REF_SYNC_D4, RB(0x44, 9),
+ RB(0x44, 10), RB(0x44, 11), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_HSR, "hclk_hsr", CLK_HSR100_D2, RB(0x90, 0),
+ RB(0x90, 2), RB(0x00, 0), RB(0x90, 1),
+ RB(0x00, 0), RB(0x98, 0), RB(0x98, 1)),
+ D_MODULE(HCLK_I2C0, "hclk_i2c0", CLK_REF_SYNC_D8, RB(0x34, 9),
+ RB(0x34, 10), RB(0x34, 11), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_I2C1, "hclk_i2c1", CLK_REF_SYNC_D8, RB(0x34, 12),
+ RB(0x34, 13), RB(0x34, 14), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_LCD, "hclk_lcd", CLK_REF_SYNC_D4, RB(0xf4, 0),
+ RB(0xf4, 1), RB(0xf4, 2), RB(0x00, 0),
+ RB(0x164, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_MSEBI_M, "hclk_msebi_m", CLK_REF_SYNC_D4, RB(0x2c, 4),
+ RB(0x2c, 5), RB(0x2c, 6), RB(0x00, 0),
+ RB(0x30, 3), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_MSEBI_S, "hclk_msebi_s", CLK_REF_SYNC_D4, RB(0x2c, 0),
+ RB(0x2c, 1), RB(0x2c, 2), RB(0x2c, 3),
+ RB(0x30, 0), RB(0x30, 1), RB(0x30, 2)),
+ D_MODULE(HCLK_NAND, "hclk_nand", CLK_REF_SYNC_D4, RB(0x50, 0),
+ RB(0x50, 1), RB(0x50, 2), RB(0x50, 3),
+ RB(0x5c, 0), RB(0x5c, 1), RB(0x5c, 2)),
+ D_MODULE(HCLK_PG_I, "hclk_pg_i", CLK_REF_SYNC_D4, RB(0xf4, 12),
+ RB(0xf4, 13), RB(0x00, 0), RB(0xf4, 14),
+ RB(0x00, 0), RB(0x164, 4), RB(0x164, 5)),
+ D_MODULE(HCLK_PG19, "hclk_pg19", CLK_REF_SYNC_D4, RB(0x44, 12),
+ RB(0x44, 13), RB(0x44, 14), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_PG20, "hclk_pg20", CLK_REF_SYNC_D4, RB(0x44, 15),
+ RB(0x44, 16), RB(0x44, 17), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_PG3, "hclk_pg3", CLK_REF_SYNC_D4, RB(0xf4, 6),
+ RB(0xf4, 7), RB(0xf4, 8), RB(0x00, 0),
+ RB(0x164, 2), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_PG4, "hclk_pg4", CLK_REF_SYNC_D4, RB(0xf4, 9),
+ RB(0xf4, 10), RB(0xf4, 11), RB(0x00, 0),
+ RB(0x164, 3), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_QSPI0, "hclk_qspi0", CLK_REF_SYNC_D4, RB(0x54, 0),
+ RB(0x54, 1), RB(0x54, 2), RB(0x54, 3),
+ RB(0x60, 0), RB(0x60, 1), RB(0x60, 2)),
+ D_MODULE(HCLK_QSPI1, "hclk_qspi1", CLK_REF_SYNC_D4, RB(0x90, 0),
+ RB(0x90, 1), RB(0x90, 2), RB(0x90, 3),
+ RB(0x98, 0), RB(0x98, 1), RB(0x98, 2)),
+ D_MODULE(HCLK_ROM, "hclk_rom", CLK_REF_SYNC_D4, RB(0x154, 0),
+ RB(0x154, 1), RB(0x154, 2), RB(0x00, 0),
+ RB(0x170, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_RTC, "hclk_rtc", CLK_REF_SYNC_D8, RB(0x140, 0),
+ RB(0x140, 3), RB(0x00, 0), RB(0x140, 2),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SDIO0, "hclk_sdio0", CLK_REF_SYNC_D4, RB(0x0c, 0),
+ RB(0x0c, 1), RB(0x0c, 2), RB(0x0c, 3),
+ RB(0x10, 0), RB(0x10, 1), RB(0x10, 2)),
+ D_MODULE(HCLK_SDIO1, "hclk_sdio1", CLK_REF_SYNC_D4, RB(0xc8, 0),
+ RB(0xc8, 1), RB(0xc8, 2), RB(0xc8, 3),
+ RB(0xcc, 0), RB(0xcc, 1), RB(0xcc, 2)),
+ D_MODULE(HCLK_SEMAP, "hclk_semap", CLK_REF_SYNC_D4, RB(0xf4, 3),
+ RB(0xf4, 4), RB(0xf4, 5), RB(0x00, 0),
+ RB(0x164, 1), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SPI0, "hclk_spi0", CLK_REF_SYNC_D4, RB(0x40, 0),
+ RB(0x40, 1), RB(0x40, 2), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SPI1, "hclk_spi1", CLK_REF_SYNC_D4, RB(0x40, 3),
+ RB(0x40, 4), RB(0x40, 5), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SPI2, "hclk_spi2", CLK_REF_SYNC_D4, RB(0x40, 6),
+ RB(0x40, 7), RB(0x40, 8), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SPI3, "hclk_spi3", CLK_REF_SYNC_D4, RB(0x40, 9),
+ RB(0x40, 10), RB(0x40, 11), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SPI4, "hclk_spi4", CLK_REF_SYNC_D4, RB(0x40, 12),
+ RB(0x40, 13), RB(0x40, 14), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SPI5, "hclk_spi5", CLK_REF_SYNC_D4, RB(0x40, 15),
+ RB(0x40, 16), RB(0x40, 17), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SWITCH, "hclk_switch", CLK_REF_SYNC_D4, RB(0x130, 0),
+ RB(0x00, 0), RB(0x130, 1), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_SWITCH_RG, "hclk_switch_rg", CLK_REF_SYNC_D4, RB(0x188, 0),
+ RB(0x188, 1), RB(0x188, 2), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_UART0, "hclk_uart0", CLK_REF_SYNC_D8, RB(0x34, 0),
+ RB(0x34, 1), RB(0x34, 2), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_UART1, "hclk_uart1", CLK_REF_SYNC_D8, RB(0x34, 3),
+ RB(0x34, 4), RB(0x34, 5), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_UART2, "hclk_uart2", CLK_REF_SYNC_D8, RB(0x34, 6),
+ RB(0x34, 7), RB(0x34, 8), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_UART3, "hclk_uart3", CLK_REF_SYNC_D4, RB(0x40, 24),
+ RB(0x40, 25), RB(0x40, 26), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_UART4, "hclk_uart4", CLK_REF_SYNC_D4, RB(0x40, 27),
+ RB(0x40, 28), RB(0x40, 29), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_UART5, "hclk_uart5", CLK_REF_SYNC_D4, RB(0x44, 0),
+ RB(0x44, 1), RB(0x44, 2), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_UART6, "hclk_uart6", CLK_REF_SYNC_D4, RB(0x44, 3),
+ RB(0x44, 4), RB(0x44, 5), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ D_MODULE(HCLK_UART7, "hclk_uart7", CLK_REF_SYNC_D4, RB(0x44, 6),
+ RB(0x44, 7), RB(0x44, 8), RB(0x00, 0),
+ RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)),
+ /*
+ * These are not hardware clocks, but are needed to handle the special
+ * case where we have a 'selector bit' that doesn't just change the
+ * parent for a clock, but also the gate it's supposed to use.
+ */
+ {
+ .index = R9A06G032_UART_GROUP_012,
+ .name = "uart_group_012",
+ .type = K_BITSEL,
+ .source = 1 + R9A06G032_DIV_UART,
+ /* R9A06G032_SYSCTRL_REG_PWRCTRL_PG0_0 */
+ .dual.sel = RB(0x34, 30),
+ .dual.group = 0,
+ },
+ {
+ .index = R9A06G032_UART_GROUP_34567,
+ .name = "uart_group_34567",
+ .type = K_BITSEL,
+ .source = 1 + R9A06G032_DIV_P2_PG,
+ /* R9A06G032_SYSCTRL_REG_PWRCTRL_PG1_PR2 */
+ .dual.sel = RB(0xec, 24),
+ .dual.group = 1,
+ },
+ D_UGATE(CLK_UART0, "clk_uart0", UART_GROUP_012, 0,
+ RB(0x34, 18), RB(0x34, 19), RB(0x34, 20), RB(0x34, 21)),
+ D_UGATE(CLK_UART1, "clk_uart1", UART_GROUP_012, 0,
+ RB(0x34, 22), RB(0x34, 23), RB(0x34, 24), RB(0x34, 25)),
+ D_UGATE(CLK_UART2, "clk_uart2", UART_GROUP_012, 0,
+ RB(0x34, 26), RB(0x34, 27), RB(0x34, 28), RB(0x34, 29)),
+ D_UGATE(CLK_UART3, "clk_uart3", UART_GROUP_34567, 1,
+ RB(0xec, 0), RB(0xec, 1), RB(0xec, 2), RB(0xec, 3)),
+ D_UGATE(CLK_UART4, "clk_uart4", UART_GROUP_34567, 1,
+ RB(0xec, 4), RB(0xec, 5), RB(0xec, 6), RB(0xec, 7)),
+ D_UGATE(CLK_UART5, "clk_uart5", UART_GROUP_34567, 1,
+ RB(0xec, 8), RB(0xec, 9), RB(0xec, 10), RB(0xec, 11)),
+ D_UGATE(CLK_UART6, "clk_uart6", UART_GROUP_34567, 1,
+ RB(0xec, 12), RB(0xec, 13), RB(0xec, 14), RB(0xec, 15)),
+ D_UGATE(CLK_UART7, "clk_uart7", UART_GROUP_34567, 1,
+ RB(0xec, 16), RB(0xec, 17), RB(0xec, 18), RB(0xec, 19)),
+};
+
+struct r9a06g032_priv {
+ struct clk_onecell_data data;
+ spinlock_t lock; /* protects concurrent access to gates */
+ void __iomem *reg;
+};
+
+static struct r9a06g032_priv *sysctrl_priv;
+
+/* Exported helper to access the DMAMUX register */
+int r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val)
+{
+ unsigned long flags;
+ u32 dmamux;
+
+ if (!sysctrl_priv)
+ return -EPROBE_DEFER;
+
+ spin_lock_irqsave(&sysctrl_priv->lock, flags);
+
+ dmamux = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_DMAMUX);
+ dmamux &= ~mask;
+ dmamux |= val & mask;
+ writel(dmamux, sysctrl_priv->reg + R9A06G032_SYSCTRL_DMAMUX);
+
+ spin_unlock_irqrestore(&sysctrl_priv->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(r9a06g032_sysctrl_set_dmamux);
+
+static void clk_rdesc_set(struct r9a06g032_priv *clocks,
+ struct regbit rb, unsigned int on)
+{
+ u32 __iomem *reg = clocks->reg + (rb.reg * 4);
+ u32 val;
+
+ if (!rb.reg && !rb.bit)
+ return;
+
+ val = readl(reg);
+ val = (val & ~BIT(rb.bit)) | ((!!on) << rb.bit);
+ writel(val, reg);
+}
+
+static int clk_rdesc_get(struct r9a06g032_priv *clocks, struct regbit rb)
+{
+ u32 __iomem *reg = clocks->reg + (rb.reg * 4);
+ u32 val = readl(reg);
+
+ return !!(val & BIT(rb.bit));
+}
+
+/*
+ * This implements the R9A06G032 clock gate 'driver'. We cannot use the system's
+ * clock gate framework as the gates on the R9A06G032 have a special enabling
+ * sequence, therefore we use this little proxy.
+ */
+struct r9a06g032_clk_gate {
+ struct clk_hw hw;
+ struct r9a06g032_priv *clocks;
+ u16 index;
+
+ struct r9a06g032_gate gate;
+};
+
+#define to_r9a06g032_gate(_hw) container_of(_hw, struct r9a06g032_clk_gate, hw)
+
+static int create_add_module_clock(struct of_phandle_args *clkspec,
+ struct device *dev)
+{
+ struct clk *clk;
+ int error;
+
+ clk = of_clk_get_from_provider(clkspec);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ error = pm_clk_create(dev);
+ if (error) {
+ clk_put(clk);
+ return error;
+ }
+
+ error = pm_clk_add_clk(dev, clk);
+ if (error) {
+ pm_clk_destroy(dev);
+ clk_put(clk);
+ }
+
+ return error;
+}
+
+static int r9a06g032_attach_dev(struct generic_pm_domain *pd,
+ struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct of_phandle_args clkspec;
+ int i = 0;
+ int error;
+ int index;
+
+ while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i++,
+ &clkspec)) {
+ if (clkspec.np != pd->dev.of_node)
+ continue;
+
+ index = clkspec.args[0];
+ if (index < R9A06G032_CLOCK_COUNT &&
+ r9a06g032_clocks[index].managed) {
+ error = create_add_module_clock(&clkspec, dev);
+ of_node_put(clkspec.np);
+ if (error)
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+static void r9a06g032_detach_dev(struct generic_pm_domain *unused, struct device *dev)
+{
+ if (!pm_clk_no_clocks(dev))
+ pm_clk_destroy(dev);
+}
+
+static int r9a06g032_add_clk_domain(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct generic_pm_domain *pd;
+
+ pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ pd->name = np->name;
+ pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON |
+ GENPD_FLAG_ACTIVE_WAKEUP;
+ pd->attach_dev = r9a06g032_attach_dev;
+ pd->detach_dev = r9a06g032_detach_dev;
+ pm_genpd_init(pd, &pm_domain_always_on_gov, false);
+
+ of_genpd_add_provider_simple(np, pd);
+ return 0;
+}
+
+static void
+r9a06g032_clk_gate_set(struct r9a06g032_priv *clocks,
+ struct r9a06g032_gate *g, int on)
+{
+ unsigned long flags;
+
+ WARN_ON(!g->gate.reg && !g->gate.bit);
+
+ spin_lock_irqsave(&clocks->lock, flags);
+ clk_rdesc_set(clocks, g->gate, on);
+ /* De-assert reset */
+ clk_rdesc_set(clocks, g->reset, 1);
+ spin_unlock_irqrestore(&clocks->lock, flags);
+
+ /* Hardware manual recommends 5us delay after enabling clock & reset */
+ udelay(5);
+
+ /* If the peripheral is memory mapped (i.e. an AXI slave), there is an
+ * associated SLVRDY bit in the System Controller that needs to be set
+ * so that the FlexWAY bus fabric passes on the read/write requests.
+ */
+ spin_lock_irqsave(&clocks->lock, flags);
+ clk_rdesc_set(clocks, g->ready, on);
+ /* Clear 'Master Idle Request' bit */
+ clk_rdesc_set(clocks, g->midle, !on);
+ spin_unlock_irqrestore(&clocks->lock, flags);
+
+ /* Note: We don't wait for FlexWAY Socket Connection signal */
+}
+
+static int r9a06g032_clk_gate_enable(struct clk_hw *hw)
+{
+ struct r9a06g032_clk_gate *g = to_r9a06g032_gate(hw);
+
+ r9a06g032_clk_gate_set(g->clocks, &g->gate, 1);
+ return 0;
+}
+
+static void r9a06g032_clk_gate_disable(struct clk_hw *hw)
+{
+ struct r9a06g032_clk_gate *g = to_r9a06g032_gate(hw);
+
+ r9a06g032_clk_gate_set(g->clocks, &g->gate, 0);
+}
+
+static int r9a06g032_clk_gate_is_enabled(struct clk_hw *hw)
+{
+ struct r9a06g032_clk_gate *g = to_r9a06g032_gate(hw);
+
+ /* if clock is in reset, the gate might be on, and still not 'be' on */
+ if (g->gate.reset.reg && !clk_rdesc_get(g->clocks, g->gate.reset))
+ return 0;
+
+ return clk_rdesc_get(g->clocks, g->gate.gate);
+}
+
+static const struct clk_ops r9a06g032_clk_gate_ops = {
+ .enable = r9a06g032_clk_gate_enable,
+ .disable = r9a06g032_clk_gate_disable,
+ .is_enabled = r9a06g032_clk_gate_is_enabled,
+};
+
+static struct clk *
+r9a06g032_register_gate(struct r9a06g032_priv *clocks,
+ const char *parent_name,
+ const struct r9a06g032_clkdesc *desc)
+{
+ struct clk *clk;
+ struct r9a06g032_clk_gate *g;
+ struct clk_init_data init = {};
+
+ g = kzalloc_obj(*g);
+ if (!g)
+ return NULL;
+
+ init.name = desc->name;
+ init.ops = &r9a06g032_clk_gate_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+
+ g->clocks = clocks;
+ g->index = desc->index;
+ g->gate = desc->gate;
+ g->hw.init = &init;
+
+ /*
+ * important here, some clocks are already in use by the CM3, we
+ * have to assume they are not Linux's to play with and try to disable
+ * at the end of the boot!
+ */
+ if (r9a06g032_clk_gate_is_enabled(&g->hw)) {
+ init.flags |= CLK_IS_CRITICAL;
+ pr_debug("%s was enabled, making read-only\n", desc->name);
+ }
+
+ clk = clk_register(NULL, &g->hw);
+ if (IS_ERR(clk)) {
+ kfree(g);
+ return NULL;
+ }
+ return clk;
+}
+
+struct r9a06g032_clk_div {
+ struct clk_hw hw;
+ struct r9a06g032_priv *clocks;
+ u16 index;
+ u16 reg;
+ u16 min, max;
+ u8 table_size;
+ u16 table[8]; /* we know there are no more than 8 */
+};
+
+#define to_r9a06g032_div(_hw) \
+ container_of(_hw, struct r9a06g032_clk_div, hw)
+
+static unsigned long
+r9a06g032_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct r9a06g032_clk_div *clk = to_r9a06g032_div(hw);
+ u32 __iomem *reg = clk->clocks->reg + (4 * clk->reg);
+ u32 div = readl(reg);
+
+ if (div < clk->min)
+ div = clk->min;
+ else if (div > clk->max)
+ div = clk->max;
+ return DIV_ROUND_UP(parent_rate, div);
+}
+
+/*
+ * Attempts to find a value that is in range of min,max,
+ * and if a table of set dividers was specified for this
+ * register, try to find the fixed divider that is the closest
+ * to the target frequency
+ */
+static long
+r9a06g032_div_clamp_div(struct r9a06g032_clk_div *clk,
+ unsigned long rate, unsigned long prate)
+{
+ /* + 1 to cope with rates that have the remainder dropped */
+ u32 div = DIV_ROUND_UP(prate, rate + 1);
+ int i;
+
+ if (div <= clk->min)
+ return clk->min;
+ if (div >= clk->max)
+ return clk->max;
+
+ for (i = 0; clk->table_size && i < clk->table_size - 1; i++) {
+ if (div >= clk->table[i] && div <= clk->table[i + 1]) {
+ unsigned long m = rate -
+ DIV_ROUND_UP(prate, clk->table[i]);
+ unsigned long p =
+ DIV_ROUND_UP(prate, clk->table[i + 1]) -
+ rate;
+ /*
+ * select the divider that generates
+ * the value closest to the ideal frequency
+ */
+ div = p >= m ? clk->table[i] : clk->table[i + 1];
+ return div;
+ }
+ }
+ return div;
+}
+
+static int
+r9a06g032_div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+ struct r9a06g032_clk_div *clk = to_r9a06g032_div(hw);
+ u32 div = DIV_ROUND_UP(req->best_parent_rate, req->rate);
+
+ pr_devel("%s %pC %ld (prate %ld) (wanted div %u)\n", __func__,
+ hw->clk, req->rate, req->best_parent_rate, div);
+ pr_devel(" min %d (%ld) max %d (%ld)\n",
+ clk->min, DIV_ROUND_UP(req->best_parent_rate, clk->min),
+ clk->max, DIV_ROUND_UP(req->best_parent_rate, clk->max));
+
+ div = r9a06g032_div_clamp_div(clk, req->rate, req->best_parent_rate);
+ /*
+ * this is a hack. Currently the serial driver asks for a clock rate
+ * that is 16 times the baud rate -- and that is wildly outside the
+ * range of the UART divider, somehow there is no provision for that
+ * case of 'let the divider as is if outside range'.
+ * The serial driver *shouldn't* play with these clocks anyway, there's
+ * several uarts attached to this divider, and changing this impacts
+ * everyone.
+ */
+ if (clk->index == R9A06G032_DIV_UART ||
+ clk->index == R9A06G032_DIV_P2_PG) {
+ pr_devel("%s div uart hack!\n", __func__);
+ req->rate = clk_get_rate(hw->clk);
+ return 0;
+ }
+ req->rate = DIV_ROUND_UP(req->best_parent_rate, div);
+ pr_devel("%s %pC %ld / %u = %ld\n", __func__, hw->clk,
+ req->best_parent_rate, div, req->rate);
+ return 0;
+}
+
+static int
+r9a06g032_div_set_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate)
+{
+ struct r9a06g032_clk_div *clk = to_r9a06g032_div(hw);
+ /* + 1 to cope with rates that have the remainder dropped */
+ u32 div = DIV_ROUND_UP(parent_rate, rate + 1);
+ u32 __iomem *reg = clk->clocks->reg + (4 * clk->reg);
+
+ pr_devel("%s %pC rate %ld parent %ld div %d\n", __func__, hw->clk,
+ rate, parent_rate, div);
+
+ /*
+ * Need to write the bit 31 with the divider value to
+ * latch it. Technically we should wait until it has been
+ * cleared too.
+ * TODO: Find whether this callback is sleepable, in case
+ * the hardware /does/ require some sort of spinloop here.
+ */
+ writel(div | BIT(31), reg);
+
+ return 0;
+}
+
+static const struct clk_ops r9a06g032_clk_div_ops = {
+ .recalc_rate = r9a06g032_div_recalc_rate,
+ .determine_rate = r9a06g032_div_determine_rate,
+ .set_rate = r9a06g032_div_set_rate,
+};
+
+static struct clk *
+r9a06g032_register_div(struct r9a06g032_priv *clocks,
+ const char *parent_name,
+ const struct r9a06g032_clkdesc *desc)
+{
+ struct r9a06g032_clk_div *div;
+ struct clk *clk;
+ struct clk_init_data init = {};
+ unsigned int i;
+
+ div = kzalloc_obj(*div);
+ if (!div)
+ return NULL;
+
+ init.name = desc->name;
+ init.ops = &r9a06g032_clk_div_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+
+ div->clocks = clocks;
+ div->index = desc->index;
+ div->reg = desc->div.reg;
+ div->hw.init = &init;
+ div->min = desc->div.min;
+ div->max = desc->div.max;
+ /* populate (optional) divider table fixed values */
+ for (i = 0; i < ARRAY_SIZE(div->table) &&
+ i < ARRAY_SIZE(desc->div.table) && desc->div.table[i]; i++) {
+ div->table[div->table_size++] = desc->div.table[i];
+ }
+
+ clk = clk_register(NULL, &div->hw);
+ if (IS_ERR(clk)) {
+ kfree(div);
+ return NULL;
+ }
+ return clk;
+}
+
+/*
+ * This clock provider handles the case of the R9A06G032 where you have
+ * peripherals that have two potential clock source and two gates, one for
+ * each of the clock source - the used clock source (for all sub clocks)
+ * is selected by a single bit.
+ * That single bit affects all sub-clocks, and therefore needs to change the
+ * active gate (and turn the others off) and force a recalculation of the rates.
+ *
+ * This implements two clock providers, one 'bitselect' that
+ * handles the switch between both parents, and another 'dualgate'
+ * that knows which gate to poke at, depending on the parent's bit position.
+ */
+struct r9a06g032_clk_bitsel {
+ struct clk_hw hw;
+ struct r9a06g032_priv *clocks;
+ u16 index;
+ struct regbit selector; /* selector register + bit */
+};
+
+#define to_clk_bitselect(_hw) \
+ container_of(_hw, struct r9a06g032_clk_bitsel, hw)
+
+static u8 r9a06g032_clk_mux_get_parent(struct clk_hw *hw)
+{
+ struct r9a06g032_clk_bitsel *set = to_clk_bitselect(hw);
+
+ return clk_rdesc_get(set->clocks, set->selector);
+}
+
+static int r9a06g032_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct r9a06g032_clk_bitsel *set = to_clk_bitselect(hw);
+
+ /* a single bit in the register selects one of two parent clocks */
+ clk_rdesc_set(set->clocks, set->selector, !!index);
+
+ return 0;
+}
+
+static const struct clk_ops clk_bitselect_ops = {
+ .determine_rate = clk_hw_determine_rate_no_reparent,
+ .get_parent = r9a06g032_clk_mux_get_parent,
+ .set_parent = r9a06g032_clk_mux_set_parent,
+};
+
+static struct clk *
+r9a06g032_register_bitsel(struct r9a06g032_priv *clocks,
+ const char *parent_name,
+ const struct r9a06g032_clkdesc *desc)
+{
+ struct clk *clk;
+ struct r9a06g032_clk_bitsel *g;
+ struct clk_init_data init = {};
+ const char *names[2];
+
+ /* allocate the gate */
+ g = kzalloc_obj(*g);
+ if (!g)
+ return NULL;
+
+ names[0] = parent_name;
+ names[1] = "clk_pll_usb";
+
+ init.name = desc->name;
+ init.ops = &clk_bitselect_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = names;
+ init.num_parents = 2;
+
+ g->clocks = clocks;
+ g->index = desc->index;
+ g->selector = desc->dual.sel;
+ g->hw.init = &init;
+
+ clk = clk_register(NULL, &g->hw);
+ if (IS_ERR(clk)) {
+ kfree(g);
+ return NULL;
+ }
+ return clk;
+}
+
+struct r9a06g032_clk_dualgate {
+ struct clk_hw hw;
+ struct r9a06g032_priv *clocks;
+ u16 index;
+ struct regbit selector; /* selector register + bit */
+ struct r9a06g032_gate gate[2];
+};
+
+#define to_clk_dualgate(_hw) \
+ container_of(_hw, struct r9a06g032_clk_dualgate, hw)
+
+static int
+r9a06g032_clk_dualgate_setenable(struct r9a06g032_clk_dualgate *g, int enable)
+{
+ u8 sel_bit = clk_rdesc_get(g->clocks, g->selector);
+
+ /* we always turn off the 'other' gate, regardless */
+ r9a06g032_clk_gate_set(g->clocks, &g->gate[!sel_bit], 0);
+ r9a06g032_clk_gate_set(g->clocks, &g->gate[sel_bit], enable);
+
+ return 0;
+}
+
+static int r9a06g032_clk_dualgate_enable(struct clk_hw *hw)
+{
+ struct r9a06g032_clk_dualgate *gate = to_clk_dualgate(hw);
+
+ r9a06g032_clk_dualgate_setenable(gate, 1);
+
+ return 0;
+}
+
+static void r9a06g032_clk_dualgate_disable(struct clk_hw *hw)
+{
+ struct r9a06g032_clk_dualgate *gate = to_clk_dualgate(hw);
+
+ r9a06g032_clk_dualgate_setenable(gate, 0);
+}
+
+static int r9a06g032_clk_dualgate_is_enabled(struct clk_hw *hw)
+{
+ struct r9a06g032_clk_dualgate *g = to_clk_dualgate(hw);
+ u8 sel_bit = clk_rdesc_get(g->clocks, g->selector);
+
+ return clk_rdesc_get(g->clocks, g->gate[sel_bit].gate);
+}
+
+static const struct clk_ops r9a06g032_clk_dualgate_ops = {
+ .enable = r9a06g032_clk_dualgate_enable,
+ .disable = r9a06g032_clk_dualgate_disable,
+ .is_enabled = r9a06g032_clk_dualgate_is_enabled,
+};
+
+static struct clk *
+r9a06g032_register_dualgate(struct r9a06g032_priv *clocks,
+ const char *parent_name,
+ const struct r9a06g032_clkdesc *desc,
+ struct regbit sel)
+{
+ struct r9a06g032_clk_dualgate *g;
+ struct clk *clk;
+ struct clk_init_data init = {};
+
+ /* allocate the gate */
+ g = kzalloc_obj(*g);
+ if (!g)
+ return NULL;
+ g->clocks = clocks;
+ g->index = desc->index;
+ g->selector = sel;
+ g->gate[0].gate = desc->dual.g1;
+ g->gate[0].reset = desc->dual.r1;
+ g->gate[1].gate = desc->dual.g2;
+ g->gate[1].reset = desc->dual.r2;
+
+ init.name = desc->name;
+ init.ops = &r9a06g032_clk_dualgate_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ g->hw.init = &init;
+ /*
+ * important here, some clocks are already in use by the CM3, we
+ * have to assume they are not Linux's to play with and try to disable
+ * at the end of the boot!
+ */
+ if (r9a06g032_clk_dualgate_is_enabled(&g->hw)) {
+ init.flags |= CLK_IS_CRITICAL;
+ pr_debug("%s was enabled, making read-only\n", desc->name);
+ }
+
+ clk = clk_register(NULL, &g->hw);
+ if (IS_ERR(clk)) {
+ kfree(g);
+ return NULL;
+ }
+ return clk;
+}
+
+static void r9a06g032_clocks_del_clk_provider(void *data)
+{
+ of_clk_del_provider(data);
+}
+
+static int r9a06g032_restart_handler(struct sys_off_data *data)
+{
+ writel(R9A06G032_SYSCTRL_SWRST, sysctrl_priv->reg + R9A06G032_SYSCTRL_RSTCTRL);
+ return NOTIFY_DONE;
+}
+
+static void __init r9a06g032_init_h2mode(struct r9a06g032_priv *clocks)
+{
+ struct device_node *usbf_np;
+ u32 usb;
+
+ for_each_compatible_node(usbf_np, NULL, "renesas,rzn1-usbf") {
+ if (of_device_is_available(usbf_np))
+ break;
+ }
+
+ usb = readl(clocks->reg + R9A06G032_SYSCTRL_USB);
+ if (usbf_np) {
+ /* 1 host and 1 device mode */
+ usb &= ~R9A06G032_SYSCTRL_USB_H2MODE;
+ of_node_put(usbf_np);
+ } else {
+ /* 2 hosts mode */
+ usb |= R9A06G032_SYSCTRL_USB_H2MODE;
+ }
+ writel(usb, clocks->reg + R9A06G032_SYSCTRL_USB);
+}
+
+static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct r9a06g032_priv *clocks;
+ struct clk **clks;
+ struct clk *mclk;
+ unsigned int i;
+ struct regbit uart_group_sel[2];
+ int error;
+
+ clocks = devm_kzalloc(dev, sizeof(*clocks), GFP_KERNEL);
+ clks = devm_kcalloc(dev, R9A06G032_CLOCK_COUNT, sizeof(struct clk *),
+ GFP_KERNEL);
+ if (!clocks || !clks)
+ return -ENOMEM;
+
+ spin_lock_init(&clocks->lock);
+
+ clocks->data.clks = clks;
+ clocks->data.clk_num = R9A06G032_CLOCK_COUNT;
+
+ mclk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(mclk))
+ return PTR_ERR(mclk);
+
+ clocks->reg = devm_of_iomap(dev, np, 0, NULL);
+ if (IS_ERR(clocks->reg))
+ return PTR_ERR(clocks->reg);
+
+ r9a06g032_init_h2mode(clocks);
+
+ /* Clear potentially pending resets */
+ writel(R9A06G032_SYSCTRL_WDA7RST_0 | R9A06G032_SYSCTRL_WDA7RST_1,
+ clocks->reg + R9A06G032_SYSCTRL_RSTCTRL);
+ /* Allow watchdog and software resets */
+ writel(R9A06G032_SYSCTRL_WDA7RST_0 | R9A06G032_SYSCTRL_WDA7RST_1 |
+ R9A06G032_SYSCTRL_SWRST | R9A06G032_SYSCTRL_RSTEN_MRESET_EN,
+ clocks->reg + R9A06G032_SYSCTRL_RSTEN);
+
+ error = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH,
+ r9a06g032_restart_handler, NULL);
+ if (error)
+ dev_warn(dev, "couldn't register restart handler (%d)\n", error);
+
+ for (i = 0; i < ARRAY_SIZE(r9a06g032_clocks); ++i) {
+ const struct r9a06g032_clkdesc *d = &r9a06g032_clocks[i];
+ const char *parent_name = d->source ?
+ __clk_get_name(clocks->data.clks[d->source - 1]) :
+ __clk_get_name(mclk);
+ struct clk *clk = NULL;
+
+ switch (d->type) {
+ case K_FFC:
+ clk = clk_register_fixed_factor(NULL, d->name,
+ parent_name, 0,
+ d->ffc.mul,
+ d->ffc.div);
+ break;
+ case K_GATE:
+ clk = r9a06g032_register_gate(clocks, parent_name, d);
+ break;
+ case K_DIV:
+ clk = r9a06g032_register_div(clocks, parent_name, d);
+ break;
+ case K_BITSEL:
+ /* keep that selector register around */
+ uart_group_sel[d->dual.group] = d->dual.sel;
+ clk = r9a06g032_register_bitsel(clocks, parent_name, d);
+ break;
+ case K_DUALGATE:
+ clk = r9a06g032_register_dualgate(clocks, parent_name,
+ d,
+ uart_group_sel[d->dual.group]);
+ break;
+ }
+ clocks->data.clks[d->index] = clk;
+ }
+ error = of_clk_add_provider(np, of_clk_src_onecell_get, &clocks->data);
+ if (error)
+ return error;
+
+ error = devm_add_action_or_reset(dev,
+ r9a06g032_clocks_del_clk_provider, np);
+ if (error)
+ return error;
+
+ error = r9a06g032_add_clk_domain(dev);
+ if (error)
+ return error;
+
+ sysctrl_priv = clocks;
+
+ error = of_platform_populate(np, NULL, NULL, dev);
+ if (error)
+ dev_err(dev, "Failed to populate children (%d)\n", error);
+
+ return 0;
+}
+
+static const struct of_device_id r9a06g032_match[] = {
+ { .compatible = "renesas,r9a06g032-sysctrl" },
+ { }
+};
+
+static struct platform_driver r9a06g032_clock_driver = {
+ .driver = {
+ .name = "renesas,r9a06g032-sysctrl",
+ .of_match_table = r9a06g032_match,
+ },
+};
+
+static int __init r9a06g032_clocks_init(void)
+{
+ return platform_driver_probe(&r9a06g032_clock_driver,
+ r9a06g032_clocks_probe);
+}
+
+subsys_initcall(r9a06g032_clocks_init);
diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
new file mode 100644
index 000000000..59d6ee2e8
--- /dev/null
+++ b/drivers/clk/renesas/r9a07g043-cpg.c
@@ -0,0 +1,433 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G2UL CPG driver
+ *
+ * Copyright (C) 2022 Renesas Electronics Corp.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/r9a07g043-cpg.h>
+
+#include "rzg2l-cpg.h"
+
+/* Specific registers. */
+#define CPG_PL2SDHI_DSEL (0x218)
+
+/* Clock select configuration. */
+#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2)
+#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2)
+
+/* Clock status configuration. */
+#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1)
+#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1)
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A07G043_CLK_P0_DIV2,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_OSC_DIV1000,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL2_DIV2,
+ CLK_PLL2_DIV2_8,
+ CLK_PLL2_DIV2_10,
+ CLK_PLL3,
+ CLK_PLL3_400,
+ CLK_PLL3_533,
+ CLK_PLL3_DIV2,
+ CLK_PLL3_DIV2_4,
+ CLK_PLL3_DIV2_4_2,
+ CLK_SEL_PLL3_3,
+ CLK_DIV_PLL3_C,
+#ifdef CONFIG_ARM64
+ CLK_M2_DIV2,
+ CLK_PLL5,
+ CLK_PLL5_500,
+ CLK_PLL5_250,
+ CLK_PLL5_FOUTPOSTDIV,
+ CLK_DSI_DIV,
+#endif
+ CLK_PLL6,
+ CLK_PLL6_250,
+ CLK_P1_DIV2,
+ CLK_PLL2_800,
+ CLK_PLL2_SDHI_533,
+ CLK_PLL2_SDHI_400,
+ CLK_PLL2_SDHI_266,
+ CLK_SD0_DIV4,
+ CLK_SD1_DIV4,
+
+ /* Module Clocks */
+ MOD_CLK_BASE,
+};
+
+/* Divider tables */
+static const struct clk_div_table dtable_1_8[] = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {3, 8},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_1_32[] = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {3, 8},
+ {4, 32},
+ {0, 0},
+};
+
+/* Mux clock tables */
+static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
+#ifdef CONFIG_ARM64
+static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
+#endif
+static const char * const sel_sdhi[] = { ".clk_533", ".clk_400", ".clk_266" };
+
+static const u32 mtable_sdhi[] = { 1, 2, 3 };
+
+static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_FIXED(".osc", R9A07G043_OSCCLK, CLK_EXTAL, 1, 1),
+ DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000),
+ DEF_SAMPLL(".pll1", CLK_PLL1, CLK_EXTAL, CPG_SAM_PLL_CONF(0)),
+ DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3),
+ DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2),
+ DEF_FIXED(".clk_800", CLK_PLL2_800, CLK_PLL2, 1, 2),
+ DEF_FIXED(".clk_533", CLK_PLL2_SDHI_533, CLK_PLL2, 1, 3),
+ DEF_FIXED(".clk_400", CLK_PLL2_SDHI_400, CLK_PLL2_800, 1, 2),
+ DEF_FIXED(".clk_266", CLK_PLL2_SDHI_266, CLK_PLL2_SDHI_533, 1, 2),
+ DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8),
+ DEF_FIXED(".pll2_div2_10", CLK_PLL2_DIV2_10, CLK_PLL2_DIV2, 1, 10),
+ DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3),
+ DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2),
+ DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4),
+ DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2),
+ DEF_FIXED(".pll3_400", CLK_PLL3_400, CLK_PLL3, 1, 4),
+ DEF_FIXED(".pll3_533", CLK_PLL3_533, CLK_PLL3, 1, 3),
+ DEF_MUX_RO(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3, sel_pll3_3),
+ DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3, DIVPL3C, dtable_1_32),
+#ifdef CONFIG_ARM64
+ DEF_FIXED(".pll5", CLK_PLL5, CLK_EXTAL, 125, 1),
+ DEF_FIXED(".pll5_500", CLK_PLL5_500, CLK_PLL5, 1, 6),
+ DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_500, 1, 2),
+ DEF_PLL5_FOUTPOSTDIV(".pll5_foutpostdiv", CLK_PLL5_FOUTPOSTDIV, CLK_EXTAL),
+#endif
+ DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6),
+ DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2),
+
+ /* Core output clk */
+ DEF_DIV("I", R9A07G043_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8),
+ DEF_DIV("P0", R9A07G043_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A, dtable_1_32),
+ DEF_FIXED("P0_DIV2", R9A07G043_CLK_P0_DIV2, R9A07G043_CLK_P0, 1, 2),
+ DEF_FIXED("TSU", R9A07G043_CLK_TSU, CLK_PLL2_DIV2_10, 1, 1),
+ DEF_DIV("P1", R9A07G043_CLK_P1, CLK_PLL3_DIV2_4, DIVPL3B, dtable_1_32),
+ DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G043_CLK_P1, 1, 2),
+ DEF_DIV("P2", R9A07G043_CLK_P2, CLK_PLL3_DIV2_4_2, DIVPL3A, dtable_1_32),
+ DEF_FIXED("M0", R9A07G043_CLK_M0, CLK_PLL3_DIV2_4, 1, 1),
+ DEF_FIXED("ZT", R9A07G043_CLK_ZT, CLK_PLL3_DIV2_4_2, 1, 1),
+#ifdef CONFIG_ARM64
+ DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2),
+#endif
+#ifdef CONFIG_RISCV
+ DEF_FIXED("HP", R9A07G043_CLK_HP, CLK_PLL6_250, 1, 1),
+#endif
+ DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
+ DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+ DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_sdhi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_sdhi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4),
+#ifdef CONFIG_ARM64
+ DEF_FIXED("M2", R9A07G043_CLK_M2, CLK_PLL3_533, 1, 2),
+ DEF_FIXED("M2_DIV2", CLK_M2_DIV2, R9A07G043_CLK_M2, 1, 2),
+ DEF_DSI_DIV("DSI_DIV", CLK_DSI_DIV, CLK_PLL5_FOUTPOSTDIV, CLK_SET_RATE_PARENT),
+ DEF_FIXED("M3", R9A07G043_CLK_M3, CLK_DSI_DIV, 1, 1),
+#endif
+};
+
+static const struct rzg2l_mod_clk r9a07g043_mod_clks[] = {
+#ifdef CONFIG_ARM64
+ DEF_MOD("gic", R9A07G043_GIC600_GICCLK, R9A07G043_CLK_P1,
+ 0x514, 0, MSTOP(BUS_REG1, BIT(7))),
+ DEF_MOD("ia55_pclk", R9A07G043_IA55_PCLK, R9A07G043_CLK_P2,
+ 0x518, 0, MSTOP(BUS_PERI_CPU, BIT(13))),
+ DEF_MOD("ia55_clk", R9A07G043_IA55_CLK, R9A07G043_CLK_P1,
+ 0x518, 1, MSTOP(BUS_PERI_CPU, BIT(13))),
+#endif
+#ifdef CONFIG_RISCV
+ DEF_MOD("iax45_pclk", R9A07G043_IAX45_PCLK, R9A07G043_CLK_P2,
+ 0x518, 0, MSTOP(BUS_PERI_CPU, BIT(13))),
+ DEF_MOD("iax45_clk", R9A07G043_IAX45_CLK, R9A07G043_CLK_P1,
+ 0x518, 1, MSTOP(BUS_PERI_CPU, BIT(13))),
+#endif
+ DEF_MOD("dmac_aclk", R9A07G043_DMAC_ACLK, R9A07G043_CLK_P1,
+ 0x52c, 0, MSTOP(BUS_REG1, BIT(2))),
+ DEF_MOD("dmac_pclk", R9A07G043_DMAC_PCLK, CLK_P1_DIV2,
+ 0x52c, 1, MSTOP(BUS_REG1, BIT(3))),
+ DEF_MOD("ostm0_pclk", R9A07G043_OSTM0_PCLK, R9A07G043_CLK_P0,
+ 0x534, 0, MSTOP(BUS_REG0, BIT(4))),
+ DEF_MOD("ostm1_pclk", R9A07G043_OSTM1_PCLK, R9A07G043_CLK_P0,
+ 0x534, 1, MSTOP(BUS_REG0, BIT(5))),
+ DEF_MOD("ostm2_pclk", R9A07G043_OSTM2_PCLK, R9A07G043_CLK_P0,
+ 0x534, 2, MSTOP(BUS_REG0, BIT(6))),
+ DEF_MOD("mtu_x_mck", R9A07G043_MTU_X_MCK_MTU3, R9A07G043_CLK_P0,
+ 0x538, 0, MSTOP(BUS_MCPU1, BIT(2))),
+ DEF_MOD("wdt0_pclk", R9A07G043_WDT0_PCLK, R9A07G043_CLK_P0,
+ 0x548, 0, MSTOP(BUS_REG0, BIT(2))),
+ DEF_MOD("wdt0_clk", R9A07G043_WDT0_CLK, R9A07G043_OSCCLK,
+ 0x548, 1, MSTOP(BUS_REG0, BIT(2))),
+ DEF_MOD("spi_clk2", R9A07G043_SPI_CLK2, R9A07G043_CLK_SPI1,
+ 0x550, 0, MSTOP(BUS_MCPU1, BIT(1))),
+ DEF_MOD("spi_clk", R9A07G043_SPI_CLK, R9A07G043_CLK_SPI0,
+ 0x550, 1, MSTOP(BUS_MCPU1, BIT(1))),
+ DEF_MOD("sdhi0_imclk", R9A07G043_SDHI0_IMCLK, CLK_SD0_DIV4,
+ 0x554, 0, MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi0_imclk2", R9A07G043_SDHI0_IMCLK2, CLK_SD0_DIV4,
+ 0x554, 1, MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi0_clk_hs", R9A07G043_SDHI0_CLK_HS, R9A07G043_CLK_SD0,
+ 0x554, 2, MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi0_aclk", R9A07G043_SDHI0_ACLK, R9A07G043_CLK_P1,
+ 0x554, 3, MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi1_imclk", R9A07G043_SDHI1_IMCLK, CLK_SD1_DIV4,
+ 0x554, 4, MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("sdhi1_imclk2", R9A07G043_SDHI1_IMCLK2, CLK_SD1_DIV4,
+ 0x554, 5, MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("sdhi1_clk_hs", R9A07G043_SDHI1_CLK_HS, R9A07G043_CLK_SD1,
+ 0x554, 6, MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("sdhi1_aclk", R9A07G043_SDHI1_ACLK, R9A07G043_CLK_P1,
+ 0x554, 7, MSTOP(BUS_PERI_COM, BIT(1))),
+#ifdef CONFIG_ARM64
+ DEF_MOD("cru_sysclk", R9A07G043_CRU_SYSCLK, CLK_M2_DIV2,
+ 0x564, 0, MSTOP(BUS_PERI_VIDEO, BIT(3))),
+ DEF_MOD("cru_vclk", R9A07G043_CRU_VCLK, R9A07G043_CLK_M2,
+ 0x564, 1, MSTOP(BUS_PERI_VIDEO, BIT(3))),
+ DEF_MOD("cru_pclk", R9A07G043_CRU_PCLK, R9A07G043_CLK_ZT,
+ 0x564, 2, MSTOP(BUS_PERI_VIDEO, BIT(3))),
+ DEF_MOD("cru_aclk", R9A07G043_CRU_ACLK, R9A07G043_CLK_M0,
+ 0x564, 3, MSTOP(BUS_PERI_VIDEO, BIT(3))),
+ DEF_COUPLED("lcdc_clk_a", R9A07G043_LCDC_CLK_A, R9A07G043_CLK_M0,
+ 0x56c, 0, MSTOP(BUS_PERI_VIDEO, GENMASK(8, 7))),
+ DEF_COUPLED("lcdc_clk_p", R9A07G043_LCDC_CLK_P, R9A07G043_CLK_ZT,
+ 0x56c, 0, MSTOP(BUS_PERI_VIDEO, GENMASK(8, 7))),
+ DEF_MOD("lcdc_clk_d", R9A07G043_LCDC_CLK_D, R9A07G043_CLK_M3,
+ 0x56c, 1, MSTOP(BUS_PERI_VIDEO, BIT(9))),
+#endif
+ DEF_MOD("ssi0_pclk", R9A07G043_SSI0_PCLK2, R9A07G043_CLK_P0,
+ 0x570, 0, MSTOP(BUS_MCPU1, BIT(10))),
+ DEF_MOD("ssi0_sfr", R9A07G043_SSI0_PCLK_SFR, R9A07G043_CLK_P0,
+ 0x570, 1, MSTOP(BUS_MCPU1, BIT(10))),
+ DEF_MOD("ssi1_pclk", R9A07G043_SSI1_PCLK2, R9A07G043_CLK_P0,
+ 0x570, 2, MSTOP(BUS_MCPU1, BIT(11))),
+ DEF_MOD("ssi1_sfr", R9A07G043_SSI1_PCLK_SFR, R9A07G043_CLK_P0,
+ 0x570, 3, MSTOP(BUS_MCPU1, BIT(11))),
+ DEF_MOD("ssi2_pclk", R9A07G043_SSI2_PCLK2, R9A07G043_CLK_P0,
+ 0x570, 4, MSTOP(BUS_MCPU1, BIT(12))),
+ DEF_MOD("ssi2_sfr", R9A07G043_SSI2_PCLK_SFR, R9A07G043_CLK_P0,
+ 0x570, 5, MSTOP(BUS_MCPU1, BIT(12))),
+ DEF_MOD("ssi3_pclk", R9A07G043_SSI3_PCLK2, R9A07G043_CLK_P0,
+ 0x570, 6, MSTOP(BUS_MCPU1, BIT(13))),
+ DEF_MOD("ssi3_sfr", R9A07G043_SSI3_PCLK_SFR, R9A07G043_CLK_P0,
+ 0x570, 7, MSTOP(BUS_MCPU1, BIT(13))),
+ DEF_MOD("usb0_host", R9A07G043_USB_U2H0_HCLK, R9A07G043_CLK_P1,
+ 0x578, 0, MSTOP(BUS_PERI_COM, BIT(5))),
+ DEF_MOD("usb1_host", R9A07G043_USB_U2H1_HCLK, R9A07G043_CLK_P1,
+ 0x578, 1, MSTOP(BUS_PERI_COM, BIT(7))),
+ DEF_MOD("usb0_func", R9A07G043_USB_U2P_EXR_CPUCLK, R9A07G043_CLK_P1,
+ 0x578, 2, MSTOP(BUS_PERI_COM, BIT(6))),
+ DEF_MOD("usb_pclk", R9A07G043_USB_PCLK, R9A07G043_CLK_P1,
+ 0x578, 3, MSTOP(BUS_PERI_COM, BIT(4))),
+ DEF_COUPLED("eth0_axi", R9A07G043_ETH0_CLK_AXI, R9A07G043_CLK_M0,
+ 0x57c, 0, MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth0_chi", R9A07G043_ETH0_CLK_CHI, R9A07G043_CLK_ZT,
+ 0x57c, 0, MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth1_axi", R9A07G043_ETH1_CLK_AXI, R9A07G043_CLK_M0,
+ 0x57c, 1, MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_COUPLED("eth1_chi", R9A07G043_ETH1_CLK_CHI, R9A07G043_CLK_ZT,
+ 0x57c, 1, MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_MOD("i2c0", R9A07G043_I2C0_PCLK, R9A07G043_CLK_P0,
+ 0x580, 0, MSTOP(BUS_MCPU2, BIT(10))),
+ DEF_MOD("i2c1", R9A07G043_I2C1_PCLK, R9A07G043_CLK_P0,
+ 0x580, 1, MSTOP(BUS_MCPU2, BIT(11))),
+ DEF_MOD("i2c2", R9A07G043_I2C2_PCLK, R9A07G043_CLK_P0,
+ 0x580, 2, MSTOP(BUS_MCPU2, BIT(12))),
+ DEF_MOD("i2c3", R9A07G043_I2C3_PCLK, R9A07G043_CLK_P0,
+ 0x580, 3, MSTOP(BUS_MCPU2, BIT(13))),
+ DEF_MOD("scif0", R9A07G043_SCIF0_CLK_PCK, R9A07G043_CLK_P0,
+ 0x584, 0, MSTOP(BUS_MCPU2, BIT(1))),
+ DEF_MOD("scif1", R9A07G043_SCIF1_CLK_PCK, R9A07G043_CLK_P0,
+ 0x584, 1, MSTOP(BUS_MCPU2, BIT(2))),
+ DEF_MOD("scif2", R9A07G043_SCIF2_CLK_PCK, R9A07G043_CLK_P0,
+ 0x584, 2, MSTOP(BUS_MCPU2, BIT(3))),
+ DEF_MOD("scif3", R9A07G043_SCIF3_CLK_PCK, R9A07G043_CLK_P0,
+ 0x584, 3, MSTOP(BUS_MCPU2, BIT(4))),
+ DEF_MOD("scif4", R9A07G043_SCIF4_CLK_PCK, R9A07G043_CLK_P0,
+ 0x584, 4, MSTOP(BUS_MCPU2, BIT(5))),
+ DEF_MOD("sci0", R9A07G043_SCI0_CLKP, R9A07G043_CLK_P0,
+ 0x588, 0, MSTOP(BUS_MCPU2, BIT(7))),
+ DEF_MOD("sci1", R9A07G043_SCI1_CLKP, R9A07G043_CLK_P0,
+ 0x588, 1, MSTOP(BUS_MCPU2, BIT(8))),
+ DEF_MOD("rspi0", R9A07G043_RSPI0_CLKB, R9A07G043_CLK_P0,
+ 0x590, 0, MSTOP(BUS_MCPU1, BIT(14))),
+ DEF_MOD("rspi1", R9A07G043_RSPI1_CLKB, R9A07G043_CLK_P0,
+ 0x590, 1, MSTOP(BUS_MCPU1, BIT(15))),
+ DEF_MOD("rspi2", R9A07G043_RSPI2_CLKB, R9A07G043_CLK_P0,
+ 0x590, 2, MSTOP(BUS_MCPU2, BIT(0))),
+ DEF_MOD("canfd", R9A07G043_CANFD_PCLK, R9A07G043_CLK_P0,
+ 0x594, 0, MSTOP(BUS_MCPU2, BIT(9))),
+ DEF_MOD("gpio", R9A07G043_GPIO_HCLK, R9A07G043_OSCCLK,
+ 0x598, 0, MSTOP(BUS_PERI_CPU, BIT(6))),
+ DEF_MOD("adc_adclk", R9A07G043_ADC_ADCLK, R9A07G043_CLK_TSU,
+ 0x5a8, 0, MSTOP(BUS_MCPU2, BIT(14))),
+ DEF_MOD("adc_pclk", R9A07G043_ADC_PCLK, R9A07G043_CLK_P0,
+ 0x5a8, 1, MSTOP(BUS_MCPU2, BIT(14))),
+ DEF_MOD("tsu_pclk", R9A07G043_TSU_PCLK, R9A07G043_CLK_TSU,
+ 0x5ac, 0, MSTOP(BUS_MCPU2, BIT(15))),
+#ifdef CONFIG_RISCV
+ DEF_MOD("nceplic_aclk", R9A07G043_NCEPLIC_ACLK, R9A07G043_CLK_P1,
+ 0x608, 0, MSTOP(BUS_REG1, BIT(7))),
+#endif
+};
+
+static const struct rzg2l_reset r9a07g043_resets[] = {
+#ifdef CONFIG_ARM64
+ DEF_RST(R9A07G043_GIC600_GICRESET_N, 0x814, 0),
+ DEF_RST(R9A07G043_GIC600_DBG_GICRESET_N, 0x814, 1),
+ DEF_RST(R9A07G043_IA55_RESETN, 0x818, 0),
+#endif
+#ifdef CONFIG_RISCV
+ DEF_RST(R9A07G043_IAX45_RESETN, 0x818, 0),
+#endif
+ DEF_RST(R9A07G043_DMAC_ARESETN, 0x82c, 0),
+ DEF_RST(R9A07G043_DMAC_RST_ASYNC, 0x82c, 1),
+ DEF_RST(R9A07G043_OSTM0_PRESETZ, 0x834, 0),
+ DEF_RST(R9A07G043_OSTM1_PRESETZ, 0x834, 1),
+ DEF_RST(R9A07G043_OSTM2_PRESETZ, 0x834, 2),
+ DEF_RST(R9A07G043_MTU_X_PRESET_MTU3, 0x838, 0),
+ DEF_RST(R9A07G043_WDT0_PRESETN, 0x848, 0),
+ DEF_RST(R9A07G043_SPI_RST, 0x850, 0),
+ DEF_RST(R9A07G043_SDHI0_IXRST, 0x854, 0),
+ DEF_RST(R9A07G043_SDHI1_IXRST, 0x854, 1),
+#ifdef CONFIG_ARM64
+ DEF_RST(R9A07G043_CRU_CMN_RSTB, 0x864, 0),
+ DEF_RST(R9A07G043_CRU_PRESETN, 0x864, 1),
+ DEF_RST(R9A07G043_CRU_ARESETN, 0x864, 2),
+ DEF_RST(R9A07G043_LCDC_RESET_N, 0x86c, 0),
+#endif
+ DEF_RST(R9A07G043_SSI0_RST_M2_REG, 0x870, 0),
+ DEF_RST(R9A07G043_SSI1_RST_M2_REG, 0x870, 1),
+ DEF_RST(R9A07G043_SSI2_RST_M2_REG, 0x870, 2),
+ DEF_RST(R9A07G043_SSI3_RST_M2_REG, 0x870, 3),
+ DEF_RST(R9A07G043_USB_U2H0_HRESETN, 0x878, 0),
+ DEF_RST(R9A07G043_USB_U2H1_HRESETN, 0x878, 1),
+ DEF_RST(R9A07G043_USB_U2P_EXL_SYSRST, 0x878, 2),
+ DEF_RST(R9A07G043_USB_PRESETN, 0x878, 3),
+ DEF_RST(R9A07G043_ETH0_RST_HW_N, 0x87c, 0),
+ DEF_RST(R9A07G043_ETH1_RST_HW_N, 0x87c, 1),
+ DEF_RST(R9A07G043_I2C0_MRST, 0x880, 0),
+ DEF_RST(R9A07G043_I2C1_MRST, 0x880, 1),
+ DEF_RST(R9A07G043_I2C2_MRST, 0x880, 2),
+ DEF_RST(R9A07G043_I2C3_MRST, 0x880, 3),
+ DEF_RST(R9A07G043_SCIF0_RST_SYSTEM_N, 0x884, 0),
+ DEF_RST(R9A07G043_SCIF1_RST_SYSTEM_N, 0x884, 1),
+ DEF_RST(R9A07G043_SCIF2_RST_SYSTEM_N, 0x884, 2),
+ DEF_RST(R9A07G043_SCIF3_RST_SYSTEM_N, 0x884, 3),
+ DEF_RST(R9A07G043_SCIF4_RST_SYSTEM_N, 0x884, 4),
+ DEF_RST(R9A07G043_SCI0_RST, 0x888, 0),
+ DEF_RST(R9A07G043_SCI1_RST, 0x888, 1),
+ DEF_RST(R9A07G043_RSPI0_RST, 0x890, 0),
+ DEF_RST(R9A07G043_RSPI1_RST, 0x890, 1),
+ DEF_RST(R9A07G043_RSPI2_RST, 0x890, 2),
+ DEF_RST(R9A07G043_CANFD_RSTP_N, 0x894, 0),
+ DEF_RST(R9A07G043_CANFD_RSTC_N, 0x894, 1),
+ DEF_RST(R9A07G043_GPIO_RSTN, 0x898, 0),
+ DEF_RST(R9A07G043_GPIO_PORT_RESETN, 0x898, 1),
+ DEF_RST(R9A07G043_GPIO_SPARE_RESETN, 0x898, 2),
+ DEF_RST(R9A07G043_ADC_PRESETN, 0x8a8, 0),
+ DEF_RST(R9A07G043_ADC_ADRST_N, 0x8a8, 1),
+ DEF_RST(R9A07G043_TSU_PRESETN, 0x8ac, 0),
+#ifdef CONFIG_RISCV
+ DEF_RST(R9A07G043_NCEPLIC_ARESETN, 0x908, 0),
+#endif
+
+};
+
+static const unsigned int r9a07g043_crit_mod_clks[] __initconst = {
+#ifdef CONFIG_ARM64
+ MOD_CLK_BASE + R9A07G043_GIC600_GICCLK,
+ MOD_CLK_BASE + R9A07G043_IA55_CLK,
+#endif
+#ifdef CONFIG_RISCV
+ MOD_CLK_BASE + R9A07G043_IAX45_CLK,
+ MOD_CLK_BASE + R9A07G043_NCEPLIC_ACLK,
+#endif
+ MOD_CLK_BASE + R9A07G043_DMAC_ACLK,
+};
+
+static const unsigned int r9a07g043_crit_resets[] = {
+ R9A07G043_DMAC_ARESETN,
+ R9A07G043_DMAC_RST_ASYNC,
+};
+
+#ifdef CONFIG_ARM64
+static const unsigned int r9a07g043_no_pm_mod_clks[] = {
+ MOD_CLK_BASE + R9A07G043_CRU_SYSCLK,
+ MOD_CLK_BASE + R9A07G043_CRU_VCLK,
+};
+#endif
+
+const struct rzg2l_cpg_info r9a07g043_cpg_info = {
+ /* Core Clocks */
+ .core_clks = r9a07g043_core_clks,
+ .num_core_clks = ARRAY_SIZE(r9a07g043_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r9a07g043_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r9a07g043_crit_mod_clks),
+
+ /* Module Clocks */
+ .mod_clks = r9a07g043_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r9a07g043_mod_clks),
+#ifdef CONFIG_ARM64
+ .num_hw_mod_clks = R9A07G043_TSU_PCLK + 1,
+
+ /* No PM Module Clocks */
+ .no_pm_mod_clks = r9a07g043_no_pm_mod_clks,
+ .num_no_pm_mod_clks = ARRAY_SIZE(r9a07g043_no_pm_mod_clks),
+#endif
+#ifdef CONFIG_RISCV
+ .num_hw_mod_clks = R9A07G043_IAX45_PCLK + 1,
+#endif
+
+ /* Resets */
+ .resets = r9a07g043_resets,
+#ifdef CONFIG_ARM64
+ .num_resets = R9A07G043_TSU_PRESETN + 1, /* Last reset ID + 1 */
+#endif
+#ifdef CONFIG_RISCV
+ .num_resets = R9A07G043_IAX45_RESETN + 1, /* Last reset ID + 1 */
+#endif
+
+ /* Critical Resets */
+ .crit_resets = r9a07g043_crit_resets,
+ .num_crit_resets = ARRAY_SIZE(r9a07g043_crit_resets),
+
+ .has_clk_mon_regs = true,
+};
diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c
new file mode 100644
index 000000000..913cca6dd
--- /dev/null
+++ b/drivers/clk/renesas/r9a07g044-cpg.c
@@ -0,0 +1,566 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G2L CPG driver
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/r9a07g044-cpg.h>
+#include <dt-bindings/clock/r9a07g054-cpg.h>
+
+#include "rzg2l-cpg.h"
+
+/* Specific registers. */
+#define CPG_PL2SDHI_DSEL (0x218)
+
+/* Clock select configuration. */
+#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2)
+#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2)
+
+/* Clock status configuration. */
+#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1)
+#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1)
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A07G054_CLK_DRP_A,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_OSC_DIV1000,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL2_DIV2,
+ CLK_PLL2_DIV2_8,
+ CLK_PLL2_DIV2_10,
+ CLK_PLL3,
+ CLK_PLL3_400,
+ CLK_PLL3_533,
+ CLK_M2_DIV2,
+ CLK_PLL3_DIV2,
+ CLK_PLL3_DIV2_2,
+ CLK_PLL3_DIV2_4,
+ CLK_PLL3_DIV2_4_2,
+ CLK_SEL_PLL3_3,
+ CLK_DIV_PLL3_C,
+ CLK_PLL4,
+ CLK_PLL5,
+ CLK_PLL5_FOUTPOSTDIV,
+ CLK_PLL5_FOUT1PH0,
+ CLK_PLL5_FOUT3,
+ CLK_PLL5_250,
+ CLK_PLL6,
+ CLK_PLL6_250,
+ CLK_P1_DIV2,
+ CLK_PLL2_800,
+ CLK_PLL2_SDHI_533,
+ CLK_PLL2_SDHI_400,
+ CLK_PLL2_SDHI_266,
+ CLK_SD0_DIV4,
+ CLK_SD1_DIV4,
+ CLK_SEL_GPU2,
+ CLK_SEL_PLL5_4,
+ CLK_DSI_DIV,
+ CLK_PLL2_533,
+ CLK_PLL2_533_DIV2,
+ CLK_DIV_DSI_LPCLK,
+
+ /* Module Clocks */
+ MOD_CLK_BASE,
+};
+
+/* Divider tables */
+static const struct clk_div_table dtable_1_8[] = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {3, 8},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_1_32[] = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {3, 8},
+ {4, 32},
+ {0, 0},
+};
+
+#ifdef CONFIG_CLK_R9A07G054
+static const struct clk_div_table dtable_4_32[] = {
+ {3, 4},
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 8},
+ {8, 9},
+ {9, 10},
+ {10, 11},
+ {11, 12},
+ {12, 13},
+ {13, 14},
+ {14, 15},
+ {15, 16},
+ {16, 17},
+ {17, 18},
+ {18, 19},
+ {19, 20},
+ {20, 21},
+ {21, 22},
+ {22, 23},
+ {23, 24},
+ {24, 25},
+ {25, 26},
+ {26, 27},
+ {27, 28},
+ {28, 29},
+ {29, 30},
+ {30, 31},
+ {31, 32},
+ {0, 0},
+};
+#endif
+
+static const struct clk_div_table dtable_16_128[] = {
+ {0, 16},
+ {1, 32},
+ {2, 64},
+ {3, 128},
+ {0, 0},
+};
+
+/* Mux clock tables */
+static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
+static const char * const sel_pll5_4[] = { ".pll5_foutpostdiv", ".pll5_fout1ph0" };
+static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
+static const char * const sel_sdhi[] = { ".clk_533", ".clk_400", ".clk_266" };
+static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
+
+static const u32 mtable_sdhi[] = { 1, 2, 3 };
+
+static const struct {
+ struct cpg_core_clk common[56];
+#ifdef CONFIG_CLK_R9A07G054
+ struct cpg_core_clk drp[3];
+#endif
+} core_clks __initconst = {
+ .common = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_FIXED(".osc", R9A07G044_OSCCLK, CLK_EXTAL, 1, 1),
+ DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000),
+ DEF_SAMPLL(".pll1", CLK_PLL1, CLK_EXTAL, CPG_SAM_PLL_CONF(0)),
+ DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3),
+ DEF_FIXED(".pll2_533", CLK_PLL2_533, CLK_PLL2, 1, 3),
+ DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3),
+ DEF_FIXED(".pll3_400", CLK_PLL3_400, CLK_PLL3, 1, 4),
+ DEF_FIXED(".pll3_533", CLK_PLL3_533, CLK_PLL3, 1, 3),
+
+ DEF_FIXED(".pll5", CLK_PLL5, CLK_EXTAL, 125, 1),
+ DEF_FIXED(".pll5_fout3", CLK_PLL5_FOUT3, CLK_PLL5, 1, 6),
+
+ DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6),
+
+ DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2),
+ DEF_FIXED(".clk_800", CLK_PLL2_800, CLK_PLL2, 1, 2),
+ DEF_FIXED(".clk_533", CLK_PLL2_SDHI_533, CLK_PLL2, 1, 3),
+ DEF_FIXED(".clk_400", CLK_PLL2_SDHI_400, CLK_PLL2_800, 1, 2),
+ DEF_FIXED(".clk_266", CLK_PLL2_SDHI_266, CLK_PLL2_SDHI_533, 1, 2),
+
+ DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8),
+ DEF_FIXED(".pll2_div2_10", CLK_PLL2_DIV2_10, CLK_PLL2_DIV2, 1, 10),
+
+ DEF_FIXED(".pll2_533_div2", CLK_PLL2_533_DIV2, CLK_PLL2_533, 1, 2),
+
+ DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2),
+ DEF_FIXED(".pll3_div2_2", CLK_PLL3_DIV2_2, CLK_PLL3_DIV2, 1, 2),
+ DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4),
+ DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2),
+ DEF_MUX_RO(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3, sel_pll3_3),
+ DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3, DIVPL3C, dtable_1_32),
+
+ DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_FOUT3, 1, 2),
+ DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2),
+ DEF_MUX_RO(".sel_gpu2", CLK_SEL_GPU2, SEL_GPU2, sel_gpu2),
+ DEF_PLL5_FOUTPOSTDIV(".pll5_foutpostdiv", CLK_PLL5_FOUTPOSTDIV, CLK_EXTAL),
+ DEF_FIXED(".pll5_fout1ph0", CLK_PLL5_FOUT1PH0, CLK_PLL5_FOUTPOSTDIV, 1, 2),
+ DEF_PLL5_4_MUX(".sel_pll5_4", CLK_SEL_PLL5_4, SEL_PLL5_4, sel_pll5_4),
+ DEF_DIV(".div_dsi_lpclk", CLK_DIV_DSI_LPCLK, CLK_PLL2_533_DIV2,
+ DIVDSILPCLK, dtable_16_128),
+
+ /* Core output clk */
+ DEF_DIV("I", R9A07G044_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8),
+ DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A, dtable_1_32),
+ DEF_FIXED("P0_DIV2", R9A07G044_CLK_P0_DIV2, R9A07G044_CLK_P0, 1, 2),
+ DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV2_10, 1, 1),
+ DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV2_4, DIVPL3B, dtable_1_32),
+ DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G044_CLK_P1, 1, 2),
+ DEF_DIV("P2", R9A07G044_CLK_P2, CLK_PLL3_DIV2_4_2, DIVPL3A, dtable_1_32),
+ DEF_FIXED("M0", R9A07G044_CLK_M0, CLK_PLL3_DIV2_4, 1, 1),
+ DEF_FIXED("ZT", R9A07G044_CLK_ZT, CLK_PLL3_DIV2_4_2, 1, 1),
+ DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, sel_pll6_2),
+ DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
+ DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+ DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_sdhi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_sdhi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
+ DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8),
+ DEF_FIXED("M1", R9A07G044_CLK_M1, CLK_PLL5_FOUTPOSTDIV, 1, 1),
+ DEF_FIXED("M2", R9A07G044_CLK_M2, CLK_PLL3_533, 1, 2),
+ DEF_FIXED("M2_DIV2", CLK_M2_DIV2, R9A07G044_CLK_M2, 1, 2),
+ DEF_DSI_DIV("DSI_DIV", CLK_DSI_DIV, CLK_SEL_PLL5_4, CLK_SET_RATE_PARENT),
+ DEF_FIXED("M3", R9A07G044_CLK_M3, CLK_DSI_DIV, 1, 1),
+ DEF_FIXED("M4", R9A07G044_CLK_M4, CLK_DIV_DSI_LPCLK, 1, 1),
+ },
+#ifdef CONFIG_CLK_R9A07G054
+ .drp = {
+ DEF_FIXED("DRP_M", R9A07G054_CLK_DRP_M, CLK_PLL3, 1, 5),
+ DEF_FIXED("DRP_D", R9A07G054_CLK_DRP_D, CLK_PLL3, 1, 2),
+ DEF_DIV("DRP_A", R9A07G054_CLK_DRP_A, CLK_PLL3, DIVPL3E, dtable_4_32),
+ },
+#endif
+};
+
+static const struct {
+ struct rzg2l_mod_clk common[79];
+#ifdef CONFIG_CLK_R9A07G054
+ struct rzg2l_mod_clk drp[5];
+#endif
+} mod_clks = {
+ .common = {
+ DEF_MOD("gic", R9A07G044_GIC600_GICCLK, R9A07G044_CLK_P1,
+ 0x514, 0, MSTOP(BUS_REG1, BIT(7))),
+ DEF_MOD("ia55_pclk", R9A07G044_IA55_PCLK, R9A07G044_CLK_P2,
+ 0x518, 0, MSTOP(BUS_PERI_CPU, BIT(13))),
+ DEF_MOD("ia55_clk", R9A07G044_IA55_CLK, R9A07G044_CLK_P1,
+ 0x518, 1, MSTOP(BUS_PERI_CPU, BIT(13))),
+ DEF_MOD("dmac_aclk", R9A07G044_DMAC_ACLK, R9A07G044_CLK_P1,
+ 0x52c, 0, MSTOP(BUS_REG1, BIT(2))),
+ DEF_MOD("dmac_pclk", R9A07G044_DMAC_PCLK, CLK_P1_DIV2,
+ 0x52c, 1, MSTOP(BUS_REG1, BIT(3))),
+ DEF_MOD("ostm0_pclk", R9A07G044_OSTM0_PCLK, R9A07G044_CLK_P0,
+ 0x534, 0, MSTOP(BUS_REG0, BIT(4))),
+ DEF_MOD("ostm1_pclk", R9A07G044_OSTM1_PCLK, R9A07G044_CLK_P0,
+ 0x534, 1, MSTOP(BUS_REG0, BIT(5))),
+ DEF_MOD("ostm2_pclk", R9A07G044_OSTM2_PCLK, R9A07G044_CLK_P0,
+ 0x534, 2, MSTOP(BUS_REG0, BIT(6))),
+ DEF_MOD("mtu_x_mck", R9A07G044_MTU_X_MCK_MTU3, R9A07G044_CLK_P0,
+ 0x538, 0, MSTOP(BUS_MCPU1, BIT(2))),
+ DEF_MOD("gpt_pclk", R9A07G044_GPT_PCLK, R9A07G044_CLK_P0,
+ 0x540, 0, MSTOP(BUS_MCPU1, BIT(4))),
+ DEF_MOD("poeg_a_clkp", R9A07G044_POEG_A_CLKP, R9A07G044_CLK_P0,
+ 0x544, 0, MSTOP(BUS_MCPU1, BIT(5))),
+ DEF_MOD("poeg_b_clkp", R9A07G044_POEG_B_CLKP, R9A07G044_CLK_P0,
+ 0x544, 1, MSTOP(BUS_MCPU1, BIT(6))),
+ DEF_MOD("poeg_c_clkp", R9A07G044_POEG_C_CLKP, R9A07G044_CLK_P0,
+ 0x544, 2, MSTOP(BUS_MCPU1, BIT(7))),
+ DEF_MOD("poeg_d_clkp", R9A07G044_POEG_D_CLKP, R9A07G044_CLK_P0,
+ 0x544, 3, MSTOP(BUS_MCPU1, BIT(8))),
+ DEF_MOD("wdt0_pclk", R9A07G044_WDT0_PCLK, R9A07G044_CLK_P0,
+ 0x548, 0, MSTOP(BUS_REG0, BIT(2))),
+ DEF_MOD("wdt0_clk", R9A07G044_WDT0_CLK, R9A07G044_OSCCLK,
+ 0x548, 1, MSTOP(BUS_REG0, BIT(2))),
+ DEF_MOD("wdt1_pclk", R9A07G044_WDT1_PCLK, R9A07G044_CLK_P0,
+ 0x548, 2, MSTOP(BUS_REG0, BIT(3))),
+ DEF_MOD("wdt1_clk", R9A07G044_WDT1_CLK, R9A07G044_OSCCLK,
+ 0x548, 3, MSTOP(BUS_REG0, BIT(3))),
+ DEF_MOD("spi_clk2", R9A07G044_SPI_CLK2, R9A07G044_CLK_SPI1,
+ 0x550, 0, MSTOP(BUS_MCPU1, BIT(1))),
+ DEF_MOD("spi_clk", R9A07G044_SPI_CLK, R9A07G044_CLK_SPI0,
+ 0x550, 1, MSTOP(BUS_MCPU1, BIT(1))),
+ DEF_MOD("sdhi0_imclk", R9A07G044_SDHI0_IMCLK, CLK_SD0_DIV4,
+ 0x554, 0, MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi0_imclk2", R9A07G044_SDHI0_IMCLK2, CLK_SD0_DIV4,
+ 0x554, 1, MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi0_clk_hs", R9A07G044_SDHI0_CLK_HS, R9A07G044_CLK_SD0,
+ 0x554, 2, MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi0_aclk", R9A07G044_SDHI0_ACLK, R9A07G044_CLK_P1,
+ 0x554, 3, MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi1_imclk", R9A07G044_SDHI1_IMCLK, CLK_SD1_DIV4,
+ 0x554, 4, MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("sdhi1_imclk2", R9A07G044_SDHI1_IMCLK2, CLK_SD1_DIV4,
+ 0x554, 5, MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("sdhi1_clk_hs", R9A07G044_SDHI1_CLK_HS, R9A07G044_CLK_SD1,
+ 0x554, 6, MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("sdhi1_aclk", R9A07G044_SDHI1_ACLK, R9A07G044_CLK_P1,
+ 0x554, 7, MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("gpu_clk", R9A07G044_GPU_CLK, R9A07G044_CLK_G,
+ 0x558, 0, MSTOP(BUS_REG1, BIT(4))),
+ DEF_MOD("gpu_axi_clk", R9A07G044_GPU_AXI_CLK, R9A07G044_CLK_P1,
+ 0x558, 1, 0),
+ DEF_MOD("gpu_ace_clk", R9A07G044_GPU_ACE_CLK, R9A07G044_CLK_P1,
+ 0x558, 2, 0),
+ DEF_MOD("cru_sysclk", R9A07G044_CRU_SYSCLK, CLK_M2_DIV2,
+ 0x564, 0, MSTOP(BUS_PERI_VIDEO, BIT(3))),
+ DEF_MOD("cru_vclk", R9A07G044_CRU_VCLK, R9A07G044_CLK_M2,
+ 0x564, 1, MSTOP(BUS_PERI_VIDEO, BIT(3))),
+ DEF_MOD("cru_pclk", R9A07G044_CRU_PCLK, R9A07G044_CLK_ZT,
+ 0x564, 2, MSTOP(BUS_PERI_VIDEO, BIT(3))),
+ DEF_MOD("cru_aclk", R9A07G044_CRU_ACLK, R9A07G044_CLK_M0,
+ 0x564, 3, MSTOP(BUS_PERI_VIDEO, BIT(3))),
+ DEF_MOD("dsi_pll_clk", R9A07G044_MIPI_DSI_PLLCLK, R9A07G044_CLK_M1,
+ 0x568, 0, MSTOP(BUS_PERI_VIDEO, GENMASK(6, 5))),
+ DEF_MOD("dsi_sys_clk", R9A07G044_MIPI_DSI_SYSCLK, CLK_M2_DIV2,
+ 0x568, 1, MSTOP(BUS_PERI_VIDEO, GENMASK(6, 5))),
+ DEF_MOD("dsi_aclk", R9A07G044_MIPI_DSI_ACLK, R9A07G044_CLK_P1,
+ 0x568, 2, MSTOP(BUS_PERI_VIDEO, GENMASK(6, 5))),
+ DEF_MOD("dsi_pclk", R9A07G044_MIPI_DSI_PCLK, R9A07G044_CLK_P2,
+ 0x568, 3, MSTOP(BUS_PERI_VIDEO, GENMASK(6, 5))),
+ DEF_MOD("dsi_vclk", R9A07G044_MIPI_DSI_VCLK, R9A07G044_CLK_M3,
+ 0x568, 4, MSTOP(BUS_PERI_VIDEO, GENMASK(6, 5))),
+ DEF_MOD("dsi_lpclk", R9A07G044_MIPI_DSI_LPCLK, R9A07G044_CLK_M4,
+ 0x568, 5, MSTOP(BUS_PERI_VIDEO, GENMASK(6, 5))),
+ DEF_COUPLED("lcdc_a", R9A07G044_LCDC_CLK_A, R9A07G044_CLK_M0,
+ 0x56c, 0, MSTOP(BUS_PERI_VIDEO, GENMASK(8, 7))),
+ DEF_COUPLED("lcdc_p", R9A07G044_LCDC_CLK_P, R9A07G044_CLK_ZT,
+ 0x56c, 0, MSTOP(BUS_PERI_VIDEO, GENMASK(8, 7))),
+ DEF_MOD("lcdc_clk_d", R9A07G044_LCDC_CLK_D, R9A07G044_CLK_M3,
+ 0x56c, 1, MSTOP(BUS_PERI_VIDEO, BIT(9))),
+ DEF_MOD("ssi0_pclk", R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 0, MSTOP(BUS_MCPU1, BIT(10))),
+ DEF_MOD("ssi0_sfr", R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 1, MSTOP(BUS_MCPU1, BIT(10))),
+ DEF_MOD("ssi1_pclk", R9A07G044_SSI1_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 2, MSTOP(BUS_MCPU1, BIT(11))),
+ DEF_MOD("ssi1_sfr", R9A07G044_SSI1_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 3, MSTOP(BUS_MCPU1, BIT(11))),
+ DEF_MOD("ssi2_pclk", R9A07G044_SSI2_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 4, MSTOP(BUS_MCPU1, BIT(12))),
+ DEF_MOD("ssi2_sfr", R9A07G044_SSI2_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 5, MSTOP(BUS_MCPU1, BIT(12))),
+ DEF_MOD("ssi3_pclk", R9A07G044_SSI3_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 6, MSTOP(BUS_MCPU1, BIT(13))),
+ DEF_MOD("ssi3_sfr", R9A07G044_SSI3_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 7, MSTOP(BUS_MCPU1, BIT(13))),
+ DEF_MOD("usb0_host", R9A07G044_USB_U2H0_HCLK, R9A07G044_CLK_P1,
+ 0x578, 0, MSTOP(BUS_PERI_COM, BIT(5))),
+ DEF_MOD("usb1_host", R9A07G044_USB_U2H1_HCLK, R9A07G044_CLK_P1,
+ 0x578, 1, MSTOP(BUS_PERI_COM, BIT(7))),
+ DEF_MOD("usb0_func", R9A07G044_USB_U2P_EXR_CPUCLK, R9A07G044_CLK_P1,
+ 0x578, 2, MSTOP(BUS_PERI_COM, BIT(6))),
+ DEF_MOD("usb_pclk", R9A07G044_USB_PCLK, R9A07G044_CLK_P1,
+ 0x578, 3, MSTOP(BUS_PERI_COM, BIT(4))),
+ DEF_COUPLED("eth0_axi", R9A07G044_ETH0_CLK_AXI, R9A07G044_CLK_M0,
+ 0x57c, 0, MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth0_chi", R9A07G044_ETH0_CLK_CHI, R9A07G044_CLK_ZT,
+ 0x57c, 0, MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth1_axi", R9A07G044_ETH1_CLK_AXI, R9A07G044_CLK_M0,
+ 0x57c, 1, MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_COUPLED("eth1_chi", R9A07G044_ETH1_CLK_CHI, R9A07G044_CLK_ZT,
+ 0x57c, 1, MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_MOD("i2c0", R9A07G044_I2C0_PCLK, R9A07G044_CLK_P0,
+ 0x580, 0, MSTOP(BUS_MCPU2, BIT(10))),
+ DEF_MOD("i2c1", R9A07G044_I2C1_PCLK, R9A07G044_CLK_P0,
+ 0x580, 1, MSTOP(BUS_MCPU2, BIT(11))),
+ DEF_MOD("i2c2", R9A07G044_I2C2_PCLK, R9A07G044_CLK_P0,
+ 0x580, 2, MSTOP(BUS_MCPU2, BIT(12))),
+ DEF_MOD("i2c3", R9A07G044_I2C3_PCLK, R9A07G044_CLK_P0,
+ 0x580, 3, MSTOP(BUS_MCPU2, BIT(13))),
+ DEF_MOD("scif0", R9A07G044_SCIF0_CLK_PCK, R9A07G044_CLK_P0,
+ 0x584, 0, MSTOP(BUS_MCPU2, BIT(1))),
+ DEF_MOD("scif1", R9A07G044_SCIF1_CLK_PCK, R9A07G044_CLK_P0,
+ 0x584, 1, MSTOP(BUS_MCPU2, BIT(2))),
+ DEF_MOD("scif2", R9A07G044_SCIF2_CLK_PCK, R9A07G044_CLK_P0,
+ 0x584, 2, MSTOP(BUS_MCPU2, BIT(3))),
+ DEF_MOD("scif3", R9A07G044_SCIF3_CLK_PCK, R9A07G044_CLK_P0,
+ 0x584, 3, MSTOP(BUS_MCPU2, BIT(4))),
+ DEF_MOD("scif4", R9A07G044_SCIF4_CLK_PCK, R9A07G044_CLK_P0,
+ 0x584, 4, MSTOP(BUS_MCPU2, BIT(5))),
+ DEF_MOD("sci0", R9A07G044_SCI0_CLKP, R9A07G044_CLK_P0,
+ 0x588, 0, MSTOP(BUS_MCPU2, BIT(7))),
+ DEF_MOD("sci1", R9A07G044_SCI1_CLKP, R9A07G044_CLK_P0,
+ 0x588, 1, MSTOP(BUS_MCPU2, BIT(8))),
+ DEF_MOD("rspi0", R9A07G044_RSPI0_CLKB, R9A07G044_CLK_P0,
+ 0x590, 0, MSTOP(BUS_MCPU1, BIT(14))),
+ DEF_MOD("rspi1", R9A07G044_RSPI1_CLKB, R9A07G044_CLK_P0,
+ 0x590, 1, MSTOP(BUS_MCPU1, BIT(15))),
+ DEF_MOD("rspi2", R9A07G044_RSPI2_CLKB, R9A07G044_CLK_P0,
+ 0x590, 2, MSTOP(BUS_MCPU2, BIT(0))),
+ DEF_MOD("canfd", R9A07G044_CANFD_PCLK, R9A07G044_CLK_P0,
+ 0x594, 0, MSTOP(BUS_MCPU2, BIT(9))),
+ DEF_MOD("gpio", R9A07G044_GPIO_HCLK, R9A07G044_OSCCLK,
+ 0x598, 0, MSTOP(BUS_PERI_CPU, BIT(6))),
+ DEF_MOD("adc_adclk", R9A07G044_ADC_ADCLK, R9A07G044_CLK_TSU,
+ 0x5a8, 0, MSTOP(BUS_MCPU2, BIT(14))),
+ DEF_MOD("adc_pclk", R9A07G044_ADC_PCLK, R9A07G044_CLK_P0,
+ 0x5a8, 1, MSTOP(BUS_MCPU2, BIT(14))),
+ DEF_MOD("tsu_pclk", R9A07G044_TSU_PCLK, R9A07G044_CLK_TSU,
+ 0x5ac, 0, MSTOP(BUS_MCPU2, BIT(15))),
+ },
+#ifdef CONFIG_CLK_R9A07G054
+ .drp = {
+ DEF_MOD("stpai_initclk", R9A07G054_STPAI_INITCLK, R9A07G044_OSCCLK,
+ 0x5e8, 0, 0),
+ DEF_MOD("stpai_aclk", R9A07G054_STPAI_ACLK, R9A07G044_CLK_P1,
+ 0x5e8, 1, 0),
+ DEF_MOD("stpai_mclk", R9A07G054_STPAI_MCLK, R9A07G054_CLK_DRP_M,
+ 0x5e8, 2, 0),
+ DEF_MOD("stpai_dclkin", R9A07G054_STPAI_DCLKIN, R9A07G054_CLK_DRP_D,
+ 0x5e8, 3, 0),
+ DEF_MOD("stpai_aclk_drp", R9A07G054_STPAI_ACLK_DRP, R9A07G054_CLK_DRP_A,
+ 0x5e8, 4, 0),
+ },
+#endif
+};
+
+static const struct rzg2l_reset r9a07g044_resets[] = {
+ DEF_RST(R9A07G044_GIC600_GICRESET_N, 0x814, 0),
+ DEF_RST(R9A07G044_GIC600_DBG_GICRESET_N, 0x814, 1),
+ DEF_RST(R9A07G044_IA55_RESETN, 0x818, 0),
+ DEF_RST(R9A07G044_DMAC_ARESETN, 0x82c, 0),
+ DEF_RST(R9A07G044_DMAC_RST_ASYNC, 0x82c, 1),
+ DEF_RST(R9A07G044_OSTM0_PRESETZ, 0x834, 0),
+ DEF_RST(R9A07G044_OSTM1_PRESETZ, 0x834, 1),
+ DEF_RST(R9A07G044_OSTM2_PRESETZ, 0x834, 2),
+ DEF_RST(R9A07G044_MTU_X_PRESET_MTU3, 0x838, 0),
+ DEF_RST(R9A07G044_GPT_RST_C, 0x840, 0),
+ DEF_RST(R9A07G044_POEG_A_RST, 0x844, 0),
+ DEF_RST(R9A07G044_POEG_B_RST, 0x844, 1),
+ DEF_RST(R9A07G044_POEG_C_RST, 0x844, 2),
+ DEF_RST(R9A07G044_POEG_D_RST, 0x844, 3),
+ DEF_RST(R9A07G044_WDT0_PRESETN, 0x848, 0),
+ DEF_RST(R9A07G044_WDT1_PRESETN, 0x848, 1),
+ DEF_RST(R9A07G044_SPI_RST, 0x850, 0),
+ DEF_RST(R9A07G044_SDHI0_IXRST, 0x854, 0),
+ DEF_RST(R9A07G044_SDHI1_IXRST, 0x854, 1),
+ DEF_RST(R9A07G044_GPU_RESETN, 0x858, 0),
+ DEF_RST(R9A07G044_GPU_AXI_RESETN, 0x858, 1),
+ DEF_RST(R9A07G044_GPU_ACE_RESETN, 0x858, 2),
+ DEF_RST(R9A07G044_CRU_CMN_RSTB, 0x864, 0),
+ DEF_RST(R9A07G044_CRU_PRESETN, 0x864, 1),
+ DEF_RST(R9A07G044_CRU_ARESETN, 0x864, 2),
+ DEF_RST(R9A07G044_MIPI_DSI_CMN_RSTB, 0x868, 0),
+ DEF_RST(R9A07G044_MIPI_DSI_ARESET_N, 0x868, 1),
+ DEF_RST(R9A07G044_MIPI_DSI_PRESET_N, 0x868, 2),
+ DEF_RST(R9A07G044_LCDC_RESET_N, 0x86c, 0),
+ DEF_RST(R9A07G044_SSI0_RST_M2_REG, 0x870, 0),
+ DEF_RST(R9A07G044_SSI1_RST_M2_REG, 0x870, 1),
+ DEF_RST(R9A07G044_SSI2_RST_M2_REG, 0x870, 2),
+ DEF_RST(R9A07G044_SSI3_RST_M2_REG, 0x870, 3),
+ DEF_RST(R9A07G044_USB_U2H0_HRESETN, 0x878, 0),
+ DEF_RST(R9A07G044_USB_U2H1_HRESETN, 0x878, 1),
+ DEF_RST(R9A07G044_USB_U2P_EXL_SYSRST, 0x878, 2),
+ DEF_RST(R9A07G044_USB_PRESETN, 0x878, 3),
+ DEF_RST(R9A07G044_ETH0_RST_HW_N, 0x87c, 0),
+ DEF_RST(R9A07G044_ETH1_RST_HW_N, 0x87c, 1),
+ DEF_RST(R9A07G044_I2C0_MRST, 0x880, 0),
+ DEF_RST(R9A07G044_I2C1_MRST, 0x880, 1),
+ DEF_RST(R9A07G044_I2C2_MRST, 0x880, 2),
+ DEF_RST(R9A07G044_I2C3_MRST, 0x880, 3),
+ DEF_RST(R9A07G044_SCIF0_RST_SYSTEM_N, 0x884, 0),
+ DEF_RST(R9A07G044_SCIF1_RST_SYSTEM_N, 0x884, 1),
+ DEF_RST(R9A07G044_SCIF2_RST_SYSTEM_N, 0x884, 2),
+ DEF_RST(R9A07G044_SCIF3_RST_SYSTEM_N, 0x884, 3),
+ DEF_RST(R9A07G044_SCIF4_RST_SYSTEM_N, 0x884, 4),
+ DEF_RST(R9A07G044_SCI0_RST, 0x888, 0),
+ DEF_RST(R9A07G044_SCI1_RST, 0x888, 1),
+ DEF_RST(R9A07G044_RSPI0_RST, 0x890, 0),
+ DEF_RST(R9A07G044_RSPI1_RST, 0x890, 1),
+ DEF_RST(R9A07G044_RSPI2_RST, 0x890, 2),
+ DEF_RST(R9A07G044_CANFD_RSTP_N, 0x894, 0),
+ DEF_RST(R9A07G044_CANFD_RSTC_N, 0x894, 1),
+ DEF_RST(R9A07G044_GPIO_RSTN, 0x898, 0),
+ DEF_RST(R9A07G044_GPIO_PORT_RESETN, 0x898, 1),
+ DEF_RST(R9A07G044_GPIO_SPARE_RESETN, 0x898, 2),
+ DEF_RST(R9A07G044_ADC_PRESETN, 0x8a8, 0),
+ DEF_RST(R9A07G044_ADC_ADRST_N, 0x8a8, 1),
+ DEF_RST(R9A07G044_TSU_PRESETN, 0x8ac, 0),
+#ifdef CONFIG_CLK_R9A07G054
+ DEF_RST(R9A07G054_STPAI_ARESETN, 0x8e8, 0),
+#endif
+};
+
+static const unsigned int r9a07g044_crit_mod_clks[] __initconst = {
+ MOD_CLK_BASE + R9A07G044_GIC600_GICCLK,
+ MOD_CLK_BASE + R9A07G044_IA55_CLK,
+ MOD_CLK_BASE + R9A07G044_DMAC_ACLK,
+};
+
+static const unsigned int r9a07g044_crit_resets[] = {
+ R9A07G044_DMAC_ARESETN,
+ R9A07G044_DMAC_RST_ASYNC,
+};
+
+static const unsigned int r9a07g044_no_pm_mod_clks[] = {
+ MOD_CLK_BASE + R9A07G044_CRU_SYSCLK,
+ MOD_CLK_BASE + R9A07G044_CRU_VCLK,
+};
+
+#ifdef CONFIG_CLK_R9A07G044
+const struct rzg2l_cpg_info r9a07g044_cpg_info = {
+ /* Core Clocks */
+ .core_clks = core_clks.common,
+ .num_core_clks = ARRAY_SIZE(core_clks.common),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r9a07g044_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r9a07g044_crit_mod_clks),
+
+ /* Module Clocks */
+ .mod_clks = mod_clks.common,
+ .num_mod_clks = ARRAY_SIZE(mod_clks.common),
+ .num_hw_mod_clks = R9A07G044_TSU_PCLK + 1,
+
+ /* No PM Module Clocks */
+ .no_pm_mod_clks = r9a07g044_no_pm_mod_clks,
+ .num_no_pm_mod_clks = ARRAY_SIZE(r9a07g044_no_pm_mod_clks),
+
+ /* Resets */
+ .resets = r9a07g044_resets,
+ .num_resets = R9A07G044_TSU_PRESETN + 1, /* Last reset ID + 1 */
+
+ /* Critical Resets */
+ .crit_resets = r9a07g044_crit_resets,
+ .num_crit_resets = ARRAY_SIZE(r9a07g044_crit_resets),
+
+ .has_clk_mon_regs = true,
+};
+#endif
+
+#ifdef CONFIG_CLK_R9A07G054
+const struct rzg2l_cpg_info r9a07g054_cpg_info = {
+ /* Core Clocks */
+ .core_clks = core_clks.common,
+ .num_core_clks = ARRAY_SIZE(core_clks.common) + ARRAY_SIZE(core_clks.drp),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r9a07g044_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r9a07g044_crit_mod_clks),
+
+ /* Module Clocks */
+ .mod_clks = mod_clks.common,
+ .num_mod_clks = ARRAY_SIZE(mod_clks.common) + ARRAY_SIZE(mod_clks.drp),
+ .num_hw_mod_clks = R9A07G054_STPAI_ACLK_DRP + 1,
+
+ /* No PM Module Clocks */
+ .no_pm_mod_clks = r9a07g044_no_pm_mod_clks,
+ .num_no_pm_mod_clks = ARRAY_SIZE(r9a07g044_no_pm_mod_clks),
+
+ /* Resets */
+ .resets = r9a07g044_resets,
+ .num_resets = R9A07G054_STPAI_ARESETN + 1, /* Last reset ID + 1 */
+
+ /* Critical Resets */
+ .crit_resets = r9a07g044_crit_resets,
+ .num_crit_resets = ARRAY_SIZE(r9a07g044_crit_resets),
+
+ .has_clk_mon_regs = true,
+};
+#endif
diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c
new file mode 100644
index 000000000..624fc5e6f
--- /dev/null
+++ b/drivers/clk/renesas/r9a08g045-cpg.c
@@ -0,0 +1,391 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G3S CPG driver
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/r9a08g045-cpg.h>
+
+#include "rzg2l-cpg.h"
+
+/* RZ/G3S Specific registers. */
+#define G3S_CPG_PL2_DDIV (0x204)
+#define G3S_CPG_SDHI_DDIV (0x218)
+#define G3S_CPG_PLL_DSEL (0x240)
+#define G3S_CPG_SDHI_DSEL (0x244)
+#define G3S_CLKDIVSTATUS (0x280)
+#define G3S_CLKSELSTATUS (0x284)
+
+/* RZ/G3S Specific division configuration. */
+#define G3S_DIVPL2B DDIV_PACK(G3S_CPG_PL2_DDIV, 4, 3)
+#define G3S_DIV_SDHI0 DDIV_PACK(G3S_CPG_SDHI_DDIV, 0, 1)
+#define G3S_DIV_SDHI1 DDIV_PACK(G3S_CPG_SDHI_DDIV, 4, 1)
+#define G3S_DIV_SDHI2 DDIV_PACK(G3S_CPG_SDHI_DDIV, 8, 1)
+
+/* RZ/G3S Clock status configuration. */
+#define G3S_DIVPL1A_STS DDIV_PACK(G3S_CLKDIVSTATUS, 0, 1)
+#define G3S_DIVPL2B_STS DDIV_PACK(G3S_CLKDIVSTATUS, 5, 1)
+#define G3S_DIVPL3A_STS DDIV_PACK(G3S_CLKDIVSTATUS, 8, 1)
+#define G3S_DIVPL3B_STS DDIV_PACK(G3S_CLKDIVSTATUS, 9, 1)
+#define G3S_DIVPL3C_STS DDIV_PACK(G3S_CLKDIVSTATUS, 10, 1)
+#define G3S_DIV_SDHI0_STS DDIV_PACK(G3S_CLKDIVSTATUS, 24, 1)
+#define G3S_DIV_SDHI1_STS DDIV_PACK(G3S_CLKDIVSTATUS, 25, 1)
+#define G3S_DIV_SDHI2_STS DDIV_PACK(G3S_CLKDIVSTATUS, 26, 1)
+
+#define G3S_SEL_PLL4_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 6, 1)
+#define G3S_SEL_SDHI0_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 16, 1)
+#define G3S_SEL_SDHI1_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 17, 1)
+#define G3S_SEL_SDHI2_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 18, 1)
+
+/* RZ/G3S Specific clocks select. */
+#define G3S_SEL_PLL4 SEL_PLL_PACK(G3S_CPG_PLL_DSEL, 6, 1)
+#define G3S_SEL_SDHI0 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 0, 2)
+#define G3S_SEL_SDHI1 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 4, 2)
+#define G3S_SEL_SDHI2 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 8, 2)
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A08G045_SWD,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_OSC_DIV1000,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL2_DIV2,
+ CLK_PLL2_DIV2_8,
+ CLK_PLL2_DIV6,
+ CLK_PLL3,
+ CLK_PLL3_DIV2,
+ CLK_PLL3_DIV2_4,
+ CLK_PLL3_DIV2_8,
+ CLK_PLL3_DIV6,
+ CLK_PLL4,
+ CLK_PLL6,
+ CLK_PLL6_DIV2,
+ CLK_SEL_SDHI0,
+ CLK_SEL_SDHI1,
+ CLK_SEL_SDHI2,
+ CLK_SEL_PLL4,
+ CLK_P1_DIV2,
+ CLK_P3_DIV2,
+ CLK_SD0_DIV4,
+ CLK_SD1_DIV4,
+ CLK_SD2_DIV4,
+
+ /* Module Clocks */
+ MOD_CLK_BASE,
+};
+
+/* Divider tables */
+static const struct clk_div_table dtable_1_2[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 0, 0 },
+};
+
+static const struct clk_div_table dtable_1_8[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 2, 4 },
+ { 3, 8 },
+ { 0, 0 },
+};
+
+static const struct clk_div_table dtable_1_32[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 2, 4 },
+ { 3, 8 },
+ { 4, 32 },
+ { 0, 0 },
+};
+
+/* Mux clock names tables. */
+static const char * const sel_sdhi[] = { ".pll2_div2", ".pll6", ".pll2_div6" };
+static const char * const sel_pll4[] = { ".osc_div1000", ".pll4" };
+
+/* Mux clock indices tables. */
+static const u32 mtable_sd[] = { 0, 2, 3 };
+static const u32 mtable_pll4[] = { 0, 1 };
+
+static const struct cpg_core_clk r9a08g045_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000),
+ DEF_G3S_PLL(".pll1", CLK_PLL1, CLK_EXTAL, CPG_PLL_CONF(0, 0x100),
+ 1100000000UL),
+ DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3),
+ DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3),
+ DEF_FIXED(".pll4", CLK_PLL4, CLK_EXTAL, 100, 3),
+ DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6),
+ DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2),
+ DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8),
+ DEF_FIXED(".pll2_div6", CLK_PLL2_DIV6, CLK_PLL2, 1, 6),
+ DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2),
+ DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4),
+ DEF_FIXED(".pll3_div2_8", CLK_PLL3_DIV2_8, CLK_PLL3_DIV2, 1, 8),
+ DEF_FIXED(".pll3_div6", CLK_PLL3_DIV6, CLK_PLL3, 1, 6),
+ DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 1, 2),
+ DEF_SD_MUX(".sel_sd0", CLK_SEL_SDHI0, G3S_SEL_SDHI0, G3S_SEL_SDHI0_STS, sel_sdhi,
+ mtable_sd, 0, NULL),
+ DEF_SD_MUX(".sel_sd1", CLK_SEL_SDHI1, G3S_SEL_SDHI1, G3S_SEL_SDHI1_STS, sel_sdhi,
+ mtable_sd, 0, NULL),
+ DEF_SD_MUX(".sel_sd2", CLK_SEL_SDHI2, G3S_SEL_SDHI2, G3S_SEL_SDHI2_STS, sel_sdhi,
+ mtable_sd, 0, NULL),
+ DEF_SD_MUX(".sel_pll4", CLK_SEL_PLL4, G3S_SEL_PLL4, G3S_SEL_PLL4_STS, sel_pll4,
+ mtable_pll4, CLK_SET_PARENT_GATE, NULL),
+
+ /* Core output clk */
+ DEF_G3S_DIV("I", R9A08G045_CLK_I, CLK_PLL1, DIVPL1A, G3S_DIVPL1A_STS, dtable_1_8,
+ 0, 0, 0, NULL),
+ DEF_G3S_DIV("P0", R9A08G045_CLK_P0, CLK_PLL2_DIV2_8, G3S_DIVPL2B, G3S_DIVPL2B_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_G3S_DIV("SD0", R9A08G045_CLK_SD0, CLK_SEL_SDHI0, G3S_DIV_SDHI0, G3S_DIV_SDHI0_STS,
+ dtable_1_2, 800000000UL, 500000000UL, CLK_SET_RATE_PARENT,
+ rzg3s_cpg_div_clk_notifier),
+ DEF_G3S_DIV("SD1", R9A08G045_CLK_SD1, CLK_SEL_SDHI1, G3S_DIV_SDHI1, G3S_DIV_SDHI1_STS,
+ dtable_1_2, 800000000UL, 500000000UL, CLK_SET_RATE_PARENT,
+ rzg3s_cpg_div_clk_notifier),
+ DEF_G3S_DIV("SD2", R9A08G045_CLK_SD2, CLK_SEL_SDHI2, G3S_DIV_SDHI2, G3S_DIV_SDHI2_STS,
+ dtable_1_2, 800000000UL, 500000000UL, CLK_SET_RATE_PARENT,
+ rzg3s_cpg_div_clk_notifier),
+ DEF_FIXED(".sd0_div4", CLK_SD0_DIV4, R9A08G045_CLK_SD0, 1, 4),
+ DEF_FIXED(".sd1_div4", CLK_SD1_DIV4, R9A08G045_CLK_SD1, 1, 4),
+ DEF_FIXED(".sd2_div4", CLK_SD2_DIV4, R9A08G045_CLK_SD2, 1, 4),
+ DEF_FIXED("M0", R9A08G045_CLK_M0, CLK_PLL3_DIV2_4, 1, 1),
+ DEF_G3S_DIV("P1", R9A08G045_CLK_P1, CLK_PLL3_DIV2_4, DIVPL3A, G3S_DIVPL3A_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A08G045_CLK_P1, 1, 2),
+ DEF_G3S_DIV("P2", R9A08G045_CLK_P2, CLK_PLL3_DIV2_8, DIVPL3B, G3S_DIVPL3B_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_G3S_DIV("P3", R9A08G045_CLK_P3, CLK_PLL3_DIV2_4, DIVPL3C, G3S_DIVPL3C_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_FIXED("P3_DIV2", CLK_P3_DIV2, R9A08G045_CLK_P3, 1, 2),
+ DEF_FIXED("P5", R9A08G045_CLK_P5, CLK_PLL2_DIV2, 1, 4),
+ DEF_FIXED("ZT", R9A08G045_CLK_ZT, CLK_PLL3_DIV2_8, 1, 1),
+ DEF_FIXED("S0", R9A08G045_CLK_S0, CLK_SEL_PLL4, 1, 2),
+ DEF_FIXED("OSC", R9A08G045_OSCCLK, CLK_EXTAL, 1, 1),
+ DEF_FIXED("OSC2", R9A08G045_OSCCLK2, CLK_EXTAL, 1, 3),
+ DEF_FIXED("HP", R9A08G045_CLK_HP, CLK_PLL6, 1, 2),
+ DEF_FIXED("TSU", R9A08G045_CLK_TSU, CLK_PLL2_DIV2, 1, 8),
+};
+
+static const struct rzg2l_mod_clk r9a08g045_mod_clks[] = {
+ DEF_MOD("gic_gicclk", R9A08G045_GIC600_GICCLK, R9A08G045_CLK_P1, 0x514, 0,
+ MSTOP(BUS_ACPU, BIT(3))),
+ DEF_MOD("ia55_pclk", R9A08G045_IA55_PCLK, R9A08G045_CLK_P2, 0x518, 0,
+ MSTOP(BUS_PERI_CPU, BIT(13))),
+ DEF_MOD("ia55_clk", R9A08G045_IA55_CLK, R9A08G045_CLK_P1, 0x518, 1,
+ MSTOP(BUS_PERI_CPU, BIT(13))),
+ DEF_MOD("dmac_aclk", R9A08G045_DMAC_ACLK, R9A08G045_CLK_P3, 0x52c, 0,
+ MSTOP(BUS_REG1, BIT(2))),
+ DEF_MOD("dmac_pclk", R9A08G045_DMAC_PCLK, CLK_P3_DIV2, 0x52c, 1,
+ MSTOP(BUS_REG1, BIT(3))),
+ DEF_MOD("wdt0_pclk", R9A08G045_WDT0_PCLK, R9A08G045_CLK_P0, 0x548, 0,
+ MSTOP(BUS_REG0, BIT(0))),
+ DEF_MOD("wdt0_clk", R9A08G045_WDT0_CLK, R9A08G045_OSCCLK, 0x548, 1,
+ MSTOP(BUS_REG0, BIT(0))),
+ DEF_MOD("sdhi0_imclk", R9A08G045_SDHI0_IMCLK, CLK_SD0_DIV4, 0x554, 0,
+ MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi0_imclk2", R9A08G045_SDHI0_IMCLK2, CLK_SD0_DIV4, 0x554, 1,
+ MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi0_clk_hs", R9A08G045_SDHI0_CLK_HS, R9A08G045_CLK_SD0, 0x554, 2,
+ MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi0_aclk", R9A08G045_SDHI0_ACLK, R9A08G045_CLK_P1, 0x554, 3,
+ MSTOP(BUS_PERI_COM, BIT(0))),
+ DEF_MOD("sdhi1_imclk", R9A08G045_SDHI1_IMCLK, CLK_SD1_DIV4, 0x554, 4,
+ MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("sdhi1_imclk2", R9A08G045_SDHI1_IMCLK2, CLK_SD1_DIV4, 0x554, 5,
+ MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("sdhi1_clk_hs", R9A08G045_SDHI1_CLK_HS, R9A08G045_CLK_SD1, 0x554, 6,
+ MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("sdhi1_aclk", R9A08G045_SDHI1_ACLK, R9A08G045_CLK_P1, 0x554, 7,
+ MSTOP(BUS_PERI_COM, BIT(1))),
+ DEF_MOD("sdhi2_imclk", R9A08G045_SDHI2_IMCLK, CLK_SD2_DIV4, 0x554, 8,
+ MSTOP(BUS_PERI_COM, BIT(11))),
+ DEF_MOD("sdhi2_imclk2", R9A08G045_SDHI2_IMCLK2, CLK_SD2_DIV4, 0x554, 9,
+ MSTOP(BUS_PERI_COM, BIT(11))),
+ DEF_MOD("sdhi2_clk_hs", R9A08G045_SDHI2_CLK_HS, R9A08G045_CLK_SD2, 0x554, 10,
+ MSTOP(BUS_PERI_COM, BIT(11))),
+ DEF_MOD("sdhi2_aclk", R9A08G045_SDHI2_ACLK, R9A08G045_CLK_P1, 0x554, 11,
+ MSTOP(BUS_PERI_COM, BIT(11))),
+ DEF_MOD("ssi0_pclk2", R9A08G045_SSI0_PCLK2, R9A08G045_CLK_P0, 0x570, 0,
+ MSTOP(BUS_MCPU1, BIT(10))),
+ DEF_MOD("ssi0_sfr", R9A08G045_SSI0_PCLK_SFR, R9A08G045_CLK_P0, 0x570, 1,
+ MSTOP(BUS_MCPU1, BIT(10))),
+ DEF_MOD("ssi1_pclk2", R9A08G045_SSI1_PCLK2, R9A08G045_CLK_P0, 0x570, 2,
+ MSTOP(BUS_MCPU1, BIT(11))),
+ DEF_MOD("ssi1_sfr", R9A08G045_SSI1_PCLK_SFR, R9A08G045_CLK_P0, 0x570, 3,
+ MSTOP(BUS_MCPU1, BIT(11))),
+ DEF_MOD("ssi2_pclk2", R9A08G045_SSI2_PCLK2, R9A08G045_CLK_P0, 0x570, 4,
+ MSTOP(BUS_MCPU1, BIT(12))),
+ DEF_MOD("ssi2_sfr", R9A08G045_SSI2_PCLK_SFR, R9A08G045_CLK_P0, 0x570, 5,
+ MSTOP(BUS_MCPU1, BIT(12))),
+ DEF_MOD("ssi3_pclk2", R9A08G045_SSI3_PCLK2, R9A08G045_CLK_P0, 0x570, 6,
+ MSTOP(BUS_MCPU1, BIT(13))),
+ DEF_MOD("ssi3_sfr", R9A08G045_SSI3_PCLK_SFR, R9A08G045_CLK_P0, 0x570, 7,
+ MSTOP(BUS_MCPU1, BIT(13))),
+ DEF_MOD("usb0_host", R9A08G045_USB_U2H0_HCLK, R9A08G045_CLK_P1, 0x578, 0,
+ MSTOP(BUS_PERI_COM, BIT(5))),
+ DEF_MOD("usb1_host", R9A08G045_USB_U2H1_HCLK, R9A08G045_CLK_P1, 0x578, 1,
+ MSTOP(BUS_PERI_COM, BIT(7))),
+ DEF_MOD("usb0_func", R9A08G045_USB_U2P_EXR_CPUCLK, R9A08G045_CLK_P1, 0x578, 2,
+ MSTOP(BUS_PERI_COM, BIT(6))),
+ DEF_MOD("usb_pclk", R9A08G045_USB_PCLK, R9A08G045_CLK_P1, 0x578, 3,
+ MSTOP(BUS_PERI_COM, BIT(4))),
+ DEF_COUPLED("eth0_axi", R9A08G045_ETH0_CLK_AXI, R9A08G045_CLK_M0, 0x57c, 0,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth0_chi", R9A08G045_ETH0_CLK_CHI, R9A08G045_CLK_ZT, 0x57c, 0,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_MOD("eth0_refclk", R9A08G045_ETH0_REFCLK, R9A08G045_CLK_HP, 0x57c, 8, 0),
+ DEF_COUPLED("eth1_axi", R9A08G045_ETH1_CLK_AXI, R9A08G045_CLK_M0, 0x57c, 1,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_COUPLED("eth1_chi", R9A08G045_ETH1_CLK_CHI, R9A08G045_CLK_ZT, 0x57c, 1,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_MOD("eth1_refclk", R9A08G045_ETH1_REFCLK, R9A08G045_CLK_HP, 0x57c, 9, 0),
+ DEF_MOD("i2c0_pclk", R9A08G045_I2C0_PCLK, R9A08G045_CLK_P0, 0x580, 0,
+ MSTOP(BUS_MCPU2, BIT(10))),
+ DEF_MOD("i2c1_pclk", R9A08G045_I2C1_PCLK, R9A08G045_CLK_P0, 0x580, 1,
+ MSTOP(BUS_MCPU2, BIT(11))),
+ DEF_MOD("i2c2_pclk", R9A08G045_I2C2_PCLK, R9A08G045_CLK_P0, 0x580, 2,
+ MSTOP(BUS_MCPU2, BIT(12))),
+ DEF_MOD("i2c3_pclk", R9A08G045_I2C3_PCLK, R9A08G045_CLK_P0, 0x580, 3,
+ MSTOP(BUS_MCPU2, BIT(13))),
+ DEF_MOD("scif0_clk_pck", R9A08G045_SCIF0_CLK_PCK, R9A08G045_CLK_P0, 0x584, 0,
+ MSTOP(BUS_MCPU2, BIT(1))),
+ DEF_MOD("scif1_clk_pck", R9A08G045_SCIF1_CLK_PCK, R9A08G045_CLK_P0, 0x584, 1,
+ MSTOP(BUS_MCPU2, BIT(2))),
+ DEF_MOD("scif2_clk_pck", R9A08G045_SCIF2_CLK_PCK, R9A08G045_CLK_P0, 0x584, 2,
+ MSTOP(BUS_MCPU2, BIT(3))),
+ DEF_MOD("scif3_clk_pck", R9A08G045_SCIF3_CLK_PCK, R9A08G045_CLK_P0, 0x584, 3,
+ MSTOP(BUS_MCPU2, BIT(4))),
+ DEF_MOD("scif4_clk_pck", R9A08G045_SCIF4_CLK_PCK, R9A08G045_CLK_P0, 0x584, 4,
+ MSTOP(BUS_MCPU2, BIT(5))),
+ DEF_MOD("scif5_clk_pck", R9A08G045_SCIF5_CLK_PCK, R9A08G045_CLK_P0, 0x584, 5,
+ MSTOP(BUS_MCPU3, BIT(4))),
+ DEF_MOD("gpio_hclk", R9A08G045_GPIO_HCLK, R9A08G045_OSCCLK, 0x598, 0,
+ MSTOP(BUS_PERI_CPU, BIT(6))),
+ DEF_MOD("adc_adclk", R9A08G045_ADC_ADCLK, R9A08G045_CLK_TSU, 0x5a8, 0,
+ MSTOP(BUS_MCPU2, BIT(14))),
+ DEF_MOD("adc_pclk", R9A08G045_ADC_PCLK, R9A08G045_CLK_TSU, 0x5a8, 1,
+ MSTOP(BUS_MCPU2, BIT(14))),
+ DEF_MOD("tsu_pclk", R9A08G045_TSU_PCLK, R9A08G045_CLK_TSU, 0x5ac, 0,
+ MSTOP(BUS_MCPU2, BIT(15))),
+ DEF_MOD("pci_aclk", R9A08G045_PCI_ACLK, R9A08G045_CLK_M0, 0x608, 0,
+ MSTOP(BUS_PERI_COM, BIT(10))),
+ DEF_MOD("pci_clkl1pm", R9A08G045_PCI_CLKL1PM, R9A08G045_CLK_ZT, 0x608, 1,
+ MSTOP(BUS_PERI_COM, BIT(10))),
+ DEF_MOD("i3c_pclk", R9A08G045_I3C_PCLK, R9A08G045_CLK_TSU, 0x610, 0,
+ MSTOP(BUS_MCPU3, BIT(10))),
+ DEF_MOD("i3c_tclk", R9A08G045_I3C_TCLK, R9A08G045_CLK_P5, 0x610, 1,
+ MSTOP(BUS_MCPU3, BIT(10))),
+ DEF_MOD("vbat_bclk", R9A08G045_VBAT_BCLK, R9A08G045_OSCCLK, 0x614, 0,
+ MSTOP(BUS_MCPU3, GENMASK(8, 7))),
+};
+
+static const struct rzg2l_reset r9a08g045_resets[] = {
+ DEF_RST(R9A08G045_GIC600_GICRESET_N, 0x814, 0),
+ DEF_RST(R9A08G045_GIC600_DBG_GICRESET_N, 0x814, 1),
+ DEF_RST(R9A08G045_IA55_RESETN, 0x818, 0),
+ DEF_RST(R9A08G045_DMAC_ARESETN, 0x82c, 0),
+ DEF_RST(R9A08G045_DMAC_RST_ASYNC, 0x82c, 1),
+ DEF_RST(R9A08G045_WDT0_PRESETN, 0x848, 0),
+ DEF_RST(R9A08G045_SDHI0_IXRST, 0x854, 0),
+ DEF_RST(R9A08G045_SDHI1_IXRST, 0x854, 1),
+ DEF_RST(R9A08G045_SDHI2_IXRST, 0x854, 2),
+ DEF_RST(R9A08G045_SSI0_RST_M2_REG, 0x870, 0),
+ DEF_RST(R9A08G045_SSI1_RST_M2_REG, 0x870, 1),
+ DEF_RST(R9A08G045_SSI2_RST_M2_REG, 0x870, 2),
+ DEF_RST(R9A08G045_SSI3_RST_M2_REG, 0x870, 3),
+ DEF_RST(R9A08G045_USB_U2H0_HRESETN, 0x878, 0),
+ DEF_RST(R9A08G045_USB_U2H1_HRESETN, 0x878, 1),
+ DEF_RST(R9A08G045_USB_U2P_EXL_SYSRST, 0x878, 2),
+ DEF_RST(R9A08G045_USB_PRESETN, 0x878, 3),
+ DEF_RST(R9A08G045_ETH0_RST_HW_N, 0x87c, 0),
+ DEF_RST(R9A08G045_ETH1_RST_HW_N, 0x87c, 1),
+ DEF_RST(R9A08G045_I2C0_MRST, 0x880, 0),
+ DEF_RST(R9A08G045_I2C1_MRST, 0x880, 1),
+ DEF_RST(R9A08G045_I2C2_MRST, 0x880, 2),
+ DEF_RST(R9A08G045_I2C3_MRST, 0x880, 3),
+ DEF_RST(R9A08G045_SCIF0_RST_SYSTEM_N, 0x884, 0),
+ DEF_RST(R9A08G045_SCIF1_RST_SYSTEM_N, 0x884, 1),
+ DEF_RST(R9A08G045_SCIF2_RST_SYSTEM_N, 0x884, 2),
+ DEF_RST(R9A08G045_SCIF3_RST_SYSTEM_N, 0x884, 3),
+ DEF_RST(R9A08G045_SCIF4_RST_SYSTEM_N, 0x884, 4),
+ DEF_RST(R9A08G045_SCIF5_RST_SYSTEM_N, 0x884, 5),
+ DEF_RST(R9A08G045_GPIO_RSTN, 0x898, 0),
+ DEF_RST(R9A08G045_GPIO_PORT_RESETN, 0x898, 1),
+ DEF_RST(R9A08G045_GPIO_SPARE_RESETN, 0x898, 2),
+ DEF_RST(R9A08G045_ADC_PRESETN, 0x8a8, 0),
+ DEF_RST(R9A08G045_ADC_ADRST_N, 0x8a8, 1),
+ DEF_RST(R9A08G045_TSU_PRESETN, 0x8ac, 0),
+ DEF_RST(R9A08G045_PCI_ARESETN, 0x908, 0),
+ DEF_RST(R9A08G045_PCI_RST_B, 0x908, 1),
+ DEF_RST(R9A08G045_PCI_RST_GP_B, 0x908, 2),
+ DEF_RST(R9A08G045_PCI_RST_PS_B, 0x908, 3),
+ DEF_RST(R9A08G045_PCI_RST_RSM_B, 0x908, 4),
+ DEF_RST(R9A08G045_PCI_RST_CFG_B, 0x908, 5),
+ DEF_RST(R9A08G045_PCI_RST_LOAD_B, 0x908, 6),
+ DEF_RST(R9A08G045_I3C_TRESETN, 0x910, 0),
+ DEF_RST(R9A08G045_I3C_PRESETN, 0x910, 1),
+ DEF_RST(R9A08G045_VBAT_BRESETN, 0x914, 0),
+};
+
+static const unsigned int r9a08g045_crit_mod_clks[] __initconst = {
+ MOD_CLK_BASE + R9A08G045_GIC600_GICCLK,
+ MOD_CLK_BASE + R9A08G045_IA55_PCLK,
+ MOD_CLK_BASE + R9A08G045_IA55_CLK,
+ MOD_CLK_BASE + R9A08G045_DMAC_ACLK,
+ MOD_CLK_BASE + R9A08G045_VBAT_BCLK,
+};
+
+static const unsigned int r9a08g045_crit_resets[] = {
+ R9A08G045_DMAC_ARESETN,
+ R9A08G045_DMAC_RST_ASYNC,
+};
+
+static const unsigned int r9a08g045_no_pm_mod_clks[] = {
+ MOD_CLK_BASE + R9A08G045_PCI_CLKL1PM,
+};
+
+const struct rzg2l_cpg_info r9a08g045_cpg_info = {
+ /* Core Clocks */
+ .core_clks = r9a08g045_core_clks,
+ .num_core_clks = ARRAY_SIZE(r9a08g045_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r9a08g045_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r9a08g045_crit_mod_clks),
+
+ /* Module Clocks */
+ .mod_clks = r9a08g045_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r9a08g045_mod_clks),
+ .num_hw_mod_clks = R9A08G045_VBAT_BCLK + 1,
+
+ /* No PM modules Clocks */
+ .no_pm_mod_clks = r9a08g045_no_pm_mod_clks,
+ .num_no_pm_mod_clks = ARRAY_SIZE(r9a08g045_no_pm_mod_clks),
+
+ /* Resets */
+ .resets = r9a08g045_resets,
+ .num_resets = R9A08G045_VBAT_BRESETN + 1, /* Last reset ID + 1 */
+
+ /* Critical Resets */
+ .crit_resets = r9a08g045_crit_resets,
+ .num_crit_resets = ARRAY_SIZE(r9a08g045_crit_resets),
+
+ .has_clk_mon_regs = true,
+};
diff --git a/drivers/clk/renesas/r9a08g046-cpg.c b/drivers/clk/renesas/r9a08g046-cpg.c
new file mode 100644
index 000000000..a57638734
--- /dev/null
+++ b/drivers/clk/renesas/r9a08g046-cpg.c
@@ -0,0 +1,508 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G3L CPG driver
+ *
+ * Copyright (C) 2026 Renesas Electronics Corp.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/renesas,r9a08g046-cpg.h>
+
+#include "rzg2l-cpg.h"
+
+/* RZ/G3L Specific registers. */
+#define G3L_CPG_PL2_DDIV (0x204)
+#define G3L_CPG_PL3_DDIV (0x208)
+#define G3L_CPG_CA55CORE_DDIV (0x234)
+#define G3L_CPG_RSCI_DDIV (0x238)
+#define G3L_CPG_RSPI_DDIV (0x23c)
+#define G3L_CLKDIVSTATUS (0x280)
+#define G3L_CPG_ETH_SSEL (0x410)
+#define G3L_CPG_RSCI_SSEL (0x414)
+#define G3L_CPG_RSPI_SSEL (0x418)
+#define G3L_CPG_ETH_SDIV (0x434)
+
+/* RZ/G3L Specific division configuration. */
+#define G3L_DIVPL2A DDIV_PACK(G3L_CPG_PL2_DDIV, 0, 2)
+#define G3L_DIVPL2B DDIV_PACK(G3L_CPG_PL2_DDIV, 4, 2)
+#define G3L_DIVPL3A DDIV_PACK(G3L_CPG_PL3_DDIV, 0, 2)
+#define G3L_DIV_CA55_CORE0 DDIV_PACK(G3L_CPG_CA55CORE_DDIV, 0, 3)
+#define G3L_DIV_CA55_CORE1 DDIV_PACK(G3L_CPG_CA55CORE_DDIV, 4, 3)
+#define G3L_DIV_CA55_CORE2 DDIV_PACK(G3L_CPG_CA55CORE_DDIV, 8, 3)
+#define G3L_DIV_CA55_CORE3 DDIV_PACK(G3L_CPG_CA55CORE_DDIV, 12, 3)
+#define G3L_DIV_RSCI0 DDIV_PACK(G3L_CPG_RSCI_DDIV, 0, 2)
+#define G3L_DIV_RSCI1 DDIV_PACK(G3L_CPG_RSCI_DDIV, 2, 2)
+#define G3L_DIV_RSCI2 DDIV_PACK(G3L_CPG_RSCI_DDIV, 4, 2)
+#define G3L_DIV_RSCI3 DDIV_PACK(G3L_CPG_RSCI_DDIV, 6, 2)
+#define G3L_DIV_RSPI0 DDIV_PACK(G3L_CPG_RSPI_DDIV, 0, 2)
+#define G3L_DIV_RSPI1 DDIV_PACK(G3L_CPG_RSPI_DDIV, 2, 2)
+#define G3L_DIV_RSPI2 DDIV_PACK(G3L_CPG_RSPI_DDIV, 4, 2)
+#define G3L_SDIV_ETH_A DDIV_PACK(G3L_CPG_ETH_SDIV, 0, 2)
+#define G3L_SDIV_ETH_B DDIV_PACK(G3L_CPG_ETH_SDIV, 4, 1)
+#define G3L_SDIV_ETH_C DDIV_PACK(G3L_CPG_ETH_SDIV, 8, 2)
+#define G3L_SDIV_ETH_D DDIV_PACK(G3L_CPG_ETH_SDIV, 12, 1)
+
+/* RZ/G3L Clock status configuration. */
+#define G3L_DIVPL2A_STS DDIV_PACK(G3L_CLKDIVSTATUS, 4, 1)
+#define G3L_DIVPL2B_STS DDIV_PACK(G3L_CLKDIVSTATUS, 5, 1)
+#define G3L_DIVPL3A_STS DDIV_PACK(G3L_CLKDIVSTATUS, 8, 1)
+#define G3L_DIV_CA55_CORE0_STS DDIV_PACK(G3L_CLKDIVSTATUS, 12, 1)
+#define G3L_DIV_CA55_CORE1_STS DDIV_PACK(G3L_CLKDIVSTATUS, 13, 1)
+#define G3L_DIV_CA55_CORE2_STS DDIV_PACK(G3L_CLKDIVSTATUS, 14, 1)
+#define G3L_DIV_CA55_CORE3_STS DDIV_PACK(G3L_CLKDIVSTATUS, 15, 1)
+#define G3L_DIV_RSCI0_STS DDIV_PACK(G3L_CLKDIVSTATUS, 16, 1)
+#define G3L_DIV_RSCI1_STS DDIV_PACK(G3L_CLKDIVSTATUS, 17, 1)
+#define G3L_DIV_RSCI2_STS DDIV_PACK(G3L_CLKDIVSTATUS, 18, 1)
+#define G3L_DIV_RSCI3_STS DDIV_PACK(G3L_CLKDIVSTATUS, 19, 1)
+#define G3L_DIV_RSPI0_STS DDIV_PACK(G3L_CLKDIVSTATUS, 20, 1)
+#define G3L_DIV_RSPI1_STS DDIV_PACK(G3L_CLKDIVSTATUS, 21, 1)
+#define G3L_DIV_RSPI2_STS DDIV_PACK(G3L_CLKDIVSTATUS, 22, 1)
+
+/* RZ/G3L Specific clocks select. */
+#define G3L_SEL_ETH0_TX SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 0, 1)
+#define G3L_SEL_ETH0_RX SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 1, 1)
+#define G3L_SEL_ETH0_RM SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 2, 1)
+#define G3L_SEL_ETH0_CLK_TX_I SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 3, 1)
+#define G3L_SEL_ETH0_CLK_RX_I SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 4, 1)
+#define G3L_SEL_ETH1_TX SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 8, 1)
+#define G3L_SEL_ETH1_RX SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 9, 1)
+#define G3L_SEL_ETH1_RM SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 10, 1)
+#define G3L_SEL_ETH1_CLK_TX_I SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 11, 1)
+#define G3L_SEL_ETH1_CLK_RX_I SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 12, 1)
+#define G3L_SEL_RSCI0 SEL_PLL_PACK(G3L_CPG_RSCI_SSEL, 0, 2)
+#define G3L_SEL_RSCI1 SEL_PLL_PACK(G3L_CPG_RSCI_SSEL, 2, 2)
+#define G3L_SEL_RSCI2 SEL_PLL_PACK(G3L_CPG_RSCI_SSEL, 4, 2)
+#define G3L_SEL_RSCI3 SEL_PLL_PACK(G3L_CPG_RSCI_SSEL, 6, 2)
+#define G3L_SEL_RSPI0 SEL_PLL_PACK(G3L_CPG_RSPI_SSEL, 0, 2)
+#define G3L_SEL_RSPI1 SEL_PLL_PACK(G3L_CPG_RSPI_SSEL, 2, 2)
+#define G3L_SEL_RSPI2 SEL_PLL_PACK(G3L_CPG_RSPI_SSEL, 4, 2)
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A08G046_USB_SCLK,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_ETH0_TXC_TX_CLK_IN,
+ CLK_ETH0_RXC_RX_CLK_IN,
+ CLK_ETH1_TXC_TX_CLK_IN,
+ CLK_ETH1_RXC_RX_CLK_IN,
+
+ /* Internal Core Clocks */
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL2_DIV2,
+ CLK_PLL2_DIV2_4,
+ CLK_PLL2_DIV5,
+ CLK_PLL2_DIV6,
+ CLK_PLL2_DIV7,
+ CLK_PLL3,
+ CLK_PLL3_DIV2,
+ CLK_PLL6,
+ CLK_PLL6_DIV10,
+ CLK_SEL_ETH0_TX,
+ CLK_SEL_ETH0_RX,
+ CLK_SEL_ETH0_RM,
+ CLK_SEL_ETH1_TX,
+ CLK_SEL_ETH1_RX,
+ CLK_SEL_ETH1_RM,
+ CLK_SEL_RSCI0,
+ CLK_SEL_RSCI1,
+ CLK_SEL_RSCI2,
+ CLK_SEL_RSCI3,
+ CLK_SEL_RSPI0,
+ CLK_SEL_RSPI1,
+ CLK_SEL_RSPI2,
+ CLK_ETH0_TR,
+ CLK_ETH0_RM,
+ CLK_ETH1_TR,
+ CLK_ETH1_RM,
+
+ /* Module Clocks */
+ MOD_CLK_BASE,
+};
+
+/* Divider tables */
+static const struct clk_div_table dtable_1_8[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 2, 4 },
+ { 3, 8 },
+ { 0, 0 },
+};
+
+static const struct clk_div_table dtable_1_32[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 2, 4 },
+ { 3, 8 },
+ { 4, 16 },
+ { 5, 32 },
+ { 0, 0 },
+};
+
+static const struct clk_div_table dtable_2_20[] = {
+ { 0, 2 },
+ { 1, 20 },
+ { 0, 0 },
+};
+
+static const struct clk_div_table dtable_2_16[] = {
+ { 0, 2 },
+ { 1, 4 },
+ { 2, 8 },
+ { 3, 16 },
+ { 0, 0 },
+};
+
+static const struct clk_div_table dtable_4_128[] = {
+ { 0, 4 },
+ { 1, 8 },
+ { 2, 16 },
+ { 3, 128 },
+ { 0, 0 },
+};
+
+static const struct clk_div_table dtable_4_200[] = {
+ { 0, 4 },
+ { 1, 20 },
+ { 2, 200 },
+ { 0, 0 },
+};
+
+static const struct clk_div_table dtable_8_256[] = {
+ { 0, 8 },
+ { 1, 16 },
+ { 2, 32 },
+ { 3, 256 },
+ { 0, 0 },
+};
+
+/* Mux clock names tables. */
+static const char * const sel_eth0_tx[] = { ".div_eth0_tr", "eth0_txc_tx_clk" };
+static const char * const sel_eth0_rx[] = { ".div_eth0_tr", "eth0_rxc_rx_clk" };
+static const char * const sel_eth0_rm[] = { ".pll6_div10", "eth0_rxc_rx_clk" };
+static const char * const sel_eth1_tx[] = { ".div_eth1_tr", "eth1_txc_tx_clk" };
+static const char * const sel_eth1_rx[] = { ".div_eth1_tr", "eth1_rxc_rx_clk" };
+static const char * const sel_eth1_rm[] = { ".pll6_div10", "eth1_rxc_rx_clk" };
+static const char * const sel_rsci_rspi[] = { ".pll2_div5", ".pll2_div6", ".pll2_div7", ".pll2_div2_4" };
+static const char * const sel_eth0_clk_tx_i[] = { ".sel_eth0_tx", ".div_eth0_rm" };
+static const char * const sel_eth0_clk_rx_i[] = { ".sel_eth0_rx", ".div_eth0_rm" };
+static const char * const sel_eth1_clk_tx_i[] = { ".sel_eth1_tx", ".div_eth1_rm" };
+static const char * const sel_eth1_clk_rx_i[] = { ".sel_eth1_rx", ".div_eth1_rm" };
+
+static const struct cpg_core_clk r9a08g046_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+ DEF_INPUT("eth0_txc_tx_clk", CLK_ETH0_TXC_TX_CLK_IN),
+ DEF_INPUT("eth0_rxc_rx_clk", CLK_ETH0_RXC_RX_CLK_IN),
+ DEF_INPUT("eth1_txc_tx_clk", CLK_ETH1_TXC_TX_CLK_IN),
+ DEF_INPUT("eth1_rxc_rx_clk", CLK_ETH1_RXC_RX_CLK_IN),
+
+ /* Internal Core Clocks */
+ DEF_G3L_PLL(".pll1", CLK_PLL1, CLK_EXTAL, CPG_PLL_CONF(0, 0x100),
+ 1200000000UL),
+ DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3),
+ DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3),
+ DEF_G3L_PLL(".pll6", CLK_PLL6, CLK_EXTAL, CPG_PLL_CONF(0x50, 0),
+ 500000000UL),
+ DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2),
+ DEF_FIXED(".pll2_div2_4", CLK_PLL2_DIV2_4, CLK_PLL2_DIV2, 1, 4),
+ DEF_FIXED(".pll2_div5", CLK_PLL2_DIV5, CLK_PLL2, 1, 5),
+ DEF_FIXED(".pll2_div6", CLK_PLL2_DIV6, CLK_PLL2, 1, 6),
+ DEF_FIXED(".pll2_div7", CLK_PLL2_DIV7, CLK_PLL2, 1, 7),
+ DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2),
+ DEF_FIXED(".pll6_div10", CLK_PLL6_DIV10, CLK_PLL6, 1, 10),
+ DEF_MUX(".sel_rsci0", CLK_SEL_RSCI0, G3L_SEL_RSCI0, sel_rsci_rspi),
+ DEF_MUX(".sel_rsci1", CLK_SEL_RSCI1, G3L_SEL_RSCI1, sel_rsci_rspi),
+ DEF_MUX(".sel_rsci2", CLK_SEL_RSCI2, G3L_SEL_RSCI2, sel_rsci_rspi),
+ DEF_MUX(".sel_rsci3", CLK_SEL_RSCI3, G3L_SEL_RSCI3, sel_rsci_rspi),
+ DEF_MUX(".sel_rspi0", CLK_SEL_RSPI0, G3L_SEL_RSPI0, sel_rsci_rspi),
+ DEF_MUX(".sel_rspi1", CLK_SEL_RSPI1, G3L_SEL_RSPI1, sel_rsci_rspi),
+ DEF_MUX(".sel_rspi2", CLK_SEL_RSPI2, G3L_SEL_RSPI2, sel_rsci_rspi),
+ DEF_MUX(".sel_eth0_tx", CLK_SEL_ETH0_TX, G3L_SEL_ETH0_TX, sel_eth0_tx),
+ DEF_MUX(".sel_eth0_rx", CLK_SEL_ETH0_RX, G3L_SEL_ETH0_RX, sel_eth0_rx),
+ DEF_MUX(".sel_eth0_rm", CLK_SEL_ETH0_RM, G3L_SEL_ETH0_RM, sel_eth0_rm),
+ DEF_MUX(".sel_eth1_tx", CLK_SEL_ETH1_TX, G3L_SEL_ETH1_TX, sel_eth1_tx),
+ DEF_MUX(".sel_eth1_rx", CLK_SEL_ETH1_RX, G3L_SEL_ETH1_RX, sel_eth1_rx),
+ DEF_MUX(".sel_eth1_rm", CLK_SEL_ETH1_RM, G3L_SEL_ETH1_RM, sel_eth1_rm),
+ DEF_DIV(".div_eth0_tr", CLK_ETH0_TR, CLK_PLL6, G3L_SDIV_ETH_A, dtable_4_200),
+ DEF_DIV(".div_eth1_tr", CLK_ETH1_TR, CLK_PLL6, G3L_SDIV_ETH_C, dtable_4_200),
+ DEF_DIV(".div_eth0_rm", CLK_ETH0_RM, CLK_SEL_ETH0_RM, G3L_SDIV_ETH_B, dtable_2_20),
+ DEF_DIV(".div_eth1_rm", CLK_ETH1_RM, CLK_SEL_ETH1_RM, G3L_SDIV_ETH_D, dtable_2_20),
+
+ /* Core output clk */
+ DEF_G3S_DIV("IC0", R9A08G046_CLK_IC0, CLK_PLL1, G3L_DIV_CA55_CORE0, G3L_DIV_CA55_CORE0_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_G3S_DIV("IC1", R9A08G046_CLK_IC1, CLK_PLL1, G3L_DIV_CA55_CORE1, G3L_DIV_CA55_CORE1_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_G3S_DIV("IC2", R9A08G046_CLK_IC2, CLK_PLL1, G3L_DIV_CA55_CORE2, G3L_DIV_CA55_CORE2_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_G3S_DIV("IC3", R9A08G046_CLK_IC3, CLK_PLL1, G3L_DIV_CA55_CORE3, G3L_DIV_CA55_CORE3_STS,
+ dtable_1_32, 0, 0, 0, NULL),
+ DEF_G3S_DIV("P0", R9A08G046_CLK_P0, CLK_PLL2_DIV2, G3L_DIVPL2B, G3L_DIVPL2B_STS,
+ dtable_8_256, 0, 0, 0, NULL),
+ DEF_G3S_DIV("P1", R9A08G046_CLK_P1, CLK_PLL3_DIV2, G3L_DIVPL3A, G3L_DIVPL3A_STS,
+ dtable_4_128, 0, 0, 0, NULL),
+ DEF_G3S_DIV("P3", R9A08G046_CLK_P3, CLK_PLL2_DIV2, G3L_DIVPL2A, G3L_DIVPL2A_STS,
+ dtable_4_128, 0, 0, 0, NULL),
+ DEF_G3S_DIV("P13", R9A08G046_CLK_P13, CLK_SEL_RSCI0, G3L_DIV_RSCI0, G3L_DIV_RSCI0_STS,
+ dtable_2_16, 0, 100000000UL, 0, NULL),
+ DEF_G3S_DIV("P14", R9A08G046_CLK_P14, CLK_SEL_RSCI1, G3L_DIV_RSCI1, G3L_DIV_RSCI1_STS,
+ dtable_2_16, 0, 100000000UL, 0, NULL),
+ DEF_G3S_DIV("P15", R9A08G046_CLK_P15, CLK_SEL_RSCI2, G3L_DIV_RSCI2, G3L_DIV_RSCI2_STS,
+ dtable_2_16, 0, 100000000UL, 0, NULL),
+ DEF_G3S_DIV("P16", R9A08G046_CLK_P16, CLK_SEL_RSCI3, G3L_DIV_RSCI3, G3L_DIV_RSCI3_STS,
+ dtable_2_16, 0, 100000000UL, 0, NULL),
+ DEF_G3S_DIV("P17", R9A08G046_CLK_P17, CLK_SEL_RSPI0, G3L_DIV_RSPI0, G3L_DIV_RSPI0_STS,
+ dtable_1_8, 0, 200000000UL, 0, NULL),
+ DEF_G3S_DIV("P18", R9A08G046_CLK_P18, CLK_SEL_RSPI1, G3L_DIV_RSPI1, G3L_DIV_RSPI1_STS,
+ dtable_1_8, 0, 200000000UL, 0, NULL),
+ DEF_G3S_DIV("P19", R9A08G046_CLK_P19, CLK_SEL_RSPI2, G3L_DIV_RSPI2, G3L_DIV_RSPI2_STS,
+ dtable_1_8, 0, 200000000UL, 0, NULL),
+ DEF_FIXED("HP", R9A08G046_CLK_HP, CLK_PLL6_DIV10, 1, 1),
+ DEF_MUX_FLAGS("ETHTX01", R9A08G046_CLK_ETHTX01, G3L_SEL_ETH0_CLK_TX_I, sel_eth0_clk_tx_i,
+ CLK_SET_RATE_PARENT),
+ DEF_MUX_FLAGS("ETHRX01", R9A08G046_CLK_ETHRX01, G3L_SEL_ETH0_CLK_RX_I, sel_eth0_clk_rx_i,
+ CLK_SET_RATE_PARENT),
+ DEF_MUX_FLAGS("ETHTX11", R9A08G046_CLK_ETHTX11, G3L_SEL_ETH1_CLK_TX_I, sel_eth1_clk_tx_i,
+ CLK_SET_RATE_PARENT),
+ DEF_MUX_FLAGS("ETHRX11", R9A08G046_CLK_ETHRX11, G3L_SEL_ETH1_CLK_RX_I, sel_eth1_clk_rx_i,
+ CLK_SET_RATE_PARENT),
+ DEF_FIXED("ETHRM0", R9A08G046_CLK_ETHRM0, CLK_SEL_ETH0_RM, 1, 1),
+ DEF_FIXED("ETHTX02", R9A08G046_CLK_ETHTX02, CLK_SEL_ETH0_TX, 1, 1),
+ DEF_FIXED("ETHRX02", R9A08G046_CLK_ETHRX02, CLK_SEL_ETH0_RX, 1, 1),
+ DEF_FIXED("ETHRM1", R9A08G046_CLK_ETHRM1, CLK_SEL_ETH1_RM, 1, 1),
+ DEF_FIXED("ETHTX12", R9A08G046_CLK_ETHTX12, CLK_SEL_ETH1_TX, 1, 1),
+ DEF_FIXED("ETHRX12", R9A08G046_CLK_ETHRX12, CLK_SEL_ETH1_RX, 1, 1),
+ DEF_FIXED("OSCCLK", R9A08G046_OSCCLK, CLK_EXTAL, 1, 1),
+};
+
+static const struct rzg2l_mod_clk r9a08g046_mod_clks[] = {
+ DEF_MOD("gic_gicclk", R9A08G046_GIC600_GICCLK, R9A08G046_CLK_P1, 0x514, 0,
+ MSTOP(BUS_PERI_COM, BIT(12))),
+ DEF_MOD("ia55_pclk", R9A08G046_IA55_PCLK, R9A08G046_CLK_P0, 0x518, 0,
+ MSTOP(BUS_PERI_CPU, BIT(13))),
+ DEF_MOD("ia55_clk", R9A08G046_IA55_CLK, R9A08G046_CLK_P1, 0x518, 1,
+ MSTOP(BUS_PERI_CPU, BIT(13))),
+ DEF_MOD("dmac_aclk", R9A08G046_DMAC_ACLK, R9A08G046_CLK_P3, 0x52c, 0,
+ MSTOP(BUS_REG1, BIT(2))),
+ DEF_MOD("dmac_pclk", R9A08G046_DMAC_PCLK, R9A08G046_CLK_P3, 0x52c, 1,
+ MSTOP(BUS_REG1, BIT(3))),
+ DEF_MOD("wdt0_pclk", R9A08G046_WDT0_PCLK, R9A08G046_CLK_P0, 0x548, 0,
+ MSTOP(BUS_REG0, BIT(0))),
+ DEF_MOD("wdt0_clk", R9A08G046_WDT0_CLK, R9A08G046_OSCCLK, 0x548, 1,
+ MSTOP(BUS_REG0, BIT(0))),
+ DEF_MOD("ssi0_pclk2", R9A08G046_SSI0_PCLK2, R9A08G046_CLK_P0, 0x570, 0,
+ MSTOP(BUS_MCPU1, BIT(10))),
+ DEF_MOD("ssi0_pclk_sfr", R9A08G046_SSI0_PCLK_SFR, R9A08G046_CLK_P0, 0x570, 1,
+ MSTOP(BUS_MCPU1, BIT(10))),
+ DEF_MOD("ssi1_pclk2", R9A08G046_SSI1_PCLK2, R9A08G046_CLK_P0, 0x570, 2,
+ MSTOP(BUS_MCPU1, BIT(11))),
+ DEF_MOD("ssi1_pclk_sfr", R9A08G046_SSI1_PCLK_SFR, R9A08G046_CLK_P0, 0x570, 3,
+ MSTOP(BUS_MCPU1, BIT(11))),
+ DEF_MOD("ssi2_pclk2", R9A08G046_SSI2_PCLK2, R9A08G046_CLK_P0, 0x570, 4,
+ MSTOP(BUS_MCPU1, BIT(12))),
+ DEF_MOD("ssi2_pclk_sfr", R9A08G046_SSI2_PCLK_SFR, R9A08G046_CLK_P0, 0x570, 5,
+ MSTOP(BUS_MCPU1, BIT(12))),
+ DEF_MOD("ssi3_pclk2", R9A08G046_SSI3_PCLK2, R9A08G046_CLK_P0, 0x570, 6,
+ MSTOP(BUS_MCPU1, BIT(13))),
+ DEF_MOD("ssi3_pclk_sfr", R9A08G046_SSI3_PCLK_SFR, R9A08G046_CLK_P0, 0x570, 7,
+ MSTOP(BUS_MCPU1, BIT(13))),
+ DEF_MOD("eth0_clk_axi", R9A08G046_ETH0_CLK_AXI, R9A08G046_CLK_P1, 0x57c, 0,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_MOD("eth1_clk_axi", R9A08G046_ETH1_CLK_AXI, R9A08G046_CLK_P1, 0x57c, 1,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_MOD("eth0_clk_chi", R9A08G046_ETH0_CLK_CHI, R9A08G046_CLK_P1, 0x57c, 2,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_MOD("eth1_clk_chi", R9A08G046_ETH1_CLK_CHI, R9A08G046_CLK_P1, 0x57c, 3,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_COUPLED("eth0_tx_i", R9A08G046_ETH0_CLK_TX_I, R9A08G046_CLK_ETHTX01, 0x57c, 4,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth0_tx_180_i", R9A08G046_ETH0_CLK_TX_180_I, R9A08G046_CLK_ETHTX02, 0x57c, 4,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth1_tx_i", R9A08G046_ETH1_CLK_TX_I, R9A08G046_CLK_ETHTX11, 0x57c, 5,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_COUPLED("eth1_tx_180_i", R9A08G046_ETH1_CLK_TX_180_I, R9A08G046_CLK_ETHTX12, 0x57c, 5,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_COUPLED("eth0_rx_i", R9A08G046_ETH0_CLK_RX_I, R9A08G046_CLK_ETHRX01, 0x57c, 6,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth0_rx_180_i", R9A08G046_ETH0_CLK_RX_180_I, R9A08G046_CLK_ETHRX02, 0x57c, 6,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth1_rx_i", R9A08G046_ETH1_CLK_RX_I, R9A08G046_CLK_ETHRX11, 0x57c, 7,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_COUPLED("eth1_rx_180_i", R9A08G046_ETH1_CLK_RX_180_I, R9A08G046_CLK_ETHRX12, 0x57c, 7,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_MOD("eth0_ptp_ref_i", R9A08G046_ETH0_CLK_PTP_REF_I, R9A08G046_CLK_HP, 0x57c, 8,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_MOD("eth1_ptp_ref_i", R9A08G046_ETH1_CLK_PTP_REF_I, R9A08G046_CLK_HP, 0x57c, 9,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_MOD("eth0_rmii_i", R9A08G046_ETH0_CLK_RMII_I, R9A08G046_CLK_ETHRM0, 0x57c, 10,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_MOD("eth1_rmii_i", R9A08G046_ETH1_CLK_RMII_I, R9A08G046_CLK_ETHRM1, 0x57c, 11,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_COUPLED("eth0_tx_i_rmii", R9A08G046_ETH0_CLK_TX_I_RMII, R9A08G046_CLK_ETHTX01, 0x57c, 12,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth0_rx_i_rmii", R9A08G046_ETH0_CLK_RX_I_RMII, R9A08G046_CLK_ETHRX01, 0x57c, 12,
+ MSTOP(BUS_PERI_COM, BIT(2))),
+ DEF_COUPLED("eth1_tx_i_rmii", R9A08G046_ETH1_CLK_TX_I_RMII, R9A08G046_CLK_ETHTX11, 0x57c, 13,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_COUPLED("eth1_rx_i_rmii", R9A08G046_ETH1_CLK_RX_I_RMII, R9A08G046_CLK_ETHRX11, 0x57c, 13,
+ MSTOP(BUS_PERI_COM, BIT(3))),
+ DEF_MOD("i2c0_pclk", R9A08G046_I2C0_PCLK, R9A08G046_CLK_P0, 0x580, 0,
+ MSTOP(BUS_MCPU2, BIT(10))),
+ DEF_MOD("i2c1_pclk", R9A08G046_I2C1_PCLK, R9A08G046_CLK_P0, 0x580, 1,
+ MSTOP(BUS_MCPU2, BIT(11))),
+ DEF_MOD("i2c2_pclk", R9A08G046_I2C2_PCLK, R9A08G046_CLK_P0, 0x580, 2,
+ MSTOP(BUS_MCPU2, BIT(12))),
+ DEF_MOD("i2c3_pclk", R9A08G046_I2C3_PCLK, R9A08G046_CLK_P0, 0x580, 3,
+ MSTOP(BUS_MCPU2, BIT(13))),
+ DEF_MOD("scif0_clk_pck", R9A08G046_SCIF0_CLK_PCK, R9A08G046_CLK_P0, 0x584, 0,
+ MSTOP(BUS_MCPU2, BIT(1))),
+ DEF_MOD("scif1_clk_pck", R9A08G046_SCIF1_CLK_PCK, R9A08G046_CLK_P0, 0x584, 1,
+ MSTOP(BUS_MCPU2, BIT(2))),
+ DEF_MOD("scif2_clk_pck", R9A08G046_SCIF2_CLK_PCK, R9A08G046_CLK_P0, 0x584, 2,
+ MSTOP(BUS_MCPU2, BIT(3))),
+ DEF_MOD("scif3_clk_pck", R9A08G046_SCIF3_CLK_PCK, R9A08G046_CLK_P0, 0x584, 3,
+ MSTOP(BUS_MCPU2, BIT(4))),
+ DEF_MOD("scif4_clk_pck", R9A08G046_SCIF4_CLK_PCK, R9A08G046_CLK_P0, 0x584, 4,
+ MSTOP(BUS_MCPU2, BIT(5))),
+ DEF_MOD("scif5_clk_pck", R9A08G046_SCIF5_CLK_PCK, R9A08G046_CLK_P0, 0x584, 5,
+ MSTOP(BUS_MCPU3, BIT(4))),
+ DEF_MOD("rspi0_pclk", R9A08G046_RSPI0_PCLK, R9A08G046_CLK_P3, 0x590, 0,
+ MSTOP(BUS_MCPU1, BIT(14))),
+ DEF_MOD("rspi1_pclk", R9A08G046_RSPI1_PCLK, R9A08G046_CLK_P3, 0x590, 1,
+ MSTOP(BUS_MCPU1, BIT(15))),
+ DEF_MOD("rspi2_pclk", R9A08G046_RSPI2_PCLK, R9A08G046_CLK_P3, 0x590, 2,
+ MSTOP(BUS_MCPU2, BIT(0))),
+ DEF_MOD("rspi0_tclk", R9A08G046_RSPI0_TCLK, R9A08G046_CLK_P17, 0x590, 8,
+ MSTOP(BUS_MCPU1, BIT(14))),
+ DEF_MOD("rspi1_tclk", R9A08G046_RSPI1_TCLK, R9A08G046_CLK_P18, 0x590, 9,
+ MSTOP(BUS_MCPU1, BIT(15))),
+ DEF_MOD("rspi2_tclk", R9A08G046_RSPI2_TCLK, R9A08G046_CLK_P19, 0x590, 10,
+ MSTOP(BUS_MCPU2, BIT(0))),
+ DEF_MOD("gpio_hclk", R9A08G046_GPIO_HCLK, R9A08G046_OSCCLK, 0x598, 0,
+ MSTOP(BUS_PERI_CPU, BIT(6))),
+ DEF_MOD("rsci0_pclk", R9A08G046_RSCI0_PCLK, R9A08G046_CLK_P0, 0x618, 0,
+ MSTOP(BUS_MCPU2, BIT(7))),
+ DEF_MOD("rsci1_pclk", R9A08G046_RSCI1_PCLK, R9A08G046_CLK_P0, 0x618, 1,
+ MSTOP(BUS_MCPU2, BIT(8))),
+ DEF_MOD("rsci2_pclk", R9A08G046_RSCI2_PCLK, R9A08G046_CLK_P0, 0x618, 2,
+ MSTOP(BUS_MCPU3, BIT(11))),
+ DEF_MOD("rsci3_pclk", R9A08G046_RSCI3_PCLK, R9A08G046_CLK_P0, 0x618, 3,
+ MSTOP(BUS_MCPU3, BIT(12))),
+ DEF_MOD("rsci0_tclk", R9A08G046_RSCI0_TCLK, R9A08G046_CLK_P13, 0x618, 8,
+ MSTOP(BUS_MCPU2, BIT(7))),
+ DEF_MOD("rsci1_tclk", R9A08G046_RSCI1_TCLK, R9A08G046_CLK_P14, 0x618, 9,
+ MSTOP(BUS_MCPU2, BIT(8))),
+ DEF_MOD("rsci2_tclk", R9A08G046_RSCI2_TCLK, R9A08G046_CLK_P15, 0x618, 10,
+ MSTOP(BUS_MCPU3, BIT(11))),
+ DEF_MOD("rsci3_tclk", R9A08G046_RSCI3_TCLK, R9A08G046_CLK_P16, 0x618, 11,
+ MSTOP(BUS_MCPU3, BIT(12))),
+};
+
+static const struct rzg2l_reset r9a08g046_resets[] = {
+ DEF_RST(R9A08G046_GIC600_GICRESET_N, 0x814, 0),
+ DEF_RST(R9A08G046_GIC600_DBG_GICRESET_N, 0x814, 1),
+ DEF_RST(R9A08G046_IA55_RESETN, 0x818, 0),
+ DEF_RST(R9A08G046_DMAC_ARESETN, 0x82c, 0),
+ DEF_RST(R9A08G046_DMAC_RST_ASYNC, 0x82c, 1),
+ DEF_RST(R9A08G046_WDT0_PRESETN, 0x848, 0),
+ DEF_RST(R9A08G046_SSI0_RST_M2_REG, 0x870, 0),
+ DEF_RST(R9A08G046_SSI1_RST_M2_REG, 0x870, 1),
+ DEF_RST(R9A08G046_SSI2_RST_M2_REG, 0x870, 2),
+ DEF_RST(R9A08G046_SSI3_RST_M2_REG, 0x870, 3),
+ DEF_RST(R9A08G046_ETH0_ARESET_N, 0x87c, 0),
+ DEF_RST(R9A08G046_ETH1_ARESET_N, 0x87c, 1),
+ DEF_RST(R9A08G046_I2C0_MRST, 0x880, 0),
+ DEF_RST(R9A08G046_I2C1_MRST, 0x880, 1),
+ DEF_RST(R9A08G046_I2C2_MRST, 0x880, 2),
+ DEF_RST(R9A08G046_I2C3_MRST, 0x880, 3),
+ DEF_RST(R9A08G046_SCIF0_RST_SYSTEM_N, 0x884, 0),
+ DEF_RST(R9A08G046_SCIF1_RST_SYSTEM_N, 0x884, 1),
+ DEF_RST(R9A08G046_SCIF2_RST_SYSTEM_N, 0x884, 2),
+ DEF_RST(R9A08G046_SCIF3_RST_SYSTEM_N, 0x884, 3),
+ DEF_RST(R9A08G046_SCIF4_RST_SYSTEM_N, 0x884, 4),
+ DEF_RST(R9A08G046_SCIF5_RST_SYSTEM_N, 0x884, 5),
+ DEF_RST(R9A08G046_RSPI0_PRESETN, 0x890, 0),
+ DEF_RST(R9A08G046_RSPI1_PRESETN, 0x890, 1),
+ DEF_RST(R9A08G046_RSPI2_PRESETN, 0x890, 2),
+ DEF_RST(R9A08G046_RSPI0_TRESETN, 0x890, 8),
+ DEF_RST(R9A08G046_RSPI1_TRESETN, 0x890, 9),
+ DEF_RST(R9A08G046_RSPI2_TRESETN, 0x890, 10),
+ DEF_RST(R9A08G046_GPIO_RSTN, 0x898, 0),
+ DEF_RST(R9A08G046_GPIO_PORT_RESETN, 0x898, 1),
+ DEF_RST(R9A08G046_GPIO_SPARE_RESETN, 0x898, 2),
+ DEF_RST(R9A08G046_RSCI0_PRESETN, 0x918, 0),
+ DEF_RST(R9A08G046_RSCI1_PRESETN, 0x918, 1),
+ DEF_RST(R9A08G046_RSCI2_PRESETN, 0x918, 2),
+ DEF_RST(R9A08G046_RSCI3_PRESETN, 0x918, 3),
+ DEF_RST(R9A08G046_RSCI0_TRESETN, 0x918, 8),
+ DEF_RST(R9A08G046_RSCI1_TRESETN, 0x918, 9),
+ DEF_RST(R9A08G046_RSCI2_TRESETN, 0x918, 10),
+ DEF_RST(R9A08G046_RSCI3_TRESETN, 0x918, 11),
+};
+
+static const unsigned int r9a08g046_crit_mod_clks[] __initconst = {
+ MOD_CLK_BASE + R9A08G046_GIC600_GICCLK,
+ MOD_CLK_BASE + R9A08G046_IA55_PCLK,
+ MOD_CLK_BASE + R9A08G046_IA55_CLK,
+ MOD_CLK_BASE + R9A08G046_DMAC_ACLK,
+};
+
+static const unsigned int r9a08g046_crit_resets[] = {
+ R9A08G046_DMAC_ARESETN,
+ R9A08G046_DMAC_RST_ASYNC,
+};
+
+static const unsigned int r9a08g046_no_pm_mod_clks[] = {
+ MOD_CLK_BASE + R9A08G046_ETH0_CLK_TX_I,
+ MOD_CLK_BASE + R9A08G046_ETH0_CLK_TX_180_I,
+ MOD_CLK_BASE + R9A08G046_ETH0_CLK_RX_I,
+ MOD_CLK_BASE + R9A08G046_ETH0_CLK_RX_180_I,
+ MOD_CLK_BASE + R9A08G046_ETH0_CLK_RMII_I,
+ MOD_CLK_BASE + R9A08G046_ETH0_CLK_TX_I_RMII,
+ MOD_CLK_BASE + R9A08G046_ETH0_CLK_RX_I_RMII,
+ MOD_CLK_BASE + R9A08G046_ETH1_CLK_TX_I,
+ MOD_CLK_BASE + R9A08G046_ETH1_CLK_TX_180_I,
+ MOD_CLK_BASE + R9A08G046_ETH1_CLK_RX_I,
+ MOD_CLK_BASE + R9A08G046_ETH1_CLK_RX_180_I,
+ MOD_CLK_BASE + R9A08G046_ETH1_CLK_RMII_I,
+ MOD_CLK_BASE + R9A08G046_ETH1_CLK_TX_I_RMII,
+ MOD_CLK_BASE + R9A08G046_ETH1_CLK_RX_I_RMII,
+};
+
+const struct rzg2l_cpg_info r9a08g046_cpg_info = {
+ /* Core Clocks */
+ .core_clks = r9a08g046_core_clks,
+ .num_core_clks = ARRAY_SIZE(r9a08g046_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r9a08g046_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r9a08g046_crit_mod_clks),
+
+ /* Module Clocks */
+ .mod_clks = r9a08g046_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r9a08g046_mod_clks),
+ .num_hw_mod_clks = R9A08G046_BSC_X_BCK_BSC + 1,
+
+ /* No PM modules Clocks */
+ .no_pm_mod_clks = r9a08g046_no_pm_mod_clks,
+ .num_no_pm_mod_clks = ARRAY_SIZE(r9a08g046_no_pm_mod_clks),
+
+ /* Resets */
+ .resets = r9a08g046_resets,
+ .num_resets = R9A08G046_BSC_X_PRESET_BSC + 1, /* Last reset ID + 1 */
+
+ /* Critical Resets */
+ .crit_resets = r9a08g046_crit_resets,
+ .num_crit_resets = ARRAY_SIZE(r9a08g046_crit_resets),
+
+ .has_clk_mon_regs = true,
+};
diff --git a/drivers/clk/renesas/r9a09g011-cpg.c b/drivers/clk/renesas/r9a09g011-cpg.c
new file mode 100644
index 000000000..a99ab1375
--- /dev/null
+++ b/drivers/clk/renesas/r9a09g011-cpg.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/V2M Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2022 Renesas Electronics Corp.
+ *
+ * Based on r9a07g044-cpg.c
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/r9a09g011-cpg.h>
+
+#include "rzg2l-cpg.h"
+
+#define DIV_A DDIV_PACK(0x200, 0, 3)
+#define DIV_B DDIV_PACK(0x204, 0, 2)
+#define DIV_D DDIV_PACK(0x204, 4, 2)
+#define DIV_E DDIV_PACK(0x204, 8, 1)
+#define DIV_W DDIV_PACK(0x328, 0, 3)
+
+#define SEL_B SEL_PLL_PACK(0x214, 0, 1)
+#define SEL_CSI0 SEL_PLL_PACK(0x330, 0, 1)
+#define SEL_CSI4 SEL_PLL_PACK(0x330, 4, 1)
+#define SEL_D SEL_PLL_PACK(0x214, 1, 1)
+#define SEL_E SEL_PLL_PACK(0x214, 2, 1)
+#define SEL_SDI SEL_PLL_PACK(0x300, 0, 1)
+#define SEL_W0 SEL_PLL_PACK(0x32C, 0, 1)
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = 0,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_MAIN_24,
+ CLK_MAIN_2,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL2_800,
+ CLK_PLL2_400,
+ CLK_PLL2_200,
+ CLK_PLL2_100,
+ CLK_PLL4,
+ CLK_DIV_A,
+ CLK_DIV_B,
+ CLK_DIV_D,
+ CLK_DIV_E,
+ CLK_DIV_W,
+ CLK_SEL_B,
+ CLK_SEL_B_D2,
+ CLK_SEL_CSI0,
+ CLK_SEL_CSI4,
+ CLK_SEL_D,
+ CLK_SEL_E,
+ CLK_SEL_SDI,
+ CLK_SEL_W0,
+
+ /* Module Clocks */
+ MOD_CLK_BASE
+};
+
+/* Divider tables */
+static const struct clk_div_table dtable_diva[] = {
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {3, 4},
+ {4, 6},
+ {5, 12},
+ {6, 24},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_divb[] = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {3, 8},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_divd[] = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_divw[] = {
+ {0, 6},
+ {1, 7},
+ {2, 8},
+ {3, 9},
+ {4, 10},
+ {5, 11},
+ {6, 12},
+ {0, 0},
+};
+
+/* Mux clock tables */
+static const char * const sel_b[] = { ".main", ".divb" };
+static const char * const sel_csi[] = { ".main_24", ".main" };
+static const char * const sel_d[] = { ".main", ".divd" };
+static const char * const sel_e[] = { ".main", ".dive" };
+static const char * const sel_w[] = { ".main", ".divw" };
+static const char * const sel_sdi[] = { ".main", ".pll2_200" };
+
+static const struct cpg_core_clk r9a09g011_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_FIXED(".main", CLK_MAIN, CLK_EXTAL, 1, 1),
+ DEF_FIXED(".main_24", CLK_MAIN_24, CLK_MAIN, 1, 2),
+ DEF_FIXED(".main_2", CLK_MAIN_2, CLK_MAIN, 1, 24),
+ DEF_FIXED(".pll1", CLK_PLL1, CLK_MAIN_2, 498, 1),
+ DEF_FIXED(".pll2", CLK_PLL2, CLK_MAIN_2, 800, 1),
+ DEF_FIXED(".pll2_800", CLK_PLL2_800, CLK_PLL2, 1, 2),
+ DEF_FIXED(".pll2_400", CLK_PLL2_400, CLK_PLL2_800, 1, 2),
+ DEF_FIXED(".pll2_200", CLK_PLL2_200, CLK_PLL2_800, 1, 4),
+ DEF_FIXED(".pll2_100", CLK_PLL2_100, CLK_PLL2_800, 1, 8),
+ DEF_SAMPLL(".pll4", CLK_PLL4, CLK_MAIN_2, CPG_SAM_PLL_CONF(0x100)),
+
+ DEF_DIV_RO(".diva", CLK_DIV_A, CLK_PLL1, DIV_A, dtable_diva),
+ DEF_DIV_RO(".divb", CLK_DIV_B, CLK_PLL2_400, DIV_B, dtable_divb),
+ DEF_DIV_RO(".divd", CLK_DIV_D, CLK_PLL2_200, DIV_D, dtable_divd),
+ DEF_DIV_RO(".dive", CLK_DIV_E, CLK_PLL2_100, DIV_E, NULL),
+ DEF_DIV_RO(".divw", CLK_DIV_W, CLK_PLL4, DIV_W, dtable_divw),
+
+ DEF_MUX_RO(".selb", CLK_SEL_B, SEL_B, sel_b),
+ DEF_MUX_RO(".seld", CLK_SEL_D, SEL_D, sel_d),
+ DEF_MUX_RO(".sele", CLK_SEL_E, SEL_E, sel_e),
+ DEF_MUX(".selsdi", CLK_SEL_SDI, SEL_SDI, sel_sdi),
+ DEF_MUX(".selcsi0", CLK_SEL_CSI0, SEL_CSI0, sel_csi),
+ DEF_MUX(".selcsi4", CLK_SEL_CSI4, SEL_CSI4, sel_csi),
+ DEF_MUX(".selw0", CLK_SEL_W0, SEL_W0, sel_w),
+
+ DEF_FIXED(".selb_d2", CLK_SEL_B_D2, CLK_SEL_B, 1, 2),
+};
+
+static const struct rzg2l_mod_clk r9a09g011_mod_clks[] __initconst = {
+ DEF_MOD("pfc", R9A09G011_PFC_PCLK, CLK_MAIN, 0x400, 2, 0),
+ DEF_MOD("gic", R9A09G011_GIC_CLK, CLK_SEL_B_D2, 0x400, 5, 0),
+ DEF_MOD("sdi0_aclk", R9A09G011_SDI0_ACLK, CLK_SEL_D, 0x408, 0, 0),
+ DEF_MOD("sdi0_imclk", R9A09G011_SDI0_IMCLK, CLK_SEL_SDI, 0x408, 1, 0),
+ DEF_MOD("sdi0_imclk2", R9A09G011_SDI0_IMCLK2, CLK_SEL_SDI, 0x408, 2, 0),
+ DEF_MOD("sdi0_clk_hs", R9A09G011_SDI0_CLK_HS, CLK_PLL2_800, 0x408, 3, 0),
+ DEF_MOD("sdi1_aclk", R9A09G011_SDI1_ACLK, CLK_SEL_D, 0x408, 4, 0),
+ DEF_MOD("sdi1_imclk", R9A09G011_SDI1_IMCLK, CLK_SEL_SDI, 0x408, 5, 0),
+ DEF_MOD("sdi1_imclk2", R9A09G011_SDI1_IMCLK2, CLK_SEL_SDI, 0x408, 6, 0),
+ DEF_MOD("sdi1_clk_hs", R9A09G011_SDI1_CLK_HS, CLK_PLL2_800, 0x408, 7, 0),
+ DEF_MOD("emm_aclk", R9A09G011_EMM_ACLK, CLK_SEL_D, 0x408, 8, 0),
+ DEF_MOD("emm_imclk", R9A09G011_EMM_IMCLK, CLK_SEL_SDI, 0x408, 9, 0),
+ DEF_MOD("emm_imclk2", R9A09G011_EMM_IMCLK2, CLK_SEL_SDI, 0x408, 10, 0),
+ DEF_MOD("emm_clk_hs", R9A09G011_EMM_CLK_HS, CLK_PLL2_800, 0x408, 11, 0),
+ DEF_COUPLED("eth_axi", R9A09G011_ETH0_CLK_AXI, CLK_PLL2_200, 0x40c, 8, 0),
+ DEF_COUPLED("eth_chi", R9A09G011_ETH0_CLK_CHI, CLK_PLL2_100, 0x40c, 8, 0),
+ DEF_MOD("eth_clk_gptp", R9A09G011_ETH0_GPTP_EXT, CLK_PLL2_100, 0x40c, 9, 0),
+ DEF_MOD("usb_aclk_h", R9A09G011_USB_ACLK_H, CLK_SEL_D, 0x40c, 4, 0),
+ DEF_MOD("usb_aclk_p", R9A09G011_USB_ACLK_P, CLK_SEL_D, 0x40c, 5, 0),
+ DEF_MOD("usb_pclk", R9A09G011_USB_PCLK, CLK_SEL_E, 0x40c, 6, 0),
+ DEF_MOD("syc_cnt_clk", R9A09G011_SYC_CNT_CLK, CLK_MAIN_24, 0x41c, 12, 0),
+ DEF_MOD("iic_pclk0", R9A09G011_IIC_PCLK0, CLK_SEL_E, 0x420, 12, 0),
+ DEF_MOD("cperi_grpb", R9A09G011_CPERI_GRPB_PCLK, CLK_SEL_E, 0x424, 0, 0),
+ DEF_MOD("tim_clk_8", R9A09G011_TIM8_CLK, CLK_MAIN_2, 0x424, 4, 0),
+ DEF_MOD("tim_clk_9", R9A09G011_TIM9_CLK, CLK_MAIN_2, 0x424, 5, 0),
+ DEF_MOD("tim_clk_10", R9A09G011_TIM10_CLK, CLK_MAIN_2, 0x424, 6, 0),
+ DEF_MOD("tim_clk_11", R9A09G011_TIM11_CLK, CLK_MAIN_2, 0x424, 7, 0),
+ DEF_MOD("tim_clk_12", R9A09G011_TIM12_CLK, CLK_MAIN_2, 0x424, 8, 0),
+ DEF_MOD("tim_clk_13", R9A09G011_TIM13_CLK, CLK_MAIN_2, 0x424, 9, 0),
+ DEF_MOD("tim_clk_14", R9A09G011_TIM14_CLK, CLK_MAIN_2, 0x424, 10, 0),
+ DEF_MOD("tim_clk_15", R9A09G011_TIM15_CLK, CLK_MAIN_2, 0x424, 11, 0),
+ DEF_MOD("iic_pclk1", R9A09G011_IIC_PCLK1, CLK_SEL_E, 0x424, 12, 0),
+ DEF_MOD("cperi_grpc", R9A09G011_CPERI_GRPC_PCLK, CLK_SEL_E, 0x428, 0, 0),
+ DEF_MOD("tim_clk_16", R9A09G011_TIM16_CLK, CLK_MAIN_2, 0x428, 4, 0),
+ DEF_MOD("tim_clk_17", R9A09G011_TIM17_CLK, CLK_MAIN_2, 0x428, 5, 0),
+ DEF_MOD("tim_clk_18", R9A09G011_TIM18_CLK, CLK_MAIN_2, 0x428, 6, 0),
+ DEF_MOD("tim_clk_19", R9A09G011_TIM19_CLK, CLK_MAIN_2, 0x428, 7, 0),
+ DEF_MOD("tim_clk_20", R9A09G011_TIM20_CLK, CLK_MAIN_2, 0x428, 8, 0),
+ DEF_MOD("tim_clk_21", R9A09G011_TIM21_CLK, CLK_MAIN_2, 0x428, 9, 0),
+ DEF_MOD("tim_clk_22", R9A09G011_TIM22_CLK, CLK_MAIN_2, 0x428, 10, 0),
+ DEF_MOD("tim_clk_23", R9A09G011_TIM23_CLK, CLK_MAIN_2, 0x428, 11, 0),
+ DEF_MOD("wdt0_pclk", R9A09G011_WDT0_PCLK, CLK_SEL_E, 0x428, 12, 0),
+ DEF_MOD("wdt0_clk", R9A09G011_WDT0_CLK, CLK_MAIN, 0x428, 13, 0),
+ DEF_MOD("cperi_grpf", R9A09G011_CPERI_GRPF_PCLK, CLK_SEL_E, 0x434, 0, 0),
+ DEF_MOD("pwm8_clk", R9A09G011_PWM8_CLK, CLK_MAIN, 0x434, 4, 0),
+ DEF_MOD("pwm9_clk", R9A09G011_PWM9_CLK, CLK_MAIN, 0x434, 5, 0),
+ DEF_MOD("pwm10_clk", R9A09G011_PWM10_CLK, CLK_MAIN, 0x434, 6, 0),
+ DEF_MOD("pwm11_clk", R9A09G011_PWM11_CLK, CLK_MAIN, 0x434, 7, 0),
+ DEF_MOD("pwm12_clk", R9A09G011_PWM12_CLK, CLK_MAIN, 0x434, 8, 0),
+ DEF_MOD("pwm13_clk", R9A09G011_PWM13_CLK, CLK_MAIN, 0x434, 9, 0),
+ DEF_MOD("pwm14_clk", R9A09G011_PWM14_CLK, CLK_MAIN, 0x434, 10, 0),
+ DEF_MOD("cperi_grpg", R9A09G011_CPERI_GRPG_PCLK, CLK_SEL_E, 0x438, 0, 0),
+ DEF_MOD("cperi_grph", R9A09G011_CPERI_GRPH_PCLK, CLK_SEL_E, 0x438, 1, 0),
+ DEF_MOD("urt_pclk", R9A09G011_URT_PCLK, CLK_SEL_E, 0x438, 4, 0),
+ DEF_MOD("urt0_clk", R9A09G011_URT0_CLK, CLK_SEL_W0, 0x438, 5, 0),
+ DEF_MOD("csi0_clk", R9A09G011_CSI0_CLK, CLK_SEL_CSI0, 0x438, 8, 0),
+ DEF_MOD("csi4_clk", R9A09G011_CSI4_CLK, CLK_SEL_CSI4, 0x438, 12, 0),
+ DEF_MOD("ca53", R9A09G011_CA53_CLK, CLK_DIV_A, 0x448, 0, 0),
+};
+
+static const struct rzg2l_reset r9a09g011_resets[] = {
+ DEF_RST(R9A09G011_PFC_PRESETN, 0x600, 2),
+ DEF_RST_MON(R9A09G011_SDI0_IXRST, 0x608, 0, 6),
+ DEF_RST_MON(R9A09G011_SDI1_IXRST, 0x608, 1, 7),
+ DEF_RST_MON(R9A09G011_EMM_IXRST, 0x608, 2, 8),
+ DEF_RST(R9A09G011_USB_PRESET_N, 0x608, 7),
+ DEF_RST(R9A09G011_USB_DRD_RESET, 0x608, 8),
+ DEF_RST(R9A09G011_USB_ARESETN_P, 0x608, 9),
+ DEF_RST(R9A09G011_USB_ARESETN_H, 0x608, 10),
+ DEF_RST_MON(R9A09G011_ETH0_RST_HW_N, 0x608, 11, 11),
+ DEF_RST_MON(R9A09G011_SYC_RST_N, 0x610, 9, 13),
+ DEF_RST(R9A09G011_TIM_GPB_PRESETN, 0x614, 1),
+ DEF_RST(R9A09G011_TIM_GPC_PRESETN, 0x614, 2),
+ DEF_RST_MON(R9A09G011_PWM_GPF_PRESETN, 0x614, 5, 23),
+ DEF_RST_MON(R9A09G011_CSI_GPG_PRESETN, 0x614, 6, 22),
+ DEF_RST_MON(R9A09G011_CSI_GPH_PRESETN, 0x614, 7, 23),
+ DEF_RST(R9A09G011_IIC_GPA_PRESETN, 0x614, 8),
+ DEF_RST(R9A09G011_IIC_GPB_PRESETN, 0x614, 9),
+ DEF_RST_MON(R9A09G011_WDT0_PRESETN, 0x614, 12, 19),
+};
+
+static const unsigned int r9a09g011_crit_mod_clks[] __initconst = {
+ MOD_CLK_BASE + R9A09G011_CA53_CLK,
+ MOD_CLK_BASE + R9A09G011_CPERI_GRPB_PCLK,
+ MOD_CLK_BASE + R9A09G011_CPERI_GRPC_PCLK,
+ MOD_CLK_BASE + R9A09G011_CPERI_GRPF_PCLK,
+ MOD_CLK_BASE + R9A09G011_CPERI_GRPG_PCLK,
+ MOD_CLK_BASE + R9A09G011_CPERI_GRPH_PCLK,
+ MOD_CLK_BASE + R9A09G011_GIC_CLK,
+ MOD_CLK_BASE + R9A09G011_SYC_CNT_CLK,
+ MOD_CLK_BASE + R9A09G011_URT_PCLK,
+};
+
+const struct rzg2l_cpg_info r9a09g011_cpg_info = {
+ /* Core Clocks */
+ .core_clks = r9a09g011_core_clks,
+ .num_core_clks = ARRAY_SIZE(r9a09g011_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Critical Module Clocks */
+ .crit_mod_clks = r9a09g011_crit_mod_clks,
+ .num_crit_mod_clks = ARRAY_SIZE(r9a09g011_crit_mod_clks),
+
+ /* Module Clocks */
+ .mod_clks = r9a09g011_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r9a09g011_mod_clks),
+ .num_hw_mod_clks = R9A09G011_CA53_CLK + 1,
+
+ /* Resets */
+ .resets = r9a09g011_resets,
+ .num_resets = ARRAY_SIZE(r9a09g011_resets),
+
+ .has_clk_mon_regs = false,
+};
diff --git a/drivers/clk/renesas/r9a09g047-cpg.c b/drivers/clk/renesas/r9a09g047-cpg.c
new file mode 100644
index 000000000..94158b683
--- /dev/null
+++ b/drivers/clk/renesas/r9a09g047-cpg.c
@@ -0,0 +1,645 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G3E CPG driver
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/renesas,r9a09g047-cpg.h>
+
+#include "rzv2h-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A09G047_USB2_0_CLK_CORE1,
+
+ /* External Input Clocks */
+ CLK_AUDIO_EXTAL,
+ CLK_RTXIN,
+ CLK_QEXTAL,
+
+ /* PLL Clocks */
+ CLK_PLLCM33,
+ CLK_PLLCLN,
+ CLK_PLLDTY,
+ CLK_PLLCA55,
+ CLK_PLLVDO,
+ CLK_PLLETH,
+ CLK_PLLDSI0,
+ CLK_PLLDSI1,
+
+ /* Internal Core Clocks */
+ CLK_PLLCM33_DIV3,
+ CLK_PLLCM33_DIV4,
+ CLK_PLLCM33_DIV5,
+ CLK_PLLCM33_DIV16,
+ CLK_PLLCM33_GEAR,
+ CLK_SMUX2_XSPI_CLK0,
+ CLK_SMUX2_XSPI_CLK1,
+ CLK_PLLCM33_XSPI,
+ CLK_PLLCLN_DIV2,
+ CLK_PLLCLN_DIV8,
+ CLK_PLLCLN_DIV16,
+ CLK_PLLCLN_DIV20,
+ CLK_PLLCLN_DIV64,
+ CLK_PLLCLN_DIV256,
+ CLK_PLLCLN_DIV1024,
+ CLK_PLLDTY_ACPU,
+ CLK_PLLDTY_ACPU_DIV2,
+ CLK_PLLDTY_ACPU_DIV4,
+ CLK_PLLDTY_DIV8,
+ CLK_PLLDTY_RCPU,
+ CLK_PLLDTY_RCPU_DIV4,
+ CLK_PLLETH_DIV_250_FIX,
+ CLK_PLLETH_DIV_125_FIX,
+ CLK_CSDIV_PLLETH_GBE0,
+ CLK_CSDIV_PLLETH_GBE1,
+ CLK_SMUX2_DSI0_CLK,
+ CLK_SMUX2_DSI1_CLK,
+ CLK_SMUX2_GBE0_TXCLK,
+ CLK_SMUX2_GBE0_RXCLK,
+ CLK_SMUX2_GBE1_TXCLK,
+ CLK_SMUX2_GBE1_RXCLK,
+ CLK_PLLDTY_DIV16,
+ CLK_PLLVDO_CRU0,
+ CLK_PLLVDO_GPU,
+ CLK_PLLETH_DIV4_LPCLK,
+ CLK_PLLETH_LPCLK,
+ CLK_PLLDSI0_DIV7,
+ CLK_PLLDSI1_DIV7,
+ CLK_PLLDSI0_CSDIV,
+ CLK_PLLDSI1_CSDIV,
+
+ /* Module Clocks */
+ MOD_CLK_BASE,
+};
+
+static const struct clk_div_table dtable_1_8[] = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {3, 8},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_4[] = {
+ {0, 2},
+ {1, 4},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_16[] = {
+ {0, 2},
+ {1, 4},
+ {2, 8},
+ {3, 16},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_16_plldsi[] = {
+ {0, 2},
+ {1, 4},
+ {2, 6},
+ {3, 8},
+ {4, 10},
+ {5, 12},
+ {6, 14},
+ {7, 16},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_64[] = {
+ {0, 2},
+ {1, 4},
+ {2, 8},
+ {3, 16},
+ {4, 64},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_100[] = {
+ {0, 2},
+ {1, 10},
+ {2, 100},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_16_128[] = {
+ {0, 16},
+ {1, 32},
+ {2, 64},
+ {3, 128},
+ {0, 0},
+};
+
+RZG3E_CPG_PLL_DSI0_LIMITS(rzg3e_cpg_pll_dsi0_limits);
+RZG3E_CPG_PLL_DSI1_LIMITS(rzg3e_cpg_pll_dsi1_limits);
+
+#define PLLDSI0 PLL_PACK_LIMITS(0xc0, 1, 0, &rzg3e_cpg_pll_dsi0_limits)
+#define PLLDSI1 PLL_PACK_LIMITS(0x160, 1, 1, &rzg3e_cpg_pll_dsi1_limits)
+
+/* Mux clock tables */
+static const char * const smux2_dsi0_clk[] = { ".plldsi0_div7", ".plldsi0_csdiv" };
+static const char * const smux2_dsi1_clk[] = { ".plldsi1_div7", ".plldsi1_csdiv" };
+static const char * const smux2_gbe0_rxclk[] = { ".plleth_gbe0", "et0_rxclk" };
+static const char * const smux2_gbe0_txclk[] = { ".plleth_gbe0", "et0_txclk" };
+static const char * const smux2_gbe1_rxclk[] = { ".plleth_gbe1", "et1_rxclk" };
+static const char * const smux2_gbe1_txclk[] = { ".plleth_gbe1", "et1_txclk" };
+static const char * const smux2_xspi_clk0[] = { ".pllcm33_div3", ".pllcm33_div4" };
+static const char * const smux2_xspi_clk1[] = { ".smux2_xspi_clk0", ".pllcm33_div5" };
+
+static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("audio_extal", CLK_AUDIO_EXTAL),
+ DEF_INPUT("rtxin", CLK_RTXIN),
+ DEF_INPUT("qextal", CLK_QEXTAL),
+
+ /* PLL Clocks */
+ DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3),
+ DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
+ DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
+ DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
+ DEF_FIXED(".plleth", CLK_PLLETH, CLK_QEXTAL, 125, 3),
+ DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2),
+ DEF_PLLDSI(".plldsi0", CLK_PLLDSI0, CLK_QEXTAL, PLLDSI0),
+ DEF_PLLDSI(".plldsi1", CLK_PLLDSI1, CLK_QEXTAL, PLLDSI1),
+
+ /* Internal Core Clocks */
+ DEF_FIXED(".pllcm33_div3", CLK_PLLCM33_DIV3, CLK_PLLCM33, 1, 3),
+ DEF_FIXED(".pllcm33_div4", CLK_PLLCM33_DIV4, CLK_PLLCM33, 1, 4),
+ DEF_FIXED(".pllcm33_div5", CLK_PLLCM33_DIV5, CLK_PLLCM33, 1, 5),
+ DEF_FIXED(".pllcm33_div16", CLK_PLLCM33_DIV16, CLK_PLLCM33, 1, 16),
+
+ DEF_DDIV(".pllcm33_gear", CLK_PLLCM33_GEAR, CLK_PLLCM33_DIV4, CDDIV0_DIVCTL1, dtable_2_64),
+
+ DEF_SMUX(".smux2_xspi_clk0", CLK_SMUX2_XSPI_CLK0, SSEL1_SELCTL2, smux2_xspi_clk0),
+ DEF_SMUX(".smux2_xspi_clk1", CLK_SMUX2_XSPI_CLK1, SSEL1_SELCTL3, smux2_xspi_clk1),
+ DEF_CSDIV(".pllcm33_xspi", CLK_PLLCM33_XSPI, CLK_SMUX2_XSPI_CLK1, CSDIV0_DIVCTL3,
+ dtable_2_16),
+ DEF_FIXED(".pllcln_div2", CLK_PLLCLN_DIV2, CLK_PLLCLN, 1, 2),
+ DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8),
+ DEF_FIXED(".pllcln_div16", CLK_PLLCLN_DIV16, CLK_PLLCLN, 1, 16),
+ DEF_FIXED(".pllcln_div20", CLK_PLLCLN_DIV20, CLK_PLLCLN, 1, 20),
+ DEF_FIXED(".pllcln_div64", CLK_PLLCLN_DIV64, CLK_PLLCLN, 1, 64),
+ DEF_FIXED(".pllcln_div256", CLK_PLLCLN_DIV256, CLK_PLLCLN, 1, 256),
+ DEF_FIXED(".pllcln_div1024", CLK_PLLCLN_DIV1024, CLK_PLLCLN, 1, 1024),
+
+ DEF_DDIV(".plldty_acpu", CLK_PLLDTY_ACPU, CLK_PLLDTY, CDDIV0_DIVCTL2, dtable_2_64),
+ DEF_FIXED(".plldty_acpu_div2", CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU, 1, 2),
+ DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4),
+ DEF_FIXED(".plldty_div8", CLK_PLLDTY_DIV8, CLK_PLLDTY, 1, 8),
+
+ DEF_FIXED(".plleth_250_fix", CLK_PLLETH_DIV_250_FIX, CLK_PLLETH, 1, 4),
+ DEF_FIXED(".plleth_125_fix", CLK_PLLETH_DIV_125_FIX, CLK_PLLETH_DIV_250_FIX, 1, 2),
+ DEF_CSDIV(".plleth_gbe0", CLK_CSDIV_PLLETH_GBE0, CLK_PLLETH_DIV_250_FIX,
+ CSDIV0_DIVCTL0, dtable_2_100),
+ DEF_CSDIV(".plleth_gbe1", CLK_CSDIV_PLLETH_GBE1, CLK_PLLETH_DIV_250_FIX,
+ CSDIV0_DIVCTL1, dtable_2_100),
+ DEF_SMUX(".smux2_gbe0_txclk", CLK_SMUX2_GBE0_TXCLK, SSEL0_SELCTL2, smux2_gbe0_txclk),
+ DEF_SMUX(".smux2_gbe0_rxclk", CLK_SMUX2_GBE0_RXCLK, SSEL0_SELCTL3, smux2_gbe0_rxclk),
+ DEF_SMUX(".smux2_gbe1_txclk", CLK_SMUX2_GBE1_TXCLK, SSEL1_SELCTL0, smux2_gbe1_txclk),
+ DEF_SMUX(".smux2_gbe1_rxclk", CLK_SMUX2_GBE1_RXCLK, SSEL1_SELCTL1, smux2_gbe1_rxclk),
+ DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16),
+ DEF_DDIV(".plldty_rcpu", CLK_PLLDTY_RCPU, CLK_PLLDTY, CDDIV3_DIVCTL2, dtable_2_64),
+ DEF_FIXED(".plldty_rcpu_div4", CLK_PLLDTY_RCPU_DIV4, CLK_PLLDTY_RCPU, 1, 4),
+
+ DEF_DDIV(".pllvdo_cru0", CLK_PLLVDO_CRU0, CLK_PLLVDO, CDDIV3_DIVCTL3, dtable_2_4),
+ DEF_DDIV(".pllvdo_gpu", CLK_PLLVDO_GPU, CLK_PLLVDO, CDDIV3_DIVCTL1, dtable_2_64),
+
+ DEF_FIXED(".plleth_div4_lpclk", CLK_PLLETH_DIV4_LPCLK, CLK_PLLETH, 1, 4),
+ DEF_CSDIV(".plleth_lpclk", CLK_PLLETH_LPCLK, CLK_PLLETH_DIV4_LPCLK,
+ CSDIV0_DIVCTL2, dtable_16_128),
+
+ DEF_PLLDSI_DIV(".plldsi0_csdiv", CLK_PLLDSI0_CSDIV, CLK_PLLDSI0,
+ CSDIV1_DIVCTL2, dtable_2_16_plldsi),
+ DEF_PLLDSI_DIV(".plldsi1_csdiv", CLK_PLLDSI1_CSDIV, CLK_PLLDSI1,
+ CSDIV1_DIVCTL3, dtable_2_16_plldsi),
+ DEF_FIXED(".plldsi0_div7", CLK_PLLDSI0_DIV7, CLK_PLLDSI0, 1, 7),
+ DEF_FIXED(".plldsi1_div7", CLK_PLLDSI1_DIV7, CLK_PLLDSI1, 1, 7),
+ DEF_PLLDSI_SMUX(".smux2_dsi0_clk", CLK_SMUX2_DSI0_CLK,
+ SSEL3_SELCTL0, smux2_dsi0_clk),
+ DEF_PLLDSI_SMUX(".smux2_dsi1_clk", CLK_SMUX2_DSI1_CLK,
+ SSEL3_SELCTL1, smux2_dsi1_clk),
+
+ /* Core Clocks */
+ DEF_FIXED("sys_0_pclk", R9A09G047_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
+ DEF_DDIV("ca55_0_coreclk0", R9A09G047_CA55_0_CORECLK0, CLK_PLLCA55,
+ CDDIV1_DIVCTL0, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk1", R9A09G047_CA55_0_CORECLK1, CLK_PLLCA55,
+ CDDIV1_DIVCTL1, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk2", R9A09G047_CA55_0_CORECLK2, CLK_PLLCA55,
+ CDDIV1_DIVCTL2, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk3", R9A09G047_CA55_0_CORECLK3, CLK_PLLCA55,
+ CDDIV1_DIVCTL3, dtable_1_8),
+ DEF_FIXED("iotop_0_shclk", R9A09G047_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
+ DEF_FIXED("spi_clk_spi", R9A09G047_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2),
+ DEF_FIXED("usb2_0_clk_core0", R9A09G047_USB2_0_CLK_CORE0, CLK_QEXTAL, 1, 1),
+ DEF_FIXED("usb2_0_clk_core1", R9A09G047_USB2_0_CLK_CORE1, CLK_QEXTAL, 1, 1),
+ DEF_FIXED("gbeth_0_clk_ptp_ref_i", R9A09G047_GBETH_0_CLK_PTP_REF_I,
+ CLK_PLLETH_DIV_125_FIX, 1, 1),
+ DEF_FIXED("gbeth_1_clk_ptp_ref_i", R9A09G047_GBETH_1_CLK_PTP_REF_I,
+ CLK_PLLETH_DIV_125_FIX, 1, 1),
+ DEF_FIXED("usb3_0_ref_alt_clk_p", R9A09G047_USB3_0_REF_ALT_CLK_P, CLK_QEXTAL, 1, 1),
+ DEF_FIXED("usb3_0_core_clk", R9A09G047_USB3_0_CLKCORE, CLK_QEXTAL, 1, 1),
+};
+
+static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = {
+ DEF_MOD("dmac_0_aclk", CLK_PLLCM33_GEAR, 0, 0, 0, 0,
+ BUS_MSTOP(5, BIT(9))),
+ DEF_MOD("dmac_1_aclk", CLK_PLLDTY_ACPU_DIV2, 0, 1, 0, 1,
+ BUS_MSTOP(3, BIT(2))),
+ DEF_MOD("dmac_2_aclk", CLK_PLLDTY_ACPU_DIV2, 0, 2, 0, 2,
+ BUS_MSTOP(3, BIT(3))),
+ DEF_MOD("dmac_3_aclk", CLK_PLLDTY_RCPU_DIV4, 0, 3, 0, 3,
+ BUS_MSTOP(10, BIT(11))),
+ DEF_MOD("dmac_4_aclk", CLK_PLLDTY_RCPU_DIV4, 0, 4, 0, 4,
+ BUS_MSTOP(10, BIT(12))),
+ DEF_MOD_CRITICAL("icu_0_pclk_i", CLK_PLLCM33_DIV16, 0, 5, 0, 5,
+ BUS_MSTOP_NONE),
+ DEF_MOD_CRITICAL("gic_0_gicclk", CLK_PLLDTY_ACPU_DIV4, 1, 3, 0, 19,
+ BUS_MSTOP(3, BIT(5))),
+ DEF_MOD("gpt_0_pclk_sfr", CLK_PLLCLN_DIV8, 3, 1, 1, 17,
+ BUS_MSTOP(6, BIT(11))),
+ DEF_MOD("gpt_1_pclk_sfr", CLK_PLLCLN_DIV8, 3, 2, 1, 18,
+ BUS_MSTOP(6, BIT(12))),
+ DEF_MOD("wdt_1_clkp", CLK_PLLCLN_DIV16, 4, 13, 2, 13,
+ BUS_MSTOP(1, BIT(0))),
+ DEF_MOD("wdt_1_clk_loco", CLK_QEXTAL, 4, 14, 2, 14,
+ BUS_MSTOP(1, BIT(0))),
+ DEF_MOD("wdt_2_clkp", CLK_PLLCLN_DIV16, 4, 15, 2, 15,
+ BUS_MSTOP(5, BIT(12))),
+ DEF_MOD("wdt_2_clk_loco", CLK_QEXTAL, 5, 0, 2, 16,
+ BUS_MSTOP(5, BIT(12))),
+ DEF_MOD("wdt_3_clkp", CLK_PLLCLN_DIV16, 5, 1, 2, 17,
+ BUS_MSTOP(5, BIT(13))),
+ DEF_MOD("wdt_3_clk_loco", CLK_QEXTAL, 5, 2, 2, 18,
+ BUS_MSTOP(5, BIT(13))),
+ DEF_MOD("rspi_0_pclk", CLK_PLLCLN_DIV8, 5, 4, 2, 20,
+ BUS_MSTOP(11, BIT(0))),
+ DEF_MOD("rspi_0_pclk_sfr", CLK_PLLCLN_DIV8, 5, 5, 2, 21,
+ BUS_MSTOP(11, BIT(0))),
+ DEF_MOD("rspi_0_tclk", CLK_PLLCLN_DIV8, 5, 6, 2, 22,
+ BUS_MSTOP(11, BIT(0))),
+ DEF_MOD("rspi_1_pclk", CLK_PLLCLN_DIV8, 5, 7, 2, 23,
+ BUS_MSTOP(11, BIT(1))),
+ DEF_MOD("rspi_1_pclk_sfr", CLK_PLLCLN_DIV8, 5, 8, 2, 24,
+ BUS_MSTOP(11, BIT(1))),
+ DEF_MOD("rspi_1_tclk", CLK_PLLCLN_DIV8, 5, 9, 2, 25,
+ BUS_MSTOP(11, BIT(1))),
+ DEF_MOD("rspi_2_pclk", CLK_PLLCLN_DIV8, 5, 10, 2, 26,
+ BUS_MSTOP(11, BIT(2))),
+ DEF_MOD("rspi_2_pclk_sfr", CLK_PLLCLN_DIV8, 5, 11, 2, 27,
+ BUS_MSTOP(11, BIT(2))),
+ DEF_MOD("rspi_2_tclk", CLK_PLLCLN_DIV8, 5, 12, 2, 28,
+ BUS_MSTOP(11, BIT(2))),
+ DEF_MOD("rsci0_pclk", CLK_PLLCLN_DIV16, 5, 13, 2, 29,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_tclk", CLK_PLLCLN_DIV16, 5, 14, 2, 30,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_ps_ps3_n", CLK_PLLCLN_DIV1024, 5, 15, 2, 31,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 0, 3, 0,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 1, 3, 1,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci1_pclk", CLK_PLLCLN_DIV16, 6, 2, 3, 2,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_tclk", CLK_PLLCLN_DIV16, 6, 3, 3, 3,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 4, 3, 4,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 5, 3, 5,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 6, 3, 6,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci2_pclk", CLK_PLLCLN_DIV16, 6, 7, 3, 7,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_tclk", CLK_PLLCLN_DIV16, 6, 8, 3, 8,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 9, 3, 9,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 10, 3, 10,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 11, 3, 11,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci3_pclk", CLK_PLLCLN_DIV16, 6, 12, 3, 12,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_tclk", CLK_PLLCLN_DIV16, 6, 13, 3, 13,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 14, 3, 14,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 15, 3, 15,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 0, 3, 16,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci4_pclk", CLK_PLLCLN_DIV16, 7, 1, 3, 17,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_tclk", CLK_PLLCLN_DIV16, 7, 2, 3, 18,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 3, 3, 19,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 4, 3, 20,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 5, 3, 21,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci5_pclk", CLK_PLLCLN_DIV16, 7, 6, 3, 22,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_tclk", CLK_PLLCLN_DIV16, 7, 7, 3, 23,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 8, 3, 24,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 9, 3, 25,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 10, 3, 26,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci6_pclk", CLK_PLLCLN_DIV16, 7, 11, 3, 27,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_tclk", CLK_PLLCLN_DIV16, 7, 12, 3, 28,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 13, 3, 29,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 14, 3, 30,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 15, 3, 31,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci7_pclk", CLK_PLLCLN_DIV16, 8, 0, 4, 0,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_tclk", CLK_PLLCLN_DIV16, 8, 1, 4, 1,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 2, 4, 2,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 3, 4, 3,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 4, 4, 4,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci8_pclk", CLK_PLLCLN_DIV16, 8, 5, 4, 5,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_tclk", CLK_PLLCLN_DIV16, 8, 6, 4, 6,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 7, 4, 7,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 8, 4, 8,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 9, 4, 9,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci9_pclk", CLK_PLLCLN_DIV16, 8, 10, 4, 10,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_tclk", CLK_PLLCLN_DIV16, 8, 11, 4, 11,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 12, 4, 12,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 13, 4, 13,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 14, 4, 14,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("scif_0_clk_pck", CLK_PLLCM33_DIV16, 8, 15, 4, 15,
+ BUS_MSTOP(3, BIT(14))),
+ DEF_MOD("i3c_0_pclkrw", CLK_PLLCLN_DIV16, 9, 0, 4, 16,
+ BUS_MSTOP(10, BIT(15))),
+ DEF_MOD("i3c_0_pclk", CLK_PLLCLN_DIV16, 9, 1, 4, 17,
+ BUS_MSTOP(10, BIT(15))),
+ DEF_MOD("i3c_0_tclk", CLK_PLLCLN_DIV8, 9, 2, 4, 18,
+ BUS_MSTOP(10, BIT(15))),
+ DEF_MOD("riic_8_ckm", CLK_PLLCM33_DIV16, 9, 3, 4, 19,
+ BUS_MSTOP(3, BIT(13))),
+ DEF_MOD("riic_0_ckm", CLK_PLLCLN_DIV16, 9, 4, 4, 20,
+ BUS_MSTOP(1, BIT(1))),
+ DEF_MOD("riic_1_ckm", CLK_PLLCLN_DIV16, 9, 5, 4, 21,
+ BUS_MSTOP(1, BIT(2))),
+ DEF_MOD("riic_2_ckm", CLK_PLLCLN_DIV16, 9, 6, 4, 22,
+ BUS_MSTOP(1, BIT(3))),
+ DEF_MOD("riic_3_ckm", CLK_PLLCLN_DIV16, 9, 7, 4, 23,
+ BUS_MSTOP(1, BIT(4))),
+ DEF_MOD("riic_4_ckm", CLK_PLLCLN_DIV16, 9, 8, 4, 24,
+ BUS_MSTOP(1, BIT(5))),
+ DEF_MOD("riic_5_ckm", CLK_PLLCLN_DIV16, 9, 9, 4, 25,
+ BUS_MSTOP(1, BIT(6))),
+ DEF_MOD("riic_6_ckm", CLK_PLLCLN_DIV16, 9, 10, 4, 26,
+ BUS_MSTOP(1, BIT(7))),
+ DEF_MOD("riic_7_ckm", CLK_PLLCLN_DIV16, 9, 11, 4, 27,
+ BUS_MSTOP(1, BIT(8))),
+ DEF_MOD("canfd_0_pclk", CLK_PLLCLN_DIV16, 9, 12, 4, 28,
+ BUS_MSTOP(10, BIT(14))),
+ DEF_MOD("canfd_0_clk_ram", CLK_PLLCLN_DIV8, 9, 13, 4, 29,
+ BUS_MSTOP(10, BIT(14))),
+ DEF_MOD("canfd_0_clkc", CLK_PLLCLN_DIV20, 9, 14, 4, 30,
+ BUS_MSTOP(10, BIT(14))),
+ DEF_MOD("spi_hclk", CLK_PLLCM33_GEAR, 9, 15, 4, 31,
+ BUS_MSTOP(4, BIT(5))),
+ DEF_MOD("spi_aclk", CLK_PLLCM33_GEAR, 10, 0, 5, 0,
+ BUS_MSTOP(4, BIT(5))),
+ DEF_MOD_NO_PM("spi_clk_spix2", CLK_PLLCM33_XSPI, 10, 1, 5, 2,
+ BUS_MSTOP(4, BIT(5))),
+ DEF_MOD("sdhi_0_imclk", CLK_PLLCLN_DIV8, 10, 3, 5, 3,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_0_imclk2", CLK_PLLCLN_DIV8, 10, 4, 5, 4,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_0_clk_hs", CLK_PLLCLN_DIV2, 10, 5, 5, 5,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_0_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 6, 5, 6,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_1_imclk", CLK_PLLCLN_DIV8, 10, 7, 5, 7,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_1_imclk2", CLK_PLLCLN_DIV8, 10, 8, 5, 8,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_1_clk_hs", CLK_PLLCLN_DIV2, 10, 9, 5, 9,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_1_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 10, 5, 10,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_2_imclk", CLK_PLLCLN_DIV8, 10, 11, 5, 11,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("sdhi_2_imclk2", CLK_PLLCLN_DIV8, 10, 12, 5, 12,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("sdhi_2_clk_hs", CLK_PLLCLN_DIV2, 10, 13, 5, 13,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("usb3_0_aclk", CLK_PLLDTY_DIV8, 10, 15, 5, 15,
+ BUS_MSTOP(7, BIT(12))),
+ DEF_MOD("usb3_0_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 0, 5, 16,
+ BUS_MSTOP(7, BIT(14))),
+ DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19,
+ BUS_MSTOP(7, BIT(7))),
+ DEF_MOD("usb2_0_u2h1_hclk", CLK_PLLDTY_DIV8, 11, 4, 5, 20,
+ BUS_MSTOP(7, BIT(8))),
+ DEF_MOD("usb2_0_u2p_exr_cpuclk", CLK_PLLDTY_ACPU_DIV4, 11, 5, 5, 21,
+ BUS_MSTOP(7, BIT(9))),
+ DEF_MOD("usb2_0_pclk_usbtst0", CLK_PLLDTY_ACPU_DIV4, 11, 6, 5, 22,
+ BUS_MSTOP(7, BIT(10))),
+ DEF_MOD("usb2_0_pclk_usbtst1", CLK_PLLDTY_ACPU_DIV4, 11, 7, 5, 23,
+ BUS_MSTOP(7, BIT(11))),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_tx_i", CLK_SMUX2_GBE0_TXCLK, 11, 8, 5, 24,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_rx_i", CLK_SMUX2_GBE0_RXCLK, 11, 9, 5, 25,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_tx_180_i", CLK_SMUX2_GBE0_TXCLK, 11, 10, 5, 26,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_rx_180_i", CLK_SMUX2_GBE0_RXCLK, 11, 11, 5, 27,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD("gbeth_0_aclk_csr_i", CLK_PLLDTY_DIV8, 11, 12, 5, 28,
+ BUS_MSTOP(8, BIT(5))),
+ DEF_MOD("gbeth_0_aclk_i", CLK_PLLDTY_DIV8, 11, 13, 5, 29,
+ BUS_MSTOP(8, BIT(5))),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_tx_i", CLK_SMUX2_GBE1_TXCLK, 11, 14, 5, 30,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_rx_i", CLK_SMUX2_GBE1_RXCLK, 11, 15, 5, 31,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_tx_180_i", CLK_SMUX2_GBE1_TXCLK, 12, 0, 6, 0,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_rx_180_i", CLK_SMUX2_GBE1_RXCLK, 12, 1, 6, 1,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD("gbeth_1_aclk_csr_i", CLK_PLLDTY_DIV8, 12, 2, 6, 2,
+ BUS_MSTOP(8, BIT(6))),
+ DEF_MOD("gbeth_1_aclk_i", CLK_PLLDTY_DIV8, 12, 3, 6, 3,
+ BUS_MSTOP(8, BIT(6))),
+ DEF_MOD("pcie_0_aclk", CLK_PLLDTY_ACPU_DIV2, 12, 4, 6, 4,
+ BUS_MSTOP(1, BIT(15))),
+ DEF_MOD("pcie_0_clk_pmu", CLK_PLLDTY_ACPU_DIV2, 12, 5, 6, 5,
+ BUS_MSTOP(1, BIT(15))),
+ DEF_MOD("cru_0_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 2, 6, 18,
+ BUS_MSTOP(9, BIT(4))),
+ DEF_MOD_NO_PM("cru_0_vclk", CLK_PLLVDO_CRU0, 13, 3, 6, 19,
+ BUS_MSTOP(9, BIT(4))),
+ DEF_MOD("cru_0_pclk", CLK_PLLDTY_DIV16, 13, 4, 6, 20,
+ BUS_MSTOP(9, BIT(4))),
+ DEF_MOD("dsi_0_pclk", CLK_PLLDTY_DIV16, 14, 8, 7, 8,
+ BUS_MSTOP(9, BIT(15) | BIT(14))),
+ DEF_MOD("dsi_0_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 9, 7, 9,
+ BUS_MSTOP(9, BIT(15) | BIT(14))),
+ DEF_MOD("dsi_0_vclk1", CLK_SMUX2_DSI0_CLK, 14, 10, 7, 10,
+ BUS_MSTOP(9, BIT(15) | BIT(14))),
+ DEF_MOD("dsi_0_lpclk", CLK_PLLETH_LPCLK, 14, 11, 7, 11,
+ BUS_MSTOP(9, BIT(15) | BIT(14))),
+ DEF_MOD("dsi_0_pllref_clk", CLK_QEXTAL, 14, 12, 7, 12,
+ BUS_MSTOP(9, BIT(15) | BIT(14))),
+ DEF_MOD("lcdc_0_clk_a", CLK_PLLDTY_ACPU_DIV2, 14, 13, 7, 13,
+ BUS_MSTOP(10, BIT(3) | BIT(2) | BIT(1))),
+ DEF_MOD("lcdc_0_clk_p", CLK_PLLDTY_DIV16, 14, 14, 7, 14,
+ BUS_MSTOP(10, BIT(3) | BIT(2) | BIT(1))),
+ DEF_MOD("lcdc_0_clk_d", CLK_SMUX2_DSI0_CLK, 14, 15, 7, 15,
+ BUS_MSTOP(10, BIT(3) | BIT(2) | BIT(1))),
+ DEF_MOD("ge3d_clk", CLK_PLLVDO_GPU, 15, 0, 7, 16,
+ BUS_MSTOP(3, BIT(4))),
+ DEF_MOD("ge3d_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17,
+ BUS_MSTOP(3, BIT(4))),
+ DEF_MOD("ge3d_ace_clk", CLK_PLLDTY_ACPU_DIV2, 15, 2, 7, 18,
+ BUS_MSTOP(3, BIT(4))),
+ DEF_MOD("tsu_1_pclk", CLK_QEXTAL, 16, 10, 8, 10,
+ BUS_MSTOP(2, BIT(15))),
+ DEF_MOD("dsi_0_vclk2", CLK_SMUX2_DSI1_CLK, 25, 0, 10, 21,
+ BUS_MSTOP(9, BIT(15) | BIT(14))),
+ DEF_MOD("lcdc_1_clk_a", CLK_PLLDTY_ACPU_DIV2, 26, 8, 10, 30,
+ BUS_MSTOP(13, BIT(5) | BIT(4) | BIT(3))),
+ DEF_MOD("lcdc_1_clk_p", CLK_PLLDTY_DIV16, 26, 9, 10, 31,
+ BUS_MSTOP(13, BIT(5) | BIT(4) | BIT(3))),
+ DEF_MOD("lcdc_1_clk_d", CLK_SMUX2_DSI1_CLK, 26, 10, 11, 0,
+ BUS_MSTOP(13, BIT(5) | BIT(4) | BIT(3))),
+};
+
+static const struct rzv2h_reset r9a09g047_resets[] __initconst = {
+ DEF_RST(3, 0, 1, 1), /* SYS_0_PRESETN */
+ DEF_RST(3, 1, 1, 2), /* DMAC_0_ARESETN */
+ DEF_RST(3, 2, 1, 3), /* DMAC_1_ARESETN */
+ DEF_RST(3, 3, 1, 4), /* DMAC_2_ARESETN */
+ DEF_RST(3, 4, 1, 5), /* DMAC_3_ARESETN */
+ DEF_RST(3, 5, 1, 6), /* DMAC_4_ARESETN */
+ DEF_RST(3, 6, 1, 7), /* ICU_0_PRESETN_I */
+ DEF_RST(3, 8, 1, 9), /* GIC_0_GICRESET_N */
+ DEF_RST(3, 9, 1, 10), /* GIC_0_DBG_GICRESET_N */
+ DEF_RST(5, 9, 2, 10), /* GPT_0_RST_P_REG */
+ DEF_RST(5, 10, 2, 11), /* GPT_0_RST_S_REG */
+ DEF_RST(5, 11, 2, 12), /* GPT_1_RST_P_REG */
+ DEF_RST(5, 12, 2, 13), /* GPT_1_RST_S_REG */
+ DEF_RST(7, 6, 3, 7), /* WDT_1_RESET */
+ DEF_RST(7, 7, 3, 8), /* WDT_2_RESET */
+ DEF_RST(7, 8, 3, 9), /* WDT_3_RESET */
+ DEF_RST(7, 11, 3, 12), /* RSPI_0_PRESETN */
+ DEF_RST(7, 12, 3, 13), /* RSPI_0_TRESETN */
+ DEF_RST(7, 13, 3, 14), /* RSPI_1_PRESETN */
+ DEF_RST(7, 14, 3, 15), /* RSPI_1_TRESETN */
+ DEF_RST(7, 15, 3, 16), /* RSPI_2_PRESETN */
+ DEF_RST(8, 0, 3, 17), /* RSPI_2_TRESETN */
+ DEF_RST(8, 1, 3, 18), /* RSCI0_PRESETN */
+ DEF_RST(8, 2, 3, 19), /* RSCI0_TRESETN */
+ DEF_RST(8, 3, 3, 20), /* RSCI1_PRESETN */
+ DEF_RST(8, 4, 3, 21), /* RSCI1_TRESETN */
+ DEF_RST(8, 5, 3, 22), /* RSCI2_PRESETN */
+ DEF_RST(8, 6, 3, 23), /* RSCI2_TRESETN */
+ DEF_RST(8, 7, 3, 24), /* RSCI3_PRESETN */
+ DEF_RST(8, 8, 3, 25), /* RSCI3_TRESETN */
+ DEF_RST(8, 9, 3, 26), /* RSCI4_PRESETN */
+ DEF_RST(8, 10, 3, 27), /* RSCI4_TRESETN */
+ DEF_RST(8, 11, 3, 28), /* RSCI5_PRESETN */
+ DEF_RST(8, 12, 3, 29), /* RSCI5_TRESETN */
+ DEF_RST(8, 13, 3, 30), /* RSCI6_PRESETN */
+ DEF_RST(8, 14, 3, 31), /* RSCI6_TRESETN */
+ DEF_RST(8, 15, 4, 0), /* RSCI7_PRESETN */
+ DEF_RST(9, 0, 4, 1), /* RSCI7_TRESETN */
+ DEF_RST(9, 1, 4, 2), /* RSCI8_PRESETN */
+ DEF_RST(9, 2, 4, 3), /* RSCI8_TRESETN */
+ DEF_RST(9, 3, 4, 4), /* RSCI9_PRESETN */
+ DEF_RST(9, 4, 4, 5), /* RSCI9_TRESETN */
+ DEF_RST(9, 5, 4, 6), /* SCIF_0_RST_SYSTEM_N */
+ DEF_RST(9, 6, 4, 7), /* I3C_0_PRESETN */
+ DEF_RST(9, 7, 4, 8), /* I3C_0_TRESETN */
+ DEF_RST(9, 8, 4, 9), /* RIIC_0_MRST */
+ DEF_RST(9, 9, 4, 10), /* RIIC_1_MRST */
+ DEF_RST(9, 10, 4, 11), /* RIIC_2_MRST */
+ DEF_RST(9, 11, 4, 12), /* RIIC_3_MRST */
+ DEF_RST(9, 12, 4, 13), /* RIIC_4_MRST */
+ DEF_RST(9, 13, 4, 14), /* RIIC_5_MRST */
+ DEF_RST(9, 14, 4, 15), /* RIIC_6_MRST */
+ DEF_RST(9, 15, 4, 16), /* RIIC_7_MRST */
+ DEF_RST(10, 0, 4, 17), /* RIIC_8_MRST */
+ DEF_RST(10, 1, 4, 18), /* CANFD_0_RSTP_N */
+ DEF_RST(10, 2, 4, 19), /* CANFD_0_RSTC_N */
+ DEF_RST(10, 3, 4, 20), /* SPI_HRESETN */
+ DEF_RST(10, 4, 4, 21), /* SPI_ARESETN */
+ DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
+ DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
+ DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
+ DEF_RST(10, 10, 4, 27), /* USB3_0_ARESETN */
+ DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */
+ DEF_RST(10, 13, 4, 30), /* USB2_0_U2H1_HRESETN */
+ DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */
+ DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */
+ DEF_RST(11, 0, 5, 1), /* GBETH_0_ARESETN_I */
+ DEF_RST(11, 1, 5, 2), /* GBETH_1_ARESETN_I */
+ DEF_RST(11, 2, 5, 3), /* PCIE_0_ARESETN */
+ DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */
+ DEF_RST(12, 6, 5, 23), /* CRU_0_ARESETN */
+ DEF_RST(12, 7, 5, 24), /* CRU_0_S_RESETN */
+ DEF_RST(13, 7, 6, 8), /* DSI_0_PRESETN */
+ DEF_RST(13, 8, 6, 9), /* DSI_0_ARESETN */
+ DEF_RST(13, 12, 6, 13), /* LCDC_0_RESET_N */
+ DEF_RST(13, 13, 6, 14), /* GE3D_RESETN */
+ DEF_RST(13, 14, 6, 15), /* GE3D_AXI_RESETN */
+ DEF_RST(13, 15, 6, 16), /* GE3D_ACE_RESETN */
+ DEF_RST(15, 8, 7, 9), /* TSU_1_PRESETN */
+ DEF_RST(17, 14, 8, 15), /* LCDC_1_RESET_N */
+};
+
+const struct rzv2h_cpg_info r9a09g047_cpg_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r9a09g047_core_clks,
+ .num_core_clks = ARRAY_SIZE(r9a09g047_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r9a09g047_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r9a09g047_mod_clks),
+ .num_hw_mod_clks = 28 * 16,
+
+ /* Resets */
+ .resets = r9a09g047_resets,
+ .num_resets = ARRAY_SIZE(r9a09g047_resets),
+
+ .num_mstop_bits = 208,
+};
diff --git a/drivers/clk/renesas/r9a09g056-cpg.c b/drivers/clk/renesas/r9a09g056-cpg.c
new file mode 100644
index 000000000..51c1e3228
--- /dev/null
+++ b/drivers/clk/renesas/r9a09g056-cpg.c
@@ -0,0 +1,658 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/V2N CPG driver
+ *
+ * Copyright (C) 2025 Renesas Electronics Corp.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/renesas,r9a09g056-cpg.h>
+
+#include "rzv2h-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A09G056_USB3_0_CLKCORE,
+
+ /* External Input Clocks */
+ CLK_AUDIO_EXTAL,
+ CLK_RTXIN,
+ CLK_QEXTAL,
+
+ /* PLL Clocks */
+ CLK_PLLCM33,
+ CLK_PLLCLN,
+ CLK_PLLDTY,
+ CLK_PLLCA55,
+ CLK_PLLVDO,
+ CLK_PLLETH,
+ CLK_PLLDSI,
+ CLK_PLLGPU,
+
+ /* Internal Core Clocks */
+ CLK_PLLCM33_DIV3,
+ CLK_PLLCM33_DIV4,
+ CLK_PLLCM33_DIV5,
+ CLK_PLLCM33_DIV16,
+ CLK_PLLCM33_GEAR,
+ CLK_SMUX2_XSPI_CLK0,
+ CLK_SMUX2_XSPI_CLK1,
+ CLK_PLLCM33_XSPI,
+ CLK_PLLCLN_DIV2,
+ CLK_PLLCLN_DIV8,
+ CLK_PLLCLN_DIV16,
+ CLK_PLLCLN_DIV20,
+ CLK_PLLCLN_DIV64,
+ CLK_PLLCLN_DIV256,
+ CLK_PLLCLN_DIV1024,
+ CLK_PLLDTY_ACPU,
+ CLK_PLLDTY_ACPU_DIV2,
+ CLK_PLLDTY_ACPU_DIV4,
+ CLK_PLLDTY_DIV8,
+ CLK_PLLDTY_DIV16,
+ CLK_PLLDTY_RCPU,
+ CLK_PLLDTY_RCPU_DIV4,
+ CLK_PLLVDO_CRU0,
+ CLK_PLLVDO_CRU1,
+ CLK_PLLVDO_ISP,
+ CLK_PLLETH_DIV_250_FIX,
+ CLK_PLLETH_DIV_125_FIX,
+ CLK_CSDIV_PLLETH_GBE0,
+ CLK_CSDIV_PLLETH_GBE1,
+ CLK_SMUX2_GBE0_TXCLK,
+ CLK_SMUX2_GBE0_RXCLK,
+ CLK_SMUX2_GBE1_TXCLK,
+ CLK_SMUX2_GBE1_RXCLK,
+ CLK_CDIV4_PLLETH_LPCLK,
+ CLK_PLLETH_LPCLK_GEAR,
+ CLK_PLLDSI_GEAR,
+ CLK_PLLGPU_GEAR,
+
+ /* Module Clocks */
+ MOD_CLK_BASE,
+};
+
+static const struct clk_div_table dtable_1_8[] = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {3, 8},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_4[] = {
+ {0, 2},
+ {1, 4},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_16[] = {
+ {0, 2},
+ {1, 4},
+ {2, 8},
+ {3, 16},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_32[] = {
+ {0, 2},
+ {1, 4},
+ {2, 6},
+ {3, 8},
+ {4, 10},
+ {5, 12},
+ {6, 14},
+ {7, 16},
+ {8, 18},
+ {9, 20},
+ {10, 22},
+ {11, 24},
+ {12, 26},
+ {13, 28},
+ {14, 30},
+ {15, 32},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_64[] = {
+ {0, 2},
+ {1, 4},
+ {2, 8},
+ {3, 16},
+ {4, 64},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_100[] = {
+ {0, 2},
+ {1, 10},
+ {2, 100},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_16_128[] = {
+ {0, 16},
+ {1, 32},
+ {2, 64},
+ {3, 128},
+ {0, 0},
+};
+
+RZV2H_CPG_PLL_DSI_LIMITS(rzv2n_cpg_pll_dsi_limits);
+#define PLLDSI PLL_PACK_LIMITS(0xc0, 1, 0, &rzv2n_cpg_pll_dsi_limits)
+
+/* Mux clock tables */
+static const char * const smux2_gbe0_rxclk[] = { ".plleth_gbe0", "et0_rxclk" };
+static const char * const smux2_gbe0_txclk[] = { ".plleth_gbe0", "et0_txclk" };
+static const char * const smux2_gbe1_rxclk[] = { ".plleth_gbe1", "et1_rxclk" };
+static const char * const smux2_gbe1_txclk[] = { ".plleth_gbe1", "et1_txclk" };
+static const char * const smux2_xspi_clk0[] = { ".pllcm33_div3", ".pllcm33_div4" };
+static const char * const smux2_xspi_clk1[] = { ".smux2_xspi_clk0", ".pllcm33_div5" };
+
+static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("audio_extal", CLK_AUDIO_EXTAL),
+ DEF_INPUT("rtxin", CLK_RTXIN),
+ DEF_INPUT("qextal", CLK_QEXTAL),
+
+ /* PLL Clocks */
+ DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3),
+ DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
+ DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
+ DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
+ DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2),
+ DEF_FIXED(".plleth", CLK_PLLETH, CLK_QEXTAL, 125, 3),
+ DEF_PLLDSI(".plldsi", CLK_PLLDSI, CLK_QEXTAL, PLLDSI),
+ DEF_PLL(".pllgpu", CLK_PLLGPU, CLK_QEXTAL, PLLGPU),
+
+ /* Internal Core Clocks */
+ DEF_FIXED(".pllcm33_div3", CLK_PLLCM33_DIV3, CLK_PLLCM33, 1, 3),
+ DEF_FIXED(".pllcm33_div4", CLK_PLLCM33_DIV4, CLK_PLLCM33, 1, 4),
+ DEF_FIXED(".pllcm33_div5", CLK_PLLCM33_DIV5, CLK_PLLCM33, 1, 5),
+ DEF_FIXED(".pllcm33_div16", CLK_PLLCM33_DIV16, CLK_PLLCM33, 1, 16),
+ DEF_DDIV(".pllcm33_gear", CLK_PLLCM33_GEAR, CLK_PLLCM33_DIV4, CDDIV0_DIVCTL1, dtable_2_64),
+ DEF_SMUX(".smux2_xspi_clk0", CLK_SMUX2_XSPI_CLK0, SSEL1_SELCTL2, smux2_xspi_clk0),
+ DEF_SMUX(".smux2_xspi_clk1", CLK_SMUX2_XSPI_CLK1, SSEL1_SELCTL3, smux2_xspi_clk1),
+ DEF_CSDIV(".pllcm33_xspi", CLK_PLLCM33_XSPI, CLK_SMUX2_XSPI_CLK1, CSDIV0_DIVCTL3,
+ dtable_2_16),
+
+ DEF_FIXED(".pllcln_div2", CLK_PLLCLN_DIV2, CLK_PLLCLN, 1, 2),
+ DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8),
+ DEF_FIXED(".pllcln_div16", CLK_PLLCLN_DIV16, CLK_PLLCLN, 1, 16),
+ DEF_FIXED(".pllcln_div20", CLK_PLLCLN_DIV20, CLK_PLLCLN, 1, 20),
+ DEF_FIXED(".pllcln_div64", CLK_PLLCLN_DIV64, CLK_PLLCLN, 1, 64),
+ DEF_FIXED(".pllcln_div256", CLK_PLLCLN_DIV256, CLK_PLLCLN, 1, 256),
+ DEF_FIXED(".pllcln_div1024", CLK_PLLCLN_DIV1024, CLK_PLLCLN, 1, 1024),
+
+ DEF_DDIV(".plldty_acpu", CLK_PLLDTY_ACPU, CLK_PLLDTY, CDDIV0_DIVCTL2, dtable_2_64),
+ DEF_FIXED(".plldty_acpu_div2", CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU, 1, 2),
+ DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4),
+ DEF_FIXED(".plldty_div8", CLK_PLLDTY_DIV8, CLK_PLLDTY, 1, 8),
+ DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16),
+ DEF_DDIV(".plldty_rcpu", CLK_PLLDTY_RCPU, CLK_PLLDTY, CDDIV3_DIVCTL2, dtable_2_64),
+ DEF_FIXED(".plldty_rcpu_div4", CLK_PLLDTY_RCPU_DIV4, CLK_PLLDTY_RCPU, 1, 4),
+
+ DEF_DDIV(".pllvdo_cru0", CLK_PLLVDO_CRU0, CLK_PLLVDO, CDDIV3_DIVCTL3, dtable_2_4),
+ DEF_DDIV(".pllvdo_cru1", CLK_PLLVDO_CRU1, CLK_PLLVDO, CDDIV4_DIVCTL0, dtable_2_4),
+ DEF_DDIV(".pllvdo_isp", CLK_PLLVDO_ISP, CLK_PLLVDO, CDDIV2_DIVCTL3, dtable_2_64),
+
+ DEF_FIXED(".plleth_250_fix", CLK_PLLETH_DIV_250_FIX, CLK_PLLETH, 1, 4),
+ DEF_FIXED(".plleth_125_fix", CLK_PLLETH_DIV_125_FIX, CLK_PLLETH_DIV_250_FIX, 1, 2),
+ DEF_CSDIV(".plleth_gbe0", CLK_CSDIV_PLLETH_GBE0,
+ CLK_PLLETH_DIV_250_FIX, CSDIV0_DIVCTL0, dtable_2_100),
+ DEF_CSDIV(".plleth_gbe1", CLK_CSDIV_PLLETH_GBE1,
+ CLK_PLLETH_DIV_250_FIX, CSDIV0_DIVCTL1, dtable_2_100),
+ DEF_SMUX(".smux2_gbe0_txclk", CLK_SMUX2_GBE0_TXCLK, SSEL0_SELCTL2, smux2_gbe0_txclk),
+ DEF_SMUX(".smux2_gbe0_rxclk", CLK_SMUX2_GBE0_RXCLK, SSEL0_SELCTL3, smux2_gbe0_rxclk),
+ DEF_SMUX(".smux2_gbe1_txclk", CLK_SMUX2_GBE1_TXCLK, SSEL1_SELCTL0, smux2_gbe1_txclk),
+ DEF_SMUX(".smux2_gbe1_rxclk", CLK_SMUX2_GBE1_RXCLK, SSEL1_SELCTL1, smux2_gbe1_rxclk),
+ DEF_FIXED(".cdiv4_plleth_lpclk", CLK_CDIV4_PLLETH_LPCLK, CLK_PLLETH, 1, 4),
+ DEF_CSDIV(".plleth_lpclk_gear", CLK_PLLETH_LPCLK_GEAR, CLK_CDIV4_PLLETH_LPCLK,
+ CSDIV0_DIVCTL2, dtable_16_128),
+
+ DEF_PLLDSI_DIV(".plldsi_gear", CLK_PLLDSI_GEAR, CLK_PLLDSI,
+ CSDIV1_DIVCTL2, dtable_2_32),
+
+ DEF_DDIV(".pllgpu_gear", CLK_PLLGPU_GEAR, CLK_PLLGPU, CDDIV3_DIVCTL1, dtable_2_64),
+
+ /* Core Clocks */
+ DEF_FIXED("sys_0_pclk", R9A09G056_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
+ DEF_DDIV("ca55_0_coreclk0", R9A09G056_CA55_0_CORE_CLK0, CLK_PLLCA55,
+ CDDIV1_DIVCTL0, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk1", R9A09G056_CA55_0_CORE_CLK1, CLK_PLLCA55,
+ CDDIV1_DIVCTL1, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk2", R9A09G056_CA55_0_CORE_CLK2, CLK_PLLCA55,
+ CDDIV1_DIVCTL2, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk3", R9A09G056_CA55_0_CORE_CLK3, CLK_PLLCA55,
+ CDDIV1_DIVCTL3, dtable_1_8),
+ DEF_FIXED("iotop_0_shclk", R9A09G056_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
+ DEF_FIXED("usb2_0_clk_core0", R9A09G056_USB2_0_CLK_CORE0, CLK_QEXTAL, 1, 1),
+ DEF_FIXED("gbeth_0_clk_ptp_ref_i", R9A09G056_GBETH_0_CLK_PTP_REF_I,
+ CLK_PLLETH_DIV_125_FIX, 1, 1),
+ DEF_FIXED("gbeth_1_clk_ptp_ref_i", R9A09G056_GBETH_1_CLK_PTP_REF_I,
+ CLK_PLLETH_DIV_125_FIX, 1, 1),
+ DEF_FIXED_MOD_STATUS("spi_clk_spi", R9A09G056_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2,
+ FIXED_MOD_CONF_XSPI),
+ DEF_FIXED("usb3_0_ref_alt_clk_p", R9A09G056_USB3_0_REF_ALT_CLK_P, CLK_QEXTAL, 1, 1),
+ DEF_FIXED("usb3_0_core_clk", R9A09G056_USB3_0_CLKCORE, CLK_QEXTAL, 1, 1),
+};
+
+static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = {
+ DEF_MOD("dmac_0_aclk", CLK_PLLCM33_GEAR, 0, 0, 0, 0,
+ BUS_MSTOP(5, BIT(9))),
+ DEF_MOD("dmac_1_aclk", CLK_PLLDTY_ACPU_DIV2, 0, 1, 0, 1,
+ BUS_MSTOP(3, BIT(2))),
+ DEF_MOD("dmac_2_aclk", CLK_PLLDTY_ACPU_DIV2, 0, 2, 0, 2,
+ BUS_MSTOP(3, BIT(3))),
+ DEF_MOD("dmac_3_aclk", CLK_PLLDTY_RCPU_DIV4, 0, 3, 0, 3,
+ BUS_MSTOP(10, BIT(11))),
+ DEF_MOD("dmac_4_aclk", CLK_PLLDTY_RCPU_DIV4, 0, 4, 0, 4,
+ BUS_MSTOP(10, BIT(12))),
+ DEF_MOD_CRITICAL("icu_0_pclk_i", CLK_PLLCM33_DIV16, 0, 5, 0, 5,
+ BUS_MSTOP_NONE),
+ DEF_MOD_CRITICAL("gic_0_gicclk", CLK_PLLDTY_ACPU_DIV4, 1, 3, 0, 19,
+ BUS_MSTOP(3, BIT(5))),
+ DEF_MOD("gtm_0_pclk", CLK_PLLCM33_DIV16, 4, 3, 2, 3,
+ BUS_MSTOP(5, BIT(10))),
+ DEF_MOD("gtm_1_pclk", CLK_PLLCM33_DIV16, 4, 4, 2, 4,
+ BUS_MSTOP(5, BIT(11))),
+ DEF_MOD("gtm_2_pclk", CLK_PLLCLN_DIV16, 4, 5, 2, 5,
+ BUS_MSTOP(2, BIT(13))),
+ DEF_MOD("gtm_3_pclk", CLK_PLLCLN_DIV16, 4, 6, 2, 6,
+ BUS_MSTOP(2, BIT(14))),
+ DEF_MOD("gtm_4_pclk", CLK_PLLCLN_DIV16, 4, 7, 2, 7,
+ BUS_MSTOP(11, BIT(13))),
+ DEF_MOD("gtm_5_pclk", CLK_PLLCLN_DIV16, 4, 8, 2, 8,
+ BUS_MSTOP(11, BIT(14))),
+ DEF_MOD("gtm_6_pclk", CLK_PLLCLN_DIV16, 4, 9, 2, 9,
+ BUS_MSTOP(11, BIT(15))),
+ DEF_MOD("gtm_7_pclk", CLK_PLLCLN_DIV16, 4, 10, 2, 10,
+ BUS_MSTOP(12, BIT(0))),
+ DEF_MOD("wdt_1_clkp", CLK_PLLCLN_DIV16, 4, 13, 2, 13,
+ BUS_MSTOP(1, BIT(0))),
+ DEF_MOD("wdt_1_clk_loco", CLK_QEXTAL, 4, 14, 2, 14,
+ BUS_MSTOP(1, BIT(0))),
+ DEF_MOD("rtc_0_clk_rtc", CLK_PLLCM33_DIV16, 5, 3, 2, 19,
+ BUS_MSTOP(3, BIT(11) | BIT(12))),
+ DEF_MOD("rspi_0_pclk", CLK_PLLCLN_DIV8, 5, 4, 2, 20,
+ BUS_MSTOP(11, BIT(0))),
+ DEF_MOD("rspi_0_pclk_sfr", CLK_PLLCLN_DIV8, 5, 5, 2, 21,
+ BUS_MSTOP(11, BIT(0))),
+ DEF_MOD("rspi_0_tclk", CLK_PLLCLN_DIV8, 5, 6, 2, 22,
+ BUS_MSTOP(11, BIT(0))),
+ DEF_MOD("rspi_1_pclk", CLK_PLLCLN_DIV8, 5, 7, 2, 23,
+ BUS_MSTOP(11, BIT(1))),
+ DEF_MOD("rspi_1_pclk_sfr", CLK_PLLCLN_DIV8, 5, 8, 2, 24,
+ BUS_MSTOP(11, BIT(1))),
+ DEF_MOD("rspi_1_tclk", CLK_PLLCLN_DIV8, 5, 9, 2, 25,
+ BUS_MSTOP(11, BIT(1))),
+ DEF_MOD("rspi_2_pclk", CLK_PLLCLN_DIV8, 5, 10, 2, 26,
+ BUS_MSTOP(11, BIT(2))),
+ DEF_MOD("rspi_2_pclk_sfr", CLK_PLLCLN_DIV8, 5, 11, 2, 27,
+ BUS_MSTOP(11, BIT(2))),
+ DEF_MOD("rspi_2_tclk", CLK_PLLCLN_DIV8, 5, 12, 2, 28,
+ BUS_MSTOP(11, BIT(2))),
+ DEF_MOD("rsci0_pclk", CLK_PLLCLN_DIV16, 5, 13, 2, 29,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_tclk", CLK_PLLCLN_DIV16, 5, 14, 2, 30,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_ps_ps3_n", CLK_PLLCLN_DIV1024, 5, 15, 2, 31,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 0, 3, 0,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 1, 3, 1,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci1_pclk", CLK_PLLCLN_DIV16, 6, 2, 3, 2,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_tclk", CLK_PLLCLN_DIV16, 6, 3, 3, 3,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 4, 3, 4,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 5, 3, 5,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 6, 3, 6,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci2_pclk", CLK_PLLCLN_DIV16, 6, 7, 3, 7,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_tclk", CLK_PLLCLN_DIV16, 6, 8, 3, 8,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 9, 3, 9,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 10, 3, 10,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 11, 3, 11,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci3_pclk", CLK_PLLCLN_DIV16, 6, 12, 3, 12,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_tclk", CLK_PLLCLN_DIV16, 6, 13, 3, 13,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 14, 3, 14,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 15, 3, 15,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 0, 3, 16,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci4_pclk", CLK_PLLCLN_DIV16, 7, 1, 3, 17,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_tclk", CLK_PLLCLN_DIV16, 7, 2, 3, 18,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 3, 3, 19,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 4, 3, 20,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 5, 3, 21,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci5_pclk", CLK_PLLCLN_DIV16, 7, 6, 3, 22,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_tclk", CLK_PLLCLN_DIV16, 7, 7, 3, 23,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 8, 3, 24,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 9, 3, 25,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 10, 3, 26,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci6_pclk", CLK_PLLCLN_DIV16, 7, 11, 3, 27,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_tclk", CLK_PLLCLN_DIV16, 7, 12, 3, 28,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 13, 3, 29,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 14, 3, 30,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 15, 3, 31,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci7_pclk", CLK_PLLCLN_DIV16, 8, 0, 4, 0,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_tclk", CLK_PLLCLN_DIV16, 8, 1, 4, 1,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 2, 4, 2,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 3, 4, 3,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 4, 4, 4,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci8_pclk", CLK_PLLCLN_DIV16, 8, 5, 4, 5,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_tclk", CLK_PLLCLN_DIV16, 8, 6, 4, 6,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 7, 4, 7,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 8, 4, 8,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 9, 4, 9,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci9_pclk", CLK_PLLCLN_DIV16, 8, 10, 4, 10,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_tclk", CLK_PLLCLN_DIV16, 8, 11, 4, 11,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 12, 4, 12,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 13, 4, 13,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 14, 4, 14,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("scif_0_clk_pck", CLK_PLLCM33_DIV16, 8, 15, 4, 15,
+ BUS_MSTOP(3, BIT(14))),
+ DEF_MOD("i3c_0_pclkrw", CLK_PLLCLN_DIV16, 9, 0, 4, 16,
+ BUS_MSTOP(10, BIT(15))),
+ DEF_MOD("i3c_0_pclk", CLK_PLLCLN_DIV16, 9, 1, 4, 17,
+ BUS_MSTOP(10, BIT(15))),
+ DEF_MOD("i3c_0_tclk", CLK_PLLCLN_DIV8, 9, 2, 4, 18,
+ BUS_MSTOP(10, BIT(15))),
+ DEF_MOD("riic_8_ckm", CLK_PLLCM33_DIV16, 9, 3, 4, 19,
+ BUS_MSTOP(3, BIT(13))),
+ DEF_MOD("riic_0_ckm", CLK_PLLCLN_DIV16, 9, 4, 4, 20,
+ BUS_MSTOP(1, BIT(1))),
+ DEF_MOD("riic_1_ckm", CLK_PLLCLN_DIV16, 9, 5, 4, 21,
+ BUS_MSTOP(1, BIT(2))),
+ DEF_MOD("riic_2_ckm", CLK_PLLCLN_DIV16, 9, 6, 4, 22,
+ BUS_MSTOP(1, BIT(3))),
+ DEF_MOD("riic_3_ckm", CLK_PLLCLN_DIV16, 9, 7, 4, 23,
+ BUS_MSTOP(1, BIT(4))),
+ DEF_MOD("riic_4_ckm", CLK_PLLCLN_DIV16, 9, 8, 4, 24,
+ BUS_MSTOP(1, BIT(5))),
+ DEF_MOD("riic_5_ckm", CLK_PLLCLN_DIV16, 9, 9, 4, 25,
+ BUS_MSTOP(1, BIT(6))),
+ DEF_MOD("riic_6_ckm", CLK_PLLCLN_DIV16, 9, 10, 4, 26,
+ BUS_MSTOP(1, BIT(7))),
+ DEF_MOD("riic_7_ckm", CLK_PLLCLN_DIV16, 9, 11, 4, 27,
+ BUS_MSTOP(1, BIT(8))),
+ DEF_MOD("canfd_0_pclk", CLK_PLLCLN_DIV16, 9, 12, 4, 28,
+ BUS_MSTOP(10, BIT(14))),
+ DEF_MOD("canfd_0_clk_ram", CLK_PLLCLN_DIV8, 9, 13, 4, 29,
+ BUS_MSTOP(10, BIT(14))),
+ DEF_MOD("canfd_0_clkc", CLK_PLLCLN_DIV20, 9, 14, 4, 30,
+ BUS_MSTOP(10, BIT(14))),
+ DEF_MOD("spi_hclk", CLK_PLLCM33_GEAR, 9, 15, 4, 31,
+ BUS_MSTOP(4, BIT(5))),
+ DEF_MOD("spi_aclk", CLK_PLLCM33_GEAR, 10, 0, 5, 0,
+ BUS_MSTOP(4, BIT(5))),
+ DEF_MOD("spi_clk_spix2", CLK_PLLCM33_XSPI, 10, 1, 5, 2,
+ BUS_MSTOP(4, BIT(5))),
+ DEF_MOD("sdhi_0_imclk", CLK_PLLCLN_DIV8, 10, 3, 5, 3,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_0_imclk2", CLK_PLLCLN_DIV8, 10, 4, 5, 4,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_0_clk_hs", CLK_PLLCLN_DIV2, 10, 5, 5, 5,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_0_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 6, 5, 6,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_1_imclk", CLK_PLLCLN_DIV8, 10, 7, 5, 7,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_1_imclk2", CLK_PLLCLN_DIV8, 10, 8, 5, 8,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_1_clk_hs", CLK_PLLCLN_DIV2, 10, 9, 5, 9,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_1_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 10, 5, 10,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_2_imclk", CLK_PLLCLN_DIV8, 10, 11, 5, 11,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("sdhi_2_imclk2", CLK_PLLCLN_DIV8, 10, 12, 5, 12,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("sdhi_2_clk_hs", CLK_PLLCLN_DIV2, 10, 13, 5, 13,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("usb3_0_aclk", CLK_PLLDTY_DIV8, 10, 15, 5, 15,
+ BUS_MSTOP(7, BIT(12))),
+ DEF_MOD("usb3_0_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 0, 5, 16,
+ BUS_MSTOP(7, BIT(14))),
+ DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19,
+ BUS_MSTOP(7, BIT(7))),
+ DEF_MOD("usb2_0_u2p_exr_cpuclk", CLK_PLLDTY_ACPU_DIV4, 11, 5, 5, 21,
+ BUS_MSTOP(7, BIT(9))),
+ DEF_MOD("usb2_0_pclk_usbtst0", CLK_PLLDTY_ACPU_DIV4, 11, 6, 5, 22,
+ BUS_MSTOP(7, BIT(10))),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_tx_i", CLK_SMUX2_GBE0_TXCLK, 11, 8, 5, 24,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_rx_i", CLK_SMUX2_GBE0_RXCLK, 11, 9, 5, 25,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_tx_180_i", CLK_SMUX2_GBE0_TXCLK, 11, 10, 5, 26,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_rx_180_i", CLK_SMUX2_GBE0_RXCLK, 11, 11, 5, 27,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD("gbeth_0_aclk_csr_i", CLK_PLLDTY_DIV8, 11, 12, 5, 28,
+ BUS_MSTOP(8, BIT(5))),
+ DEF_MOD("gbeth_0_aclk_i", CLK_PLLDTY_DIV8, 11, 13, 5, 29,
+ BUS_MSTOP(8, BIT(5))),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_tx_i", CLK_SMUX2_GBE1_TXCLK, 11, 14, 5, 30,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_rx_i", CLK_SMUX2_GBE1_RXCLK, 11, 15, 5, 31,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_tx_180_i", CLK_SMUX2_GBE1_TXCLK, 12, 0, 6, 0,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_rx_180_i", CLK_SMUX2_GBE1_RXCLK, 12, 1, 6, 1,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD("gbeth_1_aclk_csr_i", CLK_PLLDTY_DIV8, 12, 2, 6, 2,
+ BUS_MSTOP(8, BIT(6))),
+ DEF_MOD("gbeth_1_aclk_i", CLK_PLLDTY_DIV8, 12, 3, 6, 3,
+ BUS_MSTOP(8, BIT(6))),
+ DEF_MOD("pcie_0_aclk", CLK_PLLDTY_ACPU_DIV2, 12, 4, 6, 4,
+ BUS_MSTOP(1, BIT(15))),
+ DEF_MOD("pcie_0_clk_pmu", CLK_PLLDTY_ACPU_DIV2, 12, 5, 6, 5,
+ BUS_MSTOP(1, BIT(15))),
+ DEF_MOD("cru_0_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 2, 6, 18,
+ BUS_MSTOP(9, BIT(4))),
+ DEF_MOD_NO_PM("cru_0_vclk", CLK_PLLVDO_CRU0, 13, 3, 6, 19,
+ BUS_MSTOP(9, BIT(4))),
+ DEF_MOD("cru_0_pclk", CLK_PLLDTY_DIV16, 13, 4, 6, 20,
+ BUS_MSTOP(9, BIT(4))),
+ DEF_MOD("cru_1_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 5, 6, 21,
+ BUS_MSTOP(9, BIT(5))),
+ DEF_MOD_NO_PM("cru_1_vclk", CLK_PLLVDO_CRU1, 13, 6, 6, 22,
+ BUS_MSTOP(9, BIT(5))),
+ DEF_MOD("cru_1_pclk", CLK_PLLDTY_DIV16, 13, 7, 6, 23,
+ BUS_MSTOP(9, BIT(5))),
+ DEF_MOD("isp_0_reg_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 2, 7, 2,
+ BUS_MSTOP(9, BIT(8))),
+ DEF_MOD("isp_0_pclk", CLK_PLLDTY_DIV16, 14, 3, 7, 3,
+ BUS_MSTOP(9, BIT(8))),
+ DEF_MOD("isp_0_vin_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 4, 7, 4,
+ BUS_MSTOP(9, BIT(9))),
+ DEF_MOD("isp_0_isp_sclk", CLK_PLLVDO_ISP, 14, 5, 7, 5,
+ BUS_MSTOP(9, BIT(9))),
+ DEF_MOD("dsi_0_pclk", CLK_PLLDTY_DIV16, 14, 8, 7, 8,
+ BUS_MSTOP(9, BIT(14) | BIT(15))),
+ DEF_MOD("dsi_0_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 9, 7, 9,
+ BUS_MSTOP(9, BIT(14) | BIT(15))),
+ DEF_MOD("dsi_0_vclk1", CLK_PLLDSI_GEAR, 14, 10, 7, 10,
+ BUS_MSTOP(9, BIT(14) | BIT(15))),
+ DEF_MOD("dsi_0_lpclk", CLK_PLLETH_LPCLK_GEAR, 14, 11, 7, 11,
+ BUS_MSTOP(9, BIT(14) | BIT(15))),
+ DEF_MOD("dsi_0_pllref_clk", CLK_QEXTAL, 14, 12, 7, 12,
+ BUS_MSTOP(9, BIT(14) | BIT(15))),
+ DEF_MOD("lcdc_0_clk_a", CLK_PLLDTY_ACPU_DIV2, 14, 13, 7, 13,
+ BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
+ DEF_MOD("lcdc_0_clk_p", CLK_PLLDTY_DIV16, 14, 14, 7, 14,
+ BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
+ DEF_MOD("lcdc_0_clk_d", CLK_PLLDSI_GEAR, 14, 15, 7, 15,
+ BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
+ DEF_MOD("gpu_0_clk", CLK_PLLGPU_GEAR, 15, 0, 7, 16,
+ BUS_MSTOP(3, BIT(4))),
+ DEF_MOD("gpu_0_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17,
+ BUS_MSTOP(3, BIT(4))),
+ DEF_MOD("gpu_0_ace_clk", CLK_PLLDTY_ACPU_DIV2, 15, 2, 7, 18,
+ BUS_MSTOP(3, BIT(4))),
+ DEF_MOD("tsu_0_pclk", CLK_QEXTAL, 16, 9, 8, 9,
+ BUS_MSTOP(5, BIT(2))),
+ DEF_MOD("tsu_1_pclk", CLK_QEXTAL, 16, 10, 8, 10,
+ BUS_MSTOP(2, BIT(15))),
+};
+
+static const struct rzv2h_reset r9a09g056_resets[] __initconst = {
+ DEF_RST(3, 0, 1, 1), /* SYS_0_PRESETN */
+ DEF_RST(3, 1, 1, 2), /* DMAC_0_ARESETN */
+ DEF_RST(3, 2, 1, 3), /* DMAC_1_ARESETN */
+ DEF_RST(3, 3, 1, 4), /* DMAC_2_ARESETN */
+ DEF_RST(3, 4, 1, 5), /* DMAC_3_ARESETN */
+ DEF_RST(3, 5, 1, 6), /* DMAC_4_ARESETN */
+ DEF_RST(3, 6, 1, 7), /* ICU_0_PRESETN_I */
+ DEF_RST(3, 8, 1, 9), /* GIC_0_GICRESET_N */
+ DEF_RST(3, 9, 1, 10), /* GIC_0_DBG_GICRESET_N */
+ DEF_RST(6, 13, 2, 30), /* GTM_0_PRESETZ */
+ DEF_RST(6, 14, 2, 31), /* GTM_1_PRESETZ */
+ DEF_RST(6, 15, 3, 0), /* GTM_2_PRESETZ */
+ DEF_RST(7, 0, 3, 1), /* GTM_3_PRESETZ */
+ DEF_RST(7, 1, 3, 2), /* GTM_4_PRESETZ */
+ DEF_RST(7, 2, 3, 3), /* GTM_5_PRESETZ */
+ DEF_RST(7, 3, 3, 4), /* GTM_6_PRESETZ */
+ DEF_RST(7, 4, 3, 5), /* GTM_7_PRESETZ */
+ DEF_RST(7, 6, 3, 7), /* WDT_1_RESET */
+ DEF_RST(8, 1, 3, 18), /* RSCI0_PRESETN */
+ DEF_RST(8, 2, 3, 19), /* RSCI0_TRESETN */
+ DEF_RST(8, 3, 3, 20), /* RSCI1_PRESETN */
+ DEF_RST(8, 4, 3, 21), /* RSCI1_TRESETN */
+ DEF_RST(8, 5, 3, 22), /* RSCI2_PRESETN */
+ DEF_RST(8, 6, 3, 23), /* RSCI2_TRESETN */
+ DEF_RST(8, 7, 3, 24), /* RSCI3_PRESETN */
+ DEF_RST(8, 8, 3, 25), /* RSCI3_TRESETN */
+ DEF_RST(8, 9, 3, 26), /* RSCI4_PRESETN */
+ DEF_RST(8, 10, 3, 27), /* RSCI4_TRESETN */
+ DEF_RST(8, 11, 3, 28), /* RSCI5_PRESETN */
+ DEF_RST(8, 12, 3, 29), /* RSCI5_TRESETN */
+ DEF_RST(8, 13, 3, 30), /* RSCI6_PRESETN */
+ DEF_RST(8, 14, 3, 31), /* RSCI6_TRESETN */
+ DEF_RST(8, 15, 4, 0), /* RSCI7_PRESETN */
+ DEF_RST(9, 0, 4, 1), /* RSCI7_TRESETN */
+ DEF_RST(9, 1, 4, 2), /* RSCI8_PRESETN */
+ DEF_RST(9, 2, 4, 3), /* RSCI8_TRESETN */
+ DEF_RST(9, 3, 4, 4), /* RSCI9_PRESETN */
+ DEF_RST(9, 4, 4, 5), /* RSCI9_TRESETN */
+ DEF_RST(7, 9, 3, 10), /* RTC_0_RST_RTC */
+ DEF_RST(7, 10, 3, 11), /* RTC_0_RST_RTC_V */
+ DEF_RST(7, 11, 3, 12), /* RSPI_0_PRESETN */
+ DEF_RST(7, 12, 3, 13), /* RSPI_0_TRESETN */
+ DEF_RST(7, 13, 3, 14), /* RSPI_1_PRESETN */
+ DEF_RST(7, 14, 3, 15), /* RSPI_1_TRESETN */
+ DEF_RST(7, 15, 3, 16), /* RSPI_2_PRESETN */
+ DEF_RST(8, 0, 3, 17), /* RSPI_2_TRESETN */
+ DEF_RST(9, 5, 4, 6), /* SCIF_0_RST_SYSTEM_N */
+ DEF_RST(9, 6, 4, 7), /* I3C_0_PRESETN */
+ DEF_RST(9, 7, 4, 8), /* I3C_0_TRESETN */
+ DEF_RST(9, 8, 4, 9), /* RIIC_0_MRST */
+ DEF_RST(9, 9, 4, 10), /* RIIC_1_MRST */
+ DEF_RST(9, 10, 4, 11), /* RIIC_2_MRST */
+ DEF_RST(9, 11, 4, 12), /* RIIC_3_MRST */
+ DEF_RST(9, 12, 4, 13), /* RIIC_4_MRST */
+ DEF_RST(9, 13, 4, 14), /* RIIC_5_MRST */
+ DEF_RST(9, 14, 4, 15), /* RIIC_6_MRST */
+ DEF_RST(9, 15, 4, 16), /* RIIC_7_MRST */
+ DEF_RST(10, 0, 4, 17), /* RIIC_8_MRST */
+ DEF_RST(10, 1, 4, 18), /* CANFD_0_RSTP_N */
+ DEF_RST(10, 2, 4, 19), /* CANFD_0_RSTC_N */
+ DEF_RST(10, 3, 4, 20), /* SPI_HRESETN */
+ DEF_RST(10, 4, 4, 21), /* SPI_ARESETN */
+ DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
+ DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
+ DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
+ DEF_RST(10, 10, 4, 27), /* USB3_0_ARESETN */
+ DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */
+ DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */
+ DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */
+ DEF_RST(11, 0, 5, 1), /* GBETH_0_ARESETN_I */
+ DEF_RST(11, 1, 5, 2), /* GBETH_1_ARESETN_I */
+ DEF_RST(11, 2, 5, 3), /* PCIE_0_ARESETN */
+ DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */
+ DEF_RST(12, 6, 5, 23), /* CRU_0_ARESETN */
+ DEF_RST(12, 7, 5, 24), /* CRU_0_S_RESETN */
+ DEF_RST(12, 8, 5, 25), /* CRU_1_PRESETN */
+ DEF_RST(12, 9, 5, 26), /* CRU_1_ARESETN */
+ DEF_RST(12, 10, 5, 27), /* CRU_1_S_RESETN */
+ DEF_RST(13, 1, 6, 2), /* ISP_0_VIN_ARESETN */
+ DEF_RST(13, 2, 6, 3), /* ISP_0_REG_ARESETN */
+ DEF_RST(13, 3, 6, 4), /* ISP_0_ISP_SRESETN */
+ DEF_RST(13, 4, 6, 5), /* ISP_0_PRESETN */
+ DEF_RST(13, 7, 6, 8), /* DSI_0_PRESETN */
+ DEF_RST(13, 8, 6, 9), /* DSI_0_ARESETN */
+ DEF_RST(13, 12, 6, 13), /* LCDC_0_RESET_N */
+ DEF_RST(13, 13, 6, 14), /* GPU_0_RESETN */
+ DEF_RST(13, 14, 6, 15), /* GPU_0_AXI_RESETN */
+ DEF_RST(13, 15, 6, 16), /* GPU_0_ACE_RESETN */
+ DEF_RST(15, 7, 7, 8), /* TSU_0_PRESETN */
+ DEF_RST(15, 8, 7, 9), /* TSU_1_PRESETN */
+};
+
+const struct rzv2h_cpg_info r9a09g056_cpg_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r9a09g056_core_clks,
+ .num_core_clks = ARRAY_SIZE(r9a09g056_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r9a09g056_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r9a09g056_mod_clks),
+ .num_hw_mod_clks = 25 * 16,
+
+ /* Resets */
+ .resets = r9a09g056_resets,
+ .num_resets = ARRAY_SIZE(r9a09g056_resets),
+
+ .num_mstop_bits = 192,
+};
diff --git a/drivers/clk/renesas/r9a09g057-cpg.c b/drivers/clk/renesas/r9a09g057-cpg.c
new file mode 100644
index 000000000..2fa5a620b
--- /dev/null
+++ b/drivers/clk/renesas/r9a09g057-cpg.c
@@ -0,0 +1,693 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/V2H(P) CPG driver
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/clock/renesas,r9a09g057-cpg.h>
+
+#include "rzv2h-cpg.h"
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A09G057_USB3_1_CLKCORE,
+
+ /* External Input Clocks */
+ CLK_AUDIO_EXTAL,
+ CLK_RTXIN,
+ CLK_QEXTAL,
+
+ /* PLL Clocks */
+ CLK_PLLCM33,
+ CLK_PLLCLN,
+ CLK_PLLDTY,
+ CLK_PLLCA55,
+ CLK_PLLVDO,
+ CLK_PLLETH,
+ CLK_PLLDSI,
+ CLK_PLLGPU,
+
+ /* Internal Core Clocks */
+ CLK_PLLCM33_DIV3,
+ CLK_PLLCM33_DIV4,
+ CLK_PLLCM33_DIV5,
+ CLK_PLLCM33_DIV16,
+ CLK_PLLCM33_GEAR,
+ CLK_SMUX2_XSPI_CLK0,
+ CLK_SMUX2_XSPI_CLK1,
+ CLK_PLLCM33_XSPI,
+ CLK_PLLCLN_DIV2,
+ CLK_PLLCLN_DIV8,
+ CLK_PLLCLN_DIV16,
+ CLK_PLLCLN_DIV20,
+ CLK_PLLCLN_DIV64,
+ CLK_PLLCLN_DIV256,
+ CLK_PLLCLN_DIV1024,
+ CLK_PLLDTY_ACPU,
+ CLK_PLLDTY_ACPU_DIV2,
+ CLK_PLLDTY_ACPU_DIV4,
+ CLK_PLLDTY_DIV8,
+ CLK_PLLDTY_DIV16,
+ CLK_PLLDTY_RCPU,
+ CLK_PLLDTY_RCPU_DIV4,
+ CLK_PLLVDO_CRU0,
+ CLK_PLLVDO_CRU1,
+ CLK_PLLVDO_CRU2,
+ CLK_PLLVDO_CRU3,
+ CLK_PLLVDO_ISP,
+ CLK_PLLETH_DIV_250_FIX,
+ CLK_PLLETH_DIV_125_FIX,
+ CLK_CSDIV_PLLETH_GBE0,
+ CLK_CSDIV_PLLETH_GBE1,
+ CLK_SMUX2_GBE0_TXCLK,
+ CLK_SMUX2_GBE0_RXCLK,
+ CLK_SMUX2_GBE1_TXCLK,
+ CLK_SMUX2_GBE1_RXCLK,
+ CLK_CDIV4_PLLETH_LPCLK,
+ CLK_PLLETH_LPCLK_GEAR,
+ CLK_PLLDSI_GEAR,
+ CLK_PLLGPU_GEAR,
+
+ /* Module Clocks */
+ MOD_CLK_BASE,
+};
+
+static const struct clk_div_table dtable_1_8[] = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {3, 8},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_4[] = {
+ {0, 2},
+ {1, 4},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_16[] = {
+ {0, 2},
+ {1, 4},
+ {2, 8},
+ {3, 16},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_32[] = {
+ {0, 2},
+ {1, 4},
+ {2, 6},
+ {3, 8},
+ {4, 10},
+ {5, 12},
+ {6, 14},
+ {7, 16},
+ {8, 18},
+ {9, 20},
+ {10, 22},
+ {11, 24},
+ {12, 26},
+ {13, 28},
+ {14, 30},
+ {15, 32},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_64[] = {
+ {0, 2},
+ {1, 4},
+ {2, 8},
+ {3, 16},
+ {4, 64},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_2_100[] = {
+ {0, 2},
+ {1, 10},
+ {2, 100},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_16_128[] = {
+ {0, 16},
+ {1, 32},
+ {2, 64},
+ {3, 128},
+ {0, 0},
+};
+
+RZV2H_CPG_PLL_DSI_LIMITS(rzv2h_cpg_pll_dsi_limits);
+#define PLLDSI PLL_PACK_LIMITS(0xc0, 1, 0, &rzv2h_cpg_pll_dsi_limits)
+
+/* Mux clock tables */
+static const char * const smux2_gbe0_rxclk[] = { ".plleth_gbe0", "et0_rxclk" };
+static const char * const smux2_gbe0_txclk[] = { ".plleth_gbe0", "et0_txclk" };
+static const char * const smux2_gbe1_rxclk[] = { ".plleth_gbe1", "et1_rxclk" };
+static const char * const smux2_gbe1_txclk[] = { ".plleth_gbe1", "et1_txclk" };
+static const char * const smux2_xspi_clk0[] = { ".pllcm33_div3", ".pllcm33_div4" };
+static const char * const smux2_xspi_clk1[] = { ".smux2_xspi_clk0", ".pllcm33_div5" };
+
+static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("audio_extal", CLK_AUDIO_EXTAL),
+ DEF_INPUT("rtxin", CLK_RTXIN),
+ DEF_INPUT("qextal", CLK_QEXTAL),
+
+ /* PLL Clocks */
+ DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3),
+ DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
+ DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
+ DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
+ DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2),
+ DEF_FIXED(".plleth", CLK_PLLETH, CLK_QEXTAL, 125, 3),
+ DEF_PLLDSI(".plldsi", CLK_PLLDSI, CLK_QEXTAL, PLLDSI),
+ DEF_PLL(".pllgpu", CLK_PLLGPU, CLK_QEXTAL, PLLGPU),
+
+ /* Internal Core Clocks */
+ DEF_FIXED(".pllcm33_div3", CLK_PLLCM33_DIV3, CLK_PLLCM33, 1, 3),
+ DEF_FIXED(".pllcm33_div4", CLK_PLLCM33_DIV4, CLK_PLLCM33, 1, 4),
+ DEF_FIXED(".pllcm33_div5", CLK_PLLCM33_DIV5, CLK_PLLCM33, 1, 5),
+ DEF_FIXED(".pllcm33_div16", CLK_PLLCM33_DIV16, CLK_PLLCM33, 1, 16),
+ DEF_DDIV(".pllcm33_gear", CLK_PLLCM33_GEAR, CLK_PLLCM33_DIV4, CDDIV0_DIVCTL1, dtable_2_64),
+ DEF_SMUX(".smux2_xspi_clk0", CLK_SMUX2_XSPI_CLK0, SSEL1_SELCTL2, smux2_xspi_clk0),
+ DEF_SMUX(".smux2_xspi_clk1", CLK_SMUX2_XSPI_CLK1, SSEL1_SELCTL3, smux2_xspi_clk1),
+ DEF_CSDIV(".pllcm33_xspi", CLK_PLLCM33_XSPI, CLK_SMUX2_XSPI_CLK1, CSDIV0_DIVCTL3,
+ dtable_2_16),
+
+ DEF_FIXED(".pllcln_div2", CLK_PLLCLN_DIV2, CLK_PLLCLN, 1, 2),
+ DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8),
+ DEF_FIXED(".pllcln_div16", CLK_PLLCLN_DIV16, CLK_PLLCLN, 1, 16),
+ DEF_FIXED(".pllcln_div20", CLK_PLLCLN_DIV20, CLK_PLLCLN, 1, 20),
+ DEF_FIXED(".pllcln_div64", CLK_PLLCLN_DIV64, CLK_PLLCLN, 1, 64),
+ DEF_FIXED(".pllcln_div256", CLK_PLLCLN_DIV256, CLK_PLLCLN, 1, 256),
+ DEF_FIXED(".pllcln_div1024", CLK_PLLCLN_DIV1024, CLK_PLLCLN, 1, 1024),
+
+ DEF_DDIV(".plldty_acpu", CLK_PLLDTY_ACPU, CLK_PLLDTY, CDDIV0_DIVCTL2, dtable_2_64),
+ DEF_FIXED(".plldty_acpu_div2", CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU, 1, 2),
+ DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4),
+ DEF_FIXED(".plldty_div8", CLK_PLLDTY_DIV8, CLK_PLLDTY, 1, 8),
+ DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16),
+ DEF_DDIV(".plldty_rcpu", CLK_PLLDTY_RCPU, CLK_PLLDTY, CDDIV3_DIVCTL2, dtable_2_64),
+ DEF_FIXED(".plldty_rcpu_div4", CLK_PLLDTY_RCPU_DIV4, CLK_PLLDTY_RCPU, 1, 4),
+
+ DEF_DDIV(".pllvdo_cru0", CLK_PLLVDO_CRU0, CLK_PLLVDO, CDDIV3_DIVCTL3, dtable_2_4),
+ DEF_DDIV(".pllvdo_cru1", CLK_PLLVDO_CRU1, CLK_PLLVDO, CDDIV4_DIVCTL0, dtable_2_4),
+ DEF_DDIV(".pllvdo_cru2", CLK_PLLVDO_CRU2, CLK_PLLVDO, CDDIV4_DIVCTL1, dtable_2_4),
+ DEF_DDIV(".pllvdo_cru3", CLK_PLLVDO_CRU3, CLK_PLLVDO, CDDIV4_DIVCTL2, dtable_2_4),
+ DEF_DDIV(".pllvdo_isp", CLK_PLLVDO_ISP, CLK_PLLVDO, CDDIV2_DIVCTL3, dtable_2_64),
+
+ DEF_FIXED(".plleth_250_fix", CLK_PLLETH_DIV_250_FIX, CLK_PLLETH, 1, 4),
+ DEF_FIXED(".plleth_125_fix", CLK_PLLETH_DIV_125_FIX, CLK_PLLETH_DIV_250_FIX, 1, 2),
+ DEF_CSDIV(".plleth_gbe0", CLK_CSDIV_PLLETH_GBE0,
+ CLK_PLLETH_DIV_250_FIX, CSDIV0_DIVCTL0, dtable_2_100),
+ DEF_CSDIV(".plleth_gbe1", CLK_CSDIV_PLLETH_GBE1,
+ CLK_PLLETH_DIV_250_FIX, CSDIV0_DIVCTL1, dtable_2_100),
+ DEF_SMUX(".smux2_gbe0_txclk", CLK_SMUX2_GBE0_TXCLK, SSEL0_SELCTL2, smux2_gbe0_txclk),
+ DEF_SMUX(".smux2_gbe0_rxclk", CLK_SMUX2_GBE0_RXCLK, SSEL0_SELCTL3, smux2_gbe0_rxclk),
+ DEF_SMUX(".smux2_gbe1_txclk", CLK_SMUX2_GBE1_TXCLK, SSEL1_SELCTL0, smux2_gbe1_txclk),
+ DEF_SMUX(".smux2_gbe1_rxclk", CLK_SMUX2_GBE1_RXCLK, SSEL1_SELCTL1, smux2_gbe1_rxclk),
+ DEF_FIXED(".cdiv4_plleth_lpclk", CLK_CDIV4_PLLETH_LPCLK, CLK_PLLETH, 1, 4),
+ DEF_CSDIV(".plleth_lpclk_gear", CLK_PLLETH_LPCLK_GEAR, CLK_CDIV4_PLLETH_LPCLK,
+ CSDIV0_DIVCTL2, dtable_16_128),
+
+ DEF_PLLDSI_DIV(".plldsi_gear", CLK_PLLDSI_GEAR, CLK_PLLDSI,
+ CSDIV1_DIVCTL2, dtable_2_32),
+
+ DEF_DDIV(".pllgpu_gear", CLK_PLLGPU_GEAR, CLK_PLLGPU, CDDIV3_DIVCTL1, dtable_2_64),
+
+ /* Core Clocks */
+ DEF_FIXED("sys_0_pclk", R9A09G057_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
+ DEF_DDIV("ca55_0_coreclk0", R9A09G057_CA55_0_CORE_CLK0, CLK_PLLCA55,
+ CDDIV1_DIVCTL0, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk1", R9A09G057_CA55_0_CORE_CLK1, CLK_PLLCA55,
+ CDDIV1_DIVCTL1, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk2", R9A09G057_CA55_0_CORE_CLK2, CLK_PLLCA55,
+ CDDIV1_DIVCTL2, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk3", R9A09G057_CA55_0_CORE_CLK3, CLK_PLLCA55,
+ CDDIV1_DIVCTL3, dtable_1_8),
+ DEF_FIXED("iotop_0_shclk", R9A09G057_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
+ DEF_FIXED("usb2_0_clk_core0", R9A09G057_USB2_0_CLK_CORE0, CLK_QEXTAL, 1, 1),
+ DEF_FIXED("usb2_0_clk_core1", R9A09G057_USB2_0_CLK_CORE1, CLK_QEXTAL, 1, 1),
+ DEF_FIXED("gbeth_0_clk_ptp_ref_i", R9A09G057_GBETH_0_CLK_PTP_REF_I,
+ CLK_PLLETH_DIV_125_FIX, 1, 1),
+ DEF_FIXED("gbeth_1_clk_ptp_ref_i", R9A09G057_GBETH_1_CLK_PTP_REF_I,
+ CLK_PLLETH_DIV_125_FIX, 1, 1),
+ DEF_FIXED_MOD_STATUS("spi_clk_spi", R9A09G057_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2,
+ FIXED_MOD_CONF_XSPI),
+ DEF_FIXED("usb3_0_ref_alt_clk_p", R9A09G057_USB3_0_REF_ALT_CLK_P, CLK_QEXTAL, 1, 1),
+ DEF_FIXED("usb3_0_core_clk", R9A09G057_USB3_0_CLKCORE, CLK_QEXTAL, 1, 1),
+ DEF_FIXED("usb3_1_ref_alt_clk_p", R9A09G057_USB3_1_REF_ALT_CLK_P, CLK_QEXTAL, 1, 1),
+ DEF_FIXED("usb3_1_core_clk", R9A09G057_USB3_1_CLKCORE, CLK_QEXTAL, 1, 1),
+};
+
+static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
+ DEF_MOD("dmac_0_aclk", CLK_PLLCM33_GEAR, 0, 0, 0, 0,
+ BUS_MSTOP(5, BIT(9))),
+ DEF_MOD("dmac_1_aclk", CLK_PLLDTY_ACPU_DIV2, 0, 1, 0, 1,
+ BUS_MSTOP(3, BIT(2))),
+ DEF_MOD("dmac_2_aclk", CLK_PLLDTY_ACPU_DIV2, 0, 2, 0, 2,
+ BUS_MSTOP(3, BIT(3))),
+ DEF_MOD("dmac_3_aclk", CLK_PLLDTY_RCPU_DIV4, 0, 3, 0, 3,
+ BUS_MSTOP(10, BIT(11))),
+ DEF_MOD("dmac_4_aclk", CLK_PLLDTY_RCPU_DIV4, 0, 4, 0, 4,
+ BUS_MSTOP(10, BIT(12))),
+ DEF_MOD_CRITICAL("icu_0_pclk_i", CLK_PLLCM33_DIV16, 0, 5, 0, 5,
+ BUS_MSTOP_NONE),
+ DEF_MOD_CRITICAL("gic_0_gicclk", CLK_PLLDTY_ACPU_DIV4, 1, 3, 0, 19,
+ BUS_MSTOP(3, BIT(5))),
+ DEF_MOD("gtm_0_pclk", CLK_PLLCM33_DIV16, 4, 3, 2, 3,
+ BUS_MSTOP(5, BIT(10))),
+ DEF_MOD("gtm_1_pclk", CLK_PLLCM33_DIV16, 4, 4, 2, 4,
+ BUS_MSTOP(5, BIT(11))),
+ DEF_MOD("gtm_2_pclk", CLK_PLLCLN_DIV16, 4, 5, 2, 5,
+ BUS_MSTOP(2, BIT(13))),
+ DEF_MOD("gtm_3_pclk", CLK_PLLCLN_DIV16, 4, 6, 2, 6,
+ BUS_MSTOP(2, BIT(14))),
+ DEF_MOD("gtm_4_pclk", CLK_PLLCLN_DIV16, 4, 7, 2, 7,
+ BUS_MSTOP(11, BIT(13))),
+ DEF_MOD("gtm_5_pclk", CLK_PLLCLN_DIV16, 4, 8, 2, 8,
+ BUS_MSTOP(11, BIT(14))),
+ DEF_MOD("gtm_6_pclk", CLK_PLLCLN_DIV16, 4, 9, 2, 9,
+ BUS_MSTOP(11, BIT(15))),
+ DEF_MOD("gtm_7_pclk", CLK_PLLCLN_DIV16, 4, 10, 2, 10,
+ BUS_MSTOP(12, BIT(0))),
+ DEF_MOD("wdt_1_clkp", CLK_PLLCLN_DIV16, 4, 13, 2, 13,
+ BUS_MSTOP(1, BIT(0))),
+ DEF_MOD("wdt_1_clk_loco", CLK_QEXTAL, 4, 14, 2, 14,
+ BUS_MSTOP(1, BIT(0))),
+ DEF_MOD("rtc_0_clk_rtc", CLK_PLLCM33_DIV16, 5, 3, 2, 19,
+ BUS_MSTOP(3, BIT(11) | BIT(12))),
+ DEF_MOD("rspi_0_pclk", CLK_PLLCLN_DIV8, 5, 4, 2, 20,
+ BUS_MSTOP(11, BIT(0))),
+ DEF_MOD("rspi_0_pclk_sfr", CLK_PLLCLN_DIV8, 5, 5, 2, 21,
+ BUS_MSTOP(11, BIT(0))),
+ DEF_MOD("rspi_0_tclk", CLK_PLLCLN_DIV8, 5, 6, 2, 22,
+ BUS_MSTOP(11, BIT(0))),
+ DEF_MOD("rspi_1_pclk", CLK_PLLCLN_DIV8, 5, 7, 2, 23,
+ BUS_MSTOP(11, BIT(1))),
+ DEF_MOD("rspi_1_pclk_sfr", CLK_PLLCLN_DIV8, 5, 8, 2, 24,
+ BUS_MSTOP(11, BIT(1))),
+ DEF_MOD("rspi_1_tclk", CLK_PLLCLN_DIV8, 5, 9, 2, 25,
+ BUS_MSTOP(11, BIT(1))),
+ DEF_MOD("rspi_2_pclk", CLK_PLLCLN_DIV8, 5, 10, 2, 26,
+ BUS_MSTOP(11, BIT(2))),
+ DEF_MOD("rspi_2_pclk_sfr", CLK_PLLCLN_DIV8, 5, 11, 2, 27,
+ BUS_MSTOP(11, BIT(2))),
+ DEF_MOD("rspi_2_tclk", CLK_PLLCLN_DIV8, 5, 12, 2, 28,
+ BUS_MSTOP(11, BIT(2))),
+ DEF_MOD("rsci0_pclk", CLK_PLLCLN_DIV16, 5, 13, 2, 29,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_tclk", CLK_PLLCLN_DIV16, 5, 14, 2, 30,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_ps_ps3_n", CLK_PLLCLN_DIV1024, 5, 15, 2, 31,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 0, 3, 0,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci0_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 1, 3, 1,
+ BUS_MSTOP(11, BIT(3))),
+ DEF_MOD("rsci1_pclk", CLK_PLLCLN_DIV16, 6, 2, 3, 2,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_tclk", CLK_PLLCLN_DIV16, 6, 3, 3, 3,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 4, 3, 4,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 5, 3, 5,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci1_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 6, 3, 6,
+ BUS_MSTOP(11, BIT(4))),
+ DEF_MOD("rsci2_pclk", CLK_PLLCLN_DIV16, 6, 7, 3, 7,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_tclk", CLK_PLLCLN_DIV16, 6, 8, 3, 8,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 9, 3, 9,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 10, 3, 10,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci2_ps_ps1_n", CLK_PLLCLN_DIV64, 6, 11, 3, 11,
+ BUS_MSTOP(11, BIT(5))),
+ DEF_MOD("rsci3_pclk", CLK_PLLCLN_DIV16, 6, 12, 3, 12,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_tclk", CLK_PLLCLN_DIV16, 6, 13, 3, 13,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_ps_ps3_n", CLK_PLLCLN_DIV1024, 6, 14, 3, 14,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_ps_ps2_n", CLK_PLLCLN_DIV256, 6, 15, 3, 15,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci3_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 0, 3, 16,
+ BUS_MSTOP(11, BIT(6))),
+ DEF_MOD("rsci4_pclk", CLK_PLLCLN_DIV16, 7, 1, 3, 17,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_tclk", CLK_PLLCLN_DIV16, 7, 2, 3, 18,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 3, 3, 19,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 4, 3, 20,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci4_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 5, 3, 21,
+ BUS_MSTOP(11, BIT(7))),
+ DEF_MOD("rsci5_pclk", CLK_PLLCLN_DIV16, 7, 6, 3, 22,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_tclk", CLK_PLLCLN_DIV16, 7, 7, 3, 23,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 8, 3, 24,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 9, 3, 25,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci5_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 10, 3, 26,
+ BUS_MSTOP(11, BIT(8))),
+ DEF_MOD("rsci6_pclk", CLK_PLLCLN_DIV16, 7, 11, 3, 27,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_tclk", CLK_PLLCLN_DIV16, 7, 12, 3, 28,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_ps_ps3_n", CLK_PLLCLN_DIV1024, 7, 13, 3, 29,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_ps_ps2_n", CLK_PLLCLN_DIV256, 7, 14, 3, 30,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci6_ps_ps1_n", CLK_PLLCLN_DIV64, 7, 15, 3, 31,
+ BUS_MSTOP(11, BIT(9))),
+ DEF_MOD("rsci7_pclk", CLK_PLLCLN_DIV16, 8, 0, 4, 0,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_tclk", CLK_PLLCLN_DIV16, 8, 1, 4, 1,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 2, 4, 2,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 3, 4, 3,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci7_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 4, 4, 4,
+ BUS_MSTOP(11, BIT(10))),
+ DEF_MOD("rsci8_pclk", CLK_PLLCLN_DIV16, 8, 5, 4, 5,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_tclk", CLK_PLLCLN_DIV16, 8, 6, 4, 6,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 7, 4, 7,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 8, 4, 8,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci8_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 9, 4, 9,
+ BUS_MSTOP(11, BIT(11))),
+ DEF_MOD("rsci9_pclk", CLK_PLLCLN_DIV16, 8, 10, 4, 10,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_tclk", CLK_PLLCLN_DIV16, 8, 11, 4, 11,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_ps_ps3_n", CLK_PLLCLN_DIV1024, 8, 12, 4, 12,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_ps_ps2_n", CLK_PLLCLN_DIV256, 8, 13, 4, 13,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("rsci9_ps_ps1_n", CLK_PLLCLN_DIV64, 8, 14, 4, 14,
+ BUS_MSTOP(11, BIT(12))),
+ DEF_MOD("scif_0_clk_pck", CLK_PLLCM33_DIV16, 8, 15, 4, 15,
+ BUS_MSTOP(3, BIT(14))),
+ DEF_MOD("i3c_0_pclkrw", CLK_PLLCLN_DIV16, 9, 0, 4, 16,
+ BUS_MSTOP(10, BIT(15))),
+ DEF_MOD("i3c_0_pclk", CLK_PLLCLN_DIV16, 9, 1, 4, 17,
+ BUS_MSTOP(10, BIT(15))),
+ DEF_MOD("i3c_0_tclk", CLK_PLLCLN_DIV8, 9, 2, 4, 18,
+ BUS_MSTOP(10, BIT(15))),
+ DEF_MOD("riic_8_ckm", CLK_PLLCM33_DIV16, 9, 3, 4, 19,
+ BUS_MSTOP(3, BIT(13))),
+ DEF_MOD("riic_0_ckm", CLK_PLLCLN_DIV16, 9, 4, 4, 20,
+ BUS_MSTOP(1, BIT(1))),
+ DEF_MOD("riic_1_ckm", CLK_PLLCLN_DIV16, 9, 5, 4, 21,
+ BUS_MSTOP(1, BIT(2))),
+ DEF_MOD("riic_2_ckm", CLK_PLLCLN_DIV16, 9, 6, 4, 22,
+ BUS_MSTOP(1, BIT(3))),
+ DEF_MOD("riic_3_ckm", CLK_PLLCLN_DIV16, 9, 7, 4, 23,
+ BUS_MSTOP(1, BIT(4))),
+ DEF_MOD("riic_4_ckm", CLK_PLLCLN_DIV16, 9, 8, 4, 24,
+ BUS_MSTOP(1, BIT(5))),
+ DEF_MOD("riic_5_ckm", CLK_PLLCLN_DIV16, 9, 9, 4, 25,
+ BUS_MSTOP(1, BIT(6))),
+ DEF_MOD("riic_6_ckm", CLK_PLLCLN_DIV16, 9, 10, 4, 26,
+ BUS_MSTOP(1, BIT(7))),
+ DEF_MOD("riic_7_ckm", CLK_PLLCLN_DIV16, 9, 11, 4, 27,
+ BUS_MSTOP(1, BIT(8))),
+ DEF_MOD("canfd_0_pclk", CLK_PLLCLN_DIV16, 9, 12, 4, 28,
+ BUS_MSTOP(10, BIT(14))),
+ DEF_MOD("canfd_0_clk_ram", CLK_PLLCLN_DIV8, 9, 13, 4, 29,
+ BUS_MSTOP(10, BIT(14))),
+ DEF_MOD("canfd_0_clkc", CLK_PLLCLN_DIV20, 9, 14, 4, 30,
+ BUS_MSTOP(10, BIT(14))),
+ DEF_MOD("spi_hclk", CLK_PLLCM33_GEAR, 9, 15, 4, 31,
+ BUS_MSTOP(4, BIT(5))),
+ DEF_MOD("spi_aclk", CLK_PLLCM33_GEAR, 10, 0, 5, 0,
+ BUS_MSTOP(4, BIT(5))),
+ DEF_MOD("spi_clk_spix2", CLK_PLLCM33_XSPI, 10, 1, 5, 2,
+ BUS_MSTOP(4, BIT(5))),
+ DEF_MOD("sdhi_0_imclk", CLK_PLLCLN_DIV8, 10, 3, 5, 3,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_0_imclk2", CLK_PLLCLN_DIV8, 10, 4, 5, 4,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_0_clk_hs", CLK_PLLCLN_DIV2, 10, 5, 5, 5,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_0_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 6, 5, 6,
+ BUS_MSTOP(8, BIT(2))),
+ DEF_MOD("sdhi_1_imclk", CLK_PLLCLN_DIV8, 10, 7, 5, 7,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_1_imclk2", CLK_PLLCLN_DIV8, 10, 8, 5, 8,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_1_clk_hs", CLK_PLLCLN_DIV2, 10, 9, 5, 9,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_1_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 10, 5, 10,
+ BUS_MSTOP(8, BIT(3))),
+ DEF_MOD("sdhi_2_imclk", CLK_PLLCLN_DIV8, 10, 11, 5, 11,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("sdhi_2_imclk2", CLK_PLLCLN_DIV8, 10, 12, 5, 12,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("sdhi_2_clk_hs", CLK_PLLCLN_DIV2, 10, 13, 5, 13,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14,
+ BUS_MSTOP(8, BIT(4))),
+ DEF_MOD("usb3_0_aclk", CLK_PLLDTY_DIV8, 10, 15, 5, 15,
+ BUS_MSTOP(7, BIT(12))),
+ DEF_MOD("usb3_0_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 0, 5, 16,
+ BUS_MSTOP(7, BIT(14))),
+ DEF_MOD("usb3_1_aclk", CLK_PLLDTY_DIV8, 11, 1, 5, 17,
+ BUS_MSTOP(7, BIT(13))),
+ DEF_MOD("usb3_1_pclk_usbtst", CLK_PLLDTY_ACPU_DIV4, 11, 2, 5, 18,
+ BUS_MSTOP(7, BIT(15))),
+ DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19,
+ BUS_MSTOP(7, BIT(7))),
+ DEF_MOD("usb2_0_u2h1_hclk", CLK_PLLDTY_DIV8, 11, 4, 5, 20,
+ BUS_MSTOP(7, BIT(8))),
+ DEF_MOD("usb2_0_u2p_exr_cpuclk", CLK_PLLDTY_ACPU_DIV4, 11, 5, 5, 21,
+ BUS_MSTOP(7, BIT(9))),
+ DEF_MOD("usb2_0_pclk_usbtst0", CLK_PLLDTY_ACPU_DIV4, 11, 6, 5, 22,
+ BUS_MSTOP(7, BIT(10))),
+ DEF_MOD("usb2_0_pclk_usbtst1", CLK_PLLDTY_ACPU_DIV4, 11, 7, 5, 23,
+ BUS_MSTOP(7, BIT(11))),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_tx_i", CLK_SMUX2_GBE0_TXCLK, 11, 8, 5, 24,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_rx_i", CLK_SMUX2_GBE0_RXCLK, 11, 9, 5, 25,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_tx_180_i", CLK_SMUX2_GBE0_TXCLK, 11, 10, 5, 26,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_0_clk_rx_180_i", CLK_SMUX2_GBE0_RXCLK, 11, 11, 5, 27,
+ BUS_MSTOP(8, BIT(5)), 1),
+ DEF_MOD("gbeth_0_aclk_csr_i", CLK_PLLDTY_DIV8, 11, 12, 5, 28,
+ BUS_MSTOP(8, BIT(5))),
+ DEF_MOD("gbeth_0_aclk_i", CLK_PLLDTY_DIV8, 11, 13, 5, 29,
+ BUS_MSTOP(8, BIT(5))),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_tx_i", CLK_SMUX2_GBE1_TXCLK, 11, 14, 5, 30,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_rx_i", CLK_SMUX2_GBE1_RXCLK, 11, 15, 5, 31,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_tx_180_i", CLK_SMUX2_GBE1_TXCLK, 12, 0, 6, 0,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD_MUX_EXTERNAL("gbeth_1_clk_rx_180_i", CLK_SMUX2_GBE1_RXCLK, 12, 1, 6, 1,
+ BUS_MSTOP(8, BIT(6)), 1),
+ DEF_MOD("gbeth_1_aclk_csr_i", CLK_PLLDTY_DIV8, 12, 2, 6, 2,
+ BUS_MSTOP(8, BIT(6))),
+ DEF_MOD("gbeth_1_aclk_i", CLK_PLLDTY_DIV8, 12, 3, 6, 3,
+ BUS_MSTOP(8, BIT(6))),
+ DEF_MOD("pcie_0_aclk", CLK_PLLDTY_ACPU_DIV2, 12, 4, 6, 4,
+ BUS_MSTOP(1, BIT(13) | BIT(15))),
+ DEF_MOD("pcie_0_clk_pmu", CLK_PLLDTY_ACPU_DIV2, 12, 5, 6, 5,
+ BUS_MSTOP(1, BIT(13) | BIT(15))),
+ DEF_MOD("cru_0_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 2, 6, 18,
+ BUS_MSTOP(9, BIT(4))),
+ DEF_MOD_NO_PM("cru_0_vclk", CLK_PLLVDO_CRU0, 13, 3, 6, 19,
+ BUS_MSTOP(9, BIT(4))),
+ DEF_MOD("cru_0_pclk", CLK_PLLDTY_DIV16, 13, 4, 6, 20,
+ BUS_MSTOP(9, BIT(4))),
+ DEF_MOD("cru_1_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 5, 6, 21,
+ BUS_MSTOP(9, BIT(5))),
+ DEF_MOD_NO_PM("cru_1_vclk", CLK_PLLVDO_CRU1, 13, 6, 6, 22,
+ BUS_MSTOP(9, BIT(5))),
+ DEF_MOD("cru_1_pclk", CLK_PLLDTY_DIV16, 13, 7, 6, 23,
+ BUS_MSTOP(9, BIT(5))),
+ DEF_MOD("cru_2_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 8, 6, 24,
+ BUS_MSTOP(9, BIT(6))),
+ DEF_MOD_NO_PM("cru_2_vclk", CLK_PLLVDO_CRU2, 13, 9, 6, 25,
+ BUS_MSTOP(9, BIT(6))),
+ DEF_MOD("cru_2_pclk", CLK_PLLDTY_DIV16, 13, 10, 6, 26,
+ BUS_MSTOP(9, BIT(6))),
+ DEF_MOD("cru_3_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 11, 6, 27,
+ BUS_MSTOP(9, BIT(7))),
+ DEF_MOD_NO_PM("cru_3_vclk", CLK_PLLVDO_CRU3, 13, 12, 6, 28,
+ BUS_MSTOP(9, BIT(7))),
+ DEF_MOD("cru_3_pclk", CLK_PLLDTY_DIV16, 13, 13, 6, 29,
+ BUS_MSTOP(9, BIT(7))),
+ DEF_MOD("isp_0_reg_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 2, 7, 2,
+ BUS_MSTOP(9, BIT(8))),
+ DEF_MOD("isp_0_pclk", CLK_PLLDTY_DIV16, 14, 3, 7, 3,
+ BUS_MSTOP(9, BIT(8))),
+ DEF_MOD("isp_0_vin_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 4, 7, 4,
+ BUS_MSTOP(9, BIT(9))),
+ DEF_MOD("isp_0_isp_sclk", CLK_PLLVDO_ISP, 14, 5, 7, 5,
+ BUS_MSTOP(9, BIT(9))),
+ DEF_MOD("dsi_0_pclk", CLK_PLLDTY_DIV16, 14, 8, 7, 8,
+ BUS_MSTOP(9, BIT(14) | BIT(15))),
+ DEF_MOD("dsi_0_aclk", CLK_PLLDTY_ACPU_DIV2, 14, 9, 7, 9,
+ BUS_MSTOP(9, BIT(14) | BIT(15))),
+ DEF_MOD("dsi_0_vclk1", CLK_PLLDSI_GEAR, 14, 10, 7, 10,
+ BUS_MSTOP(9, BIT(14) | BIT(15))),
+ DEF_MOD("dsi_0_lpclk", CLK_PLLETH_LPCLK_GEAR, 14, 11, 7, 11,
+ BUS_MSTOP(9, BIT(14) | BIT(15))),
+ DEF_MOD("dsi_0_pllref_clk", CLK_QEXTAL, 14, 12, 7, 12,
+ BUS_MSTOP(9, BIT(14) | BIT(15))),
+ DEF_MOD("lcdc_0_clk_a", CLK_PLLDTY_ACPU_DIV2, 14, 13, 7, 13,
+ BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
+ DEF_MOD("lcdc_0_clk_p", CLK_PLLDTY_DIV16, 14, 14, 7, 14,
+ BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
+ DEF_MOD("lcdc_0_clk_d", CLK_PLLDSI_GEAR, 14, 15, 7, 15,
+ BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
+ DEF_MOD("gpu_0_clk", CLK_PLLGPU_GEAR, 15, 0, 7, 16,
+ BUS_MSTOP(3, BIT(4))),
+ DEF_MOD("gpu_0_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17,
+ BUS_MSTOP(3, BIT(4))),
+ DEF_MOD("gpu_0_ace_clk", CLK_PLLDTY_ACPU_DIV2, 15, 2, 7, 18,
+ BUS_MSTOP(3, BIT(4))),
+ DEF_MOD("tsu_0_pclk", CLK_QEXTAL, 16, 9, 8, 9,
+ BUS_MSTOP(5, BIT(2))),
+ DEF_MOD("tsu_1_pclk", CLK_QEXTAL, 16, 10, 8, 10,
+ BUS_MSTOP(2, BIT(15))),
+};
+
+static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
+ DEF_RST(3, 0, 1, 1), /* SYS_0_PRESETN */
+ DEF_RST(3, 1, 1, 2), /* DMAC_0_ARESETN */
+ DEF_RST(3, 2, 1, 3), /* DMAC_1_ARESETN */
+ DEF_RST(3, 3, 1, 4), /* DMAC_2_ARESETN */
+ DEF_RST(3, 4, 1, 5), /* DMAC_3_ARESETN */
+ DEF_RST(3, 5, 1, 6), /* DMAC_4_ARESETN */
+ DEF_RST(3, 6, 1, 7), /* ICU_0_PRESETN_I */
+ DEF_RST(3, 8, 1, 9), /* GIC_0_GICRESET_N */
+ DEF_RST(3, 9, 1, 10), /* GIC_0_DBG_GICRESET_N */
+ DEF_RST(6, 13, 2, 30), /* GTM_0_PRESETZ */
+ DEF_RST(6, 14, 2, 31), /* GTM_1_PRESETZ */
+ DEF_RST(6, 15, 3, 0), /* GTM_2_PRESETZ */
+ DEF_RST(7, 0, 3, 1), /* GTM_3_PRESETZ */
+ DEF_RST(7, 1, 3, 2), /* GTM_4_PRESETZ */
+ DEF_RST(7, 2, 3, 3), /* GTM_5_PRESETZ */
+ DEF_RST(7, 3, 3, 4), /* GTM_6_PRESETZ */
+ DEF_RST(7, 4, 3, 5), /* GTM_7_PRESETZ */
+ DEF_RST(7, 6, 3, 7), /* WDT_1_RESET */
+ DEF_RST(8, 1, 3, 18), /* RSCI0_PRESETN */
+ DEF_RST(8, 2, 3, 19), /* RSCI0_TRESETN */
+ DEF_RST(8, 3, 3, 20), /* RSCI1_PRESETN */
+ DEF_RST(8, 4, 3, 21), /* RSCI1_TRESETN */
+ DEF_RST(8, 5, 3, 22), /* RSCI2_PRESETN */
+ DEF_RST(8, 6, 3, 23), /* RSCI2_TRESETN */
+ DEF_RST(8, 7, 3, 24), /* RSCI3_PRESETN */
+ DEF_RST(8, 8, 3, 25), /* RSCI3_TRESETN */
+ DEF_RST(8, 9, 3, 26), /* RSCI4_PRESETN */
+ DEF_RST(8, 10, 3, 27), /* RSCI4_TRESETN */
+ DEF_RST(8, 11, 3, 28), /* RSCI5_PRESETN */
+ DEF_RST(8, 12, 3, 29), /* RSCI5_TRESETN */
+ DEF_RST(8, 13, 3, 30), /* RSCI6_PRESETN */
+ DEF_RST(8, 14, 3, 31), /* RSCI6_TRESETN */
+ DEF_RST(8, 15, 4, 0), /* RSCI7_PRESETN */
+ DEF_RST(9, 0, 4, 1), /* RSCI7_TRESETN */
+ DEF_RST(9, 1, 4, 2), /* RSCI8_PRESETN */
+ DEF_RST(9, 2, 4, 3), /* RSCI8_TRESETN */
+ DEF_RST(9, 3, 4, 4), /* RSCI9_PRESETN */
+ DEF_RST(9, 4, 4, 5), /* RSCI9_TRESETN */
+ DEF_RST(7, 9, 3, 10), /* RTC_0_RST_RTC */
+ DEF_RST(7, 10, 3, 11), /* RTC_0_RST_RTC_V */
+ DEF_RST(7, 11, 3, 12), /* RSPI_0_PRESETN */
+ DEF_RST(7, 12, 3, 13), /* RSPI_0_TRESETN */
+ DEF_RST(7, 13, 3, 14), /* RSPI_1_PRESETN */
+ DEF_RST(7, 14, 3, 15), /* RSPI_1_TRESETN */
+ DEF_RST(7, 15, 3, 16), /* RSPI_2_PRESETN */
+ DEF_RST(8, 0, 3, 17), /* RSPI_2_TRESETN */
+ DEF_RST(9, 5, 4, 6), /* SCIF_0_RST_SYSTEM_N */
+ DEF_RST(9, 6, 4, 7), /* I3C_0_PRESETN */
+ DEF_RST(9, 7, 4, 8), /* I3C_0_TRESETN */
+ DEF_RST(9, 8, 4, 9), /* RIIC_0_MRST */
+ DEF_RST(9, 9, 4, 10), /* RIIC_1_MRST */
+ DEF_RST(9, 10, 4, 11), /* RIIC_2_MRST */
+ DEF_RST(9, 11, 4, 12), /* RIIC_3_MRST */
+ DEF_RST(9, 12, 4, 13), /* RIIC_4_MRST */
+ DEF_RST(9, 13, 4, 14), /* RIIC_5_MRST */
+ DEF_RST(9, 14, 4, 15), /* RIIC_6_MRST */
+ DEF_RST(9, 15, 4, 16), /* RIIC_7_MRST */
+ DEF_RST(10, 0, 4, 17), /* RIIC_8_MRST */
+ DEF_RST(10, 1, 4, 18), /* CANFD_0_RSTP_N */
+ DEF_RST(10, 2, 4, 19), /* CANFD_0_RSTC_N */
+ DEF_RST(10, 3, 4, 20), /* SPI_HRESETN */
+ DEF_RST(10, 4, 4, 21), /* SPI_ARESETN */
+ DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
+ DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
+ DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
+ DEF_RST(10, 10, 4, 27), /* USB3_0_ARESETN */
+ DEF_RST(10, 11, 4, 28), /* USB3_1_ARESETN */
+ DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */
+ DEF_RST(10, 13, 4, 30), /* USB2_0_U2H1_HRESETN */
+ DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */
+ DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */
+ DEF_RST(11, 0, 5, 1), /* GBETH_0_ARESETN_I */
+ DEF_RST(11, 1, 5, 2), /* GBETH_1_ARESETN_I */
+ DEF_RST(11, 2, 5, 3), /* PCIE_0_ARESETN */
+ DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */
+ DEF_RST(12, 6, 5, 23), /* CRU_0_ARESETN */
+ DEF_RST(12, 7, 5, 24), /* CRU_0_S_RESETN */
+ DEF_RST(12, 8, 5, 25), /* CRU_1_PRESETN */
+ DEF_RST(12, 9, 5, 26), /* CRU_1_ARESETN */
+ DEF_RST(12, 10, 5, 27), /* CRU_1_S_RESETN */
+ DEF_RST(12, 11, 5, 28), /* CRU_2_PRESETN */
+ DEF_RST(12, 12, 5, 29), /* CRU_2_ARESETN */
+ DEF_RST(12, 13, 5, 30), /* CRU_2_S_RESETN */
+ DEF_RST(12, 14, 5, 31), /* CRU_3_PRESETN */
+ DEF_RST(12, 15, 6, 0), /* CRU_3_ARESETN */
+ DEF_RST(13, 0, 6, 1), /* CRU_3_S_RESETN */
+ DEF_RST(13, 1, 6, 2), /* ISP_0_VIN_ARESETN */
+ DEF_RST(13, 2, 6, 3), /* ISP_0_REG_ARESETN */
+ DEF_RST(13, 3, 6, 4), /* ISP_0_ISP_SRESETN */
+ DEF_RST(13, 4, 6, 5), /* ISP_0_PRESETN */
+ DEF_RST(13, 7, 6, 8), /* DSI_0_PRESETN */
+ DEF_RST(13, 8, 6, 9), /* DSI_0_ARESETN */
+ DEF_RST(13, 12, 6, 13), /* LCDC_0_RESET_N */
+ DEF_RST(13, 13, 6, 14), /* GPU_0_RESETN */
+ DEF_RST(13, 14, 6, 15), /* GPU_0_AXI_RESETN */
+ DEF_RST(13, 15, 6, 16), /* GPU_0_ACE_RESETN */
+ DEF_RST(15, 7, 7, 8), /* TSU_0_PRESETN */
+ DEF_RST(15, 8, 7, 9), /* TSU_1_PRESETN */
+};
+
+const struct rzv2h_cpg_info r9a09g057_cpg_info __initconst = {
+ /* Core Clocks */
+ .core_clks = r9a09g057_core_clks,
+ .num_core_clks = ARRAY_SIZE(r9a09g057_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r9a09g057_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r9a09g057_mod_clks),
+ .num_hw_mod_clks = 25 * 16,
+
+ /* Resets */
+ .resets = r9a09g057_resets,
+ .num_resets = ARRAY_SIZE(r9a09g057_resets),
+
+ .num_mstop_bits = 192,
+};
diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a09g077-cpg.c
new file mode 100644
index 000000000..f777601a2
--- /dev/null
+++ b/drivers/clk/renesas/r9a09g077-cpg.c
@@ -0,0 +1,519 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r9a09g077 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2025 Renesas Electronics Corp.
+ *
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/math.h>
+#include <linux/types.h>
+
+#include <dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h>
+#include <dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h>
+#include "renesas-cpg-mssr.h"
+
+#define RZT2H_REG_BLOCK_SHIFT 11
+#define RZT2H_REG_OFFSET_MASK GENMASK(10, 0)
+#define RZT2H_REG_CONF(block, offset) (((block) << RZT2H_REG_BLOCK_SHIFT) | \
+ ((offset) & RZT2H_REG_OFFSET_MASK))
+
+#define RZT2H_REG_BLOCK(x) ((x) >> RZT2H_REG_BLOCK_SHIFT)
+#define RZT2H_REG_OFFSET(x) ((x) & RZT2H_REG_OFFSET_MASK)
+
+#define SCKCR RZT2H_REG_CONF(0, 0x00)
+#define SCKCR2 RZT2H_REG_CONF(1, 0x04)
+#define SCKCR3 RZT2H_REG_CONF(0, 0x08)
+
+#define OFFSET_MASK GENMASK(31, 20)
+#define SHIFT_MASK GENMASK(19, 12)
+#define WIDTH_MASK GENMASK(11, 8)
+
+#define CONF_PACK(offset, shift, width) \
+ (FIELD_PREP_CONST(OFFSET_MASK, (offset)) | \
+ FIELD_PREP_CONST(SHIFT_MASK, (shift)) | \
+ FIELD_PREP_CONST(WIDTH_MASK, (width)))
+
+#define GET_SHIFT(val) FIELD_GET(SHIFT_MASK, val)
+#define GET_WIDTH(val) FIELD_GET(WIDTH_MASK, val)
+#define GET_REG_OFFSET(val) FIELD_GET(OFFSET_MASK, val)
+
+#define FSELXSPI0 CONF_PACK(SCKCR, 0, 3)
+#define FSELXSPI1 CONF_PACK(SCKCR, 8, 3)
+#define DIVSEL_XSPI0 CONF_PACK(SCKCR, 6, 1)
+#define DIVSEL_XSPI1 CONF_PACK(SCKCR, 14, 1)
+#define FSELCANFD CONF_PACK(SCKCR, 20, 1)
+#define SEL_PLL CONF_PACK(SCKCR, 22, 1)
+
+#define DIVCA55C0 CONF_PACK(SCKCR2, 8, 1)
+#define DIVCA55C1 CONF_PACK(SCKCR2, 9, 1)
+#define DIVCA55C2 CONF_PACK(SCKCR2, 10, 1)
+#define DIVCA55C3 CONF_PACK(SCKCR2, 11, 1)
+#define DIVCA55S CONF_PACK(SCKCR2, 12, 1)
+#define DIVSPI3ASYNC CONF_PACK(SCKCR2, 16, 2)
+#define DIVSCI5ASYNC CONF_PACK(SCKCR2, 18, 2)
+
+#define DIVSPI0ASYNC CONF_PACK(SCKCR3, 0, 2)
+#define DIVSPI1ASYNC CONF_PACK(SCKCR3, 2, 2)
+#define DIVSPI2ASYNC CONF_PACK(SCKCR3, 4, 2)
+#define DIVSCI0ASYNC CONF_PACK(SCKCR3, 6, 2)
+#define DIVSCI1ASYNC CONF_PACK(SCKCR3, 8, 2)
+#define DIVSCI2ASYNC CONF_PACK(SCKCR3, 10, 2)
+#define DIVSCI3ASYNC CONF_PACK(SCKCR3, 12, 2)
+#define DIVSCI4ASYNC CONF_PACK(SCKCR3, 14, 2)
+
+enum rzt2h_clk_types {
+ CLK_TYPE_RZT2H_DIV = CLK_TYPE_CUSTOM, /* Clock with divider */
+ CLK_TYPE_RZT2H_MUX, /* Clock with clock source selector */
+ CLK_TYPE_RZT2H_FSELXSPI, /* Clock with FSELXSPIn source selector */
+};
+
+#define DEF_DIV(_name, _id, _parent, _conf, _dtable) \
+ DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_DIV, .conf = _conf, \
+ .parent = _parent, .dtable = _dtable, .flag = 0)
+#define DEF_MUX(_name, _id, _conf, _parent_names, _num_parents, _mux_flags) \
+ DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_MUX, .conf = _conf, \
+ .parent_names = _parent_names, .num_parents = _num_parents, \
+ .flag = CLK_SET_RATE_PARENT, .mux_flags = _mux_flags)
+#define DEF_DIV_FSELXSPI(_name, _id, _parent, _conf, _dtable) \
+ DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_FSELXSPI, .conf = _conf, \
+ .parent = _parent, .dtable = _dtable, .flag = 0)
+
+enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A09G077_PCLKCAN,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+
+ /* Internal Core Clocks */
+ CLK_LOCO,
+ CLK_PLL0,
+ CLK_PLL1,
+ CLK_PLL2,
+ CLK_PLL4,
+ CLK_SEL_CLK_PLL0,
+ CLK_SEL_CLK_PLL1,
+ CLK_SEL_CLK_PLL2,
+ CLK_SEL_CLK_PLL4,
+ CLK_PLL4D1,
+ CLK_PLL4D1_DIV3,
+ CLK_PLL4D1_DIV4,
+ CLK_PLL4D3,
+ CLK_PLL4D3_DIV10,
+ CLK_PLL4D3_DIV20,
+ CLK_SCI0ASYNC,
+ CLK_SCI1ASYNC,
+ CLK_SCI2ASYNC,
+ CLK_SCI3ASYNC,
+ CLK_SCI4ASYNC,
+ CLK_SCI5ASYNC,
+ CLK_SPI0ASYNC,
+ CLK_SPI1ASYNC,
+ CLK_SPI2ASYNC,
+ CLK_SPI3ASYNC,
+ CLK_DIVSELXSPI0_SCKCR,
+ CLK_DIVSELXSPI1_SCKCR,
+
+ /* Module Clocks */
+ MOD_CLK_BASE,
+};
+
+static const struct clk_div_table dtable_1_2[] = {
+ {0, 2},
+ {1, 1},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_6_8_16_32_64[] = {
+ {6, 64},
+ {5, 32},
+ {4, 16},
+ {3, 8},
+ {2, 6},
+ {0, 0},
+};
+
+static const struct clk_div_table dtable_24_25_30_32[] = {
+ {0, 32},
+ {1, 30},
+ {2, 25},
+ {3, 24},
+ {0, 0},
+};
+
+/* Mux clock tables */
+
+static const char * const sel_clk_pll0[] = { ".loco", ".pll0" };
+static const char * const sel_clk_pll1[] = { ".loco", ".pll1" };
+static const char * const sel_clk_pll2[] = { ".loco", ".pll2" };
+static const char * const sel_clk_pll4[] = { ".loco", ".pll4" };
+static const char * const sel_clk_pll4d1_div3_div4[] = { ".pll4d1_div3", ".pll4d1_div4" };
+static const char * const sel_clk_pll4d3_div10_div20[] = { ".pll4d3_div10", ".pll4d3_div20" };
+
+static const struct cpg_core_clk r9a09g077_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+
+ /* Internal Core Clocks */
+ DEF_RATE(".loco", CLK_LOCO, 1000 * 1000),
+ DEF_FIXED(".pll0", CLK_PLL0, CLK_EXTAL, 1, 48),
+ DEF_FIXED(".pll1", CLK_PLL1, CLK_EXTAL, 1, 40),
+ DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 1, 32),
+ DEF_FIXED(".pll4", CLK_PLL4, CLK_EXTAL, 1, 96),
+
+ DEF_MUX(".sel_clk_pll0", CLK_SEL_CLK_PLL0, SEL_PLL,
+ sel_clk_pll0, ARRAY_SIZE(sel_clk_pll0), CLK_MUX_READ_ONLY),
+ DEF_MUX(".sel_clk_pll1", CLK_SEL_CLK_PLL1, SEL_PLL,
+ sel_clk_pll1, ARRAY_SIZE(sel_clk_pll1), CLK_MUX_READ_ONLY),
+ DEF_MUX(".sel_clk_pll2", CLK_SEL_CLK_PLL2, SEL_PLL,
+ sel_clk_pll2, ARRAY_SIZE(sel_clk_pll2), CLK_MUX_READ_ONLY),
+ DEF_MUX(".sel_clk_pll4", CLK_SEL_CLK_PLL4, SEL_PLL,
+ sel_clk_pll4, ARRAY_SIZE(sel_clk_pll4), CLK_MUX_READ_ONLY),
+
+ DEF_FIXED(".pll4d1", CLK_PLL4D1, CLK_SEL_CLK_PLL4, 1, 1),
+ DEF_FIXED(".pll4d1_div3", CLK_PLL4D1_DIV3, CLK_PLL4D1, 3, 1),
+ DEF_FIXED(".pll4d1_div4", CLK_PLL4D1_DIV4, CLK_PLL4D1, 4, 1),
+ DEF_FIXED(".pll4d3", CLK_PLL4D3, CLK_SEL_CLK_PLL4, 3, 1),
+ DEF_FIXED(".pll4d3_div10", CLK_PLL4D3_DIV10, CLK_PLL4D3, 10, 1),
+ DEF_FIXED(".pll4d3_div20", CLK_PLL4D3_DIV20, CLK_PLL4D3, 20, 1),
+
+ DEF_DIV(".sci0async", CLK_SCI0ASYNC, CLK_PLL4D1, DIVSCI0ASYNC,
+ dtable_24_25_30_32),
+ DEF_DIV(".sci1async", CLK_SCI1ASYNC, CLK_PLL4D1, DIVSCI1ASYNC,
+ dtable_24_25_30_32),
+ DEF_DIV(".sci2async", CLK_SCI2ASYNC, CLK_PLL4D1, DIVSCI2ASYNC,
+ dtable_24_25_30_32),
+ DEF_DIV(".sci3async", CLK_SCI3ASYNC, CLK_PLL4D1, DIVSCI3ASYNC,
+ dtable_24_25_30_32),
+ DEF_DIV(".sci4async", CLK_SCI4ASYNC, CLK_PLL4D1, DIVSCI4ASYNC,
+ dtable_24_25_30_32),
+ DEF_DIV(".sci5async", CLK_SCI5ASYNC, CLK_PLL4D1, DIVSCI5ASYNC,
+ dtable_24_25_30_32),
+
+ DEF_DIV(".spi0async", CLK_SPI0ASYNC, CLK_PLL4D1, DIVSPI0ASYNC,
+ dtable_24_25_30_32),
+ DEF_DIV(".spi1async", CLK_SPI1ASYNC, CLK_PLL4D1, DIVSPI1ASYNC,
+ dtable_24_25_30_32),
+ DEF_DIV(".spi2async", CLK_SPI2ASYNC, CLK_PLL4D1, DIVSPI2ASYNC,
+ dtable_24_25_30_32),
+ DEF_DIV(".spi3async", CLK_SPI3ASYNC, CLK_PLL4D1, DIVSPI3ASYNC,
+ dtable_24_25_30_32),
+
+ DEF_MUX(".divselxspi0", CLK_DIVSELXSPI0_SCKCR, DIVSEL_XSPI0,
+ sel_clk_pll4d1_div3_div4,
+ ARRAY_SIZE(sel_clk_pll4d1_div3_div4), 0),
+ DEF_MUX(".divselxspi1", CLK_DIVSELXSPI1_SCKCR, DIVSEL_XSPI1,
+ sel_clk_pll4d1_div3_div4,
+ ARRAY_SIZE(sel_clk_pll4d1_div3_div4), 0),
+
+ /* Core output clk */
+ DEF_DIV("CA55C0", R9A09G077_CLK_CA55C0, CLK_SEL_CLK_PLL0, DIVCA55C0,
+ dtable_1_2),
+ DEF_DIV("CA55C1", R9A09G077_CLK_CA55C1, CLK_SEL_CLK_PLL0, DIVCA55C1,
+ dtable_1_2),
+ DEF_DIV("CA55C2", R9A09G077_CLK_CA55C2, CLK_SEL_CLK_PLL0, DIVCA55C2,
+ dtable_1_2),
+ DEF_DIV("CA55C3", R9A09G077_CLK_CA55C3, CLK_SEL_CLK_PLL0, DIVCA55C3,
+ dtable_1_2),
+ DEF_DIV("CA55S", R9A09G077_CLK_CA55S, CLK_SEL_CLK_PLL0, DIVCA55S,
+ dtable_1_2),
+ DEF_FIXED("PCLKGPTL", R9A09G077_CLK_PCLKGPTL, CLK_SEL_CLK_PLL1, 2, 1),
+ DEF_FIXED("PCLKH", R9A09G077_CLK_PCLKH, CLK_SEL_CLK_PLL1, 4, 1),
+ DEF_FIXED("PCLKM", R9A09G077_CLK_PCLKM, CLK_SEL_CLK_PLL1, 8, 1),
+ DEF_FIXED("PCLKL", R9A09G077_CLK_PCLKL, CLK_SEL_CLK_PLL1, 16, 1),
+ DEF_FIXED("PCLKAH", R9A09G077_CLK_PCLKAH, CLK_PLL4D1, 6, 1),
+ DEF_FIXED("PCLKAM", R9A09G077_CLK_PCLKAM, CLK_PLL4D1, 12, 1),
+ DEF_FIXED("SDHI_CLKHS", R9A09G077_SDHI_CLKHS, CLK_SEL_CLK_PLL2, 1, 1),
+ DEF_FIXED("USB_CLK", R9A09G077_USB_CLK, CLK_PLL4D1, 48, 1),
+ DEF_FIXED("ETCLKA", R9A09G077_ETCLKA, CLK_SEL_CLK_PLL1, 5, 1),
+ DEF_FIXED("ETCLKB", R9A09G077_ETCLKB, CLK_SEL_CLK_PLL1, 8, 1),
+ DEF_FIXED("ETCLKC", R9A09G077_ETCLKC, CLK_SEL_CLK_PLL1, 10, 1),
+ DEF_FIXED("ETCLKD", R9A09G077_ETCLKD, CLK_SEL_CLK_PLL1, 20, 1),
+ DEF_FIXED("ETCLKE", R9A09G077_ETCLKE, CLK_SEL_CLK_PLL1, 40, 1),
+ DEF_DIV_FSELXSPI("XSPI_CLK0", R9A09G077_XSPI_CLK0, CLK_DIVSELXSPI0_SCKCR,
+ FSELXSPI0, dtable_6_8_16_32_64),
+ DEF_DIV_FSELXSPI("XSPI_CLK1", R9A09G077_XSPI_CLK1, CLK_DIVSELXSPI1_SCKCR,
+ FSELXSPI1, dtable_6_8_16_32_64),
+ DEF_MUX("PCLKCAN", R9A09G077_PCLKCAN, FSELCANFD,
+ sel_clk_pll4d3_div10_div20, ARRAY_SIZE(sel_clk_pll4d3_div10_div20), 0),
+};
+
+static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = {
+ DEF_MOD("xspi0", 4, R9A09G077_CLK_PCLKH),
+ DEF_MOD("xspi1", 5, R9A09G077_CLK_PCLKH),
+ DEF_MOD("sci0fck", 8, CLK_SCI0ASYNC),
+ DEF_MOD("sci1fck", 9, CLK_SCI1ASYNC),
+ DEF_MOD("sci2fck", 10, CLK_SCI2ASYNC),
+ DEF_MOD("sci3fck", 11, CLK_SCI3ASYNC),
+ DEF_MOD("sci4fck", 12, CLK_SCI4ASYNC),
+ DEF_MOD("iic0", 100, R9A09G077_CLK_PCLKL),
+ DEF_MOD("iic1", 101, R9A09G077_CLK_PCLKL),
+ DEF_MOD("spi0", 104, CLK_SPI0ASYNC),
+ DEF_MOD("spi1", 105, CLK_SPI1ASYNC),
+ DEF_MOD("spi2", 106, CLK_SPI2ASYNC),
+ DEF_MOD("mtu3", 200, R9A09G077_CLK_PCLKH),
+ DEF_MOD("adc0", 206, R9A09G077_CLK_PCLKH),
+ DEF_MOD("adc1", 207, R9A09G077_CLK_PCLKH),
+ DEF_MOD("adc2", 225, R9A09G077_CLK_PCLKM),
+ DEF_MOD("tsu", 307, R9A09G077_CLK_PCLKL),
+ DEF_MOD("canfd", 310, R9A09G077_CLK_PCLKM),
+ DEF_MOD("gmac0", 400, R9A09G077_CLK_PCLKM),
+ DEF_MOD("ethsw", 401, R9A09G077_CLK_PCLKM),
+ DEF_MOD("ethss", 403, R9A09G077_CLK_PCLKM),
+ DEF_MOD("usb", 408, R9A09G077_CLK_PCLKAM),
+ DEF_MOD("gmac1", 416, R9A09G077_CLK_PCLKAM),
+ DEF_MOD("gmac2", 417, R9A09G077_CLK_PCLKAM),
+ DEF_MOD("sci5fck", 600, CLK_SCI5ASYNC),
+ DEF_MOD("iic2", 601, R9A09G077_CLK_PCLKL),
+ DEF_MOD("spi3", 602, CLK_SPI3ASYNC),
+ DEF_MOD("sdhi0", 1212, R9A09G077_CLK_PCLKAM),
+ DEF_MOD("sdhi1", 1213, R9A09G077_CLK_PCLKAM),
+};
+
+static struct clk * __init
+r9a09g077_cpg_div_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ void __iomem *addr, struct cpg_mssr_pub *pub)
+{
+ const struct clk *parent;
+ const char *parent_name;
+ struct clk_hw *clk_hw;
+
+ parent = pub->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ if (core->dtable)
+ clk_hw = devm_clk_hw_register_divider_table(dev, core->name,
+ parent_name,
+ CLK_SET_RATE_PARENT,
+ addr,
+ GET_SHIFT(core->conf),
+ GET_WIDTH(core->conf),
+ core->flag,
+ core->dtable,
+ &pub->rmw_lock);
+ else
+ clk_hw = devm_clk_hw_register_divider(dev, core->name,
+ parent_name,
+ CLK_SET_RATE_PARENT,
+ addr,
+ GET_SHIFT(core->conf),
+ GET_WIDTH(core->conf),
+ core->flag, &pub->rmw_lock);
+
+ if (IS_ERR(clk_hw))
+ return ERR_CAST(clk_hw);
+
+ return clk_hw->clk;
+}
+
+static struct clk * __init
+r9a09g077_cpg_mux_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ void __iomem *addr, struct cpg_mssr_pub *pub)
+{
+ struct clk_hw *clk_hw;
+
+ clk_hw = devm_clk_hw_register_mux(dev, core->name,
+ core->parent_names, core->num_parents,
+ core->flag,
+ addr,
+ GET_SHIFT(core->conf),
+ GET_WIDTH(core->conf),
+ core->mux_flags, &pub->rmw_lock);
+ if (IS_ERR(clk_hw))
+ return ERR_CAST(clk_hw);
+
+ return clk_hw->clk;
+}
+
+static unsigned int r9a09g077_cpg_fselxspi_get_divider(struct clk_hw *hw, unsigned long rate,
+ unsigned int num_parents)
+{
+ struct clk_fixed_factor *ff;
+ struct clk_hw *parent_hw;
+ unsigned long best_rate;
+ unsigned int i;
+
+ for (i = 0; i < num_parents; i++) {
+ parent_hw = clk_hw_get_parent_by_index(hw, i);
+ best_rate = clk_hw_round_rate(parent_hw, rate);
+
+ if (best_rate == rate) {
+ ff = to_clk_fixed_factor(parent_hw);
+ return ff->div;
+ }
+ }
+
+ /* No parent could provide the exact rate - this should not happen */
+ return 0;
+}
+
+static int r9a09g077_cpg_fselxspi_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+ unsigned long parent_rate, best = 0, now;
+ const struct clk_div_table *clkt;
+ unsigned long rate = req->rate;
+ unsigned int num_parents;
+ unsigned int divselxspi;
+ unsigned int div = 0;
+
+ if (!rate)
+ rate = 1;
+
+ /* Get the number of parents for FSELXSPIn */
+ num_parents = clk_hw_get_num_parents(req->best_parent_hw);
+
+ for (clkt = divider->table; clkt->div; clkt++) {
+ parent_rate = clk_hw_round_rate(req->best_parent_hw, rate * clkt->div);
+ /* Skip if parent can't provide any valid rate */
+ if (!parent_rate)
+ continue;
+
+ /* Determine which DIVSELXSPIn divider (3 or 4) provides this parent_rate */
+ divselxspi = r9a09g077_cpg_fselxspi_get_divider(req->best_parent_hw, parent_rate,
+ num_parents);
+ if (!divselxspi)
+ continue;
+
+ /*
+ * DIVSELXSPIx supports 800MHz and 600MHz operation.
+ * When divselxspi is 4 (600MHz operation), only FSELXSPIn dividers of 8 and 16
+ * are supported. Otherwise, when divselxspi is 3 (800MHz operation),
+ * dividers of 6, 8, 16, 32, and 64 are supported. This check ensures that
+ * FSELXSPIx is set correctly based on hardware limitations.
+ */
+ if (divselxspi == 4 && (clkt->div != 8 && clkt->div != 16))
+ continue;
+
+ now = DIV_ROUND_UP_ULL(parent_rate, clkt->div);
+ if (abs(rate - now) < abs(rate - best)) {
+ div = clkt->div;
+ best = now;
+ req->best_parent_rate = parent_rate;
+ }
+ }
+
+ if (!div) {
+ req->best_parent_rate = clk_hw_round_rate(req->best_parent_hw, 1);
+ divselxspi = r9a09g077_cpg_fselxspi_get_divider(req->best_parent_hw,
+ req->best_parent_rate,
+ num_parents);
+ /* default to divider 3 which will result DIVSELXSPIn = 800 MHz */
+ if (!divselxspi)
+ divselxspi = 3;
+
+ /*
+ * Use the maximum divider based on the parent clock rate:
+ * - 64 when DIVSELXSPIx is 800 MHz (divider = 3)
+ * - 16 when DIVSELXSPIx is 600 MHz (divider = 4)
+ */
+ div = divselxspi == 3 ? 64 : 16;
+ }
+
+ req->rate = DIV_ROUND_UP_ULL(req->best_parent_rate, div);
+
+ return 0;
+}
+
+static struct clk * __init
+r9a09g077_cpg_fselxspi_div_clk_register(struct device *dev,
+ const struct cpg_core_clk *core,
+ void __iomem *addr,
+ struct cpg_mssr_pub *pub)
+{
+ static struct clk_ops *xspi_div_ops;
+ struct clk_init_data init = {};
+ const struct clk *parent;
+ const char *parent_name;
+ struct clk_divider *div;
+ struct clk_hw *hw;
+ int ret;
+
+ parent = pub->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ if (!xspi_div_ops) {
+ xspi_div_ops = devm_kzalloc(dev, sizeof(*xspi_div_ops), GFP_KERNEL);
+ if (!xspi_div_ops)
+ return ERR_PTR(-ENOMEM);
+ memcpy(xspi_div_ops, &clk_divider_ops,
+ sizeof(const struct clk_ops));
+ xspi_div_ops->determine_rate = r9a09g077_cpg_fselxspi_determine_rate;
+ }
+
+ parent_name = __clk_get_name(parent);
+ init.name = core->name;
+ init.ops = xspi_div_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ div->reg = addr;
+ div->shift = GET_SHIFT(core->conf);
+ div->width = GET_WIDTH(core->conf);
+ div->flags = core->flag;
+ div->lock = &pub->rmw_lock;
+ div->hw.init = &init;
+ div->table = core->dtable;
+
+ hw = &div->hw;
+ ret = devm_clk_hw_register(dev, hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return hw->clk;
+}
+
+static struct clk * __init
+r9a09g077_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct cpg_mssr_pub *pub)
+{
+ u32 offset = GET_REG_OFFSET(core->conf);
+ void __iomem *base = RZT2H_REG_BLOCK(offset) ? pub->base1 : pub->base0;
+ void __iomem *addr = base + RZT2H_REG_OFFSET(offset);
+
+ switch (core->type) {
+ case CLK_TYPE_RZT2H_DIV:
+ return r9a09g077_cpg_div_clk_register(dev, core, addr, pub);
+ case CLK_TYPE_RZT2H_MUX:
+ return r9a09g077_cpg_mux_clk_register(dev, core, addr, pub);
+ case CLK_TYPE_RZT2H_FSELXSPI:
+ return r9a09g077_cpg_fselxspi_div_clk_register(dev, core, addr, pub);
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+}
+
+const struct cpg_mssr_info r9a09g077_cpg_mssr_info = {
+ /* Core Clocks */
+ .core_clks = r9a09g077_core_clks,
+ .num_core_clks = ARRAY_SIZE(r9a09g077_core_clks),
+ .last_dt_core_clk = LAST_DT_CORE_CLK,
+ .num_total_core_clks = MOD_CLK_BASE,
+
+ /* Module Clocks */
+ .mod_clks = r9a09g077_mod_clks,
+ .num_mod_clks = ARRAY_SIZE(r9a09g077_mod_clks),
+ .num_hw_mod_clks = 14 * 32,
+
+ .reg_layout = CLK_REG_LAYOUT_RZ_T2H,
+ .cpg_clk_register = r9a09g077_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/rcar-cpg-lib.c b/drivers/clk/renesas/rcar-cpg-lib.c
new file mode 100644
index 000000000..fc73aa685
--- /dev/null
+++ b/drivers/clk/renesas/rcar-cpg-lib.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car Gen3 Clock Pulse Generator Library
+ *
+ * Copyright (C) 2015-2018 Glider bvba
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ *
+ * Based on clk-rcar-gen3.c
+ *
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+
+#include "rcar-cpg-lib.h"
+
+DEFINE_SPINLOCK(cpg_lock);
+
+void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&cpg_lock, flags);
+ val = readl(reg);
+ val &= ~clear;
+ val |= set;
+ writel(val, reg);
+ spin_unlock_irqrestore(&cpg_lock, flags);
+}
+
+static int cpg_simple_notifier_call(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct cpg_simple_notifier *csn =
+ container_of(nb, struct cpg_simple_notifier, nb);
+
+ switch (action) {
+ case PM_EVENT_SUSPEND:
+ csn->saved = readl(csn->reg);
+ return NOTIFY_OK;
+
+ case PM_EVENT_RESUME:
+ writel(csn->saved, csn->reg);
+ return NOTIFY_OK;
+ }
+ return NOTIFY_DONE;
+}
+
+void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
+ struct cpg_simple_notifier *csn)
+{
+ csn->nb.notifier_call = cpg_simple_notifier_call;
+ raw_notifier_chain_register(notifiers, &csn->nb);
+}
+
+/*
+ * SDn Clock
+ */
+
+#define SDnSRCFC_SHIFT 2
+#define STPnHCK BIT(9 - SDnSRCFC_SHIFT)
+
+static const struct clk_div_table cpg_sdh_div_table[] = {
+ /*
+ * These values are recommended by the datasheet. Because they come
+ * first, Linux will only use these.
+ */
+ { 0, 1 }, { 1, 2 }, { STPnHCK | 2, 4 }, { STPnHCK | 3, 8 },
+ { STPnHCK | 4, 16 },
+ /*
+ * These values are not recommended because STPnHCK is wrong. But they
+ * have been seen because of broken firmware. So, we support reading
+ * them but Linux will sanitize them when initializing through
+ * recalc_rate.
+ */
+ { STPnHCK | 0, 1 }, { STPnHCK | 1, 2 }, { 2, 4 }, { 3, 8 }, { 4, 16 },
+ /* Sentinel */
+ { 0, 0 }
+};
+
+struct clk * __init cpg_sdh_clk_register(const char *name,
+ void __iomem *sdnckcr, const char *parent_name,
+ struct raw_notifier_head *notifiers)
+{
+ struct cpg_simple_notifier *csn;
+ struct clk *clk;
+
+ csn = kzalloc_obj(*csn);
+ if (!csn)
+ return ERR_PTR(-ENOMEM);
+
+ csn->reg = sdnckcr;
+
+ clk = clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
+ SDnSRCFC_SHIFT, 8, 0, cpg_sdh_div_table,
+ &cpg_lock);
+ if (IS_ERR(clk)) {
+ kfree(csn);
+ return clk;
+ }
+
+ cpg_simple_notifier_register(notifiers, csn);
+ return clk;
+}
+
+static const struct clk_div_table cpg_sd_div_table[] = {
+ { 0, 2 }, { 1, 4 }, { 0, 0 },
+};
+
+struct clk * __init cpg_sd_clk_register(const char *name,
+ void __iomem *sdnckcr, const char *parent_name)
+{
+ return clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
+ 0, 2, 0, cpg_sd_div_table, &cpg_lock);
+}
+
+struct rpc_clock {
+ struct clk_divider div;
+ struct clk_gate gate;
+ /*
+ * One notifier covers both RPC and RPCD2 clocks as they are both
+ * controlled by the same RPCCKCR register...
+ */
+ struct cpg_simple_notifier csn;
+};
+
+static const struct clk_div_table cpg_rpc_div_table[] = {
+ { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 },
+};
+
+struct clk * __init cpg_rpc_clk_register(const char *name,
+ void __iomem *rpcckcr, const char *parent_name,
+ struct raw_notifier_head *notifiers)
+{
+ struct rpc_clock *rpc;
+ struct clk *clk;
+
+ rpc = kzalloc_obj(*rpc);
+ if (!rpc)
+ return ERR_PTR(-ENOMEM);
+
+ rpc->div.reg = rpcckcr;
+ rpc->div.width = 3;
+ rpc->div.table = cpg_rpc_div_table;
+ rpc->div.lock = &cpg_lock;
+
+ rpc->gate.reg = rpcckcr;
+ rpc->gate.bit_idx = 8;
+ rpc->gate.flags = CLK_GATE_SET_TO_DISABLE;
+ rpc->gate.lock = &cpg_lock;
+
+ rpc->csn.reg = rpcckcr;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &rpc->div.hw, &clk_divider_ops,
+ &rpc->gate.hw, &clk_gate_ops,
+ CLK_SET_RATE_PARENT);
+ if (IS_ERR(clk)) {
+ kfree(rpc);
+ return clk;
+ }
+
+ cpg_simple_notifier_register(notifiers, &rpc->csn);
+ return clk;
+}
+
+struct rpcd2_clock {
+ struct clk_fixed_factor fixed;
+ struct clk_gate gate;
+};
+
+struct clk * __init cpg_rpcd2_clk_register(const char *name,
+ void __iomem *rpcckcr,
+ const char *parent_name)
+{
+ struct rpcd2_clock *rpcd2;
+ struct clk *clk;
+
+ rpcd2 = kzalloc_obj(*rpcd2);
+ if (!rpcd2)
+ return ERR_PTR(-ENOMEM);
+
+ rpcd2->fixed.mult = 1;
+ rpcd2->fixed.div = 2;
+
+ rpcd2->gate.reg = rpcckcr;
+ rpcd2->gate.bit_idx = 9;
+ rpcd2->gate.flags = CLK_GATE_SET_TO_DISABLE;
+ rpcd2->gate.lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &rpcd2->fixed.hw, &clk_fixed_factor_ops,
+ &rpcd2->gate.hw, &clk_gate_ops,
+ CLK_SET_RATE_PARENT);
+ if (IS_ERR(clk))
+ kfree(rpcd2);
+
+ return clk;
+}
diff --git a/drivers/clk/renesas/rcar-cpg-lib.h b/drivers/clk/renesas/rcar-cpg-lib.h
new file mode 100644
index 000000000..94627df1c
--- /dev/null
+++ b/drivers/clk/renesas/rcar-cpg-lib.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * R-Car Gen3 Clock Pulse Generator Library
+ *
+ * Copyright (C) 2015-2018 Glider bvba
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ *
+ * Based on clk-rcar-gen3.c
+ *
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#ifndef __CLK_RENESAS_RCAR_CPG_LIB_H__
+#define __CLK_RENESAS_RCAR_CPG_LIB_H__
+
+extern spinlock_t cpg_lock;
+
+struct cpg_simple_notifier {
+ struct notifier_block nb;
+ void __iomem *reg;
+ u32 saved;
+};
+
+void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
+ struct cpg_simple_notifier *csn);
+
+void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set);
+
+struct clk * __init cpg_sdh_clk_register(const char *name,
+ void __iomem *sdnckcr, const char *parent_name,
+ struct raw_notifier_head *notifiers);
+
+struct clk * __init cpg_sd_clk_register(const char *name,
+ void __iomem *sdnckcr, const char *parent_name);
+
+struct clk * __init cpg_rpc_clk_register(const char *name,
+ void __iomem *rpcckcr, const char *parent_name,
+ struct raw_notifier_head *notifiers);
+
+struct clk * __init cpg_rpcd2_clk_register(const char *name,
+ void __iomem *rpcckcr,
+ const char *parent_name);
+#endif
diff --git a/drivers/clk/renesas/rcar-gen2-cpg.c b/drivers/clk/renesas/rcar-gen2-cpg.c
new file mode 100644
index 000000000..484b27edf
--- /dev/null
+++ b/drivers/clk/renesas/rcar-gen2-cpg.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ */
+
+#include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+#define CPG_FRQCRB 0x0004
+#define CPG_FRQCRB_KICK BIT(31)
+#define CPG_SDCKCR 0x0074
+#define CPG_PLL0CR 0x00d8
+#define CPG_PLL0CR_STC_SHIFT 24
+#define CPG_PLL0CR_STC_MASK (0x7f << CPG_PLL0CR_STC_SHIFT)
+#define CPG_FRQCRC 0x00e0
+#define CPG_FRQCRC_ZFC_SHIFT 8
+#define CPG_FRQCRC_ZFC_MASK (0x1f << CPG_FRQCRC_ZFC_SHIFT)
+#define CPG_ADSPCKCR 0x025c
+#define CPG_RCANCKCR 0x0270
+
+static DEFINE_SPINLOCK(cpg_lock);
+
+/*
+ * Z Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable. clk->rate = parent->rate * mult / 32
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+struct cpg_z_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ void __iomem *kick_reg;
+};
+
+#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ unsigned int val;
+
+ val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;
+ mult = 32 - val;
+
+ return div_u64((u64)parent_rate * mult, 32);
+}
+
+static int cpg_z_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ unsigned long prate = req->best_parent_rate;
+ unsigned int min_mult, max_mult, mult;
+
+ min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
+ max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
+ if (max_mult < min_mult)
+ return -EINVAL;
+
+ mult = div64_ul(req->rate * 32ULL, prate);
+ mult = clamp(mult, min_mult, max_mult);
+
+ req->rate = div_u64((u64)prate * mult, 32);
+ return 0;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ u32 val, kick;
+ unsigned int i;
+
+ mult = div64_ul(rate * 32ULL, parent_rate);
+ mult = clamp(mult, 1U, 32U);
+
+ if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+ return -EBUSY;
+
+ val = readl(zclk->reg);
+ val &= ~CPG_FRQCRC_ZFC_MASK;
+ val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
+ writel(val, zclk->reg);
+
+ /*
+ * Set KICK bit in FRQCRB to update hardware setting and wait for
+ * clock change completion.
+ */
+ kick = readl(zclk->kick_reg);
+ kick |= CPG_FRQCRB_KICK;
+ writel(kick, zclk->kick_reg);
+
+ /*
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Using experimental measurements, it seems that no more than
+ * ~10 iterations are needed, independently of the CPU rate.
+ * Since this value might be dependent on external xtal rate, pll1
+ * rate or even the other emulation clocks rate, use 1000 as a
+ * "super" safe value.
+ */
+ for (i = 1000; i; i--) {
+ if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+ return 0;
+
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+ .recalc_rate = cpg_z_clk_recalc_rate,
+ .determine_rate = cpg_z_clk_determine_rate,
+ .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_init_data init = {};
+ struct cpg_z_clk *zclk;
+ struct clk *clk;
+
+ zclk = kzalloc_obj(*zclk);
+ if (!zclk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_z_clk_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ zclk->reg = base + CPG_FRQCRC;
+ zclk->kick_reg = base + CPG_FRQCRB;
+ zclk->hw.init = &init;
+
+ clk = clk_register(NULL, &zclk->hw);
+ if (IS_ERR(clk))
+ kfree(zclk);
+
+ return clk;
+}
+
+static struct clk * __init cpg_rcan_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_fixed_factor *fixed;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ fixed = kzalloc_obj(*fixed);
+ if (!fixed)
+ return ERR_PTR(-ENOMEM);
+
+ fixed->mult = 1;
+ fixed->div = 6;
+
+ gate = kzalloc_obj(*gate);
+ if (!gate) {
+ kfree(fixed);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_RCANCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &fixed->hw, &clk_fixed_factor_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(fixed);
+ }
+
+ return clk;
+}
+
+/* ADSP divisors */
+static const struct clk_div_table cpg_adsp_div_table[] = {
+ { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 },
+ { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
+ { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static struct clk * __init cpg_adsp_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_divider *div;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ div = kzalloc_obj(*div);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->reg = base + CPG_ADSPCKCR;
+ div->width = 4;
+ div->table = cpg_adsp_div_table;
+ div->lock = &cpg_lock;
+
+ gate = kzalloc_obj(*gate);
+ if (!gate) {
+ kfree(div);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = base + CPG_ADSPCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg_lock;
+
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+ &div->hw, &clk_divider_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(div);
+ }
+
+ return clk;
+}
+
+/* SDHI divisors */
+static const struct clk_div_table cpg_sdh_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static const struct clk_div_table cpg_sd01_div_table[] = {
+ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },
+ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },
+ { 0, 0 },
+};
+
+static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata;
+static unsigned int cpg_pll0_div __initdata;
+static u32 cpg_mode __initdata;
+static u32 cpg_quirks __initdata;
+
+#define SD_SKIP_FIRST BIT(0) /* Skip first clock in SD table */
+
+static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
+ {
+ .soc_id = "r8a77470",
+ .data = (void *)SD_SKIP_FIRST,
+ },
+ { /* sentinel */ }
+};
+
+struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+ struct cpg_mssr_pub *pub)
+{
+ const struct clk_div_table *table = NULL;
+ void __iomem *base = pub->base0;
+ struct clk **clks = pub->clks;
+ const struct clk *parent;
+ const char *parent_name;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+ unsigned int shift;
+
+ parent = clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ switch (core->type) {
+ /* R-Car Gen2 */
+ case CLK_TYPE_GEN2_MAIN:
+ div = cpg_pll_config->extal_div;
+ break;
+
+ case CLK_TYPE_GEN2_PLL0:
+ /*
+ * PLL0 is a configurable multiplier clock except on R-Car
+ * V2H/E2. Register the PLL0 clock as a fixed factor clock for
+ * now as there's no generic multiplier clock implementation and
+ * we currently have no need to change the multiplier value.
+ */
+ mult = cpg_pll_config->pll0_mult;
+ div = cpg_pll0_div;
+ if (!mult) {
+ u32 pll0cr = readl(base + CPG_PLL0CR);
+
+ mult = (((pll0cr & CPG_PLL0CR_STC_MASK) >>
+ CPG_PLL0CR_STC_SHIFT) + 1) * 2;
+ }
+ break;
+
+ case CLK_TYPE_GEN2_PLL1:
+ mult = cpg_pll_config->pll1_mult / 2;
+ break;
+
+ case CLK_TYPE_GEN2_PLL3:
+ mult = cpg_pll_config->pll3_mult;
+ break;
+
+ case CLK_TYPE_GEN2_Z:
+ return cpg_z_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_LB:
+ div = cpg_mode & BIT(18) ? 36 : 24;
+ break;
+
+ case CLK_TYPE_GEN2_ADSP:
+ return cpg_adsp_clk_register(core->name, parent_name, base);
+
+ case CLK_TYPE_GEN2_SDH:
+ table = cpg_sdh_div_table;
+ shift = 8;
+ break;
+
+ case CLK_TYPE_GEN2_SD0:
+ table = cpg_sd01_div_table;
+ if (cpg_quirks & SD_SKIP_FIRST)
+ table++;
+
+ shift = 4;
+ break;
+
+ case CLK_TYPE_GEN2_SD1:
+ table = cpg_sd01_div_table;
+ if (cpg_quirks & SD_SKIP_FIRST)
+ table++;
+
+ shift = 0;
+ break;
+
+ case CLK_TYPE_GEN2_QSPI:
+ div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
+ 8 : 10;
+ break;
+
+ case CLK_TYPE_GEN2_RCAN:
+ return cpg_rcan_clk_register(core->name, parent_name, base);
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!table)
+ return clk_register_fixed_factor(NULL, core->name, parent_name,
+ 0, mult, div);
+ else
+ return clk_register_divider_table(NULL, core->name,
+ parent_name, 0,
+ base + CPG_SDCKCR, shift, 4,
+ 0, table, &cpg_lock);
+}
+
+int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
+ unsigned int pll0_div, u32 mode)
+{
+ const struct soc_device_attribute *attr;
+
+ cpg_pll_config = config;
+ cpg_pll0_div = pll0_div;
+ cpg_mode = mode;
+ attr = soc_device_match(cpg_quirks_match);
+ if (attr)
+ cpg_quirks = (uintptr_t)attr->data;
+ pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks);
+
+ return 0;
+}
diff --git a/drivers/clk/renesas/rcar-gen2-cpg.h b/drivers/clk/renesas/rcar-gen2-cpg.h
new file mode 100644
index 000000000..3d4b127fd
--- /dev/null
+++ b/drivers/clk/renesas/rcar-gen2-cpg.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN2_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN2_CPG_H__
+
+enum rcar_gen2_clk_types {
+ CLK_TYPE_GEN2_MAIN = CLK_TYPE_CUSTOM,
+ CLK_TYPE_GEN2_PLL0,
+ CLK_TYPE_GEN2_PLL1,
+ CLK_TYPE_GEN2_PLL3,
+ CLK_TYPE_GEN2_Z,
+ CLK_TYPE_GEN2_LB,
+ CLK_TYPE_GEN2_ADSP,
+ CLK_TYPE_GEN2_SDH,
+ CLK_TYPE_GEN2_SD0,
+ CLK_TYPE_GEN2_SD1,
+ CLK_TYPE_GEN2_QSPI,
+ CLK_TYPE_GEN2_RCAN,
+};
+
+struct rcar_gen2_cpg_pll_config {
+ u8 extal_div;
+ u8 pll1_mult;
+ u8 pll3_mult;
+ u8 pll0_mult; /* leave as zero if PLL0CR exists */
+};
+
+struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+ struct cpg_mssr_pub *pub);
+int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
+ unsigned int pll0_div, u32 mode);
+
+#endif
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c
new file mode 100644
index 000000000..e5b503332
--- /dev/null
+++ b/drivers/clk/renesas/rcar-gen3-cpg.c
@@ -0,0 +1,551 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car Gen3 Clock Pulse Generator
+ *
+ * Copyright (C) 2015-2018 Glider bvba
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ *
+ * Based on clk-rcar-gen3.c
+ *
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/bug.h>
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-cpg-lib.h"
+#include "rcar-gen3-cpg.h"
+
+#define CPG_PLLECR 0x00d0 /* PLL Enable Control Register */
+
+#define CPG_PLLECR_PLLST(n) BIT(8 + (n)) /* PLLn Circuit Status */
+
+#define CPG_PLL0CR 0x00d8 /* PLLn Control Registers */
+#define CPG_PLL2CR 0x002c
+#define CPG_PLL4CR 0x01f4
+
+#define CPG_PLLnCR_STC_MASK GENMASK(30, 24) /* PLL Circuit Mult. Ratio */
+
+#define CPG_RCKCR_CKSEL BIT(15) /* RCLK Clock Source Select */
+
+/* PLL Clocks */
+struct cpg_pll_clk {
+ struct clk_hw hw;
+ void __iomem *pllcr_reg;
+ void __iomem *pllecr_reg;
+ unsigned int fixed_mult;
+ u32 pllecr_pllst_mask;
+};
+
+#define to_pll_clk(_hw) container_of(_hw, struct cpg_pll_clk, hw)
+
+static unsigned long cpg_pll_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
+ unsigned int mult;
+
+ mult = FIELD_GET(CPG_PLLnCR_STC_MASK, readl(pll_clk->pllcr_reg)) + 1;
+
+ return parent_rate * mult * pll_clk->fixed_mult;
+}
+
+static int cpg_pll_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
+ unsigned int min_mult, max_mult, mult;
+ unsigned long prate;
+
+ prate = req->best_parent_rate * pll_clk->fixed_mult;
+ min_mult = max(div64_ul(req->min_rate, prate), 1ULL);
+ max_mult = min(div64_ul(req->max_rate, prate), 128ULL);
+ if (max_mult < min_mult)
+ return -EINVAL;
+
+ mult = DIV_ROUND_CLOSEST_ULL(req->rate, prate);
+ mult = clamp(mult, min_mult, max_mult);
+
+ req->rate = prate * mult;
+ return 0;
+}
+
+static int cpg_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
+ unsigned int mult, i;
+ u32 val;
+
+ mult = DIV_ROUND_CLOSEST_ULL(rate, parent_rate * pll_clk->fixed_mult);
+ mult = clamp(mult, 1U, 128U);
+
+ val = readl(pll_clk->pllcr_reg);
+ val &= ~CPG_PLLnCR_STC_MASK;
+ val |= FIELD_PREP(CPG_PLLnCR_STC_MASK, mult - 1);
+ writel(val, pll_clk->pllcr_reg);
+
+ for (i = 1000; i; i--) {
+ if (readl(pll_clk->pllecr_reg) & pll_clk->pllecr_pllst_mask)
+ return 0;
+
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_pll_clk_ops = {
+ .recalc_rate = cpg_pll_clk_recalc_rate,
+ .determine_rate = cpg_pll_clk_determine_rate,
+ .set_rate = cpg_pll_clk_set_rate,
+};
+
+static struct clk * __init cpg_pll_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base,
+ unsigned int mult,
+ unsigned int offset,
+ unsigned int index)
+
+{
+ struct cpg_pll_clk *pll_clk;
+ struct clk_init_data init = {};
+ struct clk *clk;
+
+ pll_clk = kzalloc_obj(*pll_clk);
+ if (!pll_clk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_pll_clk_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pll_clk->hw.init = &init;
+ pll_clk->pllcr_reg = base + offset;
+ pll_clk->pllecr_reg = base + CPG_PLLECR;
+ pll_clk->fixed_mult = mult; /* PLL refclk x (setting + 1) x mult */
+ pll_clk->pllecr_pllst_mask = CPG_PLLECR_PLLST(index);
+
+ clk = clk_register(NULL, &pll_clk->hw);
+ if (IS_ERR(clk))
+ kfree(pll_clk);
+
+ return clk;
+}
+
+/*
+ * Z Clock & Z2 Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable.
+ * clk->rate = (parent->rate * mult / 32 ) / fixed_div
+ * parent - fixed parent. No clk_set_parent support
+ */
+#define CPG_FRQCRB 0x00000004
+#define CPG_FRQCRB_KICK BIT(31)
+#define CPG_FRQCRC 0x000000e0
+
+struct cpg_z_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ void __iomem *kick_reg;
+ unsigned long max_rate; /* Maximum rate for normal mode */
+ unsigned int fixed_div;
+ u32 mask;
+};
+
+#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult = 32 - field_get(zclk->mask, readl(zclk->reg));
+
+ return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
+ 32 * zclk->fixed_div);
+}
+
+static int cpg_z_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int min_mult, max_mult, mult;
+ unsigned long rate, prate;
+
+ rate = min(req->rate, req->max_rate);
+ if (rate <= zclk->max_rate) {
+ /* Set parent rate to initial value for normal modes */
+ prate = zclk->max_rate;
+ } else {
+ /* Set increased parent rate for boost modes */
+ prate = rate;
+ }
+ req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
+ prate * zclk->fixed_div);
+
+ prate = req->best_parent_rate / zclk->fixed_div;
+ min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
+ max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
+ if (max_mult < min_mult)
+ return -EINVAL;
+
+ mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);
+ mult = clamp(mult, min_mult, max_mult);
+
+ req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);
+ return 0;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ unsigned int i;
+
+ mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
+ parent_rate);
+ mult = clamp(mult, 1U, 32U);
+
+ if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+ return -EBUSY;
+
+ cpg_reg_modify(zclk->reg, zclk->mask,
+ field_prep(zclk->mask, 32 - mult));
+
+ /*
+ * Set KICK bit in FRQCRB to update hardware setting and wait for
+ * clock change completion.
+ */
+ cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
+
+ /*
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Using experimental measurements, it seems that no more than
+ * ~10 iterations are needed, independently of the CPU rate.
+ * Since this value might be dependent on external xtal rate, pll1
+ * rate or even the other emulation clocks rate, use 1000 as a
+ * "super" safe value.
+ */
+ for (i = 1000; i; i--) {
+ if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+ return 0;
+
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+ .recalc_rate = cpg_z_clk_recalc_rate,
+ .determine_rate = cpg_z_clk_determine_rate,
+ .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init __cpg_z_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *reg,
+ unsigned int div,
+ unsigned int offset,
+ unsigned int fcr,
+ unsigned int flags)
+{
+ struct clk_init_data init = {};
+ struct cpg_z_clk *zclk;
+ struct clk *clk;
+
+ zclk = kzalloc_obj(*zclk);
+ if (!zclk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_z_clk_ops;
+ init.flags = flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ zclk->reg = reg + fcr;
+ zclk->kick_reg = reg + CPG_FRQCRB;
+ zclk->hw.init = &init;
+ zclk->mask = GENMASK(offset + 4, offset);
+ zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
+
+ clk = clk_register(NULL, &zclk->hw);
+ if (IS_ERR(clk)) {
+ kfree(zclk);
+ return clk;
+ }
+
+ zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
+ zclk->fixed_div;
+ return clk;
+}
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *reg,
+ unsigned int div,
+ unsigned int offset)
+{
+ return __cpg_z_clk_register(name, parent_name, reg, div, offset,
+ CPG_FRQCRC, CLK_SET_RATE_PARENT);
+}
+
+static struct clk * __init cpg_zg_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *reg,
+ unsigned int div,
+ unsigned int offset)
+{
+ return __cpg_z_clk_register(name, parent_name, reg, div, offset,
+ CPG_FRQCRB, 0);
+
+}
+
+static const struct clk_div_table cpg_rpcsrc_div_table[] = {
+ { 2, 5 }, { 3, 6 }, { 0, 0 },
+};
+
+static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata;
+static unsigned int cpg_clk_extalr __initdata;
+static u32 cpg_mode __initdata;
+static u32 cpg_quirks __initdata;
+
+#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
+
+static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
+ {
+ .soc_id = "r8a7796", .revision = "ES1.0",
+ .data = (void *)(RCKCR_CKSEL),
+ },
+ { /* sentinel */ }
+};
+
+struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+ struct cpg_mssr_pub *pub)
+{
+ struct raw_notifier_head *notifiers = &pub->notifiers;
+ void __iomem *base = pub->base0;
+ struct clk **clks = pub->clks;
+ const struct clk *parent;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+ u32 value;
+
+ parent = clks[core->parent & 0xffff]; /* some types use high bits */
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ switch (core->type) {
+ case CLK_TYPE_GEN3_MAIN:
+ div = cpg_pll_config->extal_div;
+ break;
+
+ case CLK_TYPE_GEN3_PLL0:
+ /*
+ * PLL0 is implemented as a custom clock, to change the
+ * multiplier when cpufreq changes between normal and boost
+ * modes.
+ */
+ return cpg_pll_clk_register(core->name, __clk_get_name(parent),
+ base, 2, CPG_PLL0CR, 0);
+
+ case CLK_TYPE_GEN3_PLL1:
+ mult = cpg_pll_config->pll1_mult;
+ div = cpg_pll_config->pll1_div;
+ break;
+
+ case CLK_TYPE_GEN3_PLL2:
+ /*
+ * PLL2 is implemented as a custom clock, to change the
+ * multiplier when cpufreq changes between normal and boost
+ * modes.
+ */
+ return cpg_pll_clk_register(core->name, __clk_get_name(parent),
+ base, 2, CPG_PLL2CR, 2);
+
+ case CLK_TYPE_GEN3_PLL3:
+ mult = cpg_pll_config->pll3_mult;
+ div = cpg_pll_config->pll3_div;
+ break;
+
+ case CLK_TYPE_GEN3_PLL4:
+ /*
+ * PLL4 is a configurable multiplier clock. Register it as a
+ * fixed factor clock for now as there's no generic multiplier
+ * clock implementation and we currently have no need to change
+ * the multiplier value.
+ */
+ value = readl(base + CPG_PLL4CR);
+ mult = (((value >> 24) & 0x7f) + 1) * 2;
+ break;
+
+ case CLK_TYPE_GEN3_SDH:
+ return cpg_sdh_clk_register(core->name, base + core->offset,
+ __clk_get_name(parent), notifiers);
+
+ case CLK_TYPE_GEN3_SD:
+ return cpg_sd_clk_register(core->name, base + core->offset,
+ __clk_get_name(parent));
+
+ case CLK_TYPE_GEN3_R:
+ if (cpg_quirks & RCKCR_CKSEL) {
+ struct cpg_simple_notifier *csn;
+
+ csn = kzalloc_obj(*csn);
+ if (!csn)
+ return ERR_PTR(-ENOMEM);
+
+ csn->reg = base + CPG_RCKCR;
+
+ /*
+ * RINT is default.
+ * Only if EXTALR is populated, we switch to it.
+ */
+ value = readl(csn->reg) & 0x3f;
+
+ if (clk_get_rate(clks[cpg_clk_extalr])) {
+ parent = clks[cpg_clk_extalr];
+ value |= CPG_RCKCR_CKSEL;
+ }
+
+ writel(value, csn->reg);
+ cpg_simple_notifier_register(notifiers, csn);
+ break;
+ }
+
+ /* Select parent clock of RCLK by MD28 */
+ if (cpg_mode & BIT(28))
+ parent = clks[cpg_clk_extalr];
+ break;
+
+ case CLK_TYPE_GEN3_MDSEL:
+ /*
+ * Clock selectable between two parents and two fixed dividers
+ * using a mode pin
+ */
+ if (cpg_mode & BIT(core->offset)) {
+ div = core->div & 0xffff;
+ } else {
+ parent = clks[core->parent >> 16];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+ div = core->div >> 16;
+ }
+ mult = 1;
+ break;
+
+ case CLK_TYPE_GEN3_Z:
+ return cpg_z_clk_register(core->name, __clk_get_name(parent),
+ base, core->div, core->offset);
+
+ case CLK_TYPE_GEN3_ZG:
+ return cpg_zg_clk_register(core->name, __clk_get_name(parent),
+ base, core->div, core->offset);
+
+ case CLK_TYPE_GEN3_OSC:
+ /*
+ * Clock combining OSC EXTAL predivider and a fixed divider
+ */
+ div = cpg_pll_config->osc_prediv * core->div;
+ break;
+
+ case CLK_TYPE_GEN3_RCKSEL:
+ /*
+ * Clock selectable between two parents and two fixed dividers
+ * using RCKCR.CKSEL
+ */
+ if (readl(base + CPG_RCKCR) & CPG_RCKCR_CKSEL) {
+ div = core->div & 0xffff;
+ } else {
+ parent = clks[core->parent >> 16];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+ div = core->div >> 16;
+ }
+ break;
+
+ case CLK_TYPE_GEN3_RPCSRC:
+ return clk_register_divider_table(NULL, core->name,
+ __clk_get_name(parent), 0,
+ base + CPG_RPCCKCR, 3, 2, 0,
+ cpg_rpcsrc_div_table,
+ &cpg_lock);
+
+ case CLK_TYPE_GEN3_E3_RPCSRC:
+ /*
+ * Register RPCSRC as fixed factor clock based on the
+ * MD[4:1] pins and CPG_RPCCKCR[4:3] register value for
+ * which has been set prior to booting the kernel.
+ */
+ value = (readl(base + CPG_RPCCKCR) & GENMASK(4, 3)) >> 3;
+
+ switch (value) {
+ case 0:
+ div = 5;
+ break;
+ case 1:
+ div = 3;
+ break;
+ case 2:
+ parent = clks[core->parent >> 16];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+ div = core->div;
+ break;
+ case 3:
+ default:
+ div = 2;
+ break;
+ }
+ break;
+
+ case CLK_TYPE_GEN3_RPC:
+ return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
+ __clk_get_name(parent), notifiers);
+
+ case CLK_TYPE_GEN3_RPCD2:
+ return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
+ __clk_get_name(parent));
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ return clk_register_fixed_factor(NULL, core->name,
+ __clk_get_name(parent), 0, mult, div);
+}
+
+int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
+ unsigned int clk_extalr, u32 mode)
+{
+ const struct soc_device_attribute *attr;
+
+ cpg_pll_config = config;
+ cpg_clk_extalr = clk_extalr;
+ cpg_mode = mode;
+ attr = soc_device_match(cpg_quirks_match);
+ if (attr)
+ cpg_quirks = (uintptr_t)attr->data;
+ pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks);
+
+ return 0;
+}
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h
new file mode 100644
index 000000000..d15a5d1df
--- /dev/null
+++ b/drivers/clk/renesas/rcar-gen3-cpg.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * R-Car Gen3 Clock Pulse Generator
+ *
+ * Copyright (C) 2015-2018 Glider bvba
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ *
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN3_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN3_CPG_H__
+
+enum rcar_gen3_clk_types {
+ CLK_TYPE_GEN3_MAIN = CLK_TYPE_CUSTOM,
+ CLK_TYPE_GEN3_PLL0,
+ CLK_TYPE_GEN3_PLL1,
+ CLK_TYPE_GEN3_PLL2,
+ CLK_TYPE_GEN3_PLL3,
+ CLK_TYPE_GEN3_PLL4,
+ CLK_TYPE_GEN3_SDH,
+ CLK_TYPE_GEN3_SD,
+ CLK_TYPE_GEN3_R,
+ CLK_TYPE_GEN3_MDSEL, /* Select parent/divider using mode pin */
+ CLK_TYPE_GEN3_Z,
+ CLK_TYPE_GEN3_ZG,
+ CLK_TYPE_GEN3_OSC, /* OSC EXTAL predivider and fixed divider */
+ CLK_TYPE_GEN3_RCKSEL, /* Select parent/divider using RCKCR.CKSEL */
+ CLK_TYPE_GEN3_RPCSRC,
+ CLK_TYPE_GEN3_E3_RPCSRC,/* Select parent/divider using RPCCKCR.DIV */
+ CLK_TYPE_GEN3_RPC,
+ CLK_TYPE_GEN3_RPCD2,
+
+ /* SoC specific definitions start here */
+ CLK_TYPE_GEN3_SOC_BASE,
+};
+
+#define DEF_GEN3_SDH(_name, _id, _parent, _offset) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN3_SDH, _parent, .offset = _offset)
+
+#define DEF_GEN3_SD(_name, _id, _parent, _offset) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
+
+#define DEF_GEN3_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN3_MDSEL, \
+ (_parent0) << 16 | (_parent1), \
+ .div = (_div0) << 16 | (_div1), .offset = _md)
+
+#define DEF_GEN3_PE(_name, _id, _parent_sscg, _div_sscg, _parent_clean, \
+ _div_clean) \
+ DEF_GEN3_MDSEL(_name, _id, 12, _parent_sscg, _div_sscg, \
+ _parent_clean, _div_clean)
+
+#define DEF_GEN3_OSC(_name, _id, _parent, _div) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN3_OSC, _parent, .div = _div)
+
+#define DEF_GEN3_RCKSEL(_name, _id, _parent0, _div0, _parent1, _div1) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN3_RCKSEL, \
+ (_parent0) << 16 | (_parent1), .div = (_div0) << 16 | (_div1))
+
+#define DEF_GEN3_Z(_name, _id, _type, _parent, _div, _offset) \
+ DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset)
+
+#define DEF_FIXED_RPCSRC_E3(_name, _id, _parent0, _parent1) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN3_E3_RPCSRC, \
+ (_parent0) << 16 | (_parent1), .div = 8)
+#define DEF_FIXED_RPCSRC_D3(_name, _id, _parent0, _parent1) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN3_E3_RPCSRC, \
+ (_parent0) << 16 | (_parent1), .div = 5)
+
+struct rcar_gen3_cpg_pll_config {
+ u8 extal_div;
+ u8 pll1_mult;
+ u8 pll1_div;
+ u8 pll3_mult;
+ u8 pll3_div;
+ u8 osc_prediv;
+};
+
+#define CPG_RPCCKCR 0x238
+#define CPG_RCKCR 0x240
+
+struct clk *rcar_gen3_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+ struct cpg_mssr_pub *pub);
+int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
+ unsigned int clk_extalr, u32 mode);
+
+#endif
diff --git a/drivers/clk/renesas/rcar-gen4-cpg.c b/drivers/clk/renesas/rcar-gen4-cpg.c
new file mode 100644
index 000000000..96922789e
--- /dev/null
+++ b/drivers/clk/renesas/rcar-gen4-cpg.c
@@ -0,0 +1,546 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car Gen4 Clock Pulse Generator
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ * Based on rcar-gen3-cpg.c
+ *
+ * Copyright (C) 2015-2018 Glider bvba
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen4-cpg.h"
+#include "rcar-cpg-lib.h"
+
+static const struct rcar_gen4_cpg_pll_config *cpg_pll_config __initdata;
+static unsigned int cpg_clk_extalr __initdata;
+static u32 cpg_mode __initdata;
+
+#define CPG_PLLECR 0x0820 /* PLL Enable Control Register */
+
+#define CPG_PLLECR_PLLST(n) BIT(8 + ((n) < 3 ? (n) - 1 : \
+ (n) > 3 ? (n) + 1 : n)) /* PLLn Circuit Status */
+
+#define CPG_PLL1CR0 0x830 /* PLLn Control Registers */
+#define CPG_PLL1CR1 0x8b0
+#define CPG_PLL2CR0 0x834
+#define CPG_PLL2CR1 0x8b8
+#define CPG_PLL3CR0 0x83c
+#define CPG_PLL3CR1 0x8c0
+#define CPG_PLL4CR0 0x844
+#define CPG_PLL4CR1 0x8c8
+#define CPG_PLL6CR0 0x84c
+#define CPG_PLL6CR1 0x8d8
+
+#define CPG_PLLxCR0_KICK BIT(31)
+#define CPG_PLLxCR0_SSMODE GENMASK(18, 16) /* PLL mode */
+#define CPG_PLLxCR0_SSMODE_FM BIT(18) /* Fractional Multiplication */
+#define CPG_PLLxCR0_SSMODE_DITH BIT(17) /* Frequency Dithering */
+#define CPG_PLLxCR0_SSMODE_CENT BIT(16) /* Center (vs. Down) Spread Dithering */
+#define CPG_PLLxCR0_SSFREQ GENMASK(14, 8) /* SSCG Modulation Frequency */
+#define CPG_PLLxCR0_SSDEPT GENMASK(6, 0) /* SSCG Modulation Depth */
+
+/* Fractional 8.25 PLL */
+#define CPG_PLLxCR0_NI8 GENMASK(27, 20) /* Integer mult. factor */
+#define CPG_PLLxCR1_NF25 GENMASK(24, 0) /* Fractional mult. factor */
+
+/* Fractional 9.24 PLL */
+#define CPG_PLLxCR0_NI9 GENMASK(28, 20) /* Integer mult. factor */
+#define CPG_PLLxCR1_NF24 GENMASK(23, 0) /* Fractional mult. factor */
+
+#define CPG_PLLxCR_STC GENMASK(30, 24) /* R_Car V3U PLLxCR */
+
+#define CPG_RPCCKCR 0x874 /* RPC Clock Freq. Control Register */
+
+#define CPG_SD0CKCR1 0x8a4 /* SD-IF0 Clock Freq. Control Reg. 1 */
+
+#define CPG_SD0CKCR1_SDSRC_SEL GENMASK(30, 29) /* SDSRC clock freq. select */
+
+/* PLL Clocks */
+struct cpg_pll_clk {
+ struct clk_hw hw;
+ void __iomem *pllcr0_reg;
+ void __iomem *pllcr1_reg;
+ void __iomem *pllecr_reg;
+ u32 pllecr_pllst_mask;
+};
+
+#define to_pll_clk(_hw) container_of(_hw, struct cpg_pll_clk, hw)
+
+static unsigned long cpg_pll_8_25_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
+ u32 cr0 = readl(pll_clk->pllcr0_reg);
+ unsigned int ni, nf;
+ unsigned long rate;
+
+ ni = (FIELD_GET(CPG_PLLxCR0_NI8, cr0) + 1) * 2;
+ rate = parent_rate * ni;
+ if (cr0 & CPG_PLLxCR0_SSMODE_FM) {
+ nf = FIELD_GET(CPG_PLLxCR1_NF25, readl(pll_clk->pllcr1_reg));
+ rate += mul_u64_u32_shr(parent_rate, nf, 24);
+ }
+
+ return rate;
+}
+
+static int cpg_pll_8_25_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
+ unsigned int min_mult, max_mult, ni, nf;
+ u32 cr0 = readl(pll_clk->pllcr0_reg);
+ unsigned long prate;
+
+ prate = req->best_parent_rate * 2;
+ min_mult = max(div64_ul(req->min_rate, prate), 1ULL);
+ max_mult = min(div64_ul(req->max_rate, prate), 256ULL);
+ if (max_mult < min_mult)
+ return -EINVAL;
+
+ if (cr0 & CPG_PLLxCR0_SSMODE_FM) {
+ ni = div64_ul(req->rate, prate);
+ if (ni < min_mult) {
+ ni = min_mult;
+ nf = 0;
+ } else {
+ ni = min(ni, max_mult);
+ nf = div64_ul((u64)(req->rate - prate * ni) << 24,
+ req->best_parent_rate);
+ }
+ } else {
+ ni = DIV_ROUND_CLOSEST_ULL(req->rate, prate);
+ ni = clamp(ni, min_mult, max_mult);
+ nf = 0;
+ }
+ req->rate = prate * ni + mul_u64_u32_shr(req->best_parent_rate, nf, 24);
+
+ return 0;
+}
+
+static int cpg_pll_8_25_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
+ unsigned long prate = parent_rate * 2;
+ u32 cr0 = readl(pll_clk->pllcr0_reg);
+ unsigned int ni, nf;
+ u32 val;
+
+ if (cr0 & CPG_PLLxCR0_SSMODE_FM) {
+ ni = div64_ul(rate, prate);
+ if (ni < 1) {
+ ni = 1;
+ nf = 0;
+ } else {
+ ni = min(ni, 256U);
+ nf = div64_ul((u64)(rate - prate * ni) << 24,
+ parent_rate);
+ }
+ } else {
+ ni = DIV_ROUND_CLOSEST_ULL(rate, prate);
+ ni = clamp(ni, 1U, 256U);
+ }
+
+ if (readl(pll_clk->pllcr0_reg) & CPG_PLLxCR0_KICK)
+ return -EBUSY;
+
+ cpg_reg_modify(pll_clk->pllcr0_reg, CPG_PLLxCR0_NI8,
+ FIELD_PREP(CPG_PLLxCR0_NI8, ni - 1));
+ if (cr0 & CPG_PLLxCR0_SSMODE_FM)
+ cpg_reg_modify(pll_clk->pllcr1_reg, CPG_PLLxCR1_NF25,
+ FIELD_PREP(CPG_PLLxCR1_NF25, nf));
+
+ /*
+ * Set KICK bit in PLLxCR0 to update hardware setting and wait for
+ * clock change completion.
+ */
+ cpg_reg_modify(pll_clk->pllcr0_reg, 0, CPG_PLLxCR0_KICK);
+
+ /*
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Using experimental measurements, it seems that no more than
+ * ~45 µs are needed, independently of the CPU rate.
+ * Since this value might be dependent on external xtal rate, pll
+ * rate or even the other emulation clocks rate, use 1000 as a
+ * "super" safe value.
+ */
+ return readl_poll_timeout(pll_clk->pllecr_reg, val,
+ val & pll_clk->pllecr_pllst_mask, 0, 1000);
+}
+
+static const struct clk_ops cpg_pll_f8_25_clk_ops = {
+ .recalc_rate = cpg_pll_8_25_clk_recalc_rate,
+};
+
+static const struct clk_ops cpg_pll_v8_25_clk_ops = {
+ .recalc_rate = cpg_pll_8_25_clk_recalc_rate,
+ .determine_rate = cpg_pll_8_25_clk_determine_rate,
+ .set_rate = cpg_pll_8_25_clk_set_rate,
+};
+
+static unsigned long cpg_pll_9_24_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
+ u32 cr0 = readl(pll_clk->pllcr0_reg);
+ unsigned int ni, nf;
+ unsigned long rate;
+
+ ni = FIELD_GET(CPG_PLLxCR0_NI9, cr0) + 1;
+ rate = parent_rate * ni;
+ if (cr0 & CPG_PLLxCR0_SSMODE_FM) {
+ nf = FIELD_GET(CPG_PLLxCR1_NF24, readl(pll_clk->pllcr1_reg));
+ rate += mul_u64_u32_shr(parent_rate, nf, 24);
+ } else {
+ rate *= 2;
+ }
+
+ return rate;
+}
+
+static const struct clk_ops cpg_pll_f9_24_clk_ops = {
+ .recalc_rate = cpg_pll_9_24_clk_recalc_rate,
+};
+
+static struct clk * __init cpg_pll_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base,
+ unsigned int index,
+ const struct clk_ops *ops)
+{
+ static const struct { u16 cr0, cr1; } pll_cr_offsets[] __initconst = {
+ [1 - 1] = { CPG_PLL1CR0, CPG_PLL1CR1 },
+ [2 - 1] = { CPG_PLL2CR0, CPG_PLL2CR1 },
+ [3 - 1] = { CPG_PLL3CR0, CPG_PLL3CR1 },
+ [4 - 1] = { CPG_PLL4CR0, CPG_PLL4CR1 },
+ [6 - 1] = { CPG_PLL6CR0, CPG_PLL6CR1 },
+ };
+ struct clk_init_data init = {};
+ struct cpg_pll_clk *pll_clk;
+ struct clk *clk;
+
+ pll_clk = kzalloc_obj(*pll_clk);
+ if (!pll_clk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pll_clk->hw.init = &init;
+ pll_clk->pllcr0_reg = base + pll_cr_offsets[index - 1].cr0;
+ pll_clk->pllcr1_reg = base + pll_cr_offsets[index - 1].cr1;
+ pll_clk->pllecr_reg = base + CPG_PLLECR;
+ pll_clk->pllecr_pllst_mask = CPG_PLLECR_PLLST(index);
+
+ clk = clk_register(NULL, &pll_clk->hw);
+ if (IS_ERR(clk))
+ kfree(pll_clk);
+
+ return clk;
+}
+
+/*
+ * Z0, Z1 and ZG Clock
+ */
+#define CPG_FRQCRB 0x00000804
+#define CPG_FRQCRB_KICK BIT(31)
+#define CPG_FRQCRC0 0x00000808
+#define CPG_FRQCRC1 0x000008e0
+
+struct cpg_z_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ void __iomem *kick_reg;
+ unsigned long max_rate; /* Maximum rate for normal mode */
+ unsigned int fixed_div;
+ u32 mask;
+};
+
+#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult = 32 - field_get(zclk->mask, readl(zclk->reg));
+
+ return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
+ 32 * zclk->fixed_div);
+}
+
+static int cpg_z_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int min_mult, max_mult, mult;
+ unsigned long rate, prate;
+
+ rate = min(req->rate, req->max_rate);
+ if (rate <= zclk->max_rate) {
+ /* Set parent rate to initial value for normal modes */
+ prate = zclk->max_rate;
+ } else {
+ /* Set increased parent rate for boost modes */
+ prate = rate;
+ }
+ req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
+ prate * zclk->fixed_div);
+
+ prate = req->best_parent_rate / zclk->fixed_div;
+ min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
+ max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
+ if (max_mult < min_mult)
+ return -EINVAL;
+
+ mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);
+ mult = clamp(mult, min_mult, max_mult);
+
+ req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);
+ return 0;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpg_z_clk *zclk = to_z_clk(hw);
+ unsigned int mult;
+ unsigned int i;
+
+ mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
+ parent_rate);
+ mult = clamp(mult, 1U, 32U);
+
+ if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+ return -EBUSY;
+
+ cpg_reg_modify(zclk->reg, zclk->mask,
+ field_prep(zclk->mask, 32 - mult));
+
+ /*
+ * Set KICK bit in FRQCRB to update hardware setting and wait for
+ * clock change completion.
+ */
+ cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
+
+ /*
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Using experimental measurements, it seems that no more than
+ * ~10 iterations are needed, independently of the CPU rate.
+ * Since this value might be dependent on external xtal rate, pll1
+ * rate or even the other emulation clocks rate, use 1000 as a
+ * "super" safe value.
+ */
+ for (i = 1000; i; i--) {
+ if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+ return 0;
+
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+ .recalc_rate = cpg_z_clk_recalc_rate,
+ .determine_rate = cpg_z_clk_determine_rate,
+ .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *reg,
+ unsigned int div,
+ unsigned int offset)
+{
+ struct clk_init_data init = {};
+ struct cpg_z_clk *zclk;
+ struct clk *clk;
+
+ zclk = kzalloc_obj(*zclk);
+ if (!zclk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &cpg_z_clk_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ if (offset < 32) {
+ zclk->reg = reg + CPG_FRQCRC0;
+ } else if (offset < 64) {
+ zclk->reg = reg + CPG_FRQCRC1;
+ offset -= 32;
+ } else if (offset < 96) {
+ zclk->reg = reg + CPG_FRQCRB;
+ offset -= 64;
+ } else {
+ return ERR_PTR(-EINVAL);
+ }
+ zclk->kick_reg = reg + CPG_FRQCRB;
+ zclk->hw.init = &init;
+ zclk->mask = GENMASK(offset + 4, offset);
+ zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
+
+ clk = clk_register(NULL, &zclk->hw);
+ if (IS_ERR(clk)) {
+ kfree(zclk);
+ return clk;
+ }
+
+ zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
+ zclk->fixed_div;
+ return clk;
+}
+
+/*
+ * RPC Clocks
+ */
+static const struct clk_div_table cpg_rpcsrc_div_table[] = {
+ { 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 },
+};
+
+struct clk * __init rcar_gen4_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+ struct cpg_mssr_pub *pub)
+{
+ struct raw_notifier_head *notifiers = &pub->notifiers;
+ void __iomem *base = pub->base0;
+ struct clk **clks = pub->clks;
+ const struct clk *parent;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+ u32 value;
+
+ parent = clks[core->parent & 0xffff]; /* some types use high bits */
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ switch (core->type) {
+ case CLK_TYPE_GEN4_MAIN:
+ div = cpg_pll_config->extal_div;
+ break;
+
+ case CLK_TYPE_GEN4_PLL1:
+ mult = cpg_pll_config->pll1_mult;
+ div = cpg_pll_config->pll1_div;
+ break;
+
+ case CLK_TYPE_GEN4_PLL5:
+ mult = cpg_pll_config->pll5_mult;
+ div = cpg_pll_config->pll5_div;
+ break;
+
+ case CLK_TYPE_GEN4_PLL2X_3X:
+ value = readl(base + core->offset);
+ mult = (FIELD_GET(CPG_PLLxCR_STC, value) + 1) * 2;
+ break;
+
+ case CLK_TYPE_GEN4_PLL_F8_25:
+ return cpg_pll_clk_register(core->name, __clk_get_name(parent),
+ base, core->offset,
+ &cpg_pll_f8_25_clk_ops);
+
+ case CLK_TYPE_GEN4_PLL_V8_25:
+ return cpg_pll_clk_register(core->name, __clk_get_name(parent),
+ base, core->offset,
+ &cpg_pll_v8_25_clk_ops);
+
+ case CLK_TYPE_GEN4_PLL_V9_24:
+ /* Variable fractional 9.24 is not yet supported, using fixed */
+ fallthrough;
+ case CLK_TYPE_GEN4_PLL_F9_24:
+ return cpg_pll_clk_register(core->name, __clk_get_name(parent),
+ base, core->offset,
+ &cpg_pll_f9_24_clk_ops);
+
+ case CLK_TYPE_GEN4_Z:
+ return cpg_z_clk_register(core->name, __clk_get_name(parent),
+ base, core->div, core->offset);
+
+ case CLK_TYPE_GEN4_SDSRC:
+ value = readl(base + CPG_SD0CKCR1);
+ div = FIELD_GET(CPG_SD0CKCR1_SDSRC_SEL, value) + 4;
+ break;
+
+ case CLK_TYPE_GEN4_SDH:
+ return cpg_sdh_clk_register(core->name, base + core->offset,
+ __clk_get_name(parent), notifiers);
+
+ case CLK_TYPE_GEN4_SD:
+ return cpg_sd_clk_register(core->name, base + core->offset,
+ __clk_get_name(parent));
+
+ case CLK_TYPE_GEN4_MDSEL:
+ /*
+ * Clock selectable between two parents and two fixed dividers
+ * using a mode pin
+ */
+ if (cpg_mode & BIT(core->offset)) {
+ div = core->div & 0xffff;
+ } else {
+ parent = clks[core->parent >> 16];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+ div = core->div >> 16;
+ }
+ mult = 1;
+ break;
+
+ case CLK_TYPE_GEN4_OSC:
+ /*
+ * Clock combining OSC EXTAL predivider and a fixed divider
+ */
+ div = cpg_pll_config->osc_prediv * core->div;
+ break;
+
+ case CLK_TYPE_GEN4_RPCSRC:
+ return clk_register_divider_table(NULL, core->name,
+ __clk_get_name(parent), 0,
+ base + CPG_RPCCKCR, 3, 2, 0,
+ cpg_rpcsrc_div_table,
+ &cpg_lock);
+
+ case CLK_TYPE_GEN4_RPC:
+ return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
+ __clk_get_name(parent), notifiers);
+
+ case CLK_TYPE_GEN4_RPCD2:
+ return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
+ __clk_get_name(parent));
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ return clk_register_fixed_factor(NULL, core->name,
+ __clk_get_name(parent), 0, mult, div);
+}
+
+int __init rcar_gen4_cpg_init(const struct rcar_gen4_cpg_pll_config *config,
+ unsigned int clk_extalr, u32 mode)
+{
+ cpg_pll_config = config;
+ cpg_clk_extalr = clk_extalr;
+ cpg_mode = mode;
+
+ return 0;
+}
diff --git a/drivers/clk/renesas/rcar-gen4-cpg.h b/drivers/clk/renesas/rcar-gen4-cpg.h
new file mode 100644
index 000000000..6c8280b37
--- /dev/null
+++ b/drivers/clk/renesas/rcar-gen4-cpg.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * R-Car Gen4 Clock Pulse Generator
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN4_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN4_CPG_H__
+
+enum rcar_gen4_clk_types {
+ CLK_TYPE_GEN4_MAIN = CLK_TYPE_CUSTOM,
+ CLK_TYPE_GEN4_PLL1,
+ CLK_TYPE_GEN4_PLL2X_3X, /* r8a779a0 only */
+ CLK_TYPE_GEN4_PLL5,
+ CLK_TYPE_GEN4_PLL_F8_25, /* Fixed fractional 8.25 PLL */
+ CLK_TYPE_GEN4_PLL_V8_25, /* Variable fractional 8.25 PLL */
+ CLK_TYPE_GEN4_PLL_F9_24, /* Fixed fractional 9.24 PLL */
+ CLK_TYPE_GEN4_PLL_V9_24, /* Variable fractional 9.24 PLL */
+ CLK_TYPE_GEN4_SDSRC,
+ CLK_TYPE_GEN4_SDH,
+ CLK_TYPE_GEN4_SD,
+ CLK_TYPE_GEN4_MDSEL, /* Select parent/divider using mode pin */
+ CLK_TYPE_GEN4_Z,
+ CLK_TYPE_GEN4_OSC, /* OSC EXTAL predivider and fixed divider */
+ CLK_TYPE_GEN4_RPCSRC,
+ CLK_TYPE_GEN4_RPC,
+ CLK_TYPE_GEN4_RPCD2,
+
+ /* SoC specific definitions start here */
+ CLK_TYPE_GEN4_SOC_BASE,
+};
+
+#define DEF_GEN4_SDH(_name, _id, _parent, _offset) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN4_SDH, _parent, .offset = _offset)
+
+#define DEF_GEN4_SD(_name, _id, _parent, _offset) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN4_SD, _parent, .offset = _offset)
+
+#define DEF_GEN4_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN4_MDSEL, \
+ (_parent0) << 16 | (_parent1), \
+ .div = (_div0) << 16 | (_div1), .offset = _md)
+
+#define DEF_GEN4_OSC(_name, _id, _parent, _div) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN4_OSC, _parent, .div = _div)
+
+#define DEF_GEN4_PLL_F8_25(_name, _idx, _id, _parent) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN4_PLL_F8_25, _parent, .offset = _idx)
+
+#define DEF_GEN4_PLL_V8_25(_name, _idx, _id, _parent) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN4_PLL_V8_25, _parent, .offset = _idx)
+
+#define DEF_GEN4_PLL_F9_24(_name, _idx, _id, _parent) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN4_PLL_F9_24, _parent, .offset = _idx)
+
+#define DEF_GEN4_PLL_V9_24(_name, _idx, _id, _parent) \
+ DEF_BASE(_name, _id, CLK_TYPE_GEN4_PLL_V9_24, _parent, .offset = _idx)
+
+#define DEF_GEN4_Z(_name, _id, _type, _parent, _div, _offset) \
+ DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset)
+
+struct rcar_gen4_cpg_pll_config {
+ u8 extal_div;
+ u8 pll1_mult;
+ u8 pll1_div;
+ u8 pll5_mult;
+ u8 pll5_div;
+ u8 osc_prediv;
+};
+
+#define CPG_SD0CKCR 0x870 /* SD-IF0 Clock Frequency Control Register */
+#define CPG_CANFDCKCR 0x878 /* CAN-FD Clock Frequency Control Register */
+#define CPG_MSOCKCR 0x87c /* MSIOF Clock Frequency Control Register */
+#define CPG_CSICKCR 0x880 /* CSI Clock Frequency Control Register */
+#define CPG_DSIEXTCKCR 0x884 /* DSI Clock Frequency Control Register */
+
+struct clk *rcar_gen4_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+ struct cpg_mssr_pub *pub);
+int rcar_gen4_cpg_init(const struct rcar_gen4_cpg_pll_config *config,
+ unsigned int clk_extalr, u32 mode);
+
+#endif
diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c
new file mode 100644
index 000000000..421ae973e
--- /dev/null
+++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car USB2.0 clock selector
+ *
+ * Copyright (C) 2017 Renesas Electronics Corp.
+ *
+ * Based on renesas-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#define USB20_CLKSET0 0x00
+#define CLKSET0_INTCLK_EN BIT(11)
+#define CLKSET0_PRIVATE BIT(0)
+#define CLKSET0_EXTAL_ONLY (CLKSET0_INTCLK_EN | CLKSET0_PRIVATE)
+
+static const struct clk_bulk_data rcar_usb2_clocks[] = {
+ { .id = "ehci_ohci", },
+ { .id = "hs-usb-if", },
+};
+
+struct usb2_clock_sel_priv {
+ void __iomem *base;
+ struct clk_hw hw;
+ struct clk_bulk_data clks[ARRAY_SIZE(rcar_usb2_clocks)];
+ struct reset_control *rsts;
+ bool extal;
+ bool xtal;
+};
+#define to_priv(_hw) container_of(_hw, struct usb2_clock_sel_priv, hw)
+
+static void usb2_clock_sel_enable_extal_only(struct usb2_clock_sel_priv *priv)
+{
+ u16 val = readw(priv->base + USB20_CLKSET0);
+
+ pr_debug("%s: enter %d %d %x\n", __func__,
+ priv->extal, priv->xtal, val);
+
+ if (priv->extal && !priv->xtal && val != CLKSET0_EXTAL_ONLY)
+ writew(CLKSET0_EXTAL_ONLY, priv->base + USB20_CLKSET0);
+}
+
+static void usb2_clock_sel_disable_extal_only(struct usb2_clock_sel_priv *priv)
+{
+ if (priv->extal && !priv->xtal)
+ writew(CLKSET0_PRIVATE, priv->base + USB20_CLKSET0);
+}
+
+static int usb2_clock_sel_enable(struct clk_hw *hw)
+{
+ struct usb2_clock_sel_priv *priv = to_priv(hw);
+ int ret;
+
+ ret = reset_control_deassert(priv->rsts);
+ if (ret)
+ return ret;
+
+ ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clks), priv->clks);
+ if (ret) {
+ reset_control_assert(priv->rsts);
+ return ret;
+ }
+
+ usb2_clock_sel_enable_extal_only(priv);
+
+ return 0;
+}
+
+static void usb2_clock_sel_disable(struct clk_hw *hw)
+{
+ struct usb2_clock_sel_priv *priv = to_priv(hw);
+
+ usb2_clock_sel_disable_extal_only(priv);
+
+ clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clks), priv->clks);
+ reset_control_assert(priv->rsts);
+}
+
+/*
+ * This module seems a mux, but this driver assumes a gate because
+ * ehci/ohci platform drivers don't support clk_set_parent() for now.
+ * If this driver acts as a gate, ehci/ohci-platform drivers don't need
+ * any modification.
+ */
+static const struct clk_ops usb2_clock_sel_clock_ops = {
+ .enable = usb2_clock_sel_enable,
+ .disable = usb2_clock_sel_disable,
+};
+
+static const struct of_device_id rcar_usb2_clock_sel_match[] = {
+ { .compatible = "renesas,rcar-gen3-usb2-clock-sel" },
+ { }
+};
+
+static int rcar_usb2_clock_sel_suspend(struct device *dev)
+{
+ struct usb2_clock_sel_priv *priv = dev_get_drvdata(dev);
+
+ usb2_clock_sel_disable_extal_only(priv);
+ pm_runtime_put(dev);
+
+ return 0;
+}
+
+static int rcar_usb2_clock_sel_resume(struct device *dev)
+{
+ struct usb2_clock_sel_priv *priv = dev_get_drvdata(dev);
+
+ pm_runtime_get_sync(dev);
+ usb2_clock_sel_enable_extal_only(priv);
+
+ return 0;
+}
+
+static void rcar_usb2_clock_sel_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+
+ of_clk_del_provider(dev->of_node);
+ pm_runtime_put(dev);
+ pm_runtime_disable(dev);
+}
+
+static int rcar_usb2_clock_sel_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct usb2_clock_sel_priv *priv;
+ struct clk *clk;
+ struct clk_init_data init = {};
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ memcpy(priv->clks, rcar_usb2_clocks, sizeof(priv->clks));
+ ret = devm_clk_bulk_get(dev, ARRAY_SIZE(priv->clks), priv->clks);
+ if (ret < 0)
+ return ret;
+
+ priv->rsts = devm_reset_control_array_get_shared(dev);
+ if (IS_ERR(priv->rsts))
+ return PTR_ERR(priv->rsts);
+
+ clk = devm_clk_get(dev, "usb_extal");
+ if (!IS_ERR(clk) && !clk_prepare_enable(clk)) {
+ priv->extal = !!clk_get_rate(clk);
+ clk_disable_unprepare(clk);
+ }
+ clk = devm_clk_get(dev, "usb_xtal");
+ if (!IS_ERR(clk) && !clk_prepare_enable(clk)) {
+ priv->xtal = !!clk_get_rate(clk);
+ clk_disable_unprepare(clk);
+ }
+
+ if (!priv->extal && !priv->xtal) {
+ dev_err(dev, "This driver needs usb_extal or usb_xtal\n");
+ return -ENOENT;
+ }
+
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+ platform_set_drvdata(pdev, priv);
+ dev_set_drvdata(dev, priv);
+
+ init.name = "rcar_usb2_clock_sel";
+ init.ops = &usb2_clock_sel_clock_ops;
+ priv->hw.init = &init;
+
+ ret = devm_clk_hw_register(dev, &priv->hw);
+ if (ret)
+ goto pm_put;
+
+ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw);
+ if (ret)
+ goto pm_put;
+
+ return 0;
+
+pm_put:
+ pm_runtime_put(dev);
+ pm_runtime_disable(dev);
+ return ret;
+}
+
+static const struct dev_pm_ops rcar_usb2_clock_sel_pm_ops = {
+ .suspend = rcar_usb2_clock_sel_suspend,
+ .resume = rcar_usb2_clock_sel_resume,
+};
+
+static struct platform_driver rcar_usb2_clock_sel_driver = {
+ .driver = {
+ .name = "rcar-usb2-clock-sel",
+ .of_match_table = rcar_usb2_clock_sel_match,
+ .pm = &rcar_usb2_clock_sel_pm_ops,
+ },
+ .probe = rcar_usb2_clock_sel_probe,
+ .remove = rcar_usb2_clock_sel_remove,
+};
+builtin_platform_driver(rcar_usb2_clock_sel_driver);
+
+MODULE_DESCRIPTION("Renesas R-Car USB2 clock selector Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
new file mode 100644
index 000000000..b6dab92cb
--- /dev/null
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -0,0 +1,1435 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2015 Glider bvba
+ *
+ * Based on clk-mstp.c, clk-rcar-gen2.c, and clk-rcar-gen3.c
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/psci.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/string_choices.h>
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "clk-div6.h"
+
+#ifdef DEBUG
+#define WARN_DEBUG(x) WARN_ON(x)
+#else
+#define WARN_DEBUG(x) do { } while (0)
+#endif
+
+#define RZT2H_RESET_REG_READ_COUNT 7
+
+/*
+ * Module Standby and Software Reset register offsets.
+ *
+ * If the registers exist, these are valid for SH-Mobile, R-Mobile,
+ * R-Car Gen2, R-Car Gen3, and RZ/G1.
+ * These are NOT valid for R-Car Gen1 and RZ/A1!
+ */
+
+/*
+ * Module Stop Status Register offsets
+ */
+
+static const u16 mstpsr[] = {
+ 0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, 0x1C0, 0x1C4,
+ 0x9A0, 0x9A4, 0x9A8, 0x9AC,
+};
+
+static const u16 mstpsr_for_gen4[] = {
+ 0x2E00, 0x2E04, 0x2E08, 0x2E0C, 0x2E10, 0x2E14, 0x2E18, 0x2E1C,
+ 0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38, 0x2E3C,
+ 0x2E40, 0x2E44, 0x2E48, 0x2E4C, 0x2E50, 0x2E54, 0x2E58, 0x2E5C,
+ 0x2E60, 0x2E64, 0x2E68, 0x2E6C, 0x2E70, 0x2E74,
+};
+
+/*
+ * System Module Stop Control Register offsets
+ */
+
+static const u16 smstpcr[] = {
+ 0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, 0x148, 0x14C,
+ 0x990, 0x994, 0x998, 0x99C,
+};
+
+static const u16 mstpcr_for_gen4[] = {
+ 0x2D00, 0x2D04, 0x2D08, 0x2D0C, 0x2D10, 0x2D14, 0x2D18, 0x2D1C,
+ 0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38, 0x2D3C,
+ 0x2D40, 0x2D44, 0x2D48, 0x2D4C, 0x2D50, 0x2D54, 0x2D58, 0x2D5C,
+ 0x2D60, 0x2D64, 0x2D68, 0x2D6C, 0x2D70, 0x2D74,
+};
+
+/*
+ * Module Stop Control Register (RZ/T2H)
+ * RZ/T2H has 2 registers blocks,
+ * Bit 12 is used to differentiate them
+ */
+
+#define RZT2H_MSTPCR_BLOCK_SHIFT 12
+#define RZT2H_MSTPCR_OFFSET_MASK GENMASK(11, 0)
+#define RZT2H_MSTPCR(block, offset) (((block) << RZT2H_MSTPCR_BLOCK_SHIFT) | \
+ ((offset) & RZT2H_MSTPCR_OFFSET_MASK))
+
+#define RZT2H_MSTPCR_BLOCK(x) ((x) >> RZT2H_MSTPCR_BLOCK_SHIFT)
+#define RZT2H_MSTPCR_OFFSET(x) ((x) & RZT2H_MSTPCR_OFFSET_MASK)
+
+static const u16 mstpcr_for_rzt2h[] = {
+ RZT2H_MSTPCR(0, 0x300), /* MSTPCRA */
+ RZT2H_MSTPCR(0, 0x304), /* MSTPCRB */
+ RZT2H_MSTPCR(0, 0x308), /* MSTPCRC */
+ RZT2H_MSTPCR(0, 0x30c), /* MSTPCRD */
+ RZT2H_MSTPCR(0, 0x310), /* MSTPCRE */
+ 0,
+ RZT2H_MSTPCR(1, 0x318), /* MSTPCRG */
+ 0,
+ RZT2H_MSTPCR(1, 0x320), /* MSTPCRI */
+ RZT2H_MSTPCR(0, 0x324), /* MSTPCRJ */
+ RZT2H_MSTPCR(0, 0x328), /* MSTPCRK */
+ RZT2H_MSTPCR(0, 0x32c), /* MSTPCRL */
+ RZT2H_MSTPCR(0, 0x330), /* MSTPCRM */
+ RZT2H_MSTPCR(1, 0x334), /* MSTPCRN */
+};
+
+/*
+ * Standby Control Register offsets (RZ/A)
+ * Base address is FRQCR register
+ */
+
+static const u16 stbcr[] = {
+ 0xFFFF/*dummy*/, 0x010, 0x014, 0x410, 0x414, 0x418, 0x41C, 0x420,
+ 0x424, 0x428, 0x42C,
+};
+
+/*
+ * Software Reset Register offsets
+ */
+
+static const u16 srcr[] = {
+ 0x0A0, 0x0A8, 0x0B0, 0x0B8, 0x0BC, 0x0C4, 0x1C8, 0x1CC,
+ 0x920, 0x924, 0x928, 0x92C,
+};
+
+static const u16 srcr_for_gen4[] = {
+ 0x2C00, 0x2C04, 0x2C08, 0x2C0C, 0x2C10, 0x2C14, 0x2C18, 0x2C1C,
+ 0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38, 0x2C3C,
+ 0x2C40, 0x2C44, 0x2C48, 0x2C4C, 0x2C50, 0x2C54, 0x2C58, 0x2C5C,
+ 0x2C60, 0x2C64, 0x2C68, 0x2C6C, 0x2C70, 0x2C74,
+};
+
+static const u16 mrcr_for_rzt2h[] = {
+ 0x240, /* MRCTLA */
+ 0x244, /* Reserved */
+ 0x248, /* Reserved */
+ 0x24C, /* Reserved */
+ 0x250, /* MRCTLE */
+ 0x254, /* Reserved */
+ 0x258, /* Reserved */
+ 0x25C, /* Reserved */
+ 0x260, /* MRCTLI */
+ 0x264, /* Reserved */
+ 0x268, /* Reserved */
+ 0x26C, /* Reserved */
+ 0x270, /* MRCTLM */
+};
+
+/*
+ * Software Reset Clearing Register offsets
+ */
+
+static const u16 srstclr[] = {
+ 0x940, 0x944, 0x948, 0x94C, 0x950, 0x954, 0x958, 0x95C,
+ 0x960, 0x964, 0x968, 0x96C,
+};
+
+static const u16 srstclr_for_gen4[] = {
+ 0x2C80, 0x2C84, 0x2C88, 0x2C8C, 0x2C90, 0x2C94, 0x2C98, 0x2C9C,
+ 0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8, 0x2CBC,
+ 0x2CC0, 0x2CC4, 0x2CC8, 0x2CCC, 0x2CD0, 0x2CD4, 0x2CD8, 0x2CDC,
+ 0x2CE0, 0x2CE4, 0x2CE8, 0x2CEC, 0x2CF0, 0x2CF4,
+};
+
+/**
+ * struct cpg_mssr_priv - Clock Pulse Generator / Module Standby
+ * and Software Reset Private Data
+ *
+ * @pub: Data passed to clock registration callback
+ * @rcdev: Optional reset controller entity
+ * @dev: CPG/MSSR device
+ * @reg_layout: CPG/MSSR register layout
+ * @np: Device node in DT for this CPG/MSSR module
+ * @num_core_clks: Number of Core Clocks in clks[]
+ * @num_mod_clks: Number of Module Clocks in clks[]
+ * @last_dt_core_clk: ID of the last Core Clock exported to DT
+ * @status_regs: Pointer to status registers array
+ * @control_regs: Pointer to control registers array
+ * @reset_regs: Pointer to reset registers array
+ * @reset_clear_regs: Pointer to reset clearing registers array
+ * @smstpcr_saved: [].mask: Mask of SMSTPCR[] bits under our control
+ * [].val: Saved values of SMSTPCR[]
+ * @reserved_ids: Temporary used, reserved id list
+ * @num_reserved_ids: Temporary used, number of reserved id list
+ * @clks: Array containing all Core and Module Clocks
+ */
+struct cpg_mssr_priv {
+ struct cpg_mssr_pub pub;
+#ifdef CONFIG_RESET_CONTROLLER
+ struct reset_controller_dev rcdev;
+#endif
+ struct device *dev;
+ enum clk_reg_layout reg_layout;
+ struct device_node *np;
+
+ unsigned int num_core_clks;
+ unsigned int num_mod_clks;
+ unsigned int last_dt_core_clk;
+
+ const u16 *status_regs;
+ const u16 *control_regs;
+ const u16 *reset_regs;
+ const u16 *reset_clear_regs;
+ struct {
+ u32 mask;
+ u32 val;
+ } smstpcr_saved[ARRAY_SIZE(mstpsr_for_gen4)];
+
+ unsigned int *reserved_ids;
+ unsigned int num_reserved_ids;
+
+ struct clk *clks[];
+};
+
+static struct cpg_mssr_priv *cpg_mssr_priv;
+
+/**
+ * struct mstp_clock - MSTP gating clock
+ * @hw: handle between common and hardware-specific interfaces
+ * @index: MSTP clock number
+ * @priv: CPG/MSSR private data
+ */
+struct mstp_clock {
+ struct clk_hw hw;
+ u32 index;
+ struct cpg_mssr_priv *priv;
+};
+
+#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)
+
+static u32 cpg_rzt2h_mstp_read(struct cpg_mssr_priv *priv, u16 offset)
+{
+ void __iomem *base =
+ RZT2H_MSTPCR_BLOCK(offset) ? priv->pub.base1 : priv->pub.base0;
+
+ return readl(base + RZT2H_MSTPCR_OFFSET(offset));
+}
+
+static void cpg_rzt2h_mstp_write(struct cpg_mssr_priv *priv, u16 offset, u32 value)
+{
+ void __iomem *base =
+ RZT2H_MSTPCR_BLOCK(offset) ? priv->pub.base1 : priv->pub.base0;
+
+ writel(value, base + RZT2H_MSTPCR_OFFSET(offset));
+}
+
+static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
+{
+ struct mstp_clock *clock = to_mstp_clock(hw);
+ struct cpg_mssr_priv *priv = clock->priv;
+ unsigned int reg = clock->index / 32;
+ unsigned int bit = clock->index % 32;
+ struct device *dev = priv->dev;
+ u32 bitmask = BIT(bit);
+ unsigned long flags;
+ u32 value;
+ int error;
+
+ dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
+ str_on_off(enable));
+ spin_lock_irqsave(&priv->pub.rmw_lock, flags);
+
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
+ value = readb(priv->pub.base0 + priv->control_regs[reg]);
+ if (enable)
+ value &= ~bitmask;
+ else
+ value |= bitmask;
+ writeb(value, priv->pub.base0 + priv->control_regs[reg]);
+
+ /* dummy read to ensure write has completed */
+ readb(priv->pub.base0 + priv->control_regs[reg]);
+ barrier_data(priv->pub.base0 + priv->control_regs[reg]);
+
+ } else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) {
+ value = cpg_rzt2h_mstp_read(priv, priv->control_regs[reg]);
+
+ if (enable)
+ value &= ~bitmask;
+ else
+ value |= bitmask;
+
+ cpg_rzt2h_mstp_write(priv, priv->control_regs[reg], value);
+ } else {
+ value = readl(priv->pub.base0 + priv->control_regs[reg]);
+ if (enable)
+ value &= ~bitmask;
+ else
+ value |= bitmask;
+ writel(value, priv->pub.base0 + priv->control_regs[reg]);
+ }
+
+ spin_unlock_irqrestore(&priv->pub.rmw_lock, flags);
+
+ if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
+ return 0;
+
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) {
+ /*
+ * For the RZ/T2H case, it is necessary to perform a read-back after
+ * accessing the MSTPCRm register and to dummy-read any register of
+ * the IP at least seven times. Instead of memory-mapping the IP
+ * register, we simply add a delay after the read operation.
+ */
+ cpg_rzt2h_mstp_read(priv, priv->control_regs[reg]);
+ udelay(10);
+ return 0;
+ }
+
+ error = readl_poll_timeout_atomic(priv->pub.base0 + priv->status_regs[reg],
+ value, !(value & bitmask), 0, 10);
+ if (error)
+ dev_err(dev, "Failed to enable SMSTP %p[%d]\n",
+ priv->pub.base0 + priv->control_regs[reg], bit);
+
+ return error;
+}
+
+static int cpg_mstp_clock_enable(struct clk_hw *hw)
+{
+ return cpg_mstp_clock_endisable(hw, true);
+}
+
+static void cpg_mstp_clock_disable(struct clk_hw *hw)
+{
+ cpg_mstp_clock_endisable(hw, false);
+}
+
+static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
+{
+ struct mstp_clock *clock = to_mstp_clock(hw);
+ struct cpg_mssr_priv *priv = clock->priv;
+ unsigned int reg = clock->index / 32;
+ u32 value;
+
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
+ value = readb(priv->pub.base0 + priv->control_regs[reg]);
+ else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H)
+ value = cpg_rzt2h_mstp_read(priv, priv->control_regs[reg]);
+ else
+ value = readl(priv->pub.base0 + priv->status_regs[reg]);
+
+ return !(value & BIT(clock->index % 32));
+}
+
+static const struct clk_ops cpg_mstp_clock_ops = {
+ .enable = cpg_mstp_clock_enable,
+ .disable = cpg_mstp_clock_disable,
+ .is_enabled = cpg_mstp_clock_is_enabled,
+};
+
+static
+struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec,
+ void *data)
+{
+ unsigned int clkidx = clkspec->args[1];
+ struct cpg_mssr_priv *priv = data;
+ struct device *dev = priv->dev;
+ unsigned int idx;
+ const char *type;
+ struct clk *clk;
+ int range_check;
+
+ if (clkspec->args_count != 2)
+ return ERR_PTR(-EINVAL);
+
+ switch (clkspec->args[0]) {
+ case CPG_CORE:
+ type = "core";
+ if (clkidx > priv->last_dt_core_clk) {
+ dev_err(dev, "Invalid %s clock index %u\n", type,
+ clkidx);
+ return ERR_PTR(-EINVAL);
+ }
+ clk = priv->clks[clkidx];
+ break;
+
+ case CPG_MOD:
+ type = "module";
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
+ idx = MOD_CLK_PACK_10(clkidx);
+ range_check = 7 - (clkidx % 10);
+ } else {
+ idx = MOD_CLK_PACK(clkidx);
+ range_check = 31 - (clkidx % 100);
+ }
+ if (range_check < 0 || idx >= priv->num_mod_clks) {
+ dev_err(dev, "Invalid %s clock index %u\n", type,
+ clkidx);
+ return ERR_PTR(-EINVAL);
+ }
+ clk = priv->clks[priv->num_core_clks + idx];
+ break;
+
+ default:
+ dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (IS_ERR(clk))
+ dev_err(dev, "Cannot get %s clock %u: %ld\n", type, clkidx,
+ PTR_ERR(clk));
+ else
+ dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n",
+ clkspec->args[0], clkspec->args[1], clk,
+ clk_get_rate(clk));
+ return clk;
+}
+
+static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct cpg_mssr_priv *priv)
+{
+ struct clk *clk = ERR_PTR(-ENOTSUPP), *parent;
+ struct device *dev = priv->dev;
+ unsigned int id = core->id, div = core->div;
+ const char *parent_name;
+
+ WARN_DEBUG(id >= priv->num_core_clks);
+ WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
+
+ switch (core->type) {
+ case CLK_TYPE_IN:
+ clk = of_clk_get_by_name(priv->np, core->name);
+ break;
+
+ case CLK_TYPE_FF:
+ case CLK_TYPE_DIV6P1:
+ case CLK_TYPE_DIV6_RO:
+ WARN_DEBUG(core->parent >= priv->num_core_clks);
+ parent = priv->pub.clks[core->parent];
+ if (IS_ERR(parent)) {
+ clk = parent;
+ goto fail;
+ }
+
+ parent_name = __clk_get_name(parent);
+
+ if (core->type == CLK_TYPE_DIV6_RO)
+ /* Multiply with the DIV6 register value */
+ div *= (readl(priv->pub.base0 + core->offset) & 0x3f) + 1;
+
+ if (core->type == CLK_TYPE_DIV6P1) {
+ clk = cpg_div6_register(core->name, 1, &parent_name,
+ priv->pub.base0 + core->offset,
+ &priv->pub.notifiers);
+ } else {
+ clk = clk_register_fixed_factor(NULL, core->name,
+ parent_name, 0,
+ core->mult, div);
+ }
+ break;
+
+ case CLK_TYPE_FR:
+ clk = clk_register_fixed_rate(NULL, core->name, NULL, 0,
+ core->mult);
+ break;
+
+ default:
+ if (info->cpg_clk_register)
+ clk = info->cpg_clk_register(dev, core, info,
+ &priv->pub);
+ else
+ dev_err(dev, "%s has unsupported core clock type %u\n",
+ core->name, core->type);
+ break;
+ }
+
+ if (IS_ERR(clk))
+ goto fail;
+
+ dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
+ priv->pub.clks[id] = clk;
+ return;
+
+fail:
+ dev_err(dev, "Failed to register %s clock %s: %ld\n", "core",
+ core->name, PTR_ERR(clk));
+}
+
+static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
+ const struct cpg_mssr_info *info,
+ struct cpg_mssr_priv *priv)
+{
+ struct mstp_clock *clock = NULL;
+ struct device *dev = priv->dev;
+ unsigned int id = mod->id;
+ struct clk_init_data init = {};
+ struct clk *parent, *clk;
+ const char *parent_name;
+ unsigned int i;
+
+ WARN_DEBUG(id < priv->num_core_clks);
+ WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks);
+ WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
+ WARN_DEBUG(PTR_ERR(priv->pub.clks[id]) != -ENOENT);
+
+ if (!mod->name) {
+ /* Skip NULLified clock */
+ return;
+ }
+
+ parent = priv->pub.clks[mod->parent];
+ if (IS_ERR(parent)) {
+ clk = parent;
+ goto fail;
+ }
+
+ clock = kzalloc_obj(*clock);
+ if (!clock) {
+ clk = ERR_PTR(-ENOMEM);
+ goto fail;
+ }
+
+ init.name = mod->name;
+ init.ops = &cpg_mstp_clock_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ parent_name = __clk_get_name(parent);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clock->index = id - priv->num_core_clks;
+ clock->priv = priv;
+ clock->hw.init = &init;
+
+ for (i = 0; i < info->num_crit_mod_clks; i++)
+ if (id == info->crit_mod_clks[i] &&
+ cpg_mstp_clock_is_enabled(&clock->hw)) {
+ dev_dbg(dev, "MSTP %s setting CLK_IS_CRITICAL\n",
+ mod->name);
+ init.flags |= CLK_IS_CRITICAL;
+ break;
+ }
+
+ /*
+ * Ignore reserved device.
+ * see
+ * cpg_mssr_reserved_init()
+ */
+ for (i = 0; i < priv->num_reserved_ids; i++) {
+ if (id == priv->reserved_ids[i]) {
+ dev_info(dev, "Ignore Linux non-assigned mod (%s)\n", mod->name);
+ init.flags |= CLK_IGNORE_UNUSED;
+ break;
+ }
+ }
+
+ clk = clk_register(NULL, &clock->hw);
+ if (IS_ERR(clk))
+ goto fail;
+
+ dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
+ priv->clks[id] = clk;
+ priv->smstpcr_saved[clock->index / 32].mask |= BIT(clock->index % 32);
+ return;
+
+fail:
+ dev_err(dev, "Failed to register %s clock %s: %ld\n", "module",
+ mod->name, PTR_ERR(clk));
+ kfree(clock);
+}
+
+struct cpg_mssr_clk_domain {
+ struct generic_pm_domain genpd;
+ unsigned int num_core_pm_clks;
+ unsigned int core_pm_clks[] __counted_by(num_core_pm_clks);
+};
+
+static struct cpg_mssr_clk_domain *cpg_mssr_clk_domain;
+
+static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
+ struct cpg_mssr_clk_domain *pd)
+{
+ unsigned int i;
+
+ if (clkspec->np != pd->genpd.dev.of_node || clkspec->args_count != 2)
+ return false;
+
+ switch (clkspec->args[0]) {
+ case CPG_CORE:
+ for (i = 0; i < pd->num_core_pm_clks; i++)
+ if (clkspec->args[1] == pd->core_pm_clks[i])
+ return true;
+ return false;
+
+ case CPG_MOD:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev)
+{
+ struct cpg_mssr_clk_domain *pd = cpg_mssr_clk_domain;
+ struct device_node *np = dev->of_node;
+ struct of_phandle_args clkspec;
+ struct clk *clk;
+ int i = 0;
+ int error;
+
+ if (!pd) {
+ dev_dbg(dev, "CPG/MSSR clock domain not yet available\n");
+ return -EPROBE_DEFER;
+ }
+
+ while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
+ &clkspec)) {
+ if (cpg_mssr_is_pm_clk(&clkspec, pd))
+ goto found;
+
+ of_node_put(clkspec.np);
+ i++;
+ }
+
+ return 0;
+
+found:
+ clk = of_clk_get_from_provider(&clkspec);
+ of_node_put(clkspec.np);
+
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ error = pm_clk_create(dev);
+ if (error)
+ goto fail_put;
+
+ error = pm_clk_add_clk(dev, clk);
+ if (error)
+ goto fail_destroy;
+
+ return 0;
+
+fail_destroy:
+ pm_clk_destroy(dev);
+fail_put:
+ clk_put(clk);
+ return error;
+}
+
+void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
+{
+ if (!pm_clk_no_clocks(dev))
+ pm_clk_destroy(dev);
+}
+
+static void cpg_mssr_genpd_remove(void *data)
+{
+ pm_genpd_remove(data);
+}
+
+static int __init cpg_mssr_add_clk_domain(struct device *dev,
+ const unsigned int *core_pm_clks,
+ unsigned int num_core_pm_clks)
+{
+ struct device_node *np = dev->of_node;
+ struct generic_pm_domain *genpd;
+ struct cpg_mssr_clk_domain *pd;
+ size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]);
+ int ret;
+
+ pd = devm_kzalloc(dev, struct_size(pd, core_pm_clks, num_core_pm_clks), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ pd->num_core_pm_clks = num_core_pm_clks;
+ memcpy(pd->core_pm_clks, core_pm_clks, pm_size);
+
+ genpd = &pd->genpd;
+ genpd->name = np->name;
+ genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON |
+ GENPD_FLAG_ACTIVE_WAKEUP;
+ genpd->attach_dev = cpg_mssr_attach_dev;
+ genpd->detach_dev = cpg_mssr_detach_dev;
+ ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, cpg_mssr_genpd_remove, genpd);
+ if (ret)
+ return ret;
+
+ cpg_mssr_clk_domain = pd;
+
+ return of_genpd_add_provider_simple(np, genpd);
+}
+
+#ifdef CONFIG_RESET_CONTROLLER
+
+#define rcdev_to_priv(x) container_of(x, struct cpg_mssr_priv, rcdev)
+
+static int cpg_mssr_reset_operate(struct reset_controller_dev *rcdev,
+ const char *func, bool set, unsigned long id)
+{
+ struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
+ unsigned int reg = id / 32;
+ unsigned int bit = id % 32;
+ const u16 off = set ? priv->reset_regs[reg] : priv->reset_clear_regs[reg];
+ u32 bitmask = BIT(bit);
+
+ if (func)
+ dev_dbg(priv->dev, "%s %u%02u\n", func, reg, bit);
+
+ writel(bitmask, priv->pub.base0 + off);
+ readl(priv->pub.base0 + off);
+ barrier_data(priv->pub.base0 + off);
+
+ return 0;
+}
+
+static int cpg_mssr_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
+
+ /* Reset module */
+ cpg_mssr_reset_operate(rcdev, "reset", true, id);
+
+ /*
+ * On R-Car Gen4, delay after SRCR has been written is 1ms.
+ * On older SoCs, delay after SRCR has been written is 35us
+ * (one cycle of the RCLK clock @ ca. 32 kHz).
+ */
+ if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4)
+ usleep_range(1000, 2000);
+ else
+ usleep_range(35, 1000);
+
+ /* Release module from reset state */
+ return cpg_mssr_reset_operate(rcdev, NULL, false, id);
+}
+
+static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ return cpg_mssr_reset_operate(rcdev, "assert", true, id);
+}
+
+static int cpg_mssr_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return cpg_mssr_reset_operate(rcdev, "deassert", false, id);
+}
+
+static int cpg_mssr_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
+ unsigned int reg = id / 32;
+ unsigned int bit = id % 32;
+ u32 bitmask = BIT(bit);
+
+ return !!(readl(priv->pub.base0 + priv->reset_regs[reg]) & bitmask);
+}
+
+static int cpg_mrcr_set_reset_state(struct reset_controller_dev *rcdev,
+ unsigned long id, bool set)
+{
+ struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
+ unsigned int reg = id / 32;
+ unsigned int bit = id % 32;
+ u32 bitmask = BIT(bit);
+ void __iomem *reg_addr;
+ unsigned long flags;
+ unsigned int i;
+ u32 val;
+
+ dev_dbg(priv->dev, "%s %u%02u\n", set ? "assert" : "deassert", reg, bit);
+
+ spin_lock_irqsave(&priv->pub.rmw_lock, flags);
+
+ reg_addr = priv->pub.base0 + priv->reset_regs[reg];
+ /* Read current value and modify */
+ val = readl(reg_addr);
+ if (set)
+ val |= bitmask;
+ else
+ val &= ~bitmask;
+ writel(val, reg_addr);
+
+ /*
+ * For secure processing after release from a module reset, one must
+ * perform multiple dummy reads of the same register.
+ */
+ for (i = 0; !set && i < RZT2H_RESET_REG_READ_COUNT; i++)
+ readl(reg_addr);
+
+ /* Verify the operation */
+ val = readl(reg_addr);
+
+ spin_unlock_irqrestore(&priv->pub.rmw_lock, flags);
+
+ if (set == !(bitmask & val)) {
+ dev_err(priv->dev, "Reset register %u%02u operation failed\n", reg, bit);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int cpg_mrcr_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ int ret;
+
+ ret = cpg_mrcr_set_reset_state(rcdev, id, true);
+ if (ret)
+ return ret;
+
+ return cpg_mrcr_set_reset_state(rcdev, id, false);
+}
+
+static int cpg_mrcr_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ return cpg_mrcr_set_reset_state(rcdev, id, true);
+}
+
+static int cpg_mrcr_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ return cpg_mrcr_set_reset_state(rcdev, id, false);
+}
+
+static const struct reset_control_ops cpg_mssr_reset_ops = {
+ .reset = cpg_mssr_reset,
+ .assert = cpg_mssr_assert,
+ .deassert = cpg_mssr_deassert,
+ .status = cpg_mssr_status,
+};
+
+static const struct reset_control_ops cpg_mrcr_reset_ops = {
+ .reset = cpg_mrcr_reset,
+ .assert = cpg_mrcr_assert,
+ .deassert = cpg_mrcr_deassert,
+ .status = cpg_mssr_status,
+};
+
+static int cpg_mssr_reset_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
+ unsigned int unpacked = reset_spec->args[0];
+ unsigned int idx = MOD_CLK_PACK(unpacked);
+
+ if (unpacked % 100 > 31 || idx >= rcdev->nr_resets) {
+ dev_err(priv->dev, "Invalid reset index %u\n", unpacked);
+ return -EINVAL;
+ }
+
+ return idx;
+}
+
+static int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
+{
+ /*
+ * RZ/T2H (and family) has the Module Reset Control Registers
+ * which allows control resets of certain modules.
+ * The number of resets is not equal to the number of module clocks.
+ */
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) {
+ priv->rcdev.ops = &cpg_mrcr_reset_ops;
+ priv->rcdev.nr_resets = ARRAY_SIZE(mrcr_for_rzt2h) * 32;
+ } else {
+ priv->rcdev.ops = &cpg_mssr_reset_ops;
+ priv->rcdev.nr_resets = priv->num_mod_clks;
+ }
+
+ priv->rcdev.of_node = priv->dev->of_node;
+ priv->rcdev.of_reset_n_cells = 1;
+ priv->rcdev.of_xlate = cpg_mssr_reset_xlate;
+
+ return devm_reset_controller_register(priv->dev, &priv->rcdev);
+}
+
+#else /* !CONFIG_RESET_CONTROLLER */
+static inline int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
+{
+ return 0;
+}
+#endif /* !CONFIG_RESET_CONTROLLER */
+
+static const struct of_device_id cpg_mssr_match[] = {
+#ifdef CONFIG_CLK_R7S9210
+ {
+ .compatible = "renesas,r7s9210-cpg-mssr",
+ .data = &r7s9210_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A7742
+ {
+ .compatible = "renesas,r8a7742-cpg-mssr",
+ .data = &r8a7742_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A7743
+ {
+ .compatible = "renesas,r8a7743-cpg-mssr",
+ .data = &r8a7743_cpg_mssr_info,
+ },
+ /* RZ/G1N is (almost) identical to RZ/G1M w.r.t. clocks. */
+ {
+ .compatible = "renesas,r8a7744-cpg-mssr",
+ .data = &r8a7743_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A7745
+ {
+ .compatible = "renesas,r8a7745-cpg-mssr",
+ .data = &r8a7745_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A77470
+ {
+ .compatible = "renesas,r8a77470-cpg-mssr",
+ .data = &r8a77470_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A774A1
+ {
+ .compatible = "renesas,r8a774a1-cpg-mssr",
+ .data = &r8a774a1_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A774B1
+ {
+ .compatible = "renesas,r8a774b1-cpg-mssr",
+ .data = &r8a774b1_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A774C0
+ {
+ .compatible = "renesas,r8a774c0-cpg-mssr",
+ .data = &r8a774c0_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A774E1
+ {
+ .compatible = "renesas,r8a774e1-cpg-mssr",
+ .data = &r8a774e1_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A7790
+ {
+ .compatible = "renesas,r8a7790-cpg-mssr",
+ .data = &r8a7790_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A7791
+ {
+ .compatible = "renesas,r8a7791-cpg-mssr",
+ .data = &r8a7791_cpg_mssr_info,
+ },
+ /* R-Car M2-N is (almost) identical to R-Car M2-W w.r.t. clocks. */
+ {
+ .compatible = "renesas,r8a7793-cpg-mssr",
+ .data = &r8a7791_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A7792
+ {
+ .compatible = "renesas,r8a7792-cpg-mssr",
+ .data = &r8a7792_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A7794
+ {
+ .compatible = "renesas,r8a7794-cpg-mssr",
+ .data = &r8a7794_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A7795
+ {
+ .compatible = "renesas,r8a7795-cpg-mssr",
+ .data = &r8a7795_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A77960
+ {
+ .compatible = "renesas,r8a7796-cpg-mssr",
+ .data = &r8a7796_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A77961
+ {
+ .compatible = "renesas,r8a77961-cpg-mssr",
+ .data = &r8a7796_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A77965
+ {
+ .compatible = "renesas,r8a77965-cpg-mssr",
+ .data = &r8a77965_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A77970
+ {
+ .compatible = "renesas,r8a77970-cpg-mssr",
+ .data = &r8a77970_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A77980
+ {
+ .compatible = "renesas,r8a77980-cpg-mssr",
+ .data = &r8a77980_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A77990
+ {
+ .compatible = "renesas,r8a77990-cpg-mssr",
+ .data = &r8a77990_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A77995
+ {
+ .compatible = "renesas,r8a77995-cpg-mssr",
+ .data = &r8a77995_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A779A0
+ {
+ .compatible = "renesas,r8a779a0-cpg-mssr",
+ .data = &r8a779a0_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A779F0
+ {
+ .compatible = "renesas,r8a779f0-cpg-mssr",
+ .data = &r8a779f0_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A779G0
+ {
+ .compatible = "renesas,r8a779g0-cpg-mssr",
+ .data = &r8a779g0_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R8A779H0
+ {
+ .compatible = "renesas,r8a779h0-cpg-mssr",
+ .data = &r8a779h0_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R9A09G077
+ {
+ .compatible = "renesas,r9a09g077-cpg-mssr",
+ .data = &r9a09g077_cpg_mssr_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R9A09G087
+ {
+ .compatible = "renesas,r9a09g087-cpg-mssr",
+ .data = &r9a09g077_cpg_mssr_info,
+ },
+#endif
+ { /* sentinel */ }
+};
+
+static void cpg_mssr_del_clk_provider(void *data)
+{
+ of_clk_del_provider(data);
+}
+
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
+static int cpg_mssr_suspend_noirq(struct device *dev)
+{
+ struct cpg_mssr_priv *priv = dev_get_drvdata(dev);
+ unsigned int reg;
+
+ /* This is the best we can do to check for the presence of PSCI */
+ if (!psci_ops.cpu_suspend)
+ return 0;
+
+ /* Save module registers with bits under our control */
+ for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
+ u32 val;
+
+ if (!priv->smstpcr_saved[reg].mask)
+ continue;
+
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
+ val = readb(priv->pub.base0 + priv->control_regs[reg]);
+ else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H)
+ val = cpg_rzt2h_mstp_read(priv, priv->control_regs[reg]);
+ else
+ val = readl(priv->pub.base0 + priv->control_regs[reg]);
+
+ priv->smstpcr_saved[reg].val = val;
+ }
+
+ /* Save core clocks */
+ raw_notifier_call_chain(&priv->pub.notifiers, PM_EVENT_SUSPEND, NULL);
+
+ return 0;
+}
+
+static int cpg_mssr_resume_noirq(struct device *dev)
+{
+ struct cpg_mssr_priv *priv = dev_get_drvdata(dev);
+ unsigned int reg;
+ u32 mask, oldval, newval;
+ int error;
+
+ /* This is the best we can do to check for the presence of PSCI */
+ if (!psci_ops.cpu_suspend)
+ return 0;
+
+ /* Restore core clocks */
+ raw_notifier_call_chain(&priv->pub.notifiers, PM_EVENT_RESUME, NULL);
+
+ /* Restore module clocks */
+ for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
+ mask = priv->smstpcr_saved[reg].mask;
+ if (!mask)
+ continue;
+
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
+ oldval = readb(priv->pub.base0 + priv->control_regs[reg]);
+ else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H)
+ oldval = cpg_rzt2h_mstp_read(priv, priv->control_regs[reg]);
+ else
+ oldval = readl(priv->pub.base0 + priv->control_regs[reg]);
+ newval = oldval & ~mask;
+ newval |= priv->smstpcr_saved[reg].val & mask;
+ if (newval == oldval)
+ continue;
+
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
+ writeb(newval, priv->pub.base0 + priv->control_regs[reg]);
+ /* dummy read to ensure write has completed */
+ readb(priv->pub.base0 + priv->control_regs[reg]);
+ barrier_data(priv->pub.base0 + priv->control_regs[reg]);
+ continue;
+ } else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) {
+ cpg_rzt2h_mstp_write(priv, priv->control_regs[reg], newval);
+ /* See cpg_mstp_clock_endisable() on why this is necessary. */
+ cpg_rzt2h_mstp_read(priv, priv->control_regs[reg]);
+ udelay(10);
+ continue;
+ } else
+ writel(newval, priv->pub.base0 + priv->control_regs[reg]);
+
+ /* Wait until enabled clocks are really enabled */
+ mask &= ~priv->smstpcr_saved[reg].val;
+ if (!mask)
+ continue;
+
+ error = readl_poll_timeout_atomic(priv->pub.base0 + priv->status_regs[reg],
+ oldval, !(oldval & mask), 0, 10);
+ if (error)
+ dev_warn(dev, "Failed to enable SMSTP%u[0x%x]\n", reg,
+ oldval & mask);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops cpg_mssr_pm = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cpg_mssr_suspend_noirq,
+ cpg_mssr_resume_noirq)
+};
+#define DEV_PM_OPS &cpg_mssr_pm
+#else
+#define DEV_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
+
+static void __init cpg_mssr_reserved_exit(struct cpg_mssr_priv *priv)
+{
+ kfree(priv->reserved_ids);
+}
+
+static int __init cpg_mssr_reserved_init(struct cpg_mssr_priv *priv,
+ const struct cpg_mssr_info *info)
+{
+ struct device_node *soc __free(device_node) = of_find_node_by_path("/soc");
+ struct device_node *node;
+ uint32_t args[MAX_PHANDLE_ARGS];
+ unsigned int *ids = NULL;
+ unsigned int num = 0;
+
+ /*
+ * Because clk_disable_unused() will disable all unused clocks, the device which is assigned
+ * to a non-Linux system will be disabled when Linux is booted.
+ *
+ * To avoid such situation, renesas-cpg-mssr assumes the device which has
+ * status = "reserved" is assigned to a non-Linux system, and adds CLK_IGNORE_UNUSED flag
+ * to its CPG_MOD clocks.
+ * see also
+ * cpg_mssr_register_mod_clk()
+ *
+ * scif5: serial@e6f30000 {
+ * ...
+ * => clocks = <&cpg CPG_MOD 202>,
+ * <&cpg CPG_CORE R8A7795_CLK_S3D1>,
+ * <&scif_clk>;
+ * ...
+ * status = "reserved";
+ * };
+ */
+ for_each_reserved_child_of_node(soc, node) {
+ struct of_phandle_iterator it;
+ int rc;
+
+ of_for_each_phandle(&it, rc, node, "clocks", "#clock-cells", -1) {
+ int idx;
+ unsigned int *new_ids;
+
+ if (it.node != priv->np)
+ continue;
+
+ if (of_phandle_iterator_args(&it, args, MAX_PHANDLE_ARGS) != 2)
+ continue;
+
+ if (args[0] != CPG_MOD)
+ continue;
+
+ new_ids = krealloc_array(ids, (num + 1), sizeof(*ids), GFP_KERNEL);
+ if (!new_ids) {
+ of_node_put(it.node);
+ kfree(ids);
+ return -ENOMEM;
+ }
+ ids = new_ids;
+
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
+ idx = MOD_CLK_PACK_10(args[1]); /* for DEF_MOD_STB() */
+ else
+ idx = MOD_CLK_PACK(args[1]); /* for DEF_MOD() */
+
+ ids[num] = info->num_total_core_clks + idx;
+
+ num++;
+ }
+ }
+
+ priv->num_reserved_ids = num;
+ priv->reserved_ids = ids;
+
+ return 0;
+}
+
+static int __init cpg_mssr_common_init(struct device *dev,
+ struct device_node *np,
+ const struct cpg_mssr_info *info)
+{
+ struct cpg_mssr_priv *priv;
+ unsigned int nclks, i;
+ int error;
+
+ if (info->init) {
+ error = info->init(dev);
+ if (error)
+ return error;
+ }
+
+ nclks = info->num_total_core_clks + info->num_hw_mod_clks;
+ priv = kzalloc_flex(*priv, clks, nclks);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->pub.clks = priv->clks;
+ priv->np = np;
+ priv->dev = dev;
+ spin_lock_init(&priv->pub.rmw_lock);
+
+ priv->pub.base0 = of_iomap(np, 0);
+ if (!priv->pub.base0) {
+ error = -ENOMEM;
+ goto out_err;
+ }
+ if (info->reg_layout == CLK_REG_LAYOUT_RZ_T2H) {
+ priv->pub.base1 = of_iomap(np, 1);
+ if (!priv->pub.base1) {
+ error = -ENOMEM;
+ goto out_err;
+ }
+ }
+
+ priv->num_core_clks = info->num_total_core_clks;
+ priv->num_mod_clks = info->num_hw_mod_clks;
+ priv->last_dt_core_clk = info->last_dt_core_clk;
+ RAW_INIT_NOTIFIER_HEAD(&priv->pub.notifiers);
+ priv->reg_layout = info->reg_layout;
+ if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3) {
+ priv->status_regs = mstpsr;
+ priv->control_regs = smstpcr;
+ priv->reset_regs = srcr;
+ priv->reset_clear_regs = srstclr;
+ } else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
+ priv->control_regs = stbcr;
+ } else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_T2H) {
+ priv->control_regs = mstpcr_for_rzt2h;
+ priv->reset_regs = mrcr_for_rzt2h;
+ } else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4) {
+ priv->status_regs = mstpsr_for_gen4;
+ priv->control_regs = mstpcr_for_gen4;
+ priv->reset_regs = srcr_for_gen4;
+ priv->reset_clear_regs = srstclr_for_gen4;
+ } else {
+ error = -EINVAL;
+ goto out_err;
+ }
+
+ for (i = 0; i < nclks; i++)
+ priv->pub.clks[i] = ERR_PTR(-ENOENT);
+
+ error = cpg_mssr_reserved_init(priv, info);
+ if (error)
+ goto out_err;
+
+ error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv);
+ if (error)
+ goto reserve_err;
+
+ cpg_mssr_priv = priv;
+
+ return 0;
+
+reserve_err:
+ cpg_mssr_reserved_exit(priv);
+out_err:
+ if (priv->pub.base0)
+ iounmap(priv->pub.base0);
+ if (priv->pub.base1)
+ iounmap(priv->pub.base1);
+ kfree(priv);
+
+ return error;
+}
+
+void __init cpg_mssr_early_init(struct device_node *np,
+ const struct cpg_mssr_info *info)
+{
+ int error;
+ int i;
+
+ error = cpg_mssr_common_init(NULL, np, info);
+ if (error)
+ return;
+
+ for (i = 0; i < info->num_early_core_clks; i++)
+ cpg_mssr_register_core_clk(&info->early_core_clks[i], info,
+ cpg_mssr_priv);
+
+ for (i = 0; i < info->num_early_mod_clks; i++)
+ cpg_mssr_register_mod_clk(&info->early_mod_clks[i], info,
+ cpg_mssr_priv);
+
+}
+
+static int __init cpg_mssr_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct cpg_mssr_info *info;
+ struct cpg_mssr_priv *priv;
+ unsigned int i;
+ int error;
+
+ info = of_device_get_match_data(dev);
+
+ if (!cpg_mssr_priv) {
+ error = cpg_mssr_common_init(dev, dev->of_node, info);
+ if (error)
+ return error;
+ }
+
+ priv = cpg_mssr_priv;
+ priv->dev = dev;
+ dev_set_drvdata(dev, priv);
+
+ for (i = 0; i < info->num_core_clks; i++)
+ cpg_mssr_register_core_clk(&info->core_clks[i], info, priv);
+
+ for (i = 0; i < info->num_mod_clks; i++)
+ cpg_mssr_register_mod_clk(&info->mod_clks[i], info, priv);
+
+ error = devm_add_action_or_reset(dev,
+ cpg_mssr_del_clk_provider,
+ np);
+ if (error)
+ goto reserve_exit;
+
+ error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks,
+ info->num_core_pm_clks);
+ if (error)
+ goto reserve_exit;
+
+ /* Reset Controller not supported for Standby Control SoCs */
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
+ goto reserve_exit;
+
+ error = cpg_mssr_reset_controller_register(priv);
+
+reserve_exit:
+ cpg_mssr_reserved_exit(priv);
+
+ return error;
+}
+
+static struct platform_driver cpg_mssr_driver = {
+ .driver = {
+ .name = "renesas-cpg-mssr",
+ .of_match_table = cpg_mssr_match,
+ .pm = DEV_PM_OPS,
+ },
+};
+
+static int __init cpg_mssr_init(void)
+{
+ return platform_driver_probe(&cpg_mssr_driver, cpg_mssr_probe);
+}
+
+subsys_initcall(cpg_mssr_init);
+
+void __init mssr_mod_nullify(struct mssr_mod_clk *mod_clks,
+ unsigned int num_mod_clks,
+ const unsigned int *clks, unsigned int n)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; i < num_mod_clks && j < n; i++)
+ if (mod_clks[i].id == clks[j]) {
+ mod_clks[i].name = NULL;
+ j++;
+ }
+}
+
+MODULE_DESCRIPTION("Renesas CPG/MSSR Driver");
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h
new file mode 100644
index 000000000..ad11ab5f0
--- /dev/null
+++ b/drivers/clk/renesas/renesas-cpg-mssr.h
@@ -0,0 +1,222 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Renesas Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2015 Glider bvba
+ */
+
+#ifndef __CLK_RENESAS_CPG_MSSR_H__
+#define __CLK_RENESAS_CPG_MSSR_H__
+
+#include <linux/notifier.h>
+
+ /*
+ * Definitions of CPG Core Clocks
+ *
+ * These include:
+ * - Clock outputs exported to DT
+ * - External input clocks
+ * - Internal CPG clocks
+ */
+
+struct cpg_core_clk {
+ /* Common */
+ const char *name;
+ unsigned int id;
+ unsigned int type;
+ /* Depending on type */
+ unsigned int parent; /* Core Clocks only */
+ unsigned int div;
+ unsigned int mult;
+ unsigned int offset;
+ union {
+ const char * const *parent_names;
+ const struct clk_div_table *dtable;
+ };
+ u32 conf;
+ u16 flag;
+ u8 mux_flags;
+ u8 num_parents;
+};
+
+/**
+ * struct cpg_mssr_pub - data shared with device-specific clk registration code
+ *
+ * @base0: CPG/MSSR register block base0 address
+ * @base1: CPG/MSSR register block base1 address
+ * @notifiers: Notifier chain to save/restore clock state for system resume
+ * @rmw_lock: protects RMW register accesses
+ * @clks: pointer to clocks
+ */
+struct cpg_mssr_pub {
+ void __iomem *base0;
+ void __iomem *base1;
+ struct raw_notifier_head notifiers;
+ spinlock_t rmw_lock;
+ struct clk **clks;
+};
+
+enum clk_types {
+ /* Generic */
+ CLK_TYPE_IN, /* External Clock Input */
+ CLK_TYPE_FF, /* Fixed Factor Clock */
+ CLK_TYPE_DIV6P1, /* DIV6 Clock with 1 parent clock */
+ CLK_TYPE_DIV6_RO, /* DIV6 Clock read only with extra divisor */
+ CLK_TYPE_FR, /* Fixed Rate Clock */
+
+ /* Custom definitions start here */
+ CLK_TYPE_CUSTOM,
+};
+
+#define DEF_TYPE(_name, _id, _type...) \
+ { .name = _name, .id = _id, .type = _type }
+#define DEF_BASE(_name, _id, _type, _parent...) \
+ DEF_TYPE(_name, _id, _type, .parent = _parent)
+
+#define DEF_INPUT(_name, _id) \
+ DEF_TYPE(_name, _id, CLK_TYPE_IN)
+#define DEF_FIXED(_name, _id, _parent, _div, _mult) \
+ DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
+#define DEF_DIV6P1(_name, _id, _parent, _offset) \
+ DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset)
+#define DEF_DIV6_RO(_name, _id, _parent, _offset, _div) \
+ DEF_BASE(_name, _id, CLK_TYPE_DIV6_RO, _parent, .offset = _offset, .div = _div, .mult = 1)
+#define DEF_RATE(_name, _id, _rate) \
+ DEF_TYPE(_name, _id, CLK_TYPE_FR, .mult = _rate)
+
+ /*
+ * Definitions of Module Clocks
+ */
+
+struct mssr_mod_clk {
+ const char *name;
+ unsigned int id;
+ unsigned int parent; /* Add MOD_CLK_BASE for Module Clocks */
+};
+
+/* Convert from sparse base-100 to packed index space */
+#define MOD_CLK_PACK(x) ((x) - ((x) / 100) * (100 - 32))
+
+#define MOD_CLK_ID(x) (MOD_CLK_BASE + MOD_CLK_PACK(x))
+
+#define DEF_MOD(_name, _mod, _parent...) \
+ { .name = _name, .id = MOD_CLK_ID(_mod), .parent = _parent }
+
+/* Convert from sparse base-10 to packed index space */
+#define MOD_CLK_PACK_10(x) ((x / 10) * 32 + (x % 10))
+
+#define MOD_CLK_ID_10(x) (MOD_CLK_BASE + MOD_CLK_PACK_10(x))
+
+#define DEF_MOD_STB(_name, _mod, _parent...) \
+ { .name = _name, .id = MOD_CLK_ID_10(_mod), .parent = _parent }
+
+struct device_node;
+
+enum clk_reg_layout {
+ CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3 = 0,
+ CLK_REG_LAYOUT_RZ_A,
+ CLK_REG_LAYOUT_RCAR_GEN4,
+ CLK_REG_LAYOUT_RZ_T2H,
+};
+
+ /**
+ * SoC-specific CPG/MSSR Description
+ *
+ * @early_core_clks: Array of Early Core Clock definitions
+ * @num_early_core_clks: Number of entries in early_core_clks[]
+ * @early_mod_clks: Array of Early Module Clock definitions
+ * @num_early_mod_clks: Number of entries in early_mod_clks[]
+ *
+ * @core_clks: Array of Core Clock definitions
+ * @num_core_clks: Number of entries in core_clks[]
+ * @last_dt_core_clk: ID of the last Core Clock exported to DT
+ * @num_total_core_clks: Total number of Core Clocks (exported + internal)
+ *
+ * @mod_clks: Array of Module Clock definitions
+ * @num_mod_clks: Number of entries in mod_clks[]
+ * @num_hw_mod_clks: Number of Module Clocks supported by the hardware
+ *
+ * @crit_mod_clks: Array with Module Clock IDs of critical clocks that
+ * should not be disabled without a knowledgeable driver
+ * @num_crit_mod_clks: Number of entries in crit_mod_clks[]
+ * @reg_layout: CPG/MSSR register layout from enum clk_reg_layout
+ *
+ * @core_pm_clks: Array with IDs of Core Clocks that are suitable for Power
+ * Management, in addition to Module Clocks
+ * @num_core_pm_clks: Number of entries in core_pm_clks[]
+ *
+ * @init: Optional callback to perform SoC-specific initialization
+ * @cpg_clk_register: Optional callback to handle special Core Clock types
+ */
+
+struct cpg_mssr_info {
+ /* Early Clocks */
+ const struct cpg_core_clk *early_core_clks;
+ unsigned int num_early_core_clks;
+ const struct mssr_mod_clk *early_mod_clks;
+ unsigned int num_early_mod_clks;
+
+ /* Core Clocks */
+ const struct cpg_core_clk *core_clks;
+ unsigned int num_core_clks;
+ unsigned int last_dt_core_clk;
+ unsigned int num_total_core_clks;
+ enum clk_reg_layout reg_layout;
+
+ /* Module Clocks */
+ const struct mssr_mod_clk *mod_clks;
+ unsigned int num_mod_clks;
+ unsigned int num_hw_mod_clks;
+
+ /* Critical Module Clocks that should not be disabled */
+ const unsigned int *crit_mod_clks;
+ unsigned int num_crit_mod_clks;
+
+ /* Core Clocks suitable for PM, in addition to the Module Clocks */
+ const unsigned int *core_pm_clks;
+ unsigned int num_core_pm_clks;
+
+ /* Callbacks */
+ int (*init)(struct device *dev);
+ struct clk *(*cpg_clk_register)(struct device *dev,
+ const struct cpg_core_clk *core,
+ const struct cpg_mssr_info *info,
+ struct cpg_mssr_pub *pub);
+};
+
+extern const struct cpg_mssr_info r7s9210_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7742_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7743_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7745_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a77470_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a774a1_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a774b1_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a774c0_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a774e1_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7790_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7791_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7792_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7794_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a77965_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a77970_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a77980_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a77990_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a77995_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a779a0_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a779f0_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a779g0_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a779h0_cpg_mssr_info;
+extern const struct cpg_mssr_info r9a09g077_cpg_mssr_info;
+
+void __init cpg_mssr_early_init(struct device_node *np,
+ const struct cpg_mssr_info *info);
+
+ /*
+ * Helpers for fixing up clock tables depending on SoC revision
+ */
+extern void mssr_mod_nullify(struct mssr_mod_clk *mod_clks,
+ unsigned int num_mod_clks,
+ const unsigned int *clks, unsigned int n);
+#endif
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
new file mode 100644
index 000000000..975b705d3
--- /dev/null
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -0,0 +1,2246 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G2L Clock Pulse Generator
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ * Based on renesas-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2013 Ideas On Board SPRL
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/atomic.h>
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/iopoll.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/string_choices.h>
+#include <linux/units.h>
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+#include "rzg2l-cpg.h"
+
+#ifdef DEBUG
+#define WARN_DEBUG(x) WARN_ON(x)
+#else
+#define WARN_DEBUG(x) do { } while (0)
+#endif
+
+#define GET_SHIFT(val) ((val >> 12) & 0xff)
+#define GET_WIDTH(val) ((val >> 8) & 0xf)
+
+#define KDIV(val) ((s16)FIELD_GET(GENMASK(31, 16), val))
+#define MDIV(val) FIELD_GET(GENMASK(15, 6), val)
+#define PDIV(val) FIELD_GET(GENMASK(5, 0), val)
+#define SDIV(val) FIELD_GET(GENMASK(2, 0), val)
+
+#define RZG3S_DIV_P GENMASK(28, 26)
+#define RZG3S_DIV_M GENMASK(25, 22)
+#define RZG3S_DIV_NI GENMASK(21, 13)
+#define RZG3S_DIV_NF GENMASK(12, 1)
+#define RZG3S_SEL_PLL BIT(0)
+
+#define CPG_PLL1_SETTING_OFFSET(conf) FIELD_GET(GENMASK(11, 0), (conf))
+#define CPG_PLL_STBY_OFFSET(conf) FIELD_GET(GENMASK(23, 12), (conf))
+#define CPG_PLL_STBY_RESETB_WEN BIT(16)
+#define CPG_PLL_STBY_RESETB BIT(0)
+#define CPG_PLL_CLK1_OFFSET(x) (CPG_PLL_STBY_OFFSET(x) + 0x4)
+#define CPG_PLL_CLK2_OFFSET(x) (CPG_PLL_STBY_OFFSET(x) + 0x8)
+#define CPG_PLL_MON_OFFSET(x) (CPG_PLL_STBY_OFFSET(x) + 0xc)
+#define CPG_PLL_MON_LOCK BIT(4)
+#define CPG_PLL_MON_RESETB BIT(0)
+
+#define CLK_ON_R(reg) (reg)
+#define CLK_MON_R(reg) (0x180 + (reg))
+#define CLK_RST_R(reg) (reg)
+#define CLK_MRST_R(reg) (0x180 + (reg))
+
+#define GET_REG_OFFSET(val) ((val >> 20) & 0xfff)
+
+#define CPG_WEN_BIT BIT(16)
+
+#define MAX_VCLK_FREQ (148500000)
+
+#define MSTOP_OFF(conf) FIELD_GET(GENMASK(31, 16), (conf))
+#define MSTOP_MASK(conf) FIELD_GET(GENMASK(15, 0), (conf))
+
+#define PLL5_FOUTVCO_MIN 800000000
+#define PLL5_FOUTVCO_MAX 3000000000
+#define PLL5_POSTDIV_MIN 1
+#define PLL5_POSTDIV_MAX 7
+#define PLL5_REFDIV_MIN 1
+#define PLL5_REFDIV_MAX 2
+#define PLL5_INTIN_MIN 20
+#define PLL5_INTIN_MAX 320
+#define PLL5_HSCLK_MIN 10000000
+#define PLL5_HSCLK_MAX 187500000
+
+/**
+ * struct clk_hw_data - clock hardware data
+ * @hw: clock hw
+ * @conf: clock configuration (register offset, shift, width)
+ * @sconf: clock status configuration (register offset, shift, width)
+ * @priv: CPG private data structure
+ */
+struct clk_hw_data {
+ struct clk_hw hw;
+ u32 conf;
+ u32 sconf;
+ struct rzg2l_cpg_priv *priv;
+};
+
+#define to_clk_hw_data(_hw) container_of(_hw, struct clk_hw_data, hw)
+
+/**
+ * struct sd_mux_hw_data - SD MUX clock hardware data
+ * @hw_data: clock hw data
+ * @mtable: clock mux table
+ */
+struct sd_mux_hw_data {
+ struct clk_hw_data hw_data;
+ const u32 *mtable;
+};
+
+#define to_sd_mux_hw_data(_hw) container_of(_hw, struct sd_mux_hw_data, hw_data)
+
+/**
+ * struct div_hw_data - divider clock hardware data
+ * @hw_data: clock hw data
+ * @dtable: pointer to divider table
+ * @invalid_rate: invalid rate for divider
+ * @max_rate: maximum rate for divider
+ * @width: divider width
+ */
+struct div_hw_data {
+ struct clk_hw_data hw_data;
+ const struct clk_div_table *dtable;
+ unsigned long invalid_rate;
+ unsigned long max_rate;
+ u32 width;
+};
+
+#define to_div_hw_data(_hw) container_of(_hw, struct div_hw_data, hw_data)
+
+struct rzg2l_pll5_param {
+ u32 pl5_fracin;
+ u16 pl5_intin;
+ u8 pl5_refdiv;
+ u8 pl5_postdiv1;
+ u8 pl5_postdiv2;
+ u8 pl5_spread;
+};
+
+/* PLL5 output will be used for DPI or MIPI-DSI */
+static int dsi_div_target = PLL5_TARGET_DPI;
+
+/* Required division ratio for MIPI D-PHY clock depending on number of lanes and bpp. */
+static u8 dsi_div_ab_desired;
+
+struct rzg2l_pll5_mux_dsi_div_param {
+ u8 clksrc;
+ u8 dsi_div_a;
+ u8 dsi_div_b;
+};
+
+/**
+ * struct rzg2l_cpg_priv - Clock Pulse Generator Private Data
+ *
+ * @rcdev: Reset controller entity
+ * @dev: CPG device
+ * @base: CPG register block base address
+ * @rmw_lock: protects register accesses
+ * @clks: Array containing all Core and Module Clocks
+ * @num_core_clks: Number of Core Clocks in clks[]
+ * @num_mod_clks: Number of Module Clocks in clks[]
+ * @num_resets: Number of Module Resets in info->resets[]
+ * @last_dt_core_clk: ID of the last Core Clock exported to DT
+ * @info: Pointer to platform data
+ * @genpd: PM domain
+ * @mux_dsi_div_params: pll5 mux and dsi div parameters
+ */
+struct rzg2l_cpg_priv {
+ struct reset_controller_dev rcdev;
+ struct device *dev;
+ void __iomem *base;
+ spinlock_t rmw_lock;
+
+ struct clk **clks;
+ unsigned int num_core_clks;
+ unsigned int num_mod_clks;
+ unsigned int num_resets;
+ unsigned int last_dt_core_clk;
+
+ const struct rzg2l_cpg_info *info;
+
+ struct generic_pm_domain genpd;
+
+ struct rzg2l_pll5_mux_dsi_div_param mux_dsi_div_params;
+};
+
+static inline u8 rzg2l_cpg_div_ab(u8 a, u8 b)
+{
+ return (b + 1) << a;
+}
+
+static void rzg2l_cpg_del_clk_provider(void *data)
+{
+ of_clk_del_provider(data);
+}
+
+/* Must be called in atomic context. */
+static int rzg2l_cpg_wait_clk_update_done(void __iomem *base, u32 conf)
+{
+ u32 bitmask = GENMASK(GET_WIDTH(conf) - 1, 0) << GET_SHIFT(conf);
+ u32 off = GET_REG_OFFSET(conf);
+ u32 val;
+
+ return readl_poll_timeout_atomic(base + off, val, !(val & bitmask), 10, 200);
+}
+
+int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ struct clk_notifier_data *cnd = data;
+ struct clk_hw *hw = __clk_get_hw(cnd->clk);
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
+ u32 shift = GET_SHIFT(clk_hw_data->conf);
+ const u32 clk_src_266 = 3;
+ unsigned long flags;
+ int ret;
+
+ if (event != PRE_RATE_CHANGE || (cnd->new_rate / MEGA == 266))
+ return NOTIFY_DONE;
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+
+ /*
+ * As per the HW manual, we should not directly switch from 533 MHz to
+ * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz)
+ * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first,
+ * and then switch to the target setting (2’b01 (533 MHz) or 2’b10
+ * (400 MHz)).
+ * Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock
+ * switching register is prohibited.
+ * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
+ * the index to value mapping is done by adding 1 to the index.
+ */
+
+ writel((CPG_WEN_BIT | clk_src_266) << shift, priv->base + off);
+
+ /* Wait for the update done. */
+ ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
+
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+
+ if (ret)
+ dev_err(priv->dev, "failed to switch to safe clk source\n");
+
+ return notifier_from_errno(ret);
+}
+
+int rzg3s_cpg_div_clk_notifier(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ struct clk_notifier_data *cnd = data;
+ struct clk_hw *hw = __clk_get_hw(cnd->clk);
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
+ u32 shift = GET_SHIFT(clk_hw_data->conf);
+ unsigned long flags;
+ int ret = 0;
+ u32 val;
+
+ if (event != PRE_RATE_CHANGE || !div_hw_data->invalid_rate ||
+ div_hw_data->invalid_rate % cnd->new_rate)
+ return NOTIFY_DONE;
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+
+ val = readl(priv->base + off);
+ val >>= shift;
+ val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0);
+
+ /*
+ * There are different constraints for the user of this notifiers as follows:
+ * 1/ SD div cannot be 1 (val == 0) if parent rate is 800MHz
+ * 2/ OCTA / SPI div cannot be 1 (val == 0) if parent rate is 400MHz
+ * As SD can have only one parent having 800MHz and OCTA div can have
+ * only one parent having 400MHz we took into account the parent rate
+ * at the beginning of function (by checking invalid_rate % new_rate).
+ * Now it is time to check the hardware divider and update it accordingly.
+ */
+ if (!val) {
+ writel((CPG_WEN_BIT | 1) << shift, priv->base + off);
+ /* Wait for the update done. */
+ ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
+ }
+
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+
+ if (ret)
+ dev_err(priv->dev, "Failed to downgrade the div\n");
+
+ return notifier_from_errno(ret);
+}
+
+static int rzg2l_register_notifier(struct clk_hw *hw, const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct notifier_block *nb;
+
+ if (!core->notifier)
+ return 0;
+
+ nb = devm_kzalloc(priv->dev, sizeof(*nb), GFP_KERNEL);
+ if (!nb)
+ return -ENOMEM;
+
+ nb->notifier_call = core->notifier;
+
+ return clk_notifier_register(hw->clk, nb);
+}
+
+static unsigned long rzg3s_div_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 val;
+
+ val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf));
+ val >>= GET_SHIFT(clk_hw_data->conf);
+ val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0);
+
+ return divider_recalc_rate(hw, parent_rate, val, div_hw_data->dtable,
+ CLK_DIVIDER_ROUND_CLOSEST, div_hw_data->width);
+}
+
+static int rzg3s_div_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data);
+
+ if (div_hw_data->max_rate && req->rate > div_hw_data->max_rate)
+ req->rate = div_hw_data->max_rate;
+
+ return divider_determine_rate(hw, req, div_hw_data->dtable, div_hw_data->width,
+ CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static int rzg3s_div_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
+ u32 shift = GET_SHIFT(clk_hw_data->conf);
+ unsigned long flags;
+ u32 val;
+ int ret;
+
+ val = divider_get_val(rate, parent_rate, div_hw_data->dtable, div_hw_data->width,
+ CLK_DIVIDER_ROUND_CLOSEST);
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+ writel((CPG_WEN_BIT | val) << shift, priv->base + off);
+ /* Wait for the update done. */
+ ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+
+ return ret;
+}
+
+static const struct clk_ops rzg3s_div_clk_ops = {
+ .recalc_rate = rzg3s_div_clk_recalc_rate,
+ .determine_rate = rzg3s_div_clk_determine_rate,
+ .set_rate = rzg3s_div_clk_set_rate,
+};
+
+static struct clk * __init
+rzg3s_cpg_div_clk_register(const struct cpg_core_clk *core, struct rzg2l_cpg_priv *priv)
+{
+ struct div_hw_data *div_hw_data;
+ struct clk_init_data init = {};
+ const struct clk_div_table *clkt;
+ struct clk_hw *clk_hw;
+ const struct clk *parent;
+ const char *parent_name;
+ u32 max = 0;
+ int ret;
+
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ div_hw_data = devm_kzalloc(priv->dev, sizeof(*div_hw_data), GFP_KERNEL);
+ if (!div_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = core->name;
+ init.flags = core->flag;
+ init.ops = &rzg3s_div_clk_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ /* Get the maximum divider to retrieve div width. */
+ for (clkt = core->dtable; clkt->div; clkt++) {
+ if (max < clkt->div)
+ max = clkt->div;
+ }
+
+ div_hw_data->hw_data.priv = priv;
+ div_hw_data->hw_data.conf = core->conf;
+ div_hw_data->hw_data.sconf = core->sconf;
+ div_hw_data->dtable = core->dtable;
+ div_hw_data->invalid_rate = core->invalid_rate;
+ div_hw_data->max_rate = core->max_rate;
+ div_hw_data->width = fls(max) - 1;
+
+ clk_hw = &div_hw_data->hw_data.hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = rzg2l_register_notifier(clk_hw, core, priv);
+ if (ret) {
+ dev_err(priv->dev, "Failed to register notifier for %s\n",
+ core->name);
+ return ERR_PTR(ret);
+ }
+
+ return clk_hw->clk;
+}
+
+static struct clk * __init
+rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv)
+{
+ void __iomem *base = priv->base;
+ struct device *dev = priv->dev;
+ const struct clk *parent;
+ const char *parent_name;
+ struct clk_hw *clk_hw;
+
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ if (core->dtable)
+ clk_hw = clk_hw_register_divider_table(dev, core->name,
+ parent_name, 0,
+ base + GET_REG_OFFSET(core->conf),
+ GET_SHIFT(core->conf),
+ GET_WIDTH(core->conf),
+ core->flag,
+ core->dtable,
+ &priv->rmw_lock);
+ else
+ clk_hw = clk_hw_register_divider(dev, core->name,
+ parent_name, 0,
+ base + GET_REG_OFFSET(core->conf),
+ GET_SHIFT(core->conf),
+ GET_WIDTH(core->conf),
+ core->flag, &priv->rmw_lock);
+
+ if (IS_ERR(clk_hw))
+ return ERR_CAST(clk_hw);
+
+ return clk_hw->clk;
+}
+
+static struct clk * __init
+rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv)
+{
+ const struct clk_hw *clk_hw;
+
+ clk_hw = devm_clk_hw_register_mux(priv->dev, core->name,
+ core->parent_names, core->num_parents,
+ core->flag,
+ priv->base + GET_REG_OFFSET(core->conf),
+ GET_SHIFT(core->conf),
+ GET_WIDTH(core->conf),
+ core->mux_flags, &priv->rmw_lock);
+ if (IS_ERR(clk_hw))
+ return ERR_CAST(clk_hw);
+
+ return clk_hw->clk;
+}
+
+static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
+ u32 shift = GET_SHIFT(clk_hw_data->conf);
+ unsigned long flags;
+ u32 val;
+ int ret;
+
+ val = clk_mux_index_to_val(sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, index);
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+
+ writel((CPG_WEN_BIT | val) << shift, priv->base + off);
+
+ /* Wait for the update done. */
+ ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
+
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+
+ if (ret)
+ dev_err(priv->dev, "Failed to switch parent\n");
+
+ return ret;
+}
+
+static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw)
+{
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
+ struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 val;
+
+ val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf));
+ val >>= GET_SHIFT(clk_hw_data->conf);
+ val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0);
+
+ return clk_mux_val_to_index(hw, sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, val);
+}
+
+static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = {
+ .determine_rate = __clk_mux_determine_rate_closest,
+ .set_parent = rzg2l_cpg_sd_clk_mux_set_parent,
+ .get_parent = rzg2l_cpg_sd_clk_mux_get_parent,
+};
+
+static struct clk * __init
+rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct sd_mux_hw_data *sd_mux_hw_data;
+ struct clk_init_data init;
+ struct clk_hw *clk_hw;
+ int ret;
+
+ sd_mux_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_mux_hw_data), GFP_KERNEL);
+ if (!sd_mux_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+ sd_mux_hw_data->hw_data.priv = priv;
+ sd_mux_hw_data->hw_data.conf = core->conf;
+ sd_mux_hw_data->hw_data.sconf = core->sconf;
+ sd_mux_hw_data->mtable = core->mtable;
+
+ init.name = core->name;
+ init.ops = &rzg2l_cpg_sd_clk_mux_ops;
+ init.flags = core->flag;
+ init.num_parents = core->num_parents;
+ init.parent_names = core->parent_names;
+
+ clk_hw = &sd_mux_hw_data->hw_data.hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = rzg2l_register_notifier(clk_hw, core, priv);
+ if (ret) {
+ dev_err(priv->dev, "Failed to register notifier for %s\n",
+ core->name);
+ return ERR_PTR(ret);
+ }
+
+ return clk_hw->clk;
+}
+
+/*
+ * VCO-->[POSTDIV1,2]--FOUTPOSTDIV--------------->|
+ * | |-->[1/(DSI DIV A * B)]--> MIPI_DSI_VCLK
+ * |-->[1/2]--FOUT1PH0-->|
+ * |
+ * |------->[1/16]--------------------------------> hsclk (MIPI-PHY)
+ */
+static unsigned long
+rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_cpg_priv *priv,
+ struct rzg2l_pll5_param *params,
+ unsigned long rate)
+{
+ const u32 extal_hz = EXTAL_FREQ_IN_MEGA_HZ * MEGA;
+ unsigned long foutpostdiv_rate;
+ unsigned int a, b, odd;
+ unsigned long hsclk;
+ u8 dsi_div_ab_calc;
+ u64 foutvco_rate;
+
+ if (dsi_div_target == PLL5_TARGET_DSI) {
+ /* Check hsclk */
+ hsclk = rate * dsi_div_ab_desired / 16;
+ if (hsclk < PLL5_HSCLK_MIN || hsclk > PLL5_HSCLK_MAX) {
+ dev_err(priv->dev, "hsclk out of range\n");
+ return 0;
+ }
+
+ /* Determine the correct clock source based on even/odd of the divider */
+ odd = dsi_div_ab_desired & 1;
+ if (odd) {
+ priv->mux_dsi_div_params.clksrc = 0; /* FOUTPOSTDIV */
+ dsi_div_ab_calc = dsi_div_ab_desired;
+ } else {
+ priv->mux_dsi_div_params.clksrc = 1; /* FOUT1PH0 */
+ dsi_div_ab_calc = dsi_div_ab_desired / 2;
+ }
+
+ /* Calculate the DIV_DSI_A and DIV_DSI_B based on the desired divider */
+ for (a = 0; a < 4; a++) {
+ /* FOUT1PH0: Max output of DIV_DSI_A is 750MHz so at least 1/2 to be safe */
+ if (!odd && a == 0)
+ continue;
+
+ /* FOUTPOSTDIV: DIV_DSI_A must always be 1/1 */
+ if (odd && a != 0)
+ break;
+
+ for (b = 0; b < 16; b++) {
+ /* FOUTPOSTDIV: DIV_DSI_B must always be odd divider 1/(b+1) */
+ if (odd && b & 1)
+ continue;
+
+ if (rzg2l_cpg_div_ab(a, b) == dsi_div_ab_calc) {
+ priv->mux_dsi_div_params.dsi_div_a = a;
+ priv->mux_dsi_div_params.dsi_div_b = b;
+ goto calc_pll_clk;
+ }
+ }
+ }
+
+ dev_err(priv->dev, "Failed to calculate DIV_DSI_A,B\n");
+
+ return 0;
+ } else if (dsi_div_target == PLL5_TARGET_DPI) {
+ /* Fixed settings for DPI */
+ priv->mux_dsi_div_params.clksrc = 0;
+ priv->mux_dsi_div_params.dsi_div_a = 3; /* Divided by 8 */
+ priv->mux_dsi_div_params.dsi_div_b = 0; /* Divided by 1 */
+ dsi_div_ab_desired = rzg2l_cpg_div_ab(priv->mux_dsi_div_params.dsi_div_a,
+ priv->mux_dsi_div_params.dsi_div_b);
+ }
+
+calc_pll_clk:
+ /* PLL5 (MIPI_DSI_PLLCLK) = VCO / POSTDIV1 / POSTDIV2 */
+ for (params->pl5_postdiv1 = PLL5_POSTDIV_MIN;
+ params->pl5_postdiv1 <= PLL5_POSTDIV_MAX;
+ params->pl5_postdiv1++) {
+ for (params->pl5_postdiv2 = PLL5_POSTDIV_MIN;
+ params->pl5_postdiv2 <= PLL5_POSTDIV_MAX;
+ params->pl5_postdiv2++) {
+ foutvco_rate = rate * params->pl5_postdiv1 * params->pl5_postdiv2 *
+ dsi_div_ab_desired;
+ if (foutvco_rate <= PLL5_FOUTVCO_MIN || foutvco_rate >= PLL5_FOUTVCO_MAX)
+ continue;
+
+ for (params->pl5_refdiv = PLL5_REFDIV_MIN;
+ params->pl5_refdiv <= PLL5_REFDIV_MAX;
+ params->pl5_refdiv++) {
+ u32 rem;
+
+ params->pl5_intin = div_u64_rem(foutvco_rate * params->pl5_refdiv,
+ extal_hz, &rem);
+
+ if (params->pl5_intin < PLL5_INTIN_MIN ||
+ params->pl5_intin > PLL5_INTIN_MAX)
+ continue;
+
+ params->pl5_fracin = div_u64((u64)rem << 24, extal_hz);
+
+ goto clk_valid;
+ }
+ }
+ }
+
+ dev_err(priv->dev, "Failed to calculate PLL5 settings\n");
+ return 0;
+
+clk_valid:
+ params->pl5_spread = 0x16;
+
+ foutvco_rate = div_u64(mul_u32_u32(EXTAL_FREQ_IN_MEGA_HZ * MEGA,
+ (params->pl5_intin << 24) + params->pl5_fracin),
+ params->pl5_refdiv) >> 24;
+ foutpostdiv_rate = DIV_U64_ROUND_CLOSEST(foutvco_rate,
+ params->pl5_postdiv1 * params->pl5_postdiv2);
+
+ return foutpostdiv_rate;
+}
+
+struct dsi_div_hw_data {
+ struct clk_hw hw;
+ u32 conf;
+ unsigned long rate;
+ struct rzg2l_cpg_priv *priv;
+};
+
+#define to_dsi_div_hw_data(_hw) container_of(_hw, struct dsi_div_hw_data, hw)
+
+static unsigned long rzg2l_cpg_dsi_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct dsi_div_hw_data *dsi_div = to_dsi_div_hw_data(hw);
+ unsigned long rate = dsi_div->rate;
+
+ if (!rate)
+ rate = parent_rate;
+
+ return rate;
+}
+
+static unsigned long rzg2l_cpg_get_vclk_parent_rate(struct clk_hw *hw,
+ unsigned long rate)
+{
+ struct dsi_div_hw_data *dsi_div = to_dsi_div_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = dsi_div->priv;
+ struct rzg2l_pll5_param params;
+ unsigned long parent_rate;
+
+ parent_rate = rzg2l_cpg_get_foutpostdiv_rate(priv, &params, rate);
+
+ if (priv->mux_dsi_div_params.clksrc)
+ parent_rate /= 2;
+
+ return parent_rate;
+}
+
+static int rzg2l_cpg_dsi_div_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ if (req->rate > MAX_VCLK_FREQ)
+ req->rate = MAX_VCLK_FREQ;
+
+ req->best_parent_rate = rzg2l_cpg_get_vclk_parent_rate(hw, req->rate);
+
+ if (!req->best_parent_rate)
+ return -EINVAL;
+
+ return 0;
+}
+
+void rzg2l_cpg_dsi_div_set_divider(u8 divider, int target)
+{
+ dsi_div_ab_desired = divider;
+ dsi_div_target = target;
+}
+EXPORT_SYMBOL_GPL(rzg2l_cpg_dsi_div_set_divider);
+
+static int rzg2l_cpg_dsi_div_set_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct dsi_div_hw_data *dsi_div = to_dsi_div_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = dsi_div->priv;
+
+ /*
+ * MUX -->DIV_DSI_{A,B} -->M3 -->VCLK
+ *
+ * Based on the dot clock, the DSI divider clock sets the divider value,
+ * calculates the pll parameters for generating FOUTPOSTDIV and the clk
+ * source for the MUX and propagates that info to the parents.
+ */
+
+ if (!rate || rate > MAX_VCLK_FREQ)
+ return -EINVAL;
+
+ dsi_div->rate = rate;
+ writel(CPG_PL5_SDIV_DIV_DSI_A_WEN | CPG_PL5_SDIV_DIV_DSI_B_WEN |
+ (priv->mux_dsi_div_params.dsi_div_a << 0) |
+ (priv->mux_dsi_div_params.dsi_div_b << 8),
+ priv->base + CPG_PL5_SDIV);
+
+ return 0;
+}
+
+static const struct clk_ops rzg2l_cpg_dsi_div_ops = {
+ .recalc_rate = rzg2l_cpg_dsi_div_recalc_rate,
+ .determine_rate = rzg2l_cpg_dsi_div_determine_rate,
+ .set_rate = rzg2l_cpg_dsi_div_set_rate,
+};
+
+static struct clk * __init
+rzg2l_cpg_dsi_div_clk_register(const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct dsi_div_hw_data *clk_hw_data;
+ const struct clk *parent;
+ const char *parent_name;
+ struct clk_init_data init;
+ struct clk_hw *clk_hw;
+ int ret;
+
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
+ if (!clk_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+ clk_hw_data->priv = priv;
+
+ parent_name = __clk_get_name(parent);
+ init.name = core->name;
+ init.ops = &rzg2l_cpg_dsi_div_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clk_hw = &clk_hw_data->hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return clk_hw->clk;
+}
+
+struct pll5_mux_hw_data {
+ struct clk_hw hw;
+ u32 conf;
+ unsigned long rate;
+ struct rzg2l_cpg_priv *priv;
+};
+
+#define to_pll5_mux_hw_data(_hw) container_of(_hw, struct pll5_mux_hw_data, hw)
+
+static int rzg2l_cpg_pll5_4_clk_mux_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_hw *parent;
+ struct pll5_mux_hw_data *hwdata = to_pll5_mux_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = hwdata->priv;
+
+ parent = clk_hw_get_parent_by_index(hw, priv->mux_dsi_div_params.clksrc);
+ req->best_parent_hw = parent;
+ req->best_parent_rate = req->rate;
+
+ return 0;
+}
+
+static int rzg2l_cpg_pll5_4_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct pll5_mux_hw_data *hwdata = to_pll5_mux_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = hwdata->priv;
+
+ /*
+ * FOUTPOSTDIV--->|
+ * | | -->MUX -->DIV_DSIA_B -->M3 -->VCLK
+ * |--FOUT1PH0-->|
+ *
+ * Based on the dot clock, the DSI divider clock calculates the parent
+ * rate and clk source for the MUX. It propagates that info to
+ * pll5_4_clk_mux which sets the clock source for DSI divider clock.
+ */
+
+ writel(CPG_OTHERFUNC1_REG_RES0_ON_WEN | index,
+ priv->base + CPG_OTHERFUNC1_REG);
+
+ return 0;
+}
+
+static u8 rzg2l_cpg_pll5_4_clk_mux_get_parent(struct clk_hw *hw)
+{
+ struct pll5_mux_hw_data *hwdata = to_pll5_mux_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = hwdata->priv;
+
+ return readl(priv->base + GET_REG_OFFSET(hwdata->conf));
+}
+
+static const struct clk_ops rzg2l_cpg_pll5_4_clk_mux_ops = {
+ .determine_rate = rzg2l_cpg_pll5_4_clk_mux_determine_rate,
+ .set_parent = rzg2l_cpg_pll5_4_clk_mux_set_parent,
+ .get_parent = rzg2l_cpg_pll5_4_clk_mux_get_parent,
+};
+
+static struct clk * __init
+rzg2l_cpg_pll5_4_mux_clk_register(const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct pll5_mux_hw_data *clk_hw_data;
+ struct clk_init_data init;
+ struct clk_hw *clk_hw;
+ int ret;
+
+ clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
+ if (!clk_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+ clk_hw_data->priv = priv;
+ clk_hw_data->conf = core->conf;
+
+ init.name = core->name;
+ init.ops = &rzg2l_cpg_pll5_4_clk_mux_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.num_parents = core->num_parents;
+ init.parent_names = core->parent_names;
+
+ clk_hw = &clk_hw_data->hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return clk_hw->clk;
+}
+
+struct sipll5 {
+ struct clk_hw hw;
+ u32 conf;
+ unsigned long foutpostdiv_rate;
+ struct rzg2l_cpg_priv *priv;
+};
+
+#define to_sipll5(_hw) container_of(_hw, struct sipll5, hw)
+
+static unsigned long rzg2l_cpg_sipll5_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sipll5 *sipll5 = to_sipll5(hw);
+ unsigned long pll5_rate = sipll5->foutpostdiv_rate;
+
+ if (!pll5_rate)
+ pll5_rate = parent_rate;
+
+ return pll5_rate;
+}
+
+static int rzg2l_cpg_sipll5_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return 0;
+}
+
+static int rzg2l_cpg_sipll5_set_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sipll5 *sipll5 = to_sipll5(hw);
+ struct rzg2l_cpg_priv *priv = sipll5->priv;
+ struct rzg2l_pll5_param params;
+ unsigned long vclk_rate;
+ int ret;
+ u32 val;
+
+ /*
+ * OSC --> PLL5 --> FOUTPOSTDIV-->|
+ * | | -->MUX -->DIV_DSIA_B -->M3 -->VCLK
+ * |--FOUT1PH0-->|
+ *
+ * Based on the dot clock, the DSI divider clock calculates the parent
+ * rate and the pll5 parameters for generating FOUTPOSTDIV. It propagates
+ * that info to sipll5 which sets parameters for generating FOUTPOSTDIV.
+ *
+ * OSC --> PLL5 --> FOUTPOSTDIV
+ */
+
+ if (!rate)
+ return -EINVAL;
+
+ vclk_rate = rate / dsi_div_ab_desired;
+ sipll5->foutpostdiv_rate =
+ rzg2l_cpg_get_foutpostdiv_rate(priv, &params, vclk_rate);
+
+ /* Put PLL5 into standby mode */
+ writel(CPG_SIPLL5_STBY_RESETB_WEN, priv->base + CPG_SIPLL5_STBY);
+ ret = readl_poll_timeout(priv->base + CPG_SIPLL5_MON, val,
+ !(val & CPG_SIPLL5_MON_PLL5_LOCK), 100, 250000);
+ if (ret) {
+ dev_err(priv->dev, "failed to release pll5 lock\n");
+ return ret;
+ }
+
+ /* Output clock setting 1 */
+ writel((params.pl5_postdiv1 << 0) | (params.pl5_postdiv2 << 4) |
+ (params.pl5_refdiv << 8), priv->base + CPG_SIPLL5_CLK1);
+
+ /* Output clock setting, SSCG modulation value setting 3 */
+ writel((params.pl5_fracin << 8), priv->base + CPG_SIPLL5_CLK3);
+
+ /* Output clock setting 4 */
+ writel(CPG_SIPLL5_CLK4_RESV_LSB | (params.pl5_intin << 16),
+ priv->base + CPG_SIPLL5_CLK4);
+
+ /* Output clock setting 5 */
+ writel(params.pl5_spread, priv->base + CPG_SIPLL5_CLK5);
+
+ /* PLL normal mode setting */
+ writel(CPG_SIPLL5_STBY_DOWNSPREAD_WEN | CPG_SIPLL5_STBY_SSCG_EN_WEN |
+ CPG_SIPLL5_STBY_RESETB_WEN | CPG_SIPLL5_STBY_RESETB,
+ priv->base + CPG_SIPLL5_STBY);
+
+ /* PLL normal mode transition, output clock stability check */
+ ret = readl_poll_timeout(priv->base + CPG_SIPLL5_MON, val,
+ (val & CPG_SIPLL5_MON_PLL5_LOCK), 100, 250000);
+ if (ret) {
+ dev_err(priv->dev, "failed to lock pll5\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct clk_ops rzg2l_cpg_sipll5_ops = {
+ .recalc_rate = rzg2l_cpg_sipll5_recalc_rate,
+ .determine_rate = rzg2l_cpg_sipll5_determine_rate,
+ .set_rate = rzg2l_cpg_sipll5_set_rate,
+};
+
+static struct clk * __init
+rzg2l_cpg_sipll5_register(const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv)
+{
+ const struct clk *parent;
+ struct clk_init_data init;
+ const char *parent_name;
+ struct sipll5 *sipll5;
+ struct clk_hw *clk_hw;
+ int ret;
+
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ sipll5 = devm_kzalloc(priv->dev, sizeof(*sipll5), GFP_KERNEL);
+ if (!sipll5)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = core->name;
+ parent_name = __clk_get_name(parent);
+ init.ops = &rzg2l_cpg_sipll5_ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ sipll5->hw.init = &init;
+ sipll5->conf = core->conf;
+ sipll5->priv = priv;
+
+ writel(CPG_SIPLL5_STBY_SSCG_EN_WEN | CPG_SIPLL5_STBY_RESETB_WEN |
+ CPG_SIPLL5_STBY_RESETB, priv->base + CPG_SIPLL5_STBY);
+
+ clk_hw = &sipll5->hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ rzg2l_cpg_dsi_div_set_divider(8, PLL5_TARGET_DPI);
+
+ return clk_hw->clk;
+}
+
+struct pll_clk {
+ struct clk_hw hw;
+ unsigned long default_rate;
+ unsigned int conf;
+ unsigned int type;
+ void __iomem *base;
+ struct rzg2l_cpg_priv *priv;
+};
+
+#define to_pll(_hw) container_of(_hw, struct pll_clk, hw)
+
+static unsigned long rzg2l_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzg2l_cpg_priv *priv = pll_clk->priv;
+ unsigned int val1, val2;
+ u64 rate;
+
+ if (pll_clk->type != CLK_TYPE_SAM_PLL)
+ return parent_rate;
+
+ val1 = readl(priv->base + CPG_PLL_CLK1_OFFSET(pll_clk->conf));
+ val2 = readl(priv->base + CPG_PLL_CLK2_OFFSET(pll_clk->conf));
+
+ rate = mul_u64_u32_shr(parent_rate, (MDIV(val1) << 16) + KDIV(val1),
+ 16 + SDIV(val2));
+
+ return DIV_ROUND_CLOSEST_ULL(rate, PDIV(val1));
+}
+
+static const struct clk_ops rzg2l_cpg_pll_ops = {
+ .recalc_rate = rzg2l_cpg_pll_clk_recalc_rate,
+};
+
+static unsigned long rzg3s_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzg2l_cpg_priv *priv = pll_clk->priv;
+ u32 nir, nfr, mr, pr, val, setting;
+ u64 rate;
+
+ setting = CPG_PLL1_SETTING_OFFSET(pll_clk->conf);
+ if (setting) {
+ val = readl(priv->base + setting);
+ if (val & RZG3S_SEL_PLL)
+ return pll_clk->default_rate;
+ }
+
+ val = readl(priv->base + CPG_PLL_CLK1_OFFSET(pll_clk->conf));
+
+ pr = 1 << FIELD_GET(RZG3S_DIV_P, val);
+ /* Hardware interprets values higher than 8 as p = 16. */
+ if (pr > 8)
+ pr = 16;
+
+ mr = FIELD_GET(RZG3S_DIV_M, val) + 1;
+ nir = FIELD_GET(RZG3S_DIV_NI, val) + 1;
+ nfr = FIELD_GET(RZG3S_DIV_NF, val);
+
+ rate = mul_u64_u32_shr(parent_rate, 4096 * nir + nfr, 12);
+
+ return DIV_ROUND_CLOSEST_ULL(rate, (mr * pr));
+}
+
+static const struct clk_ops rzg3s_cpg_pll_ops = {
+ .recalc_rate = rzg3s_cpg_pll_clk_recalc_rate,
+};
+
+static struct clk * __init
+rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv,
+ const struct clk_ops *ops)
+{
+ struct device *dev = priv->dev;
+ const struct clk *parent;
+ struct clk_init_data init;
+ const char *parent_name;
+ struct pll_clk *pll_clk;
+ int ret;
+
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL);
+ if (!pll_clk)
+ return ERR_PTR(-ENOMEM);
+
+ parent_name = __clk_get_name(parent);
+ init.name = core->name;
+ init.ops = ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pll_clk->hw.init = &init;
+ pll_clk->conf = core->conf;
+ pll_clk->base = priv->base;
+ pll_clk->priv = priv;
+ pll_clk->type = core->type;
+ pll_clk->default_rate = core->default_rate;
+
+ ret = devm_clk_hw_register(dev, &pll_clk->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return pll_clk->hw.clk;
+}
+
+static int rzg3l_cpg_pll_clk_is_enabled(struct clk_hw *hw)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzg2l_cpg_priv *priv = pll_clk->priv;
+ u32 val = readl(priv->base + CPG_PLL_MON_OFFSET(pll_clk->conf));
+ u32 mon_val = CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK;
+
+ /* Ensure both RESETB and LOCK bits are set */
+ return (mon_val == (val & mon_val));
+}
+
+static int rzg3l_cpg_pll_clk_endisable(struct clk_hw *hw, bool enable)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzg2l_cpg_priv *priv = pll_clk->priv;
+ u32 mon_mask = CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK;
+ u32 val = CPG_PLL_STBY_RESETB_WEN;
+ u32 stby_offset, mon_offset;
+ u32 mon_val = 0;
+ int ret;
+
+ stby_offset = CPG_PLL_STBY_OFFSET(pll_clk->conf);
+ mon_offset = CPG_PLL_MON_OFFSET(pll_clk->conf);
+
+ if (enable) {
+ val |= CPG_PLL_STBY_RESETB;
+ mon_val = mon_mask;
+ }
+
+ writel(val, priv->base + stby_offset);
+
+ /* ensure PLL is in normal/standby mode */
+ ret = readl_poll_timeout_atomic(priv->base + mon_offset, val,
+ mon_val == (val & mon_mask), 10, 100);
+ if (ret)
+ dev_err(priv->dev, "Failed to %s PLL 0x%x/%pC\n", enable ?
+ "enable" : "disable", stby_offset, hw->clk);
+
+ return ret;
+}
+
+static int rzg3l_cpg_pll_clk_enable(struct clk_hw *hw)
+{
+ if (rzg3l_cpg_pll_clk_is_enabled(hw))
+ return 0;
+
+ return rzg3l_cpg_pll_clk_endisable(hw, true);
+}
+
+static const struct clk_ops rzg3l_cpg_pll_ops = {
+ .is_enabled = rzg3l_cpg_pll_clk_is_enabled,
+ .enable = rzg3l_cpg_pll_clk_enable,
+ .recalc_rate = rzg3s_cpg_pll_clk_recalc_rate,
+};
+
+static struct clk
+*rzg2l_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec,
+ void *data)
+{
+ unsigned int clkidx = clkspec->args[1];
+ struct rzg2l_cpg_priv *priv = data;
+ struct device *dev = priv->dev;
+ const char *type;
+ struct clk *clk;
+
+ switch (clkspec->args[0]) {
+ case CPG_CORE:
+ type = "core";
+ if (clkidx > priv->last_dt_core_clk) {
+ dev_err(dev, "Invalid %s clock index %u\n", type, clkidx);
+ return ERR_PTR(-EINVAL);
+ }
+ clk = priv->clks[clkidx];
+ break;
+
+ case CPG_MOD:
+ type = "module";
+ if (clkidx >= priv->num_mod_clks) {
+ dev_err(dev, "Invalid %s clock index %u\n", type,
+ clkidx);
+ return ERR_PTR(-EINVAL);
+ }
+ clk = priv->clks[priv->num_core_clks + clkidx];
+ break;
+
+ default:
+ dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (IS_ERR(clk))
+ dev_err(dev, "Cannot get %s clock %u: %ld\n", type, clkidx,
+ PTR_ERR(clk));
+ else
+ dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n",
+ clkspec->args[0], clkspec->args[1], clk,
+ clk_get_rate(clk));
+ return clk;
+}
+
+static void __init
+rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
+ const struct rzg2l_cpg_info *info,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct clk *clk = ERR_PTR(-EOPNOTSUPP), *parent;
+ struct device *dev = priv->dev;
+ unsigned int id = core->id, div = core->div;
+ const char *parent_name;
+ struct clk_hw *clk_hw;
+
+ WARN_DEBUG(id >= priv->num_core_clks);
+ WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
+
+ switch (core->type) {
+ case CLK_TYPE_IN:
+ clk = of_clk_get_by_name(priv->dev->of_node, core->name);
+ break;
+ case CLK_TYPE_FF:
+ WARN_DEBUG(core->parent >= priv->num_core_clks);
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent)) {
+ clk = parent;
+ goto fail;
+ }
+
+ parent_name = __clk_get_name(parent);
+ clk_hw = devm_clk_hw_register_fixed_factor(dev, core->name, parent_name,
+ CLK_SET_RATE_PARENT,
+ core->mult, div);
+ if (IS_ERR(clk_hw))
+ clk = ERR_CAST(clk_hw);
+ else
+ clk = clk_hw->clk;
+ break;
+ case CLK_TYPE_SAM_PLL:
+ clk = rzg2l_cpg_pll_clk_register(core, priv, &rzg2l_cpg_pll_ops);
+ break;
+ case CLK_TYPE_G3L_PLL:
+ clk = rzg2l_cpg_pll_clk_register(core, priv, &rzg3l_cpg_pll_ops);
+ break;
+ case CLK_TYPE_G3S_PLL:
+ clk = rzg2l_cpg_pll_clk_register(core, priv, &rzg3s_cpg_pll_ops);
+ break;
+ case CLK_TYPE_SIPLL5:
+ clk = rzg2l_cpg_sipll5_register(core, priv);
+ break;
+ case CLK_TYPE_DIV:
+ clk = rzg2l_cpg_div_clk_register(core, priv);
+ break;
+ case CLK_TYPE_G3S_DIV:
+ clk = rzg3s_cpg_div_clk_register(core, priv);
+ break;
+ case CLK_TYPE_MUX:
+ clk = rzg2l_cpg_mux_clk_register(core, priv);
+ break;
+ case CLK_TYPE_SD_MUX:
+ clk = rzg2l_cpg_sd_mux_clk_register(core, priv);
+ break;
+ case CLK_TYPE_PLL5_4_MUX:
+ clk = rzg2l_cpg_pll5_4_mux_clk_register(core, priv);
+ break;
+ case CLK_TYPE_DSI_DIV:
+ clk = rzg2l_cpg_dsi_div_clk_register(core, priv);
+ break;
+ default:
+ goto fail;
+ }
+
+ if (IS_ERR(clk))
+ goto fail;
+
+ dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
+ priv->clks[id] = clk;
+ return;
+
+fail:
+ dev_err(dev, "Failed to register %s clock %s: %ld\n", "core",
+ core->name, PTR_ERR(clk));
+}
+
+/**
+ * struct mstop - MSTOP specific data structure
+ * @usecnt: Usage counter for MSTOP settings (when zero the settings
+ * are applied to register)
+ * @conf: MSTOP configuration (register offset, setup bits)
+ */
+struct mstop {
+ atomic_t usecnt;
+ u32 conf;
+};
+
+/**
+ * struct mod_clock - Module clock
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ * @priv: CPG/MSTP private data
+ * @sibling: pointer to the other coupled clock
+ * @mstop: MSTOP configuration
+ * @shared_mstop_clks: clocks sharing the MSTOP with this clock
+ * @off: register offset
+ * @bit: ON/MON bit
+ * @num_shared_mstop_clks: number of the clocks sharing MSTOP with this clock
+ * @enabled: soft state of the clock, if it is coupled with another clock
+ */
+struct mod_clock {
+ struct clk_hw hw;
+ struct rzg2l_cpg_priv *priv;
+ struct mod_clock *sibling;
+ struct mstop *mstop;
+ struct mod_clock **shared_mstop_clks;
+ u16 off;
+ u8 bit;
+ u8 num_shared_mstop_clks;
+ bool enabled;
+};
+
+#define to_mod_clock(_hw) container_of(_hw, struct mod_clock, hw)
+
+#define for_each_mod_clock(mod_clock, hw, priv) \
+ for (unsigned int __i = 0; (priv) && __i < (priv)->num_mod_clks; __i++) \
+ if ((priv)->clks[(priv)->num_core_clks + __i] == ERR_PTR(-ENOENT)) \
+ continue; \
+ else if (((hw) = __clk_get_hw((priv)->clks[(priv)->num_core_clks + __i])) && \
+ ((mod_clock) = to_mod_clock(hw)))
+
+/* Need to be called with a lock held to avoid concurrent access to mstop->usecnt. */
+static void rzg2l_mod_clock_module_set_state(struct mod_clock *clock,
+ bool standby)
+{
+ struct rzg2l_cpg_priv *priv = clock->priv;
+ struct mstop *mstop = clock->mstop;
+ bool update = false;
+ u32 value;
+
+ if (!mstop)
+ return;
+
+ value = MSTOP_MASK(mstop->conf) << 16;
+
+ if (standby) {
+ unsigned int criticals = 0;
+
+ for (unsigned int i = 0; i < clock->num_shared_mstop_clks; i++) {
+ struct mod_clock *clk = clock->shared_mstop_clks[i];
+
+ if (clk_hw_get_flags(&clk->hw) & CLK_IS_CRITICAL)
+ criticals++;
+ }
+
+ if (!clock->num_shared_mstop_clks &&
+ clk_hw_get_flags(&clock->hw) & CLK_IS_CRITICAL)
+ criticals++;
+
+ /*
+ * If this is a shared MSTOP and it is shared with critical clocks,
+ * and the system boots up with this clock enabled but no driver
+ * uses it the CCF will disable it (as it is unused). As we don't
+ * increment reference counter for it at registration (to avoid
+ * messing with clocks enabled at probe but later used by drivers)
+ * do not set the MSTOP here too if it is shared with critical
+ * clocks and ref counted only by those critical clocks.
+ */
+ if (criticals && criticals == atomic_read(&mstop->usecnt))
+ return;
+
+ value |= MSTOP_MASK(mstop->conf);
+
+ /* Allow updates on probe when usecnt = 0. */
+ if (!atomic_read(&mstop->usecnt))
+ update = true;
+ else
+ update = atomic_dec_and_test(&mstop->usecnt);
+ } else {
+ if (!atomic_read(&mstop->usecnt))
+ update = true;
+ atomic_inc(&mstop->usecnt);
+ }
+
+ if (update)
+ writel(value, priv->base + MSTOP_OFF(mstop->conf));
+}
+
+static int rzg2l_mod_clock_mstop_show(struct seq_file *s, void *what)
+{
+ struct rzg2l_cpg_priv *priv = s->private;
+ struct mod_clock *clk;
+ struct clk_hw *hw;
+
+ seq_printf(s, "%-20s %-5s %-10s\n", "", "", "MSTOP");
+ seq_printf(s, "%-20s %-5s %-10s\n", "", "clk", "-------------------------");
+ seq_printf(s, "%-20s %-5s %-5s %-5s %-6s %-6s\n",
+ "clk_name", "cnt", "cnt", "off", "val", "shared");
+ seq_printf(s, "%-20s %-5s %-5s %-5s %-6s %-6s\n",
+ "--------", "-----", "-----", "-----", "------", "------");
+
+ for_each_mod_clock(clk, hw, priv) {
+ u32 val;
+
+ if (!clk->mstop)
+ continue;
+
+ val = readl(priv->base + MSTOP_OFF(clk->mstop->conf)) &
+ MSTOP_MASK(clk->mstop->conf);
+
+ seq_printf(s, "%-20s %-5d %-5d 0x%-3lx 0x%-4x", clk_hw_get_name(hw),
+ __clk_get_enable_count(hw->clk), atomic_read(&clk->mstop->usecnt),
+ MSTOP_OFF(clk->mstop->conf), val);
+
+ for (unsigned int i = 0; i < clk->num_shared_mstop_clks; i++)
+ seq_printf(s, " %pC", clk->shared_mstop_clks[i]->hw.clk);
+
+ seq_puts(s, "\n");
+ }
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(rzg2l_mod_clock_mstop);
+
+static int rzg2l_mod_clock_endisable_helper(struct clk_hw *hw, bool enable,
+ bool set_mstop_state)
+{
+ struct mod_clock *clock = to_mod_clock(hw);
+ struct rzg2l_cpg_priv *priv = clock->priv;
+ unsigned int reg = clock->off;
+ struct device *dev = priv->dev;
+ u32 bitmask = BIT(clock->bit);
+ u32 value;
+ int error;
+
+ if (!clock->off) {
+ dev_dbg(dev, "%pC does not support ON/OFF\n", hw->clk);
+ return 0;
+ }
+
+ dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", CLK_ON_R(reg), hw->clk,
+ str_on_off(enable));
+
+ value = bitmask << 16;
+ if (enable)
+ value |= bitmask;
+
+ scoped_guard(spinlock_irqsave, &priv->rmw_lock) {
+ if (enable) {
+ writel(value, priv->base + CLK_ON_R(reg));
+ if (set_mstop_state)
+ rzg2l_mod_clock_module_set_state(clock, false);
+ } else {
+ if (set_mstop_state)
+ rzg2l_mod_clock_module_set_state(clock, true);
+ writel(value, priv->base + CLK_ON_R(reg));
+ }
+ }
+
+ if (!enable)
+ return 0;
+
+ if (!priv->info->has_clk_mon_regs)
+ return 0;
+
+ error = readl_poll_timeout_atomic(priv->base + CLK_MON_R(reg), value,
+ value & bitmask, 0, 10);
+ if (error)
+ dev_err(dev, "Failed to enable CLK_ON 0x%x/%pC\n",
+ CLK_ON_R(reg), hw->clk);
+
+ return error;
+}
+
+static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable)
+{
+ return rzg2l_mod_clock_endisable_helper(hw, enable, true);
+}
+
+static int rzg2l_mod_clock_enable(struct clk_hw *hw)
+{
+ struct mod_clock *clock = to_mod_clock(hw);
+
+ if (clock->sibling) {
+ struct rzg2l_cpg_priv *priv = clock->priv;
+ unsigned long flags;
+ bool enabled;
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+ enabled = clock->sibling->enabled;
+ clock->enabled = true;
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+ if (enabled)
+ return 0;
+ }
+
+ return rzg2l_mod_clock_endisable(hw, true);
+}
+
+static void rzg2l_mod_clock_disable(struct clk_hw *hw)
+{
+ struct mod_clock *clock = to_mod_clock(hw);
+
+ if (clock->sibling) {
+ struct rzg2l_cpg_priv *priv = clock->priv;
+ unsigned long flags;
+ bool enabled;
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+ enabled = clock->sibling->enabled;
+ clock->enabled = false;
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+ if (enabled)
+ return;
+ }
+
+ rzg2l_mod_clock_endisable(hw, false);
+}
+
+static int rzg2l_mod_clock_is_enabled(struct clk_hw *hw)
+{
+ struct mod_clock *clock = to_mod_clock(hw);
+ struct rzg2l_cpg_priv *priv = clock->priv;
+ u32 bitmask = BIT(clock->bit);
+ u32 value;
+
+ if (!clock->off) {
+ dev_dbg(priv->dev, "%pC does not support ON/OFF\n", hw->clk);
+ return 1;
+ }
+
+ if (clock->sibling)
+ return clock->enabled;
+
+ if (priv->info->has_clk_mon_regs)
+ value = readl(priv->base + CLK_MON_R(clock->off));
+ else
+ value = readl(priv->base + clock->off);
+
+ return value & bitmask;
+}
+
+static const struct clk_ops rzg2l_mod_clock_ops = {
+ .enable = rzg2l_mod_clock_enable,
+ .disable = rzg2l_mod_clock_disable,
+ .is_enabled = rzg2l_mod_clock_is_enabled,
+};
+
+static struct mod_clock
+*rzg2l_mod_clock_get_sibling(struct mod_clock *clock,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct mod_clock *clk;
+ struct clk_hw *hw;
+
+ for_each_mod_clock(clk, hw, priv) {
+ if (clock->off == clk->off && clock->bit == clk->bit)
+ return clk;
+ }
+
+ return NULL;
+}
+
+static struct mstop *rzg2l_mod_clock_get_mstop(struct rzg2l_cpg_priv *priv, u32 conf)
+{
+ struct mod_clock *clk;
+ struct clk_hw *hw;
+
+ for_each_mod_clock(clk, hw, priv) {
+ if (!clk->mstop)
+ continue;
+
+ if (clk->mstop->conf == conf)
+ return clk->mstop;
+ }
+
+ return NULL;
+}
+
+static void rzg2l_mod_clock_init_mstop_helper(struct rzg2l_cpg_priv *priv,
+ struct mod_clock *clk)
+{
+ /*
+ * Out of reset all modules are enabled. Set module state in case
+ * associated clocks are disabled at probe/resume. Otherwise module
+ * is in invalid HW state.
+ */
+ scoped_guard(spinlock_irqsave, &priv->rmw_lock) {
+ if (!rzg2l_mod_clock_is_enabled(&clk->hw))
+ rzg2l_mod_clock_module_set_state(clk, true);
+ }
+}
+
+static void rzg2l_mod_enable_crit_clock_init_mstop(struct rzg2l_cpg_priv *priv)
+{
+ struct mod_clock *clk;
+ struct clk_hw *hw;
+
+ for_each_mod_clock(clk, hw, priv) {
+ if ((clk_hw_get_flags(&clk->hw) & CLK_IS_CRITICAL) &&
+ (!rzg2l_mod_clock_is_enabled(&clk->hw)))
+ rzg2l_mod_clock_endisable_helper(&clk->hw, true, false);
+
+ if (clk->mstop)
+ rzg2l_mod_clock_init_mstop_helper(priv, clk);
+ }
+}
+
+static void rzg2l_mod_clock_init_mstop(struct rzg2l_cpg_priv *priv)
+{
+ struct mod_clock *clk;
+ struct clk_hw *hw;
+
+ for_each_mod_clock(clk, hw, priv) {
+ if (!clk->mstop)
+ continue;
+
+ rzg2l_mod_clock_init_mstop_helper(priv, clk);
+ }
+}
+
+static int rzg2l_mod_clock_update_shared_mstop_clks(struct rzg2l_cpg_priv *priv,
+ struct mod_clock *clock)
+{
+ struct mod_clock *clk;
+ struct clk_hw *hw;
+
+ if (!clock->mstop)
+ return 0;
+
+ for_each_mod_clock(clk, hw, priv) {
+ int num_shared_mstop_clks, incr = 1;
+ struct mod_clock **new_clks;
+
+ if (clk->mstop != clock->mstop)
+ continue;
+
+ num_shared_mstop_clks = clk->num_shared_mstop_clks;
+ if (!num_shared_mstop_clks)
+ incr++;
+
+ new_clks = devm_krealloc(priv->dev, clk->shared_mstop_clks,
+ (num_shared_mstop_clks + incr) * sizeof(*new_clks),
+ GFP_KERNEL);
+ if (!new_clks)
+ return -ENOMEM;
+
+ if (!num_shared_mstop_clks)
+ new_clks[num_shared_mstop_clks++] = clk;
+ new_clks[num_shared_mstop_clks++] = clock;
+
+ for (unsigned int i = 0; i < num_shared_mstop_clks; i++) {
+ new_clks[i]->shared_mstop_clks = new_clks;
+ new_clks[i]->num_shared_mstop_clks = num_shared_mstop_clks;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static void __init
+rzg2l_cpg_register_mod_clk(const struct rzg2l_mod_clk *mod,
+ const struct rzg2l_cpg_info *info,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct mod_clock *clock = NULL;
+ struct device *dev = priv->dev;
+ unsigned int id = mod->id;
+ struct clk_init_data init;
+ struct clk *parent, *clk;
+ const char *parent_name;
+ unsigned int i;
+ int ret;
+
+ WARN_DEBUG(id < priv->num_core_clks);
+ WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks);
+ WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
+ WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
+
+ parent = priv->clks[mod->parent];
+ if (IS_ERR(parent)) {
+ clk = parent;
+ goto fail;
+ }
+
+ clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL);
+ if (!clock) {
+ clk = ERR_PTR(-ENOMEM);
+ goto fail;
+ }
+
+ init.name = mod->name;
+ init.ops = &rzg2l_mod_clock_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ for (i = 0; i < info->num_crit_mod_clks; i++)
+ if (id == info->crit_mod_clks[i]) {
+ dev_dbg(dev, "CPG %s setting CLK_IS_CRITICAL\n",
+ mod->name);
+ init.flags |= CLK_IS_CRITICAL;
+ break;
+ }
+
+ parent_name = __clk_get_name(parent);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clock->off = mod->off;
+ clock->bit = mod->bit;
+ clock->priv = priv;
+ clock->hw.init = &init;
+
+ if (mod->mstop_conf) {
+ struct mstop *mstop = rzg2l_mod_clock_get_mstop(priv, mod->mstop_conf);
+
+ if (!mstop) {
+ mstop = devm_kzalloc(dev, sizeof(*mstop), GFP_KERNEL);
+ if (!mstop) {
+ clk = ERR_PTR(-ENOMEM);
+ goto fail;
+ }
+ mstop->conf = mod->mstop_conf;
+ atomic_set(&mstop->usecnt, 0);
+ }
+ clock->mstop = mstop;
+ }
+
+ ret = devm_clk_hw_register(dev, &clock->hw);
+ if (ret) {
+ clk = ERR_PTR(ret);
+ goto fail;
+ }
+
+ if (mod->is_coupled) {
+ struct mod_clock *sibling;
+
+ clock->enabled = rzg2l_mod_clock_is_enabled(&clock->hw);
+ sibling = rzg2l_mod_clock_get_sibling(clock, priv);
+ if (sibling) {
+ clock->sibling = sibling;
+ sibling->sibling = clock;
+ }
+ }
+
+ /* Keep this before priv->clks[id] is updated. */
+ ret = rzg2l_mod_clock_update_shared_mstop_clks(priv, clock);
+ if (ret) {
+ clk = ERR_PTR(ret);
+ goto fail;
+ }
+
+ clk = clock->hw.clk;
+ dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
+ priv->clks[id] = clk;
+
+ return;
+
+fail:
+ dev_err(dev, "Failed to register %s clock %s: %ld\n", "module",
+ mod->name, PTR_ERR(clk));
+}
+
+#define rcdev_to_priv(x) container_of(x, struct rzg2l_cpg_priv, rcdev)
+
+static int __rzg2l_cpg_assert(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev);
+ const struct rzg2l_cpg_info *info = priv->info;
+ unsigned int reg = info->resets[id].off;
+ u32 mask = BIT(info->resets[id].bit);
+ s8 monbit = info->resets[id].monbit;
+ u32 value = mask << 16;
+ u32 mon;
+ int ret;
+
+ dev_dbg(rcdev->dev, "%s id:%ld offset:0x%x\n",
+ assert ? "assert" : "deassert", id, CLK_RST_R(reg));
+
+ if (assert) {
+ for (unsigned int i = 0; i < priv->info->num_crit_resets; i++) {
+ if (id == priv->info->crit_resets[i])
+ return 0;
+ }
+ }
+
+ if (!assert)
+ value |= mask;
+ writel(value, priv->base + CLK_RST_R(reg));
+
+ if (info->has_clk_mon_regs) {
+ reg = CLK_MRST_R(reg);
+ } else if (monbit >= 0) {
+ reg = CPG_RST_MON;
+ mask = BIT(monbit);
+ } else {
+ /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
+ udelay(35);
+ return 0;
+ }
+
+ ret = readl_poll_timeout_atomic(priv->base + reg, mon,
+ assert == !!(mon & mask), 10, 200);
+ if (ret) {
+ value ^= mask;
+ writel(value, priv->base + CLK_RST_R(info->resets[id].off));
+ }
+
+ return ret;
+}
+
+static int rzg2l_cpg_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return __rzg2l_cpg_assert(rcdev, id, true);
+}
+
+static int rzg2l_cpg_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return __rzg2l_cpg_assert(rcdev, id, false);
+}
+
+static int rzg2l_cpg_deassert_crit_resets(struct reset_controller_dev *rcdev,
+ const struct rzg2l_cpg_info *info)
+{
+ int ret;
+
+ for (unsigned int i = 0; i < info->num_crit_resets; i++) {
+ ret = rzg2l_cpg_deassert(rcdev, info->crit_resets[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rzg2l_cpg_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ int ret;
+
+ ret = rzg2l_cpg_assert(rcdev, id);
+ if (ret)
+ return ret;
+
+ return rzg2l_cpg_deassert(rcdev, id);
+}
+
+static int rzg2l_cpg_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev);
+ const struct rzg2l_cpg_info *info = priv->info;
+ s8 monbit = info->resets[id].monbit;
+ unsigned int reg;
+ u32 bitmask;
+
+ if (info->has_clk_mon_regs) {
+ reg = CLK_MRST_R(info->resets[id].off);
+ bitmask = BIT(info->resets[id].bit);
+ } else if (monbit >= 0) {
+ reg = CPG_RST_MON;
+ bitmask = BIT(monbit);
+ } else {
+ return -ENOTSUPP;
+ }
+
+ return !!(readl(priv->base + reg) & bitmask);
+}
+
+static const struct reset_control_ops rzg2l_cpg_reset_ops = {
+ .reset = rzg2l_cpg_reset,
+ .assert = rzg2l_cpg_assert,
+ .deassert = rzg2l_cpg_deassert,
+ .status = rzg2l_cpg_status,
+};
+
+static int rzg2l_cpg_reset_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev);
+ const struct rzg2l_cpg_info *info = priv->info;
+ unsigned int id = reset_spec->args[0];
+
+ if (id >= rcdev->nr_resets || !info->resets[id].off) {
+ dev_err(rcdev->dev, "Invalid reset index %u\n", id);
+ return -EINVAL;
+ }
+
+ return id;
+}
+
+static int rzg2l_cpg_reset_controller_register(struct rzg2l_cpg_priv *priv)
+{
+ priv->rcdev.ops = &rzg2l_cpg_reset_ops;
+ priv->rcdev.of_node = priv->dev->of_node;
+ priv->rcdev.dev = priv->dev;
+ priv->rcdev.of_reset_n_cells = 1;
+ priv->rcdev.of_xlate = rzg2l_cpg_reset_xlate;
+ priv->rcdev.nr_resets = priv->num_resets;
+
+ return devm_reset_controller_register(priv->dev, &priv->rcdev);
+}
+
+static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_priv *priv,
+ const struct of_phandle_args *clkspec)
+{
+ if (clkspec->np != priv->genpd.dev.of_node || clkspec->args_count != 2)
+ return false;
+
+ switch (clkspec->args[0]) {
+ case CPG_MOD: {
+ const struct rzg2l_cpg_info *info = priv->info;
+ unsigned int id = clkspec->args[1];
+
+ if (id >= priv->num_mod_clks)
+ return false;
+
+ id += info->num_total_core_clks;
+
+ for (unsigned int i = 0; i < info->num_no_pm_mod_clks; i++) {
+ if (info->no_pm_mod_clks[i] == id)
+ return false;
+ }
+
+ return true;
+ }
+
+ case CPG_CORE:
+ default:
+ return false;
+ }
+}
+
+static int rzg2l_cpg_attach_dev(struct generic_pm_domain *domain, struct device *dev)
+{
+ struct rzg2l_cpg_priv *priv = container_of(domain, struct rzg2l_cpg_priv, genpd);
+ struct device_node *np = dev->of_node;
+ struct of_phandle_args clkspec;
+ bool once = true;
+ struct clk *clk;
+ unsigned int i;
+ int error;
+
+ for (i = 0; !of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, &clkspec); i++) {
+ if (!rzg2l_cpg_is_pm_clk(priv, &clkspec)) {
+ of_node_put(clkspec.np);
+ continue;
+ }
+
+ if (once) {
+ once = false;
+ error = pm_clk_create(dev);
+ if (error) {
+ of_node_put(clkspec.np);
+ goto err;
+ }
+ }
+ clk = of_clk_get_from_provider(&clkspec);
+ of_node_put(clkspec.np);
+ if (IS_ERR(clk)) {
+ error = PTR_ERR(clk);
+ goto fail_destroy;
+ }
+
+ error = pm_clk_add_clk(dev, clk);
+ if (error) {
+ dev_err(dev, "pm_clk_add_clk failed %d\n", error);
+ goto fail_put;
+ }
+ }
+
+ return 0;
+
+fail_put:
+ clk_put(clk);
+
+fail_destroy:
+ pm_clk_destroy(dev);
+err:
+ return error;
+}
+
+static void rzg2l_cpg_detach_dev(struct generic_pm_domain *unused, struct device *dev)
+{
+ if (!pm_clk_no_clocks(dev))
+ pm_clk_destroy(dev);
+}
+
+static void rzg2l_cpg_genpd_remove(void *data)
+{
+ pm_genpd_remove(data);
+}
+
+static int __init rzg2l_cpg_add_clk_domain(struct rzg2l_cpg_priv *priv)
+{
+ struct device *dev = priv->dev;
+ struct device_node *np = dev->of_node;
+ struct generic_pm_domain *genpd = &priv->genpd;
+ int ret;
+
+ genpd->name = np->name;
+ genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON |
+ GENPD_FLAG_ACTIVE_WAKEUP;
+ genpd->attach_dev = rzg2l_cpg_attach_dev;
+ genpd->detach_dev = rzg2l_cpg_detach_dev;
+ ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, rzg2l_cpg_genpd_remove, genpd);
+ if (ret)
+ return ret;
+
+ return of_genpd_add_provider_simple(np, genpd);
+}
+
+static int __init rzg2l_cpg_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct rzg2l_cpg_info *info;
+ struct rzg2l_cpg_priv *priv;
+ unsigned int nclks, i;
+ struct clk **clks;
+ int error;
+
+ info = of_device_get_match_data(dev);
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ priv->info = info;
+ spin_lock_init(&priv->rmw_lock);
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ nclks = info->num_total_core_clks + info->num_hw_mod_clks;
+ clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL);
+ if (!clks)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, priv);
+ priv->clks = clks;
+ priv->num_core_clks = info->num_total_core_clks;
+ priv->num_mod_clks = info->num_hw_mod_clks;
+ priv->num_resets = info->num_resets;
+ priv->last_dt_core_clk = info->last_dt_core_clk;
+
+ for (i = 0; i < nclks; i++)
+ clks[i] = ERR_PTR(-ENOENT);
+
+ for (i = 0; i < info->num_core_clks; i++)
+ rzg2l_cpg_register_core_clk(&info->core_clks[i], info, priv);
+
+ for (i = 0; i < info->num_mod_clks; i++)
+ rzg2l_cpg_register_mod_clk(&info->mod_clks[i], info, priv);
+
+ /*
+ * Initialize MSTOP after all the clocks were registered to avoid
+ * invalid reference counting when multiple clocks (critical,
+ * non-critical) share the same MSTOP.
+ */
+ rzg2l_mod_clock_init_mstop(priv);
+
+ error = of_clk_add_provider(np, rzg2l_cpg_clk_src_twocell_get, priv);
+ if (error)
+ return error;
+
+ error = devm_add_action_or_reset(dev, rzg2l_cpg_del_clk_provider, np);
+ if (error)
+ return error;
+
+ error = rzg2l_cpg_add_clk_domain(priv);
+ if (error)
+ return error;
+
+ error = rzg2l_cpg_reset_controller_register(priv);
+ if (error)
+ return error;
+
+ error = rzg2l_cpg_deassert_crit_resets(&priv->rcdev, info);
+ if (error)
+ return error;
+
+ debugfs_create_file("mstop", 0444, NULL, priv, &rzg2l_mod_clock_mstop_fops);
+ return 0;
+}
+
+static int rzg2l_cpg_resume(struct device *dev)
+{
+ struct rzg2l_cpg_priv *priv = dev_get_drvdata(dev);
+ int ret;
+
+ ret = rzg2l_cpg_deassert_crit_resets(&priv->rcdev, priv->info);
+ if (ret)
+ return ret;
+
+ rzg2l_mod_enable_crit_clock_init_mstop(priv);
+
+ return 0;
+}
+
+static const struct dev_pm_ops rzg2l_cpg_pm_ops = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, rzg2l_cpg_resume)
+};
+
+static const struct of_device_id rzg2l_cpg_match[] = {
+#ifdef CONFIG_CLK_R9A07G043
+ {
+ .compatible = "renesas,r9a07g043-cpg",
+ .data = &r9a07g043_cpg_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R9A07G044
+ {
+ .compatible = "renesas,r9a07g044-cpg",
+ .data = &r9a07g044_cpg_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R9A07G054
+ {
+ .compatible = "renesas,r9a07g054-cpg",
+ .data = &r9a07g054_cpg_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R9A08G045
+ {
+ .compatible = "renesas,r9a08g045-cpg",
+ .data = &r9a08g045_cpg_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R9A08G046
+ {
+ .compatible = "renesas,r9a08g046-cpg",
+ .data = &r9a08g046_cpg_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R9A09G011
+ {
+ .compatible = "renesas,r9a09g011-cpg",
+ .data = &r9a09g011_cpg_info,
+ },
+#endif
+ { /* sentinel */ }
+};
+
+static struct platform_driver rzg2l_cpg_driver = {
+ .driver = {
+ .name = "rzg2l-cpg",
+ .of_match_table = rzg2l_cpg_match,
+ .pm = pm_sleep_ptr(&rzg2l_cpg_pm_ops),
+ },
+};
+
+static int __init rzg2l_cpg_init(void)
+{
+ return platform_driver_probe(&rzg2l_cpg_driver, rzg2l_cpg_probe);
+}
+
+subsys_initcall(rzg2l_cpg_init);
+
+MODULE_DESCRIPTION("Renesas RZ/G2L CPG Driver");
diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
new file mode 100644
index 000000000..bd6169f62
--- /dev/null
+++ b/drivers/clk/renesas/rzg2l-cpg.h
@@ -0,0 +1,329 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * RZ/G2L Clock Pulse Generator
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ */
+
+#ifndef __RENESAS_RZG2L_CPG_H__
+#define __RENESAS_RZG2L_CPG_H__
+
+#include <linux/notifier.h>
+
+#define CPG_SIPLL5_STBY (0x140)
+#define CPG_SIPLL5_CLK1 (0x144)
+#define CPG_SIPLL5_CLK3 (0x14C)
+#define CPG_SIPLL5_CLK4 (0x150)
+#define CPG_SIPLL5_CLK5 (0x154)
+#define CPG_SIPLL5_MON (0x15C)
+#define CPG_PL1_DDIV (0x200)
+#define CPG_PL2_DDIV (0x204)
+#define CPG_PL3A_DDIV (0x208)
+#define CPG_PL6_DDIV (0x210)
+#define CPG_PL3C_SDIV (0x214)
+#define CPG_CLKSTATUS (0x280)
+#define CPG_PL3_SSEL (0x408)
+#define CPG_PL6_SSEL (0x414)
+#define CPG_PL6_ETH_SSEL (0x418)
+#define CPG_PL5_SDIV (0x420)
+#define CPG_RST_MON (0x680)
+#define CPG_BUS_ACPU_MSTOP (0xB60)
+#define CPG_BUS_MCPU1_MSTOP (0xB64)
+#define CPG_BUS_MCPU2_MSTOP (0xB68)
+#define CPG_BUS_PERI_COM_MSTOP (0xB6C)
+#define CPG_BUS_PERI_CPU_MSTOP (0xB70)
+#define CPG_BUS_PERI_DDR_MSTOP (0xB74)
+#define CPG_BUS_PERI_VIDEO_MSTOP (0xB78)
+#define CPG_BUS_REG0_MSTOP (0xB7C)
+#define CPG_BUS_REG1_MSTOP (0xB80)
+#define CPG_BUS_TZCDDR_MSTOP (0xB84)
+#define CPG_MHU_MSTOP (0xB88)
+#define CPG_BUS_MCPU3_MSTOP (0xB90)
+#define CPG_BUS_PERI_CPU2_MSTOP (0xB94)
+#define CPG_OTHERFUNC1_REG (0xBE8)
+
+#define CPG_SIPLL5_STBY_RESETB BIT(0)
+#define CPG_SIPLL5_STBY_RESETB_WEN BIT(16)
+#define CPG_SIPLL5_STBY_SSCG_EN_WEN BIT(18)
+#define CPG_SIPLL5_STBY_DOWNSPREAD_WEN BIT(20)
+#define CPG_SIPLL5_CLK4_RESV_LSB (0xFF)
+#define CPG_SIPLL5_MON_PLL5_LOCK BIT(4)
+
+#define CPG_OTHERFUNC1_REG_RES0_ON_WEN BIT(16)
+
+#define CPG_PL5_SDIV_DIV_DSI_A_WEN BIT(16)
+#define CPG_PL5_SDIV_DIV_DSI_B_WEN BIT(24)
+
+#define CPG_CLKSTATUS_SELSDHI0_STS BIT(28)
+#define CPG_CLKSTATUS_SELSDHI1_STS BIT(29)
+
+#define CPG_SAM_PLL_CONF(stby) ((stby) << 12)
+#define CPG_PLL_CONF(stby, setting) ((stby) << 12 | (setting))
+
+#define DDIV_PACK(offset, bitpos, size) \
+ (((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
+#define DIVPL1A DDIV_PACK(CPG_PL1_DDIV, 0, 2)
+#define DIVPL2A DDIV_PACK(CPG_PL2_DDIV, 0, 3)
+#define DIVDSILPCLK DDIV_PACK(CPG_PL2_DDIV, 12, 2)
+#define DIVPL3A DDIV_PACK(CPG_PL3A_DDIV, 0, 3)
+#define DIVPL3B DDIV_PACK(CPG_PL3A_DDIV, 4, 3)
+#define DIVPL3C DDIV_PACK(CPG_PL3A_DDIV, 8, 3)
+#define DIVPL3E DDIV_PACK(CPG_PL3C_SDIV, 8, 5)
+#define DIVGPU DDIV_PACK(CPG_PL6_DDIV, 0, 2)
+
+#define SEL_PLL_PACK(offset, bitpos, size) \
+ (((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
+
+#define SEL_PLL3_3 SEL_PLL_PACK(CPG_PL3_SSEL, 8, 1)
+#define SEL_PLL5_4 SEL_PLL_PACK(CPG_OTHERFUNC1_REG, 0, 1)
+#define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1)
+#define SEL_GPU2 SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1)
+
+#define MSTOP(name, bitmask) ((CPG_##name##_MSTOP) << 16 | (bitmask))
+
+#define EXTAL_FREQ_IN_MEGA_HZ (24)
+
+/**
+ * Definitions of CPG Core Clocks
+ *
+ * These include:
+ * - Clock outputs exported to DT
+ * - External input clocks
+ * - Internal CPG clocks
+ */
+struct cpg_core_clk {
+ const char *name;
+ unsigned int id;
+ unsigned int parent;
+ unsigned int div;
+ unsigned int mult;
+ unsigned int type;
+ unsigned int conf;
+ unsigned int sconf;
+ const struct clk_div_table *dtable;
+ const u32 *mtable;
+ const unsigned long invalid_rate;
+ union {
+ const unsigned long max_rate;
+ const unsigned long default_rate;
+ };
+ const char * const *parent_names;
+ notifier_fn_t notifier;
+ u32 flag;
+ u32 mux_flags;
+ int num_parents;
+};
+
+enum clk_types {
+ /* Generic */
+ CLK_TYPE_IN, /* External Clock Input */
+ CLK_TYPE_FF, /* Fixed Factor Clock */
+ CLK_TYPE_SAM_PLL,
+ CLK_TYPE_G3L_PLL,
+ CLK_TYPE_G3S_PLL,
+
+ /* Clock with divider */
+ CLK_TYPE_DIV,
+ CLK_TYPE_G3S_DIV,
+
+ /* Clock with clock source selector */
+ CLK_TYPE_MUX,
+
+ /* Clock with SD clock source selector */
+ CLK_TYPE_SD_MUX,
+
+ /* Clock for SIPLL5 */
+ CLK_TYPE_SIPLL5,
+
+ /* Clock for PLL5_4 clock source selector */
+ CLK_TYPE_PLL5_4_MUX,
+
+ /* Clock for DSI divider */
+ CLK_TYPE_DSI_DIV,
+
+};
+
+#define DEF_TYPE(_name, _id, _type...) \
+ { .name = _name, .id = _id, .type = _type }
+#define DEF_BASE(_name, _id, _type, _parent...) \
+ DEF_TYPE(_name, _id, _type, .parent = _parent)
+#define DEF_SAMPLL(_name, _id, _parent, _conf) \
+ DEF_TYPE(_name, _id, CLK_TYPE_SAM_PLL, .parent = _parent, .conf = _conf)
+#define DEF_G3L_PLL(_name, _id, _parent, _conf, _default_rate) \
+ DEF_TYPE(_name, _id, CLK_TYPE_G3L_PLL, .parent = _parent, .conf = _conf, \
+ .default_rate = _default_rate)
+#define DEF_G3S_PLL(_name, _id, _parent, _conf, _default_rate) \
+ DEF_TYPE(_name, _id, CLK_TYPE_G3S_PLL, .parent = _parent, .conf = _conf, \
+ .default_rate = _default_rate)
+#define DEF_INPUT(_name, _id) \
+ DEF_TYPE(_name, _id, CLK_TYPE_IN)
+#define DEF_FIXED(_name, _id, _parent, _mult, _div) \
+ DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
+#define DEF_DIV(_name, _id, _parent, _conf, _dtable) \
+ DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \
+ .parent = _parent, .dtable = _dtable, \
+ .flag = CLK_DIVIDER_HIWORD_MASK)
+#define DEF_DIV_RO(_name, _id, _parent, _conf, _dtable) \
+ DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \
+ .parent = _parent, .dtable = _dtable, \
+ .flag = CLK_DIVIDER_READ_ONLY)
+#define DEF_G3S_DIV(_name, _id, _parent, _conf, _sconf, _dtable, _invalid_rate, \
+ _max_rate, _clk_flags, _notif) \
+ DEF_TYPE(_name, _id, CLK_TYPE_G3S_DIV, .conf = _conf, .sconf = _sconf, \
+ .parent = _parent, .dtable = _dtable, \
+ .invalid_rate = _invalid_rate, \
+ .max_rate = _max_rate, .flag = (_clk_flags), \
+ .notifier = _notif)
+#define DEF_MUX_FLAGS(_name, _id, _conf, _parent_names, _flag) \
+ DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \
+ .parent_names = _parent_names, \
+ .num_parents = ARRAY_SIZE(_parent_names), \
+ .mux_flags = CLK_MUX_HIWORD_MASK, \
+ .flag = _flag)
+#define DEF_MUX(_name, _id, _conf, _parent_names) \
+ DEF_MUX_FLAGS(_name, _id, _conf, _parent_names, 0)
+#define DEF_MUX_RO(_name, _id, _conf, _parent_names) \
+ DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \
+ .parent_names = _parent_names, \
+ .num_parents = ARRAY_SIZE(_parent_names), \
+ .mux_flags = CLK_MUX_READ_ONLY)
+#define DEF_SD_MUX(_name, _id, _conf, _sconf, _parent_names, _mtable, _clk_flags, _notifier) \
+ DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, .sconf = _sconf, \
+ .parent_names = _parent_names, \
+ .num_parents = ARRAY_SIZE(_parent_names), \
+ .mtable = _mtable, .flag = _clk_flags, .notifier = _notifier)
+#define DEF_PLL5_FOUTPOSTDIV(_name, _id, _parent) \
+ DEF_TYPE(_name, _id, CLK_TYPE_SIPLL5, .parent = _parent)
+#define DEF_PLL5_4_MUX(_name, _id, _conf, _parent_names) \
+ DEF_TYPE(_name, _id, CLK_TYPE_PLL5_4_MUX, .conf = _conf, \
+ .parent_names = _parent_names, \
+ .num_parents = ARRAY_SIZE(_parent_names))
+#define DEF_DSI_DIV(_name, _id, _parent, _flag) \
+ DEF_TYPE(_name, _id, CLK_TYPE_DSI_DIV, .parent = _parent, .flag = _flag)
+
+/**
+ * struct rzg2l_mod_clk - Module Clocks definitions
+ *
+ * @name: handle between common and hardware-specific interfaces
+ * @id: clock index in array containing all Core and Module Clocks
+ * @parent: id of parent clock
+ * @mstop_conf: MSTOP configuration
+ * @off: register offset
+ * @bit: ON/MON bit
+ * @is_coupled: flag to indicate coupled clock
+ */
+struct rzg2l_mod_clk {
+ const char *name;
+ unsigned int id;
+ unsigned int parent;
+ u32 mstop_conf;
+ u16 off;
+ u8 bit;
+ bool is_coupled;
+};
+
+#define DEF_MOD_BASE(_name, _id, _parent, _off, _bit, _mstop_conf, _is_coupled) \
+ { \
+ .name = _name, \
+ .id = MOD_CLK_BASE + (_id), \
+ .parent = (_parent), \
+ .mstop_conf = (_mstop_conf), \
+ .off = (_off), \
+ .bit = (_bit), \
+ .is_coupled = (_is_coupled), \
+ }
+
+#define DEF_MOD(_name, _id, _parent, _off, _bit, _mstop_conf) \
+ DEF_MOD_BASE(_name, _id, _parent, _off, _bit, _mstop_conf, false)
+
+#define DEF_COUPLED(_name, _id, _parent, _off, _bit, _mstop_conf) \
+ DEF_MOD_BASE(_name, _id, _parent, _off, _bit, _mstop_conf, true)
+
+/**
+ * struct rzg2l_reset - Reset definitions
+ *
+ * @off: register offset
+ * @bit: reset bit
+ * @monbit: monitor bit in CPG_RST_MON register, -1 if none
+ */
+struct rzg2l_reset {
+ u16 off;
+ u8 bit;
+ s8 monbit;
+};
+
+#define DEF_RST_MON(_id, _off, _bit, _monbit) \
+ [_id] = { \
+ .off = (_off), \
+ .bit = (_bit), \
+ .monbit = (_monbit) \
+ }
+#define DEF_RST(_id, _off, _bit) \
+ DEF_RST_MON(_id, _off, _bit, -1)
+
+/**
+ * struct rzg2l_cpg_info - SoC-specific CPG Description
+ *
+ * @core_clks: Array of Core Clock definitions
+ * @num_core_clks: Number of entries in core_clks[]
+ * @last_dt_core_clk: ID of the last Core Clock exported to DT
+ * @num_total_core_clks: Total number of Core Clocks (exported + internal)
+ *
+ * @mod_clks: Array of Module Clock definitions
+ * @num_mod_clks: Number of entries in mod_clks[]
+ * @num_hw_mod_clks: Number of Module Clocks supported by the hardware
+ *
+ * @resets: Array of Module Reset definitions
+ * @num_resets: Number of entries in resets[]
+ *
+ * @crit_mod_clks: Array with Module Clock IDs of critical clocks that
+ * should not be disabled without a knowledgeable driver
+ * @num_crit_mod_clks: Number of entries in crit_mod_clks[]
+ * @crit_resets: Array with Reset IDs of critical resets that should not be
+ * asserted without a knowledgeable driver
+ * @num_crit_resets: Number of entries in crit_resets[]
+ * @has_clk_mon_regs: Flag indicating whether the SoC has CLK_MON registers
+ */
+struct rzg2l_cpg_info {
+ /* Core Clocks */
+ const struct cpg_core_clk *core_clks;
+ unsigned int num_core_clks;
+ unsigned int last_dt_core_clk;
+ unsigned int num_total_core_clks;
+
+ /* Module Clocks */
+ const struct rzg2l_mod_clk *mod_clks;
+ unsigned int num_mod_clks;
+ unsigned int num_hw_mod_clks;
+
+ /* No PM Module Clocks */
+ const unsigned int *no_pm_mod_clks;
+ unsigned int num_no_pm_mod_clks;
+
+ /* Resets */
+ const struct rzg2l_reset *resets;
+ unsigned int num_resets;
+
+ /* Critical Module Clocks that should not be disabled */
+ const unsigned int *crit_mod_clks;
+ unsigned int num_crit_mod_clks;
+
+ /* Critical Resets that should not be asserted */
+ const unsigned int *crit_resets;
+ unsigned int num_crit_resets;
+
+ bool has_clk_mon_regs;
+};
+
+extern const struct rzg2l_cpg_info r9a07g043_cpg_info;
+extern const struct rzg2l_cpg_info r9a07g044_cpg_info;
+extern const struct rzg2l_cpg_info r9a07g054_cpg_info;
+extern const struct rzg2l_cpg_info r9a08g045_cpg_info;
+extern const struct rzg2l_cpg_info r9a08g046_cpg_info;
+extern const struct rzg2l_cpg_info r9a09g011_cpg_info;
+
+int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event, void *data);
+int rzg3s_cpg_div_clk_notifier(struct notifier_block *nb, unsigned long event, void *data);
+
+#endif
diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c
new file mode 100644
index 000000000..5bdfdc415
--- /dev/null
+++ b/drivers/clk/renesas/rzv2h-cpg.c
@@ -0,0 +1,1874 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/V2H(P) Clock Pulse Generator
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ *
+ * Based on rzg2l-cpg.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2013 Ideas On Board SPRL
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/iopoll.h>
+#include <linux/limits.h>
+#include <linux/math.h>
+#include <linux/math64.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/refcount.h>
+#include <linux/reset-controller.h>
+#include <linux/string_choices.h>
+#include <linux/units.h>
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+#include "rzv2h-cpg.h"
+
+#ifdef DEBUG
+#define WARN_DEBUG(x) WARN_ON(x)
+#else
+#define WARN_DEBUG(x) do { } while (0)
+#endif
+
+#define GET_CLK_ON_OFFSET(x) (0x600 + ((x) * 4))
+#define GET_CLK_MON_OFFSET(x) (0x800 + ((x) * 4))
+#define GET_RST_OFFSET(x) (0x900 + ((x) * 4))
+#define GET_RST_MON_OFFSET(x) (0xA00 + ((x) * 4))
+
+#define CPG_BUS_1_MSTOP (0xd00)
+#define CPG_BUS_MSTOP(m) (CPG_BUS_1_MSTOP + ((m) - 1) * 4)
+
+#define CPG_PLL_STBY(x) ((x))
+#define CPG_PLL_STBY_RESETB BIT(0)
+#define CPG_PLL_STBY_SSC_EN BIT(2)
+#define CPG_PLL_STBY_RESETB_WEN BIT(16)
+#define CPG_PLL_STBY_SSC_EN_WEN BIT(18)
+#define CPG_PLL_CLK1(x) ((x) + 0x004)
+#define CPG_PLL_CLK1_KDIV GENMASK(31, 16)
+#define CPG_PLL_CLK1_MDIV GENMASK(15, 6)
+#define CPG_PLL_CLK1_PDIV GENMASK(5, 0)
+#define CPG_PLL_CLK2(x) ((x) + 0x008)
+#define CPG_PLL_CLK2_SDIV GENMASK(2, 0)
+#define CPG_PLL_MON(x) ((x) + 0x010)
+#define CPG_PLL_MON_RESETB BIT(0)
+#define CPG_PLL_MON_LOCK BIT(4)
+
+#define DDIV_DIVCTL_WEN(shift) BIT((shift) + 16)
+
+#define GET_MOD_CLK_ID(base, index, bit) \
+ ((base) + ((((index) * (16))) + (bit)))
+
+#define CPG_CLKSTATUS0 (0x700)
+
+/* On RZ/G3E SoC we have two DSI PLLs */
+#define MAX_CPG_DSI_PLL 2
+
+#define CPG_PLLDSI_SMUX_LVDS_DUTY_NUM 4
+#define CPG_PLLDSI_SMUX_LVDS_DUTY_DEN 7
+#define CPG_PLLDSI_SMUX_DSI_RGB_DUTY_NUM 1
+#define CPG_PLLDSI_SMUX_DSI_RGB_DUTY_DEN 2
+
+/**
+ * struct rzv2h_pll_dsi_info - PLL DSI information, holds the limits and parameters
+ *
+ * @pll_dsi_limits: PLL DSI parameters limits
+ * @pll_dsi_parameters: Calculated PLL DSI parameters
+ * @req_pll_dsi_rate: Requested PLL DSI rate
+ */
+struct rzv2h_pll_dsi_info {
+ const struct rzv2h_pll_limits *pll_dsi_limits;
+ struct rzv2h_pll_div_pars pll_dsi_parameters;
+ unsigned long req_pll_dsi_rate;
+};
+
+/**
+ * struct rzv2h_cpg_priv - Clock Pulse Generator Private Data
+ *
+ * @dev: CPG device
+ * @base: CPG register block base address
+ * @rmw_lock: protects register accesses
+ * @clks: Array containing all Core and Module Clocks
+ * @num_core_clks: Number of Core Clocks in clks[]
+ * @num_mod_clks: Number of Module Clocks in clks[]
+ * @resets: Array of resets
+ * @num_resets: Number of Module Resets in info->resets[]
+ * @last_dt_core_clk: ID of the last Core Clock exported to DT
+ * @ff_mod_status_ops: Fixed Factor Module Status Clock operations
+ * @mstop_count: Array of mstop values
+ * @rcdev: Reset controller entity
+ * @pll_dsi_info: Array of PLL DSI information, holds the limits and parameters
+ */
+struct rzv2h_cpg_priv {
+ struct device *dev;
+ void __iomem *base;
+ spinlock_t rmw_lock;
+
+ struct clk **clks;
+ unsigned int num_core_clks;
+ unsigned int num_mod_clks;
+ struct rzv2h_reset *resets;
+ unsigned int num_resets;
+ unsigned int last_dt_core_clk;
+
+ struct clk_ops *ff_mod_status_ops;
+
+ atomic_t *mstop_count;
+
+ struct reset_controller_dev rcdev;
+
+ struct rzv2h_pll_dsi_info pll_dsi_info[MAX_CPG_DSI_PLL];
+};
+
+#define rcdev_to_priv(x) container_of(x, struct rzv2h_cpg_priv, rcdev)
+
+struct pll_clk {
+ struct rzv2h_cpg_priv *priv;
+ struct clk_hw hw;
+ struct pll pll;
+};
+
+#define to_pll(_hw) container_of(_hw, struct pll_clk, hw)
+
+/**
+ * struct mod_clock - Module clock
+ *
+ * @priv: CPG private data
+ * @mstop_data: mstop data relating to module clock
+ * @hw: handle between common and hardware-specific interfaces
+ * @no_pm: flag to indicate PM is not supported
+ * @on_index: register offset
+ * @on_bit: ON/MON bit
+ * @mon_index: monitor register offset
+ * @mon_bit: monitor bit
+ * @ext_clk_mux_index: mux index for external clock source, or -1 if internal
+ */
+struct mod_clock {
+ struct rzv2h_cpg_priv *priv;
+ unsigned int mstop_data;
+ struct clk_hw hw;
+ bool no_pm;
+ u8 on_index;
+ u8 on_bit;
+ s8 mon_index;
+ u8 mon_bit;
+ s8 ext_clk_mux_index;
+};
+
+#define to_mod_clock(_hw) container_of(_hw, struct mod_clock, hw)
+
+/**
+ * struct ddiv_clk - DDIV clock
+ *
+ * @priv: CPG private data
+ * @div: divider clk
+ * @mon: monitor bit in CPG_CLKSTATUS0 register
+ */
+struct ddiv_clk {
+ struct rzv2h_cpg_priv *priv;
+ struct clk_divider div;
+ u8 mon;
+};
+
+#define to_ddiv_clock(_div) container_of(_div, struct ddiv_clk, div)
+
+/**
+ * struct rzv2h_ff_mod_status_clk - Fixed Factor Module Status Clock
+ *
+ * @priv: CPG private data
+ * @conf: fixed mod configuration
+ * @fix: fixed factor clock
+ */
+struct rzv2h_ff_mod_status_clk {
+ struct rzv2h_cpg_priv *priv;
+ struct fixed_mod_conf conf;
+ struct clk_fixed_factor fix;
+};
+
+#define to_rzv2h_ff_mod_status_clk(_hw) \
+ container_of(_hw, struct rzv2h_ff_mod_status_clk, fix.hw)
+
+/**
+ * struct rzv2h_plldsi_div_clk - PLL DSI DDIV clock
+ *
+ * @dtable: divider table
+ * @priv: CPG private data
+ * @hw: divider clk
+ * @ddiv: divider configuration
+ */
+struct rzv2h_plldsi_div_clk {
+ const struct clk_div_table *dtable;
+ struct rzv2h_cpg_priv *priv;
+ struct clk_hw hw;
+ struct ddiv ddiv;
+};
+
+#define to_plldsi_div_clk(_hw) \
+ container_of(_hw, struct rzv2h_plldsi_div_clk, hw)
+
+#define RZ_V2H_OSC_CLK_IN_MEGA (24 * MEGA)
+#define RZV2H_MAX_DIV_TABLES (16)
+
+/**
+ * rzv2h_get_pll_pars - Finds the best combination of PLL parameters
+ * for a given frequency.
+ *
+ * @limits: Pointer to the structure containing the limits for the PLL parameters
+ * @pars: Pointer to the structure where the best calculated PLL parameters values
+ * will be stored
+ * @freq_millihz: Target output frequency in millihertz
+ *
+ * This function calculates the best set of PLL parameters (M, K, P, S) to achieve
+ * the desired frequency.
+ * There is no direct formula to calculate the PLL parameters, as it's an open
+ * system of equations, therefore this function uses an iterative approach to
+ * determine the best solution. The best solution is one that minimizes the error
+ * (desired frequency - actual frequency).
+ *
+ * Return: true if a valid set of parameters values is found, false otherwise.
+ */
+bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits,
+ struct rzv2h_pll_pars *pars, u64 freq_millihz)
+{
+ u64 fout_min_millihz = mul_u32_u32(limits->fout.min, MILLI);
+ u64 fout_max_millihz = mul_u32_u32(limits->fout.max, MILLI);
+ struct rzv2h_pll_pars p, best;
+
+ if (freq_millihz > fout_max_millihz ||
+ freq_millihz < fout_min_millihz)
+ return false;
+
+ /* Initialize best error to maximum possible value */
+ best.error_millihz = S64_MAX;
+
+ for (p.p = limits->p.min; p.p <= limits->p.max; p.p++) {
+ u32 fref = RZ_V2H_OSC_CLK_IN_MEGA / p.p;
+ u16 divider;
+
+ for (divider = 1 << limits->s.min, p.s = limits->s.min;
+ p.s <= limits->s.max; p.s++, divider <<= 1) {
+ for (p.m = limits->m.min; p.m <= limits->m.max; p.m++) {
+ u64 output_m, output_k_range;
+ s64 pll_k, output_k;
+ u64 fvco, output;
+
+ /*
+ * The frequency generated by the PLL + divider
+ * is calculated as follows:
+ *
+ * With:
+ * Freq = Ffout = Ffvco / 2^(pll_s)
+ * Ffvco = (pll_m + (pll_k / 65536)) * Ffref
+ * Ffref = 24MHz / pll_p
+ *
+ * Freq can also be rewritten as:
+ * Freq = Ffvco / 2^(pll_s)
+ * = ((pll_m + (pll_k / 65536)) * Ffref) / 2^(pll_s)
+ * = (pll_m * Ffref) / 2^(pll_s) + ((pll_k / 65536) * Ffref) / 2^(pll_s)
+ * = output_m + output_k
+ *
+ * Every parameter has been determined at this
+ * point, but pll_k.
+ *
+ * Considering that:
+ * limits->k.min <= pll_k <= limits->k.max
+ * Then:
+ * -0.5 <= (pll_k / 65536) < 0.5
+ * Therefore:
+ * -Ffref / (2 * 2^(pll_s)) <= output_k < Ffref / (2 * 2^(pll_s))
+ */
+
+ /* Compute output M component (in mHz) */
+ output_m = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(p.m, fref) * MILLI,
+ divider);
+ /* Compute range for output K (in mHz) */
+ output_k_range = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(fref, MILLI),
+ 2 * divider);
+ /*
+ * No point in continuing if we can't achieve
+ * the desired frequency
+ */
+ if (freq_millihz < (output_m - output_k_range) ||
+ freq_millihz >= (output_m + output_k_range)) {
+ continue;
+ }
+
+ /*
+ * Compute the K component
+ *
+ * Since:
+ * Freq = output_m + output_k
+ * Then:
+ * output_k = Freq - output_m
+ * = ((pll_k / 65536) * Ffref) / 2^(pll_s)
+ * Therefore:
+ * pll_k = (output_k * 65536 * 2^(pll_s)) / Ffref
+ */
+ output_k = freq_millihz - output_m;
+ pll_k = div_s64(output_k * 65536ULL * divider,
+ fref);
+ pll_k = DIV_S64_ROUND_CLOSEST(pll_k, MILLI);
+
+ /* Validate K value within allowed limits */
+ if (pll_k < limits->k.min ||
+ pll_k > limits->k.max)
+ continue;
+
+ p.k = pll_k;
+
+ /* Compute (Ffvco * 65536) */
+ fvco = mul_u32_u32(p.m * 65536 + p.k, fref);
+ if (fvco < mul_u32_u32(limits->fvco.min, 65536) ||
+ fvco > mul_u32_u32(limits->fvco.max, 65536))
+ continue;
+
+ /* PLL_M component of (output * 65536 * PLL_P) */
+ output = mul_u32_u32(p.m * 65536, RZ_V2H_OSC_CLK_IN_MEGA);
+ /* PLL_K component of (output * 65536 * PLL_P) */
+ output += p.k * RZ_V2H_OSC_CLK_IN_MEGA;
+ /* Make it in mHz */
+ output *= MILLI;
+ output = DIV_U64_ROUND_CLOSEST(output, 65536 * p.p * divider);
+
+ /* Check output frequency against limits */
+ if (output < fout_min_millihz ||
+ output > fout_max_millihz)
+ continue;
+
+ p.error_millihz = freq_millihz - output;
+ p.freq_millihz = output;
+
+ /* If an exact match is found, return immediately */
+ if (p.error_millihz == 0) {
+ *pars = p;
+ return true;
+ }
+
+ /* Update best match if error is smaller */
+ if (abs(best.error_millihz) > abs(p.error_millihz))
+ best = p;
+ }
+ }
+ }
+
+ /* If no valid parameters were found, return false */
+ if (best.error_millihz == S64_MAX)
+ return false;
+
+ *pars = best;
+ return true;
+}
+EXPORT_SYMBOL_NS_GPL(rzv2h_get_pll_pars, "RZV2H_CPG");
+
+/*
+ * rzv2h_get_pll_divs_pars - Finds the best combination of PLL parameters
+ * and divider value for a given frequency.
+ *
+ * @limits: Pointer to the structure containing the limits for the PLL parameters
+ * @pars: Pointer to the structure where the best calculated PLL parameters and
+ * divider values will be stored
+ * @table: Pointer to the array of valid divider values
+ * @table_size: Size of the divider values array
+ * @freq_millihz: Target output frequency in millihertz
+ *
+ * This function calculates the best set of PLL parameters (M, K, P, S) and divider
+ * value to achieve the desired frequency. See rzv2h_get_pll_pars() for more details
+ * on how the PLL parameters are calculated.
+ *
+ * freq_millihz is the desired frequency generated by the PLL followed by a
+ * a gear.
+ */
+bool rzv2h_get_pll_divs_pars(const struct rzv2h_pll_limits *limits,
+ struct rzv2h_pll_div_pars *pars,
+ const u8 *table, u8 table_size, u64 freq_millihz)
+{
+ struct rzv2h_pll_div_pars p, best;
+
+ best.div.error_millihz = S64_MAX;
+ p.div.error_millihz = S64_MAX;
+ for (unsigned int i = 0; i < table_size; i++) {
+ if (!rzv2h_get_pll_pars(limits, &p.pll, freq_millihz * table[i]))
+ continue;
+
+ p.div.divider_value = table[i];
+ p.div.freq_millihz = DIV_U64_ROUND_CLOSEST(p.pll.freq_millihz, table[i]);
+ p.div.error_millihz = freq_millihz - p.div.freq_millihz;
+
+ if (p.div.error_millihz == 0) {
+ *pars = p;
+ return true;
+ }
+
+ if (abs(best.div.error_millihz) > abs(p.div.error_millihz))
+ best = p;
+ }
+
+ if (best.div.error_millihz == S64_MAX)
+ return false;
+
+ *pars = best;
+ return true;
+}
+EXPORT_SYMBOL_NS_GPL(rzv2h_get_pll_divs_pars, "RZV2H_CPG");
+
+/**
+ * struct rzv2h_plldsi_mux_clk - PLL DSI MUX clock
+ *
+ * @priv: CPG private data
+ * @mux: mux clk
+ */
+struct rzv2h_plldsi_mux_clk {
+ struct rzv2h_cpg_priv *priv;
+ struct clk_mux mux;
+};
+
+#define to_plldsi_clk_mux(_mux) \
+ container_of(_mux, struct rzv2h_plldsi_mux_clk, mux)
+
+static unsigned long rzv2h_cpg_plldsi_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
+ struct rzv2h_cpg_priv *priv = dsi_div->priv;
+ struct ddiv ddiv = dsi_div->ddiv;
+ u32 div;
+
+ div = readl(priv->base + ddiv.offset);
+ div >>= ddiv.shift;
+ div &= clk_div_mask(ddiv.width);
+ div = dsi_div->dtable[div].div;
+
+ return DIV_ROUND_CLOSEST_ULL(parent_rate, div);
+}
+
+static int rzv2h_cpg_plldsi_div_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
+ struct pll_clk *pll_clk = to_pll(clk_hw_get_parent(hw));
+ struct rzv2h_cpg_priv *priv = dsi_div->priv;
+ u8 table[RZV2H_MAX_DIV_TABLES] = { 0 };
+ struct rzv2h_pll_div_pars *dsi_params;
+ struct rzv2h_pll_dsi_info *dsi_info;
+ const struct clk_div_table *div;
+ unsigned int i = 0;
+ u64 rate_millihz;
+
+ dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance];
+ dsi_params = &dsi_info->pll_dsi_parameters;
+
+ rate_millihz = mul_u32_u32(req->rate, MILLI);
+ if (rate_millihz == dsi_params->div.error_millihz + dsi_params->div.freq_millihz)
+ goto exit_determine_rate;
+
+ for (div = dsi_div->dtable; div->div; div++) {
+ if (i >= RZV2H_MAX_DIV_TABLES)
+ return -EINVAL;
+ table[i++] = div->div;
+ }
+
+ if (!rzv2h_get_pll_divs_pars(dsi_info->pll_dsi_limits, dsi_params, table, i,
+ rate_millihz)) {
+ dev_err(priv->dev, "failed to determine rate for req->rate: %lu\n",
+ req->rate);
+ return -EINVAL;
+ }
+
+exit_determine_rate:
+ req->rate = DIV_ROUND_CLOSEST_ULL(dsi_params->div.freq_millihz, MILLI);
+ req->best_parent_rate = req->rate * dsi_params->div.divider_value;
+ dsi_info->req_pll_dsi_rate = req->best_parent_rate;
+
+ return 0;
+}
+
+static int rzv2h_cpg_plldsi_div_set_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
+ struct pll_clk *pll_clk = to_pll(clk_hw_get_parent(hw));
+ struct rzv2h_cpg_priv *priv = dsi_div->priv;
+ struct rzv2h_pll_div_pars *dsi_params;
+ struct rzv2h_pll_dsi_info *dsi_info;
+ struct ddiv ddiv = dsi_div->ddiv;
+ const struct clk_div_table *clkt;
+ bool divider_found = false;
+ u32 val, shift;
+
+ dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance];
+ dsi_params = &dsi_info->pll_dsi_parameters;
+
+ for (clkt = dsi_div->dtable; clkt->div; clkt++) {
+ if (clkt->div == dsi_params->div.divider_value) {
+ divider_found = true;
+ break;
+ }
+ }
+
+ if (!divider_found)
+ return -EINVAL;
+
+ shift = ddiv.shift;
+ val = readl(priv->base + ddiv.offset) | DDIV_DIVCTL_WEN(shift);
+ val &= ~(clk_div_mask(ddiv.width) << shift);
+ val |= clkt->val << shift;
+ writel(val, priv->base + ddiv.offset);
+
+ return 0;
+}
+
+static const struct clk_ops rzv2h_cpg_plldsi_div_ops = {
+ .recalc_rate = rzv2h_cpg_plldsi_div_recalc_rate,
+ .determine_rate = rzv2h_cpg_plldsi_div_determine_rate,
+ .set_rate = rzv2h_cpg_plldsi_div_set_rate,
+};
+
+static struct clk * __init
+rzv2h_cpg_plldsi_div_clk_register(const struct cpg_core_clk *core,
+ struct rzv2h_cpg_priv *priv)
+{
+ struct rzv2h_plldsi_div_clk *clk_hw_data;
+ struct clk **clks = priv->clks;
+ struct clk_init_data init;
+ const struct clk *parent;
+ const char *parent_name;
+ struct clk_hw *clk_hw;
+ int ret;
+
+ parent = clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
+ if (!clk_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+ clk_hw_data->priv = priv;
+ clk_hw_data->ddiv = core->cfg.ddiv;
+ clk_hw_data->dtable = core->dtable;
+
+ parent_name = __clk_get_name(parent);
+ init.name = core->name;
+ init.ops = &rzv2h_cpg_plldsi_div_ops;
+ init.flags = core->flag;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clk_hw = &clk_hw_data->hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return clk_hw->clk;
+}
+
+static int rzv2h_cpg_plldsi_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzv2h_cpg_priv *priv = pll_clk->priv;
+ struct rzv2h_pll_dsi_info *dsi_info;
+ u64 rate_millihz;
+
+ dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance];
+ /* check if the divider has already invoked the algorithm */
+ if (req->rate == dsi_info->req_pll_dsi_rate)
+ return 0;
+
+ /* If the req->rate doesn't match we do the calculation assuming there is no divider */
+ rate_millihz = mul_u32_u32(req->rate, MILLI);
+ if (!rzv2h_get_pll_pars(dsi_info->pll_dsi_limits,
+ &dsi_info->pll_dsi_parameters.pll, rate_millihz)) {
+ dev_err(priv->dev,
+ "failed to determine rate for req->rate: %lu\n",
+ req->rate);
+ return -EINVAL;
+ }
+
+ req->rate = DIV_ROUND_CLOSEST_ULL(dsi_info->pll_dsi_parameters.pll.freq_millihz, MILLI);
+ dsi_info->req_pll_dsi_rate = req->rate;
+
+ return 0;
+}
+
+static int rzv2h_cpg_pll_set_rate(struct pll_clk *pll_clk,
+ struct rzv2h_pll_pars *params,
+ bool ssc_disable)
+{
+ struct rzv2h_cpg_priv *priv = pll_clk->priv;
+ u16 offset = pll_clk->pll.offset;
+ u32 val;
+ int ret;
+
+ /* Put PLL into standby mode */
+ writel(CPG_PLL_STBY_RESETB_WEN, priv->base + CPG_PLL_STBY(offset));
+ ret = readl_poll_timeout_atomic(priv->base + CPG_PLL_MON(offset),
+ val, !(val & CPG_PLL_MON_LOCK),
+ 100, 2000);
+ if (ret) {
+ dev_err(priv->dev, "Failed to put PLLDSI into standby mode\n");
+ return ret;
+ }
+
+ /* Output clock setting 1 */
+ writel(FIELD_PREP(CPG_PLL_CLK1_KDIV, (u16)params->k) |
+ FIELD_PREP(CPG_PLL_CLK1_MDIV, params->m) |
+ FIELD_PREP(CPG_PLL_CLK1_PDIV, params->p),
+ priv->base + CPG_PLL_CLK1(offset));
+
+ /* Output clock setting 2 */
+ val = readl(priv->base + CPG_PLL_CLK2(offset));
+ writel((val & ~CPG_PLL_CLK2_SDIV) | FIELD_PREP(CPG_PLL_CLK2_SDIV, params->s),
+ priv->base + CPG_PLL_CLK2(offset));
+
+ /* Put PLL to normal mode */
+ if (ssc_disable)
+ val = CPG_PLL_STBY_SSC_EN_WEN;
+ else
+ val = CPG_PLL_STBY_SSC_EN_WEN | CPG_PLL_STBY_SSC_EN;
+ writel(val | CPG_PLL_STBY_RESETB_WEN | CPG_PLL_STBY_RESETB,
+ priv->base + CPG_PLL_STBY(offset));
+
+ /* PLL normal mode transition, output clock stability check */
+ ret = readl_poll_timeout_atomic(priv->base + CPG_PLL_MON(offset),
+ val, (val & CPG_PLL_MON_LOCK),
+ 100, 2000);
+ if (ret) {
+ dev_err(priv->dev, "Failed to put PLLDSI into normal mode\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rzv2h_cpg_plldsi_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzv2h_pll_dsi_info *dsi_info;
+ struct rzv2h_cpg_priv *priv = pll_clk->priv;
+
+ dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance];
+
+ return rzv2h_cpg_pll_set_rate(pll_clk, &dsi_info->pll_dsi_parameters.pll, true);
+}
+
+static u8 rzv2h_cpg_plldsi_smux_get_parent(struct clk_hw *hw)
+{
+ return clk_mux_ops.get_parent(hw);
+}
+
+static int rzv2h_cpg_plldsi_smux_set_parent(struct clk_hw *hw, u8 index)
+{
+ return clk_mux_ops.set_parent(hw, index);
+}
+
+static int rzv2h_cpg_plldsi_smux_lvds_determine_rate(struct rzv2h_cpg_priv *priv,
+ struct pll_clk *pll_clk,
+ struct clk_rate_request *req)
+{
+ struct rzv2h_pll_div_pars *dsi_params;
+ struct rzv2h_pll_dsi_info *dsi_info;
+ u8 lvds_table[] = { 7 };
+ u64 rate_millihz;
+
+ dsi_info = &priv->pll_dsi_info[pll_clk->pll.instance];
+ dsi_params = &dsi_info->pll_dsi_parameters;
+
+ rate_millihz = mul_u32_u32(req->rate, MILLI);
+ if (!rzv2h_get_pll_divs_pars(dsi_info->pll_dsi_limits, dsi_params,
+ lvds_table, ARRAY_SIZE(lvds_table), rate_millihz)) {
+ dev_err(priv->dev, "failed to determine rate for req->rate: %lu\n",
+ req->rate);
+ return -EINVAL;
+ }
+
+ req->rate = DIV_ROUND_CLOSEST_ULL(dsi_params->div.freq_millihz, MILLI);
+ req->best_parent_rate = req->rate;
+ dsi_info->req_pll_dsi_rate = req->best_parent_rate * dsi_params->div.divider_value;
+
+ return 0;
+}
+
+static int rzv2h_cpg_plldsi_smux_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_mux *mux = to_clk_mux(hw);
+ struct rzv2h_plldsi_mux_clk *dsi_mux = to_plldsi_clk_mux(mux);
+ struct pll_clk *pll_clk = to_pll(clk_hw_get_parent(hw));
+ struct rzv2h_cpg_priv *priv = dsi_mux->priv;
+
+ /*
+ * For LVDS output (parent index 0), calculate PLL parameters with
+ * fixed divider value of 7. For DSI/RGB output (parent index 1) skip
+ * PLL calculation here as it's handled by determine_rate of the
+ * divider (up one level).
+ */
+ if (!clk_mux_ops.get_parent(hw))
+ return rzv2h_cpg_plldsi_smux_lvds_determine_rate(priv, pll_clk, req);
+
+ req->best_parent_rate = req->rate;
+ return 0;
+}
+
+static int rzv2h_cpg_plldsi_smux_get_duty_cycle(struct clk_hw *hw,
+ struct clk_duty *duty)
+{
+ u8 parent = clk_mux_ops.get_parent(hw);
+
+ /*
+ * CDIV7_DSIx_CLK - LVDS path (div7) - duty 4/7.
+ * CSDIV_DSIx - DSI/RGB path (csdiv) - duty 1/2.
+ */
+ if (parent == 0) {
+ duty->num = CPG_PLLDSI_SMUX_LVDS_DUTY_NUM;
+ duty->den = CPG_PLLDSI_SMUX_LVDS_DUTY_DEN;
+ } else {
+ duty->num = CPG_PLLDSI_SMUX_DSI_RGB_DUTY_NUM;
+ duty->den = CPG_PLLDSI_SMUX_DSI_RGB_DUTY_DEN;
+ }
+
+ return 0;
+}
+
+static int rzv2h_cpg_plldsi_smux_set_duty_cycle(struct clk_hw *hw,
+ struct clk_duty *duty)
+{
+ struct clk_hw *parent_hw;
+ u8 parent_idx;
+
+ /*
+ * Select parent based on requested duty cycle:
+ * - If duty > 50% (num/den > 1/2), select LVDS path (parent 0)
+ * - Otherwise, select DSI/RGB path (parent 1)
+ */
+ if (duty->num * CPG_PLLDSI_SMUX_DSI_RGB_DUTY_DEN >
+ duty->den * CPG_PLLDSI_SMUX_DSI_RGB_DUTY_NUM)
+ parent_idx = 0;
+ else
+ parent_idx = 1;
+
+ if (parent_idx >= clk_hw_get_num_parents(hw))
+ return -EINVAL;
+
+ parent_hw = clk_hw_get_parent_by_index(hw, parent_idx);
+ if (!parent_hw)
+ return -EINVAL;
+
+ return clk_hw_set_parent(hw, parent_hw);
+}
+
+static const struct clk_ops rzv2h_cpg_plldsi_smux_ops = {
+ .determine_rate = rzv2h_cpg_plldsi_smux_determine_rate,
+ .get_parent = rzv2h_cpg_plldsi_smux_get_parent,
+ .set_parent = rzv2h_cpg_plldsi_smux_set_parent,
+ .get_duty_cycle = rzv2h_cpg_plldsi_smux_get_duty_cycle,
+ .set_duty_cycle = rzv2h_cpg_plldsi_smux_set_duty_cycle,
+};
+
+static struct clk * __init
+rzv2h_cpg_plldsi_smux_clk_register(const struct cpg_core_clk *core,
+ struct rzv2h_cpg_priv *priv)
+{
+ struct rzv2h_plldsi_mux_clk *clk_hw_data;
+ struct clk_init_data init;
+ struct clk_hw *clk_hw;
+ struct smuxed smux;
+ int ret;
+
+ smux = core->cfg.smux;
+
+ if (smux.shift + smux.width > 16) {
+ dev_err(priv->dev, "mux value exceeds LOWORD field\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
+ if (!clk_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+ clk_hw_data->priv = priv;
+
+ init.name = core->name;
+ init.ops = &rzv2h_cpg_plldsi_smux_ops;
+ init.flags = core->flag;
+ init.parent_names = core->parent_names;
+ init.num_parents = core->num_parents;
+
+ clk_hw_data->mux.reg = priv->base + smux.offset;
+
+ clk_hw_data->mux.shift = smux.shift;
+ clk_hw_data->mux.mask = clk_div_mask(smux.width);
+ clk_hw_data->mux.flags = core->mux_flags;
+ clk_hw_data->mux.lock = &priv->rmw_lock;
+
+ clk_hw = &clk_hw_data->mux.hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return clk_hw->clk;
+}
+
+static int rzv2h_cpg_pll_clk_is_enabled(struct clk_hw *hw)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzv2h_cpg_priv *priv = pll_clk->priv;
+ u32 val = readl(priv->base + CPG_PLL_MON(pll_clk->pll.offset));
+
+ /* Ensure both RESETB and LOCK bits are set */
+ return (val & (CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK)) ==
+ (CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK);
+}
+
+static int rzv2h_cpg_pll_clk_enable(struct clk_hw *hw)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzv2h_cpg_priv *priv = pll_clk->priv;
+ struct pll pll = pll_clk->pll;
+ u32 stby_offset;
+ u32 mon_offset;
+ u32 val;
+ int ret;
+
+ if (rzv2h_cpg_pll_clk_is_enabled(hw))
+ return 0;
+
+ stby_offset = CPG_PLL_STBY(pll.offset);
+ mon_offset = CPG_PLL_MON(pll.offset);
+
+ writel(CPG_PLL_STBY_RESETB_WEN | CPG_PLL_STBY_RESETB,
+ priv->base + stby_offset);
+
+ /*
+ * Ensure PLL enters into normal mode
+ *
+ * Note: There is no HW information about the worst case latency.
+ *
+ * Since this latency might depend on external crystal or PLL rate,
+ * use a "super" safe timeout value.
+ */
+ ret = readl_poll_timeout_atomic(priv->base + mon_offset, val,
+ (val & (CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK)) ==
+ (CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK), 200, 2000);
+ if (ret)
+ dev_err(priv->dev, "Failed to enable PLL 0x%x/%pC\n",
+ stby_offset, hw->clk);
+
+ return ret;
+}
+
+static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzv2h_cpg_priv *priv = pll_clk->priv;
+ struct pll pll = pll_clk->pll;
+ unsigned int clk1, clk2;
+ u64 rate;
+
+ if (!pll.has_clkn)
+ return 0;
+
+ clk1 = readl(priv->base + CPG_PLL_CLK1(pll.offset));
+ clk2 = readl(priv->base + CPG_PLL_CLK2(pll.offset));
+
+ rate = mul_u64_u32_shr(parent_rate, (FIELD_GET(CPG_PLL_CLK1_MDIV, clk1) << 16) +
+ (s16)FIELD_GET(CPG_PLL_CLK1_KDIV, clk1),
+ 16 + FIELD_GET(CPG_PLL_CLK2_SDIV, clk2));
+
+ return DIV_ROUND_CLOSEST_ULL(rate, FIELD_GET(CPG_PLL_CLK1_PDIV, clk1));
+}
+
+static const struct clk_ops rzv2h_cpg_plldsi_ops = {
+ .recalc_rate = rzv2h_cpg_pll_clk_recalc_rate,
+ .determine_rate = rzv2h_cpg_plldsi_determine_rate,
+ .set_rate = rzv2h_cpg_plldsi_set_rate,
+};
+
+static const struct clk_ops rzv2h_cpg_pll_ops = {
+ .is_enabled = rzv2h_cpg_pll_clk_is_enabled,
+ .enable = rzv2h_cpg_pll_clk_enable,
+ .recalc_rate = rzv2h_cpg_pll_clk_recalc_rate,
+};
+
+static struct clk * __init
+rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core,
+ struct rzv2h_cpg_priv *priv,
+ const struct clk_ops *ops)
+{
+ struct device *dev = priv->dev;
+ struct clk_init_data init;
+ const struct clk *parent;
+ const char *parent_name;
+ struct pll_clk *pll_clk;
+ int ret;
+
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL);
+ if (!pll_clk)
+ return ERR_PTR(-ENOMEM);
+
+ if (core->type == CLK_TYPE_PLLDSI)
+ priv->pll_dsi_info[core->cfg.pll.instance].pll_dsi_limits =
+ core->cfg.pll.limits;
+
+ parent_name = __clk_get_name(parent);
+ init.name = core->name;
+ init.ops = ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pll_clk->hw.init = &init;
+ pll_clk->pll = core->cfg.pll;
+ pll_clk->priv = priv;
+
+ ret = devm_clk_hw_register(dev, &pll_clk->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return pll_clk->hw.clk;
+}
+
+static unsigned long rzv2h_ddiv_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+ unsigned int val;
+
+ val = readl(divider->reg) >> divider->shift;
+ val &= clk_div_mask(divider->width);
+
+ return divider_recalc_rate(hw, parent_rate, val, divider->table,
+ divider->flags, divider->width);
+}
+
+static int rzv2h_ddiv_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+
+ return divider_determine_rate(hw, req, divider->table, divider->width,
+ divider->flags);
+}
+
+static inline int rzv2h_cpg_wait_ddiv_clk_update_done(void __iomem *base, u8 mon)
+{
+ u32 bitmask = BIT(mon);
+ u32 val;
+
+ if (mon == CSDIV_NO_MON)
+ return 0;
+
+ return readl_poll_timeout_atomic(base + CPG_CLKSTATUS0, val, !(val & bitmask), 10, 200);
+}
+
+static int rzv2h_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+ struct ddiv_clk *ddiv = to_ddiv_clock(divider);
+ struct rzv2h_cpg_priv *priv = ddiv->priv;
+ unsigned long flags = 0;
+ int value;
+ u32 val;
+ int ret;
+
+ value = divider_get_val(rate, parent_rate, divider->table,
+ divider->width, divider->flags);
+ if (value < 0)
+ return value;
+
+ spin_lock_irqsave(divider->lock, flags);
+
+ ret = rzv2h_cpg_wait_ddiv_clk_update_done(priv->base, ddiv->mon);
+ if (ret)
+ goto ddiv_timeout;
+
+ val = readl(divider->reg) | DDIV_DIVCTL_WEN(divider->shift);
+ val &= ~(clk_div_mask(divider->width) << divider->shift);
+ val |= (u32)value << divider->shift;
+ writel(val, divider->reg);
+
+ ret = rzv2h_cpg_wait_ddiv_clk_update_done(priv->base, ddiv->mon);
+
+ddiv_timeout:
+ spin_unlock_irqrestore(divider->lock, flags);
+ return ret;
+}
+
+static const struct clk_ops rzv2h_ddiv_clk_divider_ops = {
+ .recalc_rate = rzv2h_ddiv_recalc_rate,
+ .determine_rate = rzv2h_ddiv_determine_rate,
+ .set_rate = rzv2h_ddiv_set_rate,
+};
+
+static struct clk * __init
+rzv2h_cpg_ddiv_clk_register(const struct cpg_core_clk *core,
+ struct rzv2h_cpg_priv *priv)
+{
+ struct ddiv cfg_ddiv = core->cfg.ddiv;
+ struct clk_init_data init = {};
+ struct device *dev = priv->dev;
+ u8 shift = cfg_ddiv.shift;
+ u8 width = cfg_ddiv.width;
+ const struct clk *parent;
+ const char *parent_name;
+ struct clk_divider *div;
+ struct ddiv_clk *ddiv;
+ int ret;
+
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+
+ if ((shift + width) > 16)
+ return ERR_PTR(-EINVAL);
+
+ ddiv = devm_kzalloc(priv->dev, sizeof(*ddiv), GFP_KERNEL);
+ if (!ddiv)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = core->name;
+ if (cfg_ddiv.no_rmw)
+ init.ops = &clk_divider_ops;
+ else
+ init.ops = &rzv2h_ddiv_clk_divider_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_PARENT;
+
+ ddiv->priv = priv;
+ ddiv->mon = cfg_ddiv.monbit;
+ div = &ddiv->div;
+ div->reg = priv->base + cfg_ddiv.offset;
+ div->shift = shift;
+ div->width = width;
+ div->flags = core->flag;
+ div->lock = &priv->rmw_lock;
+ div->hw.init = &init;
+ div->table = core->dtable;
+
+ ret = devm_clk_hw_register(dev, &div->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return div->hw.clk;
+}
+
+static struct clk * __init
+rzv2h_cpg_mux_clk_register(const struct cpg_core_clk *core,
+ struct rzv2h_cpg_priv *priv)
+{
+ struct smuxed mux = core->cfg.smux;
+ const struct clk_hw *clk_hw;
+
+ clk_hw = devm_clk_hw_register_mux(priv->dev, core->name,
+ core->parent_names, core->num_parents,
+ core->flag, priv->base + mux.offset,
+ mux.shift, mux.width,
+ core->mux_flags, &priv->rmw_lock);
+ if (IS_ERR(clk_hw))
+ return ERR_CAST(clk_hw);
+
+ return clk_hw->clk;
+}
+
+static int
+rzv2h_clk_ff_mod_status_is_enabled(struct clk_hw *hw)
+{
+ struct rzv2h_ff_mod_status_clk *fix = to_rzv2h_ff_mod_status_clk(hw);
+ struct rzv2h_cpg_priv *priv = fix->priv;
+ u32 offset = GET_CLK_MON_OFFSET(fix->conf.mon_index);
+ u32 bitmask = BIT(fix->conf.mon_bit);
+ u32 val;
+
+ val = readl(priv->base + offset);
+ return !!(val & bitmask);
+}
+
+static struct clk * __init
+rzv2h_cpg_fixed_mod_status_clk_register(const struct cpg_core_clk *core,
+ struct rzv2h_cpg_priv *priv)
+{
+ struct rzv2h_ff_mod_status_clk *clk_hw_data;
+ struct clk_init_data init = { };
+ struct clk_fixed_factor *fix;
+ const struct clk *parent;
+ const char *parent_name;
+ int ret;
+
+ WARN_DEBUG(core->parent >= priv->num_core_clks);
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ parent_name = __clk_get_name(parent);
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent))
+ return ERR_CAST(parent);
+
+ clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
+ if (!clk_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+ clk_hw_data->priv = priv;
+ clk_hw_data->conf = core->cfg.fixed_mod;
+
+ init.name = core->name;
+ init.ops = priv->ff_mod_status_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ fix = &clk_hw_data->fix;
+ fix->hw.init = &init;
+ fix->mult = core->mult;
+ fix->div = core->div;
+
+ ret = devm_clk_hw_register(priv->dev, &clk_hw_data->fix.hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return clk_hw_data->fix.hw.clk;
+}
+
+static struct clk
+*rzv2h_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec,
+ void *data)
+{
+ unsigned int clkidx = clkspec->args[1];
+ struct rzv2h_cpg_priv *priv = data;
+ struct device *dev = priv->dev;
+ const char *type;
+ struct clk *clk;
+
+ switch (clkspec->args[0]) {
+ case CPG_CORE:
+ type = "core";
+ if (clkidx > priv->last_dt_core_clk) {
+ dev_err(dev, "Invalid %s clock index %u\n", type, clkidx);
+ return ERR_PTR(-EINVAL);
+ }
+ clk = priv->clks[clkidx];
+ break;
+
+ case CPG_MOD:
+ type = "module";
+ if (clkidx >= priv->num_mod_clks) {
+ dev_err(dev, "Invalid %s clock index %u\n", type, clkidx);
+ return ERR_PTR(-EINVAL);
+ }
+ clk = priv->clks[priv->num_core_clks + clkidx];
+ break;
+
+ default:
+ dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (IS_ERR(clk))
+ dev_err(dev, "Cannot get %s clock %u: %ld\n", type, clkidx,
+ PTR_ERR(clk));
+ else
+ dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n",
+ clkspec->args[0], clkspec->args[1], clk,
+ clk_get_rate(clk));
+ return clk;
+}
+
+static void __init
+rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core,
+ struct rzv2h_cpg_priv *priv)
+{
+ struct clk *clk = ERR_PTR(-EOPNOTSUPP), *parent;
+ unsigned int id = core->id, div = core->div;
+ struct device *dev = priv->dev;
+ const char *parent_name;
+ struct clk_hw *clk_hw;
+
+ WARN_DEBUG(id >= priv->num_core_clks);
+ WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
+
+ switch (core->type) {
+ case CLK_TYPE_IN:
+ clk = of_clk_get_by_name(priv->dev->of_node, core->name);
+ break;
+ case CLK_TYPE_FF:
+ WARN_DEBUG(core->parent >= priv->num_core_clks);
+ parent = priv->clks[core->parent];
+ if (IS_ERR(parent)) {
+ clk = parent;
+ goto fail;
+ }
+
+ parent_name = __clk_get_name(parent);
+ clk_hw = devm_clk_hw_register_fixed_factor(dev, core->name,
+ parent_name, CLK_SET_RATE_PARENT,
+ core->mult, div);
+ if (IS_ERR(clk_hw))
+ clk = ERR_CAST(clk_hw);
+ else
+ clk = clk_hw->clk;
+ break;
+ case CLK_TYPE_FF_MOD_STATUS:
+ if (!priv->ff_mod_status_ops) {
+ priv->ff_mod_status_ops =
+ devm_kzalloc(dev, sizeof(*priv->ff_mod_status_ops), GFP_KERNEL);
+ if (!priv->ff_mod_status_ops) {
+ clk = ERR_PTR(-ENOMEM);
+ goto fail;
+ }
+ memcpy(priv->ff_mod_status_ops, &clk_fixed_factor_ops,
+ sizeof(const struct clk_ops));
+ priv->ff_mod_status_ops->is_enabled = rzv2h_clk_ff_mod_status_is_enabled;
+ }
+ clk = rzv2h_cpg_fixed_mod_status_clk_register(core, priv);
+ break;
+ case CLK_TYPE_PLL:
+ clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_pll_ops);
+ break;
+ case CLK_TYPE_DDIV:
+ clk = rzv2h_cpg_ddiv_clk_register(core, priv);
+ break;
+ case CLK_TYPE_SMUX:
+ clk = rzv2h_cpg_mux_clk_register(core, priv);
+ break;
+ case CLK_TYPE_PLLDSI:
+ clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_plldsi_ops);
+ break;
+ case CLK_TYPE_PLLDSI_DIV:
+ clk = rzv2h_cpg_plldsi_div_clk_register(core, priv);
+ break;
+ case CLK_TYPE_PLLDSI_SMUX:
+ clk = rzv2h_cpg_plldsi_smux_clk_register(core, priv);
+ break;
+ default:
+ goto fail;
+ }
+
+ if (IS_ERR(clk))
+ goto fail;
+
+ dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
+ priv->clks[id] = clk;
+ return;
+
+fail:
+ dev_err(dev, "Failed to register core clock %s: %ld\n",
+ core->name, PTR_ERR(clk));
+}
+
+static void rzv2h_mod_clock_mstop_enable(struct rzv2h_cpg_priv *priv,
+ u32 mstop_data)
+{
+ unsigned long mstop_mask = FIELD_GET(BUS_MSTOP_BITS_MASK, mstop_data);
+ u16 mstop_index = FIELD_GET(BUS_MSTOP_IDX_MASK, mstop_data);
+ atomic_t *mstop = &priv->mstop_count[mstop_index * 16];
+ unsigned long flags;
+ unsigned int i;
+ u32 val = 0;
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+ for_each_set_bit(i, &mstop_mask, 16) {
+ if (!atomic_read(&mstop[i]))
+ val |= BIT(i) << 16;
+ atomic_inc(&mstop[i]);
+ }
+ if (val)
+ writel(val, priv->base + CPG_BUS_MSTOP(mstop_index));
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+}
+
+static void rzv2h_mod_clock_mstop_disable(struct rzv2h_cpg_priv *priv,
+ u32 mstop_data)
+{
+ unsigned long mstop_mask = FIELD_GET(BUS_MSTOP_BITS_MASK, mstop_data);
+ u16 mstop_index = FIELD_GET(BUS_MSTOP_IDX_MASK, mstop_data);
+ atomic_t *mstop = &priv->mstop_count[mstop_index * 16];
+ unsigned long flags;
+ unsigned int i;
+ u32 val = 0;
+
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+ for_each_set_bit(i, &mstop_mask, 16) {
+ if (!atomic_read(&mstop[i]) ||
+ atomic_dec_and_test(&mstop[i]))
+ val |= BIT(i) << 16 | BIT(i);
+ }
+ if (val)
+ writel(val, priv->base + CPG_BUS_MSTOP(mstop_index));
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+}
+
+static int rzv2h_parent_clk_mux_to_index(struct clk_hw *hw)
+{
+ struct clk_hw *parent_hw;
+ struct clk *parent_clk;
+ struct clk_mux *mux;
+ u32 val;
+
+ /* This will always succeed, so no need to check for IS_ERR() */
+ parent_clk = clk_get_parent(hw->clk);
+
+ parent_hw = __clk_get_hw(parent_clk);
+ mux = to_clk_mux(parent_hw);
+
+ val = readl(mux->reg) >> mux->shift;
+ val &= mux->mask;
+ return clk_mux_val_to_index(parent_hw, mux->table, 0, val);
+}
+
+static int rzv2h_mod_clock_is_enabled(struct clk_hw *hw)
+{
+ struct mod_clock *clock = to_mod_clock(hw);
+ struct rzv2h_cpg_priv *priv = clock->priv;
+ int mon_index = clock->mon_index;
+ u32 bitmask;
+ u32 offset;
+
+ if (clock->ext_clk_mux_index >= 0 &&
+ rzv2h_parent_clk_mux_to_index(hw) == clock->ext_clk_mux_index)
+ mon_index = -1;
+
+ if (mon_index >= 0) {
+ offset = GET_CLK_MON_OFFSET(mon_index);
+ bitmask = BIT(clock->mon_bit);
+
+ if (!(readl(priv->base + offset) & bitmask))
+ return 0;
+ }
+
+ offset = GET_CLK_ON_OFFSET(clock->on_index);
+ bitmask = BIT(clock->on_bit);
+
+ return readl(priv->base + offset) & bitmask;
+}
+
+static int rzv2h_mod_clock_endisable(struct clk_hw *hw, bool enable)
+{
+ bool enabled = rzv2h_mod_clock_is_enabled(hw);
+ struct mod_clock *clock = to_mod_clock(hw);
+ unsigned int reg = GET_CLK_ON_OFFSET(clock->on_index);
+ struct rzv2h_cpg_priv *priv = clock->priv;
+ u32 bitmask = BIT(clock->on_bit);
+ struct device *dev = priv->dev;
+ u32 value;
+ int error;
+
+ dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", reg, hw->clk,
+ str_on_off(enable));
+
+ if (enabled == enable)
+ return 0;
+
+ value = bitmask << 16;
+ if (enable) {
+ value |= bitmask;
+ writel(value, priv->base + reg);
+ if (clock->mstop_data != BUS_MSTOP_NONE)
+ rzv2h_mod_clock_mstop_enable(priv, clock->mstop_data);
+ } else {
+ if (clock->mstop_data != BUS_MSTOP_NONE)
+ rzv2h_mod_clock_mstop_disable(priv, clock->mstop_data);
+ writel(value, priv->base + reg);
+ }
+
+ if (!enable || clock->mon_index < 0)
+ return 0;
+
+ reg = GET_CLK_MON_OFFSET(clock->mon_index);
+ bitmask = BIT(clock->mon_bit);
+ error = readl_poll_timeout_atomic(priv->base + reg, value,
+ value & bitmask, 0, 10);
+ if (error)
+ dev_err(dev, "Failed to enable CLK_ON 0x%x/%pC\n",
+ GET_CLK_ON_OFFSET(clock->on_index), hw->clk);
+
+ return error;
+}
+
+static int rzv2h_mod_clock_enable(struct clk_hw *hw)
+{
+ return rzv2h_mod_clock_endisable(hw, true);
+}
+
+static void rzv2h_mod_clock_disable(struct clk_hw *hw)
+{
+ rzv2h_mod_clock_endisable(hw, false);
+}
+
+static const struct clk_ops rzv2h_mod_clock_ops = {
+ .enable = rzv2h_mod_clock_enable,
+ .disable = rzv2h_mod_clock_disable,
+ .is_enabled = rzv2h_mod_clock_is_enabled,
+};
+
+static void __init
+rzv2h_cpg_register_mod_clk(const struct rzv2h_mod_clk *mod,
+ struct rzv2h_cpg_priv *priv)
+{
+ struct mod_clock *clock = NULL;
+ struct device *dev = priv->dev;
+ struct clk_init_data init;
+ struct clk *parent, *clk;
+ const char *parent_name;
+ unsigned int id;
+ int ret;
+
+ id = GET_MOD_CLK_ID(priv->num_core_clks, mod->on_index, mod->on_bit);
+ WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks);
+ WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
+ WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
+
+ parent = priv->clks[mod->parent];
+ if (IS_ERR(parent)) {
+ clk = parent;
+ goto fail;
+ }
+
+ clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL);
+ if (!clock) {
+ clk = ERR_PTR(-ENOMEM);
+ goto fail;
+ }
+
+ init.name = mod->name;
+ init.ops = &rzv2h_mod_clock_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ if (mod->critical)
+ init.flags |= CLK_IS_CRITICAL;
+
+ parent_name = __clk_get_name(parent);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clock->on_index = mod->on_index;
+ clock->on_bit = mod->on_bit;
+ clock->mon_index = mod->mon_index;
+ clock->mon_bit = mod->mon_bit;
+ clock->no_pm = mod->no_pm;
+ clock->ext_clk_mux_index = mod->ext_clk_mux_index;
+ clock->priv = priv;
+ clock->hw.init = &init;
+ clock->mstop_data = mod->mstop_data;
+
+ ret = devm_clk_hw_register(dev, &clock->hw);
+ if (ret) {
+ clk = ERR_PTR(ret);
+ goto fail;
+ }
+
+ priv->clks[id] = clock->hw.clk;
+
+ /*
+ * Ensure the module clocks and MSTOP bits are synchronized when they are
+ * turned ON by the bootloader. Enable MSTOP bits for module clocks that were
+ * turned ON in an earlier boot stage.
+ */
+ if (clock->mstop_data != BUS_MSTOP_NONE &&
+ !mod->critical && rzv2h_mod_clock_is_enabled(&clock->hw)) {
+ rzv2h_mod_clock_mstop_enable(priv, clock->mstop_data);
+ } else if (clock->mstop_data != BUS_MSTOP_NONE && mod->critical) {
+ unsigned long mstop_mask = FIELD_GET(BUS_MSTOP_BITS_MASK, clock->mstop_data);
+ u16 mstop_index = FIELD_GET(BUS_MSTOP_IDX_MASK, clock->mstop_data);
+ atomic_t *mstop = &priv->mstop_count[mstop_index * 16];
+ unsigned long flags;
+ unsigned int i;
+ u32 val = 0;
+
+ /*
+ * Critical clocks are turned ON immediately upon registration, and the
+ * MSTOP counter is updated through the rzv2h_mod_clock_enable() path.
+ * However, if the critical clocks were already turned ON by the initial
+ * bootloader, synchronize the atomic counter here and clear the MSTOP bit.
+ */
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+ for_each_set_bit(i, &mstop_mask, 16) {
+ if (atomic_read(&mstop[i]))
+ continue;
+ val |= BIT(i) << 16;
+ atomic_inc(&mstop[i]);
+ }
+ if (val)
+ writel(val, priv->base + CPG_BUS_MSTOP(mstop_index));
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+ }
+
+ return;
+
+fail:
+ dev_err(dev, "Failed to register module clock %s: %ld\n",
+ mod->name, PTR_ERR(clk));
+}
+
+static int __rzv2h_cpg_assert(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct rzv2h_cpg_priv *priv = rcdev_to_priv(rcdev);
+ unsigned int reg = GET_RST_OFFSET(priv->resets[id].reset_index);
+ u32 mask = BIT(priv->resets[id].reset_bit);
+ u8 monbit = priv->resets[id].mon_bit;
+ u32 value = mask << 16;
+ u32 mon;
+ int ret;
+
+ dev_dbg(rcdev->dev, "%s id:%ld offset:0x%x\n",
+ assert ? "assert" : "deassert", id, reg);
+
+ if (!assert)
+ value |= mask;
+ writel(value, priv->base + reg);
+
+ reg = GET_RST_MON_OFFSET(priv->resets[id].mon_index);
+ mask = BIT(monbit);
+
+ ret = readl_poll_timeout_atomic(priv->base + reg, mon,
+ assert == !!(mon & mask), 10, 200);
+ if (ret) {
+ value ^= mask;
+ writel(value, priv->base + GET_RST_OFFSET(priv->resets[id].reset_index));
+ }
+
+ return ret;
+}
+
+static int rzv2h_cpg_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return __rzv2h_cpg_assert(rcdev, id, true);
+}
+
+static int rzv2h_cpg_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return __rzv2h_cpg_assert(rcdev, id, false);
+}
+
+static int rzv2h_cpg_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ int ret;
+
+ ret = rzv2h_cpg_assert(rcdev, id);
+ if (ret)
+ return ret;
+
+ return rzv2h_cpg_deassert(rcdev, id);
+}
+
+static int rzv2h_cpg_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct rzv2h_cpg_priv *priv = rcdev_to_priv(rcdev);
+ unsigned int reg = GET_RST_MON_OFFSET(priv->resets[id].mon_index);
+ u8 monbit = priv->resets[id].mon_bit;
+
+ return !!(readl(priv->base + reg) & BIT(monbit));
+}
+
+static const struct reset_control_ops rzv2h_cpg_reset_ops = {
+ .reset = rzv2h_cpg_reset,
+ .assert = rzv2h_cpg_assert,
+ .deassert = rzv2h_cpg_deassert,
+ .status = rzv2h_cpg_status,
+};
+
+static int rzv2h_cpg_reset_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ struct rzv2h_cpg_priv *priv = rcdev_to_priv(rcdev);
+ unsigned int id = reset_spec->args[0];
+ u8 rst_index = id / 16;
+ u8 rst_bit = id % 16;
+ unsigned int i;
+
+ for (i = 0; i < rcdev->nr_resets; i++) {
+ if (rst_index == priv->resets[i].reset_index &&
+ rst_bit == priv->resets[i].reset_bit)
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+static int rzv2h_cpg_reset_controller_register(struct rzv2h_cpg_priv *priv)
+{
+ priv->rcdev.ops = &rzv2h_cpg_reset_ops;
+ priv->rcdev.of_node = priv->dev->of_node;
+ priv->rcdev.dev = priv->dev;
+ priv->rcdev.of_reset_n_cells = 1;
+ priv->rcdev.of_xlate = rzv2h_cpg_reset_xlate;
+ priv->rcdev.nr_resets = priv->num_resets;
+
+ return devm_reset_controller_register(priv->dev, &priv->rcdev);
+}
+
+/**
+ * struct rzv2h_cpg_pd - RZ/V2H power domain data structure
+ * @priv: pointer to CPG private data structure
+ * @genpd: generic PM domain
+ */
+struct rzv2h_cpg_pd {
+ struct rzv2h_cpg_priv *priv;
+ struct generic_pm_domain genpd;
+};
+
+static bool rzv2h_cpg_is_pm_clk(struct rzv2h_cpg_pd *pd,
+ const struct of_phandle_args *clkspec)
+{
+ if (clkspec->np != pd->genpd.dev.of_node || clkspec->args_count != 2)
+ return false;
+
+ switch (clkspec->args[0]) {
+ case CPG_MOD: {
+ struct rzv2h_cpg_priv *priv = pd->priv;
+ unsigned int id = clkspec->args[1];
+ struct mod_clock *clock;
+
+ if (id >= priv->num_mod_clks)
+ return false;
+
+ if (priv->clks[priv->num_core_clks + id] == ERR_PTR(-ENOENT))
+ return false;
+
+ clock = to_mod_clock(__clk_get_hw(priv->clks[priv->num_core_clks + id]));
+
+ return !clock->no_pm;
+ }
+
+ case CPG_CORE:
+ default:
+ return false;
+ }
+}
+
+static int rzv2h_cpg_attach_dev(struct generic_pm_domain *domain, struct device *dev)
+{
+ struct rzv2h_cpg_pd *pd = container_of(domain, struct rzv2h_cpg_pd, genpd);
+ struct device_node *np = dev->of_node;
+ struct of_phandle_args clkspec;
+ bool once = true;
+ struct clk *clk;
+ unsigned int i;
+ int error;
+
+ for (i = 0; !of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, &clkspec); i++) {
+ if (!rzv2h_cpg_is_pm_clk(pd, &clkspec)) {
+ of_node_put(clkspec.np);
+ continue;
+ }
+
+ if (once) {
+ once = false;
+ error = pm_clk_create(dev);
+ if (error) {
+ of_node_put(clkspec.np);
+ goto err;
+ }
+ }
+ clk = of_clk_get_from_provider(&clkspec);
+ of_node_put(clkspec.np);
+ if (IS_ERR(clk)) {
+ error = PTR_ERR(clk);
+ goto fail_destroy;
+ }
+
+ error = pm_clk_add_clk(dev, clk);
+ if (error) {
+ dev_err(dev, "pm_clk_add_clk failed %d\n",
+ error);
+ goto fail_put;
+ }
+ }
+
+ return 0;
+
+fail_put:
+ clk_put(clk);
+
+fail_destroy:
+ pm_clk_destroy(dev);
+err:
+ return error;
+}
+
+static void rzv2h_cpg_detach_dev(struct generic_pm_domain *unused, struct device *dev)
+{
+ if (!pm_clk_no_clocks(dev))
+ pm_clk_destroy(dev);
+}
+
+static void rzv2h_cpg_genpd_remove_simple(void *data)
+{
+ pm_genpd_remove(data);
+}
+
+static int __init rzv2h_cpg_add_pm_domains(struct rzv2h_cpg_priv *priv)
+{
+ struct device *dev = priv->dev;
+ struct device_node *np = dev->of_node;
+ struct rzv2h_cpg_pd *pd;
+ int ret;
+
+ pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ pd->genpd.name = np->name;
+ pd->priv = priv;
+ pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
+ pd->genpd.attach_dev = rzv2h_cpg_attach_dev;
+ pd->genpd.detach_dev = rzv2h_cpg_detach_dev;
+ ret = pm_genpd_init(&pd->genpd, &pm_domain_always_on_gov, false);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, rzv2h_cpg_genpd_remove_simple, &pd->genpd);
+ if (ret)
+ return ret;
+
+ return of_genpd_add_provider_simple(np, &pd->genpd);
+}
+
+static void rzv2h_cpg_del_clk_provider(void *data)
+{
+ of_clk_del_provider(data);
+}
+
+static int __init rzv2h_cpg_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct rzv2h_cpg_info *info;
+ struct rzv2h_cpg_priv *priv;
+ unsigned int nclks, i;
+ struct clk **clks;
+ int error;
+
+ info = of_device_get_match_data(dev);
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->rmw_lock);
+
+ priv->dev = dev;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ nclks = info->num_total_core_clks + info->num_hw_mod_clks;
+ clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL);
+ if (!clks)
+ return -ENOMEM;
+
+ priv->mstop_count = devm_kcalloc(dev, info->num_mstop_bits,
+ sizeof(*priv->mstop_count), GFP_KERNEL);
+ if (!priv->mstop_count)
+ return -ENOMEM;
+
+ /* Adjust for CPG_BUS_m_MSTOP starting from m = 1 */
+ priv->mstop_count -= 16;
+
+ priv->resets = devm_kmemdup_array(dev, info->resets, info->num_resets,
+ sizeof(*info->resets), GFP_KERNEL);
+ if (!priv->resets)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, priv);
+ priv->clks = clks;
+ priv->num_core_clks = info->num_total_core_clks;
+ priv->num_mod_clks = info->num_hw_mod_clks;
+ priv->last_dt_core_clk = info->last_dt_core_clk;
+ priv->num_resets = info->num_resets;
+
+ for (i = 0; i < nclks; i++)
+ clks[i] = ERR_PTR(-ENOENT);
+
+ for (i = 0; i < info->num_core_clks; i++)
+ rzv2h_cpg_register_core_clk(&info->core_clks[i], priv);
+
+ for (i = 0; i < info->num_mod_clks; i++)
+ rzv2h_cpg_register_mod_clk(&info->mod_clks[i], priv);
+
+ error = of_clk_add_provider(np, rzv2h_cpg_clk_src_twocell_get, priv);
+ if (error)
+ return error;
+
+ error = devm_add_action_or_reset(dev, rzv2h_cpg_del_clk_provider, np);
+ if (error)
+ return error;
+
+ error = rzv2h_cpg_add_pm_domains(priv);
+ if (error)
+ return error;
+
+ error = rzv2h_cpg_reset_controller_register(priv);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+static const struct of_device_id rzv2h_cpg_match[] = {
+#ifdef CONFIG_CLK_R9A09G047
+ {
+ .compatible = "renesas,r9a09g047-cpg",
+ .data = &r9a09g047_cpg_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R9A09G056
+ {
+ .compatible = "renesas,r9a09g056-cpg",
+ .data = &r9a09g056_cpg_info,
+ },
+#endif
+#ifdef CONFIG_CLK_R9A09G057
+ {
+ .compatible = "renesas,r9a09g057-cpg",
+ .data = &r9a09g057_cpg_info,
+ },
+#endif
+ { /* sentinel */ }
+};
+
+static struct platform_driver rzv2h_cpg_driver = {
+ .driver = {
+ .name = "rzv2h-cpg",
+ .of_match_table = rzv2h_cpg_match,
+ },
+};
+
+static int __init rzv2h_cpg_init(void)
+{
+ return platform_driver_probe(&rzv2h_cpg_driver, rzv2h_cpg_probe);
+}
+
+subsys_initcall(rzv2h_cpg_init);
+
+MODULE_DESCRIPTION("Renesas RZ/V2H CPG Driver");
diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h
new file mode 100644
index 000000000..dec0f7b62
--- /dev/null
+++ b/drivers/clk/renesas/rzv2h-cpg.h
@@ -0,0 +1,380 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Renesas RZ/V2H(P) Clock Pulse Generator
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+
+#ifndef __RENESAS_RZV2H_CPG_H__
+#define __RENESAS_RZV2H_CPG_H__
+
+#include <linux/bitfield.h>
+#include <linux/types.h>
+
+/**
+ * struct pll - Structure for PLL configuration
+ *
+ * @offset: STBY register offset
+ * @has_clkn: Flag to indicate if CLK1/2 are accessible or not
+ * @instance: PLL instance number
+ */
+struct pll {
+ unsigned int offset:9;
+ unsigned int has_clkn:1;
+ unsigned int instance:2;
+ const struct rzv2h_pll_limits *limits;
+};
+
+#define PLL_PACK_LIMITS(_offset, _has_clkn, _instance, _limits) \
+ ((struct pll){ \
+ .offset = _offset, \
+ .has_clkn = _has_clkn, \
+ .instance = _instance, \
+ .limits = _limits \
+ })
+
+#define PLL_PACK(_offset, _has_clkn, _instance) \
+ PLL_PACK_LIMITS(_offset, _has_clkn, _instance, NULL)
+
+#define PLLCA55 PLL_PACK(0x60, 1, 0)
+#define PLLGPU PLL_PACK(0x120, 1, 0)
+
+/**
+ * struct ddiv - Structure for dynamic switching divider
+ *
+ * @offset: register offset
+ * @shift: position of the divider bit
+ * @width: width of the divider
+ * @monbit: monitor bit in CPG_CLKSTATUS0 register
+ * @no_rmw: flag to indicate if the register is read-modify-write
+ * (1: no RMW, 0: RMW)
+ */
+struct ddiv {
+ unsigned int offset:11;
+ unsigned int shift:4;
+ unsigned int width:4;
+ unsigned int monbit:5;
+ unsigned int no_rmw:1;
+};
+
+/*
+ * On RZ/V2H(P), the dynamic divider clock supports up to 19 monitor bits,
+ * while on RZ/G3E, it supports up to 16 monitor bits. Use the maximum value
+ * `0x1f` to indicate that monitor bits are not supported for static divider
+ * clocks.
+ */
+#define CSDIV_NO_MON (0x1f)
+
+#define DDIV_PACK(_offset, _shift, _width, _monbit) \
+ ((struct ddiv){ \
+ .offset = _offset, \
+ .shift = _shift, \
+ .width = _width, \
+ .monbit = _monbit \
+ })
+
+#define DDIV_PACK_NO_RMW(_offset, _shift, _width, _monbit) \
+ ((struct ddiv){ \
+ .offset = (_offset), \
+ .shift = (_shift), \
+ .width = (_width), \
+ .monbit = (_monbit), \
+ .no_rmw = 1 \
+ })
+
+/**
+ * struct smuxed - Structure for static muxed clocks
+ *
+ * @offset: register offset
+ * @shift: position of the divider field
+ * @width: width of the divider field
+ */
+struct smuxed {
+ unsigned int offset:11;
+ unsigned int shift:4;
+ unsigned int width:4;
+};
+
+#define SMUX_PACK(_offset, _shift, _width) \
+ ((struct smuxed){ \
+ .offset = (_offset), \
+ .shift = (_shift), \
+ .width = (_width), \
+ })
+
+/**
+ * struct fixed_mod_conf - Structure for fixed module configuration
+ *
+ * @mon_index: monitor index
+ * @mon_bit: monitor bit
+ */
+struct fixed_mod_conf {
+ u8 mon_index;
+ u8 mon_bit;
+};
+
+#define FIXED_MOD_CONF_PACK(_index, _bit) \
+ ((struct fixed_mod_conf){ \
+ .mon_index = (_index), \
+ .mon_bit = (_bit), \
+ })
+
+#define CPG_SSEL0 (0x300)
+#define CPG_SSEL1 (0x304)
+#define CPG_SSEL3 (0x30C)
+#define CPG_CDDIV0 (0x400)
+#define CPG_CDDIV1 (0x404)
+#define CPG_CDDIV2 (0x408)
+#define CPG_CDDIV3 (0x40C)
+#define CPG_CDDIV4 (0x410)
+#define CPG_CSDIV0 (0x500)
+#define CPG_CSDIV1 (0x504)
+
+#define CDDIV0_DIVCTL1 DDIV_PACK(CPG_CDDIV0, 4, 3, 1)
+#define CDDIV0_DIVCTL2 DDIV_PACK(CPG_CDDIV0, 8, 3, 2)
+#define CDDIV1_DIVCTL0 DDIV_PACK(CPG_CDDIV1, 0, 2, 4)
+#define CDDIV1_DIVCTL1 DDIV_PACK(CPG_CDDIV1, 4, 2, 5)
+#define CDDIV1_DIVCTL2 DDIV_PACK(CPG_CDDIV1, 8, 2, 6)
+#define CDDIV1_DIVCTL3 DDIV_PACK(CPG_CDDIV1, 12, 2, 7)
+#define CDDIV2_DIVCTL3 DDIV_PACK(CPG_CDDIV2, 12, 3, 11)
+#define CDDIV3_DIVCTL1 DDIV_PACK(CPG_CDDIV3, 4, 3, 13)
+#define CDDIV3_DIVCTL2 DDIV_PACK(CPG_CDDIV3, 8, 3, 14)
+#define CDDIV3_DIVCTL3 DDIV_PACK(CPG_CDDIV3, 12, 1, 15)
+#define CDDIV4_DIVCTL0 DDIV_PACK(CPG_CDDIV4, 0, 1, 16)
+#define CDDIV4_DIVCTL1 DDIV_PACK(CPG_CDDIV4, 4, 1, 17)
+#define CDDIV4_DIVCTL2 DDIV_PACK(CPG_CDDIV4, 8, 1, 18)
+
+#define CSDIV0_DIVCTL0 DDIV_PACK(CPG_CSDIV0, 0, 2, CSDIV_NO_MON)
+#define CSDIV0_DIVCTL1 DDIV_PACK(CPG_CSDIV0, 4, 2, CSDIV_NO_MON)
+#define CSDIV0_DIVCTL2 DDIV_PACK(CPG_CSDIV0, 8, 2, CSDIV_NO_MON)
+#define CSDIV0_DIVCTL3 DDIV_PACK_NO_RMW(CPG_CSDIV0, 12, 2, CSDIV_NO_MON)
+#define CSDIV1_DIVCTL2 DDIV_PACK(CPG_CSDIV1, 8, 4, CSDIV_NO_MON)
+#define CSDIV1_DIVCTL3 DDIV_PACK(CPG_CSDIV1, 12, 4, CSDIV_NO_MON)
+
+#define SSEL0_SELCTL2 SMUX_PACK(CPG_SSEL0, 8, 1)
+#define SSEL0_SELCTL3 SMUX_PACK(CPG_SSEL0, 12, 1)
+#define SSEL1_SELCTL0 SMUX_PACK(CPG_SSEL1, 0, 1)
+#define SSEL1_SELCTL1 SMUX_PACK(CPG_SSEL1, 4, 1)
+#define SSEL1_SELCTL2 SMUX_PACK(CPG_SSEL1, 8, 1)
+#define SSEL1_SELCTL3 SMUX_PACK(CPG_SSEL1, 12, 1)
+#define SSEL3_SELCTL0 SMUX_PACK(CPG_SSEL3, 0, 1)
+#define SSEL3_SELCTL1 SMUX_PACK(CPG_SSEL3, 4, 1)
+
+#define BUS_MSTOP_IDX_MASK GENMASK(31, 16)
+#define BUS_MSTOP_BITS_MASK GENMASK(15, 0)
+#define BUS_MSTOP(idx, mask) (FIELD_PREP_CONST(BUS_MSTOP_IDX_MASK, (idx)) | \
+ FIELD_PREP_CONST(BUS_MSTOP_BITS_MASK, (mask)))
+#define BUS_MSTOP_NONE GENMASK(31, 0)
+
+#define FIXED_MOD_CONF_XSPI FIXED_MOD_CONF_PACK(5, 1)
+
+/**
+ * Definitions of CPG Core Clocks
+ *
+ * These include:
+ * - Clock outputs exported to DT
+ * - External input clocks
+ * - Internal CPG clocks
+ */
+struct cpg_core_clk {
+ const char *name;
+ unsigned int id;
+ unsigned int parent;
+ unsigned int div;
+ unsigned int mult;
+ unsigned int type;
+ union {
+ unsigned int conf;
+ struct ddiv ddiv;
+ struct pll pll;
+ struct smuxed smux;
+ struct fixed_mod_conf fixed_mod;
+ } cfg;
+ const struct clk_div_table *dtable;
+ const char * const *parent_names;
+ unsigned int num_parents;
+ u8 mux_flags;
+ u32 flag;
+};
+
+enum clk_types {
+ /* Generic */
+ CLK_TYPE_IN, /* External Clock Input */
+ CLK_TYPE_FF, /* Fixed Factor Clock */
+ CLK_TYPE_FF_MOD_STATUS, /* Fixed Factor Clock which can report the status of module clock */
+ CLK_TYPE_PLL,
+ CLK_TYPE_DDIV, /* Dynamic Switching Divider */
+ CLK_TYPE_SMUX, /* Static Mux */
+ CLK_TYPE_PLLDSI, /* PLLDSI */
+ CLK_TYPE_PLLDSI_DIV, /* PLLDSI divider */
+ CLK_TYPE_PLLDSI_SMUX, /* PLLDSI Static Mux */
+};
+
+#define DEF_TYPE(_name, _id, _type...) \
+ { .name = _name, .id = _id, .type = _type }
+#define DEF_BASE(_name, _id, _type, _parent...) \
+ DEF_TYPE(_name, _id, _type, .parent = _parent)
+#define DEF_PLL(_name, _id, _parent, _pll_packed) \
+ DEF_TYPE(_name, _id, CLK_TYPE_PLL, .parent = _parent, .cfg.pll = _pll_packed)
+#define DEF_INPUT(_name, _id) \
+ DEF_TYPE(_name, _id, CLK_TYPE_IN)
+#define DEF_FIXED(_name, _id, _parent, _mult, _div) \
+ DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
+#define DEF_FIXED_MOD_STATUS(_name, _id, _parent, _mult, _div, _gate) \
+ DEF_BASE(_name, _id, CLK_TYPE_FF_MOD_STATUS, _parent, .div = _div, \
+ .mult = _mult, .cfg.fixed_mod = _gate)
+#define DEF_DDIV(_name, _id, _parent, _ddiv_packed, _dtable) \
+ DEF_TYPE(_name, _id, CLK_TYPE_DDIV, \
+ .cfg.ddiv = _ddiv_packed, \
+ .parent = _parent, \
+ .dtable = _dtable, \
+ .flag = CLK_DIVIDER_HIWORD_MASK)
+#define DEF_CSDIV(_name, _id, _parent, _ddiv_packed, _dtable) \
+ DEF_DDIV(_name, _id, _parent, _ddiv_packed, _dtable)
+#define DEF_SMUX(_name, _id, _smux_packed, _parent_names) \
+ DEF_TYPE(_name, _id, CLK_TYPE_SMUX, \
+ .cfg.smux = _smux_packed, \
+ .parent_names = _parent_names, \
+ .num_parents = ARRAY_SIZE(_parent_names), \
+ .flag = CLK_SET_RATE_PARENT, \
+ .mux_flags = CLK_MUX_HIWORD_MASK)
+#define DEF_PLLDSI(_name, _id, _parent, _pll_packed) \
+ DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI, .parent = _parent, .cfg.pll = _pll_packed)
+#define DEF_PLLDSI_DIV(_name, _id, _parent, _ddiv_packed, _dtable) \
+ DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI_DIV, \
+ .cfg.ddiv = _ddiv_packed, \
+ .dtable = _dtable, \
+ .parent = _parent, \
+ .flag = CLK_SET_RATE_PARENT)
+#define DEF_PLLDSI_SMUX(_name, _id, _smux_packed, _parent_names) \
+ DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI_SMUX, \
+ .cfg.smux = _smux_packed, \
+ .parent_names = _parent_names, \
+ .num_parents = ARRAY_SIZE(_parent_names), \
+ .flag = CLK_SET_RATE_PARENT, \
+ .mux_flags = CLK_MUX_HIWORD_MASK)
+
+/**
+ * struct rzv2h_mod_clk - Module Clocks definitions
+ *
+ * @name: handle between common and hardware-specific interfaces
+ * @mstop_data: packed data mstop register offset and mask
+ * @parent: id of parent clock
+ * @critical: flag to indicate the clock is critical
+ * @no_pm: flag to indicate PM is not supported
+ * @on_index: control register index
+ * @on_bit: ON bit
+ * @mon_index: monitor register index
+ * @mon_bit: monitor bit
+ * @ext_clk_mux_index: mux index for external clock source, or -1 if internal
+ */
+struct rzv2h_mod_clk {
+ const char *name;
+ u32 mstop_data;
+ u16 parent;
+ bool critical;
+ bool no_pm;
+ u8 on_index;
+ u8 on_bit;
+ s8 mon_index;
+ u8 mon_bit;
+ s8 ext_clk_mux_index;
+};
+
+#define DEF_MOD_BASE(_name, _mstop, _parent, _critical, _no_pm, _onindex, \
+ _onbit, _monindex, _monbit, _ext_clk_mux_index) \
+ { \
+ .name = (_name), \
+ .mstop_data = (_mstop), \
+ .parent = (_parent), \
+ .critical = (_critical), \
+ .no_pm = (_no_pm), \
+ .on_index = (_onindex), \
+ .on_bit = (_onbit), \
+ .mon_index = (_monindex), \
+ .mon_bit = (_monbit), \
+ .ext_clk_mux_index = (_ext_clk_mux_index), \
+ }
+
+#define DEF_MOD(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \
+ DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex, _onbit, _monindex, _monbit, -1)
+
+#define DEF_MOD_CRITICAL(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \
+ DEF_MOD_BASE(_name, _mstop, _parent, true, false, _onindex, _onbit, _monindex, _monbit, -1)
+
+#define DEF_MOD_NO_PM(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \
+ DEF_MOD_BASE(_name, _mstop, _parent, false, true, _onindex, _onbit, _monindex, _monbit, -1)
+
+#define DEF_MOD_MUX_EXTERNAL(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop, \
+ _ext_clk_mux_index) \
+ DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex, _onbit, _monindex, _monbit, \
+ _ext_clk_mux_index)
+
+/**
+ * struct rzv2h_reset - Reset definitions
+ *
+ * @reset_index: reset register index
+ * @reset_bit: reset bit
+ * @mon_index: monitor register index
+ * @mon_bit: monitor bit
+ */
+struct rzv2h_reset {
+ u8 reset_index;
+ u8 reset_bit;
+ u8 mon_index;
+ u8 mon_bit;
+};
+
+#define DEF_RST_BASE(_resindex, _resbit, _monindex, _monbit) \
+ { \
+ .reset_index = (_resindex), \
+ .reset_bit = (_resbit), \
+ .mon_index = (_monindex), \
+ .mon_bit = (_monbit), \
+ }
+
+#define DEF_RST(_resindex, _resbit, _monindex, _monbit) \
+ DEF_RST_BASE(_resindex, _resbit, _monindex, _monbit)
+
+/**
+ * struct rzv2h_cpg_info - SoC-specific CPG Description
+ *
+ * @core_clks: Array of Core Clock definitions
+ * @num_core_clks: Number of entries in core_clks[]
+ * @last_dt_core_clk: ID of the last Core Clock exported to DT
+ * @num_total_core_clks: Total number of Core Clocks (exported + internal)
+ *
+ * @mod_clks: Array of Module Clock definitions
+ * @num_mod_clks: Number of entries in mod_clks[]
+ * @num_hw_mod_clks: Number of Module Clocks supported by the hardware
+ *
+ * @resets: Array of Module Reset definitions
+ * @num_resets: Number of entries in resets[]
+ *
+ * @num_mstop_bits: Maximum number of MSTOP bits supported, equivalent to the
+ * number of CPG_BUS_m_MSTOP registers multiplied by 16.
+ */
+struct rzv2h_cpg_info {
+ /* Core Clocks */
+ const struct cpg_core_clk *core_clks;
+ unsigned int num_core_clks;
+ unsigned int last_dt_core_clk;
+ unsigned int num_total_core_clks;
+
+ /* Module Clocks */
+ const struct rzv2h_mod_clk *mod_clks;
+ unsigned int num_mod_clks;
+ unsigned int num_hw_mod_clks;
+
+ /* Resets */
+ const struct rzv2h_reset *resets;
+ unsigned int num_resets;
+
+ unsigned int num_mstop_bits;
+};
+
+extern const struct rzv2h_cpg_info r9a09g047_cpg_info;
+extern const struct rzv2h_cpg_info r9a09g056_cpg_info;
+extern const struct rzv2h_cpg_info r9a09g057_cpg_info;
+
+#endif /* __RENESAS_RZV2H_CPG_H__ */