xref: /optee_os/core/drivers/atmel_rstc.c (revision 9e86f0a2065ab429a5b05e148b3f39c62f86c108)
11dc7d0e9SClément Léger // SPDX-License-Identifier: BSD-2-Clause
21dc7d0e9SClément Léger /*
31dc7d0e9SClément Léger  * Copyright (c) 2021, Microchip
41dc7d0e9SClément Léger  */
51dc7d0e9SClément Léger 
61dc7d0e9SClément Léger #include <drivers/atmel_rstc.h>
7*9e86f0a2STony Han #include <drivers/rstctrl.h>
81dc7d0e9SClément Léger #include <io.h>
91dc7d0e9SClément Léger #include <kernel/dt.h>
109e3c57c8SEtienne Carriere #include <kernel/dt_driver.h>
11c2c7da1dSClément Léger #include <matrix.h>
126370f75dSTony Han #include <platform_config.h>
13*9e86f0a2STony Han #include <sys/queue.h>
141dc7d0e9SClément Léger #include <tee_api_defines.h>
151dc7d0e9SClément Léger #include <tee_api_types.h>
161dc7d0e9SClément Léger #include <types_ext.h>
171dc7d0e9SClément Léger 
181dc7d0e9SClément Léger #define AT91_RSTC_CR		0x0
191dc7d0e9SClément Léger #define AT91_RSTC_CR_KEY	SHIFT_U32(0xA5, 24)
201dc7d0e9SClément Léger #define AT91_RSTC_CR_PROCRST	BIT32(0)
211dc7d0e9SClément Léger #define AT91_RSTC_CR_PERRST	BIT32(2)
221dc7d0e9SClément Léger 
23d557d174STony Han #define AT91_RSTC_GRSTR		0xE4
24d557d174STony Han #define AT91_RSTC_GRSTR_USB(x)	SHIFT_U32(1, 4 + (x))
25d557d174STony Han 
261dc7d0e9SClément Léger static vaddr_t rstc_base;
271dc7d0e9SClément Léger 
28*9e86f0a2STony Han struct sam_rstline {
29*9e86f0a2STony Han 	unsigned int reset_id;
30*9e86f0a2STony Han 	struct rstctrl rstctrl;
31*9e86f0a2STony Han 	SLIST_ENTRY(sam_rstline) link;
32*9e86f0a2STony Han };
33*9e86f0a2STony Han 
34*9e86f0a2STony Han static struct sam_rstline *to_sam_rstline(struct rstctrl *ptr)
35*9e86f0a2STony Han {
36*9e86f0a2STony Han 	assert(ptr);
37*9e86f0a2STony Han 
38*9e86f0a2STony Han 	return container_of(ptr, struct sam_rstline, rstctrl);
39*9e86f0a2STony Han }
40*9e86f0a2STony Han 
41*9e86f0a2STony Han static TEE_Result reset_assert(struct rstctrl *rstctrl,
42*9e86f0a2STony Han 			       unsigned int to_us __unused)
43*9e86f0a2STony Han {
44*9e86f0a2STony Han 	unsigned int id = to_sam_rstline(rstctrl)->reset_id;
45*9e86f0a2STony Han 
46*9e86f0a2STony Han 	io_setbits32(rstc_base + RESET_OFFSET(id), BIT(RESET_BIT_POS(id)));
47*9e86f0a2STony Han 	dsb();
48*9e86f0a2STony Han 
49*9e86f0a2STony Han 	return TEE_SUCCESS;
50*9e86f0a2STony Han }
51*9e86f0a2STony Han 
52*9e86f0a2STony Han static TEE_Result reset_deassert(struct rstctrl *rstctrl,
53*9e86f0a2STony Han 				 unsigned int to_us __unused)
54*9e86f0a2STony Han {
55*9e86f0a2STony Han 	unsigned int id = to_sam_rstline(rstctrl)->reset_id;
56*9e86f0a2STony Han 
57*9e86f0a2STony Han 	io_clrbits32(rstc_base + RESET_OFFSET(id), BIT(RESET_BIT_POS(id)));
58*9e86f0a2STony Han 	dsb();
59*9e86f0a2STony Han 
60*9e86f0a2STony Han 	return TEE_SUCCESS;
61*9e86f0a2STony Han }
62*9e86f0a2STony Han 
63*9e86f0a2STony Han static const struct rstctrl_ops sama7_rstc_ops = {
64*9e86f0a2STony Han 	.assert_level = reset_assert,
65*9e86f0a2STony Han 	.deassert_level = reset_deassert,
66*9e86f0a2STony Han };
67*9e86f0a2STony Han DECLARE_KEEP_PAGER(sama7_rstc_ops);
68*9e86f0a2STony Han 
691dc7d0e9SClément Léger bool atmel_rstc_available(void)
701dc7d0e9SClément Léger {
711dc7d0e9SClément Léger 	return rstc_base != 0;
721dc7d0e9SClément Léger }
731dc7d0e9SClément Léger 
741dc7d0e9SClément Léger void __noreturn atmel_rstc_reset(void)
751dc7d0e9SClément Léger {
761dc7d0e9SClément Léger 	uint32_t val = AT91_RSTC_CR_KEY | AT91_RSTC_CR_PROCRST |
771dc7d0e9SClément Léger 		       AT91_RSTC_CR_PERRST;
781dc7d0e9SClément Léger 
791dc7d0e9SClément Léger 	io_write32(rstc_base + AT91_RSTC_CR, val);
801dc7d0e9SClément Léger 
811dc7d0e9SClément Léger 	/*
821dc7d0e9SClément Léger 	 * After the previous write, the CPU will reset so we will never hit
831dc7d0e9SClément Léger 	 * this loop.
841dc7d0e9SClément Léger 	 */
851dc7d0e9SClément Léger 	while (true)
861dc7d0e9SClément Léger 		;
871dc7d0e9SClément Léger }
881dc7d0e9SClément Léger 
89d557d174STony Han void sam_rstc_usb_por(unsigned char id, bool enable)
90d557d174STony Han {
91d557d174STony Han 	if (!atmel_rstc_available())
92d557d174STony Han 		panic();
93d557d174STony Han 
94d557d174STony Han 	if (enable)
95d557d174STony Han 		io_setbits32(rstc_base + AT91_RSTC_GRSTR,
96d557d174STony Han 			     AT91_RSTC_GRSTR_USB(id));
97d557d174STony Han 	else
98d557d174STony Han 		io_clrbits32(rstc_base + AT91_RSTC_GRSTR,
99d557d174STony Han 			     AT91_RSTC_GRSTR_USB(id));
100d557d174STony Han }
101d557d174STony Han 
102379dc2aeSTony Han /* Non-null reference for compat data */
103379dc2aeSTony Han static const uint8_t rstc_always_secure;
104379dc2aeSTony Han 
1051dc7d0e9SClément Léger static TEE_Result atmel_rstc_probe(const void *fdt, int node,
106379dc2aeSTony Han 				   const void *compat_data)
1071dc7d0e9SClément Léger 
1081dc7d0e9SClément Léger {
1091dc7d0e9SClément Léger 	size_t size = 0;
1101dc7d0e9SClément Léger 
111f354a5d8SGatien Chevallier 	if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC)
112c2c7da1dSClément Léger 		return TEE_ERROR_BAD_PARAMETERS;
113c2c7da1dSClément Léger 
114379dc2aeSTony Han 	if (compat_data != &rstc_always_secure)
115c2c7da1dSClément Léger 		matrix_configure_periph_secure(AT91C_ID_SYS);
116c2c7da1dSClément Léger 
117a5d5bbc8SVesa Jääskeläinen 	if (dt_map_dev(fdt, node, &rstc_base, &size, DT_MAP_AUTO) < 0)
1181dc7d0e9SClément Léger 		return TEE_ERROR_GENERIC;
1191dc7d0e9SClément Léger 
1201dc7d0e9SClément Léger 	return TEE_SUCCESS;
1211dc7d0e9SClément Léger }
1221dc7d0e9SClément Léger 
1231dc7d0e9SClément Léger static const struct dt_device_match atmel_rstc_match_table[] = {
1241dc7d0e9SClément Léger 	{ .compatible = "atmel,sama5d3-rstc" },
125379dc2aeSTony Han 	{
126379dc2aeSTony Han 		.compatible = "microchip,sama7g5-rstc",
127379dc2aeSTony Han 		.compat_data = &rstc_always_secure,
128379dc2aeSTony Han 	},
1291dc7d0e9SClément Léger 	{ }
1301dc7d0e9SClément Léger };
1311dc7d0e9SClément Léger 
13261bdedeaSJerome Forissier DEFINE_DT_DRIVER(atmel_rstc_dt_driver) = {
1331dc7d0e9SClément Léger 	.name = "atmel_rstc",
1341dc7d0e9SClément Léger 	.type = DT_DRIVER_NOTYPE,
1351dc7d0e9SClément Léger 	.match_table = atmel_rstc_match_table,
1361dc7d0e9SClément Léger 	.probe = atmel_rstc_probe,
1371dc7d0e9SClément Léger };
138