1 /* 2 * QEMU lowRISC Ibex Timer device 3 * 4 * Copyright (c) 2021 Western Digital 5 * 6 * For details check the documentation here: 7 * https://docs.opentitan.org/hw/ip/rv_timer/doc/ 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a copy 10 * of this software and associated documentation files (the "Software"), to deal 11 * in the Software without restriction, including without limitation the rights 12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 * copies of the Software, and to permit persons to whom the Software is 14 * furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 * THE SOFTWARE. 26 */ 27 28 #include "qemu/osdep.h" 29 #include "qemu/log.h" 30 #include "qemu/timer.h" 31 #include "hw/timer/ibex_timer.h" 32 #include "hw/irq.h" 33 #include "hw/qdev-properties.h" 34 #include "target/riscv/cpu.h" 35 #include "migration/vmstate.h" 36 37 REG32(ALERT_TEST, 0x00) 38 FIELD(ALERT_TEST, FATAL_FAULT, 0, 1) 39 REG32(CTRL, 0x04) 40 FIELD(CTRL, ACTIVE, 0, 1) 41 REG32(CFG0, 0x100) 42 FIELD(CFG0, PRESCALE, 0, 12) 43 FIELD(CFG0, STEP, 16, 8) 44 REG32(LOWER0, 0x104) 45 REG32(UPPER0, 0x108) 46 REG32(COMPARE_LOWER0, 0x10C) 47 REG32(COMPARE_UPPER0, 0x110) 48 REG32(INTR_ENABLE, 0x114) 49 FIELD(INTR_ENABLE, IE_0, 0, 1) 50 REG32(INTR_STATE, 0x118) 51 FIELD(INTR_STATE, IS_0, 0, 1) 52 REG32(INTR_TEST, 0x11C) 53 FIELD(INTR_TEST, T_0, 0, 1) 54 55 static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq) 56 { 57 return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 58 timebase_freq, NANOSECONDS_PER_SECOND); 59 } 60 61 static void ibex_timer_update_irqs(IbexTimerState *s) 62 { 63 CPUState *cs = qemu_get_cpu(0); 64 RISCVCPU *cpu = RISCV_CPU(cs); 65 uint64_t value = s->timer_compare_lower0 | 66 ((uint64_t)s->timer_compare_upper0 << 32); 67 uint64_t next, diff; 68 uint64_t now = cpu_riscv_read_rtc(s->timebase_freq); 69 70 if (!(s->timer_ctrl & R_CTRL_ACTIVE_MASK)) { 71 /* Timer isn't active */ 72 return; 73 } 74 75 /* Update the CPUs mtimecmp */ 76 cpu->env.timecmp = value; 77 78 if (cpu->env.timecmp <= now) { 79 /* 80 * If the mtimecmp was in the past raise the interrupt now. 81 */ 82 qemu_irq_raise(s->m_timer_irq); 83 if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) { 84 s->timer_intr_state |= R_INTR_STATE_IS_0_MASK; 85 qemu_set_irq(s->irq, true); 86 } 87 return; 88 } 89 90 /* Setup a timer to trigger the interrupt in the future */ 91 qemu_irq_lower(s->m_timer_irq); 92 qemu_set_irq(s->irq, false); 93 94 diff = cpu->env.timecmp - now; 95 next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 96 muldiv64(diff, 97 NANOSECONDS_PER_SECOND, 98 s->timebase_freq); 99 100 if (next < qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) { 101 /* We overflowed the timer, just set it as large as we can */ 102 timer_mod(cpu->env.timer, 0x7FFFFFFFFFFFFFFF); 103 } else { 104 timer_mod(cpu->env.timer, next); 105 } 106 } 107 108 static void ibex_timer_cb(void *opaque) 109 { 110 IbexTimerState *s = opaque; 111 112 qemu_irq_raise(s->m_timer_irq); 113 if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) { 114 s->timer_intr_state |= R_INTR_STATE_IS_0_MASK; 115 qemu_set_irq(s->irq, true); 116 } 117 } 118 119 static void ibex_timer_reset(DeviceState *dev) 120 { 121 IbexTimerState *s = IBEX_TIMER(dev); 122 123 CPUState *cpu = qemu_get_cpu(0); 124 CPURISCVState *env = cpu->env_ptr; 125 env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 126 &ibex_timer_cb, s); 127 env->timecmp = 0; 128 129 s->timer_ctrl = 0x00000000; 130 s->timer_cfg0 = 0x00010000; 131 s->timer_compare_lower0 = 0xFFFFFFFF; 132 s->timer_compare_upper0 = 0xFFFFFFFF; 133 s->timer_intr_enable = 0x00000000; 134 s->timer_intr_state = 0x00000000; 135 136 ibex_timer_update_irqs(s); 137 } 138 139 static uint64_t ibex_timer_read(void *opaque, hwaddr addr, 140 unsigned int size) 141 { 142 IbexTimerState *s = opaque; 143 uint64_t now = cpu_riscv_read_rtc(s->timebase_freq); 144 uint64_t retvalue = 0; 145 146 switch (addr >> 2) { 147 case R_ALERT_TEST: 148 qemu_log_mask(LOG_GUEST_ERROR, 149 "Attempted to read ALERT_TEST, a write only register"); 150 break; 151 case R_CTRL: 152 retvalue = s->timer_ctrl; 153 break; 154 case R_CFG0: 155 retvalue = s->timer_cfg0; 156 break; 157 case R_LOWER0: 158 retvalue = now; 159 break; 160 case R_UPPER0: 161 retvalue = now >> 32; 162 break; 163 case R_COMPARE_LOWER0: 164 retvalue = s->timer_compare_lower0; 165 break; 166 case R_COMPARE_UPPER0: 167 retvalue = s->timer_compare_upper0; 168 break; 169 case R_INTR_ENABLE: 170 retvalue = s->timer_intr_enable; 171 break; 172 case R_INTR_STATE: 173 retvalue = s->timer_intr_state; 174 break; 175 case R_INTR_TEST: 176 qemu_log_mask(LOG_GUEST_ERROR, 177 "Attempted to read INTR_TEST, a write only register"); 178 break; 179 default: 180 qemu_log_mask(LOG_GUEST_ERROR, 181 "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); 182 return 0; 183 } 184 185 return retvalue; 186 } 187 188 static void ibex_timer_write(void *opaque, hwaddr addr, 189 uint64_t val64, unsigned int size) 190 { 191 IbexTimerState *s = opaque; 192 uint32_t val = val64; 193 194 switch (addr >> 2) { 195 case R_ALERT_TEST: 196 qemu_log_mask(LOG_UNIMP, "Alert triggering not supported"); 197 break; 198 case R_CTRL: 199 s->timer_ctrl = val; 200 break; 201 case R_CFG0: 202 qemu_log_mask(LOG_UNIMP, "Changing prescale or step not supported"); 203 s->timer_cfg0 = val; 204 break; 205 case R_LOWER0: 206 qemu_log_mask(LOG_UNIMP, "Changing timer value is not supported"); 207 break; 208 case R_UPPER0: 209 qemu_log_mask(LOG_UNIMP, "Changing timer value is not supported"); 210 break; 211 case R_COMPARE_LOWER0: 212 s->timer_compare_lower0 = val; 213 ibex_timer_update_irqs(s); 214 break; 215 case R_COMPARE_UPPER0: 216 s->timer_compare_upper0 = val; 217 ibex_timer_update_irqs(s); 218 break; 219 case R_INTR_ENABLE: 220 s->timer_intr_enable = val; 221 break; 222 case R_INTR_STATE: 223 /* Write 1 to clear */ 224 s->timer_intr_state &= ~val; 225 break; 226 case R_INTR_TEST: 227 if (s->timer_intr_enable & val & R_INTR_ENABLE_IE_0_MASK) { 228 s->timer_intr_state |= R_INTR_STATE_IS_0_MASK; 229 qemu_set_irq(s->irq, true); 230 } 231 break; 232 default: 233 qemu_log_mask(LOG_GUEST_ERROR, 234 "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); 235 } 236 } 237 238 static const MemoryRegionOps ibex_timer_ops = { 239 .read = ibex_timer_read, 240 .write = ibex_timer_write, 241 .endianness = DEVICE_NATIVE_ENDIAN, 242 .impl.min_access_size = 4, 243 .impl.max_access_size = 4, 244 }; 245 246 static int ibex_timer_post_load(void *opaque, int version_id) 247 { 248 IbexTimerState *s = opaque; 249 250 ibex_timer_update_irqs(s); 251 return 0; 252 } 253 254 static const VMStateDescription vmstate_ibex_timer = { 255 .name = TYPE_IBEX_TIMER, 256 .version_id = 2, 257 .minimum_version_id = 2, 258 .post_load = ibex_timer_post_load, 259 .fields = (VMStateField[]) { 260 VMSTATE_UINT32(timer_ctrl, IbexTimerState), 261 VMSTATE_UINT32(timer_cfg0, IbexTimerState), 262 VMSTATE_UINT32(timer_compare_lower0, IbexTimerState), 263 VMSTATE_UINT32(timer_compare_upper0, IbexTimerState), 264 VMSTATE_UINT32(timer_intr_enable, IbexTimerState), 265 VMSTATE_UINT32(timer_intr_state, IbexTimerState), 266 VMSTATE_END_OF_LIST() 267 } 268 }; 269 270 static Property ibex_timer_properties[] = { 271 DEFINE_PROP_UINT32("timebase-freq", IbexTimerState, timebase_freq, 10000), 272 DEFINE_PROP_END_OF_LIST(), 273 }; 274 275 static void ibex_timer_init(Object *obj) 276 { 277 IbexTimerState *s = IBEX_TIMER(obj); 278 279 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); 280 281 memory_region_init_io(&s->mmio, obj, &ibex_timer_ops, s, 282 TYPE_IBEX_TIMER, 0x400); 283 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); 284 } 285 286 static void ibex_timer_realize(DeviceState *dev, Error **errp) 287 { 288 IbexTimerState *s = IBEX_TIMER(dev); 289 290 qdev_init_gpio_out(dev, &s->m_timer_irq, 1); 291 } 292 293 294 static void ibex_timer_class_init(ObjectClass *klass, void *data) 295 { 296 DeviceClass *dc = DEVICE_CLASS(klass); 297 298 dc->reset = ibex_timer_reset; 299 dc->vmsd = &vmstate_ibex_timer; 300 dc->realize = ibex_timer_realize; 301 device_class_set_props(dc, ibex_timer_properties); 302 } 303 304 static const TypeInfo ibex_timer_info = { 305 .name = TYPE_IBEX_TIMER, 306 .parent = TYPE_SYS_BUS_DEVICE, 307 .instance_size = sizeof(IbexTimerState), 308 .instance_init = ibex_timer_init, 309 .class_init = ibex_timer_class_init, 310 }; 311 312 static void ibex_timer_register_types(void) 313 { 314 type_register_static(&ibex_timer_info); 315 } 316 317 type_init(ibex_timer_register_types) 318