• Subject: [Qemu-devel] [PATCH v6 00/21] SDHCI: clean Specs v1/v2, implement Spec v3
  • Author: Philippe Mathieu-Daudé
  • Date: Jan. 11, 2018, 8:56 p.m.
  • Patches: 20 / 21
Changeset
hw/sd/sdhci-internal.h       |  74 ++++++++++--
include/hw/sd/sd.h           |  20 ++++
include/hw/sd/sdhci.h        |  21 +++-
hw/arm/bcm2835_peripherals.c |  33 ++++--
hw/arm/exynos4210.c          |  13 +-
hw/arm/fsl-imx6.c            |  13 ++
hw/arm/xilinx_zynq.c         |  64 ++++++----
hw/arm/xlnx-zynqmp.c         |  38 ++++--
hw/sd/core.c                 |  61 +++++++++-
hw/sd/sd.c                   |  29 +++++
hw/sd/sdhci.c                | 274 ++++++++++++++++++++++++++++---------------
hw/sd/trace-events           |   8 ++
12 files changed, 490 insertions(+), 158 deletions(-)
[Qemu-devel] [PATCH v6 00/21] SDHCI: clean Specs v1/v2, implement Spec v3
Posted by Philippe Mathieu-Daudé, 6 days ago
Since v5:
- addressed Alistair reviews
- dropped "abstract generic-sdhci"
- dropped Linux Device Tree names
- split qtests in another series
- change the bcm2835 minimum blocksize to 1KB (Andrew Baumann)
- added Alistair R-b
- based on Alistair work:
  - add SD tunning sequence via Host Control 2 to use UHS-I cards
  - add CMD/DAT[] fields in the Present State (used in next series
    to switch card voltage)

based on Alistair work:
- add SD tunning sequence via Host Control 2 to use UHS-I cards
- add CMD/DAT[] fields in the Present State (used in next series
  to switch card voltage)

Since v4 ("SDHCI: add qtests and fix few issues"):
- spec_version default to v2 (current behaviour)
- addressed Alistair review (no v1, tell user about valid version)

Since v3:
- no change, but split back in 2 series, 1st part is "SDHCI: housekeeping v5",
Based-on: 20180103180805.18140-18-f4bug@amsat.org

Since v2:
- more detailed 'capabilities', all boards converted to use these properties
- since all qtests pass, removed the previous 'capareg' property
- added Stefan/Alistair R-b
- corrected 'access' LED behavior (Alistair's review)
- more uses of the registerfields API
- remove some dead code
- cosmetix:
  - added more comments
  - renamed a pair of registers
  - reordered few struct members

Since v1:
- addressed Alistair Francis review comments, added some R-b
- only move register defines to "sd-internal.h"
- fixed deposit64() arguments
- dropped unuseful s->fifo_buffer = NULL
- use a qemu_irq for the LED, restrict the logging to ON/OFF
- fixed a trace format string error
- included Andrey Smirnov ACMD12ERRSTS write patch
- dropped few unuseful patches, and separate the Python polemical ones for later

From the "SDHCI housekeeping" series:
- 1: we restrict part of "sd/sd.h" into local "sd-internal.h",
- 2,3: we somehow beautiful the code, no logical changes,
- 4-7: we refactor the common sysbus/pci qdev code,
- 8-10: we add plenty of trace events which will result useful later,
- 11: we finally expose a "dma-memory" property.
From the "SDHCI: add a qtest and fix few issues" series:
- 12,13: fix registers
- 14,15: boards can specify which SDHCI Spec to use (v2 and v3 so far)
- 15-20: HCI qtest

Regards,

Phil.

$ git backport-diff # with v4
001/21:[0007] [FC] 'sdhci: add a 'spec_version property' (default to v2)'
002/21:[0005] [FC] 'sdhci: add basic Spec v1 capabilities'
003/21:[----] [-C] 'sdhci: add max-block-length capability (Spec v1)'
004/21:[0003] [FC] 'sdhci: add clock capabilities (Spec v1)'
005/21:[0004] [FC] 'sdhci: add DMA and 64-bit capabilities (Spec v2)'
006/21:[----] [--] 'sdhci: add BLOCK_SIZE_MASK for DMA'
007/21:[----] [--] 'sdhci: Fix 64-bit ADMA2'
008/21:[0008] [FC] 'sdhci: add v3 capabilities'
009/21:[0002] [FC] 'sdhci: rename the hostctl1 register'
010/21:[----] [--] 'hw/arm/exynos4210: implement SDHCI Spec v2'
011/21:[----] [--] 'hw/arm/xilinx_zynq: implement SDHCI Spec v2'
012/21:[0007] [FC] 'hw/arm/bcm2835_peripherals: implement SDHCI Spec v3'
013/21:[down] 'hw/arm/bcm2835_peripherals: change maximum block size to 1kB'
014/21:[0003] [FC] 'hw/arm/fsl-imx6: implement SDHCI Spec v3'
015/21:[----] [--] 'hw/arm/xilinx_zynqmp: implement SDHCI Spec v3'
016/21:[----] [-C] 'sdhci: remove the deprecated 'capareg' property'
017/21:[----] [--] 'sdhci: add Spec v4.2 register definitions'
018/21:[down] 'sdhci: implement the Host Control 2 register for the tunning sequence'
019/21:[down] 'sdbus: add trace events'
020/21:[down] 'sdhci: implement UHS-I voltage switch'
021/21:[down] 'sdhci: implement CMD/DAT[] fields in the Present State register'

Based-on: 20180111193021.17466-14-f4bug@amsat.org

Philippe Mathieu-Daudé (20):
  sdhci: sdhci: add a 'spec_version property' (default to v2)
  sdhci: add basic Spec v1 capabilities
  sdhci: add max-block-length capability (Spec v1)
  sdhci: add clock capabilities (Spec v1)
  sdhci: add DMA and 64-bit capabilities (Spec v2)
  sdhci: add BLOCK_SIZE_MASK for DMA
  sdhci: add v3 capabilities
  sdhci: rename the hostctl1 register
  hw/arm/exynos4210: implement SDHCI Spec v2
  hw/arm/xilinx_zynq: implement SDHCI Spec v2
  hw/arm/bcm2835_peripherals: implement SDHCI Spec v3
  hw/arm/bcm2835_peripherals: change maximum block size to 1kB
  hw/arm/fsl-imx6: implement SDHCI Spec v3
  hw/arm/xilinx_zynqmp: implement SDHCI Spec v3
  sdhci: remove the deprecated 'capareg' property
  sdhci: add Spec v4.2 register definitions
  sdhci: implement the Host Control 2 register for the tunning sequence
  sdbus: add trace events
  sdhci: implement UHS-I voltage switch
  sdhci: implement CMD/DAT[] fields in the Present State register

Sai Pavan Boddu (1):
  sdhci: Fix 64-bit ADMA2

 hw/sd/sdhci-internal.h       |  74 ++++++++++--
 include/hw/sd/sd.h           |  20 ++++
 include/hw/sd/sdhci.h        |  21 +++-
 hw/arm/bcm2835_peripherals.c |  33 ++++--
 hw/arm/exynos4210.c          |  13 +-
 hw/arm/fsl-imx6.c            |  13 ++
 hw/arm/xilinx_zynq.c         |  64 ++++++----
 hw/arm/xlnx-zynqmp.c         |  38 ++++--
 hw/sd/core.c                 |  61 +++++++++-
 hw/sd/sd.c                   |  29 +++++
 hw/sd/sdhci.c                | 274 ++++++++++++++++++++++++++++---------------
 hw/sd/trace-events           |   8 ++
 12 files changed, 490 insertions(+), 158 deletions(-)

-- 
2.15.1


[Qemu-devel] [PATCH v6 01/21] sdhci: add a 'spec_version property' (default to v2)
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
---
 hw/sd/sdhci-internal.h |  4 ++--
 include/hw/sd/sdhci.h  |  2 ++
 hw/sd/sdhci.c          | 19 +++++++++++++++++--
 3 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index fc807f08f3..b7751c815f 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -210,9 +210,9 @@
 /* Slot interrupt status */
 #define SDHC_SLOT_INT_STATUS            0xFC
 
-/* HWInit Host Controller Version Register 0x0401 */
+/* HWInit Host Controller Version Register */
 #define SDHC_HCVER                      0xFE
-#define SD_HOST_SPECv2_VERS             0x2401
+#define SDHC_HCVER_VENDOR               0x24
 
 #define SDHC_REGISTERS_MAP_SIZE         0x100
 #define SDHC_INSERTION_DELAY            (NANOSECONDS_PER_SECOND)
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 6117004949..8786676ac8 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -76,6 +76,7 @@ typedef struct SDHCIState {
     /* Read-only registers */
     uint64_t capareg;      /* Capabilities Register */
     uint64_t maxcurr;      /* Maximum Current Capabilities Register */
+    uint16_t version;      /* Host Controller Version Register */
 
     uint8_t  *fifo_buffer; /* SD host i/o FIFO buffer */
     uint32_t buf_maxsz;
@@ -90,6 +91,7 @@ typedef struct SDHCIState {
 
     /* Configurable properties */
     bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
+    uint8_t spec_version;
 } SDHCIState;
 
 #define TYPE_PCI_SDHCI "sdhci-pci"
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 7a2901ae4a..c8f750451e 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -173,7 +173,8 @@ static void sdhci_reset(SDHCIState *s)
 
     timer_del(s->insert_timer);
     timer_del(s->transfer_timer);
-    /* Set all registers to 0. Capabilities registers are not cleared
+
+    /* Set all registers to 0. Capabilities/Version registers are not cleared
      * and assumed to always preserve their value, given to them during
      * initialization */
     memset(&s->sdmasysad, 0, (uintptr_t)&s->capareg - (uintptr_t)&s->sdmasysad);
@@ -917,7 +918,7 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, unsigned size)
         ret = (uint32_t)(s->admasysaddr >> 32);
         break;
     case SDHC_SLOT_INT_STATUS:
-        ret = (SD_HOST_SPECv2_VERS << 16) | sdhci_slotint(s);
+        ret = (s->version << 16) | sdhci_slotint(s);
         break;
     default:
         qemu_log_mask(LOG_UNIMP, "SDHC rd_%ub @0x%02" HWADDR_PRIx " "
@@ -1173,6 +1174,15 @@ static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
     }
 }
 
+static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
+{
+    if (s->spec_version != 2) {
+        error_setg(errp, "Only Spec v2 is supported");
+        return;
+    }
+    s->version = (SDHC_HCVER_VENDOR << 8) | (s->spec_version - 1);
+}
+
 static void sdhci_initfn(SDHCIState *s)
 {
     qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
@@ -1184,6 +1194,10 @@ static void sdhci_initfn(SDHCIState *s)
 
 static void sdhci_common_realize(SDHCIState *s, Error **errp)
 {
+    sdhci_init_readonly_registers(s, errp);
+    if (errp && *errp) {
+        return;
+    }
     s->buf_maxsz = sdhci_get_fifolen(s);
     s->fifo_buffer = g_malloc0(s->buf_maxsz);
 
@@ -1282,6 +1296,7 @@ const VMStateDescription sdhci_vmstate = {
 /* Capabilities registers provide information on supported features of this
  * specific host controller implementation */
 static Property sdhci_properties[] = {
+    DEFINE_PROP_UINT8("sd-spec-version", SDHCIState, spec_version, 2),
     DEFINE_PROP_UINT64("capareg", SDHCIState, capareg,
             SDHC_CAPAB_REG_DEFAULT),
     DEFINE_PROP_UINT64("maxcurr", SDHCIState, maxcurr, 0),
-- 
2.15.1


[Qemu-devel] [PATCH v6 02/21] sdhci: add basic Spec v1 capabilities
Posted by Philippe Mathieu-Daudé, 6 days ago
(Note than Spec v2 is supported by default)

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sdhci-internal.h | 24 +++++++++++++++++++-
 include/hw/sd/sdhci.h  |  6 +++++
 hw/sd/sdhci.c          | 61 +++++++++++++++++++++++++++++++++++++-------------
 3 files changed, 74 insertions(+), 17 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index b7751c815f..9acafe7b01 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -24,6 +24,8 @@
 #ifndef SDHCI_INTERNAL_H
 #define SDHCI_INTERNAL_H
 
+#include "hw/registerfields.h"
+
 /* R/W SDMA System Address register 0x0 */
 #define SDHC_SYSAD                     0x00
 
@@ -84,6 +86,9 @@
 
 /* R/W Host control Register 0x0 */
 #define SDHC_HOSTCTL                   0x28
+FIELD(SDHC_HOSTCTL, LED_CTRL,          0, 1);
+FIELD(SDHC_HOSTCTL, DATATRANSFERWIDTH, 1, 1); /* SD mode only */
+FIELD(SDHC_HOSTCTL, HIGH_SPEED,        2, 1);
 #define SDHC_CTRL_DMA_CHECK_MASK       0x18
 #define SDHC_CTRL_SDMA                 0x00
 #define SDHC_CTRL_ADMA1_32             0x08
@@ -94,6 +99,7 @@
 /* R/W Power Control Register 0x0 */
 #define SDHC_PWRCON                    0x29
 #define SDHC_POWER_ON                  (1 << 0)
+FIELD(SDHC_PWRCON, BUS_VOLTAGE,        1, 3);
 
 /* R/W Block Gap Control Register 0x0 */
 #define SDHC_BLKGAP                    0x2A
@@ -116,6 +122,7 @@
 
 /* R/W Timeout Control Register 0x0 */
 #define SDHC_TIMEOUTCON                0x2E
+FIELD(SDHC_TIMEOUTCON, COUNTER,        0, 4);
 
 /* R/W Software Reset Register 0x0 */
 #define SDHC_SWRST                     0x2F
@@ -172,17 +179,32 @@
 
 /* ROC Auto CMD12 error status register 0x0 */
 #define SDHC_ACMD12ERRSTS              0x3C
+FIELD(SDHC_ACMD12ERRSTS, TIMEOUT_ERR,  1, 1);
+FIELD(SDHC_ACMD12ERRSTS, CRC_ERR,      2, 1);
+FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,    4, 1);
 
 /* HWInit Capabilities Register 0x05E80080 */
 #define SDHC_CAPAB                     0x40
-#define SDHC_CAN_DO_DMA                0x00400000
 #define SDHC_CAN_DO_ADMA2              0x00080000
 #define SDHC_CAN_DO_ADMA1              0x00100000
 #define SDHC_64_BIT_BUS_SUPPORT        (1 << 28)
 #define SDHC_CAPAB_BLOCKSIZE(x)        (((x) >> 16) & 0x3)
+FIELD(SDHC_CAPAB, TOCLKFREQ,           0, 6);
+FIELD(SDHC_CAPAB, TOUNIT,              7, 1);
+FIELD(SDHC_CAPAB, BASECLKFREQ,         8, 8);
+FIELD(SDHC_CAPAB, MAXBLOCKLENGTH,     16, 2);
+FIELD(SDHC_CAPAB, HIGHSPEED,          21, 1);
+FIELD(SDHC_CAPAB, SDMA,               22, 1);
+FIELD(SDHC_CAPAB, SUSPRESUME,         23, 1);
+FIELD(SDHC_CAPAB, V33,                24, 1);
+FIELD(SDHC_CAPAB, V30,                25, 1);
+FIELD(SDHC_CAPAB, V18,                26, 1);
 
 /* HWInit Maximum Current Capabilities Register 0x0 */
 #define SDHC_MAXCURR                   0x48
+FIELD(SDHC_MAXCURR, V33_VDD1,          0, 8);
+FIELD(SDHC_MAXCURR, V30_VDD1,          8, 8);
+FIELD(SDHC_MAXCURR, V18_VDD1,         16, 8);
 
 /* W Force Event Auto CMD12 Error Interrupt Register 0x0000 */
 #define SDHC_FEAER                     0x50
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 8786676ac8..09b756eb7a 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -92,6 +92,12 @@ typedef struct SDHCIState {
     /* Configurable properties */
     bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
     uint8_t spec_version;
+    struct {
+        bool suspend;
+        bool high_speed;
+        bool sdma;
+        bool v33, v30, v18;
+    } cap;
 } SDHCIState;
 
 #define TYPE_PCI_SDHCI "sdhci-pci"
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index c8f750451e..d26ea821d0 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -44,12 +44,6 @@
  * 0 - not supported, 1 - supported, other - prohibited.
  */
 #define SDHC_CAPAB_64BITBUS       0ul        /* 64-bit System Bus Support */
-#define SDHC_CAPAB_18V            1ul        /* Voltage support 1.8v */
-#define SDHC_CAPAB_30V            0ul        /* Voltage support 3.0v */
-#define SDHC_CAPAB_33V            1ul        /* Voltage support 3.3v */
-#define SDHC_CAPAB_SUSPRESUME     0ul        /* Suspend/resume support */
-#define SDHC_CAPAB_SDMA           1ul        /* SDMA support */
-#define SDHC_CAPAB_HIGHSPEED      1ul        /* High speed support */
 #define SDHC_CAPAB_ADMA1          1ul        /* ADMA1 support */
 #define SDHC_CAPAB_ADMA2          1ul        /* ADMA2 support */
 /* Maximum host controller R/W buffers size
@@ -63,9 +57,7 @@
 #define SDHC_CAPAB_TOCLKFREQ      52ul
 
 /* Now check all parameters and calculate CAPABILITIES REGISTER value */
-#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_18V > 1 || SDHC_CAPAB_30V > 1 ||     \
-    SDHC_CAPAB_33V > 1 || SDHC_CAPAB_SUSPRESUME > 1 || SDHC_CAPAB_SDMA > 1 ||  \
-    SDHC_CAPAB_HIGHSPEED > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 ||\
+#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 || \
     SDHC_CAPAB_TOUNIT > 1
 #error Capabilities features can have value 0 or 1 only!
 #endif
@@ -90,16 +82,36 @@
 #endif
 
 #define SDHC_CAPAB_REG_DEFAULT                                 \
-   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_18V << 26) |     \
-    (SDHC_CAPAB_30V << 25) | (SDHC_CAPAB_33V << 24) |          \
-    (SDHC_CAPAB_SUSPRESUME << 23) | (SDHC_CAPAB_SDMA << 22) |  \
-    (SDHC_CAPAB_HIGHSPEED << 21) | (SDHC_CAPAB_ADMA1 << 20) |  \
+   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_ADMA1 << 20) |   \
     (SDHC_CAPAB_ADMA2 << 19) | (MAX_BLOCK_LENGTH << 16) |      \
     (SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
     (SDHC_CAPAB_TOCLKFREQ))
 
 #define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
 
+static void sdhci_init_capareg(SDHCIState *s, Error **errp)
+{
+    uint64_t capareg = 0;
+
+    switch (s->spec_version) {
+    case 2: /* default version */
+
+    /* fallback */
+    case 1:
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, HIGHSPEED, s->cap.high_speed);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, SDMA, s->cap.sdma);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, SUSPRESUME, s->cap.suspend);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V33, s->cap.v33);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V30, s->cap.v30);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V18, s->cap.v18);
+        break;
+
+    default:
+        error_setg(errp, "Unsupported spec version: %u", s->spec_version);
+    }
+    s->capareg = capareg;
+}
+
 static uint8_t sdhci_slotint(SDHCIState *s)
 {
     return (s->norintsts & s->norintsigen) || (s->errintsts & s->errintsigen) ||
@@ -1026,7 +1038,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
     case SDHC_TRNMOD:
         /* DMA can be enabled only if it is supported as indicated by
          * capabilities register */
-        if (!(s->capareg & SDHC_CAN_DO_DMA)) {
+        if (!(s->capareg & R_SDHC_CAPAB_SDMA_MASK)) {
             value &= ~SDHC_TRNS_DMA;
         }
         MASKED_WRITE(s->trnmod, mask, value & SDHC_TRNMOD_MASK);
@@ -1181,6 +1193,10 @@ static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
         return;
     }
     s->version = (SDHC_HCVER_VENDOR << 8) | (s->spec_version - 1);
+
+    if (s->capareg == UINT64_MAX) {
+        sdhci_init_capareg(s, errp);
+    }
 }
 
 static void sdhci_initfn(SDHCIState *s)
@@ -1297,8 +1313,21 @@ const VMStateDescription sdhci_vmstate = {
  * specific host controller implementation */
 static Property sdhci_properties[] = {
     DEFINE_PROP_UINT8("sd-spec-version", SDHCIState, spec_version, 2),
-    DEFINE_PROP_UINT64("capareg", SDHCIState, capareg,
-            SDHC_CAPAB_REG_DEFAULT),
+
+    /* DMA */
+    DEFINE_PROP_BOOL("sdma", SDHCIState, cap.sdma, true),
+    /* Suspend/resume support */
+    DEFINE_PROP_BOOL("suspend", SDHCIState, cap.suspend, false),
+    /* High speed support */
+    DEFINE_PROP_BOOL("high-speed", SDHCIState, cap.high_speed, true),
+    /* Voltage support 3.3/3.0/1.8V */
+    DEFINE_PROP_BOOL("3v3", SDHCIState, cap.v33, true),
+    DEFINE_PROP_BOOL("3v0", SDHCIState, cap.v30, false),
+    DEFINE_PROP_BOOL("1v8", SDHCIState, cap.v18, false),
+
+    /* capareg: deprecated */
+    DEFINE_PROP_UINT64("capareg", SDHCIState, capareg, UINT64_MAX),
+
     DEFINE_PROP_UINT64("maxcurr", SDHCIState, maxcurr, 0),
     DEFINE_PROP_BOOL("pending-insert-quirk", SDHCIState, pending_insert_quirk,
                      false),
-- 
2.15.1


Re: [Qemu-devel] [PATCH v6 02/21] sdhci: add basic Spec v1 capabilities
Posted by Alistair Francis, 5 days ago
On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
<f4bug@amsat.org> wrote:
> (Note than Spec v2 is supported by default)
>
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> ---
>  hw/sd/sdhci-internal.h | 24 +++++++++++++++++++-
>  include/hw/sd/sdhci.h  |  6 +++++
>  hw/sd/sdhci.c          | 61 +++++++++++++++++++++++++++++++++++++-------------
>  3 files changed, 74 insertions(+), 17 deletions(-)
>
> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
> index b7751c815f..9acafe7b01 100644
> --- a/hw/sd/sdhci-internal.h
> +++ b/hw/sd/sdhci-internal.h
> @@ -24,6 +24,8 @@
>  #ifndef SDHCI_INTERNAL_H
>  #define SDHCI_INTERNAL_H
>
> +#include "hw/registerfields.h"
> +
>  /* R/W SDMA System Address register 0x0 */
>  #define SDHC_SYSAD                     0x00
>
> @@ -84,6 +86,9 @@
>
>  /* R/W Host control Register 0x0 */
>  #define SDHC_HOSTCTL                   0x28
> +FIELD(SDHC_HOSTCTL, LED_CTRL,          0, 1);
> +FIELD(SDHC_HOSTCTL, DATATRANSFERWIDTH, 1, 1); /* SD mode only */
> +FIELD(SDHC_HOSTCTL, HIGH_SPEED,        2, 1);
>  #define SDHC_CTRL_DMA_CHECK_MASK       0x18
>  #define SDHC_CTRL_SDMA                 0x00
>  #define SDHC_CTRL_ADMA1_32             0x08
> @@ -94,6 +99,7 @@
>  /* R/W Power Control Register 0x0 */
>  #define SDHC_PWRCON                    0x29
>  #define SDHC_POWER_ON                  (1 << 0)
> +FIELD(SDHC_PWRCON, BUS_VOLTAGE,        1, 3);
>
>  /* R/W Block Gap Control Register 0x0 */
>  #define SDHC_BLKGAP                    0x2A
> @@ -116,6 +122,7 @@
>
>  /* R/W Timeout Control Register 0x0 */
>  #define SDHC_TIMEOUTCON                0x2E
> +FIELD(SDHC_TIMEOUTCON, COUNTER,        0, 4);
>
>  /* R/W Software Reset Register 0x0 */
>  #define SDHC_SWRST                     0x2F
> @@ -172,17 +179,32 @@
>
>  /* ROC Auto CMD12 error status register 0x0 */
>  #define SDHC_ACMD12ERRSTS              0x3C
> +FIELD(SDHC_ACMD12ERRSTS, TIMEOUT_ERR,  1, 1);
> +FIELD(SDHC_ACMD12ERRSTS, CRC_ERR,      2, 1);
> +FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,    4, 1);
>
>  /* HWInit Capabilities Register 0x05E80080 */
>  #define SDHC_CAPAB                     0x40
> -#define SDHC_CAN_DO_DMA                0x00400000
>  #define SDHC_CAN_DO_ADMA2              0x00080000
>  #define SDHC_CAN_DO_ADMA1              0x00100000
>  #define SDHC_64_BIT_BUS_SUPPORT        (1 << 28)
>  #define SDHC_CAPAB_BLOCKSIZE(x)        (((x) >> 16) & 0x3)
> +FIELD(SDHC_CAPAB, TOCLKFREQ,           0, 6);
> +FIELD(SDHC_CAPAB, TOUNIT,              7, 1);
> +FIELD(SDHC_CAPAB, BASECLKFREQ,         8, 8);
> +FIELD(SDHC_CAPAB, MAXBLOCKLENGTH,     16, 2);
> +FIELD(SDHC_CAPAB, HIGHSPEED,          21, 1);
> +FIELD(SDHC_CAPAB, SDMA,               22, 1);
> +FIELD(SDHC_CAPAB, SUSPRESUME,         23, 1);
> +FIELD(SDHC_CAPAB, V33,                24, 1);
> +FIELD(SDHC_CAPAB, V30,                25, 1);
> +FIELD(SDHC_CAPAB, V18,                26, 1);
>
>  /* HWInit Maximum Current Capabilities Register 0x0 */
>  #define SDHC_MAXCURR                   0x48
> +FIELD(SDHC_MAXCURR, V33_VDD1,          0, 8);
> +FIELD(SDHC_MAXCURR, V30_VDD1,          8, 8);
> +FIELD(SDHC_MAXCURR, V18_VDD1,         16, 8);
>
>  /* W Force Event Auto CMD12 Error Interrupt Register 0x0000 */
>  #define SDHC_FEAER                     0x50
> diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
> index 8786676ac8..09b756eb7a 100644
> --- a/include/hw/sd/sdhci.h
> +++ b/include/hw/sd/sdhci.h
> @@ -92,6 +92,12 @@ typedef struct SDHCIState {
>      /* Configurable properties */
>      bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
>      uint8_t spec_version;
> +    struct {
> +        bool suspend;
> +        bool high_speed;
> +        bool sdma;
> +        bool v33, v30, v18;
> +    } cap;
>  } SDHCIState;
>
>  #define TYPE_PCI_SDHCI "sdhci-pci"
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index c8f750451e..d26ea821d0 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -44,12 +44,6 @@
>   * 0 - not supported, 1 - supported, other - prohibited.
>   */
>  #define SDHC_CAPAB_64BITBUS       0ul        /* 64-bit System Bus Support */
> -#define SDHC_CAPAB_18V            1ul        /* Voltage support 1.8v */
> -#define SDHC_CAPAB_30V            0ul        /* Voltage support 3.0v */
> -#define SDHC_CAPAB_33V            1ul        /* Voltage support 3.3v */
> -#define SDHC_CAPAB_SUSPRESUME     0ul        /* Suspend/resume support */
> -#define SDHC_CAPAB_SDMA           1ul        /* SDMA support */
> -#define SDHC_CAPAB_HIGHSPEED      1ul        /* High speed support */
>  #define SDHC_CAPAB_ADMA1          1ul        /* ADMA1 support */
>  #define SDHC_CAPAB_ADMA2          1ul        /* ADMA2 support */
>  /* Maximum host controller R/W buffers size
> @@ -63,9 +57,7 @@
>  #define SDHC_CAPAB_TOCLKFREQ      52ul
>
>  /* Now check all parameters and calculate CAPABILITIES REGISTER value */
> -#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_18V > 1 || SDHC_CAPAB_30V > 1 ||     \
> -    SDHC_CAPAB_33V > 1 || SDHC_CAPAB_SUSPRESUME > 1 || SDHC_CAPAB_SDMA > 1 ||  \
> -    SDHC_CAPAB_HIGHSPEED > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 ||\
> +#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 || \
>      SDHC_CAPAB_TOUNIT > 1
>  #error Capabilities features can have value 0 or 1 only!
>  #endif
> @@ -90,16 +82,36 @@
>  #endif
>
>  #define SDHC_CAPAB_REG_DEFAULT                                 \
> -   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_18V << 26) |     \
> -    (SDHC_CAPAB_30V << 25) | (SDHC_CAPAB_33V << 24) |          \
> -    (SDHC_CAPAB_SUSPRESUME << 23) | (SDHC_CAPAB_SDMA << 22) |  \
> -    (SDHC_CAPAB_HIGHSPEED << 21) | (SDHC_CAPAB_ADMA1 << 20) |  \
> +   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_ADMA1 << 20) |   \
>      (SDHC_CAPAB_ADMA2 << 19) | (MAX_BLOCK_LENGTH << 16) |      \
>      (SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
>      (SDHC_CAPAB_TOCLKFREQ))
>
>  #define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
>
> +static void sdhci_init_capareg(SDHCIState *s, Error **errp)
> +{
> +    uint64_t capareg = 0;
> +
> +    switch (s->spec_version) {
> +    case 2: /* default version */
> +
> +    /* fallback */
> +    case 1:
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, HIGHSPEED, s->cap.high_speed);
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, SDMA, s->cap.sdma);
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, SUSPRESUME, s->cap.suspend);
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V33, s->cap.v33);
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V30, s->cap.v30);
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V18, s->cap.v18);
> +        break;
> +
> +    default:
> +        error_setg(errp, "Unsupported spec version: %u", s->spec_version);

Probably best to have a return here, encase some logic added below
later relies on this being successful.


> +    }
> +    s->capareg = capareg;
> +}
> +
>  static uint8_t sdhci_slotint(SDHCIState *s)
>  {
>      return (s->norintsts & s->norintsigen) || (s->errintsts & s->errintsigen) ||
> @@ -1026,7 +1038,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
>      case SDHC_TRNMOD:
>          /* DMA can be enabled only if it is supported as indicated by
>           * capabilities register */
> -        if (!(s->capareg & SDHC_CAN_DO_DMA)) {
> +        if (!(s->capareg & R_SDHC_CAPAB_SDMA_MASK)) {
>              value &= ~SDHC_TRNS_DMA;
>          }
>          MASKED_WRITE(s->trnmod, mask, value & SDHC_TRNMOD_MASK);
> @@ -1181,6 +1193,10 @@ static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
>          return;
>      }
>      s->version = (SDHC_HCVER_VENDOR << 8) | (s->spec_version - 1);
> +
> +    if (s->capareg == UINT64_MAX) {
> +        sdhci_init_capareg(s, errp);
> +    }
>  }
>
>  static void sdhci_initfn(SDHCIState *s)
> @@ -1297,8 +1313,21 @@ const VMStateDescription sdhci_vmstate = {
>   * specific host controller implementation */
>  static Property sdhci_properties[] = {
>      DEFINE_PROP_UINT8("sd-spec-version", SDHCIState, spec_version, 2),
> -    DEFINE_PROP_UINT64("capareg", SDHCIState, capareg,
> -            SDHC_CAPAB_REG_DEFAULT),
> +
> +    /* DMA */
> +    DEFINE_PROP_BOOL("sdma", SDHCIState, cap.sdma, true),
> +    /* Suspend/resume support */
> +    DEFINE_PROP_BOOL("suspend", SDHCIState, cap.suspend, false),
> +    /* High speed support */
> +    DEFINE_PROP_BOOL("high-speed", SDHCIState, cap.high_speed, true),
> +    /* Voltage support 3.3/3.0/1.8V */
> +    DEFINE_PROP_BOOL("3v3", SDHCIState, cap.v33, true),
> +    DEFINE_PROP_BOOL("3v0", SDHCIState, cap.v30, false),
> +    DEFINE_PROP_BOOL("1v8", SDHCIState, cap.v18, false),

This is a change of the default value.

I think you really need to specify specific changes in the commit
message. That way is the defaults cause breakages we will be able to
bisect it in the future.

Alistair

> +
> +    /* capareg: deprecated */
> +    DEFINE_PROP_UINT64("capareg", SDHCIState, capareg, UINT64_MAX),
> +
>      DEFINE_PROP_UINT64("maxcurr", SDHCIState, maxcurr, 0),
>      DEFINE_PROP_BOOL("pending-insert-quirk", SDHCIState, pending_insert_quirk,
>                       false),
> --
> 2.15.1
>
>

Re: [Qemu-devel] [PATCH v6 02/21] sdhci: add basic Spec v1 capabilities
Posted by Philippe Mathieu-Daudé, 5 days ago
Hi Alistair,

On 01/12/2018 09:00 PM, Alistair Francis wrote:
> On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
> <f4bug@amsat.org> wrote:
>> (Note than Spec v2 is supported by default)
>>
>> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>> ---
>>  hw/sd/sdhci-internal.h | 24 +++++++++++++++++++-
>>  include/hw/sd/sdhci.h  |  6 +++++
>>  hw/sd/sdhci.c          | 61 +++++++++++++++++++++++++++++++++++++-------------
>>  3 files changed, 74 insertions(+), 17 deletions(-)
>>
>> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
>> index b7751c815f..9acafe7b01 100644
>> --- a/hw/sd/sdhci-internal.h
>> +++ b/hw/sd/sdhci-internal.h
>> @@ -24,6 +24,8 @@
>>  #ifndef SDHCI_INTERNAL_H
>>  #define SDHCI_INTERNAL_H
>>
>> +#include "hw/registerfields.h"
>> +
>>  /* R/W SDMA System Address register 0x0 */
>>  #define SDHC_SYSAD                     0x00
>>
>> @@ -84,6 +86,9 @@
>>
>>  /* R/W Host control Register 0x0 */
>>  #define SDHC_HOSTCTL                   0x28
>> +FIELD(SDHC_HOSTCTL, LED_CTRL,          0, 1);
>> +FIELD(SDHC_HOSTCTL, DATATRANSFERWIDTH, 1, 1); /* SD mode only */
>> +FIELD(SDHC_HOSTCTL, HIGH_SPEED,        2, 1);
>>  #define SDHC_CTRL_DMA_CHECK_MASK       0x18
>>  #define SDHC_CTRL_SDMA                 0x00
>>  #define SDHC_CTRL_ADMA1_32             0x08
>> @@ -94,6 +99,7 @@
>>  /* R/W Power Control Register 0x0 */
>>  #define SDHC_PWRCON                    0x29
>>  #define SDHC_POWER_ON                  (1 << 0)
>> +FIELD(SDHC_PWRCON, BUS_VOLTAGE,        1, 3);
>>
>>  /* R/W Block Gap Control Register 0x0 */
>>  #define SDHC_BLKGAP                    0x2A
>> @@ -116,6 +122,7 @@
>>
>>  /* R/W Timeout Control Register 0x0 */
>>  #define SDHC_TIMEOUTCON                0x2E
>> +FIELD(SDHC_TIMEOUTCON, COUNTER,        0, 4);
>>
>>  /* R/W Software Reset Register 0x0 */
>>  #define SDHC_SWRST                     0x2F
>> @@ -172,17 +179,32 @@
>>
>>  /* ROC Auto CMD12 error status register 0x0 */
>>  #define SDHC_ACMD12ERRSTS              0x3C
>> +FIELD(SDHC_ACMD12ERRSTS, TIMEOUT_ERR,  1, 1);
>> +FIELD(SDHC_ACMD12ERRSTS, CRC_ERR,      2, 1);
>> +FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,    4, 1);
>>
>>  /* HWInit Capabilities Register 0x05E80080 */
>>  #define SDHC_CAPAB                     0x40
>> -#define SDHC_CAN_DO_DMA                0x00400000
>>  #define SDHC_CAN_DO_ADMA2              0x00080000
>>  #define SDHC_CAN_DO_ADMA1              0x00100000
>>  #define SDHC_64_BIT_BUS_SUPPORT        (1 << 28)
>>  #define SDHC_CAPAB_BLOCKSIZE(x)        (((x) >> 16) & 0x3)
>> +FIELD(SDHC_CAPAB, TOCLKFREQ,           0, 6);
>> +FIELD(SDHC_CAPAB, TOUNIT,              7, 1);
>> +FIELD(SDHC_CAPAB, BASECLKFREQ,         8, 8);
>> +FIELD(SDHC_CAPAB, MAXBLOCKLENGTH,     16, 2);
>> +FIELD(SDHC_CAPAB, HIGHSPEED,          21, 1);
>> +FIELD(SDHC_CAPAB, SDMA,               22, 1);
>> +FIELD(SDHC_CAPAB, SUSPRESUME,         23, 1);
>> +FIELD(SDHC_CAPAB, V33,                24, 1);
>> +FIELD(SDHC_CAPAB, V30,                25, 1);
>> +FIELD(SDHC_CAPAB, V18,                26, 1);
>>
>>  /* HWInit Maximum Current Capabilities Register 0x0 */
>>  #define SDHC_MAXCURR                   0x48
>> +FIELD(SDHC_MAXCURR, V33_VDD1,          0, 8);
>> +FIELD(SDHC_MAXCURR, V30_VDD1,          8, 8);
>> +FIELD(SDHC_MAXCURR, V18_VDD1,         16, 8);
>>
>>  /* W Force Event Auto CMD12 Error Interrupt Register 0x0000 */
>>  #define SDHC_FEAER                     0x50
>> diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
>> index 8786676ac8..09b756eb7a 100644
>> --- a/include/hw/sd/sdhci.h
>> +++ b/include/hw/sd/sdhci.h
>> @@ -92,6 +92,12 @@ typedef struct SDHCIState {
>>      /* Configurable properties */
>>      bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
>>      uint8_t spec_version;
>> +    struct {
>> +        bool suspend;
>> +        bool high_speed;
>> +        bool sdma;
>> +        bool v33, v30, v18;
>> +    } cap;
>>  } SDHCIState;
>>
>>  #define TYPE_PCI_SDHCI "sdhci-pci"
>> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
>> index c8f750451e..d26ea821d0 100644
>> --- a/hw/sd/sdhci.c
>> +++ b/hw/sd/sdhci.c
>> @@ -44,12 +44,6 @@
>>   * 0 - not supported, 1 - supported, other - prohibited.
>>   */
>>  #define SDHC_CAPAB_64BITBUS       0ul        /* 64-bit System Bus Support */
>> -#define SDHC_CAPAB_18V            1ul        /* Voltage support 1.8v */
>> -#define SDHC_CAPAB_30V            0ul        /* Voltage support 3.0v */
>> -#define SDHC_CAPAB_33V            1ul        /* Voltage support 3.3v */
>> -#define SDHC_CAPAB_SUSPRESUME     0ul        /* Suspend/resume support */
>> -#define SDHC_CAPAB_SDMA           1ul        /* SDMA support */
>> -#define SDHC_CAPAB_HIGHSPEED      1ul        /* High speed support */
>>  #define SDHC_CAPAB_ADMA1          1ul        /* ADMA1 support */
>>  #define SDHC_CAPAB_ADMA2          1ul        /* ADMA2 support */
>>  /* Maximum host controller R/W buffers size
>> @@ -63,9 +57,7 @@
>>  #define SDHC_CAPAB_TOCLKFREQ      52ul
>>
>>  /* Now check all parameters and calculate CAPABILITIES REGISTER value */
>> -#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_18V > 1 || SDHC_CAPAB_30V > 1 ||     \
>> -    SDHC_CAPAB_33V > 1 || SDHC_CAPAB_SUSPRESUME > 1 || SDHC_CAPAB_SDMA > 1 ||  \
>> -    SDHC_CAPAB_HIGHSPEED > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 ||\
>> +#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 || \
>>      SDHC_CAPAB_TOUNIT > 1
>>  #error Capabilities features can have value 0 or 1 only!
>>  #endif
>> @@ -90,16 +82,36 @@
>>  #endif
>>
>>  #define SDHC_CAPAB_REG_DEFAULT                                 \
>> -   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_18V << 26) |     \
>> -    (SDHC_CAPAB_30V << 25) | (SDHC_CAPAB_33V << 24) |          \
>> -    (SDHC_CAPAB_SUSPRESUME << 23) | (SDHC_CAPAB_SDMA << 22) |  \
>> -    (SDHC_CAPAB_HIGHSPEED << 21) | (SDHC_CAPAB_ADMA1 << 20) |  \
>> +   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_ADMA1 << 20) |   \
>>      (SDHC_CAPAB_ADMA2 << 19) | (MAX_BLOCK_LENGTH << 16) |      \
>>      (SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
>>      (SDHC_CAPAB_TOCLKFREQ))
>>
>>  #define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
>>
>> +static void sdhci_init_capareg(SDHCIState *s, Error **errp)
>> +{
>> +    uint64_t capareg = 0;
>> +
>> +    switch (s->spec_version) {
>> +    case 2: /* default version */
>> +
>> +    /* fallback */
>> +    case 1:
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, HIGHSPEED, s->cap.high_speed);
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, SDMA, s->cap.sdma);
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, SUSPRESUME, s->cap.suspend);
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V33, s->cap.v33);
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V30, s->cap.v30);
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V18, s->cap.v18);
>> +        break;
>> +
>> +    default:
>> +        error_setg(errp, "Unsupported spec version: %u", s->spec_version);
> 
> Probably best to have a return here, encase some logic added below
> later relies on this being successful.

Indeed, better safe than sorry.
>> +    }
>> +    s->capareg = capareg;
>> +}
>> +
>>  static uint8_t sdhci_slotint(SDHCIState *s)
>>  {
>>      return (s->norintsts & s->norintsigen) || (s->errintsts & s->errintsigen) ||
>> @@ -1026,7 +1038,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
>>      case SDHC_TRNMOD:
>>          /* DMA can be enabled only if it is supported as indicated by
>>           * capabilities register */
>> -        if (!(s->capareg & SDHC_CAN_DO_DMA)) {
>> +        if (!(s->capareg & R_SDHC_CAPAB_SDMA_MASK)) {
>>              value &= ~SDHC_TRNS_DMA;
>>          }
>>          MASKED_WRITE(s->trnmod, mask, value & SDHC_TRNMOD_MASK);
>> @@ -1181,6 +1193,10 @@ static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
>>          return;
>>      }
>>      s->version = (SDHC_HCVER_VENDOR << 8) | (s->spec_version - 1);
>> +
>> +    if (s->capareg == UINT64_MAX) {
>> +        sdhci_init_capareg(s, errp);
>> +    }
>>  }
>>
>>  static void sdhci_initfn(SDHCIState *s)
>> @@ -1297,8 +1313,21 @@ const VMStateDescription sdhci_vmstate = {
>>   * specific host controller implementation */
>>  static Property sdhci_properties[] = {
>>      DEFINE_PROP_UINT8("sd-spec-version", SDHCIState, spec_version, 2),
>> -    DEFINE_PROP_UINT64("capareg", SDHCIState, capareg,
>> -            SDHC_CAPAB_REG_DEFAULT),
>> +
>> +    /* DMA */
>> +    DEFINE_PROP_BOOL("sdma", SDHCIState, cap.sdma, true),
>> +    /* Suspend/resume support */
>> +    DEFINE_PROP_BOOL("suspend", SDHCIState, cap.suspend, false),
>> +    /* High speed support */
>> +    DEFINE_PROP_BOOL("high-speed", SDHCIState, cap.high_speed, true),
>> +    /* Voltage support 3.3/3.0/1.8V */
>> +    DEFINE_PROP_BOOL("3v3", SDHCIState, cap.v33, true),
>> +    DEFINE_PROP_BOOL("3v0", SDHCIState, cap.v30, false),
>> +    DEFINE_PROP_BOOL("1v8", SDHCIState, cap.v18, false),
> 
> This is a change of the default value.
> 
> I think you really need to specify specific changes in the commit
> message. That way is the defaults cause breakages we will be able to
> bisect it in the future.

You are right I need to be more descriptive in my messages.

I wonder how to consider the "default" SDHC_CAPAB_REG_DEFAULT, it seems
to only correctly matches the Zynq-7000 SDHCI.

Note that I only deprecate the 'capareg' property, it isn't modified
until all HCI are correctly passed to the new properties (verified using
the qtests), then I remove it.
This way this series is bisectable and due to the qtests, no breakage
should be introduced.

I tried to use the Spec default value for each property introduced.
I will sort the properties per Spec introduction, with a comment around.

>> +
>> +    /* capareg: deprecated */
>> +    DEFINE_PROP_UINT64("capareg", SDHCIState, capareg, UINT64_MAX),
>> +
>>      DEFINE_PROP_UINT64("maxcurr", SDHCIState, maxcurr, 0),
>>      DEFINE_PROP_BOOL("pending-insert-quirk", SDHCIState, pending_insert_quirk,
>>                       false),
>> --
>> 2.15.1
>>
>>

Re: [Qemu-devel] [PATCH v6 02/21] sdhci: add basic Spec v1capabilities
Posted by Alistair, 5 days ago
Sorry for the top post, I’m on my phone.

Changing them should be fine (as you said it doesn't actually change anything) I think it is just worth mentioning in the commit.

Thanks,
Alistair

From: Philippe Mathieu-Daudé
Sent: Friday, 12 January 2018 5:57 PM
To: Alistair Francis
Cc: Edgar E . Iglesias; Peter Maydell; Prasad J Pandit; Grégory Estrade; Andrey Smirnov; Peter Crosthwaite; qemu-devel@nongnu.org Developers; Krzysztof Kozlowski; Jean-Christophe Dubois; Sai Pavan Boddu; Igor Mitsyanko; qemu-arm; Clement Deschamps; Andrew Baumann
Subject: Re: [Qemu-devel] [PATCH v6 02/21] sdhci: add basic Spec v1capabilities

Hi Alistair,

On 01/12/2018 09:00 PM, Alistair Francis wrote:
> On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
> <f4bug@amsat.org> wrote:
>> (Note than Spec v2 is supported by default)
>>
>> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>> ---
>>  hw/sd/sdhci-internal.h | 24 +++++++++++++++++++-
>>  include/hw/sd/sdhci.h  |  6 +++++
>>  hw/sd/sdhci.c          | 61 +++++++++++++++++++++++++++++++++++++-------------
>>  3 files changed, 74 insertions(+), 17 deletions(-)
>>
>> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
>> index b7751c815f..9acafe7b01 100644
>> --- a/hw/sd/sdhci-internal.h
>> +++ b/hw/sd/sdhci-internal.h
>> @@ -24,6 +24,8 @@
>>  #ifndef SDHCI_INTERNAL_H
>>  #define SDHCI_INTERNAL_H
>>
>> +#include "hw/registerfields.h"
>> +
>>  /* R/W SDMA System Address register 0x0 */
>>  #define SDHC_SYSAD                     0x00
>>
>> @@ -84,6 +86,9 @@
>>
>>  /* R/W Host control Register 0x0 */
>>  #define SDHC_HOSTCTL                   0x28
>> +FIELD(SDHC_HOSTCTL, LED_CTRL,          0, 1);
>> +FIELD(SDHC_HOSTCTL, DATATRANSFERWIDTH, 1, 1); /* SD mode only */
>> +FIELD(SDHC_HOSTCTL, HIGH_SPEED,        2, 1);
>>  #define SDHC_CTRL_DMA_CHECK_MASK       0x18
>>  #define SDHC_CTRL_SDMA                 0x00
>>  #define SDHC_CTRL_ADMA1_32             0x08
>> @@ -94,6 +99,7 @@
>>  /* R/W Power Control Register 0x0 */
>>  #define SDHC_PWRCON                    0x29
>>  #define SDHC_POWER_ON                  (1 << 0)
>> +FIELD(SDHC_PWRCON, BUS_VOLTAGE,        1, 3);
>>
>>  /* R/W Block Gap Control Register 0x0 */
>>  #define SDHC_BLKGAP                    0x2A
>> @@ -116,6 +122,7 @@
>>
>>  /* R/W Timeout Control Register 0x0 */
>>  #define SDHC_TIMEOUTCON                0x2E
>> +FIELD(SDHC_TIMEOUTCON, COUNTER,        0, 4);
>>
>>  /* R/W Software Reset Register 0x0 */
>>  #define SDHC_SWRST                     0x2F
>> @@ -172,17 +179,32 @@
>>
>>  /* ROC Auto CMD12 error status register 0x0 */
>>  #define SDHC_ACMD12ERRSTS              0x3C
>> +FIELD(SDHC_ACMD12ERRSTS, TIMEOUT_ERR,  1, 1);
>> +FIELD(SDHC_ACMD12ERRSTS, CRC_ERR,      2, 1);
>> +FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,    4, 1);
>>
>>  /* HWInit Capabilities Register 0x05E80080 */
>>  #define SDHC_CAPAB                     0x40
>> -#define SDHC_CAN_DO_DMA                0x00400000
>>  #define SDHC_CAN_DO_ADMA2              0x00080000
>>  #define SDHC_CAN_DO_ADMA1              0x00100000
>>  #define SDHC_64_BIT_BUS_SUPPORT        (1 << 28)
>>  #define SDHC_CAPAB_BLOCKSIZE(x)        (((x) >> 16) & 0x3)
>> +FIELD(SDHC_CAPAB, TOCLKFREQ,           0, 6);
>> +FIELD(SDHC_CAPAB, TOUNIT,              7, 1);
>> +FIELD(SDHC_CAPAB, BASECLKFREQ,         8, 8);
>> +FIELD(SDHC_CAPAB, MAXBLOCKLENGTH,     16, 2);
>> +FIELD(SDHC_CAPAB, HIGHSPEED,          21, 1);
>> +FIELD(SDHC_CAPAB, SDMA,               22, 1);
>> +FIELD(SDHC_CAPAB, SUSPRESUME,         23, 1);
>> +FIELD(SDHC_CAPAB, V33,                24, 1);
>> +FIELD(SDHC_CAPAB, V30,                25, 1);
>> +FIELD(SDHC_CAPAB, V18,                26, 1);
>>
>>  /* HWInit Maximum Current Capabilities Register 0x0 */
>>  #define SDHC_MAXCURR                   0x48
>> +FIELD(SDHC_MAXCURR, V33_VDD1,          0, 8);
>> +FIELD(SDHC_MAXCURR, V30_VDD1,          8, 8);
>> +FIELD(SDHC_MAXCURR, V18_VDD1,         16, 8);
>>
>>  /* W Force Event Auto CMD12 Error Interrupt Register 0x0000 */
>>  #define SDHC_FEAER                     0x50
>> diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
>> index 8786676ac8..09b756eb7a 100644
>> --- a/include/hw/sd/sdhci.h
>> +++ b/include/hw/sd/sdhci.h
>> @@ -92,6 +92,12 @@ typedef struct SDHCIState {
>>      /* Configurable properties */
>>      bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
>>      uint8_t spec_version;
>> +    struct {
>> +        bool suspend;
>> +        bool high_speed;
>> +        bool sdma;
>> +        bool v33, v30, v18;
>> +    } cap;
>>  } SDHCIState;
>>
>>  #define TYPE_PCI_SDHCI "sdhci-pci"
>> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
>> index c8f750451e..d26ea821d0 100644
>> --- a/hw/sd/sdhci.c
>> +++ b/hw/sd/sdhci.c
>> @@ -44,12 +44,6 @@
>>   * 0 - not supported, 1 - supported, other - prohibited.
>>   */
>>  #define SDHC_CAPAB_64BITBUS       0ul        /* 64-bit System Bus Support */
>> -#define SDHC_CAPAB_18V            1ul        /* Voltage support 1.8v */
>> -#define SDHC_CAPAB_30V            0ul        /* Voltage support 3.0v */
>> -#define SDHC_CAPAB_33V            1ul        /* Voltage support 3.3v */
>> -#define SDHC_CAPAB_SUSPRESUME     0ul        /* Suspend/resume support */
>> -#define SDHC_CAPAB_SDMA           1ul        /* SDMA support */
>> -#define SDHC_CAPAB_HIGHSPEED      1ul        /* High speed support */
>>  #define SDHC_CAPAB_ADMA1          1ul        /* ADMA1 support */
>>  #define SDHC_CAPAB_ADMA2          1ul        /* ADMA2 support */
>>  /* Maximum host controller R/W buffers size
>> @@ -63,9 +57,7 @@
>>  #define SDHC_CAPAB_TOCLKFREQ      52ul
>>
>>  /* Now check all parameters and calculate CAPABILITIES REGISTER value */
>> -#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_18V > 1 || SDHC_CAPAB_30V > 1 ||     \
>> -    SDHC_CAPAB_33V > 1 || SDHC_CAPAB_SUSPRESUME > 1 || SDHC_CAPAB_SDMA > 1 ||  \
>> -    SDHC_CAPAB_HIGHSPEED > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 ||\
>> +#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 || \
>>      SDHC_CAPAB_TOUNIT > 1
>>  #error Capabilities features can have value 0 or 1 only!
>>  #endif
>> @@ -90,16 +82,36 @@
>>  #endif
>>
>>  #define SDHC_CAPAB_REG_DEFAULT                                 \
>> -   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_18V << 26) |     \
>> -    (SDHC_CAPAB_30V << 25) | (SDHC_CAPAB_33V << 24) |          \
>> -    (SDHC_CAPAB_SUSPRESUME << 23) | (SDHC_CAPAB_SDMA << 22) |  \
>> -    (SDHC_CAPAB_HIGHSPEED << 21) | (SDHC_CAPAB_ADMA1 << 20) |  \
>> +   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_ADMA1 << 20) |   \
>>      (SDHC_CAPAB_ADMA2 << 19) | (MAX_BLOCK_LENGTH << 16) |      \
>>      (SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
>>      (SDHC_CAPAB_TOCLKFREQ))
>>
>>  #define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
>>
>> +static void sdhci_init_capareg(SDHCIState *s, Error **errp)
>> +{
>> +    uint64_t capareg = 0;
>> +
>> +    switch (s->spec_version) {
>> +    case 2: /* default version */
>> +
>> +    /* fallback */
>> +    case 1:
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, HIGHSPEED, s->cap.high_speed);
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, SDMA, s->cap.sdma);
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, SUSPRESUME, s->cap.suspend);
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V33, s->cap.v33);
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V30, s->cap.v30);
>> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, V18, s->cap.v18);
>> +        break;
>> +
>> +    default:
>> +        error_setg(errp, "Unsupported spec version: %u", s->spec_version);
> 
> Probably best to have a return here, encase some logic added below
> later relies on this being successful.

Indeed, better safe than sorry.
>> +    }
>> +    s->capareg = capareg;
>> +}
>> +
>>  static uint8_t sdhci_slotint(SDHCIState *s)
>>  {
>>      return (s->norintsts & s->norintsigen) || (s->errintsts & s->errintsigen) ||
>> @@ -1026,7 +1038,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
>>      case SDHC_TRNMOD:
>>          /* DMA can be enabled only if it is supported as indicated by
>>           * capabilities register */
>> -        if (!(s->capareg & SDHC_CAN_DO_DMA)) {
>> +        if (!(s->capareg & R_SDHC_CAPAB_SDMA_MASK)) {
>>              value &= ~SDHC_TRNS_DMA;
>>          }
>>          MASKED_WRITE(s->trnmod, mask, value & SDHC_TRNMOD_MASK);
>> @@ -1181,6 +1193,10 @@ static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
>>          return;
>>      }
>>      s->version = (SDHC_HCVER_VENDOR << 8) | (s->spec_version - 1);
>> +
>> +    if (s->capareg == UINT64_MAX) {
>> +        sdhci_init_capareg(s, errp);
>> +    }
>>  }
>>
>>  static void sdhci_initfn(SDHCIState *s)
>> @@ -1297,8 +1313,21 @@ const VMStateDescription sdhci_vmstate = {
>>   * specific host controller implementation */
>>  static Property sdhci_properties[] = {
>>      DEFINE_PROP_UINT8("sd-spec-version", SDHCIState, spec_version, 2),
>> -    DEFINE_PROP_UINT64("capareg", SDHCIState, capareg,
>> -            SDHC_CAPAB_REG_DEFAULT),
>> +
>> +    /* DMA */
>> +    DEFINE_PROP_BOOL("sdma", SDHCIState, cap.sdma, true),
>> +    /* Suspend/resume support */
>> +    DEFINE_PROP_BOOL("suspend", SDHCIState, cap.suspend, false),
>> +    /* High speed support */
>> +    DEFINE_PROP_BOOL("high-speed", SDHCIState, cap.high_speed, true),
>> +    /* Voltage support 3.3/3.0/1.8V */
>> +    DEFINE_PROP_BOOL("3v3", SDHCIState, cap.v33, true),
>> +    DEFINE_PROP_BOOL("3v0", SDHCIState, cap.v30, false),
>> +    DEFINE_PROP_BOOL("1v8", SDHCIState, cap.v18, false),
> 
> This is a change of the default value.
> 
> I think you really need to specify specific changes in the commit
> message. That way is the defaults cause breakages we will be able to
> bisect it in the future.

You are right I need to be more descriptive in my messages.

I wonder how to consider the "default" SDHC_CAPAB_REG_DEFAULT, it seems
to only correctly matches the Zynq-7000 SDHCI.

Note that I only deprecate the 'capareg' property, it isn't modified
until all HCI are correctly passed to the new properties (verified using
the qtests), then I remove it.
This way this series is bisectable and due to the qtests, no breakage
should be introduced.

I tried to use the Spec default value for each property introduced.
I will sort the properties per Spec introduction, with a comment around.

>> +
>> +    /* capareg: deprecated */
>> +    DEFINE_PROP_UINT64("capareg", SDHCIState, capareg, UINT64_MAX),
>> +
>>      DEFINE_PROP_UINT64("maxcurr", SDHCIState, maxcurr, 0),
>>      DEFINE_PROP_BOOL("pending-insert-quirk", SDHCIState, pending_insert_quirk,
>>                       false),
>> --
>> 2.15.1
>>
>>


[Qemu-devel] [PATCH v6 03/21] sdhci: add max-block-length capability (Spec v1)
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
---
 hw/sd/sdhci-internal.h |  1 -
 include/hw/sd/sdhci.h  |  1 +
 hw/sd/sdhci.c          | 38 +++++++++++++-------------------------
 3 files changed, 14 insertions(+), 26 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index 9acafe7b01..c5e26bf8f3 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -188,7 +188,6 @@ FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,    4, 1);
 #define SDHC_CAN_DO_ADMA2              0x00080000
 #define SDHC_CAN_DO_ADMA1              0x00100000
 #define SDHC_64_BIT_BUS_SUPPORT        (1 << 28)
-#define SDHC_CAPAB_BLOCKSIZE(x)        (((x) >> 16) & 0x3)
 FIELD(SDHC_CAPAB, TOCLKFREQ,           0, 6);
 FIELD(SDHC_CAPAB, TOUNIT,              7, 1);
 FIELD(SDHC_CAPAB, BASECLKFREQ,         8, 8);
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 09b756eb7a..b61953f7c5 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -93,6 +93,7 @@ typedef struct SDHCIState {
     bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
     uint8_t spec_version;
     struct {
+        uint16_t max_blk_len;
         bool suspend;
         bool high_speed;
         bool sdma;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index d26ea821d0..54c1411d19 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -46,9 +46,6 @@
 #define SDHC_CAPAB_64BITBUS       0ul        /* 64-bit System Bus Support */
 #define SDHC_CAPAB_ADMA1          1ul        /* ADMA1 support */
 #define SDHC_CAPAB_ADMA2          1ul        /* ADMA2 support */
-/* Maximum host controller R/W buffers size
- * Possible values: 512, 1024, 2048 bytes */
-#define SDHC_CAPAB_MAXBLOCKLENGTH 512ul
 /* Maximum clock frequency for SDclock in MHz
  * value in range 10-63 MHz, 0 - not defined */
 #define SDHC_CAPAB_BASECLKFREQ    52ul
@@ -62,16 +59,6 @@
 #error Capabilities features can have value 0 or 1 only!
 #endif
 
-#if SDHC_CAPAB_MAXBLOCKLENGTH == 512
-#define MAX_BLOCK_LENGTH 0ul
-#elif SDHC_CAPAB_MAXBLOCKLENGTH == 1024
-#define MAX_BLOCK_LENGTH 1ul
-#elif SDHC_CAPAB_MAXBLOCKLENGTH == 2048
-#define MAX_BLOCK_LENGTH 2ul
-#else
-#error Max host controller block size can have value 512, 1024 or 2048 only!
-#endif
-
 #if (SDHC_CAPAB_BASECLKFREQ > 0 && SDHC_CAPAB_BASECLKFREQ < 10) || \
     SDHC_CAPAB_BASECLKFREQ > 63
 #error SDclock frequency can have value in range 0, 10-63 only!
@@ -83,7 +70,7 @@
 
 #define SDHC_CAPAB_REG_DEFAULT                                 \
    ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_ADMA1 << 20) |   \
-    (SDHC_CAPAB_ADMA2 << 19) | (MAX_BLOCK_LENGTH << 16) |      \
+    (SDHC_CAPAB_ADMA2 << 19) |                                 \
     (SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
     (SDHC_CAPAB_TOCLKFREQ))
 
@@ -92,12 +79,20 @@
 static void sdhci_init_capareg(SDHCIState *s, Error **errp)
 {
     uint64_t capareg = 0;
+    uint32_t val;
 
     switch (s->spec_version) {
     case 2: /* default version */
 
     /* fallback */
     case 1:
+        val = ctz32(s->cap.max_blk_len >> 9);
+        if (val >= 0b11) {
+            error_setg(errp, "block size can be 512, 1024 or 2048 only");
+            return;
+        }
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, MAXBLOCKLENGTH, val);
+
         capareg = FIELD_DP64(capareg, SDHC_CAPAB, HIGHSPEED, s->cap.high_speed);
         capareg = FIELD_DP64(capareg, SDHC_CAPAB, SDMA, s->cap.sdma);
         capareg = FIELD_DP64(capareg, SDHC_CAPAB, SUSPRESUME, s->cap.suspend);
@@ -1173,17 +1168,7 @@ static const MemoryRegionOps sdhci_mmio_ops = {
 
 static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
 {
-    switch (SDHC_CAPAB_BLOCKSIZE(s->capareg)) {
-    case 0:
-        return 512;
-    case 1:
-        return 1024;
-    case 2:
-        return 2048;
-    default:
-        hw_error("SDHC: unsupported value for maximum block size\n");
-        return 0;
-    }
+    return 1 << (9 + FIELD_EX32(s->capareg, SDHC_CAPAB, MAXBLOCKLENGTH));
 }
 
 static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
@@ -1314,6 +1299,9 @@ const VMStateDescription sdhci_vmstate = {
 static Property sdhci_properties[] = {
     DEFINE_PROP_UINT8("sd-spec-version", SDHCIState, spec_version, 2),
 
+    /* Maximum host controller R/W buffers size
+     * Possible values: 512, 1024, 2048 bytes */
+    DEFINE_PROP_UINT16("max-block-length", SDHCIState, cap.max_blk_len, 512),
     /* DMA */
     DEFINE_PROP_BOOL("sdma", SDHCIState, cap.sdma, true),
     /* Suspend/resume support */
-- 
2.15.1


[Qemu-devel] [PATCH v6 04/21] sdhci: add clock capabilities (Spec v1)
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 include/hw/sd/sdhci.h |  2 ++
 hw/sd/sdhci.c         | 53 ++++++++++++++++++++++++++++++++-------------------
 2 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index b61953f7c5..b5b4e411ff 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -93,6 +93,8 @@ typedef struct SDHCIState {
     bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
     uint8_t spec_version;
     struct {
+        uint8_t timeout_clk_freq, base_clk_freq_mhz;
+        bool timeout_clk_in_mhz;
         uint16_t max_blk_len;
         bool suspend;
         bool high_speed;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 54c1411d19..4c1fcf2c32 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -46,36 +46,32 @@
 #define SDHC_CAPAB_64BITBUS       0ul        /* 64-bit System Bus Support */
 #define SDHC_CAPAB_ADMA1          1ul        /* ADMA1 support */
 #define SDHC_CAPAB_ADMA2          1ul        /* ADMA2 support */
-/* Maximum clock frequency for SDclock in MHz
- * value in range 10-63 MHz, 0 - not defined */
-#define SDHC_CAPAB_BASECLKFREQ    52ul
-#define SDHC_CAPAB_TOUNIT         1ul  /* Timeout clock unit 0 - kHz, 1 - MHz */
-/* Timeout clock frequency 1-63, 0 - not defined */
-#define SDHC_CAPAB_TOCLKFREQ      52ul
 
 /* Now check all parameters and calculate CAPABILITIES REGISTER value */
-#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 || \
-    SDHC_CAPAB_TOUNIT > 1
+#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1
 #error Capabilities features can have value 0 or 1 only!
 #endif
 
-#if (SDHC_CAPAB_BASECLKFREQ > 0 && SDHC_CAPAB_BASECLKFREQ < 10) || \
-    SDHC_CAPAB_BASECLKFREQ > 63
-#error SDclock frequency can have value in range 0, 10-63 only!
-#endif
-
-#if SDHC_CAPAB_TOCLKFREQ > 63
-#error Timeout clock frequency can have value in range 0-63 only!
-#endif
-
 #define SDHC_CAPAB_REG_DEFAULT                                 \
    ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_ADMA1 << 20) |   \
-    (SDHC_CAPAB_ADMA2 << 19) |                                 \
-    (SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
-    (SDHC_CAPAB_TOCLKFREQ))
+    (SDHC_CAPAB_ADMA2 << 19))
 
 #define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
 
+static void sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
+                                         uint8_t freq, Error **errp)
+{
+    switch (freq) {
+    case 0:
+    case 10 ... 63:
+        break;
+    default:
+        error_setg(errp, "SD %s clock frequency can have value"
+                   "in range 0-63 only", desc);
+        return;
+    }
+}
+
 static void sdhci_init_capareg(SDHCIState *s, Error **errp)
 {
     uint64_t capareg = 0;
@@ -86,6 +82,16 @@ static void sdhci_init_capareg(SDHCIState *s, Error **errp)
 
     /* fallback */
     case 1:
+        sdhci_check_capab_freq_range(s, "Timeout", s->cap.timeout_clk_freq,
+                                     errp);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, TOCLKFREQ,
+                             s->cap.timeout_clk_freq);
+        sdhci_check_capab_freq_range(s, "Base", s->cap.base_clk_freq_mhz, errp);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, BASECLKFREQ,
+                             s->cap.base_clk_freq_mhz);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, TOUNIT,
+                             s->cap.timeout_clk_in_mhz);
+
         val = ctz32(s->cap.max_blk_len >> 9);
         if (val >= 0b11) {
             error_setg(errp, "block size can be 512, 1024 or 2048 only");
@@ -1299,6 +1305,13 @@ const VMStateDescription sdhci_vmstate = {
 static Property sdhci_properties[] = {
     DEFINE_PROP_UINT8("sd-spec-version", SDHCIState, spec_version, 2),
 
+    /* Timeout clock frequency 1-63, 0 - not defined */
+    DEFINE_PROP_UINT8("timeout-freq", SDHCIState, cap.timeout_clk_freq, 0),
+    /* Timeout clock unit 0 - kHz, 1 - MHz */
+    DEFINE_PROP_BOOL("freq-in-mhz", SDHCIState, cap.timeout_clk_in_mhz, true),
+    /* Maximum base clock frequency for SD clock in MHz (range 10-63 MHz, 0) */
+    DEFINE_PROP_UINT8("max-frequency", SDHCIState, cap.base_clk_freq_mhz, 0),
+
     /* Maximum host controller R/W buffers size
      * Possible values: 512, 1024, 2048 bytes */
     DEFINE_PROP_UINT16("max-block-length", SDHCIState, cap.max_blk_len, 512),
-- 
2.15.1


Re: [Qemu-devel] [PATCH v6 04/21] sdhci: add clock capabilities (Spec v1)
Posted by Alistair Francis, 5 days ago
On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
<f4bug@amsat.org> wrote:
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> ---
>  include/hw/sd/sdhci.h |  2 ++
>  hw/sd/sdhci.c         | 53 ++++++++++++++++++++++++++++++++-------------------
>  2 files changed, 35 insertions(+), 20 deletions(-)
>
> diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
> index b61953f7c5..b5b4e411ff 100644
> --- a/include/hw/sd/sdhci.h
> +++ b/include/hw/sd/sdhci.h
> @@ -93,6 +93,8 @@ typedef struct SDHCIState {
>      bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
>      uint8_t spec_version;
>      struct {
> +        uint8_t timeout_clk_freq, base_clk_freq_mhz;
> +        bool timeout_clk_in_mhz;
>          uint16_t max_blk_len;
>          bool suspend;
>          bool high_speed;
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index 54c1411d19..4c1fcf2c32 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -46,36 +46,32 @@
>  #define SDHC_CAPAB_64BITBUS       0ul        /* 64-bit System Bus Support */
>  #define SDHC_CAPAB_ADMA1          1ul        /* ADMA1 support */
>  #define SDHC_CAPAB_ADMA2          1ul        /* ADMA2 support */
> -/* Maximum clock frequency for SDclock in MHz
> - * value in range 10-63 MHz, 0 - not defined */
> -#define SDHC_CAPAB_BASECLKFREQ    52ul
> -#define SDHC_CAPAB_TOUNIT         1ul  /* Timeout clock unit 0 - kHz, 1 - MHz */
> -/* Timeout clock frequency 1-63, 0 - not defined */
> -#define SDHC_CAPAB_TOCLKFREQ      52ul
>
>  /* Now check all parameters and calculate CAPABILITIES REGISTER value */
> -#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 || \
> -    SDHC_CAPAB_TOUNIT > 1
> +#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1
>  #error Capabilities features can have value 0 or 1 only!
>  #endif
>
> -#if (SDHC_CAPAB_BASECLKFREQ > 0 && SDHC_CAPAB_BASECLKFREQ < 10) || \
> -    SDHC_CAPAB_BASECLKFREQ > 63
> -#error SDclock frequency can have value in range 0, 10-63 only!
> -#endif
> -
> -#if SDHC_CAPAB_TOCLKFREQ > 63
> -#error Timeout clock frequency can have value in range 0-63 only!
> -#endif
> -
>  #define SDHC_CAPAB_REG_DEFAULT                                 \
>     ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_ADMA1 << 20) |   \
> -    (SDHC_CAPAB_ADMA2 << 19) |                                 \
> -    (SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
> -    (SDHC_CAPAB_TOCLKFREQ))
> +    (SDHC_CAPAB_ADMA2 << 19))
>
>  #define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
>
> +static void sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
> +                                         uint8_t freq, Error **errp)
> +{
> +    switch (freq) {
> +    case 0:
> +    case 10 ... 63:
> +        break;
> +    default:
> +        error_setg(errp, "SD %s clock frequency can have value"
> +                   "in range 0-63 only", desc);
> +        return;
> +    }
> +}
> +
>  static void sdhci_init_capareg(SDHCIState *s, Error **errp)
>  {
>      uint64_t capareg = 0;
> @@ -86,6 +82,16 @@ static void sdhci_init_capareg(SDHCIState *s, Error **errp)
>
>      /* fallback */
>      case 1:
> +        sdhci_check_capab_freq_range(s, "Timeout", s->cap.timeout_clk_freq,
> +                                     errp);
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, TOCLKFREQ,
> +                             s->cap.timeout_clk_freq);
> +        sdhci_check_capab_freq_range(s, "Base", s->cap.base_clk_freq_mhz, errp);
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, BASECLKFREQ,
> +                             s->cap.base_clk_freq_mhz);
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, TOUNIT,
> +                             s->cap.timeout_clk_in_mhz);
> +
>          val = ctz32(s->cap.max_blk_len >> 9);
>          if (val >= 0b11) {
>              error_setg(errp, "block size can be 512, 1024 or 2048 only");
> @@ -1299,6 +1305,13 @@ const VMStateDescription sdhci_vmstate = {
>  static Property sdhci_properties[] = {
>      DEFINE_PROP_UINT8("sd-spec-version", SDHCIState, spec_version, 2),
>
> +    /* Timeout clock frequency 1-63, 0 - not defined */
> +    DEFINE_PROP_UINT8("timeout-freq", SDHCIState, cap.timeout_clk_freq, 0),
> +    /* Timeout clock unit 0 - kHz, 1 - MHz */
> +    DEFINE_PROP_BOOL("freq-in-mhz", SDHCIState, cap.timeout_clk_in_mhz, true),
> +    /* Maximum base clock frequency for SD clock in MHz (range 10-63 MHz, 0) */
> +    DEFINE_PROP_UINT8("max-frequency", SDHCIState, cap.base_clk_freq_mhz, 0),

Haven't all the defaults changed? Needs to be mentioned in the commit
message if that is on purpose.

Alistair

> +
>      /* Maximum host controller R/W buffers size
>       * Possible values: 512, 1024, 2048 bytes */
>      DEFINE_PROP_UINT16("max-block-length", SDHCIState, cap.max_blk_len, 512),
> --
> 2.15.1
>
>

[Qemu-devel] [PATCH v6 05/21] sdhci: add DMA and 64-bit capabilities (Spec v2)
Posted by Philippe Mathieu-Daudé, 6 days ago
new properties are introduced, with default value to Spec v2:
- adma1 (disabled, deprecated in v2)
- adma2 (enabled)
- 64bit (disabled)

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sdhci-internal.h | 14 +++++++-------
 include/hw/sd/sdhci.h  |  4 ++++
 hw/sd/sdhci.c          | 36 ++++++++++++++----------------------
 3 files changed, 25 insertions(+), 29 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index c5e26bf8f3..4ed9727ec3 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -89,12 +89,12 @@
 FIELD(SDHC_HOSTCTL, LED_CTRL,          0, 1);
 FIELD(SDHC_HOSTCTL, DATATRANSFERWIDTH, 1, 1); /* SD mode only */
 FIELD(SDHC_HOSTCTL, HIGH_SPEED,        2, 1);
-#define SDHC_CTRL_DMA_CHECK_MASK       0x18
+FIELD(SDHC_HOSTCTL, DMA,               3, 2);
 #define SDHC_CTRL_SDMA                 0x00
-#define SDHC_CTRL_ADMA1_32             0x08
+#define SDHC_CTRL_ADMA1_32             0x08 /* NOT ALLOWED since v2 */
 #define SDHC_CTRL_ADMA2_32             0x10
-#define SDHC_CTRL_ADMA2_64             0x18
-#define SDHC_DMA_TYPE(x)               ((x) & SDHC_CTRL_DMA_CHECK_MASK)
+#define SDHC_CTRL_ADMA2_64             0x18 /* only v1 & v2 (v3 optional) */
+#define SDHC_DMA_TYPE(x)               ((x) & R_SDHC_HOSTCTL_DMA_MASK)
 
 /* R/W Power Control Register 0x0 */
 #define SDHC_PWRCON                    0x29
@@ -185,19 +185,19 @@ FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,    4, 1);
 
 /* HWInit Capabilities Register 0x05E80080 */
 #define SDHC_CAPAB                     0x40
-#define SDHC_CAN_DO_ADMA2              0x00080000
-#define SDHC_CAN_DO_ADMA1              0x00100000
-#define SDHC_64_BIT_BUS_SUPPORT        (1 << 28)
 FIELD(SDHC_CAPAB, TOCLKFREQ,           0, 6);
 FIELD(SDHC_CAPAB, TOUNIT,              7, 1);
 FIELD(SDHC_CAPAB, BASECLKFREQ,         8, 8);
 FIELD(SDHC_CAPAB, MAXBLOCKLENGTH,     16, 2);
+FIELD(SDHC_CAPAB, ADMA2,              19, 1); /* since v2 */
+FIELD(SDHC_CAPAB, ADMA1,              20, 1); /* v1 only? */
 FIELD(SDHC_CAPAB, HIGHSPEED,          21, 1);
 FIELD(SDHC_CAPAB, SDMA,               22, 1);
 FIELD(SDHC_CAPAB, SUSPRESUME,         23, 1);
 FIELD(SDHC_CAPAB, V33,                24, 1);
 FIELD(SDHC_CAPAB, V30,                25, 1);
 FIELD(SDHC_CAPAB, V18,                26, 1);
+FIELD(SDHC_CAPAB, BUS64BIT,           28, 1); /* since v2 */
 
 /* HWInit Maximum Current Capabilities Register 0x0 */
 #define SDHC_MAXCURR                   0x48
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index b5b4e411ff..26b50583af 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -93,6 +93,7 @@ typedef struct SDHCIState {
     bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
     uint8_t spec_version;
     struct {
+        /* v1 */
         uint8_t timeout_clk_freq, base_clk_freq_mhz;
         bool timeout_clk_in_mhz;
         uint16_t max_blk_len;
@@ -100,6 +101,9 @@ typedef struct SDHCIState {
         bool high_speed;
         bool sdma;
         bool v33, v30, v18;
+        /* v2 */
+        bool adma1, adma2;
+        bool bus64;
     } cap;
 } SDHCIState;
 
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 4c1fcf2c32..e2c7ec021d 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -38,24 +38,6 @@
 #define TYPE_SDHCI_BUS "sdhci-bus"
 #define SDHCI_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_SDHCI_BUS)
 
-/* Default SD/MMC host controller features information, which will be
- * presented in CAPABILITIES register of generic SD host controller at reset.
- * If not stated otherwise:
- * 0 - not supported, 1 - supported, other - prohibited.
- */
-#define SDHC_CAPAB_64BITBUS       0ul        /* 64-bit System Bus Support */
-#define SDHC_CAPAB_ADMA1          1ul        /* ADMA1 support */
-#define SDHC_CAPAB_ADMA2          1ul        /* ADMA2 support */
-
-/* Now check all parameters and calculate CAPABILITIES REGISTER value */
-#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1
-#error Capabilities features can have value 0 or 1 only!
-#endif
-
-#define SDHC_CAPAB_REG_DEFAULT                                 \
-   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_ADMA1 << 20) |   \
-    (SDHC_CAPAB_ADMA2 << 19))
-
 #define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
 
 static void sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
@@ -72,6 +54,8 @@ static void sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
     }
 }
 
+/* Default SD/MMC host controller features information, which will be
+ * presented in CAPABILITIES register of generic SD host controller at reset. */
 static void sdhci_init_capareg(SDHCIState *s, Error **errp)
 {
     uint64_t capareg = 0;
@@ -79,6 +63,10 @@ static void sdhci_init_capareg(SDHCIState *s, Error **errp)
 
     switch (s->spec_version) {
     case 2: /* default version */
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, ADMA1, s->cap.adma1);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, ADMA2, s->cap.adma2);
+        /* 64-bit System Bus Support */
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, BUS64BIT, s->cap.bus64);
 
     /* fallback */
     case 1:
@@ -792,7 +780,7 @@ static void sdhci_data_transfer(void *opaque)
 
             break;
         case SDHC_CTRL_ADMA1_32:
-            if (!(s->capareg & SDHC_CAN_DO_ADMA1)) {
+            if (!(s->capareg & R_SDHC_CAPAB_ADMA1_MASK)) {
                 trace_sdhci_error("ADMA1 not supported");
                 break;
             }
@@ -800,7 +788,7 @@ static void sdhci_data_transfer(void *opaque)
             sdhci_do_adma(s);
             break;
         case SDHC_CTRL_ADMA2_32:
-            if (!(s->capareg & SDHC_CAN_DO_ADMA2)) {
+            if (!(s->capareg & R_SDHC_CAPAB_ADMA2_MASK)) {
                 trace_sdhci_error("ADMA2 not supported");
                 break;
             }
@@ -808,8 +796,8 @@ static void sdhci_data_transfer(void *opaque)
             sdhci_do_adma(s);
             break;
         case SDHC_CTRL_ADMA2_64:
-            if (!(s->capareg & SDHC_CAN_DO_ADMA2) ||
-                    !(s->capareg & SDHC_64_BIT_BUS_SUPPORT)) {
+            if (!(s->capareg & R_SDHC_CAPAB_ADMA2_MASK) ||
+                    !(s->capareg & R_SDHC_CAPAB_BUS64BIT_MASK)) {
                 trace_sdhci_error("64 bit ADMA not supported");
                 break;
             }
@@ -1317,6 +1305,8 @@ static Property sdhci_properties[] = {
     DEFINE_PROP_UINT16("max-block-length", SDHCIState, cap.max_blk_len, 512),
     /* DMA */
     DEFINE_PROP_BOOL("sdma", SDHCIState, cap.sdma, true),
+    DEFINE_PROP_BOOL("adma1", SDHCIState, cap.adma1, false),
+    DEFINE_PROP_BOOL("adma2", SDHCIState, cap.adma2, true),
     /* Suspend/resume support */
     DEFINE_PROP_BOOL("suspend", SDHCIState, cap.suspend, false),
     /* High speed support */
@@ -1326,6 +1316,8 @@ static Property sdhci_properties[] = {
     DEFINE_PROP_BOOL("3v0", SDHCIState, cap.v30, false),
     DEFINE_PROP_BOOL("1v8", SDHCIState, cap.v18, false),
 
+    DEFINE_PROP_BOOL("64bit", SDHCIState, cap.bus64, false),
+
     /* capareg: deprecated */
     DEFINE_PROP_UINT64("capareg", SDHCIState, capareg, UINT64_MAX),
 
-- 
2.15.1


Re: [Qemu-devel] [PATCH v6 05/21] sdhci: add DMA and 64-bit capabilities (Spec v2)
Posted by Alistair Francis, 5 days ago
On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
<f4bug@amsat.org> wrote:
> new properties are introduced, with default value to Spec v2:
> - adma1 (disabled, deprecated in v2)
> - adma2 (enabled)
> - 64bit (disabled)
>
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> ---
>  hw/sd/sdhci-internal.h | 14 +++++++-------
>  include/hw/sd/sdhci.h  |  4 ++++
>  hw/sd/sdhci.c          | 36 ++++++++++++++----------------------
>  3 files changed, 25 insertions(+), 29 deletions(-)
>
> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
> index c5e26bf8f3..4ed9727ec3 100644
> --- a/hw/sd/sdhci-internal.h
> +++ b/hw/sd/sdhci-internal.h
> @@ -89,12 +89,12 @@
>  FIELD(SDHC_HOSTCTL, LED_CTRL,          0, 1);
>  FIELD(SDHC_HOSTCTL, DATATRANSFERWIDTH, 1, 1); /* SD mode only */
>  FIELD(SDHC_HOSTCTL, HIGH_SPEED,        2, 1);
> -#define SDHC_CTRL_DMA_CHECK_MASK       0x18
> +FIELD(SDHC_HOSTCTL, DMA,               3, 2);
>  #define SDHC_CTRL_SDMA                 0x00
> -#define SDHC_CTRL_ADMA1_32             0x08
> +#define SDHC_CTRL_ADMA1_32             0x08 /* NOT ALLOWED since v2 */
>  #define SDHC_CTRL_ADMA2_32             0x10
> -#define SDHC_CTRL_ADMA2_64             0x18
> -#define SDHC_DMA_TYPE(x)               ((x) & SDHC_CTRL_DMA_CHECK_MASK)
> +#define SDHC_CTRL_ADMA2_64             0x18 /* only v1 & v2 (v3 optional) */
> +#define SDHC_DMA_TYPE(x)               ((x) & R_SDHC_HOSTCTL_DMA_MASK)
>
>  /* R/W Power Control Register 0x0 */
>  #define SDHC_PWRCON                    0x29
> @@ -185,19 +185,19 @@ FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,    4, 1);
>
>  /* HWInit Capabilities Register 0x05E80080 */
>  #define SDHC_CAPAB                     0x40
> -#define SDHC_CAN_DO_ADMA2              0x00080000
> -#define SDHC_CAN_DO_ADMA1              0x00100000
> -#define SDHC_64_BIT_BUS_SUPPORT        (1 << 28)
>  FIELD(SDHC_CAPAB, TOCLKFREQ,           0, 6);
>  FIELD(SDHC_CAPAB, TOUNIT,              7, 1);
>  FIELD(SDHC_CAPAB, BASECLKFREQ,         8, 8);
>  FIELD(SDHC_CAPAB, MAXBLOCKLENGTH,     16, 2);
> +FIELD(SDHC_CAPAB, ADMA2,              19, 1); /* since v2 */
> +FIELD(SDHC_CAPAB, ADMA1,              20, 1); /* v1 only? */
>  FIELD(SDHC_CAPAB, HIGHSPEED,          21, 1);
>  FIELD(SDHC_CAPAB, SDMA,               22, 1);
>  FIELD(SDHC_CAPAB, SUSPRESUME,         23, 1);
>  FIELD(SDHC_CAPAB, V33,                24, 1);
>  FIELD(SDHC_CAPAB, V30,                25, 1);
>  FIELD(SDHC_CAPAB, V18,                26, 1);
> +FIELD(SDHC_CAPAB, BUS64BIT,           28, 1); /* since v2 */
>
>  /* HWInit Maximum Current Capabilities Register 0x0 */
>  #define SDHC_MAXCURR                   0x48
> diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
> index b5b4e411ff..26b50583af 100644
> --- a/include/hw/sd/sdhci.h
> +++ b/include/hw/sd/sdhci.h
> @@ -93,6 +93,7 @@ typedef struct SDHCIState {
>      bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
>      uint8_t spec_version;
>      struct {
> +        /* v1 */
>          uint8_t timeout_clk_freq, base_clk_freq_mhz;
>          bool timeout_clk_in_mhz;
>          uint16_t max_blk_len;
> @@ -100,6 +101,9 @@ typedef struct SDHCIState {
>          bool high_speed;
>          bool sdma;
>          bool v33, v30, v18;
> +        /* v2 */
> +        bool adma1, adma2;
> +        bool bus64;
>      } cap;
>  } SDHCIState;
>
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index 4c1fcf2c32..e2c7ec021d 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -38,24 +38,6 @@
>  #define TYPE_SDHCI_BUS "sdhci-bus"
>  #define SDHCI_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_SDHCI_BUS)
>
> -/* Default SD/MMC host controller features information, which will be
> - * presented in CAPABILITIES register of generic SD host controller at reset.
> - * If not stated otherwise:
> - * 0 - not supported, 1 - supported, other - prohibited.
> - */
> -#define SDHC_CAPAB_64BITBUS       0ul        /* 64-bit System Bus Support */
> -#define SDHC_CAPAB_ADMA1          1ul        /* ADMA1 support */
> -#define SDHC_CAPAB_ADMA2          1ul        /* ADMA2 support */
> -
> -/* Now check all parameters and calculate CAPABILITIES REGISTER value */
> -#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1
> -#error Capabilities features can have value 0 or 1 only!
> -#endif
> -
> -#define SDHC_CAPAB_REG_DEFAULT                                 \
> -   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_ADMA1 << 20) |   \
> -    (SDHC_CAPAB_ADMA2 << 19))
> -
>  #define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
>
>  static void sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
> @@ -72,6 +54,8 @@ static void sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
>      }
>  }
>
> +/* Default SD/MMC host controller features information, which will be
> + * presented in CAPABILITIES register of generic SD host controller at reset. */

*/ should be on a new line.

Once that is fixed:

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Alistair

>  static void sdhci_init_capareg(SDHCIState *s, Error **errp)
>  {
>      uint64_t capareg = 0;
> @@ -79,6 +63,10 @@ static void sdhci_init_capareg(SDHCIState *s, Error **errp)
>
>      switch (s->spec_version) {
>      case 2: /* default version */
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, ADMA1, s->cap.adma1);
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, ADMA2, s->cap.adma2);
> +        /* 64-bit System Bus Support */
> +        capareg = FIELD_DP64(capareg, SDHC_CAPAB, BUS64BIT, s->cap.bus64);
>
>      /* fallback */
>      case 1:
> @@ -792,7 +780,7 @@ static void sdhci_data_transfer(void *opaque)
>
>              break;
>          case SDHC_CTRL_ADMA1_32:
> -            if (!(s->capareg & SDHC_CAN_DO_ADMA1)) {
> +            if (!(s->capareg & R_SDHC_CAPAB_ADMA1_MASK)) {
>                  trace_sdhci_error("ADMA1 not supported");
>                  break;
>              }
> @@ -800,7 +788,7 @@ static void sdhci_data_transfer(void *opaque)
>              sdhci_do_adma(s);
>              break;
>          case SDHC_CTRL_ADMA2_32:
> -            if (!(s->capareg & SDHC_CAN_DO_ADMA2)) {
> +            if (!(s->capareg & R_SDHC_CAPAB_ADMA2_MASK)) {
>                  trace_sdhci_error("ADMA2 not supported");
>                  break;
>              }
> @@ -808,8 +796,8 @@ static void sdhci_data_transfer(void *opaque)
>              sdhci_do_adma(s);
>              break;
>          case SDHC_CTRL_ADMA2_64:
> -            if (!(s->capareg & SDHC_CAN_DO_ADMA2) ||
> -                    !(s->capareg & SDHC_64_BIT_BUS_SUPPORT)) {
> +            if (!(s->capareg & R_SDHC_CAPAB_ADMA2_MASK) ||
> +                    !(s->capareg & R_SDHC_CAPAB_BUS64BIT_MASK)) {
>                  trace_sdhci_error("64 bit ADMA not supported");
>                  break;
>              }
> @@ -1317,6 +1305,8 @@ static Property sdhci_properties[] = {
>      DEFINE_PROP_UINT16("max-block-length", SDHCIState, cap.max_blk_len, 512),
>      /* DMA */
>      DEFINE_PROP_BOOL("sdma", SDHCIState, cap.sdma, true),
> +    DEFINE_PROP_BOOL("adma1", SDHCIState, cap.adma1, false),
> +    DEFINE_PROP_BOOL("adma2", SDHCIState, cap.adma2, true),
>      /* Suspend/resume support */
>      DEFINE_PROP_BOOL("suspend", SDHCIState, cap.suspend, false),
>      /* High speed support */
> @@ -1326,6 +1316,8 @@ static Property sdhci_properties[] = {
>      DEFINE_PROP_BOOL("3v0", SDHCIState, cap.v30, false),
>      DEFINE_PROP_BOOL("1v8", SDHCIState, cap.v18, false),
>
> +    DEFINE_PROP_BOOL("64bit", SDHCIState, cap.bus64, false),
> +
>      /* capareg: deprecated */
>      DEFINE_PROP_UINT64("capareg", SDHCIState, capareg, UINT64_MAX),
>
> --
> 2.15.1
>
>

[Qemu-devel] [PATCH v6 07/21] sdhci: Fix 64-bit ADMA2
Posted by Philippe Mathieu-Daudé, 6 days ago
From: Sai Pavan Boddu <saipava@xilinx.com>

The 64-bit ADMA address is not converted to the cpu endianes correctly.
This patch fixes the issue and uses a valid mask for the attribute data.

Signed-off-by: Sai Pavan Boddu <saipava@xilinx.com>
[AF: Re-write commit message]
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
---
 hw/sd/sdhci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index f0a29711f7..ab4ffeca1d 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -617,8 +617,8 @@ static void get_adma_description(SDHCIState *s, ADMADescr *dscr)
         dscr->length = le16_to_cpu(dscr->length);
         dma_memory_read(&s->dma_as, entry_addr + 4,
                         (uint8_t *)(&dscr->addr), 8);
-        dscr->attr = le64_to_cpu(dscr->attr);
-        dscr->attr &= 0xfffffff8;
+        dscr->addr = le64_to_cpu(dscr->addr);
+        dscr->attr &= (uint8_t) ~0xC0;
         dscr->incr = 12;
         break;
     }
-- 
2.15.1


[Qemu-devel] [PATCH v6 08/21] sdhci: add v3 capabilities
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sdhci-internal.h | 21 +++++++++++++++++++++
 include/hw/sd/sdhci.h  |  2 ++
 hw/sd/sdhci.c          | 22 ++++++++++++++++++++--
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index 4ed9727ec3..ac4704eb61 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -43,6 +43,7 @@
 #define SDHC_TRNS_DMA                  0x0001
 #define SDHC_TRNS_BLK_CNT_EN           0x0002
 #define SDHC_TRNS_ACMD12               0x0004
+#define SDHC_TRNS_ACMD23               0x0008 /* since v3 */
 #define SDHC_TRNS_READ                 0x0010
 #define SDHC_TRNS_MULTI                0x0020
 #define SDHC_TRNMOD_MASK               0x0037
@@ -183,12 +184,23 @@ FIELD(SDHC_ACMD12ERRSTS, TIMEOUT_ERR,  1, 1);
 FIELD(SDHC_ACMD12ERRSTS, CRC_ERR,      2, 1);
 FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,    4, 1);
 
+/* Host Control Register 2 (since v3) */
+#define SDHC_HOSTCTL2                  0x3E
+FIELD(SDHC_HOSTCTL2, UHS_MODE_SEL,     0, 3);
+FIELD(SDHC_HOSTCTL2, V18_ENA,          3, 1); /* UHS-I only */
+FIELD(SDHC_HOSTCTL2, DRIVER_STRENGTH,  4, 2); /* UHS-I only */
+FIELD(SDHC_HOSTCTL2, EXECUTE_TUNING,   6, 1); /* UHS-I only */
+FIELD(SDHC_HOSTCTL2, SAMPLING_CLKSEL,  7, 1); /* UHS-I only */
+FIELD(SDHC_HOSTCTL2, ASYNC_INT,       14, 1);
+FIELD(SDHC_HOSTCTL2, PRESET_ENA,      15, 1);
+
 /* HWInit Capabilities Register 0x05E80080 */
 #define SDHC_CAPAB                     0x40
 FIELD(SDHC_CAPAB, TOCLKFREQ,           0, 6);
 FIELD(SDHC_CAPAB, TOUNIT,              7, 1);
 FIELD(SDHC_CAPAB, BASECLKFREQ,         8, 8);
 FIELD(SDHC_CAPAB, MAXBLOCKLENGTH,     16, 2);
+FIELD(SDHC_CAPAB, EMBEDDED_8BIT,      18, 1); /* since v3 */
 FIELD(SDHC_CAPAB, ADMA2,              19, 1); /* since v2 */
 FIELD(SDHC_CAPAB, ADMA1,              20, 1); /* v1 only? */
 FIELD(SDHC_CAPAB, HIGHSPEED,          21, 1);
@@ -198,6 +210,15 @@ FIELD(SDHC_CAPAB, V33,                24, 1);
 FIELD(SDHC_CAPAB, V30,                25, 1);
 FIELD(SDHC_CAPAB, V18,                26, 1);
 FIELD(SDHC_CAPAB, BUS64BIT,           28, 1); /* since v2 */
+FIELD(SDHC_CAPAB, ASYNC_INT,          29, 1); /* since v3 */
+FIELD(SDHC_CAPAB, SLOT_TYPE,          30, 2); /* since v3 */
+FIELD(SDHC_CAPAB, BUS_SPEED,          32, 3); /* since v3 */
+FIELD(SDHC_CAPAB, DRIVER_STRENGTH,    36, 3); /* since v3 */
+FIELD(SDHC_CAPAB, DRIVER_TYPE_A,      36, 1); /* since v3 */
+FIELD(SDHC_CAPAB, DRIVER_TYPE_C,      37, 1); /* since v3 */
+FIELD(SDHC_CAPAB, DRIVER_TYPE_D,      38, 1); /* since v3 */
+FIELD(SDHC_CAPAB, TIMER_RETUNNING,    40, 4); /* since v3 */
+FIELD(SDHC_CAPAB, SDR50_TUNNING,      45, 1); /* since v3 */
 
 /* HWInit Maximum Current Capabilities Register 0x0 */
 #define SDHC_MAXCURR                   0x48
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 26b50583af..f45e911065 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -104,6 +104,8 @@ typedef struct SDHCIState {
         /* v2 */
         bool adma1, adma2;
         bool bus64;
+        /* v3 */
+        uint8_t slot_type, sdr, strength;
     } cap;
 } SDHCIState;
 
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index ab4ffeca1d..773eb68fd6 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -63,6 +63,18 @@ static void sdhci_init_capareg(SDHCIState *s, Error **errp)
     uint32_t val;
 
     switch (s->spec_version) {
+    case 3:
+        val = FIELD_EX64(capareg, SDHC_CAPAB, SLOT_TYPE);
+        if (val) {
+            error_setg(errp, "slot-type not supported");
+            return;
+        }
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, SLOT_TYPE, val);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, BUS_SPEED, s->cap.sdr);
+        capareg = FIELD_DP64(capareg, SDHC_CAPAB, DRIVER_STRENGTH,
+                             s->cap.strength);
+
+    /* fallback */
     case 2: /* default version */
         capareg = FIELD_DP64(capareg, SDHC_CAPAB, ADMA1, s->cap.adma1);
         capareg = FIELD_DP64(capareg, SDHC_CAPAB, ADMA2, s->cap.adma2);
@@ -1169,8 +1181,11 @@ static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
 
 static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
 {
-    if (s->spec_version != 2) {
-        error_setg(errp, "Only Spec v2 is supported");
+    switch (s->spec_version) {
+    case 2 ... 3:
+        break;
+    default:
+        error_setg(errp, "Only Spec v2/v3 are supported");
         return;
     }
     s->version = (SDHC_HCVER_VENDOR << 8) | (s->spec_version - 1);
@@ -1319,6 +1334,9 @@ static Property sdhci_properties[] = {
     DEFINE_PROP_BOOL("1v8", SDHCIState, cap.v18, false),
 
     DEFINE_PROP_BOOL("64bit", SDHCIState, cap.bus64, false),
+    DEFINE_PROP_UINT8("slot-type", SDHCIState, cap.slot_type, 0),
+    DEFINE_PROP_UINT8("bus-speed", SDHCIState, cap.sdr, 0),
+    DEFINE_PROP_UINT8("driver-strength", SDHCIState, cap.strength, 0),
 
     /* capareg: deprecated */
     DEFINE_PROP_UINT64("capareg", SDHCIState, capareg, UINT64_MAX),
-- 
2.15.1


[Qemu-devel] [PATCH v6 09/21] sdhci: rename the hostctl1 register
Posted by Philippe Mathieu-Daudé, 6 days ago
As per the Spec v3.00

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
---
 include/hw/sd/sdhci.h |  2 +-
 hw/sd/sdhci.c         | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index f45e911065..890dd1bbac 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -57,7 +57,7 @@ typedef struct SDHCIState {
     uint16_t cmdreg;       /* Command Register */
     uint32_t rspreg[4];    /* Response Registers 0-3 */
     uint32_t prnsts;       /* Present State Register */
-    uint8_t  hostctl;      /* Host Control Register */
+    uint8_t  hostctl1;     /* Host Control Register */
     uint8_t  pwrcon;       /* Power control Register */
     uint8_t  blkgap;       /* Block Gap Control Register */
     uint8_t  wakcon;       /* WakeUp Control Register */
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 773eb68fd6..6593f5d8b5 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -595,7 +595,7 @@ static void get_adma_description(SDHCIState *s, ADMADescr *dscr)
     uint32_t adma1 = 0;
     uint64_t adma2 = 0;
     hwaddr entry_addr = (hwaddr)s->admasysaddr;
-    switch (SDHC_DMA_TYPE(s->hostctl)) {
+    switch (SDHC_DMA_TYPE(s->hostctl1)) {
     case SDHC_CTRL_ADMA2_32:
         dma_memory_read(&s->dma_as, entry_addr, (uint8_t *)&adma2,
                         sizeof(adma2));
@@ -784,7 +784,7 @@ static void sdhci_data_transfer(void *opaque)
     SDHCIState *s = (SDHCIState *)opaque;
 
     if (s->trnmod & SDHC_TRNS_DMA) {
-        switch (SDHC_DMA_TYPE(s->hostctl)) {
+        switch (SDHC_DMA_TYPE(s->hostctl1)) {
         case SDHC_CTRL_SDMA:
             if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
                 sdhci_sdma_transfer_single_block(s);
@@ -893,7 +893,7 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, unsigned size)
         ret = s->prnsts;
         break;
     case SDHC_HOSTCTL:
-        ret = s->hostctl | (s->pwrcon << 8) | (s->blkgap << 16) |
+        ret = s->hostctl1 | (s->pwrcon << 8) | (s->blkgap << 16) |
               (s->wakcon << 24);
         break;
     case SDHC_CLKCON:
@@ -1011,7 +1011,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
         MASKED_WRITE(s->sdmasysad, mask, value);
         /* Writing to last byte of sdmasysad might trigger transfer */
         if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt &&
-                s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) {
+                s->blksize && SDHC_DMA_TYPE(s->hostctl1) == SDHC_CTRL_SDMA) {
             if (s->trnmod & SDHC_TRNS_MULTI) {
                 sdhci_sdma_transfer_multi_blocks(s);
             } else {
@@ -1063,7 +1063,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
         if (!(mask & 0xFF0000)) {
             sdhci_blkgap_write(s, value >> 16);
         }
-        MASKED_WRITE(s->hostctl, mask, value);
+        MASKED_WRITE(s->hostctl1, mask, value);
         MASKED_WRITE(s->pwrcon, mask >> 8, value >> 8);
         MASKED_WRITE(s->wakcon, mask >> 24, value >> 24);
         if (!(s->prnsts & SDHC_CARD_PRESENT) || ((s->pwrcon >> 1) & 0x7) < 5 ||
@@ -1277,7 +1277,7 @@ const VMStateDescription sdhci_vmstate = {
         VMSTATE_UINT16(cmdreg, SDHCIState),
         VMSTATE_UINT32_ARRAY(rspreg, SDHCIState, 4),
         VMSTATE_UINT32(prnsts, SDHCIState),
-        VMSTATE_UINT8(hostctl, SDHCIState),
+        VMSTATE_UINT8(hostctl1, SDHCIState),
         VMSTATE_UINT8(pwrcon, SDHCIState),
         VMSTATE_UINT8(blkgap, SDHCIState),
         VMSTATE_UINT8(wakcon, SDHCIState),
-- 
2.15.1


[Qemu-devel] [PATCH v6 10/21] hw/arm/exynos4210: implement SDHCI Spec v2
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/arm/exynos4210.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index e8e1d81e62..0e6acac784 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -75,7 +75,6 @@
 #define EXYNOS4210_INT_COMBINER_BASE_ADDR   0x10448000
 
 /* SD/MMC host controllers */
-#define EXYNOS4210_SDHCI_CAPABILITIES       0x05E80080
 #define EXYNOS4210_SDHCI_BASE_ADDR          0x12510000
 #define EXYNOS4210_SDHCI_ADDR(n)            (EXYNOS4210_SDHCI_BASE_ADDR + \
                                                 0x00010000 * (n))
@@ -377,8 +376,18 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
         BlockBackend *blk;
         DriveInfo *di;
 
+        /* Compatible with:
+         * - SD Host Controller Specification Version 2.0
+         * - SDIO Specification Version 2.0
+         * - MMC Specification Version 4.3
+         *
+         * - SDMA
+         * - ADMA
+         */
         dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
-        qdev_prop_set_uint32(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
+        qdev_prop_set_uint8(dev, "sd-spec-version", 2);
+        qdev_prop_set_bit(dev, "suspend", true);
+        qdev_prop_set_bit(dev, "1v8", true);
         qdev_init_nofail(dev);
 
         busdev = SYS_BUS_DEVICE(dev);
-- 
2.15.1


Re: [Qemu-devel] [PATCH v6 10/21] hw/arm/exynos4210: implement SDHCI Spec v2
Posted by Alistair Francis, 5 days ago
On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
<f4bug@amsat.org> wrote:
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Acked-by: Alistair Francis <alistair.francis@xilinx.com>

Alistair

> ---
>  hw/arm/exynos4210.c | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
> index e8e1d81e62..0e6acac784 100644
> --- a/hw/arm/exynos4210.c
> +++ b/hw/arm/exynos4210.c
> @@ -75,7 +75,6 @@
>  #define EXYNOS4210_INT_COMBINER_BASE_ADDR   0x10448000
>
>  /* SD/MMC host controllers */
> -#define EXYNOS4210_SDHCI_CAPABILITIES       0x05E80080
>  #define EXYNOS4210_SDHCI_BASE_ADDR          0x12510000
>  #define EXYNOS4210_SDHCI_ADDR(n)            (EXYNOS4210_SDHCI_BASE_ADDR + \
>                                                  0x00010000 * (n))
> @@ -377,8 +376,18 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
>          BlockBackend *blk;
>          DriveInfo *di;
>
> +        /* Compatible with:
> +         * - SD Host Controller Specification Version 2.0
> +         * - SDIO Specification Version 2.0
> +         * - MMC Specification Version 4.3
> +         *
> +         * - SDMA
> +         * - ADMA
> +         */
>          dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
> -        qdev_prop_set_uint32(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
> +        qdev_prop_set_uint8(dev, "sd-spec-version", 2);
> +        qdev_prop_set_bit(dev, "suspend", true);
> +        qdev_prop_set_bit(dev, "1v8", true);
>          qdev_init_nofail(dev);
>
>          busdev = SYS_BUS_DEVICE(dev);
> --
> 2.15.1
>
>

[Qemu-devel] [PATCH v6 11/21] hw/arm/xilinx_zynq: implement SDHCI Spec v2
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/arm/xilinx_zynq.c | 64 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 40 insertions(+), 24 deletions(-)

diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 1836a4ed45..9a106db7b7 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -165,10 +165,8 @@ static void zynq_init(MachineState *machine)
     MemoryRegion *address_space_mem = get_system_memory();
     MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
     MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
-    DeviceState *dev, *carddev;
+    DeviceState *dev;
     SysBusDevice *busdev;
-    DriveInfo *di;
-    BlockBackend *blk;
     qemu_irq pic[64];
     int n;
 
@@ -247,27 +245,45 @@ static void zynq_init(MachineState *machine)
     gem_init(&nd_table[0], 0xE000B000, pic[54-IRQ_OFFSET]);
     gem_init(&nd_table[1], 0xE000C000, pic[77-IRQ_OFFSET]);
 
-    dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
-
-    di = drive_get_next(IF_SD);
-    blk = di ? blk_by_legacy_dinfo(di) : NULL;
-    carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
-    qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
-    object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
-
-    dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
-
-    di = drive_get_next(IF_SD);
-    blk = di ? blk_by_legacy_dinfo(di) : NULL;
-    carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
-    qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
-    object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
+    for (n = 0; n < 2; n++) {
+        int hci_irq = n ? 79 : 56;
+        hwaddr hci_addr = n ? 0xE0101000 : 0xE0100000;
+        DriveInfo *di;
+        BlockBackend *blk;
+        DeviceState *carddev;
+
+        /* Compatible with:
+         * - SD Host Controller Specification Version 2.0 Part A2
+         * - SDIO Specification Version 2.0
+         * - MMC Specification Version 3.31
+         *
+         * - SDMA (single operation DMA)
+         * - ADMA1 (4 KB boundary limited DMA)
+         * - ADMA2
+         *
+         * - up to seven functions in SD1, SD4, but does not support SPI mode
+         * - SD high-speed (SDHS) card
+         * - SD High Capacity (SDHC) card
+         *
+         * - Low-speed, 1 KHz to 400 KHz
+         * - Full-speed, 1 MHz to 50 MHz (25 MB/sec)
+         */
+        dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
+        qdev_prop_set_uint8(dev, "sd-spec-version", 2);
+        qdev_prop_set_bit(dev, "adma1", true);
+        qdev_prop_set_bit(dev, "high-speed", true);
+        qdev_prop_set_uint16(dev, "max-block-length", 1024);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, hci_addr);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[hci_irq - IRQ_OFFSET]);
+
+        di = drive_get_next(IF_SD);
+        blk = di ? blk_by_legacy_dinfo(di) : NULL;
+        carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
+        qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
+        object_property_set_bool(OBJECT(carddev), true, "realized",
+                                 &error_fatal);
+    }
 
     dev = qdev_create(NULL, TYPE_ZYNQ_XADC);
     qdev_init_nofail(dev);
-- 
2.15.1


Re: [Qemu-devel] [PATCH v6 11/21] hw/arm/xilinx_zynq: implement SDHCI Spec v2
Posted by Alistair Francis, 1 day ago
On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
<f4bug@amsat.org> wrote:
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Alistair

> ---
>  hw/arm/xilinx_zynq.c | 64 ++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 40 insertions(+), 24 deletions(-)
>
> diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
> index 1836a4ed45..9a106db7b7 100644
> --- a/hw/arm/xilinx_zynq.c
> +++ b/hw/arm/xilinx_zynq.c
> @@ -165,10 +165,8 @@ static void zynq_init(MachineState *machine)
>      MemoryRegion *address_space_mem = get_system_memory();
>      MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
>      MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
> -    DeviceState *dev, *carddev;
> +    DeviceState *dev;
>      SysBusDevice *busdev;
> -    DriveInfo *di;
> -    BlockBackend *blk;
>      qemu_irq pic[64];
>      int n;
>
> @@ -247,27 +245,45 @@ static void zynq_init(MachineState *machine)
>      gem_init(&nd_table[0], 0xE000B000, pic[54-IRQ_OFFSET]);
>      gem_init(&nd_table[1], 0xE000C000, pic[77-IRQ_OFFSET]);
>
> -    dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
> -    qdev_init_nofail(dev);
> -    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000);
> -    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
> -
> -    di = drive_get_next(IF_SD);
> -    blk = di ? blk_by_legacy_dinfo(di) : NULL;
> -    carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
> -    qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
> -    object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
> -
> -    dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
> -    qdev_init_nofail(dev);
> -    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
> -    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
> -
> -    di = drive_get_next(IF_SD);
> -    blk = di ? blk_by_legacy_dinfo(di) : NULL;
> -    carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
> -    qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
> -    object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
> +    for (n = 0; n < 2; n++) {
> +        int hci_irq = n ? 79 : 56;
> +        hwaddr hci_addr = n ? 0xE0101000 : 0xE0100000;
> +        DriveInfo *di;
> +        BlockBackend *blk;
> +        DeviceState *carddev;
> +
> +        /* Compatible with:
> +         * - SD Host Controller Specification Version 2.0 Part A2
> +         * - SDIO Specification Version 2.0
> +         * - MMC Specification Version 3.31
> +         *
> +         * - SDMA (single operation DMA)
> +         * - ADMA1 (4 KB boundary limited DMA)
> +         * - ADMA2
> +         *
> +         * - up to seven functions in SD1, SD4, but does not support SPI mode
> +         * - SD high-speed (SDHS) card
> +         * - SD High Capacity (SDHC) card
> +         *
> +         * - Low-speed, 1 KHz to 400 KHz
> +         * - Full-speed, 1 MHz to 50 MHz (25 MB/sec)
> +         */
> +        dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
> +        qdev_prop_set_uint8(dev, "sd-spec-version", 2);
> +        qdev_prop_set_bit(dev, "adma1", true);
> +        qdev_prop_set_bit(dev, "high-speed", true);
> +        qdev_prop_set_uint16(dev, "max-block-length", 1024);
> +        qdev_init_nofail(dev);
> +        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, hci_addr);
> +        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[hci_irq - IRQ_OFFSET]);
> +
> +        di = drive_get_next(IF_SD);
> +        blk = di ? blk_by_legacy_dinfo(di) : NULL;
> +        carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
> +        qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
> +        object_property_set_bool(OBJECT(carddev), true, "realized",
> +                                 &error_fatal);
> +    }
>
>      dev = qdev_create(NULL, TYPE_ZYNQ_XADC);
>      qdev_init_nofail(dev);
> --
> 2.15.1
>
>

[Qemu-devel] [PATCH v6 12/21] hw/arm/bcm2835_peripherals: implement SDHCI Spec v3
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/arm/bcm2835_peripherals.c | 32 +++++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 12e0dd11af..79d680cb1b 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -18,9 +18,6 @@
 /* Peripheral base address on the VC (GPU) system bus */
 #define BCM2835_VC_PERI_BASE 0x7e000000
 
-/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
-#define BCM2835_SDHC_CAPAREG 0x52034b4
-
 static void bcm2835_peripherals_init(Object *obj)
 {
     BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
@@ -254,14 +251,27 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
     memory_region_add_subregion(&s->peri_mr, RNG_OFFSET,
                 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0));
 
-    /* Extended Mass Media Controller */
-    object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
-                            &err);
-    if (err) {
-        error_propagate(errp, err);
-        return;
-    }
-
+    /* Extended Mass Media Controller
+     *
+     * Compatible with:
+     * - SD Host Controller Specification Version 3.0 Draft 1.0
+     * - SDIO Specification Version 3.0
+     * - MMC Specification Version 4.4
+     *
+     * - 32-bit access only
+     * - default clocks
+     * - no DMA
+     * - SD high-speed (SDHS) card
+     * - maximum block size: 1kB
+     *
+     * For the exact details please refer to the Arasan documentation:
+     *   SD3.0_Host_AHB_eMMC4.4_Usersguide_ver5.9_jan11_10.pdf   ¯\_(ツ)_/¯
+     */
+    object_property_set_uint(OBJECT(&s->sdhci), 3, "sd-spec-version", &err);
+    object_property_set_uint(OBJECT(&s->sdhci), 52, "timeout-freq", &err);
+    object_property_set_uint(OBJECT(&s->sdhci), 52, "max-frequency", &err);
+    object_property_set_bool(OBJECT(&s->sdhci), false, "adma1", &err);
+    object_property_set_bool(OBJECT(&s->sdhci), true, "1v8", &err);
     object_property_set_bool(OBJECT(&s->sdhci), true, "pending-insert-quirk",
                              &err);
     if (err) {
-- 
2.15.1


[Qemu-devel] [PATCH v6 13/21] hw/arm/bcm2835_peripherals: change maximum block size to 1kB
Posted by Philippe Mathieu-Daudé, 6 days ago
following the datasheet.

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/arm/bcm2835_peripherals.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 79d680cb1b..72d4dd73b5 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -272,6 +272,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
     object_property_set_uint(OBJECT(&s->sdhci), 52, "max-frequency", &err);
     object_property_set_bool(OBJECT(&s->sdhci), false, "adma1", &err);
     object_property_set_bool(OBJECT(&s->sdhci), true, "1v8", &err);
+    object_property_set_uint(OBJECT(&s->sdhci), 1024, "max-block-length", &err);
     object_property_set_bool(OBJECT(&s->sdhci), true, "pending-insert-quirk",
                              &err);
     if (err) {
-- 
2.15.1


[Qemu-devel] [PATCH v6 14/21] hw/arm/fsl-imx6: implement SDHCI Spec v3
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/arm/fsl-imx6.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index b0d4088290..e7d13d54e6 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -348,6 +348,19 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
             { FSL_IMX6_uSDHC4_ADDR, FSL_IMX6_uSDHC4_IRQ },
         };
 
+        /* UHS-I SDIO3.0 SDR104 1.8V ADMA */
+        object_property_set_uint(OBJECT(&s->esdhc[i]), 3, "sd-spec-version",
+                                 &err);
+        object_property_set_uint(OBJECT(&s->esdhc[i]), 52, "timeout-freq",
+                                 &err);
+        object_property_set_uint(OBJECT(&s->esdhc[i]), 52, "max-frequency",
+                                 &err);
+        object_property_set_bool(OBJECT(&s->esdhc[i]), true, "adma1", &err);
+        object_property_set_bool(OBJECT(&s->esdhc[i]), true, "1v8", &err);
+        if (err) {
+            error_propagate(errp, err);
+            return;
+        }
         object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
         if (err) {
             error_propagate(errp, err);
-- 
2.15.1


[Qemu-devel] [PATCH v6 15/21] hw/arm/xilinx_zynqmp: implement SDHCI Spec v3
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/arm/xlnx-zynqmp.c | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 325642058b..dacf89c566 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -381,22 +381,38 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, gic_spi[SATA_INTR]);
 
     for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
-        char *bus_name;
-
-        object_property_set_bool(OBJECT(&s->sdhci[i]), true,
-                                 "realized", &err);
+        char *bus_name = g_strdup_printf("sd-bus%d", i);
+        SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sdhci[i]);
+        Object *sdhci = OBJECT(&s->sdhci[i]);
+
+        /* Compatible with:
+         * - SD Host Controller Specification Version 3.00
+         * - SDIO Specification Version 3.0
+         * - eMMC Specification Version 4.51
+         *
+         * Host clock rate variable between 0 and 208 MHz
+         * Transfers the data in SDR104, SDR50, DDR50 modes
+         * (SDR104 mode: up to 832Mbits/s using 4 parallel data lines)
+         * Transfers the data in 1 bit and 4 bit SD modes
+         * UHS speed modes, 1.8V
+         * voltage switch, tuning commands
+         */
+        object_property_set_uint(sdhci, 3, "sd-spec-version", &err);
+        object_property_set_bool(sdhci, true, "suspend", &err);
+        object_property_set_bool(sdhci, true, "1v8", &err);
+        object_property_set_bool(sdhci, true, "64bit", &err);
+        object_property_set_uint(sdhci, 0b111, "bus-speed", &err);
+        object_property_set_uint(sdhci, 0b111, "driver-strength", &err);
+        object_property_set_bool(sdhci, true, "realized", &err);
         if (err) {
             error_propagate(errp, err);
             return;
         }
-        sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[i]), 0,
-                        sdhci_addr[i]);
-        sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[i]), 0,
-                           gic_spi[sdhci_intr[i]]);
+        sysbus_mmio_map(sbd, 0, sdhci_addr[i]);
+        sysbus_connect_irq(sbd, 0, gic_spi[sdhci_intr[i]]);
+
         /* Alias controller SD bus to the SoC itself */
-        bus_name = g_strdup_printf("sd-bus%d", i);
-        object_property_add_alias(OBJECT(s), bus_name,
-                                  OBJECT(&s->sdhci[i]), "sd-bus",
+        object_property_add_alias(OBJECT(s), bus_name, sdhci, "sd-bus",
                                   &error_abort);
         g_free(bus_name);
     }
-- 
2.15.1


Re: [Qemu-devel] [PATCH v6 15/21] hw/arm/xilinx_zynqmp: implement SDHCI Spec v3
Posted by Alistair Francis, 5 days ago
On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
<f4bug@amsat.org> wrote:
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Alistair

> ---
>  hw/arm/xlnx-zynqmp.c | 38 +++++++++++++++++++++++++++-----------
>  1 file changed, 27 insertions(+), 11 deletions(-)
>
> diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
> index 325642058b..dacf89c566 100644
> --- a/hw/arm/xlnx-zynqmp.c
> +++ b/hw/arm/xlnx-zynqmp.c
> @@ -381,22 +381,38 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
>      sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, gic_spi[SATA_INTR]);
>
>      for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
> -        char *bus_name;
> -
> -        object_property_set_bool(OBJECT(&s->sdhci[i]), true,
> -                                 "realized", &err);
> +        char *bus_name = g_strdup_printf("sd-bus%d", i);
> +        SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sdhci[i]);
> +        Object *sdhci = OBJECT(&s->sdhci[i]);
> +
> +        /* Compatible with:
> +         * - SD Host Controller Specification Version 3.00
> +         * - SDIO Specification Version 3.0
> +         * - eMMC Specification Version 4.51
> +         *
> +         * Host clock rate variable between 0 and 208 MHz
> +         * Transfers the data in SDR104, SDR50, DDR50 modes
> +         * (SDR104 mode: up to 832Mbits/s using 4 parallel data lines)
> +         * Transfers the data in 1 bit and 4 bit SD modes
> +         * UHS speed modes, 1.8V
> +         * voltage switch, tuning commands
> +         */
> +        object_property_set_uint(sdhci, 3, "sd-spec-version", &err);
> +        object_property_set_bool(sdhci, true, "suspend", &err);
> +        object_property_set_bool(sdhci, true, "1v8", &err);
> +        object_property_set_bool(sdhci, true, "64bit", &err);
> +        object_property_set_uint(sdhci, 0b111, "bus-speed", &err);
> +        object_property_set_uint(sdhci, 0b111, "driver-strength", &err);
> +        object_property_set_bool(sdhci, true, "realized", &err);
>          if (err) {
>              error_propagate(errp, err);
>              return;
>          }
> -        sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[i]), 0,
> -                        sdhci_addr[i]);
> -        sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[i]), 0,
> -                           gic_spi[sdhci_intr[i]]);
> +        sysbus_mmio_map(sbd, 0, sdhci_addr[i]);
> +        sysbus_connect_irq(sbd, 0, gic_spi[sdhci_intr[i]]);
> +
>          /* Alias controller SD bus to the SoC itself */
> -        bus_name = g_strdup_printf("sd-bus%d", i);
> -        object_property_add_alias(OBJECT(s), bus_name,
> -                                  OBJECT(&s->sdhci[i]), "sd-bus",
> +        object_property_add_alias(OBJECT(s), bus_name, sdhci, "sd-bus",
>                                    &error_abort);
>          g_free(bus_name);
>      }
> --
> 2.15.1
>
>

[Qemu-devel] [PATCH v6 16/21] sdhci: remove the deprecated 'capareg' property
Posted by Philippe Mathieu-Daudé, 6 days ago
All SDHCI consumers have been upgraded to set correct properties.

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
---
 hw/sd/sdhci.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 6593f5d8b5..8e4805c84e 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1190,9 +1190,7 @@ static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
     }
     s->version = (SDHC_HCVER_VENDOR << 8) | (s->spec_version - 1);
 
-    if (s->capareg == UINT64_MAX) {
-        sdhci_init_capareg(s, errp);
-    }
+    sdhci_init_capareg(s, errp);
 }
 
 static void sdhci_initfn(SDHCIState *s)
@@ -1338,9 +1336,6 @@ static Property sdhci_properties[] = {
     DEFINE_PROP_UINT8("bus-speed", SDHCIState, cap.sdr, 0),
     DEFINE_PROP_UINT8("driver-strength", SDHCIState, cap.strength, 0),
 
-    /* capareg: deprecated */
-    DEFINE_PROP_UINT64("capareg", SDHCIState, capareg, UINT64_MAX),
-
     DEFINE_PROP_UINT64("maxcurr", SDHCIState, maxcurr, 0),
     DEFINE_PROP_BOOL("pending-insert-quirk", SDHCIState, pending_insert_quirk,
                      false),
-- 
2.15.1


[Qemu-devel] [PATCH v6 17/21] sdhci: add Spec v4.2 register definitions
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sdhci-internal.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index ac4704eb61..b82e847636 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -191,6 +191,10 @@ FIELD(SDHC_HOSTCTL2, V18_ENA,          3, 1); /* UHS-I only */
 FIELD(SDHC_HOSTCTL2, DRIVER_STRENGTH,  4, 2); /* UHS-I only */
 FIELD(SDHC_HOSTCTL2, EXECUTE_TUNING,   6, 1); /* UHS-I only */
 FIELD(SDHC_HOSTCTL2, SAMPLING_CLKSEL,  7, 1); /* UHS-I only */
+FIELD(SDHC_HOSTCTL2, UHS_II_ENA,       8, 1); /* since v4 */
+FIELD(SDHC_HOSTCTL2, ADMA2_LENGTH,    10, 1); /* since v4 */
+FIELD(SDHC_HOSTCTL2, CMD23_ENA,       11, 1); /* since v4 */
+FIELD(SDHC_HOSTCTL2, VERSION4,        12, 1); /* since v4 */
 FIELD(SDHC_HOSTCTL2, ASYNC_INT,       14, 1);
 FIELD(SDHC_HOSTCTL2, PRESET_ENA,      15, 1);
 
@@ -219,12 +223,16 @@ FIELD(SDHC_CAPAB, DRIVER_TYPE_C,      37, 1); /* since v3 */
 FIELD(SDHC_CAPAB, DRIVER_TYPE_D,      38, 1); /* since v3 */
 FIELD(SDHC_CAPAB, TIMER_RETUNNING,    40, 4); /* since v3 */
 FIELD(SDHC_CAPAB, SDR50_TUNNING,      45, 1); /* since v3 */
+FIELD(SDHC_CAPAB, CLK_MUL,            48, 8); /* since v4.20 */
+FIELD(SDHC_CAPAB, ADMA3,              59, 1); /* since v4.20 */
+FIELD(SDHC_CAPAB, V18_VDD2,           60, 1); /* since v4.20 */
 
 /* HWInit Maximum Current Capabilities Register 0x0 */
 #define SDHC_MAXCURR                   0x48
 FIELD(SDHC_MAXCURR, V33_VDD1,          0, 8);
 FIELD(SDHC_MAXCURR, V30_VDD1,          8, 8);
 FIELD(SDHC_MAXCURR, V18_VDD1,         16, 8);
+FIELD(SDHC_MAXCURR, V18_VDD2,         32, 8); /* since v4.20 */
 
 /* W Force Event Auto CMD12 Error Interrupt Register 0x0000 */
 #define SDHC_FEAER                     0x50
-- 
2.15.1


Re: [Qemu-devel] [PATCH v6 17/21] sdhci: add Spec v4.2 register definitions
Posted by Alistair Francis, 5 days ago
On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
<f4bug@amsat.org> wrote:
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Alistair

> ---
>  hw/sd/sdhci-internal.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
> index ac4704eb61..b82e847636 100644
> --- a/hw/sd/sdhci-internal.h
> +++ b/hw/sd/sdhci-internal.h
> @@ -191,6 +191,10 @@ FIELD(SDHC_HOSTCTL2, V18_ENA,          3, 1); /* UHS-I only */
>  FIELD(SDHC_HOSTCTL2, DRIVER_STRENGTH,  4, 2); /* UHS-I only */
>  FIELD(SDHC_HOSTCTL2, EXECUTE_TUNING,   6, 1); /* UHS-I only */
>  FIELD(SDHC_HOSTCTL2, SAMPLING_CLKSEL,  7, 1); /* UHS-I only */
> +FIELD(SDHC_HOSTCTL2, UHS_II_ENA,       8, 1); /* since v4 */
> +FIELD(SDHC_HOSTCTL2, ADMA2_LENGTH,    10, 1); /* since v4 */
> +FIELD(SDHC_HOSTCTL2, CMD23_ENA,       11, 1); /* since v4 */
> +FIELD(SDHC_HOSTCTL2, VERSION4,        12, 1); /* since v4 */
>  FIELD(SDHC_HOSTCTL2, ASYNC_INT,       14, 1);
>  FIELD(SDHC_HOSTCTL2, PRESET_ENA,      15, 1);
>
> @@ -219,12 +223,16 @@ FIELD(SDHC_CAPAB, DRIVER_TYPE_C,      37, 1); /* since v3 */
>  FIELD(SDHC_CAPAB, DRIVER_TYPE_D,      38, 1); /* since v3 */
>  FIELD(SDHC_CAPAB, TIMER_RETUNNING,    40, 4); /* since v3 */
>  FIELD(SDHC_CAPAB, SDR50_TUNNING,      45, 1); /* since v3 */
> +FIELD(SDHC_CAPAB, CLK_MUL,            48, 8); /* since v4.20 */
> +FIELD(SDHC_CAPAB, ADMA3,              59, 1); /* since v4.20 */
> +FIELD(SDHC_CAPAB, V18_VDD2,           60, 1); /* since v4.20 */
>
>  /* HWInit Maximum Current Capabilities Register 0x0 */
>  #define SDHC_MAXCURR                   0x48
>  FIELD(SDHC_MAXCURR, V33_VDD1,          0, 8);
>  FIELD(SDHC_MAXCURR, V30_VDD1,          8, 8);
>  FIELD(SDHC_MAXCURR, V18_VDD1,         16, 8);
> +FIELD(SDHC_MAXCURR, V18_VDD2,         32, 8); /* since v4.20 */
>
>  /* W Force Event Auto CMD12 Error Interrupt Register 0x0000 */
>  #define SDHC_FEAER                     0x50
> --
> 2.15.1
>
>

[Qemu-devel] [PATCH v6 18/21] sdhci: implement the Host Control 2 register for the tunning sequence
Posted by Philippe Mathieu-Daudé, 6 days ago
[based on a patch from Alistair Francis <alistair.francis@xilinx.com>
 from qemu/xilinx tag xilinx-v2015.2]
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 include/hw/sd/sdhci.h |  1 +
 hw/sd/sdhci.c         | 22 +++++++++++++++++++---
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 890dd1bbac..e66d6d6abd 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -71,6 +71,7 @@ typedef struct SDHCIState {
     uint16_t norintsigen;  /* Normal Interrupt Signal Enable Register */
     uint16_t errintsigen;  /* Error Interrupt Signal Enable Register */
     uint16_t acmd12errsts; /* Auto CMD12 error status register */
+    uint16_t hostctl2;     /* Host Control 2 */
     uint64_t admasysaddr;  /* ADMA System Address Register */
 
     /* Read-only registers */
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 8e4805c84e..834b835f3e 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -312,14 +312,29 @@ static void sdhci_end_transfer(SDHCIState *s)
 static void sdhci_read_block_from_card(SDHCIState *s)
 {
     int index = 0;
+    uint8_t data;
+    const uint16_t blk_size = s->blksize & BLOCK_SIZE_MASK;
 
     if ((s->trnmod & SDHC_TRNS_MULTI) &&
             (s->trnmod & SDHC_TRNS_BLK_CNT_EN) && (s->blkcnt == 0)) {
         return;
     }
 
-    for (index = 0; index < (s->blksize & BLOCK_SIZE_MASK); index++) {
-        s->fifo_buffer[index] = sdbus_read_data(&s->sdbus);
+    for (index = 0; index < blk_size; index++) {
+        data = sdbus_read_data(&s->sdbus);
+        if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
+            /* Device is not in tunning */
+            s->fifo_buffer[index] = data;
+        }
+    }
+
+    if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
+        /* Device is in tunning */
+        s->hostctl2 &= ~R_SDHC_HOSTCTL2_EXECUTE_TUNING_MASK;
+        s->hostctl2 |= R_SDHC_HOSTCTL2_SAMPLING_CLKSEL_MASK;
+        s->prnsts &= ~(SDHC_DAT_LINE_ACTIVE | SDHC_DOING_READ |
+                       SDHC_DATA_INHIBIT);
+        goto read_done;
     }
 
     /* New data now available for READ through Buffer Port Register */
@@ -344,6 +359,7 @@ static void sdhci_read_block_from_card(SDHCIState *s)
         }
     }
 
+read_done:
     sdhci_update_irq(s);
 }
 
@@ -909,7 +925,7 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, unsigned size)
         ret = s->norintsigen | (s->errintsigen << 16);
         break;
     case SDHC_ACMD12ERRSTS:
-        ret = s->acmd12errsts;
+        ret = s->acmd12errsts | (s->hostctl2 << 16);
         break;
     case SDHC_CAPAB:
         ret = (uint32_t)s->capareg;
-- 
2.15.1


[Qemu-devel] [PATCH v6 19/21] sdbus: add trace events
Posted by Philippe Mathieu-Daudé, 6 days ago
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/core.c       | 14 ++++++++++++--
 hw/sd/trace-events |  5 +++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/hw/sd/core.c b/hw/sd/core.c
index 295dc44ab7..498284f109 100644
--- a/hw/sd/core.c
+++ b/hw/sd/core.c
@@ -23,6 +23,12 @@
 #include "hw/qdev-core.h"
 #include "sysemu/block-backend.h"
 #include "hw/sd/sd.h"
+#include "trace.h"
+
+static inline const char *sdbus_name(SDBus *sdbus)
+{
+    return sdbus->qbus.name;
+}
 
 static SDState *get_card(SDBus *sdbus)
 {
@@ -39,6 +45,7 @@ int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
 {
     SDState *card = get_card(sdbus);
 
+    trace_sdbus_command(sdbus_name(sdbus), req->cmd, req->arg, req->crc);
     if (card) {
         SDCardClass *sc = SD_CARD_GET_CLASS(card);
 
@@ -52,6 +59,7 @@ void sdbus_write_data(SDBus *sdbus, uint8_t value)
 {
     SDState *card = get_card(sdbus);
 
+    trace_sdbus_write(sdbus_name(sdbus), value);
     if (card) {
         SDCardClass *sc = SD_CARD_GET_CLASS(card);
 
@@ -62,14 +70,16 @@ void sdbus_write_data(SDBus *sdbus, uint8_t value)
 uint8_t sdbus_read_data(SDBus *sdbus)
 {
     SDState *card = get_card(sdbus);
+    uint8_t value = 0;
 
     if (card) {
         SDCardClass *sc = SD_CARD_GET_CLASS(card);
 
-        return sc->read_data(card);
+        value = sc->read_data(card);
     }
+    trace_sdbus_read(sdbus_name(sdbus), value);
 
-    return 0;
+    return value;
 }
 
 bool sdbus_data_ready(SDBus *sdbus)
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 0a121156a3..c0f51f11d4 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -1,5 +1,10 @@
 # See docs/devel/tracing.txt for syntax documentation.
 
+# hw/sd/core.c
+sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg, uint8_t crc) "@%s CMD%02d arg 0x%08x crc 0x%02x"
+sdbus_read(const char *bus_name, uint8_t value) "@%s value 0x%02x"
+sdbus_write(const char *bus_name, uint8_t value) "@%s value 0x%02x"
+
 # hw/sd/sdhci.c
 sdhci_set_inserted(const char *level) "card state changed: %s"
 sdhci_send_command(uint8_t cmd, uint32_t arg) "CMD%02u ARG[0x%08x]"
-- 
2.15.1


Re: [Qemu-devel] [PATCH v6 19/21] sdbus: add trace events
Posted by Alistair Francis, 5 days ago
On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
<f4bug@amsat.org> wrote:
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Alistair

> ---
>  hw/sd/core.c       | 14 ++++++++++++--
>  hw/sd/trace-events |  5 +++++
>  2 files changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/hw/sd/core.c b/hw/sd/core.c
> index 295dc44ab7..498284f109 100644
> --- a/hw/sd/core.c
> +++ b/hw/sd/core.c
> @@ -23,6 +23,12 @@
>  #include "hw/qdev-core.h"
>  #include "sysemu/block-backend.h"
>  #include "hw/sd/sd.h"
> +#include "trace.h"
> +
> +static inline const char *sdbus_name(SDBus *sdbus)
> +{
> +    return sdbus->qbus.name;
> +}
>
>  static SDState *get_card(SDBus *sdbus)
>  {
> @@ -39,6 +45,7 @@ int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
>  {
>      SDState *card = get_card(sdbus);
>
> +    trace_sdbus_command(sdbus_name(sdbus), req->cmd, req->arg, req->crc);
>      if (card) {
>          SDCardClass *sc = SD_CARD_GET_CLASS(card);
>
> @@ -52,6 +59,7 @@ void sdbus_write_data(SDBus *sdbus, uint8_t value)
>  {
>      SDState *card = get_card(sdbus);
>
> +    trace_sdbus_write(sdbus_name(sdbus), value);
>      if (card) {
>          SDCardClass *sc = SD_CARD_GET_CLASS(card);
>
> @@ -62,14 +70,16 @@ void sdbus_write_data(SDBus *sdbus, uint8_t value)
>  uint8_t sdbus_read_data(SDBus *sdbus)
>  {
>      SDState *card = get_card(sdbus);
> +    uint8_t value = 0;
>
>      if (card) {
>          SDCardClass *sc = SD_CARD_GET_CLASS(card);
>
> -        return sc->read_data(card);
> +        value = sc->read_data(card);
>      }
> +    trace_sdbus_read(sdbus_name(sdbus), value);
>
> -    return 0;
> +    return value;
>  }
>
>  bool sdbus_data_ready(SDBus *sdbus)
> diff --git a/hw/sd/trace-events b/hw/sd/trace-events
> index 0a121156a3..c0f51f11d4 100644
> --- a/hw/sd/trace-events
> +++ b/hw/sd/trace-events
> @@ -1,5 +1,10 @@
>  # See docs/devel/tracing.txt for syntax documentation.
>
> +# hw/sd/core.c
> +sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg, uint8_t crc) "@%s CMD%02d arg 0x%08x crc 0x%02x"
> +sdbus_read(const char *bus_name, uint8_t value) "@%s value 0x%02x"
> +sdbus_write(const char *bus_name, uint8_t value) "@%s value 0x%02x"
> +
>  # hw/sd/sdhci.c
>  sdhci_set_inserted(const char *level) "card state changed: %s"
>  sdhci_send_command(uint8_t cmd, uint32_t arg) "CMD%02u ARG[0x%08x]"
> --
> 2.15.1
>
>

[Qemu-devel] [PATCH v6 20/21] sdhci: implement UHS-I voltage switch
Posted by Philippe Mathieu-Daudé, 6 days ago
[based on a patch from Alistair Francis <alistair.francis@xilinx.com>
 from qemu/xilinx tag xilinx-v2015.2]
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 include/hw/sd/sd.h    | 16 ++++++++++++++++
 include/hw/sd/sdhci.h |  1 +
 hw/sd/core.c          | 13 +++++++++++++
 hw/sd/sd.c            | 13 +++++++++++++
 hw/sd/sdhci.c         | 12 +++++++++++-
 hw/sd/trace-events    |  1 +
 6 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index 96caefe373..f086679493 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -55,6 +55,20 @@
 #define AKE_SEQ_ERROR		(1 << 3)
 #define OCR_CCS_BITN        30
 
+typedef enum {
+    SD_VOLTAGE_0_4V     = 400,  /* currently not supported */
+    SD_VOLTAGE_1_8V     = 1800,
+    SD_VOLTAGE_3_0V     = 3000,
+    SD_VOLTAGE_3_3V     = 3300,
+} sd_voltage_mv_t;
+
+typedef enum  {
+    UHS_NOT_SUPPORTED   = 0,
+    UHS_I               = 1,
+    UHS_II              = 2,    /* currently not supported */
+    UHS_III             = 3,    /* currently not supported */
+} sd_uhs_mode_t;
+
 typedef enum {
     sd_none = -1,
     sd_bc = 0,	/* broadcast -- no response */
@@ -88,6 +102,7 @@ typedef struct {
     void (*write_data)(SDState *sd, uint8_t value);
     uint8_t (*read_data)(SDState *sd);
     bool (*data_ready)(SDState *sd);
+    void (*set_voltage)(SDState *sd, uint16_t millivolts);
     void (*enable)(SDState *sd, bool enable);
     bool (*get_inserted)(SDState *sd);
     bool (*get_readonly)(SDState *sd);
@@ -134,6 +149,7 @@ void sd_enable(SDState *sd, bool enable);
 /* Functions to be used by qdevified callers (working via
  * an SDBus rather than directly with SDState)
  */
+void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts);
 int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response);
 void sdbus_write_data(SDBus *sd, uint8_t value);
 uint8_t sdbus_read_data(SDBus *sd);
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index e66d6d6abd..2803e78e7f 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -107,6 +107,7 @@ typedef struct SDHCIState {
         bool bus64;
         /* v3 */
         uint8_t slot_type, sdr, strength;
+        uint8_t uhs_mode;
     } cap;
 } SDHCIState;
 
diff --git a/hw/sd/core.c b/hw/sd/core.c
index 498284f109..6d198ea775 100644
--- a/hw/sd/core.c
+++ b/hw/sd/core.c
@@ -41,6 +41,19 @@ static SDState *get_card(SDBus *sdbus)
     return SD_CARD(kid->child);
 }
 
+void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts)
+{
+    SDState *card = get_card(sdbus);
+
+    trace_sdbus_set_voltage(sdbus_name(sdbus), millivolts);
+    if (card) {
+        SDCardClass *sc = SD_CARD_GET_CLASS(card);
+
+        assert(sc->set_voltage);
+        sc->set_voltage(card, millivolts);
+    }
+}
+
 int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
 {
     SDState *card = get_card(sdbus);
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 35347a5bbc..609b2da14f 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -128,6 +128,18 @@ struct SDState {
     bool enable;
 };
 
+static void sd_set_voltage(SDState *sd, uint16_t millivolts)
+{
+    switch (millivolts) {
+    case 3001 ... 3600: /* SD_VOLTAGE_3_3V */
+    case 2001 ... 3000: /* SD_VOLTAGE_3_0V */
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "SD card voltage not supported: %.3fV",
+                      millivolts / 1000.f);
+    }
+}
+
 static void sd_set_mode(SDState *sd)
 {
     switch (sd->state) {
@@ -1925,6 +1937,7 @@ static void sd_class_init(ObjectClass *klass, void *data)
     dc->reset = sd_reset;
     dc->bus_type = TYPE_SD_BUS;
 
+    sc->set_voltage = sd_set_voltage;
     sc->do_command = sd_do_command;
     sc->write_data = sd_write_data;
     sc->read_data = sd_read_data;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 834b835f3e..a4727b4577 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1159,7 +1159,16 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
         sdhci_update_irq(s);
         break;
     case SDHC_ACMD12ERRSTS:
-        MASKED_WRITE(s->acmd12errsts, mask, value);
+        MASKED_WRITE(s->acmd12errsts, mask, value & UINT16_MAX);
+        if (s->cap.uhs_mode >= UHS_I) {
+            MASKED_WRITE(s->hostctl2, mask >> 16, value >> 16);
+
+            if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, V18_ENA)) {
+                sdbus_set_voltage(&s->sdbus, SD_VOLTAGE_1_8V);
+            } else {
+                sdbus_set_voltage(&s->sdbus, SD_VOLTAGE_3_3V);
+            }
+        }
         break;
 
     case SDHC_CAPAB:
@@ -1346,6 +1355,7 @@ static Property sdhci_properties[] = {
     DEFINE_PROP_BOOL("3v3", SDHCIState, cap.v33, true),
     DEFINE_PROP_BOOL("3v0", SDHCIState, cap.v30, false),
     DEFINE_PROP_BOOL("1v8", SDHCIState, cap.v18, false),
+    DEFINE_PROP_UINT8("uhs", SDHCIState, cap.uhs_mode, UHS_NOT_SUPPORTED),
 
     DEFINE_PROP_BOOL("64bit", SDHCIState, cap.bus64, false),
     DEFINE_PROP_UINT8("slot-type", SDHCIState, cap.slot_type, 0),
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index c0f51f11d4..f874489980 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -4,6 +4,7 @@
 sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg, uint8_t crc) "@%s CMD%02d arg 0x%08x crc 0x%02x"
 sdbus_read(const char *bus_name, uint8_t value) "@%s value 0x%02x"
 sdbus_write(const char *bus_name, uint8_t value) "@%s value 0x%02x"
+sdbus_set_voltage(const char *bus_name, uint16_t millivolts) "@%s %u (mV)"
 
 # hw/sd/sdhci.c
 sdhci_set_inserted(const char *level) "card state changed: %s"
-- 
2.15.1


Re: [Qemu-devel] [PATCH v6 20/21] sdhci: implement UHS-I voltage switch
Posted by Alistair Francis, 1 day ago
On Thu, Jan 11, 2018 at 12:56 PM, Philippe Mathieu-Daudé
<f4bug@amsat.org> wrote:
> [based on a patch from Alistair Francis <alistair.francis@xilinx.com>
>  from qemu/xilinx tag xilinx-v2015.2]
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Alistair

> ---
>  include/hw/sd/sd.h    | 16 ++++++++++++++++
>  include/hw/sd/sdhci.h |  1 +
>  hw/sd/core.c          | 13 +++++++++++++
>  hw/sd/sd.c            | 13 +++++++++++++
>  hw/sd/sdhci.c         | 12 +++++++++++-
>  hw/sd/trace-events    |  1 +
>  6 files changed, 55 insertions(+), 1 deletion(-)
>
> diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
> index 96caefe373..f086679493 100644
> --- a/include/hw/sd/sd.h
> +++ b/include/hw/sd/sd.h
> @@ -55,6 +55,20 @@
>  #define AKE_SEQ_ERROR          (1 << 3)
>  #define OCR_CCS_BITN        30
>
> +typedef enum {
> +    SD_VOLTAGE_0_4V     = 400,  /* currently not supported */
> +    SD_VOLTAGE_1_8V     = 1800,
> +    SD_VOLTAGE_3_0V     = 3000,
> +    SD_VOLTAGE_3_3V     = 3300,
> +} sd_voltage_mv_t;
> +
> +typedef enum  {
> +    UHS_NOT_SUPPORTED   = 0,
> +    UHS_I               = 1,
> +    UHS_II              = 2,    /* currently not supported */
> +    UHS_III             = 3,    /* currently not supported */
> +} sd_uhs_mode_t;
> +
>  typedef enum {
>      sd_none = -1,
>      sd_bc = 0, /* broadcast -- no response */
> @@ -88,6 +102,7 @@ typedef struct {
>      void (*write_data)(SDState *sd, uint8_t value);
>      uint8_t (*read_data)(SDState *sd);
>      bool (*data_ready)(SDState *sd);
> +    void (*set_voltage)(SDState *sd, uint16_t millivolts);
>      void (*enable)(SDState *sd, bool enable);
>      bool (*get_inserted)(SDState *sd);
>      bool (*get_readonly)(SDState *sd);
> @@ -134,6 +149,7 @@ void sd_enable(SDState *sd, bool enable);
>  /* Functions to be used by qdevified callers (working via
>   * an SDBus rather than directly with SDState)
>   */
> +void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts);
>  int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response);
>  void sdbus_write_data(SDBus *sd, uint8_t value);
>  uint8_t sdbus_read_data(SDBus *sd);
> diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
> index e66d6d6abd..2803e78e7f 100644
> --- a/include/hw/sd/sdhci.h
> +++ b/include/hw/sd/sdhci.h
> @@ -107,6 +107,7 @@ typedef struct SDHCIState {
>          bool bus64;
>          /* v3 */
>          uint8_t slot_type, sdr, strength;
> +        uint8_t uhs_mode;
>      } cap;
>  } SDHCIState;
>
> diff --git a/hw/sd/core.c b/hw/sd/core.c
> index 498284f109..6d198ea775 100644
> --- a/hw/sd/core.c
> +++ b/hw/sd/core.c
> @@ -41,6 +41,19 @@ static SDState *get_card(SDBus *sdbus)
>      return SD_CARD(kid->child);
>  }
>
> +void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts)
> +{
> +    SDState *card = get_card(sdbus);
> +
> +    trace_sdbus_set_voltage(sdbus_name(sdbus), millivolts);
> +    if (card) {
> +        SDCardClass *sc = SD_CARD_GET_CLASS(card);
> +
> +        assert(sc->set_voltage);
> +        sc->set_voltage(card, millivolts);
> +    }
> +}
> +
>  int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
>  {
>      SDState *card = get_card(sdbus);
> diff --git a/hw/sd/sd.c b/hw/sd/sd.c
> index 35347a5bbc..609b2da14f 100644
> --- a/hw/sd/sd.c
> +++ b/hw/sd/sd.c
> @@ -128,6 +128,18 @@ struct SDState {
>      bool enable;
>  };
>
> +static void sd_set_voltage(SDState *sd, uint16_t millivolts)
> +{
> +    switch (millivolts) {
> +    case 3001 ... 3600: /* SD_VOLTAGE_3_3V */
> +    case 2001 ... 3000: /* SD_VOLTAGE_3_0V */
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "SD card voltage not supported: %.3fV",
> +                      millivolts / 1000.f);
> +    }
> +}
> +
>  static void sd_set_mode(SDState *sd)
>  {
>      switch (sd->state) {
> @@ -1925,6 +1937,7 @@ static void sd_class_init(ObjectClass *klass, void *data)
>      dc->reset = sd_reset;
>      dc->bus_type = TYPE_SD_BUS;
>
> +    sc->set_voltage = sd_set_voltage;
>      sc->do_command = sd_do_command;
>      sc->write_data = sd_write_data;
>      sc->read_data = sd_read_data;
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index 834b835f3e..a4727b4577 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -1159,7 +1159,16 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
>          sdhci_update_irq(s);
>          break;
>      case SDHC_ACMD12ERRSTS:
> -        MASKED_WRITE(s->acmd12errsts, mask, value);
> +        MASKED_WRITE(s->acmd12errsts, mask, value & UINT16_MAX);
> +        if (s->cap.uhs_mode >= UHS_I) {
> +            MASKED_WRITE(s->hostctl2, mask >> 16, value >> 16);
> +
> +            if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, V18_ENA)) {
> +                sdbus_set_voltage(&s->sdbus, SD_VOLTAGE_1_8V);
> +            } else {
> +                sdbus_set_voltage(&s->sdbus, SD_VOLTAGE_3_3V);
> +            }
> +        }
>          break;
>
>      case SDHC_CAPAB:
> @@ -1346,6 +1355,7 @@ static Property sdhci_properties[] = {
>      DEFINE_PROP_BOOL("3v3", SDHCIState, cap.v33, true),
>      DEFINE_PROP_BOOL("3v0", SDHCIState, cap.v30, false),
>      DEFINE_PROP_BOOL("1v8", SDHCIState, cap.v18, false),
> +    DEFINE_PROP_UINT8("uhs", SDHCIState, cap.uhs_mode, UHS_NOT_SUPPORTED),
>
>      DEFINE_PROP_BOOL("64bit", SDHCIState, cap.bus64, false),
>      DEFINE_PROP_UINT8("slot-type", SDHCIState, cap.slot_type, 0),
> diff --git a/hw/sd/trace-events b/hw/sd/trace-events
> index c0f51f11d4..f874489980 100644
> --- a/hw/sd/trace-events
> +++ b/hw/sd/trace-events
> @@ -4,6 +4,7 @@
>  sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg, uint8_t crc) "@%s CMD%02d arg 0x%08x crc 0x%02x"
>  sdbus_read(const char *bus_name, uint8_t value) "@%s value 0x%02x"
>  sdbus_write(const char *bus_name, uint8_t value) "@%s value 0x%02x"
> +sdbus_set_voltage(const char *bus_name, uint16_t millivolts) "@%s %u (mV)"
>
>  # hw/sd/sdhci.c
>  sdhci_set_inserted(const char *level) "card state changed: %s"
> --
> 2.15.1
>
>

[Qemu-devel] [PATCH v6 21/21] sdhci: implement CMD/DAT[] fields in the Present State register
Posted by Philippe Mathieu-Daudé, 6 days ago
[based on a patch from Alistair Francis <alistair.francis@xilinx.com>
 from qemu/xilinx tag xilinx-v2015.2]
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 hw/sd/sdhci-internal.h |  2 ++
 include/hw/sd/sd.h     |  4 ++++
 hw/sd/core.c           | 34 ++++++++++++++++++++++++++++++++++
 hw/sd/sd.c             | 16 ++++++++++++++++
 hw/sd/sdhci.c          |  4 ++++
 hw/sd/trace-events     |  2 ++
 6 files changed, 62 insertions(+)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index b82e847636..8bcca39310 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -82,6 +82,8 @@
 #define SDHC_CARD_PRESENT              0x00010000
 #define SDHC_CARD_DETECT               0x00040000
 #define SDHC_WRITE_PROTECT             0x00080000
+FIELD(SDHC_PRNSTS, DAT_LVL,            20, 4);
+FIELD(SDHC_PRNSTS, CMD_LVL,            24, 1);
 #define TRANSFERRING_DATA(x)           \
     ((x) & (SDHC_DOING_READ | SDHC_DOING_WRITE))
 
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index f086679493..bf1eb0713c 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -103,6 +103,8 @@ typedef struct {
     uint8_t (*read_data)(SDState *sd);
     bool (*data_ready)(SDState *sd);
     void (*set_voltage)(SDState *sd, uint16_t millivolts);
+    uint8_t (*get_dat_lines)(SDState *sd);
+    bool (*get_cmd_line)(SDState *sd);
     void (*enable)(SDState *sd, bool enable);
     bool (*get_inserted)(SDState *sd);
     bool (*get_readonly)(SDState *sd);
@@ -150,6 +152,8 @@ void sd_enable(SDState *sd, bool enable);
  * an SDBus rather than directly with SDState)
  */
 void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts);
+uint8_t sdbus_get_dat_lines(SDBus *sdbus);
+bool sdbus_get_cmd_line(SDBus *sdbus);
 int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response);
 void sdbus_write_data(SDBus *sd, uint8_t value);
 uint8_t sdbus_read_data(SDBus *sd);
diff --git a/hw/sd/core.c b/hw/sd/core.c
index 6d198ea775..3c6eae6c88 100644
--- a/hw/sd/core.c
+++ b/hw/sd/core.c
@@ -41,6 +41,40 @@ static SDState *get_card(SDBus *sdbus)
     return SD_CARD(kid->child);
 }
 
+uint8_t sdbus_get_dat_lines(SDBus *sdbus)
+{
+    SDState *slave = get_card(sdbus);
+    uint8_t dat_lines = 0b1111; /* 4 bit bus width */
+
+    if (slave) {
+        SDCardClass *sc = SD_CARD_GET_CLASS(slave);
+
+        if (sc->get_dat_lines) {
+            dat_lines = sc->get_dat_lines(slave);
+        }
+    }
+    trace_sdbus_get_dat_lines(sdbus_name(sdbus), dat_lines);
+
+    return dat_lines;
+}
+
+bool sdbus_get_cmd_line(SDBus *sdbus)
+{
+    SDState *slave = get_card(sdbus);
+    bool cmd_line = true;
+
+    if (slave) {
+        SDCardClass *sc = SD_CARD_GET_CLASS(slave);
+
+        if (sc->get_cmd_line) {
+            cmd_line = sc->get_cmd_line(slave);
+        }
+    }
+    trace_sdbus_get_cmd_line(sdbus_name(sdbus), cmd_line);
+
+    return cmd_line;
+}
+
 void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts)
 {
     SDState *card = get_card(sdbus);
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 609b2da14f..ab9be561d2 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -126,8 +126,20 @@ struct SDState {
     BlockBackend *blk;
 
     bool enable;
+    uint8_t dat_lines;
+    bool cmd_line;
 };
 
+static uint8_t sd_get_dat_lines(SDState *sd)
+{
+    return sd->enable ? sd->dat_lines : 0;
+}
+
+static bool sd_get_cmd_line(SDState *sd)
+{
+    return sd->enable ? sd->cmd_line : false;
+}
+
 static void sd_set_voltage(SDState *sd, uint16_t millivolts)
 {
     switch (millivolts) {
@@ -457,6 +469,8 @@ static void sd_reset(DeviceState *dev)
     sd->blk_len = 0x200;
     sd->pwd_len = 0;
     sd->expecting_acmd = false;
+    sd->dat_lines = 0xf;
+    sd->cmd_line = true;
     sd->multi_blk_cnt = 0;
 }
 
@@ -1938,6 +1952,8 @@ static void sd_class_init(ObjectClass *klass, void *data)
     dc->bus_type = TYPE_SD_BUS;
 
     sc->set_voltage = sd_set_voltage;
+    sc->get_dat_lines = sd_get_dat_lines;
+    sc->get_cmd_line = sd_get_cmd_line;
     sc->do_command = sd_do_command;
     sc->write_data = sd_write_data;
     sc->read_data = sd_read_data;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index a4727b4577..1f834e8a3d 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -907,6 +907,10 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, unsigned size)
         break;
     case SDHC_PRNSTS:
         ret = s->prnsts;
+        ret = FIELD_DP32(ret, SDHC_PRNSTS, DAT_LVL,
+                         sdbus_get_dat_lines(&s->sdbus));
+        ret = FIELD_DP32(ret, SDHC_PRNSTS, CMD_LVL,
+                         sdbus_get_cmd_line(&s->sdbus));
         break;
     case SDHC_HOSTCTL:
         ret = s->hostctl1 | (s->pwrcon << 8) | (s->blkgap << 16) |
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index f874489980..82efd79bea 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -5,6 +5,8 @@ sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg, uint8_t crc) "@%s
 sdbus_read(const char *bus_name, uint8_t value) "@%s value 0x%02x"
 sdbus_write(const char *bus_name, uint8_t value) "@%s value 0x%02x"
 sdbus_set_voltage(const char *bus_name, uint16_t millivolts) "@%s %u (mV)"
+sdbus_get_dat_lines(const char *bus_name, uint8_t dat_lines) "@%s dat_lines: %u"
+sdbus_get_cmd_line(const char *bus_name, bool cmd_line) "@%s cmd_line: %u"
 
 # hw/sd/sdhci.c
 sdhci_set_inserted(const char *level) "card state changed: %s"
-- 
2.15.1