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