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