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 re-tuning modes 1 and 2
details: https://anonhg.NetBSD.org/src/rev/0ffdef0648b7
branches: trunk
changeset: 339718:0ffdef0648b7
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Wed Aug 05 12:28:47 2015 +0000
description:
support re-tuning modes 1 and 2
diffstat:
sys/dev/sdmmc/sdhc.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/sdmmc/sdhcreg.h | 8 ++++-
2 files changed, 64 insertions(+), 4 deletions(-)
diffs (204 lines):
diff -r 1d91c643f717 -r 0ffdef0648b7 sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c Wed Aug 05 10:30:25 2015 +0000
+++ b/sys/dev/sdmmc/sdhc.c Wed Aug 05 12:28:47 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdhc.c,v 1.79 2015/08/05 10:30:25 jmcneill Exp $ */
+/* $NetBSD: sdhc.c,v 1.80 2015/08/05 12:28:47 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.79 2015/08/05 10:30:25 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.80 2015/08/05 12:28:47 jmcneill Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -36,6 +36,7 @@
#include <sys/systm.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
+#include <sys/atomic.h>
#include <dev/sdmmc/sdhcreg.h>
#include <dev/sdmmc/sdhcvar.h>
@@ -78,6 +79,11 @@
kmutex_t intr_lock;
kcondvar_t intr_cv;
+ callout_t tuning_timer;
+ int tuning_timing;
+ u_int tuning_timer_count;
+ u_int tuning_timer_pending;
+
int specver; /* spec. version */
uint32_t flags; /* flags for this host */
@@ -184,6 +190,7 @@
struct sdmmc_command *);
static int sdhc_signal_voltage(sdmmc_chipset_handle_t, int);
static int sdhc_execute_tuning(sdmmc_chipset_handle_t, int);
+static void sdhc_tuning_timer(void *);
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);
@@ -279,6 +286,8 @@
mutex_init(&hp->intr_lock, MUTEX_DEFAULT, IPL_SDMMC);
cv_init(&hp->intr_cv, "sdhcintr");
+ callout_init(&hp->tuning_timer, CALLOUT_MPSAFE);
+ callout_setfunc(&hp->tuning_timer, sdhc_tuning_timer, hp);
if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
sdhcver = HREAD4(hp, SDHC_ESDHC_HOST_CTL_VERSION);
@@ -329,6 +338,18 @@
}
}
+ const u_int retuning_mode = (caps2 >> SDHC_RETUNING_MODES_SHIFT) &
+ SDHC_RETUNING_MODES_MASK;
+ if (retuning_mode == SDHC_RETUNING_MODE_1) {
+ hp->tuning_timer_count = (caps2 >> SDHC_TIMER_COUNT_SHIFT) &
+ SDHC_TIMER_COUNT_MASK;
+ if (hp->tuning_timer_count == 0xf)
+ hp->tuning_timer_count = 0;
+ if (hp->tuning_timer_count)
+ hp->tuning_timer_count =
+ 1 << (hp->tuning_timer_count - 1);
+ }
+
/*
* Use DMA if the host system and the controller support it.
* Suports integrated or external DMA egine, with or without
@@ -442,6 +463,11 @@
SET(hp->ocr, MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V);
aprint_normal(" 3.3V");
}
+ if (hp->specver >= SDHC_SPEC_VERS_300) {
+ aprint_normal(", re-tuning mode %d", retuning_mode + 1);
+ if (hp->tuning_timer_count)
+ aprint_normal(" (%us timer)", hp->tuning_timer_count);
+ }
/*
* Determine the maximum block length supported by the host
@@ -560,6 +586,7 @@
return 0;
err:
+ callout_destroy(&hp->tuning_timer);
cv_destroy(&hp->intr_cv);
mutex_destroy(&hp->intr_lock);
free(hp, M_DEVBUF);
@@ -595,6 +622,8 @@
sdhc_soft_reset(hp, SDHC_RESET_ALL);
mutex_exit(&hp->intr_lock);
}
+ callout_halt(&hp->tuning_timer, NULL);
+ callout_destroy(&hp->tuning_timer);
cv_destroy(&hp->intr_cv);
mutex_destroy(&hp->intr_lock);
if (hp->ios > 0) {
@@ -841,6 +870,7 @@
/* If power is disabled, reset the host and return now. */
if (ocr == 0) {
(void)sdhc_host_reset1(hp);
+ callout_halt(&hp->tuning_timer, &hp->intr_lock);
goto out;
}
@@ -1241,6 +1271,8 @@
uint8_t hostctl;
int opcode, error, retry = 40;
+ hp->tuning_timing = timing;
+
switch (timing) {
case SDMMC_TIMING_MMC_HS200:
opcode = MMC_SEND_TUNING_BLOCK_HS200;
@@ -1318,9 +1350,22 @@
return EIO; /* tuning failed */
}
+ if (hp->tuning_timer_count) {
+ callout_schedule(&hp->tuning_timer,
+ hz * hp->tuning_timer_count);
+ }
+
return 0; /* tuning completed */
}
+static void
+sdhc_tuning_timer(void *arg)
+{
+ struct sdhc_host *hp = arg;
+
+ atomic_swap_uint(&hp->tuning_timer_pending, 1);
+}
+
static int
sdhc_wait_state(struct sdhc_host *hp, uint32_t mask, uint32_t value)
{
@@ -1345,6 +1390,10 @@
mutex_enter(&hp->intr_lock);
+ if (atomic_cas_uint(&hp->tuning_timer_pending, 1, 0) == 1) {
+ (void)sdhc_execute_tuning(hp, hp->tuning_timing);
+ }
+
if (cmd->c_data && ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
const uint16_t ready = SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY;
if (ISSET(hp->flags, SHF_USE_DMA)) {
@@ -2097,6 +2146,13 @@
}
/*
+ * Schedule re-tuning process (UHS).
+ */
+ if (ISSET(status, SDHC_RETUNING_EVENT)) {
+ atomic_swap_uint(&hp->tuning_timer_pending, 1);
+ }
+
+ /*
* Wake up the blocking process to service command
* related interrupt(s).
*/
diff -r 1d91c643f717 -r 0ffdef0648b7 sys/dev/sdmmc/sdhcreg.h
--- a/sys/dev/sdmmc/sdhcreg.h Wed Aug 05 10:30:25 2015 +0000
+++ b/sys/dev/sdmmc/sdhcreg.h Wed Aug 05 12:28:47 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdhcreg.h,v 1.16 2015/08/05 10:30:25 jmcneill Exp $ */
+/* $NetBSD: sdhcreg.h,v 1.17 2015/08/05 12:28:47 jmcneill Exp $ */
/* $OpenBSD: sdhcreg.h,v 1.4 2006/07/30 17:20:40 fgsch Exp $ */
/*
@@ -112,6 +112,7 @@
#define SDHC_RESET_ALL (1<<0)
#define SDHC_NINTR_STATUS 0x30
#define SDHC_ERROR_INTERRUPT (1<<15)
+#define SDHC_RETUNING_EVENT (1<<12)
#define SDHC_CARD_INTERRUPT (1<<8)
#define SDHC_CARD_REMOVAL (1<<7)
#define SDHC_CARD_INSERTION (1<<6)
@@ -121,7 +122,7 @@
#define SDHC_BLOCK_GAP_EVENT (1<<2)
#define SDHC_TRANSFER_COMPLETE (1<<1)
#define SDHC_COMMAND_COMPLETE (1<<0)
-#define SDHC_NINTR_STATUS_MASK 0x81ff
+#define SDHC_NINTR_STATUS_MASK 0x91ff
#define SDHC_EINTR_STATUS 0x32
#define SDHC_DMA_ERROR (1<<12)
#define SDHC_ADMA_ERROR (1<<9)
@@ -190,6 +191,9 @@
#define SDHC_TUNING_SDR50 (1<<13)
#define SDHC_RETUNING_MODES_SHIFT 14
#define SDHC_RETUNING_MODES_MASK 0x3
+#define SDHC_RETUNING_MODE_1 (0 << SDHC_RETUNING_MODES_SHIFT)
+#define SDHC_RETUNING_MODE_2 (1 << SDHC_RETUNING_MODES_SHIFT)
+#define SDHC_RETUNING_MODE_3 (2 << SDHC_RETUNING_MODES_SHIFT)
#define SDHC_CLOCK_MULTIPLIER_SHIFT 16
#define SDHC_CLOCK_MULTIPLIER_MASK 0xff
#define SDHC_ADMA_ERROR_STATUS 0x54
Home |
Main Index |
Thread Index |
Old Index