diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-02-19 14:45:36 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-03-08 17:20:01 +0000 |
commit | cd3a53b727d2f86e9db795cee69cc142332ca079 (patch) | |
tree | a3f955d06d5c007f522254e702d6c4f9659af55d /include/hw/clock.h | |
parent | e4341623a3b87e7eca87d42b7b88da967cd21c49 (diff) |
clock: Add clock_ns_to_ticks() function
Add a clock_ns_to_ticks() function which does the opposite of
clock_ticks_to_ns(): given a duration in nanoseconds, it returns the
number of clock ticks that would happen in that time. This is useful
for devices that have a free running counter register whose value can
be calculated when it is read.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Luc Michel <luc@lmichel.fr>
Reviewed-by: Hao Wu <wuhaotsh@google.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210219144617.4782-4-peter.maydell@linaro.org
Diffstat (limited to 'include/hw/clock.h')
-rw-r--r-- | include/hw/clock.h | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/include/hw/clock.h b/include/hw/clock.h index 2ba44e1442..a7187eab95 100644 --- a/include/hw/clock.h +++ b/include/hw/clock.h @@ -287,6 +287,47 @@ static inline uint64_t clock_ticks_to_ns(const Clock *clk, uint64_t ticks) } /** + * clock_ns_to_ticks: + * @clk: the clock to query + * @ns: duration in nanoseconds + * + * Returns the number of ticks this clock would make in the given + * number of nanoseconds. Because a clock can have a period which + * is not a whole number of nanoseconds, it is important to use this + * function rather than attempting to obtain a "period in nanoseconds" + * value and then dividing the duration by that value. + * + * If the clock is stopped (ie it has period zero), returns 0. + * + * For some inputs the result could overflow a 64-bit value (because + * the clock's period is short and the duration is long). In these + * cases we truncate the result to a 64-bit value. This is on the + * assumption that generally the result is going to be used to report + * a 32-bit or 64-bit guest register value, so wrapping either cannot + * happen or is the desired behaviour. + */ +static inline uint64_t clock_ns_to_ticks(const Clock *clk, uint64_t ns) +{ + /* + * ticks = duration_in_ns / period_in_ns + * = ns / (period / 2^32) + * = (ns * 2^32) / period + * The hi, lo inputs to divu128() are (ns << 32) as a 128 bit value. + */ + uint64_t lo = ns << 32; + uint64_t hi = ns >> 32; + if (clk->period == 0) { + return 0; + } + /* + * Ignore divu128() return value as we've caught div-by-zero and don't + * need different behaviour for overflow. + */ + divu128(&lo, &hi, clk->period); + return lo; +} + +/** * clock_is_enabled: * @clk: a clock * |