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

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:     target_phys_addr_t base;
                     82:     int32_t clock;
                     83:     int32_t oldclock;
                     84:     uint64_t lastload;
                     85:     uint32_t freq;
                     86:     struct pxa2xx_timer0_s timer[4];
                     87:     struct pxa2xx_timer4_s *tm4;
                     88:     uint32_t events;
                     89:     uint32_t irq_enabled;
                     90:     uint32_t reset3;
                     91:     uint32_t snapshot;
                     92: } pxa2xx_timer_info;
                     93: 
                     94: static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
                     95: {
                     96:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                     97:     int i;
                     98:     uint32_t now_vm;
                     99:     uint64_t new_qemu;
                    100: 
                    101:     now_vm = s->clock +
                    102:             muldiv64(now_qemu - s->lastload, s->freq, ticks_per_sec);
                    103: 
                    104:     for (i = 0; i < 4; i ++) {
                    105:         new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
                    106:                         ticks_per_sec, s->freq);
                    107:         qemu_mod_timer(s->timer[i].qtimer, new_qemu);
                    108:     }
                    109: }
                    110: 
                    111: static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
                    112: {
                    113:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    114:     uint32_t now_vm;
                    115:     uint64_t new_qemu;
                    116:     static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
                    117:     int counter;
                    118: 
                    119:     if (s->tm4[n].control & (1 << 7))
                    120:         counter = n;
                    121:     else
                    122:         counter = counters[n];
                    123: 
                    124:     if (!s->tm4[counter].freq) {
                    125:         qemu_del_timer(s->tm4[n].tm.qtimer);
                    126:         return;
                    127:     }
                    128: 
                    129:     now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
                    130:                     s->tm4[counter].lastload,
                    131:                     s->tm4[counter].freq, ticks_per_sec);
                    132: 
                    133:     new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
                    134:                     ticks_per_sec, s->tm4[counter].freq);
                    135:     qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
                    136: }
                    137: 
                    138: static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
                    139: {
                    140:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    141:     int tm = 0;
                    142: 
                    143:     offset -= s->base;
                    144: 
                    145:     switch (offset) {
                    146:     case OSMR3:  tm ++;
                    147:     case OSMR2:  tm ++;
                    148:     case OSMR1:  tm ++;
                    149:     case OSMR0:
                    150:         return s->timer[tm].value;
                    151:     case OSMR11: tm ++;
                    152:     case OSMR10: tm ++;
                    153:     case OSMR9:  tm ++;
                    154:     case OSMR8:  tm ++;
                    155:     case OSMR7:  tm ++;
                    156:     case OSMR6:  tm ++;
                    157:     case OSMR5:  tm ++;
                    158:     case OSMR4:
                    159:         if (!s->tm4)
                    160:             goto badreg;
                    161:         return s->tm4[tm].tm.value;
                    162:     case OSCR:
                    163:         return s->clock + muldiv64(qemu_get_clock(vm_clock) -
                    164:                         s->lastload, s->freq, ticks_per_sec);
                    165:     case OSCR11: tm ++;
                    166:     case OSCR10: tm ++;
                    167:     case OSCR9:  tm ++;
                    168:     case OSCR8:  tm ++;
                    169:     case OSCR7:  tm ++;
                    170:     case OSCR6:  tm ++;
                    171:     case OSCR5:  tm ++;
                    172:     case OSCR4:
                    173:         if (!s->tm4)
                    174:             goto badreg;
                    175: 
                    176:         if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
                    177:             if (s->tm4[tm - 1].freq)
                    178:                 s->snapshot = s->tm4[tm - 1].clock + muldiv64(
                    179:                                 qemu_get_clock(vm_clock) -
                    180:                                 s->tm4[tm - 1].lastload,
                    181:                                 s->tm4[tm - 1].freq, ticks_per_sec);
                    182:             else
                    183:                 s->snapshot = s->tm4[tm - 1].clock;
                    184:         }
                    185: 
                    186:         if (!s->tm4[tm].freq)
                    187:             return s->tm4[tm].clock;
                    188:         return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
                    189:                         s->tm4[tm].lastload, s->tm4[tm].freq, ticks_per_sec);
                    190:     case OIER:
                    191:         return s->irq_enabled;
                    192:     case OSSR: /* Status register */
                    193:         return s->events;
                    194:     case OWER:
                    195:         return s->reset3;
                    196:     case OMCR11: tm ++;
                    197:     case OMCR10: tm ++;
                    198:     case OMCR9:  tm ++;
                    199:     case OMCR8:  tm ++;
                    200:     case OMCR7:  tm ++;
                    201:     case OMCR6:  tm ++;
                    202:     case OMCR5:  tm ++;
                    203:     case OMCR4:
                    204:         if (!s->tm4)
                    205:             goto badreg;
                    206:         return s->tm4[tm].control;
                    207:     case OSNR:
                    208:         return s->snapshot;
                    209:     default:
                    210:     badreg:
                    211:         cpu_abort(cpu_single_env, "pxa2xx_timer_read: Bad offset "
                    212:                         REG_FMT "\n", offset);
                    213:     }
                    214: 
                    215:     return 0;
                    216: }
                    217: 
                    218: static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
                    219:                 uint32_t value)
                    220: {
                    221:     int i, tm = 0;
                    222:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    223: 
                    224:     offset -= s->base;
                    225: 
                    226:     switch (offset) {
                    227:     case OSMR3:  tm ++;
                    228:     case OSMR2:  tm ++;
                    229:     case OSMR1:  tm ++;
                    230:     case OSMR0:
                    231:         s->timer[tm].value = value;
                    232:         pxa2xx_timer_update(s, qemu_get_clock(vm_clock));
                    233:         break;
                    234:     case OSMR11: tm ++;
                    235:     case OSMR10: tm ++;
                    236:     case OSMR9:  tm ++;
                    237:     case OSMR8:  tm ++;
                    238:     case OSMR7:  tm ++;
                    239:     case OSMR6:  tm ++;
                    240:     case OSMR5:  tm ++;
                    241:     case OSMR4:
                    242:         if (!s->tm4)
                    243:             goto badreg;
                    244:         s->tm4[tm].tm.value = value;
                    245:         pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
                    246:         break;
                    247:     case OSCR:
                    248:         s->oldclock = s->clock;
                    249:         s->lastload = qemu_get_clock(vm_clock);
                    250:         s->clock = value;
                    251:         pxa2xx_timer_update(s, s->lastload);
                    252:         break;
                    253:     case OSCR11: tm ++;
                    254:     case OSCR10: tm ++;
                    255:     case OSCR9:  tm ++;
                    256:     case OSCR8:  tm ++;
                    257:     case OSCR7:  tm ++;
                    258:     case OSCR6:  tm ++;
                    259:     case OSCR5:  tm ++;
                    260:     case OSCR4:
                    261:         if (!s->tm4)
                    262:             goto badreg;
                    263:         s->tm4[tm].oldclock = s->tm4[tm].clock;
                    264:         s->tm4[tm].lastload = qemu_get_clock(vm_clock);
                    265:         s->tm4[tm].clock = value;
                    266:         pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
                    267:         break;
                    268:     case OIER:
                    269:         s->irq_enabled = value & 0xfff;
                    270:         break;
                    271:     case OSSR: /* Status register */
                    272:         s->events &= ~value;
                    273:         for (i = 0; i < 4; i ++, value >>= 1) {
                    274:             if (s->timer[i].level && (value & 1)) {
                    275:                 s->timer[i].level = 0;
                    276:                 qemu_irq_lower(s->timer[i].irq);
                    277:             }
                    278:         }
                    279:         if (s->tm4) {
                    280:             for (i = 0; i < 8; i ++, value >>= 1)
                    281:                 if (s->tm4[i].tm.level && (value & 1))
                    282:                     s->tm4[i].tm.level = 0;
                    283:             if (!(s->events & 0xff0))
                    284:                 qemu_irq_lower(s->tm4->tm.irq);
                    285:         }
                    286:         break;
                    287:     case OWER: /* XXX: Reset on OSMR3 match? */
                    288:         s->reset3 = value;
                    289:         break;
                    290:     case OMCR7:  tm ++;
                    291:     case OMCR6:  tm ++;
                    292:     case OMCR5:  tm ++;
                    293:     case OMCR4:
                    294:         if (!s->tm4)
                    295:             goto badreg;
                    296:         s->tm4[tm].control = value & 0x0ff;
                    297:         /* XXX Stop if running (shouldn't happen) */
                    298:         if ((value & (1 << 7)) || tm == 0)
                    299:             s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
                    300:         else {
                    301:             s->tm4[tm].freq = 0;
                    302:             pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
                    303:         }
                    304:         break;
                    305:     case OMCR11: tm ++;
                    306:     case OMCR10: tm ++;
                    307:     case OMCR9:  tm ++;
                    308:     case OMCR8:  tm += 4;
                    309:         if (!s->tm4)
                    310:             goto badreg;
                    311:         s->tm4[tm].control = value & 0x3ff;
                    312:         /* XXX Stop if running (shouldn't happen) */
                    313:         if ((value & (1 << 7)) || !(tm & 1))
                    314:             s->tm4[tm].freq =
                    315:                     pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
                    316:         else {
                    317:             s->tm4[tm].freq = 0;
                    318:             pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
                    319:         }
                    320:         break;
                    321:     default:
                    322:     badreg:
                    323:         cpu_abort(cpu_single_env, "pxa2xx_timer_write: Bad offset "
                    324:                         REG_FMT "\n", offset);
                    325:     }
                    326: }
                    327: 
                    328: static CPUReadMemoryFunc *pxa2xx_timer_readfn[] = {
                    329:     pxa2xx_timer_read,
                    330:     pxa2xx_timer_read,
                    331:     pxa2xx_timer_read,
                    332: };
                    333: 
                    334: static CPUWriteMemoryFunc *pxa2xx_timer_writefn[] = {
                    335:     pxa2xx_timer_write,
                    336:     pxa2xx_timer_write,
                    337:     pxa2xx_timer_write,
                    338: };
                    339: 
                    340: static void pxa2xx_timer_tick(void *opaque)
                    341: {
                    342:     struct pxa2xx_timer0_s *t = (struct pxa2xx_timer0_s *) opaque;
                    343:     pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
                    344: 
                    345:     if (i->irq_enabled & (1 << t->num)) {
                    346:         t->level = 1;
                    347:         i->events |= 1 << t->num;
                    348:         qemu_irq_raise(t->irq);
                    349:     }
                    350: 
                    351:     if (t->num == 3)
                    352:         if (i->reset3 & 1) {
                    353:             i->reset3 = 0;
                    354:             qemu_system_reset_request();
                    355:         }
                    356: }
                    357: 
                    358: static void pxa2xx_timer_tick4(void *opaque)
                    359: {
                    360:     struct pxa2xx_timer4_s *t = (struct pxa2xx_timer4_s *) opaque;
                    361:     pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->tm.info;
                    362: 
                    363:     pxa2xx_timer_tick(&t->tm);
                    364:     if (t->control & (1 << 3))
                    365:         t->clock = 0;
                    366:     if (t->control & (1 << 6))
                    367:         pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
                    368: }
                    369: 
                    370: static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
                    371: {
                    372:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    373:     int i;
                    374: 
                    375:     qemu_put_be32s(f, &s->clock);
                    376:     qemu_put_be32s(f, &s->oldclock);
                    377:     qemu_put_be64s(f, &s->lastload);
                    378: 
                    379:     for (i = 0; i < 4; i ++) {
                    380:         qemu_put_be32s(f, &s->timer[i].value);
                    381:         qemu_put_be32(f, s->timer[i].level);
                    382:     }
                    383:     if (s->tm4)
                    384:         for (i = 0; i < 8; i ++) {
                    385:             qemu_put_be32s(f, &s->tm4[i].tm.value);
                    386:             qemu_put_be32(f, s->tm4[i].tm.level);
                    387:             qemu_put_be32s(f, &s->tm4[i].oldclock);
                    388:             qemu_put_be32s(f, &s->tm4[i].clock);
                    389:             qemu_put_be64s(f, &s->tm4[i].lastload);
                    390:             qemu_put_be32s(f, &s->tm4[i].freq);
                    391:             qemu_put_be32s(f, &s->tm4[i].control);
                    392:         }
                    393: 
                    394:     qemu_put_be32s(f, &s->events);
                    395:     qemu_put_be32s(f, &s->irq_enabled);
                    396:     qemu_put_be32s(f, &s->reset3);
                    397:     qemu_put_be32s(f, &s->snapshot);
                    398: }
                    399: 
                    400: static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
                    401: {
                    402:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    403:     int64_t now;
                    404:     int i;
                    405: 
                    406:     qemu_get_be32s(f, &s->clock);
                    407:     qemu_get_be32s(f, &s->oldclock);
                    408:     qemu_get_be64s(f, &s->lastload);
                    409: 
                    410:     now = qemu_get_clock(vm_clock);
                    411:     for (i = 0; i < 4; i ++) {
                    412:         qemu_get_be32s(f, &s->timer[i].value);
                    413:         s->timer[i].level = qemu_get_be32(f);
                    414:     }
                    415:     pxa2xx_timer_update(s, now);
                    416: 
                    417:     if (s->tm4)
                    418:         for (i = 0; i < 8; i ++) {
                    419:             qemu_get_be32s(f, &s->tm4[i].tm.value);
                    420:             s->tm4[i].tm.level = qemu_get_be32(f);
                    421:             qemu_get_be32s(f, &s->tm4[i].oldclock);
                    422:             qemu_get_be32s(f, &s->tm4[i].clock);
                    423:             qemu_get_be64s(f, &s->tm4[i].lastload);
                    424:             qemu_get_be32s(f, &s->tm4[i].freq);
                    425:             qemu_get_be32s(f, &s->tm4[i].control);
                    426:             pxa2xx_timer_update4(s, now, i);
                    427:         }
                    428: 
                    429:     qemu_get_be32s(f, &s->events);
                    430:     qemu_get_be32s(f, &s->irq_enabled);
                    431:     qemu_get_be32s(f, &s->reset3);
                    432:     qemu_get_be32s(f, &s->snapshot);
                    433: 
                    434:     return 0;
                    435: }
                    436: 
                    437: static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
                    438:                 qemu_irq *irqs)
                    439: {
                    440:     int i;
                    441:     int iomemtype;
                    442:     pxa2xx_timer_info *s;
                    443: 
                    444:     s = (pxa2xx_timer_info *) qemu_mallocz(sizeof(pxa2xx_timer_info));
                    445:     s->base = base;
                    446:     s->irq_enabled = 0;
                    447:     s->oldclock = 0;
                    448:     s->clock = 0;
                    449:     s->lastload = qemu_get_clock(vm_clock);
                    450:     s->reset3 = 0;
                    451: 
                    452:     for (i = 0; i < 4; i ++) {
                    453:         s->timer[i].value = 0;
                    454:         s->timer[i].irq = irqs[i];
                    455:         s->timer[i].info = s;
                    456:         s->timer[i].num = i;
                    457:         s->timer[i].level = 0;
                    458:         s->timer[i].qtimer = qemu_new_timer(vm_clock,
                    459:                         pxa2xx_timer_tick, &s->timer[i]);
                    460:     }
                    461: 
                    462:     iomemtype = cpu_register_io_memory(0, pxa2xx_timer_readfn,
                    463:                     pxa2xx_timer_writefn, s);
                    464:     cpu_register_physical_memory(base, 0x00001000, iomemtype);
                    465: 
                    466:     register_savevm("pxa2xx_timer", 0, 0,
                    467:                     pxa2xx_timer_save, pxa2xx_timer_load, s);
                    468: 
                    469:     return s;
                    470: }
                    471: 
                    472: void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs)
                    473: {
                    474:     pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
                    475:     s->freq = PXA25X_FREQ;
                    476:     s->tm4 = 0;
                    477: }
                    478: 
                    479: void pxa27x_timer_init(target_phys_addr_t base,
                    480:                 qemu_irq *irqs, qemu_irq irq4)
                    481: {
                    482:     pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
                    483:     int i;
                    484:     s->freq = PXA27X_FREQ;
                    485:     s->tm4 = (struct pxa2xx_timer4_s *) qemu_mallocz(8 *
                    486:                     sizeof(struct pxa2xx_timer4_s));
                    487:     for (i = 0; i < 8; i ++) {
                    488:         s->tm4[i].tm.value = 0;
                    489:         s->tm4[i].tm.irq = irq4;
                    490:         s->tm4[i].tm.info = s;
                    491:         s->tm4[i].tm.num = i + 4;
                    492:         s->tm4[i].tm.level = 0;
                    493:         s->tm4[i].freq = 0;
                    494:         s->tm4[i].control = 0x0;
                    495:         s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
                    496:                         pxa2xx_timer_tick4, &s->tm4[i]);
                    497:     }
                    498: }

unix.superglobalmegacorp.com

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