blob: a371705b198546a07253a00f794da83c43d763da [file] [log] [blame]
Masahiro Yamada574388c2016-09-03 11:37:40 +09001/*
Masahiro Yamada4e371402020-02-03 19:46:00 +09002 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
Masahiro Yamada574388c2016-09-03 11:37:40 +09003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Masahiro Yamada4e371402020-02-03 19:46:00 +09007#include <assert.h>
8
Masahiro Yamada574388c2016-09-03 11:37:40 +09009#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010#include <common/debug.h>
Masahiro Yamadaf36272d2019-07-08 13:46:44 +090011#include <errno.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000012#include <lib/mmio.h>
13#include <lib/psci/psci.h>
Masahiro Yamada574388c2016-09-03 11:37:40 +090014
15#include "uniphier.h"
16
Masahiro Yamada4e371402020-02-03 19:46:00 +090017#define UNIPHIER_ROM_RSV0 0x0
Masahiro Yamada574388c2016-09-03 11:37:40 +090018
Masahiro Yamada4e371402020-02-03 19:46:00 +090019#define UNIPHIER_SLFRSTSEL 0x10
Masahiro Yamada501b88b2019-07-26 20:04:28 +090020#define UNIPHIER_SLFRSTSEL_MASK GENMASK(1, 0)
Masahiro Yamada4e371402020-02-03 19:46:00 +090021#define UNIPHIER_SLFRSTCTL 0x14
Masahiro Yamada501b88b2019-07-26 20:04:28 +090022#define UNIPHIER_SLFRSTCTL_RST BIT(0)
Masahiro Yamada574388c2016-09-03 11:37:40 +090023
24#define MPIDR_AFFINITY_INVALID ((u_register_t)-1)
25
Masahiro Yamada4e371402020-02-03 19:46:00 +090026static uintptr_t uniphier_rom_rsv_base;
27static uintptr_t uniphier_slfrst_base;
28
Masahiro Yamada574388c2016-09-03 11:37:40 +090029uintptr_t uniphier_sec_entrypoint;
30
31void uniphier_warmboot_entrypoint(void);
32void __dead2 uniphier_fake_pwr_down(void);
33u_register_t uniphier_holding_pen_release;
34static int uniphier_psci_scp_mode;
35
36static int uniphier_psci_pwr_domain_on(u_register_t mpidr)
37{
38 uniphier_holding_pen_release = mpidr;
39 flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
40 sizeof(uniphier_holding_pen_release));
41
Masahiro Yamada4e371402020-02-03 19:46:00 +090042 mmio_write_64(uniphier_rom_rsv_base + UNIPHIER_ROM_RSV0,
Masahiro Yamada574388c2016-09-03 11:37:40 +090043 (uint64_t)&uniphier_warmboot_entrypoint);
44 sev();
45
46 return PSCI_E_SUCCESS;
47}
48
49static void uniphier_psci_pwr_domain_off(const psci_power_state_t *target_state)
50{
51 uniphier_gic_cpuif_disable();
52}
53
54static void uniphier_psci_pwr_domain_on_finish(
55 const psci_power_state_t *target_state)
56{
57 uniphier_gic_pcpu_init();
58 uniphier_gic_cpuif_enable();
59
60 uniphier_cci_enable();
61}
62
63static void __dead2 uniphier_psci_pwr_domain_pwr_down_wfi(
64 const psci_power_state_t *target_state)
65{
66 /*
Masahiro Yamada501b88b2019-07-26 20:04:28 +090067 * The Boot ROM cannot distinguish warm and cold resets.
Masahiro Yamada574388c2016-09-03 11:37:40 +090068 * Instead of the CPU reset, fake it.
69 */
70 uniphier_holding_pen_release = MPIDR_AFFINITY_INVALID;
71 flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
72 sizeof(uniphier_holding_pen_release));
73
74 uniphier_fake_pwr_down();
75}
76
77static void uniphier_self_system_reset(void)
78{
Masahiro Yamada4e371402020-02-03 19:46:00 +090079 mmio_clrbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTSEL,
80 UNIPHIER_SLFRSTSEL_MASK);
81 mmio_setbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTCTL,
82 UNIPHIER_SLFRSTCTL_RST);
Masahiro Yamada574388c2016-09-03 11:37:40 +090083}
84
85static void __dead2 uniphier_psci_system_off(void)
86{
87 if (uniphier_psci_scp_mode) {
88 uniphier_scp_system_off();
89 } else {
90 NOTICE("SCP is disabled; can't shutdown the system.\n");
91 NOTICE("Resetting the system instead.\n");
92 uniphier_self_system_reset();
93 }
94
95 wfi();
96 ERROR("UniPhier System Off: operation not handled.\n");
97 panic();
98}
99
100static void __dead2 uniphier_psci_system_reset(void)
101{
102 if (uniphier_psci_scp_mode)
103 uniphier_scp_system_reset();
104 else
105 uniphier_self_system_reset();
106
107 wfi();
108 ERROR("UniPhier System Reset: operation not handled.\n");
109 panic();
110}
111
112static const struct plat_psci_ops uniphier_psci_ops = {
113 .pwr_domain_on = uniphier_psci_pwr_domain_on,
114 .pwr_domain_off = uniphier_psci_pwr_domain_off,
115 .pwr_domain_on_finish = uniphier_psci_pwr_domain_on_finish,
116 .pwr_domain_pwr_down_wfi = uniphier_psci_pwr_domain_pwr_down_wfi,
117 .system_off = uniphier_psci_system_off,
118 .system_reset = uniphier_psci_system_reset,
119};
120
121int plat_setup_psci_ops(uintptr_t sec_entrypoint,
122 const struct plat_psci_ops **psci_ops)
123{
Masahiro Yamada4e371402020-02-03 19:46:00 +0900124 uniphier_sec_entrypoint = sec_entrypoint;
125 flush_dcache_range((uint64_t)&uniphier_sec_entrypoint,
126 sizeof(uniphier_sec_entrypoint));
Masahiro Yamadaf36272d2019-07-08 13:46:44 +0900127
Masahiro Yamada4e371402020-02-03 19:46:00 +0900128 *psci_ops = &uniphier_psci_ops;
129
130 return 0;
131}
132
133struct uniphier_psci_ctrl_base {
134 uintptr_t rom_rsv_base;
135 uintptr_t slfrst_base;
136};
137
138static const struct uniphier_psci_ctrl_base uniphier_psci_ctrl_base[] = {
139 [UNIPHIER_SOC_LD11] = {
140 .rom_rsv_base = 0x59801200,
141 .slfrst_base = 0x61843000,
142 },
143 [UNIPHIER_SOC_LD20] = {
144 .rom_rsv_base = 0x59801200,
145 .slfrst_base = 0x61843000,
146 },
147 [UNIPHIER_SOC_PXS3] = {
148 .rom_rsv_base = 0x59801200,
149 .slfrst_base = 0x61843000,
150 },
151};
152
153void uniphier_psci_init(unsigned int soc)
154{
155 assert(soc < ARRAY_SIZE(uniphier_psci_ctrl_base));
156 uniphier_rom_rsv_base = uniphier_psci_ctrl_base[soc].rom_rsv_base;
157 uniphier_slfrst_base = uniphier_psci_ctrl_base[soc].slfrst_base;
Masahiro Yamadaf36272d2019-07-08 13:46:44 +0900158
159 if (uniphier_get_boot_master(soc) == UNIPHIER_BOOT_MASTER_SCP) {
160 uniphier_psci_scp_mode = uniphier_scp_is_running();
161 flush_dcache_range((uint64_t)&uniphier_psci_scp_mode,
162 sizeof(uniphier_psci_scp_mode));
163
164 if (uniphier_psci_scp_mode)
165 uniphier_scp_open_com();
166 }
Masahiro Yamada574388c2016-09-03 11:37:40 +0900167}