xref: /optee_os/core/drivers/atmel_rstc.c (revision d557d174c2d61127096592743c41e829c915889b)
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>
71dc7d0e9SClément Léger #include <io.h>
81dc7d0e9SClément Léger #include <kernel/dt.h>
99e3c57c8SEtienne Carriere #include <kernel/dt_driver.h>
10c2c7da1dSClément Léger #include <matrix.h>
116370f75dSTony Han #include <platform_config.h>
121dc7d0e9SClément Léger #include <tee_api_defines.h>
131dc7d0e9SClément Léger #include <tee_api_types.h>
141dc7d0e9SClément Léger #include <types_ext.h>
151dc7d0e9SClément Léger 
161dc7d0e9SClément Léger #define AT91_RSTC_CR		0x0
171dc7d0e9SClément Léger #define AT91_RSTC_CR_KEY	SHIFT_U32(0xA5, 24)
181dc7d0e9SClément Léger #define AT91_RSTC_CR_PROCRST	BIT32(0)
191dc7d0e9SClément Léger #define AT91_RSTC_CR_PERRST	BIT32(2)
201dc7d0e9SClément Léger 
21*d557d174STony Han #define AT91_RSTC_GRSTR		0xE4
22*d557d174STony Han #define AT91_RSTC_GRSTR_USB(x)	SHIFT_U32(1, 4 + (x))
23*d557d174STony Han 
241dc7d0e9SClément Léger static vaddr_t rstc_base;
251dc7d0e9SClément Léger 
261dc7d0e9SClément Léger bool atmel_rstc_available(void)
271dc7d0e9SClément Léger {
281dc7d0e9SClément Léger 	return rstc_base != 0;
291dc7d0e9SClément Léger }
301dc7d0e9SClément Léger 
311dc7d0e9SClément Léger void __noreturn atmel_rstc_reset(void)
321dc7d0e9SClément Léger {
331dc7d0e9SClément Léger 	uint32_t val = AT91_RSTC_CR_KEY | AT91_RSTC_CR_PROCRST |
341dc7d0e9SClément Léger 		       AT91_RSTC_CR_PERRST;
351dc7d0e9SClément Léger 
361dc7d0e9SClément Léger 	io_write32(rstc_base + AT91_RSTC_CR, val);
371dc7d0e9SClément Léger 
381dc7d0e9SClément Léger 	/*
391dc7d0e9SClément Léger 	 * After the previous write, the CPU will reset so we will never hit
401dc7d0e9SClément Léger 	 * this loop.
411dc7d0e9SClément Léger 	 */
421dc7d0e9SClément Léger 	while (true)
431dc7d0e9SClément Léger 		;
441dc7d0e9SClément Léger }
451dc7d0e9SClément Léger 
46*d557d174STony Han void sam_rstc_usb_por(unsigned char id, bool enable)
47*d557d174STony Han {
48*d557d174STony Han 	if (!atmel_rstc_available())
49*d557d174STony Han 		panic();
50*d557d174STony Han 
51*d557d174STony Han 	if (enable)
52*d557d174STony Han 		io_setbits32(rstc_base + AT91_RSTC_GRSTR,
53*d557d174STony Han 			     AT91_RSTC_GRSTR_USB(id));
54*d557d174STony Han 	else
55*d557d174STony Han 		io_clrbits32(rstc_base + AT91_RSTC_GRSTR,
56*d557d174STony Han 			     AT91_RSTC_GRSTR_USB(id));
57*d557d174STony Han }
58*d557d174STony Han 
59379dc2aeSTony Han /* Non-null reference for compat data */
60379dc2aeSTony Han static const uint8_t rstc_always_secure;
61379dc2aeSTony Han 
621dc7d0e9SClément Léger static TEE_Result atmel_rstc_probe(const void *fdt, int node,
63379dc2aeSTony Han 				   const void *compat_data)
641dc7d0e9SClément Léger 
651dc7d0e9SClément Léger {
661dc7d0e9SClément Léger 	size_t size = 0;
671dc7d0e9SClément Léger 
68f354a5d8SGatien Chevallier 	if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC)
69c2c7da1dSClément Léger 		return TEE_ERROR_BAD_PARAMETERS;
70c2c7da1dSClément Léger 
71379dc2aeSTony Han 	if (compat_data != &rstc_always_secure)
72c2c7da1dSClément Léger 		matrix_configure_periph_secure(AT91C_ID_SYS);
73c2c7da1dSClément Léger 
74a5d5bbc8SVesa Jääskeläinen 	if (dt_map_dev(fdt, node, &rstc_base, &size, DT_MAP_AUTO) < 0)
751dc7d0e9SClément Léger 		return TEE_ERROR_GENERIC;
761dc7d0e9SClément Léger 
771dc7d0e9SClément Léger 	return TEE_SUCCESS;
781dc7d0e9SClément Léger }
791dc7d0e9SClément Léger 
801dc7d0e9SClément Léger static const struct dt_device_match atmel_rstc_match_table[] = {
811dc7d0e9SClément Léger 	{ .compatible = "atmel,sama5d3-rstc" },
82379dc2aeSTony Han 	{
83379dc2aeSTony Han 		.compatible = "microchip,sama7g5-rstc",
84379dc2aeSTony Han 		.compat_data = &rstc_always_secure,
85379dc2aeSTony Han 	},
861dc7d0e9SClément Léger 	{ }
871dc7d0e9SClément Léger };
881dc7d0e9SClément Léger 
8961bdedeaSJerome Forissier DEFINE_DT_DRIVER(atmel_rstc_dt_driver) = {
901dc7d0e9SClément Léger 	.name = "atmel_rstc",
911dc7d0e9SClément Léger 	.type = DT_DRIVER_NOTYPE,
921dc7d0e9SClément Léger 	.match_table = atmel_rstc_match_table,
931dc7d0e9SClément Léger 	.probe = atmel_rstc_probe,
941dc7d0e9SClément Léger };
95