Annotation of qemu/hw/grlib_gptimer.c, revision 1.1.1.4

1.1       root        1: /*
                      2:  * QEMU GRLIB GPTimer Emulator
                      3:  *
                      4:  * Copyright (c) 2010-2011 AdaCore
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: 
                     25: #include "sysbus.h"
                     26: #include "qemu-timer.h"
1.1.1.4 ! root       27: #include "ptimer.h"
1.1       root       28: 
                     29: #include "trace.h"
                     30: 
                     31: #define UNIT_REG_SIZE    16     /* Size of memory mapped regs for the unit */
                     32: #define GPTIMER_REG_SIZE 16     /* Size of memory mapped regs for a GPTimer */
                     33: 
                     34: #define GPTIMER_MAX_TIMERS 8
                     35: 
                     36: /* GPTimer Config register fields */
                     37: #define GPTIMER_ENABLE      (1 << 0)
                     38: #define GPTIMER_RESTART     (1 << 1)
                     39: #define GPTIMER_LOAD        (1 << 2)
                     40: #define GPTIMER_INT_ENABLE  (1 << 3)
                     41: #define GPTIMER_INT_PENDING (1 << 4)
                     42: #define GPTIMER_CHAIN       (1 << 5) /* Not supported */
                     43: #define GPTIMER_DEBUG_HALT  (1 << 6) /* Not supported */
                     44: 
                     45: /* Memory mapped register offsets */
                     46: #define SCALER_OFFSET         0x00
                     47: #define SCALER_RELOAD_OFFSET  0x04
                     48: #define CONFIG_OFFSET         0x08
                     49: #define COUNTER_OFFSET        0x00
                     50: #define COUNTER_RELOAD_OFFSET 0x04
                     51: #define TIMER_BASE            0x10
                     52: 
                     53: typedef struct GPTimer     GPTimer;
                     54: typedef struct GPTimerUnit GPTimerUnit;
                     55: 
                     56: struct GPTimer {
                     57:     QEMUBH *bh;
                     58:     struct ptimer_state *ptimer;
                     59: 
                     60:     qemu_irq     irq;
                     61:     int          id;
                     62:     GPTimerUnit *unit;
                     63: 
                     64:     /* registers */
                     65:     uint32_t counter;
                     66:     uint32_t reload;
                     67:     uint32_t config;
                     68: };
                     69: 
                     70: struct GPTimerUnit {
                     71:     SysBusDevice  busdev;
1.1.1.4 ! root       72:     MemoryRegion iomem;
1.1       root       73: 
                     74:     uint32_t nr_timers;         /* Number of timers available */
                     75:     uint32_t freq_hz;           /* System frequency */
                     76:     uint32_t irq_line;          /* Base irq line */
                     77: 
                     78:     GPTimer *timers;
                     79: 
                     80:     /* registers */
                     81:     uint32_t scaler;
                     82:     uint32_t reload;
                     83:     uint32_t config;
                     84: };
                     85: 
                     86: static void grlib_gptimer_enable(GPTimer *timer)
                     87: {
                     88:     assert(timer != NULL);
                     89: 
                     90: 
                     91:     ptimer_stop(timer->ptimer);
                     92: 
                     93:     if (!(timer->config & GPTIMER_ENABLE)) {
                     94:         /* Timer disabled */
                     95:         trace_grlib_gptimer_disabled(timer->id, timer->config);
                     96:         return;
                     97:     }
                     98: 
                     99:     /* ptimer is triggered when the counter reach 0 but GPTimer is triggered at
                    100:        underflow. Set count + 1 to simulate the GPTimer behavior. */
                    101: 
                    102:     trace_grlib_gptimer_enable(timer->id, timer->counter + 1);
                    103: 
                    104:     ptimer_set_count(timer->ptimer, timer->counter + 1);
                    105:     ptimer_run(timer->ptimer, 1);
                    106: }
                    107: 
                    108: static void grlib_gptimer_restart(GPTimer *timer)
                    109: {
                    110:     assert(timer != NULL);
                    111: 
                    112:     trace_grlib_gptimer_restart(timer->id, timer->reload);
                    113: 
                    114:     timer->counter = timer->reload;
                    115:     grlib_gptimer_enable(timer);
                    116: }
                    117: 
                    118: static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler)
                    119: {
                    120:     int i = 0;
                    121:     uint32_t value = 0;
                    122: 
                    123:     assert(unit != NULL);
                    124: 
                    125:     if (scaler > 0) {
                    126:         value = unit->freq_hz / (scaler + 1);
                    127:     } else {
                    128:         value = unit->freq_hz;
                    129:     }
                    130: 
                    131:     trace_grlib_gptimer_set_scaler(scaler, value);
                    132: 
                    133:     for (i = 0; i < unit->nr_timers; i++) {
                    134:         ptimer_set_freq(unit->timers[i].ptimer, value);
                    135:     }
                    136: }
                    137: 
                    138: static void grlib_gptimer_hit(void *opaque)
                    139: {
                    140:     GPTimer *timer = opaque;
                    141:     assert(timer != NULL);
                    142: 
                    143:     trace_grlib_gptimer_hit(timer->id);
                    144: 
                    145:     /* Timer expired */
                    146: 
                    147:     if (timer->config & GPTIMER_INT_ENABLE) {
                    148:         /* Set the pending bit (only unset by write in the config register) */
                    149:         timer->config |= GPTIMER_INT_PENDING;
                    150:         qemu_irq_pulse(timer->irq);
                    151:     }
                    152: 
                    153:     if (timer->config & GPTIMER_RESTART) {
                    154:         grlib_gptimer_restart(timer);
                    155:     }
                    156: }
                    157: 
1.1.1.4 ! root      158: static uint64_t grlib_gptimer_read(void *opaque, target_phys_addr_t addr,
        !           159:                                    unsigned size)
1.1       root      160: {
                    161:     GPTimerUnit        *unit  = opaque;
                    162:     target_phys_addr_t  timer_addr;
                    163:     int                 id;
                    164:     uint32_t            value = 0;
                    165: 
                    166:     addr &= 0xff;
                    167: 
                    168:     /* Unit registers */
                    169:     switch (addr) {
                    170:     case SCALER_OFFSET:
1.1.1.2   root      171:         trace_grlib_gptimer_readl(-1, addr, unit->scaler);
1.1       root      172:         return unit->scaler;
                    173: 
                    174:     case SCALER_RELOAD_OFFSET:
1.1.1.2   root      175:         trace_grlib_gptimer_readl(-1, addr, unit->reload);
1.1       root      176:         return unit->reload;
                    177: 
                    178:     case CONFIG_OFFSET:
1.1.1.2   root      179:         trace_grlib_gptimer_readl(-1, addr, unit->config);
1.1       root      180:         return unit->config;
                    181: 
                    182:     default:
                    183:         break;
                    184:     }
                    185: 
                    186:     timer_addr = (addr % TIMER_BASE);
                    187:     id         = (addr - TIMER_BASE) / TIMER_BASE;
                    188: 
                    189:     if (id >= 0 && id < unit->nr_timers) {
                    190: 
                    191:         /* GPTimer registers */
                    192:         switch (timer_addr) {
                    193:         case COUNTER_OFFSET:
                    194:             value = ptimer_get_count(unit->timers[id].ptimer);
1.1.1.2   root      195:             trace_grlib_gptimer_readl(id, addr, value);
1.1       root      196:             return value;
                    197: 
                    198:         case COUNTER_RELOAD_OFFSET:
                    199:             value = unit->timers[id].reload;
1.1.1.2   root      200:             trace_grlib_gptimer_readl(id, addr, value);
1.1       root      201:             return value;
                    202: 
                    203:         case CONFIG_OFFSET:
1.1.1.2   root      204:             trace_grlib_gptimer_readl(id, addr, unit->timers[id].config);
1.1       root      205:             return unit->timers[id].config;
                    206: 
                    207:         default:
                    208:             break;
                    209:         }
                    210: 
                    211:     }
                    212: 
1.1.1.2   root      213:     trace_grlib_gptimer_readl(-1, addr, 0);
1.1       root      214:     return 0;
                    215: }
                    216: 
1.1.1.4 ! root      217: static void grlib_gptimer_write(void *opaque, target_phys_addr_t addr,
        !           218:                                 uint64_t value, unsigned size)
1.1       root      219: {
                    220:     GPTimerUnit        *unit = opaque;
                    221:     target_phys_addr_t  timer_addr;
                    222:     int                 id;
                    223: 
                    224:     addr &= 0xff;
                    225: 
                    226:     /* Unit registers */
                    227:     switch (addr) {
                    228:     case SCALER_OFFSET:
                    229:         value &= 0xFFFF; /* clean up the value */
                    230:         unit->scaler = value;
1.1.1.2   root      231:         trace_grlib_gptimer_writel(-1, addr, unit->scaler);
1.1       root      232:         return;
                    233: 
                    234:     case SCALER_RELOAD_OFFSET:
                    235:         value &= 0xFFFF; /* clean up the value */
                    236:         unit->reload = value;
1.1.1.2   root      237:         trace_grlib_gptimer_writel(-1, addr, unit->reload);
1.1       root      238:         grlib_gptimer_set_scaler(unit, value);
                    239:         return;
                    240: 
                    241:     case CONFIG_OFFSET:
                    242:         /* Read Only (disable timer freeze not supported) */
1.1.1.2   root      243:         trace_grlib_gptimer_writel(-1, addr, 0);
1.1       root      244:         return;
                    245: 
                    246:     default:
                    247:         break;
                    248:     }
                    249: 
                    250:     timer_addr = (addr % TIMER_BASE);
                    251:     id         = (addr - TIMER_BASE) / TIMER_BASE;
                    252: 
                    253:     if (id >= 0 && id < unit->nr_timers) {
                    254: 
                    255:         /* GPTimer registers */
                    256:         switch (timer_addr) {
                    257:         case COUNTER_OFFSET:
1.1.1.2   root      258:             trace_grlib_gptimer_writel(id, addr, value);
1.1       root      259:             unit->timers[id].counter = value;
                    260:             grlib_gptimer_enable(&unit->timers[id]);
                    261:             return;
                    262: 
                    263:         case COUNTER_RELOAD_OFFSET:
1.1.1.2   root      264:             trace_grlib_gptimer_writel(id, addr, value);
1.1       root      265:             unit->timers[id].reload = value;
                    266:             return;
                    267: 
                    268:         case CONFIG_OFFSET:
1.1.1.2   root      269:             trace_grlib_gptimer_writel(id, addr, value);
1.1       root      270: 
                    271:             if (value & GPTIMER_INT_PENDING) {
                    272:                 /* clear pending bit */
                    273:                 value &= ~GPTIMER_INT_PENDING;
                    274:             } else {
                    275:                 /* keep pending bit */
                    276:                 value |= unit->timers[id].config & GPTIMER_INT_PENDING;
                    277:             }
                    278: 
                    279:             unit->timers[id].config = value;
                    280: 
                    281:             /* gptimer_restart calls gptimer_enable, so if "enable" and "load"
                    282:                bits are present, we just have to call restart. */
                    283: 
                    284:             if (value & GPTIMER_LOAD) {
                    285:                 grlib_gptimer_restart(&unit->timers[id]);
                    286:             } else if (value & GPTIMER_ENABLE) {
                    287:                 grlib_gptimer_enable(&unit->timers[id]);
                    288:             }
                    289: 
                    290:             /* These fields must always be read as 0 */
                    291:             value &= ~(GPTIMER_LOAD & GPTIMER_DEBUG_HALT);
                    292: 
                    293:             unit->timers[id].config = value;
                    294:             return;
                    295: 
                    296:         default:
                    297:             break;
                    298:         }
                    299: 
                    300:     }
                    301: 
1.1.1.2   root      302:     trace_grlib_gptimer_writel(-1, addr, value);
1.1       root      303: }
                    304: 
1.1.1.4 ! root      305: static const MemoryRegionOps grlib_gptimer_ops = {
        !           306:     .read = grlib_gptimer_read,
        !           307:     .write = grlib_gptimer_write,
        !           308:     .endianness = DEVICE_NATIVE_ENDIAN,
        !           309:     .valid = {
        !           310:         .min_access_size = 4,
        !           311:         .max_access_size = 4,
        !           312:     },
1.1       root      313: };
                    314: 
                    315: static void grlib_gptimer_reset(DeviceState *d)
                    316: {
                    317:     GPTimerUnit *unit = container_of(d, GPTimerUnit, busdev.qdev);
                    318:     int          i    = 0;
                    319: 
                    320:     assert(unit != NULL);
                    321: 
                    322:     unit->scaler = 0;
                    323:     unit->reload = 0;
                    324:     unit->config = 0;
                    325: 
                    326:     unit->config  = unit->nr_timers;
                    327:     unit->config |= unit->irq_line << 3;
                    328:     unit->config |= 1 << 8;     /* separate interrupt */
                    329:     unit->config |= 1 << 9;     /* Disable timer freeze */
                    330: 
                    331: 
                    332:     for (i = 0; i < unit->nr_timers; i++) {
                    333:         GPTimer *timer = &unit->timers[i];
                    334: 
                    335:         timer->counter = 0;
                    336:         timer->reload = 0;
                    337:         timer->config = 0;
                    338:         ptimer_stop(timer->ptimer);
                    339:         ptimer_set_count(timer->ptimer, 0);
                    340:         ptimer_set_freq(timer->ptimer, unit->freq_hz);
                    341:     }
                    342: }
                    343: 
                    344: static int grlib_gptimer_init(SysBusDevice *dev)
                    345: {
                    346:     GPTimerUnit  *unit = FROM_SYSBUS(typeof(*unit), dev);
                    347:     unsigned int  i;
                    348: 
                    349:     assert(unit->nr_timers > 0);
                    350:     assert(unit->nr_timers <= GPTIMER_MAX_TIMERS);
                    351: 
1.1.1.3   root      352:     unit->timers = g_malloc0(sizeof unit->timers[0] * unit->nr_timers);
1.1       root      353: 
                    354:     for (i = 0; i < unit->nr_timers; i++) {
                    355:         GPTimer *timer = &unit->timers[i];
                    356: 
                    357:         timer->unit   = unit;
                    358:         timer->bh     = qemu_bh_new(grlib_gptimer_hit, timer);
                    359:         timer->ptimer = ptimer_init(timer->bh);
                    360:         timer->id     = i;
                    361: 
                    362:         /* One IRQ line for each timer */
                    363:         sysbus_init_irq(dev, &timer->irq);
                    364: 
                    365:         ptimer_set_freq(timer->ptimer, unit->freq_hz);
                    366:     }
                    367: 
1.1.1.4 ! root      368:     memory_region_init_io(&unit->iomem, &grlib_gptimer_ops, unit, "gptimer",
        !           369:                           UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers);
1.1       root      370: 
1.1.1.4 ! root      371:     sysbus_init_mmio(dev, &unit->iomem);
1.1       root      372:     return 0;
                    373: }
                    374: 
1.1.1.4 ! root      375: static Property grlib_gptimer_properties[] = {
        !           376:     DEFINE_PROP_UINT32("frequency", GPTimerUnit, freq_hz,   40000000),
        !           377:     DEFINE_PROP_UINT32("irq-line",  GPTimerUnit, irq_line,  8),
        !           378:     DEFINE_PROP_UINT32("nr-timers", GPTimerUnit, nr_timers, 2),
        !           379:     DEFINE_PROP_END_OF_LIST(),
        !           380: };
        !           381: 
        !           382: static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
        !           383: {
        !           384:     DeviceClass *dc = DEVICE_CLASS(klass);
        !           385:     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
        !           386: 
        !           387:     k->init = grlib_gptimer_init;
        !           388:     dc->reset = grlib_gptimer_reset;
        !           389:     dc->props = grlib_gptimer_properties;
        !           390: }
        !           391: 
        !           392: static TypeInfo grlib_gptimer_info = {
        !           393:     .name          = "grlib,gptimer",
        !           394:     .parent        = TYPE_SYS_BUS_DEVICE,
        !           395:     .instance_size = sizeof(GPTimerUnit),
        !           396:     .class_init    = grlib_gptimer_class_init,
1.1       root      397: };
                    398: 
1.1.1.4 ! root      399: static void grlib_gptimer_register_types(void)
1.1       root      400: {
1.1.1.4 ! root      401:     type_register_static(&grlib_gptimer_info);
1.1       root      402: }
                    403: 
1.1.1.4 ! root      404: type_init(grlib_gptimer_register_types)

unix.superglobalmegacorp.com

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