blob: 72b997939bda984af0cd8efe108ad499a253cfb8 [file] [log] [blame]
cmchao011d87d2010-05-31 23:54:16 +08001/*
2 * TI OMAP2 32kHz sync timer emulation.
3 *
4 * Copyright (C) 2007-2008 Nokia Corporation
5 * Written by Andrzej Zaborowski <andrew@openedhand.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) any later version of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, see <http://www.gnu.org/licenses/>.
19 */
Peter Maydell282bc812016-01-26 18:17:18 +000020#include "qemu/osdep.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010021#include "qemu/timer.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010022#include "hw/arm/omap.h"
cmchao011d87d2010-05-31 23:54:16 +080023struct omap_synctimer_s {
Avi Kivityfcb40162011-11-24 14:32:34 +020024 MemoryRegion iomem;
cmchao011d87d2010-05-31 23:54:16 +080025 uint32_t val;
26 uint16_t readh;
27};
28
29/* 32-kHz Sync Timer of the OMAP2 */
30static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
Rutuja Shah73bcb242016-03-21 21:32:30 +053031 return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 0x8000,
32 NANOSECONDS_PER_SECOND);
cmchao011d87d2010-05-31 23:54:16 +080033}
34
35void omap_synctimer_reset(struct omap_synctimer_s *s)
36{
37 s->val = omap_synctimer_read(s);
38}
39
Avi Kivitya8170e52012-10-23 12:30:10 +020040static uint32_t omap_synctimer_readw(void *opaque, hwaddr addr)
cmchao011d87d2010-05-31 23:54:16 +080041{
42 struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
43
44 switch (addr) {
45 case 0x00: /* 32KSYNCNT_REV */
46 return 0x21;
47
48 case 0x10: /* CR */
49 return omap_synctimer_read(s) - s->val;
50 }
51
52 OMAP_BAD_REG(addr);
53 return 0;
54}
55
Avi Kivitya8170e52012-10-23 12:30:10 +020056static uint32_t omap_synctimer_readh(void *opaque, hwaddr addr)
cmchao011d87d2010-05-31 23:54:16 +080057{
58 struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
59 uint32_t ret;
60
61 if (addr & 2)
62 return s->readh;
63 else {
64 ret = omap_synctimer_readw(opaque, addr);
65 s->readh = ret >> 16;
66 return ret & 0xffff;
67 }
68}
69
Peter Maydell27f5bab2017-09-16 17:46:15 +010070static uint64_t omap_synctimer_readfn(void *opaque, hwaddr addr,
71 unsigned size)
72{
73 switch (size) {
74 case 1:
75 return omap_badwidth_read32(opaque, addr);
76 case 2:
77 return omap_synctimer_readh(opaque, addr);
78 case 4:
79 return omap_synctimer_readw(opaque, addr);
80 default:
81 g_assert_not_reached();
82 }
83}
84
85static void omap_synctimer_writefn(void *opaque, hwaddr addr,
86 uint64_t value, unsigned size)
cmchao011d87d2010-05-31 23:54:16 +080087{
88 OMAP_BAD_REG(addr);
89}
90
Avi Kivityfcb40162011-11-24 14:32:34 +020091static const MemoryRegionOps omap_synctimer_ops = {
Peter Maydell27f5bab2017-09-16 17:46:15 +010092 .read = omap_synctimer_readfn,
93 .write = omap_synctimer_writefn,
94 .valid.min_access_size = 1,
95 .valid.max_access_size = 4,
Avi Kivityfcb40162011-11-24 14:32:34 +020096 .endianness = DEVICE_NATIVE_ENDIAN,
cmchao011d87d2010-05-31 23:54:16 +080097};
98
99struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
100 struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
101{
Anthony Liguori7267c092011-08-20 22:09:37 -0500102 struct omap_synctimer_s *s = g_malloc0(sizeof(*s));
cmchao011d87d2010-05-31 23:54:16 +0800103
104 omap_synctimer_reset(s);
Paolo Bonzini2c9b15c2013-06-06 05:41:28 -0400105 memory_region_init_io(&s->iomem, NULL, &omap_synctimer_ops, s, "omap.synctimer",
Avi Kivityfcb40162011-11-24 14:32:34 +0200106 omap_l4_region_size(ta, 0));
Avi Kivityf44336c2011-11-28 15:40:49 +0200107 omap_l4_attach(ta, 0, &s->iomem);
cmchao011d87d2010-05-31 23:54:16 +0800108
109 return s;
110}