xref: /rk3399_ARM-atf/plat/mediatek/mt8173/plat_pm.c (revision 51faada71a219a8b94cd8d8e423f0f22e9da4d8f)
1 /*
2  * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of ARM nor the names of its contributors may be used
15  * to endorse or promote products derived from this software without specific
16  * prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <arch_helpers.h>
32 #include <assert.h>
33 #include <bakery_lock.h>
34 #include <cci.h>
35 #include <console.h>
36 #include <debug.h>
37 #include <errno.h>
38 #include <gicv2.h>
39 #include <mcucfg.h>
40 #include <mmio.h>
41 #include <mt8173_def.h>
42 #include <mt_cpuxgpt.h> /* generic_timer_backup() */
43 #include <plat_arm.h>
44 #include <plat_private.h>
45 #include <power_tracer.h>
46 #include <psci.h>
47 #include <rtc.h>
48 #include <scu.h>
49 #include <spm_hotplug.h>
50 #include <spm_mcdi.h>
51 #include <spm_suspend.h>
52 
53 #if !ENABLE_PLAT_COMPAT
54 #define MTK_PWR_LVL0	0
55 #define MTK_PWR_LVL1	1
56 #define MTK_PWR_LVL2	2
57 
58 /* Macros to read the MTK power domain state */
59 #define MTK_CORE_PWR_STATE(state)	(state)->pwr_domain_state[MTK_PWR_LVL0]
60 #define MTK_CLUSTER_PWR_STATE(state)	(state)->pwr_domain_state[MTK_PWR_LVL1]
61 #define MTK_SYSTEM_PWR_STATE(state)	((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) ?\
62 			(state)->pwr_domain_state[MTK_PWR_LVL2] : 0)
63 #endif
64 
65 #if PSCI_EXTENDED_STATE_ID
66 /*
67  *  The table storing the valid idle power states. Ensure that the
68  *  array entries are populated in ascending order of state-id to
69  *  enable us to use binary search during power state validation.
70  *  The table must be terminated by a NULL entry.
71  */
72 const unsigned int mtk_pm_idle_states[] = {
73 	/* State-id - 0x001 */
74 	mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
75 		MTK_LOCAL_STATE_RET, MTK_PWR_LVL0, PSTATE_TYPE_STANDBY),
76 	/* State-id - 0x002 */
77 	mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
78 		MTK_LOCAL_STATE_OFF, MTK_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
79 	/* State-id - 0x022 */
80 	mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_OFF,
81 		MTK_LOCAL_STATE_OFF, MTK_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
82 #if PLAT_MAX_PWR_LVL > MTK_PWR_LVL1
83 	/* State-id - 0x222 */
84 	mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_OFF, MTK_LOCAL_STATE_OFF,
85 		MTK_LOCAL_STATE_OFF, MTK_PWR_LVL2, PSTATE_TYPE_POWERDOWN),
86 #endif
87 	0,
88 };
89 #endif
90 
91 struct core_context {
92 	unsigned long timer_data[8];
93 	unsigned int count;
94 	unsigned int rst;
95 	unsigned int abt;
96 	unsigned int brk;
97 };
98 
99 struct cluster_context {
100 	struct core_context core[PLATFORM_MAX_CPUS_PER_CLUSTER];
101 };
102 
103 /*
104  * Top level structure to hold the complete context of a multi cluster system
105  */
106 struct system_context {
107 	struct cluster_context cluster[PLATFORM_CLUSTER_COUNT];
108 };
109 
110 /*
111  * Top level structure which encapsulates the context of the entire system
112  */
113 static struct system_context dormant_data[1];
114 
115 static inline struct cluster_context *system_cluster(
116 						struct system_context *system,
117 						uint32_t clusterid)
118 {
119 	return &system->cluster[clusterid];
120 }
121 
122 static inline struct core_context *cluster_core(struct cluster_context *cluster,
123 						uint32_t cpuid)
124 {
125 	return &cluster->core[cpuid];
126 }
127 
128 static struct cluster_context *get_cluster_data(unsigned long mpidr)
129 {
130 	uint32_t clusterid;
131 
132 	clusterid = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
133 
134 	return system_cluster(dormant_data, clusterid);
135 }
136 
137 static struct core_context *get_core_data(unsigned long mpidr)
138 {
139 	struct cluster_context *cluster;
140 	uint32_t cpuid;
141 
142 	cluster = get_cluster_data(mpidr);
143 	cpuid = mpidr & MPIDR_CPU_MASK;
144 
145 	return cluster_core(cluster, cpuid);
146 }
147 
148 static void mt_save_generic_timer(unsigned long *container)
149 {
150 	uint64_t ctl;
151 	uint64_t val;
152 
153 	__asm__ volatile("mrs	%x0, cntkctl_el1\n\t"
154 			 "mrs	%x1, cntp_cval_el0\n\t"
155 			 "stp	%x0, %x1, [%2, #0]"
156 			 : "=&r" (ctl), "=&r" (val)
157 			 : "r" (container)
158 			 : "memory");
159 
160 	__asm__ volatile("mrs	%x0, cntp_tval_el0\n\t"
161 			 "mrs	%x1, cntp_ctl_el0\n\t"
162 			 "stp	%x0, %x1, [%2, #16]"
163 			 : "=&r" (val), "=&r" (ctl)
164 			 : "r" (container)
165 			 : "memory");
166 
167 	__asm__ volatile("mrs	%x0, cntv_tval_el0\n\t"
168 			 "mrs	%x1, cntv_ctl_el0\n\t"
169 			 "stp	%x0, %x1, [%2, #32]"
170 			 : "=&r" (val), "=&r" (ctl)
171 			 : "r" (container)
172 			 : "memory");
173 }
174 
175 static void mt_restore_generic_timer(unsigned long *container)
176 {
177 	uint64_t ctl;
178 	uint64_t val;
179 
180 	__asm__ volatile("ldp	%x0, %x1, [%2, #0]\n\t"
181 			 "msr	cntkctl_el1, %x0\n\t"
182 			 "msr	cntp_cval_el0, %x1"
183 			 : "=&r" (ctl), "=&r" (val)
184 			 : "r" (container)
185 			 : "memory");
186 
187 	__asm__ volatile("ldp	%x0, %x1, [%2, #16]\n\t"
188 			 "msr	cntp_tval_el0, %x0\n\t"
189 			 "msr	cntp_ctl_el0, %x1"
190 			 : "=&r" (val), "=&r" (ctl)
191 			 : "r" (container)
192 			 : "memory");
193 
194 	__asm__ volatile("ldp	%x0, %x1, [%2, #32]\n\t"
195 			 "msr	cntv_tval_el0, %x0\n\t"
196 			 "msr	cntv_ctl_el0, %x1"
197 			 : "=&r" (val), "=&r" (ctl)
198 			 : "r" (container)
199 			 : "memory");
200 }
201 
202 static inline uint64_t read_cntpctl(void)
203 {
204 	uint64_t cntpctl;
205 
206 	__asm__ volatile("mrs	%x0, cntp_ctl_el0"
207 			 : "=r" (cntpctl) : : "memory");
208 
209 	return cntpctl;
210 }
211 
212 static inline void write_cntpctl(uint64_t cntpctl)
213 {
214 	__asm__ volatile("msr	cntp_ctl_el0, %x0" : : "r"(cntpctl));
215 }
216 
217 static void stop_generic_timer(void)
218 {
219 	/*
220 	 * Disable the timer and mask the irq to prevent
221 	 * suprious interrupts on this cpu interface. It
222 	 * will bite us when we come back if we don't. It
223 	 * will be replayed on the inbound cluster.
224 	 */
225 	uint64_t cntpctl = read_cntpctl();
226 
227 	write_cntpctl(clr_cntp_ctl_enable(cntpctl));
228 }
229 
230 static void mt_cpu_save(unsigned long mpidr)
231 {
232 	struct core_context *core;
233 
234 	core = get_core_data(mpidr);
235 	mt_save_generic_timer(core->timer_data);
236 
237 	/* disable timer irq, and upper layer should enable it again. */
238 	stop_generic_timer();
239 }
240 
241 static void mt_cpu_restore(unsigned long mpidr)
242 {
243 	struct core_context *core;
244 
245 	core = get_core_data(mpidr);
246 	mt_restore_generic_timer(core->timer_data);
247 }
248 
249 static void mt_platform_save_context(unsigned long mpidr)
250 {
251 	/* mcusys_save_context: */
252 	mt_cpu_save(mpidr);
253 }
254 
255 static void mt_platform_restore_context(unsigned long mpidr)
256 {
257 	/* mcusys_restore_context: */
258 	mt_cpu_restore(mpidr);
259 }
260 
261 #if ENABLE_PLAT_COMPAT
262 /*******************************************************************************
263 * Private function which is used to determine if any platform actions
264 * should be performed for the specified affinity instance given its
265 * state. Nothing needs to be done if the 'state' is not off or if this is not
266 * the highest affinity level which will enter the 'state'.
267 *******************************************************************************/
268 static int32_t plat_do_plat_actions(unsigned int afflvl, unsigned int state)
269 {
270 	unsigned int max_phys_off_afflvl;
271 
272 	assert(afflvl <= MPIDR_AFFLVL2);
273 
274 	if (state != PSCI_STATE_OFF)
275 		return -EAGAIN;
276 
277 	/*
278 	 * Find the highest affinity level which will be suspended and postpone
279 	 * all the platform specific actions until that level is hit.
280 	 */
281 	max_phys_off_afflvl = psci_get_max_phys_off_afflvl();
282 	assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
283 	if (afflvl != max_phys_off_afflvl)
284 		return -EAGAIN;
285 
286 	return 0;
287 }
288 
289 /*******************************************************************************
290  * MTK_platform handler called when an affinity instance is about to enter
291  * standby.
292  ******************************************************************************/
293 static void plat_affinst_standby(unsigned int power_state)
294 {
295 	unsigned int target_afflvl;
296 
297 	/* Sanity check the requested state */
298 	target_afflvl = psci_get_pstate_afflvl(power_state);
299 
300 	/*
301 	 * It's possible to enter standby only on affinity level 0 i.e. a cpu
302 	 * on the MTK_platform. Ignore any other affinity level.
303 	 */
304 	if (target_afflvl == MPIDR_AFFLVL0) {
305 		/*
306 		 * Enter standby state. dsb is good practice before using wfi
307 		 * to enter low power states.
308 		 */
309 		dsb();
310 		wfi();
311 	}
312 }
313 #else
314 static void plat_cpu_standby(plat_local_state_t cpu_state)
315 {
316 	unsigned int scr;
317 
318 	scr = read_scr_el3();
319 	write_scr_el3(scr | SCR_IRQ_BIT);
320 	isb();
321 	dsb();
322 	wfi();
323 	write_scr_el3(scr);
324 }
325 #endif
326 
327 /*******************************************************************************
328  * MTK_platform handler called when an affinity instance is about to be turned
329  * on. The level and mpidr determine the affinity instance.
330  ******************************************************************************/
331 #if ENABLE_PLAT_COMPAT
332 static int plat_affinst_on(unsigned long mpidr,
333 		    unsigned long sec_entrypoint,
334 		    unsigned int afflvl,
335 		    unsigned int state)
336 {
337 	int rc = PSCI_E_SUCCESS;
338 	unsigned long cpu_id;
339 	unsigned long cluster_id;
340 	uintptr_t rv;
341 
342 	/*
343 	 * It's possible to turn on only affinity level 0 i.e. a cpu
344 	 * on the MTK_platform. Ignore any other affinity level.
345 	 */
346 	if (afflvl != MPIDR_AFFLVL0)
347 		return rc;
348 
349 	cpu_id = mpidr & MPIDR_CPU_MASK;
350 	cluster_id = mpidr & MPIDR_CLUSTER_MASK;
351 
352 	if (cluster_id)
353 		rv = (uintptr_t)&mt8173_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw;
354 	else
355 		rv = (uintptr_t)&mt8173_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw;
356 
357 	mmio_write_32(rv, sec_entrypoint);
358 	INFO("mt_on[%ld:%ld], entry %x\n",
359 		cluster_id, cpu_id, mmio_read_32(rv));
360 
361 	spm_hotplug_on(mpidr);
362 
363 	return rc;
364 }
365 #else
366 static uintptr_t secure_entrypoint;
367 
368 static int plat_power_domain_on(unsigned long mpidr)
369 {
370 	int rc = PSCI_E_SUCCESS;
371 	unsigned long cpu_id;
372 	unsigned long cluster_id;
373 	uintptr_t rv;
374 
375 	cpu_id = mpidr & MPIDR_CPU_MASK;
376 	cluster_id = mpidr & MPIDR_CLUSTER_MASK;
377 
378 	if (cluster_id)
379 		rv = (uintptr_t)&mt8173_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw;
380 	else
381 		rv = (uintptr_t)&mt8173_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw;
382 
383 	mmio_write_32(rv, secure_entrypoint);
384 	INFO("mt_on[%ld:%ld], entry %x\n",
385 		cluster_id, cpu_id, mmio_read_32(rv));
386 
387 	spm_hotplug_on(mpidr);
388 	return rc;
389 }
390 #endif
391 
392 /*******************************************************************************
393  * MTK_platform handler called when an affinity instance is about to be turned
394  * off. The level and mpidr determine the affinity instance. The 'state' arg.
395  * allows the platform to decide whether the cluster is being turned off and
396  * take apt actions.
397  *
398  * CAUTION: This function is called with coherent stacks so that caches can be
399  * turned off, flushed and coherency disabled. There is no guarantee that caches
400  * will remain turned on across calls to this function as each affinity level is
401  * dealt with. So do not write & read global variables across calls. It will be
402  * wise to do flush a write to the global to prevent unpredictable results.
403  ******************************************************************************/
404 #if ENABLE_PLAT_COMPAT
405 static void plat_affinst_off(unsigned int afflvl, unsigned int state)
406 {
407 	unsigned long mpidr = read_mpidr_el1();
408 
409 	/* Determine if any platform actions need to be executed. */
410 	if (plat_do_plat_actions(afflvl, state) == -EAGAIN)
411 		return;
412 
413 	/* Prevent interrupts from spuriously waking up this cpu */
414 	gicv2_cpuif_disable();
415 
416 	spm_hotplug_off(mpidr);
417 
418 	trace_power_flow(mpidr, CPU_DOWN);
419 
420 	if (afflvl != MPIDR_AFFLVL0) {
421 		/* Disable coherency if this cluster is to be turned off */
422 		plat_cci_disable();
423 
424 		trace_power_flow(mpidr, CLUSTER_DOWN);
425 	}
426 }
427 #else
428 static void plat_power_domain_off(const psci_power_state_t *state)
429 {
430 	unsigned long mpidr = read_mpidr_el1();
431 
432 	/* Prevent interrupts from spuriously waking up this cpu */
433 	gicv2_cpuif_disable();
434 
435 	spm_hotplug_off(mpidr);
436 
437 	trace_power_flow(mpidr, CPU_DOWN);
438 
439 	if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
440 		/* Disable coherency if this cluster is to be turned off */
441 		plat_cci_disable();
442 
443 		trace_power_flow(mpidr, CLUSTER_DOWN);
444 	}
445 }
446 #endif
447 
448 /*******************************************************************************
449  * MTK_platform handler called when an affinity instance is about to be
450  * suspended. The level and mpidr determine the affinity instance. The 'state'
451  * arg. allows the platform to decide whether the cluster is being turned off
452  * and take apt actions.
453  *
454  * CAUTION: This function is called with coherent stacks so that caches can be
455  * turned off, flushed and coherency disabled. There is no guarantee that caches
456  * will remain turned on across calls to this function as each affinity level is
457  * dealt with. So do not write & read global variables across calls. It will be
458  * wise to do flush a write to the global to prevent unpredictable results.
459  ******************************************************************************/
460 #if ENABLE_PLAT_COMPAT
461 static void plat_affinst_suspend(unsigned long sec_entrypoint,
462 			  unsigned int afflvl,
463 			  unsigned int state)
464 {
465 	unsigned long mpidr = read_mpidr_el1();
466 	unsigned long cluster_id;
467 	unsigned long cpu_id;
468 	uintptr_t rv;
469 
470 	/* Determine if any platform actions need to be executed. */
471 	if (plat_do_plat_actions(afflvl, state) == -EAGAIN)
472 		return;
473 
474 	cpu_id = mpidr & MPIDR_CPU_MASK;
475 	cluster_id = mpidr & MPIDR_CLUSTER_MASK;
476 
477 	if (cluster_id)
478 		rv = (uintptr_t)&mt8173_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw;
479 	else
480 		rv = (uintptr_t)&mt8173_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw;
481 
482 	mmio_write_32(rv, sec_entrypoint);
483 
484 	if (afflvl < MPIDR_AFFLVL2)
485 		spm_mcdi_prepare_for_off_state(mpidr, afflvl);
486 
487 	if (afflvl >= MPIDR_AFFLVL0)
488 		mt_platform_save_context(mpidr);
489 
490 	/* Perform the common cluster specific operations */
491 	if (afflvl >= MPIDR_AFFLVL1) {
492 		/* Disable coherency if this cluster is to be turned off */
493 		plat_cci_disable();
494 	}
495 
496 	if (afflvl >= MPIDR_AFFLVL2) {
497 		disable_scu(mpidr);
498 		generic_timer_backup();
499 		spm_system_suspend();
500 		/* Prevent interrupts from spuriously waking up this cpu */
501 		gicv2_cpuif_disable();
502 	}
503 }
504 #else
505 static void plat_power_domain_suspend(const psci_power_state_t *state)
506 {
507 	unsigned long mpidr = read_mpidr_el1();
508 	unsigned long cluster_id;
509 	unsigned long cpu_id;
510 	uintptr_t rv;
511 
512 	cpu_id = mpidr & MPIDR_CPU_MASK;
513 	cluster_id = mpidr & MPIDR_CLUSTER_MASK;
514 
515 	if (cluster_id)
516 		rv = (uintptr_t)&mt8173_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw;
517 	else
518 		rv = (uintptr_t)&mt8173_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw;
519 
520 	mmio_write_32(rv, secure_entrypoint);
521 
522 	if (MTK_SYSTEM_PWR_STATE(state) != MTK_LOCAL_STATE_OFF) {
523 		spm_mcdi_prepare_for_off_state(mpidr, MTK_PWR_LVL0);
524 		if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF)
525 			spm_mcdi_prepare_for_off_state(mpidr, MTK_PWR_LVL1);
526 	}
527 
528 	mt_platform_save_context(mpidr);
529 
530 	/* Perform the common cluster specific operations */
531 	if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
532 		/* Disable coherency if this cluster is to be turned off */
533 		plat_cci_disable();
534 	}
535 
536 	if (MTK_SYSTEM_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
537 		disable_scu(mpidr);
538 		generic_timer_backup();
539 		spm_system_suspend();
540 		/* Prevent interrupts from spuriously waking up this cpu */
541 		gicv2_cpuif_disable();
542 	}
543 }
544 #endif
545 
546 /*******************************************************************************
547  * MTK_platform handler called when an affinity instance has just been powered
548  * on after being turned off earlier. The level and mpidr determine the affinity
549  * instance. The 'state' arg. allows the platform to decide whether the cluster
550  * was turned off prior to wakeup and do what's necessary to setup it up
551  * correctly.
552  ******************************************************************************/
553 #if ENABLE_PLAT_COMPAT
554 static void plat_affinst_on_finish(unsigned int afflvl, unsigned int state)
555 {
556 	unsigned long mpidr = read_mpidr_el1();
557 
558 	/* Determine if any platform actions need to be executed. */
559 	if (plat_do_plat_actions(afflvl, state) == -EAGAIN)
560 		return;
561 
562 	/* Perform the common cluster specific operations */
563 	if (afflvl >= MPIDR_AFFLVL1) {
564 		/* Enable coherency if this cluster was off */
565 		plat_cci_enable();
566 		trace_power_flow(mpidr, CLUSTER_UP);
567 	}
568 
569 	/* Enable the gic cpu interface */
570 	gicv2_cpuif_enable();
571 	gicv2_pcpu_distif_init();
572 	trace_power_flow(mpidr, CPU_UP);
573 }
574 #else
575 void mtk_system_pwr_domain_resume(void);
576 
577 static void plat_power_domain_on_finish(const psci_power_state_t *state)
578 {
579 	unsigned long mpidr = read_mpidr_el1();
580 
581 	assert(state->pwr_domain_state[MPIDR_AFFLVL0] == MTK_LOCAL_STATE_OFF);
582 
583 	if ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) &&
584 		(state->pwr_domain_state[MTK_PWR_LVL2] == MTK_LOCAL_STATE_OFF))
585 		mtk_system_pwr_domain_resume();
586 
587 	if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) {
588 		plat_cci_enable();
589 		trace_power_flow(mpidr, CLUSTER_UP);
590 	}
591 
592 	if ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) &&
593 		(state->pwr_domain_state[MTK_PWR_LVL2] == MTK_LOCAL_STATE_OFF))
594 		return;
595 
596 	/* Enable the gic cpu interface */
597 	gicv2_cpuif_enable();
598 	gicv2_pcpu_distif_init();
599 	trace_power_flow(mpidr, CPU_UP);
600 }
601 #endif
602 
603 /*******************************************************************************
604  * MTK_platform handler called when an affinity instance has just been powered
605  * on after having been suspended earlier. The level and mpidr determine the
606  * affinity instance.
607  ******************************************************************************/
608 #if ENABLE_PLAT_COMPAT
609 static void plat_affinst_suspend_finish(unsigned int afflvl, unsigned int state)
610 {
611 	unsigned long mpidr = read_mpidr_el1();
612 
613 	/* Determine if any platform actions need to be executed. */
614 	if (plat_do_plat_actions(afflvl, state) == -EAGAIN)
615 		return;
616 
617 	if (afflvl >= MPIDR_AFFLVL2) {
618 		/* Enable the gic cpu interface */
619 		plat_arm_gic_init();
620 		spm_system_suspend_finish();
621 		enable_scu(mpidr);
622 	}
623 
624 	/* Perform the common cluster specific operations */
625 	if (afflvl >= MPIDR_AFFLVL1) {
626 		/* Enable coherency if this cluster was off */
627 		plat_cci_enable();
628 	}
629 
630 	if (afflvl >= MPIDR_AFFLVL0)
631 		mt_platform_restore_context(mpidr);
632 
633 	if (afflvl < MPIDR_AFFLVL2)
634 		spm_mcdi_finish_for_on_state(mpidr, afflvl);
635 
636 	gicv2_pcpu_distif_init();
637 }
638 #else
639 static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
640 {
641 	unsigned long mpidr = read_mpidr_el1();
642 
643 	if (state->pwr_domain_state[MTK_PWR_LVL0] == MTK_LOCAL_STATE_RET)
644 		return;
645 
646 	if (MTK_SYSTEM_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
647 		/* Enable the gic cpu interface */
648 		plat_arm_gic_init();
649 		spm_system_suspend_finish();
650 		enable_scu(mpidr);
651 	}
652 
653 	/* Perform the common cluster specific operations */
654 	if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
655 		/* Enable coherency if this cluster was off */
656 		plat_cci_enable();
657 	}
658 
659 	mt_platform_restore_context(mpidr);
660 
661 	if (MTK_SYSTEM_PWR_STATE(state) != MTK_LOCAL_STATE_OFF) {
662 		spm_mcdi_finish_for_on_state(mpidr, MTK_PWR_LVL0);
663 		if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF)
664 			spm_mcdi_finish_for_on_state(mpidr, MTK_PWR_LVL1);
665 	}
666 
667 	gicv2_pcpu_distif_init();
668 }
669 #endif
670 
671 #if ENABLE_PLAT_COMPAT
672 static unsigned int plat_get_sys_suspend_power_state(void)
673 {
674 	/* StateID: 0, StateType: 1(power down), PowerLevel: 2(system) */
675 	return psci_make_powerstate(0, 1, 2);
676 }
677 #else
678 static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
679 {
680 	assert(PLAT_MAX_PWR_LVL >= 2);
681 
682 	for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
683 		req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
684 }
685 #endif
686 
687 /*******************************************************************************
688  * MTK handlers to shutdown/reboot the system
689  ******************************************************************************/
690 static void __dead2 plat_system_off(void)
691 {
692 	INFO("MTK System Off\n");
693 
694 	rtc_bbpu_power_down();
695 
696 	wfi();
697 	ERROR("MTK System Off: operation not handled.\n");
698 	panic();
699 }
700 
701 static void __dead2 plat_system_reset(void)
702 {
703 	/* Write the System Configuration Control Register */
704 	INFO("MTK System Reset\n");
705 
706 	mmio_clrsetbits_32(MTK_WDT_BASE,
707 		(MTK_WDT_MODE_DUAL_MODE | MTK_WDT_MODE_IRQ),
708 		MTK_WDT_MODE_KEY);
709 	mmio_setbits_32(MTK_WDT_BASE, (MTK_WDT_MODE_KEY | MTK_WDT_MODE_EXTEN));
710 	mmio_setbits_32(MTK_WDT_SWRST, MTK_WDT_SWRST_KEY);
711 
712 	wfi();
713 	ERROR("MTK System Reset: operation not handled.\n");
714 	panic();
715 }
716 
717 #if !ENABLE_PLAT_COMPAT
718 #if !PSCI_EXTENDED_STATE_ID
719 static int plat_validate_power_state(unsigned int power_state,
720 					psci_power_state_t *req_state)
721 {
722 	int pstate = psci_get_pstate_type(power_state);
723 	int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
724 	int i;
725 
726 	assert(req_state);
727 
728 	if (pwr_lvl > PLAT_MAX_PWR_LVL)
729 		return PSCI_E_INVALID_PARAMS;
730 
731 	/* Sanity check the requested state */
732 	if (pstate == PSTATE_TYPE_STANDBY) {
733 		/*
734 		 * It's possible to enter standby only on power level 0
735 		 * Ignore any other power level.
736 		 */
737 		if (pwr_lvl != 0)
738 			return PSCI_E_INVALID_PARAMS;
739 
740 		req_state->pwr_domain_state[MTK_PWR_LVL0] =
741 					MTK_LOCAL_STATE_RET;
742 	} else {
743 		for (i = 0; i <= pwr_lvl; i++)
744 			req_state->pwr_domain_state[i] =
745 					MTK_LOCAL_STATE_OFF;
746 	}
747 
748 	/*
749 	 * We expect the 'state id' to be zero.
750 	 */
751 	if (psci_get_pstate_id(power_state))
752 		return PSCI_E_INVALID_PARAMS;
753 
754 	return PSCI_E_SUCCESS;
755 }
756 #else
757 int plat_validate_power_state(unsigned int power_state,
758 				psci_power_state_t *req_state)
759 {
760 	unsigned int state_id;
761 	int i;
762 
763 	assert(req_state);
764 
765 	/*
766 	 *  Currently we are using a linear search for finding the matching
767 	 *  entry in the idle power state array. This can be made a binary
768 	 *  search if the number of entries justify the additional complexity.
769 	 */
770 	for (i = 0; !!mtk_pm_idle_states[i]; i++) {
771 		if (power_state == mtk_pm_idle_states[i])
772 			break;
773 	}
774 
775 	/* Return error if entry not found in the idle state array */
776 	if (!mtk_pm_idle_states[i])
777 		return PSCI_E_INVALID_PARAMS;
778 
779 	i = 0;
780 	state_id = psci_get_pstate_id(power_state);
781 
782 	/* Parse the State ID and populate the state info parameter */
783 	while (state_id) {
784 		req_state->pwr_domain_state[i++] = state_id &
785 						MTK_LOCAL_PSTATE_MASK;
786 		state_id >>= MTK_LOCAL_PSTATE_WIDTH;
787 	}
788 
789 	return PSCI_E_SUCCESS;
790 }
791 #endif
792 
793 void mtk_system_pwr_domain_resume(void)
794 {
795 	console_init(MT8173_UART0_BASE, MT8173_UART_CLOCK, MT8173_BAUDRATE);
796 
797 	/* Assert system power domain is available on the platform */
798 	assert(PLAT_MAX_PWR_LVL >= MTK_PWR_LVL2);
799 
800 	plat_arm_gic_init();
801 }
802 #endif
803 
804 #if ENABLE_PLAT_COMPAT
805 /*******************************************************************************
806  * Export the platform handlers to enable psci to invoke them
807  ******************************************************************************/
808 static const plat_pm_ops_t plat_plat_pm_ops = {
809 	.affinst_standby		= plat_affinst_standby,
810 	.affinst_on			= plat_affinst_on,
811 	.affinst_off			= plat_affinst_off,
812 	.affinst_suspend		= plat_affinst_suspend,
813 	.affinst_on_finish		= plat_affinst_on_finish,
814 	.affinst_suspend_finish		= plat_affinst_suspend_finish,
815 	.system_off			= plat_system_off,
816 	.system_reset			= plat_system_reset,
817 	.get_sys_suspend_power_state	= plat_get_sys_suspend_power_state,
818 };
819 
820 /*******************************************************************************
821  * Export the platform specific power ops & initialize the mtk_platform power
822  * controller
823  ******************************************************************************/
824 int platform_setup_pm(const plat_pm_ops_t **plat_ops)
825 {
826 	*plat_ops = &plat_plat_pm_ops;
827 	return 0;
828 }
829 #else
830 static const plat_psci_ops_t plat_plat_pm_ops = {
831 	.cpu_standby			= plat_cpu_standby,
832 	.pwr_domain_on			= plat_power_domain_on,
833 	.pwr_domain_on_finish		= plat_power_domain_on_finish,
834 	.pwr_domain_off			= plat_power_domain_off,
835 	.pwr_domain_suspend		= plat_power_domain_suspend,
836 	.pwr_domain_suspend_finish	= plat_power_domain_suspend_finish,
837 	.system_off			= plat_system_off,
838 	.system_reset			= plat_system_reset,
839 	.validate_power_state		= plat_validate_power_state,
840 	.get_sys_suspend_power_state	= plat_get_sys_suspend_power_state,
841 };
842 
843 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
844 			const plat_psci_ops_t **psci_ops)
845 {
846 	*psci_ops = &plat_plat_pm_ops;
847 	secure_entrypoint = sec_entrypoint;
848 	return 0;
849 }
850 
851 /*
852  * The PSCI generic code uses this API to let the platform participate in state
853  * coordination during a power management operation. It compares the platform
854  * specific local power states requested by each cpu for a given power domain
855  * and returns the coordinated target power state that the domain should
856  * enter. A platform assigns a number to a local power state. This default
857  * implementation assumes that the platform assigns these numbers in order of
858  * increasing depth of the power state i.e. for two power states X & Y, if X < Y
859  * then X represents a shallower power state than Y. As a result, the
860  * coordinated target local power state for a power domain will be the minimum
861  * of the requested local power states.
862  */
863 plat_local_state_t plat_get_target_pwr_state(unsigned int lvl,
864 					     const plat_local_state_t *states,
865 					     unsigned int ncpu)
866 {
867 	plat_local_state_t target = PLAT_MAX_OFF_STATE, temp;
868 
869 	assert(ncpu);
870 
871 	do {
872 		temp = *states++;
873 		if (temp < target)
874 			target = temp;
875 	} while (--ncpu);
876 
877 	return target;
878 }
879 #endif
880