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