Statistics
| Branch: | Revision:

root / hw / stellaris.c @ 90d37239

History | View | Annotate | Download (37.6 kB)

1 9ee6e8bb pbrook
/*
2 1654b2d6 aurel32
 * Luminary Micro Stellaris peripherals
3 9ee6e8bb pbrook
 *
4 9ee6e8bb pbrook
 * Copyright (c) 2006 CodeSourcery.
5 9ee6e8bb pbrook
 * Written by Paul Brook
6 9ee6e8bb pbrook
 *
7 9ee6e8bb pbrook
 * This code is licenced under the GPL.
8 9ee6e8bb pbrook
 */
9 9ee6e8bb pbrook
10 a7d518a6 Paul Brook
#include "sysbus.h"
11 87ecb68b pbrook
#include "arm-misc.h"
12 87ecb68b pbrook
#include "primecell.h"
13 87ecb68b pbrook
#include "devices.h"
14 87ecb68b pbrook
#include "qemu-timer.h"
15 87ecb68b pbrook
#include "i2c.h"
16 eea589cc pbrook
#include "net.h"
17 775616c3 pbrook
#include "sd.h"
18 87ecb68b pbrook
#include "sysemu.h"
19 87ecb68b pbrook
#include "boards.h"
20 9ee6e8bb pbrook
21 cf0dbb21 pbrook
#define GPIO_A 0
22 cf0dbb21 pbrook
#define GPIO_B 1
23 cf0dbb21 pbrook
#define GPIO_C 2
24 cf0dbb21 pbrook
#define GPIO_D 3
25 cf0dbb21 pbrook
#define GPIO_E 4
26 cf0dbb21 pbrook
#define GPIO_F 5
27 cf0dbb21 pbrook
#define GPIO_G 6
28 cf0dbb21 pbrook
29 cf0dbb21 pbrook
#define BP_OLED_I2C  0x01
30 cf0dbb21 pbrook
#define BP_OLED_SSI  0x02
31 cf0dbb21 pbrook
#define BP_GAMEPAD   0x04
32 cf0dbb21 pbrook
33 9ee6e8bb pbrook
typedef const struct {
34 9ee6e8bb pbrook
    const char *name;
35 9ee6e8bb pbrook
    uint32_t did0;
36 9ee6e8bb pbrook
    uint32_t did1;
37 9ee6e8bb pbrook
    uint32_t dc0;
38 9ee6e8bb pbrook
    uint32_t dc1;
39 9ee6e8bb pbrook
    uint32_t dc2;
40 9ee6e8bb pbrook
    uint32_t dc3;
41 9ee6e8bb pbrook
    uint32_t dc4;
42 cf0dbb21 pbrook
    uint32_t peripherals;
43 9ee6e8bb pbrook
} stellaris_board_info;
44 9ee6e8bb pbrook
45 9ee6e8bb pbrook
/* General purpose timer module.  */
46 9ee6e8bb pbrook
47 9ee6e8bb pbrook
typedef struct gptm_state {
48 9ee6e8bb pbrook
    uint32_t config;
49 9ee6e8bb pbrook
    uint32_t mode[2];
50 9ee6e8bb pbrook
    uint32_t control;
51 9ee6e8bb pbrook
    uint32_t state;
52 9ee6e8bb pbrook
    uint32_t mask;
53 9ee6e8bb pbrook
    uint32_t load[2];
54 9ee6e8bb pbrook
    uint32_t match[2];
55 9ee6e8bb pbrook
    uint32_t prescale[2];
56 9ee6e8bb pbrook
    uint32_t match_prescale[2];
57 9ee6e8bb pbrook
    uint32_t rtc;
58 9ee6e8bb pbrook
    int64_t tick[2];
59 9ee6e8bb pbrook
    struct gptm_state *opaque[2];
60 9ee6e8bb pbrook
    QEMUTimer *timer[2];
61 9ee6e8bb pbrook
    /* The timers have an alternate output used to trigger the ADC.  */
62 9ee6e8bb pbrook
    qemu_irq trigger;
63 9ee6e8bb pbrook
    qemu_irq irq;
64 9ee6e8bb pbrook
} gptm_state;
65 9ee6e8bb pbrook
66 9ee6e8bb pbrook
static void gptm_update_irq(gptm_state *s)
67 9ee6e8bb pbrook
{
68 9ee6e8bb pbrook
    int level;
69 9ee6e8bb pbrook
    level = (s->state & s->mask) != 0;
70 9ee6e8bb pbrook
    qemu_set_irq(s->irq, level);
71 9ee6e8bb pbrook
}
72 9ee6e8bb pbrook
73 9ee6e8bb pbrook
static void gptm_stop(gptm_state *s, int n)
74 9ee6e8bb pbrook
{
75 9ee6e8bb pbrook
    qemu_del_timer(s->timer[n]);
76 9ee6e8bb pbrook
}
77 9ee6e8bb pbrook
78 9ee6e8bb pbrook
static void gptm_reload(gptm_state *s, int n, int reset)
79 9ee6e8bb pbrook
{
80 9ee6e8bb pbrook
    int64_t tick;
81 9ee6e8bb pbrook
    if (reset)
82 9ee6e8bb pbrook
        tick = qemu_get_clock(vm_clock);
83 9ee6e8bb pbrook
    else
84 9ee6e8bb pbrook
        tick = s->tick[n];
85 9ee6e8bb pbrook
86 9ee6e8bb pbrook
    if (s->config == 0) {
87 9ee6e8bb pbrook
        /* 32-bit CountDown.  */
88 9ee6e8bb pbrook
        uint32_t count;
89 9ee6e8bb pbrook
        count = s->load[0] | (s->load[1] << 16);
90 e57ec016 pbrook
        tick += (int64_t)count * system_clock_scale;
91 9ee6e8bb pbrook
    } else if (s->config == 1) {
92 9ee6e8bb pbrook
        /* 32-bit RTC.  1Hz tick.  */
93 9ee6e8bb pbrook
        tick += ticks_per_sec;
94 9ee6e8bb pbrook
    } else if (s->mode[n] == 0xa) {
95 9ee6e8bb pbrook
        /* PWM mode.  Not implemented.  */
96 9ee6e8bb pbrook
    } else {
97 2ac71179 Paul Brook
        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
98 9ee6e8bb pbrook
    }
99 9ee6e8bb pbrook
    s->tick[n] = tick;
100 9ee6e8bb pbrook
    qemu_mod_timer(s->timer[n], tick);
101 9ee6e8bb pbrook
}
102 9ee6e8bb pbrook
103 9ee6e8bb pbrook
static void gptm_tick(void *opaque)
104 9ee6e8bb pbrook
{
105 9ee6e8bb pbrook
    gptm_state **p = (gptm_state **)opaque;
106 9ee6e8bb pbrook
    gptm_state *s;
107 9ee6e8bb pbrook
    int n;
108 9ee6e8bb pbrook
109 9ee6e8bb pbrook
    s = *p;
110 9ee6e8bb pbrook
    n = p - s->opaque;
111 9ee6e8bb pbrook
    if (s->config == 0) {
112 9ee6e8bb pbrook
        s->state |= 1;
113 9ee6e8bb pbrook
        if ((s->control & 0x20)) {
114 9ee6e8bb pbrook
            /* Output trigger.  */
115 9ee6e8bb pbrook
            qemu_irq_raise(s->trigger);
116 9ee6e8bb pbrook
            qemu_irq_lower(s->trigger);
117 9ee6e8bb pbrook
        }
118 9ee6e8bb pbrook
        if (s->mode[0] & 1) {
119 9ee6e8bb pbrook
            /* One-shot.  */
120 9ee6e8bb pbrook
            s->control &= ~1;
121 9ee6e8bb pbrook
        } else {
122 9ee6e8bb pbrook
            /* Periodic.  */
123 9ee6e8bb pbrook
            gptm_reload(s, 0, 0);
124 9ee6e8bb pbrook
        }
125 9ee6e8bb pbrook
    } else if (s->config == 1) {
126 9ee6e8bb pbrook
        /* RTC.  */
127 9ee6e8bb pbrook
        uint32_t match;
128 9ee6e8bb pbrook
        s->rtc++;
129 9ee6e8bb pbrook
        match = s->match[0] | (s->match[1] << 16);
130 9ee6e8bb pbrook
        if (s->rtc > match)
131 9ee6e8bb pbrook
            s->rtc = 0;
132 9ee6e8bb pbrook
        if (s->rtc == 0) {
133 9ee6e8bb pbrook
            s->state |= 8;
134 9ee6e8bb pbrook
        }
135 9ee6e8bb pbrook
        gptm_reload(s, 0, 0);
136 9ee6e8bb pbrook
    } else if (s->mode[n] == 0xa) {
137 9ee6e8bb pbrook
        /* PWM mode.  Not implemented.  */
138 9ee6e8bb pbrook
    } else {
139 2ac71179 Paul Brook
        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
140 9ee6e8bb pbrook
    }
141 9ee6e8bb pbrook
    gptm_update_irq(s);
142 9ee6e8bb pbrook
}
143 9ee6e8bb pbrook
144 9ee6e8bb pbrook
static uint32_t gptm_read(void *opaque, target_phys_addr_t offset)
145 9ee6e8bb pbrook
{
146 9ee6e8bb pbrook
    gptm_state *s = (gptm_state *)opaque;
147 9ee6e8bb pbrook
148 9ee6e8bb pbrook
    switch (offset) {
149 9ee6e8bb pbrook
    case 0x00: /* CFG */
150 9ee6e8bb pbrook
        return s->config;
151 9ee6e8bb pbrook
    case 0x04: /* TAMR */
152 9ee6e8bb pbrook
        return s->mode[0];
153 9ee6e8bb pbrook
    case 0x08: /* TBMR */
154 9ee6e8bb pbrook
        return s->mode[1];
155 9ee6e8bb pbrook
    case 0x0c: /* CTL */
156 9ee6e8bb pbrook
        return s->control;
157 9ee6e8bb pbrook
    case 0x18: /* IMR */
158 9ee6e8bb pbrook
        return s->mask;
159 9ee6e8bb pbrook
    case 0x1c: /* RIS */
160 9ee6e8bb pbrook
        return s->state;
161 9ee6e8bb pbrook
    case 0x20: /* MIS */
162 9ee6e8bb pbrook
        return s->state & s->mask;
163 9ee6e8bb pbrook
    case 0x24: /* CR */
164 9ee6e8bb pbrook
        return 0;
165 9ee6e8bb pbrook
    case 0x28: /* TAILR */
166 9ee6e8bb pbrook
        return s->load[0] | ((s->config < 4) ? (s->load[1] << 16) : 0);
167 9ee6e8bb pbrook
    case 0x2c: /* TBILR */
168 9ee6e8bb pbrook
        return s->load[1];
169 9ee6e8bb pbrook
    case 0x30: /* TAMARCHR */
170 9ee6e8bb pbrook
        return s->match[0] | ((s->config < 4) ? (s->match[1] << 16) : 0);
171 9ee6e8bb pbrook
    case 0x34: /* TBMATCHR */
172 9ee6e8bb pbrook
        return s->match[1];
173 9ee6e8bb pbrook
    case 0x38: /* TAPR */
174 9ee6e8bb pbrook
        return s->prescale[0];
175 9ee6e8bb pbrook
    case 0x3c: /* TBPR */
176 9ee6e8bb pbrook
        return s->prescale[1];
177 9ee6e8bb pbrook
    case 0x40: /* TAPMR */
178 9ee6e8bb pbrook
        return s->match_prescale[0];
179 9ee6e8bb pbrook
    case 0x44: /* TBPMR */
180 9ee6e8bb pbrook
        return s->match_prescale[1];
181 9ee6e8bb pbrook
    case 0x48: /* TAR */
182 9ee6e8bb pbrook
        if (s->control == 1)
183 9ee6e8bb pbrook
            return s->rtc;
184 9ee6e8bb pbrook
    case 0x4c: /* TBR */
185 2ac71179 Paul Brook
        hw_error("TODO: Timer value read\n");
186 9ee6e8bb pbrook
    default:
187 2ac71179 Paul Brook
        hw_error("gptm_read: Bad offset 0x%x\n", (int)offset);
188 9ee6e8bb pbrook
        return 0;
189 9ee6e8bb pbrook
    }
190 9ee6e8bb pbrook
}
191 9ee6e8bb pbrook
192 9ee6e8bb pbrook
static void gptm_write(void *opaque, target_phys_addr_t offset, uint32_t value)
193 9ee6e8bb pbrook
{
194 9ee6e8bb pbrook
    gptm_state *s = (gptm_state *)opaque;
195 9ee6e8bb pbrook
    uint32_t oldval;
196 9ee6e8bb pbrook
197 9ee6e8bb pbrook
    /* The timers should be disabled before changing the configuration.
198 9ee6e8bb pbrook
       We take advantage of this and defer everything until the timer
199 9ee6e8bb pbrook
       is enabled.  */
200 9ee6e8bb pbrook
    switch (offset) {
201 9ee6e8bb pbrook
    case 0x00: /* CFG */
202 9ee6e8bb pbrook
        s->config = value;
203 9ee6e8bb pbrook
        break;
204 9ee6e8bb pbrook
    case 0x04: /* TAMR */
205 9ee6e8bb pbrook
        s->mode[0] = value;
206 9ee6e8bb pbrook
        break;
207 9ee6e8bb pbrook
    case 0x08: /* TBMR */
208 9ee6e8bb pbrook
        s->mode[1] = value;
209 9ee6e8bb pbrook
        break;
210 9ee6e8bb pbrook
    case 0x0c: /* CTL */
211 9ee6e8bb pbrook
        oldval = s->control;
212 9ee6e8bb pbrook
        s->control = value;
213 9ee6e8bb pbrook
        /* TODO: Implement pause.  */
214 9ee6e8bb pbrook
        if ((oldval ^ value) & 1) {
215 9ee6e8bb pbrook
            if (value & 1) {
216 9ee6e8bb pbrook
                gptm_reload(s, 0, 1);
217 9ee6e8bb pbrook
            } else {
218 9ee6e8bb pbrook
                gptm_stop(s, 0);
219 9ee6e8bb pbrook
            }
220 9ee6e8bb pbrook
        }
221 9ee6e8bb pbrook
        if (((oldval ^ value) & 0x100) && s->config >= 4) {
222 9ee6e8bb pbrook
            if (value & 0x100) {
223 9ee6e8bb pbrook
                gptm_reload(s, 1, 1);
224 9ee6e8bb pbrook
            } else {
225 9ee6e8bb pbrook
                gptm_stop(s, 1);
226 9ee6e8bb pbrook
            }
227 9ee6e8bb pbrook
        }
228 9ee6e8bb pbrook
        break;
229 9ee6e8bb pbrook
    case 0x18: /* IMR */
230 9ee6e8bb pbrook
        s->mask = value & 0x77;
231 9ee6e8bb pbrook
        gptm_update_irq(s);
232 9ee6e8bb pbrook
        break;
233 9ee6e8bb pbrook
    case 0x24: /* CR */
234 9ee6e8bb pbrook
        s->state &= ~value;
235 9ee6e8bb pbrook
        break;
236 9ee6e8bb pbrook
    case 0x28: /* TAILR */
237 9ee6e8bb pbrook
        s->load[0] = value & 0xffff;
238 9ee6e8bb pbrook
        if (s->config < 4) {
239 9ee6e8bb pbrook
            s->load[1] = value >> 16;
240 9ee6e8bb pbrook
        }
241 9ee6e8bb pbrook
        break;
242 9ee6e8bb pbrook
    case 0x2c: /* TBILR */
243 9ee6e8bb pbrook
        s->load[1] = value & 0xffff;
244 9ee6e8bb pbrook
        break;
245 9ee6e8bb pbrook
    case 0x30: /* TAMARCHR */
246 9ee6e8bb pbrook
        s->match[0] = value & 0xffff;
247 9ee6e8bb pbrook
        if (s->config < 4) {
248 9ee6e8bb pbrook
            s->match[1] = value >> 16;
249 9ee6e8bb pbrook
        }
250 9ee6e8bb pbrook
        break;
251 9ee6e8bb pbrook
    case 0x34: /* TBMATCHR */
252 9ee6e8bb pbrook
        s->match[1] = value >> 16;
253 9ee6e8bb pbrook
        break;
254 9ee6e8bb pbrook
    case 0x38: /* TAPR */
255 9ee6e8bb pbrook
        s->prescale[0] = value;
256 9ee6e8bb pbrook
        break;
257 9ee6e8bb pbrook
    case 0x3c: /* TBPR */
258 9ee6e8bb pbrook
        s->prescale[1] = value;
259 9ee6e8bb pbrook
        break;
260 9ee6e8bb pbrook
    case 0x40: /* TAPMR */
261 9ee6e8bb pbrook
        s->match_prescale[0] = value;
262 9ee6e8bb pbrook
        break;
263 9ee6e8bb pbrook
    case 0x44: /* TBPMR */
264 9ee6e8bb pbrook
        s->match_prescale[0] = value;
265 9ee6e8bb pbrook
        break;
266 9ee6e8bb pbrook
    default:
267 2ac71179 Paul Brook
        hw_error("gptm_write: Bad offset 0x%x\n", (int)offset);
268 9ee6e8bb pbrook
    }
269 9ee6e8bb pbrook
    gptm_update_irq(s);
270 9ee6e8bb pbrook
}
271 9ee6e8bb pbrook
272 9ee6e8bb pbrook
static CPUReadMemoryFunc *gptm_readfn[] = {
273 9ee6e8bb pbrook
   gptm_read,
274 9ee6e8bb pbrook
   gptm_read,
275 9ee6e8bb pbrook
   gptm_read
276 9ee6e8bb pbrook
};
277 9ee6e8bb pbrook
278 9ee6e8bb pbrook
static CPUWriteMemoryFunc *gptm_writefn[] = {
279 9ee6e8bb pbrook
   gptm_write,
280 9ee6e8bb pbrook
   gptm_write,
281 9ee6e8bb pbrook
   gptm_write
282 9ee6e8bb pbrook
};
283 9ee6e8bb pbrook
284 23e39294 pbrook
static void gptm_save(QEMUFile *f, void *opaque)
285 23e39294 pbrook
{
286 23e39294 pbrook
    gptm_state *s = (gptm_state *)opaque;
287 23e39294 pbrook
288 23e39294 pbrook
    qemu_put_be32(f, s->config);
289 23e39294 pbrook
    qemu_put_be32(f, s->mode[0]);
290 23e39294 pbrook
    qemu_put_be32(f, s->mode[1]);
291 23e39294 pbrook
    qemu_put_be32(f, s->control);
292 23e39294 pbrook
    qemu_put_be32(f, s->state);
293 23e39294 pbrook
    qemu_put_be32(f, s->mask);
294 23e39294 pbrook
    qemu_put_be32(f, s->mode[0]);
295 23e39294 pbrook
    qemu_put_be32(f, s->mode[0]);
296 23e39294 pbrook
    qemu_put_be32(f, s->load[0]);
297 23e39294 pbrook
    qemu_put_be32(f, s->load[1]);
298 23e39294 pbrook
    qemu_put_be32(f, s->match[0]);
299 23e39294 pbrook
    qemu_put_be32(f, s->match[1]);
300 23e39294 pbrook
    qemu_put_be32(f, s->prescale[0]);
301 23e39294 pbrook
    qemu_put_be32(f, s->prescale[1]);
302 23e39294 pbrook
    qemu_put_be32(f, s->match_prescale[0]);
303 23e39294 pbrook
    qemu_put_be32(f, s->match_prescale[1]);
304 23e39294 pbrook
    qemu_put_be32(f, s->rtc);
305 23e39294 pbrook
    qemu_put_be64(f, s->tick[0]);
306 23e39294 pbrook
    qemu_put_be64(f, s->tick[1]);
307 23e39294 pbrook
    qemu_put_timer(f, s->timer[0]);
308 23e39294 pbrook
    qemu_put_timer(f, s->timer[1]);
309 23e39294 pbrook
}
310 23e39294 pbrook
311 23e39294 pbrook
static int gptm_load(QEMUFile *f, void *opaque, int version_id)
312 23e39294 pbrook
{
313 23e39294 pbrook
    gptm_state *s = (gptm_state *)opaque;
314 23e39294 pbrook
315 23e39294 pbrook
    if (version_id != 1)
316 23e39294 pbrook
        return -EINVAL;
317 23e39294 pbrook
318 23e39294 pbrook
    s->config = qemu_get_be32(f);
319 23e39294 pbrook
    s->mode[0] = qemu_get_be32(f);
320 23e39294 pbrook
    s->mode[1] = qemu_get_be32(f);
321 23e39294 pbrook
    s->control = qemu_get_be32(f);
322 23e39294 pbrook
    s->state = qemu_get_be32(f);
323 23e39294 pbrook
    s->mask = qemu_get_be32(f);
324 23e39294 pbrook
    s->mode[0] = qemu_get_be32(f);
325 23e39294 pbrook
    s->mode[0] = qemu_get_be32(f);
326 23e39294 pbrook
    s->load[0] = qemu_get_be32(f);
327 23e39294 pbrook
    s->load[1] = qemu_get_be32(f);
328 23e39294 pbrook
    s->match[0] = qemu_get_be32(f);
329 23e39294 pbrook
    s->match[1] = qemu_get_be32(f);
330 23e39294 pbrook
    s->prescale[0] = qemu_get_be32(f);
331 23e39294 pbrook
    s->prescale[1] = qemu_get_be32(f);
332 23e39294 pbrook
    s->match_prescale[0] = qemu_get_be32(f);
333 23e39294 pbrook
    s->match_prescale[1] = qemu_get_be32(f);
334 23e39294 pbrook
    s->rtc = qemu_get_be32(f);
335 23e39294 pbrook
    s->tick[0] = qemu_get_be64(f);
336 23e39294 pbrook
    s->tick[1] = qemu_get_be64(f);
337 23e39294 pbrook
    qemu_get_timer(f, s->timer[0]);
338 23e39294 pbrook
    qemu_get_timer(f, s->timer[1]);
339 23e39294 pbrook
340 23e39294 pbrook
    return 0;
341 23e39294 pbrook
}
342 23e39294 pbrook
343 9ee6e8bb pbrook
static void stellaris_gptm_init(uint32_t base, qemu_irq irq, qemu_irq trigger)
344 9ee6e8bb pbrook
{
345 9ee6e8bb pbrook
    int iomemtype;
346 9ee6e8bb pbrook
    gptm_state *s;
347 9ee6e8bb pbrook
348 9ee6e8bb pbrook
    s = (gptm_state *)qemu_mallocz(sizeof(gptm_state));
349 9ee6e8bb pbrook
    s->irq = irq;
350 9ee6e8bb pbrook
    s->trigger = trigger;
351 9ee6e8bb pbrook
    s->opaque[0] = s->opaque[1] = s;
352 9ee6e8bb pbrook
353 9ee6e8bb pbrook
    iomemtype = cpu_register_io_memory(0, gptm_readfn,
354 9ee6e8bb pbrook
                                       gptm_writefn, s);
355 9ee6e8bb pbrook
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
356 9ee6e8bb pbrook
    s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]);
357 9ee6e8bb pbrook
    s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]);
358 23e39294 pbrook
    register_savevm("stellaris_gptm", -1, 1, gptm_save, gptm_load, s);
359 9ee6e8bb pbrook
}
360 9ee6e8bb pbrook
361 9ee6e8bb pbrook
362 9ee6e8bb pbrook
/* System controller.  */
363 9ee6e8bb pbrook
364 9ee6e8bb pbrook
typedef struct {
365 9ee6e8bb pbrook
    uint32_t pborctl;
366 9ee6e8bb pbrook
    uint32_t ldopctl;
367 9ee6e8bb pbrook
    uint32_t int_status;
368 9ee6e8bb pbrook
    uint32_t int_mask;
369 9ee6e8bb pbrook
    uint32_t resc;
370 9ee6e8bb pbrook
    uint32_t rcc;
371 9ee6e8bb pbrook
    uint32_t rcgc[3];
372 9ee6e8bb pbrook
    uint32_t scgc[3];
373 9ee6e8bb pbrook
    uint32_t dcgc[3];
374 9ee6e8bb pbrook
    uint32_t clkvclr;
375 9ee6e8bb pbrook
    uint32_t ldoarst;
376 eea589cc pbrook
    uint32_t user0;
377 eea589cc pbrook
    uint32_t user1;
378 9ee6e8bb pbrook
    qemu_irq irq;
379 9ee6e8bb pbrook
    stellaris_board_info *board;
380 9ee6e8bb pbrook
} ssys_state;
381 9ee6e8bb pbrook
382 9ee6e8bb pbrook
static void ssys_update(ssys_state *s)
383 9ee6e8bb pbrook
{
384 9ee6e8bb pbrook
  qemu_set_irq(s->irq, (s->int_status & s->int_mask) != 0);
385 9ee6e8bb pbrook
}
386 9ee6e8bb pbrook
387 9ee6e8bb pbrook
static uint32_t pllcfg_sandstorm[16] = {
388 9ee6e8bb pbrook
    0x31c0, /* 1 Mhz */
389 9ee6e8bb pbrook
    0x1ae0, /* 1.8432 Mhz */
390 9ee6e8bb pbrook
    0x18c0, /* 2 Mhz */
391 9ee6e8bb pbrook
    0xd573, /* 2.4576 Mhz */
392 9ee6e8bb pbrook
    0x37a6, /* 3.57954 Mhz */
393 9ee6e8bb pbrook
    0x1ae2, /* 3.6864 Mhz */
394 9ee6e8bb pbrook
    0x0c40, /* 4 Mhz */
395 9ee6e8bb pbrook
    0x98bc, /* 4.906 Mhz */
396 9ee6e8bb pbrook
    0x935b, /* 4.9152 Mhz */
397 9ee6e8bb pbrook
    0x09c0, /* 5 Mhz */
398 9ee6e8bb pbrook
    0x4dee, /* 5.12 Mhz */
399 9ee6e8bb pbrook
    0x0c41, /* 6 Mhz */
400 9ee6e8bb pbrook
    0x75db, /* 6.144 Mhz */
401 9ee6e8bb pbrook
    0x1ae6, /* 7.3728 Mhz */
402 9ee6e8bb pbrook
    0x0600, /* 8 Mhz */
403 9ee6e8bb pbrook
    0x585b /* 8.192 Mhz */
404 9ee6e8bb pbrook
};
405 9ee6e8bb pbrook
406 9ee6e8bb pbrook
static uint32_t pllcfg_fury[16] = {
407 9ee6e8bb pbrook
    0x3200, /* 1 Mhz */
408 9ee6e8bb pbrook
    0x1b20, /* 1.8432 Mhz */
409 9ee6e8bb pbrook
    0x1900, /* 2 Mhz */
410 9ee6e8bb pbrook
    0xf42b, /* 2.4576 Mhz */
411 9ee6e8bb pbrook
    0x37e3, /* 3.57954 Mhz */
412 9ee6e8bb pbrook
    0x1b21, /* 3.6864 Mhz */
413 9ee6e8bb pbrook
    0x0c80, /* 4 Mhz */
414 9ee6e8bb pbrook
    0x98ee, /* 4.906 Mhz */
415 9ee6e8bb pbrook
    0xd5b4, /* 4.9152 Mhz */
416 9ee6e8bb pbrook
    0x0a00, /* 5 Mhz */
417 9ee6e8bb pbrook
    0x4e27, /* 5.12 Mhz */
418 9ee6e8bb pbrook
    0x1902, /* 6 Mhz */
419 9ee6e8bb pbrook
    0xec1c, /* 6.144 Mhz */
420 9ee6e8bb pbrook
    0x1b23, /* 7.3728 Mhz */
421 9ee6e8bb pbrook
    0x0640, /* 8 Mhz */
422 9ee6e8bb pbrook
    0xb11c /* 8.192 Mhz */
423 9ee6e8bb pbrook
};
424 9ee6e8bb pbrook
425 9ee6e8bb pbrook
static uint32_t ssys_read(void *opaque, target_phys_addr_t offset)
426 9ee6e8bb pbrook
{
427 9ee6e8bb pbrook
    ssys_state *s = (ssys_state *)opaque;
428 9ee6e8bb pbrook
429 9ee6e8bb pbrook
    switch (offset) {
430 9ee6e8bb pbrook
    case 0x000: /* DID0 */
431 9ee6e8bb pbrook
        return s->board->did0;
432 9ee6e8bb pbrook
    case 0x004: /* DID1 */
433 9ee6e8bb pbrook
        return s->board->did1;
434 9ee6e8bb pbrook
    case 0x008: /* DC0 */
435 9ee6e8bb pbrook
        return s->board->dc0;
436 9ee6e8bb pbrook
    case 0x010: /* DC1 */
437 9ee6e8bb pbrook
        return s->board->dc1;
438 9ee6e8bb pbrook
    case 0x014: /* DC2 */
439 9ee6e8bb pbrook
        return s->board->dc2;
440 9ee6e8bb pbrook
    case 0x018: /* DC3 */
441 9ee6e8bb pbrook
        return s->board->dc3;
442 9ee6e8bb pbrook
    case 0x01c: /* DC4 */
443 9ee6e8bb pbrook
        return s->board->dc4;
444 9ee6e8bb pbrook
    case 0x030: /* PBORCTL */
445 9ee6e8bb pbrook
        return s->pborctl;
446 9ee6e8bb pbrook
    case 0x034: /* LDOPCTL */
447 9ee6e8bb pbrook
        return s->ldopctl;
448 9ee6e8bb pbrook
    case 0x040: /* SRCR0 */
449 9ee6e8bb pbrook
        return 0;
450 9ee6e8bb pbrook
    case 0x044: /* SRCR1 */
451 9ee6e8bb pbrook
        return 0;
452 9ee6e8bb pbrook
    case 0x048: /* SRCR2 */
453 9ee6e8bb pbrook
        return 0;
454 9ee6e8bb pbrook
    case 0x050: /* RIS */
455 9ee6e8bb pbrook
        return s->int_status;
456 9ee6e8bb pbrook
    case 0x054: /* IMC */
457 9ee6e8bb pbrook
        return s->int_mask;
458 9ee6e8bb pbrook
    case 0x058: /* MISC */
459 9ee6e8bb pbrook
        return s->int_status & s->int_mask;
460 9ee6e8bb pbrook
    case 0x05c: /* RESC */
461 9ee6e8bb pbrook
        return s->resc;
462 9ee6e8bb pbrook
    case 0x060: /* RCC */
463 9ee6e8bb pbrook
        return s->rcc;
464 9ee6e8bb pbrook
    case 0x064: /* PLLCFG */
465 9ee6e8bb pbrook
        {
466 9ee6e8bb pbrook
            int xtal;
467 9ee6e8bb pbrook
            xtal = (s->rcc >> 6) & 0xf;
468 9ee6e8bb pbrook
            if (s->board->did0 & (1 << 16)) {
469 9ee6e8bb pbrook
                return pllcfg_fury[xtal];
470 9ee6e8bb pbrook
            } else {
471 9ee6e8bb pbrook
                return pllcfg_sandstorm[xtal];
472 9ee6e8bb pbrook
            }
473 9ee6e8bb pbrook
        }
474 9ee6e8bb pbrook
    case 0x100: /* RCGC0 */
475 9ee6e8bb pbrook
        return s->rcgc[0];
476 9ee6e8bb pbrook
    case 0x104: /* RCGC1 */
477 9ee6e8bb pbrook
        return s->rcgc[1];
478 9ee6e8bb pbrook
    case 0x108: /* RCGC2 */
479 9ee6e8bb pbrook
        return s->rcgc[2];
480 9ee6e8bb pbrook
    case 0x110: /* SCGC0 */
481 9ee6e8bb pbrook
        return s->scgc[0];
482 9ee6e8bb pbrook
    case 0x114: /* SCGC1 */
483 9ee6e8bb pbrook
        return s->scgc[1];
484 9ee6e8bb pbrook
    case 0x118: /* SCGC2 */
485 9ee6e8bb pbrook
        return s->scgc[2];
486 9ee6e8bb pbrook
    case 0x120: /* DCGC0 */
487 9ee6e8bb pbrook
        return s->dcgc[0];
488 9ee6e8bb pbrook
    case 0x124: /* DCGC1 */
489 9ee6e8bb pbrook
        return s->dcgc[1];
490 9ee6e8bb pbrook
    case 0x128: /* DCGC2 */
491 9ee6e8bb pbrook
        return s->dcgc[2];
492 9ee6e8bb pbrook
    case 0x150: /* CLKVCLR */
493 9ee6e8bb pbrook
        return s->clkvclr;
494 9ee6e8bb pbrook
    case 0x160: /* LDOARST */
495 9ee6e8bb pbrook
        return s->ldoarst;
496 eea589cc pbrook
    case 0x1e0: /* USER0 */
497 eea589cc pbrook
        return s->user0;
498 eea589cc pbrook
    case 0x1e4: /* USER1 */
499 eea589cc pbrook
        return s->user1;
500 9ee6e8bb pbrook
    default:
501 2ac71179 Paul Brook
        hw_error("ssys_read: Bad offset 0x%x\n", (int)offset);
502 9ee6e8bb pbrook
        return 0;
503 9ee6e8bb pbrook
    }
504 9ee6e8bb pbrook
}
505 9ee6e8bb pbrook
506 23e39294 pbrook
static void ssys_calculate_system_clock(ssys_state *s)
507 23e39294 pbrook
{
508 23e39294 pbrook
    system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
509 23e39294 pbrook
}
510 23e39294 pbrook
511 9ee6e8bb pbrook
static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value)
512 9ee6e8bb pbrook
{
513 9ee6e8bb pbrook
    ssys_state *s = (ssys_state *)opaque;
514 9ee6e8bb pbrook
515 9ee6e8bb pbrook
    switch (offset) {
516 9ee6e8bb pbrook
    case 0x030: /* PBORCTL */
517 9ee6e8bb pbrook
        s->pborctl = value & 0xffff;
518 9ee6e8bb pbrook
        break;
519 9ee6e8bb pbrook
    case 0x034: /* LDOPCTL */
520 9ee6e8bb pbrook
        s->ldopctl = value & 0x1f;
521 9ee6e8bb pbrook
        break;
522 9ee6e8bb pbrook
    case 0x040: /* SRCR0 */
523 9ee6e8bb pbrook
    case 0x044: /* SRCR1 */
524 9ee6e8bb pbrook
    case 0x048: /* SRCR2 */
525 9ee6e8bb pbrook
        fprintf(stderr, "Peripheral reset not implemented\n");
526 9ee6e8bb pbrook
        break;
527 9ee6e8bb pbrook
    case 0x054: /* IMC */
528 9ee6e8bb pbrook
        s->int_mask = value & 0x7f;
529 9ee6e8bb pbrook
        break;
530 9ee6e8bb pbrook
    case 0x058: /* MISC */
531 9ee6e8bb pbrook
        s->int_status &= ~value;
532 9ee6e8bb pbrook
        break;
533 9ee6e8bb pbrook
    case 0x05c: /* RESC */
534 9ee6e8bb pbrook
        s->resc = value & 0x3f;
535 9ee6e8bb pbrook
        break;
536 9ee6e8bb pbrook
    case 0x060: /* RCC */
537 9ee6e8bb pbrook
        if ((s->rcc & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
538 9ee6e8bb pbrook
            /* PLL enable.  */
539 9ee6e8bb pbrook
            s->int_status |= (1 << 6);
540 9ee6e8bb pbrook
        }
541 9ee6e8bb pbrook
        s->rcc = value;
542 23e39294 pbrook
        ssys_calculate_system_clock(s);
543 9ee6e8bb pbrook
        break;
544 9ee6e8bb pbrook
    case 0x100: /* RCGC0 */
545 9ee6e8bb pbrook
        s->rcgc[0] = value;
546 9ee6e8bb pbrook
        break;
547 9ee6e8bb pbrook
    case 0x104: /* RCGC1 */
548 9ee6e8bb pbrook
        s->rcgc[1] = value;
549 9ee6e8bb pbrook
        break;
550 9ee6e8bb pbrook
    case 0x108: /* RCGC2 */
551 9ee6e8bb pbrook
        s->rcgc[2] = value;
552 9ee6e8bb pbrook
        break;
553 9ee6e8bb pbrook
    case 0x110: /* SCGC0 */
554 9ee6e8bb pbrook
        s->scgc[0] = value;
555 9ee6e8bb pbrook
        break;
556 9ee6e8bb pbrook
    case 0x114: /* SCGC1 */
557 9ee6e8bb pbrook
        s->scgc[1] = value;
558 9ee6e8bb pbrook
        break;
559 9ee6e8bb pbrook
    case 0x118: /* SCGC2 */
560 9ee6e8bb pbrook
        s->scgc[2] = value;
561 9ee6e8bb pbrook
        break;
562 9ee6e8bb pbrook
    case 0x120: /* DCGC0 */
563 9ee6e8bb pbrook
        s->dcgc[0] = value;
564 9ee6e8bb pbrook
        break;
565 9ee6e8bb pbrook
    case 0x124: /* DCGC1 */
566 9ee6e8bb pbrook
        s->dcgc[1] = value;
567 9ee6e8bb pbrook
        break;
568 9ee6e8bb pbrook
    case 0x128: /* DCGC2 */
569 9ee6e8bb pbrook
        s->dcgc[2] = value;
570 9ee6e8bb pbrook
        break;
571 9ee6e8bb pbrook
    case 0x150: /* CLKVCLR */
572 9ee6e8bb pbrook
        s->clkvclr = value;
573 9ee6e8bb pbrook
        break;
574 9ee6e8bb pbrook
    case 0x160: /* LDOARST */
575 9ee6e8bb pbrook
        s->ldoarst = value;
576 9ee6e8bb pbrook
        break;
577 9ee6e8bb pbrook
    default:
578 2ac71179 Paul Brook
        hw_error("ssys_write: Bad offset 0x%x\n", (int)offset);
579 9ee6e8bb pbrook
    }
580 9ee6e8bb pbrook
    ssys_update(s);
581 9ee6e8bb pbrook
}
582 9ee6e8bb pbrook
583 9ee6e8bb pbrook
static CPUReadMemoryFunc *ssys_readfn[] = {
584 9ee6e8bb pbrook
   ssys_read,
585 9ee6e8bb pbrook
   ssys_read,
586 9ee6e8bb pbrook
   ssys_read
587 9ee6e8bb pbrook
};
588 9ee6e8bb pbrook
589 9ee6e8bb pbrook
static CPUWriteMemoryFunc *ssys_writefn[] = {
590 9ee6e8bb pbrook
   ssys_write,
591 9ee6e8bb pbrook
   ssys_write,
592 9ee6e8bb pbrook
   ssys_write
593 9ee6e8bb pbrook
};
594 9ee6e8bb pbrook
595 9596ebb7 pbrook
static void ssys_reset(void *opaque)
596 9ee6e8bb pbrook
{
597 9ee6e8bb pbrook
    ssys_state *s = (ssys_state *)opaque;
598 9ee6e8bb pbrook
599 9ee6e8bb pbrook
    s->pborctl = 0x7ffd;
600 9ee6e8bb pbrook
    s->rcc = 0x078e3ac0;
601 9ee6e8bb pbrook
    s->rcgc[0] = 1;
602 9ee6e8bb pbrook
    s->scgc[0] = 1;
603 9ee6e8bb pbrook
    s->dcgc[0] = 1;
604 9ee6e8bb pbrook
}
605 9ee6e8bb pbrook
606 23e39294 pbrook
static void ssys_save(QEMUFile *f, void *opaque)
607 23e39294 pbrook
{
608 23e39294 pbrook
    ssys_state *s = (ssys_state *)opaque;
609 23e39294 pbrook
610 23e39294 pbrook
    qemu_put_be32(f, s->pborctl);
611 23e39294 pbrook
    qemu_put_be32(f, s->ldopctl);
612 23e39294 pbrook
    qemu_put_be32(f, s->int_mask);
613 23e39294 pbrook
    qemu_put_be32(f, s->int_status);
614 23e39294 pbrook
    qemu_put_be32(f, s->resc);
615 23e39294 pbrook
    qemu_put_be32(f, s->rcc);
616 23e39294 pbrook
    qemu_put_be32(f, s->rcgc[0]);
617 23e39294 pbrook
    qemu_put_be32(f, s->rcgc[1]);
618 23e39294 pbrook
    qemu_put_be32(f, s->rcgc[2]);
619 23e39294 pbrook
    qemu_put_be32(f, s->scgc[0]);
620 23e39294 pbrook
    qemu_put_be32(f, s->scgc[1]);
621 23e39294 pbrook
    qemu_put_be32(f, s->scgc[2]);
622 23e39294 pbrook
    qemu_put_be32(f, s->dcgc[0]);
623 23e39294 pbrook
    qemu_put_be32(f, s->dcgc[1]);
624 23e39294 pbrook
    qemu_put_be32(f, s->dcgc[2]);
625 23e39294 pbrook
    qemu_put_be32(f, s->clkvclr);
626 23e39294 pbrook
    qemu_put_be32(f, s->ldoarst);
627 23e39294 pbrook
}
628 23e39294 pbrook
629 23e39294 pbrook
static int ssys_load(QEMUFile *f, void *opaque, int version_id)
630 23e39294 pbrook
{
631 23e39294 pbrook
    ssys_state *s = (ssys_state *)opaque;
632 23e39294 pbrook
633 23e39294 pbrook
    if (version_id != 1)
634 23e39294 pbrook
        return -EINVAL;
635 23e39294 pbrook
636 23e39294 pbrook
    s->pborctl = qemu_get_be32(f);
637 23e39294 pbrook
    s->ldopctl = qemu_get_be32(f);
638 23e39294 pbrook
    s->int_mask = qemu_get_be32(f);
639 23e39294 pbrook
    s->int_status = qemu_get_be32(f);
640 23e39294 pbrook
    s->resc = qemu_get_be32(f);
641 23e39294 pbrook
    s->rcc = qemu_get_be32(f);
642 23e39294 pbrook
    s->rcgc[0] = qemu_get_be32(f);
643 23e39294 pbrook
    s->rcgc[1] = qemu_get_be32(f);
644 23e39294 pbrook
    s->rcgc[2] = qemu_get_be32(f);
645 23e39294 pbrook
    s->scgc[0] = qemu_get_be32(f);
646 23e39294 pbrook
    s->scgc[1] = qemu_get_be32(f);
647 23e39294 pbrook
    s->scgc[2] = qemu_get_be32(f);
648 23e39294 pbrook
    s->dcgc[0] = qemu_get_be32(f);
649 23e39294 pbrook
    s->dcgc[1] = qemu_get_be32(f);
650 23e39294 pbrook
    s->dcgc[2] = qemu_get_be32(f);
651 23e39294 pbrook
    s->clkvclr = qemu_get_be32(f);
652 23e39294 pbrook
    s->ldoarst = qemu_get_be32(f);
653 23e39294 pbrook
    ssys_calculate_system_clock(s);
654 23e39294 pbrook
655 23e39294 pbrook
    return 0;
656 23e39294 pbrook
}
657 23e39294 pbrook
658 9ee6e8bb pbrook
static void stellaris_sys_init(uint32_t base, qemu_irq irq,
659 eea589cc pbrook
                               stellaris_board_info * board,
660 eea589cc pbrook
                               uint8_t *macaddr)
661 9ee6e8bb pbrook
{
662 9ee6e8bb pbrook
    int iomemtype;
663 9ee6e8bb pbrook
    ssys_state *s;
664 9ee6e8bb pbrook
665 9ee6e8bb pbrook
    s = (ssys_state *)qemu_mallocz(sizeof(ssys_state));
666 9ee6e8bb pbrook
    s->irq = irq;
667 9ee6e8bb pbrook
    s->board = board;
668 eea589cc pbrook
    /* Most devices come preprogrammed with a MAC address in the user data. */
669 eea589cc pbrook
    s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
670 eea589cc pbrook
    s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
671 9ee6e8bb pbrook
672 9ee6e8bb pbrook
    iomemtype = cpu_register_io_memory(0, ssys_readfn,
673 9ee6e8bb pbrook
                                       ssys_writefn, s);
674 9ee6e8bb pbrook
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
675 9ee6e8bb pbrook
    ssys_reset(s);
676 23e39294 pbrook
    register_savevm("stellaris_sys", -1, 1, ssys_save, ssys_load, s);
677 9ee6e8bb pbrook
}
678 9ee6e8bb pbrook
679 9ee6e8bb pbrook
680 9ee6e8bb pbrook
/* I2C controller.  */
681 9ee6e8bb pbrook
682 9ee6e8bb pbrook
typedef struct {
683 1de9610c Paul Brook
    SysBusDevice busdev;
684 9ee6e8bb pbrook
    i2c_bus *bus;
685 9ee6e8bb pbrook
    qemu_irq irq;
686 9ee6e8bb pbrook
    uint32_t msa;
687 9ee6e8bb pbrook
    uint32_t mcs;
688 9ee6e8bb pbrook
    uint32_t mdr;
689 9ee6e8bb pbrook
    uint32_t mtpr;
690 9ee6e8bb pbrook
    uint32_t mimr;
691 9ee6e8bb pbrook
    uint32_t mris;
692 9ee6e8bb pbrook
    uint32_t mcr;
693 9ee6e8bb pbrook
} stellaris_i2c_state;
694 9ee6e8bb pbrook
695 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_BUSY    0x01
696 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_ERROR   0x02
697 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_ADRACK  0x04
698 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_DATACK  0x08
699 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_ARBLST  0x10
700 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_IDLE    0x20
701 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_BUSBSY  0x40
702 9ee6e8bb pbrook
703 9ee6e8bb pbrook
static uint32_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset)
704 9ee6e8bb pbrook
{
705 9ee6e8bb pbrook
    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
706 9ee6e8bb pbrook
707 9ee6e8bb pbrook
    switch (offset) {
708 9ee6e8bb pbrook
    case 0x00: /* MSA */
709 9ee6e8bb pbrook
        return s->msa;
710 9ee6e8bb pbrook
    case 0x04: /* MCS */
711 9ee6e8bb pbrook
        /* We don't emulate timing, so the controller is never busy.  */
712 9ee6e8bb pbrook
        return s->mcs | STELLARIS_I2C_MCS_IDLE;
713 9ee6e8bb pbrook
    case 0x08: /* MDR */
714 9ee6e8bb pbrook
        return s->mdr;
715 9ee6e8bb pbrook
    case 0x0c: /* MTPR */
716 9ee6e8bb pbrook
        return s->mtpr;
717 9ee6e8bb pbrook
    case 0x10: /* MIMR */
718 9ee6e8bb pbrook
        return s->mimr;
719 9ee6e8bb pbrook
    case 0x14: /* MRIS */
720 9ee6e8bb pbrook
        return s->mris;
721 9ee6e8bb pbrook
    case 0x18: /* MMIS */
722 9ee6e8bb pbrook
        return s->mris & s->mimr;
723 9ee6e8bb pbrook
    case 0x20: /* MCR */
724 9ee6e8bb pbrook
        return s->mcr;
725 9ee6e8bb pbrook
    default:
726 2ac71179 Paul Brook
        hw_error("strllaris_i2c_read: Bad offset 0x%x\n", (int)offset);
727 9ee6e8bb pbrook
        return 0;
728 9ee6e8bb pbrook
    }
729 9ee6e8bb pbrook
}
730 9ee6e8bb pbrook
731 9ee6e8bb pbrook
static void stellaris_i2c_update(stellaris_i2c_state *s)
732 9ee6e8bb pbrook
{
733 9ee6e8bb pbrook
    int level;
734 9ee6e8bb pbrook
735 9ee6e8bb pbrook
    level = (s->mris & s->mimr) != 0;
736 9ee6e8bb pbrook
    qemu_set_irq(s->irq, level);
737 9ee6e8bb pbrook
}
738 9ee6e8bb pbrook
739 9ee6e8bb pbrook
static void stellaris_i2c_write(void *opaque, target_phys_addr_t offset,
740 9ee6e8bb pbrook
                                uint32_t value)
741 9ee6e8bb pbrook
{
742 9ee6e8bb pbrook
    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
743 9ee6e8bb pbrook
744 9ee6e8bb pbrook
    switch (offset) {
745 9ee6e8bb pbrook
    case 0x00: /* MSA */
746 9ee6e8bb pbrook
        s->msa = value & 0xff;
747 9ee6e8bb pbrook
        break;
748 9ee6e8bb pbrook
    case 0x04: /* MCS */
749 9ee6e8bb pbrook
        if ((s->mcr & 0x10) == 0) {
750 9ee6e8bb pbrook
            /* Disabled.  Do nothing.  */
751 9ee6e8bb pbrook
            break;
752 9ee6e8bb pbrook
        }
753 9ee6e8bb pbrook
        /* Grab the bus if this is starting a transfer.  */
754 9ee6e8bb pbrook
        if ((value & 2) && (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
755 9ee6e8bb pbrook
            if (i2c_start_transfer(s->bus, s->msa >> 1, s->msa & 1)) {
756 9ee6e8bb pbrook
                s->mcs |= STELLARIS_I2C_MCS_ARBLST;
757 9ee6e8bb pbrook
            } else {
758 9ee6e8bb pbrook
                s->mcs &= ~STELLARIS_I2C_MCS_ARBLST;
759 9ee6e8bb pbrook
                s->mcs |= STELLARIS_I2C_MCS_BUSBSY;
760 9ee6e8bb pbrook
            }
761 9ee6e8bb pbrook
        }
762 9ee6e8bb pbrook
        /* If we don't have the bus then indicate an error.  */
763 9ee6e8bb pbrook
        if (!i2c_bus_busy(s->bus)
764 9ee6e8bb pbrook
                || (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
765 9ee6e8bb pbrook
            s->mcs |= STELLARIS_I2C_MCS_ERROR;
766 9ee6e8bb pbrook
            break;
767 9ee6e8bb pbrook
        }
768 9ee6e8bb pbrook
        s->mcs &= ~STELLARIS_I2C_MCS_ERROR;
769 9ee6e8bb pbrook
        if (value & 1) {
770 9ee6e8bb pbrook
            /* Transfer a byte.  */
771 9ee6e8bb pbrook
            /* TODO: Handle errors.  */
772 9ee6e8bb pbrook
            if (s->msa & 1) {
773 9ee6e8bb pbrook
                /* Recv */
774 9ee6e8bb pbrook
                s->mdr = i2c_recv(s->bus) & 0xff;
775 9ee6e8bb pbrook
            } else {
776 9ee6e8bb pbrook
                /* Send */
777 9ee6e8bb pbrook
                i2c_send(s->bus, s->mdr);
778 9ee6e8bb pbrook
            }
779 9ee6e8bb pbrook
            /* Raise an interrupt.  */
780 9ee6e8bb pbrook
            s->mris |= 1;
781 9ee6e8bb pbrook
        }
782 9ee6e8bb pbrook
        if (value & 4) {
783 9ee6e8bb pbrook
            /* Finish transfer.  */
784 9ee6e8bb pbrook
            i2c_end_transfer(s->bus);
785 9ee6e8bb pbrook
            s->mcs &= ~STELLARIS_I2C_MCS_BUSBSY;
786 9ee6e8bb pbrook
        }
787 9ee6e8bb pbrook
        break;
788 9ee6e8bb pbrook
    case 0x08: /* MDR */
789 9ee6e8bb pbrook
        s->mdr = value & 0xff;
790 9ee6e8bb pbrook
        break;
791 9ee6e8bb pbrook
    case 0x0c: /* MTPR */
792 9ee6e8bb pbrook
        s->mtpr = value & 0xff;
793 9ee6e8bb pbrook
        break;
794 9ee6e8bb pbrook
    case 0x10: /* MIMR */
795 9ee6e8bb pbrook
        s->mimr = 1;
796 9ee6e8bb pbrook
        break;
797 9ee6e8bb pbrook
    case 0x1c: /* MICR */
798 9ee6e8bb pbrook
        s->mris &= ~value;
799 9ee6e8bb pbrook
        break;
800 9ee6e8bb pbrook
    case 0x20: /* MCR */
801 9ee6e8bb pbrook
        if (value & 1)
802 2ac71179 Paul Brook
            hw_error(
803 9ee6e8bb pbrook
                      "stellaris_i2c_write: Loopback not implemented\n");
804 9ee6e8bb pbrook
        if (value & 0x20)
805 2ac71179 Paul Brook
            hw_error(
806 9ee6e8bb pbrook
                      "stellaris_i2c_write: Slave mode not implemented\n");
807 9ee6e8bb pbrook
        s->mcr = value & 0x31;
808 9ee6e8bb pbrook
        break;
809 9ee6e8bb pbrook
    default:
810 2ac71179 Paul Brook
        hw_error("stellaris_i2c_write: Bad offset 0x%x\n",
811 9ee6e8bb pbrook
                  (int)offset);
812 9ee6e8bb pbrook
    }
813 9ee6e8bb pbrook
    stellaris_i2c_update(s);
814 9ee6e8bb pbrook
}
815 9ee6e8bb pbrook
816 9ee6e8bb pbrook
static void stellaris_i2c_reset(stellaris_i2c_state *s)
817 9ee6e8bb pbrook
{
818 9ee6e8bb pbrook
    if (s->mcs & STELLARIS_I2C_MCS_BUSBSY)
819 9ee6e8bb pbrook
        i2c_end_transfer(s->bus);
820 9ee6e8bb pbrook
821 9ee6e8bb pbrook
    s->msa = 0;
822 9ee6e8bb pbrook
    s->mcs = 0;
823 9ee6e8bb pbrook
    s->mdr = 0;
824 9ee6e8bb pbrook
    s->mtpr = 1;
825 9ee6e8bb pbrook
    s->mimr = 0;
826 9ee6e8bb pbrook
    s->mris = 0;
827 9ee6e8bb pbrook
    s->mcr = 0;
828 9ee6e8bb pbrook
    stellaris_i2c_update(s);
829 9ee6e8bb pbrook
}
830 9ee6e8bb pbrook
831 9ee6e8bb pbrook
static CPUReadMemoryFunc *stellaris_i2c_readfn[] = {
832 9ee6e8bb pbrook
   stellaris_i2c_read,
833 9ee6e8bb pbrook
   stellaris_i2c_read,
834 9ee6e8bb pbrook
   stellaris_i2c_read
835 9ee6e8bb pbrook
};
836 9ee6e8bb pbrook
837 9ee6e8bb pbrook
static CPUWriteMemoryFunc *stellaris_i2c_writefn[] = {
838 9ee6e8bb pbrook
   stellaris_i2c_write,
839 9ee6e8bb pbrook
   stellaris_i2c_write,
840 9ee6e8bb pbrook
   stellaris_i2c_write
841 9ee6e8bb pbrook
};
842 9ee6e8bb pbrook
843 23e39294 pbrook
static void stellaris_i2c_save(QEMUFile *f, void *opaque)
844 23e39294 pbrook
{
845 23e39294 pbrook
    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
846 23e39294 pbrook
847 23e39294 pbrook
    qemu_put_be32(f, s->msa);
848 23e39294 pbrook
    qemu_put_be32(f, s->mcs);
849 23e39294 pbrook
    qemu_put_be32(f, s->mdr);
850 23e39294 pbrook
    qemu_put_be32(f, s->mtpr);
851 23e39294 pbrook
    qemu_put_be32(f, s->mimr);
852 23e39294 pbrook
    qemu_put_be32(f, s->mris);
853 23e39294 pbrook
    qemu_put_be32(f, s->mcr);
854 23e39294 pbrook
}
855 23e39294 pbrook
856 23e39294 pbrook
static int stellaris_i2c_load(QEMUFile *f, void *opaque, int version_id)
857 23e39294 pbrook
{
858 23e39294 pbrook
    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
859 23e39294 pbrook
860 23e39294 pbrook
    if (version_id != 1)
861 23e39294 pbrook
        return -EINVAL;
862 23e39294 pbrook
863 23e39294 pbrook
    s->msa = qemu_get_be32(f);
864 23e39294 pbrook
    s->mcs = qemu_get_be32(f);
865 23e39294 pbrook
    s->mdr = qemu_get_be32(f);
866 23e39294 pbrook
    s->mtpr = qemu_get_be32(f);
867 23e39294 pbrook
    s->mimr = qemu_get_be32(f);
868 23e39294 pbrook
    s->mris = qemu_get_be32(f);
869 23e39294 pbrook
    s->mcr = qemu_get_be32(f);
870 23e39294 pbrook
871 23e39294 pbrook
    return 0;
872 23e39294 pbrook
}
873 23e39294 pbrook
874 1de9610c Paul Brook
static void stellaris_i2c_init(SysBusDevice * dev)
875 9ee6e8bb pbrook
{
876 1de9610c Paul Brook
    stellaris_i2c_state *s = FROM_SYSBUS(stellaris_i2c_state, dev);
877 1de9610c Paul Brook
    i2c_bus *bus = i2c_init_bus();
878 9ee6e8bb pbrook
    int iomemtype;
879 9ee6e8bb pbrook
880 1de9610c Paul Brook
    sysbus_init_irq(dev, &s->irq);
881 1de9610c Paul Brook
    qdev_attach_child_bus(&dev->qdev, "i2c", bus);
882 9ee6e8bb pbrook
    s->bus = bus;
883 9ee6e8bb pbrook
884 9ee6e8bb pbrook
    iomemtype = cpu_register_io_memory(0, stellaris_i2c_readfn,
885 9ee6e8bb pbrook
                                       stellaris_i2c_writefn, s);
886 1de9610c Paul Brook
    sysbus_init_mmio(dev, 0x1000, iomemtype);
887 9ee6e8bb pbrook
    /* ??? For now we only implement the master interface.  */
888 9ee6e8bb pbrook
    stellaris_i2c_reset(s);
889 23e39294 pbrook
    register_savevm("stellaris_i2c", -1, 1,
890 23e39294 pbrook
                    stellaris_i2c_save, stellaris_i2c_load, s);
891 9ee6e8bb pbrook
}
892 9ee6e8bb pbrook
893 9ee6e8bb pbrook
/* Analogue to Digital Converter.  This is only partially implemented,
894 9ee6e8bb pbrook
   enough for applications that use a combined ADC and timer tick.  */
895 9ee6e8bb pbrook
896 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_CONTROLLER 0
897 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_COMP       1
898 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_EXTERNAL   4
899 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_TIMER      5
900 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_PWM0       6
901 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_PWM1       7
902 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_PWM2       8
903 9ee6e8bb pbrook
904 9ee6e8bb pbrook
#define STELLARIS_ADC_FIFO_EMPTY    0x0100
905 9ee6e8bb pbrook
#define STELLARIS_ADC_FIFO_FULL     0x1000
906 9ee6e8bb pbrook
907 9ee6e8bb pbrook
typedef struct
908 9ee6e8bb pbrook
{
909 9ee6e8bb pbrook
    uint32_t actss;
910 9ee6e8bb pbrook
    uint32_t ris;
911 9ee6e8bb pbrook
    uint32_t im;
912 9ee6e8bb pbrook
    uint32_t emux;
913 9ee6e8bb pbrook
    uint32_t ostat;
914 9ee6e8bb pbrook
    uint32_t ustat;
915 9ee6e8bb pbrook
    uint32_t sspri;
916 9ee6e8bb pbrook
    uint32_t sac;
917 9ee6e8bb pbrook
    struct {
918 9ee6e8bb pbrook
        uint32_t state;
919 9ee6e8bb pbrook
        uint32_t data[16];
920 9ee6e8bb pbrook
    } fifo[4];
921 9ee6e8bb pbrook
    uint32_t ssmux[4];
922 9ee6e8bb pbrook
    uint32_t ssctl[4];
923 23e39294 pbrook
    uint32_t noise;
924 9ee6e8bb pbrook
    qemu_irq irq;
925 9ee6e8bb pbrook
} stellaris_adc_state;
926 9ee6e8bb pbrook
927 9ee6e8bb pbrook
static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
928 9ee6e8bb pbrook
{
929 9ee6e8bb pbrook
    int tail;
930 9ee6e8bb pbrook
931 9ee6e8bb pbrook
    tail = s->fifo[n].state & 0xf;
932 9ee6e8bb pbrook
    if (s->fifo[n].state & STELLARIS_ADC_FIFO_EMPTY) {
933 9ee6e8bb pbrook
        s->ustat |= 1 << n;
934 9ee6e8bb pbrook
    } else {
935 9ee6e8bb pbrook
        s->fifo[n].state = (s->fifo[n].state & ~0xf) | ((tail + 1) & 0xf);
936 9ee6e8bb pbrook
        s->fifo[n].state &= ~STELLARIS_ADC_FIFO_FULL;
937 9ee6e8bb pbrook
        if (tail + 1 == ((s->fifo[n].state >> 4) & 0xf))
938 9ee6e8bb pbrook
            s->fifo[n].state |= STELLARIS_ADC_FIFO_EMPTY;
939 9ee6e8bb pbrook
    }
940 9ee6e8bb pbrook
    return s->fifo[n].data[tail];
941 9ee6e8bb pbrook
}
942 9ee6e8bb pbrook
943 9ee6e8bb pbrook
static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
944 9ee6e8bb pbrook
                                     uint32_t value)
945 9ee6e8bb pbrook
{
946 9ee6e8bb pbrook
    int head;
947 9ee6e8bb pbrook
948 9ee6e8bb pbrook
    head = (s->fifo[n].state >> 4) & 0xf;
949 9ee6e8bb pbrook
    if (s->fifo[n].state & STELLARIS_ADC_FIFO_FULL) {
950 9ee6e8bb pbrook
        s->ostat |= 1 << n;
951 9ee6e8bb pbrook
        return;
952 9ee6e8bb pbrook
    }
953 9ee6e8bb pbrook
    s->fifo[n].data[head] = value;
954 9ee6e8bb pbrook
    head = (head + 1) & 0xf;
955 9ee6e8bb pbrook
    s->fifo[n].state &= ~STELLARIS_ADC_FIFO_EMPTY;
956 9ee6e8bb pbrook
    s->fifo[n].state = (s->fifo[n].state & ~0xf0) | (head << 4);
957 9ee6e8bb pbrook
    if ((s->fifo[n].state & 0xf) == head)
958 9ee6e8bb pbrook
        s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
959 9ee6e8bb pbrook
}
960 9ee6e8bb pbrook
961 9ee6e8bb pbrook
static void stellaris_adc_update(stellaris_adc_state *s)
962 9ee6e8bb pbrook
{
963 9ee6e8bb pbrook
    int level;
964 9ee6e8bb pbrook
965 9ee6e8bb pbrook
    level = (s->ris & s->im) != 0;
966 9ee6e8bb pbrook
    qemu_set_irq(s->irq, level);
967 9ee6e8bb pbrook
}
968 9ee6e8bb pbrook
969 9ee6e8bb pbrook
static void stellaris_adc_trigger(void *opaque, int irq, int level)
970 9ee6e8bb pbrook
{
971 9ee6e8bb pbrook
    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
972 9ee6e8bb pbrook
973 9ee6e8bb pbrook
    if ((s->actss & 1) == 0) {
974 9ee6e8bb pbrook
        return;
975 9ee6e8bb pbrook
    }
976 9ee6e8bb pbrook
977 23e39294 pbrook
    /* Some applications use the ADC as a random number source, so introduce
978 23e39294 pbrook
       some variation into the signal.  */
979 23e39294 pbrook
    s->noise = s->noise * 314159 + 1;
980 9ee6e8bb pbrook
    /* ??? actual inputs not implemented.  Return an arbitrary value.  */
981 23e39294 pbrook
    stellaris_adc_fifo_write(s, 0, 0x200 + ((s->noise >> 16) & 7));
982 9ee6e8bb pbrook
    s->ris |= 1;
983 9ee6e8bb pbrook
    stellaris_adc_update(s);
984 9ee6e8bb pbrook
}
985 9ee6e8bb pbrook
986 9ee6e8bb pbrook
static void stellaris_adc_reset(stellaris_adc_state *s)
987 9ee6e8bb pbrook
{
988 9ee6e8bb pbrook
    int n;
989 9ee6e8bb pbrook
990 9ee6e8bb pbrook
    for (n = 0; n < 4; n++) {
991 9ee6e8bb pbrook
        s->ssmux[n] = 0;
992 9ee6e8bb pbrook
        s->ssctl[n] = 0;
993 9ee6e8bb pbrook
        s->fifo[n].state = STELLARIS_ADC_FIFO_EMPTY;
994 9ee6e8bb pbrook
    }
995 9ee6e8bb pbrook
}
996 9ee6e8bb pbrook
997 9ee6e8bb pbrook
static uint32_t stellaris_adc_read(void *opaque, target_phys_addr_t offset)
998 9ee6e8bb pbrook
{
999 9ee6e8bb pbrook
    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
1000 9ee6e8bb pbrook
1001 9ee6e8bb pbrook
    /* TODO: Implement this.  */
1002 9ee6e8bb pbrook
    if (offset >= 0x40 && offset < 0xc0) {
1003 9ee6e8bb pbrook
        int n;
1004 9ee6e8bb pbrook
        n = (offset - 0x40) >> 5;
1005 9ee6e8bb pbrook
        switch (offset & 0x1f) {
1006 9ee6e8bb pbrook
        case 0x00: /* SSMUX */
1007 9ee6e8bb pbrook
            return s->ssmux[n];
1008 9ee6e8bb pbrook
        case 0x04: /* SSCTL */
1009 9ee6e8bb pbrook
            return s->ssctl[n];
1010 9ee6e8bb pbrook
        case 0x08: /* SSFIFO */
1011 9ee6e8bb pbrook
            return stellaris_adc_fifo_read(s, n);
1012 9ee6e8bb pbrook
        case 0x0c: /* SSFSTAT */
1013 9ee6e8bb pbrook
            return s->fifo[n].state;
1014 9ee6e8bb pbrook
        default:
1015 9ee6e8bb pbrook
            break;
1016 9ee6e8bb pbrook
        }
1017 9ee6e8bb pbrook
    }
1018 9ee6e8bb pbrook
    switch (offset) {
1019 9ee6e8bb pbrook
    case 0x00: /* ACTSS */
1020 9ee6e8bb pbrook
        return s->actss;
1021 9ee6e8bb pbrook
    case 0x04: /* RIS */
1022 9ee6e8bb pbrook
        return s->ris;
1023 9ee6e8bb pbrook
    case 0x08: /* IM */
1024 9ee6e8bb pbrook
        return s->im;
1025 9ee6e8bb pbrook
    case 0x0c: /* ISC */
1026 9ee6e8bb pbrook
        return s->ris & s->im;
1027 9ee6e8bb pbrook
    case 0x10: /* OSTAT */
1028 9ee6e8bb pbrook
        return s->ostat;
1029 9ee6e8bb pbrook
    case 0x14: /* EMUX */
1030 9ee6e8bb pbrook
        return s->emux;
1031 9ee6e8bb pbrook
    case 0x18: /* USTAT */
1032 9ee6e8bb pbrook
        return s->ustat;
1033 9ee6e8bb pbrook
    case 0x20: /* SSPRI */
1034 9ee6e8bb pbrook
        return s->sspri;
1035 9ee6e8bb pbrook
    case 0x30: /* SAC */
1036 9ee6e8bb pbrook
        return s->sac;
1037 9ee6e8bb pbrook
    default:
1038 2ac71179 Paul Brook
        hw_error("strllaris_adc_read: Bad offset 0x%x\n",
1039 9ee6e8bb pbrook
                  (int)offset);
1040 9ee6e8bb pbrook
        return 0;
1041 9ee6e8bb pbrook
    }
1042 9ee6e8bb pbrook
}
1043 9ee6e8bb pbrook
1044 9ee6e8bb pbrook
static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
1045 9ee6e8bb pbrook
                                uint32_t value)
1046 9ee6e8bb pbrook
{
1047 9ee6e8bb pbrook
    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
1048 9ee6e8bb pbrook
1049 9ee6e8bb pbrook
    /* TODO: Implement this.  */
1050 9ee6e8bb pbrook
    if (offset >= 0x40 && offset < 0xc0) {
1051 9ee6e8bb pbrook
        int n;
1052 9ee6e8bb pbrook
        n = (offset - 0x40) >> 5;
1053 9ee6e8bb pbrook
        switch (offset & 0x1f) {
1054 9ee6e8bb pbrook
        case 0x00: /* SSMUX */
1055 9ee6e8bb pbrook
            s->ssmux[n] = value & 0x33333333;
1056 9ee6e8bb pbrook
            return;
1057 9ee6e8bb pbrook
        case 0x04: /* SSCTL */
1058 9ee6e8bb pbrook
            if (value != 6) {
1059 2ac71179 Paul Brook
                hw_error("ADC: Unimplemented sequence %x\n",
1060 9ee6e8bb pbrook
                          value);
1061 9ee6e8bb pbrook
            }
1062 9ee6e8bb pbrook
            s->ssctl[n] = value;
1063 9ee6e8bb pbrook
            return;
1064 9ee6e8bb pbrook
        default:
1065 9ee6e8bb pbrook
            break;
1066 9ee6e8bb pbrook
        }
1067 9ee6e8bb pbrook
    }
1068 9ee6e8bb pbrook
    switch (offset) {
1069 9ee6e8bb pbrook
    case 0x00: /* ACTSS */
1070 9ee6e8bb pbrook
        s->actss = value & 0xf;
1071 9ee6e8bb pbrook
        if (value & 0xe) {
1072 2ac71179 Paul Brook
            hw_error("Not implemented:  ADC sequencers 1-3\n");
1073 9ee6e8bb pbrook
        }
1074 9ee6e8bb pbrook
        break;
1075 9ee6e8bb pbrook
    case 0x08: /* IM */
1076 9ee6e8bb pbrook
        s->im = value;
1077 9ee6e8bb pbrook
        break;
1078 9ee6e8bb pbrook
    case 0x0c: /* ISC */
1079 9ee6e8bb pbrook
        s->ris &= ~value;
1080 9ee6e8bb pbrook
        break;
1081 9ee6e8bb pbrook
    case 0x10: /* OSTAT */
1082 9ee6e8bb pbrook
        s->ostat &= ~value;
1083 9ee6e8bb pbrook
        break;
1084 9ee6e8bb pbrook
    case 0x14: /* EMUX */
1085 9ee6e8bb pbrook
        s->emux = value;
1086 9ee6e8bb pbrook
        break;
1087 9ee6e8bb pbrook
    case 0x18: /* USTAT */
1088 9ee6e8bb pbrook
        s->ustat &= ~value;
1089 9ee6e8bb pbrook
        break;
1090 9ee6e8bb pbrook
    case 0x20: /* SSPRI */
1091 9ee6e8bb pbrook
        s->sspri = value;
1092 9ee6e8bb pbrook
        break;
1093 9ee6e8bb pbrook
    case 0x28: /* PSSI */
1094 2ac71179 Paul Brook
        hw_error("Not implemented:  ADC sample initiate\n");
1095 9ee6e8bb pbrook
        break;
1096 9ee6e8bb pbrook
    case 0x30: /* SAC */
1097 9ee6e8bb pbrook
        s->sac = value;
1098 9ee6e8bb pbrook
        break;
1099 9ee6e8bb pbrook
    default:
1100 2ac71179 Paul Brook
        hw_error("stellaris_adc_write: Bad offset 0x%x\n", (int)offset);
1101 9ee6e8bb pbrook
    }
1102 9ee6e8bb pbrook
    stellaris_adc_update(s);
1103 9ee6e8bb pbrook
}
1104 9ee6e8bb pbrook
1105 9ee6e8bb pbrook
static CPUReadMemoryFunc *stellaris_adc_readfn[] = {
1106 9ee6e8bb pbrook
   stellaris_adc_read,
1107 9ee6e8bb pbrook
   stellaris_adc_read,
1108 9ee6e8bb pbrook
   stellaris_adc_read
1109 9ee6e8bb pbrook
};
1110 9ee6e8bb pbrook
1111 9ee6e8bb pbrook
static CPUWriteMemoryFunc *stellaris_adc_writefn[] = {
1112 9ee6e8bb pbrook
   stellaris_adc_write,
1113 9ee6e8bb pbrook
   stellaris_adc_write,
1114 9ee6e8bb pbrook
   stellaris_adc_write
1115 9ee6e8bb pbrook
};
1116 9ee6e8bb pbrook
1117 23e39294 pbrook
static void stellaris_adc_save(QEMUFile *f, void *opaque)
1118 23e39294 pbrook
{
1119 23e39294 pbrook
    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
1120 23e39294 pbrook
    int i;
1121 23e39294 pbrook
    int j;
1122 23e39294 pbrook
1123 23e39294 pbrook
    qemu_put_be32(f, s->actss);
1124 23e39294 pbrook
    qemu_put_be32(f, s->ris);
1125 23e39294 pbrook
    qemu_put_be32(f, s->im);
1126 23e39294 pbrook
    qemu_put_be32(f, s->emux);
1127 23e39294 pbrook
    qemu_put_be32(f, s->ostat);
1128 23e39294 pbrook
    qemu_put_be32(f, s->ustat);
1129 23e39294 pbrook
    qemu_put_be32(f, s->sspri);
1130 23e39294 pbrook
    qemu_put_be32(f, s->sac);
1131 23e39294 pbrook
    for (i = 0; i < 4; i++) {
1132 23e39294 pbrook
        qemu_put_be32(f, s->fifo[i].state);
1133 23e39294 pbrook
        for (j = 0; j < 16; j++) {
1134 23e39294 pbrook
            qemu_put_be32(f, s->fifo[i].data[j]);
1135 23e39294 pbrook
        }
1136 23e39294 pbrook
        qemu_put_be32(f, s->ssmux[i]);
1137 23e39294 pbrook
        qemu_put_be32(f, s->ssctl[i]);
1138 23e39294 pbrook
    }
1139 23e39294 pbrook
    qemu_put_be32(f, s->noise);
1140 23e39294 pbrook
}
1141 23e39294 pbrook
1142 23e39294 pbrook
static int stellaris_adc_load(QEMUFile *f, void *opaque, int version_id)
1143 23e39294 pbrook
{
1144 23e39294 pbrook
    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
1145 23e39294 pbrook
    int i;
1146 23e39294 pbrook
    int j;
1147 23e39294 pbrook
1148 23e39294 pbrook
    if (version_id != 1)
1149 23e39294 pbrook
        return -EINVAL;
1150 23e39294 pbrook
1151 23e39294 pbrook
    s->actss = qemu_get_be32(f);
1152 23e39294 pbrook
    s->ris = qemu_get_be32(f);
1153 23e39294 pbrook
    s->im = qemu_get_be32(f);
1154 23e39294 pbrook
    s->emux = qemu_get_be32(f);
1155 23e39294 pbrook
    s->ostat = qemu_get_be32(f);
1156 23e39294 pbrook
    s->ustat = qemu_get_be32(f);
1157 23e39294 pbrook
    s->sspri = qemu_get_be32(f);
1158 23e39294 pbrook
    s->sac = qemu_get_be32(f);
1159 23e39294 pbrook
    for (i = 0; i < 4; i++) {
1160 23e39294 pbrook
        s->fifo[i].state = qemu_get_be32(f);
1161 23e39294 pbrook
        for (j = 0; j < 16; j++) {
1162 23e39294 pbrook
            s->fifo[i].data[j] = qemu_get_be32(f);
1163 23e39294 pbrook
        }
1164 23e39294 pbrook
        s->ssmux[i] = qemu_get_be32(f);
1165 23e39294 pbrook
        s->ssctl[i] = qemu_get_be32(f);
1166 23e39294 pbrook
    }
1167 23e39294 pbrook
    s->noise = qemu_get_be32(f);
1168 23e39294 pbrook
1169 23e39294 pbrook
    return 0;
1170 23e39294 pbrook
}
1171 23e39294 pbrook
1172 9ee6e8bb pbrook
static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq irq)
1173 9ee6e8bb pbrook
{
1174 9ee6e8bb pbrook
    stellaris_adc_state *s;
1175 9ee6e8bb pbrook
    int iomemtype;
1176 9ee6e8bb pbrook
    qemu_irq *qi;
1177 9ee6e8bb pbrook
1178 9ee6e8bb pbrook
    s = (stellaris_adc_state *)qemu_mallocz(sizeof(stellaris_adc_state));
1179 9ee6e8bb pbrook
    s->irq = irq;
1180 9ee6e8bb pbrook
1181 9ee6e8bb pbrook
    iomemtype = cpu_register_io_memory(0, stellaris_adc_readfn,
1182 9ee6e8bb pbrook
                                       stellaris_adc_writefn, s);
1183 9ee6e8bb pbrook
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
1184 9ee6e8bb pbrook
    stellaris_adc_reset(s);
1185 9ee6e8bb pbrook
    qi = qemu_allocate_irqs(stellaris_adc_trigger, s, 1);
1186 23e39294 pbrook
    register_savevm("stellaris_adc", -1, 1,
1187 23e39294 pbrook
                    stellaris_adc_save, stellaris_adc_load, s);
1188 9ee6e8bb pbrook
    return qi[0];
1189 9ee6e8bb pbrook
}
1190 9ee6e8bb pbrook
1191 775616c3 pbrook
/* Some boards have both an OLED controller and SD card connected to
1192 775616c3 pbrook
   the same SSI port, with the SD card chip select connected to a
1193 775616c3 pbrook
   GPIO pin.  Technically the OLED chip select is connected to the SSI
1194 775616c3 pbrook
   Fss pin.  We do not bother emulating that as both devices should
1195 775616c3 pbrook
   never be selected simultaneously, and our OLED controller ignores stray
1196 775616c3 pbrook
   0xff commands that occur when deselecting the SD card.  */
1197 775616c3 pbrook
1198 775616c3 pbrook
typedef struct {
1199 775616c3 pbrook
    ssi_xfer_cb xfer_cb[2];
1200 775616c3 pbrook
    void *opaque[2];
1201 775616c3 pbrook
    qemu_irq irq;
1202 775616c3 pbrook
    int current_dev;
1203 775616c3 pbrook
} stellaris_ssi_bus_state;
1204 775616c3 pbrook
1205 775616c3 pbrook
static void stellaris_ssi_bus_select(void *opaque, int irq, int level)
1206 775616c3 pbrook
{
1207 775616c3 pbrook
    stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
1208 775616c3 pbrook
1209 775616c3 pbrook
    s->current_dev = level;
1210 775616c3 pbrook
}
1211 775616c3 pbrook
1212 775616c3 pbrook
static int stellaris_ssi_bus_xfer(void *opaque, int val)
1213 775616c3 pbrook
{
1214 775616c3 pbrook
    stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
1215 775616c3 pbrook
1216 775616c3 pbrook
    return s->xfer_cb[s->current_dev](s->opaque[s->current_dev], val);
1217 775616c3 pbrook
}
1218 775616c3 pbrook
1219 23e39294 pbrook
static void stellaris_ssi_bus_save(QEMUFile *f, void *opaque)
1220 23e39294 pbrook
{
1221 23e39294 pbrook
    stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
1222 23e39294 pbrook
1223 23e39294 pbrook
    qemu_put_be32(f, s->current_dev);
1224 23e39294 pbrook
}
1225 23e39294 pbrook
1226 23e39294 pbrook
static int stellaris_ssi_bus_load(QEMUFile *f, void *opaque, int version_id)
1227 23e39294 pbrook
{
1228 23e39294 pbrook
    stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
1229 23e39294 pbrook
1230 23e39294 pbrook
    if (version_id != 1)
1231 23e39294 pbrook
        return -EINVAL;
1232 23e39294 pbrook
1233 23e39294 pbrook
    s->current_dev = qemu_get_be32(f);
1234 23e39294 pbrook
1235 23e39294 pbrook
    return 0;
1236 23e39294 pbrook
}
1237 23e39294 pbrook
1238 775616c3 pbrook
static void *stellaris_ssi_bus_init(qemu_irq *irqp,
1239 775616c3 pbrook
                                    ssi_xfer_cb cb0, void *opaque0,
1240 775616c3 pbrook
                                    ssi_xfer_cb cb1, void *opaque1)
1241 775616c3 pbrook
{
1242 775616c3 pbrook
    qemu_irq *qi;
1243 775616c3 pbrook
    stellaris_ssi_bus_state *s;
1244 775616c3 pbrook
1245 775616c3 pbrook
    s = (stellaris_ssi_bus_state *)qemu_mallocz(sizeof(stellaris_ssi_bus_state));
1246 775616c3 pbrook
    s->xfer_cb[0] = cb0;
1247 775616c3 pbrook
    s->opaque[0] = opaque0;
1248 775616c3 pbrook
    s->xfer_cb[1] = cb1;
1249 775616c3 pbrook
    s->opaque[1] = opaque1;
1250 775616c3 pbrook
    qi = qemu_allocate_irqs(stellaris_ssi_bus_select, s, 1);
1251 775616c3 pbrook
    *irqp = *qi;
1252 23e39294 pbrook
    register_savevm("stellaris_ssi_bus", -1, 1,
1253 23e39294 pbrook
                    stellaris_ssi_bus_save, stellaris_ssi_bus_load, s);
1254 775616c3 pbrook
    return s;
1255 775616c3 pbrook
}
1256 775616c3 pbrook
1257 9ee6e8bb pbrook
/* Board init.  */
1258 9ee6e8bb pbrook
static stellaris_board_info stellaris_boards[] = {
1259 9ee6e8bb pbrook
  { "LM3S811EVB",
1260 9ee6e8bb pbrook
    0,
1261 9ee6e8bb pbrook
    0x0032000e,
1262 9ee6e8bb pbrook
    0x001f001f, /* dc0 */
1263 9ee6e8bb pbrook
    0x001132bf,
1264 9ee6e8bb pbrook
    0x01071013,
1265 9ee6e8bb pbrook
    0x3f0f01ff,
1266 9ee6e8bb pbrook
    0x0000001f,
1267 cf0dbb21 pbrook
    BP_OLED_I2C
1268 9ee6e8bb pbrook
  },
1269 9ee6e8bb pbrook
  { "LM3S6965EVB",
1270 9ee6e8bb pbrook
    0x10010002,
1271 9ee6e8bb pbrook
    0x1073402e,
1272 9ee6e8bb pbrook
    0x00ff007f, /* dc0 */
1273 9ee6e8bb pbrook
    0x001133ff,
1274 9ee6e8bb pbrook
    0x030f5317,
1275 9ee6e8bb pbrook
    0x0f0f87ff,
1276 9ee6e8bb pbrook
    0x5000007f,
1277 cf0dbb21 pbrook
    BP_OLED_SSI | BP_GAMEPAD
1278 9ee6e8bb pbrook
  }
1279 9ee6e8bb pbrook
};
1280 9ee6e8bb pbrook
1281 9ee6e8bb pbrook
static void stellaris_init(const char *kernel_filename, const char *cpu_model,
1282 3023f332 aliguori
                           stellaris_board_info *board)
1283 9ee6e8bb pbrook
{
1284 9ee6e8bb pbrook
    static const int uart_irq[] = {5, 6, 33, 34};
1285 9ee6e8bb pbrook
    static const int timer_irq[] = {19, 21, 23, 35};
1286 9ee6e8bb pbrook
    static const uint32_t gpio_addr[7] =
1287 9ee6e8bb pbrook
      { 0x40004000, 0x40005000, 0x40006000, 0x40007000,
1288 9ee6e8bb pbrook
        0x40024000, 0x40025000, 0x40026000};
1289 9ee6e8bb pbrook
    static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
1290 9ee6e8bb pbrook
1291 9ee6e8bb pbrook
    qemu_irq *pic;
1292 f3d8b1eb aurel32
    qemu_irq *gpio_in[7];
1293 f3d8b1eb aurel32
    qemu_irq *gpio_out[7];
1294 9ee6e8bb pbrook
    qemu_irq adc;
1295 9ee6e8bb pbrook
    int sram_size;
1296 9ee6e8bb pbrook
    int flash_size;
1297 9ee6e8bb pbrook
    i2c_bus *i2c;
1298 9ee6e8bb pbrook
    int i;
1299 9ee6e8bb pbrook
1300 9ee6e8bb pbrook
    flash_size = ((board->dc0 & 0xffff) + 1) << 1;
1301 9ee6e8bb pbrook
    sram_size = (board->dc0 >> 18) + 1;
1302 9ee6e8bb pbrook
    pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model);
1303 9ee6e8bb pbrook
1304 9ee6e8bb pbrook
    if (board->dc1 & (1 << 16)) {
1305 9ee6e8bb pbrook
        adc = stellaris_adc_init(0x40038000, pic[14]);
1306 9ee6e8bb pbrook
    } else {
1307 9ee6e8bb pbrook
        adc = NULL;
1308 9ee6e8bb pbrook
    }
1309 9ee6e8bb pbrook
    for (i = 0; i < 4; i++) {
1310 9ee6e8bb pbrook
        if (board->dc2 & (0x10000 << i)) {
1311 9ee6e8bb pbrook
            stellaris_gptm_init(0x40030000 + i * 0x1000,
1312 9ee6e8bb pbrook
                                pic[timer_irq[i]], adc);
1313 9ee6e8bb pbrook
        }
1314 9ee6e8bb pbrook
    }
1315 9ee6e8bb pbrook
1316 eea589cc pbrook
    stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr);
1317 9ee6e8bb pbrook
1318 9ee6e8bb pbrook
    for (i = 0; i < 7; i++) {
1319 9ee6e8bb pbrook
        if (board->dc4 & (1 << i)) {
1320 9ee6e8bb pbrook
            gpio_in[i] = pl061_init(gpio_addr[i], pic[gpio_irq[i]],
1321 9ee6e8bb pbrook
                                    &gpio_out[i]);
1322 9ee6e8bb pbrook
        }
1323 9ee6e8bb pbrook
    }
1324 9ee6e8bb pbrook
1325 9ee6e8bb pbrook
    if (board->dc2 & (1 << 12)) {
1326 1de9610c Paul Brook
        DeviceState *dev;
1327 1de9610c Paul Brook
        dev = sysbus_create_simple("stellaris-i2c", 0x40020000, pic[8]);
1328 1de9610c Paul Brook
        i2c = qdev_get_child_bus(dev, "i2c");
1329 cf0dbb21 pbrook
        if (board->peripherals & BP_OLED_I2C) {
1330 d2199005 Paul Brook
            i2c_create_slave(i2c, "ssd0303", 0x3d);
1331 9ee6e8bb pbrook
        }
1332 9ee6e8bb pbrook
    }
1333 9ee6e8bb pbrook
1334 9ee6e8bb pbrook
    for (i = 0; i < 4; i++) {
1335 9ee6e8bb pbrook
        if (board->dc2 & (1 << i)) {
1336 a7d518a6 Paul Brook
            sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000,
1337 a7d518a6 Paul Brook
                                 pic[uart_irq[i]]);
1338 9ee6e8bb pbrook
        }
1339 9ee6e8bb pbrook
    }
1340 9ee6e8bb pbrook
    if (board->dc2 & (1 << 4)) {
1341 cf0dbb21 pbrook
        if (board->peripherals & BP_OLED_SSI) {
1342 9ee6e8bb pbrook
            void * oled;
1343 775616c3 pbrook
            void * sd;
1344 775616c3 pbrook
            void *ssi_bus;
1345 e4bcb14c ths
            int index;
1346 775616c3 pbrook
1347 3023f332 aliguori
            oled = ssd0323_init(&gpio_out[GPIO_C][7]);
1348 e4bcb14c ths
            index = drive_get_index(IF_SD, 0, 0);
1349 e4bcb14c ths
            sd = ssi_sd_init(drives_table[index].bdrv);
1350 775616c3 pbrook
1351 775616c3 pbrook
            ssi_bus = stellaris_ssi_bus_init(&gpio_out[GPIO_D][0],
1352 775616c3 pbrook
                                             ssi_sd_xfer, sd,
1353 775616c3 pbrook
                                             ssd0323_xfer_ssi, oled);
1354 775616c3 pbrook
1355 775616c3 pbrook
            pl022_init(0x40008000, pic[7], stellaris_ssi_bus_xfer, ssi_bus);
1356 775616c3 pbrook
            /* Make sure the select pin is high.  */
1357 775616c3 pbrook
            qemu_irq_raise(gpio_out[GPIO_D][0]);
1358 9ee6e8bb pbrook
        } else {
1359 9ee6e8bb pbrook
            pl022_init(0x40008000, pic[7], NULL, NULL);
1360 9ee6e8bb pbrook
        }
1361 9ee6e8bb pbrook
    }
1362 a5580466 Paul Brook
    if (board->dc4 & (1 << 28)) {
1363 a5580466 Paul Brook
        DeviceState *enet;
1364 a5580466 Paul Brook
1365 a5580466 Paul Brook
        qemu_check_nic_model(&nd_table[0], "stellaris");
1366 a5580466 Paul Brook
1367 a5580466 Paul Brook
        enet = qdev_create(NULL, "stellaris_enet");
1368 a5580466 Paul Brook
        qdev_set_netdev(enet, &nd_table[0]);
1369 a5580466 Paul Brook
        qdev_init(enet);
1370 a5580466 Paul Brook
        sysbus_mmio_map(sysbus_from_qdev(enet), 0, 0x40048000);
1371 a5580466 Paul Brook
        sysbus_connect_irq(sysbus_from_qdev(enet), 0, pic[42]);
1372 a5580466 Paul Brook
    }
1373 cf0dbb21 pbrook
    if (board->peripherals & BP_GAMEPAD) {
1374 cf0dbb21 pbrook
        qemu_irq gpad_irq[5];
1375 cf0dbb21 pbrook
        static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
1376 cf0dbb21 pbrook
1377 cf0dbb21 pbrook
        gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */
1378 cf0dbb21 pbrook
        gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */
1379 cf0dbb21 pbrook
        gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */
1380 cf0dbb21 pbrook
        gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */
1381 cf0dbb21 pbrook
        gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */
1382 cf0dbb21 pbrook
1383 cf0dbb21 pbrook
        stellaris_gamepad_init(5, gpad_irq, gpad_keycode);
1384 cf0dbb21 pbrook
    }
1385 9ee6e8bb pbrook
}
1386 9ee6e8bb pbrook
1387 9ee6e8bb pbrook
/* FIXME: Figure out how to generate these from stellaris_boards.  */
1388 fbe1b595 Paul Brook
static void lm3s811evb_init(ram_addr_t ram_size,
1389 3023f332 aliguori
                     const char *boot_device,
1390 9ee6e8bb pbrook
                     const char *kernel_filename, const char *kernel_cmdline,
1391 9ee6e8bb pbrook
                     const char *initrd_filename, const char *cpu_model)
1392 9ee6e8bb pbrook
{
1393 3023f332 aliguori
    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]);
1394 9ee6e8bb pbrook
}
1395 9ee6e8bb pbrook
1396 fbe1b595 Paul Brook
static void lm3s6965evb_init(ram_addr_t ram_size,
1397 3023f332 aliguori
                     const char *boot_device,
1398 9ee6e8bb pbrook
                     const char *kernel_filename, const char *kernel_cmdline,
1399 9ee6e8bb pbrook
                     const char *initrd_filename, const char *cpu_model)
1400 9ee6e8bb pbrook
{
1401 3023f332 aliguori
    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]);
1402 9ee6e8bb pbrook
}
1403 9ee6e8bb pbrook
1404 9ee6e8bb pbrook
QEMUMachine lm3s811evb_machine = {
1405 4b32e168 aliguori
    .name = "lm3s811evb",
1406 4b32e168 aliguori
    .desc = "Stellaris LM3S811EVB",
1407 4b32e168 aliguori
    .init = lm3s811evb_init,
1408 9ee6e8bb pbrook
};
1409 9ee6e8bb pbrook
1410 9ee6e8bb pbrook
QEMUMachine lm3s6965evb_machine = {
1411 4b32e168 aliguori
    .name = "lm3s6965evb",
1412 4b32e168 aliguori
    .desc = "Stellaris LM3S6965EVB",
1413 4b32e168 aliguori
    .init = lm3s6965evb_init,
1414 9ee6e8bb pbrook
};
1415 1de9610c Paul Brook
1416 1de9610c Paul Brook
static void stellaris_register_devices(void)
1417 1de9610c Paul Brook
{
1418 1de9610c Paul Brook
    sysbus_register_dev("stellaris-i2c", sizeof(stellaris_i2c_state),
1419 1de9610c Paul Brook
                        stellaris_i2c_init);
1420 1de9610c Paul Brook
}
1421 1de9610c Paul Brook
1422 1de9610c Paul Brook
device_init(stellaris_register_devices)