|
|
1.1 root 1: /*
2: * TI OMAP2 32kHz sync timer emulation.
3: *
4: * Copyright (C) 2007-2008 Nokia Corporation
5: * Written by Andrzej Zaborowski <[email protected]>
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: */
20: #include "hw.h"
21: #include "qemu-timer.h"
22: #include "omap.h"
23: struct omap_synctimer_s {
1.1.1.4 ! root 24: MemoryRegion iomem;
1.1 root 25: uint32_t val;
26: uint16_t readh;
27: };
28:
29: /* 32-kHz Sync Timer of the OMAP2 */
30: static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
1.1.1.2 root 31: return muldiv64(qemu_get_clock_ns(vm_clock), 0x8000, get_ticks_per_sec());
1.1 root 32: }
33:
34: void omap_synctimer_reset(struct omap_synctimer_s *s)
35: {
36: s->val = omap_synctimer_read(s);
37: }
38:
39: static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr)
40: {
41: struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
42:
43: switch (addr) {
44: case 0x00: /* 32KSYNCNT_REV */
45: return 0x21;
46:
47: case 0x10: /* CR */
48: return omap_synctimer_read(s) - s->val;
49: }
50:
51: OMAP_BAD_REG(addr);
52: return 0;
53: }
54:
55: static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
56: {
57: struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
58: uint32_t ret;
59:
60: if (addr & 2)
61: return s->readh;
62: else {
63: ret = omap_synctimer_readw(opaque, addr);
64: s->readh = ret >> 16;
65: return ret & 0xffff;
66: }
67: }
68:
69: static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
70: uint32_t value)
71: {
72: OMAP_BAD_REG(addr);
73: }
74:
1.1.1.4 ! root 75: static const MemoryRegionOps omap_synctimer_ops = {
! 76: .old_mmio = {
! 77: .read = {
! 78: omap_badwidth_read32,
! 79: omap_synctimer_readh,
! 80: omap_synctimer_readw,
! 81: },
! 82: .write = {
! 83: omap_badwidth_write32,
! 84: omap_synctimer_write,
! 85: omap_synctimer_write,
! 86: },
! 87: },
! 88: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 89: };
90:
91: struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
92: struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
93: {
1.1.1.3 root 94: struct omap_synctimer_s *s = g_malloc0(sizeof(*s));
1.1 root 95:
96: omap_synctimer_reset(s);
1.1.1.4 ! root 97: memory_region_init_io(&s->iomem, &omap_synctimer_ops, s, "omap.synctimer",
! 98: omap_l4_region_size(ta, 0));
! 99: omap_l4_attach(ta, 0, &s->iomem);
1.1 root 100:
101: return s;
102: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.