12e9c9e82SBenjamin Fair /* 22e9c9e82SBenjamin Fair * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. 32e9c9e82SBenjamin Fair * 42e9c9e82SBenjamin Fair * SPDX-License-Identifier: BSD-3-Clause 52e9c9e82SBenjamin Fair */ 62e9c9e82SBenjamin Fair 72e9c9e82SBenjamin Fair #include <arch_helpers.h> 82e9c9e82SBenjamin Fair #include <assert.h> 92e9c9e82SBenjamin Fair #include <debug.h> 102e9c9e82SBenjamin Fair #include <k3_gicv3.h> 112e9c9e82SBenjamin Fair #include <psci.h> 122e9c9e82SBenjamin Fair #include <stdbool.h> 132e9c9e82SBenjamin Fair 142e9c9e82SBenjamin Fair #define STUB() ERROR("stub %s called\n", __func__) 152e9c9e82SBenjamin Fair 162e9c9e82SBenjamin Fair uintptr_t k3_sec_entrypoint; 172e9c9e82SBenjamin Fair 182e9c9e82SBenjamin Fair static void k3_cpu_standby(plat_local_state_t cpu_state) 192e9c9e82SBenjamin Fair { 20*deed2b83SAndrew F. Davis unsigned int scr; 21*deed2b83SAndrew F. Davis 22*deed2b83SAndrew F. Davis scr = read_scr_el3(); 23*deed2b83SAndrew F. Davis /* Enable the Non secure interrupt to wake the CPU */ 24*deed2b83SAndrew F. Davis write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); 25*deed2b83SAndrew F. Davis isb(); 26*deed2b83SAndrew F. Davis /* dsb is good practice before using wfi to enter low power states */ 272e9c9e82SBenjamin Fair dsb(); 28*deed2b83SAndrew F. Davis /* Enter standby state */ 292e9c9e82SBenjamin Fair wfi(); 30*deed2b83SAndrew F. Davis /* Restore SCR */ 31*deed2b83SAndrew F. Davis write_scr_el3(scr); 322e9c9e82SBenjamin Fair } 332e9c9e82SBenjamin Fair 342e9c9e82SBenjamin Fair static int k3_pwr_domain_on(u_register_t mpidr) 352e9c9e82SBenjamin Fair { 362e9c9e82SBenjamin Fair sev(); 372e9c9e82SBenjamin Fair 382e9c9e82SBenjamin Fair /* TODO: Indicate to System firmware about powering up */ 392e9c9e82SBenjamin Fair 402e9c9e82SBenjamin Fair return PSCI_E_SUCCESS; 412e9c9e82SBenjamin Fair } 422e9c9e82SBenjamin Fair 432e9c9e82SBenjamin Fair void k3_pwr_domain_off(const psci_power_state_t *target_state) 442e9c9e82SBenjamin Fair { 452e9c9e82SBenjamin Fair /* Prevent interrupts from spuriously waking up this cpu */ 462e9c9e82SBenjamin Fair k3_gic_cpuif_disable(); 472e9c9e82SBenjamin Fair 482e9c9e82SBenjamin Fair /* TODO: Indicate to System firmware about powering down */ 492e9c9e82SBenjamin Fair } 502e9c9e82SBenjamin Fair 512e9c9e82SBenjamin Fair void k3_pwr_domain_on_finish(const psci_power_state_t *target_state) 522e9c9e82SBenjamin Fair { 532e9c9e82SBenjamin Fair /* TODO: Indicate to System firmware about completion */ 542e9c9e82SBenjamin Fair 552e9c9e82SBenjamin Fair k3_gic_pcpu_init(); 562e9c9e82SBenjamin Fair k3_gic_cpuif_enable(); 572e9c9e82SBenjamin Fair } 582e9c9e82SBenjamin Fair 592e9c9e82SBenjamin Fair static void __dead2 k3_system_reset(void) 602e9c9e82SBenjamin Fair { 612e9c9e82SBenjamin Fair /* TODO: Indicate to System firmware about system reset */ 622e9c9e82SBenjamin Fair STUB(); 632e9c9e82SBenjamin Fair 642e9c9e82SBenjamin Fair while (true) 652e9c9e82SBenjamin Fair wfi(); 662e9c9e82SBenjamin Fair } 672e9c9e82SBenjamin Fair 682e9c9e82SBenjamin Fair static int k3_validate_power_state(unsigned int power_state, 692e9c9e82SBenjamin Fair psci_power_state_t *req_state) 702e9c9e82SBenjamin Fair { 712e9c9e82SBenjamin Fair /* TODO: perform the proper validation */ 722e9c9e82SBenjamin Fair 732e9c9e82SBenjamin Fair return PSCI_E_SUCCESS; 742e9c9e82SBenjamin Fair } 752e9c9e82SBenjamin Fair 762e9c9e82SBenjamin Fair static int k3_validate_ns_entrypoint(uintptr_t entrypoint) 772e9c9e82SBenjamin Fair { 782e9c9e82SBenjamin Fair /* TODO: perform the proper validation */ 792e9c9e82SBenjamin Fair 802e9c9e82SBenjamin Fair return PSCI_E_SUCCESS; 812e9c9e82SBenjamin Fair } 822e9c9e82SBenjamin Fair 832e9c9e82SBenjamin Fair static const plat_psci_ops_t k3_plat_psci_ops = { 842e9c9e82SBenjamin Fair .cpu_standby = k3_cpu_standby, 852e9c9e82SBenjamin Fair .pwr_domain_on = k3_pwr_domain_on, 862e9c9e82SBenjamin Fair .pwr_domain_off = k3_pwr_domain_off, 872e9c9e82SBenjamin Fair .pwr_domain_on_finish = k3_pwr_domain_on_finish, 882e9c9e82SBenjamin Fair .system_reset = k3_system_reset, 892e9c9e82SBenjamin Fair .validate_power_state = k3_validate_power_state, 902e9c9e82SBenjamin Fair .validate_ns_entrypoint = k3_validate_ns_entrypoint 912e9c9e82SBenjamin Fair }; 922e9c9e82SBenjamin Fair 932e9c9e82SBenjamin Fair int plat_setup_psci_ops(uintptr_t sec_entrypoint, 942e9c9e82SBenjamin Fair const plat_psci_ops_t **psci_ops) 952e9c9e82SBenjamin Fair { 962e9c9e82SBenjamin Fair k3_sec_entrypoint = sec_entrypoint; 972e9c9e82SBenjamin Fair 982e9c9e82SBenjamin Fair *psci_ops = &k3_plat_psci_ops; 992e9c9e82SBenjamin Fair 1002e9c9e82SBenjamin Fair return 0; 1012e9c9e82SBenjamin Fair } 102