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