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 { fprintf(stderr, "%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, 0); 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_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) { 222 /* if the compare feature is on and timers are running */ 223 uint32_t tmp = imx_epit_update_count(s); 224 uint64_t next; 225 if (tmp > s->cmp) { 226 /* It'll fire in this round of the timer */ 227 next = tmp - s->cmp; 228 } else { /* catch it next time around */ 229 next = tmp - s->cmp + ((s->cr & CR_RLD) ? TIMER_MAX : s->lr); 230 } 231 ptimer_set_count(s->timer_cmp, next); 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 uint64_t oldcr; 241 242 DPRINTF("(%s, value = 0x%08x)\n", imx_epit_reg_name(reg), (uint32_t)value); 243 244 switch (reg) { 245 case 0: /* CR */ 246 247 oldcr = s->cr; 248 s->cr = value & 0x03ffffff; 249 if (s->cr & CR_SWR) { 250 /* handle the reset */ 251 imx_epit_reset(DEVICE(s)); 252 } else { 253 imx_epit_set_freq(s); 254 } 255 256 if (s->freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) { 257 if (s->cr & CR_ENMOD) { 258 if (s->cr & CR_RLD) { 259 ptimer_set_limit(s->timer_reload, s->lr, 1); 260 ptimer_set_limit(s->timer_cmp, s->lr, 1); 261 } else { 262 ptimer_set_limit(s->timer_reload, TIMER_MAX, 1); 263 ptimer_set_limit(s->timer_cmp, TIMER_MAX, 1); 264 } 265 } 266 267 imx_epit_reload_compare_timer(s); 268 ptimer_run(s->timer_reload, 0); 269 if (s->cr & CR_OCIEN) { 270 ptimer_run(s->timer_cmp, 0); 271 } else { 272 ptimer_stop(s->timer_cmp); 273 } 274 } else if (!(s->cr & CR_EN)) { 275 /* stop both timers */ 276 ptimer_stop(s->timer_reload); 277 ptimer_stop(s->timer_cmp); 278 } else if (s->cr & CR_OCIEN) { 279 if (!(oldcr & CR_OCIEN)) { 280 imx_epit_reload_compare_timer(s); 281 ptimer_run(s->timer_cmp, 0); 282 } 283 } else { 284 ptimer_stop(s->timer_cmp); 285 } 286 break; 287 288 case 1: /* SR - ACK*/ 289 /* writing 1 to OCIF clear the OCIF bit */ 290 if (value & 0x01) { 291 s->sr = 0; 292 imx_epit_update_int(s); 293 } 294 break; 295 296 case 2: /* LR - set ticks */ 297 s->lr = value; 298 299 if (s->cr & CR_RLD) { 300 /* Also set the limit if the LRD bit is set */ 301 /* If IOVW bit is set then set the timer value */ 302 ptimer_set_limit(s->timer_reload, s->lr, s->cr & CR_IOVW); 303 ptimer_set_limit(s->timer_cmp, s->lr, 0); 304 } else if (s->cr & CR_IOVW) { 305 /* If IOVW bit is set then set the timer value */ 306 ptimer_set_count(s->timer_reload, s->lr); 307 } 308 309 imx_epit_reload_compare_timer(s); 310 break; 311 312 case 3: /* CMP */ 313 s->cmp = value; 314 315 imx_epit_reload_compare_timer(s); 316 317 break; 318 319 default: 320 IPRINTF("Bad offset %x\n", reg); 321 322 break; 323 } 324 } 325 static void imx_epit_cmp(void *opaque) 326 { 327 IMXEPITState *s = IMX_EPIT(opaque); 328 329 DPRINTF("sr was %d\n", s->sr); 330 331 s->sr = 1; 332 imx_epit_update_int(s); 333 } 334 335 void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm) 336 { 337 IMXEPITState *pp; 338 DeviceState *dev; 339 340 dev = sysbus_create_simple(TYPE_IMX_EPIT, addr, irq); 341 pp = IMX_EPIT(dev); 342 pp->ccm = ccm; 343 } 344 345 static const MemoryRegionOps imx_epit_ops = { 346 .read = imx_epit_read, 347 .write = imx_epit_write, 348 .endianness = DEVICE_NATIVE_ENDIAN, 349 }; 350 351 static const VMStateDescription vmstate_imx_timer_epit = { 352 .name = "imx.epit", 353 .version_id = 2, 354 .minimum_version_id = 2, 355 .minimum_version_id_old = 2, 356 .fields = (VMStateField[]) { 357 VMSTATE_UINT32(cr, IMXEPITState), 358 VMSTATE_UINT32(sr, IMXEPITState), 359 VMSTATE_UINT32(lr, IMXEPITState), 360 VMSTATE_UINT32(cmp, IMXEPITState), 361 VMSTATE_UINT32(cnt, IMXEPITState), 362 VMSTATE_UINT32(freq, IMXEPITState), 363 VMSTATE_PTIMER(timer_reload, IMXEPITState), 364 VMSTATE_PTIMER(timer_cmp, IMXEPITState), 365 VMSTATE_END_OF_LIST() 366 } 367 }; 368 369 static void imx_epit_realize(DeviceState *dev, Error **errp) 370 { 371 IMXEPITState *s = IMX_EPIT(dev); 372 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 373 QEMUBH *bh; 374 375 DPRINTF("\n"); 376 377 sysbus_init_irq(sbd, &s->irq); 378 memory_region_init_io(&s->iomem, OBJECT(s), &imx_epit_ops, s, TYPE_IMX_EPIT, 379 0x00001000); 380 sysbus_init_mmio(sbd, &s->iomem); 381 382 s->timer_reload = ptimer_init(NULL); 383 384 bh = qemu_bh_new(imx_epit_cmp, s); 385 s->timer_cmp = ptimer_init(bh); 386 } 387 388 static void imx_epit_class_init(ObjectClass *klass, void *data) 389 { 390 DeviceClass *dc = DEVICE_CLASS(klass); 391 392 dc->realize = imx_epit_realize; 393 dc->reset = imx_epit_reset; 394 dc->vmsd = &vmstate_imx_timer_epit; 395 dc->desc = "i.MX periodic timer"; 396 } 397 398 static const TypeInfo imx_epit_info = { 399 .name = TYPE_IMX_EPIT, 400 .parent = TYPE_SYS_BUS_DEVICE, 401 .instance_size = sizeof(IMXEPITState), 402 .class_init = imx_epit_class_init, 403 }; 404 405 static void imx_epit_register_types(void) 406 { 407 type_register_static(&imx_epit_info); 408 } 409 410 type_init(imx_epit_register_types) 411