xref: /rk3399_ARM-atf/plat/qti/msm8916/msm8916_pm.c (revision 1240dc7ef11e850bdf7a4e66de3d858e26555842)
1dddba19aSStephan Gerhold /*
201ba69cdSStephan Gerhold  * Copyright (c) 2021-2022, Stephan Gerhold <stephan@gerhold.net>
3dddba19aSStephan Gerhold  *
4dddba19aSStephan Gerhold  * SPDX-License-Identifier: BSD-3-Clause
5dddba19aSStephan Gerhold  */
6dddba19aSStephan Gerhold 
7dddba19aSStephan Gerhold #include <arch.h>
801ba69cdSStephan Gerhold #include <arch_helpers.h>
9dddba19aSStephan Gerhold #include <common/debug.h>
10*1240dc7eSStephan Gerhold #include <drivers/arm/cci.h>
11a758c0b6SStephan Gerhold #include <drivers/arm/gicv2.h>
12dddba19aSStephan Gerhold #include <drivers/delay_timer.h>
13dddba19aSStephan Gerhold #include <lib/mmio.h>
14dddba19aSStephan Gerhold #include <lib/psci/psci.h>
15dddba19aSStephan Gerhold #include <plat/common/platform.h>
16dddba19aSStephan Gerhold 
17dddba19aSStephan Gerhold #include <msm8916_mmap.h>
18a758c0b6SStephan Gerhold #include "msm8916_pm.h"
19a758c0b6SStephan Gerhold 
201d7ed58fSStephan Gerhold /*
211d7ed58fSStephan Gerhold  * On platforms with two clusters the index of the APCS memory region is swapped
221d7ed58fSStephan Gerhold  * compared to the MPIDR cluster affinity level: APCS cluster 0 manages CPUs
231d7ed58fSStephan Gerhold  * with cluster affinity level 1, while APCS cluster 1 manages CPUs with level 0.
241d7ed58fSStephan Gerhold  *
251d7ed58fSStephan Gerhold  * On platforms with a single cluster there is only one APCS memory region.
261d7ed58fSStephan Gerhold  */
271d7ed58fSStephan Gerhold #if PLATFORM_CLUSTER_COUNT == 2
281d7ed58fSStephan Gerhold #define MPIDR_APCS_CLUSTER(mpidr)	!MPIDR_AFFLVL1_VAL(mpidr)
291d7ed58fSStephan Gerhold #else
301d7ed58fSStephan Gerhold #define MPIDR_APCS_CLUSTER(mpidr)	0
311d7ed58fSStephan Gerhold #endif
321d7ed58fSStephan Gerhold 
33*1240dc7eSStephan Gerhold #define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
34*1240dc7eSStephan Gerhold 
35a758c0b6SStephan Gerhold static int msm8916_pwr_domain_on(u_register_t mpidr)
36a758c0b6SStephan Gerhold {
371d7ed58fSStephan Gerhold 	msm8916_cpu_boot(APCS_ALIAS_ACS(MPIDR_APCS_CLUSTER(mpidr),
381d7ed58fSStephan Gerhold 					MPIDR_AFFLVL0_VAL(mpidr)));
39a758c0b6SStephan Gerhold 	return PSCI_E_SUCCESS;
40a758c0b6SStephan Gerhold }
41a758c0b6SStephan Gerhold 
42a758c0b6SStephan Gerhold static void msm8916_pwr_domain_on_finish(const psci_power_state_t *target_state)
43a758c0b6SStephan Gerhold {
44*1240dc7eSStephan Gerhold 	if (PLATFORM_CLUSTER_COUNT > 1 &&
45*1240dc7eSStephan Gerhold 	    CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
46*1240dc7eSStephan Gerhold 		cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
47*1240dc7eSStephan Gerhold 	}
48*1240dc7eSStephan Gerhold 
49a758c0b6SStephan Gerhold 	gicv2_pcpu_distif_init();
50a758c0b6SStephan Gerhold 	gicv2_cpuif_enable();
51a758c0b6SStephan Gerhold }
52dddba19aSStephan Gerhold 
53dddba19aSStephan Gerhold static void __dead2 msm8916_system_reset(void)
54dddba19aSStephan Gerhold {
55dddba19aSStephan Gerhold 	mmio_write_32(MPM_PS_HOLD, 0);
56dddba19aSStephan Gerhold 	mdelay(1000);
57dddba19aSStephan Gerhold 
58dddba19aSStephan Gerhold 	ERROR("PSCI: System reset failed\n");
59dddba19aSStephan Gerhold 	panic();
60dddba19aSStephan Gerhold }
61dddba19aSStephan Gerhold 
62dddba19aSStephan Gerhold static const plat_psci_ops_t msm8916_psci_ops = {
63a758c0b6SStephan Gerhold 	.pwr_domain_on			= msm8916_pwr_domain_on,
64a758c0b6SStephan Gerhold 	.pwr_domain_on_finish		= msm8916_pwr_domain_on_finish,
65dddba19aSStephan Gerhold 	.system_off			= msm8916_system_reset,
66dddba19aSStephan Gerhold 	.system_reset			= msm8916_system_reset,
67dddba19aSStephan Gerhold };
68dddba19aSStephan Gerhold 
69dddba19aSStephan Gerhold /* Defined and used in msm8916_helpers.S */
70dddba19aSStephan Gerhold extern uintptr_t msm8916_entry_point;
71dddba19aSStephan Gerhold 
72dddba19aSStephan Gerhold int plat_setup_psci_ops(uintptr_t sec_entrypoint,
73dddba19aSStephan Gerhold 			const plat_psci_ops_t **psci_ops)
74dddba19aSStephan Gerhold {
7501ba69cdSStephan Gerhold 	/*
7601ba69cdSStephan Gerhold 	 * The entry point is read with caches off (and even from two different
7701ba69cdSStephan Gerhold 	 * physical addresses when read through the "boot remapper"), so make
7801ba69cdSStephan Gerhold 	 * sure it is flushed to memory.
7901ba69cdSStephan Gerhold 	 */
80dddba19aSStephan Gerhold 	msm8916_entry_point = sec_entrypoint;
8101ba69cdSStephan Gerhold 	flush_dcache_range((uintptr_t)&msm8916_entry_point, sizeof(uintptr_t));
8201ba69cdSStephan Gerhold 
83dddba19aSStephan Gerhold 	*psci_ops = &msm8916_psci_ops;
84dddba19aSStephan Gerhold 	return 0;
85dddba19aSStephan Gerhold }
86