From: Kane-Chen-AS <kane_c...@aspeedtech.com> This patch wires up the OTP memory device (`aspeed.otpmem`) into the AST1030 and AST2600 SoC models. The device is initialized, attached to a backing block drive (`-drive id=otpmem`) and linked to the SBC controller via a QOM link.
The default OTP memory image can be generated using the following command. ```bash for i in $(seq 1 2048); do printf '\x00\x00\x00\x00\xff\xff\xff\xff' done > otpmem.img ``` To load the OTP memory image into the guest, use: ```bash ./qemu-system-arm \ -drive id=otpmem,file=otpmem.img,if=none,format=raw \ ... ``` Note: Do not use the -snapshot option, or OTP data writes will not persist to the image file. Signed-off-by: Kane-Chen-AS <kane_c...@aspeedtech.com> --- hw/arm/aspeed_ast10x0.c | 19 +++++++++++++++++++ hw/arm/aspeed_ast2600.c | 19 +++++++++++++++++++ include/hw/arm/aspeed_soc.h | 2 ++ 3 files changed, 40 insertions(+) diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c index ec329f4991..eaa70feb9f 100644 --- a/hw/arm/aspeed_ast10x0.c +++ b/hw/arm/aspeed_ast10x0.c @@ -15,6 +15,7 @@ #include "system/system.h" #include "hw/qdev-clock.h" #include "hw/misc/unimp.h" +#include "system/block-backend-global-state.h" #include "hw/arm/aspeed_soc.h" #define ASPEED_SOC_IOMEM_SIZE 0x00200000 @@ -156,6 +157,8 @@ static void aspeed_soc_ast1030_init(Object *obj) object_initialize_child(obj, "sbc", &s->sbc, TYPE_ASPEED_SBC); + object_initialize_child(obj, "otpmem", &s->otpmem, TYPE_ASPEED_OTPMEM); + for (i = 0; i < sc->wdts_num; i++) { snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname); object_initialize_child(obj, "wdt[*]", &s->wdt[i], typename); @@ -194,6 +197,7 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp) Error *err = NULL; int i; g_autofree char *sram_name = NULL; + BlockBackend *blk; if (!clock_has_source(s->sysclk)) { error_setg(errp, "sysclk clock must be wired up by the board code"); @@ -359,6 +363,21 @@ static void aspeed_soc_ast1030_realize(DeviceState *dev_soc, Error **errp) ASPEED_SMC_GET_CLASS(&s->spi[i])->flash_window_base); } + /* OTP memory */ + blk = blk_by_name(ASPEED_OTPMEM_DRIVE); + if (blk) { + blk_set_perm(blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE, + 0, &error_fatal); + qdev_prop_set_drive(DEVICE(&s->otpmem), "drive", blk); + + if (!sysbus_realize(SYS_BUS_DEVICE(&s->otpmem), errp)) { + return; + } + /* Assign OTP memory to SBC */ + object_property_set_link(OBJECT(&s->sbc), "otpmem", + OBJECT(&s->otpmem), &error_abort); + } + /* Secure Boot Controller */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->sbc), errp)) { return; diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 1f994ba26c..9fe3eeeb0e 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -10,6 +10,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/misc/unimp.h" +#include "system/block-backend-global-state.h" #include "hw/arm/aspeed_soc.h" #include "qemu/module.h" #include "qemu/error-report.h" @@ -263,6 +264,8 @@ static void aspeed_soc_ast2600_init(Object *obj) object_initialize_child(obj, "sbc", &s->sbc, TYPE_ASPEED_SBC); + object_initialize_child(obj, "otpmem", &s->otpmem, TYPE_ASPEED_OTPMEM); + object_initialize_child(obj, "iomem", &s->iomem, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "video", &s->video, TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "dpmcu", &s->dpmcu, TYPE_UNIMPLEMENTED_DEVICE); @@ -293,6 +296,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); qemu_irq irq; g_autofree char *sram_name = NULL; + BlockBackend *blk; /* Default boot region (SPI memory or ROMs) */ memory_region_init(&s->spi_boot_container, OBJECT(s), @@ -628,6 +632,21 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->i3c.devices[i]), 0, irq); } + /* OTP memory */ + blk = blk_by_name(ASPEED_OTPMEM_DRIVE); + if (blk) { + blk_set_perm(blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE, + 0, &error_fatal); + qdev_prop_set_drive(DEVICE(&s->otpmem), "drive", blk); + + if (!sysbus_realize(SYS_BUS_DEVICE(&s->otpmem), errp)) { + return; + } + /* Assign OTP memory to SBC */ + object_property_set_link(OBJECT(&s->sbc), "otpmem", + OBJECT(&s->otpmem), &error_abort); + } + /* Secure Boot Controller */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->sbc), errp)) { return; diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index f069d17d16..2d15c6047a 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -36,6 +36,7 @@ #include "hw/usb/hcd-ehci.h" #include "qom/object.h" #include "hw/misc/aspeed_lpc.h" +#include "hw/misc/aspeed_otpmem.h" #include "hw/misc/unimp.h" #include "hw/misc/aspeed_peci.h" #include "hw/fsi/aspeed_apb2opb.h" @@ -73,6 +74,7 @@ struct AspeedSoCState { AspeedSMCState spi[ASPEED_SPIS_NUM]; EHCISysBusState ehci[ASPEED_EHCIS_NUM]; AspeedSBCState sbc; + AspeedOTPMemState otpmem; AspeedSLIState sli; AspeedSLIState sliio; MemoryRegion secsram; -- 2.43.0