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