2 * Renesas RCar Gen3 CPG MSSR driver
4 * Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com>
6 * Based on the following driver from Linux kernel:
7 * r8a7796 Clock Pulse Generator / Module Standby and Software Reset
9 * Copyright (C) 2016 Glider bvba
11 * SPDX-License-Identifier: GPL-2.0+
15 #include <clk-uclass.h>
21 #include <dt-bindings/clock/renesas-cpg-mssr.h>
23 #include "renesas-cpg-mssr.h"
24 #include "rcar-gen3-cpg.h"
26 #define CPG_RST_MODEMR 0x0060
28 #define CPG_PLL0CR 0x00d8
29 #define CPG_PLL2CR 0x002c
30 #define CPG_PLL4CR 0x01f4
32 #define CPG_RPC_PREDIV_MASK 0x3
33 #define CPG_RPC_PREDIV_OFFSET 3
34 #define CPG_RPC_POSTDIV_MASK 0x7
35 #define CPG_RPC_POSTDIV_OFFSET 0
40 #define CPG_SD_STP_HCK BIT(9)
41 #define CPG_SD_STP_CK BIT(8)
43 #define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK)
44 #define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0)
46 #define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
48 .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
49 ((stp_ck) ? CPG_SD_STP_CK : 0) | \
62 * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc
63 *-------------------------------------------------------------------
75 static const struct sd_div_table cpg_sd_div_table
[] = {
76 /* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */
77 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4),
78 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8),
79 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16),
80 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32),
81 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64),
82 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2),
83 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4),
84 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8),
85 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16),
86 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32),
89 static int gen3_clk_setup_sdif_div(struct clk
*clk
)
91 struct gen3_clk_priv
*priv
= dev_get_priv(clk
->dev
);
92 struct cpg_mssr_info
*info
= priv
->info
;
93 const struct cpg_core_clk
*core
;
97 ret
= renesas_clk_get_parent(clk
, info
, &parent
);
99 printf("%s[%i] parent fail, ret=%i\n", __func__
, __LINE__
, ret
);
103 if (renesas_clk_is_mod(&parent
))
106 ret
= renesas_clk_get_core(&parent
, info
, &core
);
110 if (core
->type
!= CLK_TYPE_GEN3_SD
)
113 debug("%s[%i] SDIF offset=%x\n", __func__
, __LINE__
, core
->offset
);
115 writel(1, priv
->base
+ core
->offset
);
120 static int gen3_clk_enable(struct clk
*clk
)
122 struct gen3_clk_priv
*priv
= dev_get_priv(clk
->dev
);
123 int ret
= gen3_clk_setup_sdif_div(clk
);
128 return renesas_clk_endisable(clk
, priv
->base
, true);
131 static int gen3_clk_disable(struct clk
*clk
)
133 struct gen3_clk_priv
*priv
= dev_get_priv(clk
->dev
);
135 return renesas_clk_endisable(clk
, priv
->base
, false);
138 static ulong
gen3_clk_get_rate(struct clk
*clk
)
140 struct gen3_clk_priv
*priv
= dev_get_priv(clk
->dev
);
141 struct cpg_mssr_info
*info
= priv
->info
;
143 const struct cpg_core_clk
*core
;
144 const struct rcar_gen3_cpg_pll_config
*pll_config
=
145 priv
->cpg_pll_config
;
146 u32 value
, mult
, prediv
, postdiv
, rate
= 0;
149 debug("%s[%i] Clock: id=%lu\n", __func__
, __LINE__
, clk
->id
);
151 ret
= renesas_clk_get_parent(clk
, info
, &parent
);
153 printf("%s[%i] parent fail, ret=%i\n", __func__
, __LINE__
, ret
);
157 if (renesas_clk_is_mod(clk
)) {
158 rate
= gen3_clk_get_rate(&parent
);
159 debug("%s[%i] MOD clk: parent=%lu => rate=%u\n",
160 __func__
, __LINE__
, parent
.id
, rate
);
164 ret
= renesas_clk_get_core(clk
, info
, &core
);
168 switch (core
->type
) {
170 if (core
->id
== info
->clk_extal_id
) {
171 rate
= clk_get_rate(&priv
->clk_extal
);
172 debug("%s[%i] EXTAL clk: rate=%u\n",
173 __func__
, __LINE__
, rate
);
177 if (core
->id
== info
->clk_extalr_id
) {
178 rate
= clk_get_rate(&priv
->clk_extalr
);
179 debug("%s[%i] EXTALR clk: rate=%u\n",
180 __func__
, __LINE__
, rate
);
186 case CLK_TYPE_GEN3_MAIN
:
187 rate
= gen3_clk_get_rate(&parent
) / pll_config
->extal_div
;
188 debug("%s[%i] MAIN clk: parent=%i extal_div=%i => rate=%u\n",
190 core
->parent
, pll_config
->extal_div
, rate
);
193 case CLK_TYPE_GEN3_PLL0
:
194 value
= readl(priv
->base
+ CPG_PLL0CR
);
195 mult
= (((value
>> 24) & 0x7f) + 1) * 2;
196 rate
= gen3_clk_get_rate(&parent
) * mult
;
197 debug("%s[%i] PLL0 clk: parent=%i mult=%u => rate=%u\n",
198 __func__
, __LINE__
, core
->parent
, mult
, rate
);
201 case CLK_TYPE_GEN3_PLL1
:
202 rate
= gen3_clk_get_rate(&parent
) * pll_config
->pll1_mult
;
203 debug("%s[%i] PLL1 clk: parent=%i mul=%i => rate=%u\n",
205 core
->parent
, pll_config
->pll1_mult
, rate
);
208 case CLK_TYPE_GEN3_PLL2
:
209 value
= readl(priv
->base
+ CPG_PLL2CR
);
210 mult
= (((value
>> 24) & 0x7f) + 1) * 2;
211 rate
= gen3_clk_get_rate(&parent
) * mult
;
212 debug("%s[%i] PLL2 clk: parent=%i mult=%u => rate=%u\n",
213 __func__
, __LINE__
, core
->parent
, mult
, rate
);
216 case CLK_TYPE_GEN3_PLL3
:
217 rate
= gen3_clk_get_rate(&parent
) * pll_config
->pll3_mult
;
218 debug("%s[%i] PLL3 clk: parent=%i mul=%i => rate=%u\n",
220 core
->parent
, pll_config
->pll3_mult
, rate
);
223 case CLK_TYPE_GEN3_PLL4
:
224 value
= readl(priv
->base
+ CPG_PLL4CR
);
225 mult
= (((value
>> 24) & 0x7f) + 1) * 2;
226 rate
= gen3_clk_get_rate(&parent
) * mult
;
227 debug("%s[%i] PLL4 clk: parent=%i mult=%u => rate=%u\n",
228 __func__
, __LINE__
, core
->parent
, mult
, rate
);
232 case CLK_TYPE_GEN3_PE
: /* FIXME */
233 rate
= (gen3_clk_get_rate(&parent
) * core
->mult
) / core
->div
;
234 debug("%s[%i] FIXED clk: parent=%i div=%i mul=%i => rate=%u\n",
236 core
->parent
, core
->mult
, core
->div
, rate
);
239 case CLK_TYPE_GEN3_SD
: /* FIXME */
240 value
= readl(priv
->base
+ core
->offset
);
241 value
&= CPG_SD_STP_MASK
| CPG_SD_FC_MASK
;
243 for (i
= 0; i
< ARRAY_SIZE(cpg_sd_div_table
); i
++) {
244 if (cpg_sd_div_table
[i
].val
!= value
)
247 rate
= gen3_clk_get_rate(&parent
) /
248 cpg_sd_div_table
[i
].div
;
249 debug("%s[%i] SD clk: parent=%i div=%i => rate=%u\n",
251 core
->parent
, cpg_sd_div_table
[i
].div
, rate
);
258 case CLK_TYPE_GEN3_RPC
:
259 rate
= gen3_clk_get_rate(&parent
);
261 value
= readl(priv
->base
+ core
->offset
);
263 prediv
= (value
>> CPG_RPC_PREDIV_OFFSET
) &
267 else if (prediv
== 3)
272 postdiv
= (value
>> CPG_RPC_POSTDIV_OFFSET
) &
273 CPG_RPC_POSTDIV_MASK
;
276 debug("%s[%i] RPC clk: parent=%i prediv=%i postdiv=%i => rate=%u\n",
278 core
->parent
, prediv
, postdiv
, rate
);
284 printf("%s[%i] unknown fail\n", __func__
, __LINE__
);
289 static ulong
gen3_clk_set_rate(struct clk
*clk
, ulong rate
)
291 return gen3_clk_get_rate(clk
);
294 static int gen3_clk_of_xlate(struct clk
*clk
, struct ofnode_phandle_args
*args
)
296 if (args
->args_count
!= 2) {
297 debug("Invaild args_count: %d\n", args
->args_count
);
301 clk
->id
= (args
->args
[0] << 16) | args
->args
[1];
306 const struct clk_ops gen3_clk_ops
= {
307 .enable
= gen3_clk_enable
,
308 .disable
= gen3_clk_disable
,
309 .get_rate
= gen3_clk_get_rate
,
310 .set_rate
= gen3_clk_set_rate
,
311 .of_xlate
= gen3_clk_of_xlate
,
314 int gen3_clk_probe(struct udevice
*dev
)
316 struct gen3_clk_priv
*priv
= dev_get_priv(dev
);
317 struct cpg_mssr_info
*info
=
318 (struct cpg_mssr_info
*)dev_get_driver_data(dev
);
323 priv
->base
= (struct gen3_base
*)devfdt_get_addr(dev
);
328 ret
= fdt_node_offset_by_compatible(gd
->fdt_blob
, -1, info
->reset_node
);
332 rst_base
= fdtdec_get_addr(gd
->fdt_blob
, ret
, "reg");
333 if (rst_base
== FDT_ADDR_T_NONE
)
336 cpg_mode
= readl(rst_base
+ CPG_RST_MODEMR
);
338 priv
->cpg_pll_config
=
339 (struct rcar_gen3_cpg_pll_config
*)info
->get_pll_config(cpg_mode
);
340 if (!priv
->cpg_pll_config
->extal_div
)
343 ret
= clk_get_by_name(dev
, "extal", &priv
->clk_extal
);
347 if (info
->extalr_node
) {
348 ret
= clk_get_by_name(dev
, info
->extalr_node
, &priv
->clk_extalr
);
356 int gen3_clk_remove(struct udevice
*dev
)
358 struct gen3_clk_priv
*priv
= dev_get_priv(dev
);
360 return renesas_clk_remove(priv
->base
, priv
->info
);