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 "hw/arm/pic.h" 16 #include "hw/android/goldfish/device.h" 17 #include "hw/hw.h" 18 19 enum { 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 28 struct 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 39 static 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_clock_get_ns(QEMU_CLOCK_VIRTUAL); 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 52 static 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_clock_get_ns(QEMU_CLOCK_VIRTUAL); 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 timer_mod(s->timer, alarm_tks); 71 } 72 } 73 return 0; 74 } 75 76 static uint32_t goldfish_timer_read(void *opaque, hwaddr offset) 77 { 78 struct timer_state *s = (struct timer_state *)opaque; 79 switch(offset) { 80 case TIMER_TIME_LOW: 81 s->now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 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 91 static void goldfish_timer_write(void *opaque, hwaddr 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_clock_get_ns(QEMU_CLOCK_VIRTUAL); 100 if (alarm_ns <= now_ns) { 101 goldfish_device_set_irq(&s->dev, 0, 1); 102 } else { 103 timer_mod(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 timer_del(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, hwaddr 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, hwaddr offset, uint32_t value) 176 { 177 struct rtc_state *s = (struct rtc_state *)opaque; 178 switch(offset) { 179 case 0x8: 180 s->alarm_low = value; 181 break; 182 case 0xc: 183 s->alarm_high = value; 184 break; 185 case 0x10: 186 goldfish_device_set_irq(&s->dev, 0, 0); 187 break; 188 default: 189 cpu_abort (cpu_single_env, "goldfish_rtc_write: Bad offset %x\n", offset); 190 } 191 } 192 193 static struct timer_state timer_state = { 194 .dev = { 195 .name = "goldfish_timer", 196 .id = -1, 197 .size = 0x1000, 198 .irq_count = 1, 199 } 200 }; 201 202 static struct timer_state rtc_state = { 203 .dev = { 204 .name = "goldfish_rtc", 205 .id = -1, 206 .size = 0x1000, 207 .irq_count = 1, 208 } 209 }; 210 211 static CPUReadMemoryFunc *goldfish_timer_readfn[] = { 212 goldfish_timer_read, 213 goldfish_timer_read, 214 goldfish_timer_read 215 }; 216 217 static CPUWriteMemoryFunc *goldfish_timer_writefn[] = { 218 goldfish_timer_write, 219 goldfish_timer_write, 220 goldfish_timer_write 221 }; 222 223 static CPUReadMemoryFunc *goldfish_rtc_readfn[] = { 224 goldfish_rtc_read, 225 goldfish_rtc_read, 226 goldfish_rtc_read 227 }; 228 229 static CPUWriteMemoryFunc *goldfish_rtc_writefn[] = { 230 goldfish_rtc_write, 231 goldfish_rtc_write, 232 goldfish_rtc_write 233 }; 234 235 void goldfish_timer_and_rtc_init(uint32_t timerbase, int timerirq) 236 { 237 timer_state.dev.base = timerbase; 238 timer_state.dev.irq = timerirq; 239 timer_state.timer = timer_new(QEMU_CLOCK_VIRTUAL, SCALE_NS, goldfish_timer_tick, &timer_state); 240 goldfish_device_add(&timer_state.dev, goldfish_timer_readfn, goldfish_timer_writefn, &timer_state); 241 register_savevm(NULL, 242 "goldfish_timer", 243 0, 244 GOLDFISH_TIMER_SAVE_VERSION, 245 goldfish_timer_save, 246 goldfish_timer_load, 247 &timer_state); 248 249 goldfish_device_add(&rtc_state.dev, goldfish_rtc_readfn, goldfish_rtc_writefn, &rtc_state); 250 register_savevm(NULL, 251 "goldfish_rtc", 252 0, 253 GOLDFISH_RTC_SAVE_VERSION, 254 goldfish_rtc_save, 255 goldfish_rtc_load, 256 &rtc_state); 257 } 258 259