1 /* 2 * ARM PrimeCell Timer modules. 3 * 4 * Copyright (c) 2005-2006 CodeSourcery. 5 * Written by Paul Brook 6 * 7 * This code is licensed under the GPL. 8 */ 9 10 #include "qemu/osdep.h" 11 #include "hw/sysbus.h" 12 #include "qemu/timer.h" 13 #include "qemu-common.h" 14 #include "hw/qdev.h" 15 #include "hw/ptimer.h" 16 #include "qemu/main-loop.h" 17 18 /* Common timer implementation. */ 19 20 #define TIMER_CTRL_ONESHOT (1 << 0) 21 #define TIMER_CTRL_32BIT (1 << 1) 22 #define TIMER_CTRL_DIV1 (0 << 2) 23 #define TIMER_CTRL_DIV16 (1 << 2) 24 #define TIMER_CTRL_DIV256 (2 << 2) 25 #define TIMER_CTRL_IE (1 << 5) 26 #define TIMER_CTRL_PERIODIC (1 << 6) 27 #define TIMER_CTRL_ENABLE (1 << 7) 28 29 typedef struct { 30 ptimer_state *timer; 31 uint32_t control; 32 uint32_t limit; 33 int freq; 34 int int_level; 35 qemu_irq irq; 36 } arm_timer_state; 37 38 /* Check all active timers, and schedule the next timer interrupt. */ 39 40 static void arm_timer_update(arm_timer_state *s) 41 { 42 /* Update interrupts. */ 43 if (s->int_level && (s->control & TIMER_CTRL_IE)) { 44 qemu_irq_raise(s->irq); 45 } else { 46 qemu_irq_lower(s->irq); 47 } 48 } 49 50 static uint32_t arm_timer_read(void *opaque, hwaddr offset) 51 { 52 arm_timer_state *s = (arm_timer_state *)opaque; 53 54 switch (offset >> 2) { 55 case 0: /* TimerLoad */ 56 case 6: /* TimerBGLoad */ 57 return s->limit; 58 case 1: /* TimerValue */ 59 return ptimer_get_count(s->timer); 60 case 2: /* TimerControl */ 61 return s->control; 62 case 4: /* TimerRIS */ 63 return s->int_level; 64 case 5: /* TimerMIS */ 65 if ((s->control & TIMER_CTRL_IE) == 0) 66 return 0; 67 return s->int_level; 68 default: 69 qemu_log_mask(LOG_GUEST_ERROR, 70 "%s: Bad offset %x\n", __func__, (int)offset); 71 return 0; 72 } 73 } 74 75 /* Reset the timer limit after settings have changed. */ 76 static void arm_timer_recalibrate(arm_timer_state *s, int reload) 77 { 78 uint32_t limit; 79 80 if ((s->control & (TIMER_CTRL_PERIODIC | TIMER_CTRL_ONESHOT)) == 0) { 81 /* Free running. */ 82 if (s->control & TIMER_CTRL_32BIT) 83 limit = 0xffffffff; 84 else 85 limit = 0xffff; 86 } else { 87 /* Periodic. */ 88 limit = s->limit; 89 } 90 ptimer_set_limit(s->timer, limit, reload); 91 } 92 93 static void arm_timer_write(void *opaque, hwaddr offset, 94 uint32_t value) 95 { 96 arm_timer_state *s = (arm_timer_state *)opaque; 97 int freq; 98 99 switch (offset >> 2) { 100 case 0: /* TimerLoad */ 101 s->limit = value; 102 arm_timer_recalibrate(s, 1); 103 break; 104 case 1: /* TimerValue */ 105 /* ??? Linux seems to want to write to this readonly register. 106 Ignore it. */ 107 break; 108 case 2: /* TimerControl */ 109 if (s->control & TIMER_CTRL_ENABLE) { 110 /* Pause the timer if it is running. This may cause some 111 inaccuracy dure to rounding, but avoids a whole lot of other 112 messyness. */ 113 ptimer_stop(s->timer); 114 } 115 s->control = value; 116 freq = s->freq; 117 /* ??? Need to recalculate expiry time after changing divisor. */ 118 switch ((value >> 2) & 3) { 119 case 1: freq >>= 4; break; 120 case 2: freq >>= 8; break; 121 } 122 arm_timer_recalibrate(s, s->control & TIMER_CTRL_ENABLE); 123 ptimer_set_freq(s->timer, freq); 124 if (s->control & TIMER_CTRL_ENABLE) { 125 /* Restart the timer if still enabled. */ 126 ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0); 127 } 128 break; 129 case 3: /* TimerIntClr */ 130 s->int_level = 0; 131 break; 132 case 6: /* TimerBGLoad */ 133 s->limit = value; 134 arm_timer_recalibrate(s, 0); 135 break; 136 default: 137 qemu_log_mask(LOG_GUEST_ERROR, 138 "%s: Bad offset %x\n", __func__, (int)offset); 139 } 140 arm_timer_update(s); 141 } 142 143 static void arm_timer_tick(void *opaque) 144 { 145 arm_timer_state *s = (arm_timer_state *)opaque; 146 s->int_level = 1; 147 arm_timer_update(s); 148 } 149 150 static const VMStateDescription vmstate_arm_timer = { 151 .name = "arm_timer", 152 .version_id = 1, 153 .minimum_version_id = 1, 154 .fields = (VMStateField[]) { 155 VMSTATE_UINT32(control, arm_timer_state), 156 VMSTATE_UINT32(limit, arm_timer_state), 157 VMSTATE_INT32(int_level, arm_timer_state), 158 VMSTATE_PTIMER(timer, arm_timer_state), 159 VMSTATE_END_OF_LIST() 160 } 161 }; 162 163 static arm_timer_state *arm_timer_init(uint32_t freq) 164 { 165 arm_timer_state *s; 166 QEMUBH *bh; 167 168 s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state)); 169 s->freq = freq; 170 s->control = TIMER_CTRL_IE; 171 172 bh = qemu_bh_new(arm_timer_tick, s); 173 s->timer = ptimer_init(bh); 174 vmstate_register(NULL, -1, &vmstate_arm_timer, s); 175 return s; 176 } 177 178 /* ARM PrimeCell SP804 dual timer module. 179 * Docs at 180 * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html 181 */ 182 183 #define TYPE_SP804 "sp804" 184 #define SP804(obj) OBJECT_CHECK(SP804State, (obj), TYPE_SP804) 185 186 typedef struct SP804State { 187 SysBusDevice parent_obj; 188 189 MemoryRegion iomem; 190 arm_timer_state *timer[2]; 191 uint32_t freq0, freq1; 192 int level[2]; 193 qemu_irq irq; 194 } SP804State; 195 196 static const uint8_t sp804_ids[] = { 197 /* Timer ID */ 198 0x04, 0x18, 0x14, 0, 199 /* PrimeCell ID */ 200 0xd, 0xf0, 0x05, 0xb1 201 }; 202 203 /* Merge the IRQs from the two component devices. */ 204 static void sp804_set_irq(void *opaque, int irq, int level) 205 { 206 SP804State *s = (SP804State *)opaque; 207 208 s->level[irq] = level; 209 qemu_set_irq(s->irq, s->level[0] || s->level[1]); 210 } 211 212 static uint64_t sp804_read(void *opaque, hwaddr offset, 213 unsigned size) 214 { 215 SP804State *s = (SP804State *)opaque; 216 217 if (offset < 0x20) { 218 return arm_timer_read(s->timer[0], offset); 219 } 220 if (offset < 0x40) { 221 return arm_timer_read(s->timer[1], offset - 0x20); 222 } 223 224 /* TimerPeriphID */ 225 if (offset >= 0xfe0 && offset <= 0xffc) { 226 return sp804_ids[(offset - 0xfe0) >> 2]; 227 } 228 229 switch (offset) { 230 /* Integration Test control registers, which we won't support */ 231 case 0xf00: /* TimerITCR */ 232 case 0xf04: /* TimerITOP (strictly write only but..) */ 233 qemu_log_mask(LOG_UNIMP, 234 "%s: integration test registers unimplemented\n", 235 __func__); 236 return 0; 237 } 238 239 qemu_log_mask(LOG_GUEST_ERROR, 240 "%s: Bad offset %x\n", __func__, (int)offset); 241 return 0; 242 } 243 244 static void sp804_write(void *opaque, hwaddr offset, 245 uint64_t value, unsigned size) 246 { 247 SP804State *s = (SP804State *)opaque; 248 249 if (offset < 0x20) { 250 arm_timer_write(s->timer[0], offset, value); 251 return; 252 } 253 254 if (offset < 0x40) { 255 arm_timer_write(s->timer[1], offset - 0x20, value); 256 return; 257 } 258 259 /* Technically we could be writing to the Test Registers, but not likely */ 260 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %x\n", 261 __func__, (int)offset); 262 } 263 264 static const MemoryRegionOps sp804_ops = { 265 .read = sp804_read, 266 .write = sp804_write, 267 .endianness = DEVICE_NATIVE_ENDIAN, 268 }; 269 270 static const VMStateDescription vmstate_sp804 = { 271 .name = "sp804", 272 .version_id = 1, 273 .minimum_version_id = 1, 274 .fields = (VMStateField[]) { 275 VMSTATE_INT32_ARRAY(level, SP804State, 2), 276 VMSTATE_END_OF_LIST() 277 } 278 }; 279 280 static int sp804_init(SysBusDevice *sbd) 281 { 282 DeviceState *dev = DEVICE(sbd); 283 SP804State *s = SP804(dev); 284 285 sysbus_init_irq(sbd, &s->irq); 286 s->timer[0] = arm_timer_init(s->freq0); 287 s->timer[1] = arm_timer_init(s->freq1); 288 s->timer[0]->irq = qemu_allocate_irq(sp804_set_irq, s, 0); 289 s->timer[1]->irq = qemu_allocate_irq(sp804_set_irq, s, 1); 290 memory_region_init_io(&s->iomem, OBJECT(s), &sp804_ops, s, 291 "sp804", 0x1000); 292 sysbus_init_mmio(sbd, &s->iomem); 293 vmstate_register(dev, -1, &vmstate_sp804, s); 294 return 0; 295 } 296 297 /* Integrator/CP timer module. */ 298 299 #define TYPE_INTEGRATOR_PIT "integrator_pit" 300 #define INTEGRATOR_PIT(obj) \ 301 OBJECT_CHECK(icp_pit_state, (obj), TYPE_INTEGRATOR_PIT) 302 303 typedef struct { 304 SysBusDevice parent_obj; 305 306 MemoryRegion iomem; 307 arm_timer_state *timer[3]; 308 } icp_pit_state; 309 310 static uint64_t icp_pit_read(void *opaque, hwaddr offset, 311 unsigned size) 312 { 313 icp_pit_state *s = (icp_pit_state *)opaque; 314 int n; 315 316 /* ??? Don't know the PrimeCell ID for this device. */ 317 n = offset >> 8; 318 if (n > 2) { 319 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n); 320 return 0; 321 } 322 323 return arm_timer_read(s->timer[n], offset & 0xff); 324 } 325 326 static void icp_pit_write(void *opaque, hwaddr offset, 327 uint64_t value, unsigned size) 328 { 329 icp_pit_state *s = (icp_pit_state *)opaque; 330 int n; 331 332 n = offset >> 8; 333 if (n > 2) { 334 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n); 335 return; 336 } 337 338 arm_timer_write(s->timer[n], offset & 0xff, value); 339 } 340 341 static const MemoryRegionOps icp_pit_ops = { 342 .read = icp_pit_read, 343 .write = icp_pit_write, 344 .endianness = DEVICE_NATIVE_ENDIAN, 345 }; 346 347 static int icp_pit_init(SysBusDevice *dev) 348 { 349 icp_pit_state *s = INTEGRATOR_PIT(dev); 350 351 /* Timer 0 runs at the system clock speed (40MHz). */ 352 s->timer[0] = arm_timer_init(40000000); 353 /* The other two timers run at 1MHz. */ 354 s->timer[1] = arm_timer_init(1000000); 355 s->timer[2] = arm_timer_init(1000000); 356 357 sysbus_init_irq(dev, &s->timer[0]->irq); 358 sysbus_init_irq(dev, &s->timer[1]->irq); 359 sysbus_init_irq(dev, &s->timer[2]->irq); 360 361 memory_region_init_io(&s->iomem, OBJECT(s), &icp_pit_ops, s, 362 "icp_pit", 0x1000); 363 sysbus_init_mmio(dev, &s->iomem); 364 /* This device has no state to save/restore. The component timers will 365 save themselves. */ 366 return 0; 367 } 368 369 static void icp_pit_class_init(ObjectClass *klass, void *data) 370 { 371 SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); 372 373 sdc->init = icp_pit_init; 374 } 375 376 static const TypeInfo icp_pit_info = { 377 .name = TYPE_INTEGRATOR_PIT, 378 .parent = TYPE_SYS_BUS_DEVICE, 379 .instance_size = sizeof(icp_pit_state), 380 .class_init = icp_pit_class_init, 381 }; 382 383 static Property sp804_properties[] = { 384 DEFINE_PROP_UINT32("freq0", SP804State, freq0, 1000000), 385 DEFINE_PROP_UINT32("freq1", SP804State, freq1, 1000000), 386 DEFINE_PROP_END_OF_LIST(), 387 }; 388 389 static void sp804_class_init(ObjectClass *klass, void *data) 390 { 391 SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); 392 DeviceClass *k = DEVICE_CLASS(klass); 393 394 sdc->init = sp804_init; 395 k->props = sp804_properties; 396 } 397 398 static const TypeInfo sp804_info = { 399 .name = TYPE_SP804, 400 .parent = TYPE_SYS_BUS_DEVICE, 401 .instance_size = sizeof(SP804State), 402 .class_init = sp804_class_init, 403 }; 404 405 static void arm_timer_register_types(void) 406 { 407 type_register_static(&icp_pit_info); 408 type_register_static(&sp804_info); 409 } 410 411 type_init(arm_timer_register_types) 412