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