]> git.ipfire.org Git - thirdparty/u-boot.git/blob - drivers/clk/renesas/clk-rcar-gen3.c
clk: renesas: Synchronize Gen3 tables with Linux 5.0
[thirdparty/u-boot.git] / drivers / clk / renesas / clk-rcar-gen3.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Renesas RCar Gen3 CPG MSSR driver
4 *
5 * Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com>
6 *
7 * Based on the following driver from Linux kernel:
8 * r8a7796 Clock Pulse Generator / Module Standby and Software Reset
9 *
10 * Copyright (C) 2016 Glider bvba
11 */
12
13 #include <common.h>
14 #include <clk-uclass.h>
15 #include <dm.h>
16 #include <errno.h>
17 #include <wait_bit.h>
18 #include <asm/io.h>
19
20 #include <dt-bindings/clock/renesas-cpg-mssr.h>
21
22 #include "renesas-cpg-mssr.h"
23 #include "rcar-gen3-cpg.h"
24
25 #define CPG_RST_MODEMR 0x0060
26
27 #define CPG_PLL0CR 0x00d8
28 #define CPG_PLL2CR 0x002c
29 #define CPG_PLL4CR 0x01f4
30
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
35
36 /*
37 * SDn Clock
38 */
39 #define CPG_SD_STP_HCK BIT(9)
40 #define CPG_SD_STP_CK BIT(8)
41
42 #define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK)
43 #define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0)
44
45 #define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
46 { \
47 .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
48 ((stp_ck) ? CPG_SD_STP_CK : 0) | \
49 ((sd_srcfc) << 2) | \
50 ((sd_fc) << 0), \
51 .div = (sd_div), \
52 }
53
54 struct sd_div_table {
55 u32 val;
56 unsigned int div;
57 };
58
59 /* SDn divider
60 * sd_srcfc sd_fc div
61 * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc
62 *-------------------------------------------------------------------
63 * 0 0 0 (1) 1 (4) 4
64 * 0 0 1 (2) 1 (4) 8
65 * 1 0 2 (4) 1 (4) 16
66 * 1 0 3 (8) 1 (4) 32
67 * 1 0 4 (16) 1 (4) 64
68 * 0 0 0 (1) 0 (2) 2
69 * 0 0 1 (2) 0 (2) 4
70 * 1 0 2 (4) 0 (2) 8
71 * 1 0 3 (8) 0 (2) 16
72 * 1 0 4 (16) 0 (2) 32
73 */
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),
86 };
87
88 static int gen3_clk_get_parent(struct gen3_clk_priv *priv, struct clk *clk,
89 struct cpg_mssr_info *info, struct clk *parent)
90 {
91 const struct cpg_core_clk *core;
92 int ret;
93
94 if (!renesas_clk_is_mod(clk)) {
95 ret = renesas_clk_get_core(clk, info, &core);
96 if (ret)
97 return ret;
98
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;
103 return 0;
104 }
105 }
106
107 return renesas_clk_get_parent(clk, info, parent);
108 }
109
110 static int gen3_clk_setup_sdif_div(struct clk *clk, ulong rate)
111 {
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;
115 struct clk parent;
116 int ret;
117
118 ret = gen3_clk_get_parent(priv, clk, info, &parent);
119 if (ret) {
120 printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret);
121 return ret;
122 }
123
124 if (renesas_clk_is_mod(&parent))
125 return 0;
126
127 ret = renesas_clk_get_core(&parent, info, &core);
128 if (ret)
129 return ret;
130
131 if (core->type != CLK_TYPE_GEN3_SD)
132 return 0;
133
134 debug("%s[%i] SDIF offset=%x\n", __func__, __LINE__, core->offset);
135
136 writel((rate == 400000000) ? 0x4 : 0x1, priv->base + core->offset);
137
138 return 0;
139 }
140
141 static int gen3_clk_enable(struct clk *clk)
142 {
143 struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
144
145 return renesas_clk_endisable(clk, priv->base, true);
146 }
147
148 static int gen3_clk_disable(struct clk *clk)
149 {
150 struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
151
152 return renesas_clk_endisable(clk, priv->base, false);
153 }
154
155 static u64 gen3_clk_get_rate64(struct clk *clk)
156 {
157 struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
158 struct cpg_mssr_info *info = priv->info;
159 struct clk parent;
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;
164 u64 rate = 0;
165 int i, ret;
166
167 debug("%s[%i] Clock: id=%lu\n", __func__, __LINE__, clk->id);
168
169 ret = gen3_clk_get_parent(priv, clk, info, &parent);
170 if (ret) {
171 printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret);
172 return ret;
173 }
174
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);
179 return rate;
180 }
181
182 ret = renesas_clk_get_core(clk, info, &core);
183 if (ret)
184 return ret;
185
186 switch (core->type) {
187 case CLK_TYPE_IN:
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);
192 return rate;
193 }
194
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);
199 return rate;
200 }
201
202 return -EINVAL;
203
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",
207 __func__, __LINE__,
208 core->parent, pll_config->extal_div, rate);
209 return rate;
210
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);
217 return rate;
218
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",
223 __func__, __LINE__,
224 core->parent, pll_config->pll1_mult,
225 pll_config->pll1_div, rate);
226 return rate;
227
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);
234 return rate;
235
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",
240 __func__, __LINE__,
241 core->parent, pll_config->pll3_mult,
242 pll_config->pll3_div, rate);
243 return rate;
244
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);
251 return rate;
252
253 case CLK_TYPE_FF:
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",
256 __func__, __LINE__,
257 core->parent, core->mult, core->div, rate);
258 return rate;
259
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",
264 __func__, __LINE__,
265 (core->parent >> (priv->sscg ? 16 : 0)) & 0xffff,
266 div, rate);
267 return rate;
268
269 case CLK_TYPE_GEN3_SD: /* FIXME */
270 value = readl(priv->base + core->offset);
271 value &= CPG_SD_STP_MASK | CPG_SD_FC_MASK;
272
273 for (i = 0; i < ARRAY_SIZE(cpg_sd_div_table); i++) {
274 if (cpg_sd_div_table[i].val != value)
275 continue;
276
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",
280 __func__, __LINE__,
281 core->parent, cpg_sd_div_table[i].div, rate);
282
283 return rate;
284 }
285
286 return -EINVAL;
287
288 case CLK_TYPE_GEN3_RPC:
289 rate = gen3_clk_get_rate64(&parent);
290
291 value = readl(priv->base + core->offset);
292
293 prediv = (value >> CPG_RPC_PREDIV_OFFSET) &
294 CPG_RPC_PREDIV_MASK;
295 if (prediv == 2)
296 rate /= 5;
297 else if (prediv == 3)
298 rate /= 6;
299 else
300 return -EINVAL;
301
302 postdiv = (value >> CPG_RPC_POSTDIV_OFFSET) &
303 CPG_RPC_POSTDIV_MASK;
304 rate /= postdiv + 1;
305
306 debug("%s[%i] RPC clk: parent=%i prediv=%i postdiv=%i => rate=%llu\n",
307 __func__, __LINE__,
308 core->parent, prediv, postdiv, rate);
309
310 return -EINVAL;
311
312 }
313
314 printf("%s[%i] unknown fail\n", __func__, __LINE__);
315
316 return -ENOENT;
317 }
318
319 static ulong gen3_clk_get_rate(struct clk *clk)
320 {
321 return gen3_clk_get_rate64(clk);
322 }
323
324 static ulong gen3_clk_set_rate(struct clk *clk, ulong rate)
325 {
326 /* Force correct SD-IF divider configuration if applicable */
327 gen3_clk_setup_sdif_div(clk, rate);
328 return gen3_clk_get_rate64(clk);
329 }
330
331 static int gen3_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
332 {
333 if (args->args_count != 2) {
334 debug("Invaild args_count: %d\n", args->args_count);
335 return -EINVAL;
336 }
337
338 clk->id = (args->args[0] << 16) | args->args[1];
339
340 return 0;
341 }
342
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,
349 };
350
351 int gen3_clk_probe(struct udevice *dev)
352 {
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);
356 fdt_addr_t rst_base;
357 u32 cpg_mode;
358 int ret;
359
360 priv->base = (struct gen3_base *)devfdt_get_addr(dev);
361 if (!priv->base)
362 return -EINVAL;
363
364 priv->info = info;
365 ret = fdt_node_offset_by_compatible(gd->fdt_blob, -1, info->reset_node);
366 if (ret < 0)
367 return ret;
368
369 rst_base = fdtdec_get_addr(gd->fdt_blob, ret, "reg");
370 if (rst_base == FDT_ADDR_T_NONE)
371 return -EINVAL;
372
373 cpg_mode = readl(rst_base + CPG_RST_MODEMR);
374
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)
378 return -EINVAL;
379
380 priv->sscg = !(cpg_mode & BIT(12));
381
382 ret = clk_get_by_name(dev, "extal", &priv->clk_extal);
383 if (ret < 0)
384 return ret;
385
386 if (info->extalr_node) {
387 ret = clk_get_by_name(dev, info->extalr_node, &priv->clk_extalr);
388 if (ret < 0)
389 return ret;
390 }
391
392 return 0;
393 }
394
395 int gen3_clk_remove(struct udevice *dev)
396 {
397 struct gen3_clk_priv *priv = dev_get_priv(dev);
398
399 return renesas_clk_remove(priv->base, priv->info);
400 }