• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 Marek Behun, CZ.NIC
3  *
4  * SPDX-License-Identifier:     BSD-3-Clause
5  * https://spdx.org/licenses
6  */
7 
8 #include <stdbool.h>
9 
10 #include <common/debug.h>
11 #include <drivers/arm/gic_common.h>
12 #include <drivers/arm/gicv3.h>
13 #include <drivers/delay_timer.h>
14 #include <lib/mmio.h>
15 #include <lib/utils_def.h>
16 
17 #include <a3700_pm.h>
18 #include <platform_def.h>
19 #include <mvebu_def.h>
20 
21 /* IO Decoder Error Interrupt Status Registers */
22 #define MVEBU_DEC_WIN_REGS_BASE(p)		(MVEBU_REGS_BASE + 0xC000 + \
23 						 (p) * 0x100)
24 #define MVEBU_DEC_WIN_ERR_INT_STS_REG(p)	(MVEBU_DEC_WIN_REGS_BASE(p) + \
25 						 0xF8)
26 
27 /* Cortex-M3 Secure Processor Mailbox Registers */
28 #define MVEBU_RWTM_PARAM0_REG			(MVEBU_RWTM_REG_BASE)
29 #define MVEBU_RWTM_CMD_REG			(MVEBU_RWTM_REG_BASE + 0x40)
30 #define MVEBU_RWTM_HOST_INT_RESET_REG		(MVEBU_RWTM_REG_BASE + 0xC8)
31 #define MVEBU_RWTM_HOST_INT_MASK_REG		(MVEBU_RWTM_REG_BASE + 0xCC)
32 #define MVEBU_RWTM_HOST_INT_SP_COMPLETE		BIT(0)
33 
34 #define MVEBU_RWTM_REBOOT_CMD		0x0009
35 #define MVEBU_RWTM_REBOOT_MAGIC		0xDEADBEEF
36 
a3700_gicd_read(uint32_t reg)37 static inline uint32_t a3700_gicd_read(uint32_t reg)
38 {
39 	return mmio_read_32(PLAT_MARVELL_GICD_BASE + reg);
40 }
41 
a3700_gicd_write(uint32_t reg,uint32_t value)42 static inline void a3700_gicd_write(uint32_t reg, uint32_t value)
43 {
44 	mmio_write_32(PLAT_MARVELL_GICD_BASE + reg, value);
45 }
46 
a3700_gicd_ctlr_clear_bits(uint32_t bits)47 static void a3700_gicd_ctlr_clear_bits(uint32_t bits)
48 {
49 	uint32_t val;
50 
51 	val = a3700_gicd_read(GICD_CTLR);
52 	if ((val & bits) != 0U) {
53 		a3700_gicd_write(GICD_CTLR, val & ~bits);
54 		mdelay(1);
55 
56 		if ((a3700_gicd_read(GICD_CTLR) & GICD_CTLR_RWP_BIT) != 0U) {
57 			ERROR("could not clear bits 0x%x in GIC distributor control\n",
58 			      bits);
59 		}
60 	}
61 }
62 
a3700_gic_dist_disable_irqs(void)63 static void a3700_gic_dist_disable_irqs(void)
64 {
65 	int i;
66 
67 	for (i = 32; i < 224; i += 32) {
68 		a3700_gicd_write(GICD_ICENABLER + (i >> 3), GENMASK_32(31, 0));
69 	}
70 }
71 
a3700_rdist_base(unsigned int proc)72 static inline uintptr_t a3700_rdist_base(unsigned int proc)
73 {
74 	return PLAT_MARVELL_GICR_BASE + (proc << GICR_V3_PCPUBASE_SHIFT);
75 }
76 
a3700_gicr_read(unsigned int proc,uint32_t reg)77 static inline uint32_t a3700_gicr_read(unsigned int proc, uint32_t reg)
78 {
79 	return mmio_read_32(a3700_rdist_base(proc) + reg);
80 }
81 
a3700_gicr_write(unsigned int proc,uint32_t reg,uint32_t value)82 static inline void a3700_gicr_write(unsigned int proc, uint32_t reg,
83 				    uint32_t value)
84 {
85 	mmio_write_32(a3700_rdist_base(proc) + reg, value);
86 }
87 
a3700_gic_redist_disable_irqs(unsigned int proc)88 static void a3700_gic_redist_disable_irqs(unsigned int proc)
89 {
90 	a3700_gicr_write(proc, GICR_ICENABLER0, GENMASK_32(31, 0));
91 	mdelay(1);
92 
93 	if ((a3700_gicr_read(proc, GICR_CTLR) & GICR_CTLR_RWP_BIT) != 0U) {
94 		ERROR("could not disable core %u PPIs & SGIs\n", proc);
95 	}
96 }
97 
a3700_gic_redist_mark_asleep(unsigned int proc)98 static void a3700_gic_redist_mark_asleep(unsigned int proc)
99 {
100 	a3700_gicr_write(proc, GICR_WAKER,
101 			 a3700_gicr_read(proc, GICR_WAKER) | WAKER_PS_BIT);
102 	mdelay(1);
103 
104 	if ((a3700_gicr_read(proc, GICR_WAKER) & WAKER_CA_BIT) == 0U) {
105 		ERROR("could not mark core %u redistributor asleep\n", proc);
106 	}
107 }
108 
a3700_io_addr_dec_ack_err_irq(void)109 static void a3700_io_addr_dec_ack_err_irq(void)
110 {
111 	unsigned int periph;
112 
113 	for (periph = 0; periph < 16; ++periph) {
114 		/* periph 6 does not exist */
115 		if (periph == 6)
116 			continue;
117 
118 		mmio_write_32(MVEBU_DEC_WIN_ERR_INT_STS_REG(periph),
119 			      GENMASK_32(1, 0));
120 	}
121 }
122 
a3700_gic_reset(void)123 static void a3700_gic_reset(void)
124 {
125 	a3700_gic_redist_disable_irqs(0);
126 	a3700_gic_redist_disable_irqs(1);
127 
128 	a3700_gic_redist_mark_asleep(0);
129 	a3700_gic_redist_mark_asleep(1);
130 
131 	a3700_io_addr_dec_ack_err_irq();
132 
133 	a3700_pm_ack_irq();
134 
135 	a3700_gic_dist_disable_irqs();
136 
137 	a3700_gicd_ctlr_clear_bits(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1NS_BIT |
138 				   CTLR_ENABLE_G1S_BIT);
139 
140 	/* Clearing ARE_S and ARE_NS bits is undefined in the specification, but
141 	 * works if the previous operations are successful. We need to do it in
142 	 * order to put GIC into the same state it was in just after reset. If
143 	 * this is successful, the rWTM firmware in the secure coprocessor will
144 	 * reset all other peripherals one by one, load new firmware and boot
145 	 * it, all without triggering the true warm reset via the WARM_RESET
146 	 * register (which may hang the board).
147 	 */
148 
149 	a3700_gicd_ctlr_clear_bits(CTLR_ARE_S_BIT);
150 	a3700_gicd_ctlr_clear_bits(CTLR_ARE_NS_BIT);
151 }
152 
rwtm_completed(void)153 static inline bool rwtm_completed(void)
154 {
155 	return (mmio_read_32(MVEBU_RWTM_HOST_INT_RESET_REG) &
156 		MVEBU_RWTM_HOST_INT_SP_COMPLETE) != 0;
157 }
158 
rwtm_wait(int ms)159 static bool rwtm_wait(int ms)
160 {
161 	while (ms && !rwtm_completed()) {
162 		mdelay(1);
163 		--ms;
164 	}
165 
166 	return rwtm_completed();
167 }
168 
cm3_system_reset(void)169 void cm3_system_reset(void)
170 {
171 	int tries = 5;
172 
173 	/* Put GIC into the same state it was just after reset. This is needed
174 	 * for the reset issue workaround to work.
175 	 */
176 	a3700_gic_reset();
177 
178 	for (; tries > 0; --tries) {
179 		mmio_clrbits_32(MVEBU_RWTM_HOST_INT_RESET_REG,
180 				MVEBU_RWTM_HOST_INT_SP_COMPLETE);
181 
182 		mmio_write_32(MVEBU_RWTM_PARAM0_REG, MVEBU_RWTM_REBOOT_MAGIC);
183 		mmio_write_32(MVEBU_RWTM_CMD_REG, MVEBU_RWTM_REBOOT_CMD);
184 
185 		if (rwtm_wait(10)) {
186 			break;
187 		}
188 
189 		mdelay(100);
190 	}
191 
192 	/* If we reach here, the command is not implemented. */
193 	WARN("System reset command not implemented in WTMI firmware!\n");
194 }
195