* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
*
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
*/
#include "sysbus.h"
#include "i2c.h"
#include "net.h"
#include "boards.h"
+#include "exec-memory.h"
#define GPIO_A 0
#define GPIO_B 1
typedef struct gptm_state {
SysBusDevice busdev;
+ MemoryRegion iomem;
uint32_t config;
uint32_t mode[2];
uint32_t control;
gptm_update_irq(s);
}
-static uint32_t gptm_read(void *opaque, target_phys_addr_t offset)
+static uint64_t gptm_read(void *opaque, target_phys_addr_t offset,
+ unsigned size)
{
gptm_state *s = (gptm_state *)opaque;
}
}
-static void gptm_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+static void gptm_write(void *opaque, target_phys_addr_t offset,
+ uint64_t value, unsigned size)
{
gptm_state *s = (gptm_state *)opaque;
uint32_t oldval;
gptm_update_irq(s);
}
-static CPUReadMemoryFunc * const gptm_readfn[] = {
- gptm_read,
- gptm_read,
- gptm_read
-};
-
-static CPUWriteMemoryFunc * const gptm_writefn[] = {
- gptm_write,
- gptm_write,
- gptm_write
+static const MemoryRegionOps gptm_ops = {
+ .read = gptm_read,
+ .write = gptm_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
static const VMStateDescription vmstate_stellaris_gptm = {
static int stellaris_gptm_init(SysBusDevice *dev)
{
- int iomemtype;
gptm_state *s = FROM_SYSBUS(gptm_state, dev);
sysbus_init_irq(dev, &s->irq);
qdev_init_gpio_out(&dev->qdev, &s->trigger, 1);
- iomemtype = cpu_register_io_memory(gptm_readfn,
- gptm_writefn, s,
- DEVICE_NATIVE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, iomemtype);
+ memory_region_init_io(&s->iomem, &gptm_ops, s,
+ "gptm", 0x1000);
+ sysbus_init_mmio(dev, &s->iomem);
s->opaque[0] = s->opaque[1] = s;
s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
/* System controller. */
typedef struct {
+ MemoryRegion iomem;
uint32_t pborctl;
uint32_t ldopctl;
uint32_t int_status;
uint32_t int_mask;
uint32_t resc;
uint32_t rcc;
+ uint32_t rcc2;
uint32_t rcgc[3];
uint32_t scgc[3];
uint32_t dcgc[3];
0xb11c /* 8.192 Mhz */
};
-static uint32_t ssys_read(void *opaque, target_phys_addr_t offset)
+#define DID0_VER_MASK 0x70000000
+#define DID0_VER_0 0x00000000
+#define DID0_VER_1 0x10000000
+
+#define DID0_CLASS_MASK 0x00FF0000
+#define DID0_CLASS_SANDSTORM 0x00000000
+#define DID0_CLASS_FURY 0x00010000
+
+static int ssys_board_class(const ssys_state *s)
+{
+ uint32_t did0 = s->board->did0;
+ switch (did0 & DID0_VER_MASK) {
+ case DID0_VER_0:
+ return DID0_CLASS_SANDSTORM;
+ case DID0_VER_1:
+ switch (did0 & DID0_CLASS_MASK) {
+ case DID0_CLASS_SANDSTORM:
+ case DID0_CLASS_FURY:
+ return did0 & DID0_CLASS_MASK;
+ }
+ /* for unknown classes, fall through */
+ default:
+ hw_error("ssys_board_class: Unknown class 0x%08x\n", did0);
+ }
+}
+
+static uint64_t ssys_read(void *opaque, target_phys_addr_t offset,
+ unsigned size)
{
ssys_state *s = (ssys_state *)opaque;
{
int xtal;
xtal = (s->rcc >> 6) & 0xf;
- if (s->board->did0 & (1 << 16)) {
+ switch (ssys_board_class(s)) {
+ case DID0_CLASS_FURY:
return pllcfg_fury[xtal];
- } else {
+ case DID0_CLASS_SANDSTORM:
return pllcfg_sandstorm[xtal];
+ default:
+ hw_error("ssys_read: Unhandled class for PLLCFG read.\n");
+ return 0;
}
}
+ case 0x070: /* RCC2 */
+ return s->rcc2;
case 0x100: /* RCGC0 */
return s->rcgc[0];
case 0x104: /* RCGC1 */
}
}
+static bool ssys_use_rcc2(ssys_state *s)
+{
+ return (s->rcc2 >> 31) & 0x1;
+}
+
+/*
+ * Caculate the sys. clock period in ms.
+ */
static void ssys_calculate_system_clock(ssys_state *s)
{
- system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
+ if (ssys_use_rcc2(s)) {
+ system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
+ } else {
+ system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
+ }
}
-static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+static void ssys_write(void *opaque, target_phys_addr_t offset,
+ uint64_t value, unsigned size)
{
ssys_state *s = (ssys_state *)opaque;
s->rcc = value;
ssys_calculate_system_clock(s);
break;
+ case 0x070: /* RCC2 */
+ if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
+ break;
+ }
+
+ if ((s->rcc2 & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
+ /* PLL enable. */
+ s->int_status |= (1 << 6);
+ }
+ s->rcc2 = value;
+ ssys_calculate_system_clock(s);
+ break;
case 0x100: /* RCGC0 */
s->rcgc[0] = value;
break;
ssys_update(s);
}
-static CPUReadMemoryFunc * const ssys_readfn[] = {
- ssys_read,
- ssys_read,
- ssys_read
-};
-
-static CPUWriteMemoryFunc * const ssys_writefn[] = {
- ssys_write,
- ssys_write,
- ssys_write
+static const MemoryRegionOps ssys_ops = {
+ .read = ssys_read,
+ .write = ssys_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
static void ssys_reset(void *opaque)
s->pborctl = 0x7ffd;
s->rcc = 0x078e3ac0;
+
+ if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
+ s->rcc2 = 0;
+ } else {
+ s->rcc2 = 0x07802810;
+ }
s->rcgc[0] = 1;
s->scgc[0] = 1;
s->dcgc[0] = 1;
+ ssys_calculate_system_clock(s);
}
static int stellaris_sys_post_load(void *opaque, int version_id)
static const VMStateDescription vmstate_stellaris_sys = {
.name = "stellaris_sys",
- .version_id = 1,
+ .version_id = 2,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.post_load = stellaris_sys_post_load,
VMSTATE_UINT32(int_status, ssys_state),
VMSTATE_UINT32(resc, ssys_state),
VMSTATE_UINT32(rcc, ssys_state),
+ VMSTATE_UINT32_V(rcc2, ssys_state, 2),
VMSTATE_UINT32_ARRAY(rcgc, ssys_state, 3),
VMSTATE_UINT32_ARRAY(scgc, ssys_state, 3),
VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
stellaris_board_info * board,
uint8_t *macaddr)
{
- int iomemtype;
ssys_state *s;
- s = (ssys_state *)qemu_mallocz(sizeof(ssys_state));
+ s = (ssys_state *)g_malloc0(sizeof(ssys_state));
s->irq = irq;
s->board = board;
/* Most devices come preprogrammed with a MAC address in the user data. */
s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
- iomemtype = cpu_register_io_memory(ssys_readfn,
- ssys_writefn, s,
- DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(base, 0x00001000, iomemtype);
+ memory_region_init_io(&s->iomem, &ssys_ops, s, "ssys", 0x00001000);
+ memory_region_add_subregion(get_system_memory(), base, &s->iomem);
ssys_reset(s);
vmstate_register(NULL, -1, &vmstate_stellaris_sys, s);
return 0;
SysBusDevice busdev;
i2c_bus *bus;
qemu_irq irq;
+ MemoryRegion iomem;
uint32_t msa;
uint32_t mcs;
uint32_t mdr;
#define STELLARIS_I2C_MCS_IDLE 0x20
#define STELLARIS_I2C_MCS_BUSBSY 0x40
-static uint32_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset)
+static uint64_t stellaris_i2c_read(void *opaque, target_phys_addr_t offset,
+ unsigned size)
{
stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
}
static void stellaris_i2c_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
+ uint64_t value, unsigned size)
{
stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
stellaris_i2c_update(s);
}
-static CPUReadMemoryFunc * const stellaris_i2c_readfn[] = {
- stellaris_i2c_read,
- stellaris_i2c_read,
- stellaris_i2c_read
-};
-
-static CPUWriteMemoryFunc * const stellaris_i2c_writefn[] = {
- stellaris_i2c_write,
- stellaris_i2c_write,
- stellaris_i2c_write
+static const MemoryRegionOps stellaris_i2c_ops = {
+ .read = stellaris_i2c_read,
+ .write = stellaris_i2c_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
static const VMStateDescription vmstate_stellaris_i2c = {
{
stellaris_i2c_state *s = FROM_SYSBUS(stellaris_i2c_state, dev);
i2c_bus *bus;
- int iomemtype;
sysbus_init_irq(dev, &s->irq);
bus = i2c_init_bus(&dev->qdev, "i2c");
s->bus = bus;
- iomemtype = cpu_register_io_memory(stellaris_i2c_readfn,
- stellaris_i2c_writefn, s,
- DEVICE_NATIVE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, iomemtype);
+ memory_region_init_io(&s->iomem, &stellaris_i2c_ops, s,
+ "i2c", 0x1000);
+ sysbus_init_mmio(dev, &s->iomem);
/* ??? For now we only implement the master interface. */
stellaris_i2c_reset(s);
vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
typedef struct
{
SysBusDevice busdev;
+ MemoryRegion iomem;
uint32_t actss;
uint32_t ris;
uint32_t im;
}
}
-static uint32_t stellaris_adc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t stellaris_adc_read(void *opaque, target_phys_addr_t offset,
+ unsigned size)
{
stellaris_adc_state *s = (stellaris_adc_state *)opaque;
}
static void stellaris_adc_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
+ uint64_t value, unsigned size)
{
stellaris_adc_state *s = (stellaris_adc_state *)opaque;
return;
case 0x04: /* SSCTL */
if (value != 6) {
- hw_error("ADC: Unimplemented sequence %x\n",
+ hw_error("ADC: Unimplemented sequence %" PRIx64 "\n",
value);
}
s->ssctl[n] = value;
stellaris_adc_update(s);
}
-static CPUReadMemoryFunc * const stellaris_adc_readfn[] = {
- stellaris_adc_read,
- stellaris_adc_read,
- stellaris_adc_read
-};
-
-static CPUWriteMemoryFunc * const stellaris_adc_writefn[] = {
- stellaris_adc_write,
- stellaris_adc_write,
- stellaris_adc_write
+static const MemoryRegionOps stellaris_adc_ops = {
+ .read = stellaris_adc_read,
+ .write = stellaris_adc_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
static const VMStateDescription vmstate_stellaris_adc = {
static int stellaris_adc_init(SysBusDevice *dev)
{
stellaris_adc_state *s = FROM_SYSBUS(stellaris_adc_state, dev);
- int iomemtype;
int n;
for (n = 0; n < 4; n++) {
sysbus_init_irq(dev, &s->irq[n]);
}
- iomemtype = cpu_register_io_memory(stellaris_adc_readfn,
- stellaris_adc_writefn, s,
- DEVICE_NATIVE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, iomemtype);
+ memory_region_init_io(&s->iomem, &stellaris_adc_ops, s,
+ "adc", 0x1000);
+ sysbus_init_mmio(dev, &s->iomem);
stellaris_adc_reset(s);
qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
0x40024000, 0x40025000, 0x40026000};
static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
+ MemoryRegion *address_space_mem = get_system_memory();
qemu_irq *pic;
DeviceState *gpio_dev[7];
qemu_irq gpio_in[7][8];
flash_size = ((board->dc0 & 0xffff) + 1) << 1;
sram_size = (board->dc0 >> 18) + 1;
- pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model);
+ pic = armv7m_init(address_space_mem,
+ flash_size, sram_size, kernel_filename, cpu_model);
if (board->dc1 & (1 << 16)) {
dev = sysbus_create_varargs("stellaris-adc", 0x40038000,
}
}
- stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr);
+ stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr.a);
for (i = 0; i < 7; i++) {
if (board->dc4 & (1 << i)) {
machine_init(stellaris_machine_init);
-static SSISlaveInfo stellaris_ssi_bus_info = {
- .qdev.name = "evb6965-ssi",
- .qdev.size = sizeof(stellaris_ssi_bus_state),
- .init = stellaris_ssi_bus_init,
- .transfer = stellaris_ssi_bus_transfer
+static void stellaris_ssi_bus_class_init(ObjectClass *klass, void *data)
+{
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = stellaris_ssi_bus_init;
+ k->transfer = stellaris_ssi_bus_transfer;
+}
+
+static DeviceInfo stellaris_ssi_bus_info = {
+ .name = "evb6965-ssi",
+ .size = sizeof(stellaris_ssi_bus_state),
+ .class_init = stellaris_ssi_bus_class_init,
+};
+
+static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = stellaris_i2c_init;
+}
+
+static DeviceInfo stellaris_i2c_info = {
+ .name = "stellaris-i2c",
+ .size = sizeof(stellaris_i2c_state),
+ .class_init = stellaris_i2c_class_init,
+};
+
+static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = stellaris_gptm_init;
+}
+
+static DeviceInfo stellaris_gptm_info = {
+ .name = "stellaris-gptm",
+ .size = sizeof(gptm_state),
+ .class_init = stellaris_gptm_class_init,
+};
+
+static void stellaris_adc_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = stellaris_adc_init;
+}
+
+static DeviceInfo stellaris_adc_info = {
+ .name = "stellaris-adc",
+ .size = sizeof(stellaris_adc_state),
+ .class_init = stellaris_adc_class_init,
};
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);
+ sysbus_qdev_register(&stellaris_i2c_info);
+ sysbus_qdev_register(&stellaris_gptm_info);
+ sysbus_qdev_register(&stellaris_adc_info);
ssi_register_slave(&stellaris_ssi_bus_info);
}