1*bffde63dSSheetal Tigadoli /* 2*bffde63dSSheetal Tigadoli * Copyright (c) 2016 - 2020, Broadcom 3*bffde63dSSheetal Tigadoli * 4*bffde63dSSheetal Tigadoli * SPDX-License-Identifier: BSD-3-Clause 5*bffde63dSSheetal Tigadoli */ 6*bffde63dSSheetal Tigadoli 7*bffde63dSSheetal Tigadoli #include <stdlib.h> 8*bffde63dSSheetal Tigadoli #include <stddef.h> 9*bffde63dSSheetal Tigadoli 10*bffde63dSSheetal Tigadoli #include "bcm_emmc.h" 11*bffde63dSSheetal Tigadoli #include "emmc_chal_types.h" 12*bffde63dSSheetal Tigadoli #include "emmc_chal_sd.h" 13*bffde63dSSheetal Tigadoli #include "emmc_csl_sdprot.h" 14*bffde63dSSheetal Tigadoli #include "emmc_csl_sdcmd.h" 15*bffde63dSSheetal Tigadoli #include "emmc_csl_sd.h" 16*bffde63dSSheetal Tigadoli #include "emmc_chal_sd.h" 17*bffde63dSSheetal Tigadoli #include "emmc_pboot_hal_memory_drv.h" 18*bffde63dSSheetal Tigadoli 19*bffde63dSSheetal Tigadoli int sd_cmd0(struct sd_handle *handle) 20*bffde63dSSheetal Tigadoli { 21*bffde63dSSheetal Tigadoli int res; 22*bffde63dSSheetal Tigadoli uint32_t argument = 0x0; /* Go to IDLE state. */ 23*bffde63dSSheetal Tigadoli 24*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 25*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_GO_IDLE_STATE, argument, 0, NULL); 26*bffde63dSSheetal Tigadoli 27*bffde63dSSheetal Tigadoli if (res == SD_OK) { 28*bffde63dSSheetal Tigadoli /* Clear all other interrupts */ 29*bffde63dSSheetal Tigadoli chal_sd_clear_irq((void *)handle->device, 0xffffffff); 30*bffde63dSSheetal Tigadoli } 31*bffde63dSSheetal Tigadoli 32*bffde63dSSheetal Tigadoli return res; 33*bffde63dSSheetal Tigadoli } 34*bffde63dSSheetal Tigadoli 35*bffde63dSSheetal Tigadoli int sd_cmd1(struct sd_handle *handle, uint32_t ocr, uint32_t *ocr_output) 36*bffde63dSSheetal Tigadoli { 37*bffde63dSSheetal Tigadoli int res; 38*bffde63dSSheetal Tigadoli uint32_t options; 39*bffde63dSSheetal Tigadoli struct sd_resp resp; 40*bffde63dSSheetal Tigadoli 41*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R3_4 << SD_CMDR_RSP_TYPE_S; 42*bffde63dSSheetal Tigadoli 43*bffde63dSSheetal Tigadoli if (ocr_output == NULL) { 44*bffde63dSSheetal Tigadoli EMMC_TRACE("Invalid args\n"); 45*bffde63dSSheetal Tigadoli return SD_FAIL; 46*bffde63dSSheetal Tigadoli } 47*bffde63dSSheetal Tigadoli 48*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 49*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_SEND_OPCOND, ocr, options, &resp); 50*bffde63dSSheetal Tigadoli 51*bffde63dSSheetal Tigadoli if (res == SD_OK) 52*bffde63dSSheetal Tigadoli *ocr_output = resp.data.r3.ocr; 53*bffde63dSSheetal Tigadoli 54*bffde63dSSheetal Tigadoli return res; 55*bffde63dSSheetal Tigadoli } 56*bffde63dSSheetal Tigadoli 57*bffde63dSSheetal Tigadoli int sd_cmd2(struct sd_handle *handle) 58*bffde63dSSheetal Tigadoli { 59*bffde63dSSheetal Tigadoli uint32_t options; 60*bffde63dSSheetal Tigadoli struct sd_resp resp; 61*bffde63dSSheetal Tigadoli 62*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 63*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S; 64*bffde63dSSheetal Tigadoli 65*bffde63dSSheetal Tigadoli return send_cmd(handle, SD_CMD_ALL_SEND_CID, 0, options, &resp); 66*bffde63dSSheetal Tigadoli } 67*bffde63dSSheetal Tigadoli 68*bffde63dSSheetal Tigadoli int sd_cmd3(struct sd_handle *handle) 69*bffde63dSSheetal Tigadoli { 70*bffde63dSSheetal Tigadoli int res; 71*bffde63dSSheetal Tigadoli uint32_t options = 0; 72*bffde63dSSheetal Tigadoli uint32_t argument; 73*bffde63dSSheetal Tigadoli struct sd_resp resp; 74*bffde63dSSheetal Tigadoli 75*bffde63dSSheetal Tigadoli /* use non zero and non 0x1 value for rca */ 76*bffde63dSSheetal Tigadoli handle->device->ctrl.rca = 0x5; 77*bffde63dSSheetal Tigadoli argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT; 78*bffde63dSSheetal Tigadoli 79*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 80*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK | 81*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CRC_EN_MASK; 82*bffde63dSSheetal Tigadoli 83*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 84*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_MMC_SET_RCA, argument, options, &resp); 85*bffde63dSSheetal Tigadoli 86*bffde63dSSheetal Tigadoli if (res != SD_OK) 87*bffde63dSSheetal Tigadoli handle->device->ctrl.rca = 0; 88*bffde63dSSheetal Tigadoli 89*bffde63dSSheetal Tigadoli return res; 90*bffde63dSSheetal Tigadoli } 91*bffde63dSSheetal Tigadoli 92*bffde63dSSheetal Tigadoli int sd_cmd7(struct sd_handle *handle, uint32_t rca) 93*bffde63dSSheetal Tigadoli { 94*bffde63dSSheetal Tigadoli int res; 95*bffde63dSSheetal Tigadoli uint32_t argument, options; 96*bffde63dSSheetal Tigadoli struct sd_resp resp; 97*bffde63dSSheetal Tigadoli 98*bffde63dSSheetal Tigadoli argument = (rca << SD_CMD7_ARG_RCA_SHIFT); 99*bffde63dSSheetal Tigadoli 100*bffde63dSSheetal Tigadoli /* 101*bffde63dSSheetal Tigadoli * Response to CMD7 is: 102*bffde63dSSheetal Tigadoli * R1 while selectiing from Stand-By State to Transfer State 103*bffde63dSSheetal Tigadoli * R1b while selecting from Disconnected State to Programming State. 104*bffde63dSSheetal Tigadoli * 105*bffde63dSSheetal Tigadoli * In this driver, we only issue a CMD7 once, to go to transfer mode 106*bffde63dSSheetal Tigadoli * during init_mmc_card(). 107*bffde63dSSheetal Tigadoli */ 108*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 109*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK | 110*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CRC_EN_MASK; 111*bffde63dSSheetal Tigadoli 112*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 113*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_SELECT_DESELECT_CARD, argument, options, 114*bffde63dSSheetal Tigadoli &resp); 115*bffde63dSSheetal Tigadoli 116*bffde63dSSheetal Tigadoli if (res == SD_OK) 117*bffde63dSSheetal Tigadoli /* Clear all other interrupts */ 118*bffde63dSSheetal Tigadoli chal_sd_clear_irq((void *)handle->device, 0xffffffff); 119*bffde63dSSheetal Tigadoli 120*bffde63dSSheetal Tigadoli return res; 121*bffde63dSSheetal Tigadoli } 122*bffde63dSSheetal Tigadoli 123*bffde63dSSheetal Tigadoli 124*bffde63dSSheetal Tigadoli /* 125*bffde63dSSheetal Tigadoli * CMD8 Get CSD_EXT 126*bffde63dSSheetal Tigadoli */ 127*bffde63dSSheetal Tigadoli int mmc_cmd8(struct sd_handle *handle, uint8_t *extCsdReg) 128*bffde63dSSheetal Tigadoli { 129*bffde63dSSheetal Tigadoli uint32_t res, options; 130*bffde63dSSheetal Tigadoli struct sd_resp resp; 131*bffde63dSSheetal Tigadoli 132*bffde63dSSheetal Tigadoli data_xfer_setup(handle, extCsdReg, CEATA_EXT_CSDBLOCK_SIZE, 133*bffde63dSSheetal Tigadoli SD_XFER_CARD_TO_HOST); 134*bffde63dSSheetal Tigadoli 135*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 136*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK | 137*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK; 138*bffde63dSSheetal Tigadoli 139*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 140*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_READ_EXT_CSD, 0, options, &resp); 141*bffde63dSSheetal Tigadoli 142*bffde63dSSheetal Tigadoli if (res == SD_OK) 143*bffde63dSSheetal Tigadoli res = process_data_xfer(handle, extCsdReg, 0, 144*bffde63dSSheetal Tigadoli CEATA_EXT_CSDBLOCK_SIZE, 145*bffde63dSSheetal Tigadoli SD_XFER_CARD_TO_HOST); 146*bffde63dSSheetal Tigadoli 147*bffde63dSSheetal Tigadoli return res; 148*bffde63dSSheetal Tigadoli } 149*bffde63dSSheetal Tigadoli 150*bffde63dSSheetal Tigadoli int sd_cmd9(struct sd_handle *handle, struct sd_card_data *card) 151*bffde63dSSheetal Tigadoli { 152*bffde63dSSheetal Tigadoli int res; 153*bffde63dSSheetal Tigadoli uint32_t argument, options, iBlkNum, multiFactor = 1; 154*bffde63dSSheetal Tigadoli uint32_t maxReadBlockLen = 1, maxWriteBlockLen = 1; 155*bffde63dSSheetal Tigadoli struct sd_resp resp; 156*bffde63dSSheetal Tigadoli 157*bffde63dSSheetal Tigadoli argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT; 158*bffde63dSSheetal Tigadoli 159*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S | 160*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CRC_EN_MASK; 161*bffde63dSSheetal Tigadoli 162*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 163*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_SEND_CSD, argument, options, &resp); 164*bffde63dSSheetal Tigadoli 165*bffde63dSSheetal Tigadoli if (res != SD_OK) 166*bffde63dSSheetal Tigadoli return res; 167*bffde63dSSheetal Tigadoli 168*bffde63dSSheetal Tigadoli if (handle->card->type == SD_CARD_MMC) { 169*bffde63dSSheetal Tigadoli card->csd.mmc.structure = (resp.data.r2.rsp4 >> 22) & 0x3; 170*bffde63dSSheetal Tigadoli card->csd.mmc.csdSpecVer = (resp.data.r2.rsp4 >> 18) & 0x0f; 171*bffde63dSSheetal Tigadoli card->csd.mmc.taac = (resp.data.r2.rsp4 >> 8) & 0xff; 172*bffde63dSSheetal Tigadoli card->csd.mmc.nsac = resp.data.r2.rsp4 & 0xff; 173*bffde63dSSheetal Tigadoli card->csd.mmc.speed = resp.data.r2.rsp3 >> 24; 174*bffde63dSSheetal Tigadoli card->csd.mmc.classes = (resp.data.r2.rsp3 >> 12) & 0xfff; 175*bffde63dSSheetal Tigadoli card->csd.mmc.rdBlkLen = (resp.data.r2.rsp3 >> 8) & 0xf; 176*bffde63dSSheetal Tigadoli card->csd.mmc.rdBlkPartial = (resp.data.r2.rsp3 >> 7) & 0x01; 177*bffde63dSSheetal Tigadoli card->csd.mmc.wrBlkMisalign = (resp.data.r2.rsp3 >> 6) & 0x1; 178*bffde63dSSheetal Tigadoli card->csd.mmc.rdBlkMisalign = (resp.data.r2.rsp3 >> 5) & 0x1; 179*bffde63dSSheetal Tigadoli card->csd.mmc.dsr = (resp.data.r2.rsp2 >> 4) & 0x01; 180*bffde63dSSheetal Tigadoli card->csd.mmc.size = 181*bffde63dSSheetal Tigadoli ((resp.data.r2.rsp3 & 0x3) << 10) + 182*bffde63dSSheetal Tigadoli ((resp.data.r2.rsp2 >> 22) & 0x3ff); 183*bffde63dSSheetal Tigadoli card->csd.mmc.vddRdCurrMin = (resp.data.r2.rsp2 >> 19) & 0x7; 184*bffde63dSSheetal Tigadoli card->csd.mmc.vddRdCurrMax = (resp.data.r2.rsp2 >> 16) & 0x7; 185*bffde63dSSheetal Tigadoli card->csd.mmc.vddWrCurrMin = (resp.data.r2.rsp2 >> 13) & 0x7; 186*bffde63dSSheetal Tigadoli card->csd.mmc.vddWrCurrMax = (resp.data.r2.rsp2 >> 10) & 0x7; 187*bffde63dSSheetal Tigadoli card->csd.mmc.devSizeMulti = (resp.data.r2.rsp2 >> 7) & 0x7; 188*bffde63dSSheetal Tigadoli card->csd.mmc.eraseGrpSize = (resp.data.r2.rsp2 >> 2) & 0x1f; 189*bffde63dSSheetal Tigadoli card->csd.mmc.eraseGrpSizeMulti = 190*bffde63dSSheetal Tigadoli ((resp.data.r2.rsp2 & 0x3) << 3) + 191*bffde63dSSheetal Tigadoli ((resp.data.r2.rsp1 >> 29) & 0x7); 192*bffde63dSSheetal Tigadoli card->csd.mmc.wrProtGroupSize = 193*bffde63dSSheetal Tigadoli ((resp.data.r2.rsp1 >> 24) & 0x1f); 194*bffde63dSSheetal Tigadoli card->csd.mmc.wrProtGroupEnable = 195*bffde63dSSheetal Tigadoli (resp.data.r2.rsp1 >> 23) & 0x1; 196*bffde63dSSheetal Tigadoli card->csd.mmc.manuDefEcc = (resp.data.r2.rsp1 >> 21) & 0x3; 197*bffde63dSSheetal Tigadoli card->csd.mmc.wrSpeedFactor = (resp.data.r2.rsp1 >> 18) & 0x7; 198*bffde63dSSheetal Tigadoli card->csd.mmc.wrBlkLen = (resp.data.r2.rsp1 >> 14) & 0xf; 199*bffde63dSSheetal Tigadoli card->csd.mmc.wrBlkPartial = (resp.data.r2.rsp1 >> 13) & 0x1; 200*bffde63dSSheetal Tigadoli card->csd.mmc.protAppl = (resp.data.r2.rsp1 >> 8) & 0x1; 201*bffde63dSSheetal Tigadoli card->csd.mmc.copyFlag = (resp.data.r2.rsp1 >> 7) & 0x1; 202*bffde63dSSheetal Tigadoli card->csd.mmc.permWrProt = (resp.data.r2.rsp1 >> 6) & 0x1; 203*bffde63dSSheetal Tigadoli card->csd.mmc.tmpWrProt = (resp.data.r2.rsp1 >> 5) & 0x1; 204*bffde63dSSheetal Tigadoli card->csd.mmc.fileFormat = (resp.data.r2.rsp1 >> 4) & 0x03; 205*bffde63dSSheetal Tigadoli card->csd.mmc.eccCode = resp.data.r2.rsp1 & 0x03; 206*bffde63dSSheetal Tigadoli maxReadBlockLen <<= card->csd.mmc.rdBlkLen; 207*bffde63dSSheetal Tigadoli maxWriteBlockLen <<= card->csd.mmc.wrBlkLen; 208*bffde63dSSheetal Tigadoli 209*bffde63dSSheetal Tigadoli iBlkNum = card->csd.mmc.size + 1; 210*bffde63dSSheetal Tigadoli multiFactor = (1 << (card->csd.mmc.devSizeMulti + 2)); 211*bffde63dSSheetal Tigadoli 212*bffde63dSSheetal Tigadoli handle->card->size = 213*bffde63dSSheetal Tigadoli iBlkNum * multiFactor * (1 << card->csd.mmc.rdBlkLen); 214*bffde63dSSheetal Tigadoli } 215*bffde63dSSheetal Tigadoli 216*bffde63dSSheetal Tigadoli handle->card->maxRdBlkLen = maxReadBlockLen; 217*bffde63dSSheetal Tigadoli handle->card->maxWtBlkLen = maxWriteBlockLen; 218*bffde63dSSheetal Tigadoli 219*bffde63dSSheetal Tigadoli if (handle->card->size < 0xA00000) { 220*bffde63dSSheetal Tigadoli /* 221*bffde63dSSheetal Tigadoli * 10MB Too small size mean, cmd9 response is wrong, 222*bffde63dSSheetal Tigadoli * Use default value 1G 223*bffde63dSSheetal Tigadoli */ 224*bffde63dSSheetal Tigadoli handle->card->size = 0x40000000; 225*bffde63dSSheetal Tigadoli handle->card->maxRdBlkLen = 512; 226*bffde63dSSheetal Tigadoli handle->card->maxWtBlkLen = 512; 227*bffde63dSSheetal Tigadoli } 228*bffde63dSSheetal Tigadoli 229*bffde63dSSheetal Tigadoli if ((handle->card->maxRdBlkLen > 512) || 230*bffde63dSSheetal Tigadoli (handle->card->maxWtBlkLen > 512)) { 231*bffde63dSSheetal Tigadoli handle->card->maxRdBlkLen = 512; 232*bffde63dSSheetal Tigadoli handle->card->maxWtBlkLen = 512; 233*bffde63dSSheetal Tigadoli } else if ((handle->card->maxRdBlkLen == 0) || 234*bffde63dSSheetal Tigadoli (handle->card->maxWtBlkLen == 0)) { 235*bffde63dSSheetal Tigadoli handle->card->maxRdBlkLen = 512; 236*bffde63dSSheetal Tigadoli handle->card->maxWtBlkLen = 512; 237*bffde63dSSheetal Tigadoli } 238*bffde63dSSheetal Tigadoli 239*bffde63dSSheetal Tigadoli handle->device->cfg.blockSize = handle->card->maxRdBlkLen; 240*bffde63dSSheetal Tigadoli 241*bffde63dSSheetal Tigadoli return res; 242*bffde63dSSheetal Tigadoli } 243*bffde63dSSheetal Tigadoli 244*bffde63dSSheetal Tigadoli int sd_cmd13(struct sd_handle *handle, uint32_t *status) 245*bffde63dSSheetal Tigadoli { 246*bffde63dSSheetal Tigadoli int res; 247*bffde63dSSheetal Tigadoli uint32_t argument, options; 248*bffde63dSSheetal Tigadoli struct sd_resp resp; 249*bffde63dSSheetal Tigadoli 250*bffde63dSSheetal Tigadoli argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT; 251*bffde63dSSheetal Tigadoli 252*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 253*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK | 254*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CRC_EN_MASK; 255*bffde63dSSheetal Tigadoli 256*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 257*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_SEND_STATUS, argument, options, &resp); 258*bffde63dSSheetal Tigadoli 259*bffde63dSSheetal Tigadoli if (res == SD_OK) { 260*bffde63dSSheetal Tigadoli *status = resp.cardStatus; 261*bffde63dSSheetal Tigadoli } 262*bffde63dSSheetal Tigadoli 263*bffde63dSSheetal Tigadoli return res; 264*bffde63dSSheetal Tigadoli } 265*bffde63dSSheetal Tigadoli 266*bffde63dSSheetal Tigadoli int sd_cmd16(struct sd_handle *handle, uint32_t length) 267*bffde63dSSheetal Tigadoli { 268*bffde63dSSheetal Tigadoli int res; 269*bffde63dSSheetal Tigadoli uint32_t argument, options, ntry; 270*bffde63dSSheetal Tigadoli struct sd_resp resp; 271*bffde63dSSheetal Tigadoli 272*bffde63dSSheetal Tigadoli argument = length; 273*bffde63dSSheetal Tigadoli 274*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 275*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CRC_EN_MASK | 276*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK; 277*bffde63dSSheetal Tigadoli 278*bffde63dSSheetal Tigadoli ntry = 0; 279*bffde63dSSheetal Tigadoli do { 280*bffde63dSSheetal Tigadoli res = sd_cmd13(handle, &resp.cardStatus); 281*bffde63dSSheetal Tigadoli if (res != SD_OK) { 282*bffde63dSSheetal Tigadoli EMMC_TRACE( 283*bffde63dSSheetal Tigadoli "cmd13 failed before cmd16: rca 0x%0x, return %d, response 0x%0x\n", 284*bffde63dSSheetal Tigadoli handle->device->ctrl.rca, res, resp.cardStatus); 285*bffde63dSSheetal Tigadoli return res; 286*bffde63dSSheetal Tigadoli } 287*bffde63dSSheetal Tigadoli 288*bffde63dSSheetal Tigadoli if (resp.cardStatus & 0x100) 289*bffde63dSSheetal Tigadoli break; 290*bffde63dSSheetal Tigadoli 291*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 rsp:0x%08x before cmd16\n", resp.cardStatus); 292*bffde63dSSheetal Tigadoli 293*bffde63dSSheetal Tigadoli if (ntry > handle->device->cfg.retryLimit) { 294*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry reach limit %d\n", 295*bffde63dSSheetal Tigadoli handle->device->cfg.retryLimit); 296*bffde63dSSheetal Tigadoli return SD_CMD_TIMEOUT; 297*bffde63dSSheetal Tigadoli } 298*bffde63dSSheetal Tigadoli 299*bffde63dSSheetal Tigadoli ntry++; 300*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry %d\n", ntry); 301*bffde63dSSheetal Tigadoli 302*bffde63dSSheetal Tigadoli SD_US_DELAY(1000); 303*bffde63dSSheetal Tigadoli 304*bffde63dSSheetal Tigadoli } while (1); 305*bffde63dSSheetal Tigadoli 306*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 307*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_SET_BLOCKLEN, argument, options, &resp); 308*bffde63dSSheetal Tigadoli 309*bffde63dSSheetal Tigadoli return res; 310*bffde63dSSheetal Tigadoli } 311*bffde63dSSheetal Tigadoli 312*bffde63dSSheetal Tigadoli int sd_cmd17(struct sd_handle *handle, 313*bffde63dSSheetal Tigadoli uint32_t addr, uint32_t len, uint8_t *buffer) 314*bffde63dSSheetal Tigadoli { 315*bffde63dSSheetal Tigadoli int res; 316*bffde63dSSheetal Tigadoli uint32_t argument, options, ntry; 317*bffde63dSSheetal Tigadoli struct sd_resp resp; 318*bffde63dSSheetal Tigadoli 319*bffde63dSSheetal Tigadoli ntry = 0; 320*bffde63dSSheetal Tigadoli do { 321*bffde63dSSheetal Tigadoli res = sd_cmd13(handle, &resp.cardStatus); 322*bffde63dSSheetal Tigadoli if (res != SD_OK) { 323*bffde63dSSheetal Tigadoli EMMC_TRACE( 324*bffde63dSSheetal Tigadoli "cmd 13 failed before cmd17: rca 0x%0x, return %d, response 0x%0x\n", 325*bffde63dSSheetal Tigadoli handle->device->ctrl.rca, res, resp.cardStatus); 326*bffde63dSSheetal Tigadoli return res; 327*bffde63dSSheetal Tigadoli } 328*bffde63dSSheetal Tigadoli 329*bffde63dSSheetal Tigadoli if (resp.cardStatus & 0x100) 330*bffde63dSSheetal Tigadoli break; 331*bffde63dSSheetal Tigadoli 332*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 rsp:0x%08x before cmd17\n", resp.cardStatus); 333*bffde63dSSheetal Tigadoli 334*bffde63dSSheetal Tigadoli if (ntry > handle->device->cfg.retryLimit) { 335*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry reach limit %d\n", 336*bffde63dSSheetal Tigadoli handle->device->cfg.retryLimit); 337*bffde63dSSheetal Tigadoli return SD_CMD_TIMEOUT; 338*bffde63dSSheetal Tigadoli } 339*bffde63dSSheetal Tigadoli 340*bffde63dSSheetal Tigadoli ntry++; 341*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry %d\n", ntry); 342*bffde63dSSheetal Tigadoli 343*bffde63dSSheetal Tigadoli SD_US_DELAY(1000); 344*bffde63dSSheetal Tigadoli 345*bffde63dSSheetal Tigadoli } while (1); 346*bffde63dSSheetal Tigadoli 347*bffde63dSSheetal Tigadoli data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST); 348*bffde63dSSheetal Tigadoli 349*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 350*bffde63dSSheetal Tigadoli argument = addr; 351*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 352*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK | 353*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CRC_EN_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK; 354*bffde63dSSheetal Tigadoli 355*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_READ_SINGLE_BLOCK, argument, options, 356*bffde63dSSheetal Tigadoli &resp); 357*bffde63dSSheetal Tigadoli 358*bffde63dSSheetal Tigadoli if (res != SD_OK) 359*bffde63dSSheetal Tigadoli return res; 360*bffde63dSSheetal Tigadoli 361*bffde63dSSheetal Tigadoli res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST); 362*bffde63dSSheetal Tigadoli 363*bffde63dSSheetal Tigadoli return res; 364*bffde63dSSheetal Tigadoli } 365*bffde63dSSheetal Tigadoli 366*bffde63dSSheetal Tigadoli int sd_cmd18(struct sd_handle *handle, 367*bffde63dSSheetal Tigadoli uint32_t addr, uint32_t len, uint8_t *buffer) 368*bffde63dSSheetal Tigadoli { 369*bffde63dSSheetal Tigadoli int res; 370*bffde63dSSheetal Tigadoli uint32_t argument, options, ntry; 371*bffde63dSSheetal Tigadoli struct sd_resp resp; 372*bffde63dSSheetal Tigadoli 373*bffde63dSSheetal Tigadoli ntry = 0; 374*bffde63dSSheetal Tigadoli do { 375*bffde63dSSheetal Tigadoli res = sd_cmd13(handle, &resp.cardStatus); 376*bffde63dSSheetal Tigadoli if (res != SD_OK) { 377*bffde63dSSheetal Tigadoli EMMC_TRACE( 378*bffde63dSSheetal Tigadoli "cmd 13 failed before cmd18: rca 0x%0x, return %d, response 0x%0x\n", 379*bffde63dSSheetal Tigadoli handle->device->ctrl.rca, res, resp.cardStatus); 380*bffde63dSSheetal Tigadoli return res; 381*bffde63dSSheetal Tigadoli } 382*bffde63dSSheetal Tigadoli 383*bffde63dSSheetal Tigadoli if (resp.cardStatus & 0x100) 384*bffde63dSSheetal Tigadoli break; 385*bffde63dSSheetal Tigadoli 386*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 rsp:0x%08x before cmd18\n", resp.cardStatus); 387*bffde63dSSheetal Tigadoli 388*bffde63dSSheetal Tigadoli if (ntry > handle->device->cfg.retryLimit) { 389*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry reach limit %d\n", 390*bffde63dSSheetal Tigadoli handle->device->cfg.retryLimit); 391*bffde63dSSheetal Tigadoli return SD_CMD_TIMEOUT; 392*bffde63dSSheetal Tigadoli } 393*bffde63dSSheetal Tigadoli 394*bffde63dSSheetal Tigadoli ntry++; 395*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry %d\n", ntry); 396*bffde63dSSheetal Tigadoli 397*bffde63dSSheetal Tigadoli SD_US_DELAY(1000); 398*bffde63dSSheetal Tigadoli } while (1); 399*bffde63dSSheetal Tigadoli 400*bffde63dSSheetal Tigadoli data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST); 401*bffde63dSSheetal Tigadoli 402*bffde63dSSheetal Tigadoli argument = addr; 403*bffde63dSSheetal Tigadoli 404*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 405*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK | 406*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_MSBS_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK | 407*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_BCEN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK | 408*bffde63dSSheetal Tigadoli BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT); 409*bffde63dSSheetal Tigadoli 410*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 411*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_READ_MULTIPLE_BLOCK, argument, options, 412*bffde63dSSheetal Tigadoli &resp); 413*bffde63dSSheetal Tigadoli 414*bffde63dSSheetal Tigadoli if (res != SD_OK) 415*bffde63dSSheetal Tigadoli return res; 416*bffde63dSSheetal Tigadoli 417*bffde63dSSheetal Tigadoli res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST); 418*bffde63dSSheetal Tigadoli 419*bffde63dSSheetal Tigadoli return res; 420*bffde63dSSheetal Tigadoli } 421*bffde63dSSheetal Tigadoli 422*bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE 423*bffde63dSSheetal Tigadoli static int card_sts_resp(struct sd_handle *handle, uint32_t *status) 424*bffde63dSSheetal Tigadoli { 425*bffde63dSSheetal Tigadoli int res; 426*bffde63dSSheetal Tigadoli uint32_t ntry = 0; 427*bffde63dSSheetal Tigadoli 428*bffde63dSSheetal Tigadoli do { 429*bffde63dSSheetal Tigadoli res = sd_cmd13(handle, status); 430*bffde63dSSheetal Tigadoli if (res != SD_OK) { 431*bffde63dSSheetal Tigadoli EMMC_TRACE( 432*bffde63dSSheetal Tigadoli "cmd 13 failed before cmd35: rca 0x%0x, return %d\n", 433*bffde63dSSheetal Tigadoli handle->device->ctrl.rca, res); 434*bffde63dSSheetal Tigadoli return res; 435*bffde63dSSheetal Tigadoli } 436*bffde63dSSheetal Tigadoli 437*bffde63dSSheetal Tigadoli if (*status & 0x100) 438*bffde63dSSheetal Tigadoli break; 439*bffde63dSSheetal Tigadoli 440*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 rsp:0x%08x before cmd35\n", resp.cardStatus); 441*bffde63dSSheetal Tigadoli 442*bffde63dSSheetal Tigadoli if (ntry > handle->device->cfg.retryLimit) { 443*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry reach limit %d\n", 444*bffde63dSSheetal Tigadoli handle->device->cfg.retryLimit); 445*bffde63dSSheetal Tigadoli return SD_CMD_TIMEOUT; 446*bffde63dSSheetal Tigadoli } 447*bffde63dSSheetal Tigadoli 448*bffde63dSSheetal Tigadoli ntry++; 449*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry %d\n", ntry); 450*bffde63dSSheetal Tigadoli 451*bffde63dSSheetal Tigadoli SD_US_DELAY(1000); 452*bffde63dSSheetal Tigadoli } while (1); 453*bffde63dSSheetal Tigadoli 454*bffde63dSSheetal Tigadoli return SD_OK; 455*bffde63dSSheetal Tigadoli } 456*bffde63dSSheetal Tigadoli 457*bffde63dSSheetal Tigadoli int sd_cmd35(struct sd_handle *handle, uint32_t start) 458*bffde63dSSheetal Tigadoli { 459*bffde63dSSheetal Tigadoli int res; 460*bffde63dSSheetal Tigadoli uint32_t argument, options; 461*bffde63dSSheetal Tigadoli struct sd_resp resp; 462*bffde63dSSheetal Tigadoli 463*bffde63dSSheetal Tigadoli res = card_sts_resp(handle, &resp.cardStatus); 464*bffde63dSSheetal Tigadoli if (res != SD_OK) 465*bffde63dSSheetal Tigadoli return res; 466*bffde63dSSheetal Tigadoli 467*bffde63dSSheetal Tigadoli argument = start; 468*bffde63dSSheetal Tigadoli 469*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 470*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CRC_EN_MASK | 471*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK; 472*bffde63dSSheetal Tigadoli 473*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 474*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_ERASE_GROUP_START, 475*bffde63dSSheetal Tigadoli argument, options, &resp); 476*bffde63dSSheetal Tigadoli 477*bffde63dSSheetal Tigadoli if (res != SD_OK) 478*bffde63dSSheetal Tigadoli return res; 479*bffde63dSSheetal Tigadoli 480*bffde63dSSheetal Tigadoli return res; 481*bffde63dSSheetal Tigadoli } 482*bffde63dSSheetal Tigadoli 483*bffde63dSSheetal Tigadoli int sd_cmd36(struct sd_handle *handle, uint32_t end) 484*bffde63dSSheetal Tigadoli { 485*bffde63dSSheetal Tigadoli int res; 486*bffde63dSSheetal Tigadoli uint32_t argument, options; 487*bffde63dSSheetal Tigadoli struct sd_resp resp; 488*bffde63dSSheetal Tigadoli 489*bffde63dSSheetal Tigadoli res = card_sts_resp(handle, &resp.cardStatus); 490*bffde63dSSheetal Tigadoli if (res != SD_OK) 491*bffde63dSSheetal Tigadoli return res; 492*bffde63dSSheetal Tigadoli 493*bffde63dSSheetal Tigadoli argument = end; 494*bffde63dSSheetal Tigadoli 495*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 496*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CRC_EN_MASK | 497*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK; 498*bffde63dSSheetal Tigadoli 499*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 500*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_ERASE_GROUP_END, 501*bffde63dSSheetal Tigadoli argument, options, &resp); 502*bffde63dSSheetal Tigadoli 503*bffde63dSSheetal Tigadoli if (res != SD_OK) 504*bffde63dSSheetal Tigadoli return res; 505*bffde63dSSheetal Tigadoli 506*bffde63dSSheetal Tigadoli return res; 507*bffde63dSSheetal Tigadoli } 508*bffde63dSSheetal Tigadoli 509*bffde63dSSheetal Tigadoli int sd_cmd38(struct sd_handle *handle) 510*bffde63dSSheetal Tigadoli { 511*bffde63dSSheetal Tigadoli int res; 512*bffde63dSSheetal Tigadoli uint32_t argument, options; 513*bffde63dSSheetal Tigadoli struct sd_resp resp; 514*bffde63dSSheetal Tigadoli 515*bffde63dSSheetal Tigadoli res = card_sts_resp(handle, &resp.cardStatus); 516*bffde63dSSheetal Tigadoli if (res != SD_OK) 517*bffde63dSSheetal Tigadoli return res; 518*bffde63dSSheetal Tigadoli 519*bffde63dSSheetal Tigadoli argument = 0; 520*bffde63dSSheetal Tigadoli 521*bffde63dSSheetal Tigadoli options = (SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) | 522*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CRC_EN_MASK | 523*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK; 524*bffde63dSSheetal Tigadoli 525*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 526*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_ERASE, argument, options, &resp); 527*bffde63dSSheetal Tigadoli 528*bffde63dSSheetal Tigadoli if (res != SD_OK) 529*bffde63dSSheetal Tigadoli return res; 530*bffde63dSSheetal Tigadoli 531*bffde63dSSheetal Tigadoli return res; 532*bffde63dSSheetal Tigadoli } 533*bffde63dSSheetal Tigadoli #endif 534*bffde63dSSheetal Tigadoli 535*bffde63dSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE 536*bffde63dSSheetal Tigadoli 537*bffde63dSSheetal Tigadoli int sd_cmd24(struct sd_handle *handle, 538*bffde63dSSheetal Tigadoli uint32_t addr, uint32_t len, uint8_t *buffer) 539*bffde63dSSheetal Tigadoli { 540*bffde63dSSheetal Tigadoli int res; 541*bffde63dSSheetal Tigadoli uint32_t argument, options, ntry; 542*bffde63dSSheetal Tigadoli struct sd_resp resp; 543*bffde63dSSheetal Tigadoli 544*bffde63dSSheetal Tigadoli ntry = 0; 545*bffde63dSSheetal Tigadoli do { 546*bffde63dSSheetal Tigadoli res = sd_cmd13(handle, &resp.cardStatus); 547*bffde63dSSheetal Tigadoli if (res != SD_OK) { 548*bffde63dSSheetal Tigadoli EMMC_TRACE( 549*bffde63dSSheetal Tigadoli "cmd 13 failed before cmd24: rca 0x%0x, return %d, response 0x%0x\n", 550*bffde63dSSheetal Tigadoli handle->device->ctrl.rca, res, &resp.cardStatus); 551*bffde63dSSheetal Tigadoli return res; 552*bffde63dSSheetal Tigadoli } 553*bffde63dSSheetal Tigadoli 554*bffde63dSSheetal Tigadoli if (resp.cardStatus & 0x100) 555*bffde63dSSheetal Tigadoli break; 556*bffde63dSSheetal Tigadoli 557*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 rsp:0x%08x before cmd24\n", resp.cardStatus); 558*bffde63dSSheetal Tigadoli 559*bffde63dSSheetal Tigadoli if (ntry > handle->device->cfg.retryLimit) { 560*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry reach limit %d\n", 561*bffde63dSSheetal Tigadoli handle->device->cfg.retryLimit); 562*bffde63dSSheetal Tigadoli return SD_CMD_TIMEOUT; 563*bffde63dSSheetal Tigadoli } 564*bffde63dSSheetal Tigadoli 565*bffde63dSSheetal Tigadoli ntry++; 566*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry %d\n", ntry); 567*bffde63dSSheetal Tigadoli 568*bffde63dSSheetal Tigadoli SD_US_DELAY(1000); 569*bffde63dSSheetal Tigadoli 570*bffde63dSSheetal Tigadoli } while (1); 571*bffde63dSSheetal Tigadoli 572*bffde63dSSheetal Tigadoli data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD); 573*bffde63dSSheetal Tigadoli 574*bffde63dSSheetal Tigadoli argument = addr; 575*bffde63dSSheetal Tigadoli 576*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 577*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK | 578*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK; 579*bffde63dSSheetal Tigadoli 580*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 581*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_WRITE_BLOCK, argument, options, &resp); 582*bffde63dSSheetal Tigadoli 583*bffde63dSSheetal Tigadoli if (res != SD_OK) 584*bffde63dSSheetal Tigadoli return res; 585*bffde63dSSheetal Tigadoli 586*bffde63dSSheetal Tigadoli res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD); 587*bffde63dSSheetal Tigadoli 588*bffde63dSSheetal Tigadoli return res; 589*bffde63dSSheetal Tigadoli } 590*bffde63dSSheetal Tigadoli 591*bffde63dSSheetal Tigadoli int sd_cmd25(struct sd_handle *handle, 592*bffde63dSSheetal Tigadoli uint32_t addr, uint32_t len, uint8_t *buffer) 593*bffde63dSSheetal Tigadoli { 594*bffde63dSSheetal Tigadoli int res = SD_OK; 595*bffde63dSSheetal Tigadoli uint32_t argument, options, ntry; 596*bffde63dSSheetal Tigadoli struct sd_resp resp; 597*bffde63dSSheetal Tigadoli 598*bffde63dSSheetal Tigadoli ntry = 0; 599*bffde63dSSheetal Tigadoli do { 600*bffde63dSSheetal Tigadoli res = sd_cmd13(handle, &resp.cardStatus); 601*bffde63dSSheetal Tigadoli if (res != SD_OK) { 602*bffde63dSSheetal Tigadoli EMMC_TRACE( 603*bffde63dSSheetal Tigadoli "cmd 13 failed before cmd25: rca 0x%0x, return %d, response 0x%0x\n", 604*bffde63dSSheetal Tigadoli handle->device->ctrl.rca, res, &resp.cardStatus); 605*bffde63dSSheetal Tigadoli return res; 606*bffde63dSSheetal Tigadoli } 607*bffde63dSSheetal Tigadoli 608*bffde63dSSheetal Tigadoli if (resp.cardStatus & 0x100) 609*bffde63dSSheetal Tigadoli break; 610*bffde63dSSheetal Tigadoli 611*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 rsp:0x%08x before cmd25\n", resp.cardStatus); 612*bffde63dSSheetal Tigadoli 613*bffde63dSSheetal Tigadoli if (ntry > handle->device->cfg.retryLimit) { 614*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry reach limit %d\n", 615*bffde63dSSheetal Tigadoli handle->device->cfg.retryLimit); 616*bffde63dSSheetal Tigadoli return SD_CMD_TIMEOUT; 617*bffde63dSSheetal Tigadoli } 618*bffde63dSSheetal Tigadoli 619*bffde63dSSheetal Tigadoli ntry++; 620*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 retry %d\n", ntry); 621*bffde63dSSheetal Tigadoli 622*bffde63dSSheetal Tigadoli SD_US_DELAY(1000); 623*bffde63dSSheetal Tigadoli } while (1); 624*bffde63dSSheetal Tigadoli 625*bffde63dSSheetal Tigadoli data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD); 626*bffde63dSSheetal Tigadoli 627*bffde63dSSheetal Tigadoli argument = addr; 628*bffde63dSSheetal Tigadoli 629*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | 630*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_MSBS_MASK | 631*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_BCEN_MASK | 632*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CRC_EN_MASK | 633*bffde63dSSheetal Tigadoli BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT); 634*bffde63dSSheetal Tigadoli 635*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 636*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_CMD_WRITE_MULTIPLE_BLOCK, 637*bffde63dSSheetal Tigadoli argument, options, &resp); 638*bffde63dSSheetal Tigadoli 639*bffde63dSSheetal Tigadoli if (res != SD_OK) 640*bffde63dSSheetal Tigadoli return res; 641*bffde63dSSheetal Tigadoli 642*bffde63dSSheetal Tigadoli res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD); 643*bffde63dSSheetal Tigadoli 644*bffde63dSSheetal Tigadoli return res; 645*bffde63dSSheetal Tigadoli } 646*bffde63dSSheetal Tigadoli #endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */ 647*bffde63dSSheetal Tigadoli 648*bffde63dSSheetal Tigadoli int mmc_cmd6(struct sd_handle *handle, uint32_t argument) 649*bffde63dSSheetal Tigadoli { 650*bffde63dSSheetal Tigadoli int res; 651*bffde63dSSheetal Tigadoli uint32_t options; 652*bffde63dSSheetal Tigadoli struct sd_resp resp; 653*bffde63dSSheetal Tigadoli 654*bffde63dSSheetal Tigadoli options = SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S | 655*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK; 656*bffde63dSSheetal Tigadoli 657*bffde63dSSheetal Tigadoli EMMC_TRACE("Sending CMD6 with argument 0x%X\n", argument); 658*bffde63dSSheetal Tigadoli 659*bffde63dSSheetal Tigadoli /* send cmd and parse result */ 660*bffde63dSSheetal Tigadoli res = send_cmd(handle, SD_ACMD_SET_BUS_WIDTH, argument, options, &resp); 661*bffde63dSSheetal Tigadoli 662*bffde63dSSheetal Tigadoli /* 663*bffde63dSSheetal Tigadoli * For R1b type response: 664*bffde63dSSheetal Tigadoli * controller issues a COMMAND COMPLETE interrupt when the R1 665*bffde63dSSheetal Tigadoli * response is received, 666*bffde63dSSheetal Tigadoli * then controller monitors DAT0 for busy status, 667*bffde63dSSheetal Tigadoli * controller issues a TRANSFER COMPLETE interrupt when busy signal 668*bffde63dSSheetal Tigadoli * clears. 669*bffde63dSSheetal Tigadoli */ 670*bffde63dSSheetal Tigadoli wait_for_event(handle, 671*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_TXDONE_MASK | SD_ERR_INTERRUPTS, 672*bffde63dSSheetal Tigadoli handle->device->cfg.wfe_retry); 673*bffde63dSSheetal Tigadoli 674*bffde63dSSheetal Tigadoli if (res == SD_OK) { 675*bffde63dSSheetal Tigadoli /* Check result of Cmd6 using Cmd13 to check card status */ 676*bffde63dSSheetal Tigadoli 677*bffde63dSSheetal Tigadoli /* Check status using Cmd13 */ 678*bffde63dSSheetal Tigadoli res = sd_cmd13(handle, &resp.cardStatus); 679*bffde63dSSheetal Tigadoli 680*bffde63dSSheetal Tigadoli if (res == SD_OK) { 681*bffde63dSSheetal Tigadoli /* Check bit 7 (SWITCH_ERROR) in card status */ 682*bffde63dSSheetal Tigadoli if ((resp.cardStatus & 0x80) != 0) { 683*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd6 failed: SWITCH_ERROR\n"); 684*bffde63dSSheetal Tigadoli res = SD_FAIL; 685*bffde63dSSheetal Tigadoli } 686*bffde63dSSheetal Tigadoli } else { 687*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd13 failed after cmd6: "); 688*bffde63dSSheetal Tigadoli EMMC_TRACE("rca 0x%0x, return %d, response 0x%0x\n", 689*bffde63dSSheetal Tigadoli handle->device->ctrl.rca, res, resp.cardStatus); 690*bffde63dSSheetal Tigadoli } 691*bffde63dSSheetal Tigadoli } 692*bffde63dSSheetal Tigadoli 693*bffde63dSSheetal Tigadoli return res; 694*bffde63dSSheetal Tigadoli } 695*bffde63dSSheetal Tigadoli 696*bffde63dSSheetal Tigadoli 697*bffde63dSSheetal Tigadoli #define SD_BUSY_CHECK 0x00203000 698*bffde63dSSheetal Tigadoli #define DAT0_LEVEL_MASK 0x100000 /* bit20 in PSTATE */ 699*bffde63dSSheetal Tigadoli #define DEV_BUSY_TIMEOUT 600000 /* 60 Sec : 600000 * 100us */ 700*bffde63dSSheetal Tigadoli 701*bffde63dSSheetal Tigadoli int send_cmd(struct sd_handle *handle, uint32_t cmdIndex, uint32_t argument, 702*bffde63dSSheetal Tigadoli uint32_t options, struct sd_resp *resp) 703*bffde63dSSheetal Tigadoli { 704*bffde63dSSheetal Tigadoli int status = SD_OK; 705*bffde63dSSheetal Tigadoli uint32_t event = 0, present, timeout = 0, retry = 0, mask = 3; 706*bffde63dSSheetal Tigadoli uint32_t temp_resp[4]; 707*bffde63dSSheetal Tigadoli 708*bffde63dSSheetal Tigadoli if (handle == NULL) { 709*bffde63dSSheetal Tigadoli EMMC_TRACE("Invalid handle for cmd%d\n", cmdIndex); 710*bffde63dSSheetal Tigadoli return SD_INVALID_HANDLE; 711*bffde63dSSheetal Tigadoli } 712*bffde63dSSheetal Tigadoli 713*bffde63dSSheetal Tigadoli mask = (SD_BUSY_CHECK & options) ? 3 : 1; 714*bffde63dSSheetal Tigadoli 715*bffde63dSSheetal Tigadoli RETRY_WRITE_CMD: 716*bffde63dSSheetal Tigadoli do { 717*bffde63dSSheetal Tigadoli /* Make sure it is ok to send command */ 718*bffde63dSSheetal Tigadoli present = 719*bffde63dSSheetal Tigadoli chal_sd_get_present_status((CHAL_HANDLE *) handle->device); 720*bffde63dSSheetal Tigadoli timeout++; 721*bffde63dSSheetal Tigadoli 722*bffde63dSSheetal Tigadoli if (present & mask) 723*bffde63dSSheetal Tigadoli SD_US_DELAY(1000); 724*bffde63dSSheetal Tigadoli else 725*bffde63dSSheetal Tigadoli break; 726*bffde63dSSheetal Tigadoli 727*bffde63dSSheetal Tigadoli } while (timeout < EMMC_BUSY_CMD_TIMEOUT_MS); 728*bffde63dSSheetal Tigadoli 729*bffde63dSSheetal Tigadoli if (timeout >= EMMC_BUSY_CMD_TIMEOUT_MS) { 730*bffde63dSSheetal Tigadoli status = SD_CMD_MISSING; 731*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd%d timedout %dms\n", cmdIndex, timeout); 732*bffde63dSSheetal Tigadoli } 733*bffde63dSSheetal Tigadoli 734*bffde63dSSheetal Tigadoli /* Reset both DAT and CMD line if only of them are stuck */ 735*bffde63dSSheetal Tigadoli if (present & mask) 736*bffde63dSSheetal Tigadoli check_error(handle, SD4_EMMC_TOP_INTR_CMDERROR_MASK); 737*bffde63dSSheetal Tigadoli 738*bffde63dSSheetal Tigadoli handle->device->ctrl.argReg = argument; 739*bffde63dSSheetal Tigadoli chal_sd_send_cmd((CHAL_HANDLE *) handle->device, cmdIndex, 740*bffde63dSSheetal Tigadoli handle->device->ctrl.argReg, options); 741*bffde63dSSheetal Tigadoli 742*bffde63dSSheetal Tigadoli handle->device->ctrl.cmdIndex = cmdIndex; 743*bffde63dSSheetal Tigadoli 744*bffde63dSSheetal Tigadoli event = wait_for_event(handle, 745*bffde63dSSheetal Tigadoli (SD4_EMMC_TOP_INTR_CMDDONE_MASK | 746*bffde63dSSheetal Tigadoli SD_ERR_INTERRUPTS), 747*bffde63dSSheetal Tigadoli handle->device->cfg.wfe_retry); 748*bffde63dSSheetal Tigadoli 749*bffde63dSSheetal Tigadoli if (handle->device->ctrl.cmdStatus == SD_CMD_MISSING) { 750*bffde63dSSheetal Tigadoli retry++; 751*bffde63dSSheetal Tigadoli 752*bffde63dSSheetal Tigadoli if (retry >= handle->device->cfg.retryLimit) { 753*bffde63dSSheetal Tigadoli status = SD_CMD_MISSING; 754*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd%d retry reaches the limit %d\n", 755*bffde63dSSheetal Tigadoli cmdIndex, retry); 756*bffde63dSSheetal Tigadoli } else { 757*bffde63dSSheetal Tigadoli /* reset both DAT & CMD line if one of them is stuck */ 758*bffde63dSSheetal Tigadoli present = chal_sd_get_present_status((CHAL_HANDLE *) 759*bffde63dSSheetal Tigadoli handle->device); 760*bffde63dSSheetal Tigadoli 761*bffde63dSSheetal Tigadoli if (present & mask) 762*bffde63dSSheetal Tigadoli check_error(handle, 763*bffde63dSSheetal Tigadoli SD4_EMMC_TOP_INTR_CMDERROR_MASK); 764*bffde63dSSheetal Tigadoli 765*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd%d retry %d PSTATE[0x%08x]\n", 766*bffde63dSSheetal Tigadoli cmdIndex, retry, 767*bffde63dSSheetal Tigadoli chal_sd_get_present_status((CHAL_HANDLE *) 768*bffde63dSSheetal Tigadoli handle->device)); 769*bffde63dSSheetal Tigadoli goto RETRY_WRITE_CMD; 770*bffde63dSSheetal Tigadoli } 771*bffde63dSSheetal Tigadoli } 772*bffde63dSSheetal Tigadoli 773*bffde63dSSheetal Tigadoli if (handle->device->ctrl.cmdStatus == SD_OK) { 774*bffde63dSSheetal Tigadoli if (resp != NULL) { 775*bffde63dSSheetal Tigadoli status = 776*bffde63dSSheetal Tigadoli chal_sd_get_response((CHAL_HANDLE *) handle->device, 777*bffde63dSSheetal Tigadoli temp_resp); 778*bffde63dSSheetal Tigadoli process_cmd_response(handle, 779*bffde63dSSheetal Tigadoli handle->device->ctrl.cmdIndex, 780*bffde63dSSheetal Tigadoli temp_resp[0], temp_resp[1], 781*bffde63dSSheetal Tigadoli temp_resp[2], temp_resp[3], resp); 782*bffde63dSSheetal Tigadoli } 783*bffde63dSSheetal Tigadoli 784*bffde63dSSheetal Tigadoli /* Check Device busy after CMD */ 785*bffde63dSSheetal Tigadoli if ((cmdIndex == 5) || (cmdIndex == 6) || (cmdIndex == 7) || 786*bffde63dSSheetal Tigadoli (cmdIndex == 28) || (cmdIndex == 29) || (cmdIndex == 38)) { 787*bffde63dSSheetal Tigadoli 788*bffde63dSSheetal Tigadoli timeout = 0; 789*bffde63dSSheetal Tigadoli do { 790*bffde63dSSheetal Tigadoli present = 791*bffde63dSSheetal Tigadoli chal_sd_get_present_status((CHAL_HANDLE *) 792*bffde63dSSheetal Tigadoli handle->device); 793*bffde63dSSheetal Tigadoli 794*bffde63dSSheetal Tigadoli timeout++; 795*bffde63dSSheetal Tigadoli 796*bffde63dSSheetal Tigadoli /* Dat[0]:bit20 low means device busy */ 797*bffde63dSSheetal Tigadoli if ((present & DAT0_LEVEL_MASK) == 0) { 798*bffde63dSSheetal Tigadoli EMMC_TRACE("Device busy: "); 799*bffde63dSSheetal Tigadoli EMMC_TRACE( 800*bffde63dSSheetal Tigadoli "cmd%d arg:0x%08x: PSTATE[0x%08x]\n", 801*bffde63dSSheetal Tigadoli cmdIndex, argument, present); 802*bffde63dSSheetal Tigadoli SD_US_DELAY(100); 803*bffde63dSSheetal Tigadoli } else { 804*bffde63dSSheetal Tigadoli break; 805*bffde63dSSheetal Tigadoli } 806*bffde63dSSheetal Tigadoli } while (timeout < DEV_BUSY_TIMEOUT); 807*bffde63dSSheetal Tigadoli } 808*bffde63dSSheetal Tigadoli } else if (handle->device->ctrl.cmdStatus && 809*bffde63dSSheetal Tigadoli handle->device->ctrl.cmdStatus != SD_CMD_MISSING) { 810*bffde63dSSheetal Tigadoli retry++; 811*bffde63dSSheetal Tigadoli status = check_error(handle, handle->device->ctrl.cmdStatus); 812*bffde63dSSheetal Tigadoli 813*bffde63dSSheetal Tigadoli EMMC_TRACE( 814*bffde63dSSheetal Tigadoli "cmd%d error: cmdStatus:0x%08x error_status:0x%08x\n", 815*bffde63dSSheetal Tigadoli cmdIndex, handle->device->ctrl.cmdStatus, status); 816*bffde63dSSheetal Tigadoli 817*bffde63dSSheetal Tigadoli if ((handle->device->ctrl.cmdIndex == 1) || 818*bffde63dSSheetal Tigadoli (handle->device->ctrl.cmdIndex == 5)) { 819*bffde63dSSheetal Tigadoli status = event; 820*bffde63dSSheetal Tigadoli } else if ((handle->device->ctrl.cmdIndex == 7) || 821*bffde63dSSheetal Tigadoli (handle->device->ctrl.cmdIndex == 41)) { 822*bffde63dSSheetal Tigadoli status = event; 823*bffde63dSSheetal Tigadoli } else if ((status == SD_ERROR_RECOVERABLE) && 824*bffde63dSSheetal Tigadoli (retry < handle->device->cfg.retryLimit)) { 825*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd%d recoverable error ", cmdIndex); 826*bffde63dSSheetal Tigadoli EMMC_TRACE("retry %d PSTATE[0x%08x].\n", retry, 827*bffde63dSSheetal Tigadoli chal_sd_get_present_status((CHAL_HANDLE *) 828*bffde63dSSheetal Tigadoli handle->device)); 829*bffde63dSSheetal Tigadoli goto RETRY_WRITE_CMD; 830*bffde63dSSheetal Tigadoli } else { 831*bffde63dSSheetal Tigadoli EMMC_TRACE("cmd%d retry reaches the limit %d\n", 832*bffde63dSSheetal Tigadoli cmdIndex, retry); 833*bffde63dSSheetal Tigadoli status = event; 834*bffde63dSSheetal Tigadoli } 835*bffde63dSSheetal Tigadoli } 836*bffde63dSSheetal Tigadoli 837*bffde63dSSheetal Tigadoli handle->device->ctrl.blkReg = 0; 838*bffde63dSSheetal Tigadoli /* clear error status for next command */ 839*bffde63dSSheetal Tigadoli handle->device->ctrl.cmdStatus = 0; 840*bffde63dSSheetal Tigadoli 841*bffde63dSSheetal Tigadoli return status; 842*bffde63dSSheetal Tigadoli } 843