1 // SPDX-License-Identifier: GPL-2.0+
3 * Renesas RCar Gen3 CPG MSSR driver
5 * Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com>
7 * Based on the following driver from Linux kernel:
8 * r8a7796 Clock Pulse Generator / Module Standby and Software Reset
10 * Copyright (C) 2016 Glider bvba
14 #include <clk-uclass.h>
20 #include <dt-bindings/clock/renesas-cpg-mssr.h>
22 #include "renesas-cpg-mssr.h"
23 #include "rcar-gen3-cpg.h"
25 #define CPG_RST_MODEMR 0x0060
27 #define CPG_PLL0CR 0x00d8
28 #define CPG_PLL2CR 0x002c
29 #define CPG_PLL4CR 0x01f4
31 #define CPG_RPC_PREDIV_MASK 0x3
32 #define CPG_RPC_PREDIV_OFFSET 3
33 #define CPG_RPC_POSTDIV_MASK 0x7
34 #define CPG_RPC_POSTDIV_OFFSET 0
39 #define CPG_SD_STP_HCK BIT(9)
40 #define CPG_SD_STP_CK BIT(8)
42 #define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK)
43 #define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0)
45 #define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
47 .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
48 ((stp_ck) ? CPG_SD_STP_CK : 0) | \
61 * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc
62 *-------------------------------------------------------------------
74 static const struct sd_div_table cpg_sd_div_table
[] = {
75 /* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */
76 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4),
77 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8),
78 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16),
79 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32),
80 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64),
81 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2),
82 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4),
83 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8),
84 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16),
85 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32),
88 static int gen3_clk_get_parent(struct gen3_clk_priv
*priv
, struct clk
*clk
,
89 struct cpg_mssr_info
*info
, struct clk
*parent
)
91 const struct cpg_core_clk
*core
;
94 if (!renesas_clk_is_mod(clk
)) {
95 ret
= renesas_clk_get_core(clk
, info
, &core
);
99 if (core
->type
== CLK_TYPE_GEN3_MDSEL
) {
100 parent
->dev
= clk
->dev
;
101 parent
->id
= core
->parent
>> (priv
->sscg
? 16 : 0);
102 parent
->id
&= 0xffff;
107 return renesas_clk_get_parent(clk
, info
, parent
);
110 static int gen3_clk_setup_sdif_div(struct clk
*clk
, ulong rate
)
112 struct gen3_clk_priv
*priv
= dev_get_priv(clk
->dev
);
113 struct cpg_mssr_info
*info
= priv
->info
;
114 const struct cpg_core_clk
*core
;
118 ret
= gen3_clk_get_parent(priv
, clk
, info
, &parent
);
120 printf("%s[%i] parent fail, ret=%i\n", __func__
, __LINE__
, ret
);
124 if (renesas_clk_is_mod(&parent
))
127 ret
= renesas_clk_get_core(&parent
, info
, &core
);
131 if (core
->type
!= CLK_TYPE_GEN3_SD
)
134 debug("%s[%i] SDIF offset=%x\n", __func__
, __LINE__
, core
->offset
);
136 writel((rate
== 400000000) ? 0x4 : 0x1, priv
->base
+ core
->offset
);
141 static int gen3_clk_enable(struct clk
*clk
)
143 struct gen3_clk_priv
*priv
= dev_get_priv(clk
->dev
);
145 return renesas_clk_endisable(clk
, priv
->base
, true);
148 static int gen3_clk_disable(struct clk
*clk
)
150 struct gen3_clk_priv
*priv
= dev_get_priv(clk
->dev
);
152 return renesas_clk_endisable(clk
, priv
->base
, false);
155 static u64
gen3_clk_get_rate64(struct clk
*clk
)
157 struct gen3_clk_priv
*priv
= dev_get_priv(clk
->dev
);
158 struct cpg_mssr_info
*info
= priv
->info
;
160 const struct cpg_core_clk
*core
;
161 const struct rcar_gen3_cpg_pll_config
*pll_config
=
162 priv
->cpg_pll_config
;
163 u32 value
, mult
, div
, prediv
, postdiv
;
167 debug("%s[%i] Clock: id=%lu\n", __func__
, __LINE__
, clk
->id
);
169 ret
= gen3_clk_get_parent(priv
, clk
, info
, &parent
);
171 printf("%s[%i] parent fail, ret=%i\n", __func__
, __LINE__
, ret
);
175 if (renesas_clk_is_mod(clk
)) {
176 rate
= gen3_clk_get_rate64(&parent
);
177 debug("%s[%i] MOD clk: parent=%lu => rate=%llu\n",
178 __func__
, __LINE__
, parent
.id
, rate
);
182 ret
= renesas_clk_get_core(clk
, info
, &core
);
186 switch (core
->type
) {
188 if (core
->id
== info
->clk_extal_id
) {
189 rate
= clk_get_rate(&priv
->clk_extal
);
190 debug("%s[%i] EXTAL clk: rate=%llu\n",
191 __func__
, __LINE__
, rate
);
195 if (core
->id
== info
->clk_extalr_id
) {
196 rate
= clk_get_rate(&priv
->clk_extalr
);
197 debug("%s[%i] EXTALR clk: rate=%llu\n",
198 __func__
, __LINE__
, rate
);
204 case CLK_TYPE_GEN3_MAIN
:
205 rate
= gen3_clk_get_rate64(&parent
) / pll_config
->extal_div
;
206 debug("%s[%i] MAIN clk: parent=%i extal_div=%i => rate=%llu\n",
208 core
->parent
, pll_config
->extal_div
, rate
);
211 case CLK_TYPE_GEN3_PLL0
:
212 value
= readl(priv
->base
+ CPG_PLL0CR
);
213 mult
= (((value
>> 24) & 0x7f) + 1) * 2;
214 rate
= gen3_clk_get_rate64(&parent
) * mult
;
215 debug("%s[%i] PLL0 clk: parent=%i mult=%u => rate=%llu\n",
216 __func__
, __LINE__
, core
->parent
, mult
, rate
);
219 case CLK_TYPE_GEN3_PLL1
:
220 rate
= gen3_clk_get_rate64(&parent
) * pll_config
->pll1_mult
;
221 rate
/= pll_config
->pll1_div
;
222 debug("%s[%i] PLL1 clk: parent=%i mul=%i div=%i => rate=%llu\n",
224 core
->parent
, pll_config
->pll1_mult
,
225 pll_config
->pll1_div
, rate
);
228 case CLK_TYPE_GEN3_PLL2
:
229 value
= readl(priv
->base
+ CPG_PLL2CR
);
230 mult
= (((value
>> 24) & 0x7f) + 1) * 2;
231 rate
= gen3_clk_get_rate64(&parent
) * mult
;
232 debug("%s[%i] PLL2 clk: parent=%i mult=%u => rate=%llu\n",
233 __func__
, __LINE__
, core
->parent
, mult
, rate
);
236 case CLK_TYPE_GEN3_PLL3
:
237 rate
= gen3_clk_get_rate64(&parent
) * pll_config
->pll3_mult
;
238 rate
/= pll_config
->pll3_div
;
239 debug("%s[%i] PLL3 clk: parent=%i mul=%i div=%i => rate=%llu\n",
241 core
->parent
, pll_config
->pll3_mult
,
242 pll_config
->pll3_div
, rate
);
245 case CLK_TYPE_GEN3_PLL4
:
246 value
= readl(priv
->base
+ CPG_PLL4CR
);
247 mult
= (((value
>> 24) & 0x7f) + 1) * 2;
248 rate
= gen3_clk_get_rate64(&parent
) * mult
;
249 debug("%s[%i] PLL4 clk: parent=%i mult=%u => rate=%llu\n",
250 __func__
, __LINE__
, core
->parent
, mult
, rate
);
254 rate
= (gen3_clk_get_rate64(&parent
) * core
->mult
) / core
->div
;
255 debug("%s[%i] FIXED clk: parent=%i mul=%i div=%i => rate=%llu\n",
257 core
->parent
, core
->mult
, core
->div
, rate
);
260 case CLK_TYPE_GEN3_MDSEL
:
261 div
= (core
->div
>> (priv
->sscg
? 16 : 0)) & 0xffff;
262 rate
= gen3_clk_get_rate64(&parent
) / div
;
263 debug("%s[%i] PE clk: parent=%i div=%u => rate=%llu\n",
265 (core
->parent
>> (priv
->sscg
? 16 : 0)) & 0xffff,
269 case CLK_TYPE_GEN3_SD
: /* FIXME */
270 value
= readl(priv
->base
+ core
->offset
);
271 value
&= CPG_SD_STP_MASK
| CPG_SD_FC_MASK
;
273 for (i
= 0; i
< ARRAY_SIZE(cpg_sd_div_table
); i
++) {
274 if (cpg_sd_div_table
[i
].val
!= value
)
277 rate
= gen3_clk_get_rate64(&parent
) /
278 cpg_sd_div_table
[i
].div
;
279 debug("%s[%i] SD clk: parent=%i div=%i => rate=%llu\n",
281 core
->parent
, cpg_sd_div_table
[i
].div
, rate
);
288 case CLK_TYPE_GEN3_RPC
:
289 rate
= gen3_clk_get_rate64(&parent
);
291 value
= readl(priv
->base
+ core
->offset
);
293 prediv
= (value
>> CPG_RPC_PREDIV_OFFSET
) &
297 else if (prediv
== 3)
302 postdiv
= (value
>> CPG_RPC_POSTDIV_OFFSET
) &
303 CPG_RPC_POSTDIV_MASK
;
306 debug("%s[%i] RPC clk: parent=%i prediv=%i postdiv=%i => rate=%llu\n",
308 core
->parent
, prediv
, postdiv
, rate
);
314 printf("%s[%i] unknown fail\n", __func__
, __LINE__
);
319 static ulong
gen3_clk_get_rate(struct clk
*clk
)
321 return gen3_clk_get_rate64(clk
);
324 static ulong
gen3_clk_set_rate(struct clk
*clk
, ulong rate
)
326 /* Force correct SD-IF divider configuration if applicable */
327 gen3_clk_setup_sdif_div(clk
, rate
);
328 return gen3_clk_get_rate64(clk
);
331 static int gen3_clk_of_xlate(struct clk
*clk
, struct ofnode_phandle_args
*args
)
333 if (args
->args_count
!= 2) {
334 debug("Invaild args_count: %d\n", args
->args_count
);
338 clk
->id
= (args
->args
[0] << 16) | args
->args
[1];
343 const struct clk_ops gen3_clk_ops
= {
344 .enable
= gen3_clk_enable
,
345 .disable
= gen3_clk_disable
,
346 .get_rate
= gen3_clk_get_rate
,
347 .set_rate
= gen3_clk_set_rate
,
348 .of_xlate
= gen3_clk_of_xlate
,
351 int gen3_clk_probe(struct udevice
*dev
)
353 struct gen3_clk_priv
*priv
= dev_get_priv(dev
);
354 struct cpg_mssr_info
*info
=
355 (struct cpg_mssr_info
*)dev_get_driver_data(dev
);
360 priv
->base
= (struct gen3_base
*)devfdt_get_addr(dev
);
365 ret
= fdt_node_offset_by_compatible(gd
->fdt_blob
, -1, info
->reset_node
);
369 rst_base
= fdtdec_get_addr(gd
->fdt_blob
, ret
, "reg");
370 if (rst_base
== FDT_ADDR_T_NONE
)
373 cpg_mode
= readl(rst_base
+ CPG_RST_MODEMR
);
375 priv
->cpg_pll_config
=
376 (struct rcar_gen3_cpg_pll_config
*)info
->get_pll_config(cpg_mode
);
377 if (!priv
->cpg_pll_config
->extal_div
)
380 priv
->sscg
= !(cpg_mode
& BIT(12));
382 ret
= clk_get_by_name(dev
, "extal", &priv
->clk_extal
);
386 if (info
->extalr_node
) {
387 ret
= clk_get_by_name(dev
, info
->extalr_node
, &priv
->clk_extalr
);
395 int gen3_clk_remove(struct udevice
*dev
)
397 struct gen3_clk_priv
*priv
= dev_get_priv(dev
);
399 return renesas_clk_remove(priv
->base
, priv
->info
);