blob: 80a1eb4b06be59b9de4db696a6b40b5f93d01ffc [file] [log] [blame]
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +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>
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +08009#include "register.h"
Jianyi Shi9c2177a2022-07-26 17:42:28 +080010#include "p_register.h"
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080011#include "uart.h"
12#include <task.h>
Jianyi Shid11ec702022-05-16 17:48:25 +080013#include "soc.h"
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080014#include "timer_source.h"
Peipeng Zhao6a02b302022-04-28 17:29:15 +080015#include "clk.h"
16#include "clk_util.h"
17#include "vad_suspend.h"
18#include "power_domain.h"
Jianyi Shia3c107b2022-04-29 11:04:46 +080019#include "mailbox-api.h"
20#include "suspend.h"
Jianyi Shi9c2177a2022-07-26 17:42:28 +080021#include "uart.h"
Jianyi Shia3c107b2022-04-29 11:04:46 +080022
23extern uint32_t get_reason_flag(void);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080024
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080025void set_time(uint32_t val)
26{
27#ifdef ARM_CPU
28 REG32(SYSCTRL_SEC_TIMERE) = 0x0;
29#else
30 REG32(SYSCTRL_TIMERF) = val;
31#endif
32}
33
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080034uint32_t get_time(void)
35{
36 uint64_t timerE = 0;
37
38#ifdef ARM_CPU
39 timerE = REG32(SYSCTRL_SEC_TIMERE);
40#else
41 timerE = REG32(SYSCTRL_TIMERF);
42#endif
xiaohu.huang38262102022-05-06 22:21:48 +080043 return (timerE);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080044}
45
46/*
47 * use_clk_src
48 * 0. osc_clk
49 * 1. sys_clk (rtc_pll) clk_div1
50 * 2. sys_clk (rtc_pll) clk_div2
51 * 3. rtc_clk
52 * Note:
53 * 1. If select sys_clk, tick clk of 1us/10us/100us/1ms/xtal3 are all same
54 * 2. If select rtc_clk, tick clk of 1us/10us/100us/1ms/xtal3 will actually
55 * be 1ms/10ms/100ms/1s/93.747us
56 */
57
58void alt_timebase(int use_clk_src)
59{
60 uint32_t clk_div = 0;
xiaohu.huang38262102022-05-06 22:21:48 +080061
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080062 if (use_clk_src == 0)
63 //select osc_clk
64 REG32(CLKCTRL_TIMEBASE_CTRL0) = 0x20018;
65 else if (use_clk_src == 1) {
66 //select sys_clk (rtc_pll) clk_div1
Jianyi Shi9c2177a2022-07-26 17:42:28 +080067 //if sys_clk is 11.171MHz
68 clk_div = 11;
69 REG32(CLKCTRL_TIMEBASE_CTRL0) = (clk_div << 19) | (0x2aa << 6);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080070 } else if (use_clk_src == 2) {
xiaohu.huang38262102022-05-06 22:21:48 +080071 //select sys_clk (rtc_pll) clk_div2 when sys_clk < 256MHz
72 //if sys_clk is 122.88MHz
Jianyi Shi9c2177a2022-07-26 17:42:28 +080073 clk_div = 123;
74 REG32(CLKCTRL_TIMEBASE_CTRL0) = (clk_div << 24) | (0x3ff << 6);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080075 } else {
76 //select rtc clk
77 // 32k/32 = 1k
78 REG32(CLKCTRL_TIMEBASE_CTRL0) = 0x20020;
79 }
80}
81
82/*
83 * This is function for axi clk setting:
84 * Includes axi_clk(AKA cpu_axi_clk/ACLK), axi_matrix, axi_sram
85 *
86 */
87void set_axi_div_clk(int sel, int div)
88{
89 uint32_t control;
90 uint32_t dyn_pre_mux;
91 uint32_t dyn_div;
92
93 // fclk_div4 = 500MHz
94 dyn_pre_mux = sel;
xiaohu.huang38262102022-05-06 22:21:48 +080095 dyn_div = div; /* divide by 1 */
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080096
97 control = REG32(CLKCTRL_AXI_CLK_CTRL0);
xiaohu.huang38262102022-05-06 22:21:48 +080098 if (control & (1 << 15)) { //default is preb, need use prea
99 control =
100 (control & ~(0x3fff)) | ((1 << 13) | (dyn_pre_mux << 10) | (dyn_div << 0));
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800101 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
102 control = control & ~(1 << 15);
103 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
104 udelay(25);
105 } else {
106 //preb
xiaohu.huang38262102022-05-06 22:21:48 +0800107 control = (control & ~((0x3fff) << 16)) |
108 ((1 << 29) | (dyn_pre_mux << 26) | (dyn_div << 16));
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800109 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
110 control = control | (1 << 15);
111 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
112 udelay(25);
113 }
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800114}
115
116/*
117 * This is function for clk81 setting
118 *
119 */
120void set_sys_div_clk(int sel, int div)
121{
122 uint32_t control;
123 uint32_t dyn_pre_mux;
124 uint32_t dyn_div;
125
126 printf("Set sys clock to 167Mhz\n");
127
128 // fclk_div4 = 500MHz
129 dyn_pre_mux = sel;
xiaohu.huang38262102022-05-06 22:21:48 +0800130 dyn_div = div; /* divide by 3 */
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800131
132 control = REG32(CLKCTRL_SYS_CLK_CTRL0);
133
xiaohu.huang38262102022-05-06 22:21:48 +0800134 if (control & (1 << 15)) { //default is preb, need use prea
135 control =
136 (control & ~(0x3fff)) | ((1 << 13) | (dyn_pre_mux << 10) | (dyn_div << 0));
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800137 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
138 control = control & ~(1 << 15);
139 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
140 udelay(25);
141 } else {
142 //preb
xiaohu.huang38262102022-05-06 22:21:48 +0800143 control = (control & ~((0x3fff) << 16)) |
144 ((1 << 29) | (dyn_pre_mux << 26) | (dyn_div << 16));
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800145 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
146 control = control | (1 << 15);
147 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
148 udelay(25);
149 }
150
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800151 /* when bus switched from 24MHz to 166MHz,
152 * the clock tick used to generate OTP waveform
153 * needs 20us waiting time to switch to new clock tick
154 */
155 udelay(25);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800156}
157/*
158 * clk_util_set_dsp_clk
159 * freq_sel:
160 * 0:800MHz fclk_2p5
161 * 1:400MHz fclk_5
162 * 2:500MHz fclk_4
163 * 3:666MHz fclk_3
164 * 4:333Mhz fclk_3/2
165 * 5:250Mhz fclk_4/2
166 * 6:200Mhz fclk_5/2
167 * 7:100Mhz fclk_5/4
168 * 8:24Mhz oscin
169 * 10:3Mhz oscin/8
170 * others:400MHz fclk_5
171 *
172 *.clk0 (cts_oscin_clk ),
173 *.clk1 (fclk_div2p5 ),
174 *.clk2 (fclk_div3 ),
175 *.clk3 (rtc_pll_clk ),
176 *.clk4 (hifi_pll_clk ),
177 *.clk5 (fclk_div4 ),
178 *.clk6 (gp1_pll_clk ),
179 *.clk7 (cts_rtc_clk ),
180 */
181
182/* --------------------------------------------------
183 * clk_util_set_dsp_clk
184 * --------------------------------------------------
185 */
186
187void clk_util_set_dsp_clk(uint32_t id, uint32_t freq_sel)
188{
xiaohu.huang38262102022-05-06 22:21:48 +0800189 uint32_t control;
190 uint32_t clk_sel;
191 uint32_t clk_div;
192 uint32_t addr = CLKCTRL_DSPA_CLK_CTRL0;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800193
194 switch (id) {
xiaohu.huang38262102022-05-06 22:21:48 +0800195 case 0:
196 addr = CLKCTRL_DSPA_CLK_CTRL0;
197 break;
198 //default : addr = CLKCTRL_DSPB_CLK_CTRL0; break;
199 default:
200 printf("CLK_UTIL:Error, no dspb here\n");
201 break;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800202 }
203
204 //Make sure not busy from last setting and we currently match the last setting
205 control = REG32(addr);
206
xiaohu.huang38262102022-05-06 22:21:48 +0800207 switch (freq_sel) {
208 case 0:
209 clk_sel = 1;
210 clk_div = 0;
211 printf("CLK_UTIL:dsp[%d]:fclk2p5:800MHz\n", id);
212 break;
213 case 1:
214 clk_sel = 1;
215 clk_div = 1;
216 printf("CLK_UTIL:dsp[%d]:fclk5:400MHz\n", id);
217 break;
218 case 2:
219 clk_sel = 5;
220 clk_div = 0;
221 printf("CLK_UTIL:dsp[%d]:fclk4:500MHz\n", id);
222 break;
223 case 3:
224 clk_sel = 2;
225 clk_div = 0;
226 printf("CLK_UTIL:dsp[%d]:fclk/3:667MHz\n", id);
227 break;
228 case 4:
229 clk_sel = 2;
230 clk_div = 1;
231 printf("CLK_UTIL:dsp[%d]:fclk3/2:333MHz\n", id);
232 break;
233 case 5:
234 clk_sel = 5;
235 clk_div = 1;
236 printf("CLK_UTIL:dsp[%d]:fclk4/2:250MHz\n", id);
237 break;
238 case 6:
239 clk_sel = 1;
240 clk_div = 3;
241 printf("CLK_UTIL:dsp[%d]:fclk5/2:200MHz\n", id);
242 break;
243 case 7:
244 clk_sel = 1;
245 clk_div = 7;
246 printf("CLK_UTIL:dsp[%d]:fclk5/4:100MHz\n", id);
247 break;
248 case 8:
249 clk_sel = 0;
250 clk_div = 0;
251 printf("CLK_UTIL:dsp[%d]:oscin:24MHz\n", id);
252 break;
253 case 10:
254 clk_sel = 0;
255 clk_div = 7;
256 printf("CLK_UTIL:dsp[%d]:oscin/8:3MHz\n", id);
257 break;
258 case 11:
259 clk_sel = 3;
260 clk_div = 0;
261 printf("CLK_UTIL:dsp[%d]:rtc pll:122.88MHz\n", id);
262 break;
263 case 12:
264 clk_sel = 7;
265 clk_div = 0;
266 printf("CLK_UTIL:dsp[%d]:rtc clk:24MHz\n", id);
267 break;
268 default:
269 clk_sel = 1;
270 clk_div = 7;
271 printf("CLK_UTIL:dsp[%d]:fclk5:400MHz\n", id);
272 break;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800273 }
274
275 //if sync_mux ==1, sel mux 0
276 if (control & (1 << 15))
xiaohu.huang38262102022-05-06 22:21:48 +0800277 control = (control & ~((1 << 15) | (0x3ff << 0) | (0x7 << 10))) | (1 << 13) |
278 (1 << 29) | (clk_div << 0) | (clk_sel << 10);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800279 else
xiaohu.huang38262102022-05-06 22:21:48 +0800280 control = (control & ~((1 << 15) | (0x3ff << 16) | (0x7 << 26))) | (1 << 13) |
281 (1 << 29) | (clk_div << 16) | (clk_sel << 26) | (1 << 15);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800282
283 REG32(addr) = control;
284}
285
286void disable_pll(int id)
287{
288 switch (id) {
xiaohu.huang38262102022-05-06 22:21:48 +0800289 case PLL_SYS:
290 REG32(ANACTRL_SYSPLL_CTRL0) = (1 << 29);
291 break;
292 case PLL_GP0:
293 REG32(ANACTRL_GP0PLL_CTRL0) = (1 << 29);
294 break;
295 case PLL_GP1:
296 REG32(ANACTRL_GP1PLL_CTRL0) = (1 << 29);
297 break;
298 case PLL_FIX:
299 REG32(ANACTRL_FIXPLL_CTRL0) = (1 << 29);
300 break;
301 case PLL_HIFI:
302 REG32(ANACTRL_HIFIPLL_CTRL0) = (1 << 29);
303 break;
304 case PLL_RTC:
305 REG32(ANACTRL_RTCPLL_CTRL0) = (1 << 29);
306 break;
307 case PLL_DDR:
308 REG32(AM_DDR_PLL_CNTL0) = (1 << 29);
309 break;
310 default:
311 printf("Error: PLL is not in the list\n");
312 break;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800313 }
314}
315
xiaohu.huang38262102022-05-06 22:21:48 +0800316int oscin_ctrl_reg;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800317void vCLK_resume(uint32_t st_f)
318{
Jianyi Shia3c107b2022-04-29 11:04:46 +0800319 int xIdx = 0;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800320
Jianyi Shi9c2177a2022-07-26 17:42:28 +0800321 if ((!st_f) && (get_reason_flag() != VAD_WAKEUP)) {
Jianyi Shia3c107b2022-04-29 11:04:46 +0800322 wakeup_dsp();
323 vTaskDelay(pdMS_TO_TICKS(90));
324 xIdx = WAKEUP_FROM_OTHER_KEY;
325 xTransferMessageAsync(AODSPA_CHANNEL, MBX_CMD_SUSPEND_WITH_DSP, &xIdx, 4);
Jianyi Shi9c2177a2022-07-26 17:42:28 +0800326 clear_dsp_wakeup_trigger();
Jianyi Shia3c107b2022-04-29 11:04:46 +0800327 }
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800328
329 if (st_f) {
Jianyi Shi9c2177a2022-07-26 17:42:28 +0800330 /* switch osc_clk back*/
331 REG32(CLKCTRL_SYSOSCIN_CTRL) = 1;
332 REG32(CLKCTRL_OSCIN_CTRL) = oscin_ctrl_reg | (1 << 31);
333 udelay(2000);
334 /* switching tick timer (using osc_clk) */
335 alt_timebase(0);
336
337 set_sys_div_clk(0, 0); // osc_clk
338 set_axi_div_clk(0, 0); // osc_clk
339 vUartChangeBaudrate_resume(921600);
340 udelay(1000);
341 disable_pll(PLL_RTC);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800342 power_switch_to_wraper(PWR_ON);
343 /* open mem_pd of srama and sramb */
344 REG32(PWRCTRL_MEM_PD2) = 0x0;
Jianyi Shi9c2177a2022-07-26 17:42:28 +0800345 } else {
346
347 xIdx = WAIT_SWITCH_TO_24MHZ;
348 xTransferMessageAsync(AODSPA_CHANNEL, MBX_CMD_SUSPEND_WITH_DSP, &xIdx, 4);
349 vTaskDelay(pdMS_TO_TICKS(90));
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800350 }
351
352 // In a55 boot code
xiaohu.huang38262102022-05-06 22:21:48 +0800353 REG32(PWRCTRL_ACCESS_CTRL) = 0x0; // default access pwrctrl
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800354}
355
356void vCLK_suspend(uint32_t st_f)
357{
Jianyi Shia3c107b2022-04-29 11:04:46 +0800358 int xIdx = 0;
359
Chengbing.wu84e237f2024-11-26 14:00:19 +0800360 printf("[AOCPU]: a5 enter vCLK_suspend.\n");
Jianyi Shi9c2177a2022-07-26 17:42:28 +0800361
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800362 if (st_f) {
363 /* close mem_pd of srama and sramb */
364 REG32(PWRCTRL_MEM_PD2) = 0xfffffffc;
365 /* poweroff wrapper */
366 power_switch_to_wraper(PWR_OFF);
Jianyi Shi9c2177a2022-07-26 17:42:28 +0800367 udelay(2000);
368 /* switch to RTC pll */
369 set_sys_div_clk(6, 10); // rtc pll (11.171MHz)
370 set_axi_div_clk(6, 0); // rtc pll (122.88MHz)
371 alt_timebase(1); // 1us/10us/100us/1ms/xtal3 = 1 us tick 11.171/11
372
373 udelay(2000);
374 vUartChangeBaudrate_suspend(11171000, 921600);
375 udelay(1000);
376
377 /* power off osc_clk */
378 REG32(CLKCTRL_SYSOSCIN_CTRL) = 0;
379 oscin_ctrl_reg = REG32(CLKCTRL_OSCIN_CTRL);
380 REG32(CLKCTRL_OSCIN_CTRL) = 0;
381 printf("[AOCPU]: running at 11.171MHz, 24MHz osc clk power off.\n");
382
383 } else {
384 xIdx = WAIT_SWITCH_TO_RTC_PLL;
385 xTransferMessageAsync(AODSPA_CHANNEL, MBX_CMD_SUSPEND_WITH_DSP, &xIdx, 4);
386 vTaskDelay(pdMS_TO_TICKS(90));
387 printf("[AOCPU]: running at 24MHz, 24MHz osc clk power off.\n");
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800388 }
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800389}