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