xref: /rk3399_ARM-atf/plat/rockchip/rk3399/drivers/m0/src/suspend.c (revision ff4735cfdfde273866a7e079dedec27b1e11438e)
1977001aaSXing Zheng /*
2977001aaSXing Zheng  * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3977001aaSXing Zheng  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
5977001aaSXing Zheng  */
6977001aaSXing Zheng 
71830f790SXing Zheng #include <pmu_regs.h>
8977001aaSXing Zheng #include "rk3399_mcu.h"
9977001aaSXing Zheng 
10977001aaSXing Zheng #define M0_SCR			0xe000ed10  /* System Control Register (SCR) */
11977001aaSXing Zheng 
12977001aaSXing Zheng #define SCR_SLEEPDEEP_SHIFT	(1 << 2)
13977001aaSXing Zheng 
14*ff4735cfSLin Huang __attribute__((noreturn)) void main(void)
15977001aaSXing Zheng {
16977001aaSXing Zheng 	unsigned int status_value;
17977001aaSXing Zheng 
18*ff4735cfSLin Huang 	/*
19*ff4735cfSLin Huang 	 * PMU sometimes doesn't clear power mode bit as it's supposed to due
20*ff4735cfSLin Huang 	 * to a hardware bug. Make the M0 clear it manually to be sure,
21*ff4735cfSLin Huang 	 * otherwise interrupts some cases with concurrent wake interrupts
22*ff4735cfSLin Huang 	 * we stay asleep forever.
23*ff4735cfSLin Huang 	 */
24977001aaSXing Zheng 	while (1) {
25977001aaSXing Zheng 		status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
26977001aaSXing Zheng 		if (status_value) {
27977001aaSXing Zheng 			mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01);
28*ff4735cfSLin Huang 			break;
29977001aaSXing Zheng 		}
30977001aaSXing Zheng 	}
31977001aaSXing Zheng 
32*ff4735cfSLin Huang 	/*
33*ff4735cfSLin Huang 	 * FSM power secquence is .. -> ST_INPUT_CLAMP(step.17) -> .. ->
34*ff4735cfSLin Huang 	 * ST_WAKEUP_RESET -> ST_EXT_PWRUP-> ST_RELEASE_CLAMP ->
35*ff4735cfSLin Huang 	 * ST_24M_OSC_EN -> .. -> ST_WAKEUP_RESET_CLR(step.26) -> ..,
36*ff4735cfSLin Huang 	 * INPUT_CLAMP and WAKEUP_RESET will hold the SOC not affect by
37*ff4735cfSLin Huang 	 * power or other single glitch, but WAKEUP_RESET need work with 24MHz,
38*ff4735cfSLin Huang 	 * so between RELEASE_CLAMP and 24M_OSC_EN, there have a chance
39*ff4735cfSLin Huang 	 * that glitch will affect SOC, and mess up SOC status, so we
40*ff4735cfSLin Huang 	 * addressmap_shared software clamp between ST_INPUT_CLAMP and
41*ff4735cfSLin Huang 	 * ST_WAKEUP_RESET_CLR to avoid this happen.
42*ff4735cfSLin Huang 	 */
43*ff4735cfSLin Huang 	while (1) {
44*ff4735cfSLin Huang 		status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
45*ff4735cfSLin Huang 		if (status_value >= 17)  {
46*ff4735cfSLin Huang 			mmio_setbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
47*ff4735cfSLin Huang 			break;
48*ff4735cfSLin Huang 		}
49*ff4735cfSLin Huang 
50*ff4735cfSLin Huang 	}
51*ff4735cfSLin Huang 
52*ff4735cfSLin Huang 	while (1) {
53*ff4735cfSLin Huang 		status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
54*ff4735cfSLin Huang 		if (status_value >= 26)  {
55*ff4735cfSLin Huang 			mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
56*ff4735cfSLin Huang 			break;
57*ff4735cfSLin Huang 		}
58*ff4735cfSLin Huang 	}
59*ff4735cfSLin Huang 
60*ff4735cfSLin Huang 	for (;;)
61*ff4735cfSLin Huang 		__asm__ volatile ("wfi");
62977001aaSXing Zheng }
63