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