2
* QEMU model of the LatticeMico32 timer block.
4
* Copyright (c) 2010 Michael Walle <michael@walle.cc>
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.
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.
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/>.
20
* Specification available at:
21
* http://www.latticesemi.com/documents/mico32timer.pdf
27
#include "qemu-timer.h"
28
#include "qemu-error.h"
30
#define DEFAULT_FREQUENCY (50*1000000)
52
struct LM32TimerState {
63
typedef struct LM32TimerState LM32TimerState;
65
static void timer_update_irq(LM32TimerState *s)
67
int state = (s->regs[R_SR] & SR_TO) && (s->regs[R_CR] & CR_ITO);
69
trace_lm32_timer_irq_state(state);
70
qemu_set_irq(s->irq, state);
73
static uint32_t timer_read(void *opaque, target_phys_addr_t addr)
75
LM32TimerState *s = opaque;
86
r = (uint32_t)ptimer_get_count(s->ptimer);
89
error_report("lm32_timer: read access to unknown register 0x"
90
TARGET_FMT_plx, addr << 2);
94
trace_lm32_timer_memory_read(addr << 2, r);
98
static void timer_write(void *opaque, target_phys_addr_t addr, uint32_t value)
100
LM32TimerState *s = opaque;
102
trace_lm32_timer_memory_write(addr, value);
107
s->regs[R_SR] &= ~SR_TO;
110
s->regs[R_CR] = value;
111
if (s->regs[R_CR] & CR_START) {
112
ptimer_run(s->ptimer, 1);
114
if (s->regs[R_CR] & CR_STOP) {
115
ptimer_stop(s->ptimer);
119
s->regs[R_PERIOD] = value;
120
ptimer_set_count(s->ptimer, value);
123
error_report("lm32_timer: write access to read only register 0x"
124
TARGET_FMT_plx, addr << 2);
127
error_report("lm32_timer: write access to unknown register 0x"
128
TARGET_FMT_plx, addr << 2);
134
static CPUReadMemoryFunc * const timer_read_fn[] = {
140
static CPUWriteMemoryFunc * const timer_write_fn[] = {
146
static void timer_hit(void *opaque)
148
LM32TimerState *s = opaque;
150
trace_lm32_timer_hit();
152
s->regs[R_SR] |= SR_TO;
154
if (s->regs[R_CR] & CR_CONT) {
155
ptimer_set_count(s->ptimer, s->regs[R_PERIOD]);
156
ptimer_run(s->ptimer, 1);
161
static void timer_reset(DeviceState *d)
163
LM32TimerState *s = container_of(d, LM32TimerState, busdev.qdev);
166
for (i = 0; i < R_MAX; i++) {
169
ptimer_stop(s->ptimer);
172
static int lm32_timer_init(SysBusDevice *dev)
174
LM32TimerState *s = FROM_SYSBUS(typeof(*s), dev);
177
sysbus_init_irq(dev, &s->irq);
179
s->bh = qemu_bh_new(timer_hit, s);
180
s->ptimer = ptimer_init(s->bh);
181
ptimer_set_freq(s->ptimer, s->freq_hz);
183
timer_regs = cpu_register_io_memory(timer_read_fn, timer_write_fn, s,
184
DEVICE_NATIVE_ENDIAN);
185
sysbus_init_mmio(dev, R_MAX * 4, timer_regs);
190
static const VMStateDescription vmstate_lm32_timer = {
191
.name = "lm32-timer",
193
.minimum_version_id = 1,
194
.minimum_version_id_old = 1,
195
.fields = (VMStateField[]) {
196
VMSTATE_PTIMER(ptimer, LM32TimerState),
197
VMSTATE_UINT32(freq_hz, LM32TimerState),
198
VMSTATE_UINT32_ARRAY(regs, LM32TimerState, R_MAX),
199
VMSTATE_END_OF_LIST()
203
static SysBusDeviceInfo lm32_timer_info = {
204
.init = lm32_timer_init,
205
.qdev.name = "lm32-timer",
206
.qdev.size = sizeof(LM32TimerState),
207
.qdev.vmsd = &vmstate_lm32_timer,
208
.qdev.reset = timer_reset,
209
.qdev.props = (Property[]) {
211
"frequency", LM32TimerState, freq_hz, DEFAULT_FREQUENCY
213
DEFINE_PROP_END_OF_LIST(),
217
static void lm32_timer_register(void)
219
sysbus_register_withprop(&lm32_timer_info);
222
device_init(lm32_timer_register)