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