blob: 7b092ccb6ca169c9f058fe4bf7e446f4c4a6d8b7 [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"
10#include "uart.h"
11#include <task.h>
Jianyi Shid11ec702022-05-16 17:48:25 +080012#include "soc.h"
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080013#include "timer_source.h"
Peipeng Zhao6a02b302022-04-28 17:29:15 +080014#include "clk.h"
15#include "clk_util.h"
16#include "vad_suspend.h"
17#include "power_domain.h"
Jianyi Shia3c107b2022-04-29 11:04:46 +080018#include "mailbox-api.h"
19#include "suspend.h"
20
21extern uint32_t get_reason_flag(void);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080022
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080023void set_time(uint32_t val)
24{
25#ifdef ARM_CPU
26 REG32(SYSCTRL_SEC_TIMERE) = 0x0;
27#else
28 REG32(SYSCTRL_TIMERF) = val;
29#endif
30}
31
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080032uint32_t get_time(void)
33{
34 uint64_t timerE = 0;
35
36#ifdef ARM_CPU
37 timerE = REG32(SYSCTRL_SEC_TIMERE);
38#else
39 timerE = REG32(SYSCTRL_TIMERF);
40#endif
xiaohu.huang38262102022-05-06 22:21:48 +080041 return (timerE);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080042}
43
44/*
45 * use_clk_src
46 * 0. osc_clk
47 * 1. sys_clk (rtc_pll) clk_div1
48 * 2. sys_clk (rtc_pll) clk_div2
49 * 3. rtc_clk
50 * Note:
51 * 1. If select sys_clk, tick clk of 1us/10us/100us/1ms/xtal3 are all same
52 * 2. If select rtc_clk, tick clk of 1us/10us/100us/1ms/xtal3 will actually
53 * be 1ms/10ms/100ms/1s/93.747us
54 */
55
56void alt_timebase(int use_clk_src)
57{
58 uint32_t clk_div = 0;
xiaohu.huang38262102022-05-06 22:21:48 +080059
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080060 if (use_clk_src == 0)
61 //select osc_clk
62 REG32(CLKCTRL_TIMEBASE_CTRL0) = 0x20018;
63 else if (use_clk_src == 1) {
64 //select sys_clk (rtc_pll) clk_div1
65 //when sys_clk < 32MHz
66 //if sys_clk is 30MHz
67 clk_div = 30;
xiaohu.huang38262102022-05-06 22:21:48 +080068 REG32(CLKCTRL_TIMEBASE_CTRL0) = (1 << 17) | (clk_div << 19) | (0x2aa << 6);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080069 } else if (use_clk_src == 2) {
xiaohu.huang38262102022-05-06 22:21:48 +080070 //select sys_clk (rtc_pll) clk_div2 when sys_clk < 256MHz
71 //if sys_clk is 122.88MHz
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080072 clk_div = 122;
xiaohu.huang38262102022-05-06 22:21:48 +080073 REG32(CLKCTRL_TIMEBASE_CTRL0) = (1 << 17) | (clk_div << 24) | (0x3ff << 6);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080074 } else {
75 //select rtc clk
76 // 32k/32 = 1k
77 REG32(CLKCTRL_TIMEBASE_CTRL0) = 0x20020;
78 }
79}
80
81/*
82 * This is function for axi clk setting:
83 * Includes axi_clk(AKA cpu_axi_clk/ACLK), axi_matrix, axi_sram
84 *
85 */
86void set_axi_div_clk(int sel, int div)
87{
88 uint32_t control;
89 uint32_t dyn_pre_mux;
90 uint32_t dyn_div;
91
92 // fclk_div4 = 500MHz
93 dyn_pre_mux = sel;
xiaohu.huang38262102022-05-06 22:21:48 +080094 dyn_div = div; /* divide by 1 */
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080095
96 control = REG32(CLKCTRL_AXI_CLK_CTRL0);
xiaohu.huang38262102022-05-06 22:21:48 +080097 if (control & (1 << 15)) { //default is preb, need use prea
98 control =
99 (control & ~(0x3fff)) | ((1 << 13) | (dyn_pre_mux << 10) | (dyn_div << 0));
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800100 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
101 control = control & ~(1 << 15);
102 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
103 udelay(25);
104 } else {
105 //preb
xiaohu.huang38262102022-05-06 22:21:48 +0800106 control = (control & ~((0x3fff) << 16)) |
107 ((1 << 29) | (dyn_pre_mux << 26) | (dyn_div << 16));
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800108 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
109 control = control | (1 << 15);
110 REG32(CLKCTRL_AXI_CLK_CTRL0) = control;
111 udelay(25);
112 }
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800113}
114
115/*
116 * This is function for clk81 setting
117 *
118 */
119void set_sys_div_clk(int sel, int div)
120{
121 uint32_t control;
122 uint32_t dyn_pre_mux;
123 uint32_t dyn_div;
124
125 printf("Set sys clock to 167Mhz\n");
126
127 // fclk_div4 = 500MHz
128 dyn_pre_mux = sel;
xiaohu.huang38262102022-05-06 22:21:48 +0800129 dyn_div = div; /* divide by 3 */
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800130
131 control = REG32(CLKCTRL_SYS_CLK_CTRL0);
132
xiaohu.huang38262102022-05-06 22:21:48 +0800133 if (control & (1 << 15)) { //default is preb, need use prea
134 control =
135 (control & ~(0x3fff)) | ((1 << 13) | (dyn_pre_mux << 10) | (dyn_div << 0));
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800136 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
137 control = control & ~(1 << 15);
138 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
139 udelay(25);
140 } else {
141 //preb
xiaohu.huang38262102022-05-06 22:21:48 +0800142 control = (control & ~((0x3fff) << 16)) |
143 ((1 << 29) | (dyn_pre_mux << 26) | (dyn_div << 16));
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800144 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
145 control = control | (1 << 15);
146 REG32(CLKCTRL_SYS_CLK_CTRL0) = control;
147 udelay(25);
148 }
149
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800150 /* when bus switched from 24MHz to 166MHz,
151 * the clock tick used to generate OTP waveform
152 * needs 20us waiting time to switch to new clock tick
153 */
154 udelay(25);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800155}
156/*
157 * clk_util_set_dsp_clk
158 * freq_sel:
159 * 0:800MHz fclk_2p5
160 * 1:400MHz fclk_5
161 * 2:500MHz fclk_4
162 * 3:666MHz fclk_3
163 * 4:333Mhz fclk_3/2
164 * 5:250Mhz fclk_4/2
165 * 6:200Mhz fclk_5/2
166 * 7:100Mhz fclk_5/4
167 * 8:24Mhz oscin
168 * 10:3Mhz oscin/8
169 * others:400MHz fclk_5
170 *
171 *.clk0 (cts_oscin_clk ),
172 *.clk1 (fclk_div2p5 ),
173 *.clk2 (fclk_div3 ),
174 *.clk3 (rtc_pll_clk ),
175 *.clk4 (hifi_pll_clk ),
176 *.clk5 (fclk_div4 ),
177 *.clk6 (gp1_pll_clk ),
178 *.clk7 (cts_rtc_clk ),
179 */
180
181/* --------------------------------------------------
182 * clk_util_set_dsp_clk
183 * --------------------------------------------------
184 */
185
186void clk_util_set_dsp_clk(uint32_t id, uint32_t freq_sel)
187{
xiaohu.huang38262102022-05-06 22:21:48 +0800188 uint32_t control;
189 uint32_t clk_sel;
190 uint32_t clk_div;
191 uint32_t addr = CLKCTRL_DSPA_CLK_CTRL0;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800192
193 switch (id) {
xiaohu.huang38262102022-05-06 22:21:48 +0800194 case 0:
195 addr = CLKCTRL_DSPA_CLK_CTRL0;
196 break;
197 //default : addr = CLKCTRL_DSPB_CLK_CTRL0; break;
198 default:
199 printf("CLK_UTIL:Error, no dspb here\n");
200 break;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800201 }
202
203 //Make sure not busy from last setting and we currently match the last setting
204 control = REG32(addr);
205
xiaohu.huang38262102022-05-06 22:21:48 +0800206 switch (freq_sel) {
207 case 0:
208 clk_sel = 1;
209 clk_div = 0;
210 printf("CLK_UTIL:dsp[%d]:fclk2p5:800MHz\n", id);
211 break;
212 case 1:
213 clk_sel = 1;
214 clk_div = 1;
215 printf("CLK_UTIL:dsp[%d]:fclk5:400MHz\n", id);
216 break;
217 case 2:
218 clk_sel = 5;
219 clk_div = 0;
220 printf("CLK_UTIL:dsp[%d]:fclk4:500MHz\n", id);
221 break;
222 case 3:
223 clk_sel = 2;
224 clk_div = 0;
225 printf("CLK_UTIL:dsp[%d]:fclk/3:667MHz\n", id);
226 break;
227 case 4:
228 clk_sel = 2;
229 clk_div = 1;
230 printf("CLK_UTIL:dsp[%d]:fclk3/2:333MHz\n", id);
231 break;
232 case 5:
233 clk_sel = 5;
234 clk_div = 1;
235 printf("CLK_UTIL:dsp[%d]:fclk4/2:250MHz\n", id);
236 break;
237 case 6:
238 clk_sel = 1;
239 clk_div = 3;
240 printf("CLK_UTIL:dsp[%d]:fclk5/2:200MHz\n", id);
241 break;
242 case 7:
243 clk_sel = 1;
244 clk_div = 7;
245 printf("CLK_UTIL:dsp[%d]:fclk5/4:100MHz\n", id);
246 break;
247 case 8:
248 clk_sel = 0;
249 clk_div = 0;
250 printf("CLK_UTIL:dsp[%d]:oscin:24MHz\n", id);
251 break;
252 case 10:
253 clk_sel = 0;
254 clk_div = 7;
255 printf("CLK_UTIL:dsp[%d]:oscin/8:3MHz\n", id);
256 break;
257 case 11:
258 clk_sel = 3;
259 clk_div = 0;
260 printf("CLK_UTIL:dsp[%d]:rtc pll:122.88MHz\n", id);
261 break;
262 case 12:
263 clk_sel = 7;
264 clk_div = 0;
265 printf("CLK_UTIL:dsp[%d]:rtc clk:24MHz\n", id);
266 break;
267 default:
268 clk_sel = 1;
269 clk_div = 7;
270 printf("CLK_UTIL:dsp[%d]:fclk5:400MHz\n", id);
271 break;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800272 }
273
274 //if sync_mux ==1, sel mux 0
275 if (control & (1 << 15))
xiaohu.huang38262102022-05-06 22:21:48 +0800276 control = (control & ~((1 << 15) | (0x3ff << 0) | (0x7 << 10))) | (1 << 13) |
277 (1 << 29) | (clk_div << 0) | (clk_sel << 10);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800278 else
xiaohu.huang38262102022-05-06 22:21:48 +0800279 control = (control & ~((1 << 15) | (0x3ff << 16) | (0x7 << 26))) | (1 << 13) |
280 (1 << 29) | (clk_div << 16) | (clk_sel << 26) | (1 << 15);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800281
282 REG32(addr) = control;
283}
284
285void disable_pll(int id)
286{
287 switch (id) {
xiaohu.huang38262102022-05-06 22:21:48 +0800288 case PLL_SYS:
289 REG32(ANACTRL_SYSPLL_CTRL0) = (1 << 29);
290 break;
291 case PLL_GP0:
292 REG32(ANACTRL_GP0PLL_CTRL0) = (1 << 29);
293 break;
294 case PLL_GP1:
295 REG32(ANACTRL_GP1PLL_CTRL0) = (1 << 29);
296 break;
297 case PLL_FIX:
298 REG32(ANACTRL_FIXPLL_CTRL0) = (1 << 29);
299 break;
300 case PLL_HIFI:
301 REG32(ANACTRL_HIFIPLL_CTRL0) = (1 << 29);
302 break;
303 case PLL_RTC:
304 REG32(ANACTRL_RTCPLL_CTRL0) = (1 << 29);
305 break;
306 case PLL_DDR:
307 REG32(AM_DDR_PLL_CNTL0) = (1 << 29);
308 break;
309 default:
310 printf("Error: PLL is not in the list\n");
311 break;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800312 }
313}
314
xiaohu.huang38262102022-05-06 22:21:48 +0800315int oscin_ctrl_reg;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800316void vCLK_resume(uint32_t st_f)
317{
Jianyi Shia3c107b2022-04-29 11:04:46 +0800318 int xIdx = 0;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800319
Jianyi Shia3c107b2022-04-29 11:04:46 +0800320 if (get_reason_flag() != VAD_WAKEUP) {
321 wakeup_dsp();
322 vTaskDelay(pdMS_TO_TICKS(90));
323 xIdx = WAKEUP_FROM_OTHER_KEY;
324 xTransferMessageAsync(AODSPA_CHANNEL, MBX_CMD_SUSPEND_WITH_DSP, &xIdx, 4);
325 }
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800326 /* switch osc_clk back*/
327 REG32(CLKCTRL_SYSOSCIN_CTRL) = 1;
xiaohu.huang38262102022-05-06 22:21:48 +0800328 REG32(CLKCTRL_OSCIN_CTRL) = oscin_ctrl_reg | (1 << 31);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800329 udelay(9000);
330
Jianyi Shid11ec702022-05-16 17:48:25 +0800331 clear_dsp_wakeup_trigger();
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800332 /* switching tick timer (using osc_clk) */
333 alt_timebase(0);
334
xiaohu.huang38262102022-05-06 22:21:48 +0800335 set_sys_div_clk(0, 0); // osc_clk
336 set_axi_div_clk(0, 0); // osc_clk
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800337
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800338
Jianyi Shia3c107b2022-04-29 11:04:46 +0800339 xIdx = WAIT_SWITCH_TO_24MHZ;
340 xTransferMessageAsync(AODSPA_CHANNEL, MBX_CMD_SUSPEND_WITH_DSP, &xIdx, 4);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800341
342 vTaskDelay(pdMS_TO_TICKS(90));
Jianyi Shia3c107b2022-04-29 11:04:46 +0800343 disable_pll(PLL_RTC);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800344
345 if (st_f) {
346 power_switch_to_wraper(PWR_ON);
347 /* open mem_pd of srama and sramb */
348 REG32(PWRCTRL_MEM_PD2) = 0x0;
349 }
350
351 // In a55 boot code
xiaohu.huang38262102022-05-06 22:21:48 +0800352 REG32(PWRCTRL_ACCESS_CTRL) = 0x0; // default access pwrctrl
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800353}
354
355void vCLK_suspend(uint32_t st_f)
356{
Jianyi Shia3c107b2022-04-29 11:04:46 +0800357 int xIdx = 0;
358
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800359 if (st_f) {
360 /* close mem_pd of srama and sramb */
361 REG32(PWRCTRL_MEM_PD2) = 0xfffffffc;
362 /* poweroff wrapper */
363 power_switch_to_wraper(PWR_OFF);
364 }
365
Jianyi Shia3c107b2022-04-29 11:04:46 +0800366 printf("[AOCPU]: enter vCLK_suspend.\n");
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800367 udelay(2000);
368 /* switch to RTC pll */
xiaohu.huang38262102022-05-06 22:21:48 +0800369 set_sys_div_clk(6, 3); // rtc pll (30.72MHz)
370 set_axi_div_clk(6, 0); // rtc pll (122.88MHz)
371 alt_timebase(1); // 1us/10us/100us/1ms/xtal3 = 1 us tick 30.72/30
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800372
373 udelay(2000);
374
Jianyi Shia3c107b2022-04-29 11:04:46 +0800375 xIdx = WAIT_SWITCH_TO_RTC_PLL;
376 xTransferMessageAsync(AODSPA_CHANNEL, MBX_CMD_SUSPEND_WITH_DSP, &xIdx, 4);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800377 vTaskDelay(pdMS_TO_TICKS(90));
378 /* power off osc_clk */
379 REG32(CLKCTRL_SYSOSCIN_CTRL) = 0;
380 oscin_ctrl_reg = REG32(CLKCTRL_OSCIN_CTRL);
381 REG32(CLKCTRL_OSCIN_CTRL) = 0;
382
383 printf("[AOCPU]: running at 30.72MHz, 24MHz osc clk power off.\n");
384 udelay(9000);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800385}