Fix the size of the property fields.
[qemu/navara.git] / hw / at91_rtt.c
blobd859865e36ebda77b9c51d8226f2dc4af337e2a1
1 /*
2 * AT91 Real-time Timer
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
22 * THE SOFTWARE.
25 #include "sysbus.h"
26 #include "qemu-timer.h"
28 #define RTT_SIZE 0x10
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
39 #define SR_ALMS 0x01
40 #define SR_RTTINC 0x02
42 typedef struct RTTState {
43 SysBusDevice busdev;
44 qemu_irq irq;
45 ptimer_state *timer;
46 uint32_t mr;
47 uint32_t ar;
48 uint32_t vr;
49 uint32_t sr;
50 } RTTState;
52 static void at91_rtt_tick(void *opaque)
54 RTTState *s = opaque;
56 s->vr++;
57 s->sr |= SR_RTTINC;
58 if (s->ar != ~0 && s->vr == s->ar + 1) {
59 s->sr |= SR_ALMS;
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)
69 RTTState *s = opaque;
70 uint32_t sr;
72 offset &= RTT_SIZE - 1;
73 switch (offset) {
74 case RTT_MR:
75 return s->mr;
76 case RTT_AR:
77 return s->ar;
78 case RTT_VR:
79 return s->vr;
80 case RTT_SR:
81 sr = s->sr;
82 qemu_set_irq(s->irq, 0);
83 s->sr = 0;
84 return sr;
85 default:
86 return 0;
90 static void at91_rtt_mem_write(void *opaque, target_phys_addr_t offset,
91 uint32_t value)
93 RTTState *s = opaque;
95 offset &= RTT_SIZE - 1;
96 switch (offset) {
97 case RTT_MR:
98 if (value & MR_RTTRST) {
99 s->vr = 0;
100 if ((value & 0xffff) == 0) {
101 ptimer_set_freq(s->timer, 1);
102 } else {
103 ptimer_set_freq(s->timer, 0x8000 / (value & 0xffff));
106 s->mr = value;
107 break;
108 case RTT_AR:
109 s->ar = value;
110 break;
114 static CPUReadMemoryFunc *at91_rtt_readfn[] = {
115 at91_rtt_mem_read,
116 at91_rtt_mem_read,
117 at91_rtt_mem_read,
120 static CPUWriteMemoryFunc *at91_rtt_writefn[] = {
121 at91_rtt_mem_write,
122 at91_rtt_mem_write,
123 at91_rtt_mem_write,
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;
141 if (version_id != 1)
142 return -EINVAL;
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);
150 return 0;
153 static void at91_rtt_reset(void *opaque)
155 RTTState *s = opaque;
157 s->mr = 0x8000;
158 s->ar = ~0;
159 s->vr = 0;
160 s->sr = 0;
163 static void at91_rtt_init(SysBusDevice *dev)
165 RTTState *s = FROM_SYSBUS(typeof (*s), dev);
166 QEMUBH *bh;
167 int rtt_regs;
169 at91_rtt_reset(s);
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)