xref: /rk3399_ARM-atf/plat/amlogic/axg/axg_pm.c (revision fcb80d7d14196ff4ca454cd4f9cc6864600c333e)
1afd241e7SCarlo Caione /*
2afd241e7SCarlo Caione  * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
3afd241e7SCarlo Caione  *
4afd241e7SCarlo Caione  * SPDX-License-Identifier: BSD-3-Clause
5afd241e7SCarlo Caione  */
6afd241e7SCarlo Caione 
7afd241e7SCarlo Caione #include <arch_helpers.h>
8afd241e7SCarlo Caione #include <assert.h>
9afd241e7SCarlo Caione #include <common/debug.h>
10afd241e7SCarlo Caione #include <drivers/arm/gicv2.h>
11afd241e7SCarlo Caione #include <drivers/console.h>
12afd241e7SCarlo Caione #include <errno.h>
13afd241e7SCarlo Caione #include <lib/mmio.h>
14afd241e7SCarlo Caione #include <lib/psci/psci.h>
15afd241e7SCarlo Caione #include <plat/common/platform.h>
16afd241e7SCarlo Caione #include <platform_def.h>
17afd241e7SCarlo Caione 
18afd241e7SCarlo Caione #include "aml_private.h"
19afd241e7SCarlo Caione 
20afd241e7SCarlo Caione #define SCPI_POWER_ON		0
21afd241e7SCarlo Caione #define SCPI_POWER_RETENTION	1
22afd241e7SCarlo Caione #define SCPI_POWER_OFF		3
23afd241e7SCarlo Caione 
24afd241e7SCarlo Caione #define SCPI_SYSTEM_SHUTDOWN	0
25afd241e7SCarlo Caione #define SCPI_SYSTEM_REBOOT	1
26afd241e7SCarlo Caione 
27afd241e7SCarlo Caione static uintptr_t axg_sec_entrypoint;
28afd241e7SCarlo Caione 
axg_pm_set_reset_addr(u_register_t mpidr,uint64_t value)29afd241e7SCarlo Caione static void axg_pm_set_reset_addr(u_register_t mpidr, uint64_t value)
30afd241e7SCarlo Caione {
31afd241e7SCarlo Caione 	unsigned int core = plat_calc_core_pos(mpidr);
32afd241e7SCarlo Caione 	uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
33afd241e7SCarlo Caione 
34afd241e7SCarlo Caione 	mmio_write_64(cpu_mailbox_addr, value);
35afd241e7SCarlo Caione }
36afd241e7SCarlo Caione 
axg_pm_reset(u_register_t mpidr,uint32_t value)37afd241e7SCarlo Caione static void axg_pm_reset(u_register_t mpidr, uint32_t value)
38afd241e7SCarlo Caione {
39afd241e7SCarlo Caione 	unsigned int core = plat_calc_core_pos(mpidr);
40afd241e7SCarlo Caione 	uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8;
41afd241e7SCarlo Caione 
42afd241e7SCarlo Caione 	mmio_write_32(cpu_mailbox_addr, value);
43afd241e7SCarlo Caione }
44afd241e7SCarlo Caione 
axg_system_reset(void)45afd241e7SCarlo Caione static void __dead2 axg_system_reset(void)
46afd241e7SCarlo Caione {
47afd241e7SCarlo Caione 	u_register_t mpidr = read_mpidr_el1();
48afd241e7SCarlo Caione 	int ret;
49afd241e7SCarlo Caione 
50afd241e7SCarlo Caione 	INFO("BL31: PSCI_SYSTEM_RESET\n");
51afd241e7SCarlo Caione 
52afd241e7SCarlo Caione 	ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
53afd241e7SCarlo Caione 	if (ret != 0) {
54afd241e7SCarlo Caione 		ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
55afd241e7SCarlo Caione 		panic();
56afd241e7SCarlo Caione 	}
57afd241e7SCarlo Caione 
58afd241e7SCarlo Caione 	axg_pm_reset(mpidr, 0);
59afd241e7SCarlo Caione 
60afd241e7SCarlo Caione 	wfi();
61afd241e7SCarlo Caione 
62afd241e7SCarlo Caione 	ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
63afd241e7SCarlo Caione 	panic();
64afd241e7SCarlo Caione }
65afd241e7SCarlo Caione 
axg_system_off(void)66afd241e7SCarlo Caione static void __dead2 axg_system_off(void)
67afd241e7SCarlo Caione {
68afd241e7SCarlo Caione 	u_register_t mpidr = read_mpidr_el1();
69afd241e7SCarlo Caione 	int ret;
70afd241e7SCarlo Caione 
71afd241e7SCarlo Caione 	INFO("BL31: PSCI_SYSTEM_OFF\n");
72afd241e7SCarlo Caione 
73afd241e7SCarlo Caione 	ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
74afd241e7SCarlo Caione 	if (ret != 0) {
75afd241e7SCarlo Caione 		ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
76afd241e7SCarlo Caione 		panic();
77afd241e7SCarlo Caione 	}
78afd241e7SCarlo Caione 
79afd241e7SCarlo Caione 	axg_pm_set_reset_addr(mpidr, 0);
80afd241e7SCarlo Caione 	axg_pm_reset(mpidr, 0);
81afd241e7SCarlo Caione 
82afd241e7SCarlo Caione 	dmbsy();
83afd241e7SCarlo Caione 	wfi();
84afd241e7SCarlo Caione 
85afd241e7SCarlo Caione 	ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
86afd241e7SCarlo Caione 	panic();
87afd241e7SCarlo Caione }
88afd241e7SCarlo Caione 
axg_pwr_domain_on(u_register_t mpidr)89afd241e7SCarlo Caione static int32_t axg_pwr_domain_on(u_register_t mpidr)
90afd241e7SCarlo Caione {
91afd241e7SCarlo Caione 	axg_pm_set_reset_addr(mpidr, axg_sec_entrypoint);
92afd241e7SCarlo Caione 	aml_scpi_set_css_power_state(mpidr,
93afd241e7SCarlo Caione 				     SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
94afd241e7SCarlo Caione 	dmbsy();
95afd241e7SCarlo Caione 	sev();
96afd241e7SCarlo Caione 
97afd241e7SCarlo Caione 	return PSCI_E_SUCCESS;
98afd241e7SCarlo Caione }
99afd241e7SCarlo Caione 
axg_pwr_domain_on_finish(const psci_power_state_t * target_state)100afd241e7SCarlo Caione static void axg_pwr_domain_on_finish(const psci_power_state_t *target_state)
101afd241e7SCarlo Caione {
102afd241e7SCarlo Caione 	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
103afd241e7SCarlo Caione 					PLAT_LOCAL_STATE_OFF);
104afd241e7SCarlo Caione 
105afd241e7SCarlo Caione 	gicv2_pcpu_distif_init();
106afd241e7SCarlo Caione 	gicv2_cpuif_enable();
107afd241e7SCarlo Caione 
108afd241e7SCarlo Caione 	axg_pm_set_reset_addr(read_mpidr_el1(), 0);
109afd241e7SCarlo Caione }
110afd241e7SCarlo Caione 
axg_pwr_domain_off(const psci_power_state_t * target_state)111afd241e7SCarlo Caione static void axg_pwr_domain_off(const psci_power_state_t *target_state)
112afd241e7SCarlo Caione {
113afd241e7SCarlo Caione 	u_register_t mpidr = read_mpidr_el1();
114afd241e7SCarlo Caione 	uint32_t system_state = SCPI_POWER_ON;
115afd241e7SCarlo Caione 	uint32_t cluster_state = SCPI_POWER_ON;
116afd241e7SCarlo Caione 
117afd241e7SCarlo Caione 	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
118afd241e7SCarlo Caione 					PLAT_LOCAL_STATE_OFF);
119afd241e7SCarlo Caione 
120afd241e7SCarlo Caione 	axg_pm_reset(mpidr, -1);
121afd241e7SCarlo Caione 
122afd241e7SCarlo Caione 	gicv2_cpuif_disable();
123afd241e7SCarlo Caione 
124afd241e7SCarlo Caione 	if (target_state->pwr_domain_state[MPIDR_AFFLVL2] ==
125afd241e7SCarlo Caione 					PLAT_LOCAL_STATE_OFF)
126afd241e7SCarlo Caione 		system_state = SCPI_POWER_OFF;
127afd241e7SCarlo Caione 
128afd241e7SCarlo Caione 	if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
129afd241e7SCarlo Caione 					PLAT_LOCAL_STATE_OFF)
130afd241e7SCarlo Caione 		cluster_state = SCPI_POWER_OFF;
131afd241e7SCarlo Caione 
132afd241e7SCarlo Caione 
133afd241e7SCarlo Caione 	aml_scpi_set_css_power_state(mpidr,
134afd241e7SCarlo Caione 				     SCPI_POWER_OFF, cluster_state,
135afd241e7SCarlo Caione 				     system_state);
136afd241e7SCarlo Caione }
137afd241e7SCarlo Caione 
axg_pwr_domain_pwr_down_wfi(const psci_power_state_t * target_state)138afd241e7SCarlo Caione static void __dead2 axg_pwr_domain_pwr_down_wfi(const psci_power_state_t
139afd241e7SCarlo Caione 						 *target_state)
140afd241e7SCarlo Caione {
141afd241e7SCarlo Caione 	dsbsy();
142afd241e7SCarlo Caione 	axg_pm_reset(read_mpidr_el1(), 0);
143afd241e7SCarlo Caione 
144afd241e7SCarlo Caione 	for (;;)
145afd241e7SCarlo Caione 		wfi();
146afd241e7SCarlo Caione }
147afd241e7SCarlo Caione 
148afd241e7SCarlo Caione /*******************************************************************************
149afd241e7SCarlo Caione  * Platform handlers and setup function.
150afd241e7SCarlo Caione  ******************************************************************************/
151afd241e7SCarlo Caione static const plat_psci_ops_t axg_ops = {
152afd241e7SCarlo Caione 	.pwr_domain_on			= axg_pwr_domain_on,
153afd241e7SCarlo Caione 	.pwr_domain_on_finish		= axg_pwr_domain_on_finish,
154afd241e7SCarlo Caione 	.pwr_domain_off			= axg_pwr_domain_off,
155*db5fe4f4SBoyan Karatotev 	.pwr_domain_pwr_down		= axg_pwr_domain_pwr_down_wfi,
156afd241e7SCarlo Caione 	.system_off			= axg_system_off,
157afd241e7SCarlo Caione 	.system_reset			= axg_system_reset
158afd241e7SCarlo Caione };
159afd241e7SCarlo Caione 
plat_setup_psci_ops(uintptr_t sec_entrypoint,const plat_psci_ops_t ** psci_ops)160afd241e7SCarlo Caione int plat_setup_psci_ops(uintptr_t sec_entrypoint,
161afd241e7SCarlo Caione 			const plat_psci_ops_t **psci_ops)
162afd241e7SCarlo Caione {
163afd241e7SCarlo Caione 	axg_sec_entrypoint = sec_entrypoint;
164afd241e7SCarlo Caione 	*psci_ops = &axg_ops;
165afd241e7SCarlo Caione 	return 0;
166afd241e7SCarlo Caione }
167