1 /* 2 * Arm SSE Subsystem System Counter 3 * 4 * Copyright (c) 2020 Linaro Limited 5 * Written by Peter Maydell 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 or 9 * (at your option) any later version. 10 */ 11 12 /* 13 * This is a model of the "System counter" which is documented in 14 * the Arm SSE-123 Example Subsystem Technical Reference Manual: 15 * https://developer.arm.com/documentation/101370/latest/ 16 * 17 * QEMU interface: 18 * + Clock input "CLK": clock 19 * + sysbus MMIO region 0: the control register frame 20 * + sysbus MMIO region 1: the status register frame 21 * 22 * Consumers of the system counter's timestamp, such as the SSE 23 * System Timer device, can also use the APIs sse_counter_for_timestamp(), 24 * sse_counter_tick_to_time() and sse_counter_register_consumer() to 25 * interact with an instance of the System Counter. Generally the 26 * consumer device should have a QOM link property which the board 27 * code can set to the appropriate instance of the system counter. 28 */ 29 30 #ifndef SSE_COUNTER_H 31 #define SSE_COUNTER_H 32 33 #include "hw/sysbus.h" 34 #include "qom/object.h" 35 #include "qemu/notify.h" 36 37 #define TYPE_SSE_COUNTER "sse-counter" 38 OBJECT_DECLARE_SIMPLE_TYPE(SSECounter, SSE_COUNTER) 39 40 struct SSECounter { 41 /*< private >*/ 42 SysBusDevice parent_obj; 43 44 /*< public >*/ 45 MemoryRegion control_mr; 46 MemoryRegion status_mr; 47 Clock *clk; 48 NotifierList notifier_list; 49 50 uint32_t cntcr; 51 uint32_t cntscr0; 52 53 /* 54 * These are used for handling clock frequency changes: they are a 55 * tuple of (QEMU_CLOCK_VIRTUAL timestamp, CNTCV at that time), 56 * taken when the clock frequency changes. sse_cntcv() needs them 57 * to calculate the current CNTCV. 58 */ 59 uint64_t ns_then; 60 uint64_t ticks_then; 61 }; 62 63 /* 64 * These functions are the interface by which a consumer of 65 * the system timestamp (such as the SSE system timer device) 66 * can communicate with the SSECounter. 67 */ 68 69 /** 70 * sse_counter_for_timestamp: 71 * @counter: SSECounter 72 * @ns: timestamp of QEMU_CLOCK_VIRTUAL in nanoseconds 73 * 74 * Returns the value of the timestamp counter at the specified 75 * point in time (assuming that no changes to scale factor, enable, etc 76 * happen in the meantime). 77 */ 78 uint64_t sse_counter_for_timestamp(SSECounter *counter, uint64_t ns); 79 80 /** 81 * sse_counter_tick_to_time: 82 * @counter: SSECounter 83 * @tick: tick value 84 * 85 * Returns the time (a QEMU_CLOCK_VIRTUAL timestamp in nanoseconds) 86 * when the timestamp counter will reach the specified tick count. 87 * If the counter is not currently running, returns UINT64_MAX. 88 */ 89 uint64_t sse_counter_tick_to_time(SSECounter *counter, uint64_t tick); 90 91 /** 92 * sse_counter_register_consumer: 93 * @counter: SSECounter 94 * @notifier: Notifier which is notified on counter changes 95 * 96 * Registers @notifier with the SSECounter. When the counter's 97 * configuration changes in a way that might invalidate information 98 * previously returned via sse_counter_for_timestamp() or 99 * sse_counter_tick_to_time(), the notifier will be called. 100 * Devices which consume the timestamp counter can use this as 101 * a cue to recalculate timer events. 102 */ 103 void sse_counter_register_consumer(SSECounter *counter, Notifier *notifier); 104 105 #endif 106