hw/sd/sdhci: Extract uSDHC-specific quirk
In Linux, the ESDHC_MIX_CTRL quirk is guarded by esdhc_is_usdhc() while the eSDHC code path uses the standard SDHC interface. Extract the quirk into a new `usdhc_write()` function. Fixes file system corruption on emulated i.MX53 where Linux' esdhc_is_usdhc() returns false. The same likely happens on e500 and imx25-pdk machines. Cc: qemu-stable@nongnu.org Fixes: 75e98bc4f859 ("hw/sd/sdhci: Add TYPE_FSL_ESDHC_BE") Reviewed-by: Bin Meng <bin.meng@processmission.com> Signed-off-by: Bernhard Beschow <shentey@gmail.com> Message-ID: <20260720201133.24796-3-shentey@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Bernhard Beschow committed
Jul 20, 2026 at 22:11 UTC
11ed6b92130a3b075cd6528e991c78538685d56a
1 file changed
+44
-29
hw/sd/sdhci.c
+44
-29
@@ -1795,34 +1795,6 @@ esdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
1795
sdhci_write(opaque, offset, value, size);
1796
break;
1797
1798
- case ESDHC_MIX_CTRL:
1799
- /*
1800
- * So, when SD/MMC stack in Linux tries to write to "Transfer
1801
- * Mode Register", ESDHC i.MX quirk code will translate it
1802
- * into a write to ESDHC_MIX_CTRL, so we do the opposite in
1803
- * order to get where we started
1804
- *
1805
- * Note that Auto CMD23 Enable bit is located in a wrong place
1806
- * on i.MX, but since it is not used by QEMU we do not care.
1807
- *
1808
- * We don't want to call sdhci_write(.., SDHC_TRNMOD, ...)
1809
- * here because it will result in a call to
1810
- * sdhci_send_command(s) which we don't want.
1811
- *
1812
- */
1813
- s->trnmod = value & UINT16_MAX;
1814
- break;
1815
- case SDHC_TRNMOD:
1816
- /*
1817
- * Similar to above, but this time a write to "Command
1818
- * Register" will be translated into a 4-byte write to
1819
- * "Transfer Mode register" where lower 16-bit of value would
1820
- * be set to zero. So what we do is fill those bits with
1821
- * cached value from s->trnmod and let the SDHCI
1822
- * infrastructure handle the rest
1823
- */
1824
- sdhci_write(opaque, offset, val | s->trnmod, size);
1825
- break;
1798
case SDHC_BLKSIZE:
1799
/*
1800
* ESDHCI does not implement "Host SDMA Buffer Boundary", and
@@ -1891,9 +1863,52 @@ static void fsl_esdhc_le_init(Object *obj)
1863
qdev_prop_set_uint8(dev, "sd-spec-version", 2);
1864
}
1865
1866
+static void
1867
+usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
1868
+{
1869
+ SDHCIState *s = SYSBUS_SDHCI(opaque);
1870
+ uint32_t value = (uint32_t)val;
1871
+
1872
+ switch (offset) {
1873
+ case ESDHC_MIX_CTRL:
1874
+ /*
1875
+ * So, when SD/MMC stack in Linux tries to write to "Transfer
1876
+ * Mode Register", uSDHC i.MX quirk code will translate it
1877
+ * into a write to ESDHC_MIX_CTRL, so we do the opposite in
1878
+ * order to get where we started.
1879
+ *
1880
+ * Note that Auto CMD23 Enable bit is located in a wrong place
1881
+ * on i.MX, but since it is not used by QEMU we do not care.
1882
+ *
1883
+ * We don't want to call sdhci_write(.., SDHC_TRNMOD, ...)
1884
+ * here because it will result in a call to
1885
+ * sdhci_send_command(s) which we don't want.
1886
+ *
1887
+ */
1888
+ s->trnmod = value & UINT16_MAX;
1889
+ break;
1890
+
1891
+ case SDHC_TRNMOD:
1892
+ /*
1893
+ * Similar to above, but this time a write to "Command
1894
+ * Register" will be translated into a 4-byte write to
1895
+ * "Transfer Mode register" where lower 16-bit of value would
1896
+ * be set to zero. So what we do is fill those bits with
1897
+ * cached value from s->trnmod and let the SDHCI
1898
+ * infrastructure handle the rest
1899
+ */
1900
+ sdhci_write(opaque, offset, val | s->trnmod, size);
1901
+ break;
1902
+
1903
+ default:
1904
+ esdhc_write(opaque, offset, val, size);
1905
+ break;
1906
+ }
1907
+}
1908
+
1909
static const MemoryRegionOps usdhc_mmio_ops = {
1910
.read = esdhc_read,
1896
- .write = esdhc_write,
1911
+ .write = usdhc_write,
1912
.valid = {
1913
.min_access_size = 1,
1914
.max_access_size = 4,