1 /*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8 #include <endian.h>
9 #include <errno.h>
10
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>
20
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 */
53 static uintptr_t warmboot_entry;
54
55 /* warm reset single core */
ls1043_reset_core(int core_pos)56 static 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,
69 htobe32(1U << 31));
70 dsb();
71 isb();
72 /* reset core */
73 mmio_write_32(LS_SCFG_BASE + LS_SCFG_CORE0_SFT_RST_OFFSET +
74 core_pos * 4, htobe32(1U << 31));
75 mdelay(10);
76 }
77
ls1043_system_reset(void)78 static 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
ls1043_pwr_domain_on(u_register_t mpidr)96 static int ls1043_pwr_domain_on(u_register_t mpidr)
97 {
98 int core_pos = plat_core_pos_by_mpidr(mpidr);
99 uint32_t core_mask, brr;
100
101 assert(core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT);
102 core_mask = 1 << core_pos;
103
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
ls1043_pwr_domain_on_finish(const psci_power_state_t * target_state)142 static 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
ls1043_pwr_domain_off(const psci_power_state_t * target_state)151 static 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
157 static 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
plat_setup_psci_ops(uintptr_t sec_entrypoint,const plat_psci_ops_t ** psci_ops)164 int 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 }
171