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