blob: 2acc874401d862944a69458b40415a2d828af1a2 [file] [log] [blame]
Masahiro Yamada574388c2016-09-03 11:37:40 +09001/*
Masahiro Yamada501b88b2019-07-26 20:04:28 +09002 * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
Masahiro Yamada574388c2016-09-03 11:37:40 +09003 *
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>
Masahiro Yamadaf36272d2019-07-08 13:46:44 +09009#include <errno.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010#include <lib/mmio.h>
11#include <lib/psci/psci.h>
Masahiro Yamada574388c2016-09-03 11:37:40 +090012
13#include "uniphier.h"
14
15#define UNIPHIER_ROM_RSV0 0x59801200
16
17#define UNIPHIER_SLFRSTSEL 0x61843010
Masahiro Yamada501b88b2019-07-26 20:04:28 +090018#define UNIPHIER_SLFRSTSEL_MASK GENMASK(1, 0)
Masahiro Yamada574388c2016-09-03 11:37:40 +090019#define UNIPHIER_SLFRSTCTL 0x61843014
Masahiro Yamada501b88b2019-07-26 20:04:28 +090020#define UNIPHIER_SLFRSTCTL_RST BIT(0)
Masahiro Yamada574388c2016-09-03 11:37:40 +090021
22#define MPIDR_AFFINITY_INVALID ((u_register_t)-1)
23
24uintptr_t uniphier_sec_entrypoint;
25
26void uniphier_warmboot_entrypoint(void);
27void __dead2 uniphier_fake_pwr_down(void);
28u_register_t uniphier_holding_pen_release;
29static int uniphier_psci_scp_mode;
30
31static int uniphier_psci_pwr_domain_on(u_register_t mpidr)
32{
33 uniphier_holding_pen_release = mpidr;
34 flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
35 sizeof(uniphier_holding_pen_release));
36
37 mmio_write_64(UNIPHIER_ROM_RSV0,
38 (uint64_t)&uniphier_warmboot_entrypoint);
39 sev();
40
41 return PSCI_E_SUCCESS;
42}
43
44static void uniphier_psci_pwr_domain_off(const psci_power_state_t *target_state)
45{
46 uniphier_gic_cpuif_disable();
47}
48
49static void uniphier_psci_pwr_domain_on_finish(
50 const psci_power_state_t *target_state)
51{
52 uniphier_gic_pcpu_init();
53 uniphier_gic_cpuif_enable();
54
55 uniphier_cci_enable();
56}
57
58static void __dead2 uniphier_psci_pwr_domain_pwr_down_wfi(
59 const psci_power_state_t *target_state)
60{
61 /*
Masahiro Yamada501b88b2019-07-26 20:04:28 +090062 * The Boot ROM cannot distinguish warm and cold resets.
Masahiro Yamada574388c2016-09-03 11:37:40 +090063 * Instead of the CPU reset, fake it.
64 */
65 uniphier_holding_pen_release = MPIDR_AFFINITY_INVALID;
66 flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
67 sizeof(uniphier_holding_pen_release));
68
69 uniphier_fake_pwr_down();
70}
71
72static void uniphier_self_system_reset(void)
73{
74 mmio_clrbits_32(UNIPHIER_SLFRSTSEL, UNIPHIER_SLFRSTSEL_MASK);
75 mmio_setbits_32(UNIPHIER_SLFRSTCTL, UNIPHIER_SLFRSTCTL_RST);
76}
77
78static void __dead2 uniphier_psci_system_off(void)
79{
80 if (uniphier_psci_scp_mode) {
81 uniphier_scp_system_off();
82 } else {
83 NOTICE("SCP is disabled; can't shutdown the system.\n");
84 NOTICE("Resetting the system instead.\n");
85 uniphier_self_system_reset();
86 }
87
88 wfi();
89 ERROR("UniPhier System Off: operation not handled.\n");
90 panic();
91}
92
93static void __dead2 uniphier_psci_system_reset(void)
94{
95 if (uniphier_psci_scp_mode)
96 uniphier_scp_system_reset();
97 else
98 uniphier_self_system_reset();
99
100 wfi();
101 ERROR("UniPhier System Reset: operation not handled.\n");
102 panic();
103}
104
105static const struct plat_psci_ops uniphier_psci_ops = {
106 .pwr_domain_on = uniphier_psci_pwr_domain_on,
107 .pwr_domain_off = uniphier_psci_pwr_domain_off,
108 .pwr_domain_on_finish = uniphier_psci_pwr_domain_on_finish,
109 .pwr_domain_pwr_down_wfi = uniphier_psci_pwr_domain_pwr_down_wfi,
110 .system_off = uniphier_psci_system_off,
111 .system_reset = uniphier_psci_system_reset,
112};
113
114int plat_setup_psci_ops(uintptr_t sec_entrypoint,
115 const struct plat_psci_ops **psci_ops)
116{
Masahiro Yamadaf36272d2019-07-08 13:46:44 +0900117 unsigned int soc;
118
119 soc = uniphier_get_soc_id();
120 if (soc == UNIPHIER_SOC_UNKNOWN) {
121 ERROR("unsupported SoC\n");
122 return -ENOTSUP;
123 }
124
125 if (uniphier_get_boot_master(soc) == UNIPHIER_BOOT_MASTER_SCP) {
126 uniphier_psci_scp_mode = uniphier_scp_is_running();
127 flush_dcache_range((uint64_t)&uniphier_psci_scp_mode,
128 sizeof(uniphier_psci_scp_mode));
129
130 if (uniphier_psci_scp_mode)
131 uniphier_scp_open_com();
132 }
133
Masahiro Yamada574388c2016-09-03 11:37:40 +0900134 uniphier_sec_entrypoint = sec_entrypoint;
135 flush_dcache_range((uint64_t)&uniphier_sec_entrypoint,
136 sizeof(uniphier_sec_entrypoint));
137
Masahiro Yamada574388c2016-09-03 11:37:40 +0900138 *psci_ops = &uniphier_psci_ops;
139
140 return 0;
141}