ati-vga: Implement DDC and EDID info from monitor
[qemu/ar7.git] / hw / timer / pl031.c
blob3378084f4a8853b2debecc36f516b756a981307e
1 /*
2 * ARM AMBA PrimeCell PL031 RTC
4 * Copyright (c) 2007 CodeSourcery
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Contributions after 2012-01-13 are licensed under the terms of the
11 * GNU GPL, version 2 or (at your option) any later version.
14 #include "qemu/osdep.h"
15 #include "qemu-common.h"
16 #include "hw/timer/pl031.h"
17 #include "hw/sysbus.h"
18 #include "qemu/timer.h"
19 #include "sysemu/sysemu.h"
20 #include "qemu/cutils.h"
21 #include "qemu/log.h"
22 #include "qemu/module.h"
23 #include "trace.h"
25 #define RTC_DR 0x00 /* Data read register */
26 #define RTC_MR 0x04 /* Match register */
27 #define RTC_LR 0x08 /* Data load register */
28 #define RTC_CR 0x0c /* Control register */
29 #define RTC_IMSC 0x10 /* Interrupt mask and set register */
30 #define RTC_RIS 0x14 /* Raw interrupt status register */
31 #define RTC_MIS 0x18 /* Masked interrupt status register */
32 #define RTC_ICR 0x1c /* Interrupt clear register */
34 static const unsigned char pl031_id[] = {
35 0x31, 0x10, 0x14, 0x00, /* Device ID */
36 0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
39 static void pl031_update(PL031State *s)
41 uint32_t flags = s->is & s->im;
43 trace_pl031_irq_state(flags);
44 qemu_set_irq(s->irq, flags);
47 static void pl031_interrupt(void * opaque)
49 PL031State *s = (PL031State *)opaque;
51 s->is = 1;
52 trace_pl031_alarm_raised();
53 pl031_update(s);
56 static uint32_t pl031_get_count(PL031State *s)
58 int64_t now = qemu_clock_get_ns(rtc_clock);
59 return s->tick_offset + now / NANOSECONDS_PER_SECOND;
62 static void pl031_set_alarm(PL031State *s)
64 uint32_t ticks;
66 /* The timer wraps around. This subtraction also wraps in the same way,
67 and gives correct results when alarm < now_ticks. */
68 ticks = s->mr - pl031_get_count(s);
69 trace_pl031_set_alarm(ticks);
70 if (ticks == 0) {
71 timer_del(s->timer);
72 pl031_interrupt(s);
73 } else {
74 int64_t now = qemu_clock_get_ns(rtc_clock);
75 timer_mod(s->timer, now + (int64_t)ticks * NANOSECONDS_PER_SECOND);
79 static uint64_t pl031_read(void *opaque, hwaddr offset,
80 unsigned size)
82 PL031State *s = (PL031State *)opaque;
83 uint64_t r;
85 switch (offset) {
86 case RTC_DR:
87 r = pl031_get_count(s);
88 break;
89 case RTC_MR:
90 r = s->mr;
91 break;
92 case RTC_IMSC:
93 r = s->im;
94 break;
95 case RTC_RIS:
96 r = s->is;
97 break;
98 case RTC_LR:
99 r = s->lr;
100 break;
101 case RTC_CR:
102 /* RTC is permanently enabled. */
103 r = 1;
104 break;
105 case RTC_MIS:
106 r = s->is & s->im;
107 break;
108 case 0xfe0 ... 0xfff:
109 r = pl031_id[(offset - 0xfe0) >> 2];
110 break;
111 case RTC_ICR:
112 qemu_log_mask(LOG_GUEST_ERROR,
113 "pl031: read of write-only register at offset 0x%x\n",
114 (int)offset);
115 r = 0;
116 break;
117 default:
118 qemu_log_mask(LOG_GUEST_ERROR,
119 "pl031_read: Bad offset 0x%x\n", (int)offset);
120 r = 0;
121 break;
124 trace_pl031_read(offset, r);
125 return r;
128 static void pl031_write(void * opaque, hwaddr offset,
129 uint64_t value, unsigned size)
131 PL031State *s = (PL031State *)opaque;
133 trace_pl031_write(offset, value);
135 switch (offset) {
136 case RTC_LR:
137 s->tick_offset += value - pl031_get_count(s);
138 pl031_set_alarm(s);
139 break;
140 case RTC_MR:
141 s->mr = value;
142 pl031_set_alarm(s);
143 break;
144 case RTC_IMSC:
145 s->im = value & 1;
146 pl031_update(s);
147 break;
148 case RTC_ICR:
149 /* The PL031 documentation (DDI0224B) states that the interrupt is
150 cleared when bit 0 of the written value is set. However the
151 arm926e documentation (DDI0287B) states that the interrupt is
152 cleared when any value is written. */
153 s->is = 0;
154 pl031_update(s);
155 break;
156 case RTC_CR:
157 /* Written value is ignored. */
158 break;
160 case RTC_DR:
161 case RTC_MIS:
162 case RTC_RIS:
163 qemu_log_mask(LOG_GUEST_ERROR,
164 "pl031: write to read-only register at offset 0x%x\n",
165 (int)offset);
166 break;
168 default:
169 qemu_log_mask(LOG_GUEST_ERROR,
170 "pl031_write: Bad offset 0x%x\n", (int)offset);
171 break;
175 static const MemoryRegionOps pl031_ops = {
176 .read = pl031_read,
177 .write = pl031_write,
178 .endianness = DEVICE_NATIVE_ENDIAN,
181 static void pl031_init(Object *obj)
183 PL031State *s = PL031(obj);
184 SysBusDevice *dev = SYS_BUS_DEVICE(obj);
185 struct tm tm;
187 memory_region_init_io(&s->iomem, obj, &pl031_ops, s, "pl031", 0x1000);
188 sysbus_init_mmio(dev, &s->iomem);
190 sysbus_init_irq(dev, &s->irq);
191 qemu_get_timedate(&tm, 0);
192 s->tick_offset = mktimegm(&tm) -
193 qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
195 s->timer = timer_new_ns(rtc_clock, pl031_interrupt, s);
198 static int pl031_pre_save(void *opaque)
200 PL031State *s = opaque;
202 /* tick_offset is base_time - rtc_clock base time. Instead, we want to
203 * store the base time relative to the QEMU_CLOCK_VIRTUAL for backwards-compatibility. */
204 int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
205 s->tick_offset_vmstate = s->tick_offset + delta / NANOSECONDS_PER_SECOND;
207 return 0;
210 static int pl031_post_load(void *opaque, int version_id)
212 PL031State *s = opaque;
214 int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
215 s->tick_offset = s->tick_offset_vmstate - delta / NANOSECONDS_PER_SECOND;
216 pl031_set_alarm(s);
217 return 0;
220 static const VMStateDescription vmstate_pl031 = {
221 .name = "pl031",
222 .version_id = 1,
223 .minimum_version_id = 1,
224 .pre_save = pl031_pre_save,
225 .post_load = pl031_post_load,
226 .fields = (VMStateField[]) {
227 VMSTATE_UINT32(tick_offset_vmstate, PL031State),
228 VMSTATE_UINT32(mr, PL031State),
229 VMSTATE_UINT32(lr, PL031State),
230 VMSTATE_UINT32(cr, PL031State),
231 VMSTATE_UINT32(im, PL031State),
232 VMSTATE_UINT32(is, PL031State),
233 VMSTATE_END_OF_LIST()
237 static void pl031_class_init(ObjectClass *klass, void *data)
239 DeviceClass *dc = DEVICE_CLASS(klass);
241 dc->vmsd = &vmstate_pl031;
244 static const TypeInfo pl031_info = {
245 .name = TYPE_PL031,
246 .parent = TYPE_SYS_BUS_DEVICE,
247 .instance_size = sizeof(PL031State),
248 .instance_init = pl031_init,
249 .class_init = pl031_class_init,
252 static void pl031_register_types(void)
254 type_register_static(&pl031_info);
257 type_init(pl031_register_types)