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 UHS-I modes on capable 3.0+ co...
details: https://anonhg.NetBSD.org/src/rev/c879b17d54f9
branches: trunk
changeset: 339673:c879b17d54f9
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sun Aug 02 21:45:12 2015 +0000
description:
add support for UHS-I modes on capable 3.0+ controllers
diffstat:
sys/dev/sdmmc/sdhc.c | 70 ++++++++++++++++++++++++++++++++++++++++++------
sys/dev/sdmmc/sdhcreg.h | 25 ++++++++++++++++-
2 files changed, 85 insertions(+), 10 deletions(-)
diffs (187 lines):
diff -r ac9be16a58f8 -r c879b17d54f9 sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c Sun Aug 02 21:44:36 2015 +0000
+++ b/sys/dev/sdmmc/sdhc.c Sun Aug 02 21:45:12 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdhc.c,v 1.70 2015/08/02 11:28:01 jmcneill Exp $ */
+/* $NetBSD: sdhc.c,v 1.71 2015/08/02 21:45:12 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.70 2015/08/02 11:28:01 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.71 2015/08/02 21:45:12 jmcneill Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -181,6 +181,7 @@
static void sdhc_card_intr_ack(sdmmc_chipset_handle_t);
static void sdhc_exec_command(sdmmc_chipset_handle_t,
struct sdmmc_command *);
+static int sdhc_signal_voltage(sdmmc_chipset_handle_t, int);
static int sdhc_start_command(struct sdhc_host *, struct sdmmc_command *);
static int sdhc_wait_state(struct sdhc_host *, uint32_t, uint32_t);
static int sdhc_soft_reset(struct sdhc_host *, int);
@@ -218,7 +219,10 @@
/* card interrupt */
.card_enable_intr = sdhc_card_enable_intr,
- .card_intr_ack = sdhc_card_intr_ack
+ .card_intr_ack = sdhc_card_intr_ack,
+
+ /* UHS functions */
+ .signal_voltage = sdhc_signal_voltage,
};
static int
@@ -249,7 +253,7 @@
{
struct sdmmcbus_attach_args saa;
struct sdhc_host *hp;
- uint32_t caps;
+ uint32_t caps, caps2;
uint16_t sdhcver;
int error;
@@ -314,6 +318,11 @@
} else {
caps = HREAD4(hp, SDHC_CAPABILITIES);
}
+ if (hp->specver >= SDHC_SPEC_VERS_300) {
+ caps2 = HREAD4(hp, SDHC_CAPABILITIES2);
+ } else {
+ caps2 = 0;
+ }
/*
* Use DMA if the host system and the controller support it.
@@ -402,11 +411,21 @@
aprint_normal(",");
if (ISSET(caps, SDHC_HIGH_SPEED_SUPP)) {
SET(hp->ocr, MMC_OCR_HCS);
- aprint_normal(" High-Speed");
+ aprint_normal(" HS");
+ }
+ if (ISSET(caps2, SDHC_SDR50_SUPP)) {
+ SET(hp->ocr, MMC_OCR_S18A);
+ aprint_normal(" SDR50");
}
- if (ISSET(caps, SDHC_VOLTAGE_SUPP_1_8V) &&
- (hp->specver < SDHC_SPEC_VERS_300 ||
- ISSET(caps, SDHC_EMBEDDED_SLOT))) {
+ 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(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");
}
@@ -812,7 +831,7 @@
* Select the lowest voltage according to capabilities.
*/
ocr &= hp->ocr;
- if (ISSET(ocr, MMC_OCR_1_7V_1_8V|MMC_OCR_1_8V_1_9V)) {
+ if (ISSET(ocr, MMC_OCR_1_7V_1_8V|MMC_OCR_1_8V_1_9V|MMC_OCR_S18A)) {
vdd = SDHC_VOLTAGE_1_8V;
} else if (ISSET(ocr, MMC_OCR_2_9V_3_0V|MMC_OCR_3_0V_3_1V)) {
vdd = SDHC_VOLTAGE_3_0V;
@@ -986,6 +1005,20 @@
goto out;
}
+ 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);
+ } else {
+ HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_SDR12);
+ }
+ }
+
/*
* Set the minimum base clock frequency divisor.
*/
@@ -1155,6 +1188,25 @@
}
static int
+sdhc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage)
+{
+ struct sdhc_host *hp = (struct sdhc_host *)sch;
+
+ switch (signal_voltage) {
+ case SDMMC_SIGNAL_VOLTAGE_180:
+ HSET2(hp, SDHC_HOST_CTL2, SDHC_1_8V_SIGNAL_EN);
+ break;
+ case SDMMC_SIGNAL_VOLTAGE_330:
+ HCLR2(hp, SDHC_HOST_CTL2, SDHC_1_8V_SIGNAL_EN);
+ break;
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+static int
sdhc_wait_state(struct sdhc_host *hp, uint32_t mask, uint32_t value)
{
uint32_t state;
diff -r ac9be16a58f8 -r c879b17d54f9 sys/dev/sdmmc/sdhcreg.h
--- a/sys/dev/sdmmc/sdhcreg.h Sun Aug 02 21:44:36 2015 +0000
+++ b/sys/dev/sdmmc/sdhcreg.h Sun Aug 02 21:45:12 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdhcreg.h,v 1.14 2015/07/29 12:11:14 jmcneill Exp $ */
+/* $NetBSD: sdhcreg.h,v 1.15 2015/08/02 21:45:12 jmcneill Exp $ */
/* $OpenBSD: sdhcreg.h,v 1.4 2006/07/30 17:20:40 fgsch Exp $ */
/*
@@ -142,6 +142,15 @@
#define SDHC_EINTR_SIGNAL_EN 0x3a
#define SDHC_EINTR_SIGNAL_MASK 0x03ff /* excluding vendor signals */
#define SDHC_CMD12_ERROR_STATUS 0x3c
+#define SDHC_HOST_CTL2 0x3e
+#define SDHC_1_8V_SIGNAL_EN (1<<3)
+#define SDHC_UHS_MODE_SELECT_SHIFT 0
+#define SDHC_UHS_MODE_SELECT_MASK 0x7
+#define SDHC_UHS_MODE_SELECT_SDR12 0
+#define SDHC_UHS_MODE_SELECT_SDR25 1
+#define SDHC_UHS_MODE_SELECT_SDR50 2
+#define SDHC_UHS_MODE_SELECT_SDR104 3
+#define SDHC_UHS_MODE_SELECT_DDR50 4
#define SDHC_CAPABILITIES 0x40
#define SDHC_SHARED_BUS_SLOT (1<<31)
#define SDHC_EMBEDDED_SLOT (1<<30)
@@ -167,6 +176,20 @@
#define SDHC_TIMEOUT_FREQ_UNIT (1<<7) /* 0=KHz, 1=MHz */
#define SDHC_TIMEOUT_FREQ_SHIFT 0
#define SDHC_TIMEOUT_FREQ_MASK 0x1f
+#define SDHC_CAPABILITIES2 0x44
+#define SDHC_SDR50_SUPP (1<<0)
+#define SDHC_SDR104_SUPP (1<<1)
+#define SDHC_DDR50_SUPP (1<<2)
+#define SDHC_DRIVER_TYPE_A (1<<4)
+#define SDHC_DRIVER_TYPE_C (1<<5)
+#define SDHC_DRIVER_TYPE_D (1<<6)
+#define SDHC_TIMER_COUNT_SHIFT 8
+#define SDHC_TIMER_COUNT_MASK 0xf
+#define SDHC_TUNING_SDR50 (1<<13)
+#define SDHC_RETUNING_MODES_SHIFT 14
+#define SDHC_RETUNING_MODES_MASK 0x3
+#define SDHC_CLOCK_MULTIPLIER_SHIFT 16
+#define SDHC_CLOCK_MULTIPLIER_MASK 0xff
#define SDHC_ADMA_ERROR_STATUS 0x54
#define SDHC_ADMA_LENGTH_MISMATCH (1<<2)
#define SDHC_ADMA_ERROR_STATE (3<<0)
Home |
Main Index |
Thread Index |
Old Index