CVS commit: [netbsd-6] src/sys/dev/sdmmc
Module Name:src Committed By: riz Date: Wed Jan 2 23:34:56 UTC 2013 Modified Files: src/sys/dev/sdmmc [netbsd-6]: sdhc.c sdhcreg.h Log Message: sys/dev/sdmmc/sdhc.cpatch sys/dev/sdmmc/sdhcreg.h patch Support SDHC version 3 clocks. [skrll, ticket #759] To generate a diff of this commit: cvs rdiff -u -r1.10.2.3 -r1.10.2.4 src/sys/dev/sdmmc/sdhc.c cvs rdiff -u -r1.5.2.1 -r1.5.2.2 src/sys/dev/sdmmc/sdhcreg.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.3 src/sys/dev/sdmmc/sdhc.c:1.10.2.4 --- src/sys/dev/sdmmc/sdhc.c:1.10.2.3 Thu Aug 9 06:36:48 2012 +++ src/sys/dev/sdmmc/sdhc.c Wed Jan 2 23:34:56 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: sdhc.c,v 1.10.2.3 2012/08/09 06:36:48 jdc Exp $ */ +/* $NetBSD: sdhc.c,v 1.10.2.4 2013/01/02 23:34:56 riz 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.3 2012/08/09 06:36:48 jdc Exp $); +__KERNEL_RCSID(0, $NetBSD: sdhc.c,v 1.10.2.4 2013/01/02 23:34:56 riz Exp $); #ifdef _KERNEL_OPT #include opt_sdmmc.h @@ -79,6 +79,8 @@ struct sdhc_host { struct kmutex intr_mtx; struct kcondvar intr_cv; + int specver; /* spec. version */ + uint32_t flags; /* flags for this host */ #define SHF_USE_DMA 0x0001 #define SHF_USE_4BIT_MODE 0x0002 @@ -223,26 +225,8 @@ sdhc_host_found(struct sdhc_softc *sc, b struct sdmmcbus_attach_args saa; struct sdhc_host *hp; uint32_t caps; -#ifdef SDHC_DEBUG uint16_t sdhcver; - sdhcver = bus_space_read_2(iot, ioh, SDHC_HOST_CTL_VERSION); - aprint_normal_dev(sc-sc_dev, SD Host Specification/Vendor Version ); - switch (SDHC_SPEC_VERSION(sdhcver)) { - case 0x00: - aprint_normal(1.0/%u\n, SDHC_VENDOR_VERSION(sdhcver)); - break; - - case 0x01: - aprint_normal(2.0/%u\n, SDHC_VENDOR_VERSION(sdhcver)); - break; - - default: - aprint_normal(2.0/%u\n, SDHC_VENDOR_VERSION(sdhcver)); - break; - } -#endif - /* Allocate one more host structure. */ hp = malloc(sizeof(struct sdhc_host), M_DEVBUF, M_WAITOK|M_ZERO); if (hp == NULL) { @@ -262,6 +246,29 @@ sdhc_host_found(struct sdhc_softc *sc, b mutex_init(hp-intr_mtx, MUTEX_DEFAULT, IPL_SDMMC); cv_init(hp-intr_cv, sdhcintr); + sdhcver = HREAD2(hp, SDHC_HOST_CTL_VERSION); + aprint_normal_dev(sc-sc_dev, SD Host Specification ); + hp-specver = SDHC_SPEC_VERSION(sdhcver); + switch (SDHC_SPEC_VERSION(sdhcver)) { + case SDHC_SPEC_VERS_100: + aprint_normal(1.0); + break; + + case SDHC_SPEC_VERS_200: + aprint_normal(2.0); + break; + + case SDHC_SPEC_VERS_300: + aprint_normal(3.0); + break; + + default: + aprint_normal(unknown version(0x%x), + SDHC_SPEC_VERSION(sdhcver)); + break; + } + aprint_normal(, rev.%u\n, SDHC_VENDOR_VERSION(sdhcver)); + /* * Reset the host controller and enable interrupts. */ @@ -289,8 +296,11 @@ sdhc_host_found(struct sdhc_softc *sc, b /* * Determine the base clock frequency. (2.2.24) */ - if (SDHC_BASE_FREQ_KHZ(caps) != 0) + if (hp-specver == SDHC_SPEC_VERS_300) { + hp-clkbase = SDHC_BASE_V3_FREQ_KHZ(caps); + } else { hp-clkbase = SDHC_BASE_FREQ_KHZ(caps); + } if (hp-clkbase == 0) { if (sc-sc_clkbase == 0) { /* The attachment driver must tell us. */ @@ -370,12 +380,16 @@ sdhc_host_found(struct sdhc_softc *sc, b saa.saa_sct = sdhc_functions; saa.saa_sch = hp; saa.saa_dmat = hp-dmat; - saa.saa_clkmin = hp-clkbase / 256; saa.saa_clkmax = hp-clkbase; if (ISSET(sc-sc_flags, SDHC_FLAG_HAVE_CGM)) - saa.saa_clkmin /= 2046; + saa.saa_clkmin = hp-clkbase / 256 / 2046; else if (ISSET(sc-sc_flags, SDHC_FLAG_HAVE_DVS)) - saa.saa_clkmin /= 16; + saa.saa_clkmin = hp-clkbase / 256 / 16; + else if (hp-specver == SDHC_SPEC_VERS_300) + saa.saa_clkmin = hp-clkbase / 0x3ff; + else + saa.saa_clkmin = hp-clkbase / 256; + saa.saa_caps = SMC_CAPS_4BIT_MODE|SMC_CAPS_AUTO_STOP; if (ISSET(sc-sc_flags, SDHC_FLAG_8BIT_MODE)) saa.saa_caps |= SMC_CAPS_8BIT_MODE; @@ -725,16 +739,29 @@ sdhc_clock_divisor(struct sdhc_host *hp, */ roundup |= dvs 1; } - panic(%s: can't find divisor for freq %u, HDEVNAME(hp), freq); + /* No divisor found. */ + return false; + } + if (hp-specver == SDHC_SPEC_VERS_300) { + div = howmany(hp-clkbase, freq); + if (div 0x3ff) + return false; + *divp = (((div 8) SDHC_SDCLK_XDIV_MASK) + SDHC_SDCLK_XDIV_SHIFT) | + (((div 0) SDHC_SDCLK_DIV_MASK) + SDHC_SDCLK_DIV_SHIFT); + return true; } else { for (div = 1; div = 256; div *= 2) { if ((hp-clkbase / div) = freq) { *divp = (div / 2) SDHC_SDCLK_DIV_SHIFT; +//freq = hp-clkbase / div; return true; } } + /* No divisor found. */ + return false; } - /* No divisor found. */ return false; } Index: src/sys/dev/sdmmc/sdhcreg.h diff -u
CVS commit: [netbsd-6] src/sys/dev/sdmmc
Module Name:src Committed By: riz Date: Wed Jan 2 23:34:56 UTC 2013 Modified Files: src/sys/dev/sdmmc [netbsd-6]: sdhc.c sdhcreg.h Log Message: sys/dev/sdmmc/sdhc.cpatch sys/dev/sdmmc/sdhcreg.h patch Support SDHC version 3 clocks. [skrll, ticket #759] To generate a diff of this commit: cvs rdiff -u -r1.10.2.3 -r1.10.2.4 src/sys/dev/sdmmc/sdhc.c cvs rdiff -u -r1.5.2.1 -r1.5.2.2 src/sys/dev/sdmmc/sdhcreg.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: [netbsd-6] src/sys/dev/sdmmc
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;
CVS commit: [netbsd-6] src/sys/dev/sdmmc
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.