xref: /rk3399_ARM-atf/plat/rockchip/rk3399/drivers/m0/src/suspend.c (revision 4bd8c929b4bc6e1731c2892b38d4a8c43e8e89dc)
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 
m0_main(void)14af81a91fSChristoph Müllner __attribute__((noreturn)) void m0_main(void)
15977001aaSXing Zheng {
16977001aaSXing Zheng 	unsigned int status_value;
17977001aaSXing Zheng 
18ff4735cfSLin Huang 	/*
19ff4735cfSLin Huang 	 * PMU sometimes doesn't clear power mode bit as it's supposed to due
20ff4735cfSLin Huang 	 * to a hardware bug. Make the M0 clear it manually to be sure,
21ff4735cfSLin Huang 	 * otherwise interrupts some cases with concurrent wake interrupts
22ff4735cfSLin Huang 	 * we stay asleep forever.
23ff4735cfSLin 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);
28ff4735cfSLin Huang 			break;
29977001aaSXing Zheng 		}
30977001aaSXing Zheng 	}
31977001aaSXing Zheng 
32ff4735cfSLin Huang 	/*
33*1b491eeaSElyes Haouas 	 * FSM power sequence is .. -> ST_INPUT_CLAMP(step.17) -> .. ->
34ff4735cfSLin Huang 	 * ST_WAKEUP_RESET -> ST_EXT_PWRUP-> ST_RELEASE_CLAMP ->
35ff4735cfSLin Huang 	 * ST_24M_OSC_EN -> .. -> ST_WAKEUP_RESET_CLR(step.26) -> ..,
36ff4735cfSLin Huang 	 * INPUT_CLAMP and WAKEUP_RESET will hold the SOC not affect by
37ff4735cfSLin Huang 	 * power or other single glitch, but WAKEUP_RESET need work with 24MHz,
38ff4735cfSLin Huang 	 * so between RELEASE_CLAMP and 24M_OSC_EN, there have a chance
39ff4735cfSLin Huang 	 * that glitch will affect SOC, and mess up SOC status, so we
40ff4735cfSLin Huang 	 * addressmap_shared software clamp between ST_INPUT_CLAMP and
41ff4735cfSLin Huang 	 * ST_WAKEUP_RESET_CLR to avoid this happen.
42ff4735cfSLin Huang 	 */
43ff4735cfSLin Huang 	while (1) {
44ff4735cfSLin Huang 		status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
45ff4735cfSLin Huang 		if (status_value >= 17)  {
46ff4735cfSLin Huang 			mmio_setbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
47ff4735cfSLin Huang 			break;
48ff4735cfSLin Huang 		}
49ff4735cfSLin Huang 
50ff4735cfSLin Huang 	}
51ff4735cfSLin Huang 
52ff4735cfSLin Huang 	while (1) {
53ff4735cfSLin Huang 		status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
54ff4735cfSLin Huang 		if (status_value >= 26)  {
55ff4735cfSLin Huang 			mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
56ff4735cfSLin Huang 			break;
57ff4735cfSLin Huang 		}
58ff4735cfSLin Huang 	}
59ff4735cfSLin Huang 
60ff4735cfSLin Huang 	for (;;)
61ff4735cfSLin Huang 		__asm__ volatile ("wfi");
62977001aaSXing Zheng }
63