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