Annotation of qemu/hw/pxa2xx_timer.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Intel XScale PXA255/270 OS Timers.
                      3:  *
                      4:  * Copyright (c) 2006 Openedhand Ltd.
                      5:  * Copyright (c) 2006 Thorsten Zitterell
                      6:  *
                      7:  * This code is licenced under the GPL.
                      8:  */
                      9: 
                     10: #include "hw.h"
                     11: #include "qemu-timer.h"
                     12: #include "sysemu.h"
                     13: #include "pxa.h"
                     14: 
                     15: #define OSMR0  0x00
                     16: #define OSMR1  0x04
                     17: #define OSMR2  0x08
                     18: #define OSMR3  0x0c
                     19: #define OSMR4  0x80
                     20: #define OSMR5  0x84
                     21: #define OSMR6  0x88
                     22: #define OSMR7  0x8c
                     23: #define OSMR8  0x90
                     24: #define OSMR9  0x94
                     25: #define OSMR10 0x98
                     26: #define OSMR11 0x9c
                     27: #define OSCR   0x10    /* OS Timer Count */
                     28: #define OSCR4  0x40
                     29: #define OSCR5  0x44
                     30: #define OSCR6  0x48
                     31: #define OSCR7  0x4c
                     32: #define OSCR8  0x50
                     33: #define OSCR9  0x54
                     34: #define OSCR10 0x58
                     35: #define OSCR11 0x5c
                     36: #define OSSR   0x14    /* Timer status register */
                     37: #define OWER   0x18
                     38: #define OIER   0x1c    /* Interrupt enable register  3-0 to E3-E0 */
                     39: #define OMCR4  0xc0    /* OS Match Control registers */
                     40: #define OMCR5  0xc4
                     41: #define OMCR6  0xc8
                     42: #define OMCR7  0xcc
                     43: #define OMCR8  0xd0
                     44: #define OMCR9  0xd4
                     45: #define OMCR10 0xd8
                     46: #define OMCR11 0xdc
                     47: #define OSNR   0x20
                     48: 
                     49: #define PXA25X_FREQ    3686400 /* 3.6864 MHz */
                     50: #define PXA27X_FREQ    3250000 /* 3.25 MHz */
                     51: 
                     52: static int pxa2xx_timer4_freq[8] = {
                     53:     [0] = 0,
                     54:     [1] = 32768,
                     55:     [2] = 1000,
                     56:     [3] = 1,
                     57:     [4] = 1000000,
                     58:     /* [5] is the "Externally supplied clock".  Assign if necessary.  */
                     59:     [5 ... 7] = 0,
                     60: };
                     61: 
                     62: struct pxa2xx_timer0_s {
                     63:     uint32_t value;
                     64:     int level;
                     65:     qemu_irq irq;
                     66:     QEMUTimer *qtimer;
                     67:     int num;
                     68:     void *info;
                     69: };
                     70: 
                     71: struct pxa2xx_timer4_s {
                     72:     struct pxa2xx_timer0_s tm;
                     73:     int32_t oldclock;
                     74:     int32_t clock;
                     75:     uint64_t lastload;
                     76:     uint32_t freq;
                     77:     uint32_t control;
                     78: };
                     79: 
                     80: typedef struct {
                     81:     int32_t clock;
                     82:     int32_t oldclock;
                     83:     uint64_t lastload;
                     84:     uint32_t freq;
                     85:     struct pxa2xx_timer0_s timer[4];
                     86:     struct pxa2xx_timer4_s *tm4;
                     87:     uint32_t events;
                     88:     uint32_t irq_enabled;
                     89:     uint32_t reset3;
                     90:     uint32_t snapshot;
                     91: } pxa2xx_timer_info;
                     92: 
                     93: static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
                     94: {
                     95:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                     96:     int i;
                     97:     uint32_t now_vm;
                     98:     uint64_t new_qemu;
                     99: 
                    100:     now_vm = s->clock +
                    101:             muldiv64(now_qemu - s->lastload, s->freq, ticks_per_sec);
                    102: 
                    103:     for (i = 0; i < 4; i ++) {
                    104:         new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
                    105:                         ticks_per_sec, s->freq);
                    106:         qemu_mod_timer(s->timer[i].qtimer, new_qemu);
                    107:     }
                    108: }
                    109: 
                    110: static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
                    111: {
                    112:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    113:     uint32_t now_vm;
                    114:     uint64_t new_qemu;
                    115:     static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
                    116:     int counter;
                    117: 
                    118:     if (s->tm4[n].control & (1 << 7))
                    119:         counter = n;
                    120:     else
                    121:         counter = counters[n];
                    122: 
                    123:     if (!s->tm4[counter].freq) {
                    124:         qemu_del_timer(s->tm4[n].tm.qtimer);
                    125:         return;
                    126:     }
                    127: 
                    128:     now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
                    129:                     s->tm4[counter].lastload,
                    130:                     s->tm4[counter].freq, ticks_per_sec);
                    131: 
                    132:     new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
                    133:                     ticks_per_sec, s->tm4[counter].freq);
                    134:     qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
                    135: }
                    136: 
                    137: static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
                    138: {
                    139:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    140:     int tm = 0;
                    141: 
                    142:     switch (offset) {
                    143:     case OSMR3:  tm ++;
                    144:     case OSMR2:  tm ++;
                    145:     case OSMR1:  tm ++;
                    146:     case OSMR0:
                    147:         return s->timer[tm].value;
                    148:     case OSMR11: tm ++;
                    149:     case OSMR10: tm ++;
                    150:     case OSMR9:  tm ++;
                    151:     case OSMR8:  tm ++;
                    152:     case OSMR7:  tm ++;
                    153:     case OSMR6:  tm ++;
                    154:     case OSMR5:  tm ++;
                    155:     case OSMR4:
                    156:         if (!s->tm4)
                    157:             goto badreg;
                    158:         return s->tm4[tm].tm.value;
                    159:     case OSCR:
                    160:         return s->clock + muldiv64(qemu_get_clock(vm_clock) -
                    161:                         s->lastload, s->freq, ticks_per_sec);
                    162:     case OSCR11: tm ++;
                    163:     case OSCR10: tm ++;
                    164:     case OSCR9:  tm ++;
                    165:     case OSCR8:  tm ++;
                    166:     case OSCR7:  tm ++;
                    167:     case OSCR6:  tm ++;
                    168:     case OSCR5:  tm ++;
                    169:     case OSCR4:
                    170:         if (!s->tm4)
                    171:             goto badreg;
                    172: 
                    173:         if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
                    174:             if (s->tm4[tm - 1].freq)
                    175:                 s->snapshot = s->tm4[tm - 1].clock + muldiv64(
                    176:                                 qemu_get_clock(vm_clock) -
                    177:                                 s->tm4[tm - 1].lastload,
                    178:                                 s->tm4[tm - 1].freq, ticks_per_sec);
                    179:             else
                    180:                 s->snapshot = s->tm4[tm - 1].clock;
                    181:         }
                    182: 
                    183:         if (!s->tm4[tm].freq)
                    184:             return s->tm4[tm].clock;
                    185:         return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
                    186:                         s->tm4[tm].lastload, s->tm4[tm].freq, ticks_per_sec);
                    187:     case OIER:
                    188:         return s->irq_enabled;
                    189:     case OSSR: /* Status register */
                    190:         return s->events;
                    191:     case OWER:
                    192:         return s->reset3;
                    193:     case OMCR11: tm ++;
                    194:     case OMCR10: tm ++;
                    195:     case OMCR9:  tm ++;
                    196:     case OMCR8:  tm ++;
                    197:     case OMCR7:  tm ++;
                    198:     case OMCR6:  tm ++;
                    199:     case OMCR5:  tm ++;
                    200:     case OMCR4:
                    201:         if (!s->tm4)
                    202:             goto badreg;
                    203:         return s->tm4[tm].control;
                    204:     case OSNR:
                    205:         return s->snapshot;
                    206:     default:
                    207:     badreg:
                    208:         cpu_abort(cpu_single_env, "pxa2xx_timer_read: Bad offset "
                    209:                         REG_FMT "\n", offset);
                    210:     }
                    211: 
                    212:     return 0;
                    213: }
                    214: 
                    215: static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
                    216:                 uint32_t value)
                    217: {
                    218:     int i, tm = 0;
                    219:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    220: 
                    221:     switch (offset) {
                    222:     case OSMR3:  tm ++;
                    223:     case OSMR2:  tm ++;
                    224:     case OSMR1:  tm ++;
                    225:     case OSMR0:
                    226:         s->timer[tm].value = value;
                    227:         pxa2xx_timer_update(s, qemu_get_clock(vm_clock));
                    228:         break;
                    229:     case OSMR11: tm ++;
                    230:     case OSMR10: tm ++;
                    231:     case OSMR9:  tm ++;
                    232:     case OSMR8:  tm ++;
                    233:     case OSMR7:  tm ++;
                    234:     case OSMR6:  tm ++;
                    235:     case OSMR5:  tm ++;
                    236:     case OSMR4:
                    237:         if (!s->tm4)
                    238:             goto badreg;
                    239:         s->tm4[tm].tm.value = value;
                    240:         pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
                    241:         break;
                    242:     case OSCR:
                    243:         s->oldclock = s->clock;
                    244:         s->lastload = qemu_get_clock(vm_clock);
                    245:         s->clock = value;
                    246:         pxa2xx_timer_update(s, s->lastload);
                    247:         break;
                    248:     case OSCR11: tm ++;
                    249:     case OSCR10: tm ++;
                    250:     case OSCR9:  tm ++;
                    251:     case OSCR8:  tm ++;
                    252:     case OSCR7:  tm ++;
                    253:     case OSCR6:  tm ++;
                    254:     case OSCR5:  tm ++;
                    255:     case OSCR4:
                    256:         if (!s->tm4)
                    257:             goto badreg;
                    258:         s->tm4[tm].oldclock = s->tm4[tm].clock;
                    259:         s->tm4[tm].lastload = qemu_get_clock(vm_clock);
                    260:         s->tm4[tm].clock = value;
                    261:         pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
                    262:         break;
                    263:     case OIER:
                    264:         s->irq_enabled = value & 0xfff;
                    265:         break;
                    266:     case OSSR: /* Status register */
                    267:         s->events &= ~value;
                    268:         for (i = 0; i < 4; i ++, value >>= 1) {
                    269:             if (s->timer[i].level && (value & 1)) {
                    270:                 s->timer[i].level = 0;
                    271:                 qemu_irq_lower(s->timer[i].irq);
                    272:             }
                    273:         }
                    274:         if (s->tm4) {
                    275:             for (i = 0; i < 8; i ++, value >>= 1)
                    276:                 if (s->tm4[i].tm.level && (value & 1))
                    277:                     s->tm4[i].tm.level = 0;
                    278:             if (!(s->events & 0xff0))
                    279:                 qemu_irq_lower(s->tm4->tm.irq);
                    280:         }
                    281:         break;
                    282:     case OWER: /* XXX: Reset on OSMR3 match? */
                    283:         s->reset3 = value;
                    284:         break;
                    285:     case OMCR7:  tm ++;
                    286:     case OMCR6:  tm ++;
                    287:     case OMCR5:  tm ++;
                    288:     case OMCR4:
                    289:         if (!s->tm4)
                    290:             goto badreg;
                    291:         s->tm4[tm].control = value & 0x0ff;
                    292:         /* XXX Stop if running (shouldn't happen) */
                    293:         if ((value & (1 << 7)) || tm == 0)
                    294:             s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
                    295:         else {
                    296:             s->tm4[tm].freq = 0;
                    297:             pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
                    298:         }
                    299:         break;
                    300:     case OMCR11: tm ++;
                    301:     case OMCR10: tm ++;
                    302:     case OMCR9:  tm ++;
                    303:     case OMCR8:  tm += 4;
                    304:         if (!s->tm4)
                    305:             goto badreg;
                    306:         s->tm4[tm].control = value & 0x3ff;
                    307:         /* XXX Stop if running (shouldn't happen) */
                    308:         if ((value & (1 << 7)) || !(tm & 1))
                    309:             s->tm4[tm].freq =
                    310:                     pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
                    311:         else {
                    312:             s->tm4[tm].freq = 0;
                    313:             pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
                    314:         }
                    315:         break;
                    316:     default:
                    317:     badreg:
                    318:         cpu_abort(cpu_single_env, "pxa2xx_timer_write: Bad offset "
                    319:                         REG_FMT "\n", offset);
                    320:     }
                    321: }
                    322: 
                    323: static CPUReadMemoryFunc *pxa2xx_timer_readfn[] = {
                    324:     pxa2xx_timer_read,
                    325:     pxa2xx_timer_read,
                    326:     pxa2xx_timer_read,
                    327: };
                    328: 
                    329: static CPUWriteMemoryFunc *pxa2xx_timer_writefn[] = {
                    330:     pxa2xx_timer_write,
                    331:     pxa2xx_timer_write,
                    332:     pxa2xx_timer_write,
                    333: };
                    334: 
                    335: static void pxa2xx_timer_tick(void *opaque)
                    336: {
                    337:     struct pxa2xx_timer0_s *t = (struct pxa2xx_timer0_s *) opaque;
                    338:     pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
                    339: 
                    340:     if (i->irq_enabled & (1 << t->num)) {
                    341:         t->level = 1;
                    342:         i->events |= 1 << t->num;
                    343:         qemu_irq_raise(t->irq);
                    344:     }
                    345: 
                    346:     if (t->num == 3)
                    347:         if (i->reset3 & 1) {
                    348:             i->reset3 = 0;
                    349:             qemu_system_reset_request();
                    350:         }
                    351: }
                    352: 
                    353: static void pxa2xx_timer_tick4(void *opaque)
                    354: {
                    355:     struct pxa2xx_timer4_s *t = (struct pxa2xx_timer4_s *) opaque;
                    356:     pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->tm.info;
                    357: 
                    358:     pxa2xx_timer_tick(&t->tm);
                    359:     if (t->control & (1 << 3))
                    360:         t->clock = 0;
                    361:     if (t->control & (1 << 6))
                    362:         pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
                    363: }
                    364: 
                    365: static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
                    366: {
                    367:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    368:     int i;
                    369: 
1.1.1.2 ! root      370:     qemu_put_be32s(f, (uint32_t *) &s->clock);
        !           371:     qemu_put_be32s(f, (uint32_t *) &s->oldclock);
1.1       root      372:     qemu_put_be64s(f, &s->lastload);
                    373: 
                    374:     for (i = 0; i < 4; i ++) {
                    375:         qemu_put_be32s(f, &s->timer[i].value);
                    376:         qemu_put_be32(f, s->timer[i].level);
                    377:     }
                    378:     if (s->tm4)
                    379:         for (i = 0; i < 8; i ++) {
                    380:             qemu_put_be32s(f, &s->tm4[i].tm.value);
                    381:             qemu_put_be32(f, s->tm4[i].tm.level);
1.1.1.2 ! root      382:             qemu_put_sbe32s(f, &s->tm4[i].oldclock);
        !           383:             qemu_put_sbe32s(f, &s->tm4[i].clock);
1.1       root      384:             qemu_put_be64s(f, &s->tm4[i].lastload);
                    385:             qemu_put_be32s(f, &s->tm4[i].freq);
                    386:             qemu_put_be32s(f, &s->tm4[i].control);
                    387:         }
                    388: 
                    389:     qemu_put_be32s(f, &s->events);
                    390:     qemu_put_be32s(f, &s->irq_enabled);
                    391:     qemu_put_be32s(f, &s->reset3);
                    392:     qemu_put_be32s(f, &s->snapshot);
                    393: }
                    394: 
                    395: static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
                    396: {
                    397:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    398:     int64_t now;
                    399:     int i;
                    400: 
1.1.1.2 ! root      401:     qemu_get_be32s(f, (uint32_t *) &s->clock);
        !           402:     qemu_get_be32s(f, (uint32_t *) &s->oldclock);
1.1       root      403:     qemu_get_be64s(f, &s->lastload);
                    404: 
                    405:     now = qemu_get_clock(vm_clock);
                    406:     for (i = 0; i < 4; i ++) {
                    407:         qemu_get_be32s(f, &s->timer[i].value);
                    408:         s->timer[i].level = qemu_get_be32(f);
                    409:     }
                    410:     pxa2xx_timer_update(s, now);
                    411: 
                    412:     if (s->tm4)
                    413:         for (i = 0; i < 8; i ++) {
                    414:             qemu_get_be32s(f, &s->tm4[i].tm.value);
                    415:             s->tm4[i].tm.level = qemu_get_be32(f);
1.1.1.2 ! root      416:             qemu_get_sbe32s(f, &s->tm4[i].oldclock);
        !           417:             qemu_get_sbe32s(f, &s->tm4[i].clock);
1.1       root      418:             qemu_get_be64s(f, &s->tm4[i].lastload);
                    419:             qemu_get_be32s(f, &s->tm4[i].freq);
                    420:             qemu_get_be32s(f, &s->tm4[i].control);
                    421:             pxa2xx_timer_update4(s, now, i);
                    422:         }
                    423: 
                    424:     qemu_get_be32s(f, &s->events);
                    425:     qemu_get_be32s(f, &s->irq_enabled);
                    426:     qemu_get_be32s(f, &s->reset3);
                    427:     qemu_get_be32s(f, &s->snapshot);
                    428: 
                    429:     return 0;
                    430: }
                    431: 
                    432: static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
                    433:                 qemu_irq *irqs)
                    434: {
                    435:     int i;
                    436:     int iomemtype;
                    437:     pxa2xx_timer_info *s;
                    438: 
                    439:     s = (pxa2xx_timer_info *) qemu_mallocz(sizeof(pxa2xx_timer_info));
                    440:     s->irq_enabled = 0;
                    441:     s->oldclock = 0;
                    442:     s->clock = 0;
                    443:     s->lastload = qemu_get_clock(vm_clock);
                    444:     s->reset3 = 0;
                    445: 
                    446:     for (i = 0; i < 4; i ++) {
                    447:         s->timer[i].value = 0;
                    448:         s->timer[i].irq = irqs[i];
                    449:         s->timer[i].info = s;
                    450:         s->timer[i].num = i;
                    451:         s->timer[i].level = 0;
                    452:         s->timer[i].qtimer = qemu_new_timer(vm_clock,
                    453:                         pxa2xx_timer_tick, &s->timer[i]);
                    454:     }
                    455: 
                    456:     iomemtype = cpu_register_io_memory(0, pxa2xx_timer_readfn,
                    457:                     pxa2xx_timer_writefn, s);
                    458:     cpu_register_physical_memory(base, 0x00001000, iomemtype);
                    459: 
                    460:     register_savevm("pxa2xx_timer", 0, 0,
                    461:                     pxa2xx_timer_save, pxa2xx_timer_load, s);
                    462: 
                    463:     return s;
                    464: }
                    465: 
                    466: void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs)
                    467: {
                    468:     pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
                    469:     s->freq = PXA25X_FREQ;
                    470:     s->tm4 = 0;
                    471: }
                    472: 
                    473: void pxa27x_timer_init(target_phys_addr_t base,
                    474:                 qemu_irq *irqs, qemu_irq irq4)
                    475: {
                    476:     pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
                    477:     int i;
                    478:     s->freq = PXA27X_FREQ;
                    479:     s->tm4 = (struct pxa2xx_timer4_s *) qemu_mallocz(8 *
                    480:                     sizeof(struct pxa2xx_timer4_s));
                    481:     for (i = 0; i < 8; i ++) {
                    482:         s->tm4[i].tm.value = 0;
                    483:         s->tm4[i].tm.irq = irq4;
                    484:         s->tm4[i].tm.info = s;
                    485:         s->tm4[i].tm.num = i + 4;
                    486:         s->tm4[i].tm.level = 0;
                    487:         s->tm4[i].freq = 0;
                    488:         s->tm4[i].control = 0x0;
                    489:         s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
                    490:                         pxa2xx_timer_tick4, &s->tm4[i]);
                    491:     }
                    492: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.