1 // SPDX-License-Identifier: GPL-2.0
3 * R7S9210 Clock Pulse Generator / Module Standby
5 * Based on r8a7795-cpg-mssr.c
7 * Copyright (C) 2018 Chris Brandt
8 * Copyright (C) 2018 Renesas Electronics Corp.
12 #include <linux/clk.h>
13 #include <linux/clk-provider.h>
14 #include <dt-bindings/clock/r7s9210-cpg-mssr.h>
15 #include "renesas-cpg-mssr.h"
17 #define CPG_FRQCR 0x00
21 /* Internal Clock ratio table */
27 /* p0 is always 32 */;
28 } ratio_tab
[5] = { /* I, G, B, P1 */
29 { 2, 4, 8, 16}, /* FRQCR = 0x012 */
30 { 4, 4, 8, 16}, /* FRQCR = 0x112 */
31 { 8, 4, 8, 16}, /* FRQCR = 0x212 */
32 { 16, 8, 16, 16}, /* FRQCR = 0x322 */
33 { 16, 16, 32, 32}, /* FRQCR = 0x333 */
37 CLK_TYPE_RZA_MAIN
= CLK_TYPE_CUSTOM
,
42 /* Core Clock Outputs exported to DT */
43 LAST_DT_CORE_CLK
= R7S9210_CLK_P0
,
45 /* External Input Clocks */
48 /* Internal Core Clocks */
56 static struct cpg_core_clk r7s9210_early_core_clks
[] = {
57 /* External Clock Inputs */
58 DEF_INPUT("extal", CLK_EXTAL
),
60 /* Internal Core Clocks */
61 DEF_BASE(".main", CLK_MAIN
, CLK_TYPE_RZA_MAIN
, CLK_EXTAL
),
62 DEF_BASE(".pll", CLK_PLL
, CLK_TYPE_RZA_PLL
, CLK_MAIN
),
64 /* Core Clock Outputs */
65 DEF_FIXED("p1c", R7S9210_CLK_P1C
, CLK_PLL
, 16, 1),
68 static const struct mssr_mod_clk r7s9210_early_mod_clks
[] __initconst
= {
69 DEF_MOD_STB("ostm2", 34, R7S9210_CLK_P1C
),
70 DEF_MOD_STB("ostm1", 35, R7S9210_CLK_P1C
),
71 DEF_MOD_STB("ostm0", 36, R7S9210_CLK_P1C
),
74 static struct cpg_core_clk r7s9210_core_clks
[] = {
75 /* Core Clock Outputs */
76 DEF_FIXED("i", R7S9210_CLK_I
, CLK_PLL
, 2, 1),
77 DEF_FIXED("g", R7S9210_CLK_G
, CLK_PLL
, 4, 1),
78 DEF_FIXED("b", R7S9210_CLK_B
, CLK_PLL
, 8, 1),
79 DEF_FIXED("p1", R7S9210_CLK_P1
, CLK_PLL
, 16, 1),
80 DEF_FIXED("p0", R7S9210_CLK_P0
, CLK_PLL
, 32, 1),
83 static const struct mssr_mod_clk r7s9210_mod_clks
[] __initconst
= {
84 DEF_MOD_STB("scif4", 43, R7S9210_CLK_P1C
),
85 DEF_MOD_STB("scif3", 44, R7S9210_CLK_P1C
),
86 DEF_MOD_STB("scif2", 45, R7S9210_CLK_P1C
),
87 DEF_MOD_STB("scif1", 46, R7S9210_CLK_P1C
),
88 DEF_MOD_STB("scif0", 47, R7S9210_CLK_P1C
),
90 DEF_MOD_STB("ether1", 64, R7S9210_CLK_B
),
91 DEF_MOD_STB("ether0", 65, R7S9210_CLK_B
),
93 DEF_MOD_STB("i2c3", 84, R7S9210_CLK_P1
),
94 DEF_MOD_STB("i2c2", 85, R7S9210_CLK_P1
),
95 DEF_MOD_STB("i2c1", 86, R7S9210_CLK_P1
),
96 DEF_MOD_STB("i2c0", 87, R7S9210_CLK_P1
),
98 DEF_MOD_STB("spi2", 95, R7S9210_CLK_P1
),
99 DEF_MOD_STB("spi1", 96, R7S9210_CLK_P1
),
100 DEF_MOD_STB("spi0", 97, R7S9210_CLK_P1
),
103 /* The clock dividers in the table vary based on DT and register settings */
104 static void __init
r7s9210_update_clk_table(struct clk
*extal_clk
,
111 /* If EXTAL is above 12MHz, then we know it is Mode 1 */
112 if (clk_get_rate(extal_clk
) > 12000000)
115 frqcr
= clk_readl(base
+ CPG_FRQCR
) & 0xFFF;
118 else if (frqcr
== 0x112)
120 else if (frqcr
== 0x212)
122 else if (frqcr
== 0x322)
124 else if (frqcr
== 0x333)
127 BUG_ON(1); /* Illegal FRQCR value */
129 for (i
= 0; i
< ARRAY_SIZE(r7s9210_core_clks
); i
++) {
130 switch (r7s9210_core_clks
[i
].id
) {
132 r7s9210_core_clks
[i
].div
= ratio_tab
[index
].i
;
135 r7s9210_core_clks
[i
].div
= ratio_tab
[index
].g
;
138 r7s9210_core_clks
[i
].div
= ratio_tab
[index
].b
;
141 case R7S9210_CLK_P1C
:
142 r7s9210_core_clks
[i
].div
= ratio_tab
[index
].p1
;
145 r7s9210_core_clks
[i
].div
= 32;
151 struct clk
* __init
rza2_cpg_clk_register(struct device
*dev
,
152 const struct cpg_core_clk
*core
, const struct cpg_mssr_info
*info
,
153 struct clk
**clks
, void __iomem
*base
,
154 struct raw_notifier_head
*notifiers
)
157 unsigned int mult
= 1;
158 unsigned int div
= 1;
160 parent
= clks
[core
->parent
];
162 return ERR_CAST(parent
);
170 mult
= 44; /* Divider 1 is 1/2 */
172 mult
= 88; /* Divider 1 is 1 */
176 return ERR_PTR(-EINVAL
);
179 if (core
->id
== CLK_MAIN
)
180 r7s9210_update_clk_table(parent
, base
);
182 return clk_register_fixed_factor(NULL
, core
->name
,
183 __clk_get_name(parent
), 0, mult
, div
);
186 const struct cpg_mssr_info r7s9210_cpg_mssr_info __initconst
= {
188 .early_core_clks
= r7s9210_early_core_clks
,
189 .num_early_core_clks
= ARRAY_SIZE(r7s9210_early_core_clks
),
190 .early_mod_clks
= r7s9210_early_mod_clks
,
191 .num_early_mod_clks
= ARRAY_SIZE(r7s9210_early_mod_clks
),
194 .core_clks
= r7s9210_core_clks
,
195 .num_core_clks
= ARRAY_SIZE(r7s9210_core_clks
),
196 .last_dt_core_clk
= LAST_DT_CORE_CLK
,
197 .num_total_core_clks
= MOD_CLK_BASE
,
200 .mod_clks
= r7s9210_mod_clks
,
201 .num_mod_clks
= ARRAY_SIZE(r7s9210_mod_clks
),
202 .num_hw_mod_clks
= 11 * 32, /* includes STBCR0 which doesn't exist */
205 .cpg_clk_register
= rza2_cpg_clk_register
,
207 /* RZ/A2 has Standby Control Registers */
211 static void __init
r7s9210_cpg_mssr_early_init(struct device_node
*np
)
213 cpg_mssr_early_init(np
, &r7s9210_cpg_mssr_info
);
216 CLK_OF_DECLARE_DRIVER(cpg_mstp_clks
, "renesas,r7s9210-cpg-mssr",
217 r7s9210_cpg_mssr_early_init
);