xref: /rk3399_ARM-atf/plat/hisilicon/poplar/plat_pm.c (revision 0818e9e864458660085259f8c67e9d5db6564ace)
1e35d0edbSJorge Ramirez-Ortiz /*
2*0818e9e8SAntonio Nino Diaz  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3e35d0edbSJorge Ramirez-Ortiz  *
4e35d0edbSJorge Ramirez-Ortiz  * SPDX-License-Identifier: BSD-3-Clause
5e35d0edbSJorge Ramirez-Ortiz  */
6e35d0edbSJorge Ramirez-Ortiz 
7e35d0edbSJorge Ramirez-Ortiz #include <arch_helpers.h>
8e35d0edbSJorge Ramirez-Ortiz #include <assert.h>
9e35d0edbSJorge Ramirez-Ortiz #include <bl_common.h>
10e35d0edbSJorge Ramirez-Ortiz #include <console.h>
11e35d0edbSJorge Ramirez-Ortiz #include <context.h>
12e35d0edbSJorge Ramirez-Ortiz #include <context_mgmt.h>
13e35d0edbSJorge Ramirez-Ortiz #include <debug.h>
14e35d0edbSJorge Ramirez-Ortiz #include <mmio.h>
15e35d0edbSJorge Ramirez-Ortiz #include <platform.h>
16*0818e9e8SAntonio Nino Diaz #include <platform_def.h>
17e35d0edbSJorge Ramirez-Ortiz #include <psci.h>
18e35d0edbSJorge Ramirez-Ortiz #include "hi3798cv200.h"
19e35d0edbSJorge Ramirez-Ortiz #include "plat_private.h"
20e35d0edbSJorge Ramirez-Ortiz 
21e35d0edbSJorge Ramirez-Ortiz #define REG_PERI_CPU_RVBARADDR		0xF8A80034
22e35d0edbSJorge Ramirez-Ortiz #define REG_PERI_CPU_AARCH_MODE		0xF8A80030
23e35d0edbSJorge Ramirez-Ortiz 
24e35d0edbSJorge Ramirez-Ortiz #define REG_CPU_LP_CPU_SW_BEGIN		10
25e35d0edbSJorge Ramirez-Ortiz #define CPU_REG_COREPO_SRST		12
26e35d0edbSJorge Ramirez-Ortiz #define CPU_REG_CORE_SRST		8
27e35d0edbSJorge Ramirez-Ortiz 
28e35d0edbSJorge Ramirez-Ortiz static void poplar_cpu_standby(plat_local_state_t cpu_state)
29e35d0edbSJorge Ramirez-Ortiz {
30e35d0edbSJorge Ramirez-Ortiz 	dsb();
31e35d0edbSJorge Ramirez-Ortiz 	wfi();
32e35d0edbSJorge Ramirez-Ortiz }
33e35d0edbSJorge Ramirez-Ortiz 
34e35d0edbSJorge Ramirez-Ortiz static int poplar_pwr_domain_on(u_register_t mpidr)
35e35d0edbSJorge Ramirez-Ortiz {
36e35d0edbSJorge Ramirez-Ortiz 	unsigned int cpu = plat_core_pos_by_mpidr(mpidr);
37e35d0edbSJorge Ramirez-Ortiz 	unsigned int regval, regval_bak;
38e35d0edbSJorge Ramirez-Ortiz 
39e35d0edbSJorge Ramirez-Ortiz 	/* Select 400MHz before start slave cores */
40e35d0edbSJorge Ramirez-Ortiz 	regval_bak = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP));
41e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x206);
42e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x606);
43e35d0edbSJorge Ramirez-Ortiz 
44e35d0edbSJorge Ramirez-Ortiz 	/* Clear the slave cpu arm_por_srst_req reset */
45e35d0edbSJorge Ramirez-Ortiz 	regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST));
46e35d0edbSJorge Ramirez-Ortiz 	regval &= ~(1 << (cpu + CPU_REG_COREPO_SRST));
47e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval);
48e35d0edbSJorge Ramirez-Ortiz 
49e35d0edbSJorge Ramirez-Ortiz 	/* Clear the slave cpu reset */
50e35d0edbSJorge Ramirez-Ortiz 	regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST));
51e35d0edbSJorge Ramirez-Ortiz 	regval &= ~(1 << (cpu + CPU_REG_CORE_SRST));
52e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval);
53e35d0edbSJorge Ramirez-Ortiz 
54e35d0edbSJorge Ramirez-Ortiz 	/* Restore cpu frequency */
55e35d0edbSJorge Ramirez-Ortiz 	regval = regval_bak & (~(1 << REG_CPU_LP_CPU_SW_BEGIN));
56e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval);
57e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval_bak);
58e35d0edbSJorge Ramirez-Ortiz 
59e35d0edbSJorge Ramirez-Ortiz 	return PSCI_E_SUCCESS;
60e35d0edbSJorge Ramirez-Ortiz }
61e35d0edbSJorge Ramirez-Ortiz 
62e35d0edbSJorge Ramirez-Ortiz static void poplar_pwr_domain_off(const psci_power_state_t *target_state)
63e35d0edbSJorge Ramirez-Ortiz {
64e35d0edbSJorge Ramirez-Ortiz 	assert(0);
65e35d0edbSJorge Ramirez-Ortiz }
66e35d0edbSJorge Ramirez-Ortiz 
67e35d0edbSJorge Ramirez-Ortiz static void poplar_pwr_domain_suspend(const psci_power_state_t *target_state)
68e35d0edbSJorge Ramirez-Ortiz {
69e35d0edbSJorge Ramirez-Ortiz 	assert(0);
70e35d0edbSJorge Ramirez-Ortiz }
71e35d0edbSJorge Ramirez-Ortiz 
72e35d0edbSJorge Ramirez-Ortiz static void poplar_pwr_domain_on_finish(const psci_power_state_t *target_state)
73e35d0edbSJorge Ramirez-Ortiz {
74e35d0edbSJorge Ramirez-Ortiz 	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
75e35d0edbSJorge Ramirez-Ortiz 					PLAT_MAX_OFF_STATE);
76e35d0edbSJorge Ramirez-Ortiz 
77e35d0edbSJorge Ramirez-Ortiz 	/* Enable the gic cpu interface */
78*0818e9e8SAntonio Nino Diaz 	poplar_gic_pcpu_init();
79e35d0edbSJorge Ramirez-Ortiz 
80e35d0edbSJorge Ramirez-Ortiz 	/* Program the gic per-cpu distributor or re-distributor interface */
81*0818e9e8SAntonio Nino Diaz 	poplar_gic_cpuif_enable();
82e35d0edbSJorge Ramirez-Ortiz }
83e35d0edbSJorge Ramirez-Ortiz 
84e35d0edbSJorge Ramirez-Ortiz static void poplar_pwr_domain_suspend_finish(
85e35d0edbSJorge Ramirez-Ortiz 		const psci_power_state_t *target_state)
86e35d0edbSJorge Ramirez-Ortiz {
87e35d0edbSJorge Ramirez-Ortiz 	assert(0);
88e35d0edbSJorge Ramirez-Ortiz }
89e35d0edbSJorge Ramirez-Ortiz 
90e35d0edbSJorge Ramirez-Ortiz static void __dead2 poplar_system_off(void)
91e35d0edbSJorge Ramirez-Ortiz {
92e35d0edbSJorge Ramirez-Ortiz 	ERROR("Poplar System Off: operation not handled.\n");
93e35d0edbSJorge Ramirez-Ortiz 	panic();
94e35d0edbSJorge Ramirez-Ortiz }
95e35d0edbSJorge Ramirez-Ortiz 
96e35d0edbSJorge Ramirez-Ortiz static void __dead2 poplar_system_reset(void)
97e35d0edbSJorge Ramirez-Ortiz {
98e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0xc00), 0x1ACCE551);
99e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x0),   0x00000100);
100e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x8),   0x00000003);
101e35d0edbSJorge Ramirez-Ortiz 
102e35d0edbSJorge Ramirez-Ortiz 	wfi();
103e35d0edbSJorge Ramirez-Ortiz 	ERROR("Poplar System Reset: operation not handled.\n");
104e35d0edbSJorge Ramirez-Ortiz 	panic();
105e35d0edbSJorge Ramirez-Ortiz }
106e35d0edbSJorge Ramirez-Ortiz 
107e35d0edbSJorge Ramirez-Ortiz static int32_t poplar_validate_power_state(unsigned int power_state,
108e35d0edbSJorge Ramirez-Ortiz 					   psci_power_state_t *req_state)
109e35d0edbSJorge Ramirez-Ortiz {
110e35d0edbSJorge Ramirez-Ortiz 	VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
111e35d0edbSJorge Ramirez-Ortiz 
112e35d0edbSJorge Ramirez-Ortiz 	int pstate = psci_get_pstate_type(power_state);
113e35d0edbSJorge Ramirez-Ortiz 
114e35d0edbSJorge Ramirez-Ortiz 	assert(req_state);
115e35d0edbSJorge Ramirez-Ortiz 
116e35d0edbSJorge Ramirez-Ortiz 	/* Sanity check the requested state */
117e35d0edbSJorge Ramirez-Ortiz 	if (pstate == PSTATE_TYPE_STANDBY)
118e35d0edbSJorge Ramirez-Ortiz 		req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
119e35d0edbSJorge Ramirez-Ortiz 	else
120e35d0edbSJorge Ramirez-Ortiz 		req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
121e35d0edbSJorge Ramirez-Ortiz 
122e35d0edbSJorge Ramirez-Ortiz 	/* We expect the 'state id' to be zero */
123e35d0edbSJorge Ramirez-Ortiz 	if (psci_get_pstate_id(power_state))
124e35d0edbSJorge Ramirez-Ortiz 		return PSCI_E_INVALID_PARAMS;
125e35d0edbSJorge Ramirez-Ortiz 
126e35d0edbSJorge Ramirez-Ortiz 	return PSCI_E_SUCCESS;
127e35d0edbSJorge Ramirez-Ortiz }
128e35d0edbSJorge Ramirez-Ortiz 
129e35d0edbSJorge Ramirez-Ortiz static int poplar_validate_ns_entrypoint(uintptr_t entrypoint)
130e35d0edbSJorge Ramirez-Ortiz {
131e35d0edbSJorge Ramirez-Ortiz 	/*
132e35d0edbSJorge Ramirez-Ortiz 	 * Check if the non secure entrypoint lies within the non
133e35d0edbSJorge Ramirez-Ortiz 	 * secure DRAM.
134e35d0edbSJorge Ramirez-Ortiz 	 */
135e35d0edbSJorge Ramirez-Ortiz 	if ((entrypoint >= DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
136e35d0edbSJorge Ramirez-Ortiz 		return PSCI_E_SUCCESS;
137e35d0edbSJorge Ramirez-Ortiz 
138e35d0edbSJorge Ramirez-Ortiz 	return PSCI_E_INVALID_ADDRESS;
139e35d0edbSJorge Ramirez-Ortiz }
140e35d0edbSJorge Ramirez-Ortiz 
141e35d0edbSJorge Ramirez-Ortiz static void poplar_get_sys_suspend_power_state(psci_power_state_t *req_state)
142e35d0edbSJorge Ramirez-Ortiz {
143e35d0edbSJorge Ramirez-Ortiz 	int i;
144e35d0edbSJorge Ramirez-Ortiz 
145e35d0edbSJorge Ramirez-Ortiz 	for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
146e35d0edbSJorge Ramirez-Ortiz 		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
147e35d0edbSJorge Ramirez-Ortiz }
148e35d0edbSJorge Ramirez-Ortiz 
149e35d0edbSJorge Ramirez-Ortiz static const plat_psci_ops_t poplar_plat_psci_ops = {
150e35d0edbSJorge Ramirez-Ortiz 	.cpu_standby			= poplar_cpu_standby,
151e35d0edbSJorge Ramirez-Ortiz 	.pwr_domain_on			= poplar_pwr_domain_on,
152e35d0edbSJorge Ramirez-Ortiz 	.pwr_domain_off			= poplar_pwr_domain_off,
153e35d0edbSJorge Ramirez-Ortiz 	.pwr_domain_suspend		= poplar_pwr_domain_suspend,
154e35d0edbSJorge Ramirez-Ortiz 	.pwr_domain_on_finish		= poplar_pwr_domain_on_finish,
155e35d0edbSJorge Ramirez-Ortiz 	.pwr_domain_suspend_finish	= poplar_pwr_domain_suspend_finish,
156e35d0edbSJorge Ramirez-Ortiz 	.system_off			= poplar_system_off,
157e35d0edbSJorge Ramirez-Ortiz 	.system_reset			= poplar_system_reset,
158e35d0edbSJorge Ramirez-Ortiz 	.validate_power_state		= poplar_validate_power_state,
159e35d0edbSJorge Ramirez-Ortiz 	.validate_ns_entrypoint		= poplar_validate_ns_entrypoint,
160e35d0edbSJorge Ramirez-Ortiz 	.get_sys_suspend_power_state	= poplar_get_sys_suspend_power_state,
161e35d0edbSJorge Ramirez-Ortiz };
162e35d0edbSJorge Ramirez-Ortiz 
163e35d0edbSJorge Ramirez-Ortiz int plat_setup_psci_ops(uintptr_t sec_entrypoint,
164e35d0edbSJorge Ramirez-Ortiz 			const plat_psci_ops_t **psci_ops)
165e35d0edbSJorge Ramirez-Ortiz {
166e35d0edbSJorge Ramirez-Ortiz 	*psci_ops = &poplar_plat_psci_ops;
167e35d0edbSJorge Ramirez-Ortiz 
168e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)REG_PERI_CPU_AARCH_MODE, 0xF);
169e35d0edbSJorge Ramirez-Ortiz 	mmio_write_32((uintptr_t)REG_PERI_CPU_RVBARADDR, sec_entrypoint);
170e35d0edbSJorge Ramirez-Ortiz 	return 0;
171e35d0edbSJorge Ramirez-Ortiz }
172