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