summaryrefslogtreecommitdiffstats
path: root/hw/core
diff options
context:
space:
mode:
Diffstat (limited to 'hw/core')
-rw-r--r--hw/core/ptimer.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
index 2aa97cb665..6ba19fd965 100644
--- a/hw/core/ptimer.c
+++ b/hw/core/ptimer.c
@@ -15,6 +15,7 @@
#include "sysemu/qtest.h"
#include "block/aio.h"
#include "sysemu/cpus.h"
+#include "hw/clock.h"
#define DELTA_ADJUST 1
#define DELTA_NO_ADJUST -1
@@ -348,6 +349,39 @@ void ptimer_set_period(ptimer_state *s, int64_t period)
}
}
+/* Set counter increment interval from a Clock */
+void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clk,
+ unsigned int divisor)
+{
+ /*
+ * The raw clock period is a 64-bit value in units of 2^-32 ns;
+ * put another way it's a 32.32 fixed-point ns value. Our internal
+ * representation of the period is 64.32 fixed point ns, so
+ * the conversion is simple.
+ */
+ uint64_t raw_period = clock_get(clk);
+ uint64_t period_frac;
+
+ assert(s->in_transaction);
+ s->delta = ptimer_get_count(s);
+ s->period = extract64(raw_period, 32, 32);
+ period_frac = extract64(raw_period, 0, 32);
+ /*
+ * divisor specifies a possible frequency divisor between the
+ * clock and the timer, so it is a multiplier on the period.
+ * We do the multiply after splitting the raw period out into
+ * period and frac to avoid having to do a 32*64->96 multiply.
+ */
+ s->period *= divisor;
+ period_frac *= divisor;
+ s->period += extract64(period_frac, 32, 32);
+ s->period_frac = (uint32_t)period_frac;
+
+ if (s->enabled) {
+ s->need_reload = true;
+ }
+}
+
/* Set counter frequency in Hz. */
void ptimer_set_freq(ptimer_state *s, uint32_t freq)
{