blob: 8e282cbad845b5079372f70a0fb7b03c3453d9e9 [file] [log] [blame]
Jiafei Pan33d4af42018-03-02 07:23:30 +00001/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Jiafei Pan33d4af42018-03-02 07:23:30 +00007#include <assert.h>
Antonio Nino Diaz93c78ed2018-08-16 16:52:57 +01008#include <endian.h>
9#include <errno.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000010
11#include <platform_def.h>
12
13#include <arch_helpers.h>
14#include <common/debug.h>
15#include <drivers/arm/gicv2.h>
16#include <drivers/delay_timer.h>
17#include <lib/mmio.h>
18#include <lib/psci/psci.h>
19#include <plat/common/platform.h>
Jiafei Pan33d4af42018-03-02 07:23:30 +000020
21#define LS_SCFG_BASE 0x01570000
22/* register to store warm boot entry, big endian, higher 32bit */
23#define LS_SCFG_SCRATCHRW0_OFFSET 0x600
24/* register to store warm boot entry, big endian, lower 32bit */
25#define LS_SCFG_SCRATCHRW1_OFFSET 0x604
26#define LS_SCFG_COREBCR_OFFSET 0x680
27
28#define LS_DCFG_BASE 0x01EE0000
29#define LS_DCFG_RSTCR_OFFSET 0x0B0
30#define LS_DCFG_RSTRQMR1_OFFSET 0x0C0
31#define LS_DCFG_BRR_OFFSET 0x0E4
32
33#define LS_SCFG_CORE0_SFT_RST_OFFSET 0x130
34#define LS_SCFG_CORE1_SFT_RST_OFFSET 0x134
35#define LS_SCFG_CORE2_SFT_RST_OFFSET 0x138
36#define LS_SCFG_CORE3_SFT_RST_OFFSET 0x13C
37
38#define LS_SCFG_CORESRENCR_OFFSET 0x204
39
40#define LS_SCFG_RVBAR0_0_OFFSET 0x220
41#define LS_SCFG_RVBAR0_1_OFFSET 0x224
42
43#define LS_SCFG_RVBAR1_0_OFFSET 0x228
44#define LS_SCFG_RVBAR1_1_OFFSET 0x22C
45
46#define LS_SCFG_RVBAR2_0_OFFSET 0x230
47#define LS_SCFG_RVBAR2_1_OFFSET 0x234
48
49#define LS_SCFG_RVBAR3_0_OFFSET 0x238
50#define LS_SCFG_RVBAR3_1_OFFSET 0x23C
51
52/* the entry for core warm boot */
53static uintptr_t warmboot_entry;
54
55/* warm reset single core */
56static void ls1043_reset_core(int core_pos)
57{
58 assert(core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT);
59
60 /* set 0 in RVBAR, boot from bootrom at 0x0 */
61 mmio_write_32(LS_SCFG_BASE + LS_SCFG_RVBAR0_0_OFFSET + core_pos * 8,
62 0);
63 mmio_write_32(LS_SCFG_BASE + LS_SCFG_RVBAR0_1_OFFSET + core_pos * 8,
64 0);
65
66 dsb();
67 /* enable core soft reset */
68 mmio_write_32(LS_SCFG_BASE + LS_SCFG_CORESRENCR_OFFSET,
Justin Chadwell9e4afb02019-07-03 14:13:34 +010069 htobe32(1U << 31));
Jiafei Pan33d4af42018-03-02 07:23:30 +000070 dsb();
71 isb();
72 /* reset core */
73 mmio_write_32(LS_SCFG_BASE + LS_SCFG_CORE0_SFT_RST_OFFSET +
Justin Chadwell9e4afb02019-07-03 14:13:34 +010074 core_pos * 4, htobe32(1U << 31));
Jiafei Pan33d4af42018-03-02 07:23:30 +000075 mdelay(10);
76}
77
78static void __dead2 ls1043_system_reset(void)
79{
80 /* clear reset request mask bits */
81 mmio_write_32(LS_DCFG_BASE + LS_DCFG_RSTRQMR1_OFFSET, 0);
82
83 /* set reset request bit */
84 mmio_write_32(LS_DCFG_BASE + LS_DCFG_RSTCR_OFFSET,
85 htobe32((uint32_t)0x2));
86
87 /* system will reset; if fail, enter wfi */
88 dsb();
89 isb();
90 wfi();
91
92 panic();
93}
94
95
96static int ls1043_pwr_domain_on(u_register_t mpidr)
97{
98 int core_pos = plat_core_pos_by_mpidr(mpidr);
Jiafei Panf7c5f302018-04-11 12:12:24 +000099 uint32_t core_mask, brr;
Jiafei Pan33d4af42018-03-02 07:23:30 +0000100
101 assert(core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT);
Jiafei Panf7c5f302018-04-11 12:12:24 +0000102 core_mask = 1 << core_pos;
Jiafei Pan33d4af42018-03-02 07:23:30 +0000103
104 /* set warm boot entry */
105 mmio_write_32(LS_SCFG_BASE + LS_SCFG_SCRATCHRW0_OFFSET,
106 htobe32((uint32_t)(warmboot_entry >> 32)));
107
108 mmio_write_32(LS_SCFG_BASE + LS_SCFG_SCRATCHRW1_OFFSET,
109 htobe32((uint32_t)warmboot_entry));
110
111 dsb();
112
113 brr = be32toh(mmio_read_32(LS_DCFG_BASE + LS_DCFG_BRR_OFFSET));
114 if (brr & core_mask) {
115 /* core has been released, must reset it to restart */
116 ls1043_reset_core(core_pos);
117
118 /* set bit in core boot control register to enable boot */
119 mmio_write_32(LS_SCFG_BASE + LS_SCFG_COREBCR_OFFSET,
120 htobe32(core_mask));
121
122 } else {
123 /* set bit in core boot control register to enable boot */
124 mmio_write_32(LS_SCFG_BASE + LS_SCFG_COREBCR_OFFSET,
125 htobe32(core_mask));
126
127 /* release core */
128 mmio_write_32(LS_DCFG_BASE + LS_DCFG_BRR_OFFSET,
129 htobe32(brr | core_mask));
130 }
131
132 mdelay(20);
133
134 /* wake core in case it is in wfe */
135 dsb();
136 isb();
137 sev();
138
139 return PSCI_E_SUCCESS;
140}
141
142static void ls1043_pwr_domain_on_finish(const psci_power_state_t *target_state)
143{
144 /* Per cpu gic distributor setup */
145 gicv2_pcpu_distif_init();
146
147 /* Enable the gic CPU interface */
148 gicv2_cpuif_enable();
149}
150
151static void ls1043_pwr_domain_off(const psci_power_state_t *target_state)
152{
153 /* Disable the gic CPU interface */
154 gicv2_cpuif_disable();
155}
156
157static plat_psci_ops_t ls1043_psci_pm_ops = {
158 .system_reset = ls1043_system_reset,
159 .pwr_domain_on = ls1043_pwr_domain_on,
160 .pwr_domain_on_finish = ls1043_pwr_domain_on_finish,
161 .pwr_domain_off = ls1043_pwr_domain_off,
162};
163
164int plat_setup_psci_ops(uintptr_t sec_entrypoint,
165 const plat_psci_ops_t **psci_ops)
166{
167 warmboot_entry = sec_entrypoint;
168 *psci_ops = &ls1043_psci_pm_ops;
169 return 0;
170}