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 18 enum { 19 TIMER_TIME_LOW = 0x00, // get low bits of current time and update TIMER_TIME_HIGH 20 TIMER_TIME_HIGH = 0x04, // get high bits of time at last TIMER_TIME_LOW read 21 TIMER_ALARM_LOW = 0x08, // set low bits of alarm and activate it 22 TIMER_ALARM_HIGH = 0x0c, // set high bits of next alarm 23 TIMER_CLEAR_INTERRUPT = 0x10, 24 TIMER_CLEAR_ALARM = 0x14 25 }; 26 27 struct timer_state { 28 struct goldfish_device dev; 29 uint32_t alarm_low; 30 int32_t alarm_high; 31 int64_t now; 32 int armed; 33 QEMUTimer *timer; 34 }; 35 36 #define GOLDFISH_TIMER_SAVE_VERSION 1 37 38 static void goldfish_timer_save(QEMUFile* f, void* opaque) 39 { 40 struct timer_state* s = opaque; 41 42 qemu_put_be64(f, s->now); /* in case the kernel is in the middle of a timer read */ 43 qemu_put_byte(f, s->armed); 44 if (s->armed) { 45 int64_t now = qemu_get_clock(vm_clock); 46 int64_t alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, get_ticks_per_sec(), 1000000000); 47 qemu_put_be64(f, alarm-now); 48 } 49 } 50 51 static int goldfish_timer_load(QEMUFile* f, void* opaque, int version_id) 52 { 53 struct timer_state* s = opaque; 54 55 if (version_id != GOLDFISH_TIMER_SAVE_VERSION) 56 return -1; 57 58 s->now = qemu_get_be64(f); 59 s->armed = qemu_get_byte(f); 60 if (s->armed) { 61 int64_t now = qemu_get_clock(vm_clock); 62 int64_t diff = qemu_get_be64(f); 63 int64_t alarm = now + diff; 64 65 if (alarm <= now) { 66 goldfish_device_set_irq(&s->dev, 0, 1); 67 s->armed = 0; 68 } else { 69 qemu_mod_timer(s->timer, alarm); 70 } 71 } 72 return 0; 73 } 74 75 static uint32_t goldfish_timer_read(void *opaque, target_phys_addr_t offset) 76 { 77 struct timer_state *s = (struct timer_state *)opaque; 78 switch(offset) { 79 case TIMER_TIME_LOW: 80 s->now = muldiv64(qemu_get_clock(vm_clock), 1000000000, get_ticks_per_sec()); 81 return s->now; 82 case TIMER_TIME_HIGH: 83 return s->now >> 32; 84 default: 85 cpu_abort (cpu_single_env, "goldfish_timer_read: Bad offset %x\n", offset); 86 return 0; 87 } 88 } 89 90 static void goldfish_timer_write(void *opaque, target_phys_addr_t offset, uint32_t value) 91 { 92 struct timer_state *s = (struct timer_state *)opaque; 93 int64_t alarm, now; 94 switch(offset) { 95 case TIMER_ALARM_LOW: 96 s->alarm_low = value; 97 alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, get_ticks_per_sec(), 1000000000); 98 now = qemu_get_clock(vm_clock); 99 if (alarm <= now) { 100 goldfish_device_set_irq(&s->dev, 0, 1); 101 } else { 102 qemu_mod_timer(s->timer, alarm); 103 s->armed = 1; 104 } 105 break; 106 case TIMER_ALARM_HIGH: 107 s->alarm_high = value; 108 //printf("alarm_high %d\n", s->alarm_high); 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 122 static 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 130 struct 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 141 static 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 148 static 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 160 static 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 175 static 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 198 static struct timer_state timer_state = { 199 .dev = { 200 .name = "goldfish_timer", 201 .id = -1, 202 .size = 0x1000, 203 .irq_count = 1, 204 } 205 }; 206 207 static struct timer_state rtc_state = { 208 .dev = { 209 .name = "goldfish_rtc", 210 .id = -1, 211 .size = 0x1000, 212 .irq_count = 1, 213 } 214 }; 215 216 static CPUReadMemoryFunc *goldfish_timer_readfn[] = { 217 goldfish_timer_read, 218 goldfish_timer_read, 219 goldfish_timer_read 220 }; 221 222 static CPUWriteMemoryFunc *goldfish_timer_writefn[] = { 223 goldfish_timer_write, 224 goldfish_timer_write, 225 goldfish_timer_write 226 }; 227 228 static CPUReadMemoryFunc *goldfish_rtc_readfn[] = { 229 goldfish_rtc_read, 230 goldfish_rtc_read, 231 goldfish_rtc_read 232 }; 233 234 static CPUWriteMemoryFunc *goldfish_rtc_writefn[] = { 235 goldfish_rtc_write, 236 goldfish_rtc_write, 237 goldfish_rtc_write 238 }; 239 240 void 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(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