Module Name: src
Committed By: jakllsch
Date: Sat Dec 15 00:03:01 UTC 2012
Modified Files:
src/sys/dev/sdmmc: sdmmc_mem.c sdmmcreg.h
Log Message:
Correctly read the 512-bit-wide big-endian Switch Function Status register.
Some of this could/will also be useful for the SD Status register.
To generate a diff of this commit:
cvs rdiff -u -r1.25 -r1.26 src/sys/dev/sdmmc/sdmmc_mem.c
cvs rdiff -u -r1.12 -r1.13 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/sdmmc_mem.c
diff -u src/sys/dev/sdmmc/sdmmc_mem.c:1.25 src/sys/dev/sdmmc/sdmmc_mem.c:1.26
--- src/sys/dev/sdmmc/sdmmc_mem.c:1.25 Fri Dec 14 23:22:21 2012
+++ src/sys/dev/sdmmc/sdmmc_mem.c Sat Dec 15 00:03:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmc_mem.c,v 1.25 2012/12/14 23:22:21 jakllsch Exp $ */
+/* $NetBSD: sdmmc_mem.c,v 1.26 2012/12/15 00:03:00 jakllsch 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.25 2012/12/14 23:22:21 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.26 2012/12/15 00:03:00 jakllsch Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -67,6 +67,8 @@ __KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,
#define DPRINTF(s) do {} while (/*CONSTCOND*/0)
#endif
+typedef struct { uint32_t _bits[512/32]; } __packed __aligned(4) sdmmc_bitfield512_t;
+
static int sdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *);
static int sdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *);
static int sdmmc_mem_send_cid(struct sdmmc_softc *, sdmmc_response *);
@@ -77,7 +79,7 @@ static int sdmmc_mem_send_scr(struct sdm
static int sdmmc_mem_decode_scr(struct sdmmc_softc *, struct sdmmc_function *);
static int sdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void *, size_t);
static int sdmmc_set_bus_width(struct sdmmc_function *, int);
-static int sdmmc_mem_sd_switch(struct sdmmc_function *, int, int, int, void *);
+static int sdmmc_mem_sd_switch(struct sdmmc_function *, int, int, int, sdmmc_bitfield512_t *);
static int sdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t,
uint8_t);
static int sdmmc_mem_spi_read_ocr(struct sdmmc_softc *, uint32_t, uint32_t *);
@@ -574,6 +576,20 @@ sdmmc_mem_set_blocklen(struct sdmmc_soft
return error;
}
+/* make 512-bit BE quantity __bitfield()-compatible */
+static void
+sdmmc_be512_to_bitfield512(sdmmc_bitfield512_t *buf) {
+ size_t i;
+ uint32_t tmp0, tmp1;
+ const size_t bitswords = __arraycount(buf->_bits);
+ for (i = 0; i < bitswords/2; i++) {
+ tmp0 = buf->_bits[i];
+ tmp1 = buf->_bits[bitswords - 1 - i];
+ buf->_bits[i] = be32toh(tmp1);
+ buf->_bits[bitswords - 1 - i] = be32toh(tmp0);
+ }
+}
+
static int
sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
{
@@ -599,7 +615,7 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc
{ MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 50000 },
};
int host_ocr, support_func, best_func, error, g, i;
- char status[64];
+ sdmmc_bitfield512_t status; /* Switch Function Status */
error = sdmmc_mem_send_scr(sc, sf, sf->raw_scr);
if (error) {
@@ -625,7 +641,7 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc
if (sf->scr.sd_spec >= SCR_SD_SPEC_VER_1_10 &&
ISSET(sf->csd.ccc, SD_CSD_CCC_SWITCH)) {
DPRINTF(("%s: switch func mode 0\n", SDMMCDEVNAME(sc)));
- error = sdmmc_mem_sd_switch(sf, 0, 1, 0, status);
+ error = sdmmc_mem_sd_switch(sf, 0, 1, 0, &status);
if (error) {
aprint_error_dev(sc->sc_dev,
"switch func mode 0 failed\n");
@@ -633,7 +649,7 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc
}
host_ocr = sdmmc_chip_host_ocr(sc->sc_sct, sc->sc_sch);
- support_func = SFUNC_STATUS_GROUP(status, 1);
+ support_func = SFUNC_STATUS_GROUP(&status, 1);
best_func = 0;
for (i = 0, g = 1;
i < __arraycount(switch_group0_functions); i++, g <<= 1) {
@@ -647,7 +663,7 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc
DPRINTF(("%s: switch func mode 1(func=%d)\n",
SDMMCDEVNAME(sc), best_func));
error =
- sdmmc_mem_sd_switch(sf, 1, 1, best_func, status);
+ sdmmc_mem_sd_switch(sf, 1, 1, best_func, &status);
if (error) {
aprint_error_dev(sc->sc_dev,
"switch func mode 1 failed:"
@@ -1059,7 +1075,7 @@ sdmmc_set_bus_width(struct sdmmc_functio
static int
sdmmc_mem_sd_switch(struct sdmmc_function *sf, int mode, int group,
- int function, void *status)
+ int function, sdmmc_bitfield512_t *status)
{
struct sdmmc_softc *sc = sf->sc;
struct sdmmc_command cmd;
@@ -1132,6 +1148,10 @@ dmamem_free:
free(ptr, M_DEVBUF);
}
}
+
+ if (error == 0)
+ sdmmc_be512_to_bitfield512(status);
+
return error;
}
Index: src/sys/dev/sdmmc/sdmmcreg.h
diff -u src/sys/dev/sdmmc/sdmmcreg.h:1.12 src/sys/dev/sdmmc/sdmmcreg.h:1.13
--- src/sys/dev/sdmmc/sdmmcreg.h:1.12 Sat Jul 28 18:38:03 2012
+++ src/sys/dev/sdmmc/sdmmcreg.h Sat Dec 15 00:03:00 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: sdmmcreg.h,v 1.12 2012/07/28 18:38:03 matt Exp $ */
+/* $NetBSD: sdmmcreg.h,v 1.13 2012/12/15 00:03:00 jakllsch Exp $ */
/* $OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $ */
/*
@@ -318,14 +318,14 @@
/* Status of Switch Function */
#define SFUNC_STATUS_GROUP(status, group) \
- be16toh(__bitfield((uint32_t *)(status), (7 - (group)) << 4, 16))
+ (__bitfield((uint32_t *)(status), 400 + (group - 1) * 16, 16))
/* 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 uint32_t
__bitfield(const uint32_t *src, size_t start, size_t len)
{
- if (start + len > 128 || len == 0 || len > 32)
+ if (start + len > 512 || len == 0 || len > 32)
return 0;
src += start / 32;