Index: mmc/bridge.h =================================================================== --- mmc/bridge.h (revision 315514) +++ mmc/bridge.h (working copy) @@ -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); \ Index: mmc/mmc.c =================================================================== --- mmc/mmc.c (revision 315514) +++ mmc/mmc.c (working copy) @@ -75,6 +75,8 @@ __FBSDID("$FreeBSD$"); #include "mmcbr_if.h" #include "mmcbus_if.h" +CTASSERT(bus_timing_max <= sizeof(uint32_t) * NBBY); + /* * Per-card data */ @@ -92,9 +94,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 +109,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; @@ -182,10 +184,14 @@ static int mmc_send_relative_addr(struct mmc_softc 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_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); @@ -264,8 +270,8 @@ mmc_acquire_bus(device_t busdev, device_t dev) { 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) @@ -287,16 +293,44 @@ mmc_acquire_bus(device_t busdev, device_t dev) 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)); } - mmc_set_card_bus_width(sc, ivar); + 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); + } mmcbr_set_bus_width(busdev, ivar->bus_width); mmcbr_update_ios(busdev); } @@ -524,6 +558,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))); @@ -533,9 +568,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); @@ -631,10 +671,30 @@ mmc_set_card_bus_width(struct mmc_softc *sc, struc 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); @@ -647,23 +707,96 @@ mmc_set_card_bus_width(struct mmc_softc *sc, struc } 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) @@ -673,6 +806,17 @@ static int 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); @@ -1166,19 +1310,82 @@ mmc_set_blocklen(struct mmc_softc *sc, uint32_t le 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_uhs_sdr12: + return (SD_SDR12_MAX); + case bus_timing_hs: + return (ivar->hs_tran_speed); + 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" : ""); @@ -1192,10 +1399,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) { @@ -1235,14 +1443,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", @@ -1271,18 +1489,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; } } @@ -1299,8 +1528,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) { @@ -1308,7 +1538,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; @@ -1338,9 +1568,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", @@ -1366,7 +1604,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) { @@ -1386,16 +1629,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. @@ -1422,9 +1677,6 @@ mmc_discover_cards(struct mmc_softc *sc) break; } } - } else { - ivar->bus_width = bus_width_1; - ivar->timing = bus_timing_normal; } /* @@ -1548,7 +1800,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? */ } @@ -1587,42 +1839,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; + int host_caps, i, nkid; + uint32_t dtr, max_dtr; + enum mmc_bus_timing max_timing, timing; + bool changed; - f_max = mmcbr_get_f_max(sc->dev); - max_dtr = max_hs_dtr = f_max; - if (mmcbr_get_caps(sc->dev) & MMC_CAP_HSPEED) + 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); Index: mmc/mmcbr_if.m =================================================================== --- mmc/mmcbr_if.m (revision 315514) +++ mmc/mmcbr_if.m (working copy) @@ -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 Index: mmc/mmcbrvar.h =================================================================== --- mmc/mmcbrvar.h (revision 315514) +++ mmc/mmcbrvar.h (working copy) @@ -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) { Index: mmc/mmcreg.h =================================================================== --- mmc/mmcreg.h (revision 315514) +++ mmc/mmcreg.h (working copy) @@ -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 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_26_MAX_HS 26000000 -#define MMC_TYPE_52_MAX_HS 52000000 +#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,13 +422,24 @@ 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 */ Index: sdhci/sdhci.c =================================================================== --- sdhci/sdhci.c (revision 315514) +++ sdhci/sdhci.c (working copy) @@ -57,6 +57,12 @@ SYSCTL_NODE(_hw, OID_AUTO, sdhci, CTLFLAG_RD, 0, " static int 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)) @@ -78,6 +84,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) \ @@ -581,7 +591,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); @@ -625,10 +635,16 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *s 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) >> @@ -684,15 +700,45 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *s 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; + host_caps |= MMC_CAP_HSPEED; if (slot->quirks & SDHCI_QUIRK_BOOT_NOACC) - slot->host.caps |= MMC_CAP_BOOT_NOACC; + host_caps |= MMC_CAP_BOOT_NOACC; if (slot->quirks & SDHCI_QUIRK_WAIT_WHILE_BUSY) - slot->host.caps |= MMC_CAP_WAIT_WHILE_BUSY; + host_caps |= MMC_CAP_WAIT_WHILE_BUSY; + if (caps2 & (SDHCI_CAN_SDR50 | SDHCI_CAN_SDR104 | SDHCI_CAN_DDR50)) + host_caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; + if (caps2 & SDHCI_CAN_SDR104) { + host_caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; + if (!(slot->quirks & SDHCI_QUIRK_BROKEN_MMC_HS200)) + host_caps |= MMC_CAP_MMC_HS200; + } else if (caps2 & SDHCI_CAN_SDR50) + host_caps |= MMC_CAP_UHS_SDR50; + if (caps2 & SDHCI_CAN_DDR50 && + !(slot->quirks & SDHCI_QUIRK_BROKEN_UHS_DDR50)) + host_caps |= MMC_CAP_UHS_DDR50; + if (slot->quirks & SDHCI_QUIRK_MMC_DDR52) + host_caps |= MMC_CAP_MMC_DDR52; + if (slot->quirks & SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 && + caps2 & SDHCI_CAN_MMC_HS400) + host_caps |= MMC_CAP_MMC_HS400; + host_caps |= MMC_CAP_SIGNALING_330; + if (host_caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | + MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50 | + MMC_CAP_MMC_DDR52_180 | MMC_CAP_MMC_HS200_180 | + MMC_CAP_MMC_HS400_180)) + host_caps |= MMC_CAP_SIGNALING_180; + if (caps & SDHCI_CTRL2_DRIVER_TYPE_A) + host_caps |= MMC_CAP_DRIVER_TYPE_A; + if (caps & SDHCI_CTRL2_DRIVER_TYPE_C) + host_caps |= MMC_CAP_DRIVER_TYPE_C; + if (caps & SDHCI_CTRL2_DRIVER_TYPE_D) + host_caps |= MMC_CAP_DRIVER_TYPE_D; + slot->host.caps = host_caps; + /* Decide if we have usable DMA. */ if (caps & SDHCI_CAN_DO_DMA) slot->opt |= SDHCI_HAVE_DMA; @@ -712,16 +758,39 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *s slot->opt &= ~SDHCI_HAVE_DMA; if (bootverbose || sdhci_debug) { - slot_printf(slot, "%uMHz%s %s%s%s%s %s\n", + slot_printf(slot, + "%uMHz%s %s VDD:%s%s%s VCCQ: 3.3V%s%s DRV: B%s%s%s %s\n", slot->max_clk / 1000000, (caps & SDHCI_CAN_DO_HISPD) ? " HS" : "", - (slot->host.caps & MMC_CAP_8_BIT_DATA) ? "8bits" : - ((slot->host.caps & MMC_CAP_4_BIT_DATA) ? "4bits" : - "1bit"), + (host_caps & MMC_CAP_8_BIT_DATA) ? "8bits" : + ((host_caps & MMC_CAP_4_BIT_DATA) ? "4bits" : "1bit"), (caps & SDHCI_CAN_VDD_330) ? " 3.3V" : "", (caps & SDHCI_CAN_VDD_300) ? " 3.0V" : "", (caps & SDHCI_CAN_VDD_180) ? " 1.8V" : "", + (host_caps & MMC_CAP_SIGNALING_180) ? " 1.8V" : "", + (host_caps & MMC_CAP_SIGNALING_120) ? " 1.2V" : "", + (caps & SDHCI_CTRL2_DRIVER_TYPE_A) ? "A" : "", + (caps & SDHCI_CTRL2_DRIVER_TYPE_C) ? "C" : "", + (caps & SDHCI_CTRL2_DRIVER_TYPE_D) ? "D" : "", (slot->opt & SDHCI_HAVE_DMA) ? "DMA" : "PIO"); + if (host_caps & (MMC_CAP_MMC_DDR52 | MMC_CAP_MMC_HS200 | + MMC_CAP_MMC_HS400 | MMC_CAP_MMC_ENH_STROBE)) + slot_printf(slot, "eMMC:%s%s%s%s\n", + (host_caps & MMC_CAP_MMC_DDR52) ? " DDR52" : "", + (host_caps & MMC_CAP_MMC_HS200) ? " HS200" : "", + (host_caps & MMC_CAP_MMC_HS400) ? " HS400" : "", + ((host_caps & + (MMC_CAP_MMC_HS400 | MMC_CAP_MMC_ENH_STROBE)) == + (MMC_CAP_MMC_HS400 | MMC_CAP_MMC_ENH_STROBE)) ? + " HS400ES" : ""); + if (host_caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | + MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104)) + slot_printf(slot, "UHS-I:%s%s%s%s%s\n", + (host_caps & MMC_CAP_UHS_SDR12) ? " SDR12" : "", + (host_caps & MMC_CAP_UHS_SDR25) ? " SDR25" : "", + (host_caps & MMC_CAP_UHS_SDR50) ? " SDR50" : "", + (host_caps & MMC_CAP_UHS_SDR104) ? " SDR104" : "", + (host_caps & MMC_CAP_UHS_DDR50) ? " DDR50" : ""); sdhci_dumpregs(slot); } @@ -819,6 +888,38 @@ sdhci_generic_get_card_present(device_t brdev __un return (RD4(slot, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); } +void +sdhci_generic_set_uhs_timing(device_t brdev __unused, struct sdhci_slot *slot) +{ + struct mmc_ios *ios; + uint16_t hostctrl2; + + if (slot->version < SDHCI_SPEC_300) + return; + + ios = &slot->host.ios; + sdhci_set_clock(slot, 0); + hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); + hostctrl2 &= ~SDHCI_CTRL2_UHS_MASK; + if (ios->timing == bus_timing_mmc_hs400 || + ios->timing == bus_timing_mmc_hs400es) + hostctrl2 |= SDHCI_CTRL2_MMC_HS400; + else if (ios->clock > SD_SDR50_MAX) + hostctrl2 |= SDHCI_CTRL2_UHS_SDR104; + else if (ios->clock > SD_SDR25_MAX) + hostctrl2 |= SDHCI_CTRL2_UHS_SDR50; + else if (ios->clock > SD_SDR12_MAX) { + if (ios->timing == bus_timing_uhs_ddr50 || + ios->timing == bus_timing_mmc_ddr52) + hostctrl2 |= SDHCI_CTRL2_UHS_DDR50; + else + hostctrl2 |= SDHCI_CTRL2_UHS_SDR25; + } else if (ios->clock > SD_MMC_CARD_ID_FREQUENCY) + hostctrl2 |= SDHCI_CTRL2_UHS_SDR12; + WR2(slot, SDHCI_HOST_CONTROL2, hostctrl2); + sdhci_set_clock(slot, ios->clock); +} + int sdhci_generic_update_ios(device_t brdev, device_t reqdev) { @@ -846,12 +947,13 @@ sdhci_generic_update_ios(device_t brdev, device_t } else { panic("Invalid bus width: %d", ios->bus_width); } - if (ios->timing == bus_timing_hs && + if (ios->clock > SD_SDR12_MAX && !(slot->quirks & SDHCI_QUIRK_DONT_SET_HISPD_BIT)) slot->hostctrl |= SDHCI_CTRL_HISPD; else slot->hostctrl &= ~SDHCI_CTRL_HISPD; WR1(slot, SDHCI_HOST_CONTROL, slot->hostctrl); + SDHCI_SET_UHS_TIMING(brdev, slot); /* Some controllers like reset after bus changes. */ if (slot->quirks & SDHCI_QUIRK_RESET_ON_IOS) sdhci_reset(slot, SDHCI_RESET_CMD | SDHCI_RESET_DATA); @@ -860,6 +962,61 @@ sdhci_generic_update_ios(device_t brdev, device_t return (0); } +int +sdhci_generic_switch_vccq(device_t brdev __unused, device_t reqdev) +{ + struct sdhci_slot *slot = device_get_ivars(reqdev); + enum mmc_vccq vccq; + int err; + uint16_t hostctrl2; + + if (slot->version < SDHCI_SPEC_300) + return (0); + + err = 0; + vccq = slot->host.ios.vccq; + SDHCI_LOCK(slot); + sdhci_set_clock(slot, 0); + hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); + switch (vccq) { + case vccq_330: + if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE)) + goto done; + hostctrl2 &= ~SDHCI_CTRL2_S18_ENABLE; + WR2(slot, SDHCI_HOST_CONTROL2, hostctrl2); + DELAY(5000); + hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); + if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE)) + goto done; + err = EAGAIN; + break; + case vccq_180: + if (!(slot->host.caps & MMC_CAP_SIGNALING_180)) { + err = EINVAL; + goto done; + } + if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE) + goto done; + hostctrl2 |= SDHCI_CTRL2_S18_ENABLE; + WR2(slot, SDHCI_HOST_CONTROL2, hostctrl2); + DELAY(5000); + hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); + if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE) + goto done; + err = EAGAIN; + break; + default: + slot_printf(slot, + "Attempt to set unsupported signaling voltage\n"); + err = EINVAL; + break; + } +done: + sdhci_set_clock(slot, slot->host.ios.clock); + SDHCI_UNLOCK(slot); + return (err); +} + static void sdhci_req_done(struct sdhci_slot *slot) { @@ -1523,6 +1680,9 @@ sdhci_generic_read_ivar(device_t bus, device_t chi case MMCBR_IVAR_VDD: *result = slot->host.ios.vdd; break; + case MMCBR_IVAR_VCCQ: + *result = slot->host.ios.vccq; + break; case MMCBR_IVAR_CAPS: *result = slot->host.caps; break; @@ -1599,6 +1759,9 @@ sdhci_generic_write_ivar(device_t bus, device_t ch case MMCBR_IVAR_VDD: slot->host.ios.vdd = value; break; + case MMCBR_IVAR_VCCQ: + slot->host.ios.vccq = value; + break; case MMCBR_IVAR_TIMING: slot->host.ios.timing = value; break; Index: sdhci/sdhci.h =================================================================== --- sdhci/sdhci.h (revision 315514) +++ sdhci/sdhci.h (working copy) @@ -77,6 +77,16 @@ #define SDHCI_QUIRK_BOOT_NOACC (1 << 21) /* Controller waits for busy responses. */ #define SDHCI_QUIRK_WAIT_WHILE_BUSY (1 << 22) +/* Controller supports eMMC DDR52 mode. */ +#define SDHCI_QUIRK_MMC_DDR52 (1 << 23) +/* Controller support for UHS DDR50 mode is broken. */ +#define SDHCI_QUIRK_BROKEN_UHS_DDR50 (1 << 24) +/* Controller support for eMMC HS200 mode is broken. */ +#define SDHCI_QUIRK_BROKEN_MMC_HS200 (1 << 25) +/* Controller reports support for eMMC HS400 mode as SDHCI_CAN_MMC_HS400. */ +#define SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 (1 << 26) +/* Controller support for SDHCI_CTRL2_PRESET_VALUE is broken. */ +#define SDHCI_QUIRK_PRESET_VALUE_BROKEN (1 << 27) /* * Controller registers @@ -237,6 +247,7 @@ #define SDHCI_CTRL2_UHS_SDR50 0x0002 #define SDHCI_CTRL2_UHS_SDR104 0x0003 #define SDHCI_CTRL2_UHS_DDR50 0x0004 +#define SDHCI_CTRL2_MMC_HS400 0x0005 /* non-standard */ #define SDHCI_CAPABILITIES 0x40 #define SDHCI_TIMEOUT_CLK_MASK 0x0000003F @@ -276,6 +287,7 @@ #define SDHCI_RETUNE_MODES_SHIFT 14 #define SDHCI_CLOCK_MULT_MASK 0x00FF0000 #define SDHCI_CLOCK_MULT_SHIFT 16 +#define SDHCI_CAN_MMC_HS400 0x80000000 /* non-standard */ #define SDHCI_MAX_CURRENT 0x48 #define SDHCI_FORCE_AUTO_EVENT 0x50 @@ -308,9 +320,13 @@ SYSCTL_DECL(_hw_sdhci); +extern u_int sdhci_quirk_clear; +extern u_int sdhci_quirk_set; + struct sdhci_slot { u_int quirks; /* Chip specific quirks */ u_int caps; /* Override SDHCI_CAPABILITIES */ + u_int caps2; /* Override SDHCI_CAPABILITIES2 */ device_t bus; /* Bus device */ device_t dev; /* Slot device */ u_char num; /* Slot number */ @@ -363,6 +379,7 @@ int sdhci_cleanup_slot(struct sdhci_slot *slot); int sdhci_generic_suspend(struct sdhci_slot *slot); int sdhci_generic_resume(struct sdhci_slot *slot); int sdhci_generic_update_ios(device_t brdev, device_t reqdev); +int sdhci_generic_switch_vccq(device_t brdev, device_t reqdev); int sdhci_generic_request(device_t brdev, device_t reqdev, struct mmc_request *req); int sdhci_generic_get_ro(device_t brdev, device_t reqdev); @@ -371,6 +388,7 @@ int sdhci_generic_release_host(device_t brdev, dev void sdhci_generic_intr(struct sdhci_slot *slot); uint32_t sdhci_generic_min_freq(device_t brdev, struct sdhci_slot *slot); bool sdhci_generic_get_card_present(device_t brdev, struct sdhci_slot *slot); +void sdhci_generic_set_uhs_timing(device_t brdev, struct sdhci_slot *slot); void sdhci_handle_card_present(struct sdhci_slot *slot, bool is_present); #endif /* __SDHCI_H__ */ Index: sdhci/sdhci_acpi.c =================================================================== --- sdhci/sdhci_acpi.c (revision 315514) +++ sdhci/sdhci_acpi.c (working copy) @@ -60,11 +60,16 @@ static const struct sdhci_acpi_device { { "80860F14", 1, "Intel Bay Trail eMMC 4.5 Controller", SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE | SDHCI_QUIRK_INTEL_POWER_UP_RESET | - SDHCI_QUIRK_WAIT_WHILE_BUSY }, + SDHCI_QUIRK_WAIT_WHILE_BUSY | + SDHCI_QUIRK_MMC_DDR52 | + SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 | + SDHCI_QUIRK_PRESET_VALUE_BROKEN }, { "80860F14", 3, "Intel Bay Trail SDXC Controller", - SDHCI_QUIRK_WAIT_WHILE_BUSY }, + SDHCI_QUIRK_WAIT_WHILE_BUSY | + SDHCI_QUIRK_PRESET_VALUE_BROKEN }, { "80860F16", 0, "Intel Bay Trail SDXC Controller", - SDHCI_QUIRK_WAIT_WHILE_BUSY }, + SDHCI_QUIRK_WAIT_WHILE_BUSY | + SDHCI_QUIRK_PRESET_VALUE_BROKEN }, { NULL, 0, NULL, 0} }; @@ -244,6 +249,8 @@ sdhci_acpi_attach(device_t dev) return (ENOMEM); } + sc->quirks &= ~sdhci_quirk_clear; + sc->quirks |= sdhci_quirk_set; sc->slot.quirks = sc->quirks; err = sdhci_init_slot(dev, &sc->slot, 0); @@ -344,12 +351,13 @@ static device_method_t sdhci_methods[] = { /* mmcbr_if */ DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios), + DEVMETHOD(mmcbr_switch_vccq, sdhci_generic_switch_vccq), DEVMETHOD(mmcbr_request, sdhci_generic_request), DEVMETHOD(mmcbr_get_ro, sdhci_generic_get_ro), DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), - /* SDHCI registers accessors */ + /* SDHCI accessors */ DEVMETHOD(sdhci_read_1, sdhci_acpi_read_1), DEVMETHOD(sdhci_read_2, sdhci_acpi_read_2), DEVMETHOD(sdhci_read_4, sdhci_acpi_read_4), @@ -358,6 +366,7 @@ static device_method_t sdhci_methods[] = { DEVMETHOD(sdhci_write_2, sdhci_acpi_write_2), DEVMETHOD(sdhci_write_4, sdhci_acpi_write_4), DEVMETHOD(sdhci_write_multi_4, sdhci_acpi_write_multi_4), + DEVMETHOD(sdhci_set_uhs_timing, sdhci_generic_set_uhs_timing), DEVMETHOD_END }; Index: sdhci/sdhci_if.m =================================================================== --- sdhci/sdhci_if.m (revision 315514) +++ sdhci/sdhci_if.m (working copy) @@ -66,6 +66,15 @@ #include #include +CODE { + static void + null_set_uhs_timing(device_t brdev __unused, + struct sdhci_slot *slot __unused) + { + + } +} + INTERFACE sdhci; METHOD uint8_t read_1 { @@ -149,3 +158,7 @@ METHOD bool get_card_present { struct sdhci_slot *slot; } DEFAULT sdhci_generic_get_card_present; +METHOD void set_uhs_timing { + device_t brdev; + struct sdhci_slot *slot; +} DEFAULT null_set_uhs_timing; Index: sdhci/sdhci_pci.c =================================================================== --- sdhci/sdhci_pci.c (revision 315514) +++ sdhci/sdhci_pci.c (working copy) @@ -106,26 +106,41 @@ static const struct sdhci_device { { 0x0f148086, 0xffff, "Intel Bay Trail eMMC 4.5 Controller", SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE | SDHCI_QUIRK_INTEL_POWER_UP_RESET | - SDHCI_QUIRK_WAIT_WHILE_BUSY }, + SDHCI_QUIRK_WAIT_WHILE_BUSY | + SDHCI_QUIRK_MMC_DDR52 | + SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 | + SDHCI_QUIRK_PRESET_VALUE_BROKEN}, { 0x0f158086, 0xffff, "Intel Bay Trail SDXC Controller", - SDHCI_QUIRK_WAIT_WHILE_BUSY }, + SDHCI_QUIRK_WAIT_WHILE_BUSY | + SDHCI_QUIRK_PRESET_VALUE_BROKEN }, { 0x0f508086, 0xffff, "Intel Bay Trail eMMC 4.5 Controller", SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE | SDHCI_QUIRK_INTEL_POWER_UP_RESET | - SDHCI_QUIRK_WAIT_WHILE_BUSY }, + SDHCI_QUIRK_WAIT_WHILE_BUSY | + SDHCI_QUIRK_MMC_DDR52 | + SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 | + SDHCI_QUIRK_PRESET_VALUE_BROKEN }, { 0x22948086, 0xffff, "Intel Braswell eMMC 4.5.1 Controller", SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE | SDHCI_QUIRK_DATA_TIMEOUT_1MHZ | SDHCI_QUIRK_INTEL_POWER_UP_RESET | - SDHCI_QUIRK_WAIT_WHILE_BUSY }, + SDHCI_QUIRK_WAIT_WHILE_BUSY | + SDHCI_QUIRK_MMC_DDR52 | + SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 | + SDHCI_QUIRK_PRESET_VALUE_BROKEN }, { 0x22968086, 0xffff, "Intel Braswell SDXC Controller", - SDHCI_QUIRK_WAIT_WHILE_BUSY }, + SDHCI_QUIRK_WAIT_WHILE_BUSY | + SDHCI_QUIRK_PRESET_VALUE_BROKEN }, { 0x5aca8086, 0xffff, "Intel Apollo Lake SDXC Controller", - SDHCI_QUIRK_WAIT_WHILE_BUSY }, + SDHCI_QUIRK_WAIT_WHILE_BUSY | + SDHCI_QUIRK_PRESET_VALUE_BROKEN }, { 0x5acc8086, 0xffff, "Intel Apollo Lake eMMC 5.0 Controller", SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE | SDHCI_QUIRK_INTEL_POWER_UP_RESET | - SDHCI_QUIRK_WAIT_WHILE_BUSY }, + SDHCI_QUIRK_WAIT_WHILE_BUSY | + SDHCI_QUIRK_MMC_DDR52 | + SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 | + SDHCI_QUIRK_PRESET_VALUE_BROKEN }, { 0, 0xffff, NULL, 0 } }; @@ -323,6 +338,8 @@ sdhci_pci_attach(device_t dev) break; } } + sc->quirks &= ~sdhci_quirk_clear; + sc->quirks |= sdhci_quirk_set; /* Some controllers need to be bumped into the right mode. */ if (sc->quirks & SDHCI_QUIRK_LOWER_FREQUENCY) sdhci_lower_frequency(dev); @@ -468,12 +485,13 @@ static device_method_t sdhci_methods[] = { /* mmcbr_if */ DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios), + DEVMETHOD(mmcbr_switch_vccq, sdhci_generic_switch_vccq), DEVMETHOD(mmcbr_request, sdhci_generic_request), DEVMETHOD(mmcbr_get_ro, sdhci_generic_get_ro), DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), - /* SDHCI registers accessors */ + /* SDHCI accessors */ DEVMETHOD(sdhci_read_1, sdhci_pci_read_1), DEVMETHOD(sdhci_read_2, sdhci_pci_read_2), DEVMETHOD(sdhci_read_4, sdhci_pci_read_4), @@ -482,6 +500,7 @@ static device_method_t sdhci_methods[] = { DEVMETHOD(sdhci_write_2, sdhci_pci_write_2), DEVMETHOD(sdhci_write_4, sdhci_pci_write_4), DEVMETHOD(sdhci_write_multi_4, sdhci_pci_write_multi_4), + DEVMETHOD(sdhci_set_uhs_timing, sdhci_generic_set_uhs_timing), DEVMETHOD_END };