From 5b44ad67128ea6246f04bcbd9c19a0cdc5247cae Mon Sep 17 00:00:00 2001 From: Rui Paulo Date: Sat, 22 Jun 2013 22:37:34 -0700 Subject: [PATCH 16/20] mmc: Only perform the bus width test if the controller supports it. --- sys/arm/at91/at91_mci.c | 2 +- sys/arm/lpc/lpc_mmc.c | 3 +- sys/arm/ti/ti_mmchs.c | 6 ++-- sys/boot/fdt/dts/am335x.dtsi | 1 + sys/dev/mmc/bridge.h | 1 + sys/dev/mmc/mmc.c | 78 ++++++++++++++++++++++++++++++++++++++++++-- sys/dev/sdhci/sdhci.c | 2 +- 7 files changed, 85 insertions(+), 8 deletions(-) diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c index c4cf9b4..b7ea107 100644 --- a/sys/arm/at91/at91_mci.c +++ b/sys/arm/at91/at91_mci.c @@ -452,7 +452,7 @@ at91_mci_attach(device_t dev) if (sc->host.f_max > 25000000) sc->host.f_max = 25000000; sc->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340; - sc->host.caps = 0; + sc->host.caps = MMC_CAP_BUSW_TEST; if (sc->sc_cap & CAP_HAS_4WIRE) sc->host.caps |= MMC_CAP_4_BIT_DATA; diff --git a/sys/arm/lpc/lpc_mmc.c b/sys/arm/lpc/lpc_mmc.c index 5a789f6..58f1fdb 100644 --- a/sys/arm/lpc/lpc_mmc.c +++ b/sys/arm/lpc/lpc_mmc.c @@ -225,8 +225,9 @@ lpc_mmc_attach(device_t dev) sc->lm_host.f_max = 2500000; sc->lm_host.host_ocr = MMC_OCR_300_310 | MMC_OCR_310_320 | MMC_OCR_320_330 | MMC_OCR_330_340; + sc->lm_host.caps = MMC_CAP_BUSW_TEST; #if 0 - sc->lm_host.caps = MMC_CAP_4_BIT_DATA; + sc->lm_host.caps |= MMC_CAP_4_BIT_DATA; #endif lpc_pwr_write(dev, LPC_CLKPWR_MS_CTRL, diff --git a/sys/arm/ti/ti_mmchs.c b/sys/arm/ti/ti_mmchs.c index 25c7d06..bb7dae8 100644 --- a/sys/arm/ti/ti_mmchs.c +++ b/sys/arm/ti/ti_mmchs.c @@ -1688,7 +1688,7 @@ ti_mmchs_attach(device_t dev) /* Get the mmchs device id from FDT */ node = ofw_bus_get_node(dev); - if ((OF_getprop(node, "mmchs-device-id", &did, sizeof(did))) <= 0) { + if (OF_getprop(node, "mmchs-device-id", &did, sizeof(did)) <= 0) { device_printf(dev, "missing mmchs-device-id attribute in FDT\n"); return (ENXIO); } @@ -1749,8 +1749,10 @@ ti_mmchs_attach(device_t dev) sc->host.f_max = sc->sc_ref_freq; sc->host.host_ocr = MMC_OCR_290_300 | MMC_OCR_300_310; sc->host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; + if (!OF_hasprop(node, "mmc,no-bus-width-test")) + sc->host.caps |= MMC_CAP_BUSW_TEST; - device_add_child(dev, "mmc", 0); + device_add_child(dev, "mmc", -1); device_set_ivars(dev, &sc->host); err = bus_generic_attach(dev); diff --git a/sys/boot/fdt/dts/am335x.dtsi b/sys/boot/fdt/dts/am335x.dtsi index 1ab047f..46bcdb0 100644 --- a/sys/boot/fdt/dts/am335x.dtsi +++ b/sys/boot/fdt/dts/am335x.dtsi @@ -120,6 +120,7 @@ interrupts = <28>; interrupt-parent = <&AINTC>; mmchs-device-id = <1>; + mmc,no-bus-width-test; status = "disabled"; }; diff --git a/sys/dev/mmc/bridge.h b/sys/dev/mmc/bridge.h index bd61c15..dce6382 100644 --- a/sys/dev/mmc/bridge.h +++ b/sys/dev/mmc/bridge.h @@ -131,6 +131,7 @@ struct mmc_host { #define MMC_CAP_4_BIT_DATA (1 << 0) /* Can do 4-bit data transfers */ #define MMC_CAP_8_BIT_DATA (1 << 1) /* Can do 8-bit data transfers */ #define MMC_CAP_HSPEED (1 << 2) /* Can do High Speed transfers */ +#define MMC_CAP_BUSW_TEST (1 << 3) /* Can do Bus Width tests */ enum mmc_card_mode mode; struct mmc_ios ios; /* Current state of the host */ }; diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c index f101e65..c80db87 100644 --- a/sys/dev/mmc/mmc.c +++ b/sys/dev/mmc/mmc.c @@ -108,7 +108,7 @@ struct mmc_ivars { static SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver"); -static int mmc_debug; +static int mmc_debug = 1; SYSCTL_INT(_hw_mmc, OID_AUTO, debug, CTLFLAG_RW, &mmc_debug, 0, "Debug level"); /* bus entry points */ @@ -187,6 +187,7 @@ static int mmc_set_timing(struct mmc_softc *sc, int timing); static int mmc_switch(struct mmc_softc *sc, uint8_t set, uint8_t index, uint8_t value); static int mmc_test_bus_width(struct mmc_softc *sc); +static int mmc_compare_ext_csds(struct mmc_softc *sc, const uint8_t *ref_csd, uint16_t); static int mmc_wait_for_app_cmd(struct mmc_softc *sc, uint32_t rca, struct mmc_command *cmd, int retries); static int mmc_wait_for_cmd(struct mmc_softc *sc, struct mmc_command *cmd, @@ -806,6 +807,73 @@ mmc_test_bus_width(struct mmc_softc *sc) return (bus_width_1); } +static int +mmc_compare_ext_csd(struct mmc_softc *sc, const uint8_t *ref_csd, + uint8_t *raw_csd) +{ + int i; + for (i = 0; i< 512; i++) { + printf("0x%02x ", ref_csd[i]); + if (i && i % 20 == 0) + printf("\n"); + } + printf("\n"); + for (i = 0; i< 512; i++) { + printf("0x%02x ", raw_csd[i]); + if (i && i % 20 == 0) + printf("\n"); + } + printf("\n"); +#define COMPARE(field) ref_csd[field] == raw_csd[field] + if (COMPARE(EXT_CSD_CARD_TYPE) && + COMPARE(EXT_CSD_REV) && + COMPARE(EXT_CSD_SEC_CNT + 0) && + COMPARE(EXT_CSD_SEC_CNT + 1) && + COMPARE(EXT_CSD_SEC_CNT + 2) && + COMPARE(EXT_CSD_SEC_CNT + 3) && + COMPARE(EXT_CSD_ERASE_TO_MULT) && + COMPARE(EXT_CSD_ERASE_GRP_SIZE)) + return (0); + else + return (1); +#undef COMPARE +} + +static int +mmc_compare_ext_csds(struct mmc_softc *sc, const uint8_t *ref_csd, uint16_t rca) +{ + uint8_t raw_csd[512]; + int err; + + return bus_width_4; + if (mmcbr_get_caps(sc->dev) & MMC_CAP_8_BIT_DATA) { + mmcbr_set_bus_width(sc->dev, bus_width_8); + mmcbr_update_ios(sc->dev); + mmc_select_card(sc, rca); + mmc_send_ext_csd(sc, raw_csd); + err = mmc_compare_ext_csd(sc, ref_csd, raw_csd); + mmcbr_set_bus_width(sc->dev, bus_width_1); + mmcbr_update_ios(sc->dev); + if (!err) + return (bus_width_8); + } + if (mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) { + mmcbr_set_bus_width(sc->dev, bus_width_4); + mmcbr_update_ios(sc->dev); + mmc_select_card(sc, rca); + mmc_send_ext_csd(sc, raw_csd); + err = mmc_compare_ext_csd(sc, ref_csd, raw_csd); + mmcbr_set_bus_width(sc->dev, bus_width_1); + mmcbr_update_ios(sc->dev); + if (!err) + return (bus_width_4); + } + + return (bus_width_1); +} + + + static uint32_t mmc_get_bits(uint32_t *bits, int bit_len, int start, int size) { @@ -1408,8 +1476,12 @@ mmc_discover_cards(struct mmc_softc *sc) ivar->hs_tran_speed = MMC_TYPE_26_MAX_HS; else ivar->hs_tran_speed = ivar->tran_speed; - /* Find max supported bus width. */ - ivar->bus_width = mmc_test_bus_width(sc); + if (mmcbr_get_caps(sc->dev) & MMC_CAP_BUSW_TEST) { + /* Find max supported bus width. */ + ivar->bus_width = mmc_test_bus_width(sc); + } else + ivar->bus_width = mmc_compare_ext_csds(sc, + ivar->raw_ext_csd, ivar->rca); mmc_select_card(sc, 0); /* Handle HC erase sector size. */ if (ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE] != 0) { diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index 15199f0..9ee2982 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -561,7 +561,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) device_printf(dev, "Hardware doesn't report any " "support voltages.\n"); } - slot->host.caps = MMC_CAP_4_BIT_DATA; + slot->host.caps = MMC_CAP_BUSW_TEST | MMC_CAP_4_BIT_DATA; if (caps & SDHCI_CAN_DO_HISPD) slot->host.caps |= MMC_CAP_HSPEED; /* Decide if we have usable DMA. */ -- 1.8.3.2