xref: /rk3399_ARM-atf/plat/ti/k3/common/k3_psci.c (revision deed2b8398ced11d72d90f4811024a5a99dde953)
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