1ff68dacbSPeter Maydell /* 2ff68dacbSPeter Maydell * ARMv7M SysTick timer 3ff68dacbSPeter Maydell * 4ff68dacbSPeter Maydell * Copyright (c) 2006-2007 CodeSourcery. 5ff68dacbSPeter Maydell * Written by Paul Brook 6ff68dacbSPeter Maydell * Copyright (c) 2017 Linaro Ltd 7ff68dacbSPeter Maydell * Written by Peter Maydell 8ff68dacbSPeter Maydell * 9ff68dacbSPeter Maydell * This code is licensed under the GPL (version 2 or later). 10ff68dacbSPeter Maydell */ 11ff68dacbSPeter Maydell 12ff68dacbSPeter Maydell #include "qemu/osdep.h" 13ff68dacbSPeter Maydell #include "hw/timer/armv7m_systick.h" 14d6454270SMarkus Armbruster #include "migration/vmstate.h" 1564552b6bSMarkus Armbruster #include "hw/irq.h" 16ff68dacbSPeter Maydell #include "hw/sysbus.h" 17*5c6e1a1cSPeter Maydell #include "hw/qdev-clock.h" 18ff68dacbSPeter Maydell #include "qemu/timer.h" 19ff68dacbSPeter Maydell #include "qemu/log.h" 200b8fa32fSMarkus Armbruster #include "qemu/module.h" 21ff68dacbSPeter Maydell #include "trace.h" 22ff68dacbSPeter Maydell 23ff68dacbSPeter Maydell /* qemu timers run at 1GHz. We want something closer to 1MHz. */ 24ff68dacbSPeter Maydell #define SYSTICK_SCALE 1000ULL 25ff68dacbSPeter Maydell 26ff68dacbSPeter Maydell #define SYSTICK_ENABLE (1 << 0) 27ff68dacbSPeter Maydell #define SYSTICK_TICKINT (1 << 1) 28ff68dacbSPeter Maydell #define SYSTICK_CLKSOURCE (1 << 2) 29ff68dacbSPeter Maydell #define SYSTICK_COUNTFLAG (1 << 16) 30ff68dacbSPeter Maydell 31ff68dacbSPeter Maydell int system_clock_scale; 32ff68dacbSPeter Maydell 33ff68dacbSPeter Maydell /* Conversion factor from qemu timer to SysTick frequencies. */ 34ff68dacbSPeter Maydell static inline int64_t systick_scale(SysTickState *s) 35ff68dacbSPeter Maydell { 36ff68dacbSPeter Maydell if (s->control & SYSTICK_CLKSOURCE) { 37ff68dacbSPeter Maydell return system_clock_scale; 38ff68dacbSPeter Maydell } else { 39ff68dacbSPeter Maydell return 1000; 40ff68dacbSPeter Maydell } 41ff68dacbSPeter Maydell } 42ff68dacbSPeter Maydell 43ff68dacbSPeter Maydell static void systick_timer_tick(void *opaque) 44ff68dacbSPeter Maydell { 45ff68dacbSPeter Maydell SysTickState *s = (SysTickState *)opaque; 46ff68dacbSPeter Maydell 47ff68dacbSPeter Maydell trace_systick_timer_tick(); 48ff68dacbSPeter Maydell 49ff68dacbSPeter Maydell s->control |= SYSTICK_COUNTFLAG; 50ff68dacbSPeter Maydell if (s->control & SYSTICK_TICKINT) { 51ff68dacbSPeter Maydell /* Tell the NVIC to pend the SysTick exception */ 52ff68dacbSPeter Maydell qemu_irq_pulse(s->irq); 53ff68dacbSPeter Maydell } 5432bd322aSPeter Maydell if (ptimer_get_limit(s->ptimer) == 0) { 5532bd322aSPeter Maydell /* 5632bd322aSPeter Maydell * Timer expiry with SYST_RVR zero disables the timer 5732bd322aSPeter Maydell * (but doesn't clear SYST_CSR.ENABLE) 5832bd322aSPeter Maydell */ 5932bd322aSPeter Maydell ptimer_stop(s->ptimer); 60ff68dacbSPeter Maydell } 61ff68dacbSPeter Maydell } 62ff68dacbSPeter Maydell 639bed521eSPeter Maydell static MemTxResult systick_read(void *opaque, hwaddr addr, uint64_t *data, 649bed521eSPeter Maydell unsigned size, MemTxAttrs attrs) 65ff68dacbSPeter Maydell { 66ff68dacbSPeter Maydell SysTickState *s = opaque; 67ff68dacbSPeter Maydell uint32_t val; 68ff68dacbSPeter Maydell 699bed521eSPeter Maydell if (attrs.user) { 709bed521eSPeter Maydell /* Generate BusFault for unprivileged accesses */ 719bed521eSPeter Maydell return MEMTX_ERROR; 729bed521eSPeter Maydell } 739bed521eSPeter Maydell 74ff68dacbSPeter Maydell switch (addr) { 75ff68dacbSPeter Maydell case 0x0: /* SysTick Control and Status. */ 76ff68dacbSPeter Maydell val = s->control; 77ff68dacbSPeter Maydell s->control &= ~SYSTICK_COUNTFLAG; 78ff68dacbSPeter Maydell break; 79ff68dacbSPeter Maydell case 0x4: /* SysTick Reload Value. */ 8032bd322aSPeter Maydell val = ptimer_get_limit(s->ptimer); 81ff68dacbSPeter Maydell break; 82ff68dacbSPeter Maydell case 0x8: /* SysTick Current Value. */ 8332bd322aSPeter Maydell val = ptimer_get_count(s->ptimer); 84ff68dacbSPeter Maydell break; 85ff68dacbSPeter Maydell case 0xc: /* SysTick Calibration Value. */ 86ff68dacbSPeter Maydell val = 10000; 87ff68dacbSPeter Maydell break; 88ff68dacbSPeter Maydell default: 89ff68dacbSPeter Maydell val = 0; 90ff68dacbSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 91ff68dacbSPeter Maydell "SysTick: Bad read offset 0x%" HWADDR_PRIx "\n", addr); 92ff68dacbSPeter Maydell break; 93ff68dacbSPeter Maydell } 94ff68dacbSPeter Maydell 95ff68dacbSPeter Maydell trace_systick_read(addr, val, size); 969bed521eSPeter Maydell *data = val; 979bed521eSPeter Maydell return MEMTX_OK; 98ff68dacbSPeter Maydell } 99ff68dacbSPeter Maydell 1009bed521eSPeter Maydell static MemTxResult systick_write(void *opaque, hwaddr addr, 1019bed521eSPeter Maydell uint64_t value, unsigned size, 1029bed521eSPeter Maydell MemTxAttrs attrs) 103ff68dacbSPeter Maydell { 104ff68dacbSPeter Maydell SysTickState *s = opaque; 105ff68dacbSPeter Maydell 1069bed521eSPeter Maydell if (attrs.user) { 1079bed521eSPeter Maydell /* Generate BusFault for unprivileged accesses */ 1089bed521eSPeter Maydell return MEMTX_ERROR; 1099bed521eSPeter Maydell } 1109bed521eSPeter Maydell 111ff68dacbSPeter Maydell trace_systick_write(addr, value, size); 112ff68dacbSPeter Maydell 113ff68dacbSPeter Maydell switch (addr) { 114ff68dacbSPeter Maydell case 0x0: /* SysTick Control and Status. */ 115ff68dacbSPeter Maydell { 11632bd322aSPeter Maydell uint32_t oldval; 117ff68dacbSPeter Maydell 11832bd322aSPeter Maydell ptimer_transaction_begin(s->ptimer); 11932bd322aSPeter Maydell oldval = s->control; 120ff68dacbSPeter Maydell s->control &= 0xfffffff8; 121ff68dacbSPeter Maydell s->control |= value & 7; 12232bd322aSPeter Maydell 123ff68dacbSPeter Maydell if ((oldval ^ value) & SYSTICK_ENABLE) { 124ff68dacbSPeter Maydell if (value & SYSTICK_ENABLE) { 12532bd322aSPeter Maydell /* 12632bd322aSPeter Maydell * Always reload the period in case board code has 12732bd322aSPeter Maydell * changed system_clock_scale. If we ever replace that 12832bd322aSPeter Maydell * global with a more sensible API then we might be able 12932bd322aSPeter Maydell * to set the period only when it actually changes. 13032bd322aSPeter Maydell */ 13132bd322aSPeter Maydell ptimer_set_period(s->ptimer, systick_scale(s)); 13232bd322aSPeter Maydell ptimer_run(s->ptimer, 0); 133ff68dacbSPeter Maydell } else { 13432bd322aSPeter Maydell ptimer_stop(s->ptimer); 135ff68dacbSPeter Maydell } 136ff68dacbSPeter Maydell } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) { 13732bd322aSPeter Maydell ptimer_set_period(s->ptimer, systick_scale(s)); 138ff68dacbSPeter Maydell } 13932bd322aSPeter Maydell ptimer_transaction_commit(s->ptimer); 140ff68dacbSPeter Maydell break; 141ff68dacbSPeter Maydell } 142ff68dacbSPeter Maydell case 0x4: /* SysTick Reload Value. */ 14332bd322aSPeter Maydell ptimer_transaction_begin(s->ptimer); 14432bd322aSPeter Maydell ptimer_set_limit(s->ptimer, value & 0xffffff, 0); 14532bd322aSPeter Maydell ptimer_transaction_commit(s->ptimer); 146ff68dacbSPeter Maydell break; 14732bd322aSPeter Maydell case 0x8: /* SysTick Current Value. */ 14832bd322aSPeter Maydell /* 14932bd322aSPeter Maydell * Writing any value clears SYST_CVR to zero and clears 15032bd322aSPeter Maydell * SYST_CSR.COUNTFLAG. The counter will then reload from SYST_RVR 15132bd322aSPeter Maydell * on the next clock edge unless SYST_RVR is zero. 15232bd322aSPeter Maydell */ 15332bd322aSPeter Maydell ptimer_transaction_begin(s->ptimer); 15432bd322aSPeter Maydell if (ptimer_get_limit(s->ptimer) == 0) { 15532bd322aSPeter Maydell ptimer_stop(s->ptimer); 15632bd322aSPeter Maydell } 15732bd322aSPeter Maydell ptimer_set_count(s->ptimer, 0); 158ff68dacbSPeter Maydell s->control &= ~SYSTICK_COUNTFLAG; 15932bd322aSPeter Maydell ptimer_transaction_commit(s->ptimer); 160ff68dacbSPeter Maydell break; 161ff68dacbSPeter Maydell default: 162ff68dacbSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 163ff68dacbSPeter Maydell "SysTick: Bad write offset 0x%" HWADDR_PRIx "\n", addr); 164ff68dacbSPeter Maydell } 1659bed521eSPeter Maydell return MEMTX_OK; 166ff68dacbSPeter Maydell } 167ff68dacbSPeter Maydell 168ff68dacbSPeter Maydell static const MemoryRegionOps systick_ops = { 1699bed521eSPeter Maydell .read_with_attrs = systick_read, 1709bed521eSPeter Maydell .write_with_attrs = systick_write, 171ff68dacbSPeter Maydell .endianness = DEVICE_NATIVE_ENDIAN, 172ff68dacbSPeter Maydell .valid.min_access_size = 4, 173ff68dacbSPeter Maydell .valid.max_access_size = 4, 174ff68dacbSPeter Maydell }; 175ff68dacbSPeter Maydell 176ff68dacbSPeter Maydell static void systick_reset(DeviceState *dev) 177ff68dacbSPeter Maydell { 178ff68dacbSPeter Maydell SysTickState *s = SYSTICK(dev); 179ff68dacbSPeter Maydell 180c9ebc8c2SPeter Maydell /* 181c9ebc8c2SPeter Maydell * Forgetting to set system_clock_scale is always a board code 182c9ebc8c2SPeter Maydell * bug. We can't check this earlier because for some boards 183c9ebc8c2SPeter Maydell * (like stellaris) it is not yet configured at the point where 184c9ebc8c2SPeter Maydell * the systick device is realized. 185c9ebc8c2SPeter Maydell */ 186c9ebc8c2SPeter Maydell assert(system_clock_scale != 0); 187c9ebc8c2SPeter Maydell 18832bd322aSPeter Maydell ptimer_transaction_begin(s->ptimer); 189ff68dacbSPeter Maydell s->control = 0; 19032bd322aSPeter Maydell ptimer_stop(s->ptimer); 19132bd322aSPeter Maydell ptimer_set_count(s->ptimer, 0); 19232bd322aSPeter Maydell ptimer_set_limit(s->ptimer, 0, 0); 19332bd322aSPeter Maydell ptimer_set_period(s->ptimer, systick_scale(s)); 19432bd322aSPeter Maydell ptimer_transaction_commit(s->ptimer); 195ff68dacbSPeter Maydell } 196ff68dacbSPeter Maydell 197ff68dacbSPeter Maydell static void systick_instance_init(Object *obj) 198ff68dacbSPeter Maydell { 199ff68dacbSPeter Maydell SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 200ff68dacbSPeter Maydell SysTickState *s = SYSTICK(obj); 201ff68dacbSPeter Maydell 202ff68dacbSPeter Maydell memory_region_init_io(&s->iomem, obj, &systick_ops, s, "systick", 0xe0); 203ff68dacbSPeter Maydell sysbus_init_mmio(sbd, &s->iomem); 204ff68dacbSPeter Maydell sysbus_init_irq(sbd, &s->irq); 205*5c6e1a1cSPeter Maydell 206*5c6e1a1cSPeter Maydell s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", NULL, NULL, 0); 207*5c6e1a1cSPeter Maydell s->cpuclk = qdev_init_clock_in(DEVICE(obj), "cpuclk", NULL, NULL, 0); 208f3a508ebSPan Nengyuan } 209f3a508ebSPan Nengyuan 210f3a508ebSPan Nengyuan static void systick_realize(DeviceState *dev, Error **errp) 211f3a508ebSPan Nengyuan { 212f3a508ebSPan Nengyuan SysTickState *s = SYSTICK(dev); 21332bd322aSPeter Maydell s->ptimer = ptimer_init(systick_timer_tick, s, 21432bd322aSPeter Maydell PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD | 21532bd322aSPeter Maydell PTIMER_POLICY_NO_COUNTER_ROUND_DOWN | 21632bd322aSPeter Maydell PTIMER_POLICY_NO_IMMEDIATE_RELOAD | 21732bd322aSPeter Maydell PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT); 218ff68dacbSPeter Maydell } 219ff68dacbSPeter Maydell 220ff68dacbSPeter Maydell static const VMStateDescription vmstate_systick = { 221ff68dacbSPeter Maydell .name = "armv7m_systick", 222*5c6e1a1cSPeter Maydell .version_id = 3, 223*5c6e1a1cSPeter Maydell .minimum_version_id = 3, 224ff68dacbSPeter Maydell .fields = (VMStateField[]) { 225*5c6e1a1cSPeter Maydell VMSTATE_CLOCK(refclk, SysTickState), 226*5c6e1a1cSPeter Maydell VMSTATE_CLOCK(cpuclk, SysTickState), 227ff68dacbSPeter Maydell VMSTATE_UINT32(control, SysTickState), 228ff68dacbSPeter Maydell VMSTATE_INT64(tick, SysTickState), 22932bd322aSPeter Maydell VMSTATE_PTIMER(ptimer, SysTickState), 230ff68dacbSPeter Maydell VMSTATE_END_OF_LIST() 231ff68dacbSPeter Maydell } 232ff68dacbSPeter Maydell }; 233ff68dacbSPeter Maydell 234ff68dacbSPeter Maydell static void systick_class_init(ObjectClass *klass, void *data) 235ff68dacbSPeter Maydell { 236ff68dacbSPeter Maydell DeviceClass *dc = DEVICE_CLASS(klass); 237ff68dacbSPeter Maydell 238ff68dacbSPeter Maydell dc->vmsd = &vmstate_systick; 239ff68dacbSPeter Maydell dc->reset = systick_reset; 240f3a508ebSPan Nengyuan dc->realize = systick_realize; 241ff68dacbSPeter Maydell } 242ff68dacbSPeter Maydell 243ff68dacbSPeter Maydell static const TypeInfo armv7m_systick_info = { 244ff68dacbSPeter Maydell .name = TYPE_SYSTICK, 245ff68dacbSPeter Maydell .parent = TYPE_SYS_BUS_DEVICE, 246ff68dacbSPeter Maydell .instance_init = systick_instance_init, 247ff68dacbSPeter Maydell .instance_size = sizeof(SysTickState), 248ff68dacbSPeter Maydell .class_init = systick_class_init, 249ff68dacbSPeter Maydell }; 250ff68dacbSPeter Maydell 251ff68dacbSPeter Maydell static void armv7m_systick_register_types(void) 252ff68dacbSPeter Maydell { 253ff68dacbSPeter Maydell type_register_static(&armv7m_systick_info); 254ff68dacbSPeter Maydell } 255ff68dacbSPeter Maydell 256ff68dacbSPeter Maydell type_init(armv7m_systick_register_types) 257