blob: e77e54fea5d7e784798c2d446d2cce2dce5d7a16 [file] [log] [blame]
bangzheng.liu5e691382023-01-10 16:20:10 +08001/*
2 * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7#include "FreeRTOS.h"
8#include <common.h>
9#include "register.h"
10#include "p_register.h"
11#include "uart.h"
12#include <task.h>
13#include "soc.h"
14#include "timer_source.h"
15#include "clk.h"
16#include "clk_util.h"
17#include "vad_suspend.h"
18#include "power_domain.h"
19#include "mailbox-api.h"
20#include "suspend.h"
21#include "uart.h"
22#include "c_mmc_reg.h"
23
24extern uint32_t get_reason_flag(void);
25
26void set_time(uint32_t val)
27{
28#ifdef ARM_CPU
29 REG32(SYSCTRL_SEC_TIMERE) = 0x0;
30#else
31 REG32(SYSCTRL_TIMERF) = val;
32#endif
33}
34
35uint32_t get_time(void)
36{
37 uint64_t timerE = 0;
38
39#ifdef ARM_CPU
40 timerE = REG32(SYSCTRL_SEC_TIMERE);
41#else
42 timerE = REG32(SYSCTRL_TIMERF);
43#endif
44 return (timerE);
45}
46
47/*
48 * use_clk_src
49 * 0. osc_clk
50 * 1. sys_clk (rtc_pll) clk_div1
51 * 2. sys_clk (rtc_pll) clk_div2
52 * 3. rtc_clk
53 * Note:
54 * 1. If select sys_clk, tick clk of 1us/10us/100us/1ms/xtal3 are all same
55 * 2. If select rtc_clk, tick clk of 1us/10us/100us/1ms/xtal3 will actually
56 * be 1ms/10ms/100ms/1s/93.747us
57 */
58
59void alt_timebase(int use_clk_src)
60{
61 uint32_t clk_div = 0;
62
63 if (use_clk_src == 0)
64 //select osc_clk
65 REG32(CLKCTRL_TIMEBASE_CTRL0) = 0x20018;
66 else if (use_clk_src == 1) {
67 //select sys_clk (rtc_pll) clk_div1
68 //if sys_clk is 11.171MHz
69 clk_div = 11;
70 REG32(CLKCTRL_TIMEBASE_CTRL0) = (clk_div << 19) | (0x2aa << 6);
71 } else if (use_clk_src == 2) {
72 //select sys_clk (rtc_pll) clk_div2 when sys_clk < 256MHz
73 //if sys_clk is 122.88MHz
74 clk_div = 123;
75 REG32(CLKCTRL_TIMEBASE_CTRL0) = (clk_div << 24) | (0x3ff << 6);
76 } else {
77 //select rtc clk
78 // 32k/32 = 1k
79 REG32(CLKCTRL_TIMEBASE_CTRL0) = 0x20020;
80 }
81}
82
83/*
84 * This is function for axi clk setting:
85 * Includes axi_clk(AKA cpu_axi_clk/ACLK), axi_matrix, axi_sram
86 *
87 */
88void set_axi_div_clk(int sel, int div)
89{
90 uint32_t control;
91 uint32_t dyn_pre_mux;
92 uint32_t dyn_div;
93
94 // fclk_div4 = 500MHz
95 dyn_pre_mux = sel;
96 dyn_div = div; /* divide by 1 */
97
98 control = REG32(CLKCTRL_AXI_CLK_CTRL0);
99 if (control & (1 << 15)) { //default is preb, need use prea
100 control =
101 (control & ~(0x3fff)) | ((1 << 13) | (dyn_pre_mux << 10) | (dyn_div << 0));
102 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
103 control = control & ~(1 << 15);
104 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
105 udelay(25);
106 } else {
107 //preb
108 control = (control & ~((0x3fff) << 16)) |
109 ((1 << 29) | (dyn_pre_mux << 26) | (dyn_div << 16));
110 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
111 control = control | (1 << 15);
112 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
113 udelay(25);
114 }
115}
116
117/*
118 * This is function for clk81 setting
119 *
120 */
121void set_sys_div_clk(int sel, int div)
122{
123 uint32_t control;
124 uint32_t dyn_pre_mux;
125 uint32_t dyn_div;
126
127 printf("Set sys clock to 167Mhz\n");
128
129 // fclk_div4 = 500MHz
130 dyn_pre_mux = sel;
131 dyn_div = div; /* divide by 3 */
132
133 control = REG32(CLKCTRL_SYS_CLK_CTRL0);
134
135 if (control & (1 << 15)) { //default is preb, need use prea
136 control =
137 (control & ~(0x3fff)) | ((1 << 13) | (dyn_pre_mux << 10) | (dyn_div << 0));
138 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
139 control = control & ~(1 << 15);
140 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
141 udelay(25);
142 } else {
143 //preb
144 control = (control & ~((0x3fff) << 16)) |
145 ((1 << 29) | (dyn_pre_mux << 26) | (dyn_div << 16));
146 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
147 control = control | (1 << 15);
148 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
149 udelay(25);
150 }
151
152 /* when bus switched from 24MHz to 166MHz,
153 * the clock tick used to generate OTP waveform
154 * needs 20us waiting time to switch to new clock tick
155 */
156 udelay(25);
157}
158/*
159 * clk_util_set_dsp_clk
160 * freq_sel:
161 * 0:800MHz fclk_2p5
162 * 1:400MHz fclk_5
163 * 2:500MHz fclk_4
164 * 3:666MHz fclk_3
165 * 4:333Mhz fclk_3/2
166 * 5:250Mhz fclk_4/2
167 * 6:200Mhz fclk_5/2
168 * 7:100Mhz fclk_5/4
169 * 8:24Mhz oscin
170 * 10:3Mhz oscin/8
171 * others:400MHz fclk_5
172 *
173 *.clk0 (cts_oscin_clk ),
174 *.clk1 (fclk_div2p5 ),
175 *.clk2 (fclk_div3 ),
176 *.clk3 (rtc_pll_clk ),
177 *.clk4 (hifi_pll_clk ),
178 *.clk5 (fclk_div4 ),
179 *.clk6 (gp1_pll_clk ),
180 *.clk7 (cts_rtc_clk ),
181 */
182
183/* --------------------------------------------------
184 * clk_util_set_dsp_clk
185 * --------------------------------------------------
186 */
187
188void clk_util_set_dsp_clk(uint32_t id, uint32_t freq_sel)
189{
190 uint32_t control;
191 uint32_t clk_sel;
192 uint32_t clk_div;
193 uint32_t addr = CLKCTRL_DSPA_CLK_CTRL0;
194
195 switch (id) {
196 case 0:
197 addr = CLKCTRL_DSPA_CLK_CTRL0;
198 break;
199 //default : addr = CLKCTRL_DSPB_CLK_CTRL0; break;
200 default:
201 printf("CLK_UTIL:Error, no dspb here\n");
202 break;
203 }
204
205 //Make sure not busy from last setting and we currently match the last setting
206 control = REG32(addr);
207
208 switch (freq_sel) {
209 case 0:
210 clk_sel = 1;
211 clk_div = 0;
212 printf("CLK_UTIL:dsp[%d]:fclk2p5:800MHz\n", id);
213 break;
214 case 1:
215 clk_sel = 1;
216 clk_div = 1;
217 printf("CLK_UTIL:dsp[%d]:fclk5:400MHz\n", id);
218 break;
219 case 2:
220 clk_sel = 5;
221 clk_div = 0;
222 printf("CLK_UTIL:dsp[%d]:fclk4:500MHz\n", id);
223 break;
224 case 3:
225 clk_sel = 2;
226 clk_div = 0;
227 printf("CLK_UTIL:dsp[%d]:fclk/3:667MHz\n", id);
228 break;
229 case 4:
230 clk_sel = 2;
231 clk_div = 1;
232 printf("CLK_UTIL:dsp[%d]:fclk3/2:333MHz\n", id);
233 break;
234 case 5:
235 clk_sel = 5;
236 clk_div = 1;
237 printf("CLK_UTIL:dsp[%d]:fclk4/2:250MHz\n", id);
238 break;
239 case 6:
240 clk_sel = 1;
241 clk_div = 3;
242 printf("CLK_UTIL:dsp[%d]:fclk5/2:200MHz\n", id);
243 break;
244 case 7:
245 clk_sel = 1;
246 clk_div = 7;
247 printf("CLK_UTIL:dsp[%d]:fclk5/4:100MHz\n", id);
248 break;
249 case 8:
250 clk_sel = 0;
251 clk_div = 0;
252 printf("CLK_UTIL:dsp[%d]:oscin:24MHz\n", id);
253 break;
254 case 10:
255 clk_sel = 0;
256 clk_div = 7;
257 printf("CLK_UTIL:dsp[%d]:oscin/8:3MHz\n", id);
258 break;
259 case 11:
260 clk_sel = 3;
261 clk_div = 0;
262 printf("CLK_UTIL:dsp[%d]:rtc pll:122.88MHz\n", id);
263 break;
264 case 12:
265 clk_sel = 7;
266 clk_div = 0;
267 printf("CLK_UTIL:dsp[%d]:rtc clk:24MHz\n", id);
268 break;
269 default:
270 clk_sel = 1;
271 clk_div = 7;
272 printf("CLK_UTIL:dsp[%d]:fclk5:400MHz\n", id);
273 break;
274 }
275
276 //if sync_mux ==1, sel mux 0
277 if (control & (1 << 15))
278 control = (control & ~((1 << 15) | (0x3ff << 0) | (0x7 << 10))) | (1 << 13) |
279 (1 << 29) | (clk_div << 0) | (clk_sel << 10);
280 else
281 control = (control & ~((1 << 15) | (0x3ff << 16) | (0x7 << 26))) | (1 << 13) |
282 (1 << 29) | (clk_div << 16) | (clk_sel << 26) | (1 << 15);
283
284 REG32(addr) = control;
285}
286
287void disable_pll(int id)
288{
289 switch (id) {
290 case PLL_SYS:
291 REG32(ANACTRL_SYSPLL_CTRL0) = (1 << 29);
292 break;
293 case PLL_GP0:
294 REG32(ANACTRL_GP0PLL_CTRL0) = (1 << 29);
295 break;
296 case PLL_GP1:
297 REG32(ANACTRL_GP1PLL_CTRL0) = (1 << 29);
298 break;
299 case PLL_FIX:
300 REG32(ANACTRL_FIXPLL_CTRL0) = (1 << 29);
301 break;
302 case PLL_HIFI:
303 REG32(ANACTRL_HIFIPLL_CTRL0) = (1 << 29);
304 break;
305 case PLL_RTC:
306 REG32(ANACTRL_RTCPLL_CTRL0) = (1 << 29);
307 break;
308 case PLL_DDR:
309 REG32(AM_DDR_PLL_CNTL0) = (1 << 29);
310 break;
311 default:
312 printf("Error: PLL is not in the list\n");
313 break;
314 }
315}
316
Jianyi Shi72cb49b2023-03-19 14:45:24 +0800317void start_off_fsm_of_chip_core(void)
318{
319 // start fsm to shut down chip_core
320 REG32(AO_PWRCTRL_SHUT_DN) = 1;
321
322 // Counter increases 1
323 REG32(AO_PWRCTRL_SW_COUNT) += 1;
324}
325
326void init_ao_pwr_ctrl(void)
327{
328 // pmic_sleep high valid
329 REG32(AO_PWRCTRL_MODE) |= (0<<1); // high valid
330
331 // SLEEP: delay between kick_off to core_iso_en = 1
Jianyi Shie3c77a72023-03-23 17:30:17 +0800332 REG32(AO_PWRCTRL_OFF_DLY0) = 10; // 10ms, unit: 1ms
Jianyi Shi72cb49b2023-03-19 14:45:24 +0800333
334 // SLEEP: delay between core_iso_en = 1 to pmic_sleep = 1
335 REG32(AO_PWRCTRL_OFF_DLY1) = 1; // 1ms, unit: 1ms
336
337 // WAKEUP: delay between pmic_sleep = 0 to core_iso_en = 0
338 REG32(AO_PWRCTRL_ON_DLY) = 1;
339
340#ifdef USE_GPIOAO_2_CTRL_PMIC
341 REG32(PADCTRL_PIN_MUX_REGAO) &= ~(0xf << 8);
342 REG32(PADCTRL_PIN_MUX_REGAO) |= (0x4 << 8);
343#else
344 REG32(PADCTRL_PIN_MUX_REGAO) &= ~(0xf << 16);
345 REG32(PADCTRL_PIN_MUX_REGAO) |= (0x4 << 16);
346#endif
347}
348
bangzheng.liu5e691382023-01-10 16:20:10 +0800349int oscin_ctrl_reg;
350void vCLK_resume(uint32_t st_f)
351{
bangzheng.liu5e691382023-01-10 16:20:10 +0800352 if (st_f) {
353 /* switch osc_clk back*/
354 REG32(CLKCTRL_SYSOSCIN_CTRL) = 1;
355 REG32(CLKCTRL_OSCIN_CTRL) = oscin_ctrl_reg | (1 << 31);
356 udelay(2000);
357 /* switching tick timer (using osc_clk) */
358 alt_timebase(0);
359
360 set_sys_div_clk(0, 0); // osc_clk
361 set_axi_div_clk(0, 0); // osc_clk
362 vUartChangeBaudrate_resume(921600);
363 udelay(1000);
364 disable_pll(PLL_RTC);
365 power_switch_to_wraper(PWR_ON);
366 /* open mem_pd of srama and sramb */
367 REG32(PWRCTRL_MEM_PD2) = 0x0;
bangzheng.liu5e691382023-01-10 16:20:10 +0800368 }
369
370 // In a55 boot code
371 REG32(PWRCTRL_ACCESS_CTRL) = 0x0; // default access pwrctrl
372}
373
374void vCLK_suspend(uint32_t st_f)
375{
bangzheng.liu5e691382023-01-10 16:20:10 +0800376 printf("[AOCPU]: enter vCLK suspend.\n");
377
378 if (st_f) {
bangzheng.liu5e691382023-01-10 16:20:10 +0800379 /* poweroff wrapper */
380 power_switch_to_wraper(PWR_OFF);
381 udelay(2000);
bangzheng.liu5e691382023-01-10 16:20:10 +0800382
Jianyi Shie3c77a72023-03-23 17:30:17 +0800383 // switch clock from sys_clk to osc_clk
384 REG32(AO_CLKCTRL_OSCIN_CTRL) |= (1<<0); // select osc_clk
385 // switch clock from osc_clk to rtc_clk
386 REG32(AO_CLKCTRL_OSCIN_CTRL) |= (1<<1); // select rtc_clk
387
Jianyi Shi72cb49b2023-03-19 14:45:24 +0800388 /***start_ao_standby_flow ***/
389 // initial ao pwr_ctrl
390 init_ao_pwr_ctrl();
bangzheng.liu5e691382023-01-10 16:20:10 +0800391
Jianyi Shi72cb49b2023-03-19 14:45:24 +0800392 // start fsm to power off chip_core
393 start_off_fsm_of_chip_core();
Jianyi Shi72cb49b2023-03-19 14:45:24 +0800394
Jianyi Shie3c77a72023-03-23 17:30:17 +0800395 printf("soc poweroff\n");
bangzheng.liu5e691382023-01-10 16:20:10 +0800396 /* power off osc_clk */
397 REG32(CLKCTRL_SYSOSCIN_CTRL) = 0;
bangzheng.liu5e691382023-01-10 16:20:10 +0800398 } else {
Jianyi Shi72cb49b2023-03-19 14:45:24 +0800399 printf("[AOCPU]: running at 24MHz.\n");
bangzheng.liu5e691382023-01-10 16:20:10 +0800400 }
401}