Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/sdmmc Skip setting power when the voltage doesn't ch...



details:   https://anonhg.NetBSD.org/src/rev/d0db7bece617
branches:  trunk
changeset: 460562:d0db7bece617
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Mon Oct 28 06:00:14 2019 +0000

description:
Skip setting power when the voltage doesn't change.
Also increase some timeouts.

diffstat:

 sys/dev/sdmmc/sdhc.c |  48 ++++++++++++++++++++++++++++++++++++------------
 1 files changed, 36 insertions(+), 12 deletions(-)

diffs (137 lines):

diff -r ef5f3933ff9a -r d0db7bece617 sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c      Mon Oct 28 03:01:55 2019 +0000
+++ b/sys/dev/sdmmc/sdhc.c      Mon Oct 28 06:00:14 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdhc.c,v 1.104 2019/10/23 05:20:52 hkenken Exp $       */
+/*     $NetBSD: sdhc.c,v 1.105 2019/10/28 06:00:14 mlelstv 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.104 2019/10/23 05:20:52 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.105 2019/10/28 06:00:14 mlelstv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -98,6 +98,8 @@
        bus_dmamap_t            adma_map;
        bus_dma_segment_t       adma_segs[1];
        void                    *adma2;
+
+       uint8_t                 vdd;    /* last vdd setting */
 };
 
 #define HDEVNAME(hp)   (device_xname((hp)->sc->sc_dev))
@@ -156,10 +158,16 @@
        }
 }
 
+static void
+hwrite4(struct sdhc_host *hp, bus_size_t o, uint32_t val)
+{
+
+       bus_space_write_4(hp->iot, hp->ioh, o, val);
+}
+
 #define HWRITE1(hp, reg, val)          hwrite1(hp, reg, val)
 #define HWRITE2(hp, reg, val)          hwrite2(hp, reg, val)
-#define HWRITE4(hp, reg, val)                                          \
-       bus_space_write_4((hp)->iot, (hp)->ioh, (reg), (val))
+#define HWRITE4(hp, reg, val)          hwrite4(hp, reg, val)
 
 #define HCLR1(hp, reg, bits)                                           \
        do if (bits) HWRITE1((hp), (reg), HREAD1((hp), (reg)) & ~(bits)); while (0)
@@ -788,6 +796,9 @@
                HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, 0);
        }
 
+       /* Let sdhc_bus_power restore power */
+       hp->vdd = 0;
+
        /*
         * Reset the entire host controller and wait up to 100ms for
         * the controller to clear the reset bit.
@@ -902,6 +913,7 @@
        int error = 0;
        const uint32_t pcmask =
            ~(SDHC_BUS_POWER | (SDHC_VOLTAGE_MASK << SDHC_VOLTAGE_SHIFT));
+       uint32_t reg;
 
        mutex_enter(&hp->intr_lock);
 
@@ -909,8 +921,10 @@
         * Disable bus power before voltage change.
         */
        if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_32BIT_ACCESS)
-           && !ISSET(hp->sc->sc_flags, SDHC_FLAG_NO_PWR0))
+           && !ISSET(hp->sc->sc_flags, SDHC_FLAG_NO_PWR0)) {
+               hp->vdd = 0;
                HWRITE1(hp, SDHC_POWER_CTL, 0);
+       }
 
        /* If power is disabled, reset the host and return now. */
        if (ocr == 0) {
@@ -935,6 +949,12 @@
                goto out;
        }
 
+       /*
+        * Did voltage change ?
+        */
+       if (vdd == hp->vdd)
+               goto out;
+
        if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
                /*
                 * Enable bus power.  Wait at least 1 ms (or 74 clocks) plus
@@ -945,13 +965,14 @@
                        HWRITE1(hp, SDHC_POWER_CTL,
                            (vdd << SDHC_VOLTAGE_SHIFT) | SDHC_BUS_POWER);
                } else {
-                       HWRITE1(hp, SDHC_POWER_CTL,
-                           HREAD1(hp, SDHC_POWER_CTL) & pcmask);
+                       reg = HREAD1(hp, SDHC_POWER_CTL) & pcmask;
+                       HWRITE1(hp, SDHC_POWER_CTL, reg);
                        sdmmc_delay(1);
-                       HWRITE1(hp, SDHC_POWER_CTL,
-                           (vdd << SDHC_VOLTAGE_SHIFT));
+                       reg |= (vdd << SDHC_VOLTAGE_SHIFT);
+                       HWRITE1(hp, SDHC_POWER_CTL, reg);
                        sdmmc_delay(1);
-                       HSET1(hp, SDHC_POWER_CTL, SDHC_BUS_POWER);
+                       reg |= SDHC_BUS_POWER;
+                       HWRITE1(hp, SDHC_POWER_CTL, reg);
                        sdmmc_delay(10000);
                }
 
@@ -966,6 +987,9 @@
                }
        }
 
+       /* power successfully changed */
+       hp->vdd = vdd;
+
 out:
        mutex_exit(&hp->intr_lock);
 
@@ -1522,7 +1546,7 @@
        uint32_t state;
        int timeout;
 
-       for (timeout = 10000; timeout > 0; timeout--) {
+       for (timeout = 100000; timeout > 0; timeout--) {
                if (((state = HREAD4(hp, SDHC_PRESENT_STATE)) & mask) == value)
                        return 0;
                sdmmc_delay(10);
@@ -1587,7 +1611,7 @@
         * is marked done for any other reason.
         */
        probing = (cmd->c_flags & SCF_TOUT_OK) != 0;
-       if (!sdhc_wait_intr(hp, SDHC_COMMAND_COMPLETE, SDHC_COMMAND_TIMEOUT, probing)) {
+       if (!sdhc_wait_intr(hp, SDHC_COMMAND_COMPLETE, SDHC_COMMAND_TIMEOUT*3, probing)) {
                DPRINTF(1,("%s: timeout for command\n", __func__));
                sdmmc_delay(50);
                cmd->c_error = ETIMEDOUT;



Home | Main Index | Thread Index | Old Index