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/delay_timer.h>
12 #include <lib/mmio.h>
13 
14 #include <mvebu_def.h>
15 
16 /* Cortex-M3 Secure Processor Mailbox Registers */
17 #define MVEBU_RWTM_PARAM0_REG			(MVEBU_RWTM_REG_BASE)
18 #define MVEBU_RWTM_CMD_REG			(MVEBU_RWTM_REG_BASE + 0x40)
19 #define MVEBU_RWTM_HOST_INT_RESET_REG		(MVEBU_RWTM_REG_BASE + 0xC8)
20 #define MVEBU_RWTM_HOST_INT_MASK_REG		(MVEBU_RWTM_REG_BASE + 0xCC)
21 #define MVEBU_RWTM_HOST_INT_SP_COMPLETE		BIT(0)
22 
23 #define MVEBU_RWTM_REBOOT_CMD		0x0009
24 #define MVEBU_RWTM_REBOOT_MAGIC		0xDEADBEEF
25 
rwtm_completed(void)26 static inline bool rwtm_completed(void)
27 {
28 	return (mmio_read_32(MVEBU_RWTM_HOST_INT_RESET_REG) &
29 		MVEBU_RWTM_HOST_INT_SP_COMPLETE) != 0;
30 }
31 
rwtm_wait(int ms)32 static bool rwtm_wait(int ms)
33 {
34 	while (ms && !rwtm_completed()) {
35 		mdelay(1);
36 		--ms;
37 	}
38 
39 	return rwtm_completed();
40 }
41 
cm3_system_reset(void)42 void cm3_system_reset(void)
43 {
44 	int tries = 5;
45 
46 	for (; tries > 0; --tries) {
47 		mmio_clrbits_32(MVEBU_RWTM_HOST_INT_RESET_REG,
48 				MVEBU_RWTM_HOST_INT_SP_COMPLETE);
49 
50 		mmio_write_32(MVEBU_RWTM_PARAM0_REG, MVEBU_RWTM_REBOOT_MAGIC);
51 		mmio_write_32(MVEBU_RWTM_CMD_REG, MVEBU_RWTM_REBOOT_CMD);
52 
53 		if (rwtm_wait(10)) {
54 			break;
55 		}
56 
57 		mdelay(100);
58 	}
59 
60 	/* If we reach here, the command is not implemented. */
61 	WARN("System reset command not implemented in WTMI firmware!\n");
62 }
63