xref: /arm-trusted-firmware/plat/socionext/uniphier/uniphier_psci.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu 
9*91f16700Schasinglulu #include <arch_helpers.h>
10*91f16700Schasinglulu #include <common/debug.h>
11*91f16700Schasinglulu #include <errno.h>
12*91f16700Schasinglulu #include <lib/mmio.h>
13*91f16700Schasinglulu #include <lib/psci/psci.h>
14*91f16700Schasinglulu 
15*91f16700Schasinglulu #include "uniphier.h"
16*91f16700Schasinglulu 
17*91f16700Schasinglulu #define UNIPHIER_ROM_RSV0		0x0
18*91f16700Schasinglulu 
19*91f16700Schasinglulu #define UNIPHIER_SLFRSTSEL		0x10
20*91f16700Schasinglulu #define   UNIPHIER_SLFRSTSEL_MASK		GENMASK(1, 0)
21*91f16700Schasinglulu #define UNIPHIER_SLFRSTCTL		0x14
22*91f16700Schasinglulu #define   UNIPHIER_SLFRSTCTL_RST		BIT(0)
23*91f16700Schasinglulu 
24*91f16700Schasinglulu #define MPIDR_AFFINITY_INVALID		((u_register_t)-1)
25*91f16700Schasinglulu 
26*91f16700Schasinglulu static uintptr_t uniphier_rom_rsv_base;
27*91f16700Schasinglulu static uintptr_t uniphier_slfrst_base;
28*91f16700Schasinglulu 
29*91f16700Schasinglulu uintptr_t uniphier_sec_entrypoint;
30*91f16700Schasinglulu 
31*91f16700Schasinglulu void uniphier_warmboot_entrypoint(void);
32*91f16700Schasinglulu void __dead2 uniphier_fake_pwr_down(void);
33*91f16700Schasinglulu u_register_t uniphier_holding_pen_release;
34*91f16700Schasinglulu static int uniphier_psci_scp_mode;
35*91f16700Schasinglulu 
36*91f16700Schasinglulu static int uniphier_psci_pwr_domain_on(u_register_t mpidr)
37*91f16700Schasinglulu {
38*91f16700Schasinglulu 	uniphier_holding_pen_release = mpidr;
39*91f16700Schasinglulu 	flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
40*91f16700Schasinglulu 			   sizeof(uniphier_holding_pen_release));
41*91f16700Schasinglulu 
42*91f16700Schasinglulu 	mmio_write_64(uniphier_rom_rsv_base + UNIPHIER_ROM_RSV0,
43*91f16700Schasinglulu 		      (uint64_t)&uniphier_warmboot_entrypoint);
44*91f16700Schasinglulu 	sev();
45*91f16700Schasinglulu 
46*91f16700Schasinglulu 	return PSCI_E_SUCCESS;
47*91f16700Schasinglulu }
48*91f16700Schasinglulu 
49*91f16700Schasinglulu static void uniphier_psci_pwr_domain_off(const psci_power_state_t *target_state)
50*91f16700Schasinglulu {
51*91f16700Schasinglulu 	uniphier_gic_cpuif_disable();
52*91f16700Schasinglulu }
53*91f16700Schasinglulu 
54*91f16700Schasinglulu static void uniphier_psci_pwr_domain_on_finish(
55*91f16700Schasinglulu 					const psci_power_state_t *target_state)
56*91f16700Schasinglulu {
57*91f16700Schasinglulu 	uniphier_gic_pcpu_init();
58*91f16700Schasinglulu 	uniphier_gic_cpuif_enable();
59*91f16700Schasinglulu 
60*91f16700Schasinglulu 	uniphier_cci_enable();
61*91f16700Schasinglulu }
62*91f16700Schasinglulu 
63*91f16700Schasinglulu static void __dead2 uniphier_psci_pwr_domain_pwr_down_wfi(
64*91f16700Schasinglulu 					const psci_power_state_t *target_state)
65*91f16700Schasinglulu {
66*91f16700Schasinglulu 	/*
67*91f16700Schasinglulu 	 * The Boot ROM cannot distinguish warm and cold resets.
68*91f16700Schasinglulu 	 * Instead of the CPU reset, fake it.
69*91f16700Schasinglulu 	 */
70*91f16700Schasinglulu 	uniphier_holding_pen_release = MPIDR_AFFINITY_INVALID;
71*91f16700Schasinglulu 	flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
72*91f16700Schasinglulu 			   sizeof(uniphier_holding_pen_release));
73*91f16700Schasinglulu 
74*91f16700Schasinglulu 	uniphier_fake_pwr_down();
75*91f16700Schasinglulu }
76*91f16700Schasinglulu 
77*91f16700Schasinglulu static void uniphier_self_system_reset(void)
78*91f16700Schasinglulu {
79*91f16700Schasinglulu 	mmio_clrbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTSEL,
80*91f16700Schasinglulu 			UNIPHIER_SLFRSTSEL_MASK);
81*91f16700Schasinglulu 	mmio_setbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTCTL,
82*91f16700Schasinglulu 			UNIPHIER_SLFRSTCTL_RST);
83*91f16700Schasinglulu }
84*91f16700Schasinglulu 
85*91f16700Schasinglulu static void __dead2 uniphier_psci_system_off(void)
86*91f16700Schasinglulu {
87*91f16700Schasinglulu 	if (uniphier_psci_scp_mode) {
88*91f16700Schasinglulu 		uniphier_scp_system_off();
89*91f16700Schasinglulu 	} else {
90*91f16700Schasinglulu 		NOTICE("SCP is disabled; can't shutdown the system.\n");
91*91f16700Schasinglulu 		NOTICE("Resetting the system instead.\n");
92*91f16700Schasinglulu 		uniphier_self_system_reset();
93*91f16700Schasinglulu 	}
94*91f16700Schasinglulu 
95*91f16700Schasinglulu 	wfi();
96*91f16700Schasinglulu 	ERROR("UniPhier System Off: operation not handled.\n");
97*91f16700Schasinglulu 	panic();
98*91f16700Schasinglulu }
99*91f16700Schasinglulu 
100*91f16700Schasinglulu static void __dead2 uniphier_psci_system_reset(void)
101*91f16700Schasinglulu {
102*91f16700Schasinglulu 	if (uniphier_psci_scp_mode)
103*91f16700Schasinglulu 		uniphier_scp_system_reset();
104*91f16700Schasinglulu 	else
105*91f16700Schasinglulu 		uniphier_self_system_reset();
106*91f16700Schasinglulu 
107*91f16700Schasinglulu 	wfi();
108*91f16700Schasinglulu 	ERROR("UniPhier System Reset: operation not handled.\n");
109*91f16700Schasinglulu 	panic();
110*91f16700Schasinglulu }
111*91f16700Schasinglulu 
112*91f16700Schasinglulu static const struct plat_psci_ops uniphier_psci_ops = {
113*91f16700Schasinglulu 	.pwr_domain_on = uniphier_psci_pwr_domain_on,
114*91f16700Schasinglulu 	.pwr_domain_off = uniphier_psci_pwr_domain_off,
115*91f16700Schasinglulu 	.pwr_domain_on_finish = uniphier_psci_pwr_domain_on_finish,
116*91f16700Schasinglulu 	.pwr_domain_pwr_down_wfi = uniphier_psci_pwr_domain_pwr_down_wfi,
117*91f16700Schasinglulu 	.system_off = uniphier_psci_system_off,
118*91f16700Schasinglulu 	.system_reset = uniphier_psci_system_reset,
119*91f16700Schasinglulu };
120*91f16700Schasinglulu 
121*91f16700Schasinglulu int plat_setup_psci_ops(uintptr_t sec_entrypoint,
122*91f16700Schasinglulu 			const struct plat_psci_ops **psci_ops)
123*91f16700Schasinglulu {
124*91f16700Schasinglulu 	uniphier_sec_entrypoint = sec_entrypoint;
125*91f16700Schasinglulu 	flush_dcache_range((uint64_t)&uniphier_sec_entrypoint,
126*91f16700Schasinglulu 			   sizeof(uniphier_sec_entrypoint));
127*91f16700Schasinglulu 
128*91f16700Schasinglulu 	*psci_ops = &uniphier_psci_ops;
129*91f16700Schasinglulu 
130*91f16700Schasinglulu 	return 0;
131*91f16700Schasinglulu }
132*91f16700Schasinglulu 
133*91f16700Schasinglulu struct uniphier_psci_ctrl_base {
134*91f16700Schasinglulu 	uintptr_t rom_rsv_base;
135*91f16700Schasinglulu 	uintptr_t slfrst_base;
136*91f16700Schasinglulu };
137*91f16700Schasinglulu 
138*91f16700Schasinglulu static const struct uniphier_psci_ctrl_base uniphier_psci_ctrl_base[] = {
139*91f16700Schasinglulu 	[UNIPHIER_SOC_LD11] = {
140*91f16700Schasinglulu 		.rom_rsv_base = 0x59801200,
141*91f16700Schasinglulu 		.slfrst_base = 0x61843000,
142*91f16700Schasinglulu 	},
143*91f16700Schasinglulu 	[UNIPHIER_SOC_LD20] = {
144*91f16700Schasinglulu 		.rom_rsv_base = 0x59801200,
145*91f16700Schasinglulu 		.slfrst_base = 0x61843000,
146*91f16700Schasinglulu 	},
147*91f16700Schasinglulu 	[UNIPHIER_SOC_PXS3] = {
148*91f16700Schasinglulu 		.rom_rsv_base = 0x59801200,
149*91f16700Schasinglulu 		.slfrst_base = 0x61843000,
150*91f16700Schasinglulu 	},
151*91f16700Schasinglulu };
152*91f16700Schasinglulu 
153*91f16700Schasinglulu void uniphier_psci_init(unsigned int soc)
154*91f16700Schasinglulu {
155*91f16700Schasinglulu 	assert(soc < ARRAY_SIZE(uniphier_psci_ctrl_base));
156*91f16700Schasinglulu 	uniphier_rom_rsv_base = uniphier_psci_ctrl_base[soc].rom_rsv_base;
157*91f16700Schasinglulu 	uniphier_slfrst_base = uniphier_psci_ctrl_base[soc].slfrst_base;
158*91f16700Schasinglulu 
159*91f16700Schasinglulu 	if (uniphier_get_boot_master(soc) == UNIPHIER_BOOT_MASTER_SCP) {
160*91f16700Schasinglulu 		uniphier_psci_scp_mode = uniphier_scp_is_running();
161*91f16700Schasinglulu 		flush_dcache_range((uint64_t)&uniphier_psci_scp_mode,
162*91f16700Schasinglulu 				   sizeof(uniphier_psci_scp_mode));
163*91f16700Schasinglulu 
164*91f16700Schasinglulu 		if (uniphier_psci_scp_mode)
165*91f16700Schasinglulu 			uniphier_scp_open_com();
166*91f16700Schasinglulu 	}
167*91f16700Schasinglulu }
168