[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [PATCH v6 20/21] sdhci: implement UHS-I voltage switch
From: |
Philippe Mathieu-Daudé |
Subject: |
[Qemu-arm] [PATCH v6 20/21] sdhci: implement UHS-I voltage switch |
Date: |
Thu, 11 Jan 2018 17:56:25 -0300 |
[based on a patch from Alistair Francis <address@hidden>
from qemu/xilinx tag xilinx-v2015.2]
Signed-off-by: Philippe Mathieu-Daudé <address@hidden>
---
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-arm] [PATCH v6 13/21] hw/arm/bcm2835_peripherals: change maximum block size to 1kB, (continued)
- [Qemu-arm] [PATCH v6 13/21] hw/arm/bcm2835_peripherals: change maximum block size to 1kB, Philippe Mathieu-Daudé, 2018/01/11
- [Qemu-arm] [PATCH v6 14/21] hw/arm/fsl-imx6: implement SDHCI Spec v3, Philippe Mathieu-Daudé, 2018/01/11
- [Qemu-arm] [PATCH v6 15/21] hw/arm/xilinx_zynqmp: implement SDHCI Spec v3, Philippe Mathieu-Daudé, 2018/01/11
- [Qemu-arm] [PATCH v6 16/21] sdhci: remove the deprecated 'capareg' property, Philippe Mathieu-Daudé, 2018/01/11
- [Qemu-arm] [PATCH v6 17/21] sdhci: add Spec v4.2 register definitions, Philippe Mathieu-Daudé, 2018/01/11
- [Qemu-arm] [PATCH v6 18/21] sdhci: implement the Host Control 2 register for the tunning sequence, Philippe Mathieu-Daudé, 2018/01/11
- [Qemu-arm] [PATCH v6 19/21] sdbus: add trace events, Philippe Mathieu-Daudé, 2018/01/11
- [Qemu-arm] [PATCH v6 20/21] sdhci: implement UHS-I voltage switch,
Philippe Mathieu-Daudé <=
- [Qemu-arm] [PATCH v6 21/21] sdhci: implement CMD/DAT[] fields in the Present State register, Philippe Mathieu-Daudé, 2018/01/11