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 use of watermark register when PIO to an E...



details:   https://anonhg.NetBSD.org/src/rev/233babad8ba7
branches:  trunk
changeset: 780312:233babad8ba7
user:      matt <matt%NetBSD.org@localhost>
date:      Fri Jul 20 02:04:13 2012 +0000

description:
Add use of watermark register when PIO to an ESDHC.  After every kill or
drain of watermask words, pause a bit to give time for the fifo to recover.
Always the command response in BE byteorder.  Rewrite __bitfield to deal
with this.

diffstat:

 sys/dev/sdmmc/sdhc.c      |  50 +++++++++++++++++++++++++++++++---------------
 sys/dev/sdmmc/sdhcreg.h   |   7 +++++-
 sys/dev/sdmmc/sdmmc_mem.c |   8 +++---
 sys/dev/sdmmc/sdmmcreg.h  |  42 +++++++++++++++-----------------------
 4 files changed, 61 insertions(+), 46 deletions(-)

diffs (225 lines):

diff -r 848528d4b448 -r 233babad8ba7 sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c      Fri Jul 20 01:26:19 2012 +0000
+++ b/sys/dev/sdmmc/sdhc.c      Fri Jul 20 02:04:13 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdhc.c,v 1.22 2012/07/17 21:35:26 matt Exp $   */
+/*     $NetBSD: sdhc.c,v 1.23 2012/07/20 02:04:13 matt 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.22 2012/07/17 21:35:26 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.23 2012/07/20 02:04:13 matt Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -1012,23 +1012,15 @@
         */
        mutex_enter(&hp->host_mtx);
        if (cmd->c_error == 0 && ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
-               uint32_t *p = cmd->c_resp;
-               int i;
-
-               for (i = 0; i < 4; i++) {
-#ifdef __BUS_SPACE_HAS_STREAM_METHODS
-                       *p++ = bus_space_read_stream_4(hp->iot, hp->ioh,
-                           SDHC_RESPONSE + i * 4);
-#else
-                       *p++ = htole32(bus_space_read_4(hp->iot, hp->ioh,
-                           SDHC_RESPONSE + i * 4));
-#endif
-                       if (!ISSET(cmd->c_flags, SCF_RSP_136))
-                               break;
+               cmd->c_resp[0] = HREAD4(hp, SDHC_RESPONSE + 0);
+               if (ISSET(cmd->c_flags, SCF_RSP_136)) {
+                       cmd->c_resp[1] = HREAD4(hp, SDHC_RESPONSE + 4);
+                       cmd->c_resp[2] = HREAD4(hp, SDHC_RESPONSE + 8);
+                       cmd->c_resp[3] = HREAD4(hp, SDHC_RESPONSE + 12);
                }
        }
        mutex_exit(&hp->host_mtx);
-       DPRINTF(1,("%s: resp = %08x\n", HDEVNAME(hp), cmd->c_resp[0]));
+       DPRINTF(1,("%s: resp = %08x\n", HDEVNAME(hp), be32toh(cmd->c_resp[0])));
 
        /*
         * If the command has data to transfer in any direction,
@@ -1403,15 +1395,30 @@
        uint16_t status = HREAD2(hp, SDHC_NINTR_STATUS);
        uint32_t v;
 
+       const size_t watermark = (HREAD4(hp, SDHC_WATERMARK_LEVEL) >> SDHC_WATERMARK_READ_SHIFT) & SDHC_WATERMARK_READ_MASK;
+       size_t count = 0;
+
        while (datalen > 3 && !ISSET(status, SDHC_TRANSFER_COMPLETE)) {
+               if (count == 0) {
+                       /*
+                        * If we've drained "watermark" words, we need to wait
+                        * a little bit so the read FIFO can refill.
+                        */
+                       sdmmc_delay(10);
+                       count = watermark;
+               }
                v = HREAD4(hp, SDHC_DATA);
                v = le32toh(v);
                *(uint32_t *)data = v;
                data += 4;
                datalen -= 4;
                status = HREAD2(hp, SDHC_NINTR_STATUS);
+               count--;
        }
        if (datalen > 0 && !ISSET(status, SDHC_TRANSFER_COMPLETE)) {
+               if (count == 0) {
+                       sdmmc_delay(10);
+               }
                v = HREAD4(hp, SDHC_DATA);
                v = le32toh(v);
                do {
@@ -1427,15 +1434,26 @@
        uint16_t status = HREAD2(hp, SDHC_NINTR_STATUS);
        uint32_t v;
 
+       const size_t watermark = (HREAD4(hp, SDHC_WATERMARK_LEVEL) >> SDHC_WATERMARK_WRITE_SHIFT) & SDHC_WATERMARK_WRITE_MASK;
+       size_t count = watermark;
+
        while (datalen > 3 && !ISSET(status, SDHC_TRANSFER_COMPLETE)) {
+               if (count == 0) {
+                       sdmmc_delay(10);
+                       count = watermark;
+               }
                v = *(uint32_t *)data;
                v = htole32(v);
                HWRITE4(hp, SDHC_DATA, v);
                data += 4;
                datalen -= 4;
                status = HREAD2(hp, SDHC_NINTR_STATUS);
+               count--;
        }
        if (datalen > 0 && !ISSET(status, SDHC_TRANSFER_COMPLETE)) {
+               if (count == 0) {
+                       sdmmc_delay(10);
+               }
                v = *(uint32_t *)data;
                v = htole32(v);
                HWRITE4(hp, SDHC_DATA, v);
diff -r 848528d4b448 -r 233babad8ba7 sys/dev/sdmmc/sdhcreg.h
--- a/sys/dev/sdmmc/sdhcreg.h   Fri Jul 20 01:26:19 2012 +0000
+++ b/sys/dev/sdmmc/sdhcreg.h   Fri Jul 20 02:04:13 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdhcreg.h,v 1.7 2012/07/12 16:34:30 jakllsch Exp $     */
+/*     $NetBSD: sdhcreg.h,v 1.8 2012/07/20 02:04:13 matt Exp $ */
 /*     $OpenBSD: sdhcreg.h,v 1.4 2006/07/30 17:20:40 fgsch Exp $       */
 
 /*
@@ -154,6 +154,11 @@
 #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_WATERMARK_LEVEL            0x44    /* ESDHC */
+#define         SDHC_WATERMARK_WRITE_SHIFT     16
+#define         SDHC_WATERMARK_WRITE_MASK      0xff
+#define         SDHC_WATERMARK_READ_SHIFT      0
+#define         SDHC_WATERMARK_READ_MASK       0xff
 #define SDHC_MAX_CAPABILITIES          0x48
 #define        SDHC_HOST_VER                   0xFC
 #define  SDHC_VVN_MASK                 0x0f
diff -r 848528d4b448 -r 233babad8ba7 sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Fri Jul 20 01:26:19 2012 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Fri Jul 20 02:04:13 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmc_mem.c,v 1.20 2012/02/01 22:34:43 matt Exp $      */
+/*     $NetBSD: sdmmc_mem.c,v 1.21 2012/07/20 02:04:13 matt 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.20 2012/02/01 22:34:43 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.21 2012/07/20 02:04:13 matt Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -934,8 +934,8 @@
        resp[1] = be32toh(sf->raw_scr[0]);              // MSW
        resp[0] |= (resp[1] & 0xff) << 24;
        resp[1] >>= 8;
-       resp[0] = htole32(resp[0]);
-       resp[1] = htole32(resp[1]);
+       resp[0] = htobe32(resp[0]);
+       resp[1] = htobe32(resp[1]);
 
        ver = SCR_STRUCTURE(resp);
        sf->scr.sd_spec = SCR_SD_SPEC(resp);
diff -r 848528d4b448 -r 233babad8ba7 sys/dev/sdmmc/sdmmcreg.h
--- a/sys/dev/sdmmc/sdmmcreg.h  Fri Jul 20 01:26:19 2012 +0000
+++ b/sys/dev/sdmmc/sdmmcreg.h  Fri Jul 20 02:04:13 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmcreg.h,v 1.9 2012/07/12 16:03:13 jakllsch Exp $    */
+/*     $NetBSD: sdmmcreg.h,v 1.10 2012/07/20 02:04:13 matt Exp $       */
 /*     $OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $        */
 
 /*
@@ -309,43 +309,35 @@
 #define SCR_SD_BUS_WIDTHS(scr)         MMC_RSP_BITS((scr), 48, 4)
 #define  SCR_SD_BUS_WIDTHS_1BIT                (1 << 0) /* 1bit (DAT0) */
 #define  SCR_SD_BUS_WIDTHS_4BIT                (1 << 2) /* 4bit (DAT0-3) */
-#define SCR_RESERVED(scr)              MMC_RSP_BITS((scr), 32, 16)
+#define SCR_SD_SPEC3(scr)              MMC_RSP_BITS((scr), 47, 1)
+#define SCR_EX_SECURITY(scr)           MMC_RSP_BITS((scr), 43, 4)
+#define SCR_RESERVED(scr)              MMC_RSP_BITS((scr), 34, 9)
+#define SCR_CMD_SUPPORT_CMD23(scr)     MMC_RSP_BITS((scr), 33, 1)
+#define SCR_CMD_SUPPORT_CMD20(scr)     MMC_RSP_BITS((scr), 32, 1)
 #define SCR_RESERVED2(scr)             MMC_RSP_BITS((scr), 0, 32)
 
 /* Status of Switch Function */
 #define SFUNC_STATUS_GROUP(status, group) \
        be16toh(__bitfield((uint32_t *)(status), (7 - (group)) << 4, 16))
 
-/* Might be slow, but it should work on big and little endian systems. */
+/* This assumes the response fields are in big endian order.  */
 #define MMC_RSP_BITS(resp, start, len) __bitfield((resp), (start)-8, (len))
-static inline int
-__bitfield(uint32_t *src, int start, int len)
+static inline uint32_t
+__bitfield(const uint32_t *src, size_t start, size_t len)
 {
-       uint8_t *sp;
-       uint32_t dst, mask;
-       int shift, bs, bc;
-
-       if (start < 0 || len < 0 || len > 32)
+       if (start + len > 128 || len == 0 || len > 32)
                return 0;
 
-       dst = 0;
-       mask = len % 32 ? UINT_MAX >> (32 - (len % 32)) : UINT_MAX;
-       shift = 0;
+       src += start / 32;
+       start %= 32;
 
-       while (len > 0) {
-               sp = (uint8_t *)src + start / 8;
-               bs = start % 8;
-               bc = 8 - bs;
-               if (bc > len)
-                       bc = len;
-               dst |= (*sp >> bs) << shift;
-               shift += bc;
-               start += bc;
-               len -= bc;
+       uint32_t dst = be32toh(src[0]) >> start;
+
+       if (__predict_false((start + len - 1) / 32 != start / 32)) {
+               dst |= be32toh(src[1]) << (32 - start);
        }
 
-       dst &= mask;
-       return (int)dst;
+       return dst & (__BIT(len) - 1);
 }
 
 #endif /* _SDMMCREG_H_ */



Home | Main Index | Thread Index | Old Index