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> 7*9e86f0a2STony Han #include <drivers/rstctrl.h> 81dc7d0e9SClément Léger #include <io.h> 91dc7d0e9SClément Léger #include <kernel/dt.h> 109e3c57c8SEtienne Carriere #include <kernel/dt_driver.h> 11c2c7da1dSClément Léger #include <matrix.h> 126370f75dSTony Han #include <platform_config.h> 13*9e86f0a2STony Han #include <sys/queue.h> 141dc7d0e9SClément Léger #include <tee_api_defines.h> 151dc7d0e9SClément Léger #include <tee_api_types.h> 161dc7d0e9SClément Léger #include <types_ext.h> 171dc7d0e9SClément Léger 181dc7d0e9SClément Léger #define AT91_RSTC_CR 0x0 191dc7d0e9SClément Léger #define AT91_RSTC_CR_KEY SHIFT_U32(0xA5, 24) 201dc7d0e9SClément Léger #define AT91_RSTC_CR_PROCRST BIT32(0) 211dc7d0e9SClément Léger #define AT91_RSTC_CR_PERRST BIT32(2) 221dc7d0e9SClément Léger 23d557d174STony Han #define AT91_RSTC_GRSTR 0xE4 24d557d174STony Han #define AT91_RSTC_GRSTR_USB(x) SHIFT_U32(1, 4 + (x)) 25d557d174STony Han 261dc7d0e9SClément Léger static vaddr_t rstc_base; 271dc7d0e9SClément Léger 28*9e86f0a2STony Han struct sam_rstline { 29*9e86f0a2STony Han unsigned int reset_id; 30*9e86f0a2STony Han struct rstctrl rstctrl; 31*9e86f0a2STony Han SLIST_ENTRY(sam_rstline) link; 32*9e86f0a2STony Han }; 33*9e86f0a2STony Han 34*9e86f0a2STony Han static struct sam_rstline *to_sam_rstline(struct rstctrl *ptr) 35*9e86f0a2STony Han { 36*9e86f0a2STony Han assert(ptr); 37*9e86f0a2STony Han 38*9e86f0a2STony Han return container_of(ptr, struct sam_rstline, rstctrl); 39*9e86f0a2STony Han } 40*9e86f0a2STony Han 41*9e86f0a2STony Han static TEE_Result reset_assert(struct rstctrl *rstctrl, 42*9e86f0a2STony Han unsigned int to_us __unused) 43*9e86f0a2STony Han { 44*9e86f0a2STony Han unsigned int id = to_sam_rstline(rstctrl)->reset_id; 45*9e86f0a2STony Han 46*9e86f0a2STony Han io_setbits32(rstc_base + RESET_OFFSET(id), BIT(RESET_BIT_POS(id))); 47*9e86f0a2STony Han dsb(); 48*9e86f0a2STony Han 49*9e86f0a2STony Han return TEE_SUCCESS; 50*9e86f0a2STony Han } 51*9e86f0a2STony Han 52*9e86f0a2STony Han static TEE_Result reset_deassert(struct rstctrl *rstctrl, 53*9e86f0a2STony Han unsigned int to_us __unused) 54*9e86f0a2STony Han { 55*9e86f0a2STony Han unsigned int id = to_sam_rstline(rstctrl)->reset_id; 56*9e86f0a2STony Han 57*9e86f0a2STony Han io_clrbits32(rstc_base + RESET_OFFSET(id), BIT(RESET_BIT_POS(id))); 58*9e86f0a2STony Han dsb(); 59*9e86f0a2STony Han 60*9e86f0a2STony Han return TEE_SUCCESS; 61*9e86f0a2STony Han } 62*9e86f0a2STony Han 63*9e86f0a2STony Han static const struct rstctrl_ops sama7_rstc_ops = { 64*9e86f0a2STony Han .assert_level = reset_assert, 65*9e86f0a2STony Han .deassert_level = reset_deassert, 66*9e86f0a2STony Han }; 67*9e86f0a2STony Han DECLARE_KEEP_PAGER(sama7_rstc_ops); 68*9e86f0a2STony Han 691dc7d0e9SClément Léger bool atmel_rstc_available(void) 701dc7d0e9SClément Léger { 711dc7d0e9SClément Léger return rstc_base != 0; 721dc7d0e9SClément Léger } 731dc7d0e9SClément Léger 741dc7d0e9SClément Léger void __noreturn atmel_rstc_reset(void) 751dc7d0e9SClément Léger { 761dc7d0e9SClément Léger uint32_t val = AT91_RSTC_CR_KEY | AT91_RSTC_CR_PROCRST | 771dc7d0e9SClément Léger AT91_RSTC_CR_PERRST; 781dc7d0e9SClément Léger 791dc7d0e9SClément Léger io_write32(rstc_base + AT91_RSTC_CR, val); 801dc7d0e9SClément Léger 811dc7d0e9SClément Léger /* 821dc7d0e9SClément Léger * After the previous write, the CPU will reset so we will never hit 831dc7d0e9SClément Léger * this loop. 841dc7d0e9SClément Léger */ 851dc7d0e9SClément Léger while (true) 861dc7d0e9SClément Léger ; 871dc7d0e9SClément Léger } 881dc7d0e9SClément Léger 89d557d174STony Han void sam_rstc_usb_por(unsigned char id, bool enable) 90d557d174STony Han { 91d557d174STony Han if (!atmel_rstc_available()) 92d557d174STony Han panic(); 93d557d174STony Han 94d557d174STony Han if (enable) 95d557d174STony Han io_setbits32(rstc_base + AT91_RSTC_GRSTR, 96d557d174STony Han AT91_RSTC_GRSTR_USB(id)); 97d557d174STony Han else 98d557d174STony Han io_clrbits32(rstc_base + AT91_RSTC_GRSTR, 99d557d174STony Han AT91_RSTC_GRSTR_USB(id)); 100d557d174STony Han } 101d557d174STony Han 102379dc2aeSTony Han /* Non-null reference for compat data */ 103379dc2aeSTony Han static const uint8_t rstc_always_secure; 104379dc2aeSTony Han 1051dc7d0e9SClément Léger static TEE_Result atmel_rstc_probe(const void *fdt, int node, 106379dc2aeSTony Han const void *compat_data) 1071dc7d0e9SClément Léger 1081dc7d0e9SClément Léger { 1091dc7d0e9SClément Léger size_t size = 0; 1101dc7d0e9SClément Léger 111f354a5d8SGatien Chevallier if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) 112c2c7da1dSClément Léger return TEE_ERROR_BAD_PARAMETERS; 113c2c7da1dSClément Léger 114379dc2aeSTony Han if (compat_data != &rstc_always_secure) 115c2c7da1dSClément Léger matrix_configure_periph_secure(AT91C_ID_SYS); 116c2c7da1dSClément Léger 117a5d5bbc8SVesa Jääskeläinen if (dt_map_dev(fdt, node, &rstc_base, &size, DT_MAP_AUTO) < 0) 1181dc7d0e9SClément Léger return TEE_ERROR_GENERIC; 1191dc7d0e9SClément Léger 1201dc7d0e9SClément Léger return TEE_SUCCESS; 1211dc7d0e9SClément Léger } 1221dc7d0e9SClément Léger 1231dc7d0e9SClément Léger static const struct dt_device_match atmel_rstc_match_table[] = { 1241dc7d0e9SClément Léger { .compatible = "atmel,sama5d3-rstc" }, 125379dc2aeSTony Han { 126379dc2aeSTony Han .compatible = "microchip,sama7g5-rstc", 127379dc2aeSTony Han .compat_data = &rstc_always_secure, 128379dc2aeSTony Han }, 1291dc7d0e9SClément Léger { } 1301dc7d0e9SClément Léger }; 1311dc7d0e9SClément Léger 13261bdedeaSJerome Forissier DEFINE_DT_DRIVER(atmel_rstc_dt_driver) = { 1331dc7d0e9SClément Léger .name = "atmel_rstc", 1341dc7d0e9SClément Léger .type = DT_DRIVER_NOTYPE, 1351dc7d0e9SClément Léger .match_table = atmel_rstc_match_table, 1361dc7d0e9SClément Léger .probe = atmel_rstc_probe, 1371dc7d0e9SClément Léger }; 138