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