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

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: 
1.1.1.3   root       62: typedef struct {
1.1       root       63:     uint32_t value;
                     64:     int level;
                     65:     qemu_irq irq;
                     66:     QEMUTimer *qtimer;
                     67:     int num;
                     68:     void *info;
1.1.1.3   root       69: } PXA2xxTimer0;
1.1       root       70: 
1.1.1.3   root       71: typedef struct {
                     72:     PXA2xxTimer0 tm;
1.1       root       73:     int32_t oldclock;
                     74:     int32_t clock;
                     75:     uint64_t lastload;
                     76:     uint32_t freq;
                     77:     uint32_t control;
1.1.1.3   root       78: } PXA2xxTimer4;
1.1       root       79: 
                     80: typedef struct {
                     81:     int32_t clock;
                     82:     int32_t oldclock;
                     83:     uint64_t lastload;
                     84:     uint32_t freq;
1.1.1.3   root       85:     PXA2xxTimer0 timer[4];
                     86:     PXA2xxTimer4 *tm4;
1.1       root       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 +
1.1.1.4   root      101:             muldiv64(now_qemu - s->lastload, s->freq, get_ticks_per_sec());
1.1       root      102: 
                    103:     for (i = 0; i < 4; i ++) {
                    104:         new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
1.1.1.4   root      105:                         get_ticks_per_sec(), s->freq);
1.1       root      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,
1.1.1.4   root      130:                     s->tm4[counter].freq, get_ticks_per_sec());
1.1       root      131: 
                    132:     new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
1.1.1.4   root      133:                     get_ticks_per_sec(), s->tm4[counter].freq);
1.1       root      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) -
1.1.1.4   root      161:                         s->lastload, s->freq, get_ticks_per_sec());
1.1       root      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,
1.1.1.4   root      178:                                 s->tm4[tm - 1].freq, get_ticks_per_sec());
1.1       root      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) -
1.1.1.4   root      186:                         s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
1.1       root      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:
1.1.1.3   root      208:         hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
1.1       root      209:     }
                    210: 
                    211:     return 0;
                    212: }
                    213: 
                    214: static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
                    215:                 uint32_t value)
                    216: {
                    217:     int i, tm = 0;
                    218:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    219: 
                    220:     switch (offset) {
                    221:     case OSMR3:  tm ++;
                    222:     case OSMR2:  tm ++;
                    223:     case OSMR1:  tm ++;
                    224:     case OSMR0:
                    225:         s->timer[tm].value = value;
                    226:         pxa2xx_timer_update(s, qemu_get_clock(vm_clock));
                    227:         break;
                    228:     case OSMR11: tm ++;
                    229:     case OSMR10: tm ++;
                    230:     case OSMR9:  tm ++;
                    231:     case OSMR8:  tm ++;
                    232:     case OSMR7:  tm ++;
                    233:     case OSMR6:  tm ++;
                    234:     case OSMR5:  tm ++;
                    235:     case OSMR4:
                    236:         if (!s->tm4)
                    237:             goto badreg;
                    238:         s->tm4[tm].tm.value = value;
                    239:         pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
                    240:         break;
                    241:     case OSCR:
                    242:         s->oldclock = s->clock;
                    243:         s->lastload = qemu_get_clock(vm_clock);
                    244:         s->clock = value;
                    245:         pxa2xx_timer_update(s, s->lastload);
                    246:         break;
                    247:     case OSCR11: tm ++;
                    248:     case OSCR10: tm ++;
                    249:     case OSCR9:  tm ++;
                    250:     case OSCR8:  tm ++;
                    251:     case OSCR7:  tm ++;
                    252:     case OSCR6:  tm ++;
                    253:     case OSCR5:  tm ++;
                    254:     case OSCR4:
                    255:         if (!s->tm4)
                    256:             goto badreg;
                    257:         s->tm4[tm].oldclock = s->tm4[tm].clock;
                    258:         s->tm4[tm].lastload = qemu_get_clock(vm_clock);
                    259:         s->tm4[tm].clock = value;
                    260:         pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
                    261:         break;
                    262:     case OIER:
                    263:         s->irq_enabled = value & 0xfff;
                    264:         break;
                    265:     case OSSR: /* Status register */
                    266:         s->events &= ~value;
                    267:         for (i = 0; i < 4; i ++, value >>= 1) {
                    268:             if (s->timer[i].level && (value & 1)) {
                    269:                 s->timer[i].level = 0;
                    270:                 qemu_irq_lower(s->timer[i].irq);
                    271:             }
                    272:         }
                    273:         if (s->tm4) {
                    274:             for (i = 0; i < 8; i ++, value >>= 1)
                    275:                 if (s->tm4[i].tm.level && (value & 1))
                    276:                     s->tm4[i].tm.level = 0;
                    277:             if (!(s->events & 0xff0))
                    278:                 qemu_irq_lower(s->tm4->tm.irq);
                    279:         }
                    280:         break;
                    281:     case OWER: /* XXX: Reset on OSMR3 match? */
                    282:         s->reset3 = value;
                    283:         break;
                    284:     case OMCR7:  tm ++;
                    285:     case OMCR6:  tm ++;
                    286:     case OMCR5:  tm ++;
                    287:     case OMCR4:
                    288:         if (!s->tm4)
                    289:             goto badreg;
                    290:         s->tm4[tm].control = value & 0x0ff;
                    291:         /* XXX Stop if running (shouldn't happen) */
                    292:         if ((value & (1 << 7)) || tm == 0)
                    293:             s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
                    294:         else {
                    295:             s->tm4[tm].freq = 0;
                    296:             pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
                    297:         }
                    298:         break;
                    299:     case OMCR11: tm ++;
                    300:     case OMCR10: tm ++;
                    301:     case OMCR9:  tm ++;
                    302:     case OMCR8:  tm += 4;
                    303:         if (!s->tm4)
                    304:             goto badreg;
                    305:         s->tm4[tm].control = value & 0x3ff;
                    306:         /* XXX Stop if running (shouldn't happen) */
                    307:         if ((value & (1 << 7)) || !(tm & 1))
                    308:             s->tm4[tm].freq =
                    309:                     pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
                    310:         else {
                    311:             s->tm4[tm].freq = 0;
                    312:             pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
                    313:         }
                    314:         break;
                    315:     default:
                    316:     badreg:
1.1.1.3   root      317:         hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
1.1       root      318:     }
                    319: }
                    320: 
1.1.1.4   root      321: static CPUReadMemoryFunc * const pxa2xx_timer_readfn[] = {
1.1       root      322:     pxa2xx_timer_read,
                    323:     pxa2xx_timer_read,
                    324:     pxa2xx_timer_read,
                    325: };
                    326: 
1.1.1.4   root      327: static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
1.1       root      328:     pxa2xx_timer_write,
                    329:     pxa2xx_timer_write,
                    330:     pxa2xx_timer_write,
                    331: };
                    332: 
                    333: static void pxa2xx_timer_tick(void *opaque)
                    334: {
1.1.1.3   root      335:     PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
1.1       root      336:     pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
                    337: 
                    338:     if (i->irq_enabled & (1 << t->num)) {
                    339:         t->level = 1;
                    340:         i->events |= 1 << t->num;
                    341:         qemu_irq_raise(t->irq);
                    342:     }
                    343: 
                    344:     if (t->num == 3)
                    345:         if (i->reset3 & 1) {
                    346:             i->reset3 = 0;
                    347:             qemu_system_reset_request();
                    348:         }
                    349: }
                    350: 
                    351: static void pxa2xx_timer_tick4(void *opaque)
                    352: {
1.1.1.3   root      353:     PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
1.1       root      354:     pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->tm.info;
                    355: 
                    356:     pxa2xx_timer_tick(&t->tm);
                    357:     if (t->control & (1 << 3))
                    358:         t->clock = 0;
                    359:     if (t->control & (1 << 6))
                    360:         pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
                    361: }
                    362: 
                    363: static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
                    364: {
                    365:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    366:     int i;
                    367: 
1.1.1.2   root      368:     qemu_put_be32s(f, (uint32_t *) &s->clock);
                    369:     qemu_put_be32s(f, (uint32_t *) &s->oldclock);
1.1       root      370:     qemu_put_be64s(f, &s->lastload);
                    371: 
                    372:     for (i = 0; i < 4; i ++) {
                    373:         qemu_put_be32s(f, &s->timer[i].value);
                    374:         qemu_put_be32(f, s->timer[i].level);
                    375:     }
                    376:     if (s->tm4)
                    377:         for (i = 0; i < 8; i ++) {
                    378:             qemu_put_be32s(f, &s->tm4[i].tm.value);
                    379:             qemu_put_be32(f, s->tm4[i].tm.level);
1.1.1.2   root      380:             qemu_put_sbe32s(f, &s->tm4[i].oldclock);
                    381:             qemu_put_sbe32s(f, &s->tm4[i].clock);
1.1       root      382:             qemu_put_be64s(f, &s->tm4[i].lastload);
                    383:             qemu_put_be32s(f, &s->tm4[i].freq);
                    384:             qemu_put_be32s(f, &s->tm4[i].control);
                    385:         }
                    386: 
                    387:     qemu_put_be32s(f, &s->events);
                    388:     qemu_put_be32s(f, &s->irq_enabled);
                    389:     qemu_put_be32s(f, &s->reset3);
                    390:     qemu_put_be32s(f, &s->snapshot);
                    391: }
                    392: 
                    393: static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
                    394: {
                    395:     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
                    396:     int64_t now;
                    397:     int i;
                    398: 
1.1.1.2   root      399:     qemu_get_be32s(f, (uint32_t *) &s->clock);
                    400:     qemu_get_be32s(f, (uint32_t *) &s->oldclock);
1.1       root      401:     qemu_get_be64s(f, &s->lastload);
                    402: 
                    403:     now = qemu_get_clock(vm_clock);
                    404:     for (i = 0; i < 4; i ++) {
                    405:         qemu_get_be32s(f, &s->timer[i].value);
                    406:         s->timer[i].level = qemu_get_be32(f);
                    407:     }
                    408:     pxa2xx_timer_update(s, now);
                    409: 
                    410:     if (s->tm4)
                    411:         for (i = 0; i < 8; i ++) {
                    412:             qemu_get_be32s(f, &s->tm4[i].tm.value);
                    413:             s->tm4[i].tm.level = qemu_get_be32(f);
1.1.1.2   root      414:             qemu_get_sbe32s(f, &s->tm4[i].oldclock);
                    415:             qemu_get_sbe32s(f, &s->tm4[i].clock);
1.1       root      416:             qemu_get_be64s(f, &s->tm4[i].lastload);
                    417:             qemu_get_be32s(f, &s->tm4[i].freq);
                    418:             qemu_get_be32s(f, &s->tm4[i].control);
                    419:             pxa2xx_timer_update4(s, now, i);
                    420:         }
                    421: 
                    422:     qemu_get_be32s(f, &s->events);
                    423:     qemu_get_be32s(f, &s->irq_enabled);
                    424:     qemu_get_be32s(f, &s->reset3);
                    425:     qemu_get_be32s(f, &s->snapshot);
                    426: 
                    427:     return 0;
                    428: }
                    429: 
                    430: static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
                    431:                 qemu_irq *irqs)
                    432: {
                    433:     int i;
                    434:     int iomemtype;
                    435:     pxa2xx_timer_info *s;
                    436: 
                    437:     s = (pxa2xx_timer_info *) qemu_mallocz(sizeof(pxa2xx_timer_info));
                    438:     s->irq_enabled = 0;
                    439:     s->oldclock = 0;
                    440:     s->clock = 0;
                    441:     s->lastload = qemu_get_clock(vm_clock);
                    442:     s->reset3 = 0;
                    443: 
                    444:     for (i = 0; i < 4; i ++) {
                    445:         s->timer[i].value = 0;
                    446:         s->timer[i].irq = irqs[i];
                    447:         s->timer[i].info = s;
                    448:         s->timer[i].num = i;
                    449:         s->timer[i].level = 0;
                    450:         s->timer[i].qtimer = qemu_new_timer(vm_clock,
                    451:                         pxa2xx_timer_tick, &s->timer[i]);
                    452:     }
                    453: 
1.1.1.3   root      454:     iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
1.1       root      455:                     pxa2xx_timer_writefn, s);
                    456:     cpu_register_physical_memory(base, 0x00001000, iomemtype);
                    457: 
1.1.1.5 ! root      458:     register_savevm(NULL, "pxa2xx_timer", 0, 0,
1.1       root      459:                     pxa2xx_timer_save, pxa2xx_timer_load, s);
                    460: 
                    461:     return s;
                    462: }
                    463: 
                    464: void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs)
                    465: {
                    466:     pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
                    467:     s->freq = PXA25X_FREQ;
1.1.1.4   root      468:     s->tm4 = NULL;
1.1       root      469: }
                    470: 
                    471: void pxa27x_timer_init(target_phys_addr_t base,
                    472:                 qemu_irq *irqs, qemu_irq irq4)
                    473: {
                    474:     pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
                    475:     int i;
                    476:     s->freq = PXA27X_FREQ;
1.1.1.3   root      477:     s->tm4 = (PXA2xxTimer4 *) qemu_mallocz(8 *
                    478:                     sizeof(PXA2xxTimer4));
1.1       root      479:     for (i = 0; i < 8; i ++) {
                    480:         s->tm4[i].tm.value = 0;
                    481:         s->tm4[i].tm.irq = irq4;
                    482:         s->tm4[i].tm.info = s;
                    483:         s->tm4[i].tm.num = i + 4;
                    484:         s->tm4[i].tm.level = 0;
                    485:         s->tm4[i].freq = 0;
                    486:         s->tm4[i].control = 0x0;
                    487:         s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
                    488:                         pxa2xx_timer_tick4, &s->tm4[i]);
                    489:     }
                    490: }

unix.superglobalmegacorp.com

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