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