4 * Copyright (c) 2009 Filip Navara
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"
30 #define RTT_MR 0x00 /* Mode Register */
31 #define RTT_AR 0x04 /* Alarm Register */
32 #define RTT_VR 0x08 /* Value Register */
33 #define RTT_SR 0x0c /* Status Register */
35 #define MR_ALMIEN 0x10000
36 #define MR_RTTINCIEN 0x20000
37 #define MR_RTTRST 0x40000
40 #define SR_RTTINC 0x02
42 typedef struct RTTState
{
52 static void at91_rtt_tick(void *opaque
)
58 if (s
->ar
!= ~0 && s
->vr
== s
->ar
+ 1) {
61 if (((s
->sr
& SR_RTTINC
) && (s
->mr
& MR_RTTINCIEN
)) ||
62 ((s
->sr
& SR_ALMS
) && (s
->mr
& MR_ALMIEN
))) {
63 qemu_set_irq(s
->irq
, 1);
67 static uint32_t at91_rtt_mem_read(void *opaque
, target_phys_addr_t offset
)
72 offset
&= RTT_SIZE
- 1;
82 qemu_set_irq(s
->irq
, 0);
90 static void at91_rtt_mem_write(void *opaque
, target_phys_addr_t offset
,
95 offset
&= RTT_SIZE
- 1;
98 if (value
& MR_RTTRST
) {
100 if ((value
& 0xffff) == 0) {
101 ptimer_set_freq(s
->timer
, 1);
103 ptimer_set_freq(s
->timer
, 0x8000 / (value
& 0xffff));
114 static CPUReadMemoryFunc
*at91_rtt_readfn
[] = {
120 static CPUWriteMemoryFunc
*at91_rtt_writefn
[] = {
126 static void at91_rtt_save(QEMUFile
*f
, void *opaque
)
128 RTTState
*s
= opaque
;
130 qemu_put_be32(f
, s
->mr
);
131 qemu_put_be32(f
, s
->ar
);
132 qemu_put_be32(f
, s
->vr
);
133 qemu_put_be32(f
, s
->sr
);
134 qemu_put_ptimer(f
, s
->timer
);
137 static int at91_rtt_load(QEMUFile
*f
, void *opaque
, int version_id
)
139 RTTState
*s
= opaque
;
144 s
->mr
= qemu_get_be32(f
);
145 s
->ar
= qemu_get_be32(f
);
146 s
->vr
= qemu_get_be32(f
);
147 s
->sr
= qemu_get_be32(f
);
148 qemu_get_ptimer(f
, s
->timer
);
153 static void at91_rtt_reset(void *opaque
)
155 RTTState
*s
= opaque
;
163 static void at91_rtt_init(SysBusDevice
*dev
)
165 RTTState
*s
= FROM_SYSBUS(typeof (*s
), dev
);
171 bh
= qemu_bh_new(at91_rtt_tick
, s
);
172 s
->timer
= ptimer_init(bh
);
173 ptimer_set_freq(s
->timer
, 1);
174 ptimer_set_limit(s
->timer
, 1, 1);
175 ptimer_run(s
->timer
, 0);
177 sysbus_init_irq(dev
, &s
->irq
);
179 rtt_regs
= cpu_register_io_memory(at91_rtt_readfn
, at91_rtt_writefn
, s
);
180 sysbus_init_mmio(dev
, RTT_SIZE
, rtt_regs
);
182 qemu_register_reset(at91_rtt_reset
, s
);
184 register_savevm("at91_rtt", -1, 1, at91_rtt_save
, at91_rtt_load
, s
);
187 static void at91_rtt_register(void)
189 sysbus_register_dev("at91,rtt", sizeof(RTTState
), at91_rtt_init
);
192 device_init(at91_rtt_register
)