From 61dcc2c2db0236fde878d053028c39fe27dc8f36 Mon Sep 17 00:00:00 2001 From: Kane-Chen-AS Date: Tue, 12 Aug 2025 17:40:05 +0800 Subject: hw/misc/aspeed_sbc: Handle OTP write command for voltage mode registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend OTP command handling to recognize specific voltage mode register addresses and emulate the expected hardware behavior. Without this change, legitimate voltage mode change requests would be incorrectly reported as "Unknown command" and logged as an error. This implementation does not perform actual mode changes, but ensures that valid requests are accepted and ignored as per hardware behavior. Signed-off-by: Kane-Chen-AS Reviewed-by: Cédric Le Goater Link: https://lore.kernel.org/qemu-devel/20250812094011.2617526-9-kane_chen@aspeedtech.com Signed-off-by: Cédric Le Goater --- hw/misc/aspeed_sbc.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'hw/misc/aspeed_sbc.c') diff --git a/hw/misc/aspeed_sbc.c b/hw/misc/aspeed_sbc.c index 787e2d0489..2fc5db749d 100644 --- a/hw/misc/aspeed_sbc.c +++ b/hw/misc/aspeed_sbc.c @@ -49,10 +49,17 @@ #define OTP_MEMORY_SIZE 0x4000 /* OTP command */ #define SBC_OTP_CMD_READ 0x23b1e361 +#define SBC_OTP_CMD_WRITE 0x23b1e362 #define SBC_OTP_CMD_PROG 0x23b1e364 #define OTP_DATA_DWORD_COUNT (0x800) #define OTP_TOTAL_DWORD_COUNT (0x1000) + +/* Voltage mode */ +#define MODE_REGISTER (0x1000) +#define MODE_REGISTER_A (0x3000) +#define MODE_REGISTER_B (0x5000) + static uint64_t aspeed_sbc_read(void *opaque, hwaddr addr, unsigned int size) { AspeedSBCState *s = ASPEED_SBC(opaque); @@ -115,6 +122,37 @@ static bool aspeed_sbc_otp_read(AspeedSBCState *s, return true; } +static bool mode_handler(uint32_t otp_addr) +{ + switch (otp_addr) { + case MODE_REGISTER: + case MODE_REGISTER_A: + case MODE_REGISTER_B: + /* HW behavior, do nothing here */ + return true; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "Unsupported address 0x%x\n", + otp_addr); + return false; + } +} + +static bool aspeed_sbc_otp_write(AspeedSBCState *s, + uint32_t otp_addr) +{ + if (otp_addr == 0) { + trace_aspeed_sbc_ignore_cmd(otp_addr); + return true; + } else { + if (mode_handler(otp_addr) == false) { + return false; + } + } + + return true; +} + static bool aspeed_sbc_otp_prog(AspeedSBCState *s, uint32_t otp_addr) { @@ -157,6 +195,9 @@ static void aspeed_sbc_handle_command(void *opaque, uint32_t cmd) case SBC_OTP_CMD_READ: ret = aspeed_sbc_otp_read(s, otp_addr); break; + case SBC_OTP_CMD_WRITE: + ret = aspeed_sbc_otp_write(s, otp_addr); + break; case SBC_OTP_CMD_PROG: ret = aspeed_sbc_otp_prog(s, otp_addr); break; -- cgit 1.4.1