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