1 /* 2 * ARM CMSDK APB dual-timer emulation 3 * 4 * Copyright (c) 2018 Linaro Limited 5 * Written by Peter Maydell 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 or 9 * (at your option) any later version. 10 */ 11 12 /* 13 * This is a model of the "APB dual-input timer" which is part of the Cortex-M 14 * System Design Kit (CMSDK) and documented in the Cortex-M System 15 * Design Kit Technical Reference Manual (ARM DDI0479C): 16 * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit 17 */ 18 19 #include "qemu/osdep.h" 20 #include "qemu/log.h" 21 #include "trace.h" 22 #include "qapi/error.h" 23 #include "qemu/main-loop.h" 24 #include "qemu/module.h" 25 #include "hw/sysbus.h" 26 #include "hw/irq.h" 27 #include "hw/registerfields.h" 28 #include "hw/timer/cmsdk-apb-dualtimer.h" 29 30 REG32(TIMER1LOAD, 0x0) 31 REG32(TIMER1VALUE, 0x4) 32 REG32(TIMER1CONTROL, 0x8) 33 FIELD(CONTROL, ONESHOT, 0, 1) 34 FIELD(CONTROL, SIZE, 1, 1) 35 FIELD(CONTROL, PRESCALE, 2, 2) 36 FIELD(CONTROL, INTEN, 5, 1) 37 FIELD(CONTROL, MODE, 6, 1) 38 FIELD(CONTROL, ENABLE, 7, 1) 39 #define R_CONTROL_VALID_MASK (R_CONTROL_ONESHOT_MASK | R_CONTROL_SIZE_MASK | \ 40 R_CONTROL_PRESCALE_MASK | R_CONTROL_INTEN_MASK | \ 41 R_CONTROL_MODE_MASK | R_CONTROL_ENABLE_MASK) 42 REG32(TIMER1INTCLR, 0xc) 43 REG32(TIMER1RIS, 0x10) 44 REG32(TIMER1MIS, 0x14) 45 REG32(TIMER1BGLOAD, 0x18) 46 REG32(TIMER2LOAD, 0x20) 47 REG32(TIMER2VALUE, 0x24) 48 REG32(TIMER2CONTROL, 0x28) 49 REG32(TIMER2INTCLR, 0x2c) 50 REG32(TIMER2RIS, 0x30) 51 REG32(TIMER2MIS, 0x34) 52 REG32(TIMER2BGLOAD, 0x38) 53 REG32(TIMERITCR, 0xf00) 54 FIELD(TIMERITCR, ENABLE, 0, 1) 55 #define R_TIMERITCR_VALID_MASK R_TIMERITCR_ENABLE_MASK 56 REG32(TIMERITOP, 0xf04) 57 FIELD(TIMERITOP, TIMINT1, 0, 1) 58 FIELD(TIMERITOP, TIMINT2, 1, 1) 59 #define R_TIMERITOP_VALID_MASK (R_TIMERITOP_TIMINT1_MASK | \ 60 R_TIMERITOP_TIMINT2_MASK) 61 REG32(PID4, 0xfd0) 62 REG32(PID5, 0xfd4) 63 REG32(PID6, 0xfd8) 64 REG32(PID7, 0xfdc) 65 REG32(PID0, 0xfe0) 66 REG32(PID1, 0xfe4) 67 REG32(PID2, 0xfe8) 68 REG32(PID3, 0xfec) 69 REG32(CID0, 0xff0) 70 REG32(CID1, 0xff4) 71 REG32(CID2, 0xff8) 72 REG32(CID3, 0xffc) 73 74 /* PID/CID values */ 75 static const int timer_id[] = { 76 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ 77 0x23, 0xb8, 0x1b, 0x00, /* PID0..PID3 */ 78 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ 79 }; 80 81 static bool cmsdk_dualtimermod_intstatus(CMSDKAPBDualTimerModule *m) 82 { 83 /* Return masked interrupt status for the timer module */ 84 return m->intstatus && (m->control & R_CONTROL_INTEN_MASK); 85 } 86 87 static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s) 88 { 89 bool timint1, timint2, timintc; 90 91 if (s->timeritcr) { 92 /* Integration test mode: outputs driven directly from TIMERITOP bits */ 93 timint1 = s->timeritop & R_TIMERITOP_TIMINT1_MASK; 94 timint2 = s->timeritop & R_TIMERITOP_TIMINT2_MASK; 95 } else { 96 timint1 = cmsdk_dualtimermod_intstatus(&s->timermod[0]); 97 timint2 = cmsdk_dualtimermod_intstatus(&s->timermod[1]); 98 } 99 100 timintc = timint1 || timint2; 101 102 qemu_set_irq(s->timermod[0].timerint, timint1); 103 qemu_set_irq(s->timermod[1].timerint, timint2); 104 qemu_set_irq(s->timerintc, timintc); 105 } 106 107 static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m, 108 uint32_t newctrl) 109 { 110 /* Handle a write to the CONTROL register */ 111 uint32_t changed; 112 113 newctrl &= R_CONTROL_VALID_MASK; 114 115 changed = m->control ^ newctrl; 116 117 if (changed & ~newctrl & R_CONTROL_ENABLE_MASK) { 118 /* ENABLE cleared, stop timer before any further changes */ 119 ptimer_stop(m->timer); 120 } 121 122 if (changed & R_CONTROL_PRESCALE_MASK) { 123 int divisor; 124 125 switch (FIELD_EX32(newctrl, CONTROL, PRESCALE)) { 126 case 0: 127 divisor = 1; 128 break; 129 case 1: 130 divisor = 16; 131 break; 132 case 2: 133 divisor = 256; 134 break; 135 case 3: 136 /* UNDEFINED; complain, and arbitrarily treat like 2 */ 137 qemu_log_mask(LOG_GUEST_ERROR, 138 "CMSDK APB dual-timer: CONTROL.PRESCALE==0b11" 139 " is undefined behaviour\n"); 140 divisor = 256; 141 break; 142 default: 143 g_assert_not_reached(); 144 } 145 ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor); 146 } 147 148 if (changed & R_CONTROL_MODE_MASK) { 149 uint32_t load; 150 if (newctrl & R_CONTROL_MODE_MASK) { 151 /* Periodic: the limit is the LOAD register value */ 152 load = m->load; 153 } else { 154 /* Free-running: counter wraps around */ 155 load = ptimer_get_limit(m->timer); 156 if (!(m->control & R_CONTROL_SIZE_MASK)) { 157 load = deposit32(m->load, 0, 16, load); 158 } 159 m->load = load; 160 load = 0xffffffff; 161 } 162 if (!(m->control & R_CONTROL_SIZE_MASK)) { 163 load &= 0xffff; 164 } 165 ptimer_set_limit(m->timer, load, 0); 166 } 167 168 if (changed & R_CONTROL_SIZE_MASK) { 169 /* Timer switched between 16 and 32 bit count */ 170 uint32_t value, load; 171 172 value = ptimer_get_count(m->timer); 173 load = ptimer_get_limit(m->timer); 174 if (newctrl & R_CONTROL_SIZE_MASK) { 175 /* 16 -> 32, top half of VALUE is in struct field */ 176 value = deposit32(m->value, 0, 16, value); 177 } else { 178 /* 32 -> 16: save top half to struct field and truncate */ 179 m->value = value; 180 value &= 0xffff; 181 } 182 183 if (newctrl & R_CONTROL_MODE_MASK) { 184 /* Periodic, timer limit has LOAD value */ 185 if (newctrl & R_CONTROL_SIZE_MASK) { 186 load = deposit32(m->load, 0, 16, load); 187 } else { 188 m->load = load; 189 load &= 0xffff; 190 } 191 } else { 192 /* Free-running, timer limit is set to give wraparound */ 193 if (newctrl & R_CONTROL_SIZE_MASK) { 194 load = 0xffffffff; 195 } else { 196 load = 0xffff; 197 } 198 } 199 ptimer_set_count(m->timer, value); 200 ptimer_set_limit(m->timer, load, 0); 201 } 202 203 if (newctrl & R_CONTROL_ENABLE_MASK) { 204 /* 205 * ENABLE is set; start the timer after all other changes. 206 * We start it even if the ENABLE bit didn't actually change, 207 * in case the timer was an expired one-shot timer that has 208 * now been changed into a free-running or periodic timer. 209 */ 210 ptimer_run(m->timer, !!(newctrl & R_CONTROL_ONESHOT_MASK)); 211 } 212 213 m->control = newctrl; 214 } 215 216 static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset, 217 unsigned size) 218 { 219 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque); 220 uint64_t r; 221 222 if (offset >= A_TIMERITCR) { 223 switch (offset) { 224 case A_TIMERITCR: 225 r = s->timeritcr; 226 break; 227 case A_PID4 ... A_CID3: 228 r = timer_id[(offset - A_PID4) / 4]; 229 break; 230 default: 231 bad_offset: 232 qemu_log_mask(LOG_GUEST_ERROR, 233 "CMSDK APB dual-timer read: bad offset %x\n", 234 (int) offset); 235 r = 0; 236 break; 237 } 238 } else { 239 int timer = offset >> 5; 240 CMSDKAPBDualTimerModule *m; 241 242 if (timer >= ARRAY_SIZE(s->timermod)) { 243 goto bad_offset; 244 } 245 246 m = &s->timermod[timer]; 247 248 switch (offset & 0x1F) { 249 case A_TIMER1LOAD: 250 case A_TIMER1BGLOAD: 251 if (m->control & R_CONTROL_MODE_MASK) { 252 /* 253 * Periodic: the ptimer limit is the LOAD register value, (or 254 * just the low 16 bits of it if the timer is in 16-bit mode) 255 */ 256 r = ptimer_get_limit(m->timer); 257 if (!(m->control & R_CONTROL_SIZE_MASK)) { 258 r = deposit32(m->load, 0, 16, r); 259 } 260 } else { 261 /* Free-running: LOAD register value is just in m->load */ 262 r = m->load; 263 } 264 break; 265 case A_TIMER1VALUE: 266 r = ptimer_get_count(m->timer); 267 if (!(m->control & R_CONTROL_SIZE_MASK)) { 268 r = deposit32(m->value, 0, 16, r); 269 } 270 break; 271 case A_TIMER1CONTROL: 272 r = m->control; 273 break; 274 case A_TIMER1RIS: 275 r = m->intstatus; 276 break; 277 case A_TIMER1MIS: 278 r = cmsdk_dualtimermod_intstatus(m); 279 break; 280 default: 281 goto bad_offset; 282 } 283 } 284 285 trace_cmsdk_apb_dualtimer_read(offset, r, size); 286 return r; 287 } 288 289 static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset, 290 uint64_t value, unsigned size) 291 { 292 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque); 293 294 trace_cmsdk_apb_dualtimer_write(offset, value, size); 295 296 if (offset >= A_TIMERITCR) { 297 switch (offset) { 298 case A_TIMERITCR: 299 s->timeritcr = value & R_TIMERITCR_VALID_MASK; 300 cmsdk_apb_dualtimer_update(s); 301 break; 302 case A_TIMERITOP: 303 s->timeritop = value & R_TIMERITOP_VALID_MASK; 304 cmsdk_apb_dualtimer_update(s); 305 break; 306 default: 307 bad_offset: 308 qemu_log_mask(LOG_GUEST_ERROR, 309 "CMSDK APB dual-timer write: bad offset %x\n", 310 (int) offset); 311 break; 312 } 313 } else { 314 int timer = offset >> 5; 315 CMSDKAPBDualTimerModule *m; 316 317 if (timer >= ARRAY_SIZE(s->timermod)) { 318 goto bad_offset; 319 } 320 321 m = &s->timermod[timer]; 322 323 switch (offset & 0x1F) { 324 case A_TIMER1LOAD: 325 /* Set the limit, and immediately reload the count from it */ 326 m->load = value; 327 m->value = value; 328 if (!(m->control & R_CONTROL_SIZE_MASK)) { 329 value &= 0xffff; 330 } 331 if (!(m->control & R_CONTROL_MODE_MASK)) { 332 /* 333 * In free-running mode this won't set the limit but will 334 * still change the current count value. 335 */ 336 ptimer_set_count(m->timer, value); 337 } else { 338 if (!value) { 339 ptimer_stop(m->timer); 340 } 341 ptimer_set_limit(m->timer, value, 1); 342 if (value && (m->control & R_CONTROL_ENABLE_MASK)) { 343 /* Force possibly-expired oneshot timer to restart */ 344 ptimer_run(m->timer, 1); 345 } 346 } 347 break; 348 case A_TIMER1BGLOAD: 349 /* Set the limit, but not the current count */ 350 m->load = value; 351 if (!(m->control & R_CONTROL_MODE_MASK)) { 352 /* In free-running mode there is no limit */ 353 break; 354 } 355 if (!(m->control & R_CONTROL_SIZE_MASK)) { 356 value &= 0xffff; 357 } 358 ptimer_set_limit(m->timer, value, 0); 359 break; 360 case A_TIMER1CONTROL: 361 cmsdk_dualtimermod_write_control(m, value); 362 cmsdk_apb_dualtimer_update(s); 363 break; 364 case A_TIMER1INTCLR: 365 m->intstatus = 0; 366 cmsdk_apb_dualtimer_update(s); 367 break; 368 default: 369 goto bad_offset; 370 } 371 } 372 } 373 374 static const MemoryRegionOps cmsdk_apb_dualtimer_ops = { 375 .read = cmsdk_apb_dualtimer_read, 376 .write = cmsdk_apb_dualtimer_write, 377 .endianness = DEVICE_LITTLE_ENDIAN, 378 /* byte/halfword accesses are just zero-padded on reads and writes */ 379 .impl.min_access_size = 4, 380 .impl.max_access_size = 4, 381 .valid.min_access_size = 1, 382 .valid.max_access_size = 4, 383 }; 384 385 static void cmsdk_dualtimermod_tick(void *opaque) 386 { 387 CMSDKAPBDualTimerModule *m = opaque; 388 389 m->intstatus = 1; 390 cmsdk_apb_dualtimer_update(m->parent); 391 } 392 393 static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m) 394 { 395 m->control = R_CONTROL_INTEN_MASK; 396 m->intstatus = 0; 397 m->load = 0; 398 m->value = 0xffffffff; 399 ptimer_stop(m->timer); 400 /* 401 * We start in free-running mode, with VALUE at 0xffffffff, and 402 * in 16-bit counter mode. This means that the ptimer count and 403 * limit must both be set to 0xffff, so we wrap at 16 bits. 404 */ 405 ptimer_set_limit(m->timer, 0xffff, 1); 406 ptimer_set_freq(m->timer, m->parent->pclk_frq); 407 } 408 409 static void cmsdk_apb_dualtimer_reset(DeviceState *dev) 410 { 411 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev); 412 int i; 413 414 trace_cmsdk_apb_dualtimer_reset(); 415 416 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) { 417 cmsdk_dualtimermod_reset(&s->timermod[i]); 418 } 419 s->timeritcr = 0; 420 s->timeritop = 0; 421 } 422 423 static void cmsdk_apb_dualtimer_init(Object *obj) 424 { 425 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 426 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(obj); 427 int i; 428 429 memory_region_init_io(&s->iomem, obj, &cmsdk_apb_dualtimer_ops, 430 s, "cmsdk-apb-dualtimer", 0x1000); 431 sysbus_init_mmio(sbd, &s->iomem); 432 sysbus_init_irq(sbd, &s->timerintc); 433 434 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) { 435 sysbus_init_irq(sbd, &s->timermod[i].timerint); 436 } 437 } 438 439 static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp) 440 { 441 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev); 442 int i; 443 444 if (s->pclk_frq == 0) { 445 error_setg(errp, "CMSDK APB timer: pclk-frq property must be set"); 446 return; 447 } 448 449 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) { 450 CMSDKAPBDualTimerModule *m = &s->timermod[i]; 451 QEMUBH *bh = qemu_bh_new(cmsdk_dualtimermod_tick, m); 452 453 m->parent = s; 454 m->timer = ptimer_init(bh, 455 PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD | 456 PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT | 457 PTIMER_POLICY_NO_IMMEDIATE_RELOAD | 458 PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); 459 } 460 } 461 462 static const VMStateDescription cmsdk_dualtimermod_vmstate = { 463 .name = "cmsdk-apb-dualtimer-module", 464 .version_id = 1, 465 .minimum_version_id = 1, 466 .fields = (VMStateField[]) { 467 VMSTATE_PTIMER(timer, CMSDKAPBDualTimerModule), 468 VMSTATE_UINT32(load, CMSDKAPBDualTimerModule), 469 VMSTATE_UINT32(value, CMSDKAPBDualTimerModule), 470 VMSTATE_UINT32(control, CMSDKAPBDualTimerModule), 471 VMSTATE_UINT32(intstatus, CMSDKAPBDualTimerModule), 472 VMSTATE_END_OF_LIST() 473 } 474 }; 475 476 static const VMStateDescription cmsdk_apb_dualtimer_vmstate = { 477 .name = "cmsdk-apb-dualtimer", 478 .version_id = 1, 479 .minimum_version_id = 1, 480 .fields = (VMStateField[]) { 481 VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer, 482 CMSDK_APB_DUALTIMER_NUM_MODULES, 483 1, cmsdk_dualtimermod_vmstate, 484 CMSDKAPBDualTimerModule), 485 VMSTATE_UINT32(timeritcr, CMSDKAPBDualTimer), 486 VMSTATE_UINT32(timeritop, CMSDKAPBDualTimer), 487 VMSTATE_END_OF_LIST() 488 } 489 }; 490 491 static Property cmsdk_apb_dualtimer_properties[] = { 492 DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer, pclk_frq, 0), 493 DEFINE_PROP_END_OF_LIST(), 494 }; 495 496 static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data) 497 { 498 DeviceClass *dc = DEVICE_CLASS(klass); 499 500 dc->realize = cmsdk_apb_dualtimer_realize; 501 dc->vmsd = &cmsdk_apb_dualtimer_vmstate; 502 dc->reset = cmsdk_apb_dualtimer_reset; 503 dc->props = cmsdk_apb_dualtimer_properties; 504 } 505 506 static const TypeInfo cmsdk_apb_dualtimer_info = { 507 .name = TYPE_CMSDK_APB_DUALTIMER, 508 .parent = TYPE_SYS_BUS_DEVICE, 509 .instance_size = sizeof(CMSDKAPBDualTimer), 510 .instance_init = cmsdk_apb_dualtimer_init, 511 .class_init = cmsdk_apb_dualtimer_class_init, 512 }; 513 514 static void cmsdk_apb_dualtimer_register_types(void) 515 { 516 type_register_static(&cmsdk_apb_dualtimer_info); 517 } 518 519 type_init(cmsdk_apb_dualtimer_register_types); 520