1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "hw.h"
21#include "qemu-timer.h"
22#include "omap.h"
23struct omap_synctimer_s {
24 uint32_t val;
25 uint16_t readh;
26};
27
28
29static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
30 return muldiv64(qemu_get_clock_ns(vm_clock), 0x8000, get_ticks_per_sec());
31}
32
33void omap_synctimer_reset(struct omap_synctimer_s *s)
34{
35 s->val = omap_synctimer_read(s);
36}
37
38static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr)
39{
40 struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
41
42 switch (addr) {
43 case 0x00:
44 return 0x21;
45
46 case 0x10:
47 return omap_synctimer_read(s) - s->val;
48 }
49
50 OMAP_BAD_REG(addr);
51 return 0;
52}
53
54static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
55{
56 struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
57 uint32_t ret;
58
59 if (addr & 2)
60 return s->readh;
61 else {
62 ret = omap_synctimer_readw(opaque, addr);
63 s->readh = ret >> 16;
64 return ret & 0xffff;
65 }
66}
67
68static CPUReadMemoryFunc * const omap_synctimer_readfn[] = {
69 omap_badwidth_read32,
70 omap_synctimer_readh,
71 omap_synctimer_readw,
72};
73
74static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
75 uint32_t value)
76{
77 OMAP_BAD_REG(addr);
78}
79
80static CPUWriteMemoryFunc * const omap_synctimer_writefn[] = {
81 omap_badwidth_write32,
82 omap_synctimer_write,
83 omap_synctimer_write,
84};
85
86struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
87 struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
88{
89 struct omap_synctimer_s *s = qemu_mallocz(sizeof(*s));
90
91 omap_synctimer_reset(s);
92 omap_l4_attach(ta, 0, l4_register_io_memory(
93 omap_synctimer_readfn, omap_synctimer_writefn, s));
94
95 return s;
96}
97