Statistics
| Branch: | Revision:

root / hw / etraxfs_timer.c @ 3e3f6754

History | View | Annotate | Download (6 kB)

1 83fa1010 ths
/*
2 83fa1010 ths
 * QEMU ETRAX System Emulator
3 83fa1010 ths
 *
4 83fa1010 ths
 * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
5 83fa1010 ths
 *
6 83fa1010 ths
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 83fa1010 ths
 * of this software and associated documentation files (the "Software"), to deal
8 83fa1010 ths
 * in the Software without restriction, including without limitation the rights
9 83fa1010 ths
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 83fa1010 ths
 * copies of the Software, and to permit persons to whom the Software is
11 83fa1010 ths
 * furnished to do so, subject to the following conditions:
12 83fa1010 ths
 *
13 83fa1010 ths
 * The above copyright notice and this permission notice shall be included in
14 83fa1010 ths
 * all copies or substantial portions of the Software.
15 83fa1010 ths
 *
16 83fa1010 ths
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 83fa1010 ths
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 83fa1010 ths
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 83fa1010 ths
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 83fa1010 ths
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 83fa1010 ths
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 83fa1010 ths
 * THE SOFTWARE.
23 83fa1010 ths
 */
24 83fa1010 ths
#include <stdio.h>
25 83fa1010 ths
#include <sys/time.h>
26 87ecb68b pbrook
#include "hw.h"
27 87ecb68b pbrook
#include "qemu-timer.h"
28 83fa1010 ths
29 83fa1010 ths
void etrax_ack_irq(CPUState *env, uint32_t mask);
30 83fa1010 ths
31 83fa1010 ths
#define R_TIME 0xb001e038
32 83fa1010 ths
#define RW_TMR0_DIV 0xb001e000
33 83fa1010 ths
#define R_TMR0_DATA 0xb001e004
34 83fa1010 ths
#define RW_TMR0_CTRL 0xb001e008
35 83fa1010 ths
#define RW_TMR1_DIV 0xb001e010
36 83fa1010 ths
#define R_TMR1_DATA 0xb001e014
37 83fa1010 ths
#define RW_TMR1_CTRL 0xb001e018
38 83fa1010 ths
39 83fa1010 ths
#define RW_INTR_MASK 0xb001e048
40 83fa1010 ths
#define RW_ACK_INTR 0xb001e04c
41 83fa1010 ths
#define R_INTR 0xb001e050
42 83fa1010 ths
#define R_MASKED_INTR 0xb001e054
43 83fa1010 ths
44 83fa1010 ths
45 83fa1010 ths
uint32_t rw_intr_mask;
46 83fa1010 ths
uint32_t rw_ack_intr;
47 83fa1010 ths
uint32_t r_intr;
48 83fa1010 ths
49 83fa1010 ths
struct fs_timer_t {
50 83fa1010 ths
        QEMUBH *bh;
51 83fa1010 ths
        unsigned int limit;
52 83fa1010 ths
        int scale;
53 83fa1010 ths
        ptimer_state *ptimer;
54 83fa1010 ths
        CPUState *env;
55 83fa1010 ths
        qemu_irq *irq;
56 83fa1010 ths
        uint32_t mask;
57 83fa1010 ths
};
58 83fa1010 ths
59 83fa1010 ths
static struct fs_timer_t timer0;
60 83fa1010 ths
61 83fa1010 ths
/* diff two timevals.  Return a single int in us. */
62 83fa1010 ths
int diff_timeval_us(struct timeval *a, struct timeval *b)
63 83fa1010 ths
{
64 83fa1010 ths
        int diff;
65 83fa1010 ths
66 83fa1010 ths
        /* assume these values are signed.  */
67 83fa1010 ths
        diff = (a->tv_sec - b->tv_sec) * 1000 * 1000;
68 83fa1010 ths
        diff += (a->tv_usec - b->tv_usec);
69 83fa1010 ths
        return diff;
70 83fa1010 ths
}
71 83fa1010 ths
72 83fa1010 ths
static uint32_t timer_readb (void *opaque, target_phys_addr_t addr)
73 83fa1010 ths
{
74 83fa1010 ths
        CPUState *env = opaque;
75 83fa1010 ths
        uint32_t r = 0;
76 83fa1010 ths
        printf ("%s %x pc=%x\n", __func__, addr, env->pc);
77 83fa1010 ths
        return r;
78 83fa1010 ths
}
79 83fa1010 ths
static uint32_t timer_readw (void *opaque, target_phys_addr_t addr)
80 83fa1010 ths
{
81 83fa1010 ths
        CPUState *env = opaque;
82 83fa1010 ths
        uint32_t r = 0;
83 83fa1010 ths
        printf ("%s %x pc=%x\n", __func__, addr, env->pc);
84 83fa1010 ths
        return r;
85 83fa1010 ths
}
86 83fa1010 ths
87 83fa1010 ths
static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
88 83fa1010 ths
{
89 83fa1010 ths
        CPUState *env = opaque;
90 83fa1010 ths
        uint32_t r = 0;
91 83fa1010 ths
92 83fa1010 ths
        switch (addr) {
93 83fa1010 ths
        case R_TMR0_DATA:
94 83fa1010 ths
                break;
95 83fa1010 ths
        case R_TMR1_DATA:
96 83fa1010 ths
                printf ("R_TMR1_DATA\n");
97 83fa1010 ths
                break;
98 83fa1010 ths
        case R_TIME:
99 83fa1010 ths
        {
100 83fa1010 ths
                static struct timeval last;
101 83fa1010 ths
                struct timeval now;
102 83fa1010 ths
                gettimeofday(&now, NULL);
103 83fa1010 ths
                if (!(last.tv_sec == 0 && last.tv_usec == 0)) {
104 83fa1010 ths
                        r = diff_timeval_us(&now, &last);
105 83fa1010 ths
                        r *= 1000; /* convert to ns.  */
106 83fa1010 ths
                        r++; /* make sure we increase for each call.  */
107 83fa1010 ths
                }
108 83fa1010 ths
                last = now;
109 83fa1010 ths
                break;
110 83fa1010 ths
        }
111 83fa1010 ths
112 83fa1010 ths
        case RW_INTR_MASK:
113 83fa1010 ths
                r = rw_intr_mask;
114 83fa1010 ths
                break;
115 83fa1010 ths
        case R_MASKED_INTR:
116 83fa1010 ths
                r = r_intr & rw_intr_mask;
117 83fa1010 ths
                break;
118 83fa1010 ths
        default:
119 83fa1010 ths
                printf ("%s %x p=%x\n", __func__, addr, env->pc);
120 83fa1010 ths
                break;
121 83fa1010 ths
        }
122 83fa1010 ths
        return r;
123 83fa1010 ths
}
124 83fa1010 ths
125 83fa1010 ths
static void
126 83fa1010 ths
timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
127 83fa1010 ths
{
128 83fa1010 ths
        CPUState *env = opaque;
129 83fa1010 ths
        printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
130 83fa1010 ths
}
131 83fa1010 ths
static void
132 83fa1010 ths
timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
133 83fa1010 ths
{
134 83fa1010 ths
        CPUState *env = opaque;
135 83fa1010 ths
        printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
136 83fa1010 ths
}
137 83fa1010 ths
138 83fa1010 ths
static void write_ctrl(struct fs_timer_t *t, uint32_t v)
139 83fa1010 ths
{
140 83fa1010 ths
        int op;
141 83fa1010 ths
        int freq;
142 83fa1010 ths
        int freq_hz;
143 83fa1010 ths
144 83fa1010 ths
        op = v & 3;
145 83fa1010 ths
        freq = v >> 2;
146 83fa1010 ths
        freq_hz = 32000000;
147 83fa1010 ths
148 83fa1010 ths
        switch (freq)
149 83fa1010 ths
        {
150 83fa1010 ths
        case 0:
151 83fa1010 ths
        case 1:
152 83fa1010 ths
                printf ("extern or disabled timer clock?\n");
153 83fa1010 ths
                break;
154 83fa1010 ths
        case 4: freq_hz =  29493000; break;
155 83fa1010 ths
        case 5: freq_hz =  32000000; break;
156 83fa1010 ths
        case 6: freq_hz =  32768000; break;
157 83fa1010 ths
        case 7: freq_hz = 100000000; break;
158 83fa1010 ths
        default:
159 83fa1010 ths
                abort();
160 83fa1010 ths
                break;
161 83fa1010 ths
        }
162 83fa1010 ths
163 83fa1010 ths
        printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit);
164 83fa1010 ths
        t->scale = 0;
165 83fa1010 ths
        if (t->limit > 2048)
166 83fa1010 ths
        {
167 83fa1010 ths
                t->scale = 2048;
168 83fa1010 ths
                ptimer_set_period(timer0.ptimer, freq_hz / t->scale);
169 83fa1010 ths
        }
170 83fa1010 ths
171 83fa1010 ths
        printf ("op=%d\n", op);
172 83fa1010 ths
        switch (op)
173 83fa1010 ths
        {
174 83fa1010 ths
                case 0:
175 83fa1010 ths
                        printf ("limit=%d %d\n", t->limit, t->limit/t->scale);
176 83fa1010 ths
                        ptimer_set_limit(t->ptimer, t->limit / t->scale, 1);
177 83fa1010 ths
                        break;
178 83fa1010 ths
                case 1:
179 83fa1010 ths
                        ptimer_stop(t->ptimer);
180 83fa1010 ths
                        break;
181 83fa1010 ths
                case 2:
182 83fa1010 ths
                        ptimer_run(t->ptimer, 0);
183 83fa1010 ths
                        break;
184 83fa1010 ths
                default:
185 83fa1010 ths
                        abort();
186 83fa1010 ths
                        break;
187 83fa1010 ths
        }
188 83fa1010 ths
}
189 83fa1010 ths
190 83fa1010 ths
static void timer_ack_irq(void)
191 83fa1010 ths
{
192 83fa1010 ths
        if (!(r_intr & timer0.mask & rw_intr_mask)) {
193 83fa1010 ths
                qemu_irq_lower(timer0.irq[0]);
194 83fa1010 ths
                etrax_ack_irq(timer0.env, 1 << 0x1b);
195 83fa1010 ths
        }
196 83fa1010 ths
}
197 83fa1010 ths
198 83fa1010 ths
static void
199 83fa1010 ths
timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
200 83fa1010 ths
{
201 83fa1010 ths
        CPUState *env = opaque;
202 83fa1010 ths
        printf ("%s %x %x pc=%x\n",
203 83fa1010 ths
                __func__, addr, value, env->pc);
204 83fa1010 ths
        switch (addr)
205 83fa1010 ths
        {
206 83fa1010 ths
                case RW_TMR0_DIV:
207 83fa1010 ths
                        printf ("RW_TMR0_DIV=%x\n", value);
208 83fa1010 ths
                        timer0.limit = value;
209 83fa1010 ths
                        break;
210 83fa1010 ths
                case RW_TMR0_CTRL:
211 83fa1010 ths
                        printf ("RW_TMR0_CTRL=%x\n", value);
212 83fa1010 ths
                        write_ctrl(&timer0, value);
213 83fa1010 ths
                        break;
214 83fa1010 ths
                case RW_TMR1_DIV:
215 83fa1010 ths
                        printf ("RW_TMR1_DIV=%x\n", value);
216 83fa1010 ths
                        break;
217 83fa1010 ths
                case RW_TMR1_CTRL:
218 83fa1010 ths
                        printf ("RW_TMR1_CTRL=%x\n", value);
219 83fa1010 ths
                        break;
220 83fa1010 ths
                case RW_INTR_MASK:
221 83fa1010 ths
                        printf ("RW_INTR_MASK=%x\n", value);
222 83fa1010 ths
                        rw_intr_mask = value;
223 83fa1010 ths
                        break;
224 83fa1010 ths
                case RW_ACK_INTR:
225 83fa1010 ths
                        r_intr &= ~value;
226 83fa1010 ths
                        timer_ack_irq();
227 83fa1010 ths
                        break;
228 83fa1010 ths
                default:
229 83fa1010 ths
                        printf ("%s %x %x pc=%x\n",
230 83fa1010 ths
                                __func__, addr, value, env->pc);
231 83fa1010 ths
                        break;
232 83fa1010 ths
        }
233 83fa1010 ths
}
234 83fa1010 ths
235 83fa1010 ths
static CPUReadMemoryFunc *timer_read[] = {
236 83fa1010 ths
    &timer_readb,
237 83fa1010 ths
    &timer_readw,
238 83fa1010 ths
    &timer_readl,
239 83fa1010 ths
};
240 83fa1010 ths
241 83fa1010 ths
static CPUWriteMemoryFunc *timer_write[] = {
242 83fa1010 ths
    &timer_writeb,
243 83fa1010 ths
    &timer_writew,
244 83fa1010 ths
    &timer_writel,
245 83fa1010 ths
};
246 83fa1010 ths
247 83fa1010 ths
static void timer_irq(void *opaque)
248 83fa1010 ths
{
249 83fa1010 ths
        struct fs_timer_t *t = opaque;
250 83fa1010 ths
251 83fa1010 ths
        r_intr |= t->mask;
252 83fa1010 ths
        if (t->mask & rw_intr_mask) {
253 83fa1010 ths
                qemu_irq_raise(t->irq[0]);
254 83fa1010 ths
        }
255 83fa1010 ths
}
256 83fa1010 ths
257 83fa1010 ths
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs)
258 83fa1010 ths
{
259 83fa1010 ths
        int timer_regs;
260 83fa1010 ths
261 83fa1010 ths
        timer0.bh = qemu_bh_new(timer_irq, &timer0);
262 83fa1010 ths
        timer0.ptimer = ptimer_init(timer0.bh);
263 83fa1010 ths
        timer0.irq = irqs + 0x1b;
264 83fa1010 ths
        timer0.mask = 1;
265 83fa1010 ths
        timer0.env = env;
266 83fa1010 ths
267 83fa1010 ths
        timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env);
268 83fa1010 ths
        cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs);
269 83fa1010 ths
}