Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-6]: src/sys/dev/sdmmc Pull up revisions:
details: https://anonhg.NetBSD.org/src/rev/72490f0234ea
branches: netbsd-6
changeset: 774379:72490f0234ea
user: jdc <jdc%NetBSD.org@localhost>
date: Wed Aug 08 06:18:59 2012 +0000
description:
Pull up revisions:
src/sys/dev/sdmmc/sdhc.c revisions 1.16,1.20,1.21,1.22,1.23 via patch,1.25
src/sys/dev/sdmmc/sdhcreg.h revision 1.8
src/sys/dev/sdmmc/sdmmc_mem.c revisions 1.21,1.22
src/sys/dev/sdmmc/sdmmcreg.h revisions 1.10,1.11,1.12
(requested by matt in ticket 441).
SDHCI byte swaps the BE response on the wire into LE registers.
As we always want response data in LE, use bus_space_read_stream.
Additonally, read response data in 1 or 4 4-byte chunks, instead of
one 4-byte chunk or 15 1-byte chunks.
bus_space_*_stream_N() functions are not universally available.
Provite alternate implementation for when they are unavailable.
Handle interrupt acknowledgement in the SDHC_FLAG_32BIT_ACCESS case in
the same way as non-SDHC_FLAG_32BIT_ACCESS case.
If there was an error in 32-bit mode, just set ERROR_INTERRUPT otherwise
see if matched anything we care about.
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.
Responses are actually in host order (except SCR which is return in
big endian so that's convert to host order).
Fix comments about __bitfield.
diffstat:
sys/dev/sdmmc/sdhc.c | 59 ++++++++++++++++++++++++++++++++++------------
sys/dev/sdmmc/sdhcreg.h | 7 ++++-
sys/dev/sdmmc/sdmmc_mem.c | 6 +---
sys/dev/sdmmc/sdmmcreg.h | 42 +++++++++++++-------------------
4 files changed, 68 insertions(+), 46 deletions(-)
diffs (235 lines):
diff -r 1a6117bc4e6c -r 72490f0234ea sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c Tue Jul 31 09:27:27 2012 +0000
+++ b/sys/dev/sdmmc/sdhc.c Wed Aug 08 06:18:59 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdhc.c,v 1.10.2.1 2012/06/11 17:45:32 riz Exp $ */
+/* $NetBSD: sdhc.c,v 1.10.2.2 2012/08/08 06:18:59 jdc 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.10.2.1 2012/06/11 17:45:32 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.10.2.2 2012/08/08 06:18:59 jdc Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -987,14 +987,11 @@
*/
mutex_enter(&hp->host_mtx);
if (cmd->c_error == 0 && ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
+ cmd->c_resp[0] = HREAD4(hp, SDHC_RESPONSE + 0);
if (ISSET(cmd->c_flags, SCF_RSP_136)) {
- uint8_t *p = (uint8_t *)cmd->c_resp;
- int i;
-
- for (i = 0; i < 15; i++)
- *p++ = HREAD1(hp, SDHC_RESPONSE + i);
- } else {
- cmd->c_resp[0] = HREAD4(hp, SDHC_RESPONSE);
+ 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);
@@ -1379,17 +1376,33 @@
esdhc_read_data_pio(struct sdhc_host *hp, uint8_t *data, u_int datalen)
{
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)) {
- uint32_t v = HREAD4(hp, SDHC_DATA);
+ 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)) {
- uint32_t v = HREAD4(hp, SDHC_DATA);
+ if (count == 0) {
+ sdmmc_delay(10);
+ }
+ v = HREAD4(hp, SDHC_DATA);
v = le32toh(v);
do {
*data++ = v;
@@ -1402,16 +1415,29 @@
esdhc_write_data_pio(struct sdhc_host *hp, uint8_t *data, u_int datalen)
{
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)) {
- uint32_t v = *(uint32_t *)data;
+ 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)) {
- uint32_t v = *(uint32_t *)data;
+ if (count == 0) {
+ sdmmc_delay(10);
+ }
+ v = *(uint32_t *)data;
v = htole32(v);
HWRITE4(hp, SDHC_DATA, v);
}
@@ -1505,8 +1531,9 @@
uint32_t xstatus = HREAD4(hp, SDHC_NINTR_STATUS);
status = xstatus;
error = xstatus >> 16;
- status |= (error ? SDHC_ERROR_INTERRUPT : 0);
- if (!ISSET(status, SDHC_NINTR_STATUS_MASK))
+ if (error)
+ xstatus |= SDHC_ERROR_INTERRUPT;
+ else if (!ISSET(status, SDHC_NINTR_STATUS_MASK))
continue; /* no interrupt for us */
/* Acknowledge the interrupts we are about to handle. */
HWRITE4(hp, SDHC_NINTR_STATUS, xstatus);
diff -r 1a6117bc4e6c -r 72490f0234ea sys/dev/sdmmc/sdhcreg.h
--- a/sys/dev/sdmmc/sdhcreg.h Tue Jul 31 09:27:27 2012 +0000
+++ b/sys/dev/sdmmc/sdhcreg.h Wed Aug 08 06:18:59 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdhcreg.h,v 1.5 2012/02/01 22:53:19 matt Exp $ */
+/* $NetBSD: sdhcreg.h,v 1.5.2.1 2012/08/08 06:18:59 jdc Exp $ */
/* $OpenBSD: sdhcreg.h,v 1.4 2006/07/30 17:20:40 fgsch Exp $ */
/*
@@ -152,6 +152,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 1a6117bc4e6c -r 72490f0234ea sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Tue Jul 31 09:27:27 2012 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Wed Aug 08 06:18:59 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.20.2.1 2012/08/08 06:18:59 jdc 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.20.2.1 2012/08/08 06:18:59 jdc Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -934,8 +934,6 @@
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]);
ver = SCR_STRUCTURE(resp);
sf->scr.sd_spec = SCR_SD_SPEC(resp);
diff -r 1a6117bc4e6c -r 72490f0234ea sys/dev/sdmmc/sdmmcreg.h
--- a/sys/dev/sdmmc/sdmmcreg.h Tue Jul 31 09:27:27 2012 +0000
+++ b/sys/dev/sdmmc/sdmmcreg.h Wed Aug 08 06:18:59 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmcreg.h,v 1.8 2012/01/27 03:07:21 matt Exp $ */
+/* $NetBSD: sdmmcreg.h,v 1.8.2.1 2012/08/08 06:18:59 jdc Exp $ */
/* $OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $ */
/*
@@ -308,43 +308,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 host byte order in 32-bit units. */
#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 = src[0] >> start;
+
+ if (__predict_false((start + len - 1) / 32 != start / 32)) {
+ dst |= src[1] << (32 - start);
}
- dst &= mask;
- return (int)dst;
+ return dst & (__BIT(len) - 1);
}
#endif /* _SDMMCREG_H_ */
Home |
Main Index |
Thread Index |
Old Index