1*1fe98f82SClément Léger // SPDX-License-Identifier: BSD-2-Clause 2*1fe98f82SClément Léger /* 3*1fe98f82SClément Léger * Copyright 2022 Microchip 4*1fe98f82SClément Léger * 5*1fe98f82SClément Léger * Driver for AT91 PIOBU 6*1fe98f82SClément Léger */ 7*1fe98f82SClément Léger 8*1fe98f82SClément Léger #include <assert.h> 9*1fe98f82SClément Léger #include <drivers/atmel_rtc.h> 10*1fe98f82SClément Léger #include <dt-bindings/gpio/atmel,piobu.h> 11*1fe98f82SClément Léger #include <gpio.h> 12*1fe98f82SClément Léger #include <io.h> 13*1fe98f82SClément Léger #include <kernel/boot.h> 14*1fe98f82SClément Léger #include <kernel/dt.h> 15*1fe98f82SClément Léger #include <kernel/pm.h> 16*1fe98f82SClément Léger #include <libfdt.h> 17*1fe98f82SClément Léger #include <mm/core_memprot.h> 18*1fe98f82SClément Léger 19*1fe98f82SClément Léger #define SECUMOD_MAX_PINS 8 20*1fe98f82SClément Léger #define SECUMOD_PIN_MASK (BIT(SECUMOD_MAX_PINS) - 1) 21*1fe98f82SClément Léger #define SECUMOD_PIN_SHIFT 16 22*1fe98f82SClément Léger #define SECUMOD_PIN_VAL(pin) BIT(SECUMOD_PIN_SHIFT + (pin)) 23*1fe98f82SClément Léger 24*1fe98f82SClément Léger #define DT_GPIO_CELLS 2 25*1fe98f82SClément Léger 26*1fe98f82SClément Léger #define SECUMOD_CR 0x0 27*1fe98f82SClément Léger #define SECUMOD_CR_KEY_SHIFT 16 28*1fe98f82SClément Léger #define SECUMOD_CR_KEY SHIFT_U32(0x89CA, SECUMOD_CR_KEY_SHIFT) 29*1fe98f82SClément Léger #define SECUMOD_CR_BACKUP BIT(0) 30*1fe98f82SClément Léger #define SECUMOD_CR_NORMAL BIT(1) 31*1fe98f82SClément Léger 32*1fe98f82SClément Léger #define SECUMOD_SR 0x8 33*1fe98f82SClément Léger #define SECUMOD_SR_JTAG BIT(3) 34*1fe98f82SClément Léger #define SECUMOD_SR_TST_PIN BIT(2) 35*1fe98f82SClément Léger 36*1fe98f82SClément Léger #define SECUMOD_SCR 0x10 37*1fe98f82SClément Léger 38*1fe98f82SClément Léger #define SECUMOD_PIOBU(x) (0x18 + (x) * 0x4) 39*1fe98f82SClément Léger #define SECUMOD_PIOBU_AFV_MASK GENMASK_32(3, 0) 40*1fe98f82SClément Léger #define SECUMOD_PIOBU_RFV_SHIFT 4 41*1fe98f82SClément Léger #define SECUMOD_PIOBU_OUTPUT BIT(8) 42*1fe98f82SClément Léger #define SECUMOD_PIOBU_SOD BIT(9) 43*1fe98f82SClément Léger #define SECUMOD_PIOBU_PDS BIT(10) 44*1fe98f82SClément Léger #define SECUMOD_PIOBU_PULLUP_SHIFT 12 45*1fe98f82SClément Léger #define SECUMOD_PIOBU_SWITCH_SHIFT 15 46*1fe98f82SClément Léger 47*1fe98f82SClément Léger #define SECUMOD_JTAGCR 0x68 48*1fe98f82SClément Léger #define SECUMOD_JTAGCR_FNTRST 0x1 49*1fe98f82SClément Léger 50*1fe98f82SClément Léger #define SECUMOD_BMPR 0x7C 51*1fe98f82SClément Léger #define SECUMOD_NMPR 0x80 52*1fe98f82SClément Léger #define SECUMOD_NIEPR 0x84 53*1fe98f82SClément Léger #define SECUMOD_NIDPR 0x88 54*1fe98f82SClément Léger #define SECUMOD_NIMPR 0x8C 55*1fe98f82SClément Léger #define SECUMOD_WKPR 0x90 56*1fe98f82SClément Léger 57*1fe98f82SClément Léger static vaddr_t secumod_base; 58*1fe98f82SClément Léger static uint32_t gpio_protected; 59*1fe98f82SClément Léger static struct gpio_chip secumod_chip; 60*1fe98f82SClément Léger 61*1fe98f82SClément Léger /* 62*1fe98f82SClément Léger * Get value from GPIO controller 63*1fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 64*1fe98f82SClément Léger * gpio_pin: pin from which value needs to be read 65*1fe98f82SClément Léger * Return target GPIO pin level. 66*1fe98f82SClément Léger */ 67*1fe98f82SClément Léger static enum gpio_level gpio_get_value(struct gpio_chip *chip __unused, 68*1fe98f82SClément Léger unsigned int gpio_pin) 69*1fe98f82SClément Léger { 70*1fe98f82SClément Léger vaddr_t piobu_addr = 0; 71*1fe98f82SClément Léger uint32_t piobu = 0; 72*1fe98f82SClément Léger 73*1fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 74*1fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 75*1fe98f82SClément Léger 76*1fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 77*1fe98f82SClément Léger piobu = io_read32(piobu_addr); 78*1fe98f82SClément Léger 79*1fe98f82SClément Léger if (piobu & SECUMOD_PIOBU_PDS) 80*1fe98f82SClément Léger return GPIO_LEVEL_HIGH; 81*1fe98f82SClément Léger else 82*1fe98f82SClément Léger return GPIO_LEVEL_LOW; 83*1fe98f82SClément Léger } 84*1fe98f82SClément Léger 85*1fe98f82SClément Léger /* 86*1fe98f82SClément Léger * Set value for GPIO controller 87*1fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 88*1fe98f82SClément Léger * gpio_pin: pin to which value needs to be written 89*1fe98f82SClément Léger * value: Level state for the target pin 90*1fe98f82SClément Léger */ 91*1fe98f82SClément Léger static void gpio_set_value(struct gpio_chip *chip __unused, 92*1fe98f82SClément Léger unsigned int gpio_pin, enum gpio_level value) 93*1fe98f82SClément Léger { 94*1fe98f82SClément Léger vaddr_t piobu_addr = 0; 95*1fe98f82SClément Léger 96*1fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 97*1fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 98*1fe98f82SClément Léger 99*1fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 100*1fe98f82SClément Léger 101*1fe98f82SClément Léger if (value == GPIO_LEVEL_HIGH) 102*1fe98f82SClément Léger io_setbits32(piobu_addr, SECUMOD_PIOBU_SOD); 103*1fe98f82SClément Léger else 104*1fe98f82SClément Léger io_clrbits32(piobu_addr, SECUMOD_PIOBU_SOD); 105*1fe98f82SClément Léger } 106*1fe98f82SClément Léger 107*1fe98f82SClément Léger /* 108*1fe98f82SClément Léger * Get direction from GPIO controller 109*1fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 110*1fe98f82SClément Léger * gpio_pin: pin from which direction needs to be read 111*1fe98f82SClément Léger */ 112*1fe98f82SClément Léger static enum gpio_dir gpio_get_direction(struct gpio_chip *chip __unused, 113*1fe98f82SClément Léger unsigned int gpio_pin) 114*1fe98f82SClément Léger { 115*1fe98f82SClément Léger vaddr_t piobu_addr = 0; 116*1fe98f82SClément Léger uint32_t piobu = 0; 117*1fe98f82SClément Léger 118*1fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 119*1fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 120*1fe98f82SClément Léger 121*1fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 122*1fe98f82SClément Léger piobu = io_read32(piobu_addr); 123*1fe98f82SClément Léger 124*1fe98f82SClément Léger if (piobu & SECUMOD_PIOBU_OUTPUT) 125*1fe98f82SClément Léger return GPIO_DIR_OUT; 126*1fe98f82SClément Léger else 127*1fe98f82SClément Léger return GPIO_DIR_IN; 128*1fe98f82SClément Léger } 129*1fe98f82SClément Léger 130*1fe98f82SClément Léger /* 131*1fe98f82SClément Léger * Set direction for GPIO controller 132*1fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 133*1fe98f82SClément Léger * gpio_pin: pin on which direction needs to be set 134*1fe98f82SClément Léger * direction: direction which needs to be set on pin 135*1fe98f82SClément Léger */ 136*1fe98f82SClément Léger static void gpio_set_direction(struct gpio_chip *chip __unused, 137*1fe98f82SClément Léger unsigned int gpio_pin, enum gpio_dir direction) 138*1fe98f82SClément Léger { 139*1fe98f82SClément Léger vaddr_t piobu_addr = 0; 140*1fe98f82SClément Léger 141*1fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 142*1fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 143*1fe98f82SClément Léger 144*1fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 145*1fe98f82SClément Léger 146*1fe98f82SClément Léger if (direction == GPIO_DIR_OUT) 147*1fe98f82SClément Léger io_setbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 148*1fe98f82SClément Léger else 149*1fe98f82SClément Léger io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 150*1fe98f82SClément Léger } 151*1fe98f82SClément Léger 152*1fe98f82SClément Léger /* 153*1fe98f82SClément Léger * Get interrupt from GPIO controller 154*1fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 155*1fe98f82SClément Léger * gpio_pin: pin from which interrupt value needs to be read 156*1fe98f82SClément Léger */ 157*1fe98f82SClément Léger static enum gpio_interrupt gpio_get_interrupt(struct gpio_chip *chip __unused, 158*1fe98f82SClément Léger unsigned int gpio_pin) 159*1fe98f82SClément Léger { 160*1fe98f82SClément Léger vaddr_t nimpr_addr = secumod_base + SECUMOD_NIMPR; 161*1fe98f82SClément Léger uint32_t data = 0; 162*1fe98f82SClément Léger 163*1fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 164*1fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 165*1fe98f82SClément Léger 166*1fe98f82SClément Léger data = io_read32(nimpr_addr); 167*1fe98f82SClément Léger 168*1fe98f82SClément Léger if (data & SECUMOD_PIN_VAL(gpio_pin)) 169*1fe98f82SClément Léger return GPIO_INTERRUPT_ENABLE; 170*1fe98f82SClément Léger else 171*1fe98f82SClément Léger return GPIO_INTERRUPT_DISABLE; 172*1fe98f82SClément Léger } 173*1fe98f82SClément Léger 174*1fe98f82SClément Léger /* 175*1fe98f82SClément Léger * Set interrupt event for GPIO controller 176*1fe98f82SClément Léger * chip: pointer to GPIO controller chip instance 177*1fe98f82SClément Léger * gpio_pin: pin on which interrupt value needs to be set 178*1fe98f82SClément Léger * interrupt: interrupt value which needs to be set on pin 179*1fe98f82SClément Léger */ 180*1fe98f82SClément Léger static void gpio_set_interrupt(struct gpio_chip *chip __unused, 181*1fe98f82SClément Léger unsigned int gpio_pin, 182*1fe98f82SClément Léger enum gpio_interrupt interrupt) 183*1fe98f82SClément Léger { 184*1fe98f82SClément Léger vaddr_t niepr_addr = secumod_base + SECUMOD_NIEPR; 185*1fe98f82SClément Léger 186*1fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS && 187*1fe98f82SClément Léger !(gpio_protected & BIT32(gpio_pin))); 188*1fe98f82SClément Léger 189*1fe98f82SClément Léger if (interrupt == GPIO_INTERRUPT_ENABLE) 190*1fe98f82SClément Léger io_setbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); 191*1fe98f82SClément Léger else 192*1fe98f82SClément Léger io_clrbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); 193*1fe98f82SClément Léger } 194*1fe98f82SClément Léger 195*1fe98f82SClément Léger static const struct gpio_ops atmel_piobu_ops = { 196*1fe98f82SClément Léger .get_direction = gpio_get_direction, 197*1fe98f82SClément Léger .set_direction = gpio_set_direction, 198*1fe98f82SClément Léger .get_value = gpio_get_value, 199*1fe98f82SClément Léger .set_value = gpio_set_value, 200*1fe98f82SClément Léger .get_interrupt = gpio_get_interrupt, 201*1fe98f82SClément Léger .set_interrupt = gpio_set_interrupt, 202*1fe98f82SClément Léger }; 203*1fe98f82SClément Léger 204*1fe98f82SClément Léger static enum itr_return secumod_it_handler(struct itr_handler *handler __unused) 205*1fe98f82SClément Léger { 206*1fe98f82SClément Léger int i = 0; 207*1fe98f82SClément Léger struct optee_rtc_time tm = { }; 208*1fe98f82SClément Léger TEE_Result res = TEE_ERROR_GENERIC; 209*1fe98f82SClément Léger uint32_t sr = io_read32(secumod_base + SECUMOD_SR); 210*1fe98f82SClément Léger 211*1fe98f82SClément Léger for (i = 0; i < SECUMOD_MAX_PINS; i++) { 212*1fe98f82SClément Léger if (sr & SECUMOD_PIN_VAL(i)) 213*1fe98f82SClément Léger EMSG("Detected tampering on pin %d", i); 214*1fe98f82SClément Léger } 215*1fe98f82SClément Léger 216*1fe98f82SClément Léger if (sr & SECUMOD_SR_JTAG) 217*1fe98f82SClément Léger EMSG("JTAG tampering attempt"); 218*1fe98f82SClément Léger 219*1fe98f82SClément Léger if (sr & SECUMOD_SR_TST_PIN) 220*1fe98f82SClément Léger EMSG("Test pin tampering attempt"); 221*1fe98f82SClément Léger 222*1fe98f82SClément Léger res = atmel_rtc_get_tamper_timestamp(&tm); 223*1fe98f82SClément Léger if (!res) { 224*1fe98f82SClément Léger EMSG("Date of tampering: %02"PRIu32"/%02"PRIu32"/%02"PRIu32"", 225*1fe98f82SClément Léger tm.tm_mday, tm.tm_mon, tm.tm_year); 226*1fe98f82SClément Léger EMSG("Time of tampering: %02"PRIu32":%02"PRIu32":%02"PRIu32"", 227*1fe98f82SClément Léger tm.tm_hour, tm.tm_min, tm.tm_sec); 228*1fe98f82SClément Léger } 229*1fe98f82SClément Léger 230*1fe98f82SClément Léger io_write32(secumod_base + SECUMOD_SCR, 231*1fe98f82SClément Léger SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); 232*1fe98f82SClément Léger 233*1fe98f82SClément Léger panic("Tampering detected, system halted"); 234*1fe98f82SClément Léger 235*1fe98f82SClément Léger return ITRR_HANDLED; 236*1fe98f82SClément Léger } 237*1fe98f82SClément Léger 238*1fe98f82SClément Léger static struct itr_handler secumod_itr_handler = { 239*1fe98f82SClément Léger .it = AT91C_ID_SECUMOD, 240*1fe98f82SClément Léger .handler = secumod_it_handler, 241*1fe98f82SClément Léger }; 242*1fe98f82SClément Léger 243*1fe98f82SClément Léger static void secumod_interrupt_init(void) 244*1fe98f82SClément Léger { 245*1fe98f82SClément Léger itr_add_type_prio(&secumod_itr_handler, IRQ_TYPE_LEVEL_HIGH, 7); 246*1fe98f82SClément Léger itr_enable(secumod_itr_handler.it); 247*1fe98f82SClément Léger } 248*1fe98f82SClément Léger 249*1fe98f82SClément Léger static void secumod_cfg_input_pio(uint8_t gpio_pin, uint32_t config) 250*1fe98f82SClément Léger { 251*1fe98f82SClément Léger vaddr_t piobu_addr = 0; 252*1fe98f82SClément Léger uint8_t afv = 0; 253*1fe98f82SClément Léger uint8_t rfv = 0; 254*1fe98f82SClément Léger uint8_t pull_mode = PIOBU_PIN_PULL_NONE; 255*1fe98f82SClément Léger uint8_t def_level = PIOBU_PIN_DEF_LEVEL_LOW; 256*1fe98f82SClément Léger 257*1fe98f82SClément Léger assert(gpio_pin < SECUMOD_MAX_PINS); 258*1fe98f82SClément Léger 259*1fe98f82SClément Léger piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 260*1fe98f82SClément Léger 261*1fe98f82SClément Léger /* Set GPIO as input */ 262*1fe98f82SClément Léger io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 263*1fe98f82SClément Léger 264*1fe98f82SClément Léger afv = PIOBU_PIN_AFV(config); 265*1fe98f82SClément Léger rfv = PIOBU_PIN_RFV(config); 266*1fe98f82SClément Léger pull_mode = PIOBU_PIN_PULL_MODE(config); 267*1fe98f82SClément Léger def_level = PIOBU_PIN_DEF_LEVEL(config); 268*1fe98f82SClément Léger 269*1fe98f82SClément Léger io_write32(piobu_addr, afv | rfv << SECUMOD_PIOBU_RFV_SHIFT | 270*1fe98f82SClément Léger pull_mode << SECUMOD_PIOBU_PULLUP_SHIFT | 271*1fe98f82SClément Léger def_level << SECUMOD_PIOBU_SWITCH_SHIFT); 272*1fe98f82SClément Léger 273*1fe98f82SClément Léger /* Enable Tampering Interrupt */ 274*1fe98f82SClément Léger gpio_set_interrupt(&secumod_chip, gpio_pin, GPIO_INTERRUPT_ENABLE); 275*1fe98f82SClément Léger 276*1fe98f82SClément Léger /* Enable Intrusion Detection */ 277*1fe98f82SClément Léger io_setbits32(secumod_base + SECUMOD_NMPR, SECUMOD_PIN_VAL(gpio_pin)); 278*1fe98f82SClément Léger 279*1fe98f82SClément Léger /* Enable Wakeup */ 280*1fe98f82SClément Léger if (PIOBU_PIN_WAKEUP(config)) 281*1fe98f82SClément Léger io_setbits32(secumod_base + SECUMOD_WKPR, 282*1fe98f82SClément Léger SECUMOD_PIN_VAL(gpio_pin)); 283*1fe98f82SClément Léger 284*1fe98f82SClément Léger gpio_protected |= BIT32(gpio_pin); 285*1fe98f82SClément Léger } 286*1fe98f82SClément Léger 287*1fe98f82SClément Léger static void secumod_hw_init(const void *fdt, int node) 288*1fe98f82SClément Léger { 289*1fe98f82SClément Léger int i = 0; 290*1fe98f82SClément Léger int len = 0; 291*1fe98f82SClément Léger uint8_t gpio_pin = 0; 292*1fe98f82SClément Léger uint32_t config = 0; 293*1fe98f82SClément Léger const uint32_t *prop = NULL; 294*1fe98f82SClément Léger 295*1fe98f82SClément Léger /* Disable JTAG Reset and Debug */ 296*1fe98f82SClément Léger io_write32(secumod_base + SECUMOD_JTAGCR, SECUMOD_JTAGCR_FNTRST); 297*1fe98f82SClément Léger 298*1fe98f82SClément Léger /* Switch IOs to normal mode */ 299*1fe98f82SClément Léger io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 300*1fe98f82SClément Léger SECUMOD_CR_NORMAL); 301*1fe98f82SClément Léger 302*1fe98f82SClément Léger /* Clear all detection intrusion in normal mode */ 303*1fe98f82SClément Léger io_write32(secumod_base + SECUMOD_NMPR, 0); 304*1fe98f82SClément Léger 305*1fe98f82SClément Léger /* Clear Alarms */ 306*1fe98f82SClément Léger io_write32(secumod_base + SECUMOD_SCR, 307*1fe98f82SClément Léger SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); 308*1fe98f82SClément Léger 309*1fe98f82SClément Léger /* Configure each IOs */ 310*1fe98f82SClément Léger prop = fdt_getprop(fdt, node, "gpios", &len); 311*1fe98f82SClément Léger if (!prop) 312*1fe98f82SClément Léger return; 313*1fe98f82SClément Léger 314*1fe98f82SClément Léger len /= sizeof(uint32_t); 315*1fe98f82SClément Léger for (i = 0; i < len; i += DT_GPIO_CELLS) { 316*1fe98f82SClément Léger gpio_pin = fdt32_to_cpu(prop[i]); 317*1fe98f82SClément Léger config = fdt32_to_cpu(prop[i + 1]); 318*1fe98f82SClément Léger 319*1fe98f82SClément Léger secumod_cfg_input_pio(gpio_pin, config); 320*1fe98f82SClément Léger } 321*1fe98f82SClément Léger } 322*1fe98f82SClément Léger 323*1fe98f82SClément Léger #ifdef CFG_PM_ARM32 324*1fe98f82SClément Léger static TEE_Result piobu_pm(enum pm_op op, uint32_t pm_hint __unused, 325*1fe98f82SClément Léger const struct pm_callback_handle *hdl __unused) 326*1fe98f82SClément Léger { 327*1fe98f82SClément Léger switch (op) { 328*1fe98f82SClément Léger case PM_OP_RESUME: 329*1fe98f82SClément Léger io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 330*1fe98f82SClément Léger SECUMOD_CR_NORMAL); 331*1fe98f82SClément Léger break; 332*1fe98f82SClément Léger case PM_OP_SUSPEND: 333*1fe98f82SClément Léger /* Enter backup mode before suspending */ 334*1fe98f82SClément Léger io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 335*1fe98f82SClément Léger SECUMOD_CR_BACKUP); 336*1fe98f82SClément Léger break; 337*1fe98f82SClément Léger default: 338*1fe98f82SClément Léger panic("Invalid PM operation"); 339*1fe98f82SClément Léger } 340*1fe98f82SClément Léger 341*1fe98f82SClément Léger return TEE_SUCCESS; 342*1fe98f82SClément Léger } 343*1fe98f82SClément Léger 344*1fe98f82SClément Léger static void piobu_register_pm(void) 345*1fe98f82SClément Léger { 346*1fe98f82SClément Léger register_pm_driver_cb(piobu_pm, NULL, "piobu"); 347*1fe98f82SClément Léger } 348*1fe98f82SClément Léger #else 349*1fe98f82SClément Léger static void piobu_register_pm(void) {} 350*1fe98f82SClément Léger #endif 351*1fe98f82SClément Léger 352*1fe98f82SClément Léger static TEE_Result atmel_secumod_probe(const void *fdt, int node, 353*1fe98f82SClément Léger const void *compat_data __unused) 354*1fe98f82SClément Léger { 355*1fe98f82SClément Léger size_t size = 0; 356*1fe98f82SClément Léger 357*1fe98f82SClément Léger if (secumod_base) 358*1fe98f82SClément Léger return TEE_ERROR_GENERIC; 359*1fe98f82SClément Léger 360*1fe98f82SClément Léger if (dt_map_dev(fdt, node, &secumod_base, &size) < 0) 361*1fe98f82SClément Léger return TEE_ERROR_GENERIC; 362*1fe98f82SClément Léger 363*1fe98f82SClément Léger secumod_hw_init(fdt, node); 364*1fe98f82SClément Léger secumod_interrupt_init(); 365*1fe98f82SClément Léger 366*1fe98f82SClément Léger secumod_chip.ops = &atmel_piobu_ops; 367*1fe98f82SClément Léger 368*1fe98f82SClément Léger piobu_register_pm(); 369*1fe98f82SClément Léger 370*1fe98f82SClément Léger return TEE_SUCCESS; 371*1fe98f82SClément Léger } 372*1fe98f82SClément Léger 373*1fe98f82SClément Léger static const struct dt_device_match atmel_secumod_match_table[] = { 374*1fe98f82SClément Léger { .compatible = "atmel,sama5d2-secumod" }, 375*1fe98f82SClément Léger { } 376*1fe98f82SClément Léger }; 377*1fe98f82SClément Léger 378*1fe98f82SClément Léger DEFINE_DT_DRIVER(atmel_secumod_dt_driver) = { 379*1fe98f82SClément Léger .name = "atmel_secumod", 380*1fe98f82SClément Léger .type = DT_DRIVER_NOTYPE, 381*1fe98f82SClément Léger .match_table = atmel_secumod_match_table, 382*1fe98f82SClément Léger .probe = atmel_secumod_probe, 383*1fe98f82SClément Léger }; 384