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
;
99 r
= goldfish_rtc_get_count(s
) & 0xffffffff;
102 r
= goldfish_rtc_get_count(s
) >> 32;
105 r
= s
->alarm_next
& 0xffffffff;
108 r
= s
->alarm_next
>> 32;
110 case RTC_IRQ_ENABLED
:
113 case RTC_ALARM_STATUS
:
114 r
= s
->alarm_running
;
117 qemu_log_mask(LOG_GUEST_ERROR
,
118 "%s: offset 0x%x is UNIMP.\n", __func__
, (uint32_t)offset
);
122 trace_goldfish_rtc_read(offset
, r
);
127 static void goldfish_rtc_write(void *opaque
, hwaddr offset
,
128 uint64_t value
, unsigned size
)
130 GoldfishRTCState
*s
= opaque
;
131 uint64_t current_tick
, new_tick
;
135 current_tick
= goldfish_rtc_get_count(s
);
136 new_tick
= deposit64(current_tick
, 0, 32, value
);
137 s
->tick_offset
+= new_tick
- current_tick
;
140 current_tick
= goldfish_rtc_get_count(s
);
141 new_tick
= deposit64(current_tick
, 32, 32, value
);
142 s
->tick_offset
+= new_tick
- current_tick
;
145 s
->alarm_next
= deposit64(s
->alarm_next
, 0, 32, value
);
146 goldfish_rtc_set_alarm(s
);
149 s
->alarm_next
= deposit64(s
->alarm_next
, 32, 32, value
);
151 case RTC_IRQ_ENABLED
:
152 s
->irq_enabled
= (uint32_t)(value
& 0x1);
153 goldfish_rtc_update(s
);
155 case RTC_CLEAR_ALARM
:
156 goldfish_rtc_clear_alarm(s
);
158 case RTC_CLEAR_INTERRUPT
:
160 goldfish_rtc_update(s
);
163 qemu_log_mask(LOG_GUEST_ERROR
,
164 "%s: offset 0x%x is UNIMP.\n", __func__
, (uint32_t)offset
);
168 trace_goldfish_rtc_write(offset
, value
);
171 static int goldfish_rtc_pre_save(void *opaque
)
174 GoldfishRTCState
*s
= opaque
;
177 * We want to migrate this offset, which sounds straightforward.
178 * Unfortunately, we cannot directly pass tick_offset because
179 * rtc_clock on destination Host might not be same source Host.
181 * To tackle, this we pass tick_offset relative to vm_clock from
182 * source Host and make it relative to rtc_clock at destination Host.
184 delta
= qemu_clock_get_ns(rtc_clock
) -
185 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
186 s
->tick_offset_vmstate
= s
->tick_offset
+ delta
;
191 static int goldfish_rtc_post_load(void *opaque
, int version_id
)
194 GoldfishRTCState
*s
= opaque
;
197 * We extract tick_offset from tick_offset_vmstate by doing
198 * reverse math compared to pre_save() function.
200 delta
= qemu_clock_get_ns(rtc_clock
) -
201 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
202 s
->tick_offset
= s
->tick_offset_vmstate
- delta
;
207 static const MemoryRegionOps goldfish_rtc_ops
= {
208 .read
= goldfish_rtc_read
,
209 .write
= goldfish_rtc_write
,
210 .endianness
= DEVICE_LITTLE_ENDIAN
,
212 .min_access_size
= 4,
217 static const VMStateDescription goldfish_rtc_vmstate
= {
218 .name
= TYPE_GOLDFISH_RTC
,
220 .pre_save
= goldfish_rtc_pre_save
,
221 .post_load
= goldfish_rtc_post_load
,
222 .fields
= (VMStateField
[]) {
223 VMSTATE_UINT64(tick_offset_vmstate
, GoldfishRTCState
),
224 VMSTATE_UINT64(alarm_next
, GoldfishRTCState
),
225 VMSTATE_UINT32(alarm_running
, GoldfishRTCState
),
226 VMSTATE_UINT32(irq_pending
, GoldfishRTCState
),
227 VMSTATE_UINT32(irq_enabled
, GoldfishRTCState
),
228 VMSTATE_END_OF_LIST()
232 static void goldfish_rtc_reset(DeviceState
*dev
)
234 GoldfishRTCState
*s
= GOLDFISH_RTC(dev
);
239 qemu_get_timedate(&tm
, 0);
240 s
->tick_offset
= mktimegm(&tm
);
241 s
->tick_offset
*= NANOSECONDS_PER_SECOND
;
242 s
->tick_offset
-= qemu_clock_get_ns(rtc_clock
);
243 s
->tick_offset_vmstate
= 0;
245 s
->alarm_running
= 0;
250 static void goldfish_rtc_realize(DeviceState
*d
, Error
**errp
)
252 SysBusDevice
*dev
= SYS_BUS_DEVICE(d
);
253 GoldfishRTCState
*s
= GOLDFISH_RTC(d
);
255 memory_region_init_io(&s
->iomem
, OBJECT(s
), &goldfish_rtc_ops
, s
,
256 "goldfish_rtc", 0x24);
257 sysbus_init_mmio(dev
, &s
->iomem
);
259 sysbus_init_irq(dev
, &s
->irq
);
261 s
->timer
= timer_new_ns(rtc_clock
, goldfish_rtc_interrupt
, s
);
264 static void goldfish_rtc_class_init(ObjectClass
*klass
, void *data
)
266 DeviceClass
*dc
= DEVICE_CLASS(klass
);
268 dc
->realize
= goldfish_rtc_realize
;
269 dc
->reset
= goldfish_rtc_reset
;
270 dc
->vmsd
= &goldfish_rtc_vmstate
;
273 static const TypeInfo goldfish_rtc_info
= {
274 .name
= TYPE_GOLDFISH_RTC
,
275 .parent
= TYPE_SYS_BUS_DEVICE
,
276 .instance_size
= sizeof(GoldfishRTCState
),
277 .class_init
= goldfish_rtc_class_init
,
280 static void goldfish_rtc_register_types(void)
282 type_register_static(&goldfish_rtc_info
);
285 type_init(goldfish_rtc_register_types
)