2
* QEMU model of the Xilinx timer block.
4
* Copyright (c) 2009 Edgar E. Iglesias.
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:
13
* The above copyright notice and this permission notice shall be included in
14
* all copies or substantial portions of the Software.
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
26
#include "qemu-timer.h"
35
#define TCSR_MDT (1<<0)
36
#define TCSR_UDT (1<<1)
37
#define TCSR_GENT (1<<2)
38
#define TCSR_CAPT (1<<3)
39
#define TCSR_ARHT (1<<4)
40
#define TCSR_LOAD (1<<5)
41
#define TCSR_ENIT (1<<6)
42
#define TCSR_ENT (1<<7)
43
#define TCSR_TINT (1<<8)
44
#define TCSR_PWMA (1<<9)
45
#define TCSR_ENALL (1<<10)
52
int nr; /* for debug. */
54
unsigned long timer_div;
66
struct xlx_timer *timers;
69
static inline unsigned int timer_from_addr(target_phys_addr_t addr)
71
/* Timers get a 4x32bit control reg area each. */
75
static void timer_update_irq(struct timerblock *t)
77
unsigned int i, irq = 0;
80
for (i = 0; i < t->nr_timers; i++) {
81
csr = t->timers[i].regs[R_TCSR];
82
irq |= (csr & TCSR_TINT) && (csr & TCSR_ENIT);
85
/* All timers within the same slave share a single IRQ line. */
86
qemu_set_irq(t->irq, !!irq);
90
timer_read(void *opaque, target_phys_addr_t addr, unsigned int size)
92
struct timerblock *t = opaque;
98
timer = timer_from_addr(addr);
99
xt = &t->timers[timer];
100
/* Further decoding to address a specific timers reg. */
105
r = ptimer_get_count(xt->ptimer);
106
if (!(xt->regs[R_TCSR] & TCSR_UDT))
108
D(qemu_log("xlx_timer t=%d read counter=%x udt=%d\n",
109
timer, r, xt->regs[R_TCSR] & TCSR_UDT));
112
if (addr < ARRAY_SIZE(xt->regs))
117
D(printf("%s timer=%d %x=%x\n", __func__, timer, addr * 4, r));
121
static void timer_enable(struct xlx_timer *xt)
125
D(printf("%s timer=%d down=%d\n", __func__,
126
xt->nr, xt->regs[R_TCSR] & TCSR_UDT));
128
ptimer_stop(xt->ptimer);
130
if (xt->regs[R_TCSR] & TCSR_UDT)
131
count = xt->regs[R_TLR];
133
count = ~0 - xt->regs[R_TLR];
134
ptimer_set_count(xt->ptimer, count);
135
ptimer_run(xt->ptimer, 1);
139
timer_write(void *opaque, target_phys_addr_t addr,
140
uint64_t val64, unsigned int size)
142
struct timerblock *t = opaque;
143
struct xlx_timer *xt;
145
uint32_t value = val64;
148
timer = timer_from_addr(addr);
149
xt = &t->timers[timer];
150
D(printf("%s addr=%x val=%x (timer=%d off=%d)\n",
151
__func__, addr * 4, value, timer, addr & 3));
152
/* Further decoding to address a specific timers reg. */
157
if (value & TCSR_TINT)
160
xt->regs[addr] = value;
161
if (value & TCSR_ENT)
166
if (addr < ARRAY_SIZE(xt->regs))
167
xt->regs[addr] = value;
173
static const MemoryRegionOps timer_ops = {
175
.write = timer_write,
176
.endianness = DEVICE_NATIVE_ENDIAN,
178
.min_access_size = 4,
183
static void timer_hit(void *opaque)
185
struct xlx_timer *xt = opaque;
186
struct timerblock *t = xt->parent;
187
D(printf("%s %d\n", __func__, timer));
188
xt->regs[R_TCSR] |= TCSR_TINT;
190
if (xt->regs[R_TCSR] & TCSR_ARHT)
195
static int xilinx_timer_init(SysBusDevice *dev)
197
struct timerblock *t = FROM_SYSBUS(typeof (*t), dev);
200
/* All timers share a single irq line. */
201
sysbus_init_irq(dev, &t->irq);
203
/* Init all the ptimers. */
204
t->timers = g_malloc0(sizeof t->timers[0] * t->nr_timers);
205
for (i = 0; i < t->nr_timers; i++) {
206
struct xlx_timer *xt = &t->timers[i];
210
xt->bh = qemu_bh_new(timer_hit, xt);
211
xt->ptimer = ptimer_init(xt->bh);
212
ptimer_set_freq(xt->ptimer, t->freq_hz);
215
memory_region_init_io(&t->mmio, &timer_ops, t, "xilinx-timer",
216
R_MAX * 4 * t->nr_timers);
217
sysbus_init_mmio_region(dev, &t->mmio);
221
static SysBusDeviceInfo xilinx_timer_info = {
222
.init = xilinx_timer_init,
223
.qdev.name = "xilinx,timer",
224
.qdev.size = sizeof(struct timerblock),
225
.qdev.props = (Property[]) {
226
DEFINE_PROP_UINT32("frequency", struct timerblock, freq_hz, 0),
227
DEFINE_PROP_UINT32("nr-timers", struct timerblock, nr_timers, 0),
228
DEFINE_PROP_END_OF_LIST(),
232
static void xilinx_timer_register(void)
234
sysbus_register_withprop(&xilinx_timer_info);
237
device_init(xilinx_timer_register)