Statistics
| Branch: | Revision:

root / hw / stellaris.c @ 113f89df

History | View | Annotate | Download (37.7 kB)

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