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