172dec079SMarius Strobl /*- 272dec079SMarius Strobl * Copyright (c) 2006 Bernd Walter. All rights reserved. 3f86e6000SWarner Losh * Copyright (c) 2006 M. Warner Losh <imp@FreeBSD.org> 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/param.h> 5472dec079SMarius Strobl #include <sys/systm.h> 5572dec079SMarius Strobl #include <sys/kernel.h> 5672dec079SMarius Strobl #include <sys/lock.h> 5772dec079SMarius Strobl #include <sys/mutex.h> 5872dec079SMarius Strobl #include <sys/time.h> 5972dec079SMarius Strobl 6072dec079SMarius Strobl #include <dev/mmc/bridge.h> 6172dec079SMarius Strobl #include <dev/mmc/mmc_private.h> 6272dec079SMarius Strobl #include <dev/mmc/mmc_subr.h> 6372dec079SMarius Strobl #include <dev/mmc/mmcreg.h> 6472dec079SMarius Strobl #include <dev/mmc/mmcbrvar.h> 6572dec079SMarius Strobl 6672dec079SMarius Strobl #include "mmcbus_if.h" 6772dec079SMarius Strobl 6872dec079SMarius Strobl #define CMD_RETRIES 3 6972dec079SMarius Strobl #define LOG_PPS 5 /* Log no more than 5 errors per second. */ 7072dec079SMarius Strobl 7172dec079SMarius Strobl int 72cd85acbaSMarius Strobl mmc_wait_for_cmd(device_t busdev, device_t dev, struct mmc_command *cmd, 7372dec079SMarius Strobl int retries) 7472dec079SMarius Strobl { 7572dec079SMarius Strobl struct mmc_request mreq; 7672dec079SMarius Strobl struct mmc_softc *sc; 7772dec079SMarius Strobl int err; 7872dec079SMarius Strobl 7972dec079SMarius Strobl do { 8072dec079SMarius Strobl memset(&mreq, 0, sizeof(mreq)); 8172dec079SMarius Strobl memset(cmd->resp, 0, sizeof(cmd->resp)); 8272dec079SMarius Strobl cmd->retries = 0; /* Retries done here, not in hardware. */ 8372dec079SMarius Strobl cmd->mrq = &mreq; 8472dec079SMarius Strobl if (cmd->data != NULL) 8572dec079SMarius Strobl cmd->data->mrq = &mreq; 8672dec079SMarius Strobl mreq.cmd = cmd; 87cd85acbaSMarius Strobl if (MMCBUS_WAIT_FOR_REQUEST(busdev, dev, &mreq) != 0) 8872dec079SMarius Strobl err = MMC_ERR_FAILED; 8972dec079SMarius Strobl else 9072dec079SMarius Strobl err = cmd->error; 9172dec079SMarius Strobl } while (err != MMC_ERR_NONE && retries-- > 0); 9272dec079SMarius Strobl 93cd85acbaSMarius Strobl if (err != MMC_ERR_NONE && busdev == dev) { 94cd85acbaSMarius Strobl sc = device_get_softc(busdev); 9572dec079SMarius Strobl if (sc->squelched == 0 && ppsratecheck(&sc->log_time, 9672dec079SMarius Strobl &sc->log_count, LOG_PPS)) { 9772dec079SMarius Strobl device_printf(sc->dev, "CMD%d failed, RESULT: %d\n", 9872dec079SMarius Strobl cmd->opcode, err); 9972dec079SMarius Strobl } 10072dec079SMarius Strobl } 10172dec079SMarius Strobl 10272dec079SMarius Strobl return (err); 10372dec079SMarius Strobl } 10472dec079SMarius Strobl 10572dec079SMarius Strobl int 106cd85acbaSMarius Strobl mmc_wait_for_app_cmd(device_t busdev, device_t dev, uint16_t rca, 10772dec079SMarius Strobl struct mmc_command *cmd, int retries) 10872dec079SMarius Strobl { 10972dec079SMarius Strobl struct mmc_command appcmd; 11072dec079SMarius Strobl struct mmc_softc *sc; 11172dec079SMarius Strobl int err; 11272dec079SMarius Strobl 113cd85acbaSMarius Strobl sc = device_get_softc(busdev); 11472dec079SMarius Strobl 11572dec079SMarius Strobl /* Squelch error reporting at lower levels, we report below. */ 11672dec079SMarius Strobl sc->squelched++; 11772dec079SMarius Strobl do { 11872dec079SMarius Strobl memset(&appcmd, 0, sizeof(appcmd)); 11972dec079SMarius Strobl appcmd.opcode = MMC_APP_CMD; 12072dec079SMarius Strobl appcmd.arg = (uint32_t)rca << 16; 12172dec079SMarius Strobl appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 122cd85acbaSMarius Strobl if (mmc_wait_for_cmd(busdev, dev, &appcmd, 0) != 0) 12372dec079SMarius Strobl err = MMC_ERR_FAILED; 12472dec079SMarius Strobl else 12572dec079SMarius Strobl err = appcmd.error; 12672dec079SMarius Strobl if (err == MMC_ERR_NONE) { 12772dec079SMarius Strobl if (!(appcmd.resp[0] & R1_APP_CMD)) 12872dec079SMarius Strobl err = MMC_ERR_FAILED; 129cd85acbaSMarius Strobl else if (mmc_wait_for_cmd(busdev, dev, cmd, 0) != 0) 13072dec079SMarius Strobl err = MMC_ERR_FAILED; 13172dec079SMarius Strobl else 13272dec079SMarius Strobl err = cmd->error; 13372dec079SMarius Strobl } 13472dec079SMarius Strobl } while (err != MMC_ERR_NONE && retries-- > 0); 13572dec079SMarius Strobl sc->squelched--; 13672dec079SMarius Strobl 137cd85acbaSMarius Strobl if (err != MMC_ERR_NONE && busdev == dev) { 13872dec079SMarius Strobl if (sc->squelched == 0 && ppsratecheck(&sc->log_time, 13972dec079SMarius Strobl &sc->log_count, LOG_PPS)) { 14072dec079SMarius Strobl device_printf(sc->dev, "ACMD%d failed, RESULT: %d\n", 14172dec079SMarius Strobl cmd->opcode, err); 14272dec079SMarius Strobl } 14372dec079SMarius Strobl } 14472dec079SMarius Strobl 14572dec079SMarius Strobl return (err); 14672dec079SMarius Strobl } 14772dec079SMarius Strobl 14872dec079SMarius Strobl int 149cd85acbaSMarius Strobl mmc_switch(device_t busdev, device_t dev, uint16_t rca, uint8_t set, 15072dec079SMarius Strobl uint8_t index, uint8_t value, u_int timeout, bool status) 15172dec079SMarius Strobl { 15272dec079SMarius Strobl struct mmc_command cmd; 153aca38eabSMarius Strobl struct mmc_softc *sc; 15472dec079SMarius Strobl int err; 15572dec079SMarius Strobl 15672dec079SMarius Strobl KASSERT(timeout != 0, ("%s: no timeout", __func__)); 15772dec079SMarius Strobl 158cd85acbaSMarius Strobl sc = device_get_softc(busdev); 159aca38eabSMarius Strobl 16072dec079SMarius Strobl memset(&cmd, 0, sizeof(cmd)); 16172dec079SMarius Strobl cmd.opcode = MMC_SWITCH_FUNC; 16272dec079SMarius Strobl cmd.arg = (MMC_SWITCH_FUNC_WR << 24) | (index << 16) | (value << 8) | 16372dec079SMarius Strobl set; 16472dec079SMarius Strobl /* 16572dec079SMarius Strobl * If the hardware supports busy detection but the switch timeout 16672dec079SMarius Strobl * exceeds the maximum host timeout, use a R1 instead of a R1B 16772dec079SMarius Strobl * response in order to keep the hardware from timing out. 16872dec079SMarius Strobl */ 169cd85acbaSMarius Strobl if (mmcbr_get_caps(busdev) & MMC_CAP_WAIT_WHILE_BUSY && 170cd85acbaSMarius Strobl timeout > mmcbr_get_max_busy_timeout(busdev)) 17172dec079SMarius Strobl cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 17272dec079SMarius Strobl else 17372dec079SMarius Strobl cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; 174aca38eabSMarius Strobl /* 175aca38eabSMarius Strobl * Pause re-tuning so it won't interfere with the busy state and also 176aca38eabSMarius Strobl * so that the result of CMD13 will always refer to switching rather 177aca38eabSMarius Strobl * than to a tuning command that may have snuck in between. 178aca38eabSMarius Strobl */ 179aca38eabSMarius Strobl sc->retune_paused++; 180cd85acbaSMarius Strobl err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES); 18172dec079SMarius Strobl if (err != MMC_ERR_NONE || status == false) 182aca38eabSMarius Strobl goto out; 183cd85acbaSMarius Strobl err = mmc_switch_status(busdev, dev, rca, timeout); 184aca38eabSMarius Strobl out: 185aca38eabSMarius Strobl sc->retune_paused--; 18672dec079SMarius Strobl return (err); 18772dec079SMarius Strobl } 18872dec079SMarius Strobl 18972dec079SMarius Strobl int 190cd85acbaSMarius Strobl mmc_switch_status(device_t busdev, device_t dev, uint16_t rca, u_int timeout) 19172dec079SMarius Strobl { 19272dec079SMarius Strobl struct timeval cur, end; 193*e7dc0841SAustin Shafer int err, crc_timeout; 19472dec079SMarius Strobl uint32_t status; 19572dec079SMarius Strobl 19672dec079SMarius Strobl KASSERT(timeout != 0, ("%s: no timeout", __func__)); 19772dec079SMarius Strobl 19872dec079SMarius Strobl /* 19972dec079SMarius Strobl * Note that when using a R1B response in mmc_switch(), bridges of 20072dec079SMarius Strobl * type MMC_CAP_WAIT_WHILE_BUSY will issue mmc_send_status() only 20172dec079SMarius Strobl * once and then exit the loop. 20272dec079SMarius Strobl */ 203aca38eabSMarius Strobl end.tv_sec = end.tv_usec = 0; 20472dec079SMarius Strobl for (;;) { 205*e7dc0841SAustin Shafer crc_timeout=0; 206*e7dc0841SAustin Shafer do { 207*e7dc0841SAustin Shafer /* 208*e7dc0841SAustin Shafer * CRC errors indicate that the command wasn't accepted 209*e7dc0841SAustin Shafer * and executed due to a communications error. Retry 210*e7dc0841SAustin Shafer * CRC errors a couple of times to cope with transient 211*e7dc0841SAustin Shafer * failures. 212*e7dc0841SAustin Shafer * 213*e7dc0841SAustin Shafer * This is required for some cheap laptops to boot. 214*e7dc0841SAustin Shafer */ 215cd85acbaSMarius Strobl err = mmc_send_status(busdev, dev, rca, &status); 216*e7dc0841SAustin Shafer crc_timeout++; 217*e7dc0841SAustin Shafer } while (err == MMC_ERR_BADCRC && crc_timeout < 10); 21872dec079SMarius Strobl if (err != MMC_ERR_NONE) 21972dec079SMarius Strobl break; 22072dec079SMarius Strobl if (R1_CURRENT_STATE(status) == R1_STATE_TRAN) 22172dec079SMarius Strobl break; 22272dec079SMarius Strobl getmicrouptime(&cur); 22372dec079SMarius Strobl if (end.tv_sec == 0 && end.tv_usec == 0) { 22472dec079SMarius Strobl end.tv_usec = timeout; 22572dec079SMarius Strobl timevaladd(&end, &cur); 22672dec079SMarius Strobl } 22772dec079SMarius Strobl if (timevalcmp(&cur, &end, >)) { 22872dec079SMarius Strobl err = MMC_ERR_TIMEOUT; 22972dec079SMarius Strobl break; 23072dec079SMarius Strobl } 23172dec079SMarius Strobl } 232aca38eabSMarius Strobl if (err == MMC_ERR_NONE && (status & R1_SWITCH_ERROR) != 0) 23372dec079SMarius Strobl return (MMC_ERR_FAILED); 23472dec079SMarius Strobl return (err); 23572dec079SMarius Strobl } 23672dec079SMarius Strobl 23772dec079SMarius Strobl int 238cd85acbaSMarius Strobl mmc_send_ext_csd(device_t busdev, device_t dev, uint8_t *rawextcsd) 23972dec079SMarius Strobl { 24072dec079SMarius Strobl struct mmc_command cmd; 24172dec079SMarius Strobl struct mmc_data data; 24272dec079SMarius Strobl int err; 24372dec079SMarius Strobl 24472dec079SMarius Strobl memset(&cmd, 0, sizeof(cmd)); 24572dec079SMarius Strobl memset(&data, 0, sizeof(data)); 24672dec079SMarius Strobl 24772dec079SMarius Strobl memset(rawextcsd, 0, MMC_EXTCSD_SIZE); 24872dec079SMarius Strobl cmd.opcode = MMC_SEND_EXT_CSD; 24972dec079SMarius Strobl cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 25072dec079SMarius Strobl cmd.data = &data; 25172dec079SMarius Strobl 25272dec079SMarius Strobl data.data = rawextcsd; 25372dec079SMarius Strobl data.len = MMC_EXTCSD_SIZE; 25472dec079SMarius Strobl data.flags = MMC_DATA_READ; 25572dec079SMarius Strobl 256cd85acbaSMarius Strobl err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES); 25772dec079SMarius Strobl return (err); 25872dec079SMarius Strobl } 25972dec079SMarius Strobl 26072dec079SMarius Strobl int 261cd85acbaSMarius Strobl mmc_send_status(device_t busdev, device_t dev, uint16_t rca, uint32_t *status) 26272dec079SMarius Strobl { 26372dec079SMarius Strobl struct mmc_command cmd; 26472dec079SMarius Strobl int err; 26572dec079SMarius Strobl 26672dec079SMarius Strobl memset(&cmd, 0, sizeof(cmd)); 26772dec079SMarius Strobl cmd.opcode = MMC_SEND_STATUS; 26872dec079SMarius Strobl cmd.arg = (uint32_t)rca << 16; 26972dec079SMarius Strobl cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 270cd85acbaSMarius Strobl err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES); 27172dec079SMarius Strobl *status = cmd.resp[0]; 27272dec079SMarius Strobl return (err); 27372dec079SMarius Strobl } 274