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 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 sequence 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