xref: /arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2015 - 2020, Broadcom
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu #include <errno.h>
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <arch.h>
11*91f16700Schasinglulu #include <arch_helpers.h>
12*91f16700Schasinglulu #include <common/debug.h>
13*91f16700Schasinglulu #include <drivers/arm/ccn.h>
14*91f16700Schasinglulu #include <drivers/delay_timer.h>
15*91f16700Schasinglulu #include <lib/bakery_lock.h>
16*91f16700Schasinglulu #include <lib/mmio.h>
17*91f16700Schasinglulu #include <lib/psci/psci.h>
18*91f16700Schasinglulu #include <lib/spinlock.h>
19*91f16700Schasinglulu #include <plat/common/platform.h>
20*91f16700Schasinglulu 
21*91f16700Schasinglulu #ifdef USE_PAXC
22*91f16700Schasinglulu #include <chimp.h>
23*91f16700Schasinglulu #endif
24*91f16700Schasinglulu #include <cmn_plat_util.h>
25*91f16700Schasinglulu #include <ihost_pm.h>
26*91f16700Schasinglulu #include <plat_brcm.h>
27*91f16700Schasinglulu #include <platform_def.h>
28*91f16700Schasinglulu 
29*91f16700Schasinglulu static uint64_t plat_sec_entrypoint;
30*91f16700Schasinglulu 
31*91f16700Schasinglulu /*******************************************************************************
32*91f16700Schasinglulu  * SR handler called when a power domain is about to be turned on. The
33*91f16700Schasinglulu  * mpidr determines the CPU to be turned on.
34*91f16700Schasinglulu  ******************************************************************************/
35*91f16700Schasinglulu static int brcm_pwr_domain_on(u_register_t mpidr)
36*91f16700Schasinglulu {
37*91f16700Schasinglulu 	int cpuid;
38*91f16700Schasinglulu 
39*91f16700Schasinglulu 	cpuid = plat_brcm_calc_core_pos(mpidr);
40*91f16700Schasinglulu 	INFO("mpidr :%lu, cpuid:%d\n", mpidr, cpuid);
41*91f16700Schasinglulu 
42*91f16700Schasinglulu #ifdef USE_SINGLE_CLUSTER
43*91f16700Schasinglulu 	if (cpuid > 1)
44*91f16700Schasinglulu 		return PSCI_E_INTERN_FAIL;
45*91f16700Schasinglulu #endif
46*91f16700Schasinglulu 
47*91f16700Schasinglulu 	ihost_power_on_cluster(mpidr);
48*91f16700Schasinglulu 
49*91f16700Schasinglulu 	ihost_power_on_secondary_core(mpidr, plat_sec_entrypoint);
50*91f16700Schasinglulu 
51*91f16700Schasinglulu 	return PSCI_E_SUCCESS;
52*91f16700Schasinglulu }
53*91f16700Schasinglulu 
54*91f16700Schasinglulu /*******************************************************************************
55*91f16700Schasinglulu  * SR handler called when a power domain has just been powered on after
56*91f16700Schasinglulu  * being turned off earlier. The target_state encodes the low power state that
57*91f16700Schasinglulu  * each level has woken up from.
58*91f16700Schasinglulu  ******************************************************************************/
59*91f16700Schasinglulu static void brcm_pwr_domain_on_finish(const psci_power_state_t *target_state)
60*91f16700Schasinglulu {
61*91f16700Schasinglulu 	unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr());
62*91f16700Schasinglulu 
63*91f16700Schasinglulu 	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
64*91f16700Schasinglulu 					PLAT_LOCAL_STATE_OFF);
65*91f16700Schasinglulu 
66*91f16700Schasinglulu 	if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
67*91f16700Schasinglulu 					PLAT_LOCAL_STATE_OFF) {
68*91f16700Schasinglulu 		INFO("Cluster #%lu entering to snoop/dvm domain\n", cluster_id);
69*91f16700Schasinglulu 		ccn_enter_snoop_dvm_domain(1 << cluster_id);
70*91f16700Schasinglulu 	}
71*91f16700Schasinglulu 
72*91f16700Schasinglulu 	/* Enable the gic cpu interface */
73*91f16700Schasinglulu 	plat_brcm_gic_pcpu_init();
74*91f16700Schasinglulu 
75*91f16700Schasinglulu 	/* Program the gic per-cpu distributor or re-distributor interface */
76*91f16700Schasinglulu 	plat_brcm_gic_cpuif_enable();
77*91f16700Schasinglulu 
78*91f16700Schasinglulu 	INFO("Gic Initialization done for this affinity instance\n");
79*91f16700Schasinglulu }
80*91f16700Schasinglulu 
81*91f16700Schasinglulu static void __dead2 brcm_system_reset(void)
82*91f16700Schasinglulu {
83*91f16700Schasinglulu 	uint32_t reset_type = SOFT_SYS_RESET_L1;
84*91f16700Schasinglulu 
85*91f16700Schasinglulu #ifdef USE_PAXC
86*91f16700Schasinglulu 	if (bcm_chimp_is_nic_mode())
87*91f16700Schasinglulu 		reset_type = SOFT_RESET_L3;
88*91f16700Schasinglulu #endif
89*91f16700Schasinglulu 	INFO("System rebooting - L%d...\n", reset_type);
90*91f16700Schasinglulu 
91*91f16700Schasinglulu 	plat_soft_reset(reset_type);
92*91f16700Schasinglulu 
93*91f16700Schasinglulu 	/* Prevent the function to return due to the attribute */
94*91f16700Schasinglulu 	while (1)
95*91f16700Schasinglulu 		;
96*91f16700Schasinglulu }
97*91f16700Schasinglulu 
98*91f16700Schasinglulu static int brcm_system_reset2(int is_vendor, int reset_type,
99*91f16700Schasinglulu 			      u_register_t cookie)
100*91f16700Schasinglulu {
101*91f16700Schasinglulu 	INFO("System rebooting - L%d...\n", reset_type);
102*91f16700Schasinglulu 
103*91f16700Schasinglulu 	plat_soft_reset(reset_type);
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 	/*
106*91f16700Schasinglulu 	 * plat_soft_reset cannot return (it is a __dead function),
107*91f16700Schasinglulu 	 * but brcm_system_reset2 has to return some value, even in
108*91f16700Schasinglulu 	 * this case.
109*91f16700Schasinglulu 	 */
110*91f16700Schasinglulu 	return 0;
111*91f16700Schasinglulu }
112*91f16700Schasinglulu 
113*91f16700Schasinglulu /*******************************************************************************
114*91f16700Schasinglulu  * Export the platform handlers via plat_brcm_psci_pm_ops. The ARM Standard
115*91f16700Schasinglulu  * platform will take care of registering the handlers with PSCI.
116*91f16700Schasinglulu  ******************************************************************************/
117*91f16700Schasinglulu const plat_psci_ops_t plat_brcm_psci_pm_ops = {
118*91f16700Schasinglulu 	.pwr_domain_on		= brcm_pwr_domain_on,
119*91f16700Schasinglulu 	.pwr_domain_on_finish	= brcm_pwr_domain_on_finish,
120*91f16700Schasinglulu 	.system_reset		= brcm_system_reset,
121*91f16700Schasinglulu 	.system_reset2		= brcm_system_reset2
122*91f16700Schasinglulu };
123*91f16700Schasinglulu 
124*91f16700Schasinglulu int plat_setup_psci_ops(uintptr_t sec_entrypoint,
125*91f16700Schasinglulu 			const plat_psci_ops_t **psci_ops)
126*91f16700Schasinglulu {
127*91f16700Schasinglulu 	*psci_ops = &plat_brcm_psci_pm_ops;
128*91f16700Schasinglulu 	plat_sec_entrypoint = sec_entrypoint;
129*91f16700Schasinglulu 
130*91f16700Schasinglulu 	return 0;
131*91f16700Schasinglulu }
132