Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 May 2017 20:46:27 +0000 (UTC)
From:      Marius Strobl <marius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r318495 - in stable/10/sys/dev: mmc sdhci
Message-ID:  <201705182046.v4IKkRrZ021500@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marius
Date: Thu May 18 20:46:27 2017
New Revision: 318495
URL: https://svnweb.freebsd.org/changeset/base/318495

Log:
  MFC: r315598
  
  o Add support for eMMC DDR bus speed mode up to 52 MHz to sdhci(4)
    and mmc(4). Given that support for DDR52 is not denoted by SDHCI
    capability registers, availability of that timing is indicated by
    a new quirk SDHCI_QUIRK_MMC_DDR52 and only enabled for Intel SDHCI
    controllers so far.
  
    Compared to 50 MHz at SDR high speed typically yielding ~45 MB/s
    read throughput with the eMMC chips tested, read performance goes
    up to ~80 MB/s at DDR52.
  
    As a side-effect, this change also fixes communication with some
    eMMC devices at SDR high speed mode due to the signaling voltage
    and UHS bits in the SDHCI controller no longer being left in an
    inappropriate state.
  
  o In sdhci(4), add two tunables hw.sdhci.quirk_clear as well as
    hw.sdhci.quirk_set, which (when hooked up in the front-end)
    allow to set/clear sdhci(4) quirks for debugging and testing
    purposes. However, especially for SDHCI controllers on the
    PCI bus which have no specific support code so far and, thus,
    are picked up as generic SDHCI controllers, hw.sdhci.quirk_set
    allows for setting the necessary quirks (if required).
  
  o In mmc(4), check and handle the return values of some more
    function calls instead of assuming that everything went right.
    In case failures actually are not problematic, indicate that
    by casting the return value to void.

Modified:
  stable/10/sys/dev/mmc/bridge.h
  stable/10/sys/dev/mmc/mmc.c
  stable/10/sys/dev/mmc/mmcbr_if.m
  stable/10/sys/dev/mmc/mmcbrvar.h
  stable/10/sys/dev/mmc/mmcreg.h
  stable/10/sys/dev/sdhci/sdhci.c
  stable/10/sys/dev/sdhci/sdhci.h
  stable/10/sys/dev/sdhci/sdhci_acpi.c
  stable/10/sys/dev/sdhci/sdhci_if.m
  stable/10/sys/dev/sdhci/sdhci_pci.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/mmc/bridge.h
==============================================================================
--- stable/10/sys/dev/mmc/bridge.h	Thu May 18 20:46:20 2017	(r318494)
+++ stable/10/sys/dev/mmc/bridge.h	Thu May 18 20:46:27 2017	(r318495)
@@ -89,6 +89,10 @@ enum mmc_vdd {
 	vdd_330, vdd_340, vdd_350, vdd_360
 };
 
+enum mmc_vccq {
+	vccq_120 = 0, vccq_180, vccq_330
+};
+
 enum mmc_power_mode {
 	power_off = 0, power_up, power_on
 };
@@ -105,18 +109,28 @@ enum mmc_bus_width {
 	bus_width_1 = 0, bus_width_4 = 2, bus_width_8 = 3
 };
 
+enum mmc_drv_type {
+	drv_type_b = 0, drv_type_a, drv_type_c, drv_type_d
+};
+
 enum mmc_bus_timing {
-	bus_timing_normal = 0, bus_timing_hs
+	bus_timing_normal = 0, bus_timing_hs, bus_timing_uhs_sdr12,
+	bus_timing_uhs_sdr25, bus_timing_uhs_sdr50, bus_timing_uhs_ddr50,
+	bus_timing_uhs_sdr104, bus_timing_mmc_ddr52, bus_timing_mmc_hs200,
+	bus_timing_mmc_hs400, bus_timing_mmc_hs400es, bus_timing_max =
+	bus_timing_mmc_hs400es
 };
 
 struct mmc_ios {
 	uint32_t	clock;	/* Speed of the clock in Hz to move data */
 	enum mmc_vdd	vdd;	/* Voltage to apply to the power pins */
+	enum mmc_vccq	vccq;	/* Voltage to use for signaling */
 	enum mmc_bus_mode bus_mode;
 	enum mmc_chip_select chip_select;
 	enum mmc_bus_width bus_width;
 	enum mmc_power_mode power_mode;
 	enum mmc_bus_timing timing;
+	enum mmc_drv_type drv_type;
 };
 
 enum mmc_card_mode {
@@ -134,6 +148,28 @@ struct mmc_host {
 #define	MMC_CAP_HSPEED		(1 <<  2) /* Can do High Speed transfers */
 #define	MMC_CAP_BOOT_NOACC	(1 <<  4) /* Cannot access boot partitions */
 #define	MMC_CAP_WAIT_WHILE_BUSY	(1 <<  5) /* Host waits for busy responses */
+#define	MMC_CAP_UHS_SDR12	(1 <<  6) /* Can do UHS SDR12 */
+#define	MMC_CAP_UHS_SDR25	(1 <<  7) /* Can do UHS SDR25 */
+#define	MMC_CAP_UHS_SDR50	(1 <<  8) /* Can do UHS SDR50 */
+#define	MMC_CAP_UHS_SDR104	(1 <<  9) /* Can do UHS SDR104 */
+#define	MMC_CAP_UHS_DDR50	(1 << 10) /* Can do UHS DDR50 */
+#define	MMC_CAP_MMC_DDR52_120	(1 << 11) /* Can do eMMC DDR52 at 1.2 V */
+#define	MMC_CAP_MMC_DDR52_180	(1 << 12) /* Can do eMMC DDR52 at 1.8 V */
+#define	MMC_CAP_MMC_DDR52	(MMC_CAP_MMC_DDR52_120 | MMC_CAP_MMC_DDR52_180)
+#define	MMC_CAP_MMC_HS200_120	(1 << 13) /* Can do eMMC HS200 at 1.2 V */
+#define	MMC_CAP_MMC_HS200_180	(1 << 14) /* Can do eMMC HS200 at 1.8 V */
+#define	MMC_CAP_MMC_HS200	(MMC_CAP_MMC_HS200_120| MMC_CAP_MMC_HS200_180)
+#define	MMC_CAP_MMC_HS400_120	(1 << 15) /* Can do eMMC HS400 at 1.2 V */
+#define	MMC_CAP_MMC_HS400_180	(1 << 16) /* Can do eMMC HS400 at 1.8 V */
+#define	MMC_CAP_MMC_HS400	(MMC_CAP_MMC_HS400_120 | MMC_CAP_MMC_HS400_180)
+#define	MMC_CAP_MMC_HSX00_120	(MMC_CAP_MMC_HS200_120 | MMC_CAP_MMC_HS400_120)
+#define	MMC_CAP_MMC_ENH_STROBE	(1 << 17) /* Can do eMMC Enhanced Strobe */
+#define	MMC_CAP_SIGNALING_120	(1 << 18) /* Can do signaling at 1.2 V */
+#define	MMC_CAP_SIGNALING_180	(1 << 19) /* Can do signaling at 1.8 V */
+#define	MMC_CAP_SIGNALING_330	(1 << 20) /* Can do signaling at 3.3 V */
+#define	MMC_CAP_DRIVER_TYPE_A	(1 << 21) /* Can do Driver Type A */
+#define	MMC_CAP_DRIVER_TYPE_C	(1 << 22) /* Can do Driver Type C */
+#define	MMC_CAP_DRIVER_TYPE_D	(1 << 23) /* Can do Driver Type D */
 	enum mmc_card_mode mode;
 	struct mmc_ios ios;	/* Current state of the host */
 };
@@ -141,7 +177,7 @@ struct mmc_host {
 extern driver_t   mmc_driver;
 extern devclass_t mmc_devclass;
 
-#define	MMC_VERSION	2
+#define	MMC_VERSION	3
 
 #define	MMC_DECLARE_BRIDGE(name)					\
     DRIVER_MODULE(mmc, name, mmc_driver, mmc_devclass, NULL, NULL);	\

Modified: stable/10/sys/dev/mmc/mmc.c
==============================================================================
--- stable/10/sys/dev/mmc/mmc.c	Thu May 18 20:46:20 2017	(r318494)
+++ stable/10/sys/dev/mmc/mmc.c	Thu May 18 20:46:27 2017	(r318495)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2006 Bernd Walter.  All rights reserved.
  * Copyright (c) 2006 M. Warner Losh.  All rights reserved.
+ * Copyright (c) 2017 Marius Strobl <marius@FreeBSD.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -75,6 +76,8 @@ __FBSDID("$FreeBSD$");
 #include "mmcbr_if.h"
 #include "mmcbus_if.h"
 
+CTASSERT(bus_timing_max <= sizeof(uint32_t) * NBBY);
+
 /*
  * Per-card data
  */
@@ -92,9 +95,11 @@ struct mmc_ivars {
 	struct mmc_sd_status sd_status;	/* SD_STATUS decoded */
 	u_char read_only;	/* True when the device is read-only */
 	u_char bus_width;	/* Bus width to use */
-	u_char timing;		/* Bus timing support */
 	u_char high_cap;	/* High Capacity card (block addressed) */
 	uint32_t sec_count;	/* Card capacity in 512byte blocks */
+	uint32_t timings;	/* Mask of bus timings supported */
+	uint32_t vccq_120;	/* Mask of bus timings at VCCQ of 1.2 V */
+	uint32_t vccq_180;	/* Mask of bus timings at VCCQ of 1.8 V */
 	uint32_t tran_speed;	/* Max speed in normal mode */
 	uint32_t hs_tran_speed;	/* Max speed in high speed mode */
 	uint32_t erase_sector;	/* Card native erase sector size */
@@ -105,8 +110,6 @@ struct mmc_ivars {
 
 #define	CMD_RETRIES	3
 
-#define	CARD_ID_FREQUENCY 400000 /* Spec requires 400kHz max during ID phase. */
-
 static SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver");
 
 static int mmc_debug;
@@ -181,12 +184,15 @@ static int mmc_send_op_cond(struct mmc_s
     uint32_t *rocr);
 static int mmc_send_relative_addr(struct mmc_softc *sc, uint32_t *resp);
 static int mmc_set_blocklen(struct mmc_softc *sc, uint32_t len);
-static int mmc_set_card_bus_width(struct mmc_softc *sc,
-    struct mmc_ivars *ivar);
+static int mmc_set_card_bus_width(struct mmc_softc *sc, struct mmc_ivars *ivar);
+static int mmc_set_power_class(struct mmc_softc *sc, struct mmc_ivars *ivar);
 static int mmc_set_relative_addr(struct mmc_softc *sc, uint16_t resp);
 static int mmc_set_timing(struct mmc_softc *sc, struct mmc_ivars *ivar,
-    int timing);
+    enum mmc_bus_timing timing);
 static int mmc_test_bus_width(struct mmc_softc *sc);
+static uint32_t mmc_timing_to_dtr(struct mmc_ivars *ivar,
+    enum mmc_bus_timing timing);
+static const char *mmc_timing_to_string(enum mmc_bus_timing timing);
 static int mmc_wait_for_command(struct mmc_softc *sc, uint32_t opcode,
     uint32_t arg, uint32_t flags, uint32_t *resp, int retries);
 static int mmc_wait_for_req(struct mmc_softc *sc, struct mmc_request *req);
@@ -265,8 +271,8 @@ mmc_acquire_bus(device_t busdev, device_
 {
 	struct mmc_softc *sc;
 	struct mmc_ivars *ivar;
-	int err;
-	int rca;
+	int err, rca;
+	enum mmc_bus_timing timing;
 
 	err = MMCBR_ACQUIRE_HOST(device_get_parent(busdev), busdev);
 	if (err)
@@ -288,16 +294,44 @@ mmc_acquire_bus(device_t busdev, device_
 		ivar = device_get_ivars(dev);
 		rca = ivar->rca;
 		if (sc->last_rca != rca) {
-			mmc_select_card(sc, rca);
+			if (mmc_select_card(sc, rca) != MMC_ERR_NONE) {
+				device_printf(sc->dev, "Card at relative "
+				    "address %d failed to select.\n", rca);
+				return (ENXIO);
+			}
 			sc->last_rca = rca;
+			timing = mmcbr_get_timing(busdev);
 			/* Prepare bus width for the new card. */
 			if (bootverbose || mmc_debug) {
 				device_printf(busdev,
-				    "setting bus width to %d bits\n",
+				    "setting bus width to %d bits %s timing\n",
 				    (ivar->bus_width == bus_width_4) ? 4 :
-				    (ivar->bus_width == bus_width_8) ? 8 : 1);
+				    (ivar->bus_width == bus_width_8) ? 8 : 1,
+				    mmc_timing_to_string(timing));
+			}
+			if (mmc_set_card_bus_width(sc, ivar) != MMC_ERR_NONE) {
+				device_printf(sc->dev, "Card at relative "
+				    "address %d failed to set bus width.\n",
+				    rca);
+				return (ENXIO);
+			}
+			if (isset(&ivar->vccq_120, timing))
+				mmcbr_set_vccq(busdev, vccq_120);
+			else if (isset(&ivar->vccq_180, timing))
+				mmcbr_set_vccq(busdev, vccq_180);
+			else
+				mmcbr_set_vccq(busdev, vccq_330);
+			if (mmcbr_switch_vccq(busdev) != 0) {
+				device_printf(sc->dev, "Failed to set VCCQ "
+				    "for card at relative address %d.\n", rca);
+				return (ENXIO);
+			}
+			if (mmc_set_power_class(sc, ivar) != MMC_ERR_NONE) {
+				device_printf(sc->dev, "Card at relative "
+				    "address %d failed to set power class.\n",
+				    rca);
+				return (ENXIO);
 			}
-			mmc_set_card_bus_width(sc, ivar);
 			mmcbr_set_bus_width(busdev, ivar->bus_width);
 			mmcbr_update_ios(busdev);
 		}
@@ -525,6 +559,7 @@ static void
 mmc_power_up(struct mmc_softc *sc)
 {
 	device_t dev;
+	enum mmc_vccq vccq;
 
 	dev = sc->dev;
 	mmcbr_set_vdd(dev, mmc_highest_voltage(mmcbr_get_host_ocr(dev)));
@@ -534,9 +569,14 @@ mmc_power_up(struct mmc_softc *sc)
 	mmcbr_set_power_mode(dev, power_up);
 	mmcbr_set_clock(dev, 0);
 	mmcbr_update_ios(dev);
+	for (vccq = vccq_330; ; vccq--) {
+		mmcbr_set_vccq(dev, vccq);
+		if (mmcbr_switch_vccq(dev) == 0 || vccq == vccq_120)
+			break;
+	}
 	mmc_ms_delay(1);
 
-	mmcbr_set_clock(dev, CARD_ID_FREQUENCY);
+	mmcbr_set_clock(dev, SD_MMC_CARD_ID_FREQUENCY);
 	mmcbr_set_timing(dev, bus_timing_normal);
 	mmcbr_set_power_mode(dev, power_on);
 	mmcbr_update_ios(dev);
@@ -632,10 +672,30 @@ mmc_set_card_bus_width(struct mmc_softc 
 			value = EXT_CSD_BUS_WIDTH_1;
 			break;
 		case bus_width_4:
-			value = EXT_CSD_BUS_WIDTH_4;
+			switch (mmcbr_get_timing(sc->dev)) {
+			case bus_timing_mmc_ddr52:
+			case bus_timing_mmc_hs200:
+			case bus_timing_mmc_hs400:
+			case bus_timing_mmc_hs400es:
+				value = EXT_CSD_BUS_WIDTH_4_DDR;
+				break;
+			default:
+				value = EXT_CSD_BUS_WIDTH_4;
+				break;
+			}
 			break;
 		case bus_width_8:
-			value = EXT_CSD_BUS_WIDTH_8;
+			switch (mmcbr_get_timing(sc->dev)) {
+			case bus_timing_mmc_ddr52:
+			case bus_timing_mmc_hs200:
+			case bus_timing_mmc_hs400:
+			case bus_timing_mmc_hs400es:
+				value = EXT_CSD_BUS_WIDTH_8_DDR;
+				break;
+			default:
+				value = EXT_CSD_BUS_WIDTH_8;
+				break;
+			}
 			break;
 		default:
 			return (MMC_ERR_INVALID);
@@ -648,23 +708,96 @@ mmc_set_card_bus_width(struct mmc_softc 
 }
 
 static int
-mmc_set_timing(struct mmc_softc *sc, struct mmc_ivars *ivar, int timing)
+mmc_set_power_class(struct mmc_softc *sc, struct mmc_ivars *ivar)
 {
-	u_char switch_res[64];
-	uint8_t	value;
-	int err;
+	device_t dev;
+	const uint8_t *ext_csd;
+	uint32_t clock;
+	uint8_t value;
 
-	switch (timing) {
-	case bus_timing_normal:
-		value = 0;
+	dev = sc->dev;
+	if (mmcbr_get_mode(dev) != mode_mmc || ivar->csd.spec_vers < 4)
+		return (MMC_ERR_NONE);
+
+	value = 0;
+	ext_csd = ivar->raw_ext_csd;
+	clock = mmcbr_get_clock(dev);
+	switch (1 << mmcbr_get_vdd(dev)) {
+	case MMC_OCR_LOW_VOLTAGE:
+		if (clock <= MMC_TYPE_HS_26_MAX)
+			value = ext_csd[EXT_CSD_PWR_CL_26_195];
+		else if (clock <= MMC_TYPE_HS_52_MAX) {
+			if (mmcbr_get_timing(dev) >= bus_timing_mmc_ddr52 &&
+			    ivar->bus_width >= bus_width_4)
+				value = ext_csd[EXT_CSD_PWR_CL_52_195_DDR];
+			else
+				value = ext_csd[EXT_CSD_PWR_CL_52_195];
+		} else if (clock <= MMC_TYPE_HS200_HS400ES_MAX)
+			value = ext_csd[EXT_CSD_PWR_CL_200_195];
 		break;
-	case bus_timing_hs:
-		value = 1;
+	case MMC_OCR_270_280:
+	case MMC_OCR_280_290:
+	case MMC_OCR_290_300:
+	case MMC_OCR_300_310:
+	case MMC_OCR_310_320:
+	case MMC_OCR_320_330:
+	case MMC_OCR_330_340:
+	case MMC_OCR_340_350:
+	case MMC_OCR_350_360:
+		if (clock <= MMC_TYPE_HS_26_MAX)
+			value = ext_csd[EXT_CSD_PWR_CL_26_360];
+		else if (clock <= MMC_TYPE_HS_52_MAX) {
+			if (mmcbr_get_timing(dev) == bus_timing_mmc_ddr52 &&
+			    ivar->bus_width >= bus_width_4)
+				value = ext_csd[EXT_CSD_PWR_CL_52_360_DDR];
+			else
+				value = ext_csd[EXT_CSD_PWR_CL_52_360];
+		} else if (clock <= MMC_TYPE_HS200_HS400ES_MAX) {
+			if (ivar->bus_width == bus_width_8)
+				value = ext_csd[EXT_CSD_PWR_CL_200_360_DDR];
+			else
+				value = ext_csd[EXT_CSD_PWR_CL_200_360];
+		}
 		break;
 	default:
+		device_printf(dev, "No power class support for VDD 0x%x\n",
+			1 << mmcbr_get_vdd(dev));
 		return (MMC_ERR_INVALID);
 	}
+
+	if (ivar->bus_width == bus_width_8)
+		value = (value & EXT_CSD_POWER_CLASS_8BIT_MASK) >>
+		    EXT_CSD_POWER_CLASS_8BIT_SHIFT;
+	else
+		value = (value & EXT_CSD_POWER_CLASS_4BIT_MASK) >>
+		    EXT_CSD_POWER_CLASS_4BIT_SHIFT;
+
+	if (value == 0)
+		return (MMC_ERR_NONE);
+
+	return (mmc_switch(dev, dev, ivar->rca, EXT_CSD_CMD_SET_NORMAL,
+	    EXT_CSD_POWER_CLASS, value, ivar->cmd6_time, true));
+}
+
+static int
+mmc_set_timing(struct mmc_softc *sc, struct mmc_ivars *ivar,
+    enum mmc_bus_timing timing)
+{
+	u_char switch_res[64];
+	uint8_t	value;
+	int err;
+
 	if (mmcbr_get_mode(sc->dev) == mode_sd) {
+		switch (timing) {
+		case bus_timing_normal:
+			value = SD_SWITCH_NORMAL_MODE;
+			break;
+		case bus_timing_hs:
+			value = SD_SWITCH_HS_MODE;
+			break;
+		default:
+			return (MMC_ERR_INVALID);
+		}
 		err = mmc_sd_switch(sc, SD_SWITCH_MODE_SET, SD_SWITCH_GROUP1,
 		    value, switch_res);
 		if (err != MMC_ERR_NONE)
@@ -674,6 +807,17 @@ mmc_set_timing(struct mmc_softc *sc, str
 		mmcbr_set_timing(sc->dev, timing);
 		mmcbr_update_ios(sc->dev);
 	} else {
+		switch (timing) {
+		case bus_timing_normal:
+			value = EXT_CSD_HS_TIMING_BC;
+			break;
+		case bus_timing_hs:
+		case bus_timing_mmc_ddr52:
+			value = EXT_CSD_HS_TIMING_HS;
+			break;
+		default:
+			return (MMC_ERR_INVALID);
+		}
 		err = mmc_switch(sc->dev, sc->dev, ivar->rca,
 		    EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, value,
 		    ivar->cmd6_time, false);
@@ -1167,19 +1311,82 @@ mmc_set_blocklen(struct mmc_softc *sc, u
 	return (err);
 }
 
+static uint32_t
+mmc_timing_to_dtr(struct mmc_ivars *ivar, enum mmc_bus_timing timing)
+{
+
+	switch (timing) {
+	case bus_timing_normal:
+		return (ivar->tran_speed);
+	case bus_timing_hs:
+		return (ivar->hs_tran_speed);
+	case bus_timing_uhs_sdr12:
+		return (SD_SDR12_MAX);
+	case bus_timing_uhs_sdr25:
+		return (SD_SDR25_MAX);
+	case bus_timing_uhs_ddr50:
+		return (SD_DDR50_MAX);
+	case bus_timing_uhs_sdr50:
+		return (SD_SDR50_MAX);
+	case bus_timing_uhs_sdr104:
+		return (SD_SDR104_MAX);
+	case bus_timing_mmc_ddr52:
+		return (MMC_TYPE_DDR52_MAX);
+	case bus_timing_mmc_hs200:
+	case bus_timing_mmc_hs400:
+	case bus_timing_mmc_hs400es:
+		return (MMC_TYPE_HS200_HS400ES_MAX);
+	}
+	return (0);
+}
+
+static const char *
+mmc_timing_to_string(enum mmc_bus_timing timing)
+{
+
+	switch (timing) {
+	case bus_timing_normal:
+		return ("normal speed");
+	case bus_timing_hs:
+		return ("high speed");
+	case bus_timing_uhs_sdr12:
+	case bus_timing_uhs_sdr25:
+	case bus_timing_uhs_sdr50:
+	case bus_timing_uhs_sdr104:
+		return ("single data rate");
+	case bus_timing_uhs_ddr50:
+	case bus_timing_mmc_ddr52:
+		return ("dual data rate");
+	case bus_timing_mmc_hs200:
+		return ("HS200");
+	case bus_timing_mmc_hs400:
+		return ("HS400");
+	case bus_timing_mmc_hs400es:
+		return ("HS400 with enhanced strobe");
+	}
+	return ("");
+}
+
 static void
 mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard)
 {
+	enum mmc_bus_timing max_timing, timing;
 
 	device_printf(dev, "Card at relative address 0x%04x%s:\n",
 	    ivar->rca, newcard ? " added" : "");
 	device_printf(dev, " card: %s\n", ivar->card_id_string);
-	device_printf(dev, " bus: %ubit, %uMHz%s\n",
+	max_timing = bus_timing_normal;
+	for (timing = bus_timing_max; timing > bus_timing_normal; timing--) {
+		if (isset(&ivar->timings, timing)) {
+			max_timing = timing;
+			break;
+		}
+	}
+	device_printf(dev, " bus: %ubit, %uMHz (%s timing)\n",
 	    (ivar->bus_width == bus_width_1 ? 1 :
 	    (ivar->bus_width == bus_width_4 ? 4 : 8)),
-	    (ivar->timing == bus_timing_hs ?
-		ivar->hs_tran_speed : ivar->tran_speed) / 1000000,
-	    ivar->timing == bus_timing_hs ? ", high speed timing" : "");
+	    mmc_timing_to_dtr(ivar, timing) / 1000000,
+	    mmc_timing_to_string(timing));
 	device_printf(dev, " memory: %u blocks, erase sector %u blocks%s\n",
 	    ivar->sec_count, ivar->erase_sector,
 	    ivar->read_only ? ", read-only" : "");
@@ -1193,10 +1400,11 @@ mmc_discover_cards(struct mmc_softc *sc)
 	struct mmc_ivars *ivar = NULL;
 	device_t *devlist;
 	device_t child;
-	int err, i, devcount, newcard;
+	int devcount, err, host_caps, i, newcard;
 	uint32_t resp, sec_count, status;
 	uint16_t rca = 2;
 
+	host_caps = mmcbr_get_caps(sc->dev);
 	if (bootverbose || mmc_debug)
 		device_printf(sc->dev, "Probing cards\n");
 	while (1) {
@@ -1236,14 +1444,24 @@ mmc_discover_cards(struct mmc_softc *sc)
 		if (mmcbr_get_ro(sc->dev))
 			ivar->read_only = 1;
 		ivar->bus_width = bus_width_1;
-		ivar->timing = bus_timing_normal;
+		setbit(&ivar->timings, bus_timing_normal);
 		ivar->mode = mmcbr_get_mode(sc->dev);
 		if (ivar->mode == mode_sd) {
 			mmc_decode_cid_sd(ivar->raw_cid, &ivar->cid);
-			mmc_send_relative_addr(sc, &resp);
+			err = mmc_send_relative_addr(sc, &resp);
+			if (err != MMC_ERR_NONE) {
+				device_printf(sc->dev,
+				    "Error getting RCA %d\n", err);
+				break;
+			}
 			ivar->rca = resp >> 16;
 			/* Get card CSD. */
-			mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
+			err = mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
+			if (err != MMC_ERR_NONE) {
+				device_printf(sc->dev,
+				    "Error getting CSD %d\n", err);
+				break;
+			}
 			if (bootverbose || mmc_debug)
 				device_printf(sc->dev,
 				    "%sard detected (CSD %08x%08x%08x%08x)\n",
@@ -1272,18 +1490,29 @@ mmc_discover_cards(struct mmc_softc *sc)
 			}
 
 			/* Get card SCR.  Card must be selected to fetch it. */
-			mmc_select_card(sc, ivar->rca);
-			mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr);
+			err = mmc_select_card(sc, ivar->rca);
+			if (err != MMC_ERR_NONE) {
+				device_printf(sc->dev,
+				    "Error selecting card %d\n", err);
+				break;
+			}
+			err = mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr);
+			if (err != MMC_ERR_NONE) {
+				device_printf(sc->dev,
+				    "Error reading SCR %d\n", err);
+				break;
+			}
 			mmc_app_decode_scr(ivar->raw_scr, &ivar->scr);
 			/* Get card switch capabilities (command class 10). */
 			if ((ivar->scr.sda_vsn >= 1) &&
 			    (ivar->csd.ccc & (1 << 10))) {
-				mmc_sd_switch(sc, SD_SWITCH_MODE_CHECK,
+				err = mmc_sd_switch(sc, SD_SWITCH_MODE_CHECK,
 				    SD_SWITCH_GROUP1, SD_SWITCH_NOCHANGE,
 				    switch_res);
-				if (switch_res[13] & (1 << SD_SWITCH_HS_MODE)) {
-					ivar->timing = bus_timing_hs;
-					ivar->hs_tran_speed = SD_MAX_HS;
+				if (err == MMC_ERR_NONE &&
+				    switch_res[13] & (1 << SD_SWITCH_HS_MODE)) {
+					setbit(&ivar->timings, bus_timing_hs);
+					ivar->hs_tran_speed = SD_HS_MAX;
 				}
 			}
 
@@ -1300,8 +1529,9 @@ mmc_discover_cards(struct mmc_softc *sc)
 			 * it is still nice to get that right.
 			 */
 			mmc_select_card(sc, 0);
-			mmc_select_card(sc, ivar->rca);
-			mmc_app_sd_status(sc, ivar->rca, ivar->raw_sd_status);
+			(void)mmc_select_card(sc, ivar->rca);
+			(void)mmc_app_sd_status(sc, ivar->rca,
+			    ivar->raw_sd_status);
 			mmc_app_decode_sd_status(ivar->raw_sd_status,
 			    &ivar->sd_status);
 			if (ivar->sd_status.au_size != 0) {
@@ -1309,7 +1539,7 @@ mmc_discover_cards(struct mmc_softc *sc)
 				    16 << ivar->sd_status.au_size;
 			}
 			/* Find max supported bus width. */
-			if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) &&
+			if ((host_caps & MMC_CAP_4_BIT_DATA) &&
 			    (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4))
 				ivar->bus_width = bus_width_4;
 
@@ -1339,9 +1569,17 @@ mmc_discover_cards(struct mmc_softc *sc)
 			return;
 		}
 		ivar->rca = rca++;
-		mmc_set_relative_addr(sc, ivar->rca);
+		err = mmc_set_relative_addr(sc, ivar->rca);
+		if (err != MMC_ERR_NONE) {
+			device_printf(sc->dev, "Error setting RCA %d\n", err);
+			break;
+		}
 		/* Get card CSD. */
-		mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
+		err = mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
+		if (err != MMC_ERR_NONE) {
+			device_printf(sc->dev, "Error getting CSD %d\n", err);
+			break;
+		}
 		if (bootverbose || mmc_debug)
 			device_printf(sc->dev,
 			    "%sard detected (CSD %08x%08x%08x%08x)\n",
@@ -1367,7 +1605,12 @@ mmc_discover_cards(struct mmc_softc *sc)
 			break;
 		}
 
-		mmc_select_card(sc, ivar->rca);
+		err = mmc_select_card(sc, ivar->rca);
+		if (err != MMC_ERR_NONE) {
+			device_printf(sc->dev, "Error selecting card %d\n",
+			    err);
+			break;
+		}
 
 		/* Only MMC >= 4.x devices support EXT_CSD. */
 		if (ivar->csd.spec_vers >= 4) {
@@ -1387,16 +1630,28 @@ mmc_discover_cards(struct mmc_softc *sc)
 				ivar->sec_count = sec_count;
 				ivar->high_cap = 1;
 			}
-			/* Get card speed in high speed mode. */
-			ivar->timing = bus_timing_hs;
-			if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE]
-			    & EXT_CSD_CARD_TYPE_52)
-				ivar->hs_tran_speed = MMC_TYPE_52_MAX_HS;
-			else if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE]
-			    & EXT_CSD_CARD_TYPE_26)
-				ivar->hs_tran_speed = MMC_TYPE_26_MAX_HS;
-			else
-				ivar->hs_tran_speed = ivar->tran_speed;
+			/* Get device speeds beyond normal mode. */
+			if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
+			    EXT_CSD_CARD_TYPE_HS_52) != 0) {
+				setbit(&ivar->timings, bus_timing_hs);
+				ivar->hs_tran_speed = MMC_TYPE_HS_52_MAX;
+			} else if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
+			    EXT_CSD_CARD_TYPE_HS_26) != 0) {
+				setbit(&ivar->timings, bus_timing_hs);
+				ivar->hs_tran_speed = MMC_TYPE_HS_26_MAX;
+			}
+			if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
+			    EXT_CSD_CARD_TYPE_DDR_52_1_2V) != 0 &&
+			    (host_caps & MMC_CAP_SIGNALING_120) != 0) {
+				setbit(&ivar->timings, bus_timing_mmc_ddr52);
+				setbit(&ivar->vccq_120, bus_timing_mmc_ddr52);
+			}
+			if ((ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] &
+			    EXT_CSD_CARD_TYPE_DDR_52_1_8V) != 0 &&
+			    (host_caps & MMC_CAP_SIGNALING_180) != 0) {
+				setbit(&ivar->timings, bus_timing_mmc_ddr52);
+				setbit(&ivar->vccq_180, bus_timing_mmc_ddr52);
+			}
 			/*
 			 * Determine generic switch timeout (provided in
 			 * units of 10 ms), defaulting to 500 ms.
@@ -1423,9 +1678,6 @@ mmc_discover_cards(struct mmc_softc *sc)
 					break;
 				}
 			}
-		} else {
-			ivar->bus_width = bus_width_1;
-			ivar->timing = bus_timing_normal;
 		}
 
 		/*
@@ -1549,7 +1801,7 @@ mmc_go_discovery(struct mmc_softc *sc)
 			mmc_idle_cards(sc);
 	} else {
 		mmcbr_set_bus_mode(dev, opendrain);
-		mmcbr_set_clock(dev, CARD_ID_FREQUENCY);
+		mmcbr_set_clock(dev, SD_MMC_CARD_ID_FREQUENCY);
 		mmcbr_update_ios(dev);
 		/* XXX recompute vdd based on new cards? */
 	}
@@ -1588,42 +1840,59 @@ mmc_calculate_clock(struct mmc_softc *sc
 {
 	device_t *kids;
 	struct mmc_ivars *ivar;
-	int i, f_max, max_dtr, max_hs_dtr, max_timing, nkid;
-
-	f_max = mmcbr_get_f_max(sc->dev);
-	max_dtr = max_hs_dtr = f_max;
-	if (mmcbr_get_caps(sc->dev) & MMC_CAP_HSPEED)
+	int host_caps, i, nkid;
+	uint32_t dtr, max_dtr;
+	enum mmc_bus_timing max_timing, timing;
+	bool changed;
+
+	max_dtr = mmcbr_get_f_max(sc->dev);
+	host_caps = mmcbr_get_caps(sc->dev);
+	if ((host_caps & MMC_CAP_MMC_DDR52) != 0)
+		max_timing = bus_timing_mmc_ddr52;
+	else if ((host_caps & MMC_CAP_HSPEED) != 0)
 		max_timing = bus_timing_hs;
 	else
 		max_timing = bus_timing_normal;
 	if (device_get_children(sc->dev, &kids, &nkid) != 0)
 		panic("can't get children");
-	for (i = 0; i < nkid; i++) {
-		ivar = device_get_ivars(kids[i]);
-		if (ivar->timing < max_timing)
-			max_timing = ivar->timing;
-		if (ivar->tran_speed < max_dtr)
-			max_dtr = ivar->tran_speed;
-		if (ivar->hs_tran_speed < max_hs_dtr)
-			max_hs_dtr = ivar->hs_tran_speed;
-	}
+	do {
+		changed = false;
+		for (i = 0; i < nkid; i++) {
+			ivar = device_get_ivars(kids[i]);
+			if (isclr(&ivar->timings, max_timing)) {
+				for (timing = max_timing; timing >=
+				    bus_timing_normal; timing--) {
+					if (isset(&ivar->timings, timing)) {
+						max_timing = timing;
+						break;
+					}
+				}
+				changed = true;
+			}
+			dtr = mmc_timing_to_dtr(ivar, max_timing);
+			if (dtr < max_dtr) {
+				max_dtr = dtr;
+				changed = true;
+			}
+		}
+	} while (changed == true);
 	if (bootverbose || mmc_debug) {
 		device_printf(sc->dev,
-		    "setting transfer rate to %d.%03dMHz%s\n",
+		    "setting transfer rate to %d.%03dMHz (%s timing)\n",
 		    max_dtr / 1000000, (max_dtr / 1000) % 1000,
-		    max_timing == bus_timing_hs ? " (high speed timing)" : "");
+		    mmc_timing_to_string(max_timing));
 	}
 	for (i = 0; i < nkid; i++) {
 		ivar = device_get_ivars(kids[i]);
-		if (ivar->timing == bus_timing_normal)
+		if ((ivar->timings & ~(1 << bus_timing_normal)) == 0)
 			continue;
-		mmc_select_card(sc, ivar->rca);
-		mmc_set_timing(sc, ivar, max_timing);
+		if (mmc_select_card(sc, ivar->rca) != MMC_ERR_NONE ||
+		    mmc_set_timing(sc, ivar, max_timing) != MMC_ERR_NONE)
+			device_printf(sc->dev, "Card at relative address %d "
+			    "failed to set timing.\n", ivar->rca);
 	}
 	mmc_select_card(sc, 0);
 	free(kids, M_TEMP);
-	if (max_timing == bus_timing_hs)
-		max_dtr = max_hs_dtr;
 	mmcbr_set_clock(sc->dev, max_dtr);
 	mmcbr_update_ios(sc->dev);
 	return (max_dtr);

Modified: stable/10/sys/dev/mmc/mmcbr_if.m
==============================================================================
--- stable/10/sys/dev/mmc/mmcbr_if.m	Thu May 18 20:46:20 2017	(r318494)
+++ stable/10/sys/dev/mmc/mmcbr_if.m	Thu May 18 20:46:27 2017	(r318495)
@@ -65,6 +65,18 @@
 INTERFACE mmcbr;
 
 #
+# Default implementations of some methods.
+#
+CODE {
+	static int
+	null_switch_vccq(device_t brdev __unused, device_t reqdev __unused)
+	{
+
+		return (0);
+	}
+};
+
+#
 # Called by the mmcbus to set up the IO pins correctly, the common/core
 # supply voltage (VDD/VCC) to use for the device, the clock frequency, the
 # type of SPI chip select, power mode and bus width.
@@ -75,6 +87,14 @@ METHOD int update_ios {
 };
 
 #
+# Called by the mmcbus to switch the signaling voltage (VCCQ).
+#
+METHOD int switch_vccq {
+	device_t	brdev;
+	device_t	reqdev;
+} DEFAULT null_switch_vccq;
+
+#
 # Called by the mmcbus or its children to schedule a mmc request.  These
 # requests are queued.  Time passes.  The bridge then gets notification
 # of the status of the request, who then notifies the requesting device

Modified: stable/10/sys/dev/mmc/mmcbrvar.h
==============================================================================
--- stable/10/sys/dev/mmc/mmcbrvar.h	Thu May 18 20:46:20 2017	(r318494)
+++ stable/10/sys/dev/mmc/mmcbrvar.h	Thu May 18 20:46:27 2017	(r318495)
@@ -71,6 +71,7 @@ enum mmcbr_device_ivars {
     MMCBR_IVAR_OCR,
     MMCBR_IVAR_POWER_MODE,
     MMCBR_IVAR_VDD,
+    MMCBR_IVAR_VCCQ,
     MMCBR_IVAR_CAPS,
     MMCBR_IVAR_TIMING,
     MMCBR_IVAR_MAX_DATA,
@@ -94,6 +95,7 @@ MMCBR_ACCESSOR(mode, MODE, int)
 MMCBR_ACCESSOR(ocr, OCR, int)
 MMCBR_ACCESSOR(power_mode, POWER_MODE, int)
 MMCBR_ACCESSOR(vdd, VDD, int)
+MMCBR_ACCESSOR(vccq, VCCQ, int)
 MMCBR_ACCESSOR(caps, CAPS, int)
 MMCBR_ACCESSOR(timing, TIMING, int)
 MMCBR_ACCESSOR(max_data, MAX_DATA, int)
@@ -107,6 +109,13 @@ mmcbr_update_ios(device_t dev)
 }
 
 static int __inline
+mmcbr_switch_vccq(device_t dev)
+{
+
+	return (MMCBR_SWITCH_VCCQ(device_get_parent(dev), dev));
+}
+
+static int __inline
 mmcbr_get_ro(device_t dev)
 {
 

Modified: stable/10/sys/dev/mmc/mmcreg.h
==============================================================================
--- stable/10/sys/dev/mmc/mmcreg.h	Thu May 18 20:46:20 2017	(r318494)
+++ stable/10/sys/dev/mmc/mmcreg.h	Thu May 18 20:46:27 2017	(r318495)
@@ -209,11 +209,11 @@ struct mmc_request {
 #define	MMC_SET_BLOCKLEN	16
 #define	MMC_READ_SINGLE_BLOCK	17
 #define	MMC_READ_MULTIPLE_BLOCK	18
-			/* reserved: 19 */
+#define	MMC_SEND_TUNING_BLOCK	19
+#define	MMC_SEND_TUNING_BLOCK_HS200 21
 
 /* Class 3: Stream write commands */
 #define	MMC_WRITE_DAT_UNTIL_STOP 20
-			/* reserved: 21 */
 			/* reserved: 22 */
 
 /* Class 4: Block oriented write commands */
@@ -304,16 +304,28 @@ struct mmc_request {
 #define	EXT_CSD_ERASE_GRP_DEF	175	/* R/W */
 #define	EXT_CSD_PART_CONFIG	179	/* R/W */
 #define	EXT_CSD_BUS_WIDTH	183	/* R/W */
+#define	EXT_CSD_STROBE_SUPPORT	184	/* RO */
 #define	EXT_CSD_HS_TIMING	185	/* R/W */
+#define	EXT_CSD_POWER_CLASS	187	/* R/W */
 #define	EXT_CSD_CARD_TYPE	196	/* RO */
+#define	EXT_CSD_DRIVER_STRENGTH	197	/* RO */
 #define	EXT_CSD_REV		192	/* RO */
 #define	EXT_CSD_PART_SWITCH_TO	199	/* RO */
+#define	EXT_CSD_PWR_CL_52_195	200	/* RO */
+#define	EXT_CSD_PWR_CL_26_195	201	/* RO */
+#define	EXT_CSD_PWR_CL_52_360	202	/* RO */
+#define	EXT_CSD_PWR_CL_26_360	203	/* RO */
 #define	EXT_CSD_SEC_CNT		212	/* RO, 4 bytes */
 #define	EXT_CSD_HC_WP_GRP_SIZE	221	/* RO */
 #define	EXT_CSD_ERASE_TO_MULT	223	/* RO */
 #define	EXT_CSD_ERASE_GRP_SIZE	224	/* RO */
 #define	EXT_CSD_BOOT_SIZE_MULT	226	/* RO */
+#define	EXT_CSD_PWR_CL_200_195	236	/* RO */
+#define	EXT_CSD_PWR_CL_200_360	237	/* RO */
+#define	EXT_CSD_PWR_CL_52_195_DDR 238	/* RO */
+#define	EXT_CSD_PWR_CL_52_360_DDR 239	/* RO */
 #define	EXT_CSD_GEN_CMD6_TIME	248	/* RO */
+#define	EXT_CSD_PWR_CL_200_360_DDR 253	/* RO */
 
 /*
  * EXT_CSD field definitions
@@ -363,15 +375,38 @@ struct mmc_request {
 #define	EXT_CSD_CMD_SET_SECURE		2
 #define	EXT_CSD_CMD_SET_CPSECURE	4
 
-#define	EXT_CSD_CARD_TYPE_26	1
-#define	EXT_CSD_CARD_TYPE_52	2
+#define	EXT_CSD_HS_TIMING_BC		0
+#define	EXT_CSD_HS_TIMING_HS		1
+#define	EXT_CSD_HS_TIMING_DDR200	2
+#define	EXT_CSD_HS_TIMING_DDR400	3
+#define	EXT_CSD_HS_TIMING_DRV_STR_SHIFT	4
+
+#define	EXT_CSD_POWER_CLASS_8BIT_MASK	0xf0
+#define	EXT_CSD_POWER_CLASS_8BIT_SHIFT	4
+#define	EXT_CSD_POWER_CLASS_4BIT_MASK	0x0f
+#define	EXT_CSD_POWER_CLASS_4BIT_SHIFT	0
+
+#define	EXT_CSD_CARD_TYPE_HS_26		0x0001
+#define	EXT_CSD_CARD_TYPE_HS_52		0x0002
+#define	EXT_CSD_CARD_TYPE_DDR_52_1_8V	0x0004
+#define	EXT_CSD_CARD_TYPE_DDR_52_1_2V	0x0008
+#define	EXT_CSD_CARD_TYPE_HS200_1_8V	0x0010
+#define	EXT_CSD_CARD_TYPE_HS200_1_2V	0x0020
+#define	EXT_CSD_CARD_TYPE_HS400_1_8V	0x0040
+#define	EXT_CSD_CARD_TYPE_HS400_1_2V	0x0080
+#define	EXT_CSD_CARD_TYPE_HS400ES	0x0100
 
 #define	EXT_CSD_BUS_WIDTH_1	0
 #define	EXT_CSD_BUS_WIDTH_4	1
 #define	EXT_CSD_BUS_WIDTH_8	2
-
-#define	MMC_TYPE_26_MAX_HS	26000000
-#define	MMC_TYPE_52_MAX_HS	52000000
+#define	EXT_CSD_BUS_WIDTH_4_DDR	5
+#define	EXT_CSD_BUS_WIDTH_8_DDR	6
+#define	EXT_CSD_BUS_WIDTH_ES	0x80
+
+#define	MMC_TYPE_HS_26_MAX		26000000
+#define	MMC_TYPE_HS_52_MAX		52000000
+#define	MMC_TYPE_DDR52_MAX		52000000
+#define	MMC_TYPE_HS200_HS400ES_MAX	200000000
 
 /*
  * SD bus widths
@@ -387,12 +422,23 @@ struct mmc_request {
 #define	SD_SWITCH_GROUP1	0
 #define	SD_SWITCH_NORMAL_MODE	0
 #define	SD_SWITCH_HS_MODE	1
+#define	SD_SWITCH_SDR50_MODE	2
+#define	SD_SWITCH_SDR104_MODE	3
+#define	SD_SWITCH_DDR50		4
 #define	SD_SWITCH_NOCHANGE	0xF
 
 #define	SD_CLR_CARD_DETECT	0
 #define	SD_SET_CARD_DETECT	1
 
-#define	SD_MAX_HS		50000000
+#define	SD_HS_MAX		50000000
+#define	SD_DDR50_MAX		50000000
+#define	SD_SDR12_MAX		25000000
+#define	SD_SDR25_MAX		50000000
+#define	SD_SDR50_MAX		100000000
+#define	SD_SDR104_MAX		208000000
+
+/* Specifications require 400 kHz max. during ID phase. */
+#define	SD_MMC_CARD_ID_FREQUENCY	400000
 
 /* OCR bits */
 
@@ -429,6 +475,12 @@ struct mmc_request {
 #define	MMC_OCR_340_350	(1U << 22)	/* Vdd voltage 3.40 ~ 3.50 */
 #define	MMC_OCR_350_360	(1U << 23)	/* Vdd voltage 3.50 ~ 3.60 */
 #define	MMC_OCR_MAX_VOLTAGE_SHIFT	23
+#define	MMC_OCR_S18R	(1U << 24)	/* Switching to 1.8 V requested (SD) */
+#define	MMC_OCR_S18A	MMC_OCR_S18R	/* Switching to 1.8 V accepted (SD) */
+#define	MMC_OCR_XPC	(1U << 28)	/* SDXC Power Control */
+#define	MMC_OCR_ACCESS_MODE_BYTE (0U << 29) /* Access Mode Byte (MMC) */
+#define	MMC_OCR_ACCESS_MODE_SECT (1U << 29) /* Access Mode Sector (MMC) */
+#define	MMC_OCR_ACCESS_MODE_MASK (3U << 29)
 #define	MMC_OCR_CCS	(1u << 30)	/* Card Capacity status (SD vs SDHC) */
 #define	MMC_OCR_CARD_BUSY (1U << 31)	/* Card Power up status */
 

Modified: stable/10/sys/dev/sdhci/sdhci.c
==============================================================================
--- stable/10/sys/dev/sdhci/sdhci.c	Thu May 18 20:46:20 2017	(r318494)
+++ stable/10/sys/dev/sdhci/sdhci.c	Thu May 18 20:46:27 2017	(r318495)
@@ -58,6 +58,12 @@ static int sdhci_debug;
 TUNABLE_INT("hw.sdhci.debug", &sdhci_debug);
 SYSCTL_INT(_hw_sdhci, OID_AUTO, debug, CTLFLAG_RWTUN, &sdhci_debug, 0,
     "Debug level");
+u_int sdhci_quirk_clear = 0;
+SYSCTL_INT(_hw_sdhci, OID_AUTO, quirk_clear, CTLFLAG_RWTUN, &sdhci_quirk_clear,
+    0, "Mask of quirks to clear");
+u_int sdhci_quirk_set = 0;
+SYSCTL_INT(_hw_sdhci, OID_AUTO, quirk_set, CTLFLAG_RWTUN, &sdhci_quirk_set, 0,
+    "Mask of quirks to set");
 
 #define	RD1(slot, off)	SDHCI_READ_1((slot)->bus, (slot), (off))
 #define	RD2(slot, off)	SDHCI_READ_2((slot)->bus, (slot), (off))
@@ -79,6 +85,10 @@ static void sdhci_card_poll(void *);
 static void sdhci_card_task(void *, int);
 
 /* helper routines */
+static void sdhci_dumpregs(struct sdhci_slot *slot);
+static int slot_printf(struct sdhci_slot *slot, const char * fmt, ...)
+    __printflike(2, 3);
+
 #define	SDHCI_LOCK(_slot)		mtx_lock(&(_slot)->mtx)
 #define	SDHCI_UNLOCK(_slot)		mtx_unlock(&(_slot)->mtx)
 #define	SDHCI_LOCK_INIT(_slot) \
@@ -582,7 +592,7 @@ sdhci_card_poll(void *arg)
 int
 sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
 {
-	uint32_t caps, freq;
+	uint32_t caps, caps2, freq, host_caps;
 	int err;
 
 	SDHCI_LOCK_INIT(slot);
@@ -626,10 +636,16 @@ sdhci_init_slot(device_t dev, struct sdh
 	sdhci_init(slot);
 	slot->version = (RD2(slot, SDHCI_HOST_VERSION)
 		>> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK;
-	if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS)
+	if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS) {
 		caps = slot->caps;
-	else
+		caps2 = slot->caps2;
+	} else {
 		caps = RD4(slot, SDHCI_CAPABILITIES);
+		if (slot->version >= SDHCI_SPEC_300)
+			caps2 = RD4(slot, SDHCI_CAPABILITIES2);
+		else
+			caps2 = 0;
+	}
 	/* Calculate base clock frequency. */
 	if (slot->version >= SDHCI_SPEC_300)
 		freq = (caps & SDHCI_CLOCK_V3_BASE_MASK) >>
@@ -685,15 +701,45 @@ sdhci_init_slot(device_t dev, struct sdh
 		device_printf(dev, "Hardware doesn't report any "
 		    "support voltages.\n");
 	}
-	slot->host.caps = MMC_CAP_4_BIT_DATA;
+	host_caps = MMC_CAP_4_BIT_DATA;
 	if (caps & SDHCI_CAN_DO_8BITBUS)
-		slot->host.caps |= MMC_CAP_8_BIT_DATA;
+		host_caps |= MMC_CAP_8_BIT_DATA;
 	if (caps & SDHCI_CAN_DO_HISPD)
-		slot->host.caps |= MMC_CAP_HSPEED;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705182046.v4IKkRrZ021500>