suspend.c 1.66 KB
Newer Older
1
2
3
/*
 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
 *
dp-arm's avatar
dp-arm committed
4
 * SPDX-License-Identifier: BSD-3-Clause
5
6
 */

7
#include <pmu_regs.h>
8
#include "rk3399_mcu.h"
9

10
11
12
13
#define M0_SCR			0xe000ed10  /* System Control Register (SCR) */

#define SCR_SLEEPDEEP_SHIFT	(1 << 2)

14
__attribute__((noreturn)) void m0_main(void)
15
16
17
{
	unsigned int status_value;

18
19
20
21
22
23
	/*
	 * PMU sometimes doesn't clear power mode bit as it's supposed to due
	 * to a hardware bug. Make the M0 clear it manually to be sure,
	 * otherwise interrupts some cases with concurrent wake interrupts
	 * we stay asleep forever.
	 */
24
25
26
27
	while (1) {
		status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
		if (status_value) {
			mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01);
28
			break;
29
		}
30
31
	}

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
	/*
	 * FSM power secquence is .. -> ST_INPUT_CLAMP(step.17) -> .. ->
	 * ST_WAKEUP_RESET -> ST_EXT_PWRUP-> ST_RELEASE_CLAMP ->
	 * ST_24M_OSC_EN -> .. -> ST_WAKEUP_RESET_CLR(step.26) -> ..,
	 * INPUT_CLAMP and WAKEUP_RESET will hold the SOC not affect by
	 * power or other single glitch, but WAKEUP_RESET need work with 24MHz,
	 * so between RELEASE_CLAMP and 24M_OSC_EN, there have a chance
	 * that glitch will affect SOC, and mess up SOC status, so we
	 * addressmap_shared software clamp between ST_INPUT_CLAMP and
	 * ST_WAKEUP_RESET_CLR to avoid this happen.
	 */
	while (1) {
		status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
		if (status_value >= 17)  {
			mmio_setbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
			break;
		}

	}

	while (1) {
		status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
		if (status_value >= 26)  {
			mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
			break;
		}
	}

	for (;;)
		__asm__ volatile ("wfi");
62
}