2 * Luminary Micro Stellaris peripherals
4 * Copyright (c) 2006 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licenced under the GPL.
12 #include "primecell.h"
14 #include "qemu-timer.h"
29 #define BP_OLED_I2C 0x01
30 #define BP_OLED_SSI 0x02
31 #define BP_GAMEPAD 0x04
33 typedef const struct {
43 } stellaris_board_info
;
45 /* General purpose timer module. */
47 typedef struct gptm_state
{
56 uint32_t match_prescale
[2];
59 struct gptm_state
*opaque
[2];
62 /* The timers have an alternate output used to trigger the ADC. */
67 static void gptm_update_irq(gptm_state
*s
)
70 level
= (s
->state
& s
->mask
) != 0;
71 qemu_set_irq(s
->irq
, level
);
74 static void gptm_stop(gptm_state
*s
, int n
)
76 qemu_del_timer(s
->timer
[n
]);
79 static void gptm_reload(gptm_state
*s
, int n
, int reset
)
83 tick
= qemu_get_clock(vm_clock
);
88 /* 32-bit CountDown. */
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. */
98 cpu_abort(cpu_single_env
, "TODO: 16-bit timer mode 0x%x\n",
102 qemu_mod_timer(s
->timer
[n
], tick
);
105 static void gptm_tick(void *opaque
)
107 gptm_state
**p
= (gptm_state
**)opaque
;
113 if (s
->config
== 0) {
115 if ((s
->control
& 0x20)) {
116 /* Output trigger. */
117 qemu_irq_raise(s
->trigger
);
118 qemu_irq_lower(s
->trigger
);
120 if (s
->mode
[0] & 1) {
125 gptm_reload(s
, 0, 0);
127 } else if (s
->config
== 1) {
131 match
= s
->match
[0] | (s
->match
[1] << 16);
137 gptm_reload(s
, 0, 0);
138 } else if (s
->mode
[n
] == 0xa) {
139 /* PWM mode. Not implemented. */
141 cpu_abort(cpu_single_env
, "TODO: 16-bit timer mode 0x%x\n",
147 static uint32_t gptm_read(void *opaque
, target_phys_addr_t offset
)
149 gptm_state
*s
= (gptm_state
*)opaque
;
155 case 0x04: /* TAMR */
157 case 0x08: /* TBMR */
166 return s
->state
& s
->mask
;
169 case 0x28: /* TAILR */
170 return s
->load
[0] | ((s
->config
< 4) ? (s
->load
[1] << 16) : 0);
171 case 0x2c: /* TBILR */
173 case 0x30: /* TAMARCHR */
174 return s
->match
[0] | ((s
->config
< 4) ? (s
->match
[1] << 16) : 0);
175 case 0x34: /* TBMATCHR */
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];
189 cpu_abort(cpu_single_env
, "TODO: Timer value read\n");
191 cpu_abort(cpu_single_env
, "gptm_read: Bad offset 0x%x\n", (int)offset
);
196 static void gptm_write(void *opaque
, target_phys_addr_t offset
, uint32_t value
)
198 gptm_state
*s
= (gptm_state
*)opaque
;
202 /* The timers should be disabled before changing the configuration.
203 We take advantage of this and defer everything until the timer
209 case 0x04: /* TAMR */
212 case 0x08: /* TBMR */
218 /* TODO: Implement pause. */
219 if ((oldval
^ value
) & 1) {
221 gptm_reload(s
, 0, 1);
226 if (((oldval
^ value
) & 0x100) && s
->config
>= 4) {
228 gptm_reload(s
, 1, 1);
235 s
->mask
= value
& 0x77;
241 case 0x28: /* TAILR */
242 s
->load
[0] = value
& 0xffff;
244 s
->load
[1] = value
>> 16;
247 case 0x2c: /* TBILR */
248 s
->load
[1] = value
& 0xffff;
250 case 0x30: /* TAMARCHR */
251 s
->match
[0] = value
& 0xffff;
253 s
->match
[1] = value
>> 16;
256 case 0x34: /* TBMATCHR */
257 s
->match
[1] = value
>> 16;
259 case 0x38: /* TAPR */
260 s
->prescale
[0] = value
;
262 case 0x3c: /* TBPR */
263 s
->prescale
[1] = value
;
265 case 0x40: /* TAPMR */
266 s
->match_prescale
[0] = value
;
268 case 0x44: /* TBPMR */
269 s
->match_prescale
[0] = value
;
272 cpu_abort(cpu_single_env
, "gptm_write: Bad offset 0x%x\n", (int)offset
);
277 static CPUReadMemoryFunc
*gptm_readfn
[] = {
283 static CPUWriteMemoryFunc
*gptm_writefn
[] = {
289 static void stellaris_gptm_init(uint32_t base
, qemu_irq irq
, qemu_irq trigger
)
294 s
= (gptm_state
*)qemu_mallocz(sizeof(gptm_state
));
297 s
->trigger
= trigger
;
298 s
->opaque
[0] = s
->opaque
[1] = s
;
300 iomemtype
= cpu_register_io_memory(0, gptm_readfn
,
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. */
309 /* System controller. */
327 stellaris_board_info
*board
;
330 static void ssys_update(ssys_state
*s
)
332 qemu_set_irq(s
->irq
, (s
->int_status
& s
->int_mask
) != 0);
335 static uint32_t pllcfg_sandstorm
[16] = {
337 0x1ae0, /* 1.8432 Mhz */
339 0xd573, /* 2.4576 Mhz */
340 0x37a6, /* 3.57954 Mhz */
341 0x1ae2, /* 3.6864 Mhz */
343 0x98bc, /* 4.906 Mhz */
344 0x935b, /* 4.9152 Mhz */
346 0x4dee, /* 5.12 Mhz */
348 0x75db, /* 6.144 Mhz */
349 0x1ae6, /* 7.3728 Mhz */
351 0x585b /* 8.192 Mhz */
354 static uint32_t pllcfg_fury
[16] = {
356 0x1b20, /* 1.8432 Mhz */
358 0xf42b, /* 2.4576 Mhz */
359 0x37e3, /* 3.57954 Mhz */
360 0x1b21, /* 3.6864 Mhz */
362 0x98ee, /* 4.906 Mhz */
363 0xd5b4, /* 4.9152 Mhz */
365 0x4e27, /* 5.12 Mhz */
367 0xec1c, /* 6.144 Mhz */
368 0x1b23, /* 7.3728 Mhz */
370 0xb11c /* 8.192 Mhz */
373 static uint32_t ssys_read(void *opaque
, target_phys_addr_t offset
)
375 ssys_state
*s
= (ssys_state
*)opaque
;
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 */
395 case 0x034: /* LDOPCTL */
397 case 0x040: /* SRCR0 */
399 case 0x044: /* SRCR1 */
401 case 0x048: /* SRCR2 */
403 case 0x050: /* RIS */
404 return s
->int_status
;
405 case 0x054: /* IMC */
407 case 0x058: /* MISC */
408 return s
->int_status
& s
->int_mask
;
409 case 0x05c: /* RESC */
411 case 0x060: /* RCC */
413 case 0x064: /* PLLCFG */
416 xtal
= (s
->rcc
>> 6) & 0xf;
417 if (s
->board
->did0
& (1 << 16)) {
418 return pllcfg_fury
[xtal
];
420 return pllcfg_sandstorm
[xtal
];
423 case 0x100: /* RCGC0 */
425 case 0x104: /* RCGC1 */
427 case 0x108: /* RCGC2 */
429 case 0x110: /* SCGC0 */
431 case 0x114: /* SCGC1 */
433 case 0x118: /* SCGC2 */
435 case 0x120: /* DCGC0 */
437 case 0x124: /* DCGC1 */
439 case 0x128: /* DCGC2 */
441 case 0x150: /* CLKVCLR */
443 case 0x160: /* LDOARST */
445 case 0x1e0: /* USER0 */
447 case 0x1e4: /* USER1 */
450 cpu_abort(cpu_single_env
, "ssys_read: Bad offset 0x%x\n", (int)offset
);
455 static void ssys_write(void *opaque
, target_phys_addr_t offset
, uint32_t value
)
457 ssys_state
*s
= (ssys_state
*)opaque
;
461 case 0x030: /* PBORCTL */
462 s
->pborctl
= value
& 0xffff;
464 case 0x034: /* LDOPCTL */
465 s
->ldopctl
= value
& 0x1f;
467 case 0x040: /* SRCR0 */
468 case 0x044: /* SRCR1 */
469 case 0x048: /* SRCR2 */
470 fprintf(stderr
, "Peripheral reset not implemented\n");
472 case 0x054: /* IMC */
473 s
->int_mask
= value
& 0x7f;
475 case 0x058: /* MISC */
476 s
->int_status
&= ~value
;
478 case 0x05c: /* RESC */
479 s
->resc
= value
& 0x3f;
481 case 0x060: /* RCC */
482 if ((s
->rcc
& (1 << 13)) != 0 && (value
& (1 << 13)) == 0) {
484 s
->int_status
|= (1 << 6);
487 system_clock_scale
= 5 * (((s
->rcc
>> 23) & 0xf) + 1);
489 case 0x100: /* RCGC0 */
492 case 0x104: /* RCGC1 */
495 case 0x108: /* RCGC2 */
498 case 0x110: /* SCGC0 */
501 case 0x114: /* SCGC1 */
504 case 0x118: /* SCGC2 */
507 case 0x120: /* DCGC0 */
510 case 0x124: /* DCGC1 */
513 case 0x128: /* DCGC2 */
516 case 0x150: /* CLKVCLR */
519 case 0x160: /* LDOARST */
523 cpu_abort(cpu_single_env
, "ssys_write: Bad offset 0x%x\n", (int)offset
);
528 static CPUReadMemoryFunc
*ssys_readfn
[] = {
534 static CPUWriteMemoryFunc
*ssys_writefn
[] = {
540 static void ssys_reset(void *opaque
)
542 ssys_state
*s
= (ssys_state
*)opaque
;
551 static void stellaris_sys_init(uint32_t base
, qemu_irq irq
,
552 stellaris_board_info
* board
,
558 s
= (ssys_state
*)qemu_mallocz(sizeof(ssys_state
));
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);
566 iomemtype
= cpu_register_io_memory(0, ssys_readfn
,
568 cpu_register_physical_memory(base
, 0x00001000, iomemtype
);
570 /* ??? Save/restore. */
574 /* I2C controller. */
587 } stellaris_i2c_state
;
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
597 static uint32_t stellaris_i2c_read(void *opaque
, target_phys_addr_t offset
)
599 stellaris_i2c_state
*s
= (stellaris_i2c_state
*)opaque
;
606 /* We don't emulate timing, so the controller is never busy. */
607 return s
->mcs
| STELLARIS_I2C_MCS_IDLE
;
610 case 0x0c: /* MTPR */
612 case 0x10: /* MIMR */
614 case 0x14: /* MRIS */
616 case 0x18: /* MMIS */
617 return s
->mris
& s
->mimr
;
621 cpu_abort(cpu_single_env
, "strllaris_i2c_read: Bad offset 0x%x\n",
627 static void stellaris_i2c_update(stellaris_i2c_state
*s
)
631 level
= (s
->mris
& s
->mimr
) != 0;
632 qemu_set_irq(s
->irq
, level
);
635 static void stellaris_i2c_write(void *opaque
, target_phys_addr_t offset
,
638 stellaris_i2c_state
*s
= (stellaris_i2c_state
*)opaque
;
643 s
->msa
= value
& 0xff;
646 if ((s
->mcr
& 0x10) == 0) {
647 /* Disabled. Do nothing. */
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
;
655 s
->mcs
&= ~STELLARIS_I2C_MCS_ARBLST
;
656 s
->mcs
|= STELLARIS_I2C_MCS_BUSBSY
;
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
;
665 s
->mcs
&= ~STELLARIS_I2C_MCS_ERROR
;
667 /* Transfer a byte. */
668 /* TODO: Handle errors. */
671 s
->mdr
= i2c_recv(s
->bus
) & 0xff;
674 i2c_send(s
->bus
, s
->mdr
);
676 /* Raise an interrupt. */
680 /* Finish transfer. */
681 i2c_end_transfer(s
->bus
);
682 s
->mcs
&= ~STELLARIS_I2C_MCS_BUSBSY
;
686 s
->mdr
= value
& 0xff;
688 case 0x0c: /* MTPR */
689 s
->mtpr
= value
& 0xff;
691 case 0x10: /* MIMR */
694 case 0x1c: /* MICR */
699 cpu_abort(cpu_single_env
,
700 "stellaris_i2c_write: Loopback not implemented\n");
702 cpu_abort(cpu_single_env
,
703 "stellaris_i2c_write: Slave mode not implemented\n");
704 s
->mcr
= value
& 0x31;
707 cpu_abort(cpu_single_env
, "stellaris_i2c_write: Bad offset 0x%x\n",
710 stellaris_i2c_update(s
);
713 static void stellaris_i2c_reset(stellaris_i2c_state
*s
)
715 if (s
->mcs
& STELLARIS_I2C_MCS_BUSBSY
)
716 i2c_end_transfer(s
->bus
);
725 stellaris_i2c_update(s
);
728 static CPUReadMemoryFunc
*stellaris_i2c_readfn
[] = {
734 static CPUWriteMemoryFunc
*stellaris_i2c_writefn
[] = {
740 static void stellaris_i2c_init(uint32_t base
, qemu_irq irq
, i2c_bus
*bus
)
742 stellaris_i2c_state
*s
;
745 s
= (stellaris_i2c_state
*)qemu_mallocz(sizeof(stellaris_i2c_state
));
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
);
757 /* Analogue to Digital Converter. This is only partially implemented,
758 enough for applications that use a combined ADC and timer tick. */
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
768 #define STELLARIS_ADC_FIFO_EMPTY 0x0100
769 #define STELLARIS_ADC_FIFO_FULL 0x1000
789 } stellaris_adc_state
;
791 static uint32_t stellaris_adc_fifo_read(stellaris_adc_state
*s
, int n
)
795 tail
= s
->fifo
[n
].state
& 0xf;
796 if (s
->fifo
[n
].state
& STELLARIS_ADC_FIFO_EMPTY
) {
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
;
804 return s
->fifo
[n
].data
[tail
];
807 static void stellaris_adc_fifo_write(stellaris_adc_state
*s
, int n
,
812 head
= (s
->fifo
[n
].state
>> 4) & 0xf;
813 if (s
->fifo
[n
].state
& STELLARIS_ADC_FIFO_FULL
) {
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
;
825 static void stellaris_adc_update(stellaris_adc_state
*s
)
829 level
= (s
->ris
& s
->im
) != 0;
830 qemu_set_irq(s
->irq
, level
);
833 static void stellaris_adc_trigger(void *opaque
, int irq
, int level
)
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;
840 if ((s
->actss
& 1) == 0) {
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));
848 stellaris_adc_update(s
);
851 static void stellaris_adc_reset(stellaris_adc_state
*s
)
855 for (n
= 0; n
< 4; n
++) {
858 s
->fifo
[n
].state
= STELLARIS_ADC_FIFO_EMPTY
;
862 static uint32_t stellaris_adc_read(void *opaque
, target_phys_addr_t offset
)
864 stellaris_adc_state
*s
= (stellaris_adc_state
*)opaque
;
866 /* TODO: Implement this. */
868 if (offset
>= 0x40 && offset
< 0xc0) {
870 n
= (offset
- 0x40) >> 5;
871 switch (offset
& 0x1f) {
872 case 0x00: /* SSMUX */
874 case 0x04: /* SSCTL */
876 case 0x08: /* SSFIFO */
877 return stellaris_adc_fifo_read(s
, n
);
878 case 0x0c: /* SSFSTAT */
879 return s
->fifo
[n
].state
;
885 case 0x00: /* ACTSS */
892 return s
->ris
& s
->im
;
893 case 0x10: /* OSTAT */
895 case 0x14: /* EMUX */
897 case 0x18: /* USTAT */
899 case 0x20: /* SSPRI */
904 cpu_abort(cpu_single_env
, "strllaris_adc_read: Bad offset 0x%x\n",
910 static void stellaris_adc_write(void *opaque
, target_phys_addr_t offset
,
913 stellaris_adc_state
*s
= (stellaris_adc_state
*)opaque
;
915 /* TODO: Implement this. */
917 if (offset
>= 0x40 && offset
< 0xc0) {
919 n
= (offset
- 0x40) >> 5;
920 switch (offset
& 0x1f) {
921 case 0x00: /* SSMUX */
922 s
->ssmux
[n
] = value
& 0x33333333;
924 case 0x04: /* SSCTL */
926 cpu_abort(cpu_single_env
, "ADC: Unimplemented sequence %x\n",
936 case 0x00: /* ACTSS */
937 s
->actss
= value
& 0xf;
939 cpu_abort(cpu_single_env
,
940 "Not implemented: ADC sequencers 1-3\n");
949 case 0x10: /* OSTAT */
952 case 0x14: /* EMUX */
955 case 0x18: /* USTAT */
958 case 0x20: /* SSPRI */
961 case 0x28: /* PSSI */
962 cpu_abort(cpu_single_env
, "Not implemented: ADC sample initiate\n");
968 cpu_abort(cpu_single_env
, "stellaris_adc_write: Bad offset 0x%x\n",
971 stellaris_adc_update(s
);
974 static CPUReadMemoryFunc
*stellaris_adc_readfn
[] = {
980 static CPUWriteMemoryFunc
*stellaris_adc_writefn
[] = {
986 static qemu_irq
stellaris_adc_init(uint32_t base
, qemu_irq irq
)
988 stellaris_adc_state
*s
;
992 s
= (stellaris_adc_state
*)qemu_mallocz(sizeof(stellaris_adc_state
));
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);
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. */
1012 ssi_xfer_cb xfer_cb
[2];
1016 } stellaris_ssi_bus_state
;
1018 static void stellaris_ssi_bus_select(void *opaque
, int irq
, int level
)
1020 stellaris_ssi_bus_state
*s
= (stellaris_ssi_bus_state
*)opaque
;
1022 s
->current_dev
= level
;
1025 static int stellaris_ssi_bus_xfer(void *opaque
, int val
)
1027 stellaris_ssi_bus_state
*s
= (stellaris_ssi_bus_state
*)opaque
;
1029 return s
->xfer_cb
[s
->current_dev
](s
->opaque
[s
->current_dev
], val
);
1032 static void *stellaris_ssi_bus_init(qemu_irq
*irqp
,
1033 ssi_xfer_cb cb0
, void *opaque0
,
1034 ssi_xfer_cb cb1
, void *opaque1
)
1037 stellaris_ssi_bus_state
*s
;
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);
1050 static stellaris_board_info stellaris_boards
[] = {
1054 0x001f001f, /* dc0 */
1064 0x00ff007f, /* dc0 */
1069 BP_OLED_SSI
| BP_GAMEPAD
1073 static void stellaris_init(const char *kernel_filename
, const char *cpu_model
,
1074 DisplayState
*ds
, stellaris_board_info
*board
)
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};
1084 qemu_irq
*gpio_in
[5];
1085 qemu_irq
*gpio_out
[5];
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
);
1096 if (board
->dc1
& (1 << 16)) {
1097 adc
= stellaris_adc_init(0x40038000, pic
[14]);
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
);
1108 stellaris_sys_init(0x400fe000, pic
[28], board
, nd_table
[0].macaddr
);
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
]],
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);
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
);
1131 if (board
->dc2
& (1 << 4)) {
1132 if (board
->peripherals
& BP_OLED_SSI
) {
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
);
1142 ssi_bus
= stellaris_ssi_bus_init(&gpio_out
[GPIO_D
][0],
1144 ssd0323_xfer_ssi
, oled
);
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]);
1150 pl022_init(0x40008000, pic
[7], NULL
, NULL
);
1153 if (board
->dc4
& (1 << 28)) {
1154 /* FIXME: Obey network model. */
1155 stellaris_enet_init(&nd_table
[0], 0x40048000, pic
[42]);
1157 if (board
->peripherals
& BP_GAMEPAD
) {
1158 qemu_irq gpad_irq
[5];
1159 static const int gpad_keycode
[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
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 */
1167 stellaris_gamepad_init(5, gpad_irq
, gpad_keycode
);
1171 /* FIXME: Figure out how to generate these from stellaris_boards. */
1172 static void lm3s811evb_init(ram_addr_t 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
)
1177 stellaris_init(kernel_filename
, cpu_model
, ds
, &stellaris_boards
[0]);
1180 static void lm3s6965evb_init(ram_addr_t 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
)
1185 stellaris_init(kernel_filename
, cpu_model
, ds
, &stellaris_boards
[1]);
1188 QEMUMachine lm3s811evb_machine
= {
1190 "Stellaris LM3S811EVB",
1192 (64 * 1024 + 8 * 1024) | RAMSIZE_FIXED
,
1195 QEMUMachine lm3s6965evb_machine
= {
1197 "Stellaris LM3S6965EVB",
1199 (256 * 1024 + 64 * 1024) | RAMSIZE_FIXED
,