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

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"
                     27: 
                     28: #include "trace.h"
                     29: 
                     30: #define UNIT_REG_SIZE    16     /* Size of memory mapped regs for the unit */
                     31: #define GPTIMER_REG_SIZE 16     /* Size of memory mapped regs for a GPTimer */
                     32: 
                     33: #define GPTIMER_MAX_TIMERS 8
                     34: 
                     35: /* GPTimer Config register fields */
                     36: #define GPTIMER_ENABLE      (1 << 0)
                     37: #define GPTIMER_RESTART     (1 << 1)
                     38: #define GPTIMER_LOAD        (1 << 2)
                     39: #define GPTIMER_INT_ENABLE  (1 << 3)
                     40: #define GPTIMER_INT_PENDING (1 << 4)
                     41: #define GPTIMER_CHAIN       (1 << 5) /* Not supported */
                     42: #define GPTIMER_DEBUG_HALT  (1 << 6) /* Not supported */
                     43: 
                     44: /* Memory mapped register offsets */
                     45: #define SCALER_OFFSET         0x00
                     46: #define SCALER_RELOAD_OFFSET  0x04
                     47: #define CONFIG_OFFSET         0x08
                     48: #define COUNTER_OFFSET        0x00
                     49: #define COUNTER_RELOAD_OFFSET 0x04
                     50: #define TIMER_BASE            0x10
                     51: 
                     52: typedef struct GPTimer     GPTimer;
                     53: typedef struct GPTimerUnit GPTimerUnit;
                     54: 
                     55: struct GPTimer {
                     56:     QEMUBH *bh;
                     57:     struct ptimer_state *ptimer;
                     58: 
                     59:     qemu_irq     irq;
                     60:     int          id;
                     61:     GPTimerUnit *unit;
                     62: 
                     63:     /* registers */
                     64:     uint32_t counter;
                     65:     uint32_t reload;
                     66:     uint32_t config;
                     67: };
                     68: 
                     69: struct GPTimerUnit {
                     70:     SysBusDevice  busdev;
                     71: 
                     72:     uint32_t nr_timers;         /* Number of timers available */
                     73:     uint32_t freq_hz;           /* System frequency */
                     74:     uint32_t irq_line;          /* Base irq line */
                     75: 
                     76:     GPTimer *timers;
                     77: 
                     78:     /* registers */
                     79:     uint32_t scaler;
                     80:     uint32_t reload;
                     81:     uint32_t config;
                     82: };
                     83: 
                     84: static void grlib_gptimer_enable(GPTimer *timer)
                     85: {
                     86:     assert(timer != NULL);
                     87: 
                     88: 
                     89:     ptimer_stop(timer->ptimer);
                     90: 
                     91:     if (!(timer->config & GPTIMER_ENABLE)) {
                     92:         /* Timer disabled */
                     93:         trace_grlib_gptimer_disabled(timer->id, timer->config);
                     94:         return;
                     95:     }
                     96: 
                     97:     /* ptimer is triggered when the counter reach 0 but GPTimer is triggered at
                     98:        underflow. Set count + 1 to simulate the GPTimer behavior. */
                     99: 
                    100:     trace_grlib_gptimer_enable(timer->id, timer->counter + 1);
                    101: 
                    102:     ptimer_set_count(timer->ptimer, timer->counter + 1);
                    103:     ptimer_run(timer->ptimer, 1);
                    104: }
                    105: 
                    106: static void grlib_gptimer_restart(GPTimer *timer)
                    107: {
                    108:     assert(timer != NULL);
                    109: 
                    110:     trace_grlib_gptimer_restart(timer->id, timer->reload);
                    111: 
                    112:     timer->counter = timer->reload;
                    113:     grlib_gptimer_enable(timer);
                    114: }
                    115: 
                    116: static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler)
                    117: {
                    118:     int i = 0;
                    119:     uint32_t value = 0;
                    120: 
                    121:     assert(unit != NULL);
                    122: 
                    123:     if (scaler > 0) {
                    124:         value = unit->freq_hz / (scaler + 1);
                    125:     } else {
                    126:         value = unit->freq_hz;
                    127:     }
                    128: 
                    129:     trace_grlib_gptimer_set_scaler(scaler, value);
                    130: 
                    131:     for (i = 0; i < unit->nr_timers; i++) {
                    132:         ptimer_set_freq(unit->timers[i].ptimer, value);
                    133:     }
                    134: }
                    135: 
                    136: static void grlib_gptimer_hit(void *opaque)
                    137: {
                    138:     GPTimer *timer = opaque;
                    139:     assert(timer != NULL);
                    140: 
                    141:     trace_grlib_gptimer_hit(timer->id);
                    142: 
                    143:     /* Timer expired */
                    144: 
                    145:     if (timer->config & GPTIMER_INT_ENABLE) {
                    146:         /* Set the pending bit (only unset by write in the config register) */
                    147:         timer->config |= GPTIMER_INT_PENDING;
                    148:         qemu_irq_pulse(timer->irq);
                    149:     }
                    150: 
                    151:     if (timer->config & GPTIMER_RESTART) {
                    152:         grlib_gptimer_restart(timer);
                    153:     }
                    154: }
                    155: 
                    156: static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
                    157: {
                    158:     GPTimerUnit        *unit  = opaque;
                    159:     target_phys_addr_t  timer_addr;
                    160:     int                 id;
                    161:     uint32_t            value = 0;
                    162: 
                    163:     addr &= 0xff;
                    164: 
                    165:     /* Unit registers */
                    166:     switch (addr) {
                    167:     case SCALER_OFFSET:
1.1.1.2 ! root      168:         trace_grlib_gptimer_readl(-1, addr, unit->scaler);
1.1       root      169:         return unit->scaler;
                    170: 
                    171:     case SCALER_RELOAD_OFFSET:
1.1.1.2 ! root      172:         trace_grlib_gptimer_readl(-1, addr, unit->reload);
1.1       root      173:         return unit->reload;
                    174: 
                    175:     case CONFIG_OFFSET:
1.1.1.2 ! root      176:         trace_grlib_gptimer_readl(-1, addr, unit->config);
1.1       root      177:         return unit->config;
                    178: 
                    179:     default:
                    180:         break;
                    181:     }
                    182: 
                    183:     timer_addr = (addr % TIMER_BASE);
                    184:     id         = (addr - TIMER_BASE) / TIMER_BASE;
                    185: 
                    186:     if (id >= 0 && id < unit->nr_timers) {
                    187: 
                    188:         /* GPTimer registers */
                    189:         switch (timer_addr) {
                    190:         case COUNTER_OFFSET:
                    191:             value = ptimer_get_count(unit->timers[id].ptimer);
1.1.1.2 ! root      192:             trace_grlib_gptimer_readl(id, addr, value);
1.1       root      193:             return value;
                    194: 
                    195:         case COUNTER_RELOAD_OFFSET:
                    196:             value = unit->timers[id].reload;
1.1.1.2 ! root      197:             trace_grlib_gptimer_readl(id, addr, value);
1.1       root      198:             return value;
                    199: 
                    200:         case CONFIG_OFFSET:
1.1.1.2 ! root      201:             trace_grlib_gptimer_readl(id, addr, unit->timers[id].config);
1.1       root      202:             return unit->timers[id].config;
                    203: 
                    204:         default:
                    205:             break;
                    206:         }
                    207: 
                    208:     }
                    209: 
1.1.1.2 ! root      210:     trace_grlib_gptimer_readl(-1, addr, 0);
1.1       root      211:     return 0;
                    212: }
                    213: 
                    214: static void
                    215: grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
                    216: {
                    217:     GPTimerUnit        *unit = opaque;
                    218:     target_phys_addr_t  timer_addr;
                    219:     int                 id;
                    220: 
                    221:     addr &= 0xff;
                    222: 
                    223:     /* Unit registers */
                    224:     switch (addr) {
                    225:     case SCALER_OFFSET:
                    226:         value &= 0xFFFF; /* clean up the value */
                    227:         unit->scaler = value;
1.1.1.2 ! root      228:         trace_grlib_gptimer_writel(-1, addr, unit->scaler);
1.1       root      229:         return;
                    230: 
                    231:     case SCALER_RELOAD_OFFSET:
                    232:         value &= 0xFFFF; /* clean up the value */
                    233:         unit->reload = value;
1.1.1.2 ! root      234:         trace_grlib_gptimer_writel(-1, addr, unit->reload);
1.1       root      235:         grlib_gptimer_set_scaler(unit, value);
                    236:         return;
                    237: 
                    238:     case CONFIG_OFFSET:
                    239:         /* Read Only (disable timer freeze not supported) */
1.1.1.2 ! root      240:         trace_grlib_gptimer_writel(-1, addr, 0);
1.1       root      241:         return;
                    242: 
                    243:     default:
                    244:         break;
                    245:     }
                    246: 
                    247:     timer_addr = (addr % TIMER_BASE);
                    248:     id         = (addr - TIMER_BASE) / TIMER_BASE;
                    249: 
                    250:     if (id >= 0 && id < unit->nr_timers) {
                    251: 
                    252:         /* GPTimer registers */
                    253:         switch (timer_addr) {
                    254:         case COUNTER_OFFSET:
1.1.1.2 ! root      255:             trace_grlib_gptimer_writel(id, addr, value);
1.1       root      256:             unit->timers[id].counter = value;
                    257:             grlib_gptimer_enable(&unit->timers[id]);
                    258:             return;
                    259: 
                    260:         case COUNTER_RELOAD_OFFSET:
1.1.1.2 ! root      261:             trace_grlib_gptimer_writel(id, addr, value);
1.1       root      262:             unit->timers[id].reload = value;
                    263:             return;
                    264: 
                    265:         case CONFIG_OFFSET:
1.1.1.2 ! root      266:             trace_grlib_gptimer_writel(id, addr, value);
1.1       root      267: 
                    268:             if (value & GPTIMER_INT_PENDING) {
                    269:                 /* clear pending bit */
                    270:                 value &= ~GPTIMER_INT_PENDING;
                    271:             } else {
                    272:                 /* keep pending bit */
                    273:                 value |= unit->timers[id].config & GPTIMER_INT_PENDING;
                    274:             }
                    275: 
                    276:             unit->timers[id].config = value;
                    277: 
                    278:             /* gptimer_restart calls gptimer_enable, so if "enable" and "load"
                    279:                bits are present, we just have to call restart. */
                    280: 
                    281:             if (value & GPTIMER_LOAD) {
                    282:                 grlib_gptimer_restart(&unit->timers[id]);
                    283:             } else if (value & GPTIMER_ENABLE) {
                    284:                 grlib_gptimer_enable(&unit->timers[id]);
                    285:             }
                    286: 
                    287:             /* These fields must always be read as 0 */
                    288:             value &= ~(GPTIMER_LOAD & GPTIMER_DEBUG_HALT);
                    289: 
                    290:             unit->timers[id].config = value;
                    291:             return;
                    292: 
                    293:         default:
                    294:             break;
                    295:         }
                    296: 
                    297:     }
                    298: 
1.1.1.2 ! root      299:     trace_grlib_gptimer_writel(-1, addr, value);
1.1       root      300: }
                    301: 
                    302: static CPUReadMemoryFunc * const grlib_gptimer_read[] = {
                    303:     NULL, NULL, grlib_gptimer_readl,
                    304: };
                    305: 
                    306: static CPUWriteMemoryFunc * const grlib_gptimer_write[] = {
                    307:     NULL, NULL, grlib_gptimer_writel,
                    308: };
                    309: 
                    310: static void grlib_gptimer_reset(DeviceState *d)
                    311: {
                    312:     GPTimerUnit *unit = container_of(d, GPTimerUnit, busdev.qdev);
                    313:     int          i    = 0;
                    314: 
                    315:     assert(unit != NULL);
                    316: 
                    317:     unit->scaler = 0;
                    318:     unit->reload = 0;
                    319:     unit->config = 0;
                    320: 
                    321:     unit->config  = unit->nr_timers;
                    322:     unit->config |= unit->irq_line << 3;
                    323:     unit->config |= 1 << 8;     /* separate interrupt */
                    324:     unit->config |= 1 << 9;     /* Disable timer freeze */
                    325: 
                    326: 
                    327:     for (i = 0; i < unit->nr_timers; i++) {
                    328:         GPTimer *timer = &unit->timers[i];
                    329: 
                    330:         timer->counter = 0;
                    331:         timer->reload = 0;
                    332:         timer->config = 0;
                    333:         ptimer_stop(timer->ptimer);
                    334:         ptimer_set_count(timer->ptimer, 0);
                    335:         ptimer_set_freq(timer->ptimer, unit->freq_hz);
                    336:     }
                    337: }
                    338: 
                    339: static int grlib_gptimer_init(SysBusDevice *dev)
                    340: {
                    341:     GPTimerUnit  *unit = FROM_SYSBUS(typeof(*unit), dev);
                    342:     unsigned int  i;
                    343:     int           timer_regs;
                    344: 
                    345:     assert(unit->nr_timers > 0);
                    346:     assert(unit->nr_timers <= GPTIMER_MAX_TIMERS);
                    347: 
                    348:     unit->timers = qemu_mallocz(sizeof unit->timers[0] * unit->nr_timers);
                    349: 
                    350:     for (i = 0; i < unit->nr_timers; i++) {
                    351:         GPTimer *timer = &unit->timers[i];
                    352: 
                    353:         timer->unit   = unit;
                    354:         timer->bh     = qemu_bh_new(grlib_gptimer_hit, timer);
                    355:         timer->ptimer = ptimer_init(timer->bh);
                    356:         timer->id     = i;
                    357: 
                    358:         /* One IRQ line for each timer */
                    359:         sysbus_init_irq(dev, &timer->irq);
                    360: 
                    361:         ptimer_set_freq(timer->ptimer, unit->freq_hz);
                    362:     }
                    363: 
                    364:     timer_regs = cpu_register_io_memory(grlib_gptimer_read,
                    365:                                         grlib_gptimer_write,
                    366:                                         unit, DEVICE_NATIVE_ENDIAN);
                    367:     if (timer_regs < 0) {
                    368:         return -1;
                    369:     }
                    370: 
                    371:     sysbus_init_mmio(dev, UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers,
                    372:                      timer_regs);
                    373:     return 0;
                    374: }
                    375: 
                    376: static SysBusDeviceInfo grlib_gptimer_info = {
                    377:     .init       = grlib_gptimer_init,
                    378:     .qdev.name  = "grlib,gptimer",
                    379:     .qdev.reset = grlib_gptimer_reset,
                    380:     .qdev.size  = sizeof(GPTimerUnit),
                    381:     .qdev.props = (Property[]) {
                    382:         DEFINE_PROP_UINT32("frequency", GPTimerUnit, freq_hz,   40000000),
                    383:         DEFINE_PROP_UINT32("irq-line",  GPTimerUnit, irq_line,  8),
                    384:         DEFINE_PROP_UINT32("nr-timers", GPTimerUnit, nr_timers, 2),
                    385:         DEFINE_PROP_END_OF_LIST()
                    386:     }
                    387: };
                    388: 
                    389: static void grlib_gptimer_register(void)
                    390: {
                    391:     sysbus_register_withprop(&grlib_gptimer_info);
                    392: }
                    393: 
                    394: device_init(grlib_gptimer_register)

unix.superglobalmegacorp.com

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