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> 106dcd18c8SClément Léger #include <drivers/gpio.h> 111fe98f82SClément Léger #include <dt-bindings/gpio/atmel,piobu.h> 121fe98f82SClément Léger #include <io.h> 131fe98f82SClément Léger #include <kernel/boot.h> 141fe98f82SClément Léger #include <kernel/dt.h> 159e3c57c8SEtienne 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 */ 688bc270b1SClément Léger static enum gpio_level secumod_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 */ 928bc270b1SClément Léger static void secumod_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 */ 1138bc270b1SClément Léger static enum gpio_dir secumod_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 */ 1378bc270b1SClément Léger static void secumod_gpio_set_direction(struct gpio_chip *chip __unused, 1388bc270b1SClément Léger unsigned int gpio_pin, 1398bc270b1SClément Léger enum gpio_dir direction) 1401fe98f82SClément Léger { 1411fe98f82SClément Léger vaddr_t piobu_addr = 0; 1421fe98f82SClément Léger 1431fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 1441fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 1451fe98f82SClément Léger 1461fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 1471fe98f82SClément Léger 1481fe98f82SClément Léger if (direction == GPIO_DIR_OUT) 1491fe98f82SClément Léger io_setbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 1501fe98f82SClément Léger else 1511fe98f82SClément Léger io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 1521fe98f82SClément Léger } 1531fe98f82SClément Léger 1541fe98f82SClément Léger /* 1551fe98f82SClément Léger * Get interrupt from GPIO controller 1561fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 1571fe98f82SClément Léger * gpio_pin: pin from which interrupt value needs to be read 1581fe98f82SClément Léger */ 1598bc270b1SClément Léger static enum gpio_interrupt 1608bc270b1SClément Léger secumod_gpio_get_interrupt(struct gpio_chip *chip __unused, 1611fe98f82SClément Léger unsigned int gpio_pin) 1621fe98f82SClément Léger { 1631fe98f82SClément Léger vaddr_t nimpr_addr = secumod_base + SECUMOD_NIMPR; 1641fe98f82SClément Léger uint32_t data = 0; 1651fe98f82SClément Léger 1661fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 1671fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 1681fe98f82SClément Léger 1691fe98f82SClément Léger data = io_read32(nimpr_addr); 1701fe98f82SClément Léger 1711fe98f82SClément Léger if (data & SECUMOD_PIN_VAL(gpio_pin)) 1721fe98f82SClément Léger return GPIO_INTERRUPT_ENABLE; 1731fe98f82SClément Léger else 1741fe98f82SClément Léger return GPIO_INTERRUPT_DISABLE; 1751fe98f82SClément Léger } 1761fe98f82SClément Léger 1771fe98f82SClément Léger /* 1781fe98f82SClément Léger * Set interrupt event for GPIO controller 1791fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 1801fe98f82SClément Léger * gpio_pin: pin on which interrupt value needs to be set 1811fe98f82SClément Léger * interrupt: interrupt value which needs to be set on pin 1821fe98f82SClément Léger */ 1838bc270b1SClément Léger static void secumod_gpio_set_interrupt(struct gpio_chip *chip __unused, 1841fe98f82SClément Léger unsigned int gpio_pin, 1851fe98f82SClément Léger enum gpio_interrupt interrupt) 1861fe98f82SClément Léger { 1871fe98f82SClément Léger vaddr_t niepr_addr = secumod_base + SECUMOD_NIEPR; 1881fe98f82SClément Léger 1891fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 1901fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 1911fe98f82SClément Léger 1921fe98f82SClément Léger if (interrupt == GPIO_INTERRUPT_ENABLE) 1931fe98f82SClément Léger io_setbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); 1941fe98f82SClément Léger else 1951fe98f82SClément Léger io_clrbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); 1961fe98f82SClément Léger } 1971fe98f82SClément Léger 1981fe98f82SClément Léger static const struct gpio_ops atmel_piobu_ops = { 1998bc270b1SClément Léger .get_direction = secumod_gpio_get_direction, 2008bc270b1SClément Léger .set_direction = secumod_gpio_set_direction, 2018bc270b1SClément Léger .get_value = secumod_gpio_get_value, 2028bc270b1SClément Léger .set_value = secumod_gpio_set_value, 2038bc270b1SClément Léger .get_interrupt = secumod_gpio_get_interrupt, 2048bc270b1SClément Léger .set_interrupt = secumod_gpio_set_interrupt, 2051fe98f82SClément Léger }; 2061fe98f82SClément Léger 207*b357d34fSEtienne Carriere static TEE_Result secumod_dt_get(struct dt_pargs *pargs, void *data, 208*b357d34fSEtienne Carriere struct gpio **out_gpio) 209b786cc03SClément Léger { 210*b357d34fSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 211b786cc03SClément Léger struct gpio *gpio = NULL; 212b786cc03SClément Léger struct gpio_chip *chip = data; 213b786cc03SClément Léger 214*b357d34fSEtienne Carriere res = gpio_dt_alloc_pin(pargs, &gpio); 215*b357d34fSEtienne Carriere if (res) 216*b357d34fSEtienne Carriere return res; 217b786cc03SClément Léger 218b786cc03SClément Léger if (gpio_protected & BIT32(gpio->pin)) { 219b786cc03SClément Léger free(gpio); 220*b357d34fSEtienne Carriere return TEE_ERROR_GENERIC; 221b786cc03SClément Léger } 222b786cc03SClément Léger 223b786cc03SClément Léger gpio->chip = chip; 224*b357d34fSEtienne Carriere *out_gpio = gpio; 225b786cc03SClément Léger 226*b357d34fSEtienne Carriere return TEE_SUCCESS; 227b786cc03SClément Léger } 228b786cc03SClément Léger 2291fe98f82SClément Léger static enum itr_return secumod_it_handler(struct itr_handler *handler __unused) 2301fe98f82SClément Léger { 2311fe98f82SClément Léger int i = 0; 2321fe98f82SClément Léger struct optee_rtc_time tm = { }; 2331fe98f82SClément Léger TEE_Result res = TEE_ERROR_GENERIC; 2341fe98f82SClément Léger uint32_t sr = io_read32(secumod_base + SECUMOD_SR); 2351fe98f82SClément Léger 2361fe98f82SClément Léger for (i = 0; i < SECUMOD_MAX_PINS; i++) { 2371fe98f82SClément Léger if (sr & SECUMOD_PIN_VAL(i)) 2381fe98f82SClément Léger EMSG("Detected tampering on pin %d", i); 2391fe98f82SClément Léger } 2401fe98f82SClément Léger 2411fe98f82SClément Léger if (sr & SECUMOD_SR_JTAG) 2421fe98f82SClément Léger EMSG("JTAG tampering attempt"); 2431fe98f82SClément Léger 2441fe98f82SClément Léger if (sr & SECUMOD_SR_TST_PIN) 2451fe98f82SClément Léger EMSG("Test pin tampering attempt"); 2461fe98f82SClément Léger 2471fe98f82SClément Léger res = atmel_rtc_get_tamper_timestamp(&tm); 2481fe98f82SClément Léger if (!res) { 2491fe98f82SClément Léger EMSG("Date of tampering: %02"PRIu32"/%02"PRIu32"/%02"PRIu32"", 2501fe98f82SClément Léger tm.tm_mday, tm.tm_mon, tm.tm_year); 2511fe98f82SClément Léger EMSG("Time of tampering: %02"PRIu32":%02"PRIu32":%02"PRIu32"", 2521fe98f82SClément Léger tm.tm_hour, tm.tm_min, tm.tm_sec); 2531fe98f82SClément Léger } 2541fe98f82SClément Léger 2551fe98f82SClément Léger io_write32(secumod_base + SECUMOD_SCR, 2561fe98f82SClément Léger SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); 2571fe98f82SClément Léger 2581fe98f82SClément Léger panic("Tampering detected, system halted"); 2591fe98f82SClément Léger 2601fe98f82SClément Léger return ITRR_HANDLED; 2611fe98f82SClément Léger } 2621fe98f82SClément Léger 2631fe98f82SClément Léger static struct itr_handler secumod_itr_handler = { 2641fe98f82SClément Léger .it = AT91C_ID_SECUMOD, 2651fe98f82SClément Léger .handler = secumod_it_handler, 2661fe98f82SClément Léger }; 2671fe98f82SClément Léger 2681fe98f82SClément Léger static void secumod_interrupt_init(void) 2691fe98f82SClément Léger { 2701fe98f82SClément Léger itr_add_type_prio(&secumod_itr_handler, IRQ_TYPE_LEVEL_HIGH, 7); 2711fe98f82SClément Léger itr_enable(secumod_itr_handler.it); 2721fe98f82SClément Léger } 2731fe98f82SClément Léger 2741fe98f82SClément Léger static void secumod_cfg_input_pio(uint8_t gpio_pin, uint32_t config) 2751fe98f82SClément Léger { 2761fe98f82SClément Léger vaddr_t piobu_addr = 0; 2771fe98f82SClément Léger uint8_t afv = 0; 2781fe98f82SClément Léger uint8_t rfv = 0; 2791fe98f82SClément Léger uint8_t pull_mode = PIOBU_PIN_PULL_NONE; 2801fe98f82SClément Léger uint8_t def_level = PIOBU_PIN_DEF_LEVEL_LOW; 2811fe98f82SClément Léger 2821fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS); 2831fe98f82SClément Léger 2841fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 2851fe98f82SClément Léger 2861fe98f82SClément Léger /* Set GPIO as input */ 2871fe98f82SClément Léger io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 2881fe98f82SClément Léger 2891fe98f82SClément Léger afv = PIOBU_PIN_AFV(config); 2901fe98f82SClément Léger rfv = PIOBU_PIN_RFV(config); 2911fe98f82SClément Léger pull_mode = PIOBU_PIN_PULL_MODE(config); 2921fe98f82SClément Léger def_level = PIOBU_PIN_DEF_LEVEL(config); 2931fe98f82SClément Léger 2941fe98f82SClément Léger io_write32(piobu_addr, afv | rfv << SECUMOD_PIOBU_RFV_SHIFT | 2951fe98f82SClément Léger pull_mode << SECUMOD_PIOBU_PULLUP_SHIFT | 2961fe98f82SClément Léger def_level << SECUMOD_PIOBU_SWITCH_SHIFT); 2971fe98f82SClément Léger 2981fe98f82SClément Léger /* Enable Tampering Interrupt */ 2998bc270b1SClément Léger secumod_gpio_set_interrupt(&secumod_chip, gpio_pin, 3008bc270b1SClément Léger GPIO_INTERRUPT_ENABLE); 3011fe98f82SClément Léger 3021fe98f82SClément Léger /* Enable Intrusion Detection */ 3031fe98f82SClément Léger io_setbits32(secumod_base + SECUMOD_NMPR, SECUMOD_PIN_VAL(gpio_pin)); 3041fe98f82SClément Léger 3051fe98f82SClément Léger /* Enable Wakeup */ 3061fe98f82SClément Léger if (PIOBU_PIN_WAKEUP(config)) 3071fe98f82SClément Léger io_setbits32(secumod_base + SECUMOD_WKPR, 3081fe98f82SClément Léger SECUMOD_PIN_VAL(gpio_pin)); 3091fe98f82SClément Léger 3101fe98f82SClément Léger gpio_protected |= BIT32(gpio_pin); 3111fe98f82SClément Léger } 3121fe98f82SClément Léger 3131fe98f82SClément Léger static void secumod_hw_init(const void *fdt, int node) 3141fe98f82SClément Léger { 3151fe98f82SClément Léger int i = 0; 3161fe98f82SClément Léger int len = 0; 3171fe98f82SClément Léger uint8_t gpio_pin = 0; 3181fe98f82SClément Léger uint32_t config = 0; 3191fe98f82SClément Léger const uint32_t *prop = NULL; 3201fe98f82SClément Léger 3211fe98f82SClément Léger /* Disable JTAG Reset and Debug */ 3221fe98f82SClément Léger io_write32(secumod_base + SECUMOD_JTAGCR, SECUMOD_JTAGCR_FNTRST); 3231fe98f82SClément Léger 3241fe98f82SClément Léger /* Switch IOs to normal mode */ 3251fe98f82SClément Léger io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 3261fe98f82SClément Léger SECUMOD_CR_NORMAL); 3271fe98f82SClément Léger 3281fe98f82SClément Léger /* Clear all detection intrusion in normal mode */ 3291fe98f82SClément Léger io_write32(secumod_base + SECUMOD_NMPR, 0); 3301fe98f82SClément Léger 3311fe98f82SClément Léger /* Clear Alarms */ 3321fe98f82SClément Léger io_write32(secumod_base + SECUMOD_SCR, 3331fe98f82SClément Léger SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); 3341fe98f82SClément Léger 3351fe98f82SClément Léger /* Configure each IOs */ 3361fe98f82SClément Léger prop = fdt_getprop(fdt, node, "gpios", &len); 3371fe98f82SClément Léger if (!prop) 3381fe98f82SClément Léger return; 3391fe98f82SClément Léger 3401fe98f82SClément Léger len /= sizeof(uint32_t); 3411fe98f82SClément Léger for (i = 0; i < len; i += DT_GPIO_CELLS) { 3421fe98f82SClément Léger gpio_pin = fdt32_to_cpu(prop[i]); 3431fe98f82SClément Léger config = fdt32_to_cpu(prop[i + 1]); 3441fe98f82SClément Léger 3451fe98f82SClément Léger secumod_cfg_input_pio(gpio_pin, config); 3461fe98f82SClément Léger } 3471fe98f82SClément Léger } 3481fe98f82SClément Léger 3491fe98f82SClément Léger #ifdef CFG_PM_ARM32 3501fe98f82SClément Léger static TEE_Result piobu_pm(enum pm_op op, uint32_t pm_hint __unused, 3511fe98f82SClément Léger const struct pm_callback_handle *hdl __unused) 3521fe98f82SClément Léger { 3531fe98f82SClément Léger switch (op) { 3541fe98f82SClément Léger case PM_OP_RESUME: 3551fe98f82SClément Léger io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 3561fe98f82SClément Léger SECUMOD_CR_NORMAL); 3571fe98f82SClément Léger break; 3581fe98f82SClément Léger case PM_OP_SUSPEND: 3591fe98f82SClément Léger /* Enter backup mode before suspending */ 3601fe98f82SClément Léger io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 3611fe98f82SClément Léger SECUMOD_CR_BACKUP); 3621fe98f82SClément Léger break; 3631fe98f82SClément Léger default: 3641fe98f82SClément Léger panic("Invalid PM operation"); 3651fe98f82SClément Léger } 3661fe98f82SClément Léger 3671fe98f82SClément Léger return TEE_SUCCESS; 3681fe98f82SClément Léger } 3691fe98f82SClément Léger 3701fe98f82SClément Léger static void piobu_register_pm(void) 3711fe98f82SClément Léger { 3721fe98f82SClément Léger register_pm_driver_cb(piobu_pm, NULL, "piobu"); 3731fe98f82SClément Léger } 3741fe98f82SClément Léger #else 3751fe98f82SClément Léger static void piobu_register_pm(void) {} 3761fe98f82SClément Léger #endif 3771fe98f82SClément Léger 3781fe98f82SClément Léger static TEE_Result atmel_secumod_probe(const void *fdt, int node, 3791fe98f82SClément Léger const void *compat_data __unused) 3801fe98f82SClément Léger { 3811fe98f82SClément Léger size_t size = 0; 3821fe98f82SClément Léger 3831fe98f82SClément Léger if (secumod_base) 3841fe98f82SClément Léger return TEE_ERROR_GENERIC; 3851fe98f82SClément Léger 386a5d5bbc8SVesa Jääskeläinen if (dt_map_dev(fdt, node, &secumod_base, &size, DT_MAP_AUTO) < 0) 3871fe98f82SClément Léger return TEE_ERROR_GENERIC; 3881fe98f82SClément Léger 3891fe98f82SClément Léger secumod_hw_init(fdt, node); 3901fe98f82SClément Léger secumod_interrupt_init(); 3911fe98f82SClément Léger 3921fe98f82SClément Léger secumod_chip.ops = &atmel_piobu_ops; 3931fe98f82SClément Léger 3941fe98f82SClément Léger piobu_register_pm(); 3951fe98f82SClément Léger 396b786cc03SClément Léger assert(gpio_ops_is_valid(&atmel_piobu_ops)); 397b786cc03SClément Léger 398b786cc03SClément Léger return gpio_register_provider(fdt, node, secumod_dt_get, &secumod_chip); 3991fe98f82SClément Léger } 4001fe98f82SClément Léger 4011fe98f82SClément Léger static const struct dt_device_match atmel_secumod_match_table[] = { 4021fe98f82SClément Léger { .compatible = "atmel,sama5d2-secumod" }, 4031fe98f82SClément Léger { } 4041fe98f82SClément Léger }; 4051fe98f82SClément Léger 4061fe98f82SClément Léger DEFINE_DT_DRIVER(atmel_secumod_dt_driver) = { 4071fe98f82SClément Léger .name = "atmel_secumod", 4081fe98f82SClément Léger .type = DT_DRIVER_NOTYPE, 4091fe98f82SClément Léger .match_table = atmel_secumod_match_table, 4101fe98f82SClément Léger .probe = atmel_secumod_probe, 4111fe98f82SClément Léger }; 412