1a50c0d6fSJean-Christophe DUBOIS /* 2a50c0d6fSJean-Christophe DUBOIS * IMX EPIT Timer 3a50c0d6fSJean-Christophe DUBOIS * 4a50c0d6fSJean-Christophe DUBOIS * Copyright (c) 2008 OK Labs 5a50c0d6fSJean-Christophe DUBOIS * Copyright (c) 2011 NICTA Pty Ltd 6a50c0d6fSJean-Christophe DUBOIS * Originally written by Hans Jiang 7a50c0d6fSJean-Christophe DUBOIS * Updated by Peter Chubb 8951cd00eSJean-Christophe Dubois * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> 9a50c0d6fSJean-Christophe DUBOIS * 10a50c0d6fSJean-Christophe DUBOIS * This code is licensed under GPL version 2 or later. See 11a50c0d6fSJean-Christophe DUBOIS * the COPYING file in the top-level directory. 12a50c0d6fSJean-Christophe DUBOIS * 13a50c0d6fSJean-Christophe DUBOIS */ 14a50c0d6fSJean-Christophe DUBOIS 158ef94f0bSPeter Maydell #include "qemu/osdep.h" 16951cd00eSJean-Christophe Dubois #include "hw/timer/imx_epit.h" 17951cd00eSJean-Christophe Dubois #include "hw/misc/imx_ccm.h" 186a1751b7SAlex Bligh #include "qemu/main-loop.h" 1903dd024fSPaolo Bonzini #include "qemu/log.h" 20a50c0d6fSJean-Christophe DUBOIS 214929f656SJean-Christophe Dubois #ifndef DEBUG_IMX_EPIT 224929f656SJean-Christophe Dubois #define DEBUG_IMX_EPIT 0 234929f656SJean-Christophe Dubois #endif 244929f656SJean-Christophe Dubois 254929f656SJean-Christophe Dubois #define DPRINTF(fmt, args...) \ 264929f656SJean-Christophe Dubois do { \ 274929f656SJean-Christophe Dubois if (DEBUG_IMX_EPIT) { \ 284929f656SJean-Christophe Dubois fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_EPIT, \ 294929f656SJean-Christophe Dubois __func__, ##args); \ 304929f656SJean-Christophe Dubois } \ 314929f656SJean-Christophe Dubois } while (0) 3295669e69SJean-Christophe DUBOIS 33*d675765aSPeter Maydell static const char *imx_epit_reg_name(uint32_t reg) 3495669e69SJean-Christophe DUBOIS { 3595669e69SJean-Christophe DUBOIS switch (reg) { 3695669e69SJean-Christophe DUBOIS case 0: 3795669e69SJean-Christophe DUBOIS return "CR"; 3895669e69SJean-Christophe DUBOIS case 1: 3995669e69SJean-Christophe DUBOIS return "SR"; 4095669e69SJean-Christophe DUBOIS case 2: 4195669e69SJean-Christophe DUBOIS return "LR"; 4295669e69SJean-Christophe DUBOIS case 3: 4395669e69SJean-Christophe DUBOIS return "CMP"; 4495669e69SJean-Christophe DUBOIS case 4: 4595669e69SJean-Christophe DUBOIS return "CNT"; 4695669e69SJean-Christophe DUBOIS default: 4795669e69SJean-Christophe DUBOIS return "[?]"; 4895669e69SJean-Christophe DUBOIS } 4995669e69SJean-Christophe DUBOIS } 5095669e69SJean-Christophe DUBOIS 51a50c0d6fSJean-Christophe DUBOIS /* 52a50c0d6fSJean-Christophe DUBOIS * Exact clock frequencies vary from board to board. 53a50c0d6fSJean-Christophe DUBOIS * These are typical. 54a50c0d6fSJean-Christophe DUBOIS */ 5595669e69SJean-Christophe DUBOIS static const IMXClk imx_epit_clocks[] = { 56c91a5883SJean-Christophe Dubois CLK_NONE, /* 00 disabled */ 57aaa9ec3bSJean-Christophe Dubois CLK_IPG, /* 01 ipg_clk, ~532MHz */ 58d552f675SJean-Christophe Dubois CLK_IPG_HIGH, /* 10 ipg_clk_highfreq */ 59a50c0d6fSJean-Christophe DUBOIS CLK_32k, /* 11 ipg_clk_32k -- ~32kHz */ 60a50c0d6fSJean-Christophe DUBOIS }; 61a50c0d6fSJean-Christophe DUBOIS 62a50c0d6fSJean-Christophe DUBOIS /* 63a50c0d6fSJean-Christophe DUBOIS * Update interrupt status 64a50c0d6fSJean-Christophe DUBOIS */ 6595669e69SJean-Christophe DUBOIS static void imx_epit_update_int(IMXEPITState *s) 66a50c0d6fSJean-Christophe DUBOIS { 6795669e69SJean-Christophe DUBOIS if (s->sr && (s->cr & CR_OCIEN) && (s->cr & CR_EN)) { 68a50c0d6fSJean-Christophe DUBOIS qemu_irq_raise(s->irq); 69a50c0d6fSJean-Christophe DUBOIS } else { 70a50c0d6fSJean-Christophe DUBOIS qemu_irq_lower(s->irq); 71a50c0d6fSJean-Christophe DUBOIS } 72a50c0d6fSJean-Christophe DUBOIS } 73a50c0d6fSJean-Christophe DUBOIS 7495669e69SJean-Christophe DUBOIS static void imx_epit_set_freq(IMXEPITState *s) 75a50c0d6fSJean-Christophe DUBOIS { 7695669e69SJean-Christophe DUBOIS uint32_t clksrc; 7795669e69SJean-Christophe DUBOIS uint32_t prescaler; 78a50c0d6fSJean-Christophe DUBOIS 79a50c0d6fSJean-Christophe DUBOIS clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2); 80a50c0d6fSJean-Christophe DUBOIS prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12); 81a50c0d6fSJean-Christophe DUBOIS 82aaa9ec3bSJean-Christophe Dubois s->freq = imx_ccm_get_clock_frequency(s->ccm, 83aaa9ec3bSJean-Christophe Dubois imx_epit_clocks[clksrc]) / prescaler; 84a50c0d6fSJean-Christophe DUBOIS 85aaa9ec3bSJean-Christophe Dubois DPRINTF("Setting ptimer frequency to %u\n", s->freq); 8695669e69SJean-Christophe DUBOIS 87aaa9ec3bSJean-Christophe Dubois if (s->freq) { 88aaa9ec3bSJean-Christophe Dubois ptimer_set_freq(s->timer_reload, s->freq); 89aaa9ec3bSJean-Christophe Dubois ptimer_set_freq(s->timer_cmp, s->freq); 90a50c0d6fSJean-Christophe DUBOIS } 91a50c0d6fSJean-Christophe DUBOIS } 92a50c0d6fSJean-Christophe DUBOIS 9395669e69SJean-Christophe DUBOIS static void imx_epit_reset(DeviceState *dev) 94a50c0d6fSJean-Christophe DUBOIS { 9595669e69SJean-Christophe DUBOIS IMXEPITState *s = IMX_EPIT(dev); 96a50c0d6fSJean-Christophe DUBOIS 97a50c0d6fSJean-Christophe DUBOIS /* 98a50c0d6fSJean-Christophe DUBOIS * Soft reset doesn't touch some bits; hard reset clears them 99a50c0d6fSJean-Christophe DUBOIS */ 10023005810SPeter Chubb s->cr &= (CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN); 101a50c0d6fSJean-Christophe DUBOIS s->sr = 0; 102203d65a4SMichael Tokarev s->lr = EPIT_TIMER_MAX; 103a50c0d6fSJean-Christophe DUBOIS s->cmp = 0; 104a50c0d6fSJean-Christophe DUBOIS s->cnt = 0; 105a50c0d6fSJean-Christophe DUBOIS /* stop both timers */ 106a50c0d6fSJean-Christophe DUBOIS ptimer_stop(s->timer_cmp); 107a50c0d6fSJean-Christophe DUBOIS ptimer_stop(s->timer_reload); 108a50c0d6fSJean-Christophe DUBOIS /* compute new frequency */ 10995669e69SJean-Christophe DUBOIS imx_epit_set_freq(s); 110203d65a4SMichael Tokarev /* init both timers to EPIT_TIMER_MAX */ 111203d65a4SMichael Tokarev ptimer_set_limit(s->timer_cmp, EPIT_TIMER_MAX, 1); 112203d65a4SMichael Tokarev ptimer_set_limit(s->timer_reload, EPIT_TIMER_MAX, 1); 113a50c0d6fSJean-Christophe DUBOIS if (s->freq && (s->cr & CR_EN)) { 114a50c0d6fSJean-Christophe DUBOIS /* if the timer is still enabled, restart it */ 11523005810SPeter Chubb ptimer_run(s->timer_reload, 0); 116a50c0d6fSJean-Christophe DUBOIS } 117a50c0d6fSJean-Christophe DUBOIS } 118a50c0d6fSJean-Christophe DUBOIS 11995669e69SJean-Christophe DUBOIS static uint32_t imx_epit_update_count(IMXEPITState *s) 120a50c0d6fSJean-Christophe DUBOIS { 121a50c0d6fSJean-Christophe DUBOIS s->cnt = ptimer_get_count(s->timer_reload); 122a50c0d6fSJean-Christophe DUBOIS 123a50c0d6fSJean-Christophe DUBOIS return s->cnt; 124a50c0d6fSJean-Christophe DUBOIS } 125a50c0d6fSJean-Christophe DUBOIS 12695669e69SJean-Christophe DUBOIS static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size) 127a50c0d6fSJean-Christophe DUBOIS { 12895669e69SJean-Christophe DUBOIS IMXEPITState *s = IMX_EPIT(opaque); 12995669e69SJean-Christophe DUBOIS uint32_t reg_value = 0; 130a50c0d6fSJean-Christophe DUBOIS 1314929f656SJean-Christophe Dubois switch (offset >> 2) { 132a50c0d6fSJean-Christophe DUBOIS case 0: /* Control Register */ 13395669e69SJean-Christophe DUBOIS reg_value = s->cr; 13495669e69SJean-Christophe DUBOIS break; 135a50c0d6fSJean-Christophe DUBOIS 136a50c0d6fSJean-Christophe DUBOIS case 1: /* Status Register */ 13795669e69SJean-Christophe DUBOIS reg_value = s->sr; 13895669e69SJean-Christophe DUBOIS break; 139a50c0d6fSJean-Christophe DUBOIS 140a50c0d6fSJean-Christophe DUBOIS case 2: /* LR - ticks*/ 14195669e69SJean-Christophe DUBOIS reg_value = s->lr; 14295669e69SJean-Christophe DUBOIS break; 143a50c0d6fSJean-Christophe DUBOIS 144a50c0d6fSJean-Christophe DUBOIS case 3: /* CMP */ 14595669e69SJean-Christophe DUBOIS reg_value = s->cmp; 14695669e69SJean-Christophe DUBOIS break; 147a50c0d6fSJean-Christophe DUBOIS 148a50c0d6fSJean-Christophe DUBOIS case 4: /* CNT */ 14995669e69SJean-Christophe DUBOIS imx_epit_update_count(s); 15095669e69SJean-Christophe DUBOIS reg_value = s->cnt; 15195669e69SJean-Christophe DUBOIS break; 15295669e69SJean-Christophe DUBOIS 15395669e69SJean-Christophe DUBOIS default: 1544929f656SJean-Christophe Dubois qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" 1554929f656SJean-Christophe Dubois HWADDR_PRIx "\n", TYPE_IMX_EPIT, __func__, offset); 15695669e69SJean-Christophe DUBOIS break; 157a50c0d6fSJean-Christophe DUBOIS } 158a50c0d6fSJean-Christophe DUBOIS 1594929f656SJean-Christophe Dubois DPRINTF("(%s) = 0x%08x\n", imx_epit_reg_name(offset >> 2), reg_value); 16095669e69SJean-Christophe DUBOIS 16195669e69SJean-Christophe DUBOIS return reg_value; 162a50c0d6fSJean-Christophe DUBOIS } 163a50c0d6fSJean-Christophe DUBOIS 16495669e69SJean-Christophe DUBOIS static void imx_epit_reload_compare_timer(IMXEPITState *s) 165a50c0d6fSJean-Christophe DUBOIS { 16623005810SPeter Chubb if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) { 16723005810SPeter Chubb /* if the compare feature is on and timers are running */ 16895669e69SJean-Christophe DUBOIS uint32_t tmp = imx_epit_update_count(s); 16923005810SPeter Chubb uint64_t next; 170a50c0d6fSJean-Christophe DUBOIS if (tmp > s->cmp) { 17123005810SPeter Chubb /* It'll fire in this round of the timer */ 17223005810SPeter Chubb next = tmp - s->cmp; 17323005810SPeter Chubb } else { /* catch it next time around */ 174203d65a4SMichael Tokarev next = tmp - s->cmp + ((s->cr & CR_RLD) ? EPIT_TIMER_MAX : s->lr); 175a50c0d6fSJean-Christophe DUBOIS } 17623005810SPeter Chubb ptimer_set_count(s->timer_cmp, next); 177a50c0d6fSJean-Christophe DUBOIS } 178a50c0d6fSJean-Christophe DUBOIS } 179a50c0d6fSJean-Christophe DUBOIS 18095669e69SJean-Christophe DUBOIS static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value, 18195669e69SJean-Christophe DUBOIS unsigned size) 182a50c0d6fSJean-Christophe DUBOIS { 18395669e69SJean-Christophe DUBOIS IMXEPITState *s = IMX_EPIT(opaque); 18423005810SPeter Chubb uint64_t oldcr; 185a50c0d6fSJean-Christophe DUBOIS 1864929f656SJean-Christophe Dubois DPRINTF("(%s, value = 0x%08x)\n", imx_epit_reg_name(offset >> 2), 1874929f656SJean-Christophe Dubois (uint32_t)value); 18895669e69SJean-Christophe DUBOIS 1894929f656SJean-Christophe Dubois switch (offset >> 2) { 190a50c0d6fSJean-Christophe DUBOIS case 0: /* CR */ 19123005810SPeter Chubb 19223005810SPeter Chubb oldcr = s->cr; 193a50c0d6fSJean-Christophe DUBOIS s->cr = value & 0x03ffffff; 194a50c0d6fSJean-Christophe DUBOIS if (s->cr & CR_SWR) { 195a50c0d6fSJean-Christophe DUBOIS /* handle the reset */ 19695669e69SJean-Christophe DUBOIS imx_epit_reset(DEVICE(s)); 197a50c0d6fSJean-Christophe DUBOIS } else { 19895669e69SJean-Christophe DUBOIS imx_epit_set_freq(s); 199a50c0d6fSJean-Christophe DUBOIS } 200a50c0d6fSJean-Christophe DUBOIS 20123005810SPeter Chubb if (s->freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) { 202a50c0d6fSJean-Christophe DUBOIS if (s->cr & CR_ENMOD) { 203a50c0d6fSJean-Christophe DUBOIS if (s->cr & CR_RLD) { 204a50c0d6fSJean-Christophe DUBOIS ptimer_set_limit(s->timer_reload, s->lr, 1); 20523005810SPeter Chubb ptimer_set_limit(s->timer_cmp, s->lr, 1); 206a50c0d6fSJean-Christophe DUBOIS } else { 207203d65a4SMichael Tokarev ptimer_set_limit(s->timer_reload, EPIT_TIMER_MAX, 1); 208203d65a4SMichael Tokarev ptimer_set_limit(s->timer_cmp, EPIT_TIMER_MAX, 1); 209a50c0d6fSJean-Christophe DUBOIS } 210a50c0d6fSJean-Christophe DUBOIS } 211a50c0d6fSJean-Christophe DUBOIS 21295669e69SJean-Christophe DUBOIS imx_epit_reload_compare_timer(s); 21323005810SPeter Chubb ptimer_run(s->timer_reload, 0); 21423005810SPeter Chubb if (s->cr & CR_OCIEN) { 21523005810SPeter Chubb ptimer_run(s->timer_cmp, 0); 216a50c0d6fSJean-Christophe DUBOIS } else { 21723005810SPeter Chubb ptimer_stop(s->timer_cmp); 21823005810SPeter Chubb } 21923005810SPeter Chubb } else if (!(s->cr & CR_EN)) { 220a50c0d6fSJean-Christophe DUBOIS /* stop both timers */ 221a50c0d6fSJean-Christophe DUBOIS ptimer_stop(s->timer_reload); 222a50c0d6fSJean-Christophe DUBOIS ptimer_stop(s->timer_cmp); 22323005810SPeter Chubb } else if (s->cr & CR_OCIEN) { 22423005810SPeter Chubb if (!(oldcr & CR_OCIEN)) { 22523005810SPeter Chubb imx_epit_reload_compare_timer(s); 22623005810SPeter Chubb ptimer_run(s->timer_cmp, 0); 22723005810SPeter Chubb } 22823005810SPeter Chubb } else { 22923005810SPeter Chubb ptimer_stop(s->timer_cmp); 230a50c0d6fSJean-Christophe DUBOIS } 231a50c0d6fSJean-Christophe DUBOIS break; 232a50c0d6fSJean-Christophe DUBOIS 233a50c0d6fSJean-Christophe DUBOIS case 1: /* SR - ACK*/ 234a50c0d6fSJean-Christophe DUBOIS /* writing 1 to OCIF clear the OCIF bit */ 235a50c0d6fSJean-Christophe DUBOIS if (value & 0x01) { 236a50c0d6fSJean-Christophe DUBOIS s->sr = 0; 23795669e69SJean-Christophe DUBOIS imx_epit_update_int(s); 238a50c0d6fSJean-Christophe DUBOIS } 239a50c0d6fSJean-Christophe DUBOIS break; 240a50c0d6fSJean-Christophe DUBOIS 241a50c0d6fSJean-Christophe DUBOIS case 2: /* LR - set ticks */ 242a50c0d6fSJean-Christophe DUBOIS s->lr = value; 243a50c0d6fSJean-Christophe DUBOIS 244a50c0d6fSJean-Christophe DUBOIS if (s->cr & CR_RLD) { 245a50c0d6fSJean-Christophe DUBOIS /* Also set the limit if the LRD bit is set */ 246a50c0d6fSJean-Christophe DUBOIS /* If IOVW bit is set then set the timer value */ 247a50c0d6fSJean-Christophe DUBOIS ptimer_set_limit(s->timer_reload, s->lr, s->cr & CR_IOVW); 24823005810SPeter Chubb ptimer_set_limit(s->timer_cmp, s->lr, 0); 249a50c0d6fSJean-Christophe DUBOIS } else if (s->cr & CR_IOVW) { 250a50c0d6fSJean-Christophe DUBOIS /* If IOVW bit is set then set the timer value */ 251a50c0d6fSJean-Christophe DUBOIS ptimer_set_count(s->timer_reload, s->lr); 252a50c0d6fSJean-Christophe DUBOIS } 253a50c0d6fSJean-Christophe DUBOIS 25495669e69SJean-Christophe DUBOIS imx_epit_reload_compare_timer(s); 255a50c0d6fSJean-Christophe DUBOIS break; 256a50c0d6fSJean-Christophe DUBOIS 257a50c0d6fSJean-Christophe DUBOIS case 3: /* CMP */ 258a50c0d6fSJean-Christophe DUBOIS s->cmp = value; 259a50c0d6fSJean-Christophe DUBOIS 26095669e69SJean-Christophe DUBOIS imx_epit_reload_compare_timer(s); 261a50c0d6fSJean-Christophe DUBOIS 262a50c0d6fSJean-Christophe DUBOIS break; 263a50c0d6fSJean-Christophe DUBOIS 264a50c0d6fSJean-Christophe DUBOIS default: 2654929f656SJean-Christophe Dubois qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" 2664929f656SJean-Christophe Dubois HWADDR_PRIx "\n", TYPE_IMX_EPIT, __func__, offset); 26795669e69SJean-Christophe DUBOIS 26895669e69SJean-Christophe DUBOIS break; 269a50c0d6fSJean-Christophe DUBOIS } 270a50c0d6fSJean-Christophe DUBOIS } 27195669e69SJean-Christophe DUBOIS static void imx_epit_cmp(void *opaque) 272a50c0d6fSJean-Christophe DUBOIS { 27395669e69SJean-Christophe DUBOIS IMXEPITState *s = IMX_EPIT(opaque); 274a50c0d6fSJean-Christophe DUBOIS 27523005810SPeter Chubb DPRINTF("sr was %d\n", s->sr); 276a50c0d6fSJean-Christophe DUBOIS 277a50c0d6fSJean-Christophe DUBOIS s->sr = 1; 27895669e69SJean-Christophe DUBOIS imx_epit_update_int(s); 279a50c0d6fSJean-Christophe DUBOIS } 280a50c0d6fSJean-Christophe DUBOIS 28195669e69SJean-Christophe DUBOIS static const MemoryRegionOps imx_epit_ops = { 28295669e69SJean-Christophe DUBOIS .read = imx_epit_read, 28395669e69SJean-Christophe DUBOIS .write = imx_epit_write, 284a50c0d6fSJean-Christophe DUBOIS .endianness = DEVICE_NATIVE_ENDIAN, 285a50c0d6fSJean-Christophe DUBOIS }; 286a50c0d6fSJean-Christophe DUBOIS 28795669e69SJean-Christophe DUBOIS static const VMStateDescription vmstate_imx_timer_epit = { 288565328fcSJean-Christophe Dubois .name = TYPE_IMX_EPIT, 289a50c0d6fSJean-Christophe DUBOIS .version_id = 2, 290a50c0d6fSJean-Christophe DUBOIS .minimum_version_id = 2, 291a50c0d6fSJean-Christophe DUBOIS .fields = (VMStateField[]) { 29295669e69SJean-Christophe DUBOIS VMSTATE_UINT32(cr, IMXEPITState), 29395669e69SJean-Christophe DUBOIS VMSTATE_UINT32(sr, IMXEPITState), 29495669e69SJean-Christophe DUBOIS VMSTATE_UINT32(lr, IMXEPITState), 29595669e69SJean-Christophe DUBOIS VMSTATE_UINT32(cmp, IMXEPITState), 29695669e69SJean-Christophe DUBOIS VMSTATE_UINT32(cnt, IMXEPITState), 29795669e69SJean-Christophe DUBOIS VMSTATE_UINT32(freq, IMXEPITState), 29895669e69SJean-Christophe DUBOIS VMSTATE_PTIMER(timer_reload, IMXEPITState), 29995669e69SJean-Christophe DUBOIS VMSTATE_PTIMER(timer_cmp, IMXEPITState), 300a50c0d6fSJean-Christophe DUBOIS VMSTATE_END_OF_LIST() 301a50c0d6fSJean-Christophe DUBOIS } 302a50c0d6fSJean-Christophe DUBOIS }; 303a50c0d6fSJean-Christophe DUBOIS 30495669e69SJean-Christophe DUBOIS static void imx_epit_realize(DeviceState *dev, Error **errp) 305a50c0d6fSJean-Christophe DUBOIS { 30695669e69SJean-Christophe DUBOIS IMXEPITState *s = IMX_EPIT(dev); 30795669e69SJean-Christophe DUBOIS SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 308a50c0d6fSJean-Christophe DUBOIS QEMUBH *bh; 309a50c0d6fSJean-Christophe DUBOIS 31095669e69SJean-Christophe DUBOIS DPRINTF("\n"); 311a50c0d6fSJean-Christophe DUBOIS 31295669e69SJean-Christophe DUBOIS sysbus_init_irq(sbd, &s->irq); 313853dca12SPaolo Bonzini memory_region_init_io(&s->iomem, OBJECT(s), &imx_epit_ops, s, TYPE_IMX_EPIT, 31495669e69SJean-Christophe DUBOIS 0x00001000); 31595669e69SJean-Christophe DUBOIS sysbus_init_mmio(sbd, &s->iomem); 31695669e69SJean-Christophe DUBOIS 317e7ea81c3SDmitry Osipenko s->timer_reload = ptimer_init(NULL, PTIMER_POLICY_DEFAULT); 318a50c0d6fSJean-Christophe DUBOIS 31995669e69SJean-Christophe DUBOIS bh = qemu_bh_new(imx_epit_cmp, s); 320e7ea81c3SDmitry Osipenko s->timer_cmp = ptimer_init(bh, PTIMER_POLICY_DEFAULT); 321a50c0d6fSJean-Christophe DUBOIS } 322a50c0d6fSJean-Christophe DUBOIS 32395669e69SJean-Christophe DUBOIS static void imx_epit_class_init(ObjectClass *klass, void *data) 324a50c0d6fSJean-Christophe DUBOIS { 325a50c0d6fSJean-Christophe DUBOIS DeviceClass *dc = DEVICE_CLASS(klass); 32695669e69SJean-Christophe DUBOIS 32795669e69SJean-Christophe DUBOIS dc->realize = imx_epit_realize; 32895669e69SJean-Christophe DUBOIS dc->reset = imx_epit_reset; 32995669e69SJean-Christophe DUBOIS dc->vmsd = &vmstate_imx_timer_epit; 330a50c0d6fSJean-Christophe DUBOIS dc->desc = "i.MX periodic timer"; 331a50c0d6fSJean-Christophe DUBOIS } 332a50c0d6fSJean-Christophe DUBOIS 33395669e69SJean-Christophe DUBOIS static const TypeInfo imx_epit_info = { 33495669e69SJean-Christophe DUBOIS .name = TYPE_IMX_EPIT, 335a50c0d6fSJean-Christophe DUBOIS .parent = TYPE_SYS_BUS_DEVICE, 33695669e69SJean-Christophe DUBOIS .instance_size = sizeof(IMXEPITState), 33795669e69SJean-Christophe DUBOIS .class_init = imx_epit_class_init, 338a50c0d6fSJean-Christophe DUBOIS }; 339a50c0d6fSJean-Christophe DUBOIS 34095669e69SJean-Christophe DUBOIS static void imx_epit_register_types(void) 341a50c0d6fSJean-Christophe DUBOIS { 34295669e69SJean-Christophe DUBOIS type_register_static(&imx_epit_info); 343a50c0d6fSJean-Christophe DUBOIS } 344a50c0d6fSJean-Christophe DUBOIS 34595669e69SJean-Christophe DUBOIS type_init(imx_epit_register_types) 346