Statistics
| Branch: | Revision:

root / hw / stellaris.c @ 23e39294

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