1*d8e919c7SMasahiro Yamada /* 2*d8e919c7SMasahiro Yamada * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*d8e919c7SMasahiro Yamada * 4*d8e919c7SMasahiro Yamada * SPDX-License-Identifier: BSD-3-Clause 5*d8e919c7SMasahiro Yamada */ 6*d8e919c7SMasahiro Yamada 7*d8e919c7SMasahiro Yamada #include <arch_helpers.h> 8*d8e919c7SMasahiro Yamada #include <debug.h> 9*d8e919c7SMasahiro Yamada #include <mmio.h> 10*d8e919c7SMasahiro Yamada #include <psci.h> 11*d8e919c7SMasahiro Yamada 12*d8e919c7SMasahiro Yamada #include "uniphier.h" 13*d8e919c7SMasahiro Yamada 14*d8e919c7SMasahiro Yamada #define UNIPHIER_ROM_RSV0 0x59801200 15*d8e919c7SMasahiro Yamada 16*d8e919c7SMasahiro Yamada #define UNIPHIER_SLFRSTSEL 0x61843010 17*d8e919c7SMasahiro Yamada #define UNIPHIER_SLFRSTSEL_MASK (0x3 << 0) 18*d8e919c7SMasahiro Yamada #define UNIPHIER_SLFRSTCTL 0x61843014 19*d8e919c7SMasahiro Yamada #define UNIPHIER_SLFRSTCTL_RST (1 << 0) 20*d8e919c7SMasahiro Yamada 21*d8e919c7SMasahiro Yamada #define MPIDR_AFFINITY_INVALID ((u_register_t)-1) 22*d8e919c7SMasahiro Yamada 23*d8e919c7SMasahiro Yamada uintptr_t uniphier_sec_entrypoint; 24*d8e919c7SMasahiro Yamada 25*d8e919c7SMasahiro Yamada void uniphier_warmboot_entrypoint(void); 26*d8e919c7SMasahiro Yamada void __dead2 uniphier_fake_pwr_down(void); 27*d8e919c7SMasahiro Yamada u_register_t uniphier_holding_pen_release; 28*d8e919c7SMasahiro Yamada static int uniphier_psci_scp_mode; 29*d8e919c7SMasahiro Yamada 30*d8e919c7SMasahiro Yamada static int uniphier_psci_pwr_domain_on(u_register_t mpidr) 31*d8e919c7SMasahiro Yamada { 32*d8e919c7SMasahiro Yamada uniphier_holding_pen_release = mpidr; 33*d8e919c7SMasahiro Yamada flush_dcache_range((uint64_t)&uniphier_holding_pen_release, 34*d8e919c7SMasahiro Yamada sizeof(uniphier_holding_pen_release)); 35*d8e919c7SMasahiro Yamada 36*d8e919c7SMasahiro Yamada mmio_write_64(UNIPHIER_ROM_RSV0, 37*d8e919c7SMasahiro Yamada (uint64_t)&uniphier_warmboot_entrypoint); 38*d8e919c7SMasahiro Yamada sev(); 39*d8e919c7SMasahiro Yamada 40*d8e919c7SMasahiro Yamada return PSCI_E_SUCCESS; 41*d8e919c7SMasahiro Yamada } 42*d8e919c7SMasahiro Yamada 43*d8e919c7SMasahiro Yamada static void uniphier_psci_pwr_domain_off(const psci_power_state_t *target_state) 44*d8e919c7SMasahiro Yamada { 45*d8e919c7SMasahiro Yamada uniphier_gic_cpuif_disable(); 46*d8e919c7SMasahiro Yamada } 47*d8e919c7SMasahiro Yamada 48*d8e919c7SMasahiro Yamada static void uniphier_psci_pwr_domain_on_finish( 49*d8e919c7SMasahiro Yamada const psci_power_state_t *target_state) 50*d8e919c7SMasahiro Yamada { 51*d8e919c7SMasahiro Yamada uniphier_gic_pcpu_init(); 52*d8e919c7SMasahiro Yamada uniphier_gic_cpuif_enable(); 53*d8e919c7SMasahiro Yamada 54*d8e919c7SMasahiro Yamada uniphier_cci_enable(); 55*d8e919c7SMasahiro Yamada } 56*d8e919c7SMasahiro Yamada 57*d8e919c7SMasahiro Yamada static void __dead2 uniphier_psci_pwr_domain_pwr_down_wfi( 58*d8e919c7SMasahiro Yamada const psci_power_state_t *target_state) 59*d8e919c7SMasahiro Yamada { 60*d8e919c7SMasahiro Yamada /* 61*d8e919c7SMasahiro Yamada * The Boot ROM cannot distinguish warn and cold resets. 62*d8e919c7SMasahiro Yamada * Instead of the CPU reset, fake it. 63*d8e919c7SMasahiro Yamada */ 64*d8e919c7SMasahiro Yamada uniphier_holding_pen_release = MPIDR_AFFINITY_INVALID; 65*d8e919c7SMasahiro Yamada flush_dcache_range((uint64_t)&uniphier_holding_pen_release, 66*d8e919c7SMasahiro Yamada sizeof(uniphier_holding_pen_release)); 67*d8e919c7SMasahiro Yamada 68*d8e919c7SMasahiro Yamada uniphier_fake_pwr_down(); 69*d8e919c7SMasahiro Yamada } 70*d8e919c7SMasahiro Yamada 71*d8e919c7SMasahiro Yamada static void uniphier_self_system_reset(void) 72*d8e919c7SMasahiro Yamada { 73*d8e919c7SMasahiro Yamada mmio_clrbits_32(UNIPHIER_SLFRSTSEL, UNIPHIER_SLFRSTSEL_MASK); 74*d8e919c7SMasahiro Yamada mmio_setbits_32(UNIPHIER_SLFRSTCTL, UNIPHIER_SLFRSTCTL_RST); 75*d8e919c7SMasahiro Yamada } 76*d8e919c7SMasahiro Yamada 77*d8e919c7SMasahiro Yamada static void __dead2 uniphier_psci_system_off(void) 78*d8e919c7SMasahiro Yamada { 79*d8e919c7SMasahiro Yamada if (uniphier_psci_scp_mode) { 80*d8e919c7SMasahiro Yamada uniphier_scp_system_off(); 81*d8e919c7SMasahiro Yamada } else { 82*d8e919c7SMasahiro Yamada NOTICE("SCP is disabled; can't shutdown the system.\n"); 83*d8e919c7SMasahiro Yamada NOTICE("Resetting the system instead.\n"); 84*d8e919c7SMasahiro Yamada uniphier_self_system_reset(); 85*d8e919c7SMasahiro Yamada } 86*d8e919c7SMasahiro Yamada 87*d8e919c7SMasahiro Yamada wfi(); 88*d8e919c7SMasahiro Yamada ERROR("UniPhier System Off: operation not handled.\n"); 89*d8e919c7SMasahiro Yamada panic(); 90*d8e919c7SMasahiro Yamada } 91*d8e919c7SMasahiro Yamada 92*d8e919c7SMasahiro Yamada static void __dead2 uniphier_psci_system_reset(void) 93*d8e919c7SMasahiro Yamada { 94*d8e919c7SMasahiro Yamada if (uniphier_psci_scp_mode) 95*d8e919c7SMasahiro Yamada uniphier_scp_system_reset(); 96*d8e919c7SMasahiro Yamada else 97*d8e919c7SMasahiro Yamada uniphier_self_system_reset(); 98*d8e919c7SMasahiro Yamada 99*d8e919c7SMasahiro Yamada wfi(); 100*d8e919c7SMasahiro Yamada ERROR("UniPhier System Reset: operation not handled.\n"); 101*d8e919c7SMasahiro Yamada panic(); 102*d8e919c7SMasahiro Yamada } 103*d8e919c7SMasahiro Yamada 104*d8e919c7SMasahiro Yamada static const struct plat_psci_ops uniphier_psci_ops = { 105*d8e919c7SMasahiro Yamada .pwr_domain_on = uniphier_psci_pwr_domain_on, 106*d8e919c7SMasahiro Yamada .pwr_domain_off = uniphier_psci_pwr_domain_off, 107*d8e919c7SMasahiro Yamada .pwr_domain_on_finish = uniphier_psci_pwr_domain_on_finish, 108*d8e919c7SMasahiro Yamada .pwr_domain_pwr_down_wfi = uniphier_psci_pwr_domain_pwr_down_wfi, 109*d8e919c7SMasahiro Yamada .system_off = uniphier_psci_system_off, 110*d8e919c7SMasahiro Yamada .system_reset = uniphier_psci_system_reset, 111*d8e919c7SMasahiro Yamada }; 112*d8e919c7SMasahiro Yamada 113*d8e919c7SMasahiro Yamada int plat_setup_psci_ops(uintptr_t sec_entrypoint, 114*d8e919c7SMasahiro Yamada const struct plat_psci_ops **psci_ops) 115*d8e919c7SMasahiro Yamada { 116*d8e919c7SMasahiro Yamada uniphier_sec_entrypoint = sec_entrypoint; 117*d8e919c7SMasahiro Yamada flush_dcache_range((uint64_t)&uniphier_sec_entrypoint, 118*d8e919c7SMasahiro Yamada sizeof(uniphier_sec_entrypoint)); 119*d8e919c7SMasahiro Yamada 120*d8e919c7SMasahiro Yamada uniphier_psci_scp_mode = uniphier_scp_is_running(); 121*d8e919c7SMasahiro Yamada flush_dcache_range((uint64_t)&uniphier_psci_scp_mode, 122*d8e919c7SMasahiro Yamada sizeof(uniphier_psci_scp_mode)); 123*d8e919c7SMasahiro Yamada 124*d8e919c7SMasahiro Yamada if (uniphier_psci_scp_mode) 125*d8e919c7SMasahiro Yamada uniphier_scp_open_com(); 126*d8e919c7SMasahiro Yamada 127*d8e919c7SMasahiro Yamada *psci_ops = &uniphier_psci_ops; 128*d8e919c7SMasahiro Yamada 129*d8e919c7SMasahiro Yamada return 0; 130*d8e919c7SMasahiro Yamada } 131