xref: /optee_os/core/drivers/atmel_rstc.c (revision 61bdedea9452abc1ec1582075fdd9cb9f81953a6)
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>
91dc7d0e9SClément Léger #include <tee_api_defines.h>
101dc7d0e9SClément Léger #include <tee_api_types.h>
111dc7d0e9SClément Léger #include <types_ext.h>
121dc7d0e9SClément Léger 
131dc7d0e9SClément Léger #define AT91_RSTC_CR		0x0
141dc7d0e9SClément Léger #define AT91_RSTC_CR_KEY	SHIFT_U32(0xA5, 24)
151dc7d0e9SClément Léger #define AT91_RSTC_CR_PROCRST	BIT32(0)
161dc7d0e9SClément Léger #define AT91_RSTC_CR_PERRST	BIT32(2)
171dc7d0e9SClément Léger 
181dc7d0e9SClément Léger static vaddr_t rstc_base;
191dc7d0e9SClément Léger 
201dc7d0e9SClément Léger bool atmel_rstc_available(void)
211dc7d0e9SClément Léger {
221dc7d0e9SClément Léger 	return rstc_base != 0;
231dc7d0e9SClément Léger }
241dc7d0e9SClément Léger 
251dc7d0e9SClément Léger void __noreturn atmel_rstc_reset(void)
261dc7d0e9SClément Léger {
271dc7d0e9SClément Léger 	uint32_t val = AT91_RSTC_CR_KEY | AT91_RSTC_CR_PROCRST |
281dc7d0e9SClément Léger 		       AT91_RSTC_CR_PERRST;
291dc7d0e9SClément Léger 
301dc7d0e9SClément Léger 	io_write32(rstc_base + AT91_RSTC_CR, val);
311dc7d0e9SClément Léger 
321dc7d0e9SClément Léger 	/*
331dc7d0e9SClément Léger 	 * After the previous write, the CPU will reset so we will never hit
341dc7d0e9SClément Léger 	 * this loop.
351dc7d0e9SClément Léger 	 */
361dc7d0e9SClément Léger 	while (true)
371dc7d0e9SClément Léger 		;
381dc7d0e9SClément Léger }
391dc7d0e9SClément Léger 
401dc7d0e9SClément Léger static TEE_Result atmel_rstc_probe(const void *fdt, int node,
411dc7d0e9SClément Léger 				   const void *compat_data __unused)
421dc7d0e9SClément Léger 
431dc7d0e9SClément Léger {
441dc7d0e9SClément Léger 	size_t size = 0;
451dc7d0e9SClément Léger 
461dc7d0e9SClément Léger 	if (dt_map_dev(fdt, node, &rstc_base, &size) < 0)
471dc7d0e9SClément Léger 		return TEE_ERROR_GENERIC;
481dc7d0e9SClément Léger 
491dc7d0e9SClément Léger 	return TEE_SUCCESS;
501dc7d0e9SClément Léger }
511dc7d0e9SClément Léger 
521dc7d0e9SClément Léger static const struct dt_device_match atmel_rstc_match_table[] = {
531dc7d0e9SClément Léger 	{ .compatible = "atmel,sama5d3-rstc" },
541dc7d0e9SClément Léger 	{ }
551dc7d0e9SClément Léger };
561dc7d0e9SClément Léger 
57*61bdedeaSJerome Forissier DEFINE_DT_DRIVER(atmel_rstc_dt_driver) = {
581dc7d0e9SClément Léger 	.name = "atmel_rstc",
591dc7d0e9SClément Léger 	.type = DT_DRIVER_NOTYPE,
601dc7d0e9SClément Léger 	.match_table = atmel_rstc_match_table,
611dc7d0e9SClément Léger 	.probe = atmel_rstc_probe,
621dc7d0e9SClément Léger };
63