1 /*
2 * Copyright (c) 2020-2026, Renesas Electronics Corporation. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdint.h>
8
9 #include <common/debug.h>
10 #include "cpg_regs.h"
11 #include <drivers/delay_timer.h>
12 #include <drivers/renesas/rza/cpg/cpg.h>
13 #include <lib/mmio.h>
14
15 #define CPG_OFF 0
16 #define CPG_ON 1
17 #define CPG_T_CLK 0
18 #define CPG_T_RST 1
19
20 #define CPG_RST_DDR_OPT_VALUE 0x0
21 #define CPG_SEL_PLL1_ON_OFF 0
22 #define CPG_SEL_PLL2_1_ON_OFF 1
23 #define CPG_SEL_PLL2_2_ON_OFF 2
24 #define CPG_SEL_PLL3_1_ON_OFF 3
25 #define CPG_SEL_PLL3_2_ON_OFF 4
26 #define CPG_SEL_PLL3_3_ON_OFF 5
27 #define CPG_SEL_PLL5_1_ON_OFF 6
28 #define CPG_SEL_PLL5_3_ON_OFF 7
29 #define CPG_SEL_PLL5_4_ON_OFF 8
30
31 typedef struct {
32 uintptr_t reg;
33 uintptr_t mon;
34 uint32_t val;
35 uint32_t type;
36 } CPG_SETUP_DATA;
37
38 typedef struct {
39 uintptr_t reg;
40 uint32_t val;
41 } CPG_REG_SETTING;
42
43 typedef struct {
44 CPG_REG_SETTING clk1_dat;
45 CPG_REG_SETTING clk2_dat;
46 CPG_REG_SETTING stby_dat;
47 } CPG_PLL_SETDATA_146;
48
49 typedef struct {
50 CPG_REG_SETTING clk1_dat;
51 CPG_REG_SETTING clk2_dat;
52 CPG_REG_SETTING clk3_dat;
53 CPG_REG_SETTING clk4_dat;
54 CPG_REG_SETTING clk5_dat;
55 CPG_REG_SETTING stby_dat;
56 } CPG_PLL_SETDATA_235;
57
58 typedef struct st_cpg_spi_clk_table {
59 int frequency;
60 uint8_t selector;
61 uint8_t divider;
62 } cpg_spi_clk_table;
63
64 static const cpg_spi_clk_table cpg_xspi_table[] = {
65 { 533000000, 0, 0 }, /* 533.0MHz */
66 { 400000000, 1, 0 }, /* 400.0MHz */
67 { 266500000, 0, 1 }, /* 266.5MHz */
68 { 200000000, 1, 1 }, /* 200.0MHz */
69 { 133250000, 0, 2 }, /* 133.3MHz */
70 { 100000000, 1, 2 }, /* 100.0MHz */
71 { 66625000, 0, 3 }, /* 66.6MHz */
72 { 50000000, 1, 3 }, /* 50.0MHz */
73 { 16656250, 0, 4 }, /* 16.7MHz */
74 { 12500000, 1, 4 }, /* 12.5MHz */
75 };
76
77 #if USE_SDRAM
78 static const CPG_PLL_SETDATA_146 cpg_pll4_setdata = {
79 #if (DDR_PLL4 == 1600)
80 { CPG_PLL4_CLK1, 0xFAE13203 },
81 { CPG_PLL4_CLK2, 0x00081000 },
82 #elif (DDR_PLL4 == 1333)
83 { CPG_PLL4_CLK1, 0xA66629C3 },
84 { CPG_PLL4_CLK2, 0x00080D00 },
85 #else
86 #error "Unknown Board Type."
87 #endif
88 { CPG_PLL4_STBY, 0x00010001 }
89 };
90 #endif
91
92 static const CPG_PLL_SETDATA_146 cpg_pll6_setdata = {
93 { CPG_PLL6_CLK1, 0x00003e83 },
94 { CPG_PLL6_CLK2, 0x00082D02 },
95 { CPG_PLL6_STBY, 0x00010001 }, /* SSC OFF */
96 };
97
98 static const CPG_SETUP_DATA early_setup_tbl[] = {
99 { CPG_CLKON_SYC, CPG_CLKMON_SYC, 0x00010001, CPG_T_CLK },
100 { CPG_RST_SYC, CPG_RSTMON_SYC, 0x00010001, CPG_T_RST }
101 };
102
103 static const CPG_SETUP_DATA cpg_clk_on_tbl[] = {
104 { /* CM33 */
105 CPG_CLKON_CM33, CPG_CLKMON_CM33, 0x00030000, CPG_T_CLK },
106 { /* MHU */
107 CPG_CLKON_MHU, CPG_CLKMON_MHU, 0x00010000, CPG_T_CLK },
108 { /* DMAC */
109 CPG_CLKON_DAMC_REG, CPG_CLKMON_DAMC_REG, 0x00030003, CPG_T_CLK },
110 { /* OSTM */
111 CPG_CLKON_OSTM, CPG_CLKMON_OSTM, 0x00060000, CPG_T_CLK },
112 { /* MTU */
113 CPG_CLKON_MTU, CPG_CLKMON_MTU, 0x00010000, CPG_T_CLK },
114 { /* POE3 */
115 CPG_CLKON_POE3, CPG_CLKMON_POE3, 0x00010000, CPG_T_CLK },
116 { /* WDT */
117 CPG_CLKON_WDT, CPG_CLKMON_WDT, 0x00300000, CPG_T_CLK },
118 #if USE_SDRAM
119 { /* DDR */
120 CPG_CLKON_DDR, CPG_CLKMON_DDR, 0x00030000, CPG_T_CLK },
121 #else
122 { /* DDR */
123 CPG_CLKON_DDR, CPG_CLKMON_DDR, 0x00030003, CPG_T_CLK },
124 #endif
125 { /* SDHI */
126 CPG_CLKON_SDHI, CPG_CLKMON_SDHI,
127 #if RZA3M
128 0x000f0000,
129 #else
130 0x00ff0000,
131 #endif
132 CPG_T_CLK },
133 { /* Image Scaling Unit */
134 CPG_CLKON_ISU, CPG_CLKMON_ISU, 0x00030000, CPG_T_CLK },
135 { /* Camera Data Receive Unit */
136 CPG_CLKON_CRU, CPG_CLKMON_CRU, 0x001f0000, CPG_T_CLK },
137 { /* LCDC */
138 CPG_CLKON_LCDC, CPG_CLKMON_LCDC, 0x00030000, CPG_T_CLK },
139 { /* Serial Sound Interface */
140 CPG_CLKON_SSI, CPG_CLKMON_SSI, 0x00ff0000, CPG_T_CLK },
141 { /* Sampling Rate Converter */
142 CPG_CLKON_SRC, CPG_CLKMON_SRC, 0x00010000, CPG_T_CLK },
143 { /* USB2.0 */
144 CPG_CLKON_USB, CPG_CLKMON_USB, 0x000f0000, CPG_T_CLK },
145 { /* ETHER */
146 CPG_CLKON_ETH, CPG_CLKMON_ETH, 0x00030000, CPG_T_CLK },
147 { /* I2C */
148 CPG_CLKON_I2C, CPG_CLKMON_I2C, 0x000f0000, CPG_T_CLK },
149 { /* SCIF */
150 CPG_CLKON_SCIF, CPG_CLKMON_SCIF, 0x001f0001, CPG_T_CLK },
151 { /* SCI */
152 CPG_CLKON_SCI, CPG_CLKMON_SCI, 0x00030000, CPG_T_CLK },
153 { /* IrDA */
154 CPG_CLKON_IRDA, CPG_CLKMON_IRDA, 0x00010000, CPG_T_CLK },
155 { /* SPI */
156 CPG_CLKON_RSPI, CPG_CLKMON_RSPI, 0x00070000, CPG_T_CLK },
157 { /* CAN */
158 CPG_CLKON_CANFD, CPG_CLKMON_CANFD, 0x00010000, CPG_T_CLK },
159 { /* GPIO */
160 CPG_CLKON_GPIO, CPG_CLKMON_GPIO, 0x00010001, CPG_T_CLK },
161 { /* ADC */
162 CPG_CLKON_ADC, CPG_CLKMON_ADC, 0x00030000, CPG_T_CLK },
163 { /* Thermal Sensor Unit */
164 CPG_CLKON_TSU, CPG_CLKMON_TSU, 0x00010000, CPG_T_CLK }
165 };
166
167 static const CPG_SETUP_DATA cpg_reset_tbl[] = {
168 { /* CM33 */
169 CPG_RST_CM33, CPG_RSTMON_CM33, 0x00070000, CPG_T_RST },
170 { /* MHU */
171 CPG_RST_MHU, CPG_RSTMON_MHU, 0x00010000, CPG_T_RST },
172 { /* DMAC */
173 CPG_RST_DMAC, CPG_RSTMON_DMAC, 0x00030003, CPG_T_RST },
174 { /* OSTM */
175 CPG_RST_OSTM, CPG_RSTMON_OSTM, 0x00060000, CPG_T_RST },
176 { /* MTU */
177 CPG_RST_MTU, CPG_RSTMON_MTU, 0x00010000, CPG_T_RST },
178 { /* POE3 */
179 CPG_RST_POE3, CPG_RSTMON_POE3, 0x00010000, CPG_T_RST },
180 { /* WDT */
181 CPG_RST_WDT, CPG_RSTMON_WDT, 0x00040000, CPG_T_RST },
182 #if USE_SDRAM
183 { /* DDR */
184 CPG_RST_DDR, CPG_RSTMON_DDR, 0x007F0000, CPG_T_RST },
185 #else
186 { /* DDR */
187 CPG_RST_DDR, CPG_RSTMON_DDR, 0x007F007F, CPG_T_RST },
188 #endif
189 { /* SDHI */
190 CPG_RST_SDHI, CPG_RSTMON_SDHI,
191 #if RZA3M
192 0x00010000,
193 #else
194 0x00030000,
195 #endif
196 CPG_T_RST },
197 { /* Image Scaling Unit */
198 CPG_RST_ISU, CPG_RSTMON_ISU, 0x00030000, CPG_T_RST },
199 { /* Camera Data Receive Unit */
200 CPG_RST_CRU, CPG_RSTMON_CRU, 0x00070000, CPG_T_RST },
201 { /* LCDC */
202 CPG_RST_LCDC, CPG_RSTMON_LCDC, 0x00010000, CPG_T_RST },
203 { /* Serial Sound Interface */
204 CPG_RST_SSIF, CPG_RSTMON_SSIF, 0x000f0000, CPG_T_RST },
205 { /* Sampling Rate Converter */
206 CPG_RST_SRC, CPG_RSTMON_SRC, 0x00010000, CPG_T_RST },
207 { /* USB2.0 */
208 CPG_RST_USB, CPG_RSTMON_USB, 0x000f0000, CPG_T_RST },
209 { /* ETHER */
210 CPG_RST_ETH, CPG_RSTMON_ETH, 0x00030000, CPG_T_RST },
211 { /* I2C */
212 CPG_RST_I2C, CPG_RSTMON_I2C, 0x000f0000, CPG_T_RST },
213 { /* SCIF */
214 CPG_RST_SCIF, CPG_RSTMON_SCIF, 0x001f0001, CPG_T_RST },
215 { /* SCI */
216 CPG_RST_SCI, CPG_RSTMON_SCI, 0x00030000, CPG_T_RST },
217 { /* IrDA */
218 CPG_RST_IRDA, CPG_RSTMON_IRDA, 0x00010000, CPG_T_RST },
219 { /* SPI */
220 CPG_RST_RSPI, CPG_RSTMON_RSPI, 0x00070000, CPG_T_RST },
221 { /* CAN */
222 CPG_RST_CANFD, CPG_RSTMON_CANFD, 0x00030000, CPG_T_RST },
223 { /* GPIO */
224 CPG_RST_GPIO, CPG_RSTMON_GPIO, 0x00070007, CPG_T_RST },
225 { /* ADC */
226 CPG_RST_ADC, CPG_RSTMON_ADC, 0x00030000, CPG_T_RST },
227 { /* Thermal Sensor Unit */
228 CPG_RST_TSU, CPG_RSTMON_TSU, 0x00010000, CPG_T_RST },
229 };
230
231 static const CPG_REG_SETTING cpg_static_select_tbl[] = {
232 { CPG_PL3A_DDIV, 0x01000100 },
233 { CPG_PL3_SSEL, 0x01000000 },
234 };
235
236 static const CPG_REG_SETTING cpg_dynamic_select_tbl[] = {
237 { CPG_PL4_DSEL, 0x00010001 },
238 #if RZA3M
239 { CPG_PL2SDHI_DSEL, 0x00010003 },
240 { CPG_PL2SDHI_DSEL, 0x00010002 },
241 #else
242 { CPG_PL2SDHI_DSEL, 0x00110033 },
243 { CPG_PL2SDHI_DSEL, 0x00110022 },
244 #endif
245 };
246
247 static const CPG_REG_SETTING cpg_sel_pll1_on_off[] = { { CPG_CLKON_CA55,
248 0x00010001 } };
249
250 static const CPG_REG_SETTING cpg_sel_pll2_1_on_off[] = {
251 { CPG_CLKON_ADC, 0x00010001 },
252 { CPG_CLKON_TSU, 0x00010001 },
253 #if RZA3M
254 { CPG_CLKON_SDHI, 0x000f0000 },
255 #else
256 { CPG_CLKON_SDHI, 0x00ff0000 },
257 #endif
258 };
259
260 static const CPG_REG_SETTING cpg_sel_pll2_2_on_off[] = {
261 #if RZA3M
262 { CPG_CLKON_SDHI, 0x000f0000 },
263 #else
264 { CPG_CLKON_SDHI, 0x00ff0000 },
265 #endif
266 };
267
268 static const CPG_REG_SETTING cpg_sel_pll3_1_on_off[] = {
269 { CPG_CLKON_AXI_ACPU_BUS, 0x000F000F },
270 { CPG_CLKON_AXI_COM_BUS, 0x00030003 },
271 { CPG_CLKON_AXI_DEFAULT_SLV, 0x00010001 },
272 { CPG_CLKON_AXI_MCPU_BUS, 0x01930193 },
273 { CPG_CLKON_AXI_TZCDDR, 0x001F001F },
274 { CPG_CLKON_AXI_VIDEO_BUS, 0x00030003 },
275 { CPG_CLKON_CA55, 0x001E001E },
276 { CPG_CLKON_CM33, 0x00010001 },
277 { CPG_CLKON_CRU, 0x000C000C },
278 { CPG_CLKON_CST, 0x07FD07FD },
279 { CPG_CLKON_DAMC_REG, 0x00030003 },
280 { CPG_CLKON_DDR, 0x00030003 },
281 { CPG_CLKON_ETH, 0x00030003 },
282 { CPG_CLKON_GIC600, 0x00010001 },
283 { CPG_CLKON_IA55, 0x00030003 },
284 { CPG_CLKON_IM33, 0x00030003 },
285 { CPG_CLKON_ISU, 0x00030003 },
286 { CPG_CLKON_JAUTH, 0x00010001 },
287 { CPG_CLKON_LCDC, 0x00010001 },
288 { CPG_CLKON_OTP, 0x00020002 },
289 { CPG_CLKON_PERI_COM, 0x00030003 },
290 { CPG_CLKON_PERI_CPU, 0x000D000D },
291 { CPG_CLKON_PERI_DDR, 0x00010001 },
292 { CPG_CLKON_PERI_VIDEO, 0x00070007 },
293 { CPG_CLKON_REG0_BUS, 0x00010001 },
294 { CPG_CLKON_REG1_BUS, 0x00030003 },
295 { CPG_CLKON_ROM, 0x00010001 },
296 #if RZA3M
297 { CPG_CLKON_SDHI, 0x000f0000 },
298 #else
299 { CPG_CLKON_SDHI, 0x00ff0000 },
300 #endif
301 { CPG_CLKON_SRAM_ACPU, 0x00010001 },
302 { CPG_CLKON_SRAM_MCPU, 0x00010001 },
303 { CPG_CLKON_SYSC, 0x00020002 },
304 { CPG_CLKON_TSIPG, 0x00030003 },
305 { CPG_CLKON_USB, 0x000F000F }
306 };
307
308 static const CPG_REG_SETTING cpg_sel_pll3_2_on_off[] = {
309 { CPG_CLKON_CRU, 0x00030003 },
310 { CPG_CLKON_SPI_MULTI, 0x00030003 },
311 { CPG_CLKON_AXI_MCPU_BUS, 0x02080208 },
312 };
313
314 static const CPG_REG_SETTING cpg_sel_pll3_3_on_off[] = {
315 { CPG_CLKON_SPI_MULTI, 0x00030003 },
316 { CPG_CLKON_AXI_MCPU_BUS, 0x02080208 },
317 };
318
319 static const CPG_REG_SETTING cpg_sel_pll5_1_on_off[] = {
320 { CPG_CLKON_CRU, 0x00100010 },
321 { CPG_CLKON_LCDC, 0x00020002 }
322 };
323
324 static const CPG_REG_SETTING cpg_sel_pll5_3_on_off[] = { { CPG_CLKON_LCDC,
325 0x00020002 } };
326
327 static const CPG_REG_SETTING cpg_sel_pll5_4_on_off[] = { { CPG_CLKON_LCDC,
328 0x00020002 } };
329
cpg_ctrl_clkrst(CPG_SETUP_DATA const * array,uint32_t num)330 static void cpg_ctrl_clkrst(CPG_SETUP_DATA const *array, uint32_t num)
331 {
332 int i;
333 uint32_t mask;
334 uint32_t cmp;
335
336 for (i = 0; i < num; i++, array++) {
337 mmio_write_32(array->reg, array->val);
338
339 mask = (array->val >> 16) & 0xFFFF;
340 cmp = array->val & 0xFFFF;
341 if (array->type == CPG_T_RST) {
342 cmp = ~(cmp);
343 }
344 while ((mmio_read_32(array->mon) & mask) != (cmp & mask))
345 ;
346 }
347 }
348
cpg_selector_on_off(uint32_t sel,uint8_t flag)349 static void cpg_selector_on_off(uint32_t sel, uint8_t flag)
350 {
351 uint32_t cnt;
352 uint32_t tbl_num;
353 CPG_REG_SETTING const *ptr;
354
355 switch (sel) {
356 case CPG_SEL_PLL1_ON_OFF:
357 tbl_num = ARRAY_SIZE(cpg_sel_pll1_on_off);
358 ptr = &cpg_sel_pll1_on_off[0];
359 break;
360 case CPG_SEL_PLL2_1_ON_OFF:
361 tbl_num = ARRAY_SIZE(cpg_sel_pll2_1_on_off);
362 ptr = &cpg_sel_pll2_1_on_off[0];
363 break;
364 case CPG_SEL_PLL2_2_ON_OFF:
365 tbl_num = ARRAY_SIZE(cpg_sel_pll2_2_on_off);
366 ptr = &cpg_sel_pll2_2_on_off[0];
367 break;
368 case CPG_SEL_PLL3_1_ON_OFF:
369 tbl_num = ARRAY_SIZE(cpg_sel_pll3_1_on_off);
370 ptr = &cpg_sel_pll3_1_on_off[0];
371 break;
372 case CPG_SEL_PLL3_2_ON_OFF:
373 tbl_num = ARRAY_SIZE(cpg_sel_pll3_2_on_off);
374 ptr = &cpg_sel_pll3_2_on_off[0];
375 break;
376 case CPG_SEL_PLL3_3_ON_OFF:
377 tbl_num = ARRAY_SIZE(cpg_sel_pll3_3_on_off);
378 ptr = &cpg_sel_pll3_3_on_off[0];
379 break;
380 case CPG_SEL_PLL5_1_ON_OFF:
381 tbl_num = ARRAY_SIZE(cpg_sel_pll5_1_on_off);
382 ptr = &cpg_sel_pll5_1_on_off[0];
383 break;
384 case CPG_SEL_PLL5_3_ON_OFF:
385 tbl_num = ARRAY_SIZE(cpg_sel_pll5_3_on_off);
386 ptr = &cpg_sel_pll5_3_on_off[0];
387 break;
388 case CPG_SEL_PLL5_4_ON_OFF:
389 tbl_num = ARRAY_SIZE(cpg_sel_pll5_4_on_off);
390 ptr = &cpg_sel_pll5_4_on_off[0];
391 break;
392 default:
393 break;
394 }
395
396 for (cnt = 0; cnt < tbl_num; cnt++) {
397 if (flag == CPG_ON) {
398 mmio_write_32(ptr[cnt].reg,
399 (mmio_read_32(ptr[cnt].reg) |
400 ptr[cnt].val));
401 } else {
402 mmio_write_32(ptr[cnt].reg,
403 (ptr[cnt].val & 0xFFFF0000));
404 }
405 }
406 }
407
cpg_pll_start_146(CPG_PLL_SETDATA_146 const * pdata)408 static void cpg_pll_start_146(CPG_PLL_SETDATA_146 const *pdata)
409 {
410 mmio_write_32(pdata->clk1_dat.reg, pdata->clk1_dat.val);
411 mmio_write_32(pdata->clk2_dat.reg, pdata->clk2_dat.val);
412 mmio_write_32(pdata->stby_dat.reg, pdata->stby_dat.val);
413 }
414
415 /* It is assumed that the PLL has stopped by the time this function is executed. */
cpg_pll_setup(void)416 static void cpg_pll_setup(void)
417 {
418 uint32_t val = 0;
419 #if USE_SDRAM
420 /* PLL4 reset (RESET=0) */
421 mmio_write_32(CPG_PLL4_STBY, PLL4_STBY_RESETB_WEN);
422
423 /* PLL4 startup */
424 /* PLL4 standby mode transition confirmation */
425 do {
426 val = mmio_read_32(CPG_PLL4_MON);
427 } while ((val & (PLL4_MON_PLL4_RESETB | PLL4_MON_PLL4_LOCK)) != 0);
428 #endif
429 /* PLL6 reset (RESET=0) */
430 mmio_write_32(CPG_PLL6_STBY, PLL6_STBY_RESETB_WEN);
431
432 /* PLL6 startup */
433 /* PLL6 standby mode transition confirmation */
434 do {
435 val = mmio_read_32(CPG_PLL6_MON);
436 } while ((val & (PLL6_MON_PLL6_RESETB | PLL6_MON_PLL6_LOCK)) != 0);
437
438 #if USE_SDRAM
439 /* Set PLL4 to normal mode */
440 cpg_pll_start_146(&cpg_pll4_setdata);
441 #endif
442 /* Set PLL6 to normal mode */
443 cpg_pll_start_146(&cpg_pll6_setdata);
444
445 #if USE_SDRAM
446 /* PLL4 normal mode transition confirmation */
447 do {
448 val = mmio_read_32(CPG_PLL4_MON);
449 } while ((val & (PLL4_MON_PLL4_RESETB | PLL4_MON_PLL4_LOCK)) == 0);
450 #endif
451 #if !(RZA3M)
452 /* PLL6 normal mode transition confirmation */
453 do {
454 val = mmio_read_32(CPG_PLL6_MON);
455 } while ((val & (PLL6_MON_PLL6_RESETB | PLL6_MON_PLL6_LOCK)) == 0);
456 #endif
457 }
458
cpg_div_sel_setup(CPG_REG_SETTING const * tbl,uint32_t size)459 static void cpg_div_sel_setup(CPG_REG_SETTING const *tbl, uint32_t size)
460 {
461 int cnt;
462
463 for (cnt = 0; cnt < size; cnt++, tbl++) {
464 mmio_write_32(tbl->reg, tbl->val);
465 }
466
467 #if USE_SDRAM
468 /* Wait for completion of settings */
469 while (mmio_read_32(CPG_CLKSTATUS) != 0)
470 ;
471 #endif
472 }
473
cpg_div_sel_static_setup(void)474 static void cpg_div_sel_static_setup(void)
475 {
476 cpg_div_sel_setup(cpg_static_select_tbl,
477 ARRAY_SIZE(cpg_static_select_tbl));
478 }
479
cpg_div_sel_dynamic_setup(void)480 static void cpg_div_sel_dynamic_setup(void)
481 {
482 cpg_div_sel_setup(cpg_dynamic_select_tbl,
483 ARRAY_SIZE(cpg_dynamic_select_tbl));
484 }
485
cpg_clk_on_setup(void)486 static void cpg_clk_on_setup(void)
487 {
488 cpg_ctrl_clkrst(&cpg_clk_on_tbl[0], ARRAY_SIZE(cpg_clk_on_tbl));
489 }
490
cpg_reset_setup(void)491 static void cpg_reset_setup(void)
492 {
493 cpg_ctrl_clkrst(&cpg_reset_tbl[0], ARRAY_SIZE(cpg_reset_tbl));
494 }
495
cpg_active_ddr(void (* disable_phy)(void))496 void cpg_active_ddr(void (*disable_phy)(void))
497 {
498 #if RZA3M
499 /* Assert AXI_PERIDDR.RESTn according to APP006 */
500 mmio_write_32(CPG_RST_PERI_DDR, 0x00010000);
501 while ((mmio_read_32(CPG_RSTMON_PERI_DDR) & 0x00000001) != 0x00000001)
502 ;
503 #endif
504 /* Assert the reset of DDRTOP */
505 mmio_write_32(CPG_RST_DDR, 0x005F0000 | (CPG_RST_DDR_OPT_VALUE << 16));
506 mmio_write_32(CPG_OTHERFUNC2_REG, 0x00010000);
507 while ((mmio_read_32(CPG_RSTMON_DDR) & 0x0000005F) != 0x0000005F)
508 ;
509
510 /* Start the clocks of DDRTOP */
511 mmio_write_32(CPG_CLKON_DDR, 0x00030003);
512 while ((mmio_read_32(CPG_CLKMON_DDR) & 0x00000003) != 0x00000003)
513 ;
514
515 udelay(1);
516
517 #if RZA3M
518 /* AXI_PERIDDR.RESTn according to APP006 */
519 mmio_write_32(CPG_RST_PERI_DDR, 0x00010001);
520 while ((mmio_read_32(CPG_RSTMON_PERI_DDR) & 0x00000001) != 0x00000000)
521 ;
522 #endif
523 /* De-assert rst_n */
524 mmio_write_32(CPG_OTHERFUNC2_REG, 0x00010001);
525
526 udelay(1);
527
528 /* De-assert PRESETN */
529 mmio_write_32(CPG_RST_DDR, 0x00020002);
530 while ((mmio_read_32(CPG_RSTMON_DDR) & 0x00000002) != 0x00000000)
531 ;
532
533 udelay(1);
534
535 disable_phy();
536
537 /* De-assert axiY_ARESETn, regARESETn, reset_n */
538 mmio_write_32(CPG_RST_DDR, 0x005D005D | (CPG_RST_DDR_OPT_VALUE << 16) |
539 CPG_RST_DDR_OPT_VALUE);
540 while ((mmio_read_32(CPG_RSTMON_DDR) & 0x0000005D) != 0x00000000)
541 ;
542
543 udelay(1);
544 }
545
cpg_reset_ddr_mc(void)546 void cpg_reset_ddr_mc(void)
547 {
548 #if RZA3M
549 /* Assert AXI_PERIDDR.RESTn according to APP006 */
550 mmio_write_32(CPG_RST_PERI_DDR, 0x00010000);
551 while ((mmio_read_32(CPG_RSTMON_PERI_DDR) & 0x00000001) != 0x00000001)
552 ;
553 #endif
554 /* Assert rst_n, axiY_ARESETn, regARESETn */
555 mmio_write_32(CPG_RST_DDR, 0x005C0000 | (CPG_RST_DDR_OPT_VALUE << 16));
556 mmio_write_32(CPG_OTHERFUNC2_REG, 0x00010000);
557 while ((mmio_read_32(CPG_RSTMON_DDR) & 0x0000005C) != 0x0000005C)
558 ;
559
560 udelay(1);
561
562 #if RZA3M
563 /* AXI_PERIDDR.RESTn according to APP006 */
564 mmio_write_32(CPG_RST_PERI_DDR, 0x00010001);
565 while ((mmio_read_32(CPG_RSTMON_PERI_DDR) & 0x00000001) != 0x00000000)
566 ;
567 #endif
568 /* De-assert rst_n */
569 mmio_write_32(CPG_OTHERFUNC2_REG, 0x00010001);
570
571 udelay(1);
572
573 /* De-assert axiY_ARESETn, regARESETn */
574 mmio_write_32(CPG_RST_DDR, 0x005C005C | (CPG_RST_DDR_OPT_VALUE << 16) |
575 CPG_RST_DDR_OPT_VALUE);
576 while ((mmio_read_32(CPG_RSTMON_DDR) & 0x0000005C) != 0x00000000)
577 ;
578
579 udelay(1);
580 }
581
cpg_early_setup(void)582 void cpg_early_setup(void)
583 {
584 cpg_ctrl_clkrst(&early_setup_tbl[0], ARRAY_SIZE(early_setup_tbl));
585 }
586
cpg_wdtrst_sel_setup(void)587 void cpg_wdtrst_sel_setup(void)
588 {
589 uint32_t reg;
590
591 reg = mmio_read_32(CPG_WDTRST_SEL);
592 reg |= WDTRST_SEL_WDTRSTSEL0 | WDTRST_SEL_WDTRSTSEL0_WEN;
593
594 mmio_write_32(CPG_WDTRST_SEL, reg);
595 }
596
cpu_cpg_setup(void)597 void cpu_cpg_setup(void)
598 {
599 while ((mmio_read_32(CPG_CLKSTATUS) & CLKSTATUS_DIVPL1_STS) !=
600 0x00000000)
601 ;
602 mmio_write_32(CPG_PL1_DDIV,
603 PL1_DDIV_DIVPL1_SET_WEN | PL1_DDIV_DIVPL1_SET_1_1);
604 while ((mmio_read_32(CPG_CLKSTATUS) & CLKSTATUS_DIVPL1_STS) !=
605 0x00000000)
606 ;
607 }
608
cpg_setup(void)609 void cpg_setup(void)
610 {
611 cpu_cpg_setup();
612 cpg_selector_on_off(CPG_SEL_PLL3_3_ON_OFF, CPG_OFF);
613 cpg_div_sel_static_setup();
614 cpg_selector_on_off(CPG_SEL_PLL3_3_ON_OFF, CPG_ON);
615 cpg_pll_setup();
616 cpg_clk_on_setup();
617 cpg_reset_setup();
618 cpg_div_sel_dynamic_setup();
619 cpg_wdtrst_sel_setup();
620 }
621
cpg_search_spi_clk_table(int frequency)622 static int cpg_search_spi_clk_table(int frequency)
623 {
624 int tables = ARRAY_SIZE(cpg_xspi_table);
625
626 for (int i = 0; i < tables; i++) {
627 if (frequency >= cpg_xspi_table[i].frequency) {
628 return i;
629 }
630 }
631 return -1;
632 }
633
cpg_rsearch_spi_clk_table(uint8_t selector,uint8_t divider)634 static int cpg_rsearch_spi_clk_table(uint8_t selector, uint8_t divider)
635 {
636 int tables = ARRAY_SIZE(cpg_xspi_table);
637
638 for (int i = 0; i < tables; i++) {
639 if (selector == cpg_xspi_table[i].selector &&
640 divider == cpg_xspi_table[i].divider) {
641 return cpg_xspi_table[i].frequency;
642 }
643 }
644 return -1;
645 }
646
wait_until_32(uintptr_t addr,uint32_t mask,uint32_t test)647 static void wait_until_32(uintptr_t addr, uint32_t mask, uint32_t test)
648 {
649 while ((mmio_read_32(addr) & mask) != test) {
650 };
651 }
652
cpg_stop_xspi_clock(enum xspi_clock spi)653 static void cpg_stop_xspi_clock(enum xspi_clock spi)
654 {
655 int onoff_pos;
656 uintptr_t clkon_ctrl;
657 uintptr_t clkmon_ctrl;
658
659 switch (spi) {
660 case XSPI_CLOCK_SPIM:
661 onoff_pos = 9;
662 clkon_ctrl = CPG_CLKON_SPI_MULTI;
663 clkmon_ctrl = CPG_CLKMON_SPI_MULTI;
664 break;
665 case XSPI_CLOCK_OCTA:
666 onoff_pos = 11;
667 clkon_ctrl = CPG_CLKON_OCTA;
668 clkmon_ctrl = CPG_CLKMON_OCTA;
669 break;
670 default:
671 ERROR("Not expected value %d passed to %s.", (int)spi,
672 __func__);
673 return;
674 }
675
676 mmio_write_32(clkon_ctrl, 0x00030000);
677 mmio_write_32(CPG_CLKON_AXI_MCPU_BUS, 0x10000 << onoff_pos);
678 wait_until_32(CPG_CLKMON_AXI_MCPU_BUS, 1 << onoff_pos, 0);
679 wait_until_32(clkmon_ctrl, 0x0003, 0);
680 }
681
cpg_start_xspi_clock(enum xspi_clock spi)682 static void cpg_start_xspi_clock(enum xspi_clock spi)
683 {
684 int onoff_pos;
685 uintptr_t clkon_ctrl;
686 uintptr_t clkmon_ctrl;
687
688 switch (spi) {
689 case XSPI_CLOCK_SPIM:
690 onoff_pos = 9;
691 clkon_ctrl = CPG_CLKON_SPI_MULTI;
692 clkmon_ctrl = CPG_CLKMON_SPI_MULTI;
693 break;
694 case XSPI_CLOCK_OCTA:
695 onoff_pos = 11;
696 clkon_ctrl = CPG_CLKON_OCTA;
697 clkmon_ctrl = CPG_CLKMON_OCTA;
698 break;
699 default:
700 ERROR("Not expected value %d passed to %s.", (int)spi,
701 __func__);
702 return;
703 }
704
705 mmio_write_32(clkon_ctrl, 0x0003ffff);
706 mmio_write_32(CPG_CLKON_AXI_MCPU_BUS, 0x10000 << onoff_pos | 0xffff);
707 wait_until_32(CPG_CLKMON_AXI_MCPU_BUS, 1 << onoff_pos, 1 << onoff_pos);
708 wait_until_32(clkmon_ctrl, 0x0003, 0x0003);
709 }
710
cpg_set_xspi_clock(enum xspi_clock spi,int frequency_hz)711 int cpg_set_xspi_clock(enum xspi_clock spi, int frequency_hz)
712 {
713 int seldiv_pos;
714 int status_pos;
715
716 switch (spi) {
717 case XSPI_CLOCK_SPIM:
718 seldiv_pos = 8;
719 status_pos = 10;
720 break;
721 case XSPI_CLOCK_OCTA:
722 seldiv_pos = 12;
723 status_pos = 12;
724 break;
725 default:
726 ERROR("Not expected value %d passed to %s.", (int)spi,
727 __func__);
728 return -1;
729 }
730
731 int index = cpg_search_spi_clk_table(frequency_hz);
732
733 if (index == -1)
734 ERROR("Not recognized frequency value %u passed to %s.",
735 frequency_hz, __func__);
736
737 int prev_sel = (mmio_read_32(CPG_PL3_SSEL) >> seldiv_pos) & 1;
738 int prev_div = (mmio_read_32(CPG_PL3A_DDIV) >> seldiv_pos) & 7;
739
740 if (prev_sel != cpg_xspi_table[index].selector) {
741 /* Changing static selector */
742 cpg_stop_xspi_clock(spi);
743 uint32_t sel = cpg_xspi_table[index].selector << seldiv_pos;
744
745 sel |= 0x10000 << seldiv_pos;
746 mmio_write_32(CPG_PL3_SSEL, sel);
747 cpg_start_xspi_clock(spi);
748 }
749
750 if (prev_div != cpg_xspi_table[index].divider) {
751 /* Changing dynamic divider */
752 wait_until_32(CPG_CLKSTATUS, 1u << status_pos, 0);
753 uint32_t div = cpg_xspi_table[index].divider << seldiv_pos;
754
755 div |= 0x10000 << seldiv_pos;
756 mmio_write_32(CPG_PL3A_DDIV, div);
757 wait_until_32(CPG_CLKSTATUS, 1u << status_pos, 0);
758 }
759
760 return 0;
761 }
762
cpg_get_xspi_clock(enum xspi_clock spi)763 int cpg_get_xspi_clock(enum xspi_clock spi)
764 {
765 uint8_t sel;
766 uint8_t div;
767 int seldiv_pos;
768
769 switch (spi) {
770 case XSPI_CLOCK_SPIM:
771 seldiv_pos = 8;
772 break;
773 case XSPI_CLOCK_OCTA:
774 seldiv_pos = 12;
775 break;
776 default:
777 ERROR("Not expected value %d passed to %s.", (int)spi,
778 __func__);
779 return -1;
780 }
781
782 sel = (uint8_t)((mmio_read_32(CPG_PL3_SSEL) >> seldiv_pos) & 1);
783 div = (uint8_t)((mmio_read_32(CPG_PL3A_DDIV) >> seldiv_pos) & 7);
784
785 int frequency = cpg_rsearch_spi_clk_table(sel, div);
786
787 if (frequency == -1)
788 ERROR("CPG register value error (sel=%d, div=%d) in %s", sel,
789 div, __func__);
790
791 return frequency;
792 }
793
cpg_clock_onoff(int clkid,uint32_t mask,uint32_t val)794 static void cpg_clock_onoff(int clkid, uint32_t mask, uint32_t val)
795 {
796 val = mask * (val & 1);
797 mmio_write_32(CPG_CLKON_CA55 + clkid * 4, (mask << 16) + val);
798 while ((mmio_read_32(CPG_CLKMON_CA55 + clkid * 4) & mask) != val)
799 ;
800 }
801
cpg_reset_onoff(int clkid,uint32_t mask,uint32_t val)802 static void cpg_reset_onoff(int clkid, uint32_t mask, uint32_t val)
803 {
804 val = mask * (val & 1);
805 mmio_write_32(CPG_RST_CA55 + clkid * 4, (mask << 16) + (val ^ 0xffff));
806 while ((mmio_read_32(CPG_RSTMON_CA55 + clkid * 4) & mask) != val)
807 ;
808 }
809
cpg_clock_on(enum clock_id clkid)810 void cpg_clock_on(enum clock_id clkid)
811 {
812 switch (clkid) {
813 case CPG_CLOCK_SPIM:
814 cpg_clock_onoff(CPG_CLOCK_SPIM, 3, 1);
815 break;
816 case CPG_CLOCK_OCTA:
817 cpg_clock_onoff(CPG_CLOCK_OCTA, 3, 1);
818 break;
819 default:
820 break;
821 }
822 }
823
cpg_clock_off(enum clock_id clkid)824 void cpg_clock_off(enum clock_id clkid)
825 {
826 switch (clkid) {
827 case CPG_CLOCK_SPIM:
828 cpg_clock_onoff(CPG_CLOCK_SPIM, 3, 0);
829 break;
830 case CPG_CLOCK_OCTA:
831 cpg_clock_onoff(CPG_CLOCK_OCTA, 3, 0);
832 break;
833 default:
834 break;
835 }
836 }
837
cpg_reset_on(enum clock_id clkid)838 void cpg_reset_on(enum clock_id clkid)
839 {
840 switch (clkid) {
841 case CPG_CLOCK_SPIM:
842 cpg_reset_onoff(CPG_CLOCK_SPIM, 1, 1);
843 break;
844 case CPG_CLOCK_OCTA:
845 cpg_reset_onoff(CPG_CLOCK_OCTA, 1, 1);
846 break;
847 default:
848 break;
849 }
850 }
851
cpg_reset_off(enum clock_id clkid)852 void cpg_reset_off(enum clock_id clkid)
853 {
854 switch (clkid) {
855 case CPG_CLOCK_SPIM:
856 cpg_reset_onoff(CPG_CLOCK_SPIM, 1, 0);
857 break;
858 case CPG_CLOCK_OCTA:
859 cpg_reset_onoff(CPG_CLOCK_OCTA, 1, 0);
860 break;
861 default:
862 break;
863 }
864 }
865