xref: /rk3399_ARM-atf/plat/socionext/uniphier/uniphier_psci.c (revision d8e919c7b81a2739300912d6edbd3f929a136dbf)
1*d8e919c7SMasahiro Yamada /*
2*d8e919c7SMasahiro Yamada  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3*d8e919c7SMasahiro Yamada  *
4*d8e919c7SMasahiro Yamada  * SPDX-License-Identifier: BSD-3-Clause
5*d8e919c7SMasahiro Yamada  */
6*d8e919c7SMasahiro Yamada 
7*d8e919c7SMasahiro Yamada #include <arch_helpers.h>
8*d8e919c7SMasahiro Yamada #include <debug.h>
9*d8e919c7SMasahiro Yamada #include <mmio.h>
10*d8e919c7SMasahiro Yamada #include <psci.h>
11*d8e919c7SMasahiro Yamada 
12*d8e919c7SMasahiro Yamada #include "uniphier.h"
13*d8e919c7SMasahiro Yamada 
14*d8e919c7SMasahiro Yamada #define UNIPHIER_ROM_RSV0		0x59801200
15*d8e919c7SMasahiro Yamada 
16*d8e919c7SMasahiro Yamada #define UNIPHIER_SLFRSTSEL		0x61843010
17*d8e919c7SMasahiro Yamada #define   UNIPHIER_SLFRSTSEL_MASK		(0x3 << 0)
18*d8e919c7SMasahiro Yamada #define UNIPHIER_SLFRSTCTL		0x61843014
19*d8e919c7SMasahiro Yamada #define   UNIPHIER_SLFRSTCTL_RST		(1 << 0)
20*d8e919c7SMasahiro Yamada 
21*d8e919c7SMasahiro Yamada #define MPIDR_AFFINITY_INVALID		((u_register_t)-1)
22*d8e919c7SMasahiro Yamada 
23*d8e919c7SMasahiro Yamada uintptr_t uniphier_sec_entrypoint;
24*d8e919c7SMasahiro Yamada 
25*d8e919c7SMasahiro Yamada void uniphier_warmboot_entrypoint(void);
26*d8e919c7SMasahiro Yamada void __dead2 uniphier_fake_pwr_down(void);
27*d8e919c7SMasahiro Yamada u_register_t uniphier_holding_pen_release;
28*d8e919c7SMasahiro Yamada static int uniphier_psci_scp_mode;
29*d8e919c7SMasahiro Yamada 
30*d8e919c7SMasahiro Yamada static int uniphier_psci_pwr_domain_on(u_register_t mpidr)
31*d8e919c7SMasahiro Yamada {
32*d8e919c7SMasahiro Yamada 	uniphier_holding_pen_release = mpidr;
33*d8e919c7SMasahiro Yamada 	flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
34*d8e919c7SMasahiro Yamada 			   sizeof(uniphier_holding_pen_release));
35*d8e919c7SMasahiro Yamada 
36*d8e919c7SMasahiro Yamada 	mmio_write_64(UNIPHIER_ROM_RSV0,
37*d8e919c7SMasahiro Yamada 		      (uint64_t)&uniphier_warmboot_entrypoint);
38*d8e919c7SMasahiro Yamada 	sev();
39*d8e919c7SMasahiro Yamada 
40*d8e919c7SMasahiro Yamada 	return PSCI_E_SUCCESS;
41*d8e919c7SMasahiro Yamada }
42*d8e919c7SMasahiro Yamada 
43*d8e919c7SMasahiro Yamada static void uniphier_psci_pwr_domain_off(const psci_power_state_t *target_state)
44*d8e919c7SMasahiro Yamada {
45*d8e919c7SMasahiro Yamada 	uniphier_gic_cpuif_disable();
46*d8e919c7SMasahiro Yamada }
47*d8e919c7SMasahiro Yamada 
48*d8e919c7SMasahiro Yamada static void uniphier_psci_pwr_domain_on_finish(
49*d8e919c7SMasahiro Yamada 					const psci_power_state_t *target_state)
50*d8e919c7SMasahiro Yamada {
51*d8e919c7SMasahiro Yamada 	uniphier_gic_pcpu_init();
52*d8e919c7SMasahiro Yamada 	uniphier_gic_cpuif_enable();
53*d8e919c7SMasahiro Yamada 
54*d8e919c7SMasahiro Yamada 	uniphier_cci_enable();
55*d8e919c7SMasahiro Yamada }
56*d8e919c7SMasahiro Yamada 
57*d8e919c7SMasahiro Yamada static void __dead2 uniphier_psci_pwr_domain_pwr_down_wfi(
58*d8e919c7SMasahiro Yamada 					const psci_power_state_t *target_state)
59*d8e919c7SMasahiro Yamada {
60*d8e919c7SMasahiro Yamada 	/*
61*d8e919c7SMasahiro Yamada 	 * The Boot ROM cannot distinguish warn and cold resets.
62*d8e919c7SMasahiro Yamada 	 * Instead of the CPU reset, fake it.
63*d8e919c7SMasahiro Yamada 	 */
64*d8e919c7SMasahiro Yamada 	uniphier_holding_pen_release = MPIDR_AFFINITY_INVALID;
65*d8e919c7SMasahiro Yamada 	flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
66*d8e919c7SMasahiro Yamada 			   sizeof(uniphier_holding_pen_release));
67*d8e919c7SMasahiro Yamada 
68*d8e919c7SMasahiro Yamada 	uniphier_fake_pwr_down();
69*d8e919c7SMasahiro Yamada }
70*d8e919c7SMasahiro Yamada 
71*d8e919c7SMasahiro Yamada static void uniphier_self_system_reset(void)
72*d8e919c7SMasahiro Yamada {
73*d8e919c7SMasahiro Yamada 	mmio_clrbits_32(UNIPHIER_SLFRSTSEL, UNIPHIER_SLFRSTSEL_MASK);
74*d8e919c7SMasahiro Yamada 	mmio_setbits_32(UNIPHIER_SLFRSTCTL, UNIPHIER_SLFRSTCTL_RST);
75*d8e919c7SMasahiro Yamada }
76*d8e919c7SMasahiro Yamada 
77*d8e919c7SMasahiro Yamada static void __dead2 uniphier_psci_system_off(void)
78*d8e919c7SMasahiro Yamada {
79*d8e919c7SMasahiro Yamada 	if (uniphier_psci_scp_mode) {
80*d8e919c7SMasahiro Yamada 		uniphier_scp_system_off();
81*d8e919c7SMasahiro Yamada 	} else {
82*d8e919c7SMasahiro Yamada 		NOTICE("SCP is disabled; can't shutdown the system.\n");
83*d8e919c7SMasahiro Yamada 		NOTICE("Resetting the system instead.\n");
84*d8e919c7SMasahiro Yamada 		uniphier_self_system_reset();
85*d8e919c7SMasahiro Yamada 	}
86*d8e919c7SMasahiro Yamada 
87*d8e919c7SMasahiro Yamada 	wfi();
88*d8e919c7SMasahiro Yamada 	ERROR("UniPhier System Off: operation not handled.\n");
89*d8e919c7SMasahiro Yamada 	panic();
90*d8e919c7SMasahiro Yamada }
91*d8e919c7SMasahiro Yamada 
92*d8e919c7SMasahiro Yamada static void __dead2 uniphier_psci_system_reset(void)
93*d8e919c7SMasahiro Yamada {
94*d8e919c7SMasahiro Yamada 	if (uniphier_psci_scp_mode)
95*d8e919c7SMasahiro Yamada 		uniphier_scp_system_reset();
96*d8e919c7SMasahiro Yamada 	else
97*d8e919c7SMasahiro Yamada 		uniphier_self_system_reset();
98*d8e919c7SMasahiro Yamada 
99*d8e919c7SMasahiro Yamada 	wfi();
100*d8e919c7SMasahiro Yamada 	ERROR("UniPhier System Reset: operation not handled.\n");
101*d8e919c7SMasahiro Yamada 	panic();
102*d8e919c7SMasahiro Yamada }
103*d8e919c7SMasahiro Yamada 
104*d8e919c7SMasahiro Yamada static const struct plat_psci_ops uniphier_psci_ops = {
105*d8e919c7SMasahiro Yamada 	.pwr_domain_on = uniphier_psci_pwr_domain_on,
106*d8e919c7SMasahiro Yamada 	.pwr_domain_off = uniphier_psci_pwr_domain_off,
107*d8e919c7SMasahiro Yamada 	.pwr_domain_on_finish = uniphier_psci_pwr_domain_on_finish,
108*d8e919c7SMasahiro Yamada 	.pwr_domain_pwr_down_wfi = uniphier_psci_pwr_domain_pwr_down_wfi,
109*d8e919c7SMasahiro Yamada 	.system_off = uniphier_psci_system_off,
110*d8e919c7SMasahiro Yamada 	.system_reset = uniphier_psci_system_reset,
111*d8e919c7SMasahiro Yamada };
112*d8e919c7SMasahiro Yamada 
113*d8e919c7SMasahiro Yamada int plat_setup_psci_ops(uintptr_t sec_entrypoint,
114*d8e919c7SMasahiro Yamada 			const struct plat_psci_ops **psci_ops)
115*d8e919c7SMasahiro Yamada {
116*d8e919c7SMasahiro Yamada 	uniphier_sec_entrypoint = sec_entrypoint;
117*d8e919c7SMasahiro Yamada 	flush_dcache_range((uint64_t)&uniphier_sec_entrypoint,
118*d8e919c7SMasahiro Yamada 			   sizeof(uniphier_sec_entrypoint));
119*d8e919c7SMasahiro Yamada 
120*d8e919c7SMasahiro Yamada 	uniphier_psci_scp_mode = uniphier_scp_is_running();
121*d8e919c7SMasahiro Yamada 	flush_dcache_range((uint64_t)&uniphier_psci_scp_mode,
122*d8e919c7SMasahiro Yamada 			   sizeof(uniphier_psci_scp_mode));
123*d8e919c7SMasahiro Yamada 
124*d8e919c7SMasahiro Yamada 	if (uniphier_psci_scp_mode)
125*d8e919c7SMasahiro Yamada 		uniphier_scp_open_com();
126*d8e919c7SMasahiro Yamada 
127*d8e919c7SMasahiro Yamada 	*psci_ops = &uniphier_psci_ops;
128*d8e919c7SMasahiro Yamada 
129*d8e919c7SMasahiro Yamada 	return 0;
130*d8e919c7SMasahiro Yamada }
131