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