aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuel Vadot <manu@FreeBSD.org>2020-07-22 19:04:45 +0000
committerEmmanuel Vadot <manu@FreeBSD.org>2020-07-22 19:04:45 +0000
commit2657d8e33e4ecf6f17aa17b67fd6bba73eeed942 (patch)
treecc438923ab94c77062f27b87b509576ba6de44fa
parent9bca4667450d83520b3f68ebd87ee67d6a40792f (diff)
downloadsrc-2657d8e33e4ecf6f17aa17b67fd6bba73eeed942.tar.gz
src-2657d8e33e4ecf6f17aa17b67fd6bba73eeed942.zip
mmccam: Add support for 1.8V sdcard
If the card reports that it support 1.8V signaling switch to this voltage. While here update the list of mode for mmccam. Submitted by: kibab
Notes
Notes: svn path=/head/; revision=363427
-rw-r--r--sys/cam/cam_ccb.h33
-rw-r--r--sys/cam/mmc/mmc_xpt.c19
2 files changed, 49 insertions, 3 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 772de3921122..cf5daf653079 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -1046,14 +1046,41 @@ struct ccb_trans_settings_mmc {
#define MMC_PM (1 << 5)
#define MMC_BT (1 << 6)
#define MMC_BM (1 << 7)
+#define MMC_VCCQ (1 << 8)
uint32_t ios_valid;
/* The folowing is used only for GET_TRAN_SETTINGS */
uint32_t host_ocr;
int host_f_min;
int host_f_max;
-#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 */
+/* Copied from sys/dev/mmc/bridge.h */
+#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_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 */
+
uint32_t host_caps;
uint32_t host_max_data;
};
diff --git a/sys/cam/mmc/mmc_xpt.c b/sys/cam/mmc/mmc_xpt.c
index 6e39cffd13ff..ad3ea9d8633c 100644
--- a/sys/cam/mmc/mmc_xpt.c
+++ b/sys/cam/mmc/mmc_xpt.c
@@ -167,6 +167,7 @@ typedef struct {
union ccb saved_ccb;
uint32_t flags;
#define PROBE_FLAG_ACMD_SENT 0x1 /* CMD55 is sent, card expects ACMD */
+#define PROBE_FLAG_HOST_CAN_DO_18V 0x2 /* Host can do 1.8V signaling */
uint8_t acmd41_count; /* how many times ACMD41 has been issued */
struct cam_periph *periph;
} mmcprobe_softc;
@@ -457,6 +458,9 @@ mmc_print_ident(struct mmc_params *ident_data)
sbuf_printf(sb, "%sSDIO", space ? " " : "");
space = true;
}
+ if (ident_data->card_features & CARD_FEATURE_18V) {
+ sbuf_printf(sb, "%s1.8-Signaling", space ? " " : "");
+ }
sbuf_printf(sb, ">\n");
if (ident_data->card_features & CARD_FEATURE_MEMORY)
@@ -636,6 +640,9 @@ mmcprobe_start(struct cam_periph *periph, union ccb *start_ccb)
init_standard_ccb(start_ccb, XPT_GET_TRAN_SETTINGS);
xpt_action(start_ccb);
+ uint32_t host_caps = cts->host_caps;
+ if (host_caps & MMC_CAP_SIGNALING_180)
+ softc->flags |= PROBE_FLAG_HOST_CAN_DO_18V;
uint32_t hv = mmc_highest_voltage(cts->host_ocr);
init_standard_ccb(start_ccb, XPT_SET_TRAN_SETTINGS);
cts->ios.vdd = hv;
@@ -1008,6 +1015,18 @@ mmcprobe_done(struct cam_periph *periph, union ccb *done_ccb)
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE,
("Card supports 1.8V signaling\n"));
mmcp->card_features |= CARD_FEATURE_18V;
+ if (softc->flags & PROBE_FLAG_HOST_CAN_DO_18V) {
+ CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE,
+ ("Host supports 1.8V signaling. Switch voltage!\n"));
+ done_ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+ done_ccb->ccb_h.flags = CAM_DIR_NONE;
+ done_ccb->ccb_h.retry_count = 0;
+ done_ccb->ccb_h.timeout = 100;
+ done_ccb->ccb_h.cbfcnp = NULL;
+ done_ccb->cts.proto_specific.mmc.ios.vccq = vccq_180;
+ done_ccb->cts.proto_specific.mmc.ios_valid = MMC_VCCQ;
+ xpt_action(done_ccb);
+ }
}
} else {
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE,