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