aboutsummaryrefslogtreecommitdiff
path: root/hw/arm
diff options
context:
space:
mode:
Diffstat (limited to 'hw/arm')
-rw-r--r--hw/arm/Kconfig1
-rw-r--r--hw/arm/npcm7xx.c58
2 files changed, 59 insertions, 0 deletions
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index cd74642034..f303c6bead 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -361,6 +361,7 @@ config NPCM7XX
select ARM_GIC
select PL310 # cache controller
select SERIAL
+ select SSI
select UNIMP
config FSL_IMX25
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 6bb1693833..7884b2b03d 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -99,6 +99,39 @@ static const hwaddr npcm7xx_uart_addr[] = {
0xf0004000,
};
+/* Direct memory-mapped access to SPI0 CS0-1. */
+static const hwaddr npcm7xx_fiu0_flash_addr[] = {
+ 0x80000000, /* CS0 */
+ 0x88000000, /* CS1 */
+};
+
+/* Direct memory-mapped access to SPI3 CS0-3. */
+static const hwaddr npcm7xx_fiu3_flash_addr[] = {
+ 0xa0000000, /* CS0 */
+ 0xa8000000, /* CS1 */
+ 0xb0000000, /* CS2 */
+ 0xb8000000, /* CS3 */
+};
+
+static const struct {
+ const char *name;
+ hwaddr regs_addr;
+ int cs_count;
+ const hwaddr *flash_addr;
+} npcm7xx_fiu[] = {
+ {
+ .name = "fiu0",
+ .regs_addr = 0xfb000000,
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr),
+ .flash_addr = npcm7xx_fiu0_flash_addr,
+ }, {
+ .name = "fiu3",
+ .regs_addr = 0xc0000000,
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr),
+ .flash_addr = npcm7xx_fiu3_flash_addr,
+ },
+};
+
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
const struct arm_boot_info *info)
{
@@ -192,6 +225,12 @@ static void npcm7xx_init(Object *obj)
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
}
+
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
+ object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
+ TYPE_NPCM7XX_FIU);
+ }
}
static void npcm7xx_realize(DeviceState *dev, Error **errp)
@@ -291,6 +330,25 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
serial_hd(i), DEVICE_LITTLE_ENDIAN);
}
+ /*
+ * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
+ * specified, but this is a programming error.
+ */
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->fiu[i]);
+ int j;
+
+ object_property_set_int(OBJECT(sbd), "cs-count",
+ npcm7xx_fiu[i].cs_count, &error_abort);
+ sysbus_realize(sbd, &error_abort);
+
+ sysbus_mmio_map(sbd, 0, npcm7xx_fiu[i].regs_addr);
+ for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) {
+ sysbus_mmio_map(sbd, j + 1, npcm7xx_fiu[i].flash_addr[j]);
+ }
+ }
+
/* RAM2 (SRAM) */
memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
NPCM7XX_RAM2_SZ, &error_abort);