Module Name:    src
Committed By:   jmcneill
Date:           Sun Dec  7 20:07:25 UTC 2014

Modified Files:
        src/sys/dev/sdmmc: sdmmc_mem.c sdmmcreg.h

Log Message:
Fix high capacity (> 2GB) eMMC support, from OpenBSD.


To generate a diff of this commit:
cvs rdiff -u -r1.31 -r1.32 src/sys/dev/sdmmc/sdmmc_mem.c
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/sdmmc/sdmmcreg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/sdmmc/sdmmc_mem.c
diff -u src/sys/dev/sdmmc/sdmmc_mem.c:1.31 src/sys/dev/sdmmc/sdmmc_mem.c:1.32
--- src/sys/dev/sdmmc/sdmmc_mem.c:1.31	Wed Mar 19 15:26:42 2014
+++ src/sys/dev/sdmmc/sdmmc_mem.c	Sun Dec  7 20:07:25 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdmmc_mem.c,v 1.31 2014/03/19 15:26:42 nonaka Exp $	*/
+/*	$NetBSD: sdmmc_mem.c,v 1.32 2014/12/07 20:07:25 jmcneill Exp $	*/
 /*	$OpenBSD: sdmmc_mem.c,v 1.10 2009/01/09 10:55:22 jsg Exp $	*/
 
 /*
@@ -45,7 +45,7 @@
 /* Routines for SD/MMC memory cards. */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.31 2014/03/19 15:26:42 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.32 2014/12/07 20:07:25 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -171,6 +171,9 @@ mmc_mode:
 	/* Tell the card(s) to enter the idle state (again). */
 	sdmmc_go_idle_state(sc);
 
+	DPRINTF(("%s: host_ocr 0x%08x\n", SDMMCDEVNAME(sc), host_ocr));
+	DPRINTF(("%s: card_ocr 0x%08x\n", SDMMCDEVNAME(sc), card_ocr));
+
 	host_ocr &= card_ocr; /* only allow the common voltages */
 	if (!ISSET(sc->sc_caps, SMC_CAPS_SPI_MODE)) {
 		/* Check SD Ver.2 */
@@ -493,6 +496,9 @@ sdmmc_mem_send_op_cond(struct sdmmc_soft
 
 	/* Don't lock */
 
+	DPRINTF(("%s: sdmmc_mem_send_op_cond: ocr=%#x\n",
+	    SDMMCDEVNAME(sc), ocr));
+
 	/*
 	 * If we change the OCR value, retry the command until the OCR
 	 * we receive in response has the "CARD BUSY" bit set, meaning
@@ -719,6 +725,7 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *s
 {
 	int width, value, hs_timing, bus_clock, error;
 	char ext_csd[512];
+	uint32_t sectors = 0;
 
 	/* change bus clock */
 	bus_clock = min(sc->sc_busclk, sf->csd.tran_speed);
@@ -743,21 +750,14 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *s
 				ext_csd[EXT_CSD_STRUCTURE]);
 			return error;
 		}
-		hs_timing = 0;
-		switch (ext_csd[EXT_CSD_CARD_TYPE]) {
-		case EXT_CSD_CARD_TYPE_26M:
-			sf->csd.tran_speed = 26000;	/* 26MHz */
-			break;
 
-		case EXT_CSD_CARD_TYPE_52M:
-		case EXT_CSD_CARD_TYPE_52M_V18:
-		case EXT_CSD_CARD_TYPE_52M_V12:
-		case EXT_CSD_CARD_TYPE_52M_V12_18:
+		if (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_F_52M) {
 			sf->csd.tran_speed = 52000;	/* 52MHz */
 			hs_timing = 1;
-			break;
-
-		default:
+		} else if (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_F_26M) {
+			sf->csd.tran_speed = 26000;	/* 26MHz */
+			hs_timing = 0;
+		} else {
 			aprint_error_dev(sc->sc_dev,
 			    "unknown CARD_TYPE: 0x%x\n",
 			    ext_csd[EXT_CSD_CARD_TYPE]);
@@ -804,6 +804,15 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *s
 			}
 		}
 
+		sectors = ext_csd[EXT_CSD_SEC_COUNT + 0] << 0 |
+		    ext_csd[EXT_CSD_SEC_COUNT + 1] << 8  |
+		    ext_csd[EXT_CSD_SEC_COUNT + 2] << 16 |
+		    ext_csd[EXT_CSD_SEC_COUNT + 3] << 24;
+		if (sectors > (2u * 1024 * 1024 * 1024) / 512) {
+			SET(sf->flags, SFF_SDHC);
+			sf->csd.capacity = sectors;
+		}
+
 		if (ISSET(sc->sc_caps, SMC_CAPS_8BIT_MODE)) {
 			width = 8;
 			value = EXT_CSD_BUS_WIDTH_8;

Index: src/sys/dev/sdmmc/sdmmcreg.h
diff -u src/sys/dev/sdmmc/sdmmcreg.h:1.14 src/sys/dev/sdmmc/sdmmcreg.h:1.15
--- src/sys/dev/sdmmc/sdmmcreg.h:1.14	Fri May  3 16:38:35 2013
+++ src/sys/dev/sdmmc/sdmmcreg.h	Sun Dec  7 20:07:25 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdmmcreg.h,v 1.14 2013/05/03 16:38:35 matt Exp $	*/
+/*	$NetBSD: sdmmcreg.h,v 1.15 2014/12/07 20:07:25 jmcneill Exp $	*/
 /*	$OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $	*/
 
 /*
@@ -115,6 +115,7 @@
 #define EXT_CSD_REV			192	/* RO */
 #define EXT_CSD_STRUCTURE		194	/* RO */
 #define EXT_CSD_CARD_TYPE		196	/* RO */
+#define EXT_CSD_SEC_COUNT		212	/* RO */
 
 /* EXT_CSD field definitions */
 #define EXT_CSD_CMD_SET_NORMAL		(1U << 0)

Reply via email to