aboutsummaryrefslogtreecommitdiff
path: root/hw/arm
diff options
context:
space:
mode:
Diffstat (limited to 'hw/arm')
-rw-r--r--hw/arm/aspeed.c38
-rw-r--r--hw/arm/aspeed_ast10x0.c13
-rw-r--r--hw/arm/aspeed_ast2600.c13
-rw-r--r--hw/arm/aspeed_soc.c55
-rw-r--r--hw/arm/fby35.c188
-rw-r--r--hw/arm/meson.build3
6 files changed, 280 insertions, 30 deletions
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 3340187132..4193a3d23d 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -26,6 +26,7 @@
#include "qemu/error-report.h"
#include "qemu/units.h"
#include "hw/qdev-clock.h"
+#include "sysemu/sysemu.h"
static struct arm_boot_info aspeed_board_binfo = {
.board_id = -1, /* device-tree-only board */
@@ -261,7 +262,7 @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr);
}
-static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
+void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
unsigned int count, int unit0)
{
int i;
@@ -301,6 +302,21 @@ static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo)
&error_fatal);
}
+static void connect_serial_hds_to_uarts(AspeedMachineState *bmc)
+{
+ AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc);
+ AspeedSoCState *s = &bmc->soc;
+ AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+
+ aspeed_soc_uart_set_chr(s, amc->uart_default, serial_hd(0));
+ for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
+ if (uart == amc->uart_default) {
+ continue;
+ }
+ aspeed_soc_uart_set_chr(s, uart, serial_hd(i));
+ }
+}
+
static void aspeed_machine_init(MachineState *machine)
{
AspeedMachineState *bmc = ASPEED_MACHINE(machine);
@@ -346,8 +362,7 @@ static void aspeed_machine_init(MachineState *machine)
object_property_set_int(OBJECT(&bmc->soc), "hw-prot-key",
ASPEED_SCU_PROT_KEY, &error_abort);
}
- qdev_prop_set_uint32(DEVICE(&bmc->soc), "uart-default",
- amc->uart_default);
+ connect_serial_hds_to_uarts(bmc);
qdev_realize(DEVICE(&bmc->soc), NULL, &error_abort);
aspeed_board_init_flashes(&bmc->soc.fmc,
@@ -1343,11 +1358,23 @@ static void fby35_reset(MachineState *state)
qemu_devices_reset();
- /* Board ID */
+ /* Board ID: 7 (Class-1, 4 slots) */
object_property_set_bool(OBJECT(gpio), "gpioV4", true, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioV5", true, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioV6", true, &error_fatal);
object_property_set_bool(OBJECT(gpio), "gpioV7", false, &error_fatal);
+
+ /* Slot presence pins, inverse polarity. (False means present) */
+ object_property_set_bool(OBJECT(gpio), "gpioH4", false, &error_fatal);
+ object_property_set_bool(OBJECT(gpio), "gpioH5", true, &error_fatal);
+ object_property_set_bool(OBJECT(gpio), "gpioH6", true, &error_fatal);
+ object_property_set_bool(OBJECT(gpio), "gpioH7", true, &error_fatal);
+
+ /* Slot 12v power pins, normal polarity. (True means powered-on) */
+ object_property_set_bool(OBJECT(gpio), "gpioB2", true, &error_fatal);
+ object_property_set_bool(OBJECT(gpio), "gpioB3", false, &error_fatal);
+ object_property_set_bool(OBJECT(gpio), "gpioB4", false, &error_fatal);
+ object_property_set_bool(OBJECT(gpio), "gpioB5", false, &error_fatal);
}
static void aspeed_machine_fby35_class_init(ObjectClass *oc, void *data)
@@ -1383,8 +1410,7 @@ static void aspeed_minibmc_machine_init(MachineState *machine)
object_property_set_link(OBJECT(&bmc->soc), "memory",
OBJECT(get_system_memory()), &error_abort);
- qdev_prop_set_uint32(DEVICE(&bmc->soc), "uart-default",
- amc->uart_default);
+ connect_serial_hds_to_uarts(bmc);
qdev_realize(DEVICE(&bmc->soc), NULL, &error_abort);
aspeed_board_init_flashes(&bmc->soc.fmc,
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index 33ef331771..4d0b9b115f 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -144,6 +144,10 @@ static void aspeed_soc_ast1030_init(Object *obj)
object_initialize_child(obj, "wdt[*]", &s->wdt[i], typename);
}
+ for (i = 0; i < sc->uarts_num; i++) {
+ object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
+ }
+
snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname);
object_initialize_child(obj, "gpio", &s->gpio, typename);
@@ -159,6 +163,7 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
DeviceState *armv7m;
Error *err = NULL;
int i;
+ g_autofree char *sram_name = NULL;
if (!clock_has_source(s->sysclk)) {
error_setg(errp, "sysclk clock must be wired up by the board code");
@@ -183,7 +188,9 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), &error_abort);
/* Internal SRAM */
- memory_region_init_ram(&s->sram, NULL, "aspeed.sram", sc->sram_size, &err);
+ sram_name = g_strdup_printf("aspeed.sram.%d",
+ CPU(s->armv7m.cpu)->cpu_index);
+ memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size, &err);
if (err != NULL) {
error_propagate(errp, err);
return;
@@ -252,7 +259,9 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp)
sc->irqmap[ASPEED_DEV_KCS] + aspeed_lpc_kcs_4));
/* UART */
- aspeed_soc_uart_init(s);
+ if (!aspeed_soc_uart_realize(s, errp)) {
+ return;
+ }
/* Timer */
object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu),
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 3f0611ac11..aa2cd90bec 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -214,6 +214,10 @@ static void aspeed_soc_ast2600_init(Object *obj)
object_initialize_child(obj, "mii[*]", &s->mii[i], TYPE_ASPEED_MII);
}
+ for (i = 0; i < sc->uarts_num; i++) {
+ object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
+ }
+
snprintf(typename, sizeof(typename), TYPE_ASPEED_XDMA "-%s", socname);
object_initialize_child(obj, "xdma", &s->xdma, typename);
@@ -276,6 +280,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
Error *err = NULL;
qemu_irq irq;
+ g_autofree char *sram_name = NULL;
/* IO space */
aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
@@ -335,8 +340,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
}
/* SRAM */
- memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
- sc->sram_size, &err);
+ sram_name = g_strdup_printf("aspeed.sram.%d", CPU(&s->cpu[0])->cpu_index);
+ memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size, &err);
if (err) {
error_propagate(errp, err);
return;
@@ -385,7 +390,9 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
/* UART */
- aspeed_soc_uart_init(s);
+ if (!aspeed_soc_uart_realize(s, errp)) {
+ return;
+ }
/* I2C */
object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr),
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 0f675e7fcd..b05b9dd416 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -208,6 +208,10 @@ static void aspeed_soc_init(Object *obj)
TYPE_FTGMAC100);
}
+ for (i = 0; i < sc->uarts_num; i++) {
+ object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_MM);
+ }
+
snprintf(typename, sizeof(typename), TYPE_ASPEED_XDMA "-%s", socname);
object_initialize_child(obj, "xdma", &s->xdma, typename);
@@ -239,6 +243,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
AspeedSoCState *s = ASPEED_SOC(dev);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
Error *err = NULL;
+ g_autofree char *sram_name = NULL;
/* IO space */
aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io",
@@ -259,8 +264,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
}
/* SRAM */
- memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
- sc->sram_size, &err);
+ sram_name = g_strdup_printf("aspeed.sram.%d", CPU(&s->cpu[0])->cpu_index);
+ memory_region_init_ram(&s->sram, OBJECT(s), sram_name, sc->sram_size, &err);
if (err) {
error_propagate(errp, err);
return;
@@ -314,7 +319,9 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
/* UART */
- aspeed_soc_uart_init(s);
+ if (!aspeed_soc_uart_realize(s, errp)) {
+ return;
+ }
/* I2C */
object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(s->dram_mr),
@@ -481,8 +488,6 @@ static Property aspeed_soc_properties[] = {
MemoryRegion *),
DEFINE_PROP_LINK("dram", AspeedSoCState, dram_mr, TYPE_MEMORY_REGION,
MemoryRegion *),
- DEFINE_PROP_UINT32("uart-default", AspeedSoCState, uart_default,
- ASPEED_DEV_UART5),
DEFINE_PROP_END_OF_LIST(),
};
@@ -572,23 +577,37 @@ qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev)
return ASPEED_SOC_GET_CLASS(s)->get_irq(s, dev);
}
-void aspeed_soc_uart_init(AspeedSoCState *s)
+bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp)
{
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
- int i, uart;
-
- /* Attach an 8250 to the IO space as our UART */
- serial_mm_init(s->memory, sc->memmap[s->uart_default], 2,
- aspeed_soc_get_irq(s, s->uart_default), 38400,
- serial_hd(0), DEVICE_LITTLE_ENDIAN);
- for (i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
- if (uart == s->uart_default) {
- uart++;
+ SerialMM *smm;
+
+ for (int i = 0, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) {
+ smm = &s->uart[i];
+
+ /* Chardev property is set by the machine. */
+ qdev_prop_set_uint8(DEVICE(smm), "regshift", 2);
+ qdev_prop_set_uint32(DEVICE(smm), "baudbase", 38400);
+ qdev_set_legacy_instance_id(DEVICE(smm), sc->memmap[uart], 2);
+ qdev_prop_set_uint8(DEVICE(smm), "endianness", DEVICE_LITTLE_ENDIAN);
+ if (!sysbus_realize(SYS_BUS_DEVICE(smm), errp)) {
+ return false;
}
- serial_mm_init(s->memory, sc->memmap[uart], 2,
- aspeed_soc_get_irq(s, uart), 38400,
- serial_hd(i), DEVICE_LITTLE_ENDIAN);
+
+ sysbus_connect_irq(SYS_BUS_DEVICE(smm), 0, aspeed_soc_get_irq(s, uart));
+ aspeed_mmio_map(s, SYS_BUS_DEVICE(smm), 0, sc->memmap[uart]);
}
+
+ return true;
+}
+
+void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr)
+{
+ AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+ int i = dev - ASPEED_DEV_UART1;
+
+ g_assert(0 <= i && i < ARRAY_SIZE(s->uart) && i < sc->uarts_num);
+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
}
/*
diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c
new file mode 100644
index 0000000000..79605f3064
--- /dev/null
+++ b/hw/arm/fby35.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates. (http://www.meta.com)
+ *
+ * This code is licensed under the GPL version 2 or later. See the COPYING
+ * file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
+#include "hw/boards.h"
+#include "hw/qdev-clock.h"
+#include "hw/arm/aspeed_soc.h"
+#include "hw/arm/boot.h"
+
+#define TYPE_FBY35 MACHINE_TYPE_NAME("fby35")
+OBJECT_DECLARE_SIMPLE_TYPE(Fby35State, FBY35);
+
+struct Fby35State {
+ MachineState parent_obj;
+
+ MemoryRegion bmc_memory;
+ MemoryRegion bmc_dram;
+ MemoryRegion bmc_boot_rom;
+ MemoryRegion bic_memory;
+ Clock *bic_sysclk;
+
+ AspeedSoCState bmc;
+ AspeedSoCState bic;
+
+ bool mmio_exec;
+};
+
+#define FBY35_BMC_RAM_SIZE (2 * GiB)
+#define FBY35_BMC_FIRMWARE_ADDR 0x0
+
+static void fby35_bmc_write_boot_rom(DriveInfo *dinfo, MemoryRegion *mr,
+ hwaddr offset, size_t rom_size,
+ Error **errp)
+{
+ BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
+ g_autofree void *storage = NULL;
+ int64_t size;
+
+ /*
+ * The block backend size should have already been 'validated' by
+ * the creation of the m25p80 object.
+ */
+ size = blk_getlength(blk);
+ if (size <= 0) {
+ error_setg(errp, "failed to get flash size");
+ return;
+ }
+
+ if (rom_size > size) {
+ rom_size = size;
+ }
+
+ storage = g_malloc0(rom_size);
+ if (blk_pread(blk, 0, rom_size, storage, 0) < 0) {
+ error_setg(errp, "failed to read the initial flash content");
+ return;
+ }
+
+ /* TODO: find a better way to install the ROM */
+ memcpy(memory_region_get_ram_ptr(mr) + offset, storage, rom_size);
+}
+
+static void fby35_bmc_init(Fby35State *s)
+{
+ DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
+
+ memory_region_init(&s->bmc_memory, OBJECT(s), "bmc-memory", UINT64_MAX);
+ memory_region_init_ram(&s->bmc_dram, OBJECT(s), "bmc-dram",
+ FBY35_BMC_RAM_SIZE, &error_abort);
+
+ object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3");
+ object_property_set_int(OBJECT(&s->bmc), "ram-size", FBY35_BMC_RAM_SIZE,
+ &error_abort);
+ object_property_set_link(OBJECT(&s->bmc), "memory", OBJECT(&s->bmc_memory),
+ &error_abort);
+ object_property_set_link(OBJECT(&s->bmc), "dram", OBJECT(&s->bmc_dram),
+ &error_abort);
+ object_property_set_int(OBJECT(&s->bmc), "hw-strap1", 0x000000C0,
+ &error_abort);
+ object_property_set_int(OBJECT(&s->bmc), "hw-strap2", 0x00000003,
+ &error_abort);
+ aspeed_soc_uart_set_chr(&s->bmc, ASPEED_DEV_UART5, serial_hd(0));
+ qdev_realize(DEVICE(&s->bmc), NULL, &error_abort);
+
+ aspeed_board_init_flashes(&s->bmc.fmc, "n25q00", 2, 0);
+
+ /* Install first FMC flash content as a boot rom. */
+ if (drive0) {
+ AspeedSMCFlash *fl = &s->bmc.fmc.flashes[0];
+ MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+ uint64_t size = memory_region_size(&fl->mmio);
+
+ if (s->mmio_exec) {
+ memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom",
+ &fl->mmio, 0, size);
+ memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
+ boot_rom);
+ } else {
+
+ memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
+ size, &error_abort);
+ memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
+ boot_rom);
+ fby35_bmc_write_boot_rom(drive0, boot_rom, FBY35_BMC_FIRMWARE_ADDR,
+ size, &error_abort);
+ }
+ }
+}
+
+static void fby35_bic_init(Fby35State *s)
+{
+ s->bic_sysclk = clock_new(OBJECT(s), "SYSCLK");
+ clock_set_hz(s->bic_sysclk, 200000000ULL);
+
+ memory_region_init(&s->bic_memory, OBJECT(s), "bic-memory", UINT64_MAX);
+
+ object_initialize_child(OBJECT(s), "bic", &s->bic, "ast1030-a1");
+ qdev_connect_clock_in(DEVICE(&s->bic), "sysclk", s->bic_sysclk);
+ object_property_set_link(OBJECT(&s->bic), "memory", OBJECT(&s->bic_memory),
+ &error_abort);
+ aspeed_soc_uart_set_chr(&s->bic, ASPEED_DEV_UART5, serial_hd(1));
+ qdev_realize(DEVICE(&s->bic), NULL, &error_abort);
+
+ aspeed_board_init_flashes(&s->bic.fmc, "sst25vf032b", 2, 2);
+ aspeed_board_init_flashes(&s->bic.spi[0], "sst25vf032b", 2, 4);
+ aspeed_board_init_flashes(&s->bic.spi[1], "sst25vf032b", 2, 6);
+}
+
+static void fby35_init(MachineState *machine)
+{
+ Fby35State *s = FBY35(machine);
+
+ fby35_bmc_init(s);
+ fby35_bic_init(s);
+}
+
+
+static bool fby35_get_mmio_exec(Object *obj, Error **errp)
+{
+ return FBY35(obj)->mmio_exec;
+}
+
+static void fby35_set_mmio_exec(Object *obj, bool value, Error **errp)
+{
+ FBY35(obj)->mmio_exec = value;
+}
+
+static void fby35_instance_init(Object *obj)
+{
+ FBY35(obj)->mmio_exec = false;
+}
+
+static void fby35_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->desc = "Meta Platforms fby35";
+ mc->init = fby35_init;
+ mc->no_floppy = 1;
+ mc->no_cdrom = 1;
+ mc->min_cpus = mc->max_cpus = mc->default_cpus = 3;
+
+ object_class_property_add_bool(oc, "execute-in-place",
+ fby35_get_mmio_exec,
+ fby35_set_mmio_exec);
+ object_class_property_set_description(oc, "execute-in-place",
+ "boot directly from CE0 flash device");
+}
+
+static const TypeInfo fby35_types[] = {
+ {
+ .name = MACHINE_TYPE_NAME("fby35"),
+ .parent = TYPE_MACHINE,
+ .class_init = fby35_class_init,
+ .instance_size = sizeof(Fby35State),
+ .instance_init = fby35_instance_init,
+ },
+};
+
+DEFINE_TYPES(fby35_types);
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 2d8381339c..92f9f6e000 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -51,7 +51,8 @@ arm_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
'aspeed_soc.c',
'aspeed.c',
'aspeed_ast2600.c',
- 'aspeed_ast10x0.c'))
+ 'aspeed_ast10x0.c',
+ 'fby35.c'))
arm_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2.c'))
arm_ss.add(when: 'CONFIG_MPS2', if_true: files('mps2-tz.c'))
arm_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-soc.c'))