Annotation of qemu/hw/arm_timer.c, revision 1.1.1.12

1.1.1.3   root        1: /*
1.1       root        2:  * ARM PrimeCell Timer modules.
                      3:  *
                      4:  * Copyright (c) 2005-2006 CodeSourcery.
                      5:  * Written by Paul Brook
                      6:  *
1.1.1.10  root        7:  * This code is licensed under the GPL.
1.1       root        8:  */
                      9: 
1.1.1.5   root       10: #include "sysbus.h"
1.1.1.3   root       11: #include "qemu-timer.h"
1.1.1.12! root       12: #include "qemu-common.h"
        !            13: #include "qdev.h"
        !            14: #include "ptimer.h"
1.1       root       15: 
                     16: /* Common timer implementation.  */
                     17: 
                     18: #define TIMER_CTRL_ONESHOT      (1 << 0)
                     19: #define TIMER_CTRL_32BIT        (1 << 1)
                     20: #define TIMER_CTRL_DIV1         (0 << 2)
                     21: #define TIMER_CTRL_DIV16        (1 << 2)
                     22: #define TIMER_CTRL_DIV256       (2 << 2)
                     23: #define TIMER_CTRL_IE           (1 << 5)
                     24: #define TIMER_CTRL_PERIODIC     (1 << 6)
                     25: #define TIMER_CTRL_ENABLE       (1 << 7)
                     26: 
                     27: typedef struct {
1.1.1.3   root       28:     ptimer_state *timer;
1.1       root       29:     uint32_t control;
                     30:     uint32_t limit;
                     31:     int freq;
                     32:     int int_level;
1.1.1.3   root       33:     qemu_irq irq;
1.1       root       34: } arm_timer_state;
                     35: 
                     36: /* Check all active timers, and schedule the next timer interrupt.  */
                     37: 
1.1.1.3   root       38: static void arm_timer_update(arm_timer_state *s)
1.1       root       39: {
                     40:     /* Update interrupts.  */
                     41:     if (s->int_level && (s->control & TIMER_CTRL_IE)) {
1.1.1.3   root       42:         qemu_irq_raise(s->irq);
1.1       root       43:     } else {
1.1.1.3   root       44:         qemu_irq_lower(s->irq);
1.1       root       45:     }
                     46: }
                     47: 
1.1.1.3   root       48: static uint32_t arm_timer_read(void *opaque, target_phys_addr_t offset)
1.1       root       49: {
                     50:     arm_timer_state *s = (arm_timer_state *)opaque;
                     51: 
                     52:     switch (offset >> 2) {
                     53:     case 0: /* TimerLoad */
                     54:     case 6: /* TimerBGLoad */
                     55:         return s->limit;
                     56:     case 1: /* TimerValue */
1.1.1.3   root       57:         return ptimer_get_count(s->timer);
1.1       root       58:     case 2: /* TimerControl */
                     59:         return s->control;
                     60:     case 4: /* TimerRIS */
                     61:         return s->int_level;
                     62:     case 5: /* TimerMIS */
                     63:         if ((s->control & TIMER_CTRL_IE) == 0)
                     64:             return 0;
                     65:         return s->int_level;
                     66:     default:
1.1.1.12! root       67:         hw_error("%s: Bad offset %x\n", __func__, (int)offset);
1.1       root       68:         return 0;
                     69:     }
                     70: }
                     71: 
1.1.1.3   root       72: /* Reset the timer limit after settings have changed.  */
                     73: static void arm_timer_recalibrate(arm_timer_state *s, int reload)
                     74: {
                     75:     uint32_t limit;
                     76: 
1.1.1.7   root       77:     if ((s->control & (TIMER_CTRL_PERIODIC | TIMER_CTRL_ONESHOT)) == 0) {
1.1.1.3   root       78:         /* Free running.  */
                     79:         if (s->control & TIMER_CTRL_32BIT)
                     80:             limit = 0xffffffff;
                     81:         else
                     82:             limit = 0xffff;
                     83:     } else {
                     84:           /* Periodic.  */
                     85:           limit = s->limit;
                     86:     }
                     87:     ptimer_set_limit(s->timer, limit, reload);
                     88: }
                     89: 
1.1       root       90: static void arm_timer_write(void *opaque, target_phys_addr_t offset,
                     91:                             uint32_t value)
                     92: {
                     93:     arm_timer_state *s = (arm_timer_state *)opaque;
1.1.1.3   root       94:     int freq;
1.1       root       95: 
                     96:     switch (offset >> 2) {
                     97:     case 0: /* TimerLoad */
                     98:         s->limit = value;
1.1.1.3   root       99:         arm_timer_recalibrate(s, 1);
1.1       root      100:         break;
                    101:     case 1: /* TimerValue */
                    102:         /* ??? Linux seems to want to write to this readonly register.
                    103:            Ignore it.  */
                    104:         break;
                    105:     case 2: /* TimerControl */
                    106:         if (s->control & TIMER_CTRL_ENABLE) {
                    107:             /* Pause the timer if it is running.  This may cause some
                    108:                inaccuracy dure to rounding, but avoids a whole lot of other
                    109:                messyness.  */
1.1.1.3   root      110:             ptimer_stop(s->timer);
1.1       root      111:         }
                    112:         s->control = value;
1.1.1.3   root      113:         freq = s->freq;
1.1       root      114:         /* ??? Need to recalculate expiry time after changing divisor.  */
                    115:         switch ((value >> 2) & 3) {
1.1.1.3   root      116:         case 1: freq >>= 4; break;
                    117:         case 2: freq >>= 8; break;
1.1       root      118:         }
1.1.1.7   root      119:         arm_timer_recalibrate(s, s->control & TIMER_CTRL_ENABLE);
1.1.1.3   root      120:         ptimer_set_freq(s->timer, freq);
1.1       root      121:         if (s->control & TIMER_CTRL_ENABLE) {
                    122:             /* Restart the timer if still enabled.  */
1.1.1.3   root      123:             ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
1.1       root      124:         }
                    125:         break;
                    126:     case 3: /* TimerIntClr */
                    127:         s->int_level = 0;
                    128:         break;
                    129:     case 6: /* TimerBGLoad */
                    130:         s->limit = value;
1.1.1.3   root      131:         arm_timer_recalibrate(s, 0);
1.1       root      132:         break;
                    133:     default:
1.1.1.12! root      134:         hw_error("%s: Bad offset %x\n", __func__, (int)offset);
1.1       root      135:     }
1.1.1.3   root      136:     arm_timer_update(s);
1.1       root      137: }
                    138: 
                    139: static void arm_timer_tick(void *opaque)
                    140: {
1.1.1.3   root      141:     arm_timer_state *s = (arm_timer_state *)opaque;
                    142:     s->int_level = 1;
                    143:     arm_timer_update(s);
1.1       root      144: }
                    145: 
1.1.1.10  root      146: static const VMStateDescription vmstate_arm_timer = {
                    147:     .name = "arm_timer",
                    148:     .version_id = 1,
                    149:     .minimum_version_id = 1,
                    150:     .minimum_version_id_old = 1,
                    151:     .fields      = (VMStateField[]) {
                    152:         VMSTATE_UINT32(control, arm_timer_state),
                    153:         VMSTATE_UINT32(limit, arm_timer_state),
                    154:         VMSTATE_INT32(int_level, arm_timer_state),
                    155:         VMSTATE_PTIMER(timer, arm_timer_state),
                    156:         VMSTATE_END_OF_LIST()
                    157:     }
                    158: };
1.1.1.4   root      159: 
1.1.1.5   root      160: static arm_timer_state *arm_timer_init(uint32_t freq)
1.1       root      161: {
                    162:     arm_timer_state *s;
1.1.1.3   root      163:     QEMUBH *bh;
1.1       root      164: 
1.1.1.11  root      165:     s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
1.1.1.3   root      166:     s->freq = freq;
1.1       root      167:     s->control = TIMER_CTRL_IE;
                    168: 
1.1.1.3   root      169:     bh = qemu_bh_new(arm_timer_tick, s);
                    170:     s->timer = ptimer_init(bh);
1.1.1.10  root      171:     vmstate_register(NULL, -1, &vmstate_arm_timer, s);
1.1       root      172:     return s;
                    173: }
                    174: 
                    175: /* ARM PrimeCell SP804 dual timer module.
1.1.1.12! root      176:  * Docs at
        !           177:  * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html
        !           178: */
1.1       root      179: 
                    180: typedef struct {
1.1.1.5   root      181:     SysBusDevice busdev;
1.1.1.11  root      182:     MemoryRegion iomem;
1.1.1.5   root      183:     arm_timer_state *timer[2];
1.1.1.12! root      184:     uint32_t freq0, freq1;
1.1       root      185:     int level[2];
1.1.1.3   root      186:     qemu_irq irq;
1.1       root      187: } sp804_state;
                    188: 
1.1.1.12! root      189: static const uint8_t sp804_ids[] = {
        !           190:     /* Timer ID */
        !           191:     0x04, 0x18, 0x14, 0,
        !           192:     /* PrimeCell ID */
        !           193:     0xd, 0xf0, 0x05, 0xb1
        !           194: };
        !           195: 
1.1.1.3   root      196: /* Merge the IRQs from the two component devices.  */
1.1       root      197: static void sp804_set_irq(void *opaque, int irq, int level)
                    198: {
                    199:     sp804_state *s = (sp804_state *)opaque;
                    200: 
                    201:     s->level[irq] = level;
1.1.1.3   root      202:     qemu_set_irq(s->irq, s->level[0] || s->level[1]);
1.1       root      203: }
                    204: 
1.1.1.11  root      205: static uint64_t sp804_read(void *opaque, target_phys_addr_t offset,
                    206:                            unsigned size)
1.1       root      207: {
                    208:     sp804_state *s = (sp804_state *)opaque;
                    209: 
                    210:     if (offset < 0x20) {
                    211:         return arm_timer_read(s->timer[0], offset);
1.1.1.12! root      212:     }
        !           213:     if (offset < 0x40) {
1.1       root      214:         return arm_timer_read(s->timer[1], offset - 0x20);
                    215:     }
1.1.1.12! root      216: 
        !           217:     /* TimerPeriphID */
        !           218:     if (offset >= 0xfe0 && offset <= 0xffc) {
        !           219:         return sp804_ids[(offset - 0xfe0) >> 2];
        !           220:     }
        !           221: 
        !           222:     switch (offset) {
        !           223:     /* Integration Test control registers, which we won't support */
        !           224:     case 0xf00: /* TimerITCR */
        !           225:     case 0xf04: /* TimerITOP (strictly write only but..) */
        !           226:         return 0;
        !           227:     }
        !           228: 
        !           229:     hw_error("%s: Bad offset %x\n", __func__, (int)offset);
        !           230:     return 0;
1.1       root      231: }
                    232: 
                    233: static void sp804_write(void *opaque, target_phys_addr_t offset,
1.1.1.11  root      234:                         uint64_t value, unsigned size)
1.1       root      235: {
                    236:     sp804_state *s = (sp804_state *)opaque;
                    237: 
                    238:     if (offset < 0x20) {
                    239:         arm_timer_write(s->timer[0], offset, value);
1.1.1.12! root      240:         return;
        !           241:     }
        !           242: 
        !           243:     if (offset < 0x40) {
1.1       root      244:         arm_timer_write(s->timer[1], offset - 0x20, value);
1.1.1.12! root      245:         return;
1.1       root      246:     }
1.1.1.12! root      247: 
        !           248:     /* Technically we could be writing to the Test Registers, but not likely */
        !           249:     hw_error("%s: Bad offset %x\n", __func__, (int)offset);
1.1       root      250: }
                    251: 
1.1.1.11  root      252: static const MemoryRegionOps sp804_ops = {
                    253:     .read = sp804_read,
                    254:     .write = sp804_write,
                    255:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1       root      256: };
                    257: 
1.1.1.10  root      258: static const VMStateDescription vmstate_sp804 = {
                    259:     .name = "sp804",
                    260:     .version_id = 1,
                    261:     .minimum_version_id = 1,
                    262:     .minimum_version_id_old = 1,
                    263:     .fields      = (VMStateField[]) {
                    264:         VMSTATE_INT32_ARRAY(level, sp804_state, 2),
                    265:         VMSTATE_END_OF_LIST()
                    266:     }
                    267: };
1.1.1.4   root      268: 
1.1.1.6   root      269: static int sp804_init(SysBusDevice *dev)
1.1       root      270: {
1.1.1.5   root      271:     sp804_state *s = FROM_SYSBUS(sp804_state, dev);
1.1.1.3   root      272:     qemu_irq *qi;
1.1       root      273: 
1.1.1.3   root      274:     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
1.1.1.5   root      275:     sysbus_init_irq(dev, &s->irq);
1.1.1.12! root      276:     s->timer[0] = arm_timer_init(s->freq0);
        !           277:     s->timer[1] = arm_timer_init(s->freq1);
1.1.1.5   root      278:     s->timer[0]->irq = qi[0];
                    279:     s->timer[1]->irq = qi[1];
1.1.1.11  root      280:     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
1.1.1.12! root      281:     sysbus_init_mmio(dev, &s->iomem);
1.1.1.10  root      282:     vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
1.1.1.6   root      283:     return 0;
1.1       root      284: }
                    285: 
                    286: /* Integrator/CP timer module.  */
                    287: 
                    288: typedef struct {
1.1.1.5   root      289:     SysBusDevice busdev;
1.1.1.11  root      290:     MemoryRegion iomem;
1.1.1.5   root      291:     arm_timer_state *timer[3];
1.1       root      292: } icp_pit_state;
                    293: 
1.1.1.11  root      294: static uint64_t icp_pit_read(void *opaque, target_phys_addr_t offset,
                    295:                              unsigned size)
1.1       root      296: {
                    297:     icp_pit_state *s = (icp_pit_state *)opaque;
                    298:     int n;
                    299: 
                    300:     /* ??? Don't know the PrimeCell ID for this device.  */
                    301:     n = offset >> 8;
1.1.1.11  root      302:     if (n > 2) {
1.1.1.12! root      303:         hw_error("%s: Bad timer %d\n", __func__, n);
1.1.1.5   root      304:     }
1.1       root      305: 
                    306:     return arm_timer_read(s->timer[n], offset & 0xff);
                    307: }
                    308: 
                    309: static void icp_pit_write(void *opaque, target_phys_addr_t offset,
1.1.1.11  root      310:                           uint64_t value, unsigned size)
1.1       root      311: {
                    312:     icp_pit_state *s = (icp_pit_state *)opaque;
                    313:     int n;
                    314: 
                    315:     n = offset >> 8;
1.1.1.11  root      316:     if (n > 2) {
1.1.1.12! root      317:         hw_error("%s: Bad timer %d\n", __func__, n);
1.1.1.5   root      318:     }
1.1       root      319: 
                    320:     arm_timer_write(s->timer[n], offset & 0xff, value);
                    321: }
                    322: 
1.1.1.11  root      323: static const MemoryRegionOps icp_pit_ops = {
                    324:     .read = icp_pit_read,
                    325:     .write = icp_pit_write,
                    326:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1       root      327: };
                    328: 
1.1.1.6   root      329: static int icp_pit_init(SysBusDevice *dev)
1.1       root      330: {
1.1.1.5   root      331:     icp_pit_state *s = FROM_SYSBUS(icp_pit_state, dev);
1.1       root      332: 
                    333:     /* Timer 0 runs at the system clock speed (40MHz).  */
1.1.1.5   root      334:     s->timer[0] = arm_timer_init(40000000);
1.1       root      335:     /* The other two timers run at 1MHz.  */
1.1.1.5   root      336:     s->timer[1] = arm_timer_init(1000000);
                    337:     s->timer[2] = arm_timer_init(1000000);
1.1       root      338: 
1.1.1.5   root      339:     sysbus_init_irq(dev, &s->timer[0]->irq);
                    340:     sysbus_init_irq(dev, &s->timer[1]->irq);
                    341:     sysbus_init_irq(dev, &s->timer[2]->irq);
                    342: 
1.1.1.11  root      343:     memory_region_init_io(&s->iomem, &icp_pit_ops, s, "icp_pit", 0x1000);
1.1.1.12! root      344:     sysbus_init_mmio(dev, &s->iomem);
1.1.1.4   root      345:     /* This device has no state to save/restore.  The component timers will
                    346:        save themselves.  */
1.1.1.6   root      347:     return 0;
1.1       root      348: }
1.1.1.5   root      349: 
1.1.1.12! root      350: static void icp_pit_class_init(ObjectClass *klass, void *data)
        !           351: {
        !           352:     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
        !           353: 
        !           354:     sdc->init = icp_pit_init;
        !           355: }
        !           356: 
        !           357: static TypeInfo icp_pit_info = {
        !           358:     .name          = "integrator_pit",
        !           359:     .parent        = TYPE_SYS_BUS_DEVICE,
        !           360:     .instance_size = sizeof(icp_pit_state),
        !           361:     .class_init    = icp_pit_class_init,
        !           362: };
        !           363: 
        !           364: static Property sp804_properties[] = {
        !           365:     DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000),
        !           366:     DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000),
        !           367:     DEFINE_PROP_END_OF_LIST(),
        !           368: };
        !           369: 
        !           370: static void sp804_class_init(ObjectClass *klass, void *data)
        !           371: {
        !           372:     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
        !           373:     DeviceClass *k = DEVICE_CLASS(klass);
        !           374: 
        !           375:     sdc->init = sp804_init;
        !           376:     k->props = sp804_properties;
        !           377: }
        !           378: 
        !           379: static TypeInfo sp804_info = {
        !           380:     .name          = "sp804",
        !           381:     .parent        = TYPE_SYS_BUS_DEVICE,
        !           382:     .instance_size = sizeof(sp804_state),
        !           383:     .class_init    = sp804_class_init,
        !           384: };
        !           385: 
        !           386: static void arm_timer_register_types(void)
1.1.1.5   root      387: {
1.1.1.12! root      388:     type_register_static(&icp_pit_info);
        !           389:     type_register_static(&sp804_info);
1.1.1.5   root      390: }
                    391: 
1.1.1.12! root      392: type_init(arm_timer_register_types)

unix.superglobalmegacorp.com