diff options
author | Emmanuel Vadot <manu@FreeBSD.org> | 2020-07-22 19:08:05 +0000 |
---|---|---|
committer | Emmanuel Vadot <manu@FreeBSD.org> | 2020-07-22 19:08:05 +0000 |
commit | fd7371f7e20010606e76ebd0fe9e609772ebbcf4 (patch) | |
tree | db112504dd368cd78077f7cd52fad396b9a577e9 /sys | |
parent | 2657d8e33e4ecf6f17aa17b67fd6bba73eeed942 (diff) | |
download | src-fd7371f7e20010606e76ebd0fe9e609772ebbcf4.tar.gz src-fd7371f7e20010606e76ebd0fe9e609772ebbcf4.zip |
mmccam: Add support for 1.2V and 1.8V eMMC
If the card reports that it support 1.2V or 1.8V signaling switch to this voltage.
Submitted by: kibab
Notes
Notes:
svn path=/head/; revision=363428
Diffstat (limited to 'sys')
-rw-r--r-- | sys/cam/mmc/mmc_da.c | 75 |
1 files changed, 71 insertions, 4 deletions
diff --git a/sys/cam/mmc/mmc_da.c b/sys/cam/mmc/mmc_da.c index 6fd6e7b76e9a..3e407013d5cf 100644 --- a/sys/cam/mmc/mmc_da.c +++ b/sys/cam/mmc/mmc_da.c @@ -136,6 +136,9 @@ struct sdda_softc { /* Generic switch timeout */ uint32_t cmd6_time; + 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 */ /* MMC partitions support */ struct sdda_part *part[MMC_PART_MAX]; uint8_t part_curr; /* Partition currently switched to */ @@ -1242,6 +1245,7 @@ sdda_start_init(void *context, union ccb *start_ccb) uint32_t sec_count; int err; int host_f_max; + uint8_t card_type; CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sdda_start_init\n")); /* periph was held for us when this task was enqueued */ @@ -1370,12 +1374,35 @@ sdda_start_init(void *context, union ccb *start_ccb) } if (mmcp->card_features & CARD_FEATURE_MMC && mmc_get_spec_vers(periph) >= 4) { - if (softc->raw_ext_csd[EXT_CSD_CARD_TYPE] - & EXT_CSD_CARD_TYPE_HS_52) + card_type = softc->raw_ext_csd[EXT_CSD_CARD_TYPE]; + if (card_type & EXT_CSD_CARD_TYPE_HS_52) softc->card_f_max = MMC_TYPE_HS_52_MAX; - else if (softc->raw_ext_csd[EXT_CSD_CARD_TYPE] - & EXT_CSD_CARD_TYPE_HS_26) + else if (card_type & EXT_CSD_CARD_TYPE_HS_26) softc->card_f_max = MMC_TYPE_HS_26_MAX; + if ((card_type & EXT_CSD_CARD_TYPE_DDR_52_1_2V) != 0 && + (host_caps & MMC_CAP_SIGNALING_120) != 0) { + setbit(&softc->timings, bus_timing_mmc_ddr52); + setbit(&softc->vccq_120, bus_timing_mmc_ddr52); + CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Card supports DDR52 at 1.2V\n")); + } + if ((card_type & EXT_CSD_CARD_TYPE_DDR_52_1_8V) != 0 && + (host_caps & MMC_CAP_SIGNALING_180) != 0) { + setbit(&softc->timings, bus_timing_mmc_ddr52); + setbit(&softc->vccq_180, bus_timing_mmc_ddr52); + CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Card supports DDR52 at 1.8V\n")); + } + if ((card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) != 0 && + (host_caps & MMC_CAP_SIGNALING_120) != 0) { + setbit(&softc->timings, bus_timing_mmc_hs200); + setbit(&softc->vccq_120, bus_timing_mmc_hs200); + CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Card supports HS200 at 1.2V\n")); + } + if ((card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) != 0 && + (host_caps & MMC_CAP_SIGNALING_180) != 0) { + setbit(&softc->timings, bus_timing_mmc_hs200); + setbit(&softc->vccq_180, bus_timing_mmc_hs200); + CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Card supports HS200 at 1.8V\n")); + } } } int f_max; @@ -1391,6 +1418,46 @@ finish_hs_tests: f_max = 25000000; } } + /* If possible, set lower-level signaling */ + enum mmc_bus_timing timing; + /* FIXME: MMCCAM supports max. bus_timing_mmc_ddr52 at the moment. */ + for (timing = bus_timing_mmc_ddr52; timing > bus_timing_normal; timing--) { + if (isset(&softc->vccq_120, timing)) { + /* Set VCCQ = 1.2V */ + start_ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS; + start_ccb->ccb_h.flags = CAM_DIR_NONE; + start_ccb->ccb_h.retry_count = 0; + start_ccb->ccb_h.timeout = 100; + start_ccb->ccb_h.cbfcnp = NULL; + cts->ios.vccq = vccq_120; + cts->ios_valid = MMC_VCCQ; + xpt_action(start_ccb); + break; + } else if (isset(&softc->vccq_180, timing)) { + /* Set VCCQ = 1.8V */ + start_ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS; + start_ccb->ccb_h.flags = CAM_DIR_NONE; + start_ccb->ccb_h.retry_count = 0; + start_ccb->ccb_h.timeout = 100; + start_ccb->ccb_h.cbfcnp = NULL; + cts->ios.vccq = vccq_180; + cts->ios_valid = MMC_VCCQ; + xpt_action(start_ccb); + break; + } else { + /* Set VCCQ = 3.3V */ + start_ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS; + start_ccb->ccb_h.flags = CAM_DIR_NONE; + start_ccb->ccb_h.retry_count = 0; + start_ccb->ccb_h.timeout = 100; + start_ccb->ccb_h.cbfcnp = NULL; + cts->ios.vccq = vccq_330; + cts->ios_valid = MMC_VCCQ; + xpt_action(start_ccb); + break; + } + } + /* Set frequency on the controller */ start_ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS; start_ccb->ccb_h.flags = CAM_DIR_NONE; |