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