The Host Control 2 register has been part of SDHCIState since its
initial implementation, but it was omitted from sdhci_vmstate.
Migration therefore resets the register to zero and can change tuning,
voltage, or DMA behavior.
Migrate nonzero values in an optional subsection. Clear the register
before loading so older streams retain the reset default without
changing the main stream version.
Fixes: ea55a221bfc0 ("sdhci: implement the Host Control 2 register (tuning
sequence)")
Signed-off-by: Bin Meng <[email protected]>
---
hw/sd/sdhci.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 55a4abdd72..749de85476 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1470,6 +1470,24 @@ void sdhci_common_unrealize(SDHCIState *s)
s->fifo_buffer = NULL;
}
+static bool sdhci_hostctl2_vmstate_needed(void *opaque)
+{
+ SDHCIState *s = opaque;
+
+ return s->hostctl2;
+}
+
+static const VMStateDescription sdhci_hostctl2_vmstate = {
+ .name = "sdhci/hostctl2",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = sdhci_hostctl2_vmstate_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT16(hostctl2, SDHCIState),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static bool sdhci_pending_insert_vmstate_needed(void *opaque)
{
SDHCIState *s = opaque;
@@ -1488,6 +1506,7 @@ static int sdhci_pre_load(void *opaque)
{
SDHCIState *s = opaque;
+ s->hostctl2 = 0;
s->sdma_boundary_paused = false;
return 0;
}
@@ -1562,6 +1581,7 @@ const VMStateDescription sdhci_vmstate = {
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription * const []) {
+ &sdhci_hostctl2_vmstate,
&sdhci_pending_insert_vmstate,
&sdhci_sdma_boundary_paused_vmstate,
NULL
--
2.34.1