Statistics
| Branch: | Revision:

root / hw / etraxfs_timer.c @ 8c9d7f83

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 83fa1010 ths
#include "vl.h"
27 83fa1010 ths
28 83fa1010 ths
void etrax_ack_irq(CPUState *env, uint32_t mask);
29 83fa1010 ths
30 83fa1010 ths
#define R_TIME 0xb001e038
31 83fa1010 ths
#define RW_TMR0_DIV 0xb001e000
32 83fa1010 ths
#define R_TMR0_DATA 0xb001e004
33 83fa1010 ths
#define RW_TMR0_CTRL 0xb001e008
34 83fa1010 ths
#define RW_TMR1_DIV 0xb001e010
35 83fa1010 ths
#define R_TMR1_DATA 0xb001e014
36 83fa1010 ths
#define RW_TMR1_CTRL 0xb001e018
37 83fa1010 ths
38 83fa1010 ths
#define RW_INTR_MASK 0xb001e048
39 83fa1010 ths
#define RW_ACK_INTR 0xb001e04c
40 83fa1010 ths
#define R_INTR 0xb001e050
41 83fa1010 ths
#define R_MASKED_INTR 0xb001e054
42 83fa1010 ths
43 83fa1010 ths
44 83fa1010 ths
uint32_t rw_intr_mask;
45 83fa1010 ths
uint32_t rw_ack_intr;
46 83fa1010 ths
uint32_t r_intr;
47 83fa1010 ths
48 83fa1010 ths
struct fs_timer_t {
49 83fa1010 ths
        QEMUBH *bh;
50 83fa1010 ths
        unsigned int limit;
51 83fa1010 ths
        int scale;
52 83fa1010 ths
        ptimer_state *ptimer;
53 83fa1010 ths
        CPUState *env;
54 83fa1010 ths
        qemu_irq *irq;
55 83fa1010 ths
        uint32_t mask;
56 83fa1010 ths
};
57 83fa1010 ths
58 83fa1010 ths
static struct fs_timer_t timer0;
59 83fa1010 ths
60 83fa1010 ths
/* diff two timevals.  Return a single int in us. */
61 83fa1010 ths
int diff_timeval_us(struct timeval *a, struct timeval *b)
62 83fa1010 ths
{
63 83fa1010 ths
        int diff;
64 83fa1010 ths
65 83fa1010 ths
        /* assume these values are signed.  */
66 83fa1010 ths
        diff = (a->tv_sec - b->tv_sec) * 1000 * 1000;
67 83fa1010 ths
        diff += (a->tv_usec - b->tv_usec);
68 83fa1010 ths
        return diff;
69 83fa1010 ths
}
70 83fa1010 ths
71 83fa1010 ths
static uint32_t timer_readb (void *opaque, target_phys_addr_t addr)
72 83fa1010 ths
{
73 83fa1010 ths
        CPUState *env = opaque;
74 83fa1010 ths
        uint32_t r = 0;
75 83fa1010 ths
        printf ("%s %x pc=%x\n", __func__, addr, env->pc);
76 83fa1010 ths
        return r;
77 83fa1010 ths
}
78 83fa1010 ths
static uint32_t timer_readw (void *opaque, target_phys_addr_t addr)
79 83fa1010 ths
{
80 83fa1010 ths
        CPUState *env = opaque;
81 83fa1010 ths
        uint32_t r = 0;
82 83fa1010 ths
        printf ("%s %x pc=%x\n", __func__, addr, env->pc);
83 83fa1010 ths
        return r;
84 83fa1010 ths
}
85 83fa1010 ths
86 83fa1010 ths
static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
87 83fa1010 ths
{
88 83fa1010 ths
        CPUState *env = opaque;
89 83fa1010 ths
        uint32_t r = 0;
90 83fa1010 ths
91 83fa1010 ths
        switch (addr) {
92 83fa1010 ths
        case R_TMR0_DATA:
93 83fa1010 ths
                break;
94 83fa1010 ths
        case R_TMR1_DATA:
95 83fa1010 ths
                printf ("R_TMR1_DATA\n");
96 83fa1010 ths
                break;
97 83fa1010 ths
        case R_TIME:
98 83fa1010 ths
        {
99 83fa1010 ths
                static struct timeval last;
100 83fa1010 ths
                struct timeval now;
101 83fa1010 ths
                gettimeofday(&now, NULL);
102 83fa1010 ths
                if (!(last.tv_sec == 0 && last.tv_usec == 0)) {
103 83fa1010 ths
                        r = diff_timeval_us(&now, &last);
104 83fa1010 ths
                        r *= 1000; /* convert to ns.  */
105 83fa1010 ths
                        r++; /* make sure we increase for each call.  */
106 83fa1010 ths
                }
107 83fa1010 ths
                last = now;
108 83fa1010 ths
                break;
109 83fa1010 ths
        }
110 83fa1010 ths
111 83fa1010 ths
        case RW_INTR_MASK:
112 83fa1010 ths
                r = rw_intr_mask;
113 83fa1010 ths
                break;
114 83fa1010 ths
        case R_MASKED_INTR:
115 83fa1010 ths
                r = r_intr & rw_intr_mask;
116 83fa1010 ths
                break;
117 83fa1010 ths
        default:
118 83fa1010 ths
                printf ("%s %x p=%x\n", __func__, addr, env->pc);
119 83fa1010 ths
                break;
120 83fa1010 ths
        }
121 83fa1010 ths
        return r;
122 83fa1010 ths
}
123 83fa1010 ths
124 83fa1010 ths
static void
125 83fa1010 ths
timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
126 83fa1010 ths
{
127 83fa1010 ths
        CPUState *env = opaque;
128 83fa1010 ths
        printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
129 83fa1010 ths
}
130 83fa1010 ths
static void
131 83fa1010 ths
timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
132 83fa1010 ths
{
133 83fa1010 ths
        CPUState *env = opaque;
134 83fa1010 ths
        printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
135 83fa1010 ths
}
136 83fa1010 ths
137 83fa1010 ths
static void write_ctrl(struct fs_timer_t *t, uint32_t v)
138 83fa1010 ths
{
139 83fa1010 ths
        int op;
140 83fa1010 ths
        int freq;
141 83fa1010 ths
        int freq_hz;
142 83fa1010 ths
143 83fa1010 ths
        op = v & 3;
144 83fa1010 ths
        freq = v >> 2;
145 83fa1010 ths
        freq_hz = 32000000;
146 83fa1010 ths
147 83fa1010 ths
        switch (freq)
148 83fa1010 ths
        {
149 83fa1010 ths
        case 0:
150 83fa1010 ths
        case 1:
151 83fa1010 ths
                printf ("extern or disabled timer clock?\n");
152 83fa1010 ths
                break;
153 83fa1010 ths
        case 4: freq_hz =  29493000; break;
154 83fa1010 ths
        case 5: freq_hz =  32000000; break;
155 83fa1010 ths
        case 6: freq_hz =  32768000; break;
156 83fa1010 ths
        case 7: freq_hz = 100000000; break;
157 83fa1010 ths
        default:
158 83fa1010 ths
                abort();
159 83fa1010 ths
                break;
160 83fa1010 ths
        }
161 83fa1010 ths
162 83fa1010 ths
        printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit);
163 83fa1010 ths
        t->scale = 0;
164 83fa1010 ths
        if (t->limit > 2048)
165 83fa1010 ths
        {
166 83fa1010 ths
                t->scale = 2048;
167 83fa1010 ths
                ptimer_set_period(timer0.ptimer, freq_hz / t->scale);
168 83fa1010 ths
        }
169 83fa1010 ths
170 83fa1010 ths
        printf ("op=%d\n", op);
171 83fa1010 ths
        switch (op)
172 83fa1010 ths
        {
173 83fa1010 ths
                case 0:
174 83fa1010 ths
                        printf ("limit=%d %d\n", t->limit, t->limit/t->scale);
175 83fa1010 ths
                        ptimer_set_limit(t->ptimer, t->limit / t->scale, 1);
176 83fa1010 ths
                        break;
177 83fa1010 ths
                case 1:
178 83fa1010 ths
                        ptimer_stop(t->ptimer);
179 83fa1010 ths
                        break;
180 83fa1010 ths
                case 2:
181 83fa1010 ths
                        ptimer_run(t->ptimer, 0);
182 83fa1010 ths
                        break;
183 83fa1010 ths
                default:
184 83fa1010 ths
                        abort();
185 83fa1010 ths
                        break;
186 83fa1010 ths
        }
187 83fa1010 ths
}
188 83fa1010 ths
189 83fa1010 ths
static void timer_ack_irq(void)
190 83fa1010 ths
{
191 83fa1010 ths
        if (!(r_intr & timer0.mask & rw_intr_mask)) {
192 83fa1010 ths
                qemu_irq_lower(timer0.irq[0]);
193 83fa1010 ths
                etrax_ack_irq(timer0.env, 1 << 0x1b);
194 83fa1010 ths
        }
195 83fa1010 ths
}
196 83fa1010 ths
197 83fa1010 ths
static void
198 83fa1010 ths
timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
199 83fa1010 ths
{
200 83fa1010 ths
        CPUState *env = opaque;
201 83fa1010 ths
        printf ("%s %x %x pc=%x\n",
202 83fa1010 ths
                __func__, addr, value, env->pc);
203 83fa1010 ths
        switch (addr)
204 83fa1010 ths
        {
205 83fa1010 ths
                case RW_TMR0_DIV:
206 83fa1010 ths
                        printf ("RW_TMR0_DIV=%x\n", value);
207 83fa1010 ths
                        timer0.limit = value;
208 83fa1010 ths
                        break;
209 83fa1010 ths
                case RW_TMR0_CTRL:
210 83fa1010 ths
                        printf ("RW_TMR0_CTRL=%x\n", value);
211 83fa1010 ths
                        write_ctrl(&timer0, value);
212 83fa1010 ths
                        break;
213 83fa1010 ths
                case RW_TMR1_DIV:
214 83fa1010 ths
                        printf ("RW_TMR1_DIV=%x\n", value);
215 83fa1010 ths
                        break;
216 83fa1010 ths
                case RW_TMR1_CTRL:
217 83fa1010 ths
                        printf ("RW_TMR1_CTRL=%x\n", value);
218 83fa1010 ths
                        break;
219 83fa1010 ths
                case RW_INTR_MASK:
220 83fa1010 ths
                        printf ("RW_INTR_MASK=%x\n", value);
221 83fa1010 ths
                        rw_intr_mask = value;
222 83fa1010 ths
                        break;
223 83fa1010 ths
                case RW_ACK_INTR:
224 83fa1010 ths
                        r_intr &= ~value;
225 83fa1010 ths
                        timer_ack_irq();
226 83fa1010 ths
                        break;
227 83fa1010 ths
                default:
228 83fa1010 ths
                        printf ("%s %x %x pc=%x\n",
229 83fa1010 ths
                                __func__, addr, value, env->pc);
230 83fa1010 ths
                        break;
231 83fa1010 ths
        }
232 83fa1010 ths
}
233 83fa1010 ths
234 83fa1010 ths
static CPUReadMemoryFunc *timer_read[] = {
235 83fa1010 ths
    &timer_readb,
236 83fa1010 ths
    &timer_readw,
237 83fa1010 ths
    &timer_readl,
238 83fa1010 ths
};
239 83fa1010 ths
240 83fa1010 ths
static CPUWriteMemoryFunc *timer_write[] = {
241 83fa1010 ths
    &timer_writeb,
242 83fa1010 ths
    &timer_writew,
243 83fa1010 ths
    &timer_writel,
244 83fa1010 ths
};
245 83fa1010 ths
246 83fa1010 ths
static void timer_irq(void *opaque)
247 83fa1010 ths
{
248 83fa1010 ths
        struct fs_timer_t *t = opaque;
249 83fa1010 ths
250 83fa1010 ths
        r_intr |= t->mask;
251 83fa1010 ths
        if (t->mask & rw_intr_mask) {
252 83fa1010 ths
                qemu_irq_raise(t->irq[0]);
253 83fa1010 ths
        }
254 83fa1010 ths
}
255 83fa1010 ths
256 83fa1010 ths
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs)
257 83fa1010 ths
{
258 83fa1010 ths
        int timer_regs;
259 83fa1010 ths
260 83fa1010 ths
        timer0.bh = qemu_bh_new(timer_irq, &timer0);
261 83fa1010 ths
        timer0.ptimer = ptimer_init(timer0.bh);
262 83fa1010 ths
        timer0.irq = irqs + 0x1b;
263 83fa1010 ths
        timer0.mask = 1;
264 83fa1010 ths
        timer0.env = env;
265 83fa1010 ths
266 83fa1010 ths
        timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env);
267 83fa1010 ths
        cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs);
268 83fa1010 ths
}