11fe98f82SClément Léger // SPDX-License-Identifier: BSD-2-Clause 21fe98f82SClément Léger /* 31fe98f82SClément Léger * Copyright 2022 Microchip 41fe98f82SClément Léger * 51fe98f82SClément Léger * Driver for AT91 PIOBU 61fe98f82SClément Léger */ 71fe98f82SClément Léger 81fe98f82SClément Léger #include <assert.h> 91fe98f82SClément Léger #include <drivers/atmel_rtc.h> 101fe98f82SClément Léger #include <dt-bindings/gpio/atmel,piobu.h> 111fe98f82SClément Léger #include <gpio.h> 121fe98f82SClément Léger #include <io.h> 131fe98f82SClément Léger #include <kernel/boot.h> 141fe98f82SClément Léger #include <kernel/dt.h> 15*9e3c57c8SEtienne Carriere #include <kernel/dt_driver.h> 161fe98f82SClément Léger #include <kernel/pm.h> 171fe98f82SClément Léger #include <libfdt.h> 181fe98f82SClément Léger #include <mm/core_memprot.h> 191fe98f82SClément Léger 201fe98f82SClément Léger #define SECUMOD_MAX_PINS 8 211fe98f82SClément Léger #define SECUMOD_PIN_MASK (BIT(SECUMOD_MAX_PINS) - 1) 221fe98f82SClément Léger #define SECUMOD_PIN_SHIFT 16 231fe98f82SClément Léger #define SECUMOD_PIN_VAL(pin) BIT(SECUMOD_PIN_SHIFT + (pin)) 241fe98f82SClément Léger 251fe98f82SClément Léger #define DT_GPIO_CELLS 2 261fe98f82SClément Léger 271fe98f82SClément Léger #define SECUMOD_CR 0x0 281fe98f82SClément Léger #define SECUMOD_CR_KEY_SHIFT 16 291fe98f82SClément Léger #define SECUMOD_CR_KEY SHIFT_U32(0x89CA, SECUMOD_CR_KEY_SHIFT) 301fe98f82SClément Léger #define SECUMOD_CR_BACKUP BIT(0) 311fe98f82SClément Léger #define SECUMOD_CR_NORMAL BIT(1) 321fe98f82SClément Léger 331fe98f82SClément Léger #define SECUMOD_SR 0x8 341fe98f82SClément Léger #define SECUMOD_SR_JTAG BIT(3) 351fe98f82SClément Léger #define SECUMOD_SR_TST_PIN BIT(2) 361fe98f82SClément Léger 371fe98f82SClément Léger #define SECUMOD_SCR 0x10 381fe98f82SClément Léger 391fe98f82SClément Léger #define SECUMOD_PIOBU(x) (0x18 + (x) * 0x4) 401fe98f82SClément Léger #define SECUMOD_PIOBU_AFV_MASK GENMASK_32(3, 0) 411fe98f82SClément Léger #define SECUMOD_PIOBU_RFV_SHIFT 4 421fe98f82SClément Léger #define SECUMOD_PIOBU_OUTPUT BIT(8) 431fe98f82SClément Léger #define SECUMOD_PIOBU_SOD BIT(9) 441fe98f82SClément Léger #define SECUMOD_PIOBU_PDS BIT(10) 451fe98f82SClément Léger #define SECUMOD_PIOBU_PULLUP_SHIFT 12 461fe98f82SClément Léger #define SECUMOD_PIOBU_SWITCH_SHIFT 15 471fe98f82SClément Léger 481fe98f82SClément Léger #define SECUMOD_JTAGCR 0x68 491fe98f82SClément Léger #define SECUMOD_JTAGCR_FNTRST 0x1 501fe98f82SClément Léger 511fe98f82SClément Léger #define SECUMOD_BMPR 0x7C 521fe98f82SClément Léger #define SECUMOD_NMPR 0x80 531fe98f82SClément Léger #define SECUMOD_NIEPR 0x84 541fe98f82SClément Léger #define SECUMOD_NIDPR 0x88 551fe98f82SClément Léger #define SECUMOD_NIMPR 0x8C 561fe98f82SClément Léger #define SECUMOD_WKPR 0x90 571fe98f82SClément Léger 581fe98f82SClément Léger static vaddr_t secumod_base; 591fe98f82SClément Léger static uint32_t gpio_protected; 601fe98f82SClément Léger static struct gpio_chip secumod_chip; 611fe98f82SClément Léger 621fe98f82SClément Léger /* 631fe98f82SClément Léger * Get value from GPIO controller 641fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 651fe98f82SClément Léger * gpio_pin: pin from which value needs to be read 661fe98f82SClément Léger * Return target GPIO pin level. 671fe98f82SClément Léger */ 681fe98f82SClément Léger static enum gpio_level gpio_get_value(struct gpio_chip *chip __unused, 691fe98f82SClément Léger unsigned int gpio_pin) 701fe98f82SClément Léger { 711fe98f82SClément Léger vaddr_t piobu_addr = 0; 721fe98f82SClément Léger uint32_t piobu = 0; 731fe98f82SClément Léger 741fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 751fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 761fe98f82SClément Léger 771fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 781fe98f82SClément Léger piobu = io_read32(piobu_addr); 791fe98f82SClément Léger 801fe98f82SClément Léger if (piobu & SECUMOD_PIOBU_PDS) 811fe98f82SClément Léger return GPIO_LEVEL_HIGH; 821fe98f82SClément Léger else 831fe98f82SClément Léger return GPIO_LEVEL_LOW; 841fe98f82SClément Léger } 851fe98f82SClément Léger 861fe98f82SClément Léger /* 871fe98f82SClément Léger * Set value for GPIO controller 881fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 891fe98f82SClément Léger * gpio_pin: pin to which value needs to be written 901fe98f82SClément Léger * value: Level state for the target pin 911fe98f82SClément Léger */ 921fe98f82SClément Léger static void gpio_set_value(struct gpio_chip *chip __unused, 931fe98f82SClément Léger unsigned int gpio_pin, enum gpio_level value) 941fe98f82SClément Léger { 951fe98f82SClément Léger vaddr_t piobu_addr = 0; 961fe98f82SClément Léger 971fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 981fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 991fe98f82SClément Léger 1001fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 1011fe98f82SClément Léger 1021fe98f82SClément Léger if (value == GPIO_LEVEL_HIGH) 1031fe98f82SClément Léger io_setbits32(piobu_addr, SECUMOD_PIOBU_SOD); 1041fe98f82SClément Léger else 1051fe98f82SClément Léger io_clrbits32(piobu_addr, SECUMOD_PIOBU_SOD); 1061fe98f82SClément Léger } 1071fe98f82SClément Léger 1081fe98f82SClément Léger /* 1091fe98f82SClément Léger * Get direction from GPIO controller 1101fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 1111fe98f82SClément Léger * gpio_pin: pin from which direction needs to be read 1121fe98f82SClément Léger */ 1131fe98f82SClément Léger static enum gpio_dir gpio_get_direction(struct gpio_chip *chip __unused, 1141fe98f82SClément Léger unsigned int gpio_pin) 1151fe98f82SClément Léger { 1161fe98f82SClément Léger vaddr_t piobu_addr = 0; 1171fe98f82SClément Léger uint32_t piobu = 0; 1181fe98f82SClément Léger 1191fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 1201fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 1211fe98f82SClément Léger 1221fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 1231fe98f82SClément Léger piobu = io_read32(piobu_addr); 1241fe98f82SClément Léger 1251fe98f82SClément Léger if (piobu & SECUMOD_PIOBU_OUTPUT) 1261fe98f82SClément Léger return GPIO_DIR_OUT; 1271fe98f82SClément Léger else 1281fe98f82SClément Léger return GPIO_DIR_IN; 1291fe98f82SClément Léger } 1301fe98f82SClément Léger 1311fe98f82SClément Léger /* 1321fe98f82SClément Léger * Set direction for GPIO controller 1331fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 1341fe98f82SClément Léger * gpio_pin: pin on which direction needs to be set 1351fe98f82SClément Léger * direction: direction which needs to be set on pin 1361fe98f82SClément Léger */ 1371fe98f82SClément Léger static void gpio_set_direction(struct gpio_chip *chip __unused, 1381fe98f82SClément Léger unsigned int gpio_pin, enum gpio_dir direction) 1391fe98f82SClément Léger { 1401fe98f82SClément Léger vaddr_t piobu_addr = 0; 1411fe98f82SClément Léger 1421fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 1431fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 1441fe98f82SClément Léger 1451fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 1461fe98f82SClément Léger 1471fe98f82SClément Léger if (direction == GPIO_DIR_OUT) 1481fe98f82SClément Léger io_setbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 1491fe98f82SClément Léger else 1501fe98f82SClément Léger io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 1511fe98f82SClément Léger } 1521fe98f82SClément Léger 1531fe98f82SClément Léger /* 1541fe98f82SClément Léger * Get interrupt from GPIO controller 1551fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 1561fe98f82SClément Léger * gpio_pin: pin from which interrupt value needs to be read 1571fe98f82SClément Léger */ 1581fe98f82SClément Léger static enum gpio_interrupt gpio_get_interrupt(struct gpio_chip *chip __unused, 1591fe98f82SClément Léger unsigned int gpio_pin) 1601fe98f82SClément Léger { 1611fe98f82SClément Léger vaddr_t nimpr_addr = secumod_base + SECUMOD_NIMPR; 1621fe98f82SClément Léger uint32_t data = 0; 1631fe98f82SClément Léger 1641fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 1651fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 1661fe98f82SClément Léger 1671fe98f82SClément Léger data = io_read32(nimpr_addr); 1681fe98f82SClément Léger 1691fe98f82SClément Léger if (data & SECUMOD_PIN_VAL(gpio_pin)) 1701fe98f82SClément Léger return GPIO_INTERRUPT_ENABLE; 1711fe98f82SClément Léger else 1721fe98f82SClément Léger return GPIO_INTERRUPT_DISABLE; 1731fe98f82SClément Léger } 1741fe98f82SClément Léger 1751fe98f82SClément Léger /* 1761fe98f82SClément Léger * Set interrupt event for GPIO controller 1771fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 1781fe98f82SClément Léger * gpio_pin: pin on which interrupt value needs to be set 1791fe98f82SClément Léger * interrupt: interrupt value which needs to be set on pin 1801fe98f82SClément Léger */ 1811fe98f82SClément Léger static void gpio_set_interrupt(struct gpio_chip *chip __unused, 1821fe98f82SClément Léger unsigned int gpio_pin, 1831fe98f82SClément Léger enum gpio_interrupt interrupt) 1841fe98f82SClément Léger { 1851fe98f82SClément Léger vaddr_t niepr_addr = secumod_base + SECUMOD_NIEPR; 1861fe98f82SClément Léger 1871fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 1881fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 1891fe98f82SClément Léger 1901fe98f82SClément Léger if (interrupt == GPIO_INTERRUPT_ENABLE) 1911fe98f82SClément Léger io_setbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); 1921fe98f82SClément Léger else 1931fe98f82SClément Léger io_clrbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); 1941fe98f82SClément Léger } 1951fe98f82SClément Léger 1961fe98f82SClément Léger static const struct gpio_ops atmel_piobu_ops = { 1971fe98f82SClément Léger .get_direction = gpio_get_direction, 1981fe98f82SClément Léger .set_direction = gpio_set_direction, 1991fe98f82SClément Léger .get_value = gpio_get_value, 2001fe98f82SClément Léger .set_value = gpio_set_value, 2011fe98f82SClément Léger .get_interrupt = gpio_get_interrupt, 2021fe98f82SClément Léger .set_interrupt = gpio_set_interrupt, 2031fe98f82SClément Léger }; 2041fe98f82SClément Léger 2051fe98f82SClément Léger static enum itr_return secumod_it_handler(struct itr_handler *handler __unused) 2061fe98f82SClément Léger { 2071fe98f82SClément Léger int i = 0; 2081fe98f82SClément Léger struct optee_rtc_time tm = { }; 2091fe98f82SClément Léger TEE_Result res = TEE_ERROR_GENERIC; 2101fe98f82SClément Léger uint32_t sr = io_read32(secumod_base + SECUMOD_SR); 2111fe98f82SClément Léger 2121fe98f82SClément Léger for (i = 0; i < SECUMOD_MAX_PINS; i++) { 2131fe98f82SClément Léger if (sr & SECUMOD_PIN_VAL(i)) 2141fe98f82SClément Léger EMSG("Detected tampering on pin %d", i); 2151fe98f82SClément Léger } 2161fe98f82SClément Léger 2171fe98f82SClément Léger if (sr & SECUMOD_SR_JTAG) 2181fe98f82SClément Léger EMSG("JTAG tampering attempt"); 2191fe98f82SClément Léger 2201fe98f82SClément Léger if (sr & SECUMOD_SR_TST_PIN) 2211fe98f82SClément Léger EMSG("Test pin tampering attempt"); 2221fe98f82SClément Léger 2231fe98f82SClément Léger res = atmel_rtc_get_tamper_timestamp(&tm); 2241fe98f82SClément Léger if (!res) { 2251fe98f82SClément Léger EMSG("Date of tampering: %02"PRIu32"/%02"PRIu32"/%02"PRIu32"", 2261fe98f82SClément Léger tm.tm_mday, tm.tm_mon, tm.tm_year); 2271fe98f82SClément Léger EMSG("Time of tampering: %02"PRIu32":%02"PRIu32":%02"PRIu32"", 2281fe98f82SClément Léger tm.tm_hour, tm.tm_min, tm.tm_sec); 2291fe98f82SClément Léger } 2301fe98f82SClément Léger 2311fe98f82SClément Léger io_write32(secumod_base + SECUMOD_SCR, 2321fe98f82SClément Léger SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); 2331fe98f82SClément Léger 2341fe98f82SClément Léger panic("Tampering detected, system halted"); 2351fe98f82SClément Léger 2361fe98f82SClément Léger return ITRR_HANDLED; 2371fe98f82SClément Léger } 2381fe98f82SClément Léger 2391fe98f82SClément Léger static struct itr_handler secumod_itr_handler = { 2401fe98f82SClément Léger .it = AT91C_ID_SECUMOD, 2411fe98f82SClément Léger .handler = secumod_it_handler, 2421fe98f82SClément Léger }; 2431fe98f82SClément Léger 2441fe98f82SClément Léger static void secumod_interrupt_init(void) 2451fe98f82SClément Léger { 2461fe98f82SClément Léger itr_add_type_prio(&secumod_itr_handler, IRQ_TYPE_LEVEL_HIGH, 7); 2471fe98f82SClément Léger itr_enable(secumod_itr_handler.it); 2481fe98f82SClément Léger } 2491fe98f82SClément Léger 2501fe98f82SClément Léger static void secumod_cfg_input_pio(uint8_t gpio_pin, uint32_t config) 2511fe98f82SClément Léger { 2521fe98f82SClément Léger vaddr_t piobu_addr = 0; 2531fe98f82SClément Léger uint8_t afv = 0; 2541fe98f82SClément Léger uint8_t rfv = 0; 2551fe98f82SClément Léger uint8_t pull_mode = PIOBU_PIN_PULL_NONE; 2561fe98f82SClément Léger uint8_t def_level = PIOBU_PIN_DEF_LEVEL_LOW; 2571fe98f82SClément Léger 2581fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS); 2591fe98f82SClément Léger 2601fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 2611fe98f82SClément Léger 2621fe98f82SClément Léger /* Set GPIO as input */ 2631fe98f82SClément Léger io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 2641fe98f82SClément Léger 2651fe98f82SClément Léger afv = PIOBU_PIN_AFV(config); 2661fe98f82SClément Léger rfv = PIOBU_PIN_RFV(config); 2671fe98f82SClément Léger pull_mode = PIOBU_PIN_PULL_MODE(config); 2681fe98f82SClément Léger def_level = PIOBU_PIN_DEF_LEVEL(config); 2691fe98f82SClément Léger 2701fe98f82SClément Léger io_write32(piobu_addr, afv | rfv << SECUMOD_PIOBU_RFV_SHIFT | 2711fe98f82SClément Léger pull_mode << SECUMOD_PIOBU_PULLUP_SHIFT | 2721fe98f82SClément Léger def_level << SECUMOD_PIOBU_SWITCH_SHIFT); 2731fe98f82SClément Léger 2741fe98f82SClément Léger /* Enable Tampering Interrupt */ 2751fe98f82SClément Léger gpio_set_interrupt(&secumod_chip, gpio_pin, GPIO_INTERRUPT_ENABLE); 2761fe98f82SClément Léger 2771fe98f82SClément Léger /* Enable Intrusion Detection */ 2781fe98f82SClément Léger io_setbits32(secumod_base + SECUMOD_NMPR, SECUMOD_PIN_VAL(gpio_pin)); 2791fe98f82SClément Léger 2801fe98f82SClément Léger /* Enable Wakeup */ 2811fe98f82SClément Léger if (PIOBU_PIN_WAKEUP(config)) 2821fe98f82SClément Léger io_setbits32(secumod_base + SECUMOD_WKPR, 2831fe98f82SClément Léger SECUMOD_PIN_VAL(gpio_pin)); 2841fe98f82SClément Léger 2851fe98f82SClément Léger gpio_protected |= BIT32(gpio_pin); 2861fe98f82SClément Léger } 2871fe98f82SClément Léger 2881fe98f82SClément Léger static void secumod_hw_init(const void *fdt, int node) 2891fe98f82SClément Léger { 2901fe98f82SClément Léger int i = 0; 2911fe98f82SClément Léger int len = 0; 2921fe98f82SClément Léger uint8_t gpio_pin = 0; 2931fe98f82SClément Léger uint32_t config = 0; 2941fe98f82SClément Léger const uint32_t *prop = NULL; 2951fe98f82SClément Léger 2961fe98f82SClément Léger /* Disable JTAG Reset and Debug */ 2971fe98f82SClément Léger io_write32(secumod_base + SECUMOD_JTAGCR, SECUMOD_JTAGCR_FNTRST); 2981fe98f82SClément Léger 2991fe98f82SClément Léger /* Switch IOs to normal mode */ 3001fe98f82SClément Léger io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 3011fe98f82SClément Léger SECUMOD_CR_NORMAL); 3021fe98f82SClément Léger 3031fe98f82SClément Léger /* Clear all detection intrusion in normal mode */ 3041fe98f82SClément Léger io_write32(secumod_base + SECUMOD_NMPR, 0); 3051fe98f82SClément Léger 3061fe98f82SClément Léger /* Clear Alarms */ 3071fe98f82SClément Léger io_write32(secumod_base + SECUMOD_SCR, 3081fe98f82SClément Léger SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); 3091fe98f82SClément Léger 3101fe98f82SClément Léger /* Configure each IOs */ 3111fe98f82SClément Léger prop = fdt_getprop(fdt, node, "gpios", &len); 3121fe98f82SClément Léger if (!prop) 3131fe98f82SClément Léger return; 3141fe98f82SClément Léger 3151fe98f82SClément Léger len /= sizeof(uint32_t); 3161fe98f82SClément Léger for (i = 0; i < len; i += DT_GPIO_CELLS) { 3171fe98f82SClément Léger gpio_pin = fdt32_to_cpu(prop[i]); 3181fe98f82SClément Léger config = fdt32_to_cpu(prop[i + 1]); 3191fe98f82SClément Léger 3201fe98f82SClément Léger secumod_cfg_input_pio(gpio_pin, config); 3211fe98f82SClément Léger } 3221fe98f82SClément Léger } 3231fe98f82SClément Léger 3241fe98f82SClément Léger #ifdef CFG_PM_ARM32 3251fe98f82SClément Léger static TEE_Result piobu_pm(enum pm_op op, uint32_t pm_hint __unused, 3261fe98f82SClément Léger const struct pm_callback_handle *hdl __unused) 3271fe98f82SClément Léger { 3281fe98f82SClément Léger switch (op) { 3291fe98f82SClément Léger case PM_OP_RESUME: 3301fe98f82SClément Léger io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 3311fe98f82SClément Léger SECUMOD_CR_NORMAL); 3321fe98f82SClément Léger break; 3331fe98f82SClément Léger case PM_OP_SUSPEND: 3341fe98f82SClément Léger /* Enter backup mode before suspending */ 3351fe98f82SClément Léger io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 3361fe98f82SClément Léger SECUMOD_CR_BACKUP); 3371fe98f82SClément Léger break; 3381fe98f82SClément Léger default: 3391fe98f82SClément Léger panic("Invalid PM operation"); 3401fe98f82SClément Léger } 3411fe98f82SClément Léger 3421fe98f82SClément Léger return TEE_SUCCESS; 3431fe98f82SClément Léger } 3441fe98f82SClément Léger 3451fe98f82SClément Léger static void piobu_register_pm(void) 3461fe98f82SClément Léger { 3471fe98f82SClément Léger register_pm_driver_cb(piobu_pm, NULL, "piobu"); 3481fe98f82SClément Léger } 3491fe98f82SClément Léger #else 3501fe98f82SClément Léger static void piobu_register_pm(void) {} 3511fe98f82SClément Léger #endif 3521fe98f82SClément Léger 3531fe98f82SClément Léger static TEE_Result atmel_secumod_probe(const void *fdt, int node, 3541fe98f82SClément Léger const void *compat_data __unused) 3551fe98f82SClément Léger { 3561fe98f82SClément Léger size_t size = 0; 3571fe98f82SClément Léger 3581fe98f82SClément Léger if (secumod_base) 3591fe98f82SClément Léger return TEE_ERROR_GENERIC; 3601fe98f82SClément Léger 361a5d5bbc8SVesa Jääskeläinen if (dt_map_dev(fdt, node, &secumod_base, &size, DT_MAP_AUTO) < 0) 3621fe98f82SClément Léger return TEE_ERROR_GENERIC; 3631fe98f82SClément Léger 3641fe98f82SClément Léger secumod_hw_init(fdt, node); 3651fe98f82SClément Léger secumod_interrupt_init(); 3661fe98f82SClément Léger 3671fe98f82SClément Léger secumod_chip.ops = &atmel_piobu_ops; 3681fe98f82SClément Léger 3691fe98f82SClément Léger piobu_register_pm(); 3701fe98f82SClément Léger 3711fe98f82SClément Léger return TEE_SUCCESS; 3721fe98f82SClément Léger } 3731fe98f82SClément Léger 3741fe98f82SClément Léger static const struct dt_device_match atmel_secumod_match_table[] = { 3751fe98f82SClément Léger { .compatible = "atmel,sama5d2-secumod" }, 3761fe98f82SClément Léger { } 3771fe98f82SClément Léger }; 3781fe98f82SClément Léger 3791fe98f82SClément Léger DEFINE_DT_DRIVER(atmel_secumod_dt_driver) = { 3801fe98f82SClément Léger .name = "atmel_secumod", 3811fe98f82SClément Léger .type = DT_DRIVER_NOTYPE, 3821fe98f82SClément Léger .match_table = atmel_secumod_match_table, 3831fe98f82SClément Léger .probe = atmel_secumod_probe, 3841fe98f82SClément Léger }; 385