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 basic UHS-I support. SDR50 and SDR104 are ...
details: https://anonhg.NetBSD.org/src/rev/ac9be16a58f8
branches: trunk
changeset: 339672:ac9be16a58f8
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sun Aug 02 21:44:36 2015 +0000
description:
Add basic UHS-I support. SDR50 and SDR104 are supported, but not DDR50.
diffstat:
sys/dev/sdmmc/sdmmc_mem.c | 82 ++++++++++++++++++++++++++++++++++++++++++----
sys/dev/sdmmc/sdmmcchip.h | 12 ++++++-
sys/dev/sdmmc/sdmmcreg.h | 4 +-
sys/dev/sdmmc/sdmmcvar.h | 3 +-
4 files changed, 90 insertions(+), 11 deletions(-)
diffs (228 lines):
diff -r 4159bf2c4b17 -r ac9be16a58f8 sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Sun Aug 02 21:22:34 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Sun Aug 02 21:44:36 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmc_mem.c,v 1.34 2015/02/27 16:08:17 nonaka Exp $ */
+/* $NetBSD: sdmmc_mem.c,v 1.35 2015/08/02 21:44:36 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.34 2015/02/27 16:08:17 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.35 2015/08/02 21:44:36 jmcneill Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -104,6 +104,7 @@
{
uint32_t host_ocr;
uint32_t card_ocr;
+ uint32_t new_ocr;
uint32_t ocr = 0;
int error;
@@ -184,19 +185,78 @@
error = sdmmc_mem_send_if_cond(sc, 0x1aa, &card_ocr);
if (error == 0 && card_ocr == 0x1aa)
SET(ocr, MMC_OCR_HCS);
+
+ if (sdmmc_chip_host_ocr(sc->sc_sct, sc->sc_sch) & MMC_OCR_S18A)
+ SET(ocr, MMC_OCR_S18A);
}
host_ocr |= ocr;
/* Send the new OCR value until all cards are ready. */
- error = sdmmc_mem_send_op_cond(sc, host_ocr, NULL);
+ error = sdmmc_mem_send_op_cond(sc, host_ocr, &new_ocr);
if (error) {
DPRINTF(("%s: couldn't send memory OCR\n", SDMMCDEVNAME(sc)));
goto out;
}
+ if (ISSET(new_ocr, MMC_OCR_S18A) && sc->sc_sct->signal_voltage) {
+ /*
+ * Card and host support low voltage mode, begin switch
+ * sequence.
+ */
+ struct sdmmc_command cmd;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.c_arg = 0;
+ cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
+ cmd.c_opcode = SD_VOLTAGE_SWITCH;
+ error = sdmmc_mmc_command(sc, &cmd);
+ if (error) {
+ DPRINTF(("%s: voltage switch command failed\n",
+ SDMMCDEVNAME(sc)));
+ goto out;
+ }
+
+ delay(1000);
+
+ /*
+ * Stop the clock
+ */
+ error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch,
+ SDMMC_SDCLK_OFF);
+ if (error)
+ goto out;
+
+ delay(1000);
+
+ /*
+ * Card switch command was successful, update host controller
+ * signal voltage setting.
+ */
+ error = sdmmc_chip_signal_voltage(sc->sc_sct,
+ sc->sc_sch, SDMMC_SIGNAL_VOLTAGE_180);
+ if (error)
+ goto out;
+
+ delay(5000);
+
+ /*
+ * Switch to SDR12 timing
+ */
+ error = sdmmc_chip_bus_clock(sc->sc_sct, sc->sc_sch, 25000);
+ if (error)
+ goto out;
+
+ delay(1000);
+
+ SET(sc->sc_flags, SMF_UHS_MODE);
+ }
+
out:
SDMMC_UNLOCK(sc);
+ if (error)
+ printf("%s: %s failed with error %d\n", SDMMCDEVNAME(sc),
+ __func__, error);
+
return error;
}
@@ -617,23 +677,26 @@
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 },
+ 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 },
+ 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 },
+ { 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 },
+ { 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 },
+ { 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;
sdmmc_bitfield512_t status; /* Switch Function Status */
@@ -684,6 +747,9 @@
i < __arraycount(switch_group0_functions); i++, g <<= 1) {
if (!(switch_group0_functions[i].v & host_ocr))
continue;
+ if (switch_group0_functions[i].uhs &&
+ !ISSET(sc->sc_flags, SMF_UHS_MODE))
+ break;
if (g & support_func)
best_func = i;
}
diff -r 4159bf2c4b17 -r ac9be16a58f8 sys/dev/sdmmc/sdmmcchip.h
--- a/sys/dev/sdmmc/sdmmcchip.h Sun Aug 02 21:22:34 2015 +0000
+++ b/sys/dev/sdmmc/sdmmcchip.h Sun Aug 02 21:44:36 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmcchip.h,v 1.4 2011/05/18 01:07:17 dyoung Exp $ */
+/* $NetBSD: sdmmcchip.h,v 1.5 2015/08/02 21:44:36 jmcneill Exp $ */
/* $OpenBSD: sdmmcchip.h,v 1.3 2007/05/31 10:09:01 uwe Exp $ */
/*
@@ -57,6 +57,9 @@
/* card interrupt */
void (*card_enable_intr)(sdmmc_chipset_handle_t, int);
void (*card_intr_ack)(sdmmc_chipset_handle_t);
+
+ /* UHS functions */
+ int (*signal_voltage)(sdmmc_chipset_handle_t, int);
};
/* host controller reset */
@@ -90,11 +93,18 @@
((tag)->card_enable_intr((handle), (enable)))
#define sdmmc_chip_card_intr_ack(tag, handle) \
((tag)->card_intr_ack((handle)))
+/* UHS functions */
+#define sdmmc_chip_signal_voltage(tag, handle, voltage) \
+ ((tag)->signal_voltage((handle), (voltage)))
/* clock frequencies for sdmmc_chip_bus_clock() */
#define SDMMC_SDCLK_OFF 0
#define SDMMC_SDCLK_400K 400
+/* voltage levels for sdmmc_chip_signal_voltage() */
+#define SDMMC_SIGNAL_VOLTAGE_330 0
+#define SDMMC_SIGNAL_VOLTAGE_180 1
+
/* SPI mode */
struct sdmmc_spi_chip_functions {
/* card initialize */
diff -r 4159bf2c4b17 -r ac9be16a58f8 sys/dev/sdmmc/sdmmcreg.h
--- a/sys/dev/sdmmc/sdmmcreg.h Sun Aug 02 21:22:34 2015 +0000
+++ b/sys/dev/sdmmc/sdmmcreg.h Sun Aug 02 21:44:36 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmcreg.h,v 1.15 2014/12/07 20:07:25 jmcneill Exp $ */
+/* $NetBSD: sdmmcreg.h,v 1.16 2015/08/02 21:44:36 jmcneill Exp $ */
/* $OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $ */
/*
@@ -58,6 +58,7 @@
#define SD_SEND_RELATIVE_ADDR 3 /* R6 */
#define SD_SEND_SWITCH_FUNC 6 /* R1 */
#define SD_SEND_IF_COND 8 /* R7 */
+#define SD_VOLTAGE_SWITCH 11 /* R1 */
/* SD application commands */ /* response type */
#define SD_APP_SET_BUS_WIDTH 6 /* R1 */
@@ -68,6 +69,7 @@
/* OCR bits */
#define MMC_OCR_MEM_READY (1U<<31)/* memory power-up status bit */
#define MMC_OCR_HCS (1<<30)
+#define MMC_OCR_S18A (1<<24)
#define MMC_OCR_3_5V_3_6V (1<<23)
#define MMC_OCR_3_4V_3_5V (1<<22)
#define MMC_OCR_3_3V_3_4V (1<<21)
diff -r 4159bf2c4b17 -r ac9be16a58f8 sys/dev/sdmmc/sdmmcvar.h
--- a/sys/dev/sdmmc/sdmmcvar.h Sun Aug 02 21:22:34 2015 +0000
+++ b/sys/dev/sdmmc/sdmmcvar.h Sun Aug 02 21:44:36 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmcvar.h,v 1.16 2015/02/27 16:08:17 nonaka Exp $ */
+/* $NetBSD: sdmmcvar.h,v 1.17 2015/08/02 21:44:36 jmcneill Exp $ */
/* $OpenBSD: sdmmcvar.h,v 1.13 2009/01/09 10:55:22 jsg Exp $ */
/*
@@ -216,6 +216,7 @@
#define SMF_MEM_MODE 0x0008 /* host in memory mode (SD or MMC) */
#define SMF_CARD_PRESENT 0x4000 /* card presence noticed */
#define SMF_CARD_ATTACHED 0x8000 /* card driver(s) attached */
+#define SMF_UHS_MODE 0x10000 /* host in UHS mode */
uint32_t sc_caps; /* host capability */
#define SMC_CAPS_AUTO_STOP 0x0001 /* send CMD12 automagically by host */
Home |
Main Index |
Thread Index |
Old Index