1 /* 2 * ARMv7M SysTick timer 3 * 4 * Copyright (c) 2006-2007 CodeSourcery. 5 * Written by Paul Brook 6 * Copyright (c) 2017 Linaro Ltd 7 * Written by Peter Maydell 8 * 9 * This code is licensed under the GPL (version 2 or later). 10 */ 11 12 #include "qemu/osdep.h" 13 #include "hw/timer/armv7m_systick.h" 14 #include "migration/vmstate.h" 15 #include "hw/irq.h" 16 #include "hw/sysbus.h" 17 #include "qemu/timer.h" 18 #include "qemu/log.h" 19 #include "qemu/module.h" 20 #include "trace.h" 21 22 /* qemu timers run at 1GHz. We want something closer to 1MHz. */ 23 #define SYSTICK_SCALE 1000ULL 24 25 #define SYSTICK_ENABLE (1 << 0) 26 #define SYSTICK_TICKINT (1 << 1) 27 #define SYSTICK_CLKSOURCE (1 << 2) 28 #define SYSTICK_COUNTFLAG (1 << 16) 29 30 int system_clock_scale; 31 32 /* Conversion factor from qemu timer to SysTick frequencies. */ 33 static inline int64_t systick_scale(SysTickState *s) 34 { 35 if (s->control & SYSTICK_CLKSOURCE) { 36 return system_clock_scale; 37 } else { 38 return 1000; 39 } 40 } 41 42 static void systick_timer_tick(void *opaque) 43 { 44 SysTickState *s = (SysTickState *)opaque; 45 46 trace_systick_timer_tick(); 47 48 s->control |= SYSTICK_COUNTFLAG; 49 if (s->control & SYSTICK_TICKINT) { 50 /* Tell the NVIC to pend the SysTick exception */ 51 qemu_irq_pulse(s->irq); 52 } 53 if (ptimer_get_limit(s->ptimer) == 0) { 54 /* 55 * Timer expiry with SYST_RVR zero disables the timer 56 * (but doesn't clear SYST_CSR.ENABLE) 57 */ 58 ptimer_stop(s->ptimer); 59 } 60 } 61 62 static MemTxResult systick_read(void *opaque, hwaddr addr, uint64_t *data, 63 unsigned size, MemTxAttrs attrs) 64 { 65 SysTickState *s = opaque; 66 uint32_t val; 67 68 if (attrs.user) { 69 /* Generate BusFault for unprivileged accesses */ 70 return MEMTX_ERROR; 71 } 72 73 switch (addr) { 74 case 0x0: /* SysTick Control and Status. */ 75 val = s->control; 76 s->control &= ~SYSTICK_COUNTFLAG; 77 break; 78 case 0x4: /* SysTick Reload Value. */ 79 val = ptimer_get_limit(s->ptimer); 80 break; 81 case 0x8: /* SysTick Current Value. */ 82 val = ptimer_get_count(s->ptimer); 83 break; 84 case 0xc: /* SysTick Calibration Value. */ 85 val = 10000; 86 break; 87 default: 88 val = 0; 89 qemu_log_mask(LOG_GUEST_ERROR, 90 "SysTick: Bad read offset 0x%" HWADDR_PRIx "\n", addr); 91 break; 92 } 93 94 trace_systick_read(addr, val, size); 95 *data = val; 96 return MEMTX_OK; 97 } 98 99 static MemTxResult systick_write(void *opaque, hwaddr addr, 100 uint64_t value, unsigned size, 101 MemTxAttrs attrs) 102 { 103 SysTickState *s = opaque; 104 105 if (attrs.user) { 106 /* Generate BusFault for unprivileged accesses */ 107 return MEMTX_ERROR; 108 } 109 110 trace_systick_write(addr, value, size); 111 112 switch (addr) { 113 case 0x0: /* SysTick Control and Status. */ 114 { 115 uint32_t oldval; 116 117 ptimer_transaction_begin(s->ptimer); 118 oldval = s->control; 119 s->control &= 0xfffffff8; 120 s->control |= value & 7; 121 122 if ((oldval ^ value) & SYSTICK_ENABLE) { 123 if (value & SYSTICK_ENABLE) { 124 /* 125 * Always reload the period in case board code has 126 * changed system_clock_scale. If we ever replace that 127 * global with a more sensible API then we might be able 128 * to set the period only when it actually changes. 129 */ 130 ptimer_set_period(s->ptimer, systick_scale(s)); 131 ptimer_run(s->ptimer, 0); 132 } else { 133 ptimer_stop(s->ptimer); 134 } 135 } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) { 136 ptimer_set_period(s->ptimer, systick_scale(s)); 137 } 138 ptimer_transaction_commit(s->ptimer); 139 break; 140 } 141 case 0x4: /* SysTick Reload Value. */ 142 ptimer_transaction_begin(s->ptimer); 143 ptimer_set_limit(s->ptimer, value & 0xffffff, 0); 144 ptimer_transaction_commit(s->ptimer); 145 break; 146 case 0x8: /* SysTick Current Value. */ 147 /* 148 * Writing any value clears SYST_CVR to zero and clears 149 * SYST_CSR.COUNTFLAG. The counter will then reload from SYST_RVR 150 * on the next clock edge unless SYST_RVR is zero. 151 */ 152 ptimer_transaction_begin(s->ptimer); 153 if (ptimer_get_limit(s->ptimer) == 0) { 154 ptimer_stop(s->ptimer); 155 } 156 ptimer_set_count(s->ptimer, 0); 157 s->control &= ~SYSTICK_COUNTFLAG; 158 ptimer_transaction_commit(s->ptimer); 159 break; 160 default: 161 qemu_log_mask(LOG_GUEST_ERROR, 162 "SysTick: Bad write offset 0x%" HWADDR_PRIx "\n", addr); 163 } 164 return MEMTX_OK; 165 } 166 167 static const MemoryRegionOps systick_ops = { 168 .read_with_attrs = systick_read, 169 .write_with_attrs = systick_write, 170 .endianness = DEVICE_NATIVE_ENDIAN, 171 .valid.min_access_size = 4, 172 .valid.max_access_size = 4, 173 }; 174 175 static void systick_reset(DeviceState *dev) 176 { 177 SysTickState *s = SYSTICK(dev); 178 179 /* 180 * Forgetting to set system_clock_scale is always a board code 181 * bug. We can't check this earlier because for some boards 182 * (like stellaris) it is not yet configured at the point where 183 * the systick device is realized. 184 */ 185 assert(system_clock_scale != 0); 186 187 ptimer_transaction_begin(s->ptimer); 188 s->control = 0; 189 ptimer_stop(s->ptimer); 190 ptimer_set_count(s->ptimer, 0); 191 ptimer_set_limit(s->ptimer, 0, 0); 192 ptimer_set_period(s->ptimer, systick_scale(s)); 193 ptimer_transaction_commit(s->ptimer); 194 } 195 196 static void systick_instance_init(Object *obj) 197 { 198 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 199 SysTickState *s = SYSTICK(obj); 200 201 memory_region_init_io(&s->iomem, obj, &systick_ops, s, "systick", 0xe0); 202 sysbus_init_mmio(sbd, &s->iomem); 203 sysbus_init_irq(sbd, &s->irq); 204 } 205 206 static void systick_realize(DeviceState *dev, Error **errp) 207 { 208 SysTickState *s = SYSTICK(dev); 209 s->ptimer = ptimer_init(systick_timer_tick, s, 210 PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD | 211 PTIMER_POLICY_NO_COUNTER_ROUND_DOWN | 212 PTIMER_POLICY_NO_IMMEDIATE_RELOAD | 213 PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT); 214 } 215 216 static const VMStateDescription vmstate_systick = { 217 .name = "armv7m_systick", 218 .version_id = 2, 219 .minimum_version_id = 2, 220 .fields = (VMStateField[]) { 221 VMSTATE_UINT32(control, SysTickState), 222 VMSTATE_INT64(tick, SysTickState), 223 VMSTATE_PTIMER(ptimer, SysTickState), 224 VMSTATE_END_OF_LIST() 225 } 226 }; 227 228 static void systick_class_init(ObjectClass *klass, void *data) 229 { 230 DeviceClass *dc = DEVICE_CLASS(klass); 231 232 dc->vmsd = &vmstate_systick; 233 dc->reset = systick_reset; 234 dc->realize = systick_realize; 235 } 236 237 static const TypeInfo armv7m_systick_info = { 238 .name = TYPE_SYSTICK, 239 .parent = TYPE_SYS_BUS_DEVICE, 240 .instance_init = systick_instance_init, 241 .instance_size = sizeof(SysTickState), 242 .class_init = systick_class_init, 243 }; 244 245 static void armv7m_systick_register_types(void) 246 { 247 type_register_static(&armv7m_systick_info); 248 } 249 250 type_init(armv7m_systick_register_types) 251