xref: /openbmc/qemu/hw/timer/arm_mptimer.c (revision 28ae3179fc52d2e4d870b635c4a412aab99759e7)
13bd88451SPaolo Bonzini /*
23bd88451SPaolo Bonzini  * Private peripheral timer/watchdog blocks for ARM 11MPCore and A9MP
33bd88451SPaolo Bonzini  *
43bd88451SPaolo Bonzini  * Copyright (c) 2006-2007 CodeSourcery.
53bd88451SPaolo Bonzini  * Copyright (c) 2011 Linaro Limited
63bd88451SPaolo Bonzini  * Written by Paul Brook, Peter Maydell
73bd88451SPaolo Bonzini  *
83bd88451SPaolo Bonzini  * This program is free software; you can redistribute it and/or
93bd88451SPaolo Bonzini  * modify it under the terms of the GNU General Public License
103bd88451SPaolo Bonzini  * as published by the Free Software Foundation; either version
113bd88451SPaolo Bonzini  * 2 of the License, or (at your option) any later version.
123bd88451SPaolo Bonzini  *
133bd88451SPaolo Bonzini  * This program is distributed in the hope that it will be useful,
143bd88451SPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
153bd88451SPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
163bd88451SPaolo Bonzini  * GNU General Public License for more details.
173bd88451SPaolo Bonzini  *
183bd88451SPaolo Bonzini  * You should have received a copy of the GNU General Public License along
193bd88451SPaolo Bonzini  * with this program; if not, see <http://www.gnu.org/licenses/>.
203bd88451SPaolo Bonzini  */
213bd88451SPaolo Bonzini 
228ef94f0bSPeter Maydell #include "qemu/osdep.h"
23650d103dSMarkus Armbruster #include "hw/hw.h"
2464552b6bSMarkus Armbruster #include "hw/irq.h"
25226fb5aaSDmitry Osipenko #include "hw/ptimer.h"
26a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
27eb110bd8SAndreas Färber #include "hw/timer/arm_mptimer.h"
28d6454270SMarkus Armbruster #include "migration/vmstate.h"
29da34e65cSMarkus Armbruster #include "qapi/error.h"
300b8fa32fSMarkus Armbruster #include "qemu/module.h"
312e5b09fdSMarkus Armbruster #include "hw/core/cpu.h"
323bd88451SPaolo Bonzini 
33226fb5aaSDmitry Osipenko #define PTIMER_POLICY                       \
34226fb5aaSDmitry Osipenko     (PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |  \
35226fb5aaSDmitry Osipenko      PTIMER_POLICY_CONTINUOUS_TRIGGER    |  \
36226fb5aaSDmitry Osipenko      PTIMER_POLICY_NO_IMMEDIATE_TRIGGER  |  \
37226fb5aaSDmitry Osipenko      PTIMER_POLICY_NO_IMMEDIATE_RELOAD   |  \
38226fb5aaSDmitry Osipenko      PTIMER_POLICY_NO_COUNTER_ROUND_DOWN)
39226fb5aaSDmitry Osipenko 
403bd88451SPaolo Bonzini /* This device implements the per-cpu private timer and watchdog block
413bd88451SPaolo Bonzini  * which is used in both the ARM11MPCore and Cortex-A9MP.
423bd88451SPaolo Bonzini  */
433bd88451SPaolo Bonzini 
get_current_cpu(ARMMPTimerState * s)443bd88451SPaolo Bonzini static inline int get_current_cpu(ARMMPTimerState *s)
453bd88451SPaolo Bonzini {
46226fb5aaSDmitry Osipenko     int cpu_id = current_cpu ? current_cpu->cpu_index : 0;
47226fb5aaSDmitry Osipenko 
48226fb5aaSDmitry Osipenko     if (cpu_id >= s->num_cpu) {
493bd88451SPaolo Bonzini         hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n",
50226fb5aaSDmitry Osipenko                  s->num_cpu, cpu_id);
513bd88451SPaolo Bonzini     }
52226fb5aaSDmitry Osipenko 
53226fb5aaSDmitry Osipenko     return cpu_id;
543bd88451SPaolo Bonzini }
553bd88451SPaolo Bonzini 
timerblock_update_irq(TimerBlock * tb)563bd88451SPaolo Bonzini static inline void timerblock_update_irq(TimerBlock *tb)
573bd88451SPaolo Bonzini {
58257621a9SDmitry Osipenko     qemu_set_irq(tb->irq, tb->status && (tb->control & 4));
593bd88451SPaolo Bonzini }
603bd88451SPaolo Bonzini 
613bd88451SPaolo Bonzini /* Return conversion factor from mpcore timer ticks to qemu timer ticks.  */
timerblock_scale(uint32_t control)62226fb5aaSDmitry Osipenko static inline uint32_t timerblock_scale(uint32_t control)
633bd88451SPaolo Bonzini {
64226fb5aaSDmitry Osipenko     return (((control >> 8) & 0xff) + 1) * 10;
653bd88451SPaolo Bonzini }
663bd88451SPaolo Bonzini 
67581b0880SPeter Maydell /* Must be called within a ptimer transaction block */
timerblock_set_count(struct ptimer_state * timer,uint32_t control,uint64_t * count)68226fb5aaSDmitry Osipenko static inline void timerblock_set_count(struct ptimer_state *timer,
69226fb5aaSDmitry Osipenko                                         uint32_t control, uint64_t *count)
703bd88451SPaolo Bonzini {
71226fb5aaSDmitry Osipenko     /* PTimer would trigger interrupt for periodic timer when counter set
72226fb5aaSDmitry Osipenko      * to 0, MPtimer under certain condition only.
73226fb5aaSDmitry Osipenko      */
74226fb5aaSDmitry Osipenko     if ((control & 3) == 3 && (control & 0xff00) == 0 && *count == 0) {
75226fb5aaSDmitry Osipenko         *count = ptimer_get_limit(timer);
763bd88451SPaolo Bonzini     }
77226fb5aaSDmitry Osipenko     ptimer_set_count(timer, *count);
783bd88451SPaolo Bonzini }
79226fb5aaSDmitry Osipenko 
80581b0880SPeter Maydell /* Must be called within a ptimer transaction block */
timerblock_run(struct ptimer_state * timer,uint32_t control,uint32_t load)81226fb5aaSDmitry Osipenko static inline void timerblock_run(struct ptimer_state *timer,
82226fb5aaSDmitry Osipenko                                   uint32_t control, uint32_t load)
83226fb5aaSDmitry Osipenko {
84226fb5aaSDmitry Osipenko     if ((control & 1) && ((control & 0xff00) || load != 0)) {
85226fb5aaSDmitry Osipenko         ptimer_run(timer, !(control & 2));
86226fb5aaSDmitry Osipenko     }
873bd88451SPaolo Bonzini }
883bd88451SPaolo Bonzini 
timerblock_tick(void * opaque)893bd88451SPaolo Bonzini static void timerblock_tick(void *opaque)
903bd88451SPaolo Bonzini {
913bd88451SPaolo Bonzini     TimerBlock *tb = (TimerBlock *)opaque;
92226fb5aaSDmitry Osipenko     /* Periodic timer with load = 0 and prescaler != 0 would re-trigger
93226fb5aaSDmitry Osipenko      * IRQ after one period, otherwise it either stops or wraps around.
94226fb5aaSDmitry Osipenko      */
95226fb5aaSDmitry Osipenko     if ((tb->control & 2) && (tb->control & 0xff00) == 0 &&
96226fb5aaSDmitry Osipenko             ptimer_get_limit(tb->timer) == 0) {
97226fb5aaSDmitry Osipenko         ptimer_stop(tb->timer);
983bd88451SPaolo Bonzini     }
99226fb5aaSDmitry Osipenko     tb->status = 1;
1003bd88451SPaolo Bonzini     timerblock_update_irq(tb);
1013bd88451SPaolo Bonzini }
1023bd88451SPaolo Bonzini 
timerblock_read(void * opaque,hwaddr addr,unsigned size)1033bd88451SPaolo Bonzini static uint64_t timerblock_read(void *opaque, hwaddr addr,
1043bd88451SPaolo Bonzini                                 unsigned size)
1053bd88451SPaolo Bonzini {
1063bd88451SPaolo Bonzini     TimerBlock *tb = (TimerBlock *)opaque;
1073bd88451SPaolo Bonzini     switch (addr) {
1083bd88451SPaolo Bonzini     case 0: /* Load */
109226fb5aaSDmitry Osipenko         return ptimer_get_limit(tb->timer);
1103bd88451SPaolo Bonzini     case 4: /* Counter.  */
111226fb5aaSDmitry Osipenko         return ptimer_get_count(tb->timer);
1123bd88451SPaolo Bonzini     case 8: /* Control.  */
1133bd88451SPaolo Bonzini         return tb->control;
1143bd88451SPaolo Bonzini     case 12: /* Interrupt status.  */
1153bd88451SPaolo Bonzini         return tb->status;
1163bd88451SPaolo Bonzini     default:
1173bd88451SPaolo Bonzini         return 0;
1183bd88451SPaolo Bonzini     }
1193bd88451SPaolo Bonzini }
1203bd88451SPaolo Bonzini 
timerblock_write(void * opaque,hwaddr addr,uint64_t value,unsigned size)1213bd88451SPaolo Bonzini static void timerblock_write(void *opaque, hwaddr addr,
1223bd88451SPaolo Bonzini                              uint64_t value, unsigned size)
1233bd88451SPaolo Bonzini {
1243bd88451SPaolo Bonzini     TimerBlock *tb = (TimerBlock *)opaque;
125226fb5aaSDmitry Osipenko     uint32_t control = tb->control;
1263bd88451SPaolo Bonzini     switch (addr) {
1273bd88451SPaolo Bonzini     case 0: /* Load */
128581b0880SPeter Maydell         ptimer_transaction_begin(tb->timer);
129226fb5aaSDmitry Osipenko         /* Setting load to 0 stops the timer without doing the tick if
130226fb5aaSDmitry Osipenko          * prescaler = 0.
131226fb5aaSDmitry Osipenko          */
132226fb5aaSDmitry Osipenko         if ((control & 1) && (control & 0xff00) == 0 && value == 0) {
133226fb5aaSDmitry Osipenko             ptimer_stop(tb->timer);
134226fb5aaSDmitry Osipenko         }
135226fb5aaSDmitry Osipenko         ptimer_set_limit(tb->timer, value, 1);
136226fb5aaSDmitry Osipenko         timerblock_run(tb->timer, control, value);
137581b0880SPeter Maydell         ptimer_transaction_commit(tb->timer);
138226fb5aaSDmitry Osipenko         break;
1393bd88451SPaolo Bonzini     case 4: /* Counter.  */
140581b0880SPeter Maydell         ptimer_transaction_begin(tb->timer);
141226fb5aaSDmitry Osipenko         /* Setting counter to 0 stops the one-shot timer, or periodic with
142226fb5aaSDmitry Osipenko          * load = 0, without doing the tick if prescaler = 0.
143226fb5aaSDmitry Osipenko          */
144226fb5aaSDmitry Osipenko         if ((control & 1) && (control & 0xff00) == 0 && value == 0 &&
145226fb5aaSDmitry Osipenko                 (!(control & 2) || ptimer_get_limit(tb->timer) == 0)) {
146226fb5aaSDmitry Osipenko             ptimer_stop(tb->timer);
1473bd88451SPaolo Bonzini         }
148226fb5aaSDmitry Osipenko         timerblock_set_count(tb->timer, control, &value);
149226fb5aaSDmitry Osipenko         timerblock_run(tb->timer, control, value);
150581b0880SPeter Maydell         ptimer_transaction_commit(tb->timer);
1513bd88451SPaolo Bonzini         break;
1523bd88451SPaolo Bonzini     case 8: /* Control.  */
153581b0880SPeter Maydell         ptimer_transaction_begin(tb->timer);
154226fb5aaSDmitry Osipenko         if ((control & 3) != (value & 3)) {
155226fb5aaSDmitry Osipenko             ptimer_stop(tb->timer);
156226fb5aaSDmitry Osipenko         }
157226fb5aaSDmitry Osipenko         if ((control & 0xff00) != (value & 0xff00)) {
158226fb5aaSDmitry Osipenko             ptimer_set_period(tb->timer, timerblock_scale(value));
159226fb5aaSDmitry Osipenko         }
1608a52340cSDmitry Osipenko         if (value & 1) {
161226fb5aaSDmitry Osipenko             uint64_t count = ptimer_get_count(tb->timer);
162226fb5aaSDmitry Osipenko             /* Re-load periodic timer counter if needed.  */
163226fb5aaSDmitry Osipenko             if ((value & 2) && count == 0) {
164226fb5aaSDmitry Osipenko                 timerblock_set_count(tb->timer, value, &count);
1658a52340cSDmitry Osipenko             }
166226fb5aaSDmitry Osipenko             timerblock_run(tb->timer, value, count);
1673bd88451SPaolo Bonzini         }
168226fb5aaSDmitry Osipenko         tb->control = value;
169581b0880SPeter Maydell         ptimer_transaction_commit(tb->timer);
1703bd88451SPaolo Bonzini         break;
1713bd88451SPaolo Bonzini     case 12: /* Interrupt status.  */
1723bd88451SPaolo Bonzini         tb->status &= ~value;
1733bd88451SPaolo Bonzini         timerblock_update_irq(tb);
1743bd88451SPaolo Bonzini         break;
1753bd88451SPaolo Bonzini     }
1763bd88451SPaolo Bonzini }
1773bd88451SPaolo Bonzini 
1783bd88451SPaolo Bonzini /* Wrapper functions to implement the "read timer/watchdog for
1793bd88451SPaolo Bonzini  * the current CPU" memory regions.
1803bd88451SPaolo Bonzini  */
arm_thistimer_read(void * opaque,hwaddr addr,unsigned size)1813bd88451SPaolo Bonzini static uint64_t arm_thistimer_read(void *opaque, hwaddr addr,
1823bd88451SPaolo Bonzini                                    unsigned size)
1833bd88451SPaolo Bonzini {
1843bd88451SPaolo Bonzini     ARMMPTimerState *s = (ARMMPTimerState *)opaque;
1853bd88451SPaolo Bonzini     int id = get_current_cpu(s);
1863bd88451SPaolo Bonzini     return timerblock_read(&s->timerblock[id], addr, size);
1873bd88451SPaolo Bonzini }
1883bd88451SPaolo Bonzini 
arm_thistimer_write(void * opaque,hwaddr addr,uint64_t value,unsigned size)1893bd88451SPaolo Bonzini static void arm_thistimer_write(void *opaque, hwaddr addr,
1903bd88451SPaolo Bonzini                                 uint64_t value, unsigned size)
1913bd88451SPaolo Bonzini {
1923bd88451SPaolo Bonzini     ARMMPTimerState *s = (ARMMPTimerState *)opaque;
1933bd88451SPaolo Bonzini     int id = get_current_cpu(s);
1943bd88451SPaolo Bonzini     timerblock_write(&s->timerblock[id], addr, value, size);
1953bd88451SPaolo Bonzini }
1963bd88451SPaolo Bonzini 
1973bd88451SPaolo Bonzini static const MemoryRegionOps arm_thistimer_ops = {
1983bd88451SPaolo Bonzini     .read = arm_thistimer_read,
1993bd88451SPaolo Bonzini     .write = arm_thistimer_write,
2003bd88451SPaolo Bonzini     .valid = {
2013bd88451SPaolo Bonzini         .min_access_size = 4,
2023bd88451SPaolo Bonzini         .max_access_size = 4,
2033bd88451SPaolo Bonzini     },
2043bd88451SPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
2053bd88451SPaolo Bonzini };
2063bd88451SPaolo Bonzini 
2073bd88451SPaolo Bonzini static const MemoryRegionOps timerblock_ops = {
2083bd88451SPaolo Bonzini     .read = timerblock_read,
2093bd88451SPaolo Bonzini     .write = timerblock_write,
2103bd88451SPaolo Bonzini     .valid = {
2113bd88451SPaolo Bonzini         .min_access_size = 4,
2123bd88451SPaolo Bonzini         .max_access_size = 4,
2133bd88451SPaolo Bonzini     },
2143bd88451SPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
2153bd88451SPaolo Bonzini };
2163bd88451SPaolo Bonzini 
timerblock_reset(TimerBlock * tb)2173bd88451SPaolo Bonzini static void timerblock_reset(TimerBlock *tb)
2183bd88451SPaolo Bonzini {
2193bd88451SPaolo Bonzini     tb->control = 0;
2203bd88451SPaolo Bonzini     tb->status = 0;
2213bd88451SPaolo Bonzini     if (tb->timer) {
222581b0880SPeter Maydell         ptimer_transaction_begin(tb->timer);
223226fb5aaSDmitry Osipenko         ptimer_stop(tb->timer);
224226fb5aaSDmitry Osipenko         ptimer_set_limit(tb->timer, 0, 1);
225226fb5aaSDmitry Osipenko         ptimer_set_period(tb->timer, timerblock_scale(0));
226581b0880SPeter Maydell         ptimer_transaction_commit(tb->timer);
2273bd88451SPaolo Bonzini     }
2283bd88451SPaolo Bonzini }
2293bd88451SPaolo Bonzini 
arm_mptimer_reset(DeviceState * dev)2303bd88451SPaolo Bonzini static void arm_mptimer_reset(DeviceState *dev)
2313bd88451SPaolo Bonzini {
23268653fd6SAndreas Färber     ARMMPTimerState *s = ARM_MPTIMER(dev);
2333bd88451SPaolo Bonzini     int i;
23468653fd6SAndreas Färber 
2353bd88451SPaolo Bonzini     for (i = 0; i < ARRAY_SIZE(s->timerblock); i++) {
2363bd88451SPaolo Bonzini         timerblock_reset(&s->timerblock[i]);
2373bd88451SPaolo Bonzini     }
2383bd88451SPaolo Bonzini }
2393bd88451SPaolo Bonzini 
arm_mptimer_init(Object * obj)240a1f9a907SPeter Maydell static void arm_mptimer_init(Object *obj)
2413bd88451SPaolo Bonzini {
2420aadb490SAndreas Färber     ARMMPTimerState *s = ARM_MPTIMER(obj);
2430aadb490SAndreas Färber 
2440aadb490SAndreas Färber     memory_region_init_io(&s->iomem, obj, &arm_thistimer_ops, s,
2450aadb490SAndreas Färber                           "arm_mptimer_timer", 0x20);
2460aadb490SAndreas Färber     sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
2470aadb490SAndreas Färber }
2480aadb490SAndreas Färber 
arm_mptimer_realize(DeviceState * dev,Error ** errp)2490aadb490SAndreas Färber static void arm_mptimer_realize(DeviceState *dev, Error **errp)
2500aadb490SAndreas Färber {
2510aadb490SAndreas Färber     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
25268653fd6SAndreas Färber     ARMMPTimerState *s = ARM_MPTIMER(dev);
2533bd88451SPaolo Bonzini     int i;
25468653fd6SAndreas Färber 
255eb110bd8SAndreas Färber     if (s->num_cpu < 1 || s->num_cpu > ARM_MPTIMER_MAX_CPUS) {
256b097e481SMarkus Armbruster         error_setg(errp, "num-cpu must be between 1 and %d",
257b097e481SMarkus Armbruster                    ARM_MPTIMER_MAX_CPUS);
258b097e481SMarkus Armbruster         return;
2593bd88451SPaolo Bonzini     }
2603bd88451SPaolo Bonzini     /* We implement one timer block per CPU, and expose multiple MMIO regions:
2613bd88451SPaolo Bonzini      *  * region 0 is "timer for this core"
2623bd88451SPaolo Bonzini      *  * region 1 is "timer for core 0"
2633bd88451SPaolo Bonzini      *  * region 2 is "timer for core 1"
2643bd88451SPaolo Bonzini      * and so on.
2653bd88451SPaolo Bonzini      * The outgoing interrupt lines are
2663bd88451SPaolo Bonzini      *  * timer for core 0
2673bd88451SPaolo Bonzini      *  * timer for core 1
2683bd88451SPaolo Bonzini      * and so on.
2693bd88451SPaolo Bonzini      */
2703bd88451SPaolo Bonzini     for (i = 0; i < s->num_cpu; i++) {
2713bd88451SPaolo Bonzini         TimerBlock *tb = &s->timerblock[i];
272581b0880SPeter Maydell         tb->timer = ptimer_init(timerblock_tick, tb, PTIMER_POLICY);
2730aadb490SAndreas Färber         sysbus_init_irq(sbd, &tb->irq);
274853dca12SPaolo Bonzini         memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
2753bd88451SPaolo Bonzini                               "arm_mptimer_timerblock", 0x20);
2760aadb490SAndreas Färber         sysbus_init_mmio(sbd, &tb->iomem);
2773bd88451SPaolo Bonzini     }
2783bd88451SPaolo Bonzini }
2793bd88451SPaolo Bonzini 
2803bd88451SPaolo Bonzini static const VMStateDescription vmstate_timerblock = {
2813bd88451SPaolo Bonzini     .name = "arm_mptimer_timerblock",
282226fb5aaSDmitry Osipenko     .version_id = 3,
283226fb5aaSDmitry Osipenko     .minimum_version_id = 3,
284ba324b3fSRichard Henderson     .fields = (const VMStateField[]) {
2853bd88451SPaolo Bonzini         VMSTATE_UINT32(control, TimerBlock),
2863bd88451SPaolo Bonzini         VMSTATE_UINT32(status, TimerBlock),
287226fb5aaSDmitry Osipenko         VMSTATE_PTIMER(timer, TimerBlock),
2883bd88451SPaolo Bonzini         VMSTATE_END_OF_LIST()
2893bd88451SPaolo Bonzini     }
2903bd88451SPaolo Bonzini };
2913bd88451SPaolo Bonzini 
2923bd88451SPaolo Bonzini static const VMStateDescription vmstate_arm_mptimer = {
2933bd88451SPaolo Bonzini     .name = "arm_mptimer",
294226fb5aaSDmitry Osipenko     .version_id = 3,
295226fb5aaSDmitry Osipenko     .minimum_version_id = 3,
296ba324b3fSRichard Henderson     .fields = (const VMStateField[]) {
2973bd88451SPaolo Bonzini         VMSTATE_STRUCT_VARRAY_UINT32(timerblock, ARMMPTimerState, num_cpu,
298226fb5aaSDmitry Osipenko                                      3, vmstate_timerblock, TimerBlock),
2993bd88451SPaolo Bonzini         VMSTATE_END_OF_LIST()
3003bd88451SPaolo Bonzini     }
3013bd88451SPaolo Bonzini };
3023bd88451SPaolo Bonzini 
3033bd88451SPaolo Bonzini static Property arm_mptimer_properties[] = {
3043bd88451SPaolo Bonzini     DEFINE_PROP_UINT32("num-cpu", ARMMPTimerState, num_cpu, 0),
3053bd88451SPaolo Bonzini     DEFINE_PROP_END_OF_LIST()
3063bd88451SPaolo Bonzini };
3073bd88451SPaolo Bonzini 
arm_mptimer_class_init(ObjectClass * klass,void * data)3083bd88451SPaolo Bonzini static void arm_mptimer_class_init(ObjectClass *klass, void *data)
3093bd88451SPaolo Bonzini {
3103bd88451SPaolo Bonzini     DeviceClass *dc = DEVICE_CLASS(klass);
3113bd88451SPaolo Bonzini 
3120aadb490SAndreas Färber     dc->realize = arm_mptimer_realize;
3133bd88451SPaolo Bonzini     dc->vmsd = &vmstate_arm_mptimer;
314*e3d08143SPeter Maydell     device_class_set_legacy_reset(dc, arm_mptimer_reset);
3154f67d30bSMarc-André Lureau     device_class_set_props(dc, arm_mptimer_properties);
3163bd88451SPaolo Bonzini }
3173bd88451SPaolo Bonzini 
3183bd88451SPaolo Bonzini static const TypeInfo arm_mptimer_info = {
31968653fd6SAndreas Färber     .name          = TYPE_ARM_MPTIMER,
3203bd88451SPaolo Bonzini     .parent        = TYPE_SYS_BUS_DEVICE,
3213bd88451SPaolo Bonzini     .instance_size = sizeof(ARMMPTimerState),
322a1f9a907SPeter Maydell     .instance_init = arm_mptimer_init,
3233bd88451SPaolo Bonzini     .class_init    = arm_mptimer_class_init,
3243bd88451SPaolo Bonzini };
3253bd88451SPaolo Bonzini 
arm_mptimer_register_types(void)3263bd88451SPaolo Bonzini static void arm_mptimer_register_types(void)
3273bd88451SPaolo Bonzini {
3283bd88451SPaolo Bonzini     type_register_static(&arm_mptimer_info);
3293bd88451SPaolo Bonzini }
3303bd88451SPaolo Bonzini 
3313bd88451SPaolo Bonzini type_init(arm_mptimer_register_types)
332