172dec079SMarius Strobl /*- 272dec079SMarius Strobl * Copyright (c) 2006 Bernd Walter. All rights reserved. 372dec079SMarius Strobl * Copyright (c) 2006 M. Warner Losh. All rights reserved. 472dec079SMarius Strobl * 572dec079SMarius Strobl * Redistribution and use in source and binary forms, with or without 672dec079SMarius Strobl * modification, are permitted provided that the following conditions 772dec079SMarius Strobl * are met: 872dec079SMarius Strobl * 1. Redistributions of source code must retain the above copyright 972dec079SMarius Strobl * notice, this list of conditions and the following disclaimer. 1072dec079SMarius Strobl * 2. Redistributions in binary form must reproduce the above copyright 1172dec079SMarius Strobl * notice, this list of conditions and the following disclaimer in the 1272dec079SMarius Strobl * documentation and/or other materials provided with the distribution. 1372dec079SMarius Strobl * 1472dec079SMarius Strobl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1572dec079SMarius Strobl * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1672dec079SMarius Strobl * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1772dec079SMarius Strobl * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1872dec079SMarius Strobl * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1972dec079SMarius Strobl * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2072dec079SMarius Strobl * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2172dec079SMarius Strobl * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2272dec079SMarius Strobl * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2372dec079SMarius Strobl * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2472dec079SMarius Strobl * 2572dec079SMarius Strobl * Portions of this software may have been developed with reference to 2672dec079SMarius Strobl * the SD Simplified Specification. The following disclaimer may apply: 2772dec079SMarius Strobl * 2872dec079SMarius Strobl * The following conditions apply to the release of the simplified 2972dec079SMarius Strobl * specification ("Simplified Specification") by the SD Card Association and 3072dec079SMarius Strobl * the SD Group. The Simplified Specification is a subset of the complete SD 3172dec079SMarius Strobl * Specification which is owned by the SD Card Association and the SD 3272dec079SMarius Strobl * Group. This Simplified Specification is provided on a non-confidential 3372dec079SMarius Strobl * basis subject to the disclaimers below. Any implementation of the 3472dec079SMarius Strobl * Simplified Specification may require a license from the SD Card 3572dec079SMarius Strobl * Association, SD Group, SD-3C LLC or other third parties. 3672dec079SMarius Strobl * 3772dec079SMarius Strobl * Disclaimers: 3872dec079SMarius Strobl * 3972dec079SMarius Strobl * The information contained in the Simplified Specification is presented only 4072dec079SMarius Strobl * as a standard specification for SD Cards and SD Host/Ancillary products and 4172dec079SMarius Strobl * is provided "AS-IS" without any representations or warranties of any 4272dec079SMarius Strobl * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD 4372dec079SMarius Strobl * Card Association for any damages, any infringements of patents or other 4472dec079SMarius Strobl * right of the SD Group, SD-3C LLC, the SD Card Association or any third 4572dec079SMarius Strobl * parties, which may result from its use. No license is granted by 4672dec079SMarius Strobl * implication, estoppel or otherwise under any patent or other rights of the 4772dec079SMarius Strobl * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing 4872dec079SMarius Strobl * herein shall be construed as an obligation by the SD Group, the SD-3C LLC 4972dec079SMarius Strobl * or the SD Card Association to disclose or distribute any technical 5072dec079SMarius Strobl * information, know-how or other confidential information to any third party. 5172dec079SMarius Strobl */ 5272dec079SMarius Strobl 5372dec079SMarius Strobl #include <sys/cdefs.h> 5472dec079SMarius Strobl __FBSDID("$FreeBSD$"); 5572dec079SMarius Strobl 5672dec079SMarius Strobl #include <sys/param.h> 5772dec079SMarius Strobl #include <sys/systm.h> 5872dec079SMarius Strobl #include <sys/kernel.h> 5972dec079SMarius Strobl #include <sys/lock.h> 6072dec079SMarius Strobl #include <sys/mutex.h> 6172dec079SMarius Strobl #include <sys/time.h> 6272dec079SMarius Strobl 6372dec079SMarius Strobl #include <dev/mmc/bridge.h> 6472dec079SMarius Strobl #include <dev/mmc/mmc_private.h> 6572dec079SMarius Strobl #include <dev/mmc/mmc_subr.h> 6672dec079SMarius Strobl #include <dev/mmc/mmcreg.h> 6772dec079SMarius Strobl #include <dev/mmc/mmcbrvar.h> 6872dec079SMarius Strobl 6972dec079SMarius Strobl #include "mmcbus_if.h" 7072dec079SMarius Strobl 7172dec079SMarius Strobl #define CMD_RETRIES 3 7272dec079SMarius Strobl #define LOG_PPS 5 /* Log no more than 5 errors per second. */ 7372dec079SMarius Strobl 7472dec079SMarius Strobl int 75*cd85acbaSMarius Strobl mmc_wait_for_cmd(device_t busdev, device_t dev, struct mmc_command *cmd, 7672dec079SMarius Strobl int retries) 7772dec079SMarius Strobl { 7872dec079SMarius Strobl struct mmc_request mreq; 7972dec079SMarius Strobl struct mmc_softc *sc; 8072dec079SMarius Strobl int err; 8172dec079SMarius Strobl 8272dec079SMarius Strobl do { 8372dec079SMarius Strobl memset(&mreq, 0, sizeof(mreq)); 8472dec079SMarius Strobl memset(cmd->resp, 0, sizeof(cmd->resp)); 8572dec079SMarius Strobl cmd->retries = 0; /* Retries done here, not in hardware. */ 8672dec079SMarius Strobl cmd->mrq = &mreq; 8772dec079SMarius Strobl if (cmd->data != NULL) 8872dec079SMarius Strobl cmd->data->mrq = &mreq; 8972dec079SMarius Strobl mreq.cmd = cmd; 90*cd85acbaSMarius Strobl if (MMCBUS_WAIT_FOR_REQUEST(busdev, dev, &mreq) != 0) 9172dec079SMarius Strobl err = MMC_ERR_FAILED; 9272dec079SMarius Strobl else 9372dec079SMarius Strobl err = cmd->error; 9472dec079SMarius Strobl } while (err != MMC_ERR_NONE && retries-- > 0); 9572dec079SMarius Strobl 96*cd85acbaSMarius Strobl if (err != MMC_ERR_NONE && busdev == dev) { 97*cd85acbaSMarius Strobl sc = device_get_softc(busdev); 9872dec079SMarius Strobl if (sc->squelched == 0 && ppsratecheck(&sc->log_time, 9972dec079SMarius Strobl &sc->log_count, LOG_PPS)) { 10072dec079SMarius Strobl device_printf(sc->dev, "CMD%d failed, RESULT: %d\n", 10172dec079SMarius Strobl cmd->opcode, err); 10272dec079SMarius Strobl } 10372dec079SMarius Strobl } 10472dec079SMarius Strobl 10572dec079SMarius Strobl return (err); 10672dec079SMarius Strobl } 10772dec079SMarius Strobl 10872dec079SMarius Strobl int 109*cd85acbaSMarius Strobl mmc_wait_for_app_cmd(device_t busdev, device_t dev, uint16_t rca, 11072dec079SMarius Strobl struct mmc_command *cmd, int retries) 11172dec079SMarius Strobl { 11272dec079SMarius Strobl struct mmc_command appcmd; 11372dec079SMarius Strobl struct mmc_softc *sc; 11472dec079SMarius Strobl int err; 11572dec079SMarius Strobl 116*cd85acbaSMarius Strobl sc = device_get_softc(busdev); 11772dec079SMarius Strobl 11872dec079SMarius Strobl /* Squelch error reporting at lower levels, we report below. */ 11972dec079SMarius Strobl sc->squelched++; 12072dec079SMarius Strobl do { 12172dec079SMarius Strobl memset(&appcmd, 0, sizeof(appcmd)); 12272dec079SMarius Strobl appcmd.opcode = MMC_APP_CMD; 12372dec079SMarius Strobl appcmd.arg = (uint32_t)rca << 16; 12472dec079SMarius Strobl appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 125*cd85acbaSMarius Strobl if (mmc_wait_for_cmd(busdev, dev, &appcmd, 0) != 0) 12672dec079SMarius Strobl err = MMC_ERR_FAILED; 12772dec079SMarius Strobl else 12872dec079SMarius Strobl err = appcmd.error; 12972dec079SMarius Strobl if (err == MMC_ERR_NONE) { 13072dec079SMarius Strobl if (!(appcmd.resp[0] & R1_APP_CMD)) 13172dec079SMarius Strobl err = MMC_ERR_FAILED; 132*cd85acbaSMarius Strobl else if (mmc_wait_for_cmd(busdev, dev, cmd, 0) != 0) 13372dec079SMarius Strobl err = MMC_ERR_FAILED; 13472dec079SMarius Strobl else 13572dec079SMarius Strobl err = cmd->error; 13672dec079SMarius Strobl } 13772dec079SMarius Strobl } while (err != MMC_ERR_NONE && retries-- > 0); 13872dec079SMarius Strobl sc->squelched--; 13972dec079SMarius Strobl 140*cd85acbaSMarius Strobl if (err != MMC_ERR_NONE && busdev == dev) { 14172dec079SMarius Strobl if (sc->squelched == 0 && ppsratecheck(&sc->log_time, 14272dec079SMarius Strobl &sc->log_count, LOG_PPS)) { 14372dec079SMarius Strobl device_printf(sc->dev, "ACMD%d failed, RESULT: %d\n", 14472dec079SMarius Strobl cmd->opcode, err); 14572dec079SMarius Strobl } 14672dec079SMarius Strobl } 14772dec079SMarius Strobl 14872dec079SMarius Strobl return (err); 14972dec079SMarius Strobl } 15072dec079SMarius Strobl 15172dec079SMarius Strobl int 152*cd85acbaSMarius Strobl mmc_switch(device_t busdev, device_t dev, uint16_t rca, uint8_t set, 15372dec079SMarius Strobl uint8_t index, uint8_t value, u_int timeout, bool status) 15472dec079SMarius Strobl { 15572dec079SMarius Strobl struct mmc_command cmd; 156aca38eabSMarius Strobl struct mmc_softc *sc; 15772dec079SMarius Strobl int err; 15872dec079SMarius Strobl 15972dec079SMarius Strobl KASSERT(timeout != 0, ("%s: no timeout", __func__)); 16072dec079SMarius Strobl 161*cd85acbaSMarius Strobl sc = device_get_softc(busdev); 162aca38eabSMarius Strobl 16372dec079SMarius Strobl memset(&cmd, 0, sizeof(cmd)); 16472dec079SMarius Strobl cmd.opcode = MMC_SWITCH_FUNC; 16572dec079SMarius Strobl cmd.arg = (MMC_SWITCH_FUNC_WR << 24) | (index << 16) | (value << 8) | 16672dec079SMarius Strobl set; 16772dec079SMarius Strobl /* 16872dec079SMarius Strobl * If the hardware supports busy detection but the switch timeout 16972dec079SMarius Strobl * exceeds the maximum host timeout, use a R1 instead of a R1B 17072dec079SMarius Strobl * response in order to keep the hardware from timing out. 17172dec079SMarius Strobl */ 172*cd85acbaSMarius Strobl if (mmcbr_get_caps(busdev) & MMC_CAP_WAIT_WHILE_BUSY && 173*cd85acbaSMarius Strobl timeout > mmcbr_get_max_busy_timeout(busdev)) 17472dec079SMarius Strobl cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 17572dec079SMarius Strobl else 17672dec079SMarius Strobl cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; 177aca38eabSMarius Strobl /* 178aca38eabSMarius Strobl * Pause re-tuning so it won't interfere with the busy state and also 179aca38eabSMarius Strobl * so that the result of CMD13 will always refer to switching rather 180aca38eabSMarius Strobl * than to a tuning command that may have snuck in between. 181aca38eabSMarius Strobl */ 182aca38eabSMarius Strobl sc->retune_paused++; 183*cd85acbaSMarius Strobl err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES); 18472dec079SMarius Strobl if (err != MMC_ERR_NONE || status == false) 185aca38eabSMarius Strobl goto out; 186*cd85acbaSMarius Strobl err = mmc_switch_status(busdev, dev, rca, timeout); 187aca38eabSMarius Strobl out: 188aca38eabSMarius Strobl sc->retune_paused--; 18972dec079SMarius Strobl return (err); 19072dec079SMarius Strobl } 19172dec079SMarius Strobl 19272dec079SMarius Strobl int 193*cd85acbaSMarius Strobl mmc_switch_status(device_t busdev, device_t dev, uint16_t rca, u_int timeout) 19472dec079SMarius Strobl { 19572dec079SMarius Strobl struct timeval cur, end; 19672dec079SMarius Strobl int err; 19772dec079SMarius Strobl uint32_t status; 19872dec079SMarius Strobl 19972dec079SMarius Strobl KASSERT(timeout != 0, ("%s: no timeout", __func__)); 20072dec079SMarius Strobl 20172dec079SMarius Strobl /* 20272dec079SMarius Strobl * Note that when using a R1B response in mmc_switch(), bridges of 20372dec079SMarius Strobl * type MMC_CAP_WAIT_WHILE_BUSY will issue mmc_send_status() only 20472dec079SMarius Strobl * once and then exit the loop. 20572dec079SMarius Strobl */ 206aca38eabSMarius Strobl end.tv_sec = end.tv_usec = 0; 20772dec079SMarius Strobl for (;;) { 208*cd85acbaSMarius Strobl err = mmc_send_status(busdev, dev, rca, &status); 20972dec079SMarius Strobl if (err != MMC_ERR_NONE) 21072dec079SMarius Strobl break; 21172dec079SMarius Strobl if (R1_CURRENT_STATE(status) == R1_STATE_TRAN) 21272dec079SMarius Strobl break; 21372dec079SMarius Strobl getmicrouptime(&cur); 21472dec079SMarius Strobl if (end.tv_sec == 0 && end.tv_usec == 0) { 21572dec079SMarius Strobl end.tv_usec = timeout; 21672dec079SMarius Strobl timevaladd(&end, &cur); 21772dec079SMarius Strobl } 21872dec079SMarius Strobl if (timevalcmp(&cur, &end, >)) { 21972dec079SMarius Strobl err = MMC_ERR_TIMEOUT; 22072dec079SMarius Strobl break; 22172dec079SMarius Strobl } 22272dec079SMarius Strobl } 223aca38eabSMarius Strobl if (err == MMC_ERR_NONE && (status & R1_SWITCH_ERROR) != 0) 22472dec079SMarius Strobl return (MMC_ERR_FAILED); 22572dec079SMarius Strobl return (err); 22672dec079SMarius Strobl } 22772dec079SMarius Strobl 22872dec079SMarius Strobl int 229*cd85acbaSMarius Strobl mmc_send_ext_csd(device_t busdev, device_t dev, uint8_t *rawextcsd) 23072dec079SMarius Strobl { 23172dec079SMarius Strobl struct mmc_command cmd; 23272dec079SMarius Strobl struct mmc_data data; 23372dec079SMarius Strobl int err; 23472dec079SMarius Strobl 23572dec079SMarius Strobl memset(&cmd, 0, sizeof(cmd)); 23672dec079SMarius Strobl memset(&data, 0, sizeof(data)); 23772dec079SMarius Strobl 23872dec079SMarius Strobl memset(rawextcsd, 0, MMC_EXTCSD_SIZE); 23972dec079SMarius Strobl cmd.opcode = MMC_SEND_EXT_CSD; 24072dec079SMarius Strobl cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 24172dec079SMarius Strobl cmd.data = &data; 24272dec079SMarius Strobl 24372dec079SMarius Strobl data.data = rawextcsd; 24472dec079SMarius Strobl data.len = MMC_EXTCSD_SIZE; 24572dec079SMarius Strobl data.flags = MMC_DATA_READ; 24672dec079SMarius Strobl 247*cd85acbaSMarius Strobl err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES); 24872dec079SMarius Strobl return (err); 24972dec079SMarius Strobl } 25072dec079SMarius Strobl 25172dec079SMarius Strobl int 252*cd85acbaSMarius Strobl mmc_send_status(device_t busdev, device_t dev, uint16_t rca, uint32_t *status) 25372dec079SMarius Strobl { 25472dec079SMarius Strobl struct mmc_command cmd; 25572dec079SMarius Strobl int err; 25672dec079SMarius Strobl 25772dec079SMarius Strobl memset(&cmd, 0, sizeof(cmd)); 25872dec079SMarius Strobl cmd.opcode = MMC_SEND_STATUS; 25972dec079SMarius Strobl cmd.arg = (uint32_t)rca << 16; 26072dec079SMarius Strobl cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 261*cd85acbaSMarius Strobl err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES); 26272dec079SMarius Strobl *status = cmd.resp[0]; 26372dec079SMarius Strobl return (err); 26472dec079SMarius Strobl } 265