Module Name:src
Committed By: jdc
Date: Wed Aug 8 06:19:00 UTC 2012
Modified Files:
src/sys/dev/sdmmc [netbsd-6]: sdhc.c sdhcreg.h sdmmc_mem.c sdmmcreg.h
Log Message:
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.
To generate a diff of this commit:
cvs rdiff -u -r1.10.2.1 -r1.10.2.2 src/sys/dev/sdmmc/sdhc.c
cvs rdiff -u -r1.5 -r1.5.2.1 src/sys/dev/sdmmc/sdhcreg.h
cvs rdiff -u -r1.20 -r1.20.2.1 src/sys/dev/sdmmc/sdmmc_mem.c
cvs rdiff -u -r1.8 -r1.8.2.1 src/sys/dev/sdmmc/sdmmcreg.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/sdmmc/sdhc.c
diff -u src/sys/dev/sdmmc/sdhc.c:1.10.2.1 src/sys/dev/sdmmc/sdhc.c:1.10.2.2
--- src/sys/dev/sdmmc/sdhc.c:1.10.2.1 Mon Jun 11 17:45:32 2012
+++ src/sys/dev/sdmmc/sdhc.c Wed Aug 8 06:18:59 2012
@@ -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 @@ sdhc_exec_command(sdmmc_chipset_handle_t
*/
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 @@ static void
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 @@ static void
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;