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

This commit is contained in:
jmcneill 2014-12-07 20:07:25 +00:00
parent 6b9fc55df2
commit 6440e1fef5
2 changed files with 25 additions and 15 deletions

View File

@ -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_softc *sc, uint32_t ocr, uint32_t *ocrp)
/* 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 *sc, struct sdmmc_function *sf)
{
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 *sc, struct sdmmc_function *sf)
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 *sc, struct sdmmc_function *sf)
}
}
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;

View File

@ -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)