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