blob: ce11aa7cbbe4d99e62705df942b43b4239387e60 [file] [log] [blame]
Masahiro Yamada574388c2016-09-03 11:37:40 +09001/*
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>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008#include <common/debug.h>
9#include <lib/mmio.h>
10#include <lib/psci/psci.h>
Masahiro Yamada574388c2016-09-03 11:37:40 +090011
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
23uintptr_t uniphier_sec_entrypoint;
24
25void uniphier_warmboot_entrypoint(void);
26void __dead2 uniphier_fake_pwr_down(void);
27u_register_t uniphier_holding_pen_release;
28static int uniphier_psci_scp_mode;
29
30static 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
43static void uniphier_psci_pwr_domain_off(const psci_power_state_t *target_state)
44{
45 uniphier_gic_cpuif_disable();
46}
47
48static 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
57static 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
71static 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
77static 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
92static 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
104static 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
113int 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}