/*
- * Luminary Micro Stellaris preipherals
+ * Luminary Micro Stellaris peripherals
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
#include "qemu-timer.h"
#include "i2c.h"
#include "net.h"
+#include "sd.h"
#include "sysemu.h"
#include "boards.h"
return qi[0];
}
+/* Some boards have both an OLED controller and SD card connected to
+ the same SSI port, with the SD card chip select connected to a
+ GPIO pin. Technically the OLED chip select is connected to the SSI
+ Fss pin. We do not bother emulating that as both devices should
+ never be selected simultaneously, and our OLED controller ignores stray
+ 0xff commands that occur when deselecting the SD card. */
+
+typedef struct {
+ ssi_xfer_cb xfer_cb[2];
+ void *opaque[2];
+ qemu_irq irq;
+ int current_dev;
+} stellaris_ssi_bus_state;
+
+static void stellaris_ssi_bus_select(void *opaque, int irq, int level)
+{
+ stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
+
+ s->current_dev = level;
+}
+
+static int stellaris_ssi_bus_xfer(void *opaque, int val)
+{
+ stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
+
+ return s->xfer_cb[s->current_dev](s->opaque[s->current_dev], val);
+}
+
+static void *stellaris_ssi_bus_init(qemu_irq *irqp,
+ ssi_xfer_cb cb0, void *opaque0,
+ ssi_xfer_cb cb1, void *opaque1)
+{
+ qemu_irq *qi;
+ stellaris_ssi_bus_state *s;
+
+ s = (stellaris_ssi_bus_state *)qemu_mallocz(sizeof(stellaris_ssi_bus_state));
+ s->xfer_cb[0] = cb0;
+ s->opaque[0] = opaque0;
+ s->xfer_cb[1] = cb1;
+ s->opaque[1] = opaque1;
+ qi = qemu_allocate_irqs(stellaris_ssi_bus_select, s, 1);
+ *irqp = *qi;
+ return s;
+}
+
/* Board init. */
static stellaris_board_info stellaris_boards[] = {
{ "LM3S811EVB",
if (board->dc2 & (1 << 4)) {
if (board->peripherals & BP_OLED_SSI) {
void * oled;
- /* FIXME: Implement chip select for OLED/MMC. */
+ void * sd;
+ void *ssi_bus;
+ int index;
+
oled = ssd0323_init(ds, &gpio_out[GPIO_C][7]);
- pl022_init(0x40008000, pic[7], ssd0323_xfer_ssi, oled);
+ index = drive_get_index(IF_SD, 0, 0);
+ sd = ssi_sd_init(drives_table[index].bdrv);
+
+ ssi_bus = stellaris_ssi_bus_init(&gpio_out[GPIO_D][0],
+ ssi_sd_xfer, sd,
+ ssd0323_xfer_ssi, oled);
+
+ pl022_init(0x40008000, pic[7], stellaris_ssi_bus_xfer, ssi_bus);
+ /* Make sure the select pin is high. */
+ qemu_irq_raise(gpio_out[GPIO_D][0]);
} else {
pl022_init(0x40008000, pic[7], NULL, NULL);
}
}
/* FIXME: Figure out how to generate these from stellaris_boards. */
-static void lm3s811evb_init(int ram_size, int vga_ram_size,
+static void lm3s811evb_init(ram_addr_t ram_size, int vga_ram_size,
const char *boot_device, DisplayState *ds,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
stellaris_init(kernel_filename, cpu_model, ds, &stellaris_boards[0]);
}
-static void lm3s6965evb_init(int ram_size, int vga_ram_size,
+static void lm3s6965evb_init(ram_addr_t ram_size, int vga_ram_size,
const char *boot_device, DisplayState *ds,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
"lm3s811evb",
"Stellaris LM3S811EVB",
lm3s811evb_init,
+ (64 * 1024 + 8 * 1024) | RAMSIZE_FIXED,
};
QEMUMachine lm3s6965evb_machine = {
"lm3s6965evb",
"Stellaris LM3S6965EVB",
lm3s6965evb_init,
+ (256 * 1024 + 64 * 1024) | RAMSIZE_FIXED,
};