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