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