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