blob: c2638302cb29a8a583a4dd1159b831f69a9225bb [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
317int oscin_ctrl_reg;
318void vCLK_resume(uint32_t st_f)
319{
320 int xIdx = 0;
321
322 if ((!st_f) && (get_reason_flag() != VAD_WAKEUP)) {
323 wakeup_dsp();
324 vTaskDelay(pdMS_TO_TICKS(90));
325 xIdx = WAKEUP_FROM_OTHER_KEY;
326 xTransferMessageAsync(AODSPA_CHANNEL, MBX_CMD_SUSPEND_WITH_DSP, &xIdx, 4);
327 clear_dsp_wakeup_trigger();
328 }
329
330 if (st_f) {
331 /* switch osc_clk back*/
332 REG32(CLKCTRL_SYSOSCIN_CTRL) = 1;
333 REG32(CLKCTRL_OSCIN_CTRL) = oscin_ctrl_reg | (1 << 31);
334 udelay(2000);
335 /* switching tick timer (using osc_clk) */
336 alt_timebase(0);
337
338 set_sys_div_clk(0, 0); // osc_clk
339 set_axi_div_clk(0, 0); // osc_clk
340 vUartChangeBaudrate_resume(921600);
341 udelay(1000);
342 disable_pll(PLL_RTC);
343 power_switch_to_wraper(PWR_ON);
344 /* open mem_pd of srama and sramb */
345 REG32(PWRCTRL_MEM_PD2) = 0x0;
346 } else {
347
348 xIdx = WAIT_SWITCH_TO_24MHZ;
349 xTransferMessageAsync(AODSPA_CHANNEL, MBX_CMD_SUSPEND_WITH_DSP, &xIdx, 4);
350 vTaskDelay(pdMS_TO_TICKS(90));
351 }
352
353 // In a55 boot code
354 REG32(PWRCTRL_ACCESS_CTRL) = 0x0; // default access pwrctrl
355}
356
357void vCLK_suspend(uint32_t st_f)
358{
359 int xIdx = 0;
360
361 printf("[AOCPU]: enter vCLK suspend.\n");
362
363 if (st_f) {
364 /* close mem_pd of srama and sramb */
365 REG32(PWRCTRL_MEM_PD2) = 0xfffffffc;
366 /* poweroff wrapper */
367 power_switch_to_wraper(PWR_OFF);
368 udelay(2000);
369 /* switch to RTC pll */
370 set_sys_div_clk(6, 10); // rtc pll (11.171MHz)
371 set_axi_div_clk(6, 0); // rtc pll (122.88MHz)
372 alt_timebase(1); // 1us/10us/100us/1ms/xtal3 = 1 us tick 11.171/11
373
374 udelay(2000);
375 vUartChangeBaudrate_suspend(11171000, 921600);
376 udelay(1000);
377
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 printf("[AOCPU]: running at 11.171MHz, 24MHz osc clk power off.\n");
383
384 } else {
385 xIdx = WAIT_SWITCH_TO_RTC_PLL;
386 xTransferMessageAsync(AODSPA_CHANNEL, MBX_CMD_SUSPEND_WITH_DSP, &xIdx, 4);
387 vTaskDelay(pdMS_TO_TICKS(90));
388 printf("[AOCPU]: running at 24MHz, 24MHz osc clk power off.\n");
389 }
390}