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