xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
1 /*
2  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 
9 #include <platform_def.h>
10 
11 #include <arch_helpers.h>
12 #include <lib/mmio.h>
13 #include <plat/common/platform.h>
14 
15 #include <../hikey960_def.h>
16 #include <hisi_ipc.h>
17 #include "hisi_pwrc.h"
18 
19 
20 /* resource lock api */
21 #define RES0_LOCK_BASE		(SOC_PCTRL_RESOURCE0_LOCK_ADDR(PCTRL_BASE))
22 #define RES1_LOCK_BASE		(SOC_PCTRL_RESOURCE1_LOCK_ADDR(PCTRL_BASE))
23 #define RES2_LOCK_BASE		(SOC_PCTRL_RESOURCE2_LOCK_ADDR(PCTRL_BASE))
24 
25 #define LOCK_BIT			(0x1 << 28)
26 #define LOCK_ID_MASK			(0x7 << 29)
27 #define CPUIDLE_LOCK_ID(core)		(0x6 - (core))
28 #define LOCK_UNLOCK_OFFSET		0x4
29 #define LOCK_STAT_OFFSET		0x8
30 
31 #define CLUSTER0_CPUS_ONLINE_MASK	(0xF << 16)
32 #define	CLUSTER1_CPUS_ONLINE_MASK	(0xF << 20)
33 
34 /* cpu hotplug flag api */
35 #define SCTRL_BASE			(SOC_ACPU_SCTRL_BASE_ADDR)
36 #define REG_SCBAKDATA3_OFFSET		(SOC_SCTRL_SCBAKDATA3_ADDR(SCTRL_BASE))
37 #define REG_SCBAKDATA8_OFFSET		(SOC_SCTRL_SCBAKDATA8_ADDR(SCTRL_BASE))
38 #define REG_SCBAKDATA9_OFFSET		(SOC_SCTRL_SCBAKDATA9_ADDR(SCTRL_BASE))
39 
40 #define CPUIDLE_FLAG_REG(cluster) \
41 			((cluster == 0) ? REG_SCBAKDATA8_OFFSET : \
42 			 REG_SCBAKDATA9_OFFSET)
43 #define CLUSTER_IDLE_BIT				BIT(8)
44 #define CLUSTER_IDLE_MASK		(CLUSTER_IDLE_BIT | 0x0F)
45 
46 #define AP_SUSPEND_FLAG			(1 << 16)
47 
48 #define CLUSTER_PWDN_IDLE		(0<<28)
49 #define CLUSTER_PWDN_HOTPLUG		(1<<28)
50 #define CLUSTER_PWDN_SR			(2<<28)
51 
52 #define CLUSTER0_PDC_OFFSET			0x260
53 #define CLUSTER1_PDC_OFFSET			0x300
54 
55 #define PDC_EN_OFFSET				0x0
56 #define PDC_COREPWRINTEN_OFFSET		0x4
57 #define PDC_COREPWRINTSTAT_OFFSET	0x8
58 #define PDC_COREGICMASK_OFFSET		0xc
59 #define PDC_COREPOWERUP_OFFSET		0x10
60 #define PDC_COREPOWERDN_OFFSET		0x14
61 #define PDC_COREPOWERSTAT_OFFSET	0x18
62 
63 #define PDC_COREPWRSTAT_MASK   (0XFFFF)
64 
65 enum pdc_gic_mask {
66 	PDC_MASK_GIC_WAKE_IRQ,
67 	PDC_UNMASK_GIC_WAKE_IRQ
68 };
69 
70 enum pdc_finish_int_mask {
71 	PDC_DISABLE_FINISH_INT,
72 	PDC_ENABLE_FINISH_INT
73 };
74 
75 static void hisi_resource_lock(unsigned int lockid, unsigned int offset)
76 {
77 	unsigned int lock_id = (lockid << 29);
78 	unsigned int lock_val =  lock_id | LOCK_BIT;
79 	unsigned int lock_state;
80 
81 	do {
82 		mmio_write_32(offset, lock_val);
83 		lock_state = mmio_read_32(LOCK_STAT_OFFSET + (uintptr_t)offset);
84 	} while ((lock_state & LOCK_ID_MASK) != lock_id);
85 }
86 
87 static void hisi_resource_unlock(unsigned int lockid, unsigned int offset)
88 {
89 	unsigned int lock_val = (lockid << 29) | LOCK_BIT;
90 
91 	mmio_write_32((LOCK_UNLOCK_OFFSET + (uintptr_t)offset), lock_val);
92 }
93 
94 
95 static void hisi_cpuhotplug_lock(unsigned int cluster, unsigned int core)
96 {
97 	unsigned int lock_id;
98 
99 	lock_id = (cluster << 2) + core;
100 
101 	hisi_resource_lock(lock_id, RES2_LOCK_BASE);
102 }
103 
104 static void hisi_cpuhotplug_unlock(unsigned int cluster, unsigned int core)
105 {
106 	unsigned int lock_id;
107 
108 	lock_id = (cluster << 2) + core;
109 
110 	hisi_resource_unlock(lock_id, RES2_LOCK_BASE);
111 }
112 
113 /* get the resource lock */
114 void hisi_cpuidle_lock(unsigned int cluster, unsigned int core)
115 {
116 	unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE);
117 
118 	hisi_resource_lock(CPUIDLE_LOCK_ID(core), offset);
119 }
120 
121 /* release the resource lock */
122 void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core)
123 {
124 	unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE);
125 
126 	hisi_resource_unlock(CPUIDLE_LOCK_ID(core), offset);
127 }
128 
129 unsigned int hisi_get_cpuidle_flag(unsigned int cluster)
130 {
131 	unsigned int val;
132 
133 	val = mmio_read_32(CPUIDLE_FLAG_REG(cluster));
134 	val &= 0xF;
135 
136 	return val;
137 }
138 
139 void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core)
140 {
141 	mmio_setbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core));
142 }
143 
144 void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core)
145 {
146 	mmio_clrbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core));
147 
148 }
149 
150 int hisi_test_ap_suspend_flag(unsigned int cluster)
151 {
152 	unsigned int val;
153 
154 	val = mmio_read_32(CPUIDLE_FLAG_REG(cluster));
155 	val &= AP_SUSPEND_FLAG;
156 	return !!val;
157 }
158 
159 void hisi_set_cluster_pwdn_flag(unsigned int cluster,
160 				unsigned int core, unsigned int value)
161 {
162 	unsigned int val;
163 
164 	hisi_cpuhotplug_lock(cluster, core);
165 
166 	val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
167 	val = (value << (cluster << 1)) | (val & 0xFFFFFFF);
168 	mmio_write_32(REG_SCBAKDATA3_OFFSET, val);
169 
170 	hisi_cpuhotplug_unlock(cluster, core);
171 }
172 
173 unsigned int hisi_get_cpu_boot_flag(unsigned int cluster, unsigned int core)
174 {
175 	unsigned int val;
176 
177 	hisi_cpuhotplug_lock(cluster, core);
178 	val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
179 	val = val >> (16 + (cluster << 2));
180 	val &= 0xF;
181 	hisi_cpuhotplug_unlock(cluster, core);
182 
183 	return val;
184 }
185 
186 unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core)
187 {
188 	unsigned int val;
189 
190 	hisi_cpuhotplug_lock(cluster, core);
191 	val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
192 	val = val >> (16 + (cluster << 2));
193 	val &= 0xF;
194 	hisi_cpuhotplug_unlock(cluster, core);
195 
196 	if (val)
197 		return 0;
198 	else
199 		return 1;
200 }
201 
202 void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core)
203 {
204 	unsigned int flag = BIT((cluster<<2) + core + 16);
205 
206 	hisi_cpuhotplug_lock(cluster, core);
207 
208 	mmio_setbits_32(REG_SCBAKDATA3_OFFSET, flag);
209 
210 	hisi_cpuhotplug_unlock(cluster, core);
211 }
212 
213 void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core)
214 {
215 	unsigned int flag = BIT((cluster<<2) + core + 16);
216 
217 	hisi_cpuhotplug_lock(cluster, core);
218 
219 	mmio_clrbits_32(REG_SCBAKDATA3_OFFSET, flag);
220 
221 	hisi_cpuhotplug_unlock(cluster, core);
222 }
223 
224 int cluster_is_powered_on(unsigned int cluster)
225 {
226 	unsigned int val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
227 	int ret;
228 
229 	if (cluster == 0)
230 		ret = val & CLUSTER0_CPUS_ONLINE_MASK;
231 	else
232 		ret = val & CLUSTER1_CPUS_ONLINE_MASK;
233 
234 	return !!ret;
235 }
236 
237 static void *hisi_get_pdc_addr(unsigned int cluster)
238 {
239 	void *pdc_base_addr;
240 	uintptr_t addr;
241 
242 	if (cluster == 0)
243 		addr = SOC_CRGPERIPH_A53_PDCEN_ADDR(CRG_BASE);
244 	else
245 		addr = SOC_CRGPERIPH_MAIA_PDCEN_ADDR(CRG_BASE);
246 	pdc_base_addr = (void *)addr;
247 
248 	return pdc_base_addr;
249 }
250 
251 static unsigned int hisi_get_pdc_stat(unsigned int cluster)
252 {
253 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
254 	unsigned int val;
255 
256 	val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPOWERSTAT_OFFSET);
257 
258 	return val;
259 }
260 
261 int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core)
262 {
263 	unsigned int mask = 0xf << (core * 4);
264 	unsigned int pdc_stat = hisi_get_pdc_stat(cluster);
265 	unsigned int boot_flag = hisi_get_cpu_boot_flag(cluster, core);
266 	unsigned int cpuidle_flag = hisi_get_cpuidle_flag(cluster);
267 
268 	mask = (PDC_COREPWRSTAT_MASK & (~mask));
269 	pdc_stat &= mask;
270 
271 	if ((boot_flag ^ cpuidle_flag) || pdc_stat)
272 		return 0;
273 	else
274 		return 1;
275 }
276 
277 void hisi_disable_pdc(unsigned int cluster)
278 {
279 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
280 
281 	mmio_write_32((uintptr_t)pdc_base_addr, 0x0);
282 }
283 
284 void hisi_enable_pdc(unsigned int cluster)
285 {
286 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
287 
288 	mmio_write_32((uintptr_t)pdc_base_addr, 0x1);
289 }
290 
291 void hisi_pdc_set_intmask(void *pdc_base_addr,
292 			unsigned int core,
293 			enum pdc_finish_int_mask intmask)
294 {
295 	unsigned int val;
296 
297 	val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET);
298 	if (intmask == PDC_ENABLE_FINISH_INT)
299 		val |= BIT(core);
300 	else
301 		val &= ~BIT(core);
302 
303 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, val);
304 }
305 
306 static inline void hisi_pdc_set_gicmask(void *pdc_base_addr,
307 					unsigned int core,
308 					enum pdc_gic_mask gicmask)
309 {
310 	unsigned int val;
311 
312 	val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET);
313 	if (gicmask == PDC_MASK_GIC_WAKE_IRQ)
314 		val |= BIT(core);
315 	else
316 		val &= ~BIT(core);
317 
318 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET, val);
319 }
320 
321 void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster)
322 {
323 	int i;
324 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
325 
326 	for (i = 0; i < 4; i++)
327 		hisi_pdc_set_gicmask(pdc_base_addr, i, PDC_MASK_GIC_WAKE_IRQ);
328 }
329 
330 static void hisi_pdc_powerup_core(unsigned int cluster, unsigned int core,
331 				  enum pdc_gic_mask gicmask,
332 				  enum pdc_finish_int_mask intmask)
333 {
334 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
335 
336 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERUP_OFFSET,
337 		      BIT(core));
338 }
339 
340 static void hisi_pdc_powerdn_core(unsigned int cluster, unsigned int core,
341 				  enum pdc_gic_mask gicmask,
342 				  enum pdc_finish_int_mask intmask)
343 {
344 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
345 
346 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET,
347 		      BIT(core));
348 }
349 
350 void hisi_powerup_core(unsigned int cluster, unsigned int core)
351 {
352 	hisi_pdc_powerup_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ,
353 			      PDC_DISABLE_FINISH_INT);
354 }
355 
356 void hisi_powerdn_core(unsigned int cluster, unsigned int core)
357 {
358 	hisi_pdc_powerdn_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ,
359 			      PDC_DISABLE_FINISH_INT);
360 }
361 
362 void hisi_powerup_cluster(unsigned int cluster, unsigned int core)
363 {
364 	hisi_ipc_pm_on_off(core, cluster, PM_ON);
365 }
366 
367 void hisi_powerdn_cluster(unsigned int cluster, unsigned int core)
368 {
369 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
370 
371 	hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_HOTPLUG);
372 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET,
373 		      (0x10001 << core));
374 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET,
375 		      BIT(core));
376 }
377 
378 void hisi_enter_core_idle(unsigned int cluster, unsigned int core)
379 {
380 	hisi_pdc_powerdn_core(cluster, core, PDC_UNMASK_GIC_WAKE_IRQ,
381 			      PDC_DISABLE_FINISH_INT);
382 }
383 
384 void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core)
385 {
386 	void *pdc_base_addr = hisi_get_pdc_addr(cluster);
387 
388 	hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_IDLE);
389 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET,
390 		      (0x10001 << core));
391 	mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET,
392 		      BIT(core));
393 }
394 
395 void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core)
396 {
397 	hisi_ipc_pm_suspend(core, cluster, 0x3);
398 }
399