1 /* 2 * IMX EPIT Timer 3 * 4 * Copyright (c) 2008 OK Labs 5 * Copyright (c) 2011 NICTA Pty Ltd 6 * Originally written by Hans Jiang 7 * Updated by Peter Chubb 8 * 9 * This code is licensed under GPL version 2 or later. See 10 * the COPYING file in the top-level directory. 11 * 12 */ 13 14 #include "hw/hw.h" 15 #include "qemu/bitops.h" 16 #include "qemu/timer.h" 17 #include "hw/ptimer.h" 18 #include "hw/sysbus.h" 19 #include "hw/arm/imx.h" 20 21 //#define DEBUG_TIMER 1 22 #ifdef DEBUG_TIMER 23 # define DPRINTF(fmt, args...) \ 24 do { printf("imx_timer: " fmt , ##args); } while (0) 25 #else 26 # define DPRINTF(fmt, args...) do {} while (0) 27 #endif 28 29 /* 30 * Define to 1 for messages about attempts to 31 * access unimplemented registers or similar. 32 */ 33 #define DEBUG_IMPLEMENTATION 1 34 #if DEBUG_IMPLEMENTATION 35 # define IPRINTF(fmt, args...) \ 36 do { fprintf(stderr, "imx_timer: " fmt, ##args); } while (0) 37 #else 38 # define IPRINTF(fmt, args...) do {} while (0) 39 #endif 40 41 /* 42 * EPIT: Enhanced periodic interrupt timer 43 */ 44 45 #define CR_EN (1 << 0) 46 #define CR_ENMOD (1 << 1) 47 #define CR_OCIEN (1 << 2) 48 #define CR_RLD (1 << 3) 49 #define CR_PRESCALE_SHIFT (4) 50 #define CR_PRESCALE_MASK (0xfff) 51 #define CR_SWR (1 << 16) 52 #define CR_IOVW (1 << 17) 53 #define CR_DBGEN (1 << 18) 54 #define CR_WAITEN (1 << 19) 55 #define CR_DOZEN (1 << 20) 56 #define CR_STOPEN (1 << 21) 57 #define CR_CLKSRC_SHIFT (24) 58 #define CR_CLKSRC_MASK (0x3 << CR_CLKSRC_SHIFT) 59 60 #define TIMER_MAX 0XFFFFFFFFUL 61 62 /* 63 * Exact clock frequencies vary from board to board. 64 * These are typical. 65 */ 66 static const IMXClk imx_timerp_clocks[] = { 67 0, /* 00 disabled */ 68 IPG, /* 01 ipg_clk, ~532MHz */ 69 IPG, /* 10 ipg_clk_highfreq */ 70 CLK_32k, /* 11 ipg_clk_32k -- ~32kHz */ 71 }; 72 73 typedef struct { 74 SysBusDevice busdev; 75 ptimer_state *timer_reload; 76 ptimer_state *timer_cmp; 77 MemoryRegion iomem; 78 DeviceState *ccm; 79 80 uint32_t cr; 81 uint32_t sr; 82 uint32_t lr; 83 uint32_t cmp; 84 uint32_t cnt; 85 86 uint32_t freq; 87 qemu_irq irq; 88 } IMXTimerPState; 89 90 /* 91 * Update interrupt status 92 */ 93 static void imx_timerp_update(IMXTimerPState *s) 94 { 95 if (s->sr && (s->cr & CR_OCIEN)) { 96 qemu_irq_raise(s->irq); 97 } else { 98 qemu_irq_lower(s->irq); 99 } 100 } 101 102 static void set_timerp_freq(IMXTimerPState *s) 103 { 104 unsigned clksrc; 105 unsigned prescaler; 106 uint32_t freq; 107 108 clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2); 109 prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12); 110 111 freq = imx_clock_frequency(s->ccm, imx_timerp_clocks[clksrc]) / prescaler; 112 113 s->freq = freq; 114 DPRINTF("Setting ptimer frequency to %u\n", freq); 115 116 if (freq) { 117 ptimer_set_freq(s->timer_reload, freq); 118 ptimer_set_freq(s->timer_cmp, freq); 119 } 120 } 121 122 static void imx_timerp_reset(DeviceState *dev) 123 { 124 IMXTimerPState *s = container_of(dev, IMXTimerPState, busdev.qdev); 125 126 /* 127 * Soft reset doesn't touch some bits; hard reset clears them 128 */ 129 s->cr &= ~(CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN); 130 s->sr = 0; 131 s->lr = TIMER_MAX; 132 s->cmp = 0; 133 s->cnt = 0; 134 /* stop both timers */ 135 ptimer_stop(s->timer_cmp); 136 ptimer_stop(s->timer_reload); 137 /* compute new frequency */ 138 set_timerp_freq(s); 139 /* init both timers to TIMER_MAX */ 140 ptimer_set_limit(s->timer_cmp, TIMER_MAX, 1); 141 ptimer_set_limit(s->timer_reload, TIMER_MAX, 1); 142 if (s->freq && (s->cr & CR_EN)) { 143 /* if the timer is still enabled, restart it */ 144 ptimer_run(s->timer_reload, 1); 145 } 146 } 147 148 static uint32_t imx_timerp_update_counts(IMXTimerPState *s) 149 { 150 s->cnt = ptimer_get_count(s->timer_reload); 151 152 return s->cnt; 153 } 154 155 static uint64_t imx_timerp_read(void *opaque, hwaddr offset, 156 unsigned size) 157 { 158 IMXTimerPState *s = (IMXTimerPState *)opaque; 159 160 DPRINTF("p-read(offset=%x)", (unsigned int)(offset >> 2)); 161 switch (offset >> 2) { 162 case 0: /* Control Register */ 163 DPRINTF("cr %x\n", s->cr); 164 return s->cr; 165 166 case 1: /* Status Register */ 167 DPRINTF("sr %x\n", s->sr); 168 return s->sr; 169 170 case 2: /* LR - ticks*/ 171 DPRINTF("lr %x\n", s->lr); 172 return s->lr; 173 174 case 3: /* CMP */ 175 DPRINTF("cmp %x\n", s->cmp); 176 return s->cmp; 177 178 case 4: /* CNT */ 179 imx_timerp_update_counts(s); 180 DPRINTF(" cnt = %x\n", s->cnt); 181 return s->cnt; 182 } 183 184 IPRINTF("imx_timerp_read: Bad offset %x\n", 185 (int)offset >> 2); 186 return 0; 187 } 188 189 static void imx_reload_compare_timer(IMXTimerPState *s) 190 { 191 if ((s->cr & CR_OCIEN) && s->cmp) { 192 /* if the compare feature is on */ 193 uint32_t tmp = imx_timerp_update_counts(s); 194 if (tmp > s->cmp) { 195 /* reinit the cmp timer if required */ 196 ptimer_set_count(s->timer_cmp, tmp - s->cmp); 197 if ((s->cr & CR_EN)) { 198 /* Restart the cmp timer if required */ 199 ptimer_run(s->timer_cmp, 0); 200 } 201 } 202 } 203 } 204 205 static void imx_timerp_write(void *opaque, hwaddr offset, 206 uint64_t value, unsigned size) 207 { 208 IMXTimerPState *s = (IMXTimerPState *)opaque; 209 DPRINTF("p-write(offset=%x, value = %x)\n", (unsigned int)offset >> 2, 210 (unsigned int)value); 211 212 switch (offset >> 2) { 213 case 0: /* CR */ 214 s->cr = value & 0x03ffffff; 215 if (s->cr & CR_SWR) { 216 /* handle the reset */ 217 imx_timerp_reset(&s->busdev.qdev); 218 } else { 219 set_timerp_freq(s); 220 } 221 222 if (s->freq && (s->cr & CR_EN)) { 223 if (s->cr & CR_ENMOD) { 224 if (s->cr & CR_RLD) { 225 ptimer_set_limit(s->timer_reload, s->lr, 1); 226 } else { 227 ptimer_set_limit(s->timer_reload, TIMER_MAX, 1); 228 } 229 } 230 231 imx_reload_compare_timer(s); 232 233 ptimer_run(s->timer_reload, 1); 234 } else { 235 /* stop both timers */ 236 ptimer_stop(s->timer_reload); 237 ptimer_stop(s->timer_cmp); 238 } 239 break; 240 241 case 1: /* SR - ACK*/ 242 /* writing 1 to OCIF clear the OCIF bit */ 243 if (value & 0x01) { 244 s->sr = 0; 245 imx_timerp_update(s); 246 } 247 break; 248 249 case 2: /* LR - set ticks */ 250 s->lr = value; 251 252 if (s->cr & CR_RLD) { 253 /* Also set the limit if the LRD bit is set */ 254 /* If IOVW bit is set then set the timer value */ 255 ptimer_set_limit(s->timer_reload, s->lr, s->cr & CR_IOVW); 256 } else if (s->cr & CR_IOVW) { 257 /* If IOVW bit is set then set the timer value */ 258 ptimer_set_count(s->timer_reload, s->lr); 259 } 260 261 imx_reload_compare_timer(s); 262 263 break; 264 265 case 3: /* CMP */ 266 s->cmp = value; 267 268 imx_reload_compare_timer(s); 269 270 break; 271 272 default: 273 IPRINTF("imx_timerp_write: Bad offset %x\n", 274 (int)offset >> 2); 275 } 276 } 277 278 static void imx_timerp_reload(void *opaque) 279 { 280 IMXTimerPState *s = (IMXTimerPState *)opaque; 281 282 DPRINTF("imxp reload\n"); 283 284 if (!(s->cr & CR_EN)) { 285 return; 286 } 287 288 if (s->cr & CR_RLD) { 289 ptimer_set_limit(s->timer_reload, s->lr, 1); 290 } else { 291 ptimer_set_limit(s->timer_reload, TIMER_MAX, 1); 292 } 293 294 if (s->cr & CR_OCIEN) { 295 /* if compare register is 0 then we handle the interrupt here */ 296 if (s->cmp == 0) { 297 s->sr = 1; 298 imx_timerp_update(s); 299 } else if (s->cmp <= s->lr) { 300 /* We should launch the compare register */ 301 ptimer_set_count(s->timer_cmp, s->lr - s->cmp); 302 ptimer_run(s->timer_cmp, 0); 303 } else { 304 IPRINTF("imxp reload: s->lr < s->cmp\n"); 305 } 306 } 307 } 308 309 static void imx_timerp_cmp(void *opaque) 310 { 311 IMXTimerPState *s = (IMXTimerPState *)opaque; 312 313 DPRINTF("imxp compare\n"); 314 315 ptimer_stop(s->timer_cmp); 316 317 /* compare register is not 0 */ 318 if (s->cmp) { 319 s->sr = 1; 320 imx_timerp_update(s); 321 } 322 } 323 324 void imx_timerp_create(const hwaddr addr, 325 qemu_irq irq, 326 DeviceState *ccm) 327 { 328 IMXTimerPState *pp; 329 DeviceState *dev; 330 331 dev = sysbus_create_simple("imx_timerp", addr, irq); 332 pp = container_of(dev, IMXTimerPState, busdev.qdev); 333 pp->ccm = ccm; 334 } 335 336 static const MemoryRegionOps imx_timerp_ops = { 337 .read = imx_timerp_read, 338 .write = imx_timerp_write, 339 .endianness = DEVICE_NATIVE_ENDIAN, 340 }; 341 342 static const VMStateDescription vmstate_imx_timerp = { 343 .name = "imx-timerp", 344 .version_id = 2, 345 .minimum_version_id = 2, 346 .minimum_version_id_old = 2, 347 .fields = (VMStateField[]) { 348 VMSTATE_UINT32(cr, IMXTimerPState), 349 VMSTATE_UINT32(sr, IMXTimerPState), 350 VMSTATE_UINT32(lr, IMXTimerPState), 351 VMSTATE_UINT32(cmp, IMXTimerPState), 352 VMSTATE_UINT32(cnt, IMXTimerPState), 353 VMSTATE_UINT32(freq, IMXTimerPState), 354 VMSTATE_PTIMER(timer_reload, IMXTimerPState), 355 VMSTATE_PTIMER(timer_cmp, IMXTimerPState), 356 VMSTATE_END_OF_LIST() 357 } 358 }; 359 360 static int imx_timerp_init(SysBusDevice *dev) 361 { 362 IMXTimerPState *s = FROM_SYSBUS(IMXTimerPState, dev); 363 QEMUBH *bh; 364 365 DPRINTF("imx_timerp_init\n"); 366 sysbus_init_irq(dev, &s->irq); 367 memory_region_init_io(&s->iomem, &imx_timerp_ops, 368 s, "imxp-timer", 369 0x00001000); 370 sysbus_init_mmio(dev, &s->iomem); 371 372 bh = qemu_bh_new(imx_timerp_reload, s); 373 s->timer_reload = ptimer_init(bh); 374 375 bh = qemu_bh_new(imx_timerp_cmp, s); 376 s->timer_cmp = ptimer_init(bh); 377 378 return 0; 379 } 380 381 382 static void imx_timerp_class_init(ObjectClass *klass, void *data) 383 { 384 DeviceClass *dc = DEVICE_CLASS(klass); 385 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 386 k->init = imx_timerp_init; 387 dc->vmsd = &vmstate_imx_timerp; 388 dc->reset = imx_timerp_reset; 389 dc->desc = "i.MX periodic timer"; 390 } 391 392 static const TypeInfo imx_timerp_info = { 393 .name = "imx_timerp", 394 .parent = TYPE_SYS_BUS_DEVICE, 395 .instance_size = sizeof(IMXTimerPState), 396 .class_init = imx_timerp_class_init, 397 }; 398 399 static void imx_timer_register_types(void) 400 { 401 type_register_static(&imx_timerp_info); 402 } 403 404 type_init(imx_timer_register_types) 405