]> git.sur5r.net Git - u-boot/blob - drivers/clk/renesas/clk-rcar-gen3.c
clk: renesas: Add PE clock handling
[u-boot] / 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_PE) {
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)
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(1, 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         int ret = gen3_clk_setup_sdif_div(clk);
145
146         if (ret)
147                 return ret;
148
149         return renesas_clk_endisable(clk, priv->base, true);
150 }
151
152 static int gen3_clk_disable(struct clk *clk)
153 {
154         struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
155
156         return renesas_clk_endisable(clk, priv->base, false);
157 }
158
159 static u64 gen3_clk_get_rate64(struct clk *clk)
160 {
161         struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
162         struct cpg_mssr_info *info = priv->info;
163         struct clk parent;
164         const struct cpg_core_clk *core;
165         const struct rcar_gen3_cpg_pll_config *pll_config =
166                                         priv->cpg_pll_config;
167         u32 value, mult, div, prediv, postdiv;
168         u64 rate = 0;
169         int i, ret;
170
171         debug("%s[%i] Clock: id=%lu\n", __func__, __LINE__, clk->id);
172
173         ret = gen3_clk_get_parent(priv, clk, info, &parent);
174         if (ret) {
175                 printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret);
176                 return ret;
177         }
178
179         if (renesas_clk_is_mod(clk)) {
180                 rate = gen3_clk_get_rate64(&parent);
181                 debug("%s[%i] MOD clk: parent=%lu => rate=%llu\n",
182                       __func__, __LINE__, parent.id, rate);
183                 return rate;
184         }
185
186         ret = renesas_clk_get_core(clk, info, &core);
187         if (ret)
188                 return ret;
189
190         switch (core->type) {
191         case CLK_TYPE_IN:
192                 if (core->id == info->clk_extal_id) {
193                         rate = clk_get_rate(&priv->clk_extal);
194                         debug("%s[%i] EXTAL clk: rate=%llu\n",
195                               __func__, __LINE__, rate);
196                         return rate;
197                 }
198
199                 if (core->id == info->clk_extalr_id) {
200                         rate = clk_get_rate(&priv->clk_extalr);
201                         debug("%s[%i] EXTALR clk: rate=%llu\n",
202                               __func__, __LINE__, rate);
203                         return rate;
204                 }
205
206                 return -EINVAL;
207
208         case CLK_TYPE_GEN3_MAIN:
209                 rate = gen3_clk_get_rate64(&parent) / pll_config->extal_div;
210                 debug("%s[%i] MAIN clk: parent=%i extal_div=%i => rate=%llu\n",
211                       __func__, __LINE__,
212                       core->parent, pll_config->extal_div, rate);
213                 return rate;
214
215         case CLK_TYPE_GEN3_PLL0:
216                 value = readl(priv->base + CPG_PLL0CR);
217                 mult = (((value >> 24) & 0x7f) + 1) * 2;
218                 rate = gen3_clk_get_rate64(&parent) * mult;
219                 debug("%s[%i] PLL0 clk: parent=%i mult=%u => rate=%llu\n",
220                       __func__, __LINE__, core->parent, mult, rate);
221                 return rate;
222
223         case CLK_TYPE_GEN3_PLL1:
224                 rate = gen3_clk_get_rate64(&parent) * pll_config->pll1_mult;
225                 rate /= pll_config->pll1_div;
226                 debug("%s[%i] PLL1 clk: parent=%i mul=%i div=%i => rate=%llu\n",
227                       __func__, __LINE__,
228                       core->parent, pll_config->pll1_mult,
229                       pll_config->pll1_div, rate);
230                 return rate;
231
232         case CLK_TYPE_GEN3_PLL2:
233                 value = readl(priv->base + CPG_PLL2CR);
234                 mult = (((value >> 24) & 0x7f) + 1) * 2;
235                 rate = gen3_clk_get_rate64(&parent) * mult;
236                 debug("%s[%i] PLL2 clk: parent=%i mult=%u => rate=%llu\n",
237                       __func__, __LINE__, core->parent, mult, rate);
238                 return rate;
239
240         case CLK_TYPE_GEN3_PLL3:
241                 rate = gen3_clk_get_rate64(&parent) * pll_config->pll3_mult;
242                 rate /= pll_config->pll3_div;
243                 debug("%s[%i] PLL3 clk: parent=%i mul=%i div=%i => rate=%llu\n",
244                       __func__, __LINE__,
245                       core->parent, pll_config->pll3_mult,
246                       pll_config->pll3_div, rate);
247                 return rate;
248
249         case CLK_TYPE_GEN3_PLL4:
250                 value = readl(priv->base + CPG_PLL4CR);
251                 mult = (((value >> 24) & 0x7f) + 1) * 2;
252                 rate = gen3_clk_get_rate64(&parent) * mult;
253                 debug("%s[%i] PLL4 clk: parent=%i mult=%u => rate=%llu\n",
254                       __func__, __LINE__, core->parent, mult, rate);
255                 return rate;
256
257         case CLK_TYPE_FF:
258                 rate = (gen3_clk_get_rate64(&parent) * core->mult) / core->div;
259                 debug("%s[%i] FIXED clk: parent=%i mul=%i div=%i => rate=%llu\n",
260                       __func__, __LINE__,
261                       core->parent, core->mult, core->div, rate);
262                 return rate;
263
264         case CLK_TYPE_GEN3_PE:
265                 div = (core->div >> (priv->sscg ? 16 : 0)) & 0xffff;
266                 rate = gen3_clk_get_rate64(&parent) / div;
267                 debug("%s[%i] PE clk: parent=%i div=%u => rate=%llu\n",
268                       __func__, __LINE__,
269                       (core->parent >> (priv->sscg ? 16 : 0)) & 0xffff,
270                       div, rate);
271                 return rate;
272
273         case CLK_TYPE_GEN3_SD:          /* FIXME */
274                 value = readl(priv->base + core->offset);
275                 value &= CPG_SD_STP_MASK | CPG_SD_FC_MASK;
276
277                 for (i = 0; i < ARRAY_SIZE(cpg_sd_div_table); i++) {
278                         if (cpg_sd_div_table[i].val != value)
279                                 continue;
280
281                         rate = gen3_clk_get_rate64(&parent) /
282                                cpg_sd_div_table[i].div;
283                         debug("%s[%i] SD clk: parent=%i div=%i => rate=%llu\n",
284                               __func__, __LINE__,
285                               core->parent, cpg_sd_div_table[i].div, rate);
286
287                         return rate;
288                 }
289
290                 return -EINVAL;
291
292         case CLK_TYPE_GEN3_RPC:
293                 rate = gen3_clk_get_rate64(&parent);
294
295                 value = readl(priv->base + core->offset);
296
297                 prediv = (value >> CPG_RPC_PREDIV_OFFSET) &
298                          CPG_RPC_PREDIV_MASK;
299                 if (prediv == 2)
300                         rate /= 5;
301                 else if (prediv == 3)
302                         rate /= 6;
303                 else
304                         return -EINVAL;
305
306                 postdiv = (value >> CPG_RPC_POSTDIV_OFFSET) &
307                           CPG_RPC_POSTDIV_MASK;
308                 rate /= postdiv + 1;
309
310                 debug("%s[%i] RPC clk: parent=%i prediv=%i postdiv=%i => rate=%llu\n",
311                       __func__, __LINE__,
312                       core->parent, prediv, postdiv, rate);
313
314                 return -EINVAL;
315
316         }
317
318         printf("%s[%i] unknown fail\n", __func__, __LINE__);
319
320         return -ENOENT;
321 }
322
323 static ulong gen3_clk_get_rate(struct clk *clk)
324 {
325         return gen3_clk_get_rate64(clk);
326 }
327
328 static ulong gen3_clk_set_rate(struct clk *clk, ulong rate)
329 {
330         /* Force correct SD-IF divider configuration if applicable */
331         gen3_clk_setup_sdif_div(clk);
332         return gen3_clk_get_rate64(clk);
333 }
334
335 static int gen3_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
336 {
337         if (args->args_count != 2) {
338                 debug("Invaild args_count: %d\n", args->args_count);
339                 return -EINVAL;
340         }
341
342         clk->id = (args->args[0] << 16) | args->args[1];
343
344         return 0;
345 }
346
347 const struct clk_ops gen3_clk_ops = {
348         .enable         = gen3_clk_enable,
349         .disable        = gen3_clk_disable,
350         .get_rate       = gen3_clk_get_rate,
351         .set_rate       = gen3_clk_set_rate,
352         .of_xlate       = gen3_clk_of_xlate,
353 };
354
355 int gen3_clk_probe(struct udevice *dev)
356 {
357         struct gen3_clk_priv *priv = dev_get_priv(dev);
358         struct cpg_mssr_info *info =
359                 (struct cpg_mssr_info *)dev_get_driver_data(dev);
360         fdt_addr_t rst_base;
361         u32 cpg_mode;
362         int ret;
363
364         priv->base = (struct gen3_base *)devfdt_get_addr(dev);
365         if (!priv->base)
366                 return -EINVAL;
367
368         priv->info = info;
369         ret = fdt_node_offset_by_compatible(gd->fdt_blob, -1, info->reset_node);
370         if (ret < 0)
371                 return ret;
372
373         rst_base = fdtdec_get_addr(gd->fdt_blob, ret, "reg");
374         if (rst_base == FDT_ADDR_T_NONE)
375                 return -EINVAL;
376
377         cpg_mode = readl(rst_base + CPG_RST_MODEMR);
378
379         priv->cpg_pll_config =
380                 (struct rcar_gen3_cpg_pll_config *)info->get_pll_config(cpg_mode);
381         if (!priv->cpg_pll_config->extal_div)
382                 return -EINVAL;
383
384         priv->sscg = !(cpg_mode & BIT(12));
385
386         ret = clk_get_by_name(dev, "extal", &priv->clk_extal);
387         if (ret < 0)
388                 return ret;
389
390         if (info->extalr_node) {
391                 ret = clk_get_by_name(dev, info->extalr_node, &priv->clk_extalr);
392                 if (ret < 0)
393                         return ret;
394         }
395
396         return 0;
397 }
398
399 int gen3_clk_remove(struct udevice *dev)
400 {
401         struct gen3_clk_priv *priv = dev_get_priv(dev);
402
403         return renesas_clk_remove(priv->base, priv->info);
404 }