blob: 79c670f87582293ed69922a9ab177b992b3ccf20 [file] [log] [blame]
Stephan Gerholddddba192021-12-01 20:01:11 +01001/*
Stephan Gerhold01ba69c2022-09-17 18:21:20 +02002 * Copyright (c) 2021-2022, Stephan Gerhold <stephan@gerhold.net>
Stephan Gerholddddba192021-12-01 20:01:11 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
Stephan Gerhold01ba69c2022-09-17 18:21:20 +02008#include <arch_helpers.h>
Stephan Gerholddddba192021-12-01 20:01:11 +01009#include <common/debug.h>
Stephan Gerhold1240dc72022-09-16 20:42:49 +020010#include <drivers/arm/cci.h>
Stephan Gerholda758c0b2021-12-01 20:04:44 +010011#include <drivers/arm/gicv2.h>
Stephan Gerholddddba192021-12-01 20:01:11 +010012#include <drivers/delay_timer.h>
13#include <lib/mmio.h>
14#include <lib/psci/psci.h>
15#include <plat/common/platform.h>
16
17#include <msm8916_mmap.h>
Stephan Gerholda758c0b2021-12-01 20:04:44 +010018#include "msm8916_pm.h"
19
Stephan Gerhold1d7ed582022-09-16 10:45:19 +020020/*
21 * On platforms with two clusters the index of the APCS memory region is swapped
22 * compared to the MPIDR cluster affinity level: APCS cluster 0 manages CPUs
23 * with cluster affinity level 1, while APCS cluster 1 manages CPUs with level 0.
24 *
25 * On platforms with a single cluster there is only one APCS memory region.
26 */
27#if PLATFORM_CLUSTER_COUNT == 2
28#define MPIDR_APCS_CLUSTER(mpidr) !MPIDR_AFFLVL1_VAL(mpidr)
29#else
30#define MPIDR_APCS_CLUSTER(mpidr) 0
31#endif
32
Stephan Gerhold1240dc72022-09-16 20:42:49 +020033#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
34
Stephan Gerholda758c0b2021-12-01 20:04:44 +010035static int msm8916_pwr_domain_on(u_register_t mpidr)
36{
Stephan Gerhold1d7ed582022-09-16 10:45:19 +020037 msm8916_cpu_boot(APCS_ALIAS_ACS(MPIDR_APCS_CLUSTER(mpidr),
38 MPIDR_AFFLVL0_VAL(mpidr)));
Stephan Gerholda758c0b2021-12-01 20:04:44 +010039 return PSCI_E_SUCCESS;
40}
41
42static void msm8916_pwr_domain_on_finish(const psci_power_state_t *target_state)
43{
Stephan Gerhold1240dc72022-09-16 20:42:49 +020044 if (PLATFORM_CLUSTER_COUNT > 1 &&
45 CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
46 cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
47 }
48
Stephan Gerholda758c0b2021-12-01 20:04:44 +010049 gicv2_pcpu_distif_init();
50 gicv2_cpuif_enable();
51}
Stephan Gerholddddba192021-12-01 20:01:11 +010052
53static void __dead2 msm8916_system_reset(void)
54{
55 mmio_write_32(MPM_PS_HOLD, 0);
56 mdelay(1000);
57
58 ERROR("PSCI: System reset failed\n");
59 panic();
60}
61
62static const plat_psci_ops_t msm8916_psci_ops = {
Stephan Gerholda758c0b2021-12-01 20:04:44 +010063 .pwr_domain_on = msm8916_pwr_domain_on,
64 .pwr_domain_on_finish = msm8916_pwr_domain_on_finish,
Stephan Gerholddddba192021-12-01 20:01:11 +010065 .system_off = msm8916_system_reset,
66 .system_reset = msm8916_system_reset,
67};
68
69/* Defined and used in msm8916_helpers.S */
70extern uintptr_t msm8916_entry_point;
71
72int plat_setup_psci_ops(uintptr_t sec_entrypoint,
73 const plat_psci_ops_t **psci_ops)
74{
Stephan Gerhold01ba69c2022-09-17 18:21:20 +020075 /*
76 * The entry point is read with caches off (and even from two different
77 * physical addresses when read through the "boot remapper"), so make
78 * sure it is flushed to memory.
79 */
Stephan Gerholddddba192021-12-01 20:01:11 +010080 msm8916_entry_point = sec_entrypoint;
Stephan Gerhold01ba69c2022-09-17 18:21:20 +020081 flush_dcache_range((uintptr_t)&msm8916_entry_point, sizeof(uintptr_t));
82
Stephan Gerholddddba192021-12-01 20:01:11 +010083 *psci_ops = &msm8916_psci_ops;
84 return 0;
85}