xref: /rk3399_ARM-atf/drivers/renesas/rza/cpg/cpg.c (revision 66a0bb47058db8a4f74ccc1543a146094829e110)
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