| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: sdmmc_mem.c,v 1.25 2012/12/14 23:22:21 jakllsch Exp $ */ | | 1 | /* $NetBSD: sdmmc_mem.c,v 1.26 2012/12/15 00:03:00 jakllsch Exp $ */ |
2 | /* $OpenBSD: sdmmc_mem.c,v 1.10 2009/01/09 10:55:22 jsg Exp $ */ | | 2 | /* $OpenBSD: sdmmc_mem.c,v 1.10 2009/01/09 10:55:22 jsg Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> | | 5 | * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> |
6 | * | | 6 | * |
7 | * Permission to use, copy, modify, and distribute this software for any | | 7 | * Permission to use, copy, modify, and distribute this software for any |
8 | * purpose with or without fee is hereby granted, provided that the above | | 8 | * purpose with or without fee is hereby granted, provided that the above |
9 | * copyright notice and this permission notice appear in all copies. | | 9 | * copyright notice and this permission notice appear in all copies. |
10 | * | | 10 | * |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | | 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | | 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | | 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | | 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| @@ -35,59 +35,61 @@ | | | @@ -35,59 +35,61 @@ |
35 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 35 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
36 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 36 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
37 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 37 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
38 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 38 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
39 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 39 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
40 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 40 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
41 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 41 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
42 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 42 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
43 | */ | | 43 | */ |
44 | | | 44 | |
45 | /* Routines for SD/MMC memory cards. */ | | 45 | /* Routines for SD/MMC memory cards. */ |
46 | | | 46 | |
47 | #include <sys/cdefs.h> | | 47 | #include <sys/cdefs.h> |
48 | __KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.25 2012/12/14 23:22:21 jakllsch Exp $"); | | 48 | __KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.26 2012/12/15 00:03:00 jakllsch Exp $"); |
49 | | | 49 | |
50 | #ifdef _KERNEL_OPT | | 50 | #ifdef _KERNEL_OPT |
51 | #include "opt_sdmmc.h" | | 51 | #include "opt_sdmmc.h" |
52 | #endif | | 52 | #endif |
53 | | | 53 | |
54 | #include <sys/param.h> | | 54 | #include <sys/param.h> |
55 | #include <sys/kernel.h> | | 55 | #include <sys/kernel.h> |
56 | #include <sys/malloc.h> | | 56 | #include <sys/malloc.h> |
57 | #include <sys/systm.h> | | 57 | #include <sys/systm.h> |
58 | #include <sys/device.h> | | 58 | #include <sys/device.h> |
59 | | | 59 | |
60 | #include <dev/sdmmc/sdmmcchip.h> | | 60 | #include <dev/sdmmc/sdmmcchip.h> |
61 | #include <dev/sdmmc/sdmmcreg.h> | | 61 | #include <dev/sdmmc/sdmmcreg.h> |
62 | #include <dev/sdmmc/sdmmcvar.h> | | 62 | #include <dev/sdmmc/sdmmcvar.h> |
63 | | | 63 | |
64 | #ifdef SDMMC_DEBUG | | 64 | #ifdef SDMMC_DEBUG |
65 | #define DPRINTF(s) do { printf s; } while (/*CONSTCOND*/0) | | 65 | #define DPRINTF(s) do { printf s; } while (/*CONSTCOND*/0) |
66 | #else | | 66 | #else |
67 | #define DPRINTF(s) do {} while (/*CONSTCOND*/0) | | 67 | #define DPRINTF(s) do {} while (/*CONSTCOND*/0) |
68 | #endif | | 68 | #endif |
69 | | | 69 | |
| | | 70 | typedef struct { uint32_t _bits[512/32]; } __packed __aligned(4) sdmmc_bitfield512_t; |
| | | 71 | |
70 | static int sdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *); | | 72 | static int sdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *); |
71 | static int sdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *); | | 73 | static int sdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *); |
72 | static int sdmmc_mem_send_cid(struct sdmmc_softc *, sdmmc_response *); | | 74 | static int sdmmc_mem_send_cid(struct sdmmc_softc *, sdmmc_response *); |
73 | static int sdmmc_mem_send_csd(struct sdmmc_softc *, struct sdmmc_function *, | | 75 | static int sdmmc_mem_send_csd(struct sdmmc_softc *, struct sdmmc_function *, |
74 | sdmmc_response *); | | 76 | sdmmc_response *); |
75 | static int sdmmc_mem_send_scr(struct sdmmc_softc *, struct sdmmc_function *, | | 77 | static int sdmmc_mem_send_scr(struct sdmmc_softc *, struct sdmmc_function *, |
76 | uint32_t scr[2]); | | 78 | uint32_t scr[2]); |
77 | static int sdmmc_mem_decode_scr(struct sdmmc_softc *, struct sdmmc_function *); | | 79 | static int sdmmc_mem_decode_scr(struct sdmmc_softc *, struct sdmmc_function *); |
78 | static int sdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void *, size_t); | | 80 | static int sdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void *, size_t); |
79 | static int sdmmc_set_bus_width(struct sdmmc_function *, int); | | 81 | static int sdmmc_set_bus_width(struct sdmmc_function *, int); |
80 | static int sdmmc_mem_sd_switch(struct sdmmc_function *, int, int, int, void *); | | 82 | static int sdmmc_mem_sd_switch(struct sdmmc_function *, int, int, int, sdmmc_bitfield512_t *); |
81 | static int sdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t, | | 83 | static int sdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t, |
82 | uint8_t); | | 84 | uint8_t); |
83 | static int sdmmc_mem_spi_read_ocr(struct sdmmc_softc *, uint32_t, uint32_t *); | | 85 | static int sdmmc_mem_spi_read_ocr(struct sdmmc_softc *, uint32_t, uint32_t *); |
84 | static int sdmmc_mem_single_read_block(struct sdmmc_function *, uint32_t, | | 86 | static int sdmmc_mem_single_read_block(struct sdmmc_function *, uint32_t, |
85 | u_char *, size_t); | | 87 | u_char *, size_t); |
86 | static int sdmmc_mem_single_write_block(struct sdmmc_function *, uint32_t, | | 88 | static int sdmmc_mem_single_write_block(struct sdmmc_function *, uint32_t, |
87 | u_char *, size_t); | | 89 | u_char *, size_t); |
88 | static int sdmmc_mem_read_block_subr(struct sdmmc_function *, uint32_t, | | 90 | static int sdmmc_mem_read_block_subr(struct sdmmc_function *, uint32_t, |
89 | u_char *, size_t); | | 91 | u_char *, size_t); |
90 | static int sdmmc_mem_write_block_subr(struct sdmmc_function *, uint32_t, | | 92 | static int sdmmc_mem_write_block_subr(struct sdmmc_function *, uint32_t, |
91 | u_char *, size_t); | | 93 | u_char *, size_t); |
92 | | | 94 | |
93 | /* | | 95 | /* |
| @@ -564,100 +566,114 @@ sdmmc_mem_set_blocklen(struct sdmmc_soft | | | @@ -564,100 +566,114 @@ sdmmc_mem_set_blocklen(struct sdmmc_soft |
564 | memset(&cmd, 0, sizeof(cmd)); | | 566 | memset(&cmd, 0, sizeof(cmd)); |
565 | cmd.c_opcode = MMC_SET_BLOCKLEN; | | 567 | cmd.c_opcode = MMC_SET_BLOCKLEN; |
566 | cmd.c_arg = SDMMC_SECTOR_SIZE; | | 568 | cmd.c_arg = SDMMC_SECTOR_SIZE; |
567 | cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1 | SCF_RSP_SPI_R1; | | 569 | cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1 | SCF_RSP_SPI_R1; |
568 | | | 570 | |
569 | error = sdmmc_mmc_command(sc, &cmd); | | 571 | error = sdmmc_mmc_command(sc, &cmd); |
570 | | | 572 | |
571 | DPRINTF(("%s: sdmmc_mem_set_blocklen: read_bl_len=%d sector_size=%d\n", | | 573 | DPRINTF(("%s: sdmmc_mem_set_blocklen: read_bl_len=%d sector_size=%d\n", |
572 | SDMMCDEVNAME(sc), 1 << sf->csd.read_bl_len, SDMMC_SECTOR_SIZE)); | | 574 | SDMMCDEVNAME(sc), 1 << sf->csd.read_bl_len, SDMMC_SECTOR_SIZE)); |
573 | | | 575 | |
574 | return error; | | 576 | return error; |
575 | } | | 577 | } |
576 | | | 578 | |
| | | 579 | /* make 512-bit BE quantity __bitfield()-compatible */ |
| | | 580 | static void |
| | | 581 | sdmmc_be512_to_bitfield512(sdmmc_bitfield512_t *buf) { |
| | | 582 | size_t i; |
| | | 583 | uint32_t tmp0, tmp1; |
| | | 584 | const size_t bitswords = __arraycount(buf->_bits); |
| | | 585 | for (i = 0; i < bitswords/2; i++) { |
| | | 586 | tmp0 = buf->_bits[i]; |
| | | 587 | tmp1 = buf->_bits[bitswords - 1 - i]; |
| | | 588 | buf->_bits[i] = be32toh(tmp1); |
| | | 589 | buf->_bits[bitswords - 1 - i] = be32toh(tmp0); |
| | | 590 | } |
| | | 591 | } |
| | | 592 | |
577 | static int | | 593 | static int |
578 | sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf) | | 594 | sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf) |
579 | { | | 595 | { |
580 | static const struct { | | 596 | static const struct { |
581 | int v; | | 597 | int v; |
582 | int freq; | | 598 | int freq; |
583 | } switch_group0_functions[] = { | | 599 | } switch_group0_functions[] = { |
584 | /* Default/SDR12 */ | | 600 | /* Default/SDR12 */ |
585 | { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V | | | 601 | { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V | |
586 | MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V, 25000 }, | | 602 | MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V, 25000 }, |
587 | | | 603 | |
588 | /* High-Speed/SDR25 */ | | 604 | /* High-Speed/SDR25 */ |
589 | { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V | | | 605 | { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V | |
590 | MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V, 50000 }, | | 606 | MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V, 50000 }, |
591 | | | 607 | |
592 | /* SDR50 */ | | 608 | /* SDR50 */ |
593 | { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 100000 }, | | 609 | { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 100000 }, |
594 | | | 610 | |
595 | /* SDR104 */ | | 611 | /* SDR104 */ |
596 | { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 208000 }, | | 612 | { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 208000 }, |
597 | | | 613 | |
598 | /* DDR50 */ | | 614 | /* DDR50 */ |
599 | { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 50000 }, | | 615 | { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 50000 }, |
600 | }; | | 616 | }; |
601 | int host_ocr, support_func, best_func, error, g, i; | | 617 | int host_ocr, support_func, best_func, error, g, i; |
602 | char status[64]; | | 618 | sdmmc_bitfield512_t status; /* Switch Function Status */ |
603 | | | 619 | |
604 | error = sdmmc_mem_send_scr(sc, sf, sf->raw_scr); | | 620 | error = sdmmc_mem_send_scr(sc, sf, sf->raw_scr); |
605 | if (error) { | | 621 | if (error) { |
606 | aprint_error_dev(sc->sc_dev, "SD_SEND_SCR send failed.\n"); | | 622 | aprint_error_dev(sc->sc_dev, "SD_SEND_SCR send failed.\n"); |
607 | return error; | | 623 | return error; |
608 | } | | 624 | } |
609 | error = sdmmc_mem_decode_scr(sc, sf); | | 625 | error = sdmmc_mem_decode_scr(sc, sf); |
610 | if (error) | | 626 | if (error) |
611 | return error; | | 627 | return error; |
612 | | | 628 | |
613 | if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE) && | | 629 | if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE) && |
614 | ISSET(sf->scr.bus_width, SCR_SD_BUS_WIDTHS_4BIT)) { | | 630 | ISSET(sf->scr.bus_width, SCR_SD_BUS_WIDTHS_4BIT)) { |
615 | DPRINTF(("%s: change bus width\n", SDMMCDEVNAME(sc))); | | 631 | DPRINTF(("%s: change bus width\n", SDMMCDEVNAME(sc))); |
616 | error = sdmmc_set_bus_width(sf, 4); | | 632 | error = sdmmc_set_bus_width(sf, 4); |
617 | if (error) { | | 633 | if (error) { |
618 | aprint_error_dev(sc->sc_dev, | | 634 | aprint_error_dev(sc->sc_dev, |
619 | "can't change bus width (%d bit)\n", 4); | | 635 | "can't change bus width (%d bit)\n", 4); |
620 | return error; | | 636 | return error; |
621 | } | | 637 | } |
622 | sf->width = 4; | | 638 | sf->width = 4; |
623 | } | | 639 | } |
624 | | | 640 | |
625 | if (sf->scr.sd_spec >= SCR_SD_SPEC_VER_1_10 && | | 641 | if (sf->scr.sd_spec >= SCR_SD_SPEC_VER_1_10 && |
626 | ISSET(sf->csd.ccc, SD_CSD_CCC_SWITCH)) { | | 642 | ISSET(sf->csd.ccc, SD_CSD_CCC_SWITCH)) { |
627 | DPRINTF(("%s: switch func mode 0\n", SDMMCDEVNAME(sc))); | | 643 | DPRINTF(("%s: switch func mode 0\n", SDMMCDEVNAME(sc))); |
628 | error = sdmmc_mem_sd_switch(sf, 0, 1, 0, status); | | 644 | error = sdmmc_mem_sd_switch(sf, 0, 1, 0, &status); |
629 | if (error) { | | 645 | if (error) { |
630 | aprint_error_dev(sc->sc_dev, | | 646 | aprint_error_dev(sc->sc_dev, |
631 | "switch func mode 0 failed\n"); | | 647 | "switch func mode 0 failed\n"); |
632 | return error; | | 648 | return error; |
633 | } | | 649 | } |
634 | | | 650 | |
635 | host_ocr = sdmmc_chip_host_ocr(sc->sc_sct, sc->sc_sch); | | 651 | host_ocr = sdmmc_chip_host_ocr(sc->sc_sct, sc->sc_sch); |
636 | support_func = SFUNC_STATUS_GROUP(status, 1); | | 652 | support_func = SFUNC_STATUS_GROUP(&status, 1); |
637 | best_func = 0; | | 653 | best_func = 0; |
638 | for (i = 0, g = 1; | | 654 | for (i = 0, g = 1; |
639 | i < __arraycount(switch_group0_functions); i++, g <<= 1) { | | 655 | i < __arraycount(switch_group0_functions); i++, g <<= 1) { |
640 | if (!(switch_group0_functions[i].v & host_ocr)) | | 656 | if (!(switch_group0_functions[i].v & host_ocr)) |
641 | continue; | | 657 | continue; |
642 | if (g & support_func) | | 658 | if (g & support_func) |
643 | best_func = i; | | 659 | best_func = i; |
644 | } | | 660 | } |
645 | if (ISSET(sc->sc_caps, SMC_CAPS_SD_HIGHSPEED) && | | 661 | if (ISSET(sc->sc_caps, SMC_CAPS_SD_HIGHSPEED) && |
646 | best_func != 0) { | | 662 | best_func != 0) { |
647 | DPRINTF(("%s: switch func mode 1(func=%d)\n", | | 663 | DPRINTF(("%s: switch func mode 1(func=%d)\n", |
648 | SDMMCDEVNAME(sc), best_func)); | | 664 | SDMMCDEVNAME(sc), best_func)); |
649 | error = | | 665 | error = |
650 | sdmmc_mem_sd_switch(sf, 1, 1, best_func, status); | | 666 | sdmmc_mem_sd_switch(sf, 1, 1, best_func, &status); |
651 | if (error) { | | 667 | if (error) { |
652 | aprint_error_dev(sc->sc_dev, | | 668 | aprint_error_dev(sc->sc_dev, |
653 | "switch func mode 1 failed:" | | 669 | "switch func mode 1 failed:" |
654 | " group 1 function %d(0x%2x)\n", | | 670 | " group 1 function %d(0x%2x)\n", |
655 | best_func, support_func); | | 671 | best_func, support_func); |
656 | return error; | | 672 | return error; |
657 | } | | 673 | } |
658 | sf->csd.tran_speed = | | 674 | sf->csd.tran_speed = |
659 | switch_group0_functions[best_func].freq; | | 675 | switch_group0_functions[best_func].freq; |
660 | | | 676 | |
661 | /* Wait 400KHz x 8 clock (2.5us * 8 + slop) */ | | 677 | /* Wait 400KHz x 8 clock (2.5us * 8 + slop) */ |
662 | delay(25); | | 678 | delay(25); |
663 | } | | 679 | } |
| @@ -1049,27 +1065,27 @@ sdmmc_set_bus_width(struct sdmmc_functio | | | @@ -1049,27 +1065,27 @@ sdmmc_set_bus_width(struct sdmmc_functio |
1049 | | | 1065 | |
1050 | default: | | 1066 | default: |
1051 | return EINVAL; | | 1067 | return EINVAL; |
1052 | } | | 1068 | } |
1053 | | | 1069 | |
1054 | error = sdmmc_app_command(sc, sf, &cmd); | | 1070 | error = sdmmc_app_command(sc, sf, &cmd); |
1055 | if (error == 0) | | 1071 | if (error == 0) |
1056 | error = sdmmc_chip_bus_width(sc->sc_sct, sc->sc_sch, width); | | 1072 | error = sdmmc_chip_bus_width(sc->sc_sct, sc->sc_sch, width); |
1057 | return error; | | 1073 | return error; |
1058 | } | | 1074 | } |
1059 | | | 1075 | |
1060 | static int | | 1076 | static int |
1061 | sdmmc_mem_sd_switch(struct sdmmc_function *sf, int mode, int group, | | 1077 | sdmmc_mem_sd_switch(struct sdmmc_function *sf, int mode, int group, |
1062 | int function, void *status) | | 1078 | int function, sdmmc_bitfield512_t *status) |
1063 | { | | 1079 | { |
1064 | struct sdmmc_softc *sc = sf->sc; | | 1080 | struct sdmmc_softc *sc = sf->sc; |
1065 | struct sdmmc_command cmd; | | 1081 | struct sdmmc_command cmd; |
1066 | bus_dma_segment_t ds[1]; | | 1082 | bus_dma_segment_t ds[1]; |
1067 | void *ptr = NULL; | | 1083 | void *ptr = NULL; |
1068 | int gsft, rseg, error = 0; | | 1084 | int gsft, rseg, error = 0; |
1069 | const int statlen = 64; | | 1085 | const int statlen = 64; |
1070 | | | 1086 | |
1071 | if (sf->scr.sd_spec >= SCR_SD_SPEC_VER_1_10 && | | 1087 | if (sf->scr.sd_spec >= SCR_SD_SPEC_VER_1_10 && |
1072 | !ISSET(sf->csd.ccc, SD_CSD_CCC_SWITCH)) | | 1088 | !ISSET(sf->csd.ccc, SD_CSD_CCC_SWITCH)) |
1073 | return EINVAL; | | 1089 | return EINVAL; |
1074 | | | 1090 | |
1075 | if (group <= 0 || group > 6 || | | 1091 | if (group <= 0 || group > 6 || |
| @@ -1122,26 +1138,30 @@ sdmmc_mem_sd_switch(struct sdmmc_functio | | | @@ -1122,26 +1138,30 @@ sdmmc_mem_sd_switch(struct sdmmc_functio |
1122 | | | 1138 | |
1123 | out: | | 1139 | out: |
1124 | if (ptr != NULL) { | | 1140 | if (ptr != NULL) { |
1125 | if (ISSET(sc->sc_caps, SMC_CAPS_DMA)) { | | 1141 | if (ISSET(sc->sc_caps, SMC_CAPS_DMA)) { |
1126 | bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap); | | 1142 | bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap); |
1127 | dmamem_unmap: | | 1143 | dmamem_unmap: |
1128 | bus_dmamem_unmap(sc->sc_dmat, ptr, statlen); | | 1144 | bus_dmamem_unmap(sc->sc_dmat, ptr, statlen); |
1129 | dmamem_free: | | 1145 | dmamem_free: |
1130 | bus_dmamem_free(sc->sc_dmat, ds, rseg); | | 1146 | bus_dmamem_free(sc->sc_dmat, ds, rseg); |
1131 | } else { | | 1147 | } else { |
1132 | free(ptr, M_DEVBUF); | | 1148 | free(ptr, M_DEVBUF); |
1133 | } | | 1149 | } |
1134 | } | | 1150 | } |
| | | 1151 | |
| | | 1152 | if (error == 0) |
| | | 1153 | sdmmc_be512_to_bitfield512(status); |
| | | 1154 | |
1135 | return error; | | 1155 | return error; |
1136 | } | | 1156 | } |
1137 | | | 1157 | |
1138 | static int | | 1158 | static int |
1139 | sdmmc_mem_mmc_switch(struct sdmmc_function *sf, uint8_t set, uint8_t index, | | 1159 | sdmmc_mem_mmc_switch(struct sdmmc_function *sf, uint8_t set, uint8_t index, |
1140 | uint8_t value) | | 1160 | uint8_t value) |
1141 | { | | 1161 | { |
1142 | struct sdmmc_softc *sc = sf->sc; | | 1162 | struct sdmmc_softc *sc = sf->sc; |
1143 | struct sdmmc_command cmd; | | 1163 | struct sdmmc_command cmd; |
1144 | | | 1164 | |
1145 | memset(&cmd, 0, sizeof(cmd)); | | 1165 | memset(&cmd, 0, sizeof(cmd)); |
1146 | cmd.c_opcode = MMC_SWITCH; | | 1166 | cmd.c_opcode = MMC_SWITCH; |
1147 | cmd.c_arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | | | 1167 | cmd.c_arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | |