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 <malloc.h> 12 #include <matrix.h> 13 #include <platform_config.h> 14 #include <stdbool.h> 15 #include <sys/queue.h> 16 #include <tee_api_defines.h> 17 #include <tee_api_types.h> 18 #include <types_ext.h> 19 20 #define AT91_RSTC_CR 0x0 21 #define AT91_RSTC_CR_KEY SHIFT_U32(0xA5, 24) 22 #define AT91_RSTC_CR_PROCRST BIT32(0) 23 #define AT91_RSTC_CR_PERRST BIT32(2) 24 25 #define AT91_RSTC_GRSTR 0xE4 26 #define AT91_RSTC_GRSTR_USB(x) SHIFT_U32(1, 4 + (x)) 27 28 static vaddr_t rstc_base; 29 30 struct sam_reset_data { 31 bool rstc_always_secure; 32 const struct rstctrl_ops *ops; 33 }; 34 35 struct sam_rstline { 36 unsigned int reset_id; 37 struct rstctrl rstctrl; 38 SLIST_ENTRY(sam_rstline) link; 39 }; 40 41 static SLIST_HEAD(, sam_rstline) sam_rst_list = 42 SLIST_HEAD_INITIALIZER(sam_rst_list); 43 44 static struct sam_rstline *to_sam_rstline(struct rstctrl *ptr) 45 { 46 assert(ptr); 47 48 return container_of(ptr, struct sam_rstline, rstctrl); 49 } 50 51 static struct sam_rstline *find_rstline(unsigned int reset_id) 52 { 53 struct sam_rstline *sam_rstline = NULL; 54 55 SLIST_FOREACH(sam_rstline, &sam_rst_list, link) 56 if (sam_rstline->reset_id == reset_id) 57 break; 58 59 return sam_rstline; 60 } 61 62 static struct 63 sam_rstline *find_or_allocate_rstline(unsigned int reset_id, 64 const struct sam_reset_data *pdata) 65 { 66 struct sam_rstline *sam_rstline = find_rstline(reset_id); 67 68 if (sam_rstline) 69 return sam_rstline; 70 71 sam_rstline = calloc(1, sizeof(*sam_rstline)); 72 if (sam_rstline) { 73 sam_rstline->reset_id = reset_id; 74 sam_rstline->rstctrl.ops = pdata->ops; 75 76 SLIST_INSERT_HEAD(&sam_rst_list, sam_rstline, link); 77 } 78 79 return sam_rstline; 80 } 81 82 static TEE_Result sam_rstctrl_dt_get(struct dt_pargs *args, void *data, 83 struct rstctrl **out_rstctrl) 84 { 85 struct sam_rstline *sam_rstline = NULL; 86 87 if (args->args_count != 1) 88 return TEE_ERROR_BAD_PARAMETERS; 89 90 sam_rstline = find_or_allocate_rstline(args->args[0], data); 91 if (!sam_rstline) 92 return TEE_ERROR_OUT_OF_MEMORY; 93 94 *out_rstctrl = &sam_rstline->rstctrl; 95 96 return TEE_SUCCESS; 97 } 98 99 static TEE_Result reset_assert(struct rstctrl *rstctrl, 100 unsigned int to_us __unused) 101 { 102 unsigned int id = to_sam_rstline(rstctrl)->reset_id; 103 104 io_setbits32(rstc_base + RESET_OFFSET(id), BIT(RESET_BIT_POS(id))); 105 dsb(); 106 107 return TEE_SUCCESS; 108 } 109 110 static TEE_Result reset_deassert(struct rstctrl *rstctrl, 111 unsigned int to_us __unused) 112 { 113 unsigned int id = to_sam_rstline(rstctrl)->reset_id; 114 115 io_clrbits32(rstc_base + RESET_OFFSET(id), BIT(RESET_BIT_POS(id))); 116 dsb(); 117 118 return TEE_SUCCESS; 119 } 120 121 static const struct rstctrl_ops sama7_rstc_ops = { 122 .assert_level = reset_assert, 123 .deassert_level = reset_deassert, 124 }; 125 DECLARE_KEEP_PAGER(sama7_rstc_ops); 126 127 static const struct sam_reset_data sama7_reset_data = { 128 .rstc_always_secure = true, 129 .ops = &sama7_rstc_ops 130 }; 131 DECLARE_KEEP_PAGER(sama7_reset_data); 132 133 struct rstctrl *sam_get_rstctrl(unsigned int reset_id) 134 { 135 struct sam_rstline *rstline = NULL; 136 137 rstline = find_or_allocate_rstline(reset_id, &sama7_reset_data); 138 assert(rstline); 139 140 return &rstline->rstctrl; 141 } 142 143 bool atmel_rstc_available(void) 144 { 145 return rstc_base != 0; 146 } 147 148 void __noreturn atmel_rstc_reset(void) 149 { 150 uint32_t val = AT91_RSTC_CR_KEY | AT91_RSTC_CR_PROCRST | 151 AT91_RSTC_CR_PERRST; 152 153 io_write32(rstc_base + AT91_RSTC_CR, val); 154 155 /* 156 * After the previous write, the CPU will reset so we will never hit 157 * this loop. 158 */ 159 while (true) 160 ; 161 } 162 163 void sam_rstc_usb_por(unsigned char id, bool enable) 164 { 165 if (!atmel_rstc_available()) 166 panic(); 167 168 if (enable) 169 io_setbits32(rstc_base + AT91_RSTC_GRSTR, 170 AT91_RSTC_GRSTR_USB(id)); 171 else 172 io_clrbits32(rstc_base + AT91_RSTC_GRSTR, 173 AT91_RSTC_GRSTR_USB(id)); 174 } 175 176 static TEE_Result atmel_rstc_probe(const void *fdt, int node, 177 const void *compat_data) 178 179 { 180 struct sam_reset_data *pdata = (struct sam_reset_data *)compat_data; 181 size_t size = 0; 182 183 if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) 184 return TEE_ERROR_BAD_PARAMETERS; 185 186 if (pdata && pdata->rstc_always_secure) 187 matrix_configure_periph_secure(AT91C_ID_SYS); 188 189 if (dt_map_dev(fdt, node, &rstc_base, &size, DT_MAP_AUTO) < 0) 190 return TEE_ERROR_GENERIC; 191 192 if (pdata) 193 return rstctrl_register_provider(fdt, node, sam_rstctrl_dt_get, 194 pdata); 195 196 return TEE_SUCCESS; 197 } 198 199 static const struct dt_device_match atmel_rstc_match_table[] = { 200 { .compatible = "atmel,sama5d3-rstc" }, 201 { 202 .compatible = "microchip,sama7g5-rstc", 203 .compat_data = &sama7_reset_data, 204 }, 205 { } 206 }; 207 208 DEFINE_DT_DRIVER(atmel_rstc_dt_driver) = { 209 .name = "atmel_rstc", 210 .type = DT_DRIVER_RSTCTRL, 211 .match_table = atmel_rstc_match_table, 212 .probe = atmel_rstc_probe, 213 }; 214