1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (C) 2018-2020 Marvell International Ltd. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu * https://spdx.org/licenses 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <common/debug.h> 9*91f16700Schasinglulu #ifdef USE_CCI 10*91f16700Schasinglulu #include <drivers/arm/cci.h> 11*91f16700Schasinglulu #endif 12*91f16700Schasinglulu #include <lib/psci/psci.h> 13*91f16700Schasinglulu #include <lib/mmio.h> 14*91f16700Schasinglulu #include <plat/common/platform.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #include <a3700_pm.h> 17*91f16700Schasinglulu #include <arch_helpers.h> 18*91f16700Schasinglulu #include <armada_common.h> 19*91f16700Schasinglulu #include <dram_win.h> 20*91f16700Schasinglulu #include <io_addr_dec.h> 21*91f16700Schasinglulu #include <mvebu.h> 22*91f16700Schasinglulu #include <mvebu_def.h> 23*91f16700Schasinglulu #include <marvell_plat_priv.h> 24*91f16700Schasinglulu #include <plat_marvell.h> 25*91f16700Schasinglulu 26*91f16700Schasinglulu /* Warm reset register */ 27*91f16700Schasinglulu #define MVEBU_WARM_RESET_REG (MVEBU_NB_REGS_BASE + 0x840) 28*91f16700Schasinglulu #define MVEBU_WARM_RESET_MAGIC 0x1D1E 29*91f16700Schasinglulu 30*91f16700Schasinglulu /* North Bridge GPIO1 SEL register */ 31*91f16700Schasinglulu #define MVEBU_NB_GPIO1_SEL_REG (MVEBU_NB_REGS_BASE + 0x830) 32*91f16700Schasinglulu #define MVEBU_NB_GPIO1_UART1_SEL BIT(19) 33*91f16700Schasinglulu #define MVEBU_NB_GPIO1_GPIO_25_26_EN BIT(17) 34*91f16700Schasinglulu #define MVEBU_NB_GPIO1_GPIO_19_EN BIT(14) 35*91f16700Schasinglulu #define MVEBU_NB_GPIO1_GPIO_18_EN BIT(13) 36*91f16700Schasinglulu 37*91f16700Schasinglulu /* CPU 1 reset register */ 38*91f16700Schasinglulu #define MVEBU_CPU_1_RESET_VECTOR (MVEBU_REGS_BASE + 0x14044) 39*91f16700Schasinglulu #define MVEBU_CPU_1_RESET_REG (MVEBU_REGS_BASE + 0xD00C) 40*91f16700Schasinglulu #define MVEBU_CPU_1_RESET_BIT 31 41*91f16700Schasinglulu 42*91f16700Schasinglulu /* IRQ register */ 43*91f16700Schasinglulu #define MVEBU_NB_IRQ_STATUS_1_REG (MVEBU_NB_SB_IRQ_REG_BASE) 44*91f16700Schasinglulu #define MVEBU_NB_IRQ_STATUS_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ 45*91f16700Schasinglulu 0x10) 46*91f16700Schasinglulu #define MVEBU_NB_IRQ_MASK_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ 47*91f16700Schasinglulu 0x18) 48*91f16700Schasinglulu #define MVEBU_SB_IRQ_STATUS_1_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ 49*91f16700Schasinglulu 0x40) 50*91f16700Schasinglulu #define MVEBU_SB_IRQ_STATUS_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ 51*91f16700Schasinglulu 0x50) 52*91f16700Schasinglulu #define MVEBU_NB_GPIO_IRQ_MASK_1_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ 53*91f16700Schasinglulu 0xC8) 54*91f16700Schasinglulu #define MVEBU_NB_GPIO_IRQ_MASK_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ 55*91f16700Schasinglulu 0xD8) 56*91f16700Schasinglulu #define MVEBU_SB_GPIO_IRQ_MASK_REG (MVEBU_NB_SB_IRQ_REG_BASE + \ 57*91f16700Schasinglulu 0xE8) 58*91f16700Schasinglulu #define MVEBU_NB_GPIO_IRQ_EN_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE) 59*91f16700Schasinglulu #define MVEBU_NB_GPIO_IRQ_EN_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \ 60*91f16700Schasinglulu 0x04) 61*91f16700Schasinglulu #define MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \ 62*91f16700Schasinglulu 0x10) 63*91f16700Schasinglulu #define MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \ 64*91f16700Schasinglulu 0x14) 65*91f16700Schasinglulu #define MVEBU_NB_GPIO_IRQ_WK_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \ 66*91f16700Schasinglulu 0x18) 67*91f16700Schasinglulu #define MVEBU_NB_GPIO_IRQ_WK_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \ 68*91f16700Schasinglulu 0x1C) 69*91f16700Schasinglulu #define MVEBU_SB_GPIO_IRQ_EN_REG (MVEBU_SB_GPIO_IRQ_REG_BASE) 70*91f16700Schasinglulu #define MVEBU_SB_GPIO_IRQ_STATUS_REG (MVEBU_SB_GPIO_IRQ_REG_BASE + \ 71*91f16700Schasinglulu 0x10) 72*91f16700Schasinglulu #define MVEBU_SB_GPIO_IRQ_WK_REG (MVEBU_SB_GPIO_IRQ_REG_BASE + \ 73*91f16700Schasinglulu 0x18) 74*91f16700Schasinglulu 75*91f16700Schasinglulu /* PMU registers */ 76*91f16700Schasinglulu #define MVEBU_PM_NB_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE) 77*91f16700Schasinglulu #define MVEBU_PM_PWR_DN_CNT_SEL BIT(28) 78*91f16700Schasinglulu #define MVEBU_PM_SB_PWR_DWN BIT(4) 79*91f16700Schasinglulu #define MVEBU_PM_INTERFACE_IDLE BIT(0) 80*91f16700Schasinglulu #define MVEBU_PM_NB_CPU_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x4) 81*91f16700Schasinglulu #define MVEBU_PM_L2_FLUSH_EN BIT(22) 82*91f16700Schasinglulu #define MVEBU_PM_NB_PWR_OPTION_REG (MVEBU_PMSU_REG_BASE + 0x8) 83*91f16700Schasinglulu #define MVEBU_PM_DDR_SR_EN BIT(29) 84*91f16700Schasinglulu #define MVEBU_PM_DDR_CLK_DIS_EN BIT(28) 85*91f16700Schasinglulu #define MVEBU_PM_WARM_RESET_EN BIT(27) 86*91f16700Schasinglulu #define MVEBU_PM_DDRPHY_PWRDWN_EN BIT(23) 87*91f16700Schasinglulu #define MVEBU_PM_DDRPHY_PAD_PWRDWN_EN BIT(22) 88*91f16700Schasinglulu #define MVEBU_PM_OSC_OFF_EN BIT(21) 89*91f16700Schasinglulu #define MVEBU_PM_TBG_OFF_EN BIT(20) 90*91f16700Schasinglulu #define MVEBU_PM_CPU_VDDV_OFF_EN BIT(19) 91*91f16700Schasinglulu #define MVEBU_PM_AVS_DISABLE_MODE BIT(14) 92*91f16700Schasinglulu #define MVEBU_PM_AVS_VDD2_MODE BIT(13) 93*91f16700Schasinglulu #define MVEBU_PM_AVS_HOLD_MODE BIT(12) 94*91f16700Schasinglulu #define MVEBU_PM_L2_SRAM_LKG_PD_EN BIT(8) 95*91f16700Schasinglulu #define MVEBU_PM_EIP_SRAM_LKG_PD_EN BIT(7) 96*91f16700Schasinglulu #define MVEBU_PM_DDRMC_SRAM_LKG_PD_EN BIT(6) 97*91f16700Schasinglulu #define MVEBU_PM_MCI_SRAM_LKG_PD_EN BIT(5) 98*91f16700Schasinglulu #define MVEBU_PM_MMC_SRAM_LKG_PD_EN BIT(4) 99*91f16700Schasinglulu #define MVEBU_PM_SATA_SRAM_LKG_PD_EN BIT(3) 100*91f16700Schasinglulu #define MVEBU_PM_DMA_SRAM_LKG_PD_EN BIT(2) 101*91f16700Schasinglulu #define MVEBU_PM_SEC_SRAM_LKG_PD_EN BIT(1) 102*91f16700Schasinglulu #define MVEBU_PM_CPU_SRAM_LKG_PD_EN BIT(0) 103*91f16700Schasinglulu #define MVEBU_PM_NB_SRAM_LKG_PD_EN (MVEBU_PM_L2_SRAM_LKG_PD_EN |\ 104*91f16700Schasinglulu MVEBU_PM_EIP_SRAM_LKG_PD_EN | MVEBU_PM_DDRMC_SRAM_LKG_PD_EN |\ 105*91f16700Schasinglulu MVEBU_PM_MCI_SRAM_LKG_PD_EN | MVEBU_PM_MMC_SRAM_LKG_PD_EN |\ 106*91f16700Schasinglulu MVEBU_PM_SATA_SRAM_LKG_PD_EN | MVEBU_PM_DMA_SRAM_LKG_PD_EN |\ 107*91f16700Schasinglulu MVEBU_PM_SEC_SRAM_LKG_PD_EN | MVEBU_PM_CPU_SRAM_LKG_PD_EN) 108*91f16700Schasinglulu #define MVEBU_PM_NB_PWR_DEBUG_REG (MVEBU_PMSU_REG_BASE + 0xC) 109*91f16700Schasinglulu #define MVEBU_PM_NB_FORCE_CLK_ON BIT(30) 110*91f16700Schasinglulu #define MVEBU_PM_IGNORE_CM3_SLEEP BIT(21) 111*91f16700Schasinglulu #define MVEBU_PM_IGNORE_CM3_DEEP BIT(20) 112*91f16700Schasinglulu #define MVEBU_PM_NB_WAKE_UP_EN_REG (MVEBU_PMSU_REG_BASE + 0x2C) 113*91f16700Schasinglulu #define MVEBU_PM_SB_WKP_NB_EN BIT(31) 114*91f16700Schasinglulu #define MVEBU_PM_NB_GPIO_WKP_EN BIT(27) 115*91f16700Schasinglulu #define MVEBU_PM_SOC_TIMER_WKP_EN BIT(26) 116*91f16700Schasinglulu #define MVEBU_PM_UART_WKP_EN BIT(25) 117*91f16700Schasinglulu #define MVEBU_PM_UART2_WKP_EN BIT(19) 118*91f16700Schasinglulu #define MVEBU_PM_CPU_TIMER_WKP_EN BIT(17) 119*91f16700Schasinglulu #define MVEBU_PM_NB_WKP_EN BIT(16) 120*91f16700Schasinglulu #define MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN BIT(13) 121*91f16700Schasinglulu #define MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN BIT(12) 122*91f16700Schasinglulu #define MVEBU_PM_CPU_0_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x34) 123*91f16700Schasinglulu #define MVEBU_PM_CPU_1_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x38) 124*91f16700Schasinglulu #define MVEBU_PM_CORE_SOC_PD BIT(2) 125*91f16700Schasinglulu #define MVEBU_PM_CORE_PROC_PD BIT(1) 126*91f16700Schasinglulu #define MVEBU_PM_CORE_PD BIT(0) 127*91f16700Schasinglulu #define MVEBU_PM_CORE_1_RETURN_ADDR_REG (MVEBU_PMSU_REG_BASE + 0x44) 128*91f16700Schasinglulu #define MVEBU_PM_CPU_VDD_OFF_INFO_1_REG (MVEBU_PMSU_REG_BASE + 0x48) 129*91f16700Schasinglulu #define MVEBU_PM_CPU_VDD_OFF_INFO_2_REG (MVEBU_PMSU_REG_BASE + 0x4C) 130*91f16700Schasinglulu #define MVEBU_PM_LOW_POWER_STATE BIT(0) 131*91f16700Schasinglulu #define MVEBU_PM_CPU_WAKE_UP_CONF_REG (MVEBU_PMSU_REG_BASE + 0x54) 132*91f16700Schasinglulu #define MVEBU_PM_CORE1_WAKEUP BIT(13) 133*91f16700Schasinglulu #define MVEBU_PM_CORE0_WAKEUP BIT(12) 134*91f16700Schasinglulu #define MVEBU_PM_WAIT_DDR_RDY_VALUE (0x15) 135*91f16700Schasinglulu #define MVEBU_PM_SB_CPU_PWR_CTRL_REG (MVEBU_SB_WAKEUP_REG_BASE) 136*91f16700Schasinglulu #define MVEBU_PM_SB_PM_START BIT(0) 137*91f16700Schasinglulu #define MVEBU_PM_SB_PWR_OPTION_REG (MVEBU_SB_WAKEUP_REG_BASE + 0x4) 138*91f16700Schasinglulu #define MVEBU_PM_SDIO_PHY_PDWN_EN BIT(17) 139*91f16700Schasinglulu #define MVEBU_PM_SB_VDDV_OFF_EN BIT(16) 140*91f16700Schasinglulu #define MVEBU_PM_EBM_SRAM_LKG_PD_EN BIT(11) 141*91f16700Schasinglulu #define MVEBU_PM_PCIE_SRAM_LKG_PD_EN BIT(10) 142*91f16700Schasinglulu #define MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN BIT(9) 143*91f16700Schasinglulu #define MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN BIT(8) 144*91f16700Schasinglulu #define MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN BIT(7) 145*91f16700Schasinglulu #define MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN BIT(6) 146*91f16700Schasinglulu #define MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN BIT(5) 147*91f16700Schasinglulu #define MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN BIT(4) 148*91f16700Schasinglulu #define MVEBU_PM_SDIO_SRAM_LKG_PD_EN BIT(3) 149*91f16700Schasinglulu #define MVEBU_PM_USB2_SRAM_LKG_PD_EN BIT(2) 150*91f16700Schasinglulu #define MVEBU_PM_USB3_H_SRAM_LKG_PD_EN BIT(1) 151*91f16700Schasinglulu #define MVEBU_PM_SB_SRAM_LKG_PD_EN (MVEBU_PM_EBM_SRAM_LKG_PD_EN |\ 152*91f16700Schasinglulu MVEBU_PM_PCIE_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN |\ 153*91f16700Schasinglulu MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN |\ 154*91f16700Schasinglulu MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN | MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN |\ 155*91f16700Schasinglulu MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN | MVEBU_PM_SDIO_SRAM_LKG_PD_EN |\ 156*91f16700Schasinglulu MVEBU_PM_USB2_SRAM_LKG_PD_EN | MVEBU_PM_USB3_H_SRAM_LKG_PD_EN) 157*91f16700Schasinglulu #define MVEBU_PM_SB_WK_EN_REG (MVEBU_SB_WAKEUP_REG_BASE + 0x10) 158*91f16700Schasinglulu #define MVEBU_PM_SB_GPIO_WKP_EN BIT(24) 159*91f16700Schasinglulu #define MVEBU_PM_SB_WKP_EN BIT(20) 160*91f16700Schasinglulu 161*91f16700Schasinglulu /* DRAM registers */ 162*91f16700Schasinglulu #define MVEBU_DRAM_STATS_CH0_REG (MVEBU_DRAM_REG_BASE + 0x4) 163*91f16700Schasinglulu #define MVEBU_DRAM_WCP_EMPTY BIT(19) 164*91f16700Schasinglulu #define MVEBU_DRAM_CMD_0_REG (MVEBU_DRAM_REG_BASE + 0x20) 165*91f16700Schasinglulu #define MVEBU_DRAM_CH0_CMD0 BIT(28) 166*91f16700Schasinglulu #define MVEBU_DRAM_CS_CMD0 BIT(24) 167*91f16700Schasinglulu #define MVEBU_DRAM_WCB_DRAIN_REQ BIT(1) 168*91f16700Schasinglulu #define MVEBU_DRAM_PWR_CTRL_REG (MVEBU_DRAM_REG_BASE + 0x54) 169*91f16700Schasinglulu #define MVEBU_DRAM_PHY_CLK_GATING_EN BIT(1) 170*91f16700Schasinglulu #define MVEBU_DRAM_PHY_AUTO_AC_OFF_EN BIT(0) 171*91f16700Schasinglulu 172*91f16700Schasinglulu /* AVS registers */ 173*91f16700Schasinglulu #define MVEBU_AVS_CTRL_2_REG (MVEBU_AVS_REG_BASE + 0x8) 174*91f16700Schasinglulu #define MVEBU_LOW_VDD_MODE_EN BIT(6) 175*91f16700Schasinglulu 176*91f16700Schasinglulu /* Clock registers */ 177*91f16700Schasinglulu #define MVEBU_NB_CLOCK_SEL_REG (MVEBU_NB_REGS_BASE + 0x10) 178*91f16700Schasinglulu #define MVEBU_A53_CPU_CLK_SEL BIT(15) 179*91f16700Schasinglulu 180*91f16700Schasinglulu /* North Bridge Step-Down Registers */ 181*91f16700Schasinglulu #define MVEBU_NB_STEP_DOWN_INT_EN_REG MVEBU_NB_STEP_DOWN_REG_BASE 182*91f16700Schasinglulu #define MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK BIT(8) 183*91f16700Schasinglulu 184*91f16700Schasinglulu #define MVEBU_NB_GPIO_18 18 185*91f16700Schasinglulu #define MVEBU_NB_GPIO_19 19 186*91f16700Schasinglulu #define MVEBU_NB_GPIO_25 25 187*91f16700Schasinglulu #define MVEBU_NB_GPIO_26 26 188*91f16700Schasinglulu 189*91f16700Schasinglulu typedef int (*wake_up_src_func)(union pm_wake_up_src_data *); 190*91f16700Schasinglulu 191*91f16700Schasinglulu struct wake_up_src_func_map { 192*91f16700Schasinglulu enum pm_wake_up_src_type type; 193*91f16700Schasinglulu wake_up_src_func func; 194*91f16700Schasinglulu }; 195*91f16700Schasinglulu 196*91f16700Schasinglulu void marvell_psci_arch_init(int die_index) 197*91f16700Schasinglulu { 198*91f16700Schasinglulu } 199*91f16700Schasinglulu 200*91f16700Schasinglulu static void a3700_pm_ack_irq(void) 201*91f16700Schasinglulu { 202*91f16700Schasinglulu uint32_t reg; 203*91f16700Schasinglulu 204*91f16700Schasinglulu reg = mmio_read_32(MVEBU_NB_IRQ_STATUS_1_REG); 205*91f16700Schasinglulu if (reg) 206*91f16700Schasinglulu mmio_write_32(MVEBU_NB_IRQ_STATUS_1_REG, reg); 207*91f16700Schasinglulu 208*91f16700Schasinglulu reg = mmio_read_32(MVEBU_NB_IRQ_STATUS_2_REG); 209*91f16700Schasinglulu if (reg) 210*91f16700Schasinglulu mmio_write_32(MVEBU_NB_IRQ_STATUS_2_REG, reg); 211*91f16700Schasinglulu 212*91f16700Schasinglulu reg = mmio_read_32(MVEBU_SB_IRQ_STATUS_1_REG); 213*91f16700Schasinglulu if (reg) 214*91f16700Schasinglulu mmio_write_32(MVEBU_SB_IRQ_STATUS_1_REG, reg); 215*91f16700Schasinglulu 216*91f16700Schasinglulu reg = mmio_read_32(MVEBU_SB_IRQ_STATUS_2_REG); 217*91f16700Schasinglulu if (reg) 218*91f16700Schasinglulu mmio_write_32(MVEBU_SB_IRQ_STATUS_2_REG, reg); 219*91f16700Schasinglulu 220*91f16700Schasinglulu reg = mmio_read_32(MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG); 221*91f16700Schasinglulu if (reg) 222*91f16700Schasinglulu mmio_write_32(MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG, reg); 223*91f16700Schasinglulu 224*91f16700Schasinglulu reg = mmio_read_32(MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG); 225*91f16700Schasinglulu if (reg) 226*91f16700Schasinglulu mmio_write_32(MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG, reg); 227*91f16700Schasinglulu 228*91f16700Schasinglulu reg = mmio_read_32(MVEBU_SB_GPIO_IRQ_STATUS_REG); 229*91f16700Schasinglulu if (reg) 230*91f16700Schasinglulu mmio_write_32(MVEBU_SB_GPIO_IRQ_STATUS_REG, reg); 231*91f16700Schasinglulu } 232*91f16700Schasinglulu 233*91f16700Schasinglulu /***************************************************************************** 234*91f16700Schasinglulu * A3700 handler called to check the validity of the power state 235*91f16700Schasinglulu * parameter. 236*91f16700Schasinglulu ***************************************************************************** 237*91f16700Schasinglulu */ 238*91f16700Schasinglulu int a3700_validate_power_state(unsigned int power_state, 239*91f16700Schasinglulu psci_power_state_t *req_state) 240*91f16700Schasinglulu { 241*91f16700Schasinglulu ERROR("%s needs to be implemented\n", __func__); 242*91f16700Schasinglulu panic(); 243*91f16700Schasinglulu } 244*91f16700Schasinglulu 245*91f16700Schasinglulu /***************************************************************************** 246*91f16700Schasinglulu * A3700 handler called when a CPU is about to enter standby. 247*91f16700Schasinglulu ***************************************************************************** 248*91f16700Schasinglulu */ 249*91f16700Schasinglulu void a3700_cpu_standby(plat_local_state_t cpu_state) 250*91f16700Schasinglulu { 251*91f16700Schasinglulu ERROR("%s needs to be implemented\n", __func__); 252*91f16700Schasinglulu panic(); 253*91f16700Schasinglulu } 254*91f16700Schasinglulu 255*91f16700Schasinglulu /***************************************************************************** 256*91f16700Schasinglulu * A3700 handler called when a power domain is about to be turned on. The 257*91f16700Schasinglulu * mpidr determines the CPU to be turned on. 258*91f16700Schasinglulu ***************************************************************************** 259*91f16700Schasinglulu */ 260*91f16700Schasinglulu int a3700_pwr_domain_on(u_register_t mpidr) 261*91f16700Schasinglulu { 262*91f16700Schasinglulu /* Set barrier */ 263*91f16700Schasinglulu dsbsy(); 264*91f16700Schasinglulu 265*91f16700Schasinglulu /* Set the cpu start address to BL1 entry point */ 266*91f16700Schasinglulu mmio_write_32(MVEBU_CPU_1_RESET_VECTOR, 267*91f16700Schasinglulu PLAT_MARVELL_CPU_ENTRY_ADDR >> 2); 268*91f16700Schasinglulu 269*91f16700Schasinglulu /* Get the cpu out of reset */ 270*91f16700Schasinglulu mmio_clrbits_32(MVEBU_CPU_1_RESET_REG, BIT(MVEBU_CPU_1_RESET_BIT)); 271*91f16700Schasinglulu mmio_setbits_32(MVEBU_CPU_1_RESET_REG, BIT(MVEBU_CPU_1_RESET_BIT)); 272*91f16700Schasinglulu 273*91f16700Schasinglulu return 0; 274*91f16700Schasinglulu } 275*91f16700Schasinglulu 276*91f16700Schasinglulu /***************************************************************************** 277*91f16700Schasinglulu * A3700 handler called to validate the entry point. 278*91f16700Schasinglulu ***************************************************************************** 279*91f16700Schasinglulu */ 280*91f16700Schasinglulu int a3700_validate_ns_entrypoint(uintptr_t entrypoint) 281*91f16700Schasinglulu { 282*91f16700Schasinglulu return PSCI_E_SUCCESS; 283*91f16700Schasinglulu } 284*91f16700Schasinglulu 285*91f16700Schasinglulu /***************************************************************************** 286*91f16700Schasinglulu * A3700 handler called when a power domain is about to be turned off. The 287*91f16700Schasinglulu * target_state encodes the power state that each level should transition to. 288*91f16700Schasinglulu ***************************************************************************** 289*91f16700Schasinglulu */ 290*91f16700Schasinglulu void a3700_pwr_domain_off(const psci_power_state_t *target_state) 291*91f16700Schasinglulu { 292*91f16700Schasinglulu /* Prevent interrupts from spuriously waking up this cpu */ 293*91f16700Schasinglulu plat_marvell_gic_cpuif_disable(); 294*91f16700Schasinglulu 295*91f16700Schasinglulu /* Core can not be powered down with pending IRQ, 296*91f16700Schasinglulu * acknowledge all the pending IRQ 297*91f16700Schasinglulu */ 298*91f16700Schasinglulu a3700_pm_ack_irq(); 299*91f16700Schasinglulu } 300*91f16700Schasinglulu 301*91f16700Schasinglulu static void a3700_set_gen_pwr_off_option(void) 302*91f16700Schasinglulu { 303*91f16700Schasinglulu /* Enable L2 flush -> processor state-machine option */ 304*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_CPU_PWR_CTRL_REG, MVEBU_PM_L2_FLUSH_EN); 305*91f16700Schasinglulu 306*91f16700Schasinglulu /* 307*91f16700Schasinglulu * North bridge cannot be VDD off (always ON). 308*91f16700Schasinglulu * The NB state machine support low power mode by its state machine. 309*91f16700Schasinglulu * This bit MUST be set for north bridge power down, e.g., 310*91f16700Schasinglulu * OSC input cutoff(NOT TEST), SRAM power down, PMIC, etc. 311*91f16700Schasinglulu * It is not related to CPU VDD OFF!! 312*91f16700Schasinglulu */ 313*91f16700Schasinglulu mmio_clrbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_CPU_VDDV_OFF_EN); 314*91f16700Schasinglulu 315*91f16700Schasinglulu /* 316*91f16700Schasinglulu * MUST: Switch CPU/AXI clock to OSC 317*91f16700Schasinglulu * NB state machine clock is always connected to OSC (slow clock). 318*91f16700Schasinglulu * But Core0/1/processor state machine's clock are connected to AXI 319*91f16700Schasinglulu * clock. Now, AXI clock takes the TBG as clock source. 320*91f16700Schasinglulu * If using AXI clock, Core0/1/processor state machine may much faster 321*91f16700Schasinglulu * than NB state machine. It will cause problem in this case if cores 322*91f16700Schasinglulu * are released before north bridge gets ready. 323*91f16700Schasinglulu */ 324*91f16700Schasinglulu mmio_clrbits_32(MVEBU_NB_CLOCK_SEL_REG, MVEBU_A53_CPU_CLK_SEL); 325*91f16700Schasinglulu 326*91f16700Schasinglulu /* 327*91f16700Schasinglulu * These register bits will trigger north bridge 328*91f16700Schasinglulu * power-down state machine regardless CM3 status. 329*91f16700Schasinglulu */ 330*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_DEBUG_REG, MVEBU_PM_IGNORE_CM3_SLEEP); 331*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_DEBUG_REG, MVEBU_PM_IGNORE_CM3_DEEP); 332*91f16700Schasinglulu 333*91f16700Schasinglulu /* 334*91f16700Schasinglulu * SRAM => controlled by north bridge state machine. 335*91f16700Schasinglulu * Core VDD OFF is not related to CPU SRAM power down. 336*91f16700Schasinglulu */ 337*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_NB_SRAM_LKG_PD_EN); 338*91f16700Schasinglulu 339*91f16700Schasinglulu /* 340*91f16700Schasinglulu * Idle AXI interface in order to get L2_WFI 341*91f16700Schasinglulu * L2 WFI is only asserted after CORE-0 and CORE-1 WFI asserted. 342*91f16700Schasinglulu * (only both core-0/1in WFI, L2 WFI will be issued by CORE.) 343*91f16700Schasinglulu * Once L2 WFI asserted, this bit is used for signalling assertion 344*91f16700Schasinglulu * to AXI IO masters. 345*91f16700Schasinglulu */ 346*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_INTERFACE_IDLE); 347*91f16700Schasinglulu 348*91f16700Schasinglulu /* Enable core0 and core1 VDD_OFF */ 349*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_PD); 350*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_PD); 351*91f16700Schasinglulu 352*91f16700Schasinglulu /* Enable North bridge power down - 353*91f16700Schasinglulu * Both Cores MUST enable this bit to power down north bridge! 354*91f16700Schasinglulu */ 355*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_SOC_PD); 356*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_SOC_PD); 357*91f16700Schasinglulu 358*91f16700Schasinglulu /* CA53 (processor domain) power down */ 359*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_PROC_PD); 360*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_PROC_PD); 361*91f16700Schasinglulu } 362*91f16700Schasinglulu 363*91f16700Schasinglulu static void a3700_en_ddr_self_refresh(void) 364*91f16700Schasinglulu { 365*91f16700Schasinglulu /* 366*91f16700Schasinglulu * Both count is 16 bits and configurable. By default, osc stb cnt 367*91f16700Schasinglulu * is 0xFFF for lower 12 bits. 368*91f16700Schasinglulu * Thus, powerdown count is smaller than osc count. 369*91f16700Schasinglulu * This count is used for exiting DDR SR mode on wakeup event. 370*91f16700Schasinglulu * The powerdown count also has impact on the following 371*91f16700Schasinglulu * state changes: idle -> count-down -> ... (power-down, vdd off, etc) 372*91f16700Schasinglulu * Here, make stable counter shorter 373*91f16700Schasinglulu * Use power down count value instead of osc_stb_cnt to speed up 374*91f16700Schasinglulu * DDR self refresh exit 375*91f16700Schasinglulu */ 376*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_PWR_DN_CNT_SEL); 377*91f16700Schasinglulu 378*91f16700Schasinglulu /* 379*91f16700Schasinglulu * Enable DDR SR mode => controlled by north bridge state machine 380*91f16700Schasinglulu * Therefore, we must powerdown north bridge to trigger the DDR SR 381*91f16700Schasinglulu * mode switching. 382*91f16700Schasinglulu */ 383*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDR_SR_EN); 384*91f16700Schasinglulu /* Disable DDR clock, otherwise DDR will not enter into SR mode. */ 385*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDR_CLK_DIS_EN); 386*91f16700Schasinglulu /* Power down DDR PHY (PAD) */ 387*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDRPHY_PWRDWN_EN); 388*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, 389*91f16700Schasinglulu MVEBU_PM_DDRPHY_PAD_PWRDWN_EN); 390*91f16700Schasinglulu 391*91f16700Schasinglulu /* Set wait time for DDR ready in ROM code */ 392*91f16700Schasinglulu mmio_write_32(MVEBU_PM_CPU_VDD_OFF_INFO_1_REG, 393*91f16700Schasinglulu MVEBU_PM_WAIT_DDR_RDY_VALUE); 394*91f16700Schasinglulu 395*91f16700Schasinglulu /* DDR flush write buffer - mandatory */ 396*91f16700Schasinglulu mmio_write_32(MVEBU_DRAM_CMD_0_REG, MVEBU_DRAM_CH0_CMD0 | 397*91f16700Schasinglulu MVEBU_DRAM_CS_CMD0 | MVEBU_DRAM_WCB_DRAIN_REQ); 398*91f16700Schasinglulu while ((mmio_read_32(MVEBU_DRAM_STATS_CH0_REG) & 399*91f16700Schasinglulu MVEBU_DRAM_WCP_EMPTY) != MVEBU_DRAM_WCP_EMPTY) 400*91f16700Schasinglulu ; 401*91f16700Schasinglulu 402*91f16700Schasinglulu /* Trigger PHY reset after ddr out of self refresh => 403*91f16700Schasinglulu * supply reset pulse for DDR phy after wake up 404*91f16700Schasinglulu */ 405*91f16700Schasinglulu mmio_setbits_32(MVEBU_DRAM_PWR_CTRL_REG, MVEBU_DRAM_PHY_CLK_GATING_EN | 406*91f16700Schasinglulu MVEBU_DRAM_PHY_AUTO_AC_OFF_EN); 407*91f16700Schasinglulu } 408*91f16700Schasinglulu 409*91f16700Schasinglulu static void a3700_pwr_dn_avs(void) 410*91f16700Schasinglulu { 411*91f16700Schasinglulu /* 412*91f16700Schasinglulu * AVS power down - controlled by north bridge statemachine 413*91f16700Schasinglulu * Enable AVS power down by clear the AVS disable bit. 414*91f16700Schasinglulu */ 415*91f16700Schasinglulu mmio_clrbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_DISABLE_MODE); 416*91f16700Schasinglulu /* 417*91f16700Schasinglulu * Should set BIT[12:13] to powerdown AVS. 418*91f16700Schasinglulu * 1. Enable AVS VDD2 mode 419*91f16700Schasinglulu * 2. After power down AVS, we must hold AVS output voltage. 420*91f16700Schasinglulu * 3. We can choose the lower VDD for AVS power down. 421*91f16700Schasinglulu */ 422*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_VDD2_MODE); 423*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_HOLD_MODE); 424*91f16700Schasinglulu 425*91f16700Schasinglulu /* Enable low VDD mode, AVS will set CPU to lowest core VDD 747mV */ 426*91f16700Schasinglulu mmio_setbits_32(MVEBU_AVS_CTRL_2_REG, MVEBU_LOW_VDD_MODE_EN); 427*91f16700Schasinglulu } 428*91f16700Schasinglulu 429*91f16700Schasinglulu static void a3700_pwr_dn_tbg(void) 430*91f16700Schasinglulu { 431*91f16700Schasinglulu /* Power down TBG */ 432*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_TBG_OFF_EN); 433*91f16700Schasinglulu } 434*91f16700Schasinglulu 435*91f16700Schasinglulu static void a3700_pwr_dn_sb(void) 436*91f16700Schasinglulu { 437*91f16700Schasinglulu /* Enable south bridge power down option */ 438*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_SB_PWR_DWN); 439*91f16700Schasinglulu 440*91f16700Schasinglulu /* Enable SDIO_PHY_PWRDWN */ 441*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SDIO_PHY_PDWN_EN); 442*91f16700Schasinglulu 443*91f16700Schasinglulu /* Enable SRAM LRM on SB */ 444*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SB_SRAM_LKG_PD_EN); 445*91f16700Schasinglulu 446*91f16700Schasinglulu /* Enable SB Power Off */ 447*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SB_VDDV_OFF_EN); 448*91f16700Schasinglulu 449*91f16700Schasinglulu /* Kick off South Bridge Power Off */ 450*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_SB_CPU_PWR_CTRL_REG, MVEBU_PM_SB_PM_START); 451*91f16700Schasinglulu } 452*91f16700Schasinglulu 453*91f16700Schasinglulu static void a3700_set_pwr_off_option(void) 454*91f16700Schasinglulu { 455*91f16700Schasinglulu /* Set general power off option */ 456*91f16700Schasinglulu a3700_set_gen_pwr_off_option(); 457*91f16700Schasinglulu 458*91f16700Schasinglulu /* Enable DDR self refresh in low power mode */ 459*91f16700Schasinglulu a3700_en_ddr_self_refresh(); 460*91f16700Schasinglulu 461*91f16700Schasinglulu /* Power down AVS */ 462*91f16700Schasinglulu a3700_pwr_dn_avs(); 463*91f16700Schasinglulu 464*91f16700Schasinglulu /* Power down TBG */ 465*91f16700Schasinglulu a3700_pwr_dn_tbg(); 466*91f16700Schasinglulu 467*91f16700Schasinglulu /* Power down south bridge, pay attention south bridge setting 468*91f16700Schasinglulu * should be done before 469*91f16700Schasinglulu */ 470*91f16700Schasinglulu a3700_pwr_dn_sb(); 471*91f16700Schasinglulu } 472*91f16700Schasinglulu 473*91f16700Schasinglulu static void a3700_set_wake_up_option(void) 474*91f16700Schasinglulu { 475*91f16700Schasinglulu /* 476*91f16700Schasinglulu * Enable the wakeup event for NB SOC => north-bridge 477*91f16700Schasinglulu * state-machine enablement on wake-up event 478*91f16700Schasinglulu */ 479*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_NB_WKP_EN); 480*91f16700Schasinglulu 481*91f16700Schasinglulu /* Enable both core0 and core1 wakeup on demand */ 482*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_CPU_WAKE_UP_CONF_REG, 483*91f16700Schasinglulu MVEBU_PM_CORE1_WAKEUP | MVEBU_PM_CORE0_WAKEUP); 484*91f16700Schasinglulu 485*91f16700Schasinglulu /* Enable warm reset in low power mode */ 486*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_WARM_RESET_EN); 487*91f16700Schasinglulu } 488*91f16700Schasinglulu 489*91f16700Schasinglulu static void a3700_pm_en_nb_gpio(uint32_t gpio) 490*91f16700Schasinglulu { 491*91f16700Schasinglulu /* For GPIO1 interrupt -- North bridge only */ 492*91f16700Schasinglulu if (gpio >= 32) { 493*91f16700Schasinglulu /* GPIO int mask */ 494*91f16700Schasinglulu mmio_clrbits_32(MVEBU_NB_GPIO_IRQ_MASK_2_REG, BIT(gpio - 32)); 495*91f16700Schasinglulu 496*91f16700Schasinglulu /* NB_CPU_WAKE-up ENABLE GPIO int */ 497*91f16700Schasinglulu mmio_setbits_32(MVEBU_NB_GPIO_IRQ_EN_HIGH_REG, BIT(gpio - 32)); 498*91f16700Schasinglulu } else { 499*91f16700Schasinglulu /* GPIO int mask */ 500*91f16700Schasinglulu mmio_clrbits_32(MVEBU_NB_GPIO_IRQ_MASK_1_REG, BIT(gpio)); 501*91f16700Schasinglulu 502*91f16700Schasinglulu /* NB_CPU_WAKE-up ENABLE GPIO int */ 503*91f16700Schasinglulu mmio_setbits_32(MVEBU_NB_GPIO_IRQ_EN_LOW_REG, BIT(gpio)); 504*91f16700Schasinglulu } 505*91f16700Schasinglulu 506*91f16700Schasinglulu mmio_setbits_32(MVEBU_NB_STEP_DOWN_INT_EN_REG, 507*91f16700Schasinglulu MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK); 508*91f16700Schasinglulu 509*91f16700Schasinglulu /* Enable using GPIO as wakeup event 510*91f16700Schasinglulu * (actually not only for north bridge) 511*91f16700Schasinglulu */ 512*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_NB_GPIO_WKP_EN | 513*91f16700Schasinglulu MVEBU_PM_NB_WKP_EN | MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN | 514*91f16700Schasinglulu MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN); 515*91f16700Schasinglulu } 516*91f16700Schasinglulu 517*91f16700Schasinglulu static void a3700_pm_en_sb_gpio(uint32_t gpio) 518*91f16700Schasinglulu { 519*91f16700Schasinglulu /* Enable using GPIO as wakeup event */ 520*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_SB_WKP_NB_EN | 521*91f16700Schasinglulu MVEBU_PM_NB_WKP_EN | MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN | 522*91f16700Schasinglulu MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN); 523*91f16700Schasinglulu 524*91f16700Schasinglulu /* SB GPIO Wake UP | South Bridge Wake Up Enable */ 525*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_SB_WK_EN_REG, MVEBU_PM_SB_GPIO_WKP_EN | 526*91f16700Schasinglulu MVEBU_PM_SB_GPIO_WKP_EN); 527*91f16700Schasinglulu 528*91f16700Schasinglulu /* GPIO int mask */ 529*91f16700Schasinglulu mmio_clrbits_32(MVEBU_SB_GPIO_IRQ_MASK_REG, BIT(gpio)); 530*91f16700Schasinglulu 531*91f16700Schasinglulu /* NB_CPU_WAKE-up ENABLE GPIO int */ 532*91f16700Schasinglulu mmio_setbits_32(MVEBU_SB_GPIO_IRQ_EN_REG, BIT(gpio)); 533*91f16700Schasinglulu } 534*91f16700Schasinglulu 535*91f16700Schasinglulu int a3700_pm_src_gpio(union pm_wake_up_src_data *src_data) 536*91f16700Schasinglulu { 537*91f16700Schasinglulu if (src_data->gpio_data.bank_num == 0) 538*91f16700Schasinglulu /* North Bridge GPIO */ 539*91f16700Schasinglulu a3700_pm_en_nb_gpio(src_data->gpio_data.gpio_num); 540*91f16700Schasinglulu else 541*91f16700Schasinglulu a3700_pm_en_sb_gpio(src_data->gpio_data.gpio_num); 542*91f16700Schasinglulu return 0; 543*91f16700Schasinglulu } 544*91f16700Schasinglulu 545*91f16700Schasinglulu int a3700_pm_src_uart1(union pm_wake_up_src_data *src_data) 546*91f16700Schasinglulu { 547*91f16700Schasinglulu /* Clear Uart1 select */ 548*91f16700Schasinglulu mmio_clrbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_UART1_SEL); 549*91f16700Schasinglulu /* set pin 19 gpio usage*/ 550*91f16700Schasinglulu mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_19_EN); 551*91f16700Schasinglulu /* Enable gpio wake-up*/ 552*91f16700Schasinglulu a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_19); 553*91f16700Schasinglulu /* set pin 18 gpio usage*/ 554*91f16700Schasinglulu mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_18_EN); 555*91f16700Schasinglulu /* Enable gpio wake-up*/ 556*91f16700Schasinglulu a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_18); 557*91f16700Schasinglulu 558*91f16700Schasinglulu return 0; 559*91f16700Schasinglulu } 560*91f16700Schasinglulu 561*91f16700Schasinglulu int a3700_pm_src_uart0(union pm_wake_up_src_data *src_data) 562*91f16700Schasinglulu { 563*91f16700Schasinglulu /* set pin 25/26 gpio usage*/ 564*91f16700Schasinglulu mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_25_26_EN); 565*91f16700Schasinglulu /* Enable gpio wake-up*/ 566*91f16700Schasinglulu a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_25); 567*91f16700Schasinglulu /* Enable gpio wake-up*/ 568*91f16700Schasinglulu a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_26); 569*91f16700Schasinglulu 570*91f16700Schasinglulu return 0; 571*91f16700Schasinglulu } 572*91f16700Schasinglulu 573*91f16700Schasinglulu struct wake_up_src_func_map src_func_table[WAKE_UP_SRC_MAX] = { 574*91f16700Schasinglulu {WAKE_UP_SRC_GPIO, a3700_pm_src_gpio}, 575*91f16700Schasinglulu {WAKE_UP_SRC_UART1, a3700_pm_src_uart1}, 576*91f16700Schasinglulu {WAKE_UP_SRC_UART0, a3700_pm_src_uart0}, 577*91f16700Schasinglulu /* FOLLOWING SRC NOT SUPPORTED YET */ 578*91f16700Schasinglulu {WAKE_UP_SRC_TIMER, NULL} 579*91f16700Schasinglulu }; 580*91f16700Schasinglulu 581*91f16700Schasinglulu static wake_up_src_func a3700_get_wake_up_src_func( 582*91f16700Schasinglulu enum pm_wake_up_src_type type) 583*91f16700Schasinglulu { 584*91f16700Schasinglulu uint32_t loop; 585*91f16700Schasinglulu 586*91f16700Schasinglulu for (loop = 0; loop < WAKE_UP_SRC_MAX; loop++) { 587*91f16700Schasinglulu if (src_func_table[loop].type == type) 588*91f16700Schasinglulu return src_func_table[loop].func; 589*91f16700Schasinglulu } 590*91f16700Schasinglulu return NULL; 591*91f16700Schasinglulu } 592*91f16700Schasinglulu 593*91f16700Schasinglulu #pragma weak mv_wake_up_src_config_get 594*91f16700Schasinglulu struct pm_wake_up_src_config *mv_wake_up_src_config_get(void) 595*91f16700Schasinglulu { 596*91f16700Schasinglulu static struct pm_wake_up_src_config wake_up_src_cfg = {}; 597*91f16700Schasinglulu return &wake_up_src_cfg; 598*91f16700Schasinglulu } 599*91f16700Schasinglulu 600*91f16700Schasinglulu static void a3700_set_wake_up_source(void) 601*91f16700Schasinglulu { 602*91f16700Schasinglulu struct pm_wake_up_src_config *wake_up_src; 603*91f16700Schasinglulu uint32_t loop; 604*91f16700Schasinglulu wake_up_src_func src_func = NULL; 605*91f16700Schasinglulu 606*91f16700Schasinglulu wake_up_src = mv_wake_up_src_config_get(); 607*91f16700Schasinglulu for (loop = 0; loop < wake_up_src->wake_up_src_num; loop++) { 608*91f16700Schasinglulu src_func = a3700_get_wake_up_src_func( 609*91f16700Schasinglulu wake_up_src->wake_up_src[loop].wake_up_src_type); 610*91f16700Schasinglulu if (src_func) 611*91f16700Schasinglulu src_func( 612*91f16700Schasinglulu &(wake_up_src->wake_up_src[loop].wake_up_data)); 613*91f16700Schasinglulu } 614*91f16700Schasinglulu } 615*91f16700Schasinglulu 616*91f16700Schasinglulu static void a3700_pm_save_lp_flag(void) 617*91f16700Schasinglulu { 618*91f16700Schasinglulu /* Save the flag for enter the low power mode */ 619*91f16700Schasinglulu mmio_setbits_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG, 620*91f16700Schasinglulu MVEBU_PM_LOW_POWER_STATE); 621*91f16700Schasinglulu } 622*91f16700Schasinglulu 623*91f16700Schasinglulu static void a3700_pm_clear_lp_flag(void) 624*91f16700Schasinglulu { 625*91f16700Schasinglulu /* Clear the flag for enter the low power mode */ 626*91f16700Schasinglulu mmio_clrbits_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG, 627*91f16700Schasinglulu MVEBU_PM_LOW_POWER_STATE); 628*91f16700Schasinglulu } 629*91f16700Schasinglulu 630*91f16700Schasinglulu static uint32_t a3700_pm_get_lp_flag(void) 631*91f16700Schasinglulu { 632*91f16700Schasinglulu /* Get the flag for enter the low power mode */ 633*91f16700Schasinglulu return mmio_read_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG) & 634*91f16700Schasinglulu MVEBU_PM_LOW_POWER_STATE; 635*91f16700Schasinglulu } 636*91f16700Schasinglulu 637*91f16700Schasinglulu /***************************************************************************** 638*91f16700Schasinglulu * A3700 handler called when a power domain is about to be suspended. The 639*91f16700Schasinglulu * target_state encodes the power state that each level should transition to. 640*91f16700Schasinglulu ***************************************************************************** 641*91f16700Schasinglulu */ 642*91f16700Schasinglulu void a3700_pwr_domain_suspend(const psci_power_state_t *target_state) 643*91f16700Schasinglulu { 644*91f16700Schasinglulu /* Prevent interrupts from spuriously waking up this cpu */ 645*91f16700Schasinglulu plat_marvell_gic_cpuif_disable(); 646*91f16700Schasinglulu 647*91f16700Schasinglulu /* Save IRQ states */ 648*91f16700Schasinglulu plat_marvell_gic_irq_save(); 649*91f16700Schasinglulu 650*91f16700Schasinglulu /* Set wake up options */ 651*91f16700Schasinglulu a3700_set_wake_up_option(); 652*91f16700Schasinglulu 653*91f16700Schasinglulu /* Set wake up sources */ 654*91f16700Schasinglulu a3700_set_wake_up_source(); 655*91f16700Schasinglulu 656*91f16700Schasinglulu /* SoC can not be powered down with pending IRQ, 657*91f16700Schasinglulu * acknowledge all the pending IRQ 658*91f16700Schasinglulu */ 659*91f16700Schasinglulu a3700_pm_ack_irq(); 660*91f16700Schasinglulu 661*91f16700Schasinglulu /* Set power off options */ 662*91f16700Schasinglulu a3700_set_pwr_off_option(); 663*91f16700Schasinglulu 664*91f16700Schasinglulu /* Save the flag for enter the low power mode */ 665*91f16700Schasinglulu a3700_pm_save_lp_flag(); 666*91f16700Schasinglulu 667*91f16700Schasinglulu isb(); 668*91f16700Schasinglulu } 669*91f16700Schasinglulu 670*91f16700Schasinglulu /***************************************************************************** 671*91f16700Schasinglulu * A3700 handler called when a power domain has just been powered on after 672*91f16700Schasinglulu * being turned off earlier. The target_state encodes the low power state that 673*91f16700Schasinglulu * each level has woken up from. 674*91f16700Schasinglulu ***************************************************************************** 675*91f16700Schasinglulu */ 676*91f16700Schasinglulu void a3700_pwr_domain_on_finish(const psci_power_state_t *target_state) 677*91f16700Schasinglulu { 678*91f16700Schasinglulu /* arch specific configuration */ 679*91f16700Schasinglulu marvell_psci_arch_init(0); 680*91f16700Schasinglulu 681*91f16700Schasinglulu /* Per-CPU interrupt initialization */ 682*91f16700Schasinglulu plat_marvell_gic_pcpu_init(); 683*91f16700Schasinglulu plat_marvell_gic_cpuif_enable(); 684*91f16700Schasinglulu 685*91f16700Schasinglulu /* Restore the per-cpu IRQ state */ 686*91f16700Schasinglulu if (a3700_pm_get_lp_flag()) 687*91f16700Schasinglulu plat_marvell_gic_irq_pcpu_restore(); 688*91f16700Schasinglulu } 689*91f16700Schasinglulu 690*91f16700Schasinglulu /***************************************************************************** 691*91f16700Schasinglulu * A3700 handler called when a power domain has just been powered on after 692*91f16700Schasinglulu * having been suspended earlier. The target_state encodes the low power state 693*91f16700Schasinglulu * that each level has woken up from. 694*91f16700Schasinglulu * TODO: At the moment we reuse the on finisher and reinitialize the secure 695*91f16700Schasinglulu * context. Need to implement a separate suspend finisher. 696*91f16700Schasinglulu ***************************************************************************** 697*91f16700Schasinglulu */ 698*91f16700Schasinglulu void a3700_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 699*91f16700Schasinglulu { 700*91f16700Schasinglulu struct dec_win_config *io_dec_map; 701*91f16700Schasinglulu uint32_t dec_win_num; 702*91f16700Schasinglulu struct dram_win_map dram_wins_map; 703*91f16700Schasinglulu 704*91f16700Schasinglulu /* arch specific configuration */ 705*91f16700Schasinglulu marvell_psci_arch_init(0); 706*91f16700Schasinglulu 707*91f16700Schasinglulu /* Interrupt initialization */ 708*91f16700Schasinglulu plat_marvell_gic_init(); 709*91f16700Schasinglulu 710*91f16700Schasinglulu /* Restore IRQ states */ 711*91f16700Schasinglulu plat_marvell_gic_irq_restore(); 712*91f16700Schasinglulu 713*91f16700Schasinglulu /* 714*91f16700Schasinglulu * Initialize CCI for this cluster after resume from suspend state. 715*91f16700Schasinglulu * No need for locks as no other CPU is active. 716*91f16700Schasinglulu */ 717*91f16700Schasinglulu plat_marvell_interconnect_init(); 718*91f16700Schasinglulu /* 719*91f16700Schasinglulu * Enable CCI coherency for the primary CPU's cluster. 720*91f16700Schasinglulu * Platform specific PSCI code will enable coherency for other 721*91f16700Schasinglulu * clusters. 722*91f16700Schasinglulu */ 723*91f16700Schasinglulu plat_marvell_interconnect_enter_coherency(); 724*91f16700Schasinglulu 725*91f16700Schasinglulu /* CPU address decoder windows initialization. */ 726*91f16700Schasinglulu cpu_wins_init(); 727*91f16700Schasinglulu 728*91f16700Schasinglulu /* fetch CPU-DRAM window mapping information by reading 729*91f16700Schasinglulu * CPU-DRAM decode windows (only the enabled ones) 730*91f16700Schasinglulu */ 731*91f16700Schasinglulu dram_win_map_build(&dram_wins_map); 732*91f16700Schasinglulu 733*91f16700Schasinglulu /* Get IO address decoder windows */ 734*91f16700Schasinglulu if (marvell_get_io_dec_win_conf(&io_dec_map, &dec_win_num)) { 735*91f16700Schasinglulu printf("No IO address decoder windows configurations found!\n"); 736*91f16700Schasinglulu return; 737*91f16700Schasinglulu } 738*91f16700Schasinglulu 739*91f16700Schasinglulu /* IO address decoder init */ 740*91f16700Schasinglulu if (init_io_addr_dec(&dram_wins_map, io_dec_map, dec_win_num)) { 741*91f16700Schasinglulu printf("IO address decoder windows initialization failed!\n"); 742*91f16700Schasinglulu return; 743*91f16700Schasinglulu } 744*91f16700Schasinglulu 745*91f16700Schasinglulu /* Clear low power mode flag */ 746*91f16700Schasinglulu a3700_pm_clear_lp_flag(); 747*91f16700Schasinglulu } 748*91f16700Schasinglulu 749*91f16700Schasinglulu /***************************************************************************** 750*91f16700Schasinglulu * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND 751*91f16700Schasinglulu * call to get the `power_state` parameter. This allows the platform to encode 752*91f16700Schasinglulu * the appropriate State-ID field within the `power_state` parameter which can 753*91f16700Schasinglulu * be utilized in `pwr_domain_suspend()` to suspend to system affinity level. 754*91f16700Schasinglulu ***************************************************************************** 755*91f16700Schasinglulu */ 756*91f16700Schasinglulu void a3700_get_sys_suspend_power_state(psci_power_state_t *req_state) 757*91f16700Schasinglulu { 758*91f16700Schasinglulu /* lower affinities use PLAT_MAX_OFF_STATE */ 759*91f16700Schasinglulu for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) 760*91f16700Schasinglulu req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 761*91f16700Schasinglulu } 762*91f16700Schasinglulu 763*91f16700Schasinglulu /***************************************************************************** 764*91f16700Schasinglulu * A3700 handlers to shutdown/reboot the system 765*91f16700Schasinglulu ***************************************************************************** 766*91f16700Schasinglulu */ 767*91f16700Schasinglulu static void __dead2 a3700_system_off(void) 768*91f16700Schasinglulu { 769*91f16700Schasinglulu ERROR("%s needs to be implemented\n", __func__); 770*91f16700Schasinglulu panic(); 771*91f16700Schasinglulu } 772*91f16700Schasinglulu 773*91f16700Schasinglulu #pragma weak cm3_system_reset 774*91f16700Schasinglulu void cm3_system_reset(void) 775*91f16700Schasinglulu { 776*91f16700Schasinglulu } 777*91f16700Schasinglulu 778*91f16700Schasinglulu /***************************************************************************** 779*91f16700Schasinglulu * A3700 handlers to reset the system 780*91f16700Schasinglulu ***************************************************************************** 781*91f16700Schasinglulu */ 782*91f16700Schasinglulu static void __dead2 a3700_system_reset(void) 783*91f16700Schasinglulu { 784*91f16700Schasinglulu /* Clean the mailbox magic number to let it as act like cold boot */ 785*91f16700Schasinglulu mmio_write_32(PLAT_MARVELL_MAILBOX_BASE, 0x0); 786*91f16700Schasinglulu 787*91f16700Schasinglulu dsbsy(); 788*91f16700Schasinglulu 789*91f16700Schasinglulu /* Flush data cache if the mail box shared RAM is cached */ 790*91f16700Schasinglulu #if PLAT_MARVELL_SHARED_RAM_CACHED 791*91f16700Schasinglulu flush_dcache_range((uintptr_t)PLAT_MARVELL_MAILBOX_BASE, 792*91f16700Schasinglulu 2 * sizeof(uint64_t)); 793*91f16700Schasinglulu #endif 794*91f16700Schasinglulu 795*91f16700Schasinglulu /* Use Cortex-M3 secure coprocessor for system reset */ 796*91f16700Schasinglulu cm3_system_reset(); 797*91f16700Schasinglulu 798*91f16700Schasinglulu /* Trigger the warm reset */ 799*91f16700Schasinglulu mmio_write_32(MVEBU_WARM_RESET_REG, MVEBU_WARM_RESET_MAGIC); 800*91f16700Schasinglulu 801*91f16700Schasinglulu /* Shouldn't get to this point */ 802*91f16700Schasinglulu panic(); 803*91f16700Schasinglulu } 804*91f16700Schasinglulu 805*91f16700Schasinglulu /***************************************************************************** 806*91f16700Schasinglulu * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard 807*91f16700Schasinglulu * platform layer will take care of registering the handlers with PSCI. 808*91f16700Schasinglulu ***************************************************************************** 809*91f16700Schasinglulu */ 810*91f16700Schasinglulu const plat_psci_ops_t plat_arm_psci_pm_ops = { 811*91f16700Schasinglulu .cpu_standby = a3700_cpu_standby, 812*91f16700Schasinglulu .pwr_domain_on = a3700_pwr_domain_on, 813*91f16700Schasinglulu .pwr_domain_off = a3700_pwr_domain_off, 814*91f16700Schasinglulu .pwr_domain_suspend = a3700_pwr_domain_suspend, 815*91f16700Schasinglulu .pwr_domain_on_finish = a3700_pwr_domain_on_finish, 816*91f16700Schasinglulu .pwr_domain_suspend_finish = a3700_pwr_domain_suspend_finish, 817*91f16700Schasinglulu .get_sys_suspend_power_state = a3700_get_sys_suspend_power_state, 818*91f16700Schasinglulu .system_off = a3700_system_off, 819*91f16700Schasinglulu .system_reset = a3700_system_reset, 820*91f16700Schasinglulu .validate_power_state = a3700_validate_power_state, 821*91f16700Schasinglulu .validate_ns_entrypoint = a3700_validate_ns_entrypoint 822*91f16700Schasinglulu }; 823