summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKane-Chen-AS <kane_chen@aspeedtech.com>2025-08-12 17:40:04 +0800
committerCédric Le Goater <clg@redhat.com>2025-09-29 18:00:20 +0200
commit02cebef5a140a0008a8bb0d3db6e33a4e7e4a9d2 (patch)
tree237b4be561f1e38c0b2af349cc76cae8fd1f549f
parentfdad6ec30dfb87df0980887a4c22e55ccf65f9c3 (diff)
downloadfocaccia-qemu-02cebef5a140a0008a8bb0d3db6e33a4e7e4a9d2.tar.gz
focaccia-qemu-02cebef5a140a0008a8bb0d3db6e33a4e7e4a9d2.zip
hw/misc/aspeed_sbc: Add CAMP2 support for OTP data reads
The OTP space contains three types of entries: data, conf, and strap.
Data entries consist of two DWORDs, while the other types contain
only one DWORD. This change adds the R_CAMP2 register (0x024 / 4) to
store the second DWORD when reading from the OTP data region.

With this enhancement, OTP reads now correctly return both DWORDs for
data entries via the CAMP registers, along with improved address
validation and error handling.

Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Link: https://lore.kernel.org/qemu-devel/20250812094011.2617526-8-kane_chen@aspeedtech.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
-rw-r--r--hw/misc/aspeed_sbc.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/hw/misc/aspeed_sbc.c b/hw/misc/aspeed_sbc.c
index 052c70fd42..787e2d0489 100644
--- a/hw/misc/aspeed_sbc.c
+++ b/hw/misc/aspeed_sbc.c
@@ -22,6 +22,7 @@
 #define R_ADDR          (0x010 / 4)
 #define R_STATUS        (0x014 / 4)
 #define R_CAMP1         (0x020 / 4)
+#define R_CAMP2         (0x024 / 4)
 #define R_QSR           (0x040 / 4)
 
 /* R_STATUS */
@@ -50,6 +51,8 @@
 #define SBC_OTP_CMD_READ 0x23b1e361
 #define SBC_OTP_CMD_PROG 0x23b1e364
 
+#define OTP_DATA_DWORD_COUNT        (0x800)
+#define OTP_TOTAL_DWORD_COUNT       (0x1000)
 static uint64_t aspeed_sbc_read(void *opaque, hwaddr addr, unsigned int size)
 {
     AspeedSBCState *s = ASPEED_SBC(opaque);
@@ -72,6 +75,16 @@ static bool aspeed_sbc_otp_read(AspeedSBCState *s,
     MemTxResult ret;
     AspeedOTPState *otp = &s->otp;
     uint32_t value, otp_offset;
+    bool is_data = false;
+
+    if (otp_addr < OTP_DATA_DWORD_COUNT) {
+        is_data = true;
+    } else if (otp_addr >= OTP_TOTAL_DWORD_COUNT) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "Invalid OTP addr 0x%x\n",
+                      otp_addr);
+        return false;
+    }
 
     otp_offset = otp_addr << 2;
     ret = address_space_read(&otp->as, otp_offset, MEMTXATTRS_UNSPECIFIED,
@@ -85,6 +98,20 @@ static bool aspeed_sbc_otp_read(AspeedSBCState *s,
     s->regs[R_CAMP1] = value;
     trace_aspeed_sbc_otp_read(otp_addr, value);
 
+    if (is_data) {
+        ret = address_space_read(&otp->as, otp_offset + 4,
+                                 MEMTXATTRS_UNSPECIFIED,
+                                 &value, sizeof(value));
+        if (ret != MEMTX_OK) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "Failed to read OTP memory, addr = %x\n",
+                          otp_addr);
+            return false;
+        }
+        s->regs[R_CAMP2] = value;
+        trace_aspeed_sbc_otp_read(otp_addr + 1, value);
+    }
+
     return true;
 }