Skip to content

Commit

Permalink
mmccam: Add support for 1.2V and 1.8V eMMC
Browse files Browse the repository at this point in the history
If the card reports that it support 1.2V or 1.8V signaling switch to this voltage.

Submitted by:	kibab
  • Loading branch information
evadot committed Jul 22, 2020
1 parent 2657d8e commit fd7371f
Showing 1 changed file with 71 additions and 4 deletions.
75 changes: 71 additions & 4 deletions sys/cam/mmc/mmc_da.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -1391,6 +1418,46 @@ sdda_start_init(void *context, union ccb *start_ccb)
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;
Expand Down

0 comments on commit fd7371f

Please sign in to comment.