master
c 667 lines 20.3 KB
Raw
1 /*
2 * Qualcomm QCT QTimer
3 *
4 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include "qemu/osdep.h"
9 #include "hw/core/irq.h"
10 #include "hw/core/qdev-properties.h"
11 #include "hw/core/sysbus.h"
12 #include "hw/timer/qct-qtimer.h"
13 #include "migration/vmstate.h"
14 #include "qemu/bitops.h"
15 #include "qemu/log.h"
16 #include "qemu/module.h"
17 #include "qemu/timer.h"
18 #include "qapi/error.h"
19 #include "trace.h"
20
21 #define QTIMER_MEM_SIZE_BYTES 0x1000
22 #define QTIMER_DEFAULT_FREQ_HZ 19200000ULL
23
24 #define QCT_QTIMER_TIMER_FRAME_ELTS (16)
25 #define QCT_QTIMER_TIMER_VIEW_ELTS (2)
26
27 #define QCT_QTIMER_AC_CNTFRQ (0x000)
28 #define QCT_QTIMER_AC_CNTSR (0x004)
29 #define QCT_QTIMER_AC_CNTTID_0 (0x08)
30 #define QCT_QTIMER_AC_CNTACR_START (0x40)
31 #define QCT_QTIMER_AC_CNTACR_END (0x5c)
32 #define QCT_QTIMER_AC_CNTTID_1 (0x108)
33 #define QCT_QTIMER_AC_CNTACR_RWPT (1 << 5) /* R/W of CNTP_* regs */
34 #define QCT_QTIMER_AC_CNTACR_RWVT (1 << 4) /* R/W of CNTV_* regs */
35 #define QCT_QTIMER_AC_CNTACR_RVOFF (1 << 3) /* R/W of CNTVOFF register */
36 #define QCT_QTIMER_AC_CNTACR_RFRQ (1 << 2) /* R/W of CNTFRQ register */
37 #define QCT_QTIMER_AC_CNTACR_RPVCT (1 << 1) /* R/W of CNTVCT register */
38 #define QCT_QTIMER_AC_CNTACR_RPCT (1 << 0) /* R/W of CNTPCT register */
39 #define QCT_QTIMER_VERSION (0x0fd0)
40
41 #define QCT_QTIMER_CNTPCT_LO (0x000)
42 #define QCT_QTIMER_CNTPCT_HI (0x004)
43 #define QCT_QTIMER_CNT_FREQ (0x010)
44 #define QCT_QTIMER_CNTPL0ACR (0x014)
45 #define QCT_QTIMER_CNTPL0ACR_PL0CTEN (1 << 9)
46 #define QCT_QTIMER_CNTPL0ACR_PL0TVEN (1 << 8)
47 #define QCT_QTIMER_CNTPL0ACR_PL0VCTEN (1 << 1)
48 #define QCT_QTIMER_CNTPL0ACR_PL0PCTEN (1 << 0)
49 #define QCT_QTIMER_CNTP_CVAL_LO (0x020)
50 #define QCT_QTIMER_CNTP_CVAL_HI (0x024)
51 #define QCT_QTIMER_CNT_MASK 0x00ffffffffffffffULL
52 #define QCT_QTIMER_CNT_HI_BITS 24
53 #define QCT_QTIMER_CNTP_TVAL (0x028)
54 #define QCT_QTIMER_CNTP_CTL (0x02c)
55 #define QCT_QTIMER_CNTP_CTL_ENABLE (1 << 0)
56 #define QCT_QTIMER_CNTP_CTL_INTEN (1 << 1)
57 #define QCT_QTIMER_CNTP_CTL_ISTAT (1 << 2)
58
59 OBJECT_DECLARE_SIMPLE_TYPE(QCTQtimerState, QCT_QTIMER)
60
61 typedef struct QCTHextimerState {
62 QCTQtimerState *qtimer;
63 QEMUTimer *timer; /* one-shot deadline timer */
64 int64_t offset_ns; /* QEMU_CLOCK_VIRTUAL ns at which cntpct == 0 */
65 uint64_t cntval; /* 64-bit physical timer compare value */
66 uint32_t control;
67 uint32_t cnt_ctrl;
68 uint32_t cntpl0acr;
69 uint32_t int_level;
70 qemu_irq irq;
71 } QCTHextimerState;
72
73 struct QCTQtimerState {
74 SysBusDevice parent_obj;
75
76 MemoryRegion iomem;
77 MemoryRegion view_iomem;
78 uint32_t secure;
79 QCTHextimerState timer[QCT_QTIMER_TIMER_FRAME_ELTS];
80 uint32_t freq_hz;
81 uint32_t nr_frames;
82 uint32_t nr_views;
83 uint32_t frame_stride;
84 uint32_t freq_scale;
85 };
86
87 /*
88 * QTimer version register:
89 *
90 * 3 2 1
91 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
92 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 * | Major | Minor | Step |
94 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95 */
96 #define QCT_QTIMER_VERSION_VALUE 0x20020000
97
98 static uint32_t qct_qtimer_cnttid(QCTQtimerState *s, unsigned int half)
99 {
100 uint32_t nibble = 0x1 | (s->nr_views > 1 ? 0x4 : 0x0);
101 uint32_t base = half * 8;
102 uint32_t cnttid = 0;
103 unsigned int i;
104
105 for (i = 0; i < 8; i++) {
106 if (base + i < s->nr_frames) {
107 cnttid |= nibble << (i * 4);
108 }
109 }
110 return cnttid;
111 }
112
113 /* Counter value derived on-demand from QEMU_CLOCK_VIRTUAL. */
114 static uint64_t hex_timer_now(QCTHextimerState *s)
115 {
116 int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
117 uint32_t scale;
118 uint64_t scaled_elapsed;
119
120 if (now <= s->offset_ns) {
121 return 0;
122 }
123 scale = MAX(s->qtimer->freq_scale, 1u);
124 scaled_elapsed = (uint64_t)(now - s->offset_ns) / scale;
125 return muldiv64(scaled_elapsed, s->qtimer->freq_hz,
126 NANOSECONDS_PER_SECOND) &
127 QCT_QTIMER_CNT_MASK;
128 }
129
130 /* Arm (or disarm) the one-shot deadline timer. */
131 static void hex_timer_rearm(QCTHextimerState *s)
132 {
133 uint32_t scale;
134 uint64_t base_ns;
135 int64_t deadline_ns;
136
137 if (!(s->control & QCT_QTIMER_CNTP_CTL_ENABLE)) {
138 timer_del(s->timer);
139 return;
140 }
141
142 scale = MAX(s->qtimer->freq_scale, 1u);
143 /*
144 * Round the ticks-to-ns conversion up so that hex_timer_now(), which
145 * truncates when it divides elapsed ns by scale, is guaranteed to
146 * report >= cntval once this deadline fires. A truncating conversion
147 * here could re-arm at the same deadline forever when scale > 1.
148 */
149 base_ns = muldiv64_round_up(s->cntval, NANOSECONDS_PER_SECOND,
150 s->qtimer->freq_hz);
151 if (base_ns >
152 ((uint64_t)INT64_MAX - (uint64_t)s->offset_ns) / scale) {
153 timer_del(s->timer);
154 return;
155 }
156 deadline_ns = s->offset_ns + (int64_t)(base_ns * scale);
157 timer_mod(s->timer, deadline_ns);
158 }
159
160 static void hex_timer_update(QCTHextimerState *s)
161 {
162 int level = s->int_level &&
163 (s->control & QCT_QTIMER_CNTP_CTL_ENABLE) &&
164 !(s->control & QCT_QTIMER_CNTP_CTL_INTEN);
165
166 trace_qtimer_interrupt();
167 qemu_set_irq(s->irq, level);
168 }
169
170 /*
171 * Access-control (AC) region: offsets below 0x1000, gates CNTFRQ/CNTSR/
172 * CNTTID/CNTACR per frame plus the shared VERSION register.
173 */
174 static uint64_t qct_qtimer_ac_read(void *opaque, hwaddr offset, unsigned size)
175 {
176 QCTQtimerState *s = opaque;
177 uint32_t frame;
178
179 switch (offset) {
180 case QCT_QTIMER_AC_CNTFRQ:
181 return s->freq_hz;
182 case QCT_QTIMER_AC_CNTSR:
183 return s->secure;
184 case QCT_QTIMER_AC_CNTTID_0:
185 return qct_qtimer_cnttid(s, 0);
186 case QCT_QTIMER_AC_CNTTID_1:
187 return qct_qtimer_cnttid(s, 1);
188 case QCT_QTIMER_AC_CNTACR_START ... QCT_QTIMER_AC_CNTACR_END:
189 frame = (offset - QCT_QTIMER_AC_CNTACR_START) / 4;
190 if (frame >= s->nr_frames) {
191 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad CNTACR offset 0x%x\n",
192 __func__, (int)offset);
193 return 0;
194 }
195 return s->timer[frame].cnt_ctrl;
196 case QCT_QTIMER_VERSION:
197 return QCT_QTIMER_VERSION_VALUE;
198 default:
199 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%x\n", __func__,
200 (int)offset);
201 return 0;
202 }
203 }
204
205 static void qct_qtimer_ac_write(void *opaque, hwaddr offset, uint64_t value,
206 unsigned size)
207 {
208 QCTQtimerState *s = opaque;
209 uint32_t frame;
210
211 switch (offset) {
212 case QCT_QTIMER_AC_CNTFRQ:
213 if (value == 0) {
214 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad CNTFRQ value 0\n",
215 __func__);
216 return;
217 }
218 s->freq_hz = value;
219 return;
220 case QCT_QTIMER_AC_CNTSR:
221 if (value > 0xff) {
222 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad CNTSR value 0x%x\n",
223 __func__, (int)value);
224 return;
225 }
226 s->secure = value;
227 return;
228 case QCT_QTIMER_AC_CNTACR_START ... QCT_QTIMER_AC_CNTACR_END:
229 frame = (offset - QCT_QTIMER_AC_CNTACR_START) / 4;
230 if (frame >= s->nr_frames) {
231 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad CNTACR offset 0x%x\n",
232 __func__, (int)offset);
233 return;
234 }
235 s->timer[frame].cnt_ctrl = value;
236 return;
237 default:
238 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%x\n", __func__,
239 (int)offset);
240 return;
241 }
242 }
243
244 static const MemoryRegionOps qct_qtimer_ac_ops = {
245 .read = qct_qtimer_ac_read,
246 .write = qct_qtimer_ac_write,
247 .endianness = DEVICE_LITTLE_ENDIAN,
248 .valid = {
249 .min_access_size = 4,
250 .max_access_size = 4,
251 .unaligned = false,
252 },
253 .impl = {
254 .min_access_size = 4,
255 .max_access_size = 4,
256 },
257 };
258
259 /*
260 * View region: a flat array of (frame, view) slots, each frame_stride
261 * bytes wide, holding the per-frame CNTPCT/CNTP_CVAL/CNTP_TVAL/CNTP_CTL
262 * register set.
263 */
264 static QCTHextimerState *qct_qtimer_demux(QCTQtimerState *s, hwaddr offset,
265 uint32_t *reg_offset,
266 uint32_t *view)
267 {
268 uint32_t stride = s->frame_stride;
269 uint32_t stride_shift = ctz32(stride);
270 uint32_t slot_nr = offset >> stride_shift;
271 uint32_t frame = slot_nr / s->nr_views;
272
273 *reg_offset = offset & (stride - 1);
274 *view = slot_nr % s->nr_views;
275 if (frame >= s->nr_frames) {
276 return NULL;
277 }
278 return &s->timer[frame];
279 }
280
281 /* Frames 8+ are described by CNTTID_1; each frame's 2nd view is a gated bit. */
282 static bool qct_qtimer_view_visible(QCTQtimerState *s, uint32_t frame,
283 uint32_t view)
284 {
285 uint32_t cnttid = qct_qtimer_cnttid(s, frame < 8 ? 0 : 1);
286 uint32_t frame_idx = frame < 8 ? frame : frame - 8;
287
288 return !view || (cnttid & (0x4 << (frame_idx * 4)));
289 }
290
291 static bool access_ok(QCTHextimerState *s, uint32_t reg_offset, uint32_t view)
292 {
293 uint32_t acr;
294 uint32_t pl0acr;
295
296 switch (reg_offset) {
297 case QCT_QTIMER_CNT_FREQ:
298 acr = QCT_QTIMER_AC_CNTACR_RFRQ;
299 pl0acr = QCT_QTIMER_CNTPL0ACR_PL0PCTEN |
300 QCT_QTIMER_CNTPL0ACR_PL0VCTEN;
301 break;
302 case QCT_QTIMER_CNTPCT_LO:
303 case QCT_QTIMER_CNTPCT_HI:
304 acr = QCT_QTIMER_AC_CNTACR_RPCT;
305 pl0acr = QCT_QTIMER_CNTPL0ACR_PL0PCTEN;
306 break;
307 case QCT_QTIMER_CNTP_CVAL_LO:
308 case QCT_QTIMER_CNTP_CVAL_HI:
309 case QCT_QTIMER_CNTP_TVAL:
310 case QCT_QTIMER_CNTP_CTL:
311 acr = QCT_QTIMER_AC_CNTACR_RWPT;
312 pl0acr = QCT_QTIMER_CNTPL0ACR_PL0CTEN;
313 break;
314 default:
315 /* CNTPL0ACR and VERSION are ungated. */
316 return true;
317 }
318
319 if (!(s->cnt_ctrl & acr)) {
320 return false;
321 }
322 return !view || (s->cntpl0acr & pl0acr);
323 }
324
325 static MemTxResult hex_timer_read(void *opaque, hwaddr offset, uint64_t *data,
326 unsigned size, MemTxAttrs attrs)
327 {
328 QCTQtimerState *qs = opaque;
329 uint32_t reg_offset;
330 uint32_t view;
331 QCTHextimerState *s = qct_qtimer_demux(qs, offset, &reg_offset, &view);
332 uint32_t frame;
333
334 if (!s) {
335 *data = 0;
336 return MEMTX_ACCESS_ERROR;
337 }
338 frame = s - qs->timer;
339
340 trace_qtimer_read(offset);
341
342 if (!qct_qtimer_view_visible(qs, frame, view)) {
343 *data = 0;
344 return MEMTX_OK;
345 }
346
347 if (!access_ok(s, reg_offset, view)) {
348 return MEMTX_ACCESS_ERROR;
349 }
350
351 switch (reg_offset) {
352 case QCT_QTIMER_CNT_FREQ:
353 *data = s->qtimer->freq_hz;
354 return MEMTX_OK;
355 case QCT_QTIMER_CNTP_CVAL_LO:
356 *data = extract64(s->cntval, 0, 32);
357 return MEMTX_OK;
358 case QCT_QTIMER_CNTP_CVAL_HI:
359 /* HI half is 24-bit per TRM; bits [31:24] are reserved. */
360 *data = extract64(s->cntval, 32, QCT_QTIMER_CNT_HI_BITS);
361 return MEMTX_OK;
362 case QCT_QTIMER_CNTPCT_LO:
363 *data = extract64(hex_timer_now(s), 0, 32);
364 return MEMTX_OK;
365 case QCT_QTIMER_CNTPCT_HI:
366 *data = extract64(hex_timer_now(s), 32, QCT_QTIMER_CNT_HI_BITS);
367 return MEMTX_OK;
368 case QCT_QTIMER_CNTP_TVAL:
369 *data = (uint32_t)(int32_t)(int64_t)(s->cntval - hex_timer_now(s));
370 return MEMTX_OK;
371 case QCT_QTIMER_CNTP_CTL:
372 /*
373 * CNTP_CTL: bit 0 EN, bit 1 IMASK, bit 2 ISTAT (interrupt
374 * pending). ISTAT tracks int_level and is read-only.
375 */
376 *data = s->control | ((s->int_level & 0x1) << 2);
377 return MEMTX_OK;
378 case QCT_QTIMER_CNTPL0ACR:
379 *data = view ? 0 : s->cntpl0acr;
380 return MEMTX_OK;
381 case QCT_QTIMER_VERSION:
382 *data = QCT_QTIMER_VERSION_VALUE;
383 return MEMTX_OK;
384 default:
385 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%x\n", __func__,
386 (int)offset);
387 *data = 0;
388 return MEMTX_ACCESS_ERROR;
389 }
390 }
391
392 static MemTxResult hex_timer_write(void *opaque, hwaddr offset,
393 uint64_t value, unsigned size,
394 MemTxAttrs attrs)
395 {
396 QCTQtimerState *qs = opaque;
397 uint32_t reg_offset;
398 uint32_t view;
399 QCTHextimerState *s = qct_qtimer_demux(qs, offset, &reg_offset, &view);
400 uint32_t frame;
401
402 if (!s) {
403 return MEMTX_ACCESS_ERROR;
404 }
405 frame = s - qs->timer;
406
407 trace_qtimer_write(offset, value);
408
409 if (!qct_qtimer_view_visible(qs, frame, view)) {
410 return MEMTX_OK;
411 }
412
413 if (!access_ok(s, reg_offset, view)) {
414 return MEMTX_ACCESS_ERROR;
415 }
416
417 switch (reg_offset) {
418 case QCT_QTIMER_CNTP_CVAL_LO:
419 s->int_level = 0;
420 s->cntval = deposit64(s->cntval, 0, 32, value);
421 hex_timer_rearm(s);
422 break;
423 case QCT_QTIMER_CNTP_CVAL_HI:
424 s->int_level = 0;
425 /* HI half is 24-bit per TRM; bits [31:24] are reserved. */
426 s->cntval = deposit64(s->cntval, 32, QCT_QTIMER_CNT_HI_BITS, value) &
427 QCT_QTIMER_CNT_MASK;
428 hex_timer_rearm(s);
429 break;
430 case QCT_QTIMER_CNTP_CTL:
431 /* ISTAT (bit 2) is read-only; keep SW writes from polluting it. */
432 s->control = value & ~QCT_QTIMER_CNTP_CTL_ISTAT;
433 hex_timer_rearm(s);
434 break;
435 case QCT_QTIMER_CNTP_TVAL:
436 /* TVAL write: CVAL = CNTPCT + TVAL (TVAL is signed 32-bit). */
437 s->int_level = 0;
438 s->cntval = (hex_timer_now(s) + (int64_t)(int32_t)value) &
439 QCT_QTIMER_CNT_MASK;
440 hex_timer_rearm(s);
441 break;
442 case QCT_QTIMER_CNTPL0ACR:
443 if (!view) {
444 s->cntpl0acr = value;
445 }
446 break;
447 default:
448 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%x\n", __func__,
449 (int)offset);
450 return MEMTX_ACCESS_ERROR;
451 }
452 hex_timer_update(s);
453 return MEMTX_OK;
454 }
455
456 static void hex_timer_tick(void *opaque)
457 {
458 QCTHextimerState *s = opaque;
459 uint64_t now = hex_timer_now(s);
460 uint64_t diff56 = (now - s->cntval) & QCT_QTIMER_CNT_MASK;
461 int64_t signed_diff = (int64_t)(diff56 << 8) >> 8;
462
463 if (signed_diff >= 0) {
464 s->int_level = 1;
465 hex_timer_update(s);
466 } else {
467 hex_timer_rearm(s);
468 }
469 }
470
471 static const MemoryRegionOps hex_timer_ops = {
472 .read_with_attrs = hex_timer_read,
473 .write_with_attrs = hex_timer_write,
474 .endianness = DEVICE_LITTLE_ENDIAN,
475 .valid = {
476 .min_access_size = 4,
477 .max_access_size = 8,
478 .unaligned = false,
479 },
480 .impl = {
481 .min_access_size = 4,
482 .max_access_size = 4,
483 },
484 };
485
486 static const VMStateDescription vmstate_qct_hextimer = {
487 .name = "qct-hextimer",
488 .version_id = 1,
489 .minimum_version_id = 1,
490 .fields = (const VMStateField[]) {
491 VMSTATE_UINT32(control, QCTHextimerState),
492 VMSTATE_UINT32(cnt_ctrl, QCTHextimerState),
493 VMSTATE_INT64(offset_ns, QCTHextimerState),
494 VMSTATE_UINT64(cntval, QCTHextimerState),
495 VMSTATE_UINT32(cntpl0acr, QCTHextimerState),
496 VMSTATE_UINT32(int_level, QCTHextimerState),
497 VMSTATE_TIMER_PTR(timer, QCTHextimerState),
498 VMSTATE_END_OF_LIST()
499 }
500 };
501
502 static const VMStateDescription vmstate_qct_qtimer = {
503 .name = "qct-qtimer",
504 .version_id = 1,
505 .minimum_version_id = 1,
506 .fields = (const VMStateField[]) {
507 VMSTATE_UINT32(freq_hz, QCTQtimerState),
508 VMSTATE_UINT32(secure, QCTQtimerState),
509 VMSTATE_STRUCT_VARRAY_UINT32(timer, QCTQtimerState, nr_frames,
510 1, vmstate_qct_hextimer, QCTHextimerState),
511 VMSTATE_END_OF_LIST()
512 }
513 };
514
515 static void qct_qtimer_realize(DeviceState *dev, Error **errp)
516 {
517 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
518 QCTQtimerState *s = QCT_QTIMER(dev);
519 unsigned int i;
520
521 if (s->nr_frames > QCT_QTIMER_TIMER_FRAME_ELTS) {
522 error_setg(errp, "nr_frames too high");
523 return;
524 }
525 if (s->nr_views > QCT_QTIMER_TIMER_VIEW_ELTS) {
526 error_setg(errp, "nr_views too high");
527 return;
528 }
529 if (s->freq_hz == 0) {
530 error_setg(errp, "freq-hz must be nonzero");
531 return;
532 }
533 if (s->frame_stride == 0 || !is_power_of_2(s->frame_stride)) {
534 error_setg(errp, "frame_stride must be a nonzero power of two");
535 return;
536 }
537
538 memory_region_init_io(&s->iomem, OBJECT(s), &qct_qtimer_ac_ops, s,
539 "qct-qtimer-ac", QTIMER_MEM_SIZE_BYTES);
540 sysbus_init_mmio(sbd, &s->iomem);
541
542 memory_region_init_io(&s->view_iomem, OBJECT(s), &hex_timer_ops, s,
543 "qct-qtimer-view",
544 (uint64_t)s->frame_stride * s->nr_frames *
545 s->nr_views);
546 sysbus_init_mmio(sbd, &s->view_iomem);
547
548 for (i = 0; i < s->nr_frames; i++) {
549 QCTHextimerState *t = &s->timer[i];
550
551 t->qtimer = s;
552 s->secure |= (1 << i);
553
554 sysbus_init_irq(sbd, &t->irq);
555 t->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, hex_timer_tick, t);
556 }
557 }
558
559 static void qct_qtimer_unrealize(DeviceState *dev)
560 {
561 QCTQtimerState *s = QCT_QTIMER(dev);
562 unsigned int i;
563
564 for (i = 0; i < s->nr_frames; i++) {
565 QCTHextimerState *t = &s->timer[i];
566
567 if (t->timer) {
568 timer_free(t->timer);
569 t->timer = NULL;
570 }
571 }
572 }
573
574 static void qct_qtimer_reset_hold(Object *obj, ResetType type)
575 {
576 QCTQtimerState *s = QCT_QTIMER(obj);
577 unsigned int i;
578
579 for (i = 0; i < s->nr_frames; i++) {
580 QCTHextimerState *t = &s->timer[i];
581
582 /*
583 * Per TRM: CTL = 0 (EN=0, IMASK=0, ISTAT=0), CVAL = 0 so that
584 * TVAL (= CVAL - CNTPCT) also reads 0 at reset. The QEMUTimer is
585 * only armed when SW sets CTL.EN=1, so cntval=0 does not cause a
586 * spurious fire before SW programs the compare value.
587 */
588 t->control = 0;
589 t->cnt_ctrl = QCT_QTIMER_AC_CNTACR_RWPT | QCT_QTIMER_AC_CNTACR_RWVT |
590 QCT_QTIMER_AC_CNTACR_RVOFF | QCT_QTIMER_AC_CNTACR_RFRQ |
591 QCT_QTIMER_AC_CNTACR_RPVCT | QCT_QTIMER_AC_CNTACR_RPCT;
592 t->cntval = 0;
593 t->cntpl0acr = 0;
594 t->int_level = 0;
595 t->offset_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
596 timer_del(t->timer);
597 qemu_set_irq(t->irq, 0);
598 }
599 }
600
601 static const Property qct_qtimer_properties[] = {
602 DEFINE_PROP_UINT32("freq-hz", QCTQtimerState, freq_hz,
603 QTIMER_DEFAULT_FREQ_HZ),
604 DEFINE_PROP_UINT32("freq-scale", QCTQtimerState, freq_scale, 1),
605 DEFINE_PROP_UINT32("nr_frames", QCTQtimerState, nr_frames, 2),
606 DEFINE_PROP_UINT32("nr_views", QCTQtimerState, nr_views, 1),
607 DEFINE_PROP_UINT32("frame_stride", QCTQtimerState, frame_stride, 0x1000),
608 };
609
610 static void qct_qtimer_class_init(ObjectClass *klass, const void *data)
611 {
612 DeviceClass *dc = DEVICE_CLASS(klass);
613 ResettableClass *rc = RESETTABLE_CLASS(klass);
614
615 device_class_set_props(dc, qct_qtimer_properties);
616 dc->realize = qct_qtimer_realize;
617 dc->unrealize = qct_qtimer_unrealize;
618 dc->vmsd = &vmstate_qct_qtimer;
619 rc->phases.hold = qct_qtimer_reset_hold;
620 }
621
622 /* QTimer interface implementation, backing HEX_SREG_TIMERLO/TIMERHI */
623 static uint32_t qct_qtimer_get_timer_lo_impl(const QctQtimerInterface *obj)
624 {
625 QCTQtimerState *s = QCT_QTIMER((QctQtimerInterface *)obj);
626
627 return s->nr_frames > 0 ? extract64(hex_timer_now(&s->timer[0]), 0, 32)
628 : 0;
629 }
630
631 static uint32_t qct_qtimer_get_timer_hi_impl(const QctQtimerInterface *obj)
632 {
633 QCTQtimerState *s = QCT_QTIMER((QctQtimerInterface *)obj);
634
635 return s->nr_frames > 0 ? extract64(hex_timer_now(&s->timer[0]), 32, 32)
636 : 0;
637 }
638
639 static void qct_qtimer_interface_class_init(ObjectClass *klass,
640 const void *data)
641 {
642 QctQtimerInterfaceClass *k = QCT_QTIMER_INTERFACE_CLASS(klass);
643
644 k->get_timer_lo = qct_qtimer_get_timer_lo_impl;
645 k->get_timer_hi = qct_qtimer_get_timer_hi_impl;
646 }
647
648 static const TypeInfo qct_qtimer_types[] = {
649 {
650 .name = TYPE_QCT_QTIMER_INTERFACE,
651 .parent = TYPE_INTERFACE,
652 .class_size = sizeof(QctQtimerInterfaceClass),
653 .class_init = qct_qtimer_interface_class_init,
654 },
655 {
656 .name = TYPE_QCT_QTIMER,
657 .parent = TYPE_SYS_BUS_DEVICE,
658 .instance_size = sizeof(QCTQtimerState),
659 .class_init = qct_qtimer_class_init,
660 .interfaces = (InterfaceInfo[]) {
661 { TYPE_QCT_QTIMER_INTERFACE },
662 { }
663 },
664 },
665 };
666
667 DEFINE_TYPES(qct_qtimer_types)