Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/sdmmc Add support for DDR50 transfer modes.
details: https://anonhg.NetBSD.org/src/rev/e182feb38cca
branches: trunk
changeset: 809830:e182feb38cca
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Aug 03 10:08:51 2015 +0000
description:
Add support for DDR50 transfer modes.
diffstat:
sys/dev/sdmmc/sdhc.c | 36 +++++--
sys/dev/sdmmc/sdmmc.c | 10 +-
sys/dev/sdmmc/sdmmc_io.c | 7 +-
sys/dev/sdmmc/sdmmc_mem.c | 205 ++++++++++++++++++++++++++++-----------------
sys/dev/sdmmc/sdmmcchip.h | 7 +-
sys/dev/sdmmc/sdmmcreg.h | 8 +-
sys/dev/sdmmc/sdmmcvar.h | 9 +-
7 files changed, 179 insertions(+), 103 deletions(-)
diffs (truncated from 607 to 300 lines):
diff -r 2e7c0c1ad0d9 -r e182feb38cca sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c Mon Aug 03 09:54:20 2015 +0000
+++ b/sys/dev/sdmmc/sdhc.c Mon Aug 03 10:08:51 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdhc.c,v 1.75 2015/08/03 05:24:37 mlelstv Exp $ */
+/* $NetBSD: sdhc.c,v 1.76 2015/08/03 10:08:51 jmcneill Exp $ */
/* $OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $ */
/*
@@ -23,7 +23,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.75 2015/08/03 05:24:37 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.76 2015/08/03 10:08:51 jmcneill Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -174,7 +174,7 @@
static int sdhc_card_detect(sdmmc_chipset_handle_t);
static int sdhc_write_protect(sdmmc_chipset_handle_t);
static int sdhc_bus_power(sdmmc_chipset_handle_t, uint32_t);
-static int sdhc_bus_clock(sdmmc_chipset_handle_t, int);
+static int sdhc_bus_clock_ddr(sdmmc_chipset_handle_t, int, bool);
static int sdhc_bus_width(sdmmc_chipset_handle_t, int);
static int sdhc_bus_rod(sdmmc_chipset_handle_t, int);
static void sdhc_card_enable_intr(sdmmc_chipset_handle_t, int);
@@ -210,7 +210,7 @@
/* bus power, clock frequency, width and ROD(OpenDrain/PushPull) */
.bus_power = sdhc_bus_power,
- .bus_clock = sdhc_bus_clock,
+ .bus_clock = NULL, /* see sdhc_bus_clock_ddr */
.bus_width = sdhc_bus_width,
.bus_rod = sdhc_bus_rod,
@@ -223,6 +223,7 @@
/* UHS functions */
.signal_voltage = sdhc_signal_voltage,
+ .bus_clock_ddr = sdhc_bus_clock_ddr,
};
static int
@@ -418,14 +419,14 @@
SET(hp->ocr, MMC_OCR_S18A);
aprint_normal(" SDR50");
}
- if (ISSET(caps2, SDHC_SDR104_SUPP)) {
- SET(hp->ocr, MMC_OCR_S18A);
- aprint_normal(" SDR104");
- }
if (ISSET(caps2, SDHC_DDR50_SUPP)) {
SET(hp->ocr, MMC_OCR_S18A);
aprint_normal(" DDR50");
}
+ if (ISSET(caps2, SDHC_SDR104_SUPP)) {
+ SET(hp->ocr, MMC_OCR_S18A);
+ aprint_normal(" SDR104 HS200");
+ }
if (ISSET(caps, SDHC_VOLTAGE_SUPP_1_8V)) {
SET(hp->ocr, MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V);
aprint_normal(" 1.8V");
@@ -534,6 +535,14 @@
saa.saa_caps |= SMC_CAPS_8BIT_MODE;
if (ISSET(caps, SDHC_HIGH_SPEED_SUPP))
saa.saa_caps |= SMC_CAPS_SD_HIGHSPEED;
+ if (ISSET(caps2, SDHC_SDR104_SUPP))
+ saa.saa_caps |= SMC_CAPS_UHS_SDR104 |
+ SMC_CAPS_UHS_SDR50 |
+ SMC_CAPS_MMC_HS200;
+ if (ISSET(caps2, SDHC_SDR50_SUPP))
+ saa.saa_caps |= SMC_CAPS_UHS_SDR50;
+ if (ISSET(caps2, SDHC_DDR50_SUPP))
+ saa.saa_caps |= SMC_CAPS_UHS_DDR50;
if (ISSET(hp->flags, SHF_USE_DMA)) {
saa.saa_caps |= SMC_CAPS_DMA;
if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED))
@@ -964,7 +973,7 @@
* Return zero on success.
*/
static int
-sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
+sdhc_bus_clock_ddr(sdmmc_chipset_handle_t sch, int freq, bool ddr)
{
struct sdhc_host *hp = (struct sdhc_host *)sch;
u_int div;
@@ -1007,14 +1016,19 @@
}
if (hp->specver >= SDHC_SPEC_VERS_300) {
- /* XXX DDR */
HCLR2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_MASK);
if (freq > 100000) {
HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_SDR104);
} else if (freq > 50000) {
HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_SDR50);
} else if (freq > 25000) {
- HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_SDR25);
+ if (ddr) {
+ HSET2(hp, SDHC_HOST_CTL2,
+ SDHC_UHS_MODE_SELECT_DDR50);
+ } else {
+ HSET2(hp, SDHC_HOST_CTL2,
+ SDHC_UHS_MODE_SELECT_SDR25);
+ }
} else if (freq > 400) {
HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_SDR12);
}
diff -r 2e7c0c1ad0d9 -r e182feb38cca sys/dev/sdmmc/sdmmc.c
--- a/sys/dev/sdmmc/sdmmc.c Mon Aug 03 09:54:20 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc.c Mon Aug 03 10:08:51 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmc.c,v 1.28 2015/08/03 05:32:50 mlelstv Exp $ */
+/* $NetBSD: sdmmc.c,v 1.29 2015/08/03 10:08:51 jmcneill Exp $ */
/* $OpenBSD: sdmmc.c,v 1.18 2009/01/09 10:58:38 jsg Exp $ */
/*
@@ -49,7 +49,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.28 2015/08/03 05:32:50 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.29 2015/08/03 10:08:51 jmcneill Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -523,7 +523,8 @@
/*
* Select the minimum clock frequency.
*/
- error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, SDMMC_SDCLK_400K);
+ error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, SDMMC_SDCLK_400K,
+ false);
if (error) {
aprint_error_dev(sc->sc_dev, "couldn't supply clock\n");
goto out;
@@ -569,7 +570,8 @@
/* Turn off bus power and clock. */
(void)sdmmc_chip_bus_width(sc->sc_sct, sc->sc_sch, 1);
- (void)sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, SDMMC_SDCLK_OFF);
+ (void)sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, SDMMC_SDCLK_OFF,
+ false);
(void)sdmmc_chip_bus_power(sc->sc_sct, sc->sc_sch, 0);
sc->sc_busclk = sc->sc_clkmax;
}
diff -r 2e7c0c1ad0d9 -r e182feb38cca sys/dev/sdmmc/sdmmc_io.c
--- a/sys/dev/sdmmc/sdmmc_io.c Mon Aug 03 09:54:20 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc_io.c Mon Aug 03 10:08:51 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmc_io.c,v 1.9 2015/08/03 05:32:50 mlelstv Exp $ */
+/* $NetBSD: sdmmc_io.c,v 1.10 2015/08/03 10:08:51 jmcneill 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.9 2015/08/03 05:32:50 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_io.c,v 1.10 2015/08/03 10:08:51 jmcneill Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -231,7 +231,8 @@
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);
+ sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, sc->sc_busclk,
+ false);
if (error)
aprint_error_dev(sc->sc_dev,
"can't change bus clock\n");
diff -r 2e7c0c1ad0d9 -r e182feb38cca sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Mon Aug 03 09:54:20 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Mon Aug 03 10:08:51 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmc_mem.c,v 1.38 2015/08/03 05:32:50 mlelstv Exp $ */
+/* $NetBSD: sdmmc_mem.c,v 1.39 2015/08/03 10:08:51 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.38 2015/08/03 05:32:50 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.39 2015/08/03 10:08:51 jmcneill Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -96,6 +96,27 @@
static int sdmmc_mem_write_block_subr(struct sdmmc_function *, bus_dmamap_t,
uint32_t, u_char *, size_t);
+static const struct {
+ const char *name;
+ int v;
+ int freq;
+} switch_group0_functions[] = {
+ /* Default/SDR12 */
+ { "Default/SDR12", 0, 25000 },
+
+ /* High-Speed/SDR25 */
+ { "High-Speed/SDR25", SMC_CAPS_SD_HIGHSPEED, 50000 },
+
+ /* SDR50 */
+ { "SDR50", SMC_CAPS_UHS_SDR50, 100000 },
+
+ /* SDR104 */
+ { "SDR104", SMC_CAPS_UHS_SDR104, 208000 },
+
+ /* DDR50 */
+ { "DDR50", SMC_CAPS_UHS_DDR50, 50000 },
+};
+
/*
* Initialize SD/MMC memory cards and memory in SDIO "combo" cards.
*/
@@ -221,7 +242,7 @@
* Stop the clock
*/
error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch,
- SDMMC_SDCLK_OFF);
+ SDMMC_SDCLK_OFF, false);
if (error)
goto out;
@@ -241,7 +262,8 @@
/*
* Switch to SDR12 timing
*/
- error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, 25000);
+ error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, 25000,
+ false);
if (error)
goto out;
@@ -672,38 +694,39 @@
}
static int
+sdmmc_mem_select_transfer_mode(struct sdmmc_softc *sc, int support_func)
+{
+ if (ISSET(sc->sc_flags, SMF_UHS_MODE)) {
+ if (ISSET(sc->sc_caps, SMC_CAPS_UHS_SDR104) &&
+ ISSET(support_func, SD_ACCESS_MODE_SDR104)) {
+ return SD_ACCESS_MODE_SDR104;
+ }
+ if (ISSET(sc->sc_caps, SMC_CAPS_UHS_DDR50) &&
+ ISSET(support_func, SD_ACCESS_MODE_DDR50)) {
+ return SD_ACCESS_MODE_DDR50;
+ }
+ if (ISSET(sc->sc_caps, SMC_CAPS_UHS_SDR50) &&
+ ISSET(support_func, SD_ACCESS_MODE_SDR50)) {
+ return SD_ACCESS_MODE_SDR50;
+ }
+ }
+ if (ISSET(sc->sc_caps, SMC_CAPS_SD_HIGHSPEED) &&
+ ISSET(support_func, SD_ACCESS_MODE_SDR25)) {
+ return SD_ACCESS_MODE_SDR25;
+ }
+ return SD_ACCESS_MODE_SDR12;
+}
+
+static int
sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
{
- static const struct {
- int v;
- int freq;
- int uhs;
- } 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, 0 },
-
- /* 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, 0 },
-
- /* SDR50 */
- { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 100000, 1 },
-
- /* SDR104 */
- { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 208000, 1 },
-
-#if notyet
- /* DDR50 */
- { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 50000, 1 },
-#endif
- };
- int host_ocr, support_func, best_func, bus_clock, error, g, i;
+ int support_func, best_func, bus_clock, error, i;
sdmmc_bitfield512_t status; /* Switch Function Status */
+ bool ddr = false;
/* change bus clock */
Home |
Main Index |
Thread Index |
Old Index