xref: /optee_os/core/drivers/atmel_rstc.c (revision 9e86f0a2065ab429a5b05e148b3f39c62f86c108)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2021, Microchip
4  */
5 
6 #include <drivers/atmel_rstc.h>
7 #include <drivers/rstctrl.h>
8 #include <io.h>
9 #include <kernel/dt.h>
10 #include <kernel/dt_driver.h>
11 #include <matrix.h>
12 #include <platform_config.h>
13 #include <sys/queue.h>
14 #include <tee_api_defines.h>
15 #include <tee_api_types.h>
16 #include <types_ext.h>
17 
18 #define AT91_RSTC_CR		0x0
19 #define AT91_RSTC_CR_KEY	SHIFT_U32(0xA5, 24)
20 #define AT91_RSTC_CR_PROCRST	BIT32(0)
21 #define AT91_RSTC_CR_PERRST	BIT32(2)
22 
23 #define AT91_RSTC_GRSTR		0xE4
24 #define AT91_RSTC_GRSTR_USB(x)	SHIFT_U32(1, 4 + (x))
25 
26 static vaddr_t rstc_base;
27 
28 struct sam_rstline {
29 	unsigned int reset_id;
30 	struct rstctrl rstctrl;
31 	SLIST_ENTRY(sam_rstline) link;
32 };
33 
34 static struct sam_rstline *to_sam_rstline(struct rstctrl *ptr)
35 {
36 	assert(ptr);
37 
38 	return container_of(ptr, struct sam_rstline, rstctrl);
39 }
40 
41 static TEE_Result reset_assert(struct rstctrl *rstctrl,
42 			       unsigned int to_us __unused)
43 {
44 	unsigned int id = to_sam_rstline(rstctrl)->reset_id;
45 
46 	io_setbits32(rstc_base + RESET_OFFSET(id), BIT(RESET_BIT_POS(id)));
47 	dsb();
48 
49 	return TEE_SUCCESS;
50 }
51 
52 static TEE_Result reset_deassert(struct rstctrl *rstctrl,
53 				 unsigned int to_us __unused)
54 {
55 	unsigned int id = to_sam_rstline(rstctrl)->reset_id;
56 
57 	io_clrbits32(rstc_base + RESET_OFFSET(id), BIT(RESET_BIT_POS(id)));
58 	dsb();
59 
60 	return TEE_SUCCESS;
61 }
62 
63 static const struct rstctrl_ops sama7_rstc_ops = {
64 	.assert_level = reset_assert,
65 	.deassert_level = reset_deassert,
66 };
67 DECLARE_KEEP_PAGER(sama7_rstc_ops);
68 
69 bool atmel_rstc_available(void)
70 {
71 	return rstc_base != 0;
72 }
73 
74 void __noreturn atmel_rstc_reset(void)
75 {
76 	uint32_t val = AT91_RSTC_CR_KEY | AT91_RSTC_CR_PROCRST |
77 		       AT91_RSTC_CR_PERRST;
78 
79 	io_write32(rstc_base + AT91_RSTC_CR, val);
80 
81 	/*
82 	 * After the previous write, the CPU will reset so we will never hit
83 	 * this loop.
84 	 */
85 	while (true)
86 		;
87 }
88 
89 void sam_rstc_usb_por(unsigned char id, bool enable)
90 {
91 	if (!atmel_rstc_available())
92 		panic();
93 
94 	if (enable)
95 		io_setbits32(rstc_base + AT91_RSTC_GRSTR,
96 			     AT91_RSTC_GRSTR_USB(id));
97 	else
98 		io_clrbits32(rstc_base + AT91_RSTC_GRSTR,
99 			     AT91_RSTC_GRSTR_USB(id));
100 }
101 
102 /* Non-null reference for compat data */
103 static const uint8_t rstc_always_secure;
104 
105 static TEE_Result atmel_rstc_probe(const void *fdt, int node,
106 				   const void *compat_data)
107 
108 {
109 	size_t size = 0;
110 
111 	if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC)
112 		return TEE_ERROR_BAD_PARAMETERS;
113 
114 	if (compat_data != &rstc_always_secure)
115 		matrix_configure_periph_secure(AT91C_ID_SYS);
116 
117 	if (dt_map_dev(fdt, node, &rstc_base, &size, DT_MAP_AUTO) < 0)
118 		return TEE_ERROR_GENERIC;
119 
120 	return TEE_SUCCESS;
121 }
122 
123 static const struct dt_device_match atmel_rstc_match_table[] = {
124 	{ .compatible = "atmel,sama5d3-rstc" },
125 	{
126 		.compatible = "microchip,sama7g5-rstc",
127 		.compat_data = &rstc_always_secure,
128 	},
129 	{ }
130 };
131 
132 DEFINE_DT_DRIVER(atmel_rstc_dt_driver) = {
133 	.name = "atmel_rstc",
134 	.type = DT_DRIVER_NOTYPE,
135 	.match_table = atmel_rstc_match_table,
136 	.probe = atmel_rstc_probe,
137 };
138