Statistics
| Branch: | Revision:

root / hw / stellaris.c @ 746d6de7

History | View | Annotate | Download (31.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 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 9ee6e8bb pbrook
static void stellaris_gptm_init(uint32_t base, qemu_irq irq, qemu_irq trigger)
290 9ee6e8bb pbrook
{
291 9ee6e8bb pbrook
    int iomemtype;
292 9ee6e8bb pbrook
    gptm_state *s;
293 9ee6e8bb pbrook
294 9ee6e8bb pbrook
    s = (gptm_state *)qemu_mallocz(sizeof(gptm_state));
295 9ee6e8bb pbrook
    s->base = base;
296 9ee6e8bb pbrook
    s->irq = irq;
297 9ee6e8bb pbrook
    s->trigger = trigger;
298 9ee6e8bb pbrook
    s->opaque[0] = s->opaque[1] = s;
299 9ee6e8bb pbrook
300 9ee6e8bb pbrook
    iomemtype = cpu_register_io_memory(0, gptm_readfn,
301 9ee6e8bb pbrook
                                       gptm_writefn, s);
302 9ee6e8bb pbrook
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
303 9ee6e8bb pbrook
    s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]);
304 9ee6e8bb pbrook
    s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]);
305 9ee6e8bb pbrook
    /* ??? Save/restore.  */
306 9ee6e8bb pbrook
}
307 9ee6e8bb pbrook
308 9ee6e8bb pbrook
309 9ee6e8bb pbrook
/* System controller.  */
310 9ee6e8bb pbrook
311 9ee6e8bb pbrook
typedef struct {
312 9ee6e8bb pbrook
    uint32_t base;
313 9ee6e8bb pbrook
    uint32_t pborctl;
314 9ee6e8bb pbrook
    uint32_t ldopctl;
315 9ee6e8bb pbrook
    uint32_t int_status;
316 9ee6e8bb pbrook
    uint32_t int_mask;
317 9ee6e8bb pbrook
    uint32_t resc;
318 9ee6e8bb pbrook
    uint32_t rcc;
319 9ee6e8bb pbrook
    uint32_t rcgc[3];
320 9ee6e8bb pbrook
    uint32_t scgc[3];
321 9ee6e8bb pbrook
    uint32_t dcgc[3];
322 9ee6e8bb pbrook
    uint32_t clkvclr;
323 9ee6e8bb pbrook
    uint32_t ldoarst;
324 eea589cc pbrook
    uint32_t user0;
325 eea589cc pbrook
    uint32_t user1;
326 9ee6e8bb pbrook
    qemu_irq irq;
327 9ee6e8bb pbrook
    stellaris_board_info *board;
328 9ee6e8bb pbrook
} ssys_state;
329 9ee6e8bb pbrook
330 9ee6e8bb pbrook
static void ssys_update(ssys_state *s)
331 9ee6e8bb pbrook
{
332 9ee6e8bb pbrook
  qemu_set_irq(s->irq, (s->int_status & s->int_mask) != 0);
333 9ee6e8bb pbrook
}
334 9ee6e8bb pbrook
335 9ee6e8bb pbrook
static uint32_t pllcfg_sandstorm[16] = {
336 9ee6e8bb pbrook
    0x31c0, /* 1 Mhz */
337 9ee6e8bb pbrook
    0x1ae0, /* 1.8432 Mhz */
338 9ee6e8bb pbrook
    0x18c0, /* 2 Mhz */
339 9ee6e8bb pbrook
    0xd573, /* 2.4576 Mhz */
340 9ee6e8bb pbrook
    0x37a6, /* 3.57954 Mhz */
341 9ee6e8bb pbrook
    0x1ae2, /* 3.6864 Mhz */
342 9ee6e8bb pbrook
    0x0c40, /* 4 Mhz */
343 9ee6e8bb pbrook
    0x98bc, /* 4.906 Mhz */
344 9ee6e8bb pbrook
    0x935b, /* 4.9152 Mhz */
345 9ee6e8bb pbrook
    0x09c0, /* 5 Mhz */
346 9ee6e8bb pbrook
    0x4dee, /* 5.12 Mhz */
347 9ee6e8bb pbrook
    0x0c41, /* 6 Mhz */
348 9ee6e8bb pbrook
    0x75db, /* 6.144 Mhz */
349 9ee6e8bb pbrook
    0x1ae6, /* 7.3728 Mhz */
350 9ee6e8bb pbrook
    0x0600, /* 8 Mhz */
351 9ee6e8bb pbrook
    0x585b /* 8.192 Mhz */
352 9ee6e8bb pbrook
};
353 9ee6e8bb pbrook
354 9ee6e8bb pbrook
static uint32_t pllcfg_fury[16] = {
355 9ee6e8bb pbrook
    0x3200, /* 1 Mhz */
356 9ee6e8bb pbrook
    0x1b20, /* 1.8432 Mhz */
357 9ee6e8bb pbrook
    0x1900, /* 2 Mhz */
358 9ee6e8bb pbrook
    0xf42b, /* 2.4576 Mhz */
359 9ee6e8bb pbrook
    0x37e3, /* 3.57954 Mhz */
360 9ee6e8bb pbrook
    0x1b21, /* 3.6864 Mhz */
361 9ee6e8bb pbrook
    0x0c80, /* 4 Mhz */
362 9ee6e8bb pbrook
    0x98ee, /* 4.906 Mhz */
363 9ee6e8bb pbrook
    0xd5b4, /* 4.9152 Mhz */
364 9ee6e8bb pbrook
    0x0a00, /* 5 Mhz */
365 9ee6e8bb pbrook
    0x4e27, /* 5.12 Mhz */
366 9ee6e8bb pbrook
    0x1902, /* 6 Mhz */
367 9ee6e8bb pbrook
    0xec1c, /* 6.144 Mhz */
368 9ee6e8bb pbrook
    0x1b23, /* 7.3728 Mhz */
369 9ee6e8bb pbrook
    0x0640, /* 8 Mhz */
370 9ee6e8bb pbrook
    0xb11c /* 8.192 Mhz */
371 9ee6e8bb pbrook
};
372 9ee6e8bb pbrook
373 9ee6e8bb pbrook
static uint32_t ssys_read(void *opaque, target_phys_addr_t offset)
374 9ee6e8bb pbrook
{
375 9ee6e8bb pbrook
    ssys_state *s = (ssys_state *)opaque;
376 9ee6e8bb pbrook
377 9ee6e8bb pbrook
    offset -= s->base;
378 9ee6e8bb pbrook
    switch (offset) {
379 9ee6e8bb pbrook
    case 0x000: /* DID0 */
380 9ee6e8bb pbrook
        return s->board->did0;
381 9ee6e8bb pbrook
    case 0x004: /* DID1 */
382 9ee6e8bb pbrook
        return s->board->did1;
383 9ee6e8bb pbrook
    case 0x008: /* DC0 */
384 9ee6e8bb pbrook
        return s->board->dc0;
385 9ee6e8bb pbrook
    case 0x010: /* DC1 */
386 9ee6e8bb pbrook
        return s->board->dc1;
387 9ee6e8bb pbrook
    case 0x014: /* DC2 */
388 9ee6e8bb pbrook
        return s->board->dc2;
389 9ee6e8bb pbrook
    case 0x018: /* DC3 */
390 9ee6e8bb pbrook
        return s->board->dc3;
391 9ee6e8bb pbrook
    case 0x01c: /* DC4 */
392 9ee6e8bb pbrook
        return s->board->dc4;
393 9ee6e8bb pbrook
    case 0x030: /* PBORCTL */
394 9ee6e8bb pbrook
        return s->pborctl;
395 9ee6e8bb pbrook
    case 0x034: /* LDOPCTL */
396 9ee6e8bb pbrook
        return s->ldopctl;
397 9ee6e8bb pbrook
    case 0x040: /* SRCR0 */
398 9ee6e8bb pbrook
        return 0;
399 9ee6e8bb pbrook
    case 0x044: /* SRCR1 */
400 9ee6e8bb pbrook
        return 0;
401 9ee6e8bb pbrook
    case 0x048: /* SRCR2 */
402 9ee6e8bb pbrook
        return 0;
403 9ee6e8bb pbrook
    case 0x050: /* RIS */
404 9ee6e8bb pbrook
        return s->int_status;
405 9ee6e8bb pbrook
    case 0x054: /* IMC */
406 9ee6e8bb pbrook
        return s->int_mask;
407 9ee6e8bb pbrook
    case 0x058: /* MISC */
408 9ee6e8bb pbrook
        return s->int_status & s->int_mask;
409 9ee6e8bb pbrook
    case 0x05c: /* RESC */
410 9ee6e8bb pbrook
        return s->resc;
411 9ee6e8bb pbrook
    case 0x060: /* RCC */
412 9ee6e8bb pbrook
        return s->rcc;
413 9ee6e8bb pbrook
    case 0x064: /* PLLCFG */
414 9ee6e8bb pbrook
        {
415 9ee6e8bb pbrook
            int xtal;
416 9ee6e8bb pbrook
            xtal = (s->rcc >> 6) & 0xf;
417 9ee6e8bb pbrook
            if (s->board->did0 & (1 << 16)) {
418 9ee6e8bb pbrook
                return pllcfg_fury[xtal];
419 9ee6e8bb pbrook
            } else {
420 9ee6e8bb pbrook
                return pllcfg_sandstorm[xtal];
421 9ee6e8bb pbrook
            }
422 9ee6e8bb pbrook
        }
423 9ee6e8bb pbrook
    case 0x100: /* RCGC0 */
424 9ee6e8bb pbrook
        return s->rcgc[0];
425 9ee6e8bb pbrook
    case 0x104: /* RCGC1 */
426 9ee6e8bb pbrook
        return s->rcgc[1];
427 9ee6e8bb pbrook
    case 0x108: /* RCGC2 */
428 9ee6e8bb pbrook
        return s->rcgc[2];
429 9ee6e8bb pbrook
    case 0x110: /* SCGC0 */
430 9ee6e8bb pbrook
        return s->scgc[0];
431 9ee6e8bb pbrook
    case 0x114: /* SCGC1 */
432 9ee6e8bb pbrook
        return s->scgc[1];
433 9ee6e8bb pbrook
    case 0x118: /* SCGC2 */
434 9ee6e8bb pbrook
        return s->scgc[2];
435 9ee6e8bb pbrook
    case 0x120: /* DCGC0 */
436 9ee6e8bb pbrook
        return s->dcgc[0];
437 9ee6e8bb pbrook
    case 0x124: /* DCGC1 */
438 9ee6e8bb pbrook
        return s->dcgc[1];
439 9ee6e8bb pbrook
    case 0x128: /* DCGC2 */
440 9ee6e8bb pbrook
        return s->dcgc[2];
441 9ee6e8bb pbrook
    case 0x150: /* CLKVCLR */
442 9ee6e8bb pbrook
        return s->clkvclr;
443 9ee6e8bb pbrook
    case 0x160: /* LDOARST */
444 9ee6e8bb pbrook
        return s->ldoarst;
445 eea589cc pbrook
    case 0x1e0: /* USER0 */
446 eea589cc pbrook
        return s->user0;
447 eea589cc pbrook
    case 0x1e4: /* USER1 */
448 eea589cc pbrook
        return s->user1;
449 9ee6e8bb pbrook
    default:
450 79b02417 pbrook
        cpu_abort(cpu_single_env, "ssys_read: Bad offset 0x%x\n", (int)offset);
451 9ee6e8bb pbrook
        return 0;
452 9ee6e8bb pbrook
    }
453 9ee6e8bb pbrook
}
454 9ee6e8bb pbrook
455 9ee6e8bb pbrook
static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value)
456 9ee6e8bb pbrook
{
457 9ee6e8bb pbrook
    ssys_state *s = (ssys_state *)opaque;
458 9ee6e8bb pbrook
459 9ee6e8bb pbrook
    offset -= s->base;
460 9ee6e8bb pbrook
    switch (offset) {
461 9ee6e8bb pbrook
    case 0x030: /* PBORCTL */
462 9ee6e8bb pbrook
        s->pborctl = value & 0xffff;
463 9ee6e8bb pbrook
        break;
464 9ee6e8bb pbrook
    case 0x034: /* LDOPCTL */
465 9ee6e8bb pbrook
        s->ldopctl = value & 0x1f;
466 9ee6e8bb pbrook
        break;
467 9ee6e8bb pbrook
    case 0x040: /* SRCR0 */
468 9ee6e8bb pbrook
    case 0x044: /* SRCR1 */
469 9ee6e8bb pbrook
    case 0x048: /* SRCR2 */
470 9ee6e8bb pbrook
        fprintf(stderr, "Peripheral reset not implemented\n");
471 9ee6e8bb pbrook
        break;
472 9ee6e8bb pbrook
    case 0x054: /* IMC */
473 9ee6e8bb pbrook
        s->int_mask = value & 0x7f;
474 9ee6e8bb pbrook
        break;
475 9ee6e8bb pbrook
    case 0x058: /* MISC */
476 9ee6e8bb pbrook
        s->int_status &= ~value;
477 9ee6e8bb pbrook
        break;
478 9ee6e8bb pbrook
    case 0x05c: /* RESC */
479 9ee6e8bb pbrook
        s->resc = value & 0x3f;
480 9ee6e8bb pbrook
        break;
481 9ee6e8bb pbrook
    case 0x060: /* RCC */
482 9ee6e8bb pbrook
        if ((s->rcc & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
483 9ee6e8bb pbrook
            /* PLL enable.  */
484 9ee6e8bb pbrook
            s->int_status |= (1 << 6);
485 9ee6e8bb pbrook
        }
486 9ee6e8bb pbrook
        s->rcc = value;
487 e57ec016 pbrook
        system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
488 9ee6e8bb pbrook
        break;
489 9ee6e8bb pbrook
    case 0x100: /* RCGC0 */
490 9ee6e8bb pbrook
        s->rcgc[0] = value;
491 9ee6e8bb pbrook
        break;
492 9ee6e8bb pbrook
    case 0x104: /* RCGC1 */
493 9ee6e8bb pbrook
        s->rcgc[1] = value;
494 9ee6e8bb pbrook
        break;
495 9ee6e8bb pbrook
    case 0x108: /* RCGC2 */
496 9ee6e8bb pbrook
        s->rcgc[2] = value;
497 9ee6e8bb pbrook
        break;
498 9ee6e8bb pbrook
    case 0x110: /* SCGC0 */
499 9ee6e8bb pbrook
        s->scgc[0] = value;
500 9ee6e8bb pbrook
        break;
501 9ee6e8bb pbrook
    case 0x114: /* SCGC1 */
502 9ee6e8bb pbrook
        s->scgc[1] = value;
503 9ee6e8bb pbrook
        break;
504 9ee6e8bb pbrook
    case 0x118: /* SCGC2 */
505 9ee6e8bb pbrook
        s->scgc[2] = value;
506 9ee6e8bb pbrook
        break;
507 9ee6e8bb pbrook
    case 0x120: /* DCGC0 */
508 9ee6e8bb pbrook
        s->dcgc[0] = value;
509 9ee6e8bb pbrook
        break;
510 9ee6e8bb pbrook
    case 0x124: /* DCGC1 */
511 9ee6e8bb pbrook
        s->dcgc[1] = value;
512 9ee6e8bb pbrook
        break;
513 9ee6e8bb pbrook
    case 0x128: /* DCGC2 */
514 9ee6e8bb pbrook
        s->dcgc[2] = value;
515 9ee6e8bb pbrook
        break;
516 9ee6e8bb pbrook
    case 0x150: /* CLKVCLR */
517 9ee6e8bb pbrook
        s->clkvclr = value;
518 9ee6e8bb pbrook
        break;
519 9ee6e8bb pbrook
    case 0x160: /* LDOARST */
520 9ee6e8bb pbrook
        s->ldoarst = value;
521 9ee6e8bb pbrook
        break;
522 9ee6e8bb pbrook
    default:
523 79b02417 pbrook
        cpu_abort(cpu_single_env, "ssys_write: Bad offset 0x%x\n", (int)offset);
524 9ee6e8bb pbrook
    }
525 9ee6e8bb pbrook
    ssys_update(s);
526 9ee6e8bb pbrook
}
527 9ee6e8bb pbrook
528 9ee6e8bb pbrook
static CPUReadMemoryFunc *ssys_readfn[] = {
529 9ee6e8bb pbrook
   ssys_read,
530 9ee6e8bb pbrook
   ssys_read,
531 9ee6e8bb pbrook
   ssys_read
532 9ee6e8bb pbrook
};
533 9ee6e8bb pbrook
534 9ee6e8bb pbrook
static CPUWriteMemoryFunc *ssys_writefn[] = {
535 9ee6e8bb pbrook
   ssys_write,
536 9ee6e8bb pbrook
   ssys_write,
537 9ee6e8bb pbrook
   ssys_write
538 9ee6e8bb pbrook
};
539 9ee6e8bb pbrook
540 9596ebb7 pbrook
static void ssys_reset(void *opaque)
541 9ee6e8bb pbrook
{
542 9ee6e8bb pbrook
    ssys_state *s = (ssys_state *)opaque;
543 9ee6e8bb pbrook
544 9ee6e8bb pbrook
    s->pborctl = 0x7ffd;
545 9ee6e8bb pbrook
    s->rcc = 0x078e3ac0;
546 9ee6e8bb pbrook
    s->rcgc[0] = 1;
547 9ee6e8bb pbrook
    s->scgc[0] = 1;
548 9ee6e8bb pbrook
    s->dcgc[0] = 1;
549 9ee6e8bb pbrook
}
550 9ee6e8bb pbrook
551 9ee6e8bb pbrook
static void stellaris_sys_init(uint32_t base, qemu_irq irq,
552 eea589cc pbrook
                               stellaris_board_info * board,
553 eea589cc pbrook
                               uint8_t *macaddr)
554 9ee6e8bb pbrook
{
555 9ee6e8bb pbrook
    int iomemtype;
556 9ee6e8bb pbrook
    ssys_state *s;
557 9ee6e8bb pbrook
558 9ee6e8bb pbrook
    s = (ssys_state *)qemu_mallocz(sizeof(ssys_state));
559 9ee6e8bb pbrook
    s->base = base;
560 9ee6e8bb pbrook
    s->irq = irq;
561 9ee6e8bb pbrook
    s->board = board;
562 eea589cc pbrook
    /* Most devices come preprogrammed with a MAC address in the user data. */
563 eea589cc pbrook
    s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
564 eea589cc pbrook
    s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
565 9ee6e8bb pbrook
566 9ee6e8bb pbrook
    iomemtype = cpu_register_io_memory(0, ssys_readfn,
567 9ee6e8bb pbrook
                                       ssys_writefn, s);
568 9ee6e8bb pbrook
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
569 9ee6e8bb pbrook
    ssys_reset(s);
570 9ee6e8bb pbrook
    /* ??? Save/restore.  */
571 9ee6e8bb pbrook
}
572 9ee6e8bb pbrook
573 9ee6e8bb pbrook
574 9ee6e8bb pbrook
/* I2C controller.  */
575 9ee6e8bb pbrook
576 9ee6e8bb pbrook
typedef struct {
577 9ee6e8bb pbrook
    i2c_bus *bus;
578 9ee6e8bb pbrook
    qemu_irq irq;
579 9ee6e8bb pbrook
    uint32_t base;
580 9ee6e8bb pbrook
    uint32_t msa;
581 9ee6e8bb pbrook
    uint32_t mcs;
582 9ee6e8bb pbrook
    uint32_t mdr;
583 9ee6e8bb pbrook
    uint32_t mtpr;
584 9ee6e8bb pbrook
    uint32_t mimr;
585 9ee6e8bb pbrook
    uint32_t mris;
586 9ee6e8bb pbrook
    uint32_t mcr;
587 9ee6e8bb pbrook
} stellaris_i2c_state;
588 9ee6e8bb pbrook
589 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_BUSY    0x01
590 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_ERROR   0x02
591 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_ADRACK  0x04
592 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_DATACK  0x08
593 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_ARBLST  0x10
594 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_IDLE    0x20
595 9ee6e8bb pbrook
#define STELLARIS_I2C_MCS_BUSBSY  0x40
596 9ee6e8bb pbrook
597 9ee6e8bb pbrook
static uint32_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset)
598 9ee6e8bb pbrook
{
599 9ee6e8bb pbrook
    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
600 9ee6e8bb pbrook
601 9ee6e8bb pbrook
    offset -= s->base;
602 9ee6e8bb pbrook
    switch (offset) {
603 9ee6e8bb pbrook
    case 0x00: /* MSA */
604 9ee6e8bb pbrook
        return s->msa;
605 9ee6e8bb pbrook
    case 0x04: /* MCS */
606 9ee6e8bb pbrook
        /* We don't emulate timing, so the controller is never busy.  */
607 9ee6e8bb pbrook
        return s->mcs | STELLARIS_I2C_MCS_IDLE;
608 9ee6e8bb pbrook
    case 0x08: /* MDR */
609 9ee6e8bb pbrook
        return s->mdr;
610 9ee6e8bb pbrook
    case 0x0c: /* MTPR */
611 9ee6e8bb pbrook
        return s->mtpr;
612 9ee6e8bb pbrook
    case 0x10: /* MIMR */
613 9ee6e8bb pbrook
        return s->mimr;
614 9ee6e8bb pbrook
    case 0x14: /* MRIS */
615 9ee6e8bb pbrook
        return s->mris;
616 9ee6e8bb pbrook
    case 0x18: /* MMIS */
617 9ee6e8bb pbrook
        return s->mris & s->mimr;
618 9ee6e8bb pbrook
    case 0x20: /* MCR */
619 9ee6e8bb pbrook
        return s->mcr;
620 9ee6e8bb pbrook
    default:
621 9ee6e8bb pbrook
        cpu_abort(cpu_single_env, "strllaris_i2c_read: Bad offset 0x%x\n",
622 9ee6e8bb pbrook
                  (int)offset);
623 9ee6e8bb pbrook
        return 0;
624 9ee6e8bb pbrook
    }
625 9ee6e8bb pbrook
}
626 9ee6e8bb pbrook
627 9ee6e8bb pbrook
static void stellaris_i2c_update(stellaris_i2c_state *s)
628 9ee6e8bb pbrook
{
629 9ee6e8bb pbrook
    int level;
630 9ee6e8bb pbrook
631 9ee6e8bb pbrook
    level = (s->mris & s->mimr) != 0;
632 9ee6e8bb pbrook
    qemu_set_irq(s->irq, level);
633 9ee6e8bb pbrook
}
634 9ee6e8bb pbrook
635 9ee6e8bb pbrook
static void stellaris_i2c_write(void *opaque, target_phys_addr_t offset,
636 9ee6e8bb pbrook
                                uint32_t value)
637 9ee6e8bb pbrook
{
638 9ee6e8bb pbrook
    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
639 9ee6e8bb pbrook
640 9ee6e8bb pbrook
    offset -= s->base;
641 9ee6e8bb pbrook
    switch (offset) {
642 9ee6e8bb pbrook
    case 0x00: /* MSA */
643 9ee6e8bb pbrook
        s->msa = value & 0xff;
644 9ee6e8bb pbrook
        break;
645 9ee6e8bb pbrook
    case 0x04: /* MCS */
646 9ee6e8bb pbrook
        if ((s->mcr & 0x10) == 0) {
647 9ee6e8bb pbrook
            /* Disabled.  Do nothing.  */
648 9ee6e8bb pbrook
            break;
649 9ee6e8bb pbrook
        }
650 9ee6e8bb pbrook
        /* Grab the bus if this is starting a transfer.  */
651 9ee6e8bb pbrook
        if ((value & 2) && (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
652 9ee6e8bb pbrook
            if (i2c_start_transfer(s->bus, s->msa >> 1, s->msa & 1)) {
653 9ee6e8bb pbrook
                s->mcs |= STELLARIS_I2C_MCS_ARBLST;
654 9ee6e8bb pbrook
            } else {
655 9ee6e8bb pbrook
                s->mcs &= ~STELLARIS_I2C_MCS_ARBLST;
656 9ee6e8bb pbrook
                s->mcs |= STELLARIS_I2C_MCS_BUSBSY;
657 9ee6e8bb pbrook
            }
658 9ee6e8bb pbrook
        }
659 9ee6e8bb pbrook
        /* If we don't have the bus then indicate an error.  */
660 9ee6e8bb pbrook
        if (!i2c_bus_busy(s->bus)
661 9ee6e8bb pbrook
                || (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
662 9ee6e8bb pbrook
            s->mcs |= STELLARIS_I2C_MCS_ERROR;
663 9ee6e8bb pbrook
            break;
664 9ee6e8bb pbrook
        }
665 9ee6e8bb pbrook
        s->mcs &= ~STELLARIS_I2C_MCS_ERROR;
666 9ee6e8bb pbrook
        if (value & 1) {
667 9ee6e8bb pbrook
            /* Transfer a byte.  */
668 9ee6e8bb pbrook
            /* TODO: Handle errors.  */
669 9ee6e8bb pbrook
            if (s->msa & 1) {
670 9ee6e8bb pbrook
                /* Recv */
671 9ee6e8bb pbrook
                s->mdr = i2c_recv(s->bus) & 0xff;
672 9ee6e8bb pbrook
            } else {
673 9ee6e8bb pbrook
                /* Send */
674 9ee6e8bb pbrook
                i2c_send(s->bus, s->mdr);
675 9ee6e8bb pbrook
            }
676 9ee6e8bb pbrook
            /* Raise an interrupt.  */
677 9ee6e8bb pbrook
            s->mris |= 1;
678 9ee6e8bb pbrook
        }
679 9ee6e8bb pbrook
        if (value & 4) {
680 9ee6e8bb pbrook
            /* Finish transfer.  */
681 9ee6e8bb pbrook
            i2c_end_transfer(s->bus);
682 9ee6e8bb pbrook
            s->mcs &= ~STELLARIS_I2C_MCS_BUSBSY;
683 9ee6e8bb pbrook
        }
684 9ee6e8bb pbrook
        break;
685 9ee6e8bb pbrook
    case 0x08: /* MDR */
686 9ee6e8bb pbrook
        s->mdr = value & 0xff;
687 9ee6e8bb pbrook
        break;
688 9ee6e8bb pbrook
    case 0x0c: /* MTPR */
689 9ee6e8bb pbrook
        s->mtpr = value & 0xff;
690 9ee6e8bb pbrook
        break;
691 9ee6e8bb pbrook
    case 0x10: /* MIMR */
692 9ee6e8bb pbrook
        s->mimr = 1;
693 9ee6e8bb pbrook
        break;
694 9ee6e8bb pbrook
    case 0x1c: /* MICR */
695 9ee6e8bb pbrook
        s->mris &= ~value;
696 9ee6e8bb pbrook
        break;
697 9ee6e8bb pbrook
    case 0x20: /* MCR */
698 9ee6e8bb pbrook
        if (value & 1)
699 9ee6e8bb pbrook
            cpu_abort(cpu_single_env,
700 9ee6e8bb pbrook
                      "stellaris_i2c_write: Loopback not implemented\n");
701 9ee6e8bb pbrook
        if (value & 0x20)
702 9ee6e8bb pbrook
            cpu_abort(cpu_single_env,
703 9ee6e8bb pbrook
                      "stellaris_i2c_write: Slave mode not implemented\n");
704 9ee6e8bb pbrook
        s->mcr = value & 0x31;
705 9ee6e8bb pbrook
        break;
706 9ee6e8bb pbrook
    default:
707 9ee6e8bb pbrook
        cpu_abort(cpu_single_env, "stellaris_i2c_write: Bad offset 0x%x\n",
708 9ee6e8bb pbrook
                  (int)offset);
709 9ee6e8bb pbrook
    }
710 9ee6e8bb pbrook
    stellaris_i2c_update(s);
711 9ee6e8bb pbrook
}
712 9ee6e8bb pbrook
713 9ee6e8bb pbrook
static void stellaris_i2c_reset(stellaris_i2c_state *s)
714 9ee6e8bb pbrook
{
715 9ee6e8bb pbrook
    if (s->mcs & STELLARIS_I2C_MCS_BUSBSY)
716 9ee6e8bb pbrook
        i2c_end_transfer(s->bus);
717 9ee6e8bb pbrook
718 9ee6e8bb pbrook
    s->msa = 0;
719 9ee6e8bb pbrook
    s->mcs = 0;
720 9ee6e8bb pbrook
    s->mdr = 0;
721 9ee6e8bb pbrook
    s->mtpr = 1;
722 9ee6e8bb pbrook
    s->mimr = 0;
723 9ee6e8bb pbrook
    s->mris = 0;
724 9ee6e8bb pbrook
    s->mcr = 0;
725 9ee6e8bb pbrook
    stellaris_i2c_update(s);
726 9ee6e8bb pbrook
}
727 9ee6e8bb pbrook
728 9ee6e8bb pbrook
static CPUReadMemoryFunc *stellaris_i2c_readfn[] = {
729 9ee6e8bb pbrook
   stellaris_i2c_read,
730 9ee6e8bb pbrook
   stellaris_i2c_read,
731 9ee6e8bb pbrook
   stellaris_i2c_read
732 9ee6e8bb pbrook
};
733 9ee6e8bb pbrook
734 9ee6e8bb pbrook
static CPUWriteMemoryFunc *stellaris_i2c_writefn[] = {
735 9ee6e8bb pbrook
   stellaris_i2c_write,
736 9ee6e8bb pbrook
   stellaris_i2c_write,
737 9ee6e8bb pbrook
   stellaris_i2c_write
738 9ee6e8bb pbrook
};
739 9ee6e8bb pbrook
740 9ee6e8bb pbrook
static void stellaris_i2c_init(uint32_t base, qemu_irq irq, i2c_bus *bus)
741 9ee6e8bb pbrook
{
742 9ee6e8bb pbrook
    stellaris_i2c_state *s;
743 9ee6e8bb pbrook
    int iomemtype;
744 9ee6e8bb pbrook
745 9ee6e8bb pbrook
    s = (stellaris_i2c_state *)qemu_mallocz(sizeof(stellaris_i2c_state));
746 9ee6e8bb pbrook
    s->base = base;
747 9ee6e8bb pbrook
    s->irq = irq;
748 9ee6e8bb pbrook
    s->bus = bus;
749 9ee6e8bb pbrook
750 9ee6e8bb pbrook
    iomemtype = cpu_register_io_memory(0, stellaris_i2c_readfn,
751 9ee6e8bb pbrook
                                       stellaris_i2c_writefn, s);
752 9ee6e8bb pbrook
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
753 9ee6e8bb pbrook
    /* ??? For now we only implement the master interface.  */
754 9ee6e8bb pbrook
    stellaris_i2c_reset(s);
755 9ee6e8bb pbrook
}
756 9ee6e8bb pbrook
757 9ee6e8bb pbrook
/* Analogue to Digital Converter.  This is only partially implemented,
758 9ee6e8bb pbrook
   enough for applications that use a combined ADC and timer tick.  */
759 9ee6e8bb pbrook
760 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_CONTROLLER 0
761 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_COMP       1
762 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_EXTERNAL   4
763 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_TIMER      5
764 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_PWM0       6
765 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_PWM1       7
766 9ee6e8bb pbrook
#define STELLARIS_ADC_EM_PWM2       8
767 9ee6e8bb pbrook
768 9ee6e8bb pbrook
#define STELLARIS_ADC_FIFO_EMPTY    0x0100
769 9ee6e8bb pbrook
#define STELLARIS_ADC_FIFO_FULL     0x1000
770 9ee6e8bb pbrook
771 9ee6e8bb pbrook
typedef struct
772 9ee6e8bb pbrook
{
773 9ee6e8bb pbrook
    uint32_t base;
774 9ee6e8bb pbrook
    uint32_t actss;
775 9ee6e8bb pbrook
    uint32_t ris;
776 9ee6e8bb pbrook
    uint32_t im;
777 9ee6e8bb pbrook
    uint32_t emux;
778 9ee6e8bb pbrook
    uint32_t ostat;
779 9ee6e8bb pbrook
    uint32_t ustat;
780 9ee6e8bb pbrook
    uint32_t sspri;
781 9ee6e8bb pbrook
    uint32_t sac;
782 9ee6e8bb pbrook
    struct {
783 9ee6e8bb pbrook
        uint32_t state;
784 9ee6e8bb pbrook
        uint32_t data[16];
785 9ee6e8bb pbrook
    } fifo[4];
786 9ee6e8bb pbrook
    uint32_t ssmux[4];
787 9ee6e8bb pbrook
    uint32_t ssctl[4];
788 9ee6e8bb pbrook
    qemu_irq irq;
789 9ee6e8bb pbrook
} stellaris_adc_state;
790 9ee6e8bb pbrook
791 9ee6e8bb pbrook
static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
792 9ee6e8bb pbrook
{
793 9ee6e8bb pbrook
    int tail;
794 9ee6e8bb pbrook
795 9ee6e8bb pbrook
    tail = s->fifo[n].state & 0xf;
796 9ee6e8bb pbrook
    if (s->fifo[n].state & STELLARIS_ADC_FIFO_EMPTY) {
797 9ee6e8bb pbrook
        s->ustat |= 1 << n;
798 9ee6e8bb pbrook
    } else {
799 9ee6e8bb pbrook
        s->fifo[n].state = (s->fifo[n].state & ~0xf) | ((tail + 1) & 0xf);
800 9ee6e8bb pbrook
        s->fifo[n].state &= ~STELLARIS_ADC_FIFO_FULL;
801 9ee6e8bb pbrook
        if (tail + 1 == ((s->fifo[n].state >> 4) & 0xf))
802 9ee6e8bb pbrook
            s->fifo[n].state |= STELLARIS_ADC_FIFO_EMPTY;
803 9ee6e8bb pbrook
    }
804 9ee6e8bb pbrook
    return s->fifo[n].data[tail];
805 9ee6e8bb pbrook
}
806 9ee6e8bb pbrook
807 9ee6e8bb pbrook
static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
808 9ee6e8bb pbrook
                                     uint32_t value)
809 9ee6e8bb pbrook
{
810 9ee6e8bb pbrook
    int head;
811 9ee6e8bb pbrook
812 9ee6e8bb pbrook
    head = (s->fifo[n].state >> 4) & 0xf;
813 9ee6e8bb pbrook
    if (s->fifo[n].state & STELLARIS_ADC_FIFO_FULL) {
814 9ee6e8bb pbrook
        s->ostat |= 1 << n;
815 9ee6e8bb pbrook
        return;
816 9ee6e8bb pbrook
    }
817 9ee6e8bb pbrook
    s->fifo[n].data[head] = value;
818 9ee6e8bb pbrook
    head = (head + 1) & 0xf;
819 9ee6e8bb pbrook
    s->fifo[n].state &= ~STELLARIS_ADC_FIFO_EMPTY;
820 9ee6e8bb pbrook
    s->fifo[n].state = (s->fifo[n].state & ~0xf0) | (head << 4);
821 9ee6e8bb pbrook
    if ((s->fifo[n].state & 0xf) == head)
822 9ee6e8bb pbrook
        s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
823 9ee6e8bb pbrook
}
824 9ee6e8bb pbrook
825 9ee6e8bb pbrook
static void stellaris_adc_update(stellaris_adc_state *s)
826 9ee6e8bb pbrook
{
827 9ee6e8bb pbrook
    int level;
828 9ee6e8bb pbrook
829 9ee6e8bb pbrook
    level = (s->ris & s->im) != 0;
830 9ee6e8bb pbrook
    qemu_set_irq(s->irq, level);
831 9ee6e8bb pbrook
}
832 9ee6e8bb pbrook
833 9ee6e8bb pbrook
static void stellaris_adc_trigger(void *opaque, int irq, int level)
834 9ee6e8bb pbrook
{
835 9ee6e8bb pbrook
    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
836 9ee6e8bb pbrook
    /* Some applications use the ADC as a random number source, so introduce
837 9ee6e8bb pbrook
       some variation into the signal.  */
838 9ee6e8bb pbrook
    static uint32_t noise = 0;
839 9ee6e8bb pbrook
840 9ee6e8bb pbrook
    if ((s->actss & 1) == 0) {
841 9ee6e8bb pbrook
        return;
842 9ee6e8bb pbrook
    }
843 9ee6e8bb pbrook
844 9ee6e8bb pbrook
    noise = noise * 314159 + 1;
845 9ee6e8bb pbrook
    /* ??? actual inputs not implemented.  Return an arbitrary value.  */
846 9ee6e8bb pbrook
    stellaris_adc_fifo_write(s, 0, 0x200 + ((noise >> 16) & 7));
847 9ee6e8bb pbrook
    s->ris |= 1;
848 9ee6e8bb pbrook
    stellaris_adc_update(s);
849 9ee6e8bb pbrook
}
850 9ee6e8bb pbrook
851 9ee6e8bb pbrook
static void stellaris_adc_reset(stellaris_adc_state *s)
852 9ee6e8bb pbrook
{
853 9ee6e8bb pbrook
    int n;
854 9ee6e8bb pbrook
855 9ee6e8bb pbrook
    for (n = 0; n < 4; n++) {
856 9ee6e8bb pbrook
        s->ssmux[n] = 0;
857 9ee6e8bb pbrook
        s->ssctl[n] = 0;
858 9ee6e8bb pbrook
        s->fifo[n].state = STELLARIS_ADC_FIFO_EMPTY;
859 9ee6e8bb pbrook
    }
860 9ee6e8bb pbrook
}
861 9ee6e8bb pbrook
862 9ee6e8bb pbrook
static uint32_t stellaris_adc_read(void *opaque, target_phys_addr_t offset)
863 9ee6e8bb pbrook
{
864 9ee6e8bb pbrook
    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
865 9ee6e8bb pbrook
866 9ee6e8bb pbrook
    /* TODO: Implement this.  */
867 9ee6e8bb pbrook
    offset -= s->base;
868 9ee6e8bb pbrook
    if (offset >= 0x40 && offset < 0xc0) {
869 9ee6e8bb pbrook
        int n;
870 9ee6e8bb pbrook
        n = (offset - 0x40) >> 5;
871 9ee6e8bb pbrook
        switch (offset & 0x1f) {
872 9ee6e8bb pbrook
        case 0x00: /* SSMUX */
873 9ee6e8bb pbrook
            return s->ssmux[n];
874 9ee6e8bb pbrook
        case 0x04: /* SSCTL */
875 9ee6e8bb pbrook
            return s->ssctl[n];
876 9ee6e8bb pbrook
        case 0x08: /* SSFIFO */
877 9ee6e8bb pbrook
            return stellaris_adc_fifo_read(s, n);
878 9ee6e8bb pbrook
        case 0x0c: /* SSFSTAT */
879 9ee6e8bb pbrook
            return s->fifo[n].state;
880 9ee6e8bb pbrook
        default:
881 9ee6e8bb pbrook
            break;
882 9ee6e8bb pbrook
        }
883 9ee6e8bb pbrook
    }
884 9ee6e8bb pbrook
    switch (offset) {
885 9ee6e8bb pbrook
    case 0x00: /* ACTSS */
886 9ee6e8bb pbrook
        return s->actss;
887 9ee6e8bb pbrook
    case 0x04: /* RIS */
888 9ee6e8bb pbrook
        return s->ris;
889 9ee6e8bb pbrook
    case 0x08: /* IM */
890 9ee6e8bb pbrook
        return s->im;
891 9ee6e8bb pbrook
    case 0x0c: /* ISC */
892 9ee6e8bb pbrook
        return s->ris & s->im;
893 9ee6e8bb pbrook
    case 0x10: /* OSTAT */
894 9ee6e8bb pbrook
        return s->ostat;
895 9ee6e8bb pbrook
    case 0x14: /* EMUX */
896 9ee6e8bb pbrook
        return s->emux;
897 9ee6e8bb pbrook
    case 0x18: /* USTAT */
898 9ee6e8bb pbrook
        return s->ustat;
899 9ee6e8bb pbrook
    case 0x20: /* SSPRI */
900 9ee6e8bb pbrook
        return s->sspri;
901 9ee6e8bb pbrook
    case 0x30: /* SAC */
902 9ee6e8bb pbrook
        return s->sac;
903 9ee6e8bb pbrook
    default:
904 9ee6e8bb pbrook
        cpu_abort(cpu_single_env, "strllaris_adc_read: Bad offset 0x%x\n",
905 9ee6e8bb pbrook
                  (int)offset);
906 9ee6e8bb pbrook
        return 0;
907 9ee6e8bb pbrook
    }
908 9ee6e8bb pbrook
}
909 9ee6e8bb pbrook
910 9ee6e8bb pbrook
static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
911 9ee6e8bb pbrook
                                uint32_t value)
912 9ee6e8bb pbrook
{
913 9ee6e8bb pbrook
    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
914 9ee6e8bb pbrook
915 9ee6e8bb pbrook
    /* TODO: Implement this.  */
916 9ee6e8bb pbrook
    offset -= s->base;
917 9ee6e8bb pbrook
    if (offset >= 0x40 && offset < 0xc0) {
918 9ee6e8bb pbrook
        int n;
919 9ee6e8bb pbrook
        n = (offset - 0x40) >> 5;
920 9ee6e8bb pbrook
        switch (offset & 0x1f) {
921 9ee6e8bb pbrook
        case 0x00: /* SSMUX */
922 9ee6e8bb pbrook
            s->ssmux[n] = value & 0x33333333;
923 9ee6e8bb pbrook
            return;
924 9ee6e8bb pbrook
        case 0x04: /* SSCTL */
925 9ee6e8bb pbrook
            if (value != 6) {
926 9ee6e8bb pbrook
                cpu_abort(cpu_single_env, "ADC: Unimplemented sequence %x\n",
927 9ee6e8bb pbrook
                          value);
928 9ee6e8bb pbrook
            }
929 9ee6e8bb pbrook
            s->ssctl[n] = value;
930 9ee6e8bb pbrook
            return;
931 9ee6e8bb pbrook
        default:
932 9ee6e8bb pbrook
            break;
933 9ee6e8bb pbrook
        }
934 9ee6e8bb pbrook
    }
935 9ee6e8bb pbrook
    switch (offset) {
936 9ee6e8bb pbrook
    case 0x00: /* ACTSS */
937 9ee6e8bb pbrook
        s->actss = value & 0xf;
938 9ee6e8bb pbrook
        if (value & 0xe) {
939 9ee6e8bb pbrook
            cpu_abort(cpu_single_env,
940 9ee6e8bb pbrook
                      "Not implemented:  ADC sequencers 1-3\n");
941 9ee6e8bb pbrook
        }
942 9ee6e8bb pbrook
        break;
943 9ee6e8bb pbrook
    case 0x08: /* IM */
944 9ee6e8bb pbrook
        s->im = value;
945 9ee6e8bb pbrook
        break;
946 9ee6e8bb pbrook
    case 0x0c: /* ISC */
947 9ee6e8bb pbrook
        s->ris &= ~value;
948 9ee6e8bb pbrook
        break;
949 9ee6e8bb pbrook
    case 0x10: /* OSTAT */
950 9ee6e8bb pbrook
        s->ostat &= ~value;
951 9ee6e8bb pbrook
        break;
952 9ee6e8bb pbrook
    case 0x14: /* EMUX */
953 9ee6e8bb pbrook
        s->emux = value;
954 9ee6e8bb pbrook
        break;
955 9ee6e8bb pbrook
    case 0x18: /* USTAT */
956 9ee6e8bb pbrook
        s->ustat &= ~value;
957 9ee6e8bb pbrook
        break;
958 9ee6e8bb pbrook
    case 0x20: /* SSPRI */
959 9ee6e8bb pbrook
        s->sspri = value;
960 9ee6e8bb pbrook
        break;
961 9ee6e8bb pbrook
    case 0x28: /* PSSI */
962 9ee6e8bb pbrook
        cpu_abort(cpu_single_env, "Not implemented:  ADC sample initiate\n");
963 9ee6e8bb pbrook
        break;
964 9ee6e8bb pbrook
    case 0x30: /* SAC */
965 9ee6e8bb pbrook
        s->sac = value;
966 9ee6e8bb pbrook
        break;
967 9ee6e8bb pbrook
    default:
968 9ee6e8bb pbrook
        cpu_abort(cpu_single_env, "stellaris_adc_write: Bad offset 0x%x\n",
969 9ee6e8bb pbrook
                  (int)offset);
970 9ee6e8bb pbrook
    }
971 9ee6e8bb pbrook
    stellaris_adc_update(s);
972 9ee6e8bb pbrook
}
973 9ee6e8bb pbrook
974 9ee6e8bb pbrook
static CPUReadMemoryFunc *stellaris_adc_readfn[] = {
975 9ee6e8bb pbrook
   stellaris_adc_read,
976 9ee6e8bb pbrook
   stellaris_adc_read,
977 9ee6e8bb pbrook
   stellaris_adc_read
978 9ee6e8bb pbrook
};
979 9ee6e8bb pbrook
980 9ee6e8bb pbrook
static CPUWriteMemoryFunc *stellaris_adc_writefn[] = {
981 9ee6e8bb pbrook
   stellaris_adc_write,
982 9ee6e8bb pbrook
   stellaris_adc_write,
983 9ee6e8bb pbrook
   stellaris_adc_write
984 9ee6e8bb pbrook
};
985 9ee6e8bb pbrook
986 9ee6e8bb pbrook
static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq irq)
987 9ee6e8bb pbrook
{
988 9ee6e8bb pbrook
    stellaris_adc_state *s;
989 9ee6e8bb pbrook
    int iomemtype;
990 9ee6e8bb pbrook
    qemu_irq *qi;
991 9ee6e8bb pbrook
992 9ee6e8bb pbrook
    s = (stellaris_adc_state *)qemu_mallocz(sizeof(stellaris_adc_state));
993 9ee6e8bb pbrook
    s->base = base;
994 9ee6e8bb pbrook
    s->irq = irq;
995 9ee6e8bb pbrook
996 9ee6e8bb pbrook
    iomemtype = cpu_register_io_memory(0, stellaris_adc_readfn,
997 9ee6e8bb pbrook
                                       stellaris_adc_writefn, s);
998 9ee6e8bb pbrook
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
999 9ee6e8bb pbrook
    stellaris_adc_reset(s);
1000 9ee6e8bb pbrook
    qi = qemu_allocate_irqs(stellaris_adc_trigger, s, 1);
1001 9ee6e8bb pbrook
    return qi[0];
1002 9ee6e8bb pbrook
}
1003 9ee6e8bb pbrook
1004 775616c3 pbrook
/* Some boards have both an OLED controller and SD card connected to
1005 775616c3 pbrook
   the same SSI port, with the SD card chip select connected to a
1006 775616c3 pbrook
   GPIO pin.  Technically the OLED chip select is connected to the SSI
1007 775616c3 pbrook
   Fss pin.  We do not bother emulating that as both devices should
1008 775616c3 pbrook
   never be selected simultaneously, and our OLED controller ignores stray
1009 775616c3 pbrook
   0xff commands that occur when deselecting the SD card.  */
1010 775616c3 pbrook
1011 775616c3 pbrook
typedef struct {
1012 775616c3 pbrook
    ssi_xfer_cb xfer_cb[2];
1013 775616c3 pbrook
    void *opaque[2];
1014 775616c3 pbrook
    qemu_irq irq;
1015 775616c3 pbrook
    int current_dev;
1016 775616c3 pbrook
} stellaris_ssi_bus_state;
1017 775616c3 pbrook
1018 775616c3 pbrook
static void stellaris_ssi_bus_select(void *opaque, int irq, int level)
1019 775616c3 pbrook
{
1020 775616c3 pbrook
    stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
1021 775616c3 pbrook
1022 775616c3 pbrook
    s->current_dev = level;
1023 775616c3 pbrook
}
1024 775616c3 pbrook
1025 775616c3 pbrook
static int stellaris_ssi_bus_xfer(void *opaque, int val)
1026 775616c3 pbrook
{
1027 775616c3 pbrook
    stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
1028 775616c3 pbrook
1029 775616c3 pbrook
    return s->xfer_cb[s->current_dev](s->opaque[s->current_dev], val);
1030 775616c3 pbrook
}
1031 775616c3 pbrook
1032 775616c3 pbrook
static void *stellaris_ssi_bus_init(qemu_irq *irqp,
1033 775616c3 pbrook
                                    ssi_xfer_cb cb0, void *opaque0,
1034 775616c3 pbrook
                                    ssi_xfer_cb cb1, void *opaque1)
1035 775616c3 pbrook
{
1036 775616c3 pbrook
    qemu_irq *qi;
1037 775616c3 pbrook
    stellaris_ssi_bus_state *s;
1038 775616c3 pbrook
1039 775616c3 pbrook
    s = (stellaris_ssi_bus_state *)qemu_mallocz(sizeof(stellaris_ssi_bus_state));
1040 775616c3 pbrook
    s->xfer_cb[0] = cb0;
1041 775616c3 pbrook
    s->opaque[0] = opaque0;
1042 775616c3 pbrook
    s->xfer_cb[1] = cb1;
1043 775616c3 pbrook
    s->opaque[1] = opaque1;
1044 775616c3 pbrook
    qi = qemu_allocate_irqs(stellaris_ssi_bus_select, s, 1);
1045 775616c3 pbrook
    *irqp = *qi;
1046 775616c3 pbrook
    return s;
1047 775616c3 pbrook
}
1048 775616c3 pbrook
1049 9ee6e8bb pbrook
/* Board init.  */
1050 9ee6e8bb pbrook
static stellaris_board_info stellaris_boards[] = {
1051 9ee6e8bb pbrook
  { "LM3S811EVB",
1052 9ee6e8bb pbrook
    0,
1053 9ee6e8bb pbrook
    0x0032000e,
1054 9ee6e8bb pbrook
    0x001f001f, /* dc0 */
1055 9ee6e8bb pbrook
    0x001132bf,
1056 9ee6e8bb pbrook
    0x01071013,
1057 9ee6e8bb pbrook
    0x3f0f01ff,
1058 9ee6e8bb pbrook
    0x0000001f,
1059 cf0dbb21 pbrook
    BP_OLED_I2C
1060 9ee6e8bb pbrook
  },
1061 9ee6e8bb pbrook
  { "LM3S6965EVB",
1062 9ee6e8bb pbrook
    0x10010002,
1063 9ee6e8bb pbrook
    0x1073402e,
1064 9ee6e8bb pbrook
    0x00ff007f, /* dc0 */
1065 9ee6e8bb pbrook
    0x001133ff,
1066 9ee6e8bb pbrook
    0x030f5317,
1067 9ee6e8bb pbrook
    0x0f0f87ff,
1068 9ee6e8bb pbrook
    0x5000007f,
1069 cf0dbb21 pbrook
    BP_OLED_SSI | BP_GAMEPAD
1070 9ee6e8bb pbrook
  }
1071 9ee6e8bb pbrook
};
1072 9ee6e8bb pbrook
1073 9ee6e8bb pbrook
static void stellaris_init(const char *kernel_filename, const char *cpu_model,
1074 9ee6e8bb pbrook
                           DisplayState *ds, stellaris_board_info *board)
1075 9ee6e8bb pbrook
{
1076 9ee6e8bb pbrook
    static const int uart_irq[] = {5, 6, 33, 34};
1077 9ee6e8bb pbrook
    static const int timer_irq[] = {19, 21, 23, 35};
1078 9ee6e8bb pbrook
    static const uint32_t gpio_addr[7] =
1079 9ee6e8bb pbrook
      { 0x40004000, 0x40005000, 0x40006000, 0x40007000,
1080 9ee6e8bb pbrook
        0x40024000, 0x40025000, 0x40026000};
1081 9ee6e8bb pbrook
    static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
1082 9ee6e8bb pbrook
1083 9ee6e8bb pbrook
    qemu_irq *pic;
1084 9ee6e8bb pbrook
    qemu_irq *gpio_in[5];
1085 9ee6e8bb pbrook
    qemu_irq *gpio_out[5];
1086 9ee6e8bb pbrook
    qemu_irq adc;
1087 9ee6e8bb pbrook
    int sram_size;
1088 9ee6e8bb pbrook
    int flash_size;
1089 9ee6e8bb pbrook
    i2c_bus *i2c;
1090 9ee6e8bb pbrook
    int i;
1091 9ee6e8bb pbrook
1092 9ee6e8bb pbrook
    flash_size = ((board->dc0 & 0xffff) + 1) << 1;
1093 9ee6e8bb pbrook
    sram_size = (board->dc0 >> 18) + 1;
1094 9ee6e8bb pbrook
    pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model);
1095 9ee6e8bb pbrook
1096 9ee6e8bb pbrook
    if (board->dc1 & (1 << 16)) {
1097 9ee6e8bb pbrook
        adc = stellaris_adc_init(0x40038000, pic[14]);
1098 9ee6e8bb pbrook
    } else {
1099 9ee6e8bb pbrook
        adc = NULL;
1100 9ee6e8bb pbrook
    }
1101 9ee6e8bb pbrook
    for (i = 0; i < 4; i++) {
1102 9ee6e8bb pbrook
        if (board->dc2 & (0x10000 << i)) {
1103 9ee6e8bb pbrook
            stellaris_gptm_init(0x40030000 + i * 0x1000,
1104 9ee6e8bb pbrook
                                pic[timer_irq[i]], adc);
1105 9ee6e8bb pbrook
        }
1106 9ee6e8bb pbrook
    }
1107 9ee6e8bb pbrook
1108 eea589cc pbrook
    stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr);
1109 9ee6e8bb pbrook
1110 9ee6e8bb pbrook
    for (i = 0; i < 7; i++) {
1111 9ee6e8bb pbrook
        if (board->dc4 & (1 << i)) {
1112 9ee6e8bb pbrook
            gpio_in[i] = pl061_init(gpio_addr[i], pic[gpio_irq[i]],
1113 9ee6e8bb pbrook
                                    &gpio_out[i]);
1114 9ee6e8bb pbrook
        }
1115 9ee6e8bb pbrook
    }
1116 9ee6e8bb pbrook
1117 9ee6e8bb pbrook
    if (board->dc2 & (1 << 12)) {
1118 9ee6e8bb pbrook
        i2c = i2c_init_bus();
1119 9ee6e8bb pbrook
        stellaris_i2c_init(0x40020000, pic[8], i2c);
1120 cf0dbb21 pbrook
        if (board->peripherals & BP_OLED_I2C) {
1121 9ee6e8bb pbrook
            ssd0303_init(ds, i2c, 0x3d);
1122 9ee6e8bb pbrook
        }
1123 9ee6e8bb pbrook
    }
1124 9ee6e8bb pbrook
1125 9ee6e8bb pbrook
    for (i = 0; i < 4; i++) {
1126 9ee6e8bb pbrook
        if (board->dc2 & (1 << i)) {
1127 9ee6e8bb pbrook
            pl011_init(0x4000c000 + i * 0x1000, pic[uart_irq[i]],
1128 9ee6e8bb pbrook
                       serial_hds[i], PL011_LUMINARY);
1129 9ee6e8bb pbrook
        }
1130 9ee6e8bb pbrook
    }
1131 9ee6e8bb pbrook
    if (board->dc2 & (1 << 4)) {
1132 cf0dbb21 pbrook
        if (board->peripherals & BP_OLED_SSI) {
1133 9ee6e8bb pbrook
            void * oled;
1134 775616c3 pbrook
            void * sd;
1135 775616c3 pbrook
            void *ssi_bus;
1136 e4bcb14c ths
            int index;
1137 775616c3 pbrook
1138 cf0dbb21 pbrook
            oled = ssd0323_init(ds, &gpio_out[GPIO_C][7]);
1139 e4bcb14c ths
            index = drive_get_index(IF_SD, 0, 0);
1140 e4bcb14c ths
            sd = ssi_sd_init(drives_table[index].bdrv);
1141 775616c3 pbrook
1142 775616c3 pbrook
            ssi_bus = stellaris_ssi_bus_init(&gpio_out[GPIO_D][0],
1143 775616c3 pbrook
                                             ssi_sd_xfer, sd,
1144 775616c3 pbrook
                                             ssd0323_xfer_ssi, oled);
1145 775616c3 pbrook
1146 775616c3 pbrook
            pl022_init(0x40008000, pic[7], stellaris_ssi_bus_xfer, ssi_bus);
1147 775616c3 pbrook
            /* Make sure the select pin is high.  */
1148 775616c3 pbrook
            qemu_irq_raise(gpio_out[GPIO_D][0]);
1149 9ee6e8bb pbrook
        } else {
1150 9ee6e8bb pbrook
            pl022_init(0x40008000, pic[7], NULL, NULL);
1151 9ee6e8bb pbrook
        }
1152 9ee6e8bb pbrook
    }
1153 eea589cc pbrook
    if (board->dc4 & (1 << 28)) {
1154 eea589cc pbrook
        /* FIXME: Obey network model.  */
1155 eea589cc pbrook
        stellaris_enet_init(&nd_table[0], 0x40048000, pic[42]);
1156 eea589cc pbrook
    }
1157 cf0dbb21 pbrook
    if (board->peripherals & BP_GAMEPAD) {
1158 cf0dbb21 pbrook
        qemu_irq gpad_irq[5];
1159 cf0dbb21 pbrook
        static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
1160 cf0dbb21 pbrook
1161 cf0dbb21 pbrook
        gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */
1162 cf0dbb21 pbrook
        gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */
1163 cf0dbb21 pbrook
        gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */
1164 cf0dbb21 pbrook
        gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */
1165 cf0dbb21 pbrook
        gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */
1166 cf0dbb21 pbrook
1167 cf0dbb21 pbrook
        stellaris_gamepad_init(5, gpad_irq, gpad_keycode);
1168 cf0dbb21 pbrook
    }
1169 9ee6e8bb pbrook
}
1170 9ee6e8bb pbrook
1171 9ee6e8bb pbrook
/* FIXME: Figure out how to generate these from stellaris_boards.  */
1172 00f82b8a aurel32
static void lm3s811evb_init(ram_addr_t ram_size, int vga_ram_size,
1173 9ee6e8bb pbrook
                     const char *boot_device, DisplayState *ds,
1174 9ee6e8bb pbrook
                     const char *kernel_filename, const char *kernel_cmdline,
1175 9ee6e8bb pbrook
                     const char *initrd_filename, const char *cpu_model)
1176 9ee6e8bb pbrook
{
1177 9ee6e8bb pbrook
    stellaris_init(kernel_filename, cpu_model, ds, &stellaris_boards[0]);
1178 9ee6e8bb pbrook
}
1179 9ee6e8bb pbrook
1180 00f82b8a aurel32
static void lm3s6965evb_init(ram_addr_t ram_size, int vga_ram_size,
1181 9ee6e8bb pbrook
                     const char *boot_device, DisplayState *ds,
1182 9ee6e8bb pbrook
                     const char *kernel_filename, const char *kernel_cmdline,
1183 9ee6e8bb pbrook
                     const char *initrd_filename, const char *cpu_model)
1184 9ee6e8bb pbrook
{
1185 9ee6e8bb pbrook
    stellaris_init(kernel_filename, cpu_model, ds, &stellaris_boards[1]);
1186 9ee6e8bb pbrook
}
1187 9ee6e8bb pbrook
1188 9ee6e8bb pbrook
QEMUMachine lm3s811evb_machine = {
1189 9ee6e8bb pbrook
    "lm3s811evb",
1190 9ee6e8bb pbrook
    "Stellaris LM3S811EVB",
1191 9ee6e8bb pbrook
    lm3s811evb_init,
1192 e61b79d6 pbrook
    (64 * 1024 + 8 * 1024) | RAMSIZE_FIXED,
1193 9ee6e8bb pbrook
};
1194 9ee6e8bb pbrook
1195 9ee6e8bb pbrook
QEMUMachine lm3s6965evb_machine = {
1196 9ee6e8bb pbrook
    "lm3s6965evb",
1197 9ee6e8bb pbrook
    "Stellaris LM3S6965EVB",
1198 9ee6e8bb pbrook
    lm3s6965evb_init,
1199 e61b79d6 pbrook
    (256 * 1024 + 64 * 1024) | RAMSIZE_FIXED,
1200 9ee6e8bb pbrook
};