aboutsummaryrefslogtreecommitdiff
path: root/hw/arm/aspeed.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/arm/aspeed.c')
-rw-r--r--hw/arm/aspeed.c83
1 files changed, 68 insertions, 15 deletions
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 53a4f66..fd5603f 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -46,6 +46,7 @@ struct AspeedMachineState {
uint32_t uart_chosen;
char *fmc_model;
char *spi_model;
+ uint32_t hw_strap1;
};
/* On 32-bit hosts, lower RAM to 1G because of the 2047 MB limit */
@@ -189,7 +190,7 @@ struct AspeedMachineState {
#define TACOMA_BMC_HW_STRAP2 0x00000040
/* Rainier hardware value: (QEMU prototype) */
-#define RAINIER_BMC_HW_STRAP1 0x00422016
+#define RAINIER_BMC_HW_STRAP1 (0x00422016 | SCU_AST2600_HW_STRAP_BOOT_SRC_EMMC)
#define RAINIER_BMC_HW_STRAP2 0x80000848
/* Fuji hardware value */
@@ -265,7 +266,8 @@ static void write_boot_rom(BlockBackend *blk, hwaddr addr, size_t rom_size,
g_autofree void *storage = NULL;
int64_t size;
- /* The block backend size should have already been 'validated' by
+ /*
+ * The block backend size should have already been 'validated' by
* the creation of the m25p80 object.
*/
size = blk_getlength(blk);
@@ -327,14 +329,20 @@ void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
}
}
-static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo)
+static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo, bool emmc,
+ bool boot_emmc)
{
DeviceState *card;
if (!dinfo) {
return;
}
- card = qdev_new(TYPE_SD_CARD);
+ card = qdev_new(emmc ? TYPE_EMMC : TYPE_SD_CARD);
+ if (emmc) {
+ qdev_prop_set_uint64(card, "boot-partition-size", 1 * MiB);
+ qdev_prop_set_uint8(card, "boot-config",
+ boot_emmc ? 0x1 << 3 : 0x0);
+ }
qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
&error_fatal);
qdev_realize_and_unref(card,
@@ -364,6 +372,8 @@ static void aspeed_machine_init(MachineState *machine)
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine);
AspeedSoCClass *sc;
int i;
+ DriveInfo *emmc0 = NULL;
+ bool boot_emmc;
bmc->soc = ASPEED_SOC(object_new(amc->soc_name));
object_property_add_child(OBJECT(machine), "soc", OBJECT(bmc->soc));
@@ -385,7 +395,7 @@ static void aspeed_machine_init(MachineState *machine)
}
}
- object_property_set_int(OBJECT(bmc->soc), "hw-strap1", amc->hw_strap1,
+ object_property_set_int(OBJECT(bmc->soc), "hw-strap1", bmc->hw_strap1,
&error_abort);
object_property_set_int(OBJECT(bmc->soc), "hw-strap2", amc->hw_strap2,
&error_abort);
@@ -436,21 +446,25 @@ static void aspeed_machine_init(MachineState *machine)
for (i = 0; i < bmc->soc->sdhci.num_slots; i++) {
sdhci_attach_drive(&bmc->soc->sdhci.slots[i],
- drive_get(IF_SD, 0, i));
+ drive_get(IF_SD, 0, i), false, false);
}
+ boot_emmc = sc->boot_from_emmc(bmc->soc);
+
if (bmc->soc->emmc.num_slots) {
- sdhci_attach_drive(&bmc->soc->emmc.slots[0],
- drive_get(IF_SD, 0, bmc->soc->sdhci.num_slots));
+ emmc0 = drive_get(IF_SD, 0, bmc->soc->sdhci.num_slots);
+ sdhci_attach_drive(&bmc->soc->emmc.slots[0], emmc0, true, boot_emmc);
}
if (!bmc->mmio_exec) {
DeviceState *dev = ssi_get_cs(bmc->soc->fmc.spi, 0);
BlockBackend *fmc0 = dev ? m25p80_get_blk(dev) : NULL;
- if (fmc0) {
+ if (fmc0 && !boot_emmc) {
uint64_t rom_size = memory_region_size(&bmc->soc->spi_boot);
aspeed_install_boot_rom(bmc, fmc0, rom_size);
+ } else if (emmc0) {
+ aspeed_install_boot_rom(bmc, blk_by_legacy_dinfo(emmc0), 64 * KiB);
}
}
@@ -463,8 +477,10 @@ static void palmetto_bmc_i2c_init(AspeedMachineState *bmc)
DeviceState *dev;
uint8_t *eeprom_buf = g_malloc0(32 * 1024);
- /* The palmetto platform expects a ds3231 RTC but a ds1338 is
- * enough to provide basic RTC features. Alarms will be missing */
+ /*
+ * The palmetto platform expects a ds3231 RTC but a ds1338 is
+ * enough to provide basic RTC features. Alarms will be missing
+ */
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 0), "ds1338", 0x68);
smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 0), 0x50,
@@ -555,8 +571,10 @@ static void romulus_bmc_i2c_init(AspeedMachineState *bmc)
{
AspeedSoCState *soc = bmc->soc;
- /* The romulus board expects Epson RX8900 I2C RTC but a ds1338 is
- * good enough */
+ /*
+ * The romulus board expects Epson RX8900 I2C RTC but a ds1338 is
+ * good enough
+ */
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32);
}
@@ -664,8 +682,10 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc)
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), TYPE_TMP105,
0x4a);
- /* The witherspoon board expects Epson RX8900 I2C RTC but a ds1338 is
- * good enough */
+ /*
+ * The witherspoon board expects Epson RX8900 I2C RTC but a ds1338 is
+ * good enough
+ */
i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32);
smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 11), 0x51,
@@ -1065,7 +1085,10 @@ static void aspeed_set_mmio_exec(Object *obj, bool value, Error **errp)
static void aspeed_machine_instance_init(Object *obj)
{
+ AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(obj);
+
ASPEED_MACHINE(obj)->mmio_exec = false;
+ ASPEED_MACHINE(obj)->hw_strap1 = amc->hw_strap1;
}
static char *aspeed_get_fmc_model(Object *obj, Error **errp)
@@ -1162,6 +1185,34 @@ static void aspeed_machine_class_init_cpus_defaults(MachineClass *mc)
mc->valid_cpu_types = sc->valid_cpu_types;
}
+static bool aspeed_machine_ast2600_get_boot_from_emmc(Object *obj, Error **errp)
+{
+ AspeedMachineState *bmc = ASPEED_MACHINE(obj);
+
+ return !!(bmc->hw_strap1 & SCU_AST2600_HW_STRAP_BOOT_SRC_EMMC);
+}
+
+static void aspeed_machine_ast2600_set_boot_from_emmc(Object *obj, bool value,
+ Error **errp)
+{
+ AspeedMachineState *bmc = ASPEED_MACHINE(obj);
+
+ if (value) {
+ bmc->hw_strap1 |= SCU_AST2600_HW_STRAP_BOOT_SRC_EMMC;
+ } else {
+ bmc->hw_strap1 &= ~SCU_AST2600_HW_STRAP_BOOT_SRC_EMMC;
+ }
+}
+
+static void aspeed_machine_ast2600_class_emmc_init(ObjectClass *oc)
+{
+ object_class_property_add_bool(oc, "boot-emmc",
+ aspeed_machine_ast2600_get_boot_from_emmc,
+ aspeed_machine_ast2600_set_boot_from_emmc);
+ object_class_property_set_description(oc, "boot-emmc",
+ "Set or unset boot from EMMC");
+}
+
static void aspeed_machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -1361,6 +1412,7 @@ static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data)
amc->i2c_init = ast2600_evb_i2c_init;
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
+ aspeed_machine_ast2600_class_emmc_init(oc);
};
static void aspeed_machine_tacoma_class_init(ObjectClass *oc, void *data)
@@ -1433,6 +1485,7 @@ static void aspeed_machine_rainier_class_init(ObjectClass *oc, void *data)
amc->i2c_init = rainier_bmc_i2c_init;
mc->default_ram_size = 1 * GiB;
aspeed_machine_class_init_cpus_defaults(mc);
+ aspeed_machine_ast2600_class_emmc_init(oc);
};
#define FUJI_BMC_RAM_SIZE ASPEED_RAM_SIZE(2 * GiB)