2 * Goldfish virtual platform RTC
4 * Copyright (C) 2019 Western Digital Corporation or its affiliates.
6 * For more details on Google Goldfish virtual platform refer:
7 * https://android.googlesource.com/platform/external/qemu/+/refs/heads/emu-2.0-release/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2 or later, as published by the Free Software Foundation.
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "qemu/osdep.h"
23 #include "qemu-common.h"
24 #include "hw/rtc/goldfish_rtc.h"
25 #include "migration/vmstate.h"
27 #include "hw/qdev-properties.h"
28 #include "hw/sysbus.h"
29 #include "qemu/bitops.h"
30 #include "qemu/timer.h"
31 #include "sysemu/sysemu.h"
32 #include "qemu/cutils.h"
37 #define RTC_TIME_LOW 0x00
38 #define RTC_TIME_HIGH 0x04
39 #define RTC_ALARM_LOW 0x08
40 #define RTC_ALARM_HIGH 0x0c
41 #define RTC_IRQ_ENABLED 0x10
42 #define RTC_CLEAR_ALARM 0x14
43 #define RTC_ALARM_STATUS 0x18
44 #define RTC_CLEAR_INTERRUPT 0x1c
46 static void goldfish_rtc_update(GoldfishRTCState
*s
)
48 qemu_set_irq(s
->irq
, (s
->irq_pending
& s
->irq_enabled
) ? 1 : 0);
51 static void goldfish_rtc_interrupt(void *opaque
)
53 GoldfishRTCState
*s
= (GoldfishRTCState
*)opaque
;
57 goldfish_rtc_update(s
);
60 static uint64_t goldfish_rtc_get_count(GoldfishRTCState
*s
)
62 return s
->tick_offset
+ (uint64_t)qemu_clock_get_ns(rtc_clock
);
65 static void goldfish_rtc_clear_alarm(GoldfishRTCState
*s
)
71 static void goldfish_rtc_set_alarm(GoldfishRTCState
*s
)
73 uint64_t ticks
= goldfish_rtc_get_count(s
);
74 uint64_t event
= s
->alarm_next
;
77 goldfish_rtc_clear_alarm(s
);
78 goldfish_rtc_interrupt(s
);
81 * We should be setting timer expiry to:
82 * qemu_clock_get_ns(rtc_clock) + (event - ticks)
83 * but this is equivalent to:
84 * event - s->tick_offset
86 timer_mod(s
->timer
, event
- s
->tick_offset
);
91 static uint64_t goldfish_rtc_read(void *opaque
, hwaddr offset
,
94 GoldfishRTCState
*s
= opaque
;
98 * From the documentation linked at the top of the file:
100 * To read the value, the kernel must perform an IO_READ(TIME_LOW), which
101 * returns an unsigned 32-bit value, before an IO_READ(TIME_HIGH), which
102 * returns a signed 32-bit value, corresponding to the higher half of the
107 r
= goldfish_rtc_get_count(s
);
108 s
->time_high
= r
>> 32;
115 r
= s
->alarm_next
& 0xffffffff;
118 r
= s
->alarm_next
>> 32;
120 case RTC_IRQ_ENABLED
:
123 case RTC_ALARM_STATUS
:
124 r
= s
->alarm_running
;
127 qemu_log_mask(LOG_GUEST_ERROR
,
128 "%s: offset 0x%x is UNIMP.\n", __func__
, (uint32_t)offset
);
132 trace_goldfish_rtc_read(offset
, r
);
137 static void goldfish_rtc_write(void *opaque
, hwaddr offset
,
138 uint64_t value
, unsigned size
)
140 GoldfishRTCState
*s
= opaque
;
141 uint64_t current_tick
, new_tick
;
145 current_tick
= goldfish_rtc_get_count(s
);
146 new_tick
= deposit64(current_tick
, 0, 32, value
);
147 s
->tick_offset
+= new_tick
- current_tick
;
150 current_tick
= goldfish_rtc_get_count(s
);
151 new_tick
= deposit64(current_tick
, 32, 32, value
);
152 s
->tick_offset
+= new_tick
- current_tick
;
155 s
->alarm_next
= deposit64(s
->alarm_next
, 0, 32, value
);
156 goldfish_rtc_set_alarm(s
);
159 s
->alarm_next
= deposit64(s
->alarm_next
, 32, 32, value
);
161 case RTC_IRQ_ENABLED
:
162 s
->irq_enabled
= (uint32_t)(value
& 0x1);
163 goldfish_rtc_update(s
);
165 case RTC_CLEAR_ALARM
:
166 goldfish_rtc_clear_alarm(s
);
168 case RTC_CLEAR_INTERRUPT
:
170 goldfish_rtc_update(s
);
173 qemu_log_mask(LOG_GUEST_ERROR
,
174 "%s: offset 0x%x is UNIMP.\n", __func__
, (uint32_t)offset
);
178 trace_goldfish_rtc_write(offset
, value
);
181 static int goldfish_rtc_pre_save(void *opaque
)
184 GoldfishRTCState
*s
= opaque
;
187 * We want to migrate this offset, which sounds straightforward.
188 * Unfortunately, we cannot directly pass tick_offset because
189 * rtc_clock on destination Host might not be same source Host.
191 * To tackle, this we pass tick_offset relative to vm_clock from
192 * source Host and make it relative to rtc_clock at destination Host.
194 delta
= qemu_clock_get_ns(rtc_clock
) -
195 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
196 s
->tick_offset_vmstate
= s
->tick_offset
+ delta
;
201 static int goldfish_rtc_post_load(void *opaque
, int version_id
)
204 GoldfishRTCState
*s
= opaque
;
207 * We extract tick_offset from tick_offset_vmstate by doing
208 * reverse math compared to pre_save() function.
210 delta
= qemu_clock_get_ns(rtc_clock
) -
211 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
212 s
->tick_offset
= s
->tick_offset_vmstate
- delta
;
217 static const MemoryRegionOps goldfish_rtc_ops
= {
218 .read
= goldfish_rtc_read
,
219 .write
= goldfish_rtc_write
,
220 .endianness
= DEVICE_LITTLE_ENDIAN
,
222 .min_access_size
= 4,
227 static const VMStateDescription goldfish_rtc_vmstate
= {
228 .name
= TYPE_GOLDFISH_RTC
,
230 .pre_save
= goldfish_rtc_pre_save
,
231 .post_load
= goldfish_rtc_post_load
,
232 .fields
= (VMStateField
[]) {
233 VMSTATE_UINT64(tick_offset_vmstate
, GoldfishRTCState
),
234 VMSTATE_UINT64(alarm_next
, GoldfishRTCState
),
235 VMSTATE_UINT32(alarm_running
, GoldfishRTCState
),
236 VMSTATE_UINT32(irq_pending
, GoldfishRTCState
),
237 VMSTATE_UINT32(irq_enabled
, GoldfishRTCState
),
238 VMSTATE_UINT32(time_high
, GoldfishRTCState
),
239 VMSTATE_END_OF_LIST()
243 static void goldfish_rtc_reset(DeviceState
*dev
)
245 GoldfishRTCState
*s
= GOLDFISH_RTC(dev
);
250 qemu_get_timedate(&tm
, 0);
251 s
->tick_offset
= mktimegm(&tm
);
252 s
->tick_offset
*= NANOSECONDS_PER_SECOND
;
253 s
->tick_offset
-= qemu_clock_get_ns(rtc_clock
);
254 s
->tick_offset_vmstate
= 0;
256 s
->alarm_running
= 0;
261 static void goldfish_rtc_realize(DeviceState
*d
, Error
**errp
)
263 SysBusDevice
*dev
= SYS_BUS_DEVICE(d
);
264 GoldfishRTCState
*s
= GOLDFISH_RTC(d
);
266 memory_region_init_io(&s
->iomem
, OBJECT(s
), &goldfish_rtc_ops
, s
,
267 "goldfish_rtc", 0x24);
268 sysbus_init_mmio(dev
, &s
->iomem
);
270 sysbus_init_irq(dev
, &s
->irq
);
272 s
->timer
= timer_new_ns(rtc_clock
, goldfish_rtc_interrupt
, s
);
275 static void goldfish_rtc_class_init(ObjectClass
*klass
, void *data
)
277 DeviceClass
*dc
= DEVICE_CLASS(klass
);
279 dc
->realize
= goldfish_rtc_realize
;
280 dc
->reset
= goldfish_rtc_reset
;
281 dc
->vmsd
= &goldfish_rtc_vmstate
;
284 static const TypeInfo goldfish_rtc_info
= {
285 .name
= TYPE_GOLDFISH_RTC
,
286 .parent
= TYPE_SYS_BUS_DEVICE
,
287 .instance_size
= sizeof(GoldfishRTCState
),
288 .class_init
= goldfish_rtc_class_init
,
291 static void goldfish_rtc_register_types(void)
293 type_register_static(&goldfish_rtc_info
);
296 type_init(goldfish_rtc_register_types
)