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