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