xref: /optee_os/core/drivers/atmel_rstc.c (revision 1dc7d0e930914cf833a0ca55b6848877468cc7d0)
1*1dc7d0e9SClément Léger // SPDX-License-Identifier: BSD-2-Clause
2*1dc7d0e9SClément Léger /*
3*1dc7d0e9SClément Léger  * Copyright (c) 2021, Microchip
4*1dc7d0e9SClément Léger  */
5*1dc7d0e9SClément Léger 
6*1dc7d0e9SClément Léger #include <drivers/atmel_rstc.h>
7*1dc7d0e9SClément Léger #include <io.h>
8*1dc7d0e9SClément Léger #include <kernel/dt.h>
9*1dc7d0e9SClément Léger #include <tee_api_defines.h>
10*1dc7d0e9SClément Léger #include <tee_api_types.h>
11*1dc7d0e9SClément Léger #include <types_ext.h>
12*1dc7d0e9SClément Léger 
13*1dc7d0e9SClément Léger #define AT91_RSTC_CR		0x0
14*1dc7d0e9SClément Léger #define AT91_RSTC_CR_KEY	SHIFT_U32(0xA5, 24)
15*1dc7d0e9SClément Léger #define AT91_RSTC_CR_PROCRST	BIT32(0)
16*1dc7d0e9SClément Léger #define AT91_RSTC_CR_PERRST	BIT32(2)
17*1dc7d0e9SClément Léger 
18*1dc7d0e9SClément Léger static vaddr_t rstc_base;
19*1dc7d0e9SClément Léger 
20*1dc7d0e9SClément Léger bool atmel_rstc_available(void)
21*1dc7d0e9SClément Léger {
22*1dc7d0e9SClément Léger 	return rstc_base != 0;
23*1dc7d0e9SClément Léger }
24*1dc7d0e9SClément Léger 
25*1dc7d0e9SClément Léger void __noreturn atmel_rstc_reset(void)
26*1dc7d0e9SClément Léger {
27*1dc7d0e9SClément Léger 	uint32_t val = AT91_RSTC_CR_KEY | AT91_RSTC_CR_PROCRST |
28*1dc7d0e9SClément Léger 		       AT91_RSTC_CR_PERRST;
29*1dc7d0e9SClément Léger 
30*1dc7d0e9SClément Léger 	io_write32(rstc_base + AT91_RSTC_CR, val);
31*1dc7d0e9SClément Léger 
32*1dc7d0e9SClément Léger 	/*
33*1dc7d0e9SClément Léger 	 * After the previous write, the CPU will reset so we will never hit
34*1dc7d0e9SClément Léger 	 * this loop.
35*1dc7d0e9SClément Léger 	 */
36*1dc7d0e9SClément Léger 	while (true)
37*1dc7d0e9SClément Léger 		;
38*1dc7d0e9SClément Léger }
39*1dc7d0e9SClément Léger 
40*1dc7d0e9SClément Léger static TEE_Result atmel_rstc_probe(const void *fdt, int node,
41*1dc7d0e9SClément Léger 				   const void *compat_data __unused)
42*1dc7d0e9SClément Léger 
43*1dc7d0e9SClément Léger {
44*1dc7d0e9SClément Léger 	size_t size = 0;
45*1dc7d0e9SClément Léger 
46*1dc7d0e9SClément Léger 	if (dt_map_dev(fdt, node, &rstc_base, &size) < 0)
47*1dc7d0e9SClément Léger 		return TEE_ERROR_GENERIC;
48*1dc7d0e9SClément Léger 
49*1dc7d0e9SClément Léger 	return TEE_SUCCESS;
50*1dc7d0e9SClément Léger }
51*1dc7d0e9SClément Léger 
52*1dc7d0e9SClément Léger static const struct dt_device_match atmel_rstc_match_table[] = {
53*1dc7d0e9SClément Léger 	{ .compatible = "atmel,sama5d3-rstc" },
54*1dc7d0e9SClément Léger 	{ }
55*1dc7d0e9SClément Léger };
56*1dc7d0e9SClément Léger 
57*1dc7d0e9SClément Léger const struct dt_driver atmel_rstc_dt_driver __dt_driver = {
58*1dc7d0e9SClément Léger 	.name = "atmel_rstc",
59*1dc7d0e9SClément Léger 	.type = DT_DRIVER_NOTYPE,
60*1dc7d0e9SClément Léger 	.match_table = atmel_rstc_match_table,
61*1dc7d0e9SClément Léger 	.probe = atmel_rstc_probe,
62*1dc7d0e9SClément Léger };
63