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