1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2022 Microchip 4 * 5 * Driver for AT91 PIOBU 6 */ 7 8 #include <assert.h> 9 #include <drivers/atmel_rtc.h> 10 #include <drivers/gpio.h> 11 #include <dt-bindings/gpio/atmel,piobu.h> 12 #include <io.h> 13 #include <kernel/boot.h> 14 #include <kernel/dt.h> 15 #include <kernel/dt_driver.h> 16 #include <kernel/interrupt.h> 17 #include <kernel/pm.h> 18 #include <libfdt.h> 19 #include <mm/core_memprot.h> 20 21 #define SECUMOD_MAX_PINS (piobu_device->compat->max_pins) 22 #define SECUMOD_PIN_MASK (BIT(SECUMOD_MAX_PINS) - 1) 23 #define SECUMOD_PIN_SHIFT 16 24 #define SECUMOD_PIN_VAL(pin) BIT(SECUMOD_PIN_SHIFT + (pin)) 25 26 #define DT_GPIO_CELLS 2 27 28 #define SECUMOD_CR 0x0 29 #define SECUMOD_CR_KEY_SHIFT 16 30 #define SECUMOD_CR_KEY SHIFT_U32(0x89CA, SECUMOD_CR_KEY_SHIFT) 31 #define SECUMOD_CR_BACKUP BIT(0) 32 #define SECUMOD_CR_NORMAL BIT(1) 33 34 #define SECUMOD_SR 0x8 35 #define SECUMOD_SR_JTAG BIT(3) 36 #define SECUMOD_SR_TST_PIN BIT(2) 37 38 #define SECUMOD_SCR 0x10 39 40 #define SECUMOD_PIOBU(x) (0x18 + (x) * 0x4) 41 #define SECUMOD_PIOBU_AFV_MASK GENMASK_32(3, 0) 42 #define SECUMOD_PIOBU_RFV_SHIFT 4 43 #define SECUMOD_PIOBU_OUTPUT BIT(8) 44 #define SECUMOD_PIOBU_SOD BIT(9) 45 #define SECUMOD_PIOBU_PDS BIT(10) 46 #define SECUMOD_PIOBU_PULLUP_SHIFT 12 47 #define SECUMOD_PIOBU_SWITCH_SHIFT 15 48 49 #define SECUMOD_JTAGCR_FNTRST 0x1 50 51 /* 52 * PIOBU instance data 53 * @compat - Reference to compat data passed at driver initialization 54 */ 55 struct piobu_instance { 56 struct piobu_compat *compat; 57 }; 58 59 /* 60 * @max_pins the number of the tamper I/Os 61 * @of_jtagcr offset of SECUMOD JTAG Protection Control Register 62 * @of_bmpr offset of SECUMOD Backup Mode Protection Register 63 * @of_nmpr offset of SECUMOD Normal Mode Protection Register 64 * @of_niepr offset of SECUMOD Normal Interrupt Enable Protection Register 65 * @of_nidpr offset of SECUMOD Normal Interrupt Disable Protection Register 66 * @of_nimpr offset of SECUMOD Normal Interrupt Mask Protection Register 67 * @of_wkpr offset of SECUMOD Wake-up Register 68 */ 69 struct piobu_compat { 70 uint8_t max_pins; 71 uint8_t of_jtagcr; 72 uint8_t of_bmpr; 73 uint8_t of_nmpr; 74 uint8_t of_niepr; 75 uint8_t of_nidpr; 76 uint8_t of_nimpr; 77 uint8_t of_wkpr; 78 }; 79 80 /* Expects at most a single instance */ 81 static struct piobu_instance *piobu_device; 82 83 static vaddr_t secumod_base; 84 static uint32_t gpio_protected; 85 static struct gpio_chip secumod_chip; 86 87 /* 88 * Get value from GPIO controller 89 * chip: pointer to GPIO controller chip instance 90 * gpio_pin: pin from which value needs to be read 91 * Return target GPIO pin level. 92 */ 93 static enum gpio_level secumod_gpio_get_value(struct gpio_chip *chip __unused, 94 unsigned int gpio_pin) 95 { 96 vaddr_t piobu_addr = 0; 97 uint32_t piobu = 0; 98 99 assert(gpio_pin < SECUMOD_MAX_PINS && 100 !(gpio_protected & BIT32(gpio_pin))); 101 102 piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 103 piobu = io_read32(piobu_addr); 104 105 if (piobu & SECUMOD_PIOBU_PDS) 106 return GPIO_LEVEL_HIGH; 107 else 108 return GPIO_LEVEL_LOW; 109 } 110 111 /* 112 * Set value for GPIO controller 113 * chip: pointer to GPIO controller chip instance 114 * gpio_pin: pin to which value needs to be written 115 * value: Level state for the target pin 116 */ 117 static void secumod_gpio_set_value(struct gpio_chip *chip __unused, 118 unsigned int gpio_pin, enum gpio_level value) 119 { 120 vaddr_t piobu_addr = 0; 121 122 assert(gpio_pin < SECUMOD_MAX_PINS && 123 !(gpio_protected & BIT32(gpio_pin))); 124 125 piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 126 127 if (value == GPIO_LEVEL_HIGH) 128 io_setbits32(piobu_addr, SECUMOD_PIOBU_SOD); 129 else 130 io_clrbits32(piobu_addr, SECUMOD_PIOBU_SOD); 131 } 132 133 /* 134 * Get direction from GPIO controller 135 * chip: pointer to GPIO controller chip instance 136 * gpio_pin: pin from which direction needs to be read 137 */ 138 static enum gpio_dir secumod_gpio_get_direction(struct gpio_chip *chip __unused, 139 unsigned int gpio_pin) 140 { 141 vaddr_t piobu_addr = 0; 142 uint32_t piobu = 0; 143 144 assert(gpio_pin < SECUMOD_MAX_PINS && 145 !(gpio_protected & BIT32(gpio_pin))); 146 147 piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 148 piobu = io_read32(piobu_addr); 149 150 if (piobu & SECUMOD_PIOBU_OUTPUT) 151 return GPIO_DIR_OUT; 152 else 153 return GPIO_DIR_IN; 154 } 155 156 /* 157 * Set direction for GPIO controller 158 * chip: pointer to GPIO controller chip instance 159 * gpio_pin: pin on which direction needs to be set 160 * direction: direction which needs to be set on pin 161 */ 162 static void secumod_gpio_set_direction(struct gpio_chip *chip __unused, 163 unsigned int gpio_pin, 164 enum gpio_dir direction) 165 { 166 vaddr_t piobu_addr = 0; 167 168 assert(gpio_pin < SECUMOD_MAX_PINS && 169 !(gpio_protected & BIT32(gpio_pin))); 170 171 piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 172 173 if (direction == GPIO_DIR_OUT) 174 io_setbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 175 else 176 io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 177 } 178 179 /* 180 * Get interrupt from GPIO controller 181 * chip: pointer to GPIO controller chip instance 182 * gpio_pin: pin from which interrupt value needs to be read 183 */ 184 static enum gpio_interrupt 185 secumod_gpio_get_interrupt(struct gpio_chip *chip __unused, 186 unsigned int gpio_pin) 187 { 188 vaddr_t nimpr_addr = secumod_base + piobu_device->compat->of_nimpr; 189 uint32_t data = 0; 190 191 assert(gpio_pin < SECUMOD_MAX_PINS && 192 !(gpio_protected & BIT32(gpio_pin))); 193 194 data = io_read32(nimpr_addr); 195 196 if (data & SECUMOD_PIN_VAL(gpio_pin)) 197 return GPIO_INTERRUPT_ENABLE; 198 else 199 return GPIO_INTERRUPT_DISABLE; 200 } 201 202 /* 203 * Set interrupt event for GPIO controller 204 * chip: pointer to GPIO controller chip instance 205 * gpio_pin: pin on which interrupt value needs to be set 206 * interrupt: interrupt value which needs to be set on pin 207 */ 208 static void secumod_gpio_set_interrupt(struct gpio_chip *chip __unused, 209 unsigned int gpio_pin, 210 enum gpio_interrupt interrupt) 211 { 212 vaddr_t niepr_addr = secumod_base + piobu_device->compat->of_niepr; 213 214 assert(gpio_pin < SECUMOD_MAX_PINS && 215 !(gpio_protected & BIT32(gpio_pin))); 216 217 if (interrupt == GPIO_INTERRUPT_ENABLE) 218 io_setbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); 219 else 220 io_clrbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); 221 } 222 223 static const struct gpio_ops atmel_piobu_ops = { 224 .get_direction = secumod_gpio_get_direction, 225 .set_direction = secumod_gpio_set_direction, 226 .get_value = secumod_gpio_get_value, 227 .set_value = secumod_gpio_set_value, 228 .get_interrupt = secumod_gpio_get_interrupt, 229 .set_interrupt = secumod_gpio_set_interrupt, 230 }; 231 232 static TEE_Result secumod_dt_get(struct dt_pargs *pargs, void *data, 233 struct gpio **out_gpio) 234 { 235 TEE_Result res = TEE_ERROR_GENERIC; 236 struct gpio *gpio = NULL; 237 struct gpio_chip *chip = data; 238 239 res = gpio_dt_alloc_pin(pargs, &gpio); 240 if (res) 241 return res; 242 243 if (gpio_protected & BIT32(gpio->pin)) { 244 free(gpio); 245 return TEE_ERROR_GENERIC; 246 } 247 248 gpio->chip = chip; 249 *out_gpio = gpio; 250 251 return TEE_SUCCESS; 252 } 253 254 static enum itr_return secumod_it_handler(struct itr_handler *handler __unused) 255 { 256 int i = 0; 257 struct optee_rtc_time tm = { }; 258 TEE_Result res = TEE_ERROR_GENERIC; 259 uint32_t sr = io_read32(secumod_base + SECUMOD_SR); 260 261 for (i = 0; i < SECUMOD_MAX_PINS; i++) { 262 if (sr & SECUMOD_PIN_VAL(i)) 263 EMSG("Detected tampering on pin %d", i); 264 } 265 266 if (sr & SECUMOD_SR_JTAG) 267 EMSG("JTAG tampering attempt"); 268 269 if (sr & SECUMOD_SR_TST_PIN) 270 EMSG("Test pin tampering attempt"); 271 272 res = atmel_rtc_get_tamper_timestamp(&tm); 273 if (!res) { 274 EMSG("Date of tampering: %02"PRIu32"/%02"PRIu32"/%02"PRIu32"", 275 tm.tm_mday, tm.tm_mon, tm.tm_year); 276 EMSG("Time of tampering: %02"PRIu32":%02"PRIu32":%02"PRIu32"", 277 tm.tm_hour, tm.tm_min, tm.tm_sec); 278 } 279 280 io_write32(secumod_base + SECUMOD_SCR, 281 SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); 282 283 panic("Tampering detected, system halted"); 284 285 return ITRR_HANDLED; 286 } 287 288 static struct itr_handler secumod_itr_handler = { 289 .it = AT91C_ID_SECUMOD, 290 .handler = secumod_it_handler, 291 }; 292 293 static void secumod_interrupt_init(void) 294 { 295 TEE_Result res = TEE_ERROR_GENERIC; 296 297 secumod_itr_handler.chip = interrupt_get_main_chip(); 298 299 res = interrupt_add_configure_handler(&secumod_itr_handler, 300 IRQ_TYPE_LEVEL_HIGH, 7); 301 if (res) 302 panic(); 303 304 interrupt_enable(secumod_itr_handler.chip, secumod_itr_handler.it); 305 } 306 307 static void secumod_cfg_input_pio(uint8_t gpio_pin, uint32_t config) 308 { 309 vaddr_t piobu_addr = 0; 310 uint8_t afv = 0; 311 uint8_t rfv = 0; 312 uint8_t pull_mode = PIOBU_PIN_PULL_NONE; 313 uint8_t def_level = PIOBU_PIN_DEF_LEVEL_LOW; 314 315 assert(gpio_pin < SECUMOD_MAX_PINS); 316 317 piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); 318 319 /* Set GPIO as input */ 320 io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); 321 322 afv = PIOBU_PIN_AFV(config); 323 rfv = PIOBU_PIN_RFV(config); 324 pull_mode = PIOBU_PIN_PULL_MODE(config); 325 def_level = PIOBU_PIN_DEF_LEVEL(config); 326 327 io_write32(piobu_addr, afv | rfv << SECUMOD_PIOBU_RFV_SHIFT | 328 pull_mode << SECUMOD_PIOBU_PULLUP_SHIFT | 329 def_level << SECUMOD_PIOBU_SWITCH_SHIFT); 330 331 /* Enable Tampering Interrupt */ 332 secumod_gpio_set_interrupt(&secumod_chip, gpio_pin, 333 GPIO_INTERRUPT_ENABLE); 334 335 /* Enable Intrusion Detection */ 336 io_setbits32(secumod_base + piobu_device->compat->of_nmpr, 337 SECUMOD_PIN_VAL(gpio_pin)); 338 339 /* Enable Wakeup */ 340 if (PIOBU_PIN_WAKEUP(config)) 341 io_setbits32(secumod_base + piobu_device->compat->of_wkpr, 342 SECUMOD_PIN_VAL(gpio_pin)); 343 344 gpio_protected |= BIT32(gpio_pin); 345 } 346 347 static void secumod_hw_init(const void *fdt, int node) 348 { 349 int i = 0; 350 int len = 0; 351 uint8_t gpio_pin = 0; 352 uint32_t config = 0; 353 const uint32_t *prop = NULL; 354 355 /* Disable JTAG Reset and Debug */ 356 io_write32(secumod_base + piobu_device->compat->of_jtagcr, 357 SECUMOD_JTAGCR_FNTRST); 358 359 /* Switch IOs to normal mode */ 360 io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 361 SECUMOD_CR_NORMAL); 362 363 /* Clear all detection intrusion in normal mode */ 364 io_write32(secumod_base + piobu_device->compat->of_nmpr, 0); 365 366 /* Clear Alarms */ 367 io_write32(secumod_base + SECUMOD_SCR, 368 SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); 369 370 /* Configure each IOs */ 371 prop = fdt_getprop(fdt, node, "gpios", &len); 372 if (!prop) 373 return; 374 375 len /= sizeof(uint32_t); 376 for (i = 0; i < len; i += DT_GPIO_CELLS) { 377 gpio_pin = fdt32_to_cpu(prop[i]); 378 config = fdt32_to_cpu(prop[i + 1]); 379 380 secumod_cfg_input_pio(gpio_pin, config); 381 } 382 } 383 384 #ifdef CFG_PM_ARM32 385 static TEE_Result piobu_pm(enum pm_op op, uint32_t pm_hint __unused, 386 const struct pm_callback_handle *hdl __unused) 387 { 388 switch (op) { 389 case PM_OP_RESUME: 390 io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 391 SECUMOD_CR_NORMAL); 392 break; 393 case PM_OP_SUSPEND: 394 /* Enter backup mode before suspending */ 395 io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | 396 SECUMOD_CR_BACKUP); 397 break; 398 default: 399 panic("Invalid PM operation"); 400 } 401 402 return TEE_SUCCESS; 403 } 404 405 static void piobu_register_pm(void) 406 { 407 register_pm_driver_cb(piobu_pm, NULL, "piobu"); 408 } 409 #else 410 static void piobu_register_pm(void) {} 411 #endif 412 413 static TEE_Result atmel_secumod_probe(const void *fdt, int node, 414 const void *compat_data) 415 { 416 size_t size = 0; 417 418 if (secumod_base) 419 return TEE_ERROR_GENERIC; 420 421 piobu_device = calloc(1, sizeof(*piobu_device)); 422 if (!piobu_device) 423 return TEE_ERROR_OUT_OF_MEMORY; 424 425 piobu_device->compat = (struct piobu_compat *)compat_data; 426 427 if (dt_map_dev(fdt, node, &secumod_base, &size, DT_MAP_AUTO) < 0) 428 return TEE_ERROR_GENERIC; 429 430 secumod_hw_init(fdt, node); 431 secumod_interrupt_init(); 432 433 secumod_chip.ops = &atmel_piobu_ops; 434 435 piobu_register_pm(); 436 437 assert(gpio_ops_is_valid(&atmel_piobu_ops)); 438 439 return gpio_register_provider(fdt, node, secumod_dt_get, &secumod_chip); 440 } 441 442 static const struct piobu_compat sama5d2_compat = { 443 .max_pins = 8, 444 .of_jtagcr = 0x68, 445 .of_bmpr = 0x7C, 446 .of_nmpr = 0x80, 447 .of_niepr = 0x84, 448 .of_nidpr = 0x88, 449 .of_nimpr = 0x8C, 450 .of_wkpr = 0x90, 451 }; 452 453 static const struct piobu_compat sama7g54_compat = { 454 .max_pins = 4, 455 .of_jtagcr = 0x70, 456 .of_bmpr = 0x84, 457 .of_nmpr = 0x88, 458 .of_niepr = 0x8C, 459 .of_nidpr = 0x90, 460 .of_nimpr = 0x94, 461 .of_wkpr = 0x98, 462 }; 463 464 static const struct dt_device_match atmel_secumod_match_table[] = { 465 { 466 .compatible = "atmel,sama5d2-secumod", 467 .compat_data = &sama5d2_compat, 468 }, 469 { 470 .compatible = "microchip,sama7g5-secumod", 471 .compat_data = &sama7g54_compat, 472 }, 473 { } 474 }; 475 476 DEFINE_DT_DRIVER(atmel_secumod_dt_driver) = { 477 .name = "atmel_secumod", 478 .type = DT_DRIVER_NOTYPE, 479 .match_table = atmel_secumod_match_table, 480 .probe = atmel_secumod_probe, 481 }; 482