On 4/23/25 04:56, Kane Chen wrote:
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 \
...
```
I thought we were going to implement the same method of the edk2 flash
devices of the q35 machine. Setting a machine option would set the drive :
qemu-system-arm -M ast2600-evb,otpmem=otpmem-drive \
-blockdev node-name=otpmem,driver=file,filename=/path/to/otpmem.img \
...
Which is not what is proposed below.
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);
+
This belongs to AspeedSBC. See below.
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);
+ }
+
The "optmem" machine option should be pointing to "drive" option of
the AspeedOTPMemState object in this object hierarchy :
/machine (ast2600-evb-machine)
/soc (ast2600-a3)
/sbc (aspeed.sbc)
/aspeed.sbc[0] (memory-region)
/optmem (aspeed.otpmem) <- move otpmem there
This will require using object_property_add_alias() in 2 or 3 levels.
object_property_add_alias(OBJECT(parent), "optmem"
OBJECT(child), "drive", &error_abort)
Please try that instead and let's see the result.
Thanks,
C.