qemu/hw/timer/lm32_timer.c
<<
>>
Prefs
   1/*
   2 *  QEMU model of the LatticeMico32 timer block.
   3 *
   4 *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 *
  19 *
  20 * Specification available at:
  21 *   http://www.latticesemi.com/documents/mico32timer.pdf
  22 */
  23
  24#include "qemu/osdep.h"
  25#include "hw/hw.h"
  26#include "hw/sysbus.h"
  27#include "trace.h"
  28#include "qemu/timer.h"
  29#include "hw/ptimer.h"
  30#include "qemu/error-report.h"
  31#include "qemu/main-loop.h"
  32#include "qemu/module.h"
  33
  34#define DEFAULT_FREQUENCY (50*1000000)
  35
  36enum {
  37    R_SR = 0,
  38    R_CR,
  39    R_PERIOD,
  40    R_SNAPSHOT,
  41    R_MAX
  42};
  43
  44enum {
  45    SR_TO    = (1 << 0),
  46    SR_RUN   = (1 << 1),
  47};
  48
  49enum {
  50    CR_ITO   = (1 << 0),
  51    CR_CONT  = (1 << 1),
  52    CR_START = (1 << 2),
  53    CR_STOP  = (1 << 3),
  54};
  55
  56#define TYPE_LM32_TIMER "lm32-timer"
  57#define LM32_TIMER(obj) OBJECT_CHECK(LM32TimerState, (obj), TYPE_LM32_TIMER)
  58
  59struct LM32TimerState {
  60    SysBusDevice parent_obj;
  61
  62    MemoryRegion iomem;
  63
  64    QEMUBH *bh;
  65    ptimer_state *ptimer;
  66
  67    qemu_irq irq;
  68    uint32_t freq_hz;
  69
  70    uint32_t regs[R_MAX];
  71};
  72typedef struct LM32TimerState LM32TimerState;
  73
  74static void timer_update_irq(LM32TimerState *s)
  75{
  76    int state = (s->regs[R_SR] & SR_TO) && (s->regs[R_CR] & CR_ITO);
  77
  78    trace_lm32_timer_irq_state(state);
  79    qemu_set_irq(s->irq, state);
  80}
  81
  82static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
  83{
  84    LM32TimerState *s = opaque;
  85    uint32_t r = 0;
  86
  87    addr >>= 2;
  88    switch (addr) {
  89    case R_SR:
  90    case R_CR:
  91    case R_PERIOD:
  92        r = s->regs[addr];
  93        break;
  94    case R_SNAPSHOT:
  95        r = (uint32_t)ptimer_get_count(s->ptimer);
  96        break;
  97    default:
  98        error_report("lm32_timer: read access to unknown register 0x"
  99                TARGET_FMT_plx, addr << 2);
 100        break;
 101    }
 102
 103    trace_lm32_timer_memory_read(addr << 2, r);
 104    return r;
 105}
 106
 107static void timer_write(void *opaque, hwaddr addr,
 108                        uint64_t value, unsigned size)
 109{
 110    LM32TimerState *s = opaque;
 111
 112    trace_lm32_timer_memory_write(addr, value);
 113
 114    addr >>= 2;
 115    switch (addr) {
 116    case R_SR:
 117        s->regs[R_SR] &= ~SR_TO;
 118        break;
 119    case R_CR:
 120        s->regs[R_CR] = value;
 121        if (s->regs[R_CR] & CR_START) {
 122            ptimer_run(s->ptimer, 1);
 123        }
 124        if (s->regs[R_CR] & CR_STOP) {
 125            ptimer_stop(s->ptimer);
 126        }
 127        break;
 128    case R_PERIOD:
 129        s->regs[R_PERIOD] = value;
 130        ptimer_set_count(s->ptimer, value);
 131        break;
 132    case R_SNAPSHOT:
 133        error_report("lm32_timer: write access to read only register 0x"
 134                TARGET_FMT_plx, addr << 2);
 135        break;
 136    default:
 137        error_report("lm32_timer: write access to unknown register 0x"
 138                TARGET_FMT_plx, addr << 2);
 139        break;
 140    }
 141    timer_update_irq(s);
 142}
 143
 144static const MemoryRegionOps timer_ops = {
 145    .read = timer_read,
 146    .write = timer_write,
 147    .endianness = DEVICE_NATIVE_ENDIAN,
 148    .valid = {
 149        .min_access_size = 4,
 150        .max_access_size = 4,
 151    },
 152};
 153
 154static void timer_hit(void *opaque)
 155{
 156    LM32TimerState *s = opaque;
 157
 158    trace_lm32_timer_hit();
 159
 160    s->regs[R_SR] |= SR_TO;
 161
 162    if (s->regs[R_CR] & CR_CONT) {
 163        ptimer_set_count(s->ptimer, s->regs[R_PERIOD]);
 164        ptimer_run(s->ptimer, 1);
 165    }
 166    timer_update_irq(s);
 167}
 168
 169static void timer_reset(DeviceState *d)
 170{
 171    LM32TimerState *s = LM32_TIMER(d);
 172    int i;
 173
 174    for (i = 0; i < R_MAX; i++) {
 175        s->regs[i] = 0;
 176    }
 177    ptimer_stop(s->ptimer);
 178}
 179
 180static void lm32_timer_init(Object *obj)
 181{
 182    LM32TimerState *s = LM32_TIMER(obj);
 183    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
 184
 185    sysbus_init_irq(dev, &s->irq);
 186
 187    s->bh = qemu_bh_new(timer_hit, s);
 188    s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
 189
 190    memory_region_init_io(&s->iomem, obj, &timer_ops, s,
 191                          "timer", R_MAX * 4);
 192    sysbus_init_mmio(dev, &s->iomem);
 193}
 194
 195static void lm32_timer_realize(DeviceState *dev, Error **errp)
 196{
 197    LM32TimerState *s = LM32_TIMER(dev);
 198
 199    ptimer_set_freq(s->ptimer, s->freq_hz);
 200}
 201
 202static const VMStateDescription vmstate_lm32_timer = {
 203    .name = "lm32-timer",
 204    .version_id = 1,
 205    .minimum_version_id = 1,
 206    .fields = (VMStateField[]) {
 207        VMSTATE_PTIMER(ptimer, LM32TimerState),
 208        VMSTATE_UINT32(freq_hz, LM32TimerState),
 209        VMSTATE_UINT32_ARRAY(regs, LM32TimerState, R_MAX),
 210        VMSTATE_END_OF_LIST()
 211    }
 212};
 213
 214static Property lm32_timer_properties[] = {
 215    DEFINE_PROP_UINT32("frequency", LM32TimerState, freq_hz, DEFAULT_FREQUENCY),
 216    DEFINE_PROP_END_OF_LIST(),
 217};
 218
 219static void lm32_timer_class_init(ObjectClass *klass, void *data)
 220{
 221    DeviceClass *dc = DEVICE_CLASS(klass);
 222
 223    dc->realize = lm32_timer_realize;
 224    dc->reset = timer_reset;
 225    dc->vmsd = &vmstate_lm32_timer;
 226    dc->props = lm32_timer_properties;
 227}
 228
 229static const TypeInfo lm32_timer_info = {
 230    .name          = TYPE_LM32_TIMER,
 231    .parent        = TYPE_SYS_BUS_DEVICE,
 232    .instance_size = sizeof(LM32TimerState),
 233    .instance_init = lm32_timer_init,
 234    .class_init    = lm32_timer_class_init,
 235};
 236
 237static void lm32_timer_register_types(void)
 238{
 239    type_register_static(&lm32_timer_info);
 240}
 241
 242type_init(lm32_timer_register_types)
 243