Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/sdmmc Support High-Speed mode.
details: https://anonhg.NetBSD.org/src/rev/9c0b8d995e09
branches: trunk
changeset: 757960:9c0b8d995e09
user: kiyohara <kiyohara%NetBSD.org@localhost>
date: Thu Oct 07 12:24:23 2010 +0000
description:
Support High-Speed mode.
diffstat:
sys/dev/sdmmc/sdmmc.c | 18 +-
sys/dev/sdmmc/sdmmc_io.c | 15 +-
sys/dev/sdmmc/sdmmc_mem.c | 373 +++++++++++++++++++++++++++++++++++++--------
sys/dev/sdmmc/sdmmcreg.h | 36 +++-
sys/dev/sdmmc/sdmmcvar.h | 7 +-
5 files changed, 354 insertions(+), 95 deletions(-)
diffs (truncated from 673 to 300 lines):
diff -r 9dfc8487f01b -r 9c0b8d995e09 sys/dev/sdmmc/sdmmc.c
--- a/sys/dev/sdmmc/sdmmc.c Thu Oct 07 12:06:09 2010 +0000
+++ b/sys/dev/sdmmc/sdmmc.c Thu Oct 07 12:24:23 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmc.c,v 1.4 2010/10/01 09:50:42 kiyohara Exp $ */
+/* $NetBSD: sdmmc.c,v 1.5 2010/10/07 12:24:23 kiyohara Exp $ */
/* $OpenBSD: sdmmc.c,v 1.18 2009/01/09 10:58:38 jsg Exp $ */
/*
@@ -50,7 +50,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.4 2010/10/01 09:50:42 kiyohara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.5 2010/10/07 12:24:23 kiyohara Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -369,20 +369,6 @@
goto err;
}
- /*
- * Set SD/MMC bus clock.
- */
-#ifdef SDMMC_DEBUG
- if ((sc->sc_busclk / 1000) != 0) {
- DPRINTF(1,("%s: bus clock: %u.%03u MHz\n", DEVNAME(sc),
- sc->sc_busclk / 1000, sc->sc_busclk % 1000));
- } else {
- DPRINTF(1,("%s: bus clock: %u KHz\n", DEVNAME(sc),
- sc->sc_busclk % 1000));
- }
-#endif
- (void)sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, sc->sc_busclk);
-
SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
if (ISSET(sc->sc_flags, SMF_IO_MODE) && sf->number < 1)
continue;
diff -r 9dfc8487f01b -r 9c0b8d995e09 sys/dev/sdmmc/sdmmc_io.c
--- a/sys/dev/sdmmc/sdmmc_io.c Thu Oct 07 12:06:09 2010 +0000
+++ b/sys/dev/sdmmc/sdmmc_io.c Thu Oct 07 12:24:23 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmc_io.c,v 1.2 2009/12/05 22:34:43 pooka Exp $ */
+/* $NetBSD: sdmmc_io.c,v 1.3 2010/10/07 12:24:23 kiyohara Exp $ */
/* $OpenBSD: sdmmc_io.c,v 1.10 2007/09/17 01:33:33 krw Exp $ */
/*
@@ -20,7 +20,7 @@
/* Routines for SD I/O cards. */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdmmc_io.c,v 1.2 2009/12/05 22:34:43 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_io.c,v 1.3 2010/10/07 12:24:23 kiyohara Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -158,6 +158,9 @@
sc->sc_fn0 = sf0;
SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf0, sf_list);
+ /* Go to Data Transfer Mode, if possible. */
+ sdmmc_chip_bus_rod(sc->sc_sct, sc->sc_sch, 0);
+
/* Verify that the RCA has been set by selecting the card. */
error = sdmmc_select_card(sc, sf0);
if (error) {
@@ -204,6 +207,14 @@
if (sdmmcdebug)
sdmmc_print_cis(sf);
#endif
+
+ if (sc->sc_busclk > sf->csd.tran_speed)
+ sc->sc_busclk = sf->csd.tran_speed;
+ error =
+ sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, sc->sc_busclk);
+ if (error)
+ aprint_error_dev(sc->sc_dev,
+ "can't change bus clock\n");
}
out:
diff -r 9dfc8487f01b -r 9c0b8d995e09 sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Thu Oct 07 12:06:09 2010 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Thu Oct 07 12:24:23 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmc_mem.c,v 1.12 2010/10/01 09:50:42 kiyohara Exp $ */
+/* $NetBSD: sdmmc_mem.c,v 1.13 2010/10/07 12:24:23 kiyohara Exp $ */
/* $OpenBSD: sdmmc_mem.c,v 1.10 2009/01/09 10:55:22 jsg Exp $ */
/*
@@ -46,7 +46,7 @@
/* Routines for SD/MMC memory cards. */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.12 2010/10/01 09:50:42 kiyohara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.13 2010/10/07 12:24:23 kiyohara Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -66,6 +66,8 @@
#define DPRINTF(s) do {} while (/*CONSTCOND*/0)
#endif
+static int sdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *);
+static int sdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *);
static int sdmmc_mem_send_cid(struct sdmmc_softc *, sdmmc_response *);
static int sdmmc_mem_send_csd(struct sdmmc_softc *, struct sdmmc_function *,
sdmmc_response *);
@@ -74,6 +76,7 @@
static int sdmmc_mem_decode_scr(struct sdmmc_softc *, struct sdmmc_function *);
static int sdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void *, size_t);
static int sdmmc_set_bus_width(struct sdmmc_function *, int);
+static int sdmmc_mem_sd_switch(struct sdmmc_function *, int, int, int, void *);
static int sdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t,
uint8_t);
static int sdmmc_mem_spi_read_ocr(struct sdmmc_softc *, uint32_t, uint32_t *);
@@ -253,6 +256,10 @@
break;
}
+ if (!ISSET(sc->sc_caps, SMC_CAPS_SPI_MODE))
+ /* Go to Data Transfer Mode, if possible. */
+ sdmmc_chip_bus_rod(sc->sc_sct, sc->sc_sch, 0);
+
/*
* All cards are either inactive or awaiting further commands.
* Read the CSDs and decode the raw CID for each card.
@@ -313,6 +320,7 @@
SET(sf->flags, SFF_SDHC);
csd->capacity = SD_CSD_V2_CAPACITY(resp);
csd->read_bl_len = SD_CSD_V2_BL_LEN;
+ csd->ccc = SD_CSD_CCC(resp);
break;
case SD_CSD_CSDVER_1_0:
@@ -356,9 +364,6 @@
if ((1 << csd->read_bl_len) > SDMMC_SECTOR_SIZE)
csd->capacity *= (1 << csd->read_bl_len) / SDMMC_SECTOR_SIZE;
- if (sc->sc_busclk > csd->tran_speed)
- sc->sc_busclk = csd->tran_speed;
-
#ifdef SDMMC_DUMP_CSD
sdmmc_print_csd(resp, csd);
#endif
@@ -436,7 +441,7 @@
int
sdmmc_mem_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
{
- int width, value, error = 0;
+ int error = 0;
SDMMC_LOCK(sc);
@@ -452,58 +457,10 @@
goto out;
}
- /* change bus width if supported */
- sf->width = 1;
- if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
- error = sdmmc_mem_send_scr(sc, sf, sf->raw_scr);
- if (error) {
- DPRINTF(("%s: SD_SEND_SCR send failed.\n",
- SDMMCDEVNAME(sc)));
- goto out;
- }
- error = sdmmc_mem_decode_scr(sc, sf);
- if (error)
- goto out;
-
- if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE) &&
- ISSET(sf->scr.bus_width, SCR_SD_BUS_WIDTHS_4BIT)) {
- error = sdmmc_set_bus_width(sf, 4);
- if (error) {
- DPRINTF(("%s: can't change bus width"
- " (%d bit)\n", SDMMCDEVNAME(sc), 4));
- goto out;
- }
- sf->width = 4;
- }
- } else if (sf->csd.mmcver >= MMC_CSD_MMCVER_4_0) {
- if (ISSET(sc->sc_caps, SMC_CAPS_8BIT_MODE)) {
- width = 8;
- value = EXT_CSD_BUS_WIDTH_8;
- } else if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE)) {
- width = 4;
- value = EXT_CSD_BUS_WIDTH_4;
- } else {
- width = 1;
- value = EXT_CSD_BUS_WIDTH_1;
- }
-
- if (width != 1) {
- error = sdmmc_mem_mmc_switch(sf, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH, value);
- if (error == 0)
- error = sdmmc_chip_bus_width(sc->sc_sct,
- sc->sc_sch, width);
- else {
- DPRINTF(("%s: can't change bus width"
- " (%d bit)\n", SDMMCDEVNAME(sc), width));
- goto out;
- }
-
- /* XXXX: need bus test? (using by CMD14 & CMD19) */
-
- sf->width = width;
- }
- }
+ if (ISSET(sc->sc_flags, SMF_SD_MODE))
+ error = sdmmc_mem_sd_init(sc, sf);
+ else
+ error = sdmmc_mem_mmc_init(sc, sf);
out:
SDMMC_UNLOCK(sc);
@@ -617,6 +574,215 @@
}
static int
+sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
+{
+ struct {
+ int v;
+ int freq;
+ } switch_group0_functions [] = {
+ /* Default/SDR12 */
+ { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V |
+ MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V, 25000 },
+
+ /* High-Speed/SDR25 */
+ { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V |
+ MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V, 50000 },
+
+ /* SDR50 */
+ { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 100000 },
+
+ /* SDR104 */
+ { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 208000 },
+
+ /* DDR50 */
+ { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 50000 },
+ };
+ int host_ocr, support_func, best_func, error, g, i;
+ char status[64];
+
+ error = sdmmc_mem_send_scr(sc, sf, sf->raw_scr);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "SD_SEND_SCR send failed.\n");
+ return error;
+ }
+ error = sdmmc_mem_decode_scr(sc, sf);
+ if (error)
+ return error;
+
+ if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE) &&
+ ISSET(sf->scr.bus_width, SCR_SD_BUS_WIDTHS_4BIT)) {
+ error = sdmmc_set_bus_width(sf, 4);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "can't change bus width (%d bit)\n", 4);
+ return error;
+ }
+ sf->width = 4;
+ } else
+ sf->width = 1;
+
+ if (sf->scr.sd_spec >= SCR_SD_SPEC_VER_1_10 &&
+ ISSET(sf->csd.ccc, SD_CSD_CCC_SWITCH)) {
+ error = sdmmc_mem_sd_switch(sf, 0, 1, 0, status);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "switch func mode 0 failed\n");
+ return error;
+ }
+
+ host_ocr = sdmmc_chip_host_ocr(sc->sc_sct, sc->sc_sch);
+ support_func = SFUNC_STATUS_GROUP(status, 1);
+ best_func = 0;
+ for (i = 0, g = 1;
+ i < __arraycount(switch_group0_functions); i++, g <<= 1) {
+ if (!(switch_group0_functions[i].v & host_ocr))
+ continue;
+ if (g & support_func)
+ best_func = i;
+ }
+ if (best_func != 0) {
+ error =
+ sdmmc_mem_sd_switch(sf, 1, 1, best_func, status);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "switch func mode 1 failed:"
+ " group 1 function %d(0x%2x)\n",
+ best_func, support_func);
+ return error;
+ }
+ sf->csd.tran_speed =
+ switch_group0_functions[best_func].freq;
Home |
Main Index |
Thread Index |
Old Index