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