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 15a50c0d6fSJean-Christophe DUBOIS #include "hw/arm/imx.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" 19a50c0d6fSJean-Christophe DUBOIS 2095669e69SJean-Christophe DUBOIS #define DEBUG_TIMER 0 2195669e69SJean-Christophe DUBOIS #if DEBUG_TIMER 2295669e69SJean-Christophe DUBOIS 2395669e69SJean-Christophe DUBOIS static char const *imx_epit_reg_name(uint32_t reg) 2495669e69SJean-Christophe DUBOIS { 2595669e69SJean-Christophe DUBOIS switch (reg) { 2695669e69SJean-Christophe DUBOIS case 0: 2795669e69SJean-Christophe DUBOIS return "CR"; 2895669e69SJean-Christophe DUBOIS case 1: 2995669e69SJean-Christophe DUBOIS return "SR"; 3095669e69SJean-Christophe DUBOIS case 2: 3195669e69SJean-Christophe DUBOIS return "LR"; 3295669e69SJean-Christophe DUBOIS case 3: 3395669e69SJean-Christophe DUBOIS return "CMP"; 3495669e69SJean-Christophe DUBOIS case 4: 3595669e69SJean-Christophe DUBOIS return "CNT"; 3695669e69SJean-Christophe DUBOIS default: 3795669e69SJean-Christophe DUBOIS return "[?]"; 3895669e69SJean-Christophe DUBOIS } 3995669e69SJean-Christophe DUBOIS } 4095669e69SJean-Christophe DUBOIS 41a50c0d6fSJean-Christophe DUBOIS # define DPRINTF(fmt, args...) \ 4223005810SPeter Chubb do { fprintf(stderr, "%s: " fmt , __func__, ##args); } while (0) 43a50c0d6fSJean-Christophe DUBOIS #else 44a50c0d6fSJean-Christophe DUBOIS # define DPRINTF(fmt, args...) do {} while (0) 45a50c0d6fSJean-Christophe DUBOIS #endif 46a50c0d6fSJean-Christophe DUBOIS 47a50c0d6fSJean-Christophe DUBOIS /* 48a50c0d6fSJean-Christophe DUBOIS * Define to 1 for messages about attempts to 49a50c0d6fSJean-Christophe DUBOIS * access unimplemented registers or similar. 50a50c0d6fSJean-Christophe DUBOIS */ 51a50c0d6fSJean-Christophe DUBOIS #define DEBUG_IMPLEMENTATION 1 52a50c0d6fSJean-Christophe DUBOIS #if DEBUG_IMPLEMENTATION 53a50c0d6fSJean-Christophe DUBOIS # define IPRINTF(fmt, args...) \ 5495669e69SJean-Christophe DUBOIS do { fprintf(stderr, "%s: " fmt, __func__, ##args); } while (0) 55a50c0d6fSJean-Christophe DUBOIS #else 56a50c0d6fSJean-Christophe DUBOIS # define IPRINTF(fmt, args...) do {} while (0) 57a50c0d6fSJean-Christophe DUBOIS #endif 58a50c0d6fSJean-Christophe DUBOIS 59a50c0d6fSJean-Christophe DUBOIS /* 60a50c0d6fSJean-Christophe DUBOIS * Exact clock frequencies vary from board to board. 61a50c0d6fSJean-Christophe DUBOIS * These are typical. 62a50c0d6fSJean-Christophe DUBOIS */ 6395669e69SJean-Christophe DUBOIS static const IMXClk imx_epit_clocks[] = { 64a50c0d6fSJean-Christophe DUBOIS 0, /* 00 disabled */ 65a50c0d6fSJean-Christophe DUBOIS IPG, /* 01 ipg_clk, ~532MHz */ 66a50c0d6fSJean-Christophe DUBOIS IPG, /* 10 ipg_clk_highfreq */ 67a50c0d6fSJean-Christophe DUBOIS CLK_32k, /* 11 ipg_clk_32k -- ~32kHz */ 68a50c0d6fSJean-Christophe DUBOIS }; 69a50c0d6fSJean-Christophe DUBOIS 70a50c0d6fSJean-Christophe DUBOIS /* 71a50c0d6fSJean-Christophe DUBOIS * Update interrupt status 72a50c0d6fSJean-Christophe DUBOIS */ 7395669e69SJean-Christophe DUBOIS static void imx_epit_update_int(IMXEPITState *s) 74a50c0d6fSJean-Christophe DUBOIS { 7595669e69SJean-Christophe DUBOIS if (s->sr && (s->cr & CR_OCIEN) && (s->cr & CR_EN)) { 76a50c0d6fSJean-Christophe DUBOIS qemu_irq_raise(s->irq); 77a50c0d6fSJean-Christophe DUBOIS } else { 78a50c0d6fSJean-Christophe DUBOIS qemu_irq_lower(s->irq); 79a50c0d6fSJean-Christophe DUBOIS } 80a50c0d6fSJean-Christophe DUBOIS } 81a50c0d6fSJean-Christophe DUBOIS 8295669e69SJean-Christophe DUBOIS static void imx_epit_set_freq(IMXEPITState *s) 83a50c0d6fSJean-Christophe DUBOIS { 8495669e69SJean-Christophe DUBOIS uint32_t clksrc; 8595669e69SJean-Christophe DUBOIS uint32_t prescaler; 86a50c0d6fSJean-Christophe DUBOIS uint32_t freq; 87a50c0d6fSJean-Christophe DUBOIS 88a50c0d6fSJean-Christophe DUBOIS clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2); 89a50c0d6fSJean-Christophe DUBOIS prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12); 90a50c0d6fSJean-Christophe DUBOIS 9195669e69SJean-Christophe DUBOIS freq = imx_clock_frequency(s->ccm, imx_epit_clocks[clksrc]) / prescaler; 92a50c0d6fSJean-Christophe DUBOIS 93a50c0d6fSJean-Christophe DUBOIS s->freq = freq; 9495669e69SJean-Christophe DUBOIS 95a50c0d6fSJean-Christophe DUBOIS DPRINTF("Setting ptimer frequency to %u\n", freq); 96a50c0d6fSJean-Christophe DUBOIS 97a50c0d6fSJean-Christophe DUBOIS if (freq) { 98a50c0d6fSJean-Christophe DUBOIS ptimer_set_freq(s->timer_reload, freq); 99a50c0d6fSJean-Christophe DUBOIS ptimer_set_freq(s->timer_cmp, freq); 100a50c0d6fSJean-Christophe DUBOIS } 101a50c0d6fSJean-Christophe DUBOIS } 102a50c0d6fSJean-Christophe DUBOIS 10395669e69SJean-Christophe DUBOIS static void imx_epit_reset(DeviceState *dev) 104a50c0d6fSJean-Christophe DUBOIS { 10595669e69SJean-Christophe DUBOIS IMXEPITState *s = IMX_EPIT(dev); 106a50c0d6fSJean-Christophe DUBOIS 107a50c0d6fSJean-Christophe DUBOIS /* 108a50c0d6fSJean-Christophe DUBOIS * Soft reset doesn't touch some bits; hard reset clears them 109a50c0d6fSJean-Christophe DUBOIS */ 11023005810SPeter Chubb s->cr &= (CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN); 111a50c0d6fSJean-Christophe DUBOIS s->sr = 0; 112203d65a4SMichael Tokarev s->lr = EPIT_TIMER_MAX; 113a50c0d6fSJean-Christophe DUBOIS s->cmp = 0; 114a50c0d6fSJean-Christophe DUBOIS s->cnt = 0; 115a50c0d6fSJean-Christophe DUBOIS /* stop both timers */ 116a50c0d6fSJean-Christophe DUBOIS ptimer_stop(s->timer_cmp); 117a50c0d6fSJean-Christophe DUBOIS ptimer_stop(s->timer_reload); 118a50c0d6fSJean-Christophe DUBOIS /* compute new frequency */ 11995669e69SJean-Christophe DUBOIS imx_epit_set_freq(s); 120203d65a4SMichael Tokarev /* init both timers to EPIT_TIMER_MAX */ 121203d65a4SMichael Tokarev ptimer_set_limit(s->timer_cmp, EPIT_TIMER_MAX, 1); 122203d65a4SMichael Tokarev ptimer_set_limit(s->timer_reload, EPIT_TIMER_MAX, 1); 123a50c0d6fSJean-Christophe DUBOIS if (s->freq && (s->cr & CR_EN)) { 124a50c0d6fSJean-Christophe DUBOIS /* if the timer is still enabled, restart it */ 12523005810SPeter Chubb ptimer_run(s->timer_reload, 0); 126a50c0d6fSJean-Christophe DUBOIS } 127a50c0d6fSJean-Christophe DUBOIS } 128a50c0d6fSJean-Christophe DUBOIS 12995669e69SJean-Christophe DUBOIS static uint32_t imx_epit_update_count(IMXEPITState *s) 130a50c0d6fSJean-Christophe DUBOIS { 131a50c0d6fSJean-Christophe DUBOIS s->cnt = ptimer_get_count(s->timer_reload); 132a50c0d6fSJean-Christophe DUBOIS 133a50c0d6fSJean-Christophe DUBOIS return s->cnt; 134a50c0d6fSJean-Christophe DUBOIS } 135a50c0d6fSJean-Christophe DUBOIS 13695669e69SJean-Christophe DUBOIS static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size) 137a50c0d6fSJean-Christophe DUBOIS { 13895669e69SJean-Christophe DUBOIS IMXEPITState *s = IMX_EPIT(opaque); 13995669e69SJean-Christophe DUBOIS uint32_t reg_value = 0; 14095669e69SJean-Christophe DUBOIS uint32_t reg = offset >> 2; 141a50c0d6fSJean-Christophe DUBOIS 14295669e69SJean-Christophe DUBOIS switch (reg) { 143a50c0d6fSJean-Christophe DUBOIS case 0: /* Control Register */ 14495669e69SJean-Christophe DUBOIS reg_value = s->cr; 14595669e69SJean-Christophe DUBOIS break; 146a50c0d6fSJean-Christophe DUBOIS 147a50c0d6fSJean-Christophe DUBOIS case 1: /* Status Register */ 14895669e69SJean-Christophe DUBOIS reg_value = s->sr; 14995669e69SJean-Christophe DUBOIS break; 150a50c0d6fSJean-Christophe DUBOIS 151a50c0d6fSJean-Christophe DUBOIS case 2: /* LR - ticks*/ 15295669e69SJean-Christophe DUBOIS reg_value = s->lr; 15395669e69SJean-Christophe DUBOIS break; 154a50c0d6fSJean-Christophe DUBOIS 155a50c0d6fSJean-Christophe DUBOIS case 3: /* CMP */ 15695669e69SJean-Christophe DUBOIS reg_value = s->cmp; 15795669e69SJean-Christophe DUBOIS break; 158a50c0d6fSJean-Christophe DUBOIS 159a50c0d6fSJean-Christophe DUBOIS case 4: /* CNT */ 16095669e69SJean-Christophe DUBOIS imx_epit_update_count(s); 16195669e69SJean-Christophe DUBOIS reg_value = s->cnt; 16295669e69SJean-Christophe DUBOIS break; 16395669e69SJean-Christophe DUBOIS 16495669e69SJean-Christophe DUBOIS default: 16595669e69SJean-Christophe DUBOIS IPRINTF("Bad offset %x\n", reg); 16695669e69SJean-Christophe DUBOIS break; 167a50c0d6fSJean-Christophe DUBOIS } 168a50c0d6fSJean-Christophe DUBOIS 16995669e69SJean-Christophe DUBOIS DPRINTF("(%s) = 0x%08x\n", imx_epit_reg_name(reg), reg_value); 17095669e69SJean-Christophe DUBOIS 17195669e69SJean-Christophe DUBOIS return reg_value; 172a50c0d6fSJean-Christophe DUBOIS } 173a50c0d6fSJean-Christophe DUBOIS 17495669e69SJean-Christophe DUBOIS static void imx_epit_reload_compare_timer(IMXEPITState *s) 175a50c0d6fSJean-Christophe DUBOIS { 17623005810SPeter Chubb if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) { 17723005810SPeter Chubb /* if the compare feature is on and timers are running */ 17895669e69SJean-Christophe DUBOIS uint32_t tmp = imx_epit_update_count(s); 17923005810SPeter Chubb uint64_t next; 180a50c0d6fSJean-Christophe DUBOIS if (tmp > s->cmp) { 18123005810SPeter Chubb /* It'll fire in this round of the timer */ 18223005810SPeter Chubb next = tmp - s->cmp; 18323005810SPeter Chubb } else { /* catch it next time around */ 184203d65a4SMichael Tokarev next = tmp - s->cmp + ((s->cr & CR_RLD) ? EPIT_TIMER_MAX : s->lr); 185a50c0d6fSJean-Christophe DUBOIS } 18623005810SPeter Chubb ptimer_set_count(s->timer_cmp, next); 187a50c0d6fSJean-Christophe DUBOIS } 188a50c0d6fSJean-Christophe DUBOIS } 189a50c0d6fSJean-Christophe DUBOIS 19095669e69SJean-Christophe DUBOIS static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value, 19195669e69SJean-Christophe DUBOIS unsigned size) 192a50c0d6fSJean-Christophe DUBOIS { 19395669e69SJean-Christophe DUBOIS IMXEPITState *s = IMX_EPIT(opaque); 19495669e69SJean-Christophe DUBOIS uint32_t reg = offset >> 2; 19523005810SPeter Chubb uint64_t oldcr; 196a50c0d6fSJean-Christophe DUBOIS 19795669e69SJean-Christophe DUBOIS DPRINTF("(%s, value = 0x%08x)\n", imx_epit_reg_name(reg), (uint32_t)value); 19895669e69SJean-Christophe DUBOIS 19995669e69SJean-Christophe DUBOIS switch (reg) { 200a50c0d6fSJean-Christophe DUBOIS case 0: /* CR */ 20123005810SPeter Chubb 20223005810SPeter Chubb oldcr = s->cr; 203a50c0d6fSJean-Christophe DUBOIS s->cr = value & 0x03ffffff; 204a50c0d6fSJean-Christophe DUBOIS if (s->cr & CR_SWR) { 205a50c0d6fSJean-Christophe DUBOIS /* handle the reset */ 20695669e69SJean-Christophe DUBOIS imx_epit_reset(DEVICE(s)); 207a50c0d6fSJean-Christophe DUBOIS } else { 20895669e69SJean-Christophe DUBOIS imx_epit_set_freq(s); 209a50c0d6fSJean-Christophe DUBOIS } 210a50c0d6fSJean-Christophe DUBOIS 21123005810SPeter Chubb if (s->freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) { 212a50c0d6fSJean-Christophe DUBOIS if (s->cr & CR_ENMOD) { 213a50c0d6fSJean-Christophe DUBOIS if (s->cr & CR_RLD) { 214a50c0d6fSJean-Christophe DUBOIS ptimer_set_limit(s->timer_reload, s->lr, 1); 21523005810SPeter Chubb ptimer_set_limit(s->timer_cmp, s->lr, 1); 216a50c0d6fSJean-Christophe DUBOIS } else { 217203d65a4SMichael Tokarev ptimer_set_limit(s->timer_reload, EPIT_TIMER_MAX, 1); 218203d65a4SMichael Tokarev ptimer_set_limit(s->timer_cmp, EPIT_TIMER_MAX, 1); 219a50c0d6fSJean-Christophe DUBOIS } 220a50c0d6fSJean-Christophe DUBOIS } 221a50c0d6fSJean-Christophe DUBOIS 22295669e69SJean-Christophe DUBOIS imx_epit_reload_compare_timer(s); 22323005810SPeter Chubb ptimer_run(s->timer_reload, 0); 22423005810SPeter Chubb if (s->cr & CR_OCIEN) { 22523005810SPeter Chubb ptimer_run(s->timer_cmp, 0); 226a50c0d6fSJean-Christophe DUBOIS } else { 22723005810SPeter Chubb ptimer_stop(s->timer_cmp); 22823005810SPeter Chubb } 22923005810SPeter Chubb } else if (!(s->cr & CR_EN)) { 230a50c0d6fSJean-Christophe DUBOIS /* stop both timers */ 231a50c0d6fSJean-Christophe DUBOIS ptimer_stop(s->timer_reload); 232a50c0d6fSJean-Christophe DUBOIS ptimer_stop(s->timer_cmp); 23323005810SPeter Chubb } else if (s->cr & CR_OCIEN) { 23423005810SPeter Chubb if (!(oldcr & CR_OCIEN)) { 23523005810SPeter Chubb imx_epit_reload_compare_timer(s); 23623005810SPeter Chubb ptimer_run(s->timer_cmp, 0); 23723005810SPeter Chubb } 23823005810SPeter Chubb } else { 23923005810SPeter Chubb ptimer_stop(s->timer_cmp); 240a50c0d6fSJean-Christophe DUBOIS } 241a50c0d6fSJean-Christophe DUBOIS break; 242a50c0d6fSJean-Christophe DUBOIS 243a50c0d6fSJean-Christophe DUBOIS case 1: /* SR - ACK*/ 244a50c0d6fSJean-Christophe DUBOIS /* writing 1 to OCIF clear the OCIF bit */ 245a50c0d6fSJean-Christophe DUBOIS if (value & 0x01) { 246a50c0d6fSJean-Christophe DUBOIS s->sr = 0; 24795669e69SJean-Christophe DUBOIS imx_epit_update_int(s); 248a50c0d6fSJean-Christophe DUBOIS } 249a50c0d6fSJean-Christophe DUBOIS break; 250a50c0d6fSJean-Christophe DUBOIS 251a50c0d6fSJean-Christophe DUBOIS case 2: /* LR - set ticks */ 252a50c0d6fSJean-Christophe DUBOIS s->lr = value; 253a50c0d6fSJean-Christophe DUBOIS 254a50c0d6fSJean-Christophe DUBOIS if (s->cr & CR_RLD) { 255a50c0d6fSJean-Christophe DUBOIS /* Also set the limit if the LRD bit is set */ 256a50c0d6fSJean-Christophe DUBOIS /* If IOVW bit is set then set the timer value */ 257a50c0d6fSJean-Christophe DUBOIS ptimer_set_limit(s->timer_reload, s->lr, s->cr & CR_IOVW); 25823005810SPeter Chubb ptimer_set_limit(s->timer_cmp, s->lr, 0); 259a50c0d6fSJean-Christophe DUBOIS } else if (s->cr & CR_IOVW) { 260a50c0d6fSJean-Christophe DUBOIS /* If IOVW bit is set then set the timer value */ 261a50c0d6fSJean-Christophe DUBOIS ptimer_set_count(s->timer_reload, s->lr); 262a50c0d6fSJean-Christophe DUBOIS } 263a50c0d6fSJean-Christophe DUBOIS 26495669e69SJean-Christophe DUBOIS imx_epit_reload_compare_timer(s); 265a50c0d6fSJean-Christophe DUBOIS break; 266a50c0d6fSJean-Christophe DUBOIS 267a50c0d6fSJean-Christophe DUBOIS case 3: /* CMP */ 268a50c0d6fSJean-Christophe DUBOIS s->cmp = value; 269a50c0d6fSJean-Christophe DUBOIS 27095669e69SJean-Christophe DUBOIS imx_epit_reload_compare_timer(s); 271a50c0d6fSJean-Christophe DUBOIS 272a50c0d6fSJean-Christophe DUBOIS break; 273a50c0d6fSJean-Christophe DUBOIS 274a50c0d6fSJean-Christophe DUBOIS default: 27595669e69SJean-Christophe DUBOIS IPRINTF("Bad offset %x\n", reg); 27695669e69SJean-Christophe DUBOIS 27795669e69SJean-Christophe DUBOIS break; 278a50c0d6fSJean-Christophe DUBOIS } 279a50c0d6fSJean-Christophe DUBOIS } 28095669e69SJean-Christophe DUBOIS static void imx_epit_cmp(void *opaque) 281a50c0d6fSJean-Christophe DUBOIS { 28295669e69SJean-Christophe DUBOIS IMXEPITState *s = IMX_EPIT(opaque); 283a50c0d6fSJean-Christophe DUBOIS 28423005810SPeter Chubb DPRINTF("sr was %d\n", s->sr); 285a50c0d6fSJean-Christophe DUBOIS 286a50c0d6fSJean-Christophe DUBOIS s->sr = 1; 28795669e69SJean-Christophe DUBOIS imx_epit_update_int(s); 288a50c0d6fSJean-Christophe DUBOIS } 289a50c0d6fSJean-Christophe DUBOIS 29095669e69SJean-Christophe DUBOIS void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm) 291a50c0d6fSJean-Christophe DUBOIS { 29295669e69SJean-Christophe DUBOIS IMXEPITState *pp; 293a50c0d6fSJean-Christophe DUBOIS DeviceState *dev; 294a50c0d6fSJean-Christophe DUBOIS 29595669e69SJean-Christophe DUBOIS dev = sysbus_create_simple(TYPE_IMX_EPIT, addr, irq); 29695669e69SJean-Christophe DUBOIS pp = IMX_EPIT(dev); 297a50c0d6fSJean-Christophe DUBOIS pp->ccm = ccm; 298a50c0d6fSJean-Christophe DUBOIS } 299a50c0d6fSJean-Christophe DUBOIS 30095669e69SJean-Christophe DUBOIS static const MemoryRegionOps imx_epit_ops = { 30195669e69SJean-Christophe DUBOIS .read = imx_epit_read, 30295669e69SJean-Christophe DUBOIS .write = imx_epit_write, 303a50c0d6fSJean-Christophe DUBOIS .endianness = DEVICE_NATIVE_ENDIAN, 304a50c0d6fSJean-Christophe DUBOIS }; 305a50c0d6fSJean-Christophe DUBOIS 30695669e69SJean-Christophe DUBOIS static const VMStateDescription vmstate_imx_timer_epit = { 307*565328fcSJean-Christophe Dubois .name = TYPE_IMX_EPIT, 308a50c0d6fSJean-Christophe DUBOIS .version_id = 2, 309a50c0d6fSJean-Christophe DUBOIS .minimum_version_id = 2, 310a50c0d6fSJean-Christophe DUBOIS .fields = (VMStateField[]) { 31195669e69SJean-Christophe DUBOIS VMSTATE_UINT32(cr, IMXEPITState), 31295669e69SJean-Christophe DUBOIS VMSTATE_UINT32(sr, IMXEPITState), 31395669e69SJean-Christophe DUBOIS VMSTATE_UINT32(lr, IMXEPITState), 31495669e69SJean-Christophe DUBOIS VMSTATE_UINT32(cmp, IMXEPITState), 31595669e69SJean-Christophe DUBOIS VMSTATE_UINT32(cnt, IMXEPITState), 31695669e69SJean-Christophe DUBOIS VMSTATE_UINT32(freq, IMXEPITState), 31795669e69SJean-Christophe DUBOIS VMSTATE_PTIMER(timer_reload, IMXEPITState), 31895669e69SJean-Christophe DUBOIS VMSTATE_PTIMER(timer_cmp, IMXEPITState), 319a50c0d6fSJean-Christophe DUBOIS VMSTATE_END_OF_LIST() 320a50c0d6fSJean-Christophe DUBOIS } 321a50c0d6fSJean-Christophe DUBOIS }; 322a50c0d6fSJean-Christophe DUBOIS 32395669e69SJean-Christophe DUBOIS static void imx_epit_realize(DeviceState *dev, Error **errp) 324a50c0d6fSJean-Christophe DUBOIS { 32595669e69SJean-Christophe DUBOIS IMXEPITState *s = IMX_EPIT(dev); 32695669e69SJean-Christophe DUBOIS SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 327a50c0d6fSJean-Christophe DUBOIS QEMUBH *bh; 328a50c0d6fSJean-Christophe DUBOIS 32995669e69SJean-Christophe DUBOIS DPRINTF("\n"); 330a50c0d6fSJean-Christophe DUBOIS 33195669e69SJean-Christophe DUBOIS sysbus_init_irq(sbd, &s->irq); 332853dca12SPaolo Bonzini memory_region_init_io(&s->iomem, OBJECT(s), &imx_epit_ops, s, TYPE_IMX_EPIT, 33395669e69SJean-Christophe DUBOIS 0x00001000); 33495669e69SJean-Christophe DUBOIS sysbus_init_mmio(sbd, &s->iomem); 33595669e69SJean-Christophe DUBOIS 33623005810SPeter Chubb s->timer_reload = ptimer_init(NULL); 337a50c0d6fSJean-Christophe DUBOIS 33895669e69SJean-Christophe DUBOIS bh = qemu_bh_new(imx_epit_cmp, s); 339a50c0d6fSJean-Christophe DUBOIS s->timer_cmp = ptimer_init(bh); 340a50c0d6fSJean-Christophe DUBOIS } 341a50c0d6fSJean-Christophe DUBOIS 34295669e69SJean-Christophe DUBOIS static void imx_epit_class_init(ObjectClass *klass, void *data) 343a50c0d6fSJean-Christophe DUBOIS { 344a50c0d6fSJean-Christophe DUBOIS DeviceClass *dc = DEVICE_CLASS(klass); 34595669e69SJean-Christophe DUBOIS 34695669e69SJean-Christophe DUBOIS dc->realize = imx_epit_realize; 34795669e69SJean-Christophe DUBOIS dc->reset = imx_epit_reset; 34895669e69SJean-Christophe DUBOIS dc->vmsd = &vmstate_imx_timer_epit; 349a50c0d6fSJean-Christophe DUBOIS dc->desc = "i.MX periodic timer"; 350a50c0d6fSJean-Christophe DUBOIS } 351a50c0d6fSJean-Christophe DUBOIS 35295669e69SJean-Christophe DUBOIS static const TypeInfo imx_epit_info = { 35395669e69SJean-Christophe DUBOIS .name = TYPE_IMX_EPIT, 354a50c0d6fSJean-Christophe DUBOIS .parent = TYPE_SYS_BUS_DEVICE, 35595669e69SJean-Christophe DUBOIS .instance_size = sizeof(IMXEPITState), 35695669e69SJean-Christophe DUBOIS .class_init = imx_epit_class_init, 357a50c0d6fSJean-Christophe DUBOIS }; 358a50c0d6fSJean-Christophe DUBOIS 35995669e69SJean-Christophe DUBOIS static void imx_epit_register_types(void) 360a50c0d6fSJean-Christophe DUBOIS { 36195669e69SJean-Christophe DUBOIS type_register_static(&imx_epit_info); 362a50c0d6fSJean-Christophe DUBOIS } 363a50c0d6fSJean-Christophe DUBOIS 36495669e69SJean-Christophe DUBOIS type_init(imx_epit_register_types) 365