Statistics
| Branch: | Revision:

root / hw / omap_synctimer.c @ dcbd0b5c

History | View | Annotate | Download (2.6 kB)

1
/*
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
 */
20
#include "hw.h"
21
#include "qemu-timer.h"
22
#include "omap.h"
23
struct omap_synctimer_s {
24
    uint32_t val;
25
    uint16_t readh;
26
};
27

    
28
/* 32-kHz Sync Timer of the OMAP2 */
29
static 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

    
33
void omap_synctimer_reset(struct omap_synctimer_s *s)
34
{
35
    s->val = omap_synctimer_read(s);
36
}
37

    
38
static 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:        /* 32KSYNCNT_REV */
44
        return 0x21;
45

    
46
    case 0x10:        /* CR */
47
        return omap_synctimer_read(s) - s->val;
48
    }
49

    
50
    OMAP_BAD_REG(addr);
51
    return 0;
52
}
53

    
54
static 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

    
68
static CPUReadMemoryFunc * const omap_synctimer_readfn[] = {
69
    omap_badwidth_read32,
70
    omap_synctimer_readh,
71
    omap_synctimer_readw,
72
};
73

    
74
static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
75
                uint32_t value)
76
{
77
    OMAP_BAD_REG(addr);
78
}
79

    
80
static CPUWriteMemoryFunc * const omap_synctimer_writefn[] = {
81
    omap_badwidth_write32,
82
    omap_synctimer_write,
83
    omap_synctimer_write,
84
};
85

    
86
struct 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
}