qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers
@ 2025-03-08 19:02 Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 01/12] hw/sd/sdhci: Remove need for SDHCIState::vendor field Philippe Mathieu-Daudé
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

Rainy saturday, time for some hobbyist contributions :)

In this series we try to address the issue Zoltan reported
and try to fix in [*], but using a more generic approach.
The SDHCI code ends up better consolidated and ready to
scale for more vendor implementations.

I expect (with few QOM knowledge) this to be trivial to review.

- Remove SDHCIState::vendor field
- Convert state fields to class ones
- Simplify endianness handling
- Add default reset values as class fields

[*] https://lore.kernel.org/qemu-devel/20250210160329.DDA7F4E600E@zero.eik.bme.hu/

Philippe Mathieu-Daudé (12):
  hw/sd/sdhci: Remove need for SDHCIState::vendor field
  hw/sd/sdhci: Introduce SDHCIClass stub
  hw/sd/sdhci: Make quirks a class property
  hw/sd/sdhci: Make I/O region size a class property
  hw/sd/sdhci: Enforce little endianness on PCI devices
  hw/sd/sdhci: Allow SDHCI classes to register their own MemoryRegionOps
  hw/sd/sdhci: Simplify MemoryRegionOps endianness check
  hw/sd/sdhci: Unify default MemoryRegionOps
  hw/sd/sdhci: Add SDHCIClass::ro::capareg field
  hw/sd/sdhci: Allow SDHCI classes to have different register reset
    values
  hw/sd/sdhci: Implement Freescale eSDHC as TYPE_FSL_ESDHC
  hw/ppc/e500: Replace generic SDHCI by Freescale eSDHC

 hw/sd/sdhci-internal.h |  25 +++----
 include/hw/sd/sdhci.h  |  43 ++++++++++-
 hw/arm/fsl-imx25.c     |   2 -
 hw/arm/fsl-imx6.c      |   2 -
 hw/arm/fsl-imx6ul.c    |   2 -
 hw/arm/fsl-imx7.c      |   2 -
 hw/arm/fsl-imx8mp.c    |   2 -
 hw/ppc/e500.c          |  10 +--
 hw/sd/sdhci-pci.c      |   1 +
 hw/sd/sdhci.c          | 163 ++++++++++++++++++++++++++---------------
 10 files changed, 155 insertions(+), 97 deletions(-)

-- 
2.47.1



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3 01/12] hw/sd/sdhci: Remove need for SDHCIState::vendor field
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 02/12] hw/sd/sdhci: Introduce SDHCIClass stub Philippe Mathieu-Daudé
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

All instances of TYPE_IMX_USDHC set vendor=SDHCI_VENDOR_IMX.
No need to special-case it.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/sd/sdhci-internal.h |  1 -
 include/hw/sd/sdhci.h  |  4 ----
 hw/arm/fsl-imx25.c     |  2 --
 hw/arm/fsl-imx6.c      |  2 --
 hw/arm/fsl-imx6ul.c    |  2 --
 hw/arm/fsl-imx7.c      |  2 --
 hw/arm/fsl-imx8mp.c    |  2 --
 hw/sd/sdhci.c          | 14 ++++----------
 8 files changed, 4 insertions(+), 25 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index 9f768c418e0..9072b06bdde 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -311,7 +311,6 @@ extern const VMStateDescription sdhci_vmstate;
     DEFINE_PROP_UINT8("endianness", _state, endianness, DEVICE_LITTLE_ENDIAN), \
     DEFINE_PROP_UINT8("sd-spec-version", _state, sd_spec_version, 2), \
     DEFINE_PROP_UINT8("uhs", _state, uhs_mode, UHS_NOT_SUPPORTED), \
-    DEFINE_PROP_UINT8("vendor", _state, vendor, SDHCI_VENDOR_NONE), \
     \
     /* Capabilities registers provide information on supported
      * features of this specific host controller implementation */ \
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 38c08e28598..48247e9a20f 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -99,7 +99,6 @@ struct SDHCIState {
     uint8_t endianness;
     uint8_t sd_spec_version;
     uint8_t uhs_mode;
-    uint8_t vendor;        /* For vendor specific functionality */
     /*
      * Write Protect pin default active low for detecting SD card
      * to be protected. Set wp_inverted to invert the signal.
@@ -108,9 +107,6 @@ struct SDHCIState {
 };
 typedef struct SDHCIState SDHCIState;
 
-#define SDHCI_VENDOR_NONE       0
-#define SDHCI_VENDOR_IMX        1
-
 /*
  * Controller does not provide transfer-complete interrupt when not
  * busy.
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
index 5359a6d8d3b..02214ca1a1c 100644
--- a/hw/arm/fsl-imx25.c
+++ b/hw/arm/fsl-imx25.c
@@ -243,8 +243,6 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
                                  &error_abort);
         object_property_set_uint(OBJECT(&s->esdhc[i]), "capareg",
                                  IMX25_ESDHC_CAPABILITIES, &error_abort);
-        object_property_set_uint(OBJECT(&s->esdhc[i]), "vendor",
-                                 SDHCI_VENDOR_IMX, &error_abort);
         if (!sysbus_realize(SYS_BUS_DEVICE(&s->esdhc[i]), errp)) {
             return;
         }
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index dc86338b3a5..a114dc0d63d 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -327,8 +327,6 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
                                  &error_abort);
         object_property_set_uint(OBJECT(&s->esdhc[i]), "capareg",
                                  IMX6_ESDHC_CAPABILITIES, &error_abort);
-        object_property_set_uint(OBJECT(&s->esdhc[i]), "vendor",
-                                 SDHCI_VENDOR_IMX, &error_abort);
         if (!sysbus_realize(SYS_BUS_DEVICE(&s->esdhc[i]), errp)) {
             return;
         }
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index 34c4aa15cd0..ce8d3ef535f 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -531,8 +531,6 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
             FSL_IMX6UL_USDHC2_IRQ,
         };
 
-        object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor",
-                                 SDHCI_VENDOR_IMX, &error_abort);
         sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), &error_abort);
 
         sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 3374018cde0..ed1f10bca26 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -471,8 +471,6 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
             FSL_IMX7_USDHC3_IRQ,
         };
 
-        object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor",
-                                 SDHCI_VENDOR_IMX, &error_abort);
         sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), &error_abort);
 
         sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 1ea98e14635..c3f6da63220 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -524,8 +524,6 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
             { fsl_imx8mp_memmap[FSL_IMX8MP_USDHC3].addr, FSL_IMX8MP_USDHC3_IRQ },
         };
 
-        object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor",
-                                 SDHCI_VENDOR_IMX, &error_abort);
         if (!sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), errp)) {
             return;
         }
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 1f45a77566c..149b748cbee 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1731,16 +1731,10 @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
 
     case USDHC_VENDOR_SPEC:
         s->vendor_spec = value;
-        switch (s->vendor) {
-        case SDHCI_VENDOR_IMX:
-            if (value & USDHC_IMX_FRC_SDCLK_ON) {
-                s->prnsts &= ~SDHC_IMX_CLOCK_GATE_OFF;
-            } else {
-                s->prnsts |= SDHC_IMX_CLOCK_GATE_OFF;
-            }
-            break;
-        default:
-            break;
+        if (value & USDHC_IMX_FRC_SDCLK_ON) {
+            s->prnsts &= ~SDHC_IMX_CLOCK_GATE_OFF;
+        } else {
+            s->prnsts |= SDHC_IMX_CLOCK_GATE_OFF;
         }
         break;
 
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 02/12] hw/sd/sdhci: Introduce SDHCIClass stub
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 01/12] hw/sd/sdhci: Remove need for SDHCIState::vendor field Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 03/12] hw/sd/sdhci: Make quirks a class property Philippe Mathieu-Daudé
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

TYPE_SYSBUS_SDHCI is a bit odd because it uses an union
to work with both SysBus / PCI parent. As this is not a
normal use, introduce SDHCIClass in its own commit.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/hw/sd/sdhci.h | 9 +++++++++
 hw/sd/sdhci.c         | 1 +
 2 files changed, 10 insertions(+)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 48247e9a20f..c4b20db3877 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -107,6 +107,13 @@ struct SDHCIState {
 };
 typedef struct SDHCIState SDHCIState;
 
+typedef struct SDHCIClass {
+    union {
+        PCIDeviceClass pci_parent_class;
+        SysBusDeviceClass sbd_parent_class;
+    };
+} SDHCIClass;
+
 /*
  * Controller does not provide transfer-complete interrupt when not
  * busy.
@@ -123,6 +130,8 @@ DECLARE_INSTANCE_CHECKER(SDHCIState, PCI_SDHCI,
 #define TYPE_SYSBUS_SDHCI "generic-sdhci"
 DECLARE_INSTANCE_CHECKER(SDHCIState, SYSBUS_SDHCI,
                          TYPE_SYSBUS_SDHCI)
+DECLARE_CLASS_CHECKERS(SDHCIClass, SYSBUS_SDHCI,
+                       TYPE_SYSBUS_SDHCI)
 
 #define TYPE_IMX_USDHC "imx-usdhc"
 
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 149b748cbee..4917a9b3632 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1960,6 +1960,7 @@ static const TypeInfo sdhci_types[] = {
         .instance_size = sizeof(SDHCIState),
         .instance_init = sdhci_sysbus_init,
         .instance_finalize = sdhci_sysbus_finalize,
+        .class_size = sizeof(SDHCIClass),
         .class_init = sdhci_sysbus_class_init,
     },
     {
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 03/12] hw/sd/sdhci: Make quirks a class property
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 01/12] hw/sd/sdhci: Remove need for SDHCIState::vendor field Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 02/12] hw/sd/sdhci: Introduce SDHCIClass stub Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 04/12] hw/sd/sdhci: Make I/O region size " Philippe Mathieu-Daudé
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

All TYPE_IMX_USDHC instances use the quirk:
move it to the class layer.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/hw/sd/sdhci.h |  3 ++-
 hw/sd/sdhci.c         | 15 +++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index c4b20db3877..0616ce3aa59 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -95,7 +95,6 @@ struct SDHCIState {
 
     /* Configurable properties */
     bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
-    uint32_t quirks;
     uint8_t endianness;
     uint8_t sd_spec_version;
     uint8_t uhs_mode;
@@ -112,6 +111,8 @@ typedef struct SDHCIClass {
         PCIDeviceClass pci_parent_class;
         SysBusDeviceClass sbd_parent_class;
     };
+
+    uint32_t quirks;
 } SDHCIClass;
 
 /*
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 4917a9b3632..2b7eb11a14a 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -345,6 +345,8 @@ static void sdhci_send_command(SDHCIState *s)
     rlen = sdbus_do_command(&s->sdbus, &request, response);
 
     if (s->cmdreg & SDHC_CMD_RESPONSE) {
+        SDHCIClass *sc = SYSBUS_SDHCI_GET_CLASS(s);
+
         if (rlen == 4) {
             s->rspreg[0] = ldl_be_p(response);
             s->rspreg[1] = s->rspreg[2] = s->rspreg[3] = 0;
@@ -366,7 +368,7 @@ static void sdhci_send_command(SDHCIState *s)
             }
         }
 
-        if (!(s->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
+        if (!(sc->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
             (s->norintstsen & SDHC_NISEN_TRSCMP) &&
             (s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) {
             s->norintsts |= SDHC_NIS_TRSCMP;
@@ -1886,7 +1888,15 @@ static void imx_usdhc_init(Object *obj)
     SDHCIState *s = SYSBUS_SDHCI(obj);
 
     s->io_ops = &usdhc_mmio_ops;
-    s->quirks = SDHCI_QUIRK_NO_BUSY_IRQ;
+}
+
+static void imx_usdhc_class_init(ObjectClass *oc, void *data)
+{
+    SDHCIClass *sc = SYSBUS_SDHCI_CLASS(oc);
+
+    sc->quirks = SDHCI_QUIRK_NO_BUSY_IRQ;
+
+    sdhci_common_class_init(oc, data);
 }
 
 /* --- qdev Samsung s3c --- */
@@ -1967,6 +1977,7 @@ static const TypeInfo sdhci_types[] = {
         .name = TYPE_IMX_USDHC,
         .parent = TYPE_SYSBUS_SDHCI,
         .instance_init = imx_usdhc_init,
+        .class_init = imx_usdhc_class_init,
     },
     {
         .name = TYPE_S3C_SDHCI,
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 04/12] hw/sd/sdhci: Make I/O region size a class property
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
                   ` (2 preceding siblings ...)
  2025-03-08 19:02 ` [PATCH v3 03/12] hw/sd/sdhci: Make quirks a class property Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 05/12] hw/sd/sdhci: Enforce little endianness on PCI devices Philippe Mathieu-Daudé
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

Be ready to have SDHC implementations to cover
a wider I/O address range.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/hw/sd/sdhci.h | 1 +
 hw/sd/sdhci.c         | 9 +++++++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 0616ce3aa59..2709a7a69d5 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -113,6 +113,7 @@ typedef struct SDHCIClass {
     };
 
     uint32_t quirks;
+    uint64_t iomem_size;
 } SDHCIClass;
 
 /*
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 2b7eb11a14a..59d506cafa3 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1443,6 +1443,7 @@ void sdhci_uninitfn(SDHCIState *s)
 void sdhci_common_realize(SDHCIState *s, Error **errp)
 {
     ERRP_GUARD();
+    SDHCIClass *sc = SYSBUS_SDHCI_GET_CLASS(s);
 
     switch (s->endianness) {
     case DEVICE_LITTLE_ENDIAN:
@@ -1468,8 +1469,9 @@ void sdhci_common_realize(SDHCIState *s, Error **errp)
     s->buf_maxsz = sdhci_get_fifolen(s);
     s->fifo_buffer = g_malloc0(s->buf_maxsz);
 
-    memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci",
-                          SDHC_REGISTERS_MAP_SIZE);
+    assert(sc->iomem_size >= SDHC_REGISTERS_MAP_SIZE);
+    memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s,
+                          object_get_typename(OBJECT(s)), sc->iomem_size);
 }
 
 void sdhci_common_unrealize(SDHCIState *s)
@@ -1621,11 +1623,14 @@ static void sdhci_sysbus_unrealize(DeviceState *dev)
 static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    SDHCIClass *sc = SYSBUS_SDHCI_CLASS(klass);
 
     device_class_set_props(dc, sdhci_sysbus_properties);
     dc->realize = sdhci_sysbus_realize;
     dc->unrealize = sdhci_sysbus_unrealize;
 
+    sc->iomem_size = SDHC_REGISTERS_MAP_SIZE;
+
     sdhci_common_class_init(klass, data);
 }
 
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 05/12] hw/sd/sdhci: Enforce little endianness on PCI devices
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
                   ` (3 preceding siblings ...)
  2025-03-08 19:02 ` [PATCH v3 04/12] hw/sd/sdhci: Make I/O region size " Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 06/12] hw/sd/sdhci: Allow SDHCI classes to register their own MemoryRegionOps Philippe Mathieu-Daudé
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

This is the default, but better be safe than sorry.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/sd/sdhci-pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/sd/sdhci-pci.c b/hw/sd/sdhci-pci.c
index 5268c0dee50..5f82178a76f 100644
--- a/hw/sd/sdhci-pci.c
+++ b/hw/sd/sdhci-pci.c
@@ -32,6 +32,7 @@ static void sdhci_pci_realize(PCIDevice *dev, Error **errp)
     SDHCIState *s = PCI_SDHCI(dev);
 
     sdhci_initfn(s);
+    qdev_prop_set_uint8(DEVICE(dev), "endianness", DEVICE_LITTLE_ENDIAN);
     sdhci_common_realize(s, errp);
     if (*errp) {
         return;
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 06/12] hw/sd/sdhci: Allow SDHCI classes to register their own MemoryRegionOps
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
                   ` (4 preceding siblings ...)
  2025-03-08 19:02 ` [PATCH v3 05/12] hw/sd/sdhci: Enforce little endianness on PCI devices Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 07/12] hw/sd/sdhci: Simplify MemoryRegionOps endianness check Philippe Mathieu-Daudé
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

Add MemoryRegionOps as a class property. For now it is only
used by TYPE_IMX_USDHC.
Otherwise the default remains in little endian.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/hw/sd/sdhci.h |  1 +
 hw/sd/sdhci.c         | 22 ++++++++--------------
 2 files changed, 9 insertions(+), 14 deletions(-)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 2709a7a69d5..60a0442c805 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -112,6 +112,7 @@ typedef struct SDHCIClass {
         SysBusDeviceClass sbd_parent_class;
     };
 
+    const MemoryRegionOps *io_ops;
     uint32_t quirks;
     uint64_t iomem_size;
 } SDHCIClass;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 59d506cafa3..d87a7bb45a4 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1427,8 +1427,6 @@ void sdhci_initfn(SDHCIState *s)
                                    sdhci_raise_insertion_irq, s);
     s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
                                      sdhci_data_transfer, s);
-
-    s->io_ops = &sdhci_mmio_le_ops;
 }
 
 void sdhci_uninitfn(SDHCIState *s)
@@ -1445,6 +1443,7 @@ void sdhci_common_realize(SDHCIState *s, Error **errp)
     ERRP_GUARD();
     SDHCIClass *sc = SYSBUS_SDHCI_GET_CLASS(s);
 
+    s->io_ops = sc->io_ops ?: &sdhci_mmio_le_ops;
     switch (s->endianness) {
     case DEVICE_LITTLE_ENDIAN:
         /* s->io_ops is little endian by default */
@@ -1888,17 +1887,11 @@ static const MemoryRegionOps usdhc_mmio_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static void imx_usdhc_init(Object *obj)
-{
-    SDHCIState *s = SYSBUS_SDHCI(obj);
-
-    s->io_ops = &usdhc_mmio_ops;
-}
-
 static void imx_usdhc_class_init(ObjectClass *oc, void *data)
 {
     SDHCIClass *sc = SYSBUS_SDHCI_CLASS(oc);
 
+    sc->io_ops = &usdhc_mmio_ops;
     sc->quirks = SDHCI_QUIRK_NO_BUSY_IRQ;
 
     sdhci_common_class_init(oc, data);
@@ -1955,11 +1948,13 @@ static const MemoryRegionOps sdhci_s3c_mmio_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static void sdhci_s3c_init(Object *obj)
+static void sdhci_s3c_class_init(ObjectClass *oc, void *data)
 {
-    SDHCIState *s = SYSBUS_SDHCI(obj);
+    SDHCIClass *sc = SYSBUS_SDHCI_CLASS(oc);
 
-    s->io_ops = &sdhci_s3c_mmio_ops;
+    sc->io_ops = &sdhci_s3c_mmio_ops;
+
+    sdhci_common_class_init(oc, data);
 }
 
 static const TypeInfo sdhci_types[] = {
@@ -1981,13 +1976,12 @@ static const TypeInfo sdhci_types[] = {
     {
         .name = TYPE_IMX_USDHC,
         .parent = TYPE_SYSBUS_SDHCI,
-        .instance_init = imx_usdhc_init,
         .class_init = imx_usdhc_class_init,
     },
     {
         .name = TYPE_S3C_SDHCI,
         .parent = TYPE_SYSBUS_SDHCI,
-        .instance_init = sdhci_s3c_init,
+        .class_init = sdhci_s3c_class_init,
     },
 };
 
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 07/12] hw/sd/sdhci: Simplify MemoryRegionOps endianness check
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
                   ` (5 preceding siblings ...)
  2025-03-08 19:02 ` [PATCH v3 06/12] hw/sd/sdhci: Allow SDHCI classes to register their own MemoryRegionOps Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 08/12] hw/sd/sdhci: Unify default MemoryRegionOps Philippe Mathieu-Daudé
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

While little endianness is the default, ome controllers
might be only implemented in big endianness.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/sd/sdhci.c | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index d87a7bb45a4..d115e88c4b9 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1443,20 +1443,10 @@ void sdhci_common_realize(SDHCIState *s, Error **errp)
     ERRP_GUARD();
     SDHCIClass *sc = SYSBUS_SDHCI_GET_CLASS(s);
 
-    s->io_ops = sc->io_ops ?: &sdhci_mmio_le_ops;
-    switch (s->endianness) {
-    case DEVICE_LITTLE_ENDIAN:
-        /* s->io_ops is little endian by default */
-        break;
-    case DEVICE_BIG_ENDIAN:
-        if (s->io_ops != &sdhci_mmio_le_ops) {
-            error_setg(errp, "SD controller doesn't support big endianness");
-            return;
-        }
-        s->io_ops = &sdhci_mmio_be_ops;
-        break;
-    default:
-        error_setg(errp, "Incorrect endianness");
+    s->io_ops = sc->io_ops ?: (s->endianness == DEVICE_BIG_ENDIAN ?
+                               &sdhci_mmio_be_ops : &sdhci_mmio_le_ops);
+    if (s->io_ops->endianness != s->endianness) {
+        error_setg(errp, "Invalid endianness for SD controller");
         return;
     }
 
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 08/12] hw/sd/sdhci: Unify default MemoryRegionOps
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
                   ` (6 preceding siblings ...)
  2025-03-08 19:02 ` [PATCH v3 07/12] hw/sd/sdhci: Simplify MemoryRegionOps endianness check Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 09/12] hw/sd/sdhci: Add SDHCIClass::ro::capareg field Philippe Mathieu-Daudé
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

Note, sdhci_mmio_le_ops[] was missing .impl.access_size = 4.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/sd/sdhci.c | 41 ++++++++++++++++-------------------------
 1 file changed, 16 insertions(+), 25 deletions(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index d115e88c4b9..15e6976220f 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1372,30 +1372,22 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
                        value >> shift, value >> shift);
 }
 
-static const MemoryRegionOps sdhci_mmio_le_ops = {
-    .read = sdhci_read,
-    .write = sdhci_write,
-    .valid = {
-        .min_access_size = 1,
-        .max_access_size = 4,
-        .unaligned = false
+static const MemoryRegionOps sdhci_mmio_ops[2] = {
+    [0 ... 1] = {
+        .read = sdhci_read,
+        .write = sdhci_write,
+        .impl = {
+            .min_access_size = 4,
+            .max_access_size = 4,
+        },
+        .valid = {
+            .min_access_size = 1,
+            .max_access_size = 4,
+            .unaligned = false
+        },
     },
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static const MemoryRegionOps sdhci_mmio_be_ops = {
-    .read = sdhci_read,
-    .write = sdhci_write,
-    .impl = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-    .valid = {
-        .min_access_size = 1,
-        .max_access_size = 4,
-        .unaligned = false
-    },
-    .endianness = DEVICE_BIG_ENDIAN,
+    [0].endianness = DEVICE_LITTLE_ENDIAN,
+    [1].endianness = DEVICE_BIG_ENDIAN,
 };
 
 static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
@@ -1443,8 +1435,7 @@ void sdhci_common_realize(SDHCIState *s, Error **errp)
     ERRP_GUARD();
     SDHCIClass *sc = SYSBUS_SDHCI_GET_CLASS(s);
 
-    s->io_ops = sc->io_ops ?: (s->endianness == DEVICE_BIG_ENDIAN ?
-                               &sdhci_mmio_be_ops : &sdhci_mmio_le_ops);
+    s->io_ops = sc->io_ops ?: &sdhci_mmio_ops[s->endianness == DEVICE_BIG_ENDIAN];
     if (s->io_ops->endianness != s->endianness) {
         error_setg(errp, "Invalid endianness for SD controller");
         return;
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 09/12] hw/sd/sdhci: Add SDHCIClass::ro::capareg field
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
                   ` (7 preceding siblings ...)
  2025-03-08 19:02 ` [PATCH v3 08/12] hw/sd/sdhci: Unify default MemoryRegionOps Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 10/12] hw/sd/sdhci: Allow SDHCI classes to have different register reset values Philippe Mathieu-Daudé
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

Capability register is read-only.

Since we allow instances to clear/set extra bits, log when
read-only bits normally set by hardware are cleared at
board level.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/hw/sd/sdhci.h | 5 +++++
 hw/sd/sdhci.c         | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 60a0442c805..53aef17ad34 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -115,6 +115,11 @@ typedef struct SDHCIClass {
     const MemoryRegionOps *io_ops;
     uint32_t quirks;
     uint64_t iomem_size;
+
+    /* Read-only registers */
+    struct {
+        uint64_t capareg;
+    } ro;
 } SDHCIClass;
 
 /*
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 15e6976220f..f08918587ef 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -73,6 +73,7 @@ static bool sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
 
 static void sdhci_check_capareg(SDHCIState *s, Error **errp)
 {
+    SDHCIClass *sc = SYSBUS_SDHCI_GET_CLASS(s);
     uint64_t msk = s->capareg;
     uint32_t val;
     bool y;
@@ -208,6 +209,11 @@ static void sdhci_check_capareg(SDHCIState *s, Error **errp)
         qemu_log_mask(LOG_UNIMP,
                       "SDHCI: unknown CAPAB mask: 0x%016" PRIx64 "\n", msk);
     }
+    msk = sc->ro.capareg & ~s->capareg;
+    if (msk) {
+        qemu_log_mask(LOG_UNIMP,
+                      "SDHCI: ignored CAPAB mask: 0x%016" PRIx64 "\n", msk);
+    }
 }
 
 static uint8_t sdhci_slotint(SDHCIState *s)
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 10/12] hw/sd/sdhci: Allow SDHCI classes to have different register reset values
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
                   ` (8 preceding siblings ...)
  2025-03-08 19:02 ` [PATCH v3 09/12] hw/sd/sdhci: Add SDHCIClass::ro::capareg field Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 11/12] hw/sd/sdhci: Implement Freescale eSDHC as TYPE_FSL_ESDHC Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 12/12] hw/ppc/e500: Replace generic SDHCI by Freescale eSDHC Philippe Mathieu-Daudé
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

For the registers which are not zeroed at reset, allow the
different implementations to set particular reset values.

Remove the misleading values commented in sdhci-internal.h.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/sd/sdhci-internal.h | 24 ++++++++++++------------
 include/hw/sd/sdhci.h  | 20 ++++++++++++++++++++
 hw/sd/sdhci.c          | 14 ++++++++++++++
 3 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index 9072b06bdde..d99a8493db2 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -70,7 +70,7 @@
 /* R/W Buffer Data Register 0x0 */
 #define SDHC_BDATA                     0x20
 
-/* R/ROC Present State Register 0x000A0000 */
+/* R/ROC Present State Register */
 #define SDHC_PRNSTS                    0x24
 #define SDHC_CMD_INHIBIT               0x00000001
 #define SDHC_DATA_INHIBIT              0x00000002
@@ -88,7 +88,7 @@ FIELD(SDHC_PRNSTS, CMD_LVL,            24, 1);
 #define TRANSFERRING_DATA(x)           \
     ((x) & (SDHC_DOING_READ | SDHC_DOING_WRITE))
 
-/* R/W Host control Register 0x0 */
+/* R/W Host control Register */
 #define SDHC_HOSTCTL                   0x28
 #define SDHC_CTRL_LED                  0x01
 #define SDHC_CTRL_DATATRANSFERWIDTH    0x02 /* SD mode only */
@@ -104,17 +104,17 @@ FIELD(SDHC_PRNSTS, CMD_LVL,            24, 1);
 #define SDHC_CTRL_CDTEST_INS           0x40
 #define SDHC_CTRL_CDTEST_EN            0x80
 
-/* R/W Power Control Register 0x0 */
+/* R/W Power Control Register */
 #define SDHC_PWRCON                    0x29
 #define SDHC_POWER_ON                  (1 << 0)
 FIELD(SDHC_PWRCON, BUS_VOLTAGE,        1, 3);
 
-/* R/W Block Gap Control Register 0x0 */
+/* R/W Block Gap Control Register */
 #define SDHC_BLKGAP                    0x2A
 #define SDHC_STOP_AT_GAP_REQ           0x01
 #define SDHC_CONTINUE_REQ              0x02
 
-/* R/W WakeUp Control Register 0x0 */
+/* R/W WakeUp Control Register */
 #define SDHC_WAKCON                    0x2B
 #define SDHC_WKUP_ON_INS               (1 << 1)
 #define SDHC_WKUP_ON_RMV               (1 << 2)
@@ -128,17 +128,17 @@ FIELD(SDHC_PWRCON, BUS_VOLTAGE,        1, 3);
 #define SDHC_CLOCK_IS_ON(x)            \
     (((x) & SDHC_CLOCK_CHK_MASK) == SDHC_CLOCK_CHK_MASK)
 
-/* R/W Timeout Control Register 0x0 */
+/* R/W Timeout Control Register */
 #define SDHC_TIMEOUTCON                0x2E
 FIELD(SDHC_TIMEOUTCON, COUNTER,        0, 4);
 
-/* R/W Software Reset Register 0x0 */
+/* R/W Software Reset Register */
 #define SDHC_SWRST                     0x2F
 #define SDHC_RESET_ALL                 0x01
 #define SDHC_RESET_CMD                 0x02
 #define SDHC_RESET_DATA                0x04
 
-/* ROC/RW1C Normal Interrupt Status Register 0x0 */
+/* ROC/RW1C Normal Interrupt Status Register */
 #define SDHC_NORINTSTS                 0x30
 #define SDHC_NIS_ERR                   0x8000
 #define SDHC_NIS_CMDCMP                0x0001
@@ -151,7 +151,7 @@ FIELD(SDHC_TIMEOUTCON, COUNTER,        0, 4);
 #define SDHC_NIS_REMOVE                0x0080
 #define SDHC_NIS_CARDINT               0x0100
 
-/* ROC/RW1C Error Interrupt Status Register 0x0 */
+/* ROC/RW1C Error Interrupt Status Register */
 #define SDHC_ERRINTSTS                 0x32
 #define SDHC_EIS_CMDTIMEOUT            0x0001
 #define SDHC_EIS_BLKGAP                0x0004
@@ -159,7 +159,7 @@ FIELD(SDHC_TIMEOUTCON, COUNTER,        0, 4);
 #define SDHC_EIS_CMD12ERR              0x0100
 #define SDHC_EIS_ADMAERR               0x0200
 
-/* R/W Normal Interrupt Status Enable Register 0x0 */
+/* R/W Normal Interrupt Status Enable Register */
 #define SDHC_NORINTSTSEN               0x34
 #define SDHC_NISEN_CMDCMP              0x0001
 #define SDHC_NISEN_TRSCMP              0x0002
@@ -170,7 +170,7 @@ FIELD(SDHC_TIMEOUTCON, COUNTER,        0, 4);
 #define SDHC_NISEN_REMOVE              0x0080
 #define SDHC_NISEN_CARDINT             0x0100
 
-/* R/W Error Interrupt Status Enable Register 0x0 */
+/* R/W Error Interrupt Status Enable Register */
 #define SDHC_ERRINTSTSEN               0x36
 #define SDHC_EISEN_CMDTIMEOUT          0x0001
 #define SDHC_EISEN_BLKGAP              0x0004
@@ -205,7 +205,7 @@ FIELD(SDHC_HOSTCTL2, VERSION4,        12, 1); /* since v4 */
 FIELD(SDHC_HOSTCTL2, ASYNC_INT,       14, 1);
 FIELD(SDHC_HOSTCTL2, PRESET_ENA,      15, 1);
 
-/* HWInit Capabilities Register 0x05E80080 */
+/* HWInit Capabilities Register */
 #define SDHC_CAPAB                     0x40
 FIELD(SDHC_CAPAB, TOCLKFREQ,           0, 6);
 FIELD(SDHC_CAPAB, TOUNIT,              7, 1);
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 53aef17ad34..e24392eb10d 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -116,6 +116,26 @@ typedef struct SDHCIClass {
     uint32_t quirks;
     uint64_t iomem_size;
 
+    /* Default reset values */
+    struct {
+        uint32_t sdmasysad;
+
+        uint16_t blksize;
+        uint16_t blkcnt;
+
+        uint32_t prnsts;
+
+        uint8_t  hostctl1;
+        uint8_t  pwrcon;
+        uint8_t  blkgap;
+        uint8_t  wakcon;
+
+        uint16_t clkcon;
+        uint8_t  timeoutcon;
+
+        uint16_t norintstsen;
+        uint16_t errintstsen;
+    } reset;
     /* Read-only registers */
     struct {
         uint64_t capareg;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index f08918587ef..cda608f8ec2 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -294,6 +294,7 @@ static void sdhci_set_readonly(DeviceState *dev, bool level)
 
 static void sdhci_reset(SDHCIState *s)
 {
+    SDHCIClass *sc = SYSBUS_SDHCI_GET_CLASS(s);
     DeviceState *dev = DEVICE(s);
 
     timer_del(s->insert_timer);
@@ -306,6 +307,19 @@ static void sdhci_reset(SDHCIState *s)
      */
     memset(&s->sdmasysad, 0, (uintptr_t)&s->capareg - (uintptr_t)&s->sdmasysad);
 
+    s->sdmasysad = sc->reset.sdmasysad;
+    s->blksize = sc->reset.blksize;
+    s->blkcnt = sc->reset.blkcnt;
+    s->prnsts = sc->reset.prnsts;
+    s->hostctl1 = sc->reset.hostctl1;
+    s->pwrcon = sc->reset.pwrcon;
+    s->blkgap = sc->reset.blkgap;
+    s->wakcon = sc->reset.wakcon;
+    s->clkcon = sc->reset.clkcon;
+    s->timeoutcon = sc->reset.timeoutcon;
+    s->norintstsen = sc->reset.norintstsen;
+    s->errintstsen = sc->reset.errintstsen;
+
     /* Reset other state based on current card insertion/readonly status */
     sdhci_set_inserted(dev, sdbus_get_inserted(&s->sdbus));
     sdhci_set_readonly(dev, sdbus_get_readonly(&s->sdbus));
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 11/12] hw/sd/sdhci: Implement Freescale eSDHC as TYPE_FSL_ESDHC
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
                   ` (9 preceding siblings ...)
  2025-03-08 19:02 ` [PATCH v3 10/12] hw/sd/sdhci: Allow SDHCI classes to have different register reset values Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  2025-03-08 19:02 ` [PATCH v3 12/12] hw/ppc/e500: Replace generic SDHCI by Freescale eSDHC Philippe Mathieu-Daudé
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

Per the MPC8569E reference manual, its SDHC I/O range is 4KiB
wide, mapped in big endian order, and it only accepts 32-bit
aligned access. Set the default register reset values.

Reported-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/hw/sd/sdhci.h |  2 ++
 hw/sd/sdhci.c         | 37 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index e24392eb10d..0e9d3b10d1b 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -161,6 +161,8 @@ DECLARE_INSTANCE_CHECKER(SDHCIState, SYSBUS_SDHCI,
 DECLARE_CLASS_CHECKERS(SDHCIClass, SYSBUS_SDHCI,
                        TYPE_SYSBUS_SDHCI)
 
+#define TYPE_FSL_ESDHC "fsl-esdhc"
+
 #define TYPE_IMX_USDHC "imx-usdhc"
 
 #define TYPE_S3C_SDHCI "s3c-sdhci"
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index cda608f8ec2..a78cff40fb1 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1644,7 +1644,37 @@ static void sdhci_bus_class_init(ObjectClass *klass, void *data)
     sbc->set_readonly = sdhci_set_readonly;
 }
 
-/* --- qdev i.MX eSDHC --- */
+/* --- Freescale eSDHC (MPC8569ERM Rev.2 from 06/2011) --- */
+
+static const MemoryRegionOps fsl_esdhc_mmio_ops = {
+    .read = sdhci_read,
+    .write = sdhci_write,
+    .valid = {
+        .min_access_size = 4,
+        .unaligned = false
+    },
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void fsl_esdhc_class_init(ObjectClass *oc, void *data)
+{
+    SDHCIClass *sc = SYSBUS_SDHCI_CLASS(oc);
+
+    sc->iomem_size = 0x1000;
+    sc->io_ops = &fsl_esdhc_mmio_ops;
+    sc->ro.capareg = 0x01e30000;
+    sc->reset.sdmasysad = 8;
+    sc->reset.blkcnt = 8;
+    sc->reset.prnsts = 0xff800000;
+    sc->reset.hostctl1 = 0x20; /* Endian mode (address-invariant) */
+    sc->reset.clkcon = 0x8000;
+    sc->reset.norintstsen = 0x013f;
+    sc->reset.errintstsen = 0x117f;
+
+    sdhci_common_class_init(oc, data);
+}
+
+/* --- qdev i.MX uSDHC --- */
 
 #define USDHC_MIX_CTRL                  0x48
 
@@ -1974,6 +2004,11 @@ static const TypeInfo sdhci_types[] = {
         .class_size = sizeof(SDHCIClass),
         .class_init = sdhci_sysbus_class_init,
     },
+    {
+        .name = TYPE_FSL_ESDHC,
+        .parent = TYPE_SYSBUS_SDHCI,
+        .class_init = fsl_esdhc_class_init,
+    },
     {
         .name = TYPE_IMX_USDHC,
         .parent = TYPE_SYSBUS_SDHCI,
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 12/12] hw/ppc/e500: Replace generic SDHCI by Freescale eSDHC
  2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
                   ` (10 preceding siblings ...)
  2025-03-08 19:02 ` [PATCH v3 11/12] hw/sd/sdhci: Implement Freescale eSDHC as TYPE_FSL_ESDHC Philippe Mathieu-Daudé
@ 2025-03-08 19:02 ` Philippe Mathieu-Daudé
  11 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-08 19:02 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Bernhard Beschow, Peter Maydell, qemu-ppc, Andrey Smirnov,
	Jean-Christophe Dubois, Bin Meng, qemu-arm, qemu-block,
	Guenter Roeck, Philippe Mathieu-Daudé

As Zoltan reported, some U-Boot versions seem to expect
correctly initialized registers before expecting interrupts.

Now than we have a proper Freescale eSDHC implementation,
use it.

Reported-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/ppc/e500.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index fe8b9f79621..e69551ccdb3 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -1027,20 +1027,12 @@ void ppce500_init(MachineState *machine)
 
     /* eSDHC */
     if (pmc->has_esdhc) {
-        dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE);
-        qdev_prop_set_string(dev, "name", "esdhc");
-        qdev_prop_set_uint64(dev, "size", MPC85XX_ESDHC_REGS_SIZE);
-        s = SYS_BUS_DEVICE(dev);
-        sysbus_realize_and_unref(s, &error_fatal);
-        memory_region_add_subregion(ccsr_addr_space, MPC85XX_ESDHC_REGS_OFFSET,
-                                    sysbus_mmio_get_region(s, 0));
-
         /*
          * Compatible with:
          * - SD Host Controller Specification Version 2.0 Part A2
          * (See MPC8569E Reference Manual)
          */
-        dev = qdev_new(TYPE_SYSBUS_SDHCI);
+        dev = qdev_new(TYPE_FSL_ESDHC);
         qdev_prop_set_uint8(dev, "sd-spec-version", 2);
         qdev_prop_set_uint8(dev, "endianness", DEVICE_BIG_ENDIAN);
         s = SYS_BUS_DEVICE(dev);
-- 
2.47.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2025-03-08 19:06 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-08 19:02 [PATCH v3 00/12] hw/sd/sdhci: Set reset value of interrupt registers Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 01/12] hw/sd/sdhci: Remove need for SDHCIState::vendor field Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 02/12] hw/sd/sdhci: Introduce SDHCIClass stub Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 03/12] hw/sd/sdhci: Make quirks a class property Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 04/12] hw/sd/sdhci: Make I/O region size " Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 05/12] hw/sd/sdhci: Enforce little endianness on PCI devices Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 06/12] hw/sd/sdhci: Allow SDHCI classes to register their own MemoryRegionOps Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 07/12] hw/sd/sdhci: Simplify MemoryRegionOps endianness check Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 08/12] hw/sd/sdhci: Unify default MemoryRegionOps Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 09/12] hw/sd/sdhci: Add SDHCIClass::ro::capareg field Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 10/12] hw/sd/sdhci: Allow SDHCI classes to have different register reset values Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 11/12] hw/sd/sdhci: Implement Freescale eSDHC as TYPE_FSL_ESDHC Philippe Mathieu-Daudé
2025-03-08 19:02 ` [PATCH v3 12/12] hw/ppc/e500: Replace generic SDHCI by Freescale eSDHC Philippe Mathieu-Daudé

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).