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