blob: dd61fe0c7cd9fe1dd2e1e44524a9eb6dc4da9f12 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Marek Vasutf3b8bf72017-07-21 23:18:03 +02002/*
Marek Vasut3f1a3a12017-10-09 20:52:33 +02003 * Renesas RCar Gen3 CPG MSSR driver
Marek Vasutf3b8bf72017-07-21 23:18:03 +02004 *
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
Marek Vasutf3b8bf72017-07-21 23:18:03 +020011 */
12
13#include <common.h>
14#include <clk-uclass.h>
15#include <dm.h>
Marek Vasutf6b32022023-01-26 21:02:03 +010016#include <dm/device-internal.h>
17#include <dm/lists.h>
Marek Vasutf3b8bf72017-07-21 23:18:03 +020018#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060019#include <log.h>
Marek Vasutf3b8bf72017-07-21 23:18:03 +020020#include <wait_bit.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060021#include <asm/global_data.h>
Marek Vasutf3b8bf72017-07-21 23:18:03 +020022#include <asm/io.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060023#include <linux/bitops.h>
Marek Vasutf6b32022023-01-26 21:02:03 +010024#include <reset-uclass.h>
Marek Vasutf3b8bf72017-07-21 23:18:03 +020025
Marek Vasut4eb4e6e2018-01-08 14:01:40 +010026#include <dt-bindings/clock/renesas-cpg-mssr.h>
27
28#include "renesas-cpg-mssr.h"
Marek Vasute11008b2018-01-15 16:44:39 +010029#include "rcar-gen3-cpg.h"
Marek Vasutf3b8bf72017-07-21 23:18:03 +020030
Marek Vasutf3b8bf72017-07-21 23:18:03 +020031#define CPG_PLL0CR 0x00d8
32#define CPG_PLL2CR 0x002c
33#define CPG_PLL4CR 0x01f4
34
Marek Vasutc1aee322017-09-15 21:10:29 +020035#define CPG_RPC_PREDIV_MASK 0x3
36#define CPG_RPC_PREDIV_OFFSET 3
37#define CPG_RPC_POSTDIV_MASK 0x7
38#define CPG_RPC_POSTDIV_OFFSET 0
39
Marek Vasutf3b8bf72017-07-21 23:18:03 +020040/*
Marek Vasutf3b8bf72017-07-21 23:18:03 +020041 * SDn Clock
42 */
43#define CPG_SD_STP_HCK BIT(9)
44#define CPG_SD_STP_CK BIT(8)
45
46#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK)
47#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0)
48
49#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
50{ \
51 .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
52 ((stp_ck) ? CPG_SD_STP_CK : 0) | \
53 ((sd_srcfc) << 2) | \
54 ((sd_fc) << 0), \
55 .div = (sd_div), \
56}
57
58struct sd_div_table {
59 u32 val;
60 unsigned int div;
61};
62
63/* SDn divider
64 * sd_srcfc sd_fc div
65 * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc
66 *-------------------------------------------------------------------
67 * 0 0 0 (1) 1 (4) 4
68 * 0 0 1 (2) 1 (4) 8
69 * 1 0 2 (4) 1 (4) 16
70 * 1 0 3 (8) 1 (4) 32
71 * 1 0 4 (16) 1 (4) 64
72 * 0 0 0 (1) 0 (2) 2
73 * 0 0 1 (2) 0 (2) 4
74 * 1 0 2 (4) 0 (2) 8
75 * 1 0 3 (8) 0 (2) 16
76 * 1 0 4 (16) 0 (2) 32
77 */
78static const struct sd_div_table cpg_sd_div_table[] = {
79/* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */
80 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4),
81 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8),
82 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16),
83 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32),
84 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64),
85 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2),
86 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4),
87 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8),
88 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16),
89 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32),
90};
91
Marek Vasut69459b22018-05-31 19:47:42 +020092static int gen3_clk_get_parent(struct gen3_clk_priv *priv, struct clk *clk,
93 struct cpg_mssr_info *info, struct clk *parent)
94{
95 const struct cpg_core_clk *core;
96 int ret;
97
98 if (!renesas_clk_is_mod(clk)) {
99 ret = renesas_clk_get_core(clk, info, &core);
100 if (ret)
101 return ret;
102
Marek Vasut78414832019-03-04 21:38:10 +0100103 if (core->type == CLK_TYPE_GEN3_MDSEL) {
Marek Vasut69459b22018-05-31 19:47:42 +0200104 parent->dev = clk->dev;
105 parent->id = core->parent >> (priv->sscg ? 16 : 0);
106 parent->id &= 0xffff;
107 return 0;
108 }
109 }
110
111 return renesas_clk_get_parent(clk, info, parent);
112}
113
Marek Vasutc26bf892018-10-30 17:54:20 +0100114static int gen3_clk_setup_sdif_div(struct clk *clk, ulong rate)
Marek Vasut5a51be52017-09-15 21:10:08 +0200115{
116 struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
Marek Vasute11008b2018-01-15 16:44:39 +0100117 struct cpg_mssr_info *info = priv->info;
Marek Vasut5a51be52017-09-15 21:10:08 +0200118 const struct cpg_core_clk *core;
119 struct clk parent;
120 int ret;
121
Marek Vasut69459b22018-05-31 19:47:42 +0200122 ret = gen3_clk_get_parent(priv, clk, info, &parent);
Marek Vasut5a51be52017-09-15 21:10:08 +0200123 if (ret) {
124 printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret);
125 return ret;
126 }
127
Marek Vasute11008b2018-01-15 16:44:39 +0100128 if (renesas_clk_is_mod(&parent))
Marek Vasut5a51be52017-09-15 21:10:08 +0200129 return 0;
130
Marek Vasute11008b2018-01-15 16:44:39 +0100131 ret = renesas_clk_get_core(&parent, info, &core);
Marek Vasut5a51be52017-09-15 21:10:08 +0200132 if (ret)
133 return ret;
134
135 if (core->type != CLK_TYPE_GEN3_SD)
136 return 0;
137
138 debug("%s[%i] SDIF offset=%x\n", __func__, __LINE__, core->offset);
139
Marek Vasutc26bf892018-10-30 17:54:20 +0100140 writel((rate == 400000000) ? 0x4 : 0x1, priv->base + core->offset);
Marek Vasut5a51be52017-09-15 21:10:08 +0200141
142 return 0;
143}
144
Marek Vasute11008b2018-01-15 16:44:39 +0100145static int gen3_clk_enable(struct clk *clk)
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200146{
147 struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200148
Hai Pham5460ee02020-05-22 10:39:04 +0700149 return renesas_clk_endisable(clk, priv->base, priv->info, true);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200150}
151
152static int gen3_clk_disable(struct clk *clk)
153{
Marek Vasute11008b2018-01-15 16:44:39 +0100154 struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
155
Hai Pham5460ee02020-05-22 10:39:04 +0700156 return renesas_clk_endisable(clk, priv->base, priv->info, false);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200157}
158
Marek Vasut8f567862021-04-27 19:36:39 +0200159static u64 gen3_clk_get_rate64(struct clk *clk);
160
161static u64 gen3_clk_get_rate64_pll_mul_reg(struct gen3_clk_priv *priv,
162 struct clk *parent,
Marek Vasut8f567862021-04-27 19:36:39 +0200163 u32 mul_reg, u32 mult, u32 div,
164 char *name)
165{
166 u32 value;
167 u64 rate;
168
169 if (mul_reg) {
170 value = readl(priv->base + mul_reg);
171 mult = (((value >> 24) & 0x7f) + 1) * 2;
172 div = 1;
173 }
174
175 rate = (gen3_clk_get_rate64(parent) * mult) / div;
176
Marek Vasut1bd25212023-01-26 21:02:05 +0100177 debug("%s[%i] %s clk: mult=%u div=%u => rate=%llu\n",
178 __func__, __LINE__, name, mult, div, rate);
Marek Vasut8f567862021-04-27 19:36:39 +0200179 return rate;
180}
181
Marek Vasut7571ac42018-05-31 19:06:02 +0200182static u64 gen3_clk_get_rate64(struct clk *clk)
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200183{
184 struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
Marek Vasutb9234192018-01-08 16:05:28 +0100185 struct cpg_mssr_info *info = priv->info;
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200186 struct clk parent;
187 const struct cpg_core_clk *core;
188 const struct rcar_gen3_cpg_pll_config *pll_config =
189 priv->cpg_pll_config;
Marek Vasut8f567862021-04-27 19:36:39 +0200190 u32 value, div, prediv, postdiv;
Marek Vasut7571ac42018-05-31 19:06:02 +0200191 u64 rate = 0;
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200192 int i, ret;
193
194 debug("%s[%i] Clock: id=%lu\n", __func__, __LINE__, clk->id);
195
Marek Vasut69459b22018-05-31 19:47:42 +0200196 ret = gen3_clk_get_parent(priv, clk, info, &parent);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200197 if (ret) {
198 printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret);
199 return ret;
200 }
201
Marek Vasute11008b2018-01-15 16:44:39 +0100202 if (renesas_clk_is_mod(clk)) {
Marek Vasut7571ac42018-05-31 19:06:02 +0200203 rate = gen3_clk_get_rate64(&parent);
204 debug("%s[%i] MOD clk: parent=%lu => rate=%llu\n",
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200205 __func__, __LINE__, parent.id, rate);
206 return rate;
207 }
208
Marek Vasute11008b2018-01-15 16:44:39 +0100209 ret = renesas_clk_get_core(clk, info, &core);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200210 if (ret)
211 return ret;
212
213 switch (core->type) {
214 case CLK_TYPE_IN:
Marek Vasutb9234192018-01-08 16:05:28 +0100215 if (core->id == info->clk_extal_id) {
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200216 rate = clk_get_rate(&priv->clk_extal);
Marek Vasut7571ac42018-05-31 19:06:02 +0200217 debug("%s[%i] EXTAL clk: rate=%llu\n",
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200218 __func__, __LINE__, rate);
219 return rate;
220 }
221
Marek Vasutb9234192018-01-08 16:05:28 +0100222 if (core->id == info->clk_extalr_id) {
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200223 rate = clk_get_rate(&priv->clk_extalr);
Marek Vasut7571ac42018-05-31 19:06:02 +0200224 debug("%s[%i] EXTALR clk: rate=%llu\n",
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200225 __func__, __LINE__, rate);
226 return rate;
227 }
228
229 return -EINVAL;
230
231 case CLK_TYPE_GEN3_MAIN:
Marek Vasut1bd25212023-01-26 21:02:05 +0100232 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut8f567862021-04-27 19:36:39 +0200233 0, 1, pll_config->extal_div,
234 "MAIN");
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200235
236 case CLK_TYPE_GEN3_PLL0:
Marek Vasut1bd25212023-01-26 21:02:05 +0100237 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut8f567862021-04-27 19:36:39 +0200238 CPG_PLL0CR, 0, 0, "PLL0");
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200239
240 case CLK_TYPE_GEN3_PLL1:
Marek Vasut1bd25212023-01-26 21:02:05 +0100241 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut8f567862021-04-27 19:36:39 +0200242 0, pll_config->pll1_mult,
243 pll_config->pll1_div, "PLL1");
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200244
245 case CLK_TYPE_GEN3_PLL2:
Marek Vasut1bd25212023-01-26 21:02:05 +0100246 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut8f567862021-04-27 19:36:39 +0200247 CPG_PLL2CR, 0, 0, "PLL2");
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200248
249 case CLK_TYPE_GEN3_PLL3:
Marek Vasut1bd25212023-01-26 21:02:05 +0100250 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut8f567862021-04-27 19:36:39 +0200251 0, pll_config->pll3_mult,
252 pll_config->pll3_div, "PLL3");
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200253
254 case CLK_TYPE_GEN3_PLL4:
Marek Vasut1bd25212023-01-26 21:02:05 +0100255 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut8f567862021-04-27 19:36:39 +0200256 CPG_PLL4CR, 0, 0, "PLL4");
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200257
Marek Vasut569acef2023-01-26 21:01:56 +0100258 case CLK_TYPE_GEN4_MAIN:
Marek Vasut1bd25212023-01-26 21:02:05 +0100259 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut0fbb8a72021-04-27 19:52:53 +0200260 0, 1, pll_config->extal_div,
261 "V3U_MAIN");
262
Marek Vasut569acef2023-01-26 21:01:56 +0100263 case CLK_TYPE_GEN4_PLL1:
Marek Vasut1bd25212023-01-26 21:02:05 +0100264 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut0fbb8a72021-04-27 19:52:53 +0200265 0, pll_config->pll1_mult,
266 pll_config->pll1_div,
267 "V3U_PLL1");
268
Marek Vasut569acef2023-01-26 21:01:56 +0100269 case CLK_TYPE_GEN4_PLL2X_3X:
Marek Vasut1bd25212023-01-26 21:02:05 +0100270 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut0fbb8a72021-04-27 19:52:53 +0200271 core->offset, 0, 0,
272 "V3U_PLL2X_3X");
273
Marek Vasut569acef2023-01-26 21:01:56 +0100274 case CLK_TYPE_GEN4_PLL5:
Marek Vasut1bd25212023-01-26 21:02:05 +0100275 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut0fbb8a72021-04-27 19:52:53 +0200276 0, pll_config->pll5_mult,
277 pll_config->pll5_div,
278 "V3U_PLL5");
279
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200280 case CLK_TYPE_FF:
Marek Vasut1bd25212023-01-26 21:02:05 +0100281 return gen3_clk_get_rate64_pll_mul_reg(priv, &parent,
Marek Vasut8f567862021-04-27 19:36:39 +0200282 0, core->mult, core->div,
283 "FIXED");
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200284
Marek Vasut78414832019-03-04 21:38:10 +0100285 case CLK_TYPE_GEN3_MDSEL:
Marek Vasut69459b22018-05-31 19:47:42 +0200286 div = (core->div >> (priv->sscg ? 16 : 0)) & 0xffff;
287 rate = gen3_clk_get_rate64(&parent) / div;
288 debug("%s[%i] PE clk: parent=%i div=%u => rate=%llu\n",
289 __func__, __LINE__,
290 (core->parent >> (priv->sscg ? 16 : 0)) & 0xffff,
291 div, rate);
292 return rate;
293
Hai Pham0985e0e2023-01-26 21:01:49 +0100294 case CLK_TYPE_GEN3_SDH: /* Fixed factor 1:1 */
Marek Vasut569acef2023-01-26 21:01:56 +0100295 fallthrough;
296 case CLK_TYPE_GEN4_SDH: /* Fixed factor 1:1 */
Hai Pham0985e0e2023-01-26 21:01:49 +0100297 return gen3_clk_get_rate64(&parent);
298
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200299 case CLK_TYPE_GEN3_SD: /* FIXME */
Marek Vasut0fbb8a72021-04-27 19:52:53 +0200300 fallthrough;
Marek Vasut569acef2023-01-26 21:01:56 +0100301 case CLK_TYPE_GEN4_SD:
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200302 value = readl(priv->base + core->offset);
303 value &= CPG_SD_STP_MASK | CPG_SD_FC_MASK;
304
305 for (i = 0; i < ARRAY_SIZE(cpg_sd_div_table); i++) {
306 if (cpg_sd_div_table[i].val != value)
307 continue;
308
Marek Vasut7571ac42018-05-31 19:06:02 +0200309 rate = gen3_clk_get_rate64(&parent) /
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200310 cpg_sd_div_table[i].div;
Marek Vasut7571ac42018-05-31 19:06:02 +0200311 debug("%s[%i] SD clk: parent=%i div=%i => rate=%llu\n",
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200312 __func__, __LINE__,
313 core->parent, cpg_sd_div_table[i].div, rate);
314
315 return rate;
316 }
317
318 return -EINVAL;
Marek Vasutc1aee322017-09-15 21:10:29 +0200319
320 case CLK_TYPE_GEN3_RPC:
Hai Pham215de2b2020-08-11 10:25:28 +0700321 case CLK_TYPE_GEN3_RPCD2:
Marek Vasut569acef2023-01-26 21:01:56 +0100322 case CLK_TYPE_GEN4_RPC:
323 case CLK_TYPE_GEN4_RPCD2:
Marek Vasut7571ac42018-05-31 19:06:02 +0200324 rate = gen3_clk_get_rate64(&parent);
Marek Vasutc1aee322017-09-15 21:10:29 +0200325
Hai Phama80b0612023-01-26 21:02:04 +0100326 value = readl(priv->base + CPG_RPCCKCR);
Marek Vasutc1aee322017-09-15 21:10:29 +0200327
328 prediv = (value >> CPG_RPC_PREDIV_OFFSET) &
329 CPG_RPC_PREDIV_MASK;
330 if (prediv == 2)
331 rate /= 5;
332 else if (prediv == 3)
333 rate /= 6;
334 else
335 return -EINVAL;
336
337 postdiv = (value >> CPG_RPC_POSTDIV_OFFSET) &
338 CPG_RPC_POSTDIV_MASK;
Marek Vasutc1aee322017-09-15 21:10:29 +0200339
Hai Pham215de2b2020-08-11 10:25:28 +0700340 if (postdiv % 2 != 0) {
341 rate /= postdiv + 1;
342
343 if (core->type == CLK_TYPE_GEN3_RPCD2)
344 rate /= 2;
345
346 debug("%s[%i] RPC clk: parent=%i prediv=%i postdiv=%i => rate=%llu\n",
347 __func__, __LINE__,
348 core->parent, prediv, postdiv, rate);
349
350 return rate;
351 }
Marek Vasutc1aee322017-09-15 21:10:29 +0200352
Hai Pham215de2b2020-08-11 10:25:28 +0700353 return -EINVAL;
Marek Vasutc1aee322017-09-15 21:10:29 +0200354
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200355 }
356
357 printf("%s[%i] unknown fail\n", __func__, __LINE__);
358
359 return -ENOENT;
360}
361
Marek Vasut7571ac42018-05-31 19:06:02 +0200362static ulong gen3_clk_get_rate(struct clk *clk)
363{
364 return gen3_clk_get_rate64(clk);
365}
366
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200367static ulong gen3_clk_set_rate(struct clk *clk, ulong rate)
368{
Marek Vasut414dbbe2018-01-11 16:28:31 +0100369 /* Force correct SD-IF divider configuration if applicable */
Marek Vasutc26bf892018-10-30 17:54:20 +0100370 gen3_clk_setup_sdif_div(clk, rate);
Marek Vasut7571ac42018-05-31 19:06:02 +0200371 return gen3_clk_get_rate64(clk);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200372}
373
374static int gen3_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
375{
376 if (args->args_count != 2) {
Sean Andersona1b654b2021-12-01 14:26:53 -0500377 debug("Invalid args_count: %d\n", args->args_count);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200378 return -EINVAL;
379 }
380
381 clk->id = (args->args[0] << 16) | args->args[1];
382
383 return 0;
384}
385
Marek Vasut4eb4e6e2018-01-08 14:01:40 +0100386const struct clk_ops gen3_clk_ops = {
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200387 .enable = gen3_clk_enable,
388 .disable = gen3_clk_disable,
389 .get_rate = gen3_clk_get_rate,
390 .set_rate = gen3_clk_set_rate,
391 .of_xlate = gen3_clk_of_xlate,
392};
393
Marek Vasutf6b32022023-01-26 21:02:03 +0100394static int gen3_clk_probe(struct udevice *dev)
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200395{
396 struct gen3_clk_priv *priv = dev_get_priv(dev);
Marek Vasut4eb4e6e2018-01-08 14:01:40 +0100397 struct cpg_mssr_info *info =
398 (struct cpg_mssr_info *)dev_get_driver_data(dev);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200399 fdt_addr_t rst_base;
400 u32 cpg_mode;
401 int ret;
402
Masahiro Yamada1096ae12020-07-17 14:36:46 +0900403 priv->base = dev_read_addr_ptr(dev);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200404 if (!priv->base)
405 return -EINVAL;
406
Marek Vasut4eb4e6e2018-01-08 14:01:40 +0100407 priv->info = info;
408 ret = fdt_node_offset_by_compatible(gd->fdt_blob, -1, info->reset_node);
409 if (ret < 0)
410 return ret;
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200411
412 rst_base = fdtdec_get_addr(gd->fdt_blob, ret, "reg");
413 if (rst_base == FDT_ADDR_T_NONE)
414 return -EINVAL;
415
Marek Vasut814217e2021-04-25 21:53:05 +0200416 cpg_mode = readl(rst_base + info->reset_modemr_offset);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200417
Marek Vasut28f90042018-01-16 19:23:17 +0100418 priv->cpg_pll_config =
419 (struct rcar_gen3_cpg_pll_config *)info->get_pll_config(cpg_mode);
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200420 if (!priv->cpg_pll_config->extal_div)
421 return -EINVAL;
422
Marek Vasut69459b22018-05-31 19:47:42 +0200423 priv->sscg = !(cpg_mode & BIT(12));
424
Hai Pham94803462020-11-05 22:30:37 +0700425 if (info->reg_layout == CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3) {
426 priv->info->status_regs = mstpsr;
427 priv->info->control_regs = smstpcr;
428 priv->info->reset_regs = srcr;
429 priv->info->reset_clear_regs = srstclr;
Hai Pham86d59f32020-08-11 10:46:34 +0700430 } else if (info->reg_layout == CLK_REG_LAYOUT_RCAR_V3U) {
431 priv->info->status_regs = mstpsr_for_v3u;
432 priv->info->control_regs = mstpcr_for_v3u;
433 priv->info->reset_regs = srcr_for_v3u;
434 priv->info->reset_clear_regs = srstclr_for_v3u;
Hai Pham94803462020-11-05 22:30:37 +0700435 } else {
436 return -EINVAL;
437 }
438
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200439 ret = clk_get_by_name(dev, "extal", &priv->clk_extal);
440 if (ret < 0)
441 return ret;
442
Marek Vasut4eb4e6e2018-01-08 14:01:40 +0100443 if (info->extalr_node) {
444 ret = clk_get_by_name(dev, info->extalr_node, &priv->clk_extalr);
Marek Vasutfb0aa292017-10-08 21:09:15 +0200445 if (ret < 0)
446 return ret;
447 }
Marek Vasutf3b8bf72017-07-21 23:18:03 +0200448
449 return 0;
450}
451
Marek Vasutf6b32022023-01-26 21:02:03 +0100452static int gen3_clk_remove(struct udevice *dev)
Marek Vasutdf6a1142017-11-25 22:08:55 +0100453{
454 struct gen3_clk_priv *priv = dev_get_priv(dev);
Marek Vasutdf6a1142017-11-25 22:08:55 +0100455
Marek Vasute11008b2018-01-15 16:44:39 +0100456 return renesas_clk_remove(priv->base, priv->info);
Marek Vasutdf6a1142017-11-25 22:08:55 +0100457}
Marek Vasutf6b32022023-01-26 21:02:03 +0100458
459U_BOOT_DRIVER(clk_gen3) = {
460 .name = "clk_gen3",
461 .id = UCLASS_CLK,
462 .priv_auto = sizeof(struct gen3_clk_priv),
463 .ops = &gen3_clk_ops,
464 .probe = gen3_clk_probe,
465 .remove = gen3_clk_remove,
466};
467
468static int gen3_reset_assert(struct reset_ctl *reset_ctl)
469{
470 struct udevice *cdev = (struct udevice *)dev_get_driver_data(reset_ctl->dev);
471 struct gen3_clk_priv *priv = dev_get_priv(cdev);
472 unsigned int reg = reset_ctl->id / 32;
473 unsigned int bit = reset_ctl->id % 32;
474 u32 bitmask = BIT(bit);
475
476 writel(bitmask, priv->base + priv->info->reset_regs[reg]);
477
478 return 0;
479}
480
481static int gen3_reset_deassert(struct reset_ctl *reset_ctl)
482{
483 struct udevice *cdev = (struct udevice *)dev_get_driver_data(reset_ctl->dev);
484 struct gen3_clk_priv *priv = dev_get_priv(cdev);
485 unsigned int reg = reset_ctl->id / 32;
486 unsigned int bit = reset_ctl->id % 32;
487 u32 bitmask = BIT(bit);
488
489 writel(bitmask, priv->base + priv->info->reset_clear_regs[reg]);
490
491 return 0;
492}
493
494static const struct reset_ops rst_gen3_ops = {
495 .rst_assert = gen3_reset_assert,
496 .rst_deassert = gen3_reset_deassert,
497};
498
499U_BOOT_DRIVER(rst_gen3) = {
500 .name = "rst_gen3",
501 .id = UCLASS_RESET,
502 .ops = &rst_gen3_ops,
503};
504
505int gen3_cpg_bind(struct udevice *parent)
506{
507 struct cpg_mssr_info *info =
508 (struct cpg_mssr_info *)dev_get_driver_data(parent);
509 struct udevice *cdev, *rdev;
510 struct driver *drv;
511 int ret;
512
513 drv = lists_driver_lookup_name("clk_gen3");
514 if (!drv)
515 return -ENOENT;
516
517 ret = device_bind_with_driver_data(parent, drv, "clk_gen3", (ulong)info,
518 dev_ofnode(parent), &cdev);
519 if (ret)
520 return ret;
521
522 drv = lists_driver_lookup_name("rst_gen3");
523 if (!drv)
524 return -ENOENT;
525
526 ret = device_bind_with_driver_data(parent, drv, "rst_gen3", (ulong)cdev,
527 dev_ofnode(parent), &rdev);
528 if (ret)
529 device_unbind(cdev);
530
531 return ret;
532}