1 /* 2 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <arch_helpers.h> 10 #include <common/debug.h> 11 #include <errno.h> 12 #include <lib/mmio.h> 13 #include <lib/psci/psci.h> 14 15 #include "uniphier.h" 16 17 #define UNIPHIER_ROM_RSV0 0x0 18 19 #define UNIPHIER_SLFRSTSEL 0x10 20 #define UNIPHIER_SLFRSTSEL_MASK GENMASK(1, 0) 21 #define UNIPHIER_SLFRSTCTL 0x14 22 #define UNIPHIER_SLFRSTCTL_RST BIT(0) 23 24 #define MPIDR_AFFINITY_INVALID ((u_register_t)-1) 25 26 static uintptr_t uniphier_rom_rsv_base; 27 static uintptr_t uniphier_slfrst_base; 28 29 uintptr_t uniphier_sec_entrypoint; 30 31 void uniphier_warmboot_entrypoint(void); 32 void __dead2 uniphier_fake_pwr_down(void); 33 u_register_t uniphier_holding_pen_release; 34 static int uniphier_psci_scp_mode; 35 36 static int uniphier_psci_pwr_domain_on(u_register_t mpidr) 37 { 38 uniphier_holding_pen_release = mpidr; 39 flush_dcache_range((uint64_t)&uniphier_holding_pen_release, 40 sizeof(uniphier_holding_pen_release)); 41 42 mmio_write_64(uniphier_rom_rsv_base + UNIPHIER_ROM_RSV0, 43 (uint64_t)&uniphier_warmboot_entrypoint); 44 sev(); 45 46 return PSCI_E_SUCCESS; 47 } 48 49 static void uniphier_psci_pwr_domain_off(const psci_power_state_t *target_state) 50 { 51 uniphier_gic_cpuif_disable(); 52 } 53 54 static void uniphier_psci_pwr_domain_on_finish( 55 const psci_power_state_t *target_state) 56 { 57 uniphier_gic_pcpu_init(); 58 uniphier_gic_cpuif_enable(); 59 60 uniphier_cci_enable(); 61 } 62 63 static void __dead2 uniphier_psci_pwr_domain_pwr_down_wfi( 64 const psci_power_state_t *target_state) 65 { 66 /* 67 * The Boot ROM cannot distinguish warm and cold resets. 68 * Instead of the CPU reset, fake it. 69 */ 70 uniphier_holding_pen_release = MPIDR_AFFINITY_INVALID; 71 flush_dcache_range((uint64_t)&uniphier_holding_pen_release, 72 sizeof(uniphier_holding_pen_release)); 73 74 uniphier_fake_pwr_down(); 75 } 76 77 static void uniphier_self_system_reset(void) 78 { 79 mmio_clrbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTSEL, 80 UNIPHIER_SLFRSTSEL_MASK); 81 mmio_setbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTCTL, 82 UNIPHIER_SLFRSTCTL_RST); 83 } 84 85 static void __dead2 uniphier_psci_system_off(void) 86 { 87 if (uniphier_psci_scp_mode) { 88 uniphier_scp_system_off(); 89 } else { 90 NOTICE("SCP is disabled; can't shutdown the system.\n"); 91 NOTICE("Resetting the system instead.\n"); 92 uniphier_self_system_reset(); 93 } 94 95 wfi(); 96 ERROR("UniPhier System Off: operation not handled.\n"); 97 panic(); 98 } 99 100 static void __dead2 uniphier_psci_system_reset(void) 101 { 102 if (uniphier_psci_scp_mode) 103 uniphier_scp_system_reset(); 104 else 105 uniphier_self_system_reset(); 106 107 wfi(); 108 ERROR("UniPhier System Reset: operation not handled.\n"); 109 panic(); 110 } 111 112 static const struct plat_psci_ops uniphier_psci_ops = { 113 .pwr_domain_on = uniphier_psci_pwr_domain_on, 114 .pwr_domain_off = uniphier_psci_pwr_domain_off, 115 .pwr_domain_on_finish = uniphier_psci_pwr_domain_on_finish, 116 .pwr_domain_pwr_down = uniphier_psci_pwr_domain_pwr_down_wfi, 117 .system_off = uniphier_psci_system_off, 118 .system_reset = uniphier_psci_system_reset, 119 }; 120 121 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 122 const struct plat_psci_ops **psci_ops) 123 { 124 uniphier_sec_entrypoint = sec_entrypoint; 125 flush_dcache_range((uint64_t)&uniphier_sec_entrypoint, 126 sizeof(uniphier_sec_entrypoint)); 127 128 *psci_ops = &uniphier_psci_ops; 129 130 return 0; 131 } 132 133 struct uniphier_psci_ctrl_base { 134 uintptr_t rom_rsv_base; 135 uintptr_t slfrst_base; 136 }; 137 138 static const struct uniphier_psci_ctrl_base uniphier_psci_ctrl_base[] = { 139 [UNIPHIER_SOC_LD11] = { 140 .rom_rsv_base = 0x59801200, 141 .slfrst_base = 0x61843000, 142 }, 143 [UNIPHIER_SOC_LD20] = { 144 .rom_rsv_base = 0x59801200, 145 .slfrst_base = 0x61843000, 146 }, 147 [UNIPHIER_SOC_PXS3] = { 148 .rom_rsv_base = 0x59801200, 149 .slfrst_base = 0x61843000, 150 }, 151 }; 152 153 void uniphier_psci_init(unsigned int soc) 154 { 155 assert(soc < ARRAY_SIZE(uniphier_psci_ctrl_base)); 156 uniphier_rom_rsv_base = uniphier_psci_ctrl_base[soc].rom_rsv_base; 157 uniphier_slfrst_base = uniphier_psci_ctrl_base[soc].slfrst_base; 158 159 if (uniphier_get_boot_master(soc) == UNIPHIER_BOOT_MASTER_SCP) { 160 uniphier_psci_scp_mode = uniphier_scp_is_running(); 161 flush_dcache_range((uint64_t)&uniphier_psci_scp_mode, 162 sizeof(uniphier_psci_scp_mode)); 163 164 if (uniphier_psci_scp_mode) 165 uniphier_scp_open_com(); 166 } 167 } 168