diff options
-rw-r--r-- | hw/armv7m.c | 41 | ||||
-rw-r--r-- | hw/pl061.c | 28 | ||||
-rw-r--r-- | hw/primecell.h | 4 | ||||
-rw-r--r-- | hw/stellaris.c | 75 |
4 files changed, 97 insertions, 51 deletions
diff --git a/hw/armv7m.c b/hw/armv7m.c index e3d00ffd7b..9657ed1f16 100644 --- a/hw/armv7m.c +++ b/hw/armv7m.c @@ -117,18 +117,35 @@ static CPUWriteMemoryFunc *bitband_writefn[] = { bitband_writel }; -static void armv7m_bitband_init(void) +typedef struct { + SysBusDevice busdev; + uint32_t base; +} BitBandState; + +static void bitband_init(SysBusDevice *dev) { + BitBandState *s = FROM_SYSBUS(BitBandState, dev); int iomemtype; - static uint32_t bitband1_offset = 0x20000000; - static uint32_t bitband2_offset = 0x40000000; + s->base = qdev_get_prop_int(&dev->qdev, "base", 0); iomemtype = cpu_register_io_memory(0, bitband_readfn, bitband_writefn, - &bitband1_offset); - cpu_register_physical_memory(0x22000000, 0x02000000, iomemtype); - iomemtype = cpu_register_io_memory(0, bitband_readfn, bitband_writefn, - &bitband2_offset); - cpu_register_physical_memory(0x42000000, 0x02000000, iomemtype); + &s->base); + sysbus_init_mmio(dev, 0x02000000, iomemtype); +} + +static void armv7m_bitband_init(void) +{ + DeviceState *dev; + + dev = qdev_create(NULL, "ARM,bitband-memory"); + qdev_set_prop_int(dev, "base", 0x20000000); + qdev_init(dev); + sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x22000000); + + dev = qdev_create(NULL, "ARM,bitband-memory"); + qdev_set_prop_int(dev, "base", 0x40000000); + qdev_init(dev); + sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x42000000); } /* Board init. */ @@ -220,3 +237,11 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, return pic; } + +static void armv7m_register_devices(void) +{ + sysbus_register_dev("ARM,bitband-memory", sizeof(BitBandState), + bitband_init); +} + +device_init(armv7m_register_devices) diff --git a/hw/pl061.c b/hw/pl061.c index 1263992bb8..aa0a322237 100644 --- a/hw/pl061.c +++ b/hw/pl061.c @@ -8,8 +8,7 @@ * This code is licenced under the GPL. */ -#include "hw.h" -#include "primecell.h" +#include "sysbus.h" //#define DEBUG_PL061 1 @@ -28,6 +27,7 @@ static const uint8_t pl061_id[12] = { 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 }; typedef struct { + SysBusDevice busdev; int locked; uint8_t data; uint8_t old_data; @@ -291,21 +291,25 @@ static int pl061_load(QEMUFile *f, void *opaque, int version_id) return 0; } -/* Returns an array of inputs. */ -qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out) +static void pl061_init(SysBusDevice *dev) { int iomemtype; - pl061_state *s; + pl061_state *s = FROM_SYSBUS(pl061_state, dev); - s = (pl061_state *)qemu_mallocz(sizeof(pl061_state)); iomemtype = cpu_register_io_memory(0, pl061_readfn, pl061_writefn, s); - cpu_register_physical_memory(base, 0x00001000, iomemtype); - s->irq = irq; + sysbus_init_mmio(dev, 0x1000, iomemtype); + sysbus_init_irq(dev, &s->irq); + qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8); + qdev_init_gpio_out(&dev->qdev, s->out, 8); pl061_reset(s); - if (out) - *out = s->out; - register_savevm("pl061_gpio", -1, 1, pl061_save, pl061_load, s); - return qemu_allocate_irqs(pl061_set_irq, s, 8); } + +static void pl061_register_devices(void) +{ + sysbus_register_dev("pl061", sizeof(pl061_state), + pl061_init); +} + +device_init(pl061_register_devices) diff --git a/hw/primecell.h b/hw/primecell.h index 3e24eb199c..490ef8cc97 100644 --- a/hw/primecell.h +++ b/hw/primecell.h @@ -5,10 +5,6 @@ /* Also includes some devices that are currently only used by the ARM boards. */ -/* pl061.c */ -void pl061_float_high(void *opaque, uint8_t mask); -qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out); - /* pl080.c */ void *pl080_init(uint32_t base, qemu_irq irq, int nchannels); diff --git a/hw/stellaris.c b/hw/stellaris.c index d0918deacb..38b9830e27 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -10,7 +10,6 @@ #include "sysbus.h" #include "ssi.h" #include "arm-misc.h" -#include "primecell.h" #include "devices.h" #include "qemu-timer.h" #include "i2c.h" @@ -45,6 +44,7 @@ typedef const struct { /* General purpose timer module. */ typedef struct gptm_state { + SysBusDevice busdev; uint32_t config; uint32_t mode[2]; uint32_t control; @@ -112,8 +112,7 @@ static void gptm_tick(void *opaque) s->state |= 1; if ((s->control & 0x20)) { /* Output trigger. */ - qemu_irq_raise(s->trigger); - qemu_irq_lower(s->trigger); + qemu_irq_pulse(s->trigger); } if (s->mode[0] & 1) { /* One-shot. */ @@ -340,19 +339,19 @@ static int gptm_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void stellaris_gptm_init(uint32_t base, qemu_irq irq, qemu_irq trigger) +static void stellaris_gptm_init(SysBusDevice *dev) { int iomemtype; - gptm_state *s; + gptm_state *s = FROM_SYSBUS(gptm_state, dev); - s = (gptm_state *)qemu_mallocz(sizeof(gptm_state)); - s->irq = irq; - s->trigger = trigger; - s->opaque[0] = s->opaque[1] = s; + sysbus_init_irq(dev, &s->irq); + qdev_init_gpio_out(&dev->qdev, &s->trigger, 1); iomemtype = cpu_register_io_memory(0, gptm_readfn, gptm_writefn, s); - cpu_register_physical_memory(base, 0x00001000, iomemtype); + sysbus_init_mmio(dev, 0x1000, iomemtype); + + s->opaque[0] = s->opaque[1] = s; s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]); s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]); register_savevm("stellaris_gptm", -1, 1, gptm_save, gptm_load, s); @@ -906,6 +905,7 @@ static void stellaris_i2c_init(SysBusDevice * dev) typedef struct { + SysBusDevice busdev; uint32_t actss; uint32_t ris; uint32_t im; @@ -1178,26 +1178,23 @@ static int stellaris_adc_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq *irq) +static void stellaris_adc_init(SysBusDevice *dev) { - stellaris_adc_state *s; + stellaris_adc_state *s = FROM_SYSBUS(stellaris_adc_state, dev); int iomemtype; - qemu_irq *qi; int n; - s = (stellaris_adc_state *)qemu_mallocz(sizeof(stellaris_adc_state)); for (n = 0; n < 4; n++) { - s->irq[n] = irq[n]; + sysbus_init_irq(dev, &s->irq[n]); } iomemtype = cpu_register_io_memory(0, stellaris_adc_readfn, stellaris_adc_writefn, s); - cpu_register_physical_memory(base, 0x00001000, iomemtype); + sysbus_init_mmio(dev, 0x1000, iomemtype); stellaris_adc_reset(s); - qi = qemu_allocate_irqs(stellaris_adc_trigger, s, 1); + qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1); register_savevm("stellaris_adc", -1, 1, stellaris_adc_save, stellaris_adc_load, s); - return qi[0]; } /* Some boards have both an OLED controller and SD card connected to @@ -1294,27 +1291,36 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31}; qemu_irq *pic; - qemu_irq *gpio_in[7]; - qemu_irq *gpio_out[7]; + DeviceState *gpio_dev[7]; + qemu_irq gpio_in[7][8]; + qemu_irq gpio_out[7][8]; qemu_irq adc; int sram_size; int flash_size; i2c_bus *i2c; + DeviceState *dev; int i; + int j; flash_size = ((board->dc0 & 0xffff) + 1) << 1; sram_size = (board->dc0 >> 18) + 1; pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model); if (board->dc1 & (1 << 16)) { - adc = stellaris_adc_init(0x40038000, pic + 14); + dev = sysbus_create_varargs("stellaris-adc", 0x40038000, + pic[14], pic[15], pic[16], pic[17], NULL); + adc = qdev_get_gpio_in(dev, 0); } else { adc = NULL; } for (i = 0; i < 4; i++) { if (board->dc2 & (0x10000 << i)) { - stellaris_gptm_init(0x40030000 + i * 0x1000, - pic[timer_irq[i]], adc); + dev = sysbus_create_simple("stellaris-gptm", + 0x40030000 + i * 0x1000, + pic[timer_irq[i]]); + /* TODO: This is incorrect, but we get away with it because + the ADC output is only ever pulsed. */ + qdev_connect_gpio_out(dev, 0, adc); } } @@ -1322,13 +1328,16 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, for (i = 0; i < 7; i++) { if (board->dc4 & (1 << i)) { - gpio_in[i] = pl061_init(gpio_addr[i], pic[gpio_irq[i]], - &gpio_out[i]); + gpio_dev[i] = sysbus_create_simple("pl061", gpio_addr[i], + pic[gpio_irq[i]]); + for (j = 0; j < 8; j++) { + gpio_in[i][j] = qdev_get_gpio_in(gpio_dev[i], j); + gpio_out[i][j] = NULL; + } } } if (board->dc2 & (1 << 12)) { - DeviceState *dev; dev = sysbus_create_simple("stellaris-i2c", 0x40020000, pic[8]); i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); if (board->peripherals & BP_OLED_I2C) { @@ -1343,7 +1352,6 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, } } if (board->dc2 & (1 << 4)) { - DeviceState *dev; dev = sysbus_create_simple("pl022", 0x40008000, pic[7]); if (board->peripherals & BP_OLED_SSI) { DeviceState *mux; @@ -1387,6 +1395,15 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, stellaris_gamepad_init(5, gpad_irq, gpad_keycode); } + for (i = 0; i < 7; i++) { + if (board->dc4 & (1 << i)) { + for (j = 0; j < 8; j++) { + if (gpio_out[i][j]) { + qdev_connect_gpio_out(gpio_dev[i], j, gpio_out[i][j]); + } + } + } + } } /* FIXME: Figure out how to generate these from stellaris_boards. */ @@ -1435,6 +1452,10 @@ static void stellaris_register_devices(void) { sysbus_register_dev("stellaris-i2c", sizeof(stellaris_i2c_state), stellaris_i2c_init); + sysbus_register_dev("stellaris-gptm", sizeof(gptm_state), + stellaris_gptm_init); + sysbus_register_dev("stellaris-adc", sizeof(stellaris_adc_state), + stellaris_adc_init); ssi_register_slave("evb6965-ssi", sizeof(stellaris_ssi_bus_state), &stellaris_ssi_bus_info); } |