Statistics
| Branch: | Revision:

root / hw / etraxfs_timer.c @ a350e694

History | View | Annotate | Download (5.9 kB)

1 83fa1010 ths
/*
2 e62b5b13 edgar_igl
 * QEMU ETRAX Timers
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 bbaf29c7 edgar_igl
#define D(x)
30 bbaf29c7 edgar_igl
31 ca87d03b edgar_igl
#define RW_TMR0_DIV   0x00
32 ca87d03b edgar_igl
#define R_TMR0_DATA   0x04
33 ca87d03b edgar_igl
#define RW_TMR0_CTRL  0x08
34 ca87d03b edgar_igl
#define RW_TMR1_DIV   0x10
35 ca87d03b edgar_igl
#define R_TMR1_DATA   0x14
36 ca87d03b edgar_igl
#define RW_TMR1_CTRL  0x18
37 ca87d03b edgar_igl
#define R_TIME        0x38
38 ca87d03b edgar_igl
#define RW_WD_CTRL    0x40
39 ca87d03b edgar_igl
#define RW_INTR_MASK  0x48
40 ca87d03b edgar_igl
#define RW_ACK_INTR   0x4c
41 ca87d03b edgar_igl
#define R_INTR        0x50
42 ca87d03b edgar_igl
#define R_MASKED_INTR 0x54
43 83fa1010 ths
44 83fa1010 ths
struct fs_timer_t {
45 ca87d03b edgar_igl
        CPUState *env;
46 ca87d03b edgar_igl
        qemu_irq *irq;
47 ca87d03b edgar_igl
        target_phys_addr_t base;
48 ca87d03b edgar_igl
49 83fa1010 ths
        QEMUBH *bh;
50 ca87d03b edgar_igl
        ptimer_state *ptimer;
51 bbaf29c7 edgar_igl
        struct timeval last;
52 e62b5b13 edgar_igl
53 60237223 edgar_igl
        /* Control registers.  */
54 60237223 edgar_igl
        uint32_t rw_tmr0_div;
55 60237223 edgar_igl
        uint32_t r_tmr0_data;
56 60237223 edgar_igl
        uint32_t rw_tmr0_ctrl;
57 60237223 edgar_igl
58 60237223 edgar_igl
        uint32_t rw_tmr1_div;
59 60237223 edgar_igl
        uint32_t r_tmr1_data;
60 60237223 edgar_igl
        uint32_t rw_tmr1_ctrl;
61 60237223 edgar_igl
62 e62b5b13 edgar_igl
        uint32_t rw_intr_mask;
63 e62b5b13 edgar_igl
        uint32_t rw_ack_intr;
64 e62b5b13 edgar_igl
        uint32_t r_intr;
65 60237223 edgar_igl
        uint32_t r_masked_intr;
66 83fa1010 ths
};
67 83fa1010 ths
68 ca87d03b edgar_igl
static uint32_t timer_rinvalid (void *opaque, target_phys_addr_t addr)
69 83fa1010 ths
{
70 ca87d03b edgar_igl
        struct fs_timer_t *t = opaque;
71 ca87d03b edgar_igl
        CPUState *env = t->env;
72 ca87d03b edgar_igl
        cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", 
73 ca87d03b edgar_igl
                  addr, env->pc);
74 ca87d03b edgar_igl
        return 0;
75 83fa1010 ths
}
76 83fa1010 ths
77 83fa1010 ths
static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
78 83fa1010 ths
{
79 ca87d03b edgar_igl
        struct fs_timer_t *t = opaque;
80 ca87d03b edgar_igl
        D(CPUState *env = t->env);
81 83fa1010 ths
        uint32_t r = 0;
82 83fa1010 ths
83 ca87d03b edgar_igl
        /* Make addr relative to this instances base.  */
84 ca87d03b edgar_igl
        addr -= t->base;
85 83fa1010 ths
        switch (addr) {
86 83fa1010 ths
        case R_TMR0_DATA:
87 83fa1010 ths
                break;
88 83fa1010 ths
        case R_TMR1_DATA:
89 bbaf29c7 edgar_igl
                D(printf ("R_TMR1_DATA\n"));
90 83fa1010 ths
                break;
91 83fa1010 ths
        case R_TIME:
92 60237223 edgar_igl
                r = qemu_get_clock(vm_clock) * 10;
93 83fa1010 ths
                break;
94 83fa1010 ths
        case RW_INTR_MASK:
95 ca87d03b edgar_igl
                r = t->rw_intr_mask;
96 83fa1010 ths
                break;
97 83fa1010 ths
        case R_MASKED_INTR:
98 ca87d03b edgar_igl
                r = t->r_intr & t->rw_intr_mask;
99 83fa1010 ths
                break;
100 83fa1010 ths
        default:
101 e62b5b13 edgar_igl
                D(printf ("%s %x p=%x\n", __func__, addr, env->pc));
102 83fa1010 ths
                break;
103 83fa1010 ths
        }
104 83fa1010 ths
        return r;
105 83fa1010 ths
}
106 83fa1010 ths
107 83fa1010 ths
static void
108 ca87d03b edgar_igl
timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value)
109 83fa1010 ths
{
110 ca87d03b edgar_igl
        struct fs_timer_t *t = opaque;
111 ca87d03b edgar_igl
        CPUState *env = t->env;
112 ca87d03b edgar_igl
        cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", 
113 ca87d03b edgar_igl
                  addr, env->pc);
114 83fa1010 ths
}
115 83fa1010 ths
116 f0b86b14 edgar_igl
#define TIMER_SLOWDOWN 1
117 60237223 edgar_igl
static void update_ctrl(struct fs_timer_t *t)
118 83fa1010 ths
{
119 60237223 edgar_igl
        unsigned int op;
120 60237223 edgar_igl
        unsigned int freq;
121 60237223 edgar_igl
        unsigned int freq_hz;
122 60237223 edgar_igl
        unsigned int div;
123 83fa1010 ths
124 60237223 edgar_igl
        op = t->rw_tmr0_ctrl & 3;
125 60237223 edgar_igl
        freq = t->rw_tmr0_ctrl >> 2;
126 83fa1010 ths
        freq_hz = 32000000;
127 83fa1010 ths
128 83fa1010 ths
        switch (freq)
129 83fa1010 ths
        {
130 83fa1010 ths
        case 0:
131 83fa1010 ths
        case 1:
132 e62b5b13 edgar_igl
                D(printf ("extern or disabled timer clock?\n"));
133 83fa1010 ths
                break;
134 83fa1010 ths
        case 4: freq_hz =  29493000; break;
135 83fa1010 ths
        case 5: freq_hz =  32000000; break;
136 83fa1010 ths
        case 6: freq_hz =  32768000; break;
137 83fa1010 ths
        case 7: freq_hz = 100000000; break;
138 83fa1010 ths
        default:
139 83fa1010 ths
                abort();
140 83fa1010 ths
                break;
141 83fa1010 ths
        }
142 83fa1010 ths
143 60237223 edgar_igl
        D(printf ("freq_hz=%d div=%d\n", freq_hz, t->rw_tmr0_div));
144 60237223 edgar_igl
        div = t->rw_tmr0_div * TIMER_SLOWDOWN;
145 60237223 edgar_igl
        div >>= 15;
146 60237223 edgar_igl
        freq_hz >>= 15;
147 60237223 edgar_igl
        ptimer_set_freq(t->ptimer, freq_hz);
148 60237223 edgar_igl
        ptimer_set_limit(t->ptimer, div, 0);
149 83fa1010 ths
150 83fa1010 ths
        switch (op)
151 83fa1010 ths
        {
152 83fa1010 ths
                case 0:
153 60237223 edgar_igl
                        /* Load.  */
154 60237223 edgar_igl
                        ptimer_set_limit(t->ptimer, div, 1);
155 60237223 edgar_igl
                        ptimer_run(t->ptimer, 1);
156 83fa1010 ths
                        break;
157 83fa1010 ths
                case 1:
158 60237223 edgar_igl
                        /* Hold.  */
159 83fa1010 ths
                        ptimer_stop(t->ptimer);
160 83fa1010 ths
                        break;
161 83fa1010 ths
                case 2:
162 60237223 edgar_igl
                        /* Run.  */
163 83fa1010 ths
                        ptimer_run(t->ptimer, 0);
164 83fa1010 ths
                        break;
165 83fa1010 ths
                default:
166 83fa1010 ths
                        abort();
167 83fa1010 ths
                        break;
168 83fa1010 ths
        }
169 83fa1010 ths
}
170 83fa1010 ths
171 60237223 edgar_igl
static void timer_update_irq(struct fs_timer_t *t)
172 83fa1010 ths
{
173 60237223 edgar_igl
        t->r_intr &= ~(t->rw_ack_intr);
174 60237223 edgar_igl
        t->r_masked_intr = t->r_intr & t->rw_intr_mask;
175 60237223 edgar_igl
176 60237223 edgar_igl
        D(printf("%s: masked_intr=%x\n", __func__, t->r_masked_intr));
177 60237223 edgar_igl
        if (t->r_masked_intr & 1)
178 60237223 edgar_igl
                qemu_irq_raise(t->irq[0]);
179 60237223 edgar_igl
        else
180 bbaf29c7 edgar_igl
                qemu_irq_lower(t->irq[0]);
181 83fa1010 ths
}
182 83fa1010 ths
183 63c1d925 edgar_igl
static void timer_hit(void *opaque)
184 60237223 edgar_igl
{
185 63c1d925 edgar_igl
        struct fs_timer_t *t = opaque;
186 60237223 edgar_igl
        t->r_intr |= 1;
187 60237223 edgar_igl
        timer_update_irq(t);
188 60237223 edgar_igl
}
189 60237223 edgar_igl
190 83fa1010 ths
static void
191 83fa1010 ths
timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
192 83fa1010 ths
{
193 ca87d03b edgar_igl
        struct fs_timer_t *t = opaque;
194 ca87d03b edgar_igl
        CPUState *env = t->env;
195 bbaf29c7 edgar_igl
196 ca87d03b edgar_igl
        /* Make addr relative to this instances base.  */
197 ca87d03b edgar_igl
        addr -= t->base;
198 83fa1010 ths
        switch (addr)
199 83fa1010 ths
        {
200 83fa1010 ths
                case RW_TMR0_DIV:
201 60237223 edgar_igl
                        t->rw_tmr0_div = value;
202 83fa1010 ths
                        break;
203 83fa1010 ths
                case RW_TMR0_CTRL:
204 bbaf29c7 edgar_igl
                        D(printf ("RW_TMR0_CTRL=%x\n", value));
205 60237223 edgar_igl
                        t->rw_tmr0_ctrl = value;
206 60237223 edgar_igl
                        update_ctrl(t);
207 83fa1010 ths
                        break;
208 83fa1010 ths
                case RW_TMR1_DIV:
209 60237223 edgar_igl
                        t->rw_tmr1_div = value;
210 83fa1010 ths
                        break;
211 83fa1010 ths
                case RW_TMR1_CTRL:
212 bbaf29c7 edgar_igl
                        D(printf ("RW_TMR1_CTRL=%x\n", value));
213 83fa1010 ths
                        break;
214 83fa1010 ths
                case RW_INTR_MASK:
215 bbaf29c7 edgar_igl
                        D(printf ("RW_INTR_MASK=%x\n", value));
216 ca87d03b edgar_igl
                        t->rw_intr_mask = value;
217 60237223 edgar_igl
                        timer_update_irq(t);
218 e62b5b13 edgar_igl
                        break;
219 e62b5b13 edgar_igl
                case RW_WD_CTRL:
220 e62b5b13 edgar_igl
                        D(printf ("RW_WD_CTRL=%x\n", value));
221 83fa1010 ths
                        break;
222 83fa1010 ths
                case RW_ACK_INTR:
223 60237223 edgar_igl
                        t->rw_ack_intr = value;
224 60237223 edgar_igl
                        timer_update_irq(t);
225 60237223 edgar_igl
                        t->rw_ack_intr = 0;
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 ca87d03b edgar_igl
    &timer_rinvalid,
236 ca87d03b edgar_igl
    &timer_rinvalid,
237 83fa1010 ths
    &timer_readl,
238 83fa1010 ths
};
239 83fa1010 ths
240 83fa1010 ths
static CPUWriteMemoryFunc *timer_write[] = {
241 ca87d03b edgar_igl
    &timer_winvalid,
242 ca87d03b edgar_igl
    &timer_winvalid,
243 83fa1010 ths
    &timer_writel,
244 83fa1010 ths
};
245 83fa1010 ths
246 ca87d03b edgar_igl
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, 
247 ca87d03b edgar_igl
                        target_phys_addr_t base)
248 83fa1010 ths
{
249 ca87d03b edgar_igl
        static struct fs_timer_t *t;
250 83fa1010 ths
        int timer_regs;
251 83fa1010 ths
252 ca87d03b edgar_igl
        t = qemu_mallocz(sizeof *t);
253 ca87d03b edgar_igl
        if (!t)
254 ca87d03b edgar_igl
                return;
255 bbaf29c7 edgar_igl
256 60237223 edgar_igl
        t->bh = qemu_bh_new(timer_hit, t);
257 ca87d03b edgar_igl
        t->ptimer = ptimer_init(t->bh);
258 60237223 edgar_igl
        t->irq = irqs;
259 ca87d03b edgar_igl
        t->env = env;
260 ca87d03b edgar_igl
        t->base = base;
261 83fa1010 ths
262 ca87d03b edgar_igl
        timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t);
263 ca87d03b edgar_igl
        cpu_register_physical_memory (base, 0x5c, timer_regs);
264 83fa1010 ths
}