1 /*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <pmu_regs.h>
8 #include "rk3399_mcu.h"
9
10 #define M0_SCR 0xe000ed10 /* System Control Register (SCR) */
11
12 #define SCR_SLEEPDEEP_SHIFT (1 << 2)
13
m0_main(void)14 __attribute__((noreturn)) void m0_main(void)
15 {
16 unsigned int status_value;
17
18 /*
19 * PMU sometimes doesn't clear power mode bit as it's supposed to due
20 * to a hardware bug. Make the M0 clear it manually to be sure,
21 * otherwise interrupts some cases with concurrent wake interrupts
22 * we stay asleep forever.
23 */
24 while (1) {
25 status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
26 if (status_value) {
27 mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01);
28 break;
29 }
30 }
31
32 /*
33 * FSM power secquence is .. -> ST_INPUT_CLAMP(step.17) -> .. ->
34 * ST_WAKEUP_RESET -> ST_EXT_PWRUP-> ST_RELEASE_CLAMP ->
35 * ST_24M_OSC_EN -> .. -> ST_WAKEUP_RESET_CLR(step.26) -> ..,
36 * INPUT_CLAMP and WAKEUP_RESET will hold the SOC not affect by
37 * power or other single glitch, but WAKEUP_RESET need work with 24MHz,
38 * so between RELEASE_CLAMP and 24M_OSC_EN, there have a chance
39 * that glitch will affect SOC, and mess up SOC status, so we
40 * addressmap_shared software clamp between ST_INPUT_CLAMP and
41 * ST_WAKEUP_RESET_CLR to avoid this happen.
42 */
43 while (1) {
44 status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
45 if (status_value >= 17) {
46 mmio_setbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
47 break;
48 }
49
50 }
51
52 while (1) {
53 status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
54 if (status_value >= 26) {
55 mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
56 break;
57 }
58 }
59
60 for (;;)
61 __asm__ volatile ("wfi");
62 }
63