Stellaris SSI qdev conversion

Signed-off-by: Paul Brook <paul@codesourcery.com>
This commit is contained in:
Paul Brook 2009-05-14 22:35:09 +01:00
parent 90d37239d4
commit 5493e33f12
7 changed files with 95 additions and 80 deletions

View File

@ -6,10 +6,6 @@
/* smc91c111.c */ /* smc91c111.c */
void smc91c111_init(NICInfo *, uint32_t, qemu_irq); void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
/* ssd0323.c */
int ssd0323_xfer_ssi(void *opaque, int data);
void *ssd0323_init(qemu_irq *cmd_p);
/* ads7846.c */ /* ads7846.c */
typedef struct ADS7846State ADS7846State; typedef struct ADS7846State ADS7846State;
uint32_t ads7846_read(void *opaque); uint32_t ads7846_read(void *opaque);

View File

@ -7,7 +7,8 @@
* This code is licenced under the GPL. * This code is licenced under the GPL.
*/ */
#include "hw.h" #include "sysbus.h"
#include "ssi.h"
#include "primecell.h" #include "primecell.h"
//#define DEBUG_PL022 1 //#define DEBUG_PL022 1
@ -40,6 +41,7 @@ do { fprintf(stderr, "pl022: error: " fmt , ## __VA_ARGS__);} while (0)
#define PL022_INT_TX 0x08 #define PL022_INT_TX 0x08
typedef struct { typedef struct {
SysBusDevice busdev;
uint32_t cr0; uint32_t cr0;
uint32_t cr1; uint32_t cr1;
uint32_t bitmask; uint32_t bitmask;
@ -55,8 +57,7 @@ typedef struct {
uint16_t tx_fifo[8]; uint16_t tx_fifo[8];
uint16_t rx_fifo[8]; uint16_t rx_fifo[8];
qemu_irq irq; qemu_irq irq;
int (*xfer_cb)(void *, int); SSIBus *ssi;
void *opaque;
} pl022_state; } pl022_state;
static const unsigned char pl022_id[8] = static const unsigned char pl022_id[8] =
@ -116,10 +117,8 @@ static void pl022_xfer(pl022_state *s)
val = s->tx_fifo[i]; val = s->tx_fifo[i];
if (s->cr1 & PL022_CR1_LBM) { if (s->cr1 & PL022_CR1_LBM) {
/* Loopback mode. */ /* Loopback mode. */
} else if (s->xfer_cb) {
val = s->xfer_cb(s->opaque, val);
} else { } else {
val = 0; val = ssi_transfer(s->ssi, val);
} }
s->rx_fifo[o] = val & s->bitmask; s->rx_fifo[o] = val & s->bitmask;
i = (i + 1) & 7; i = (i + 1) & 7;
@ -289,19 +288,24 @@ static int pl022_load(QEMUFile *f, void *opaque, int version_id)
return 0; return 0;
} }
void pl022_init(uint32_t base, qemu_irq irq, int (*xfer_cb)(void *, int), static void pl022_init(SysBusDevice *dev)
void * opaque)
{ {
pl022_state *s = FROM_SYSBUS(pl022_state, dev);
int iomemtype; int iomemtype;
pl022_state *s;
s = (pl022_state *)qemu_mallocz(sizeof(pl022_state));
iomemtype = cpu_register_io_memory(0, pl022_readfn, iomemtype = cpu_register_io_memory(0, pl022_readfn,
pl022_writefn, s); pl022_writefn, s);
cpu_register_physical_memory(base, 0x00001000, iomemtype); sysbus_init_mmio(dev, 0x1000, iomemtype);
s->irq = irq; sysbus_init_irq(dev, &s->irq);
s->xfer_cb = xfer_cb; s->ssi = ssi_create_bus();
s->opaque = opaque; qdev_attach_child_bus(&dev->qdev, "ssi", s->ssi);
pl022_reset(s); pl022_reset(s);
register_savevm("pl022_ssp", -1, 1, pl022_save, pl022_load, s); register_savevm("pl022_ssp", -1, 1, pl022_save, pl022_load, s);
} }
static void pl022_register_devices(void)
{
sysbus_register_dev("pl022", sizeof(pl022_state), pl022_init);
}
device_init(pl022_register_devices)

View File

@ -5,11 +5,6 @@
/* Also includes some devices that are currently only used by the /* Also includes some devices that are currently only used by the
ARM boards. */ ARM boards. */
/* pl022.c */
typedef int (*ssi_xfer_cb)(void *, int);
void pl022_init(uint32_t base, qemu_irq irq, ssi_xfer_cb xfer_cb,
void *opaque);
/* pl061.c */ /* pl061.c */
void pl061_float_high(void *opaque, uint8_t mask); void pl061_float_high(void *opaque, uint8_t mask);
qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out); qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out);

View File

@ -76,8 +76,4 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert);
int sd_data_ready(SDState *sd); int sd_data_ready(SDState *sd);
void sd_enable(SDState *sd, int enable); void sd_enable(SDState *sd, int enable);
/* ssi-sd.c */
int ssi_sd_xfer(void *opaque, int val);
void *ssi_sd_init(BlockDriverState *bs);
#endif /* __hw_sd_h */ #endif /* __hw_sd_h */

View File

@ -10,8 +10,7 @@
/* The controller can support a variety of different displays, but we only /* The controller can support a variety of different displays, but we only
implement one. Most of the commends relating to brightness and geometry implement one. Most of the commends relating to brightness and geometry
setup are ignored. */ setup are ignored. */
#include "hw.h" #include "ssi.h"
#include "devices.h"
#include "console.h" #include "console.h"
//#define DEBUG_SSD0323 1 //#define DEBUG_SSD0323 1
@ -43,6 +42,7 @@ enum ssd0323_mode
}; };
typedef struct { typedef struct {
SSISlave ssidev;
DisplayState *ds; DisplayState *ds;
int cmd_len; int cmd_len;
@ -60,9 +60,10 @@ typedef struct {
uint8_t framebuffer[128 * 80 / 2]; uint8_t framebuffer[128 * 80 / 2];
} ssd0323_state; } ssd0323_state;
int ssd0323_xfer_ssi(void *opaque, int data) static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data)
{ {
ssd0323_state *s = (ssd0323_state *)opaque; ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev);
switch (s->mode) { switch (s->mode) {
case SSD0323_DATA: case SSD0323_DATA:
DPRINTF("data 0x%02x\n", data); DPRINTF("data 0x%02x\n", data);
@ -321,12 +322,10 @@ static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
return 0; return 0;
} }
void *ssd0323_init(qemu_irq *cmd_p) static void ssd0323_init(SSISlave *dev)
{ {
ssd0323_state *s; ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev);
qemu_irq *cmd;
s = (ssd0323_state *)qemu_mallocz(sizeof(ssd0323_state));
s->col_end = 63; s->col_end = 63;
s->row_end = 79; s->row_end = 79;
s->ds = graphic_console_init(ssd0323_update_display, s->ds = graphic_console_init(ssd0323_update_display,
@ -334,10 +333,19 @@ void *ssd0323_init(qemu_irq *cmd_p)
NULL, NULL, s); NULL, NULL, s);
qemu_console_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY); qemu_console_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY);
cmd = qemu_allocate_irqs(ssd0323_cd, s, 1); qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
*cmd_p = *cmd;
register_savevm("ssd0323_oled", -1, 1, ssd0323_save, ssd0323_load, s); register_savevm("ssd0323_oled", -1, 1, ssd0323_save, ssd0323_load, s);
return s;
} }
static SSISlaveInfo ssd0323_info = {
.init = ssd0323_init,
.transfer = ssd0323_transfer
};
static void ssd03232_register_devices(void)
{
ssi_register_slave("ssd0323", sizeof(ssd0323_state), &ssd0323_info);
}
device_init(ssd03232_register_devices)

View File

@ -1,14 +1,15 @@
/* /*
* SSI to SD card adapter. * SSI to SD card adapter.
* *
* Copyright (c) 2007 CodeSourcery. * Copyright (c) 2007-2009 CodeSourcery.
* Written by Paul Brook * Written by Paul Brook
* *
* This code is licenced under the GPL. * This code is licenced under the GNU GPL v2.
*/ */
#include "hw.h" #include "ssi.h"
#include "sd.h" #include "sd.h"
#include "sysemu.h"
//#define DEBUG_SSI_SD 1 //#define DEBUG_SSI_SD 1
@ -32,6 +33,7 @@ typedef enum {
} ssi_sd_mode; } ssi_sd_mode;
typedef struct { typedef struct {
SSISlave ssidev;
ssi_sd_mode mode; ssi_sd_mode mode;
int cmd; int cmd;
uint8_t cmdarg[4]; uint8_t cmdarg[4];
@ -59,9 +61,9 @@ typedef struct {
#define SSI_SDR_ADDRESS_ERROR 0x2000 #define SSI_SDR_ADDRESS_ERROR 0x2000
#define SSI_SDR_PARAMETER_ERROR 0x4000 #define SSI_SDR_PARAMETER_ERROR 0x4000
int ssi_sd_xfer(void *opaque, int val) static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
{ {
ssi_sd_state *s = (ssi_sd_state *)opaque; ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev);
/* Special case: allow CMD12 (STOP TRANSMISSION) while reading data. */ /* Special case: allow CMD12 (STOP TRANSMISSION) while reading data. */
if (s->mode == SSI_SD_DATA_READ && val == 0x4d) { if (s->mode == SSI_SD_DATA_READ && val == 0x4d) {
@ -227,13 +229,25 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
return 0; return 0;
} }
void *ssi_sd_init(BlockDriverState *bs) static void ssi_sd_init(SSISlave *dev)
{ {
ssi_sd_state *s; ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev);
BlockDriverState *bs;
s = (ssi_sd_state *)qemu_mallocz(sizeof(ssi_sd_state));
s->mode = SSI_SD_CMD; s->mode = SSI_SD_CMD;
bs = qdev_init_bdrv(&dev->qdev, IF_SD);
s->sd = sd_init(bs, 1); s->sd = sd_init(bs, 1);
register_savevm("ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s); register_savevm("ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
return s;
} }
static SSISlaveInfo ssi_sd_info = {
.init = ssi_sd_init,
.transfer = ssi_sd_transfer
};
static void ssi_sd_register_devices(void)
{
ssi_register_slave("ssi-sd", sizeof(ssi_sd_state), &ssi_sd_info);
}
device_init(ssi_sd_register_devices)

View File

@ -8,13 +8,13 @@
*/ */
#include "sysbus.h" #include "sysbus.h"
#include "ssi.h"
#include "arm-misc.h" #include "arm-misc.h"
#include "primecell.h" #include "primecell.h"
#include "devices.h" #include "devices.h"
#include "qemu-timer.h" #include "qemu-timer.h"
#include "i2c.h" #include "i2c.h"
#include "net.h" #include "net.h"
#include "sd.h"
#include "sysemu.h" #include "sysemu.h"
#include "boards.h" #include "boards.h"
@ -1196,10 +1196,10 @@ static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq irq)
0xff commands that occur when deselecting the SD card. */ 0xff commands that occur when deselecting the SD card. */
typedef struct { typedef struct {
ssi_xfer_cb xfer_cb[2]; SSISlave ssidev;
void *opaque[2];
qemu_irq irq; qemu_irq irq;
int current_dev; int current_dev;
SSIBus *bus[2];
} stellaris_ssi_bus_state; } stellaris_ssi_bus_state;
static void stellaris_ssi_bus_select(void *opaque, int irq, int level) static void stellaris_ssi_bus_select(void *opaque, int irq, int level)
@ -1209,11 +1209,11 @@ static void stellaris_ssi_bus_select(void *opaque, int irq, int level)
s->current_dev = level; s->current_dev = level;
} }
static int stellaris_ssi_bus_xfer(void *opaque, int val) static uint32_t stellaris_ssi_bus_transfer(SSISlave *dev, uint32_t val)
{ {
stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque; stellaris_ssi_bus_state *s = FROM_SSI_SLAVE(stellaris_ssi_bus_state, dev);
return s->xfer_cb[s->current_dev](s->opaque[s->current_dev], val); return ssi_transfer(s->bus[s->current_dev], val);
} }
static void stellaris_ssi_bus_save(QEMUFile *f, void *opaque) static void stellaris_ssi_bus_save(QEMUFile *f, void *opaque)
@ -1235,23 +1235,18 @@ static int stellaris_ssi_bus_load(QEMUFile *f, void *opaque, int version_id)
return 0; return 0;
} }
static void *stellaris_ssi_bus_init(qemu_irq *irqp, static void stellaris_ssi_bus_init(SSISlave *dev)
ssi_xfer_cb cb0, void *opaque0,
ssi_xfer_cb cb1, void *opaque1)
{ {
qemu_irq *qi; stellaris_ssi_bus_state *s = FROM_SSI_SLAVE(stellaris_ssi_bus_state, dev);
stellaris_ssi_bus_state *s;
s->bus[0] = ssi_create_bus();
qdev_attach_child_bus(&dev->qdev, "ssi0", s->bus[0]);
s->bus[1] = ssi_create_bus();
qdev_attach_child_bus(&dev->qdev, "ssi1", s->bus[1]);
qdev_init_gpio_in(&dev->qdev, stellaris_ssi_bus_select, 1);
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;
register_savevm("stellaris_ssi_bus", -1, 1, register_savevm("stellaris_ssi_bus", -1, 1,
stellaris_ssi_bus_save, stellaris_ssi_bus_load, s); stellaris_ssi_bus_save, stellaris_ssi_bus_load, s);
return s;
} }
/* Board init. */ /* Board init. */
@ -1338,25 +1333,25 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
} }
} }
if (board->dc2 & (1 << 4)) { if (board->dc2 & (1 << 4)) {
DeviceState *dev;
dev = sysbus_create_simple("pl022", 0x40008000, pic[7]);
if (board->peripherals & BP_OLED_SSI) { if (board->peripherals & BP_OLED_SSI) {
void * oled; DeviceState *mux;
void * sd; void *bus;
void *ssi_bus;
int index;
oled = ssd0323_init(&gpio_out[GPIO_C][7]); bus = qdev_get_child_bus(dev, "ssi");
index = drive_get_index(IF_SD, 0, 0); mux = ssi_create_slave(bus, "evb6965-ssi");
sd = ssi_sd_init(drives_table[index].bdrv); gpio_out[GPIO_D][0] = qdev_get_gpio_in(mux, 0);
ssi_bus = stellaris_ssi_bus_init(&gpio_out[GPIO_D][0], bus = qdev_get_child_bus(mux, "ssi0");
ssi_sd_xfer, sd, dev = ssi_create_slave(bus, "ssi-sd");
ssd0323_xfer_ssi, oled);
bus = qdev_get_child_bus(mux, "ssi1");
dev = ssi_create_slave(bus, "ssd0323");
gpio_out[GPIO_C][7] = qdev_get_gpio_in(dev, 0);
pl022_init(0x40008000, pic[7], stellaris_ssi_bus_xfer, ssi_bus);
/* Make sure the select pin is high. */ /* Make sure the select pin is high. */
qemu_irq_raise(gpio_out[GPIO_D][0]); qemu_irq_raise(gpio_out[GPIO_D][0]);
} else {
pl022_init(0x40008000, pic[7], NULL, NULL);
} }
} }
if (board->dc4 & (1 << 28)) { if (board->dc4 & (1 << 28)) {
@ -1413,10 +1408,17 @@ QEMUMachine lm3s6965evb_machine = {
.init = lm3s6965evb_init, .init = lm3s6965evb_init,
}; };
static SSISlaveInfo stellaris_ssi_bus_info = {
.init = stellaris_ssi_bus_init,
.transfer = stellaris_ssi_bus_transfer
};
static void stellaris_register_devices(void) static void stellaris_register_devices(void)
{ {
sysbus_register_dev("stellaris-i2c", sizeof(stellaris_i2c_state), sysbus_register_dev("stellaris-i2c", sizeof(stellaris_i2c_state),
stellaris_i2c_init); stellaris_i2c_init);
ssi_register_slave("evb6965-ssi", sizeof(stellaris_ssi_bus_state),
&stellaris_ssi_bus_info);
} }
device_init(stellaris_register_devices) device_init(stellaris_register_devices)