| /* | |
| * Arm SSE Subsystem System Counter | |
| * | |
| * Copyright (c) 2020 Linaro Limited | |
| * Written by Peter Maydell | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License version 2 or | |
| * (at your option) any later version. | |
| */ | |
| /* | |
| * This is a model of the "System counter" which is documented in | |
| * the Arm SSE-123 Example Subsystem Technical Reference Manual: | |
| * https://developer.arm.com/documentation/101370/latest/ | |
| * | |
| * QEMU interface: | |
| * + Clock input "CLK": clock | |
| * + sysbus MMIO region 0: the control register frame | |
| * + sysbus MMIO region 1: the status register frame | |
| * | |
| * Consumers of the system counter's timestamp, such as the SSE | |
| * System Timer device, can also use the APIs sse_counter_for_timestamp(), | |
| * sse_counter_tick_to_time() and sse_counter_register_consumer() to | |
| * interact with an instance of the System Counter. Generally the | |
| * consumer device should have a QOM link property which the board | |
| * code can set to the appropriate instance of the system counter. | |
| */ | |
| #ifndef SSE_COUNTER_H | |
| #define SSE_COUNTER_H | |
| #include "hw/core/sysbus.h" | |
| #include "qom/object.h" | |
| #include "qemu/notify.h" | |
| #define TYPE_SSE_COUNTER "sse-counter" | |
| OBJECT_DECLARE_SIMPLE_TYPE(SSECounter, SSE_COUNTER) | |
| struct SSECounter { | |
| /*< private >*/ | |
| SysBusDevice parent_obj; | |
| /*< public >*/ | |
| MemoryRegion control_mr; | |
| MemoryRegion status_mr; | |
| Clock *clk; | |
| NotifierList notifier_list; | |
| uint32_t cntcr; | |
| uint32_t cntscr0; | |
| /* | |
| * These are used for handling clock frequency changes: they are a | |
| * tuple of (QEMU_CLOCK_VIRTUAL timestamp, CNTCV at that time), | |
| * taken when the clock frequency changes. sse_cntcv() needs them | |
| * to calculate the current CNTCV. | |
| */ | |
| uint64_t ns_then; | |
| uint64_t ticks_then; | |
| }; | |
| /* | |
| * These functions are the interface by which a consumer of | |
| * the system timestamp (such as the SSE system timer device) | |
| * can communicate with the SSECounter. | |
| */ | |
| /** | |
| * sse_counter_for_timestamp: | |
| * @counter: SSECounter | |
| * @ns: timestamp of QEMU_CLOCK_VIRTUAL in nanoseconds | |
| * | |
| * Returns the value of the timestamp counter at the specified | |
| * point in time (assuming that no changes to scale factor, enable, etc | |
| * happen in the meantime). | |
| */ | |
| uint64_t sse_counter_for_timestamp(SSECounter *counter, uint64_t ns); | |
| /** | |
| * sse_counter_tick_to_time: | |
| * @counter: SSECounter | |
| * @tick: tick value | |
| * | |
| * Returns the time (a QEMU_CLOCK_VIRTUAL timestamp in nanoseconds) | |
| * when the timestamp counter will reach the specified tick count. | |
| * If the counter is not currently running, returns UINT64_MAX. | |
| */ | |
| uint64_t sse_counter_tick_to_time(SSECounter *counter, uint64_t tick); | |
| /** | |
| * sse_counter_register_consumer: | |
| * @counter: SSECounter | |
| * @notifier: Notifier which is notified on counter changes | |
| * | |
| * Registers @notifier with the SSECounter. When the counter's | |
| * configuration changes in a way that might invalidate information | |
| * previously returned via sse_counter_for_timestamp() or | |
| * sse_counter_tick_to_time(), the notifier will be called. | |
| * Devices which consume the timestamp counter can use this as | |
| * a cue to recalculate timer events. | |
| */ | |
| void sse_counter_register_consumer(SSECounter *counter, Notifier *notifier); | |
| #endif |