Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Jul 2020 19:08:05 +0000 (UTC)
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r363428 - head/sys/cam/mmc
Message-ID:  <202007221908.06MJ85q9089506@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: manu
Date: Wed Jul 22 19:08:05 2020
New Revision: 363428
URL: https://svnweb.freebsd.org/changeset/base/363428

Log:
  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

Modified:
  head/sys/cam/mmc/mmc_da.c

Modified: head/sys/cam/mmc/mmc_da.c
==============================================================================
--- head/sys/cam/mmc/mmc_da.c	Wed Jul 22 19:04:45 2020	(r363427)
+++ head/sys/cam/mmc/mmc_da.c	Wed Jul 22 19:08:05 2020	(r363428)
@@ -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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007221908.06MJ85q9089506>