1/* Copyright (C) 2007-2008 The Android Open Source Project 2** 3** This software is licensed under the terms of the GNU General Public 4** License version 2, as published by the Free Software Foundation, and 5** may be copied, distributed, and modified under those terms. 6** 7** This program is distributed in the hope that it will be useful, 8** but WITHOUT ANY WARRANTY; without even the implied warranty of 9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10** GNU General Public License for more details. 11*/ 12#include "qemu-common.h" 13#include "qemu-timer.h" 14#include "cpu.h" 15#include "arm_pic.h" 16#include "goldfish_device.h" 17#include "hw/hw.h" 18 19enum { 20 TIMER_TIME_LOW = 0x00, // get low bits of current time and update TIMER_TIME_HIGH 21 TIMER_TIME_HIGH = 0x04, // get high bits of time at last TIMER_TIME_LOW read 22 TIMER_ALARM_LOW = 0x08, // set low bits of alarm and activate it 23 TIMER_ALARM_HIGH = 0x0c, // set high bits of next alarm 24 TIMER_CLEAR_INTERRUPT = 0x10, 25 TIMER_CLEAR_ALARM = 0x14 26}; 27 28struct timer_state { 29 struct goldfish_device dev; 30 uint32_t alarm_low_ns; 31 int32_t alarm_high_ns; 32 int64_t now_ns; 33 int armed; 34 QEMUTimer *timer; 35}; 36 37#define GOLDFISH_TIMER_SAVE_VERSION 1 38 39static void goldfish_timer_save(QEMUFile* f, void* opaque) 40{ 41 struct timer_state* s = opaque; 42 43 qemu_put_be64(f, s->now_ns); /* in case the kernel is in the middle of a timer read */ 44 qemu_put_byte(f, s->armed); 45 if (s->armed) { 46 int64_t now_ns = qemu_get_clock_ns(vm_clock); 47 int64_t alarm_ns = (s->alarm_low_ns | (int64_t)s->alarm_high_ns << 32); 48 qemu_put_be64(f, alarm_ns - now_ns); 49 } 50} 51 52static int goldfish_timer_load(QEMUFile* f, void* opaque, int version_id) 53{ 54 struct timer_state* s = opaque; 55 56 if (version_id != GOLDFISH_TIMER_SAVE_VERSION) 57 return -1; 58 59 s->now_ns = qemu_get_be64(f); 60 s->armed = qemu_get_byte(f); 61 if (s->armed) { 62 int64_t now_tks = qemu_get_clock(vm_clock); 63 int64_t diff_tks = qemu_get_be64(f); 64 int64_t alarm_tks = now_tks + diff_tks; 65 66 if (alarm_tks <= now_tks) { 67 goldfish_device_set_irq(&s->dev, 0, 1); 68 s->armed = 0; 69 } else { 70 qemu_mod_timer(s->timer, alarm_tks); 71 } 72 } 73 return 0; 74} 75 76static uint32_t goldfish_timer_read(void *opaque, target_phys_addr_t offset) 77{ 78 struct timer_state *s = (struct timer_state *)opaque; 79 switch(offset) { 80 case TIMER_TIME_LOW: 81 s->now_ns = qemu_get_clock_ns(vm_clock); 82 return s->now_ns; 83 case TIMER_TIME_HIGH: 84 return s->now_ns >> 32; 85 default: 86 cpu_abort (cpu_single_env, "goldfish_timer_read: Bad offset %x\n", offset); 87 return 0; 88 } 89} 90 91static void goldfish_timer_write(void *opaque, target_phys_addr_t offset, uint32_t value_ns) 92{ 93 struct timer_state *s = (struct timer_state *)opaque; 94 int64_t alarm_ns, now_ns; 95 switch(offset) { 96 case TIMER_ALARM_LOW: 97 s->alarm_low_ns = value_ns; 98 alarm_ns = (s->alarm_low_ns | (int64_t)s->alarm_high_ns << 32); 99 now_ns = qemu_get_clock_ns(vm_clock); 100 if (alarm_ns <= now_ns) { 101 goldfish_device_set_irq(&s->dev, 0, 1); 102 } else { 103 qemu_mod_timer(s->timer, alarm_ns); 104 s->armed = 1; 105 } 106 break; 107 case TIMER_ALARM_HIGH: 108 s->alarm_high_ns = value_ns; 109 break; 110 case TIMER_CLEAR_ALARM: 111 qemu_del_timer(s->timer); 112 s->armed = 0; 113 /* fall through */ 114 case TIMER_CLEAR_INTERRUPT: 115 goldfish_device_set_irq(&s->dev, 0, 0); 116 break; 117 default: 118 cpu_abort (cpu_single_env, "goldfish_timer_write: Bad offset %x\n", offset); 119 } 120} 121 122static void goldfish_timer_tick(void *opaque) 123{ 124 struct timer_state *s = (struct timer_state *)opaque; 125 126 s->armed = 0; 127 goldfish_device_set_irq(&s->dev, 0, 1); 128} 129 130struct rtc_state { 131 struct goldfish_device dev; 132 uint32_t alarm_low; 133 int32_t alarm_high; 134 int64_t now; 135}; 136 137/* we save the RTC for the case where the kernel is in the middle of a rtc_read 138 * (i.e. it has read the low 32-bit of s->now, but not the high 32-bits yet */ 139#define GOLDFISH_RTC_SAVE_VERSION 1 140 141static void goldfish_rtc_save(QEMUFile* f, void* opaque) 142{ 143 struct rtc_state* s = opaque; 144 145 qemu_put_be64(f, s->now); 146} 147 148static int goldfish_rtc_load(QEMUFile* f, void* opaque, int version_id) 149{ 150 struct rtc_state* s = opaque; 151 152 if (version_id != GOLDFISH_RTC_SAVE_VERSION) 153 return -1; 154 155 /* this is an old value that is not correct. but that's ok anyway */ 156 s->now = qemu_get_be64(f); 157 return 0; 158} 159 160static uint32_t goldfish_rtc_read(void *opaque, target_phys_addr_t offset) 161{ 162 struct rtc_state *s = (struct rtc_state *)opaque; 163 switch(offset) { 164 case 0x0: 165 s->now = (int64_t)time(NULL) * 1000000000; 166 return s->now; 167 case 0x4: 168 return s->now >> 32; 169 default: 170 cpu_abort (cpu_single_env, "goldfish_rtc_read: Bad offset %x\n", offset); 171 return 0; 172 } 173} 174 175static void goldfish_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t value) 176{ 177 struct rtc_state *s = (struct rtc_state *)opaque; 178 int64_t alarm; 179 switch(offset) { 180 case 0x8: 181 s->alarm_low = value; 182 alarm = s->alarm_low | (int64_t)s->alarm_high << 32; 183 //printf("next alarm at %lld, tps %lld\n", alarm, ticks_per_sec); 184 //qemu_mod_timer(s->timer, alarm); 185 break; 186 case 0xc: 187 s->alarm_high = value; 188 //printf("alarm_high %d\n", s->alarm_high); 189 break; 190 case 0x10: 191 goldfish_device_set_irq(&s->dev, 0, 0); 192 break; 193 default: 194 cpu_abort (cpu_single_env, "goldfish_rtc_write: Bad offset %x\n", offset); 195 } 196} 197 198static struct timer_state timer_state = { 199 .dev = { 200 .name = "goldfish_timer", 201 .id = -1, 202 .size = 0x1000, 203 .irq_count = 1, 204 } 205}; 206 207static struct timer_state rtc_state = { 208 .dev = { 209 .name = "goldfish_rtc", 210 .id = -1, 211 .size = 0x1000, 212 .irq_count = 1, 213 } 214}; 215 216static CPUReadMemoryFunc *goldfish_timer_readfn[] = { 217 goldfish_timer_read, 218 goldfish_timer_read, 219 goldfish_timer_read 220}; 221 222static CPUWriteMemoryFunc *goldfish_timer_writefn[] = { 223 goldfish_timer_write, 224 goldfish_timer_write, 225 goldfish_timer_write 226}; 227 228static CPUReadMemoryFunc *goldfish_rtc_readfn[] = { 229 goldfish_rtc_read, 230 goldfish_rtc_read, 231 goldfish_rtc_read 232}; 233 234static CPUWriteMemoryFunc *goldfish_rtc_writefn[] = { 235 goldfish_rtc_write, 236 goldfish_rtc_write, 237 goldfish_rtc_write 238}; 239 240void goldfish_timer_and_rtc_init(uint32_t timerbase, int timerirq) 241{ 242 timer_state.dev.base = timerbase; 243 timer_state.dev.irq = timerirq; 244 timer_state.timer = qemu_new_timer_ns(vm_clock, goldfish_timer_tick, &timer_state); 245 goldfish_device_add(&timer_state.dev, goldfish_timer_readfn, goldfish_timer_writefn, &timer_state); 246 register_savevm( "goldfish_timer", 0, GOLDFISH_TIMER_SAVE_VERSION, 247 goldfish_timer_save, goldfish_timer_load, &timer_state); 248 249 goldfish_device_add(&rtc_state.dev, goldfish_rtc_readfn, goldfish_rtc_writefn, &rtc_state); 250 register_savevm( "goldfish_rtc", 0, GOLDFISH_RTC_SAVE_VERSION, 251 goldfish_rtc_save, goldfish_rtc_load, &rtc_state); 252} 253 254