aboutsummaryrefslogtreecommitdiff
path: root/drivers/clk/renesas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/renesas')
-rw-r--r--drivers/clk/renesas/Kconfig102
-rw-r--r--drivers/clk/renesas/Makefile17
-rw-r--r--drivers/clk/renesas/clk-div6.c83
-rw-r--r--drivers/clk/renesas/clk-mstp.c9
-rw-r--r--drivers/clk/renesas/clk-rcar-gen2.c457
-rw-r--r--drivers/clk/renesas/clk-rz.c4
-rw-r--r--drivers/clk/renesas/clk-sh73a0.c2
-rw-r--r--drivers/clk/renesas/r7s9210-cpg-mssr.c3
-rw-r--r--drivers/clk/renesas/r8a7742-cpg-mssr.c276
-rw-r--r--drivers/clk/renesas/r8a7743-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a7745-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a77470-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a774a1-cpg-mssr.c22
-rw-r--r--drivers/clk/renesas/r8a774b1-cpg-mssr.c339
-rw-r--r--drivers/clk/renesas/r8a774c0-cpg-mssr.c19
-rw-r--r--drivers/clk/renesas/r8a774e1-cpg-mssr.c352
-rw-r--r--drivers/clk/renesas/r8a7790-cpg-mssr.c4
-rw-r--r--drivers/clk/renesas/r8a7791-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a7792-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a7794-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a7795-cpg-mssr.c28
-rw-r--r--drivers/clk/renesas/r8a7796-cpg-mssr.c53
-rw-r--r--drivers/clk/renesas/r8a77965-cpg-mssr.c33
-rw-r--r--drivers/clk/renesas/r8a77970-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a77980-cpg-mssr.c15
-rw-r--r--drivers/clk/renesas/r8a77990-cpg-mssr.c26
-rw-r--r--drivers/clk/renesas/r8a77995-cpg-mssr.c21
-rw-r--r--drivers/clk/renesas/r8a779a0-cpg-mssr.c300
-rw-r--r--drivers/clk/renesas/r8a779f0-cpg-mssr.c205
-rw-r--r--drivers/clk/renesas/r8a779g0-cpg-mssr.c218
-rw-r--r--drivers/clk/renesas/r9a06g032-clocks.c90
-rw-r--r--drivers/clk/renesas/r9a07g043-cpg.c320
-rw-r--r--drivers/clk/renesas/r9a07g044-cpg.c448
-rw-r--r--drivers/clk/renesas/r9a09g011-cpg.c172
-rw-r--r--drivers/clk/renesas/rcar-cpg-lib.c196
-rw-r--r--drivers/clk/renesas/rcar-cpg-lib.h43
-rw-r--r--drivers/clk/renesas/rcar-gen2-cpg.c28
-rw-r--r--drivers/clk/renesas/rcar-gen2-cpg.h8
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.c572
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.h12
-rw-r--r--drivers/clk/renesas/rcar-gen4-cpg.c310
-rw-r--r--drivers/clk/renesas/rcar-gen4-cpg.h79
-rw-r--r--drivers/clk/renesas/rcar-usb2-clock-sel.c71
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.c247
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.h19
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.c1434
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.h275
47 files changed, 5832 insertions, 1094 deletions
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
index b879e3e3a6b4..cacaf9b87d26 100644
--- a/drivers/clk/renesas/Kconfig
+++ b/drivers/clk/renesas/Kconfig
@@ -8,40 +8,40 @@ config CLK_RENESAS
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_R8A7795
- select CLK_R8A7796 if ARCH_R8A7796
+ select CLK_R8A7795 if ARCH_R8A77950 || 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_R9A06G032 if ARCH_R9A06G032
+ select CLK_R9A07G043 if ARCH_R9A07G043
+ select CLK_R9A07G044 if ARCH_R9A07G044
+ select CLK_R9A07G054 if ARCH_R9A07G054
+ select CLK_R9A09G011 if ARCH_R9A09G011
select CLK_SH73A0 if ARCH_SH73A0
if CLK_RENESAS
-config CLK_RENESAS_LEGACY
- bool "Legacy DT clock support"
- depends on CLK_R8A7790 || CLK_R8A7791 || CLK_R8A7792 || CLK_R8A7794
- help
- Enable backward compatibility with old device trees describing a
- hierarchical representation of the various CPG and MSTP clocks.
-
- Say Y if you want your kernel to work with old DTBs.
- It is safe to say N if you use the DTS that is supplied with the
- current kernel source tree.
-
# SoC
config CLK_EMEV2
bool "Emma Mobile EV2 clock support" if COMPILE_TEST
@@ -64,6 +64,10 @@ config CLK_R8A7740
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
@@ -80,10 +84,18 @@ 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
@@ -94,35 +106,32 @@ config CLK_R8A7779
config CLK_R8A7790
bool "R-Car H2 clock support" if COMPILE_TEST
- select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY
select CLK_RCAR_GEN2_CPG
- select CLK_RENESAS_DIV6
config CLK_R8A7791
bool "R-Car M2-W/N clock support" if COMPILE_TEST
- select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY
select CLK_RCAR_GEN2_CPG
- select CLK_RENESAS_DIV6
config CLK_R8A7792
bool "R-Car V2H clock support" if COMPILE_TEST
- select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY
select CLK_RCAR_GEN2_CPG
config CLK_R8A7794
bool "R-Car E2 clock support" if COMPILE_TEST
- select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY
select CLK_RCAR_GEN2_CPG
- select CLK_RENESAS_DIV6
config CLK_R8A7795
bool "R-Car H3 clock support" if COMPILE_TEST
select CLK_RCAR_GEN3_CPG
-config CLK_R8A7796
+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
@@ -143,10 +152,36 @@ 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_R9A06G032
- bool "Renesas R9A06G032 clock driver"
- help
- This is a driver for R9A06G032 clocks
+ 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_R9A09G011
+ bool "RZ/V2M clock support" if COMPILE_TEST
+ select CLK_RZG2L
config CLK_SH73A0
bool "SH-Mobile AG5 clock support" if COMPILE_TEST
@@ -155,25 +190,34 @@ config CLK_SH73A0
# Family
-config CLK_RCAR_GEN2
- bool "R-Car Gen2 legacy clock support" if COMPILE_TEST
- select CLK_RENESAS_CPG_MSTP
- select CLK_RENESAS_DIV6
+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 CPG clock support" if COMPILE_TEST
+ 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 "Renesas 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 "Renesas RZ/{G2L,G2UL,V2L} family clock support" if COMPILE_TEST
+ select RESET_CONTROLLER
+
# Generic
config CLK_RENESAS_CPG_MSSR
bool "CPG/MSSR clock support" if COMPILE_TEST
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
index c793e3cc9452..de907623fe3f 100644
--- a/drivers/clk/renesas/Makefile
+++ b/drivers/clk/renesas/Makefile
@@ -5,11 +5,14 @@ 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
@@ -17,20 +20,30 @@ 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_R8A7796) += r8a7796-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_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_R9A09G011) += r9a09g011-cpg.o
obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o
# Family
-obj-$(CONFIG_CLK_RCAR_GEN2) += clk-rcar-gen2.o
+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
# Generic
obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o
diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c
index 5ca183e70166..3abd6e5400ad 100644
--- a/drivers/clk/renesas/clk-div6.c
+++ b/drivers/clk/renesas/clk-div6.c
@@ -28,8 +28,7 @@
* @hw: handle between common and hardware-specific interfaces
* @reg: IO-remapped register
* @div: divisor value (1-64)
- * @src_shift: Shift to access the register bits to select the parent clock
- * @src_width: Number of register bits to select the parent clock (may be 0)
+ * @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
*/
@@ -37,8 +36,7 @@ struct div6_clock {
struct clk_hw hw;
void __iomem *reg;
unsigned int div;
- u32 src_shift;
- u32 src_width;
+ u32 src_mask;
struct notifier_block nb;
u8 parents[];
};
@@ -99,15 +97,52 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long rate,
rate = 1;
div = DIV_ROUND_CLOSEST(parent_rate, rate);
- return clamp_t(unsigned int, div, 1, 64);
+ return clamp(div, 1U, 64U);
}
-static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int cpg_div6_clock_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- unsigned int div = cpg_div6_clock_calc_div(rate, *parent_rate);
+ 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;
- return *parent_rate / div;
+ 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,
@@ -133,11 +168,11 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
unsigned int i;
u8 hw_index;
- if (clock->src_width == 0)
+ if (clock->src_mask == 0)
return 0;
- hw_index = (readl(clock->reg) >> clock->src_shift) &
- (BIT(clock->src_width) - 1);
+ hw_index = (readl(clock->reg) & clock->src_mask) >>
+ __ffs(clock->src_mask);
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
if (clock->parents[i] == hw_index)
return i;
@@ -151,18 +186,13 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index)
{
struct div6_clock *clock = to_div6_clock(hw);
- u8 hw_index;
- u32 mask;
+ u32 src;
if (index >= clk_hw_get_num_parents(hw))
return -EINVAL;
- mask = ~((BIT(clock->src_width) - 1) << clock->src_shift);
- hw_index = clock->parents[index];
-
- writel((readl(clock->reg) & mask) | (hw_index << clock->src_shift),
- clock->reg);
-
+ src = clock->parents[index] << __ffs(clock->src_mask);
+ writel((readl(clock->reg) & ~clock->src_mask) | src, clock->reg);
return 0;
}
@@ -173,7 +203,7 @@ static const struct clk_ops cpg_div6_clock_ops = {
.get_parent = cpg_div6_clock_get_parent,
.set_parent = cpg_div6_clock_set_parent,
.recalc_rate = cpg_div6_clock_recalc_rate,
- .round_rate = cpg_div6_clock_round_rate,
+ .determine_rate = cpg_div6_clock_determine_rate,
.set_rate = cpg_div6_clock_set_rate,
};
@@ -216,7 +246,7 @@ struct clk * __init cpg_div6_register(const char *name,
struct raw_notifier_head *notifiers)
{
unsigned int valid_parents;
- struct clk_init_data init;
+ struct clk_init_data init = {};
struct div6_clock *clock;
struct clk *clk;
unsigned int i;
@@ -236,17 +266,15 @@ struct clk * __init cpg_div6_register(const char *name,
switch (num_parents) {
case 1:
/* fixed parent clock */
- clock->src_shift = clock->src_width = 0;
+ clock->src_mask = 0;
break;
case 4:
/* clock with EXSRC bits 6-7 */
- clock->src_shift = 6;
- clock->src_width = 2;
+ clock->src_mask = GENMASK(7, 6);
break;
case 8:
/* VCLK with EXSRC bits 12-14 */
- clock->src_shift = 12;
- clock->src_width = 3;
+ clock->src_mask = GENMASK(14, 12);
break;
default:
pr_err("%s: invalid number of parents for DIV6 clock %s\n",
@@ -267,7 +295,6 @@ struct clk * __init cpg_div6_register(const char *name,
/* Register the clock. */
init.name = name;
init.ops = &cpg_div6_clock_ops;
- init.flags = 0;
init.parent_names = parent_names;
init.num_parents = valid_parents;
diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c
index 2db9093546c6..90804ac06fa5 100644
--- a/drivers/clk/renesas/clk-mstp.c
+++ b/drivers/clk/renesas/clk-mstp.c
@@ -150,7 +150,7 @@ 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 clk_init_data init = {};
struct mstp_clock *clock;
struct clk *clk;
@@ -189,10 +189,8 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
unsigned int i;
group = kzalloc(struct_size(group, clks, MSTP_MAX_CLOCKS), GFP_KERNEL);
- if (group == NULL) {
- kfree(group);
+ if (!group)
return;
- }
clks = group->clks;
spin_lock_init(&group->lock);
@@ -334,7 +332,8 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np)
return;
pd->name = np->name;
- pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
+ 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);
diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c
deleted file mode 100644
index da9fe3f032eb..000000000000
--- a/drivers/clk/renesas/clk-rcar-gen2.c
+++ /dev/null
@@ -1,457 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * rcar_gen2 Core CPG Clocks
- *
- * Copyright (C) 2013 Ideas On Board SPRL
- *
- * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.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/math64.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>
-
-struct rcar_gen2_cpg {
- struct clk_onecell_data data;
- spinlock_t lock;
- void __iomem *reg;
-};
-
-#define CPG_FRQCRB 0x00000004
-#define CPG_FRQCRB_KICK BIT(31)
-#define CPG_SDCKCR 0x00000074
-#define CPG_PLL0CR 0x000000d8
-#define CPG_FRQCRC 0x000000e0
-#define CPG_FRQCRC_ZFC_MASK (0x1f << 8)
-#define CPG_FRQCRC_ZFC_SHIFT 8
-#define CPG_ADSPCKCR 0x0000025c
-#define CPG_RCANCKCR 0x00000270
-
-/* -----------------------------------------------------------------------------
- * 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 long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
-{
- unsigned long prate = *parent_rate;
- unsigned int mult;
-
- if (!prate)
- prate = 1;
-
- mult = div_u64((u64)rate * 32, prate);
- mult = clamp(mult, 1U, 32U);
-
- return *parent_rate / 32 * mult;
-}
-
-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 = div_u64((u64)rate * 32, 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,
- .round_rate = cpg_z_clk_round_rate,
- .set_rate = cpg_z_clk_set_rate,
-};
-
-static struct clk * __init cpg_z_clk_register(struct rcar_gen2_cpg *cpg)
-{
- static const char *parent_name = "pll0";
- struct clk_init_data init;
- struct cpg_z_clk *zclk;
- struct clk *clk;
-
- zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
- if (!zclk)
- return ERR_PTR(-ENOMEM);
-
- init.name = "z";
- init.ops = &cpg_z_clk_ops;
- init.flags = 0;
- init.parent_names = &parent_name;
- init.num_parents = 1;
-
- zclk->reg = cpg->reg + CPG_FRQCRC;
- zclk->kick_reg = cpg->reg + 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(struct rcar_gen2_cpg *cpg,
- struct device_node *np)
-{
- const char *parent_name = of_clk_get_parent_name(np, 1);
- struct clk_fixed_factor *fixed;
- struct clk_gate *gate;
- struct clk *clk;
-
- fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
- if (!fixed)
- return ERR_PTR(-ENOMEM);
-
- fixed->mult = 1;
- fixed->div = 6;
-
- gate = kzalloc(sizeof(*gate), GFP_KERNEL);
- if (!gate) {
- kfree(fixed);
- return ERR_PTR(-ENOMEM);
- }
-
- gate->reg = cpg->reg + CPG_RCANCKCR;
- gate->bit_idx = 8;
- gate->flags = CLK_GATE_SET_TO_DISABLE;
- gate->lock = &cpg->lock;
-
- clk = clk_register_composite(NULL, "rcan", &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(struct rcar_gen2_cpg *cpg)
-{
- const char *parent_name = "pll1";
- struct clk_divider *div;
- struct clk_gate *gate;
- struct clk *clk;
-
- div = kzalloc(sizeof(*div), GFP_KERNEL);
- if (!div)
- return ERR_PTR(-ENOMEM);
-
- div->reg = cpg->reg + CPG_ADSPCKCR;
- div->width = 4;
- div->table = cpg_adsp_div_table;
- div->lock = &cpg->lock;
-
- gate = kzalloc(sizeof(*gate), GFP_KERNEL);
- if (!gate) {
- kfree(div);
- return ERR_PTR(-ENOMEM);
- }
-
- gate->reg = cpg->reg + CPG_ADSPCKCR;
- gate->bit_idx = 8;
- gate->flags = CLK_GATE_SET_TO_DISABLE;
- gate->lock = &cpg->lock;
-
- clk = clk_register_composite(NULL, "adsp", &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;
-}
-
-/* -----------------------------------------------------------------------------
- * CPG Clock Data
- */
-
-/*
- * MD EXTAL PLL0 PLL1 PLL3
- * 14 13 19 (MHz) *1 *1
- *---------------------------------------------------
- * 0 0 0 15 x 1 x172/2 x208/2 x106
- * 0 0 1 15 x 1 x172/2 x208/2 x88
- * 0 1 0 20 x 1 x130/2 x156/2 x80
- * 0 1 1 20 x 1 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.6 indicates VCO output (PLLx = VCO/2)
- */
-#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
- (((md) & BIT(13)) >> 12) | \
- (((md) & BIT(19)) >> 19))
-struct cpg_pll_config {
- unsigned int extal_div;
- unsigned int pll1_mult;
- unsigned int pll3_mult;
- unsigned int pll0_mult; /* For R-Car V2H and E2 only */
-};
-
-static const struct 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 },
-};
-
-/* 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 },
-};
-
-/* -----------------------------------------------------------------------------
- * Initialization
- */
-
-static u32 cpg_mode __initdata;
-
-static const char * const pll0_mult_match[] = {
- "renesas,r8a7792-cpg-clocks",
- "renesas,r8a7794-cpg-clocks",
- NULL
-};
-
-static struct clk * __init
-rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
- const struct cpg_pll_config *config,
- const char *name)
-{
- const struct clk_div_table *table = NULL;
- const char *parent_name;
- unsigned int shift;
- unsigned int mult = 1;
- unsigned int div = 1;
-
- if (!strcmp(name, "main")) {
- parent_name = of_clk_get_parent_name(np, 0);
- div = config->extal_div;
- } else if (!strcmp(name, "pll0")) {
- /* PLL0 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.
- */
- if (of_device_compatible_match(np, pll0_mult_match)) {
- /* R-Car V2H and E2 do not have PLL0CR */
- mult = config->pll0_mult;
- div = 3;
- } else {
- u32 value = readl(cpg->reg + CPG_PLL0CR);
- mult = ((value >> 24) & ((1 << 7) - 1)) + 1;
- }
- parent_name = "main";
- } else if (!strcmp(name, "pll1")) {
- parent_name = "main";
- mult = config->pll1_mult / 2;
- } else if (!strcmp(name, "pll3")) {
- parent_name = "main";
- mult = config->pll3_mult;
- } else if (!strcmp(name, "lb")) {
- parent_name = "pll1";
- div = cpg_mode & BIT(18) ? 36 : 24;
- } else if (!strcmp(name, "qspi")) {
- parent_name = "pll1_div2";
- div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2)
- ? 8 : 10;
- } else if (!strcmp(name, "sdh")) {
- parent_name = "pll1";
- table = cpg_sdh_div_table;
- shift = 8;
- } else if (!strcmp(name, "sd0")) {
- parent_name = "pll1";
- table = cpg_sd01_div_table;
- shift = 4;
- } else if (!strcmp(name, "sd1")) {
- parent_name = "pll1";
- table = cpg_sd01_div_table;
- shift = 0;
- } else if (!strcmp(name, "z")) {
- return cpg_z_clk_register(cpg);
- } else if (!strcmp(name, "rcan")) {
- return cpg_rcan_clk_register(cpg, np);
- } else if (!strcmp(name, "adsp")) {
- return cpg_adsp_clk_register(cpg);
- } else {
- 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,
- cpg->reg + CPG_SDCKCR, shift,
- 4, 0, table, &cpg->lock);
-}
-
-/*
- * Reset register definitions.
- */
-#define MODEMR 0xe6160060
-
-static u32 __init rcar_gen2_read_mode_pins(void)
-{
- void __iomem *modemr = ioremap_nocache(MODEMR, 4);
- u32 mode;
-
- BUG_ON(!modemr);
- mode = ioread32(modemr);
- iounmap(modemr);
-
- return mode;
-}
-
-static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
-{
- const struct cpg_pll_config *config;
- struct rcar_gen2_cpg *cpg;
- struct clk **clks;
- unsigned int i;
- int num_clks;
-
- if (rcar_rst_read_mode_pins(&cpg_mode)) {
- /* Backward-compatibility with old DT */
- pr_warn("%pOF: failed to obtain mode pins from RST\n", np);
- cpg_mode = rcar_gen2_read_mode_pins();
- }
-
- 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(sizeof(*cpg), GFP_KERNEL);
- clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
- 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;
-
- cpg->reg = of_iomap(np, 0);
- if (WARN_ON(cpg->reg == NULL))
- return;
-
- config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_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 = rcar_gen2_cpg_register_clock(np, cpg, config, 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);
-
- cpg_mstp_add_clk_domain(np);
-}
-CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks",
- rcar_gen2_cpg_clocks_init);
diff --git a/drivers/clk/renesas/clk-rz.c b/drivers/clk/renesas/clk-rz.c
index fbc34beafc78..7b703f14e20b 100644
--- a/drivers/clk/renesas/clk-rz.c
+++ b/drivers/clk/renesas/clk-rz.c
@@ -37,8 +37,8 @@ static u16 __init rz_cpg_read_mode_pins(void)
void __iomem *ppr0, *pibc0;
u16 modes;
- ppr0 = ioremap_nocache(PPR0, 2);
- pibc0 = ioremap_nocache(PIBC0, 2);
+ ppr0 = ioremap(PPR0, 2);
+ pibc0 = ioremap(PIBC0, 2);
BUG_ON(!ppr0 || !pibc0);
iowrite16(4, pibc0); /* enable input buffer */
modes = ioread16(ppr0);
diff --git a/drivers/clk/renesas/clk-sh73a0.c b/drivers/clk/renesas/clk-sh73a0.c
index 5f25a70bc61c..4146c1d717b9 100644
--- a/drivers/clk/renesas/clk-sh73a0.c
+++ b/drivers/clk/renesas/clk-sh73a0.c
@@ -121,7 +121,7 @@ sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg,
(phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR);
parent_name = phy_no ? "dsi1pck" : "dsi0pck";
- mult = __raw_readl(dsi_reg);
+ mult = readl(dsi_reg);
if (!(mult & 0x8000))
mult = 1;
else
diff --git a/drivers/clk/renesas/r7s9210-cpg-mssr.c b/drivers/clk/renesas/r7s9210-cpg-mssr.c
index cf65d4e0e116..a85227c248f3 100644
--- a/drivers/clk/renesas/r7s9210-cpg-mssr.c
+++ b/drivers/clk/renesas/r7s9210-cpg-mssr.c
@@ -93,6 +93,7 @@ static const struct mssr_mod_clk r7s9210_mod_clks[] __initconst = {
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),
@@ -213,7 +214,7 @@ const struct cpg_mssr_info r7s9210_cpg_mssr_info __initconst = {
.cpg_clk_register = rza2_cpg_clk_register,
/* RZ/A2 has Standby Control Registers */
- .stbyctrl = true,
+ .reg_layout = CLK_REG_LAYOUT_RZ_A,
};
static void __init r7s9210_cpg_mssr_early_init(struct device_node *np)
diff --git a/drivers/clk/renesas/r8a7742-cpg-mssr.c b/drivers/clk/renesas/r8a7742-cpg-mssr.c
new file mode 100644
index 000000000000..e541489bd1cd
--- /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
index c01d9af2525a..0bba12a48d22 100644
--- a/drivers/clk/renesas/r8a7743-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7743-cpg-mssr.c
@@ -92,7 +92,7 @@ static const struct mssr_mod_clk r8a7743_mod_clks[] __initconst = {
DEF_MOD("tmu0", 125, R8A7743_CLK_CP),
DEF_MOD("vsp1du1", 127, R8A7743_CLK_ZS),
DEF_MOD("vsp1du0", 128, R8A7743_CLK_ZS),
- DEF_MOD("vsp1-sy", 131, 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),
diff --git a/drivers/clk/renesas/r8a7745-cpg-mssr.c b/drivers/clk/renesas/r8a7745-cpg-mssr.c
index 493874e5ebee..dc4a64e8dfb5 100644
--- a/drivers/clk/renesas/r8a7745-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7745-cpg-mssr.c
@@ -90,7 +90,7 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
DEF_MOD("cmt0", 124, R8A7745_CLK_R),
DEF_MOD("tmu0", 125, R8A7745_CLK_CP),
DEF_MOD("vsp1du0", 128, R8A7745_CLK_ZS),
- DEF_MOD("vsp1-sy", 131, 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),
diff --git a/drivers/clk/renesas/r8a77470-cpg-mssr.c b/drivers/clk/renesas/r8a77470-cpg-mssr.c
index d81ae65f0d18..f3d6e65011d7 100644
--- a/drivers/clk/renesas/r8a77470-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a77470-cpg-mssr.c
@@ -85,7 +85,7 @@ static const struct mssr_mod_clk r8a77470_mod_clks[] __initconst = {
DEF_MOD("tmu2", 122, R8A77470_CLK_P),
DEF_MOD("cmt0", 124, R8A77470_CLK_R),
DEF_MOD("vsp1du0", 128, R8A77470_CLK_ZS),
- DEF_MOD("vsp1-sy", 131, 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),
diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c
index e05bfa200480..ad03c09ebc1f 100644
--- a/drivers/clk/renesas/r8a774a1-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c
@@ -41,6 +41,7 @@ enum clk_ids {
CLK_S2,
CLK_S3,
CLK_SDSRC,
+ CLK_RPCSRC,
CLK_RINT,
/* Module Clocks */
@@ -68,6 +69,8 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = {
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 */
@@ -93,10 +96,17 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = {
DEF_FIXED("s3d2", R8A774A1_CLK_S3D2, CLK_S3, 2, 1),
DEF_FIXED("s3d4", R8A774A1_CLK_S3D4, CLK_S3, 4, 1),
- DEF_GEN3_SD("sd0", R8A774A1_CLK_SD0, CLK_SDSRC, 0x074),
- DEF_GEN3_SD("sd1", R8A774A1_CLK_SD1, CLK_SDSRC, 0x078),
- DEF_GEN3_SD("sd2", R8A774A1_CLK_SD2, CLK_SDSRC, 0x268),
- DEF_GEN3_SD("sd3", R8A774A1_CLK_SD3, CLK_SDSRC, 0x26c),
+ 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),
@@ -200,9 +210,10 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
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("i2c-dvfs", 926, R8A774A1_CLK_CP),
+ 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),
@@ -237,6 +248,7 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
};
static const unsigned int r8a774a1_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
diff --git a/drivers/clk/renesas/r8a774b1-cpg-mssr.c b/drivers/clk/renesas/r8a774b1-cpg-mssr.c
new file mode 100644
index 000000000000..ab087b02ef90
--- /dev/null
+++ b/drivers/clk/renesas/r8a774b1-cpg-mssr.c
@@ -0,0 +1,339 @@
+// 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_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("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("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
index f91e7a484753..c9c8fde0f0a6 100644
--- a/drivers/clk/renesas/r8a774c0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a774c0-cpg-mssr.c
@@ -44,6 +44,7 @@ enum clk_ids {
CLK_S2,
CLK_S3,
CLK_SDSRC,
+ CLK_RPCSRC,
CLK_RINT,
CLK_OCO,
@@ -74,6 +75,8 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
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),
@@ -100,9 +103,15 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
DEF_FIXED("s3d2", R8A774C0_CLK_S3D2, CLK_S3, 2, 1),
DEF_FIXED("s3d4", R8A774C0_CLK_S3D4, CLK_S3, 4, 1),
- DEF_GEN3_SD("sd0", R8A774C0_CLK_SD0, CLK_SDSRC, 0x0074),
- DEF_GEN3_SD("sd1", R8A774C0_CLK_SD1, CLK_SDSRC, 0x0078),
- DEF_GEN3_SD("sd3", R8A774C0_CLK_SD3, CLK_SDSRC, 0x026c),
+ 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),
@@ -199,9 +208,10 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
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("i2c-dvfs", 926, R8A774C0_CLK_CP),
+ 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),
@@ -238,6 +248,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
};
static const unsigned int r8a774c0_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
diff --git a/drivers/clk/renesas/r8a774e1-cpg-mssr.c b/drivers/clk/renesas/r8a774e1-cpg-mssr.c
new file mode 100644
index 000000000000..a790061db877
--- /dev/null
+++ b/drivers/clk/renesas/r8a774e1-cpg-mssr.c
@@ -0,0 +1,352 @@
+// 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_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("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_S0D1),
+ 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
index c57cb93f8315..f7d233e0c142 100644
--- a/drivers/clk/renesas/r8a7790-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7790-cpg-mssr.c
@@ -108,8 +108,8 @@ static const struct mssr_mod_clk r8a7790_mod_clks[] __initconst = {
DEF_MOD("tmu0", 125, R8A7790_CLK_CP),
DEF_MOD("vsp1du1", 127, R8A7790_CLK_ZS),
DEF_MOD("vsp1du0", 128, R8A7790_CLK_ZS),
- DEF_MOD("vsp1-rt", 130, R8A7790_CLK_ZS),
- DEF_MOD("vsp1-sy", 131, 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),
diff --git a/drivers/clk/renesas/r8a7791-cpg-mssr.c b/drivers/clk/renesas/r8a7791-cpg-mssr.c
index 65702debcabb..a0de784868da 100644
--- a/drivers/clk/renesas/r8a7791-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7791-cpg-mssr.c
@@ -102,7 +102,7 @@ static const struct mssr_mod_clk r8a7791_mod_clks[] __initconst = {
DEF_MOD("tmu0", 125, R8A7791_CLK_CP),
DEF_MOD("vsp1du1", 127, R8A7791_CLK_ZS),
DEF_MOD("vsp1du0", 128, R8A7791_CLK_ZS),
- DEF_MOD("vsp1-sy", 131, 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),
diff --git a/drivers/clk/renesas/r8a7792-cpg-mssr.c b/drivers/clk/renesas/r8a7792-cpg-mssr.c
index cf8b84a3a060..77af250876a5 100644
--- a/drivers/clk/renesas/r8a7792-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7792-cpg-mssr.c
@@ -88,7 +88,7 @@ static const struct mssr_mod_clk r8a7792_mod_clks[] __initconst = {
DEF_MOD("tmu0", 125, R8A7792_CLK_CP),
DEF_MOD("vsp1du1", 127, R8A7792_CLK_ZS),
DEF_MOD("vsp1du0", 128, R8A7792_CLK_ZS),
- DEF_MOD("vsp1-sy", 131, 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),
diff --git a/drivers/clk/renesas/r8a7794-cpg-mssr.c b/drivers/clk/renesas/r8a7794-cpg-mssr.c
index c1948693c5c1..4d7fa26a72c9 100644
--- a/drivers/clk/renesas/r8a7794-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7794-cpg-mssr.c
@@ -97,7 +97,7 @@ static const struct mssr_mod_clk r8a7794_mod_clks[] __initconst = {
DEF_MOD("cmt0", 124, R8A7794_CLK_R),
DEF_MOD("tmu0", 125, R8A7794_CLK_CP),
DEF_MOD("vsp1du0", 128, R8A7794_CLK_ZS),
- DEF_MOD("vsp1-sy", 131, 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),
diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c
index fbc8c75f4314..301475c74f50 100644
--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c
@@ -44,6 +44,7 @@ enum clk_ids {
CLK_S3,
CLK_SDSRC,
CLK_SSPSRC,
+ CLK_RPCSRC,
CLK_RINT,
/* Module Clocks */
@@ -71,6 +72,8 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
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 */
@@ -97,10 +100,17 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1),
DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1),
- DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_SDSRC, 0x074),
- DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_SDSRC, 0x078),
- DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_SDSRC, 0x268),
- DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_SDSRC, 0x26c),
+ 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),
@@ -121,6 +131,11 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
DEF_MOD("fdp1-2", 117, R8A7795_CLK_S2D1), /* ES1.x */
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),
@@ -217,6 +232,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
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),
@@ -242,6 +258,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
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("i2c-dvfs", 926, R8A7795_CLK_CP),
@@ -279,10 +296,10 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
};
static const unsigned int r8a7795_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
-
/*
* CPG Clock Data
*/
@@ -354,6 +371,7 @@ static const unsigned int r8a7795es1_mod_nullify[] __initconst = {
static const struct mssr_mod_reparent r8a7795es1_mod_reparent[] __initconst = {
{ MOD_CLK_ID(118), R8A7795_CLK_S2D1 }, /* FDP1-1 */
{ MOD_CLK_ID(119), R8A7795_CLK_S2D1 }, /* FDP1-0 */
+ { MOD_CLK_ID(121), R8A7795_CLK_S3D2 }, /* TMU4 */
{ MOD_CLK_ID(217), R8A7795_CLK_S3D1 }, /* SYS-DMAC2 */
{ MOD_CLK_ID(218), R8A7795_CLK_S3D1 }, /* SYS-DMAC1 */
{ MOD_CLK_ID(219), R8A7795_CLK_S3D1 }, /* SYS-DMAC0 */
diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c
index 90cc6a102602..c4969318508e 100644
--- a/drivers/clk/renesas/r8a7796-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * r8a7796 Clock Pulse Generator / Module Standby and Software Reset
+ * r8a7796 (R-Car M3-W/W+) Clock Pulse Generator / Module Standby and Software
+ * Reset
*
- * Copyright (C) 2016 Glider bvba
- * Copyright (C) 2018 Renesas Electronics Corp.
+ * Copyright (C) 2016-2019 Glider bvba
+ * Copyright (C) 2018-2019 Renesas Electronics Corp.
*
* Based on r8a7795-cpg-mssr.c
*
@@ -14,6 +15,7 @@
#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>
@@ -44,6 +46,7 @@ enum clk_ids {
CLK_S3,
CLK_SDSRC,
CLK_SSPSRC,
+ CLK_RPCSRC,
CLK_RINT,
/* Module Clocks */
@@ -71,6 +74,8 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
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 */
@@ -97,12 +102,20 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
DEF_FIXED("s3d2", R8A7796_CLK_S3D2, CLK_S3, 2, 1),
DEF_FIXED("s3d4", R8A7796_CLK_S3D4, CLK_S3, 4, 1),
- DEF_GEN3_SD("sd0", R8A7796_CLK_SD0, CLK_SDSRC, 0x074),
- DEF_GEN3_SD("sd1", R8A7796_CLK_SD1, CLK_SDSRC, 0x078),
- DEF_GEN3_SD("sd2", R8A7796_CLK_SD2, CLK_SDSRC, 0x268),
- DEF_GEN3_SD("sd3", R8A7796_CLK_SD3, CLK_SDSRC, 0x26c),
+ 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),
@@ -116,8 +129,13 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
DEF_BASE("r", R8A7796_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
};
-static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
+static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = {
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),
@@ -130,6 +148,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
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),
@@ -191,6 +210,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
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),
@@ -213,6 +233,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
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("i2c-dvfs", 926, R8A7796_CLK_CP),
@@ -250,10 +271,10 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
};
static const unsigned int r8a7796_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
-
/*
* CPG Clock Data
*/
@@ -304,6 +325,14 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
{ 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;
@@ -320,6 +349,12 @@ static int __init r8a7796_cpg_mssr_init(struct device *dev)
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);
}
diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c
index b4e8c5b7d515..78f6e530848e 100644
--- a/drivers/clk/renesas/r8a77965-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c
@@ -43,6 +43,7 @@ enum clk_ids {
CLK_S3,
CLK_SDSRC,
CLK_SSPSRC,
+ CLK_RPCSRC,
CLK_RINT,
/* Module Clocks */
@@ -69,6 +70,8 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = {
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 */
@@ -94,12 +97,20 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = {
DEF_FIXED("s3d2", R8A77965_CLK_S3D2, CLK_S3, 2, 1),
DEF_FIXED("s3d4", R8A77965_CLK_S3D4, CLK_S3, 4, 1),
- DEF_GEN3_SD("sd0", R8A77965_CLK_SD0, CLK_SDSRC, 0x074),
- DEF_GEN3_SD("sd1", R8A77965_CLK_SD1, CLK_SDSRC, 0x078),
- DEF_GEN3_SD("sd2", R8A77965_CLK_SD2, CLK_SDSRC, 0x268),
- DEF_GEN3_SD("sd3", R8A77965_CLK_SD3, CLK_SDSRC, 0x26c),
+ 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("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),
@@ -115,6 +126,11 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = {
static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
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),
@@ -127,6 +143,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
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),
@@ -191,6 +208,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
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),
@@ -215,6 +233,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
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("i2c-dvfs", 926, R8A77965_CLK_CP),
@@ -235,6 +254,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
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)),
@@ -253,6 +273,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
};
static const unsigned int r8a77965_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
@@ -323,7 +344,7 @@ static int __init r8a77965_cpg_mssr_init(struct device *dev)
}
return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
-};
+}
const struct cpg_mssr_info r8a77965_cpg_mssr_info __initconst = {
/* Core Clocks */
diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c
index cbed3769a100..0f59c84229a8 100644
--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c
@@ -165,10 +165,10 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = {
};
static const unsigned int r8a77970_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
-
/*
* CPG Clock Data
*/
diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c
index 7227f675e61f..06f925aff407 100644
--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c
@@ -66,13 +66,10 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = {
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),
- 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_RATE(".oco", CLK_OCO, 32768),
/* Core Clock Outputs */
DEF_FIXED("ztr", R8A77980_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
@@ -96,7 +93,11 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = {
DEF_FIXED("s3d2", R8A77980_CLK_S3D2, CLK_S3, 2, 1),
DEF_FIXED("s3d4", R8A77980_CLK_S3D4, CLK_S3, 4, 1),
- DEF_GEN3_SD("sd0", R8A77980_CLK_SD0, CLK_SDSRC, 0x0074),
+ 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),
@@ -180,10 +181,10 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = {
};
static const unsigned int r8a77980_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
-
/*
* CPG Clock Data
*/
diff --git a/drivers/clk/renesas/r8a77990-cpg-mssr.c b/drivers/clk/renesas/r8a77990-cpg-mssr.c
index ceabf55c21c2..b666d099365e 100644
--- a/drivers/clk/renesas/r8a77990-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a77990-cpg-mssr.c
@@ -44,6 +44,7 @@ enum clk_ids {
CLK_S2,
CLK_S3,
CLK_SDSRC,
+ CLK_RPCSRC,
CLK_RINT,
CLK_OCO,
@@ -74,6 +75,8 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = {
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),
@@ -100,11 +103,18 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = {
DEF_FIXED("s3d2", R8A77990_CLK_S3D2, CLK_S3, 2, 1),
DEF_FIXED("s3d4", R8A77990_CLK_S3D4, CLK_S3, 4, 1),
- DEF_GEN3_SD("sd0", R8A77990_CLK_SD0, CLK_SDSRC, 0x0074),
- DEF_GEN3_SD("sd1", R8A77990_CLK_SD1, CLK_SDSRC, 0x0078),
- DEF_GEN3_SD("sd3", R8A77990_CLK_SD3, CLK_SDSRC, 0x026c),
+ 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),
@@ -123,6 +133,11 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = {
};
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),
@@ -135,6 +150,7 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = {
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),
@@ -190,6 +206,7 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = {
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),
@@ -204,6 +221,7 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = {
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("i2c-dvfs", 926, R8A77990_CLK_CP),
@@ -225,6 +243,7 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = {
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)),
@@ -243,6 +262,7 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = {
};
static const unsigned int r8a77990_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c
index 962bb337f2e7..24ba9093a72f 100644
--- a/drivers/clk/renesas/r8a77995-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c
@@ -42,6 +42,7 @@ enum clk_ids {
CLK_S2,
CLK_S3,
CLK_SDSRC,
+ CLK_RPCSRC,
CLK_RINT,
CLK_OCO,
@@ -70,11 +71,14 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = {
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),
@@ -91,6 +95,7 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = {
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),
@@ -101,7 +106,11 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = {
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_SD("sd0", R8A77995_CLK_SD0, CLK_SDSRC, 0x268),
+ 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),
@@ -110,6 +119,11 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = {
};
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),
@@ -122,6 +136,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = {
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),
@@ -151,6 +166,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = {
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_S1D2),
DEF_MOD("etheravb", 812, R8A77995_CLK_S3D2),
DEF_MOD("imr0", 823, R8A77995_CLK_S1D2),
@@ -164,6 +180,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = {
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("i2c3", 928, R8A77995_CLK_S3D2),
DEF_MOD("i2c2", 929, R8A77995_CLK_S3D2),
DEF_MOD("i2c1", 930, R8A77995_CLK_S3D2),
@@ -181,10 +198,10 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = {
};
static const unsigned int r8a77995_crit_mod_clks[] __initconst = {
+ MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
-
/*
* CPG Clock Data
*/
diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
new file mode 100644
index 000000000000..d74d46833012
--- /dev/null
+++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
@@ -0,0 +1,300 @@
+// 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_OSC,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+ CLK_EXTALR,
+
+ /* Internal Core Clocks */
+ CLK_MAIN,
+ CLK_PLL1,
+ CLK_PLL20,
+ CLK_PLL21,
+ CLK_PLL30,
+ CLK_PLL31,
+ 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)
+
+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, 0x0834),
+ DEF_PLL(".pll21", CLK_PLL21, 0x0838),
+ DEF_PLL(".pll30", CLK_PLL30, 0x083c),
+ DEF_PLL(".pll31", CLK_PLL31, 0x0840),
+
+ 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_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("sdh0", R8A779A0_CLK_SD0H, CLK_SDSRC, 0x870),
+ DEF_GEN4_SD("sd0", R8A779A0_CLK_SD0, R8A779A0_CLK_SD0H, 0x870),
+
+ 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, 0x87c),
+ DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878),
+ DEF_DIV6P1("csi0", R8A779A0_CLK_CSI0, CLK_PLL5_DIV4, 0x880),
+ DEF_DIV6P1("dsi", R8A779A0_CLK_DSI, CLK_PLL5_DIV4, 0x884),
+
+ 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("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_CANFD),
+ 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("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("sydm1", 709, R8A779A0_CLK_S1D2),
+ DEF_MOD("sydm2", 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),
+};
+
+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] = {
+ /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL4 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */
+ { 1, 128, 1, 0, 0, 0, 0, 144, 1, 192, 1, 0, 0, 16, },
+ { 1, 106, 1, 0, 0, 0, 0, 120, 1, 160, 1, 0, 0, 19, },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ { 2, 128, 1, 0, 0, 0, 0, 144, 1, 192, 1, 0, 0, 32, },
+};
+
+
+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 000000000000..c17ebe6b5992
--- /dev/null
+++ b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
@@ -0,0 +1,205 @@
+// 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_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_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN4_PLL1, CLK_MAIN),
+ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN4_PLL2, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN4_PLL3, CLK_MAIN),
+ DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN),
+ DEF_BASE(".pll6", CLK_PLL6, CLK_TYPE_GEN4_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_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_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_GEN4_SD("sd0", R8A779F0_CLK_SD0, CLK_SDSRC, 0x870),
+
+ 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, 0x87c),
+
+ 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("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("scif0", 702, R8A779F0_CLK_S0D12_PER),
+ DEF_MOD("scif1", 703, R8A779F0_CLK_S0D12_PER),
+ DEF_MOD("scif3", 704, R8A779F0_CLK_S0D12_PER),
+ DEF_MOD("scif4", 705, R8A779F0_CLK_S0D12_PER),
+ DEF_MOD("sys-dmac0", 709, R8A779F0_CLK_S0D3_PER),
+ DEF_MOD("sys-dmac1", 710, R8A779F0_CLK_S0D3_PER),
+ DEF_MOD("wdt", 907, R8A779F0_CLK_R),
+ DEF_MOD("pfc0", 915, R8A779F0_CLK_CL16M),
+ 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] = {
+ /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL4 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */
+ { 1, 200, 1, 150, 1, 200, 1, 0, 0, 200, 1, 134, 1, 15, },
+ { 1, 160, 1, 120, 1, 160, 1, 0, 0, 160, 1, 106, 1, 19, },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ { 2, 160, 1, 120, 1, 160, 1, 0, 0, 160, 1, 106, 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 000000000000..3fc4233b1ead
--- /dev/null
+++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
@@ -0,0 +1,218 @@
+// 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_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_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_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_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN4_PLL1, CLK_MAIN),
+ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN4_PLL2, CLK_MAIN),
+ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN4_PLL3, CLK_MAIN),
+ DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN4_PLL4, CLK_MAIN),
+ DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN),
+ DEF_BASE(".pll6", CLK_PLL6, CLK_TYPE_GEN4_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(".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_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("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("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_GEN4_SD("sd0", R8A779G0_CLK_SD0, CLK_SDSRC, 0x870),
+ DEF_DIV6P1("mso", R8A779G0_CLK_MSO, CLK_PLL5_DIV4, 0x87c),
+
+ 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("hscif0", 514, R8A779G0_CLK_S0D3_PER),
+ DEF_MOD("hscif1", 515, R8A779G0_CLK_S0D3_PER),
+ DEF_MOD("hscif2", 516, R8A779G0_CLK_S0D3_PER),
+ DEF_MOD("hscif3", 517, R8A779G0_CLK_S0D3_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 /15
+ * 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 /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] = {
+ /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL4 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */
+ { 1, 192, 1, 204, 1, 192, 1, 144, 1, 192, 1, 168, 1, 15, },
+ { 1, 160, 1, 170, 1, 160, 1, 120, 1, 160, 1, 140, 1, 19, },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ { 2, 192, 1, 204, 1, 192, 1, 144, 1, 192, 1, 168, 1, 38, },
+};
+
+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/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c
index b33e1383efe3..35ffc462af1a 100644
--- a/drivers/clk/renesas/r9a06g032-clocks.c
+++ b/drivers/clk/renesas/r9a06g032-clocks.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * R9A09G032 clock driver
+ * R9A06G032 clock driver
*
* Copyright (C) 2018 Renesas Electronics Europe Limited
*
@@ -16,13 +16,17 @@
#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/slab.h>
+#include <linux/soc/renesas/r9a06g032-sysctrl.h>
#include <linux/spinlock.h>
#include <dt-bindings/clock/r9a06g032-sysctrl.h>
+#define R9A06G032_SYSCTRL_DMAMUX 0xA0
+
struct r9a06g032_gate {
u16 gate, reset, ready, midle,
scon, mirack, mistat;
@@ -55,7 +59,7 @@ struct r9a06g032_clkdesc {
u16 sel, g1, r1, g2, r2;
} dual;
};
-} __packed;
+};
#define I_GATE(_clk, _rst, _rdy, _midle, _scon, _mirack, _mistat) \
{ .gate = _clk, .reset = _rst, \
@@ -256,7 +260,7 @@ static const struct r9a06g032_clkdesc r9a06g032_clocks[] = {
D_MODULE(HCLK_QSPI0, "hclk_qspi0", CLK_REF_SYNC_D4, 0x2a0, 0x2a1, 0x2a2, 0x2a3, 0x300, 0x301, 0x302),
D_MODULE(HCLK_QSPI1, "hclk_qspi1", CLK_REF_SYNC_D4, 0x480, 0x481, 0x482, 0x483, 0x4c0, 0x4c1, 0x4c2),
D_MODULE(HCLK_ROM, "hclk_rom", CLK_REF_SYNC_D4, 0xaa0, 0xaa1, 0xaa2, 0, 0xb80, 0, 0),
- D_MODULE(HCLK_RTC, "hclk_rtc", CLK_REF_SYNC_D8, 0xa00, 0, 0, 0, 0, 0, 0),
+ D_MODULE(HCLK_RTC, "hclk_rtc", CLK_REF_SYNC_D8, 0xa00, 0xa03, 0, 0xa02, 0, 0, 0),
D_MODULE(HCLK_SDIO0, "hclk_sdio0", CLK_REF_SYNC_D4, 0x60, 0x61, 0x62, 0x63, 0x80, 0x81, 0x82),
D_MODULE(HCLK_SDIO1, "hclk_sdio1", CLK_REF_SYNC_D4, 0x640, 0x641, 0x642, 0x643, 0x660, 0x661, 0x662),
D_MODULE(HCLK_SEMAP, "hclk_semap", CLK_REF_SYNC_D4, 0x7a3, 0x7a4, 0x7a5, 0, 0xb21, 0, 0),
@@ -279,7 +283,7 @@ static const struct r9a06g032_clkdesc r9a06g032_clocks[] = {
/*
* 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 suposed to use.
+ * parent for a clock, but also the gate it's supposed to use.
*/
{
.index = R9A06G032_UART_GROUP_012,
@@ -311,10 +315,34 @@ static const struct r9a06g032_clkdesc r9a06g032_clocks[] = {
struct r9a06g032_priv {
struct clk_onecell_data data;
- spinlock_t lock; /* protects concurent access to gates */
+ 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);
+
/* register/bit pairs are encoded as an uint16_t */
static void
clk_rdesc_set(struct r9a06g032_priv *clocks,
@@ -338,8 +366,8 @@ clk_rdesc_get(struct r9a06g032_priv *clocks,
}
/*
- * This implements the R9A09G032 clock gate 'driver'. We cannot use the system's
- * clock gate framework as the gates on the R9A09G032 have a special enabling
+ * 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 {
@@ -421,7 +449,8 @@ static int r9a06g032_add_clk_domain(struct device *dev)
return -ENOMEM;
pd->name = np->name;
- pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
+ 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);
@@ -503,7 +532,7 @@ r9a06g032_register_gate(struct r9a06g032_priv *clocks,
{
struct clk *clk;
struct r9a06g032_clk_gate *g;
- struct clk_init_data init;
+ struct clk_init_data init = {};
g = kzalloc(sizeof(*g), GFP_KERNEL);
if (!g)
@@ -603,20 +632,19 @@ r9a06g032_div_clamp_div(struct r9a06g032_clk_div *clk,
return div;
}
-static long
-r9a06g032_div_round_rate(struct clk_hw *hw,
- unsigned long rate, unsigned long *prate)
+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(*prate, rate);
+ 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, rate, *prate, div);
+ hw->clk, req->rate, req->best_parent_rate, div);
pr_devel(" min %d (%ld) max %d (%ld)\n",
- clk->min, DIV_ROUND_UP(*prate, clk->min),
- clk->max, DIV_ROUND_UP(*prate, clk->max));
+ 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, rate, *prate);
+ 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
@@ -629,11 +657,13 @@ r9a06g032_div_round_rate(struct clk_hw *hw,
if (clk->index == R9A06G032_DIV_UART ||
clk->index == R9A06G032_DIV_P2_PG) {
pr_devel("%s div uart hack!\n", __func__);
- return clk_get_rate(hw->clk);
+ 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,
- *prate, div, DIV_ROUND_UP(*prate, div));
- return DIV_ROUND_UP(*prate, div);
+ req->best_parent_rate, div, req->rate);
+ return 0;
}
static int
@@ -662,7 +692,7 @@ r9a06g032_div_set_rate(struct clk_hw *hw,
static const struct clk_ops r9a06g032_clk_div_ops = {
.recalc_rate = r9a06g032_div_recalc_rate,
- .round_rate = r9a06g032_div_round_rate,
+ .determine_rate = r9a06g032_div_determine_rate,
.set_rate = r9a06g032_div_set_rate,
};
@@ -673,7 +703,7 @@ r9a06g032_register_div(struct r9a06g032_priv *clocks,
{
struct r9a06g032_clk_div *div;
struct clk *clk;
- struct clk_init_data init;
+ struct clk_init_data init = {};
unsigned int i;
div = kzalloc(sizeof(*div), GFP_KERNEL);
@@ -757,7 +787,7 @@ r9a06g032_register_bitsel(struct r9a06g032_priv *clocks,
{
struct clk *clk;
struct r9a06g032_clk_bitsel *g;
- struct clk_init_data init;
+ struct clk_init_data init = {};
const char *names[2];
/* allocate the gate */
@@ -848,7 +878,7 @@ r9a06g032_register_dualgate(struct r9a06g032_priv *clocks,
{
struct r9a06g032_clk_dualgate *g;
struct clk *clk;
- struct clk_init_data init;
+ struct clk_init_data init = {};
/* allocate the gate */
g = kzalloc(sizeof(*g), GFP_KERNEL);
@@ -961,7 +991,17 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
if (error)
return error;
- return r9a06g032_add_clk_domain(dev);
+ 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[] = {
diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
new file mode 100644
index 000000000000..33c2bd8df2e5
--- /dev/null
+++ b/drivers/clk/renesas/r9a07g043-cpg.c
@@ -0,0 +1,320 @@
+// 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"
+
+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,
+ CLK_PLL5,
+ CLK_PLL5_500,
+ 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,
+
+ /* 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" };
+static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
+static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
+
+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, PLL146_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),
+ 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_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),
+ DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2),
+ 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_shdi),
+ DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, sel_shdi),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4),
+};
+
+static struct rzg2l_mod_clk r9a07g043_mod_clks[] = {
+ DEF_MOD("gic", R9A07G043_GIC600_GICCLK, R9A07G043_CLK_P1,
+ 0x514, 0),
+ DEF_MOD("ia55_pclk", R9A07G043_IA55_PCLK, R9A07G043_CLK_P2,
+ 0x518, 0),
+ DEF_MOD("ia55_clk", R9A07G043_IA55_CLK, R9A07G043_CLK_P1,
+ 0x518, 1),
+ DEF_MOD("dmac_aclk", R9A07G043_DMAC_ACLK, R9A07G043_CLK_P1,
+ 0x52c, 0),
+ DEF_MOD("dmac_pclk", R9A07G043_DMAC_PCLK, CLK_P1_DIV2,
+ 0x52c, 1),
+ DEF_MOD("ostm0_pclk", R9A07G043_OSTM0_PCLK, R9A07G043_CLK_P0,
+ 0x534, 0),
+ DEF_MOD("ostm1_pclk", R9A07G043_OSTM1_PCLK, R9A07G043_CLK_P0,
+ 0x534, 1),
+ DEF_MOD("ostm2_pclk", R9A07G043_OSTM2_PCLK, R9A07G043_CLK_P0,
+ 0x534, 2),
+ DEF_MOD("wdt0_pclk", R9A07G043_WDT0_PCLK, R9A07G043_CLK_P0,
+ 0x548, 0),
+ DEF_MOD("wdt0_clk", R9A07G043_WDT0_CLK, R9A07G043_OSCCLK,
+ 0x548, 1),
+ DEF_MOD("wdt2_pclk", R9A07G043_WDT2_PCLK, R9A07G043_CLK_P0,
+ 0x548, 4),
+ DEF_MOD("wdt2_clk", R9A07G043_WDT2_CLK, R9A07G043_OSCCLK,
+ 0x548, 5),
+ DEF_MOD("spi_clk2", R9A07G043_SPI_CLK2, R9A07G043_CLK_SPI1,
+ 0x550, 0),
+ DEF_MOD("spi_clk", R9A07G043_SPI_CLK, R9A07G043_CLK_SPI0,
+ 0x550, 1),
+ DEF_MOD("sdhi0_imclk", R9A07G043_SDHI0_IMCLK, CLK_SD0_DIV4,
+ 0x554, 0),
+ DEF_MOD("sdhi0_imclk2", R9A07G043_SDHI0_IMCLK2, CLK_SD0_DIV4,
+ 0x554, 1),
+ DEF_MOD("sdhi0_clk_hs", R9A07G043_SDHI0_CLK_HS, R9A07G043_CLK_SD0,
+ 0x554, 2),
+ DEF_MOD("sdhi0_aclk", R9A07G043_SDHI0_ACLK, R9A07G043_CLK_P1,
+ 0x554, 3),
+ DEF_MOD("sdhi1_imclk", R9A07G043_SDHI1_IMCLK, CLK_SD1_DIV4,
+ 0x554, 4),
+ DEF_MOD("sdhi1_imclk2", R9A07G043_SDHI1_IMCLK2, CLK_SD1_DIV4,
+ 0x554, 5),
+ DEF_MOD("sdhi1_clk_hs", R9A07G043_SDHI1_CLK_HS, R9A07G043_CLK_SD1,
+ 0x554, 6),
+ DEF_MOD("sdhi1_aclk", R9A07G043_SDHI1_ACLK, R9A07G043_CLK_P1,
+ 0x554, 7),
+ DEF_MOD("ssi0_pclk", R9A07G043_SSI0_PCLK2, R9A07G043_CLK_P0,
+ 0x570, 0),
+ DEF_MOD("ssi0_sfr", R9A07G043_SSI0_PCLK_SFR, R9A07G043_CLK_P0,
+ 0x570, 1),
+ DEF_MOD("ssi1_pclk", R9A07G043_SSI1_PCLK2, R9A07G043_CLK_P0,
+ 0x570, 2),
+ DEF_MOD("ssi1_sfr", R9A07G043_SSI1_PCLK_SFR, R9A07G043_CLK_P0,
+ 0x570, 3),
+ DEF_MOD("ssi2_pclk", R9A07G043_SSI2_PCLK2, R9A07G043_CLK_P0,
+ 0x570, 4),
+ DEF_MOD("ssi2_sfr", R9A07G043_SSI2_PCLK_SFR, R9A07G043_CLK_P0,
+ 0x570, 5),
+ DEF_MOD("ssi3_pclk", R9A07G043_SSI3_PCLK2, R9A07G043_CLK_P0,
+ 0x570, 6),
+ DEF_MOD("ssi3_sfr", R9A07G043_SSI3_PCLK_SFR, R9A07G043_CLK_P0,
+ 0x570, 7),
+ DEF_MOD("usb0_host", R9A07G043_USB_U2H0_HCLK, R9A07G043_CLK_P1,
+ 0x578, 0),
+ DEF_MOD("usb1_host", R9A07G043_USB_U2H1_HCLK, R9A07G043_CLK_P1,
+ 0x578, 1),
+ DEF_MOD("usb0_func", R9A07G043_USB_U2P_EXR_CPUCLK, R9A07G043_CLK_P1,
+ 0x578, 2),
+ DEF_MOD("usb_pclk", R9A07G043_USB_PCLK, R9A07G043_CLK_P1,
+ 0x578, 3),
+ DEF_COUPLED("eth0_axi", R9A07G043_ETH0_CLK_AXI, R9A07G043_CLK_M0,
+ 0x57c, 0),
+ DEF_COUPLED("eth0_chi", R9A07G043_ETH0_CLK_CHI, R9A07G043_CLK_ZT,
+ 0x57c, 0),
+ DEF_COUPLED("eth1_axi", R9A07G043_ETH1_CLK_AXI, R9A07G043_CLK_M0,
+ 0x57c, 1),
+ DEF_COUPLED("eth1_chi", R9A07G043_ETH1_CLK_CHI, R9A07G043_CLK_ZT,
+ 0x57c, 1),
+ DEF_MOD("i2c0", R9A07G043_I2C0_PCLK, R9A07G043_CLK_P0,
+ 0x580, 0),
+ DEF_MOD("i2c1", R9A07G043_I2C1_PCLK, R9A07G043_CLK_P0,
+ 0x580, 1),
+ DEF_MOD("i2c2", R9A07G043_I2C2_PCLK, R9A07G043_CLK_P0,
+ 0x580, 2),
+ DEF_MOD("i2c3", R9A07G043_I2C3_PCLK, R9A07G043_CLK_P0,
+ 0x580, 3),
+ DEF_MOD("scif0", R9A07G043_SCIF0_CLK_PCK, R9A07G043_CLK_P0,
+ 0x584, 0),
+ DEF_MOD("scif1", R9A07G043_SCIF1_CLK_PCK, R9A07G043_CLK_P0,
+ 0x584, 1),
+ DEF_MOD("scif2", R9A07G043_SCIF2_CLK_PCK, R9A07G043_CLK_P0,
+ 0x584, 2),
+ DEF_MOD("scif3", R9A07G043_SCIF3_CLK_PCK, R9A07G043_CLK_P0,
+ 0x584, 3),
+ DEF_MOD("scif4", R9A07G043_SCIF4_CLK_PCK, R9A07G043_CLK_P0,
+ 0x584, 4),
+ DEF_MOD("sci0", R9A07G043_SCI0_CLKP, R9A07G043_CLK_P0,
+ 0x588, 0),
+ DEF_MOD("sci1", R9A07G043_SCI1_CLKP, R9A07G043_CLK_P0,
+ 0x588, 1),
+ DEF_MOD("rspi0", R9A07G043_RSPI0_CLKB, R9A07G043_CLK_P0,
+ 0x590, 0),
+ DEF_MOD("rspi1", R9A07G043_RSPI1_CLKB, R9A07G043_CLK_P0,
+ 0x590, 1),
+ DEF_MOD("rspi2", R9A07G043_RSPI2_CLKB, R9A07G043_CLK_P0,
+ 0x590, 2),
+ DEF_MOD("canfd", R9A07G043_CANFD_PCLK, R9A07G043_CLK_P0,
+ 0x594, 0),
+ DEF_MOD("gpio", R9A07G043_GPIO_HCLK, R9A07G043_OSCCLK,
+ 0x598, 0),
+ DEF_MOD("adc_adclk", R9A07G043_ADC_ADCLK, R9A07G043_CLK_TSU,
+ 0x5a8, 0),
+ DEF_MOD("adc_pclk", R9A07G043_ADC_PCLK, R9A07G043_CLK_P0,
+ 0x5a8, 1),
+ DEF_MOD("tsu_pclk", R9A07G043_TSU_PCLK, R9A07G043_CLK_TSU,
+ 0x5ac, 0),
+};
+
+static struct rzg2l_reset r9a07g043_resets[] = {
+ DEF_RST(R9A07G043_GIC600_GICRESET_N, 0x814, 0),
+ DEF_RST(R9A07G043_GIC600_DBG_GICRESET_N, 0x814, 1),
+ DEF_RST(R9A07G043_IA55_RESETN, 0x818, 0),
+ 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_WDT0_PRESETN, 0x848, 0),
+ DEF_RST(R9A07G043_WDT2_PRESETN, 0x848, 2),
+ DEF_RST(R9A07G043_SPI_RST, 0x850, 0),
+ DEF_RST(R9A07G043_SDHI0_IXRST, 0x854, 0),
+ DEF_RST(R9A07G043_SDHI1_IXRST, 0x854, 1),
+ 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),
+};
+
+static const unsigned int r9a07g043_crit_mod_clks[] __initconst = {
+ MOD_CLK_BASE + R9A07G043_GIC600_GICCLK,
+ MOD_CLK_BASE + R9A07G043_IA55_CLK,
+ MOD_CLK_BASE + R9A07G043_DMAC_ACLK,
+};
+
+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),
+ .num_hw_mod_clks = R9A07G043_TSU_PCLK + 1,
+
+ /* Resets */
+ .resets = r9a07g043_resets,
+ .num_resets = R9A07G043_TSU_PRESETN + 1, /* Last reset ID + 1 */
+
+ .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 000000000000..b288897852c7
--- /dev/null
+++ b/drivers/clk/renesas/r9a07g044-cpg.c
@@ -0,0 +1,448 @@
+// 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"
+
+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},
+};
+
+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_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
+static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
+
+static const struct {
+ struct cpg_core_clk common[56];
+#ifdef CONFIG_CLK_R9A07G054
+ struct cpg_core_clk drp[0];
+#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, PLL146_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_shdi),
+ DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, sel_shdi),
+ 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 = {
+ },
+#endif
+};
+
+static const struct {
+ struct rzg2l_mod_clk common[71];
+#ifdef CONFIG_CLK_R9A07G054
+ struct rzg2l_mod_clk drp[0];
+#endif
+} mod_clks = {
+ .common = {
+ DEF_MOD("gic", R9A07G044_GIC600_GICCLK, R9A07G044_CLK_P1,
+ 0x514, 0),
+ DEF_MOD("ia55_pclk", R9A07G044_IA55_PCLK, R9A07G044_CLK_P2,
+ 0x518, 0),
+ DEF_MOD("ia55_clk", R9A07G044_IA55_CLK, R9A07G044_CLK_P1,
+ 0x518, 1),
+ DEF_MOD("dmac_aclk", R9A07G044_DMAC_ACLK, R9A07G044_CLK_P1,
+ 0x52c, 0),
+ DEF_MOD("dmac_pclk", R9A07G044_DMAC_PCLK, CLK_P1_DIV2,
+ 0x52c, 1),
+ DEF_MOD("ostm0_pclk", R9A07G044_OSTM0_PCLK, R9A07G044_CLK_P0,
+ 0x534, 0),
+ DEF_MOD("ostm1_pclk", R9A07G044_OSTM1_PCLK, R9A07G044_CLK_P0,
+ 0x534, 1),
+ DEF_MOD("ostm2_pclk", R9A07G044_OSTM2_PCLK, R9A07G044_CLK_P0,
+ 0x534, 2),
+ DEF_MOD("wdt0_pclk", R9A07G044_WDT0_PCLK, R9A07G044_CLK_P0,
+ 0x548, 0),
+ DEF_MOD("wdt0_clk", R9A07G044_WDT0_CLK, R9A07G044_OSCCLK,
+ 0x548, 1),
+ DEF_MOD("wdt1_pclk", R9A07G044_WDT1_PCLK, R9A07G044_CLK_P0,
+ 0x548, 2),
+ DEF_MOD("wdt1_clk", R9A07G044_WDT1_CLK, R9A07G044_OSCCLK,
+ 0x548, 3),
+ DEF_MOD("wdt2_pclk", R9A07G044_WDT2_PCLK, R9A07G044_CLK_P0,
+ 0x548, 4),
+ DEF_MOD("wdt2_clk", R9A07G044_WDT2_CLK, R9A07G044_OSCCLK,
+ 0x548, 5),
+ DEF_MOD("spi_clk2", R9A07G044_SPI_CLK2, R9A07G044_CLK_SPI1,
+ 0x550, 0),
+ DEF_MOD("spi_clk", R9A07G044_SPI_CLK, R9A07G044_CLK_SPI0,
+ 0x550, 1),
+ DEF_MOD("sdhi0_imclk", R9A07G044_SDHI0_IMCLK, CLK_SD0_DIV4,
+ 0x554, 0),
+ DEF_MOD("sdhi0_imclk2", R9A07G044_SDHI0_IMCLK2, CLK_SD0_DIV4,
+ 0x554, 1),
+ DEF_MOD("sdhi0_clk_hs", R9A07G044_SDHI0_CLK_HS, R9A07G044_CLK_SD0,
+ 0x554, 2),
+ DEF_MOD("sdhi0_aclk", R9A07G044_SDHI0_ACLK, R9A07G044_CLK_P1,
+ 0x554, 3),
+ DEF_MOD("sdhi1_imclk", R9A07G044_SDHI1_IMCLK, CLK_SD1_DIV4,
+ 0x554, 4),
+ DEF_MOD("sdhi1_imclk2", R9A07G044_SDHI1_IMCLK2, CLK_SD1_DIV4,
+ 0x554, 5),
+ DEF_MOD("sdhi1_clk_hs", R9A07G044_SDHI1_CLK_HS, R9A07G044_CLK_SD1,
+ 0x554, 6),
+ DEF_MOD("sdhi1_aclk", R9A07G044_SDHI1_ACLK, R9A07G044_CLK_P1,
+ 0x554, 7),
+ DEF_MOD("gpu_clk", R9A07G044_GPU_CLK, R9A07G044_CLK_G,
+ 0x558, 0),
+ DEF_MOD("gpu_axi_clk", R9A07G044_GPU_AXI_CLK, R9A07G044_CLK_P1,
+ 0x558, 1),
+ DEF_MOD("gpu_ace_clk", R9A07G044_GPU_ACE_CLK, R9A07G044_CLK_P1,
+ 0x558, 2),
+ DEF_MOD("dsi_pll_clk", R9A07G044_MIPI_DSI_PLLCLK, R9A07G044_CLK_M1,
+ 0x568, 0),
+ DEF_MOD("dsi_sys_clk", R9A07G044_MIPI_DSI_SYSCLK, CLK_M2_DIV2,
+ 0x568, 1),
+ DEF_MOD("dsi_aclk", R9A07G044_MIPI_DSI_ACLK, R9A07G044_CLK_P1,
+ 0x568, 2),
+ DEF_MOD("dsi_pclk", R9A07G044_MIPI_DSI_PCLK, R9A07G044_CLK_P2,
+ 0x568, 3),
+ DEF_MOD("dsi_vclk", R9A07G044_MIPI_DSI_VCLK, R9A07G044_CLK_M3,
+ 0x568, 4),
+ DEF_MOD("dsi_lpclk", R9A07G044_MIPI_DSI_LPCLK, R9A07G044_CLK_M4,
+ 0x568, 5),
+ DEF_COUPLED("lcdc_a", R9A07G044_LCDC_CLK_A, R9A07G044_CLK_M0,
+ 0x56c, 0),
+ DEF_COUPLED("lcdc_p", R9A07G044_LCDC_CLK_P, R9A07G044_CLK_ZT,
+ 0x56c, 0),
+ DEF_MOD("lcdc_clk_d", R9A07G044_LCDC_CLK_D, R9A07G044_CLK_M3,
+ 0x56c, 1),
+ DEF_MOD("ssi0_pclk", R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 0),
+ DEF_MOD("ssi0_sfr", R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 1),
+ DEF_MOD("ssi1_pclk", R9A07G044_SSI1_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 2),
+ DEF_MOD("ssi1_sfr", R9A07G044_SSI1_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 3),
+ DEF_MOD("ssi2_pclk", R9A07G044_SSI2_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 4),
+ DEF_MOD("ssi2_sfr", R9A07G044_SSI2_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 5),
+ DEF_MOD("ssi3_pclk", R9A07G044_SSI3_PCLK2, R9A07G044_CLK_P0,
+ 0x570, 6),
+ DEF_MOD("ssi3_sfr", R9A07G044_SSI3_PCLK_SFR, R9A07G044_CLK_P0,
+ 0x570, 7),
+ DEF_MOD("usb0_host", R9A07G044_USB_U2H0_HCLK, R9A07G044_CLK_P1,
+ 0x578, 0),
+ DEF_MOD("usb1_host", R9A07G044_USB_U2H1_HCLK, R9A07G044_CLK_P1,
+ 0x578, 1),
+ DEF_MOD("usb0_func", R9A07G044_USB_U2P_EXR_CPUCLK, R9A07G044_CLK_P1,
+ 0x578, 2),
+ DEF_MOD("usb_pclk", R9A07G044_USB_PCLK, R9A07G044_CLK_P1,
+ 0x578, 3),
+ DEF_COUPLED("eth0_axi", R9A07G044_ETH0_CLK_AXI, R9A07G044_CLK_M0,
+ 0x57c, 0),
+ DEF_COUPLED("eth0_chi", R9A07G044_ETH0_CLK_CHI, R9A07G044_CLK_ZT,
+ 0x57c, 0),
+ DEF_COUPLED("eth1_axi", R9A07G044_ETH1_CLK_AXI, R9A07G044_CLK_M0,
+ 0x57c, 1),
+ DEF_COUPLED("eth1_chi", R9A07G044_ETH1_CLK_CHI, R9A07G044_CLK_ZT,
+ 0x57c, 1),
+ DEF_MOD("i2c0", R9A07G044_I2C0_PCLK, R9A07G044_CLK_P0,
+ 0x580, 0),
+ DEF_MOD("i2c1", R9A07G044_I2C1_PCLK, R9A07G044_CLK_P0,
+ 0x580, 1),
+ DEF_MOD("i2c2", R9A07G044_I2C2_PCLK, R9A07G044_CLK_P0,
+ 0x580, 2),
+ DEF_MOD("i2c3", R9A07G044_I2C3_PCLK, R9A07G044_CLK_P0,
+ 0x580, 3),
+ DEF_MOD("scif0", R9A07G044_SCIF0_CLK_PCK, R9A07G044_CLK_P0,
+ 0x584, 0),
+ DEF_MOD("scif1", R9A07G044_SCIF1_CLK_PCK, R9A07G044_CLK_P0,
+ 0x584, 1),
+ DEF_MOD("scif2", R9A07G044_SCIF2_CLK_PCK, R9A07G044_CLK_P0,
+ 0x584, 2),
+ DEF_MOD("scif3", R9A07G044_SCIF3_CLK_PCK, R9A07G044_CLK_P0,
+ 0x584, 3),
+ DEF_MOD("scif4", R9A07G044_SCIF4_CLK_PCK, R9A07G044_CLK_P0,
+ 0x584, 4),
+ DEF_MOD("sci0", R9A07G044_SCI0_CLKP, R9A07G044_CLK_P0,
+ 0x588, 0),
+ DEF_MOD("sci1", R9A07G044_SCI1_CLKP, R9A07G044_CLK_P0,
+ 0x588, 1),
+ DEF_MOD("rspi0", R9A07G044_RSPI0_CLKB, R9A07G044_CLK_P0,
+ 0x590, 0),
+ DEF_MOD("rspi1", R9A07G044_RSPI1_CLKB, R9A07G044_CLK_P0,
+ 0x590, 1),
+ DEF_MOD("rspi2", R9A07G044_RSPI2_CLKB, R9A07G044_CLK_P0,
+ 0x590, 2),
+ DEF_MOD("canfd", R9A07G044_CANFD_PCLK, R9A07G044_CLK_P0,
+ 0x594, 0),
+ DEF_MOD("gpio", R9A07G044_GPIO_HCLK, R9A07G044_OSCCLK,
+ 0x598, 0),
+ DEF_MOD("adc_adclk", R9A07G044_ADC_ADCLK, R9A07G044_CLK_TSU,
+ 0x5a8, 0),
+ DEF_MOD("adc_pclk", R9A07G044_ADC_PCLK, R9A07G044_CLK_P0,
+ 0x5a8, 1),
+ DEF_MOD("tsu_pclk", R9A07G044_TSU_PCLK, R9A07G044_CLK_TSU,
+ 0x5ac, 0),
+ },
+#ifdef CONFIG_CLK_R9A07G054
+ .drp = {
+ },
+#endif
+};
+
+static 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_WDT0_PRESETN, 0x848, 0),
+ DEF_RST(R9A07G044_WDT1_PRESETN, 0x848, 1),
+ DEF_RST(R9A07G044_WDT2_PRESETN, 0x848, 2),
+ 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_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),
+};
+
+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,
+};
+
+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,
+
+ /* Resets */
+ .resets = r9a07g044_resets,
+ .num_resets = R9A07G044_TSU_PRESETN + 1, /* Last reset ID + 1 */
+
+ .has_clk_mon_regs = true,
+};
+
+#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,
+
+ /* Resets */
+ .resets = r9a07g044_resets,
+ .num_resets = R9A07G054_STPAI_ARESETN + 1, /* Last reset ID + 1 */
+
+ .has_clk_mon_regs = true,
+};
+#endif
diff --git a/drivers/clk/renesas/r9a09g011-cpg.c b/drivers/clk/renesas/r9a09g011-cpg.c
new file mode 100644
index 000000000000..40693bb85b80
--- /dev/null
+++ b/drivers/clk/renesas/r9a09g011-cpg.c
@@ -0,0 +1,172 @@
+// 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 RZV2M_SAMPLL4_CLK1 0x104
+#define RZV2M_SAMPLL4_CLK2 0x108
+
+#define PLL4_CONF (RZV2M_SAMPLL4_CLK1 << 22 | RZV2M_SAMPLL4_CLK2 << 12)
+
+#define DIV_A DDIV_PACK(0x200, 0, 3)
+#define DIV_B DDIV_PACK(0x204, 0, 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_E SEL_PLL_PACK(0x214, 2, 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_E,
+ CLK_DIV_W,
+ CLK_SEL_B,
+ CLK_SEL_B_D2,
+ CLK_SEL_E,
+ 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_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_e[] = { ".main", ".dive" };
+static const char * const sel_w[] = { ".main", ".divw" };
+
+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, PLL4_CONF),
+
+ 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(".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(".sele", CLK_SEL_E, SEL_E, sel_e),
+ 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("gic", R9A09G011_GIC_CLK, CLK_SEL_B_D2, 0x400, 5),
+ DEF_COUPLED("eth_axi", R9A09G011_ETH0_CLK_AXI, CLK_PLL2_200, 0x40c, 8),
+ DEF_COUPLED("eth_chi", R9A09G011_ETH0_CLK_CHI, CLK_PLL2_100, 0x40c, 8),
+ DEF_MOD("eth_clk_gptp", R9A09G011_ETH0_GPTP_EXT, CLK_PLL2_100, 0x40c, 9),
+ DEF_MOD("syc_cnt_clk", R9A09G011_SYC_CNT_CLK, CLK_MAIN_24, 0x41c, 12),
+ DEF_MOD("urt_pclk", R9A09G011_URT_PCLK, CLK_SEL_E, 0x438, 4),
+ DEF_MOD("urt0_clk", R9A09G011_URT0_CLK, CLK_SEL_W0, 0x438, 5),
+ DEF_MOD("ca53", R9A09G011_CA53_CLK, CLK_DIV_A, 0x448, 0),
+};
+
+static const struct rzg2l_reset r9a09g011_resets[] = {
+ DEF_RST_MON(R9A09G011_ETH0_RST_HW_N, 0x608, 11, 11),
+ DEF_RST_MON(R9A09G011_SYC_RST_N, 0x610, 9, 13),
+};
+
+static const unsigned int r9a09g011_crit_mod_clks[] __initconst = {
+ MOD_CLK_BASE + R9A09G011_CA53_CLK,
+ 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/rcar-cpg-lib.c b/drivers/clk/renesas/rcar-cpg-lib.c
new file mode 100644
index 000000000000..e2e0447de190
--- /dev/null
+++ b/drivers/clk/renesas/rcar-cpg-lib.c
@@ -0,0 +1,196 @@
+// 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"
+
+spinlock_t 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[] = {
+ { 0, 1 }, { 1, 2 }, { STPnHCK | 2, 4 }, { STPnHCK | 3, 8 },
+ { STPnHCK | 4, 16 }, { 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(sizeof(*csn), GFP_KERNEL);
+ 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(sizeof(*rpc), GFP_KERNEL);
+ 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(sizeof(*rpcd2), GFP_KERNEL);
+ 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 000000000000..94627df1c94c
--- /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
index f596a2dafcf4..edae874fa2b6 100644
--- a/drivers/clk/renesas/rcar-gen2-cpg.c
+++ b/drivers/clk/renesas/rcar-gen2-cpg.c
@@ -63,19 +63,22 @@ static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
return div_u64((u64)parent_rate * mult, 32);
}
-static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int cpg_z_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- unsigned long prate = *parent_rate;
- unsigned int mult;
+ unsigned long prate = req->best_parent_rate;
+ unsigned int min_mult, max_mult, mult;
- if (!prate)
- prate = 1;
+ 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_u64((u64)rate * 32, prate);
- mult = clamp(mult, 1U, 32U);
+ mult = div64_ul(req->rate * 32ULL, prate);
+ mult = clamp(mult, min_mult, max_mult);
- return *parent_rate / 32 * 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,
@@ -86,7 +89,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
u32 val, kick;
unsigned int i;
- mult = div_u64((u64)rate * 32, parent_rate);
+ mult = div64_ul(rate * 32ULL, parent_rate);
mult = clamp(mult, 1U, 32U);
if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
@@ -126,7 +129,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops cpg_z_clk_ops = {
.recalc_rate = cpg_z_clk_recalc_rate,
- .round_rate = cpg_z_clk_round_rate,
+ .determine_rate = cpg_z_clk_determine_rate,
.set_rate = cpg_z_clk_set_rate,
};
@@ -134,7 +137,7 @@ static struct clk * __init cpg_z_clk_register(const char *name,
const char *parent_name,
void __iomem *base)
{
- struct clk_init_data init;
+ struct clk_init_data init = {};
struct cpg_z_clk *zclk;
struct clk *clk;
@@ -144,7 +147,6 @@ static struct clk * __init cpg_z_clk_register(const char *name,
init.name = name;
init.ops = &cpg_z_clk_ops;
- init.flags = 0;
init.parent_names = &parent_name;
init.num_parents = 1;
diff --git a/drivers/clk/renesas/rcar-gen2-cpg.h b/drivers/clk/renesas/rcar-gen2-cpg.h
index db2f57ef2f99..bdcd4a38d48d 100644
--- a/drivers/clk/renesas/rcar-gen2-cpg.h
+++ b/drivers/clk/renesas/rcar-gen2-cpg.h
@@ -24,10 +24,10 @@ enum rcar_gen2_clk_types {
};
struct rcar_gen2_cpg_pll_config {
- unsigned int extal_div;
- unsigned int pll1_mult;
- unsigned int pll3_mult;
- unsigned int pll0_mult; /* leave as zero if PLL0CR exists */
+ 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,
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c
index d25c8ba00a65..e668f23c75e7 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.c
+++ b/drivers/clk/renesas/rcar-gen3-cpg.c
@@ -23,58 +23,128 @@
#include <linux/sys_soc.h>
#include "renesas-cpg-mssr.h"
+#include "rcar-cpg-lib.h"
#include "rcar-gen3-cpg.h"
-#define CPG_PLL0CR 0x00d8
+#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 */
-static spinlock_t cpg_lock;
+/* 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 void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set)
+static unsigned long cpg_pll_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
{
- unsigned long flags;
+ struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
+ unsigned int mult;
u32 val;
- spin_lock_irqsave(&cpg_lock, flags);
- val = readl(reg);
- val &= ~clear;
- val |= set;
- writel(val, reg);
- spin_unlock_irqrestore(&cpg_lock, flags);
-};
+ val = readl(pll_clk->pllcr_reg) & CPG_PLLnCR_STC_MASK;
+ mult = (val >> __ffs(CPG_PLLnCR_STC_MASK)) + 1;
-struct cpg_simple_notifier {
- struct notifier_block nb;
- void __iomem *reg;
- u32 saved;
-};
+ return parent_rate * mult * pll_clk->fixed_mult;
+}
-static int cpg_simple_notifier_call(struct notifier_block *nb,
- unsigned long action, void *data)
+static int cpg_pll_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- struct cpg_simple_notifier *csn =
- container_of(nb, struct cpg_simple_notifier, nb);
+ 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;
- switch (action) {
- case PM_EVENT_SUSPEND:
- csn->saved = readl(csn->reg);
- return NOTIFY_OK;
+ mult = DIV_ROUND_CLOSEST_ULL(req->rate, prate);
+ mult = clamp(mult, min_mult, max_mult);
- case PM_EVENT_RESUME:
- writel(csn->saved, csn->reg);
- return NOTIFY_OK;
+ 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 |= (mult - 1) << __ffs(CPG_PLLnCR_STC_MASK);
+ 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 NOTIFY_DONE;
+
+ return -ETIMEDOUT;
}
-static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
- struct cpg_simple_notifier *csn)
+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)
+
{
- csn->nb.notifier_call = cpg_simple_notifier_call;
- raw_notifier_chain_register(notifiers, &csn->nb);
+ struct cpg_pll_clk *pll_clk;
+ struct clk_init_data init = {};
+ struct clk *clk;
+
+ pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+ 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;
}
/*
@@ -83,7 +153,8 @@ static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
* 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 ) / 2
+ * rate - rate is adjustable.
+ * clk->rate = (parent->rate * mult / 32 ) / fixed_div
* parent - fixed parent. No clk_set_parent support
*/
#define CPG_FRQCRB 0x00000004
@@ -94,8 +165,9 @@ struct cpg_z_clk {
struct clk_hw hw;
void __iomem *reg;
void __iomem *kick_reg;
- unsigned long mask;
+ 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)
@@ -114,18 +186,35 @@ static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
32 * zclk->fixed_div);
}
-static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+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 long prate;
- unsigned int mult;
+ 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 = *parent_rate / zclk->fixed_div;
- mult = div_u64(rate * 32ULL, prate);
- mult = clamp(mult, 1U, 32U);
+ 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;
- return (u64)prate * mult / 32;
+ 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,
@@ -142,8 +231,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
return -EBUSY;
- cpg_reg_modify(zclk->reg, zclk->mask,
- ((32 - mult) << __ffs(zclk->mask)) & zclk->mask);
+ cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));
/*
* Set KICK bit in FRQCRB to update hardware setting and wait for
@@ -156,7 +244,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
*
* Using experimental measurements, it seems that no more than
* ~10 iterations are needed, independently of the CPU rate.
- * Since this value might be dependent of external xtal rate, pll1
+ * 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.
*/
@@ -172,7 +260,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops cpg_z_clk_ops = {
.recalc_rate = cpg_z_clk_recalc_rate,
- .round_rate = cpg_z_clk_round_rate,
+ .determine_rate = cpg_z_clk_determine_rate,
.set_rate = cpg_z_clk_set_rate,
};
@@ -182,7 +270,7 @@ static struct clk * __init cpg_z_clk_register(const char *name,
unsigned int div,
unsigned int offset)
{
- struct clk_init_data init;
+ struct clk_init_data init = {};
struct cpg_z_clk *zclk;
struct clk *clk;
@@ -192,7 +280,7 @@ static struct clk * __init cpg_z_clk_register(const char *name,
init.name = name;
init.ops = &cpg_z_clk_ops;
- init.flags = 0;
+ init.flags = CLK_SET_RATE_PARENT;
init.parent_names = &parent_name;
init.num_parents = 1;
@@ -203,335 +291,41 @@ static struct clk * __init cpg_z_clk_register(const char *name,
zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
clk = clk_register(NULL, &zclk->hw);
- if (IS_ERR(clk))
+ if (IS_ERR(clk)) {
kfree(zclk);
-
- return clk;
-}
-
-/*
- * SDn Clock
- */
-#define CPG_SD_STP_HCK BIT(9)
-#define CPG_SD_STP_CK BIT(8)
-
-#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK)
-#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0)
-
-#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
-{ \
- .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
- ((stp_ck) ? CPG_SD_STP_CK : 0) | \
- ((sd_srcfc) << 2) | \
- ((sd_fc) << 0), \
- .div = (sd_div), \
-}
-
-struct sd_div_table {
- u32 val;
- unsigned int div;
-};
-
-struct sd_clock {
- struct clk_hw hw;
- const struct sd_div_table *div_table;
- struct cpg_simple_notifier csn;
- unsigned int div_num;
- unsigned int cur_div_idx;
-};
-
-/* SDn divider
- * sd_srcfc sd_fc div
- * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc
- *-------------------------------------------------------------------
- * 0 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP)
- * 0 0 1 (2) 1 (4) 8 : SDR50
- * 1 0 2 (4) 1 (4) 16 : HS / SDR25
- * 1 0 3 (8) 1 (4) 32 : NS / SDR12
- * 1 0 4 (16) 1 (4) 64
- * 0 0 0 (1) 0 (2) 2
- * 0 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP)
- * 1 0 2 (4) 0 (2) 8
- * 1 0 3 (8) 0 (2) 16
- * 1 0 4 (16) 0 (2) 32
- *
- * NOTE: There is a quirk option to ignore the first row of the dividers
- * table when searching for suitable settings. This is because HS400 on
- * early ES versions of H3 and M3-W requires a specific setting to work.
- */
-static const struct sd_div_table cpg_sd_div_table[] = {
-/* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */
- CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4),
- CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8),
- CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16),
- CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32),
- CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64),
- CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2),
- CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4),
- CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8),
- CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16),
- CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32),
-};
-
-#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
-
-static int cpg_sd_clock_enable(struct clk_hw *hw)
-{
- struct sd_clock *clock = to_sd_clock(hw);
-
- cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK,
- clock->div_table[clock->cur_div_idx].val &
- CPG_SD_STP_MASK);
-
- return 0;
-}
-
-static void cpg_sd_clock_disable(struct clk_hw *hw)
-{
- struct sd_clock *clock = to_sd_clock(hw);
-
- cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK);
-}
-
-static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
-{
- struct sd_clock *clock = to_sd_clock(hw);
-
- return !(readl(clock->csn.reg) & CPG_SD_STP_MASK);
-}
-
-static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- struct sd_clock *clock = to_sd_clock(hw);
-
- return DIV_ROUND_CLOSEST(parent_rate,
- clock->div_table[clock->cur_div_idx].div);
-}
-
-static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock,
- unsigned long rate,
- unsigned long parent_rate)
-{
- unsigned long calc_rate, diff, diff_min = ULONG_MAX;
- unsigned int i, best_div = 0;
-
- for (i = 0; i < clock->div_num; i++) {
- calc_rate = DIV_ROUND_CLOSEST(parent_rate,
- clock->div_table[i].div);
- diff = calc_rate > rate ? calc_rate - rate : rate - calc_rate;
- if (diff < diff_min) {
- best_div = clock->div_table[i].div;
- diff_min = diff;
- }
- }
-
- return best_div;
-}
-
-static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
-{
- struct sd_clock *clock = to_sd_clock(hw);
- unsigned int div = cpg_sd_clock_calc_div(clock, rate, *parent_rate);
-
- return DIV_ROUND_CLOSEST(*parent_rate, div);
-}
-
-static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct sd_clock *clock = to_sd_clock(hw);
- unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate);
- unsigned int i;
-
- for (i = 0; i < clock->div_num; i++)
- if (div == clock->div_table[i].div)
- break;
-
- if (i >= clock->div_num)
- return -EINVAL;
-
- clock->cur_div_idx = i;
-
- cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK,
- clock->div_table[i].val &
- (CPG_SD_STP_MASK | CPG_SD_FC_MASK));
-
- return 0;
-}
-
-static const struct clk_ops cpg_sd_clock_ops = {
- .enable = cpg_sd_clock_enable,
- .disable = cpg_sd_clock_disable,
- .is_enabled = cpg_sd_clock_is_enabled,
- .recalc_rate = cpg_sd_clock_recalc_rate,
- .round_rate = cpg_sd_clock_round_rate,
- .set_rate = cpg_sd_clock_set_rate,
-};
-
-static u32 cpg_quirks __initdata;
-
-#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */
-#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
-#define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */
-
-static struct clk * __init cpg_sd_clk_register(const char *name,
- void __iomem *base, unsigned int offset, const char *parent_name,
- struct raw_notifier_head *notifiers)
-{
- struct clk_init_data init;
- struct sd_clock *clock;
- struct clk *clk;
- u32 val;
-
- clock = kzalloc(sizeof(*clock), GFP_KERNEL);
- if (!clock)
- return ERR_PTR(-ENOMEM);
-
- init.name = name;
- init.ops = &cpg_sd_clock_ops;
- init.flags = CLK_SET_RATE_PARENT;
- init.parent_names = &parent_name;
- init.num_parents = 1;
-
- clock->csn.reg = base + offset;
- clock->hw.init = &init;
- clock->div_table = cpg_sd_div_table;
- clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
-
- if (cpg_quirks & SD_SKIP_FIRST) {
- clock->div_table++;
- clock->div_num--;
+ return clk;
}
- val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK;
- val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK);
- writel(val, clock->csn.reg);
-
- clk = clk_register(NULL, &clock->hw);
- if (IS_ERR(clk))
- goto free_clock;
-
- cpg_simple_notifier_register(notifiers, &clock->csn);
- return clk;
-
-free_clock:
- kfree(clock);
+ zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
+ zclk->fixed_div;
return clk;
}
-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_rpcsrc_div_table[] = {
{ 2, 5 }, { 3, 6 }, { 0, 0 },
};
-static const struct clk_div_table cpg_rpc_div_table[] = {
- { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 },
-};
-
-static struct clk * __init cpg_rpc_clk_register(const char *name,
- void __iomem *base, const char *parent_name,
- struct raw_notifier_head *notifiers)
-{
- struct rpc_clock *rpc;
- struct clk *clk;
-
- rpc = kzalloc(sizeof(*rpc), GFP_KERNEL);
- if (!rpc)
- return ERR_PTR(-ENOMEM);
-
- rpc->div.reg = base + CPG_RPCCKCR;
- rpc->div.width = 3;
- rpc->div.table = cpg_rpc_div_table;
- rpc->div.lock = &cpg_lock;
-
- rpc->gate.reg = base + CPG_RPCCKCR;
- rpc->gate.bit_idx = 8;
- rpc->gate.flags = CLK_GATE_SET_TO_DISABLE;
- rpc->gate.lock = &cpg_lock;
-
- rpc->csn.reg = base + CPG_RPCCKCR;
-
- clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
- &rpc->div.hw, &clk_divider_ops,
- &rpc->gate.hw, &clk_gate_ops, 0);
- 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;
-};
-
-static struct clk * __init cpg_rpcd2_clk_register(const char *name,
- void __iomem *base,
- const char *parent_name)
-{
- struct rpcd2_clock *rpcd2;
- struct clk *clk;
-
- rpcd2 = kzalloc(sizeof(*rpcd2), GFP_KERNEL);
- if (!rpcd2)
- return ERR_PTR(-ENOMEM);
-
- rpcd2->fixed.mult = 1;
- rpcd2->fixed.div = 2;
-
- rpcd2->gate.reg = base + CPG_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, 0);
- if (IS_ERR(clk))
- kfree(rpcd2);
-
- return clk;
-}
-
-
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 PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */
+#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
+
static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
{
.soc_id = "r8a7795", .revision = "ES1.0",
- .data = (void *)(PLL_ERRATA | RCKCR_CKSEL | SD_SKIP_FIRST),
+ .data = (void *)(PLL_ERRATA | RCKCR_CKSEL),
},
{
.soc_id = "r8a7795", .revision = "ES1.*",
- .data = (void *)(RCKCR_CKSEL | SD_SKIP_FIRST),
- },
- {
- .soc_id = "r8a7795", .revision = "ES2.0",
- .data = (void *)SD_SKIP_FIRST,
+ .data = (void *)(RCKCR_CKSEL),
},
{
.soc_id = "r8a7796", .revision = "ES1.0",
- .data = (void *)(RCKCR_CKSEL | SD_SKIP_FIRST),
- },
- {
- .soc_id = "r8a7796", .revision = "ES1.1",
- .data = (void *)SD_SKIP_FIRST,
+ .data = (void *)(RCKCR_CKSEL),
},
{ /* sentinel */ }
};
@@ -557,16 +351,13 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
case CLK_TYPE_GEN3_PLL0:
/*
- * PLL0 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.
+ * PLL0 is implemented as a custom clock, to change the
+ * multiplier when cpufreq changes between normal and boost
+ * modes.
*/
- value = readl(base + CPG_PLL0CR);
- mult = (((value >> 24) & 0x7f) + 1) * 2;
- if (cpg_quirks & PLL_ERRATA)
- mult *= 2;
- break;
+ mult = (cpg_quirks & PLL_ERRATA) ? 4 : 2;
+ return cpg_pll_clk_register(core->name, __clk_get_name(parent),
+ base, mult, CPG_PLL0CR, 0);
case CLK_TYPE_GEN3_PLL1:
mult = cpg_pll_config->pll1_mult;
@@ -575,16 +366,13 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
case CLK_TYPE_GEN3_PLL2:
/*
- * PLL2 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.
+ * PLL2 is implemented as a custom clock, to change the
+ * multiplier when cpufreq changes between normal and boost
+ * modes.
*/
- value = readl(base + CPG_PLL2CR);
- mult = (((value >> 24) & 0x7f) + 1) * 2;
- if (cpg_quirks & PLL_ERRATA)
- mult *= 2;
- break;
+ mult = (cpg_quirks & PLL_ERRATA) ? 4 : 2;
+ return cpg_pll_clk_register(core->name, __clk_get_name(parent),
+ base, mult, CPG_PLL2CR, 2);
case CLK_TYPE_GEN3_PLL3:
mult = cpg_pll_config->pll3_mult;
@@ -604,10 +392,14 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
mult *= 2;
break;
- case CLK_TYPE_GEN3_SD:
- return cpg_sd_clk_register(core->name, base, core->offset,
+ 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;
@@ -688,12 +480,40 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
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,
+ 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,
+ return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
__clk_get_name(parent));
default:
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h
index c4ac80cac6a0..9028bf4295ce 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.h
+++ b/drivers/clk/renesas/rcar-gen3-cpg.h
@@ -17,6 +17,7 @@ enum rcar_gen3_clk_types {
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 */
@@ -24,6 +25,7 @@ enum rcar_gen3_clk_types {
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,
@@ -31,6 +33,9 @@ enum rcar_gen3_clk_types {
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)
@@ -54,6 +59,13 @@ enum rcar_gen3_clk_types {
#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;
diff --git a/drivers/clk/renesas/rcar-gen4-cpg.c b/drivers/clk/renesas/rcar-gen4-cpg.c
new file mode 100644
index 000000000000..c7ed43d6aa67
--- /dev/null
+++ b/drivers/clk/renesas/rcar-gen4-cpg.c
@@ -0,0 +1,310 @@
+// 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/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 __initconst;
+static unsigned int cpg_clk_extalr __initdata;
+static u32 cpg_mode __initdata;
+
+/*
+ * Z0 Clock & Z1 Clock
+ */
+#define CPG_FRQCRB 0x00000804
+#define CPG_FRQCRB_KICK BIT(31)
+#define CPG_FRQCRC 0x00000808
+
+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;
+ u32 val;
+
+ val = readl(zclk->reg) & zclk->mask;
+ mult = 32 - (val >> __ffs(zclk->mask));
+
+ 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, (32 - mult) << __ffs(zclk->mask));
+
+ /*
+ * 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(sizeof(*zclk), GFP_KERNEL);
+ 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;
+
+ zclk->reg = reg + CPG_FRQCRC;
+ 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 clk **clks, void __iomem *base,
+ struct raw_notifier_head *notifiers)
+{
+ 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_PLL2:
+ mult = cpg_pll_config->pll2_mult;
+ div = cpg_pll_config->pll2_div;
+ break;
+
+ case CLK_TYPE_GEN4_PLL3:
+ mult = cpg_pll_config->pll3_mult;
+ div = cpg_pll_config->pll3_div;
+ break;
+
+ case CLK_TYPE_GEN4_PLL4:
+ mult = cpg_pll_config->pll4_mult;
+ div = cpg_pll_config->pll4_div;
+ break;
+
+ case CLK_TYPE_GEN4_PLL5:
+ mult = cpg_pll_config->pll5_mult;
+ div = cpg_pll_config->pll5_div;
+ break;
+
+ case CLK_TYPE_GEN4_PLL6:
+ mult = cpg_pll_config->pll6_mult;
+ div = cpg_pll_config->pll6_div;
+ break;
+
+ case CLK_TYPE_GEN4_PLL2X_3X:
+ value = readl(base + core->offset);
+ mult = (((value >> 24) & 0x7f) + 1) * 2;
+ break;
+
+ 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:
+ div = ((readl(base + SD0CKCR1) >> 29) & 0x03) + 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;
+
+ spin_lock_init(&cpg_lock);
+
+ 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 000000000000..0b15dcfdca7b
--- /dev/null
+++ b/drivers/clk/renesas/rcar-gen4-cpg.h
@@ -0,0 +1,79 @@
+/* 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_PLL2,
+ CLK_TYPE_GEN4_PLL2X_3X, /* r8a779a0 only */
+ CLK_TYPE_GEN4_PLL3,
+ CLK_TYPE_GEN4_PLL5,
+ CLK_TYPE_GEN4_PLL4,
+ CLK_TYPE_GEN4_PLL6,
+ CLK_TYPE_GEN4_SDSRC,
+ CLK_TYPE_GEN4_SDH,
+ CLK_TYPE_GEN4_SD,
+ CLK_TYPE_GEN4_MDSEL, /* Select parent/divider using mode pin */
+ 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_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 pll2_mult;
+ u8 pll2_div;
+ u8 pll3_mult;
+ u8 pll3_div;
+ u8 pll4_mult;
+ u8 pll4_div;
+ u8 pll5_mult;
+ u8 pll5_div;
+ u8 pll6_mult;
+ u8 pll6_div;
+ u8 osc_prediv;
+};
+
+#define CPG_RPCCKCR 0x874
+#define SD0CKCR1 0x8a4
+
+struct clk *rcar_gen4_cpg_clk_register(struct device *dev,
+ const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+ struct clk **clks, void __iomem *base,
+ struct raw_notifier_head *notifiers);
+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
index cc90b11a9c25..684d8937965e 100644
--- a/drivers/clk/renesas/rcar-usb2-clock-sel.c
+++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c
@@ -19,6 +19,7 @@
#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
@@ -26,9 +27,16 @@
#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;
};
@@ -53,14 +61,32 @@ static void usb2_clock_sel_disable_extal_only(struct usb2_clock_sel_priv *priv)
static int usb2_clock_sel_enable(struct clk_hw *hw)
{
- usb2_clock_sel_enable_extal_only(to_priv(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)
{
- usb2_clock_sel_disable_extal_only(to_priv(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);
}
/*
@@ -102,10 +128,8 @@ static int rcar_usb2_clock_sel_resume(struct device *dev)
static int rcar_usb2_clock_sel_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct usb2_clock_sel_priv *priv = platform_get_drvdata(pdev);
of_clk_del_provider(dev->of_node);
- clk_hw_unregister(&priv->hw);
pm_runtime_put(dev);
pm_runtime_disable(dev);
@@ -117,21 +141,26 @@ 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 resource *res;
struct clk *clk;
- struct clk_init_data init;
+ struct clk_init_data init = {};
+ int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(dev, res);
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
- pm_runtime_enable(dev);
- pm_runtime_get_sync(dev);
+ 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)) {
@@ -149,21 +178,29 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev)
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;
- init.flags = 0;
- init.parent_names = NULL;
- init.num_parents = 0;
priv->hw.init = &init;
- clk = clk_register(NULL, &priv->hw);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
+ ret = devm_clk_hw_register(dev, &priv->hw);
+ if (ret)
+ goto pm_put;
- return of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw);
+ 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 = {
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index 52bbb9ce3807..1a0cdf001b2f 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -57,8 +57,12 @@ static const u16 mstpsr[] = {
0x9A0, 0x9A4, 0x9A8, 0x9AC,
};
-#define MSTPSR(i) mstpsr[i]
-
+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,
+};
/*
* System Module Stop Control Register offsets
@@ -69,7 +73,12 @@ static const u16 smstpcr[] = {
0x990, 0x994, 0x998, 0x99C,
};
-#define SMSTPCR(i) smstpcr[i]
+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,
+};
/*
* Standby Control Register offsets (RZ/A)
@@ -81,8 +90,6 @@ static const u16 stbcr[] = {
0x424, 0x428, 0x42C,
};
-#define STBCR(i) stbcr[i]
-
/*
* Software Reset Register offsets
*/
@@ -92,34 +99,49 @@ static const u16 srcr[] = {
0x920, 0x924, 0x928, 0x92C,
};
-#define SRCR(i) srcr[i]
-
-
-/* Realtime Module Stop Control Register offsets */
-#define RMSTPCR(i) (smstpcr[i] - 0x20)
+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,
+};
-/* Modem Module Stop Control Register offsets (r8a73a4) */
-#define MMSTPCR(i) (smstpcr[i] + 0x20)
+/*
+ * Software Reset Clearing Register offsets
+ */
-/* Software Reset Clearing Register offsets */
-#define SRSTCLR(i) (0x940 + (i) * 4)
+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,
+};
/**
- * Clock Pulse Generator / Module Standby and Software Reset Private Data
+ * struct cpg_mssr_priv - Clock Pulse Generator / Module Standby
+ * and Software Reset Private Data
*
* @rcdev: Optional reset controller entity
* @dev: CPG/MSSR device
* @base: CPG/MSSR register block base address
+ * @reg_layout: CPG/MSSR register layout
* @rmw_lock: protects RMW register accesses
* @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
- * @stbyctrl: This device has Standby Control Registers
* @notifiers: Notifier chain to save/restore clock state for system resume
- * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control
- * @smstpcr_saved[].val: Saved values of SMSTPCR[]
+ * @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[]
* @clks: Array containing all Core and Module Clocks
*/
struct cpg_mssr_priv {
@@ -128,19 +150,23 @@ struct cpg_mssr_priv {
#endif
struct device *dev;
void __iomem *base;
+ enum clk_reg_layout reg_layout;
spinlock_t rmw_lock;
struct device_node *np;
unsigned int num_core_clks;
unsigned int num_mod_clks;
unsigned int last_dt_core_clk;
- bool stbyctrl;
struct raw_notifier_head notifiers;
+ 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(smstpcr)];
+ } smstpcr_saved[ARRAY_SIZE(mstpsr_for_gen4)];
struct clk *clks[];
};
@@ -177,40 +203,40 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
enable ? "ON" : "OFF");
spin_lock_irqsave(&priv->rmw_lock, flags);
- if (priv->stbyctrl) {
- value = readb(priv->base + STBCR(reg));
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
+ value = readb(priv->base + priv->control_regs[reg]);
if (enable)
value &= ~bitmask;
else
value |= bitmask;
- writeb(value, priv->base + STBCR(reg));
+ writeb(value, priv->base + priv->control_regs[reg]);
/* dummy read to ensure write has completed */
- readb(priv->base + STBCR(reg));
- barrier_data(priv->base + STBCR(reg));
+ readb(priv->base + priv->control_regs[reg]);
+ barrier_data(priv->base + priv->control_regs[reg]);
} else {
- value = readl(priv->base + SMSTPCR(reg));
+ value = readl(priv->base + priv->control_regs[reg]);
if (enable)
value &= ~bitmask;
else
value |= bitmask;
- writel(value, priv->base + SMSTPCR(reg));
+ writel(value, priv->base + priv->control_regs[reg]);
}
spin_unlock_irqrestore(&priv->rmw_lock, flags);
- if (!enable || priv->stbyctrl)
+ if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
return 0;
for (i = 1000; i > 0; --i) {
- if (!(readl(priv->base + MSTPSR(reg)) & bitmask))
+ if (!(readl(priv->base + priv->status_regs[reg]) & bitmask))
break;
cpu_relax();
}
if (!i) {
dev_err(dev, "Failed to enable SMSTP %p[%d]\n",
- priv->base + SMSTPCR(reg), bit);
+ priv->base + priv->control_regs[reg], bit);
return -ETIMEDOUT;
}
@@ -233,10 +259,10 @@ static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
struct cpg_mssr_priv *priv = clock->priv;
u32 value;
- if (priv->stbyctrl)
- value = readb(priv->base + STBCR(clock->index / 32));
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
+ value = readb(priv->base + priv->control_regs[clock->index / 32]);
else
- value = readl(priv->base + MSTPSR(clock->index / 32));
+ value = readl(priv->base + priv->status_regs[clock->index / 32]);
return !(value & BIT(clock->index % 32));
}
@@ -272,7 +298,7 @@ struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec,
case CPG_MOD:
type = "module";
- if (priv->stbyctrl) {
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
idx = MOD_CLK_PACK_10(clkidx);
range_check = 7 - (clkidx % 10);
} else {
@@ -386,7 +412,7 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
struct mstp_clock *clock = NULL;
struct device *dev = priv->dev;
unsigned int id = mod->id;
- struct clk_init_data init;
+ struct clk_init_data init = {};
struct clk *parent, *clk;
const char *parent_name;
unsigned int i;
@@ -416,14 +442,6 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
init.name = mod->name;
init.ops = &cpg_mstp_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, "MSTP %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;
@@ -432,6 +450,15 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
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;
+ }
+
clk = clk_register(NULL, &clock->hw);
if (IS_ERR(clk))
goto fail;
@@ -533,6 +560,11 @@ void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *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)
@@ -541,6 +573,7 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
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, sizeof(*pd) + pm_size, GFP_KERNEL);
if (!pd)
@@ -551,14 +584,21 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
genpd = &pd->genpd;
genpd->name = np->name;
- genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
+ 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;
- pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+ 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;
- of_genpd_add_provider_simple(np, genpd);
- return 0;
+ return of_genpd_add_provider_simple(np, genpd);
}
#ifdef CONFIG_RESET_CONTROLLER
@@ -572,23 +612,17 @@ static int cpg_mssr_reset(struct reset_controller_dev *rcdev,
unsigned int reg = id / 32;
unsigned int bit = id % 32;
u32 bitmask = BIT(bit);
- unsigned long flags;
- u32 value;
dev_dbg(priv->dev, "reset %u%02u\n", reg, bit);
/* Reset module */
- spin_lock_irqsave(&priv->rmw_lock, flags);
- value = readl(priv->base + SRCR(reg));
- value |= bitmask;
- writel(value, priv->base + SRCR(reg));
- spin_unlock_irqrestore(&priv->rmw_lock, flags);
+ writel(bitmask, priv->base + priv->reset_regs[reg]);
/* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
udelay(35);
/* Release module from reset state */
- writel(bitmask, priv->base + SRSTCLR(reg));
+ writel(bitmask, priv->base + priv->reset_clear_regs[reg]);
return 0;
}
@@ -599,16 +633,10 @@ static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id)
unsigned int reg = id / 32;
unsigned int bit = id % 32;
u32 bitmask = BIT(bit);
- unsigned long flags;
- u32 value;
dev_dbg(priv->dev, "assert %u%02u\n", reg, bit);
- spin_lock_irqsave(&priv->rmw_lock, flags);
- value = readl(priv->base + SRCR(reg));
- value |= bitmask;
- writel(value, priv->base + SRCR(reg));
- spin_unlock_irqrestore(&priv->rmw_lock, flags);
+ writel(bitmask, priv->base + priv->reset_regs[reg]);
return 0;
}
@@ -622,7 +650,7 @@ static int cpg_mssr_deassert(struct reset_controller_dev *rcdev,
dev_dbg(priv->dev, "deassert %u%02u\n", reg, bit);
- writel(bitmask, priv->base + SRSTCLR(reg));
+ writel(bitmask, priv->base + priv->reset_clear_regs[reg]);
return 0;
}
@@ -634,7 +662,7 @@ static int cpg_mssr_status(struct reset_controller_dev *rcdev,
unsigned int bit = id % 32;
u32 bitmask = BIT(bit);
- return !!(readl(priv->base + SRCR(reg)) & bitmask);
+ return !!(readl(priv->base + priv->reset_regs[reg]) & bitmask);
}
static const struct reset_control_ops cpg_mssr_reset_ops = {
@@ -684,6 +712,12 @@ static const struct of_device_id cpg_mssr_match[] = {
.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",
@@ -713,12 +747,24 @@ static const struct of_device_id cpg_mssr_match[] = {
.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",
@@ -754,12 +800,18 @@ static const struct of_device_id cpg_mssr_match[] = {
.data = &r8a7795_cpg_mssr_info,
},
#endif
-#ifdef CONFIG_CLK_R8A7796
+#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",
@@ -790,6 +842,24 @@ static const struct of_device_id cpg_mssr_match[] = {
.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
{ /* sentinel */ }
};
@@ -812,7 +882,9 @@ static int cpg_mssr_suspend_noirq(struct device *dev)
for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
if (priv->smstpcr_saved[reg].mask)
priv->smstpcr_saved[reg].val =
- readl(priv->base + SMSTPCR(reg));
+ priv->reg_layout == CLK_REG_LAYOUT_RZ_A ?
+ readb(priv->base + priv->control_regs[reg]) :
+ readl(priv->base + priv->control_regs[reg]);
}
/* Save core clocks */
@@ -840,23 +912,23 @@ static int cpg_mssr_resume_noirq(struct device *dev)
if (!mask)
continue;
- if (priv->stbyctrl)
- oldval = readb(priv->base + STBCR(reg));
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
+ oldval = readb(priv->base + priv->control_regs[reg]);
else
- oldval = readl(priv->base + SMSTPCR(reg));
+ oldval = readl(priv->base + priv->control_regs[reg]);
newval = oldval & ~mask;
newval |= priv->smstpcr_saved[reg].val & mask;
if (newval == oldval)
continue;
- if (priv->stbyctrl) {
- writeb(newval, priv->base + STBCR(reg));
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
+ writeb(newval, priv->base + priv->control_regs[reg]);
/* dummy read to ensure write has completed */
- readb(priv->base + STBCR(reg));
- barrier_data(priv->base + STBCR(reg));
+ readb(priv->base + priv->control_regs[reg]);
+ barrier_data(priv->base + priv->control_regs[reg]);
continue;
} else
- writel(newval, priv->base + SMSTPCR(reg));
+ writel(newval, priv->base + priv->control_regs[reg]);
/* Wait until enabled clocks are really enabled */
mask &= ~priv->smstpcr_saved[reg].val;
@@ -864,15 +936,16 @@ static int cpg_mssr_resume_noirq(struct device *dev)
continue;
for (i = 1000; i > 0; --i) {
- oldval = readl(priv->base + MSTPSR(reg));
+ oldval = readl(priv->base + priv->status_regs[reg]);
if (!(oldval & mask))
break;
cpu_relax();
}
if (!i)
- dev_warn(dev, "Failed to enable SMSTP %p[0x%x]\n",
- priv->base + SMSTPCR(reg), oldval & mask);
+ dev_warn(dev, "Failed to enable %s%u[0x%x]\n",
+ priv->reg_layout == CLK_REG_LAYOUT_RZ_A ?
+ "STB" : "SMSTP", reg, oldval & mask);
}
return 0;
@@ -921,7 +994,23 @@ static int __init cpg_mssr_common_init(struct device *dev,
priv->num_mod_clks = info->num_hw_mod_clks;
priv->last_dt_core_clk = info->last_dt_core_clk;
RAW_INIT_NOTIFIER_HEAD(&priv->notifiers);
- priv->stbyctrl = info->stbyctrl;
+ 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_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->clks[i] = ERR_PTR(-ENOENT);
@@ -999,7 +1088,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
return error;
/* Reset Controller not supported for Standby Control SoCs */
- if (info->stbyctrl)
+ if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
return 0;
error = cpg_mssr_reset_controller_register(priv);
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h
index 4ddcdf3bfb95..1c3c057d17f5 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.h
+++ b/drivers/clk/renesas/renesas-cpg-mssr.h
@@ -85,6 +85,12 @@ struct mssr_mod_clk {
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,
+};
+
/**
* SoC-specific CPG/MSSR Description
*
@@ -105,6 +111,7 @@ struct device_node;
* @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
@@ -112,10 +119,6 @@ struct device_node;
*
* @init: Optional callback to perform SoC-specific initialization
* @cpg_clk_register: Optional callback to handle special Core Clock types
- *
- * @stbyctrl: This device has Standby Control Registers which are 8-bits
- * wide, no status registers (MSTPSR) and have different address
- * offsets.
*/
struct cpg_mssr_info {
@@ -130,7 +133,7 @@ struct cpg_mssr_info {
unsigned int num_core_clks;
unsigned int last_dt_core_clk;
unsigned int num_total_core_clks;
- bool stbyctrl;
+ enum clk_reg_layout reg_layout;
/* Module Clocks */
const struct mssr_mod_clk *mod_clks;
@@ -155,11 +158,14 @@ struct cpg_mssr_info {
};
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;
@@ -171,6 +177,9 @@ 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;
void __init cpg_mssr_early_init(struct device_node *np,
const struct cpg_mssr_info *info);
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
new file mode 100644
index 000000000000..e2999ab2b53c
--- /dev/null
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -0,0 +1,1434 @@
+// 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/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/iopoll.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.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/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 DIV_RSMASK(v, s, m) ((v >> s) & m)
+#define GET_SHIFT(val) ((val >> 12) & 0xff)
+#define GET_WIDTH(val) ((val >> 8) & 0xf)
+
+#define KDIV(val) DIV_RSMASK(val, 16, 0xffff)
+#define MDIV(val) DIV_RSMASK(val, 6, 0x3ff)
+#define PDIV(val) DIV_RSMASK(val, 0, 0x3f)
+#define SDIV(val) DIV_RSMASK(val, 0, 0x7)
+
+#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 GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff)
+#define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff)
+
+#define MAX_VCLK_FREQ (148500000)
+
+struct sd_hw_data {
+ struct clk_hw hw;
+ u32 conf;
+ struct rzg2l_cpg_priv *priv;
+};
+
+#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw)
+
+struct rzg2l_pll5_param {
+ u32 pl5_fracin;
+ u8 pl5_refdiv;
+ u8 pl5_intin;
+ u8 pl5_postdiv1;
+ u8 pl5_postdiv2;
+ u8 pl5_spread;
+};
+
+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
+ * @pll5_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 rzg2l_pll5_mux_dsi_div_param mux_dsi_div_params;
+};
+
+static void rzg2l_cpg_del_clk_provider(void *data)
+{
+ of_clk_del_provider(data);
+}
+
+static struct clk * __init
+rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core,
+ struct clk **clks,
+ void __iomem *base,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct device *dev = priv->dev;
+ const struct clk *parent;
+ const char *parent_name;
+ struct clk_hw *clk_hw;
+
+ parent = clks[core->parent & 0xffff];
+ 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,
+ void __iomem *base,
+ 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,
+ 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_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return clk_mux_determine_rate_flags(hw, req, 0);
+}
+
+static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct sd_hw_data *hwdata = to_sd_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = hwdata->priv;
+ u32 off = GET_REG_OFFSET(hwdata->conf);
+ u32 shift = GET_SHIFT(hwdata->conf);
+ const u32 clk_src_266 = 2;
+ u32 bitmask;
+
+ /*
+ * 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.
+ */
+ bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16;
+ if (index != clk_src_266) {
+ u32 msk, val;
+ int ret;
+
+ writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off);
+
+ msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS;
+
+ ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val,
+ !(val & msk), 100,
+ CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
+ if (ret) {
+ dev_err(priv->dev, "failed to switch clk source\n");
+ return ret;
+ }
+ }
+
+ writel(bitmask | ((index + 1) << shift), priv->base + off);
+
+ return 0;
+}
+
+static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw)
+{
+ struct sd_hw_data *hwdata = to_sd_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = hwdata->priv;
+ u32 val = readl(priv->base + GET_REG_OFFSET(hwdata->conf));
+
+ val >>= GET_SHIFT(hwdata->conf);
+ val &= GENMASK(GET_WIDTH(hwdata->conf) - 1, 0);
+ if (val) {
+ val--;
+ } else {
+ /* Prohibited clk source, change it to 533 MHz(reset value) */
+ rzg2l_cpg_sd_clk_mux_set_parent(hw, 0);
+ }
+
+ return val;
+}
+
+static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = {
+ .determine_rate = rzg2l_cpg_sd_clk_mux_determine_rate,
+ .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,
+ void __iomem *base,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct sd_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 = GET_SHIFT(core->conf) ? "sd1" : "sd0";
+ init.ops = &rzg2l_cpg_sd_clk_mux_ops;
+ init.flags = 0;
+ 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;
+}
+
+static unsigned long
+rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params,
+ unsigned long rate)
+{
+ unsigned long foutpostdiv_rate;
+
+ params->pl5_intin = rate / MEGA;
+ params->pl5_fracin = div_u64(((u64)rate % MEGA) << 24, MEGA);
+ params->pl5_refdiv = 2;
+ params->pl5_postdiv1 = 1;
+ params->pl5_postdiv2 = 1;
+ params->pl5_spread = 0x16;
+
+ foutpostdiv_rate =
+ EXTAL_FREQ_IN_MEGA_HZ * MEGA / params->pl5_refdiv *
+ ((((params->pl5_intin << 24) + params->pl5_fracin)) >> 24) /
+ (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(&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);
+
+ return 0;
+}
+
+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 clk **clks,
+ 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 = clks[core->parent & 0xffff];
+ 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_get_vclk_rate(struct clk_hw *hw,
+ unsigned long rate)
+{
+ struct sipll5 *sipll5 = to_sipll5(hw);
+ struct rzg2l_cpg_priv *priv = sipll5->priv;
+ unsigned long vclk;
+
+ vclk = rate / ((1 << priv->mux_dsi_div_params.dsi_div_a) *
+ (priv->mux_dsi_div_params.dsi_div_b + 1));
+
+ if (priv->mux_dsi_div_params.clksrc)
+ vclk /= 2;
+
+ return vclk;
+}
+
+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 long rzg2l_cpg_sipll5_round_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *parent_rate)
+{
+ return rate;
+}
+
+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 = rzg2l_cpg_get_vclk_rate(hw, rate);
+ sipll5->foutpostdiv_rate =
+ rzg2l_cpg_get_foutpostdiv_rate(&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");
+ return ret;
+ }
+
+ /* Output clock setting 1 */
+ writel(CPG_SIPLL5_CLK1_POSTDIV1_WEN | CPG_SIPLL5_CLK1_POSTDIV2_WEN |
+ CPG_SIPLL5_CLK1_REFDIV_WEN | (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");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct clk_ops rzg2l_cpg_sipll5_ops = {
+ .recalc_rate = rzg2l_cpg_sipll5_recalc_rate,
+ .round_rate = rzg2l_cpg_sipll5_round_rate,
+ .set_rate = rzg2l_cpg_sipll5_set_rate,
+};
+
+static struct clk * __init
+rzg2l_cpg_sipll5_register(const struct cpg_core_clk *core,
+ struct clk **clks,
+ 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 = clks[core->parent & 0xffff];
+ 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);
+
+ priv->mux_dsi_div_params.clksrc = 1; /* Use clk src 1 for DSI */
+ priv->mux_dsi_div_params.dsi_div_a = 1; /* Divided by 2 */
+ priv->mux_dsi_div_params.dsi_div_b = 2; /* Divided by 3 */
+
+ return clk_hw->clk;
+}
+
+struct pll_clk {
+ struct clk_hw hw;
+ 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;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+
+ if (pll_clk->type != CLK_TYPE_SAM_PLL)
+ return parent_rate;
+
+ val1 = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf));
+ val2 = readl(priv->base + GET_REG_SAMPLL_CLK2(pll_clk->conf));
+ mult = MDIV(val1) + KDIV(val1) / 65536;
+ div = PDIV(val1) << SDIV(val2);
+
+ return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, div);
+}
+
+static const struct clk_ops rzg2l_cpg_pll_ops = {
+ .recalc_rate = rzg2l_cpg_pll_clk_recalc_rate,
+};
+
+static struct clk * __init
+rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core,
+ struct clk **clks,
+ void __iomem *base,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct device *dev = priv->dev;
+ const struct clk *parent;
+ struct clk_init_data init;
+ const char *parent_name;
+ struct pll_clk *pll_clk;
+
+ parent = clks[core->parent & 0xffff];
+ 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 = &rzg2l_cpg_pll_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 = base;
+ pll_clk->priv = priv;
+ pll_clk->type = core->type;
+
+ return clk_register(NULL, &pll_clk->hw);
+}
+
+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", 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;
+
+ WARN_DEBUG(id >= priv->num_core_clks);
+ WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
+
+ if (!core->name) {
+ /* Skip NULLified clock */
+ return;
+ }
+
+ 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 = clk_register_fixed_factor(NULL, core->name,
+ parent_name, CLK_SET_RATE_PARENT,
+ core->mult, div);
+ break;
+ case CLK_TYPE_SAM_PLL:
+ clk = rzg2l_cpg_pll_clk_register(core, priv->clks,
+ priv->base, priv);
+ break;
+ case CLK_TYPE_SIPLL5:
+ clk = rzg2l_cpg_sipll5_register(core, priv->clks, priv);
+ break;
+ case CLK_TYPE_DIV:
+ clk = rzg2l_cpg_div_clk_register(core, priv->clks,
+ priv->base, priv);
+ break;
+ case CLK_TYPE_MUX:
+ clk = rzg2l_cpg_mux_clk_register(core, priv->base, priv);
+ break;
+ case CLK_TYPE_SD_MUX:
+ clk = rzg2l_cpg_sd_mux_clk_register(core, priv->base, 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->clks, priv);
+ break;
+ default:
+ goto fail;
+ }
+
+ if (IS_ERR_OR_NULL(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 mstp_clock - MSTP gating clock
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ * @off: register offset
+ * @bit: ON/MON bit
+ * @enabled: soft state of the clock, if it is coupled with another clock
+ * @priv: CPG/MSTP private data
+ * @sibling: pointer to the other coupled clock
+ */
+struct mstp_clock {
+ struct clk_hw hw;
+ u16 off;
+ u8 bit;
+ bool enabled;
+ struct rzg2l_cpg_priv *priv;
+ struct mstp_clock *sibling;
+};
+
+#define to_mod_clock(_hw) container_of(_hw, struct mstp_clock, hw)
+
+static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable)
+{
+ struct mstp_clock *clock = to_mod_clock(hw);
+ struct rzg2l_cpg_priv *priv = clock->priv;
+ unsigned int reg = clock->off;
+ struct device *dev = priv->dev;
+ unsigned long flags;
+ unsigned int i;
+ u32 bitmask = BIT(clock->bit);
+ u32 value;
+
+ if (!clock->off) {
+ dev_dbg(dev, "%pC does not support ON/OFF\n", hw->clk);
+ return 0;
+ }
+
+ dev_dbg(dev, "CLK_ON %u/%pC %s\n", CLK_ON_R(reg), hw->clk,
+ enable ? "ON" : "OFF");
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+
+ if (enable)
+ value = (bitmask << 16) | bitmask;
+ else
+ value = bitmask << 16;
+ writel(value, priv->base + CLK_ON_R(reg));
+
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+
+ if (!enable)
+ return 0;
+
+ if (!priv->info->has_clk_mon_regs)
+ return 0;
+
+ for (i = 1000; i > 0; --i) {
+ if (((readl(priv->base + CLK_MON_R(reg))) & bitmask))
+ break;
+ cpu_relax();
+ }
+
+ if (!i) {
+ dev_err(dev, "Failed to enable CLK_ON %p\n",
+ priv->base + CLK_ON_R(reg));
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int rzg2l_mod_clock_enable(struct clk_hw *hw)
+{
+ struct mstp_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 mstp_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 mstp_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 mstp_clock
+*rzg2l_mod_clock__get_sibling(struct mstp_clock *clock,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct clk_hw *hw;
+ unsigned int i;
+
+ for (i = 0; i < priv->num_mod_clks; i++) {
+ struct mstp_clock *clk;
+
+ if (priv->clks[priv->num_core_clks + i] == ERR_PTR(-ENOENT))
+ continue;
+
+ hw = __clk_get_hw(priv->clks[priv->num_core_clks + i]);
+ clk = to_mod_clock(hw);
+ if (clock->off == clk->off && clock->bit == clk->bit)
+ return clk;
+ }
+
+ return NULL;
+}
+
+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 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->clks[id]) != -ENOENT);
+
+ if (!mod->name) {
+ /* Skip NULLified clock */
+ return;
+ }
+
+ 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;
+
+ 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;
+
+ if (mod->is_coupled) {
+ struct mstp_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;
+ }
+ }
+
+ 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_reset(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;
+ unsigned int reg = info->resets[id].off;
+ u32 dis = BIT(info->resets[id].bit);
+ u32 we = dis << 16;
+
+ dev_dbg(rcdev->dev, "reset id:%ld offset:0x%x\n", id, CLK_RST_R(reg));
+
+ /* Reset module */
+ writel(we, priv->base + CLK_RST_R(reg));
+
+ /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
+ udelay(35);
+
+ /* Release module from reset state */
+ writel(we | dis, priv->base + CLK_RST_R(reg));
+
+ return 0;
+}
+
+static int rzg2l_cpg_assert(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;
+ unsigned int reg = info->resets[id].off;
+ u32 value = BIT(info->resets[id].bit) << 16;
+
+ dev_dbg(rcdev->dev, "assert id:%ld offset:0x%x\n", id, CLK_RST_R(reg));
+
+ writel(value, priv->base + CLK_RST_R(reg));
+ return 0;
+}
+
+static int rzg2l_cpg_deassert(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;
+ unsigned int reg = info->resets[id].off;
+ u32 dis = BIT(info->resets[id].bit);
+ u32 value = (dis << 16) | dis;
+
+ dev_dbg(rcdev->dev, "deassert id:%ld offset:0x%x\n", id,
+ CLK_RST_R(reg));
+
+ writel(value, priv->base + CLK_RST_R(reg));
+ return 0;
+}
+
+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;
+ unsigned int reg = info->resets[id].off;
+ u32 bitmask = BIT(info->resets[id].bit);
+ s8 monbit = info->resets[id].monbit;
+
+ if (info->has_clk_mon_regs) {
+ return !(readl(priv->base + CLK_MRST_R(reg)) & bitmask);
+ } else if (monbit >= 0) {
+ u32 monbitmask = BIT(monbit);
+
+ return !!(readl(priv->base + CPG_RST_MON) & monbitmask);
+ }
+ return -ENOTSUPP;
+}
+
+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(const struct of_phandle_args *clkspec)
+{
+ if (clkspec->args_count != 2)
+ return false;
+
+ switch (clkspec->args[0]) {
+ case CPG_MOD:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static int rzg2l_cpg_attach_dev(struct generic_pm_domain *unused, struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct of_phandle_args clkspec;
+ bool once = true;
+ struct clk *clk;
+ int error;
+ int i = 0;
+
+ while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
+ &clkspec)) {
+ if (rzg2l_cpg_is_pm_clk(&clkspec)) {
+ 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;
+ }
+ } else {
+ of_node_put(clkspec.np);
+ }
+ i++;
+ }
+
+ 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 device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct generic_pm_domain *genpd;
+ int ret;
+
+ genpd = devm_kzalloc(dev, sizeof(*genpd), GFP_KERNEL);
+ if (!genpd)
+ return -ENOMEM;
+
+ 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);
+
+ 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(dev);
+ if (error)
+ return error;
+
+ error = rzg2l_cpg_reset_controller_register(priv);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+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_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,
+ },
+};
+
+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");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
new file mode 100644
index 000000000000..cecbdf5e4f93
--- /dev/null
+++ b/drivers/clk/renesas/rzg2l-cpg.h
@@ -0,0 +1,275 @@
+/* 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__
+
+#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_PL2SDHI_DSEL (0x218)
+#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_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_CLK1_POSTDIV1_WEN BIT(16)
+#define CPG_SIPLL5_CLK1_POSTDIV2_WEN BIT(20)
+#define CPG_SIPLL5_CLK1_REFDIV_WEN BIT(24)
+#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_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 20000
+
+/* n = 0/1/2 for PLL1/4/6 */
+#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n))
+#define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n))
+
+#define PLL146_CONF(n) (CPG_SAMPLL_CLK1(n) << 22 | CPG_SAMPLL_CLK2(n) << 12)
+
+#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 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 SEL_SDHI0 DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2)
+#define SEL_SDHI1 DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2)
+
+#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;
+ const struct clk_div_table *dtable;
+ const char * const *parent_names;
+ int flag;
+ int 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,
+
+ /* Clock with divider */
+ CLK_TYPE_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_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_MUX(_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_HIWORD_MASK)
+#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, _parent_names) \
+ DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \
+ .parent_names = _parent_names, \
+ .num_parents = ARRAY_SIZE(_parent_names))
+#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
+ * @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;
+ u16 off;
+ u8 bit;
+ bool is_coupled;
+};
+
+#define DEF_MOD_BASE(_name, _id, _parent, _off, _bit, _is_coupled) \
+ { \
+ .name = _name, \
+ .id = MOD_CLK_BASE + (_id), \
+ .parent = (_parent), \
+ .off = (_off), \
+ .bit = (_bit), \
+ .is_coupled = (_is_coupled), \
+ }
+
+#define DEF_MOD(_name, _id, _parent, _off, _bit) \
+ DEF_MOD_BASE(_name, _id, _parent, _off, _bit, false)
+
+#define DEF_COUPLED(_name, _id, _parent, _off, _bit) \
+ DEF_MOD_BASE(_name, _id, _parent, _off, _bit, 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[]
+ * @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;
+
+ /* 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;
+
+ 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 r9a09g011_cpg_info;
+
+#endif