From 13951ccfcdf0f31902a93859506ccf8c0ef66583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Fri, 12 Jul 2024 17:13:15 +0200 Subject: [PATCH 01/15] aspeed/smc: Fix possible integer overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coverity reports a possible integer overflow because routine aspeeed_smc_hclk_divisor() has a codepath returning 0, which could lead to an integer overflow when computing variable 'hclk_shift' in the caller aspeed_smc_dma_calibration(). The value passed to aspeed_smc_hclk_divisor() is always between 0 and 15 and, in this case, there is always a matching hclk divisor. Remove the return 0 and use g_assert_not_reached() instead. Fixes: Coverity CID 1547822 Suggested-by: Peter Maydell Signed-off-by: Cédric Le Goater Reviewed-by: Peter Maydell --- hw/ssi/aspeed_smc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index 49205ab76d38..f39fb85a35e9 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -789,8 +789,7 @@ static uint8_t aspeed_smc_hclk_divisor(uint8_t hclk_mask) } } - aspeed_smc_error("invalid HCLK mask %x", hclk_mask); - return 0; + g_assert_not_reached(); } /* From dddfc771e034887560c30fd2720b7798c04f5642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Jul 2024 08:30:15 +0200 Subject: [PATCH 02/15] aspeed: Change type of eMMC device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QEMU device model representing the eMMC device of the machine is currently created with type SD_CARD. Change the type to EMMC now that it is available. Signed-off-by: Cédric Le Goater Reviewed-by: Andrew Jeffery Tested-by: Andrew Jeffery Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé --- hw/arm/aspeed.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 53a4f665d0d0..105b990233fa 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -327,14 +327,14 @@ 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) { DeviceState *card; if (!dinfo) { return; } - card = qdev_new(TYPE_SD_CARD); + card = qdev_new(emmc ? TYPE_EMMC : TYPE_SD_CARD); qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), &error_fatal); qdev_realize_and_unref(card, @@ -436,12 +436,13 @@ 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); } if (bmc->soc->emmc.num_slots) { sdhci_attach_drive(&bmc->soc->emmc.slots[0], - drive_get(IF_SD, 0, bmc->soc->sdhci.num_slots)); + drive_get(IF_SD, 0, bmc->soc->sdhci.num_slots), + true); } if (!bmc->mmio_exec) { From 255aed8134190966d0bd090c97391f6512c2fbc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Jul 2024 08:30:16 +0200 Subject: [PATCH 03/15] aspeed: Load eMMC first boot area as a boot rom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first boot area partition (64K) of the eMMC device should contain an initial boot loader (u-boot SPL). Load it as a ROM only if an eMMC device is available to boot from but no flash device is. Signed-off-by: Cédric Le Goater Reviewed-by: Andrew Jeffery Tested-by: Andrew Jeffery Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé --- hw/arm/aspeed.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 105b990233fa..756deb91efd1 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -364,6 +364,7 @@ static void aspeed_machine_init(MachineState *machine) AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine); AspeedSoCClass *sc; int i; + DriveInfo *emmc0 = NULL; bmc->soc = ASPEED_SOC(object_new(amc->soc_name)); object_property_add_child(OBJECT(machine), "soc", OBJECT(bmc->soc)); @@ -440,9 +441,8 @@ static void aspeed_machine_init(MachineState *machine) } if (bmc->soc->emmc.num_slots) { - sdhci_attach_drive(&bmc->soc->emmc.slots[0], - drive_get(IF_SD, 0, bmc->soc->sdhci.num_slots), - true); + emmc0 = drive_get(IF_SD, 0, bmc->soc->sdhci.num_slots); + sdhci_attach_drive(&bmc->soc->emmc.slots[0], emmc0, true); } if (!bmc->mmio_exec) { @@ -452,6 +452,8 @@ static void aspeed_machine_init(MachineState *machine) if (fmc0) { 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); } } From cc8bae6f6270c52c8f9854a83f9cefec3e5ec108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Jul 2024 08:30:17 +0200 Subject: [PATCH 04/15] aspeed/scu: Add boot-from-eMMC HW strapping bit for AST2600 SoC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bit SCU500[2] of the AST2600 controls the boot device of the SoC. Future changes will configure this bit to boot from eMMC disk images specially built for this purpose. Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater Reviewed-by: Andrew Jeffery Tested-by: Andrew Jeffery Tested-by: Philippe Mathieu-Daudé --- include/hw/misc/aspeed_scu.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h index 58db28db45aa..356be95e4585 100644 --- a/include/hw/misc/aspeed_scu.h +++ b/include/hw/misc/aspeed_scu.h @@ -349,6 +349,10 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s); #define SCU_AST2600_H_PLL_BYPASS_EN (0x1 << 24) #define SCU_AST2600_H_PLL_OFF (0x1 << 23) +/* STRAP1 SCU500 */ +#define SCU_AST2600_HW_STRAP_BOOT_SRC_EMMC (0x1 << 2) +#define SCU_AST2600_HW_STRAP_BOOT_SRC_SPI (0x0 << 2) + /* * SCU310 Clock Selection Register Set 4 (for Aspeed AST1030 SOC) * From eea55625df839813c66c5e2e8f41d9131d591f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Jul 2024 08:30:18 +0200 Subject: [PATCH 05/15] aspeed: Introduce a AspeedSoCClass 'boot_from_emmc' handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Report support on the AST2600 SoC if the boot-from-eMMC HW strapping bit is set at the board level. AST2700 also has support but it is not yet ready in QEMU and others SoCs do not have support, so return false always for these. Signed-off-by: Cédric Le Goater Reviewed-by: Andrew Jeffery Tested-by: Andrew Jeffery Tested-by: Philippe Mathieu-Daudé --- hw/arm/aspeed_ast2600.c | 8 ++++++++ hw/arm/aspeed_soc_common.c | 7 +++++++ include/hw/arm/aspeed_soc.h | 1 + 3 files changed, 16 insertions(+) diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 31713de74a5f..be3eb70cdd77 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -646,6 +646,13 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) } } +static bool aspeed_soc_ast2600_boot_from_emmc(AspeedSoCState *s) +{ + uint32_t hw_strap1 = object_property_get_uint(OBJECT(&s->scu), + "hw-strap1", &error_abort); + return !!(hw_strap1 & SCU_AST2600_HW_STRAP_BOOT_SRC_EMMC); +} + static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) { static const char * const valid_cpu_types[] = { @@ -673,6 +680,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) sc->memmap = aspeed_soc_ast2600_memmap; sc->num_cpus = 2; sc->get_irq = aspeed_soc_ast2600_get_irq; + sc->boot_from_emmc = aspeed_soc_ast2600_boot_from_emmc; } static const TypeInfo aspeed_soc_ast2600_types[] = { diff --git a/hw/arm/aspeed_soc_common.c b/hw/arm/aspeed_soc_common.c index 1e8f2558fdc2..05551461aea0 100644 --- a/hw/arm/aspeed_soc_common.c +++ b/hw/arm/aspeed_soc_common.c @@ -134,6 +134,11 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) } } +static bool aspeed_soc_boot_from_emmc(AspeedSoCState *s) +{ + return false; +} + static Property aspeed_soc_properties[] = { DEFINE_PROP_LINK("dram", AspeedSoCState, dram_mr, TYPE_MEMORY_REGION, MemoryRegion *), @@ -145,9 +150,11 @@ static Property aspeed_soc_properties[] = { static void aspeed_soc_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc); dc->realize = aspeed_soc_realize; device_class_set_props(dc, aspeed_soc_properties); + sc->boot_from_emmc = aspeed_soc_boot_from_emmc; } static const TypeInfo aspeed_soc_types[] = { diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 849ba37f9524..624d489e0d63 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -164,6 +164,7 @@ struct AspeedSoCClass { const hwaddr *memmap; uint32_t num_cpus; qemu_irq (*get_irq)(AspeedSoCState *s, int dev); + bool (*boot_from_emmc)(AspeedSoCState *s); }; const char *aspeed_soc_cpu_type(AspeedSoCClass *sc); From e554e45b447880e37538d300ac6e12111788ac4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Jul 2024 08:30:19 +0200 Subject: [PATCH 06/15] aspeed: Tune eMMC device properties to reflect HW strapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the boot-from-eMMC HW strapping bit is set, use the 'boot-config' property to set the boot config register to boot from the first boot area partition of the eMMC device. Also set the boot partition size of the device. Signed-off-by: Cédric Le Goater Reviewed-by: Andrew Jeffery Tested-by: Andrew Jeffery Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé --- hw/arm/aspeed.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 756deb91efd1..bc4ca1754213 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -327,7 +327,8 @@ void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, } } -static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo, bool emmc) +static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo, bool emmc, + bool boot_emmc) { DeviceState *card; @@ -335,6 +336,11 @@ static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo, bool emmc) return; } 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, @@ -365,6 +371,7 @@ static void aspeed_machine_init(MachineState *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)); @@ -437,19 +444,21 @@ 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), false); + drive_get(IF_SD, 0, i), false, false); } + boot_emmc = sc->boot_from_emmc(bmc->soc); + if (bmc->soc->emmc.num_slots) { emmc0 = drive_get(IF_SD, 0, bmc->soc->sdhci.num_slots); - sdhci_attach_drive(&bmc->soc->emmc.slots[0], emmc0, true); + 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) { From 01ea09eb7a6e8369a98fb360d2ed3bf1ecfc1753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Jul 2024 08:30:20 +0200 Subject: [PATCH 07/15] aspeed: Add boot-from-eMMC HW strapping bit to rainier-bmc machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This value is taken from a running Rainier machine. Signed-off-by: Cédric Le Goater Reviewed-by: Andrew Jeffery Tested-by: Andrew Jeffery Tested-by: Philippe Mathieu-Daudé --- hw/arm/aspeed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index bc4ca1754213..a8f5c14ae535 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -189,7 +189,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 */ From 621845a9e38215977432cff8c946b78f6820c6b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Jul 2024 08:30:21 +0200 Subject: [PATCH 08/15] aspeed: Introduce a 'hw_strap1' machine attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To change default behavior of a machine and boot from eMMC, future changes will add a machine option to let the user configure the boot-from-eMMC HW strapping bit. Add a new machine attribute first. Signed-off-by: Cédric Le Goater Reviewed-by: Andrew Jeffery Tested-by: Andrew Jeffery Tested-by: Philippe Mathieu-Daudé --- hw/arm/aspeed.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index a8f5c14ae535..9939559f6dd0 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 */ @@ -393,7 +394,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); @@ -1077,7 +1078,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) From 056b779eaf10ab84e8ca9d02662a975f4de3d3b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Jul 2024 08:30:22 +0200 Subject: [PATCH 09/15] aspeed: Introduce a 'boot-emmc' machine option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default behavior of some Aspeed machines is to boot from the eMMC device, like the rainier-bmc. Others like ast2600-evb could also boot from eMMC if the HW strapping boot-from-eMMC bit was set. Add a property to set or unset this bit. This is useful to test boot images. For now, only activate this property on the ast2600-evb and rainier-bmc machines for which eMMC images are available or can be built. Signed-off-by: Cédric Le Goater Reviewed-by: Andrew Jeffery Tested-by: Andrew Jeffery Tested-by: Philippe Mathieu-Daudé --- docs/system/arm/aspeed.rst | 2 ++ hw/arm/aspeed.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index cd9559e3e291..6733ffd2b941 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -123,6 +123,8 @@ To boot the machine from the flash image, use an MTD drive : Options specific to Aspeed machines are : + * ``boot-emmc`` to set or unset boot from eMMC (AST2600). + * ``execute-in-place`` which emulates the boot from the CE0 flash device by using the FMC controller to load the instructions, and not simply from RAM. This takes a little longer. diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 9939559f6dd0..5cdef873a5fc 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -1178,6 +1178,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); @@ -1377,6 +1405,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) @@ -1449,6 +1478,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) From a82e7e9eca7396ca39b0eb07d52e58d406d15728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Jul 2024 14:00:34 +0200 Subject: [PATCH 10/15] tests/avocado/machine_aspeed.py: Add eMMC boot tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The image was built using the process described in commit c8cb19876d3e ("hw/sd/sdcard: Support boot area in emmc image") with artefacts from the latest successful build of the IBM P10 BMC platform available on: https://jenkins.openbmc.org/job/ci-openbmc/distro=ubuntu,label=docker-builder,target=p10bmc/lastSuccessfulBuild/ Signed-off-by: Cédric Le Goater Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé --- tests/avocado/machine_aspeed.py | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py index f66ad38d3503..29e6b388a9fd 100644 --- a/tests/avocado/machine_aspeed.py +++ b/tests/avocado/machine_aspeed.py @@ -439,3 +439,42 @@ def test_aarch64_ast2700_evb_sdk_v09_02(self): self.wait_for_console_pattern('nodistro.0 ast2700-default ttyS12') self.ssh_connect('root', '0penBmc', False) +class AST2x00MachineMMC(QemuSystemTest): + + timeout = 240 + + def wait_for_console_pattern(self, success_message, vm=None): + wait_for_console_pattern(self, success_message, + failure_message='Kernel panic - not syncing', + vm=vm) + + def test_arm_aspeed_emmc_boot(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:rainier-bmc + :avocado: tags=device:emmc + """ + + image_url = ('https://fileserver.linaro.org/s/B6pJTwWEkzSDi36/download/' + 'mmc-p10bmc-20240617.qcow2') + image_hash = ('d523fb478d2b84d5adc5658d08502bc64b1486955683814f89c6137518acd90b') + image_path = self.fetch_asset(image_url, asset_hash=image_hash, + algorithm='sha256') + + self.require_netdev('user') + + self.vm.set_console() + self.vm.add_args('-drive', + 'file=' + image_path + ',if=sd,id=sd2,index=2', + '-net', 'nic', '-net', 'user') + self.vm.launch() + + self.wait_for_console_pattern('U-Boot SPL 2019.04') + self.wait_for_console_pattern('Trying to boot from MMC1') + self.wait_for_console_pattern('U-Boot 2019.04') + self.wait_for_console_pattern('eMMC 2nd Boot') + self.wait_for_console_pattern('## Loading kernel from FIT Image') + self.wait_for_console_pattern('Starting kernel ...') + self.wait_for_console_pattern('Booting Linux on physical CPU 0xf00') + self.wait_for_console_pattern('mmcblk0: p1 p2 p3 p4 p5 p6 p7') + self.wait_for_console_pattern('IBM eBMC (OpenBMC for IBM Enterprise') From 13b5ae94ed4d03d4992af867d0edb075651a4da9 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Thu, 18 Jul 2024 14:49:11 +0800 Subject: [PATCH 11/15] aspeed/adc: Add AST2700 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AST2700 and AST2600 ADC controllers are identical. Introduce ast2700 class and set 2 engines. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater --- hw/adc/aspeed_adc.c | 16 ++++++++++++++++ include/hw/adc/aspeed_adc.h | 1 + 2 files changed, 17 insertions(+) diff --git a/hw/adc/aspeed_adc.c b/hw/adc/aspeed_adc.c index 68bdbc73b0e6..48328ef89194 100644 --- a/hw/adc/aspeed_adc.c +++ b/hw/adc/aspeed_adc.c @@ -398,6 +398,15 @@ static void aspeed_1030_adc_class_init(ObjectClass *klass, void *data) aac->nr_engines = 2; } +static void aspeed_2700_adc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedADCClass *aac = ASPEED_ADC_CLASS(klass); + + dc->desc = "ASPEED 2700 ADC Controller"; + aac->nr_engines = 2; +} + static const TypeInfo aspeed_adc_info = { .name = TYPE_ASPEED_ADC, .parent = TYPE_SYS_BUS_DEVICE, @@ -430,6 +439,12 @@ static const TypeInfo aspeed_1030_adc_info = { .class_init = aspeed_1030_adc_class_init, /* No change since AST2600 */ }; +static const TypeInfo aspeed_2700_adc_info = { + .name = TYPE_ASPEED_2700_ADC, + .parent = TYPE_ASPEED_ADC, + .class_init = aspeed_2700_adc_class_init, +}; + static void aspeed_adc_register_types(void) { type_register_static(&aspeed_adc_engine_info); @@ -438,6 +453,7 @@ static void aspeed_adc_register_types(void) type_register_static(&aspeed_2500_adc_info); type_register_static(&aspeed_2600_adc_info); type_register_static(&aspeed_1030_adc_info); + type_register_static(&aspeed_2700_adc_info); } type_init(aspeed_adc_register_types); diff --git a/include/hw/adc/aspeed_adc.h b/include/hw/adc/aspeed_adc.h index ff1d06ea91de..f502f197ac00 100644 --- a/include/hw/adc/aspeed_adc.h +++ b/include/hw/adc/aspeed_adc.h @@ -18,6 +18,7 @@ #define TYPE_ASPEED_2500_ADC TYPE_ASPEED_ADC "-ast2500" #define TYPE_ASPEED_2600_ADC TYPE_ASPEED_ADC "-ast2600" #define TYPE_ASPEED_1030_ADC TYPE_ASPEED_ADC "-ast1030" +#define TYPE_ASPEED_2700_ADC TYPE_ASPEED_ADC "-ast2700" OBJECT_DECLARE_TYPE(AspeedADCState, AspeedADCClass, ASPEED_ADC) #define TYPE_ASPEED_ADC_ENGINE "aspeed.adc.engine" From 11bea810f7c1215e36824ed291a64e8f4e6f28df Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Thu, 18 Jul 2024 14:49:12 +0800 Subject: [PATCH 12/15] aspeed/soc: support ADC for AST2700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add ADC model for AST2700 ADC support. The ADC controller registers base address is start at 0x14C0_0000 and its address space is 0x1000. The ADC controller interrupt is connected to GICINT130_INTC group at bit 16. The GIC IRQ is 130. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater --- hw/arm/aspeed_ast27x0.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index a9fb0d4b8874..4257b5e8af82 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -60,6 +60,7 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_SLIIO] = 0x14C1E000, [ASPEED_GIC_DIST] = 0x12200000, [ASPEED_GIC_REDIST] = 0x12280000, + [ASPEED_DEV_ADC] = 0x14C00000, }; #define AST2700_MAX_IRQ 288 @@ -344,6 +345,9 @@ static void aspeed_soc_ast2700_init(Object *obj) object_initialize_child(obj, "sli", &s->sli, TYPE_ASPEED_2700_SLI); object_initialize_child(obj, "sliio", &s->sliio, TYPE_ASPEED_2700_SLIIO); object_initialize_child(obj, "intc", &a->intc, TYPE_ASPEED_2700_INTC); + + snprintf(typename, sizeof(typename), "aspeed.adc-%s", socname); + object_initialize_child(obj, "adc", &s->adc, typename); } /* @@ -601,6 +605,14 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sliio), 0, sc->memmap[ASPEED_DEV_SLIIO]); + /* ADC */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) { + return; + } + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->adc), 0, sc->memmap[ASPEED_DEV_ADC]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0, + aspeed_soc_get_irq(s, ASPEED_DEV_ADC)); + create_unimplemented_device("ast2700.dpmcu", 0x11000000, 0x40000); create_unimplemented_device("ast2700.iomem0", 0x12000000, 0x01000000); create_unimplemented_device("ast2700.iomem1", 0x14000000, 0x01000000); From f2202be27852eeb18d05ee6cebaba6f09ea74e55 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Thu, 18 Jul 2024 14:49:13 +0800 Subject: [PATCH 13/15] hw/i2c/aspeed: support to set the different memory size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the datasheet of ASPEED SOCs, an I2C controller owns 8KB of register space for AST2700, owns 4KB of register space for AST2600, AST2500 and AST2400, and owns 64KB of register space for AST1030. It set the memory region size 4KB by default and it does not compatible register space for AST2700. Introduce a new class attribute to set the I2C controller memory size for different ASPEED SOCs. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater --- hw/i2c/aspeed_i2c.c | 6 +++++- include/hw/i2c/aspeed_i2c.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index b43afd250de4..7d5a53c4c015 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -1014,7 +1014,7 @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->irq); memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_i2c_ctrl_ops, s, - "aspeed.i2c", 0x1000); + "aspeed.i2c", aic->mem_size); sysbus_init_mmio(sbd, &s->iomem); for (i = 0; i < aic->num_busses; i++) { @@ -1286,6 +1286,7 @@ static void aspeed_2400_i2c_class_init(ObjectClass *klass, void *data) aic->pool_size = 0x800; aic->pool_base = 0x800; aic->bus_pool_base = aspeed_2400_i2c_bus_pool_base; + aic->mem_size = 0x1000; } static const TypeInfo aspeed_2400_i2c_info = { @@ -1320,6 +1321,7 @@ static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data) aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base; aic->check_sram = true; aic->has_dma = true; + aic->mem_size = 0x1000; } static const TypeInfo aspeed_2500_i2c_info = { @@ -1353,6 +1355,7 @@ static void aspeed_2600_i2c_class_init(ObjectClass *klass, void *data) aic->pool_base = 0xC00; aic->bus_pool_base = aspeed_2600_i2c_bus_pool_base; aic->has_dma = true; + aic->mem_size = 0x1000; } static const TypeInfo aspeed_2600_i2c_info = { @@ -1376,6 +1379,7 @@ static void aspeed_1030_i2c_class_init(ObjectClass *klass, void *data) aic->pool_base = 0xC00; aic->bus_pool_base = aspeed_2600_i2c_bus_pool_base; aic->has_dma = true; + aic->mem_size = 0x10000; } static const TypeInfo aspeed_1030_i2c_info = { diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index a064479e599c..065b636d2999 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -283,7 +283,7 @@ struct AspeedI2CClass { uint8_t *(*bus_pool_base)(AspeedI2CBus *); bool check_sram; bool has_dma; - + uint64_t mem_size; }; static inline bool aspeed_i2c_is_new_mode(AspeedI2CState *s) From 5d337540c417997b589d71020497e0c127d1c4e1 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Thu, 18 Jul 2024 14:49:15 +0800 Subject: [PATCH 14/15] hw/i2c/aspeed: rename the I2C class pool attribute to share_pool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the datasheet of ASPEED SOCs, each I2C bus has their own pool buffer since AST2500. Only AST2400 utilized a pool buffer share to all I2C bus. And firmware required to set the offset of pool buffer by writing "Function Control Register(I2CD 00)" To make this model more readable, will change to introduce a new bus pool buffer attribute in AspeedI2Cbus. So, it does not need to calculate the pool buffer offset for different I2C bus. This patch rename the I2C class pool attribute to share_pool. It make user more understand share pool and bus pool are different. Incrementing the version of aspeed_i2c_vmstate to 3. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater --- hw/i2c/aspeed_i2c.c | 39 ++++++++++++++++++++----------------- include/hw/i2c/aspeed_i2c.h | 4 ++-- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index 7d5a53c4c015..b52a99896c5c 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -906,7 +906,7 @@ static const MemoryRegionOps aspeed_i2c_ctrl_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static uint64_t aspeed_i2c_pool_read(void *opaque, hwaddr offset, +static uint64_t aspeed_i2c_share_pool_read(void *opaque, hwaddr offset, unsigned size) { AspeedI2CState *s = opaque; @@ -914,26 +914,26 @@ static uint64_t aspeed_i2c_pool_read(void *opaque, hwaddr offset, int i; for (i = 0; i < size; i++) { - ret |= (uint64_t) s->pool[offset + i] << (8 * i); + ret |= (uint64_t) s->share_pool[offset + i] << (8 * i); } return ret; } -static void aspeed_i2c_pool_write(void *opaque, hwaddr offset, +static void aspeed_i2c_share_pool_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { AspeedI2CState *s = opaque; int i; for (i = 0; i < size; i++) { - s->pool[offset + i] = (value >> (8 * i)) & 0xFF; + s->share_pool[offset + i] = (value >> (8 * i)) & 0xFF; } } -static const MemoryRegionOps aspeed_i2c_pool_ops = { - .read = aspeed_i2c_pool_read, - .write = aspeed_i2c_pool_write, +static const MemoryRegionOps aspeed_i2c_share_pool_ops = { + .read = aspeed_i2c_share_pool_read, + .write = aspeed_i2c_share_pool_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, @@ -953,14 +953,15 @@ static const VMStateDescription aspeed_i2c_bus_vmstate = { static const VMStateDescription aspeed_i2c_vmstate = { .name = TYPE_ASPEED_I2C, - .version_id = 2, - .minimum_version_id = 2, + .version_id = 3, + .minimum_version_id = 3, .fields = (const VMStateField[]) { VMSTATE_UINT32(intr_status, AspeedI2CState), VMSTATE_STRUCT_ARRAY(busses, AspeedI2CState, ASPEED_I2C_NR_BUSSES, 1, aspeed_i2c_bus_vmstate, AspeedI2CBus), - VMSTATE_UINT8_ARRAY(pool, AspeedI2CState, ASPEED_I2C_MAX_POOL_SIZE), + VMSTATE_UINT8_ARRAY(share_pool, AspeedI2CState, + ASPEED_I2C_SHARE_POOL_SIZE), VMSTATE_END_OF_LIST() } }; @@ -995,7 +996,7 @@ static void aspeed_i2c_instance_init(Object *obj) * 0x140 ... 0x17F: Device 5 * 0x180 ... 0x1BF: Device 6 * 0x1C0 ... 0x1FF: Device 7 - * 0x200 ... 0x2FF: Buffer Pool (unused in linux driver) + * 0x200 ... 0x2FF: Buffer Pool (AST2500 unused in linux driver) * 0x300 ... 0x33F: Device 8 * 0x340 ... 0x37F: Device 9 * 0x380 ... 0x3BF: Device 10 @@ -1003,7 +1004,7 @@ static void aspeed_i2c_instance_init(Object *obj) * 0x400 ... 0x43F: Device 12 * 0x440 ... 0x47F: Device 13 * 0x480 ... 0x4BF: Device 14 - * 0x800 ... 0xFFF: Buffer Pool (unused in linux driver) + * 0x800 ... 0xFFF: Buffer Pool (AST2400 unused in linux driver) */ static void aspeed_i2c_realize(DeviceState *dev, Error **errp) { @@ -1037,8 +1038,9 @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp) &s->busses[i].mr); } - memory_region_init_io(&s->pool_iomem, OBJECT(s), &aspeed_i2c_pool_ops, s, - "aspeed.i2c-pool", aic->pool_size); + memory_region_init_io(&s->pool_iomem, OBJECT(s), + &aspeed_i2c_share_pool_ops, s, + "aspeed.i2c-share-pool", aic->pool_size); memory_region_add_subregion(&s->iomem, aic->pool_base, &s->pool_iomem); if (aic->has_dma) { @@ -1266,8 +1268,9 @@ static qemu_irq aspeed_2400_i2c_bus_get_irq(AspeedI2CBus *bus) static uint8_t *aspeed_2400_i2c_bus_pool_base(AspeedI2CBus *bus) { uint8_t *pool_page = - &bus->controller->pool[ARRAY_FIELD_EX32(bus->regs, I2CD_FUN_CTRL, - POOL_PAGE_SEL) * 0x100]; + &bus->controller->share_pool[ARRAY_FIELD_EX32(bus->regs, + I2CD_FUN_CTRL, + POOL_PAGE_SEL) * 0x100]; return &pool_page[ARRAY_FIELD_EX32(bus->regs, I2CD_POOL_CTRL, OFFSET)]; } @@ -1302,7 +1305,7 @@ static qemu_irq aspeed_2500_i2c_bus_get_irq(AspeedI2CBus *bus) static uint8_t *aspeed_2500_i2c_bus_pool_base(AspeedI2CBus *bus) { - return &bus->controller->pool[bus->id * 0x10]; + return &bus->controller->share_pool[bus->id * 0x10]; } static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data) @@ -1337,7 +1340,7 @@ static qemu_irq aspeed_2600_i2c_bus_get_irq(AspeedI2CBus *bus) static uint8_t *aspeed_2600_i2c_bus_pool_base(AspeedI2CBus *bus) { - return &bus->controller->pool[bus->id * 0x20]; + return &bus->controller->share_pool[bus->id * 0x20]; } static void aspeed_2600_i2c_class_init(ObjectClass *klass, void *data) diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h index 065b636d2999..fad5e9259a51 100644 --- a/include/hw/i2c/aspeed_i2c.h +++ b/include/hw/i2c/aspeed_i2c.h @@ -34,7 +34,7 @@ OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C) #define ASPEED_I2C_NR_BUSSES 16 -#define ASPEED_I2C_MAX_POOL_SIZE 0x800 +#define ASPEED_I2C_SHARE_POOL_SIZE 0x800 #define ASPEED_I2C_OLD_NUM_REG 11 #define ASPEED_I2C_NEW_NUM_REG 22 @@ -257,7 +257,7 @@ struct AspeedI2CState { uint32_t ctrl_global; uint32_t new_clk_divider; MemoryRegion pool_iomem; - uint8_t pool[ASPEED_I2C_MAX_POOL_SIZE]; + uint8_t share_pool[ASPEED_I2C_SHARE_POOL_SIZE]; AspeedI2CBus busses[ASPEED_I2C_NR_BUSSES]; MemoryRegion *dram_mr; From 4db1c16441923fc152142ae4bcc1cba23064cb8b Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Thu, 18 Jul 2024 14:49:24 +0800 Subject: [PATCH 15/15] aspeed: fix coding style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix coding style issues from checkpatch.pl Test command: ./scripts/checkpatch.pl --no-tree -f hw/arm/aspeed.c Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater --- hw/arm/aspeed.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 5cdef873a5fc..fd5603f7aa23 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -266,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); @@ -476,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, @@ -568,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); } @@ -677,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,