Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154536333
D15568.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D15568.id.diff
View Options
Index: head/sys/cam/mmc/mmc_da.c
===================================================================
--- head/sys/cam/mmc/mmc_da.c
+++ head/sys/cam/mmc/mmc_da.c
@@ -171,7 +171,7 @@
static void sdda_process_mmc_partitions(struct cam_periph *periph, union ccb *start_ccb);
static uint32_t sdda_get_host_caps(struct cam_periph *periph, union ccb *ccb);
static void sdda_init_switch_part(struct cam_periph *periph, union ccb *start_ccb, u_int part);
-
+static int mmc_select_card(struct cam_periph *periph, union ccb *ccb, uint32_t rca);
static inline uint32_t mmc_get_sector_size(struct cam_periph *periph) {return MMC_SECTOR_SIZE;}
/* TODO: actually issue GET_TRAN_SETTINGS to get R/O status */
@@ -901,6 +901,38 @@
}
static int
+mmc_select_card(struct cam_periph *periph, union ccb *ccb, uint32_t rca)
+{
+ int flags;
+
+ flags = (rca ? MMC_RSP_R1B : MMC_RSP_NONE) | MMC_CMD_AC;
+ cam_fill_mmcio(&ccb->mmcio,
+ /*retries*/ 0,
+ /*cbfcnp*/ NULL,
+ /*flags*/ CAM_DIR_IN,
+ /*mmc_opcode*/ MMC_SELECT_CARD,
+ /*mmc_arg*/ rca << 16,
+ /*mmc_flags*/ flags,
+ /*mmc_data*/ NULL,
+ /*timeout*/ 0);
+
+ cam_periph_runccb(ccb, sddaerror, CAM_FLAG_NONE, /*sense_flags*/0, NULL);
+
+ if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)) {
+ if (ccb->mmcio.cmd.error != 0) {
+ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_PERIPH,
+ ("%s: MMC_SELECT command failed", __func__));
+ return EIO;
+ }
+ return 0; /* Normal return */
+ } else {
+ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_PERIPH,
+ ("%s: CAM request failed\n", __func__));
+ return EIO;
+ }
+}
+
+static int
mmc_switch(struct cam_periph *periph, union ccb *ccb,
uint8_t set, uint8_t index, uint8_t value, u_int timeout)
{
@@ -953,18 +985,24 @@
uint8_t *res) {
struct mmc_data mmc_d;
+ uint32_t arg;
memset(res, 0, 64);
mmc_d.len = 64;
mmc_d.data = res;
mmc_d.flags = MMC_DATA_READ;
+ arg = mode << 31; /* 0 - check, 1 - set */
+ arg |= 0x00FFFFFF;
+ arg &= ~(0xF << (grp * 4));
+ arg |= value << (grp * 4);
+
cam_fill_mmcio(&ccb->mmcio,
/*retries*/ 0,
/*cbfcnp*/ NULL,
/*flags*/ CAM_DIR_IN,
/*mmc_opcode*/ SD_SWITCH_FUNC,
- /*mmc_arg*/ mode << 31,
+ /*mmc_arg*/ arg,
/*mmc_flags*/ MMC_RSP_R1 | MMC_CMD_ADTC,
/*mmc_data*/ &mmc_d,
/*timeout*/ 0);
@@ -1273,6 +1311,19 @@
CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Card supports HS\n"));
softc->card_f_max = SD_HS_MAX;
}
+
+ /*
+ * We deselect then reselect the card here. Some cards
+ * become unselected and timeout with the above two
+ * commands, although the state tables / diagrams in the
+ * standard suggest they go back to the transfer state.
+ * Other cards don't become deselected, and if we
+ * attempt to blindly re-select them, we get timeout
+ * errors from some controllers. So we deselect then
+ * reselect to handle all situations.
+ */
+ mmc_select_card(periph, start_ccb, 0);
+ mmc_select_card(periph, start_ccb, get_rca(periph));
} else {
CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Not trying the switch\n"));
goto finish_hs_tests;
@@ -1293,6 +1344,15 @@
f_max = min(host_f_max, softc->card_f_max);
CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Set SD freq to %d MHz (min out of host f=%d MHz and card f=%d MHz)\n", f_max / 1000000, host_f_max / 1000000, softc->card_f_max / 1000000));
+ /* Enable high-speed timing on the card */
+ if (f_max > 25000000) {
+ err = mmc_set_timing(periph, start_ccb, bus_timing_hs);
+ if (err != MMC_ERR_NONE) {
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("Cannot switch card to high-speed mode"));
+ f_max = 25000000;
+ }
+ }
+ /* Set frequency on the controller */
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;
@@ -1326,12 +1386,6 @@
bus_width_str(max_host_bus_width),
bus_width_str(max_card_bus_width)));
sdda_set_bus_width(periph, start_ccb, desired_bus_width);
-
- if (f_max > 25000000) {
- err = mmc_set_timing(periph, start_ccb, bus_timing_hs);
- if (err != MMC_ERR_NONE)
- CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("Cannot switch card to high-speed mode"));
- }
softc->state = SDDA_STATE_NORMAL;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 29, 8:53 PM (1 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32307874
Default Alt Text
D15568.id.diff (4 KB)
Attached To
Mode
D15568: Enable high-speed on the card before increasing frequency on the controller
Attached
Detach File
Event Timeline
Log In to Comment