Statistics
| Branch: | Revision:

root / hw / slavio_timer.c @ b854bc19

History | View | Annotate | Download (10.4 kB)

1
/*
2
 * QEMU Sparc SLAVIO timer controller emulation
3
 *
4
 * Copyright (c) 2003-2005 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "vl.h"
25

    
26
//#define DEBUG_TIMER
27

    
28
#ifdef DEBUG_TIMER
29
#define DPRINTF(fmt, args...) \
30
do { printf("TIMER: " fmt , ##args); } while (0)
31
#else
32
#define DPRINTF(fmt, args...)
33
#endif
34

    
35
/*
36
 * Registers of hardware timer in sun4m.
37
 *
38
 * This is the timer/counter part of chip STP2001 (Slave I/O), also
39
 * produced as NCR89C105. See
40
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
41
 *
42
 * The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0
43
 * are zero. Bit 31 is 1 when count has been reached.
44
 *
45
 * Per-CPU timers interrupt local CPU, system timer uses normal
46
 * interrupt routing.
47
 *
48
 */
49

    
50
#define MAX_CPUS 16
51

    
52
typedef struct SLAVIO_TIMERState {
53
    qemu_irq irq;
54
    ptimer_state *timer;
55
    uint32_t count, counthigh, reached;
56
    uint64_t limit;
57
    // processor only
58
    int running;
59
    struct SLAVIO_TIMERState *master;
60
    int slave_index;
61
    // system only
62
    struct SLAVIO_TIMERState *slave[MAX_CPUS];
63
    uint32_t slave_mode;
64
} SLAVIO_TIMERState;
65

    
66
#define TIMER_MAXADDR 0x1f
67
#define SYS_TIMER_SIZE 0x14
68
#define CPU_TIMER_SIZE 0x10
69

    
70
static int slavio_timer_is_user(SLAVIO_TIMERState *s)
71
{
72
    return s->master && (s->master->slave_mode & (1 << s->slave_index));
73
}
74

    
75
// Update count, set irq, update expire_time
76
// Convert from ptimer countdown units
77
static void slavio_timer_get_out(SLAVIO_TIMERState *s)
78
{
79
    uint64_t count;
80

    
81
    count = s->limit - (ptimer_get_count(s->timer) << 9);
82
    DPRINTF("get_out: limit %" PRIx64 " count %x%08x\n", s->limit, s->counthigh,
83
            s->count);
84
    s->count = count & 0xfffffe00;
85
    s->counthigh = count >> 32;
86
}
87

    
88
// timer callback
89
static void slavio_timer_irq(void *opaque)
90
{
91
    SLAVIO_TIMERState *s = opaque;
92

    
93
    slavio_timer_get_out(s);
94
    DPRINTF("callback: count %x%08x\n", s->counthigh, s->count);
95
    if (!slavio_timer_is_user(s)) {
96
        s->reached = 0x80000000;
97
        qemu_irq_raise(s->irq);
98
    }
99
}
100

    
101
static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
102
{
103
    SLAVIO_TIMERState *s = opaque;
104
    uint32_t saddr, ret;
105

    
106
    saddr = (addr & TIMER_MAXADDR) >> 2;
107
    switch (saddr) {
108
    case 0:
109
        // read limit (system counter mode) or read most signifying
110
        // part of counter (user mode)
111
        if (slavio_timer_is_user(s)) {
112
            // read user timer MSW
113
            slavio_timer_get_out(s);
114
            ret = s->counthigh;
115
        } else {
116
            // read limit
117
            // clear irq
118
            qemu_irq_lower(s->irq);
119
            s->reached = 0;
120
            ret = s->limit & 0x7fffffff;
121
        }
122
        break;
123
    case 1:
124
        // read counter and reached bit (system mode) or read lsbits
125
        // of counter (user mode)
126
        slavio_timer_get_out(s);
127
        if (slavio_timer_is_user(s)) // read user timer LSW
128
            ret = s->count & 0xffffffe00;
129
        else // read limit
130
            ret = (s->count & 0x7ffffe00) | s->reached;
131
        break;
132
    case 3:
133
        // only available in processor counter/timer
134
        // read start/stop status
135
        ret = s->running;
136
        break;
137
    case 4:
138
        // only available in system counter
139
        // read user/system mode
140
        ret = s->slave_mode;
141
        break;
142
    default:
143
        DPRINTF("invalid read address " TARGET_FMT_plx "\n", addr);
144
        ret = 0;
145
        break;
146
    }
147
    DPRINTF("read " TARGET_FMT_plx " = %08x\n", addr, ret);
148

    
149
    return ret;
150
}
151

    
152
static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
153
{
154
    SLAVIO_TIMERState *s = opaque;
155
    uint32_t saddr;
156
    int reload = 0;
157

    
158
    DPRINTF("write " TARGET_FMT_plx " %08x\n", addr, val);
159
    saddr = (addr & TIMER_MAXADDR) >> 2;
160
    switch (saddr) {
161
    case 0:
162
        if (slavio_timer_is_user(s)) {
163
            // set user counter MSW, reset counter
164
            qemu_irq_lower(s->irq);
165
            s->limit = 0x7ffffffffffffe00ULL;
166
            DPRINTF("processor %d user timer reset\n", s->slave_index);
167
            ptimer_set_limit(s->timer, s->limit >> 9, 1);
168
        } else {
169
            // set limit, reset counter
170
            qemu_irq_lower(s->irq);
171
            s->limit = val & 0x7ffffe00ULL;
172
            if (!s->limit)
173
                s->limit = 0x7ffffe00ULL;
174
            ptimer_set_limit(s->timer, s->limit >> 9, 1);
175
        }
176
        break;
177
    case 1:
178
        if (slavio_timer_is_user(s)) {
179
            // set user counter LSW, reset counter
180
            qemu_irq_lower(s->irq);
181
            s->limit = 0x7ffffffffffffe00ULL;
182
            DPRINTF("processor %d user timer reset\n", s->slave_index);
183
            ptimer_set_limit(s->timer, s->limit >> 9, 1);
184
        } else
185
            DPRINTF("not user timer\n");
186
        break;
187
    case 2:
188
        // set limit without resetting counter
189
        s->limit = val & 0x7ffffe00ULL;
190
        if (!s->limit)
191
            s->limit = 0x7ffffe00ULL;
192
        ptimer_set_limit(s->timer, s->limit >> 9, reload);
193
        break;
194
    case 3:
195
        if (slavio_timer_is_user(s)) {
196
            // start/stop user counter
197
            if ((val & 1) && !s->running) {
198
                DPRINTF("processor %d user timer started\n", s->slave_index);
199
                ptimer_run(s->timer, 0);
200
                s->running = 1;
201
            } else if (!(val & 1) && s->running) {
202
                DPRINTF("processor %d user timer stopped\n", s->slave_index);
203
                ptimer_stop(s->timer);
204
                s->running = 0;
205
            }
206
        }
207
        break;
208
    case 4:
209
        if (s->master == NULL) {
210
            unsigned int i;
211

    
212
            for (i = 0; i < MAX_CPUS; i++) {
213
                if (val & (1 << i)) {
214
                    qemu_irq_lower(s->slave[i]->irq);
215
                    s->slave[i]->limit = -1ULL;
216
                }
217
                if ((val & (1 << i)) != (s->slave_mode & (1 << i))) {
218
                    ptimer_stop(s->slave[i]->timer);
219
                    ptimer_set_limit(s->slave[i]->timer, s->slave[i]->limit >> 9, 1);
220
                    DPRINTF("processor %d timer changed\n", s->slave[i]->slave_index);
221
                    ptimer_run(s->slave[i]->timer, 0);
222
                }
223
            }
224
            s->slave_mode = val & ((1 << MAX_CPUS) - 1);
225
        } else
226
            DPRINTF("not system timer\n");
227
        break;
228
    default:
229
        DPRINTF("invalid write address " TARGET_FMT_plx "\n", addr);
230
        break;
231
    }
232
}
233

    
234
static CPUReadMemoryFunc *slavio_timer_mem_read[3] = {
235
    slavio_timer_mem_readl,
236
    slavio_timer_mem_readl,
237
    slavio_timer_mem_readl,
238
};
239

    
240
static CPUWriteMemoryFunc *slavio_timer_mem_write[3] = {
241
    slavio_timer_mem_writel,
242
    slavio_timer_mem_writel,
243
    slavio_timer_mem_writel,
244
};
245

    
246
static void slavio_timer_save(QEMUFile *f, void *opaque)
247
{
248
    SLAVIO_TIMERState *s = opaque;
249

    
250
    qemu_put_be64s(f, &s->limit);
251
    qemu_put_be32s(f, &s->count);
252
    qemu_put_be32s(f, &s->counthigh);
253
    qemu_put_be32(f, 0); // Was irq
254
    qemu_put_be32s(f, &s->reached);
255
    qemu_put_be32s(f, &s->running);
256
    qemu_put_be32s(f, 0); // Was mode
257
    qemu_put_ptimer(f, s->timer);
258
}
259

    
260
static int slavio_timer_load(QEMUFile *f, void *opaque, int version_id)
261
{
262
    SLAVIO_TIMERState *s = opaque;
263
    uint32_t tmp;
264

    
265
    if (version_id != 2)
266
        return -EINVAL;
267

    
268
    qemu_get_be64s(f, &s->limit);
269
    qemu_get_be32s(f, &s->count);
270
    qemu_get_be32s(f, &s->counthigh);
271
    qemu_get_be32s(f, &tmp); // Was irq
272
    qemu_get_be32s(f, &s->reached);
273
    qemu_get_be32s(f, &s->running);
274
    qemu_get_be32s(f, &tmp); // Was mode
275
    qemu_get_ptimer(f, s->timer);
276

    
277
    return 0;
278
}
279

    
280
static void slavio_timer_reset(void *opaque)
281
{
282
    SLAVIO_TIMERState *s = opaque;
283

    
284
    if (slavio_timer_is_user(s))
285
        s->limit = 0x7ffffffffffffe00ULL;
286
    else
287
        s->limit = 0x7ffffe00ULL;
288
    s->count = 0;
289
    s->reached = 0;
290
    ptimer_set_limit(s->timer, s->limit >> 9, 1);
291
    ptimer_run(s->timer, 0);
292
    s->running = 1;
293
    qemu_irq_lower(s->irq);
294
}
295

    
296
static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr,
297
                                            qemu_irq irq,
298
                                            SLAVIO_TIMERState *master,
299
                                            int slave_index)
300
{
301
    int slavio_timer_io_memory;
302
    SLAVIO_TIMERState *s;
303
    QEMUBH *bh;
304

    
305
    s = qemu_mallocz(sizeof(SLAVIO_TIMERState));
306
    if (!s)
307
        return s;
308
    s->irq = irq;
309
    s->master = master;
310
    s->slave_index = slave_index;
311
    bh = qemu_bh_new(slavio_timer_irq, s);
312
    s->timer = ptimer_init(bh);
313
    ptimer_set_period(s->timer, 500ULL);
314

    
315
    slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
316
                                                    slavio_timer_mem_write, s);
317
    if (master)
318
        cpu_register_physical_memory(addr, CPU_TIMER_SIZE, slavio_timer_io_memory);
319
    else
320
        cpu_register_physical_memory(addr, SYS_TIMER_SIZE, slavio_timer_io_memory);
321
    register_savevm("slavio_timer", addr, 2, slavio_timer_save, slavio_timer_load, s);
322
    qemu_register_reset(slavio_timer_reset, s);
323
    slavio_timer_reset(s);
324

    
325
    return s;
326
}
327

    
328
void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
329
                           qemu_irq *cpu_irqs)
330
{
331
    SLAVIO_TIMERState *master;
332
    unsigned int i;
333

    
334
    master = slavio_timer_init(base + 0x10000ULL, master_irq, NULL, 0);
335

    
336
    for (i = 0; i < MAX_CPUS; i++) {
337
        master->slave[i] = slavio_timer_init(base + (target_phys_addr_t)
338
                                             (i * TARGET_PAGE_SIZE),
339
                                             cpu_irqs[i], master, i);
340
    }
341
}