1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright 2021 NXP 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu * 6*91f16700Schasinglulu * 7*91f16700Schasinglulu */ 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <endian.h> 10*91f16700Schasinglulu #include <stdio.h> 11*91f16700Schasinglulu #include <stdlib.h> 12*91f16700Schasinglulu #include <string.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu #include <arch_helpers.h> 15*91f16700Schasinglulu #include <common/debug.h> 16*91f16700Schasinglulu #include <drivers/io/io_block.h> 17*91f16700Schasinglulu #include "nxp_timer.h" 18*91f16700Schasinglulu #include "sd_mmc.h" 19*91f16700Schasinglulu #include <utils.h> 20*91f16700Schasinglulu #include <utils_def.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu 23*91f16700Schasinglulu /* Private structure for MMC driver data */ 24*91f16700Schasinglulu static struct mmc mmc_drv_data; 25*91f16700Schasinglulu 26*91f16700Schasinglulu #ifndef NXP_POLICY_OTA 27*91f16700Schasinglulu /* 28*91f16700Schasinglulu * For NXP_POLICY_OTA, SD needs to do R/W on OCRAM. OCRAM is secure memory at 29*91f16700Schasinglulu * default. SD can only do non-secure DMA. Configuring SD to work in PIO mode 30*91f16700Schasinglulu * instead of DMA mode will make SD R/W on OCRAM available. 31*91f16700Schasinglulu */ 32*91f16700Schasinglulu /* To debug without dma comment this MACRO */ 33*91f16700Schasinglulu #define NXP_SD_DMA_CAPABILITY 34*91f16700Schasinglulu #endif 35*91f16700Schasinglulu #define SD_TIMEOUT 1000 /* ms */ 36*91f16700Schasinglulu #define SD_TIMEOUT_HIGH 20000 /* ms */ 37*91f16700Schasinglulu #define SD_BLOCK_TIMEOUT 8 /* ms */ 38*91f16700Schasinglulu 39*91f16700Schasinglulu #define ERROR_ESDHC_CARD_DETECT_FAIL -1 40*91f16700Schasinglulu #define ERROR_ESDHC_UNUSABLE_CARD -2 41*91f16700Schasinglulu #define ERROR_ESDHC_COMMUNICATION_ERROR -3 42*91f16700Schasinglulu #define ERROR_ESDHC_BLOCK_LENGTH -4 43*91f16700Schasinglulu #define ERROR_ESDHC_DMA_ERROR -5 44*91f16700Schasinglulu #define ERROR_ESDHC_BUSY -6 45*91f16700Schasinglulu 46*91f16700Schasinglulu /*************************************************************** 47*91f16700Schasinglulu * Function : set_speed 48*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 49*91f16700Schasinglulu * clock - Clock Value to be set 50*91f16700Schasinglulu * Return : void 51*91f16700Schasinglulu * Description : Calculates the value of SDCLKFS and DVS to be set 52*91f16700Schasinglulu * for getting the required clock assuming the base_clk 53*91f16700Schasinglulu * as a fixed value (MAX_PLATFORM_CLOCK) 54*91f16700Schasinglulu *****************************************************************/ 55*91f16700Schasinglulu static void set_speed(struct mmc *mmc, uint32_t clock) 56*91f16700Schasinglulu { 57*91f16700Schasinglulu /* sdhc_clk = (base clock) / [(SDCLKFS × 2) × (DVS +1)] */ 58*91f16700Schasinglulu 59*91f16700Schasinglulu uint32_t dvs = 1U; 60*91f16700Schasinglulu uint32_t sdclkfs = 2U; 61*91f16700Schasinglulu /* TBD - Change this to actual platform clock by reading via RCW */ 62*91f16700Schasinglulu uint32_t base_clk = MAX_PLATFORM_CLOCK; 63*91f16700Schasinglulu 64*91f16700Schasinglulu if (base_clk / 16 > clock) { 65*91f16700Schasinglulu for (sdclkfs = 2U; sdclkfs < 256U; sdclkfs *= 2U) { 66*91f16700Schasinglulu if ((base_clk / sdclkfs) <= (clock * 16)) { 67*91f16700Schasinglulu break; 68*91f16700Schasinglulu } 69*91f16700Schasinglulu } 70*91f16700Schasinglulu } 71*91f16700Schasinglulu 72*91f16700Schasinglulu for (dvs = 1U; dvs <= 16U; dvs++) { 73*91f16700Schasinglulu if ((base_clk / (dvs * sdclkfs)) <= clock) { 74*91f16700Schasinglulu break; 75*91f16700Schasinglulu } 76*91f16700Schasinglulu } 77*91f16700Schasinglulu 78*91f16700Schasinglulu sdclkfs >>= 1U; 79*91f16700Schasinglulu dvs -= 1U; 80*91f16700Schasinglulu 81*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->sysctl, 82*91f16700Schasinglulu (ESDHC_SYSCTL_DTOCV(TIMEOUT_COUNTER_SDCLK_2_27) | 83*91f16700Schasinglulu ESDHC_SYSCTL_SDCLKFS(sdclkfs) | ESDHC_SYSCTL_DVS(dvs) | 84*91f16700Schasinglulu ESDHC_SYSCTL_SDCLKEN)); 85*91f16700Schasinglulu } 86*91f16700Schasinglulu 87*91f16700Schasinglulu /*************************************************************************** 88*91f16700Schasinglulu * Function : esdhc_init 89*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 90*91f16700Schasinglulu * card_detect - flag to indicate if card insert needs 91*91f16700Schasinglulu * to be detected or not. For SDHC2 controller, Card detect 92*91f16700Schasinglulu * is not present, so this field will be false 93*91f16700Schasinglulu * Return : SUCCESS or Error Code 94*91f16700Schasinglulu * Description : 1. Set Initial Clock Speed 95*91f16700Schasinglulu * 2. Card Detect if not eMMC 96*91f16700Schasinglulu * 3. Enable Controller Clock 97*91f16700Schasinglulu * 4. Send 80 ticks for card to power up 98*91f16700Schasinglulu * 5. Set LE mode and Bus Width as 1 bit. 99*91f16700Schasinglulu ***************************************************************************/ 100*91f16700Schasinglulu static int esdhc_init(struct mmc *mmc, bool card_detect) 101*91f16700Schasinglulu { 102*91f16700Schasinglulu uint32_t val; 103*91f16700Schasinglulu uint64_t start_time; 104*91f16700Schasinglulu 105*91f16700Schasinglulu /* Reset the entire host controller */ 106*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_RSTA; 107*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->sysctl, val); 108*91f16700Schasinglulu 109*91f16700Schasinglulu /* Wait until the controller is available */ 110*91f16700Schasinglulu start_time = get_timer_val(0); 111*91f16700Schasinglulu while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { 112*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_RSTA; 113*91f16700Schasinglulu if (val == 0U) { 114*91f16700Schasinglulu break; 115*91f16700Schasinglulu } 116*91f16700Schasinglulu } 117*91f16700Schasinglulu 118*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->sysctl) & 119*91f16700Schasinglulu (ESDHC_SYSCTL_RSTA); 120*91f16700Schasinglulu if (val != 0U) { 121*91f16700Schasinglulu ERROR("SD Reset failed\n"); 122*91f16700Schasinglulu return ERROR_ESDHC_BUSY; 123*91f16700Schasinglulu } 124*91f16700Schasinglulu 125*91f16700Schasinglulu /* Set initial clock speed */ 126*91f16700Schasinglulu set_speed(mmc, CARD_IDENTIFICATION_FREQ); 127*91f16700Schasinglulu 128*91f16700Schasinglulu if (card_detect) { 129*91f16700Schasinglulu /* Check CINS in prsstat register */ 130*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->prsstat) & 131*91f16700Schasinglulu ESDHC_PRSSTAT_CINS; 132*91f16700Schasinglulu if (val == 0) { 133*91f16700Schasinglulu ERROR("CINS not set in prsstat\n"); 134*91f16700Schasinglulu return ERROR_ESDHC_CARD_DETECT_FAIL; 135*91f16700Schasinglulu } 136*91f16700Schasinglulu } 137*91f16700Schasinglulu 138*91f16700Schasinglulu /* Enable controller clock */ 139*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_SDCLKEN; 140*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->sysctl, val); 141*91f16700Schasinglulu 142*91f16700Schasinglulu /* Send 80 clock ticks for the card to power up */ 143*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_INITA; 144*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->sysctl, val); 145*91f16700Schasinglulu 146*91f16700Schasinglulu start_time = get_timer_val(0); 147*91f16700Schasinglulu while (get_timer_val(start_time) < SD_TIMEOUT) { 148*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_INITA; 149*91f16700Schasinglulu if (val != 0U) { 150*91f16700Schasinglulu break; 151*91f16700Schasinglulu } 152*91f16700Schasinglulu } 153*91f16700Schasinglulu 154*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_INITA; 155*91f16700Schasinglulu if (val == 0U) { 156*91f16700Schasinglulu ERROR("Failed to power up the card\n"); 157*91f16700Schasinglulu return ERROR_ESDHC_CARD_DETECT_FAIL; 158*91f16700Schasinglulu } 159*91f16700Schasinglulu 160*91f16700Schasinglulu INFO("Card detected successfully\n"); 161*91f16700Schasinglulu 162*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->proctl); 163*91f16700Schasinglulu val = val | (ESDHC_PROCTL_EMODE_LE | ESDHC_PROCTL_DTW_1BIT); 164*91f16700Schasinglulu 165*91f16700Schasinglulu /* Set little endian mode, set bus width as 1-bit */ 166*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->proctl, val); 167*91f16700Schasinglulu 168*91f16700Schasinglulu /* Enable cache snooping for DMA transactions */ 169*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->ctl) | ESDHC_DCR_SNOOP; 170*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->ctl, val); 171*91f16700Schasinglulu 172*91f16700Schasinglulu return 0; 173*91f16700Schasinglulu } 174*91f16700Schasinglulu 175*91f16700Schasinglulu /*************************************************************************** 176*91f16700Schasinglulu * Function : esdhc_send_cmd 177*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 178*91f16700Schasinglulu * cmd - Command Number 179*91f16700Schasinglulu * args - Command Args 180*91f16700Schasinglulu * Return : SUCCESS is 0, or Error Code ( < 0) 181*91f16700Schasinglulu * Description : Updates the eSDHC registers cmdargs and xfertype 182*91f16700Schasinglulu ***************************************************************************/ 183*91f16700Schasinglulu static int esdhc_send_cmd(struct mmc *mmc, uint32_t cmd, uint32_t args) 184*91f16700Schasinglulu { 185*91f16700Schasinglulu uint32_t val; 186*91f16700Schasinglulu uint64_t start_time; 187*91f16700Schasinglulu uint32_t xfertyp = 0; 188*91f16700Schasinglulu 189*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL); 190*91f16700Schasinglulu 191*91f16700Schasinglulu /* Wait for the command line & data line to be free */ 192*91f16700Schasinglulu /* (poll the CIHB,CDIHB bit of the present state register) */ 193*91f16700Schasinglulu start_time = get_timer_val(0); 194*91f16700Schasinglulu while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { 195*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->prsstat) & 196*91f16700Schasinglulu (ESDHC_PRSSTAT_CIHB | ESDHC_PRSSTAT_CDIHB); 197*91f16700Schasinglulu if (val == 0U) { 198*91f16700Schasinglulu break; 199*91f16700Schasinglulu } 200*91f16700Schasinglulu } 201*91f16700Schasinglulu 202*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->prsstat) & 203*91f16700Schasinglulu (ESDHC_PRSSTAT_CIHB | ESDHC_PRSSTAT_CDIHB); 204*91f16700Schasinglulu if (val != 0U) { 205*91f16700Schasinglulu ERROR("SD send cmd: Command Line or Data Line Busy cmd = %x\n", 206*91f16700Schasinglulu cmd); 207*91f16700Schasinglulu return ERROR_ESDHC_BUSY; 208*91f16700Schasinglulu } 209*91f16700Schasinglulu 210*91f16700Schasinglulu if (cmd == CMD2 || cmd == CMD9) { 211*91f16700Schasinglulu xfertyp |= ESDHC_XFERTYP_RSPTYP_136; 212*91f16700Schasinglulu } else if (cmd == CMD7 || (cmd == CMD6 && mmc->card.type == MMC_CARD)) { 213*91f16700Schasinglulu xfertyp |= ESDHC_XFERTYP_RSPTYP_48_BUSY; 214*91f16700Schasinglulu } else if (cmd != CMD0) { 215*91f16700Schasinglulu xfertyp |= ESDHC_XFERTYP_RSPTYP_48; 216*91f16700Schasinglulu } 217*91f16700Schasinglulu 218*91f16700Schasinglulu if (cmd == CMD2 || cmd == CMD9) { 219*91f16700Schasinglulu xfertyp |= ESDHC_XFERTYP_CCCEN; /* Command index check enable */ 220*91f16700Schasinglulu } else if ((cmd != CMD0) && (cmd != ACMD41) && (cmd != CMD1)) { 221*91f16700Schasinglulu xfertyp = xfertyp | ESDHC_XFERTYP_CCCEN | ESDHC_XFERTYP_CICEN; 222*91f16700Schasinglulu } 223*91f16700Schasinglulu 224*91f16700Schasinglulu if ((cmd == CMD8 || cmd == CMD14 || cmd == CMD19) && 225*91f16700Schasinglulu mmc->card.type == MMC_CARD) { 226*91f16700Schasinglulu xfertyp |= ESDHC_XFERTYP_DPSEL; 227*91f16700Schasinglulu if (cmd != CMD19) { 228*91f16700Schasinglulu xfertyp |= ESDHC_XFERTYP_DTDSEL; 229*91f16700Schasinglulu } 230*91f16700Schasinglulu } 231*91f16700Schasinglulu 232*91f16700Schasinglulu if (cmd == CMD6 || cmd == CMD17 || cmd == CMD18 || cmd == CMD24 || 233*91f16700Schasinglulu cmd == ACMD51) { 234*91f16700Schasinglulu if (!(mmc->card.type == MMC_CARD && cmd == CMD6)) { 235*91f16700Schasinglulu if (cmd == CMD24) { 236*91f16700Schasinglulu xfertyp |= ESDHC_XFERTYP_DPSEL; 237*91f16700Schasinglulu } else { 238*91f16700Schasinglulu xfertyp |= (ESDHC_XFERTYP_DPSEL | 239*91f16700Schasinglulu ESDHC_XFERTYP_DTDSEL); 240*91f16700Schasinglulu } 241*91f16700Schasinglulu } 242*91f16700Schasinglulu 243*91f16700Schasinglulu if (cmd == CMD18) { 244*91f16700Schasinglulu xfertyp |= ESDHC_XFERTYP_BCEN; 245*91f16700Schasinglulu if (mmc->dma_support != 0) { 246*91f16700Schasinglulu /* Set BCEN of XFERTYP */ 247*91f16700Schasinglulu xfertyp |= ESDHC_XFERTYP_DMAEN; 248*91f16700Schasinglulu } 249*91f16700Schasinglulu } 250*91f16700Schasinglulu 251*91f16700Schasinglulu if ((cmd == CMD17 || cmd == CMD24) && (mmc->dma_support != 0)) { 252*91f16700Schasinglulu xfertyp |= ESDHC_XFERTYP_DMAEN; 253*91f16700Schasinglulu } 254*91f16700Schasinglulu } 255*91f16700Schasinglulu 256*91f16700Schasinglulu xfertyp |= ((cmd & 0x3F) << 24); 257*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->cmdarg, args); 258*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->xfertyp, xfertyp); 259*91f16700Schasinglulu 260*91f16700Schasinglulu #ifdef NXP_SD_DEBUG 261*91f16700Schasinglulu INFO("cmd = %d\n", cmd); 262*91f16700Schasinglulu INFO("args = %x\n", args); 263*91f16700Schasinglulu INFO("xfertyp: = %x\n", xfertyp); 264*91f16700Schasinglulu #endif 265*91f16700Schasinglulu return 0; 266*91f16700Schasinglulu } 267*91f16700Schasinglulu 268*91f16700Schasinglulu /*************************************************************************** 269*91f16700Schasinglulu * Function : esdhc_wait_response 270*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 271*91f16700Schasinglulu * response - Value updated 272*91f16700Schasinglulu * Return : SUCCESS - Response Received 273*91f16700Schasinglulu * COMMUNICATION_ERROR - Command not Complete 274*91f16700Schasinglulu * COMMAND_ERROR - CIE, CCE or CEBE error 275*91f16700Schasinglulu * RESP_TIMEOUT - CTOE error 276*91f16700Schasinglulu * Description : Checks for successful command completion. 277*91f16700Schasinglulu * Clears the CC bit at the end. 278*91f16700Schasinglulu ***************************************************************************/ 279*91f16700Schasinglulu static int esdhc_wait_response(struct mmc *mmc, uint32_t *response) 280*91f16700Schasinglulu { 281*91f16700Schasinglulu uint32_t val; 282*91f16700Schasinglulu uint64_t start_time; 283*91f16700Schasinglulu uint32_t status = 0U; 284*91f16700Schasinglulu 285*91f16700Schasinglulu /* Wait for the command to complete */ 286*91f16700Schasinglulu start_time = get_timer_val(0); 287*91f16700Schasinglulu while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { 288*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_CC; 289*91f16700Schasinglulu if (val != 0U) { 290*91f16700Schasinglulu break; 291*91f16700Schasinglulu } 292*91f16700Schasinglulu } 293*91f16700Schasinglulu 294*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_CC; 295*91f16700Schasinglulu if (val == 0U) { 296*91f16700Schasinglulu ERROR("%s:IRQSTAT Cmd not complete(CC not set)\n", __func__); 297*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 298*91f16700Schasinglulu } 299*91f16700Schasinglulu 300*91f16700Schasinglulu status = esdhc_in32(&mmc->esdhc_regs->irqstat); 301*91f16700Schasinglulu 302*91f16700Schasinglulu /* Check whether the interrupt is a CRC, CTOE or CIE error */ 303*91f16700Schasinglulu if ((status & (ESDHC_IRQSTAT_CIE | ESDHC_IRQSTAT_CEBE | 304*91f16700Schasinglulu ESDHC_IRQSTAT_CCE)) != 0) { 305*91f16700Schasinglulu ERROR("%s: IRQSTAT CRC, CEBE or CIE error = %x\n", 306*91f16700Schasinglulu __func__, status); 307*91f16700Schasinglulu return COMMAND_ERROR; 308*91f16700Schasinglulu } 309*91f16700Schasinglulu 310*91f16700Schasinglulu if ((status & ESDHC_IRQSTAT_CTOE) != 0) { 311*91f16700Schasinglulu INFO("%s: IRQSTAT CTOE set = %x\n", __func__, status); 312*91f16700Schasinglulu return RESP_TIMEOUT; 313*91f16700Schasinglulu } 314*91f16700Schasinglulu 315*91f16700Schasinglulu if ((status & ESDHC_IRQSTAT_DMAE) != 0) { 316*91f16700Schasinglulu ERROR("%s: IRQSTAT DMAE set = %x\n", __func__, status); 317*91f16700Schasinglulu return ERROR_ESDHC_DMA_ERROR; 318*91f16700Schasinglulu } 319*91f16700Schasinglulu 320*91f16700Schasinglulu if (response != NULL) { 321*91f16700Schasinglulu /* Get response values from eSDHC CMDRSPx registers. */ 322*91f16700Schasinglulu response[0] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[0]); 323*91f16700Schasinglulu response[1] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[1]); 324*91f16700Schasinglulu response[2] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[2]); 325*91f16700Schasinglulu response[3] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[3]); 326*91f16700Schasinglulu #ifdef NXP_SD_DEBUG 327*91f16700Schasinglulu INFO("Resp R1 R2 R3 R4\n"); 328*91f16700Schasinglulu INFO("Resp R1 = %x\n", response[0]); 329*91f16700Schasinglulu INFO("R2 = %x\n", response[1]); 330*91f16700Schasinglulu INFO("R3 = %x\n", response[2]); 331*91f16700Schasinglulu INFO("R4 = %x\n", response[3]); 332*91f16700Schasinglulu INFO("\n"); 333*91f16700Schasinglulu #endif 334*91f16700Schasinglulu } 335*91f16700Schasinglulu 336*91f16700Schasinglulu /* Clear the CC bit - w1c */ 337*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->irqstat) | ESDHC_IRQSTAT_CC; 338*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->irqstat, val); 339*91f16700Schasinglulu 340*91f16700Schasinglulu return 0; 341*91f16700Schasinglulu } 342*91f16700Schasinglulu 343*91f16700Schasinglulu /*************************************************************************** 344*91f16700Schasinglulu * Function : mmc_switch_to_high_frquency 345*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 346*91f16700Schasinglulu * Return : SUCCESS or Error Code 347*91f16700Schasinglulu * Description : mmc card below ver 4.0 does not support high speed 348*91f16700Schasinglulu * freq = 20 MHz 349*91f16700Schasinglulu * Send CMD6 (CMD_SWITCH_FUNC) With args 0x03B90100 350*91f16700Schasinglulu * Send CMD13 (CMD_SEND_STATUS) 351*91f16700Schasinglulu * if SWITCH Error, freq = 26 MHz 352*91f16700Schasinglulu * if no error, freq = 52 MHz 353*91f16700Schasinglulu ***************************************************************************/ 354*91f16700Schasinglulu static int mmc_switch_to_high_frquency(struct mmc *mmc) 355*91f16700Schasinglulu { 356*91f16700Schasinglulu int error; 357*91f16700Schasinglulu uint32_t response[4]; 358*91f16700Schasinglulu uint64_t start_time; 359*91f16700Schasinglulu 360*91f16700Schasinglulu mmc->card.bus_freq = MMC_SS_20MHZ; 361*91f16700Schasinglulu /* mmc card below ver 4.0 does not support high speed */ 362*91f16700Schasinglulu if (mmc->card.version < MMC_CARD_VERSION_4_X) { 363*91f16700Schasinglulu return 0; 364*91f16700Schasinglulu } 365*91f16700Schasinglulu 366*91f16700Schasinglulu /* send switch cmd to change the card to High speed */ 367*91f16700Schasinglulu error = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, SET_EXT_CSD_HS_TIMING); 368*91f16700Schasinglulu if (error != 0) { 369*91f16700Schasinglulu return error; 370*91f16700Schasinglulu } 371*91f16700Schasinglulu error = esdhc_wait_response(mmc, response); 372*91f16700Schasinglulu if (error != 0) { 373*91f16700Schasinglulu return error; 374*91f16700Schasinglulu } 375*91f16700Schasinglulu 376*91f16700Schasinglulu start_time = get_timer_val(0); 377*91f16700Schasinglulu do { 378*91f16700Schasinglulu /* check the status for which error */ 379*91f16700Schasinglulu error = esdhc_send_cmd(mmc, 380*91f16700Schasinglulu CMD_SEND_STATUS, mmc->card.rca << 16); 381*91f16700Schasinglulu if (error != 0) { 382*91f16700Schasinglulu return error; 383*91f16700Schasinglulu } 384*91f16700Schasinglulu 385*91f16700Schasinglulu error = esdhc_wait_response(mmc, response); 386*91f16700Schasinglulu if (error != 0) { 387*91f16700Schasinglulu return error; 388*91f16700Schasinglulu } 389*91f16700Schasinglulu } while (((response[0] & SWITCH_ERROR) != 0) && 390*91f16700Schasinglulu (get_timer_val(start_time) < SD_TIMEOUT)); 391*91f16700Schasinglulu 392*91f16700Schasinglulu /* Check for the present state of card */ 393*91f16700Schasinglulu if ((response[0] & SWITCH_ERROR) != 0) { 394*91f16700Schasinglulu mmc->card.bus_freq = MMC_HS_26MHZ; 395*91f16700Schasinglulu } else { 396*91f16700Schasinglulu mmc->card.bus_freq = MMC_HS_52MHZ; 397*91f16700Schasinglulu } 398*91f16700Schasinglulu 399*91f16700Schasinglulu return 0; 400*91f16700Schasinglulu } 401*91f16700Schasinglulu 402*91f16700Schasinglulu /*************************************************************************** 403*91f16700Schasinglulu * Function : esdhc_set_data_attributes 404*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 405*91f16700Schasinglulu * blkcnt 406*91f16700Schasinglulu * blklen 407*91f16700Schasinglulu * Return : SUCCESS or Error Code 408*91f16700Schasinglulu * Description : Set block attributes and watermark level register 409*91f16700Schasinglulu ***************************************************************************/ 410*91f16700Schasinglulu static int esdhc_set_data_attributes(struct mmc *mmc, uint32_t *dest_ptr, 411*91f16700Schasinglulu uint32_t blkcnt, uint32_t blklen) 412*91f16700Schasinglulu { 413*91f16700Schasinglulu uint32_t val; 414*91f16700Schasinglulu uint64_t start_time; 415*91f16700Schasinglulu uint32_t wml; 416*91f16700Schasinglulu uint32_t wl; 417*91f16700Schasinglulu uint32_t dst = (uint32_t)((uint64_t)(dest_ptr)); 418*91f16700Schasinglulu 419*91f16700Schasinglulu /* set blkattr when no transactions are executing */ 420*91f16700Schasinglulu start_time = get_timer_val(0); 421*91f16700Schasinglulu while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { 422*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA; 423*91f16700Schasinglulu if (val == 0U) { 424*91f16700Schasinglulu break; 425*91f16700Schasinglulu } 426*91f16700Schasinglulu } 427*91f16700Schasinglulu 428*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA; 429*91f16700Schasinglulu if (val != 0U) { 430*91f16700Schasinglulu ERROR("%s: Data line active.Can't set attribute\n", __func__); 431*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 432*91f16700Schasinglulu } 433*91f16700Schasinglulu 434*91f16700Schasinglulu wml = esdhc_in32(&mmc->esdhc_regs->wml); 435*91f16700Schasinglulu wml &= ~(ESDHC_WML_WR_BRST_MASK | ESDHC_WML_RD_BRST_MASK | 436*91f16700Schasinglulu ESDHC_WML_RD_WML_MASK | ESDHC_WML_WR_WML_MASK); 437*91f16700Schasinglulu 438*91f16700Schasinglulu if ((mmc->dma_support != 0) && (dest_ptr != NULL)) { 439*91f16700Schasinglulu /* Set burst length to 128 bytes */ 440*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->wml, 441*91f16700Schasinglulu wml | ESDHC_WML_WR_BRST(BURST_128_BYTES)); 442*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->wml, 443*91f16700Schasinglulu wml | ESDHC_WML_RD_BRST(BURST_128_BYTES)); 444*91f16700Schasinglulu 445*91f16700Schasinglulu /* Set DMA System Destination Address */ 446*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->dsaddr, dst); 447*91f16700Schasinglulu } else { 448*91f16700Schasinglulu wl = (blklen >= BLOCK_LEN_512) ? 449*91f16700Schasinglulu WML_512_BYTES : ((blklen + 3) / 4); 450*91f16700Schasinglulu /* Set 'Read Water Mark Level' register */ 451*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->wml, wml | ESDHC_WML_RD_WML(wl)); 452*91f16700Schasinglulu } 453*91f16700Schasinglulu 454*91f16700Schasinglulu /* Configure block Attributes register */ 455*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->blkattr, 456*91f16700Schasinglulu ESDHC_BLKATTR_BLKCNT(blkcnt) | ESDHC_BLKATTR_BLKSZE(blklen)); 457*91f16700Schasinglulu 458*91f16700Schasinglulu mmc->block_len = blklen; 459*91f16700Schasinglulu 460*91f16700Schasinglulu return 0; 461*91f16700Schasinglulu } 462*91f16700Schasinglulu 463*91f16700Schasinglulu /*************************************************************************** 464*91f16700Schasinglulu * Function : esdhc_read_data_nodma 465*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 466*91f16700Schasinglulu * dest_ptr - Buffer where read data is to be copied 467*91f16700Schasinglulu * len - Length of Data to be read 468*91f16700Schasinglulu * Return : SUCCESS or Error Code 469*91f16700Schasinglulu * Description : Read data from the sdhc buffer without using DMA 470*91f16700Schasinglulu * and using polling mode 471*91f16700Schasinglulu ***************************************************************************/ 472*91f16700Schasinglulu static int esdhc_read_data_nodma(struct mmc *mmc, void *dest_ptr, uint32_t len) 473*91f16700Schasinglulu { 474*91f16700Schasinglulu uint32_t i = 0U; 475*91f16700Schasinglulu uint32_t status; 476*91f16700Schasinglulu uint32_t num_blocks; 477*91f16700Schasinglulu uint32_t *dst = (uint32_t *)dest_ptr; 478*91f16700Schasinglulu uint32_t val; 479*91f16700Schasinglulu uint64_t start_time; 480*91f16700Schasinglulu 481*91f16700Schasinglulu num_blocks = len / mmc->block_len; 482*91f16700Schasinglulu 483*91f16700Schasinglulu while ((num_blocks--) != 0U) { 484*91f16700Schasinglulu 485*91f16700Schasinglulu start_time = get_timer_val(0); 486*91f16700Schasinglulu while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { 487*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->prsstat) & 488*91f16700Schasinglulu ESDHC_PRSSTAT_BREN; 489*91f16700Schasinglulu if (val != 0U) { 490*91f16700Schasinglulu break; 491*91f16700Schasinglulu } 492*91f16700Schasinglulu } 493*91f16700Schasinglulu 494*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->prsstat) 495*91f16700Schasinglulu & ESDHC_PRSSTAT_BREN; 496*91f16700Schasinglulu if (val == 0U) { 497*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 498*91f16700Schasinglulu } 499*91f16700Schasinglulu 500*91f16700Schasinglulu for (i = 0U, status = esdhc_in32(&mmc->esdhc_regs->irqstat); 501*91f16700Schasinglulu i < mmc->block_len / 4; i++, dst++) { 502*91f16700Schasinglulu /* get data from data port */ 503*91f16700Schasinglulu val = mmio_read_32( 504*91f16700Schasinglulu (uintptr_t)&mmc->esdhc_regs->datport); 505*91f16700Schasinglulu esdhc_out32(dst, val); 506*91f16700Schasinglulu /* Increment destination pointer */ 507*91f16700Schasinglulu status = esdhc_in32(&mmc->esdhc_regs->irqstat); 508*91f16700Schasinglulu } 509*91f16700Schasinglulu /* Check whether the interrupt is an DTOE/DCE/DEBE */ 510*91f16700Schasinglulu if ((status & (ESDHC_IRQSTAT_DTOE | ESDHC_IRQSTAT_DCE | 511*91f16700Schasinglulu ESDHC_IRQSTAT_DEBE)) != 0) { 512*91f16700Schasinglulu ERROR("SD read error - DTOE, DCE, DEBE bit set = %x\n", 513*91f16700Schasinglulu status); 514*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 515*91f16700Schasinglulu } 516*91f16700Schasinglulu } 517*91f16700Schasinglulu 518*91f16700Schasinglulu /* Wait for TC */ 519*91f16700Schasinglulu 520*91f16700Schasinglulu start_time = get_timer_val(0); 521*91f16700Schasinglulu while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { 522*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; 523*91f16700Schasinglulu if (val != 0U) { 524*91f16700Schasinglulu break; 525*91f16700Schasinglulu } 526*91f16700Schasinglulu } 527*91f16700Schasinglulu 528*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; 529*91f16700Schasinglulu if (val == 0U) { 530*91f16700Schasinglulu ERROR("SD read timeout: Transfer bit not set in IRQSTAT\n"); 531*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 532*91f16700Schasinglulu } 533*91f16700Schasinglulu 534*91f16700Schasinglulu return 0; 535*91f16700Schasinglulu } 536*91f16700Schasinglulu 537*91f16700Schasinglulu /*************************************************************************** 538*91f16700Schasinglulu * Function : esdhc_write_data_nodma 539*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 540*91f16700Schasinglulu * src_ptr - Buffer where data is copied from 541*91f16700Schasinglulu * len - Length of Data to be written 542*91f16700Schasinglulu * Return : SUCCESS or Error Code 543*91f16700Schasinglulu * Description : Write data to the sdhc buffer without using DMA 544*91f16700Schasinglulu * and using polling mode 545*91f16700Schasinglulu ***************************************************************************/ 546*91f16700Schasinglulu static int esdhc_write_data_nodma(struct mmc *mmc, void *src_ptr, uint32_t len) 547*91f16700Schasinglulu { 548*91f16700Schasinglulu uint32_t i = 0U; 549*91f16700Schasinglulu uint32_t status; 550*91f16700Schasinglulu uint32_t num_blocks; 551*91f16700Schasinglulu uint32_t *src = (uint32_t *)src_ptr; 552*91f16700Schasinglulu uint32_t val; 553*91f16700Schasinglulu uint64_t start_time; 554*91f16700Schasinglulu 555*91f16700Schasinglulu num_blocks = len / mmc->block_len; 556*91f16700Schasinglulu 557*91f16700Schasinglulu while ((num_blocks--) != 0U) { 558*91f16700Schasinglulu start_time = get_timer_val(0); 559*91f16700Schasinglulu while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { 560*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->prsstat) & 561*91f16700Schasinglulu ESDHC_PRSSTAT_BWEN; 562*91f16700Schasinglulu if (val != 0U) { 563*91f16700Schasinglulu break; 564*91f16700Schasinglulu } 565*91f16700Schasinglulu } 566*91f16700Schasinglulu 567*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->prsstat) & 568*91f16700Schasinglulu ESDHC_PRSSTAT_BWEN; 569*91f16700Schasinglulu if (val == 0U) { 570*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 571*91f16700Schasinglulu } 572*91f16700Schasinglulu 573*91f16700Schasinglulu for (i = 0U, status = esdhc_in32(&mmc->esdhc_regs->irqstat); 574*91f16700Schasinglulu i < mmc->block_len / 4; i++, src++) { 575*91f16700Schasinglulu val = esdhc_in32(src); 576*91f16700Schasinglulu /* put data to data port */ 577*91f16700Schasinglulu mmio_write_32((uintptr_t)&mmc->esdhc_regs->datport, 578*91f16700Schasinglulu val); 579*91f16700Schasinglulu /* Increment source pointer */ 580*91f16700Schasinglulu status = esdhc_in32(&mmc->esdhc_regs->irqstat); 581*91f16700Schasinglulu } 582*91f16700Schasinglulu /* Check whether the interrupt is an DTOE/DCE/DEBE */ 583*91f16700Schasinglulu if ((status & (ESDHC_IRQSTAT_DTOE | ESDHC_IRQSTAT_DCE | 584*91f16700Schasinglulu ESDHC_IRQSTAT_DEBE)) != 0) { 585*91f16700Schasinglulu ERROR("SD write error - DTOE, DCE, DEBE bit set = %x\n", 586*91f16700Schasinglulu status); 587*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 588*91f16700Schasinglulu } 589*91f16700Schasinglulu } 590*91f16700Schasinglulu 591*91f16700Schasinglulu /* Wait for TC */ 592*91f16700Schasinglulu start_time = get_timer_val(0); 593*91f16700Schasinglulu while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { 594*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; 595*91f16700Schasinglulu if (val != 0U) { 596*91f16700Schasinglulu break; 597*91f16700Schasinglulu } 598*91f16700Schasinglulu } 599*91f16700Schasinglulu 600*91f16700Schasinglulu val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; 601*91f16700Schasinglulu if (val == 0U) { 602*91f16700Schasinglulu ERROR("SD write timeout: Transfer bit not set in IRQSTAT\n"); 603*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 604*91f16700Schasinglulu } 605*91f16700Schasinglulu 606*91f16700Schasinglulu return 0; 607*91f16700Schasinglulu } 608*91f16700Schasinglulu 609*91f16700Schasinglulu /*************************************************************************** 610*91f16700Schasinglulu * Function : esdhc_read_data_dma 611*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 612*91f16700Schasinglulu * len - Length of Data to be read 613*91f16700Schasinglulu * Return : SUCCESS or Error Code 614*91f16700Schasinglulu * Description : Read data from the sd card using DMA. 615*91f16700Schasinglulu ***************************************************************************/ 616*91f16700Schasinglulu static int esdhc_read_data_dma(struct mmc *mmc, uint32_t len) 617*91f16700Schasinglulu { 618*91f16700Schasinglulu uint32_t status; 619*91f16700Schasinglulu uint32_t tblk; 620*91f16700Schasinglulu uint64_t start_time; 621*91f16700Schasinglulu 622*91f16700Schasinglulu tblk = SD_BLOCK_TIMEOUT * (len / mmc->block_len); 623*91f16700Schasinglulu 624*91f16700Schasinglulu start_time = get_timer_val(0); 625*91f16700Schasinglulu 626*91f16700Schasinglulu /* poll till TC is set */ 627*91f16700Schasinglulu do { 628*91f16700Schasinglulu status = esdhc_in32(&mmc->esdhc_regs->irqstat); 629*91f16700Schasinglulu 630*91f16700Schasinglulu if ((status & (ESDHC_IRQSTAT_DEBE | ESDHC_IRQSTAT_DCE 631*91f16700Schasinglulu | ESDHC_IRQSTAT_DTOE)) != 0) { 632*91f16700Schasinglulu ERROR("SD read error - DTOE, DCE, DEBE bit set = %x\n", 633*91f16700Schasinglulu status); 634*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 635*91f16700Schasinglulu } 636*91f16700Schasinglulu 637*91f16700Schasinglulu if ((status & ESDHC_IRQSTAT_DMAE) != 0) { 638*91f16700Schasinglulu ERROR("SD read error - DMA error = %x\n", status); 639*91f16700Schasinglulu return ERROR_ESDHC_DMA_ERROR; 640*91f16700Schasinglulu } 641*91f16700Schasinglulu 642*91f16700Schasinglulu } while (((status & ESDHC_IRQSTAT_TC) == 0) && 643*91f16700Schasinglulu ((esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA) != 0) && 644*91f16700Schasinglulu (get_timer_val(start_time) < SD_TIMEOUT_HIGH + tblk)); 645*91f16700Schasinglulu 646*91f16700Schasinglulu if (get_timer_val(start_time) > SD_TIMEOUT_HIGH + tblk) { 647*91f16700Schasinglulu ERROR("SD read DMA timeout\n"); 648*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 649*91f16700Schasinglulu } 650*91f16700Schasinglulu 651*91f16700Schasinglulu return 0; 652*91f16700Schasinglulu } 653*91f16700Schasinglulu 654*91f16700Schasinglulu /*************************************************************************** 655*91f16700Schasinglulu * Function : esdhc_write_data_dma 656*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 657*91f16700Schasinglulu * len - Length of Data to be written 658*91f16700Schasinglulu * Return : SUCCESS or Error Code 659*91f16700Schasinglulu * Description : Write data to the sd card using DMA. 660*91f16700Schasinglulu ***************************************************************************/ 661*91f16700Schasinglulu static int esdhc_write_data_dma(struct mmc *mmc, uint32_t len) 662*91f16700Schasinglulu { 663*91f16700Schasinglulu uint32_t status; 664*91f16700Schasinglulu uint32_t tblk; 665*91f16700Schasinglulu uint64_t start_time; 666*91f16700Schasinglulu 667*91f16700Schasinglulu tblk = SD_BLOCK_TIMEOUT * (len / mmc->block_len); 668*91f16700Schasinglulu 669*91f16700Schasinglulu start_time = get_timer_val(0); 670*91f16700Schasinglulu 671*91f16700Schasinglulu /* poll till TC is set */ 672*91f16700Schasinglulu do { 673*91f16700Schasinglulu status = esdhc_in32(&mmc->esdhc_regs->irqstat); 674*91f16700Schasinglulu 675*91f16700Schasinglulu if ((status & (ESDHC_IRQSTAT_DEBE | ESDHC_IRQSTAT_DCE 676*91f16700Schasinglulu | ESDHC_IRQSTAT_DTOE)) != 0) { 677*91f16700Schasinglulu ERROR("SD write error - DTOE, DCE, DEBE bit set = %x\n", 678*91f16700Schasinglulu status); 679*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 680*91f16700Schasinglulu } 681*91f16700Schasinglulu 682*91f16700Schasinglulu if ((status & ESDHC_IRQSTAT_DMAE) != 0) { 683*91f16700Schasinglulu ERROR("SD write error - DMA error = %x\n", status); 684*91f16700Schasinglulu return ERROR_ESDHC_DMA_ERROR; 685*91f16700Schasinglulu } 686*91f16700Schasinglulu } while (((status & ESDHC_IRQSTAT_TC) == 0) && 687*91f16700Schasinglulu ((esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA) != 0) && 688*91f16700Schasinglulu (get_timer_val(start_time) < SD_TIMEOUT_HIGH + tblk)); 689*91f16700Schasinglulu 690*91f16700Schasinglulu if (get_timer_val(start_time) > SD_TIMEOUT_HIGH + tblk) { 691*91f16700Schasinglulu ERROR("SD write DMA timeout\n"); 692*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 693*91f16700Schasinglulu } 694*91f16700Schasinglulu 695*91f16700Schasinglulu return 0; 696*91f16700Schasinglulu } 697*91f16700Schasinglulu 698*91f16700Schasinglulu /*************************************************************************** 699*91f16700Schasinglulu * Function : esdhc_read_data 700*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 701*91f16700Schasinglulu * dest_ptr - Buffer where read data is to be copied 702*91f16700Schasinglulu * len - Length of Data to be read 703*91f16700Schasinglulu * Return : SUCCESS or Error Code 704*91f16700Schasinglulu * Description : Calls esdhc_read_data_nodma and clear interrupt status 705*91f16700Schasinglulu ***************************************************************************/ 706*91f16700Schasinglulu int esdhc_read_data(struct mmc *mmc, void *dest_ptr, uint32_t len) 707*91f16700Schasinglulu { 708*91f16700Schasinglulu int ret; 709*91f16700Schasinglulu 710*91f16700Schasinglulu if (mmc->dma_support && len > 64) { 711*91f16700Schasinglulu ret = esdhc_read_data_dma(mmc, len); 712*91f16700Schasinglulu } else { 713*91f16700Schasinglulu ret = esdhc_read_data_nodma(mmc, dest_ptr, len); 714*91f16700Schasinglulu } 715*91f16700Schasinglulu 716*91f16700Schasinglulu /* clear interrupt status */ 717*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL); 718*91f16700Schasinglulu 719*91f16700Schasinglulu return ret; 720*91f16700Schasinglulu } 721*91f16700Schasinglulu 722*91f16700Schasinglulu /*************************************************************************** 723*91f16700Schasinglulu * Function : esdhc_write_data 724*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 725*91f16700Schasinglulu * src_ptr - Buffer where data is copied from 726*91f16700Schasinglulu * len - Length of Data to be written 727*91f16700Schasinglulu * Return : SUCCESS or Error Code 728*91f16700Schasinglulu * Description : Calls esdhc_write_data_nodma and clear interrupt status 729*91f16700Schasinglulu ***************************************************************************/ 730*91f16700Schasinglulu int esdhc_write_data(struct mmc *mmc, void *src_ptr, uint32_t len) 731*91f16700Schasinglulu { 732*91f16700Schasinglulu int ret; 733*91f16700Schasinglulu 734*91f16700Schasinglulu if (mmc->dma_support && len > 64) { 735*91f16700Schasinglulu ret = esdhc_write_data_dma(mmc, len); 736*91f16700Schasinglulu } else { 737*91f16700Schasinglulu ret = esdhc_write_data_nodma(mmc, src_ptr, len); 738*91f16700Schasinglulu } 739*91f16700Schasinglulu 740*91f16700Schasinglulu /* clear interrupt status */ 741*91f16700Schasinglulu esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL); 742*91f16700Schasinglulu 743*91f16700Schasinglulu return ret; 744*91f16700Schasinglulu } 745*91f16700Schasinglulu 746*91f16700Schasinglulu /*************************************************************************** 747*91f16700Schasinglulu * Function : sd_switch_to_high_freq 748*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 749*91f16700Schasinglulu * Return : SUCCESS or Error Code 750*91f16700Schasinglulu * Description : 1. Send ACMD51 (CMD_SEND_SCR) 751*91f16700Schasinglulu * 2. Read the SCR to check if card supports higher freq 752*91f16700Schasinglulu * 3. check version from SCR 753*91f16700Schasinglulu * 4. If SD 1.0, return (no Switch) freq = 25 MHz. 754*91f16700Schasinglulu * 5. Send CMD6 (CMD_SWITCH_FUNC) with args 0x00FFFFF1 to 755*91f16700Schasinglulu * check the status of switch func 756*91f16700Schasinglulu * 6. Send CMD6 (CMD_SWITCH_FUNC) With args 0x80FFFFF1 to 757*91f16700Schasinglulu * switch to high frequency = 50 Mhz 758*91f16700Schasinglulu ***************************************************************************/ 759*91f16700Schasinglulu static int sd_switch_to_high_freq(struct mmc *mmc) 760*91f16700Schasinglulu { 761*91f16700Schasinglulu int err; 762*91f16700Schasinglulu uint8_t scr[8]; 763*91f16700Schasinglulu uint8_t status[64]; 764*91f16700Schasinglulu uint32_t response[4]; 765*91f16700Schasinglulu uint32_t version; 766*91f16700Schasinglulu uint32_t count; 767*91f16700Schasinglulu uint32_t sd_versions[] = {SD_CARD_VERSION_1_0, SD_CARD_VERSION_1_10, 768*91f16700Schasinglulu SD_CARD_VERSION_2_0}; 769*91f16700Schasinglulu 770*91f16700Schasinglulu mmc->card.bus_freq = SD_SS_25MHZ; 771*91f16700Schasinglulu /* Send Application command */ 772*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_APP_CMD, mmc->card.rca << 16); 773*91f16700Schasinglulu if (err != 0) { 774*91f16700Schasinglulu return err; 775*91f16700Schasinglulu } 776*91f16700Schasinglulu 777*91f16700Schasinglulu err = esdhc_wait_response(mmc, response); 778*91f16700Schasinglulu if (err != 0) { 779*91f16700Schasinglulu return err; 780*91f16700Schasinglulu } 781*91f16700Schasinglulu 782*91f16700Schasinglulu esdhc_set_data_attributes(mmc, NULL, 1, 8); 783*91f16700Schasinglulu /* Read the SCR to find out if this card supports higher speeds */ 784*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_SEND_SCR, mmc->card.rca << 16); 785*91f16700Schasinglulu if (err != 0) { 786*91f16700Schasinglulu return err; 787*91f16700Schasinglulu } 788*91f16700Schasinglulu err = esdhc_wait_response(mmc, response); 789*91f16700Schasinglulu if (err != 0) { 790*91f16700Schasinglulu return err; 791*91f16700Schasinglulu } 792*91f16700Schasinglulu 793*91f16700Schasinglulu /* read 8 bytes of scr data */ 794*91f16700Schasinglulu err = esdhc_read_data(mmc, scr, 8U); 795*91f16700Schasinglulu if (err != 0) { 796*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 797*91f16700Schasinglulu } 798*91f16700Schasinglulu 799*91f16700Schasinglulu /* check version from SCR */ 800*91f16700Schasinglulu version = scr[0] & U(0xF); 801*91f16700Schasinglulu if (version <= 2U) { 802*91f16700Schasinglulu mmc->card.version = sd_versions[version]; 803*91f16700Schasinglulu } else { 804*91f16700Schasinglulu mmc->card.version = SD_CARD_VERSION_2_0; 805*91f16700Schasinglulu } 806*91f16700Schasinglulu 807*91f16700Schasinglulu /* does not support switch func */ 808*91f16700Schasinglulu if (mmc->card.version == SD_CARD_VERSION_1_0) { 809*91f16700Schasinglulu return 0; 810*91f16700Schasinglulu } 811*91f16700Schasinglulu 812*91f16700Schasinglulu /* read 64 bytes of status */ 813*91f16700Schasinglulu esdhc_set_data_attributes(mmc, NULL, 1U, 64U); 814*91f16700Schasinglulu 815*91f16700Schasinglulu /* check the status of switch func */ 816*91f16700Schasinglulu for (count = 0U; count < 4U; count++) { 817*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, 818*91f16700Schasinglulu SD_SWITCH_FUNC_CHECK_MODE); 819*91f16700Schasinglulu if (err != 0) { 820*91f16700Schasinglulu return err; 821*91f16700Schasinglulu } 822*91f16700Schasinglulu err = esdhc_wait_response(mmc, response); 823*91f16700Schasinglulu if (err != 0) { 824*91f16700Schasinglulu return err; 825*91f16700Schasinglulu } 826*91f16700Schasinglulu /* read 64 bytes of scr data */ 827*91f16700Schasinglulu err = esdhc_read_data(mmc, status, 64U); 828*91f16700Schasinglulu if (err != 0) { 829*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 830*91f16700Schasinglulu } 831*91f16700Schasinglulu 832*91f16700Schasinglulu if ((status[29] & SD_SWITCH_FUNC_HIGH_SPEED) == 0) { 833*91f16700Schasinglulu break; 834*91f16700Schasinglulu } 835*91f16700Schasinglulu } 836*91f16700Schasinglulu 837*91f16700Schasinglulu if ((status[13] & SD_SWITCH_FUNC_HIGH_SPEED) == 0) { 838*91f16700Schasinglulu return 0; 839*91f16700Schasinglulu } 840*91f16700Schasinglulu 841*91f16700Schasinglulu /* SWITCH */ 842*91f16700Schasinglulu esdhc_set_data_attributes(mmc, NULL, 1, 64); 843*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, SD_SWITCH_FUNC_SWITCH_MODE); 844*91f16700Schasinglulu if (err != 0) { 845*91f16700Schasinglulu return err; 846*91f16700Schasinglulu } 847*91f16700Schasinglulu err = esdhc_wait_response(mmc, response); 848*91f16700Schasinglulu if (err != 0) { 849*91f16700Schasinglulu return err; 850*91f16700Schasinglulu } 851*91f16700Schasinglulu 852*91f16700Schasinglulu err = esdhc_read_data(mmc, status, 64U); 853*91f16700Schasinglulu if (err != 0) { 854*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 855*91f16700Schasinglulu } 856*91f16700Schasinglulu 857*91f16700Schasinglulu if ((status[16]) == U(0x01)) { 858*91f16700Schasinglulu mmc->card.bus_freq = SD_HS_50MHZ; 859*91f16700Schasinglulu } 860*91f16700Schasinglulu 861*91f16700Schasinglulu return 0; 862*91f16700Schasinglulu } 863*91f16700Schasinglulu 864*91f16700Schasinglulu /*************************************************************************** 865*91f16700Schasinglulu * Function : change_state_to_transfer_state 866*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 867*91f16700Schasinglulu * Return : SUCCESS or Error Code 868*91f16700Schasinglulu * Description : 1. Send CMD7 (CMD_SELECT_CARD) to toggles the card 869*91f16700Schasinglulu * between stand-by and transfer state 870*91f16700Schasinglulu * 2. Send CMD13 (CMD_SEND_STATUS) to check state as 871*91f16700Schasinglulu * Transfer State 872*91f16700Schasinglulu ***************************************************************************/ 873*91f16700Schasinglulu static int change_state_to_transfer_state(struct mmc *mmc) 874*91f16700Schasinglulu { 875*91f16700Schasinglulu int error = 0; 876*91f16700Schasinglulu uint32_t response[4]; 877*91f16700Schasinglulu uint64_t start_time; 878*91f16700Schasinglulu 879*91f16700Schasinglulu /* Command CMD_SELECT_CARD/CMD7 toggles the card between stand-by 880*91f16700Schasinglulu * and transfer states 881*91f16700Schasinglulu */ 882*91f16700Schasinglulu error = esdhc_send_cmd(mmc, CMD_SELECT_CARD, mmc->card.rca << 16); 883*91f16700Schasinglulu if (error != 0) { 884*91f16700Schasinglulu return error; 885*91f16700Schasinglulu } 886*91f16700Schasinglulu error = esdhc_wait_response(mmc, response); 887*91f16700Schasinglulu if (error != 0) { 888*91f16700Schasinglulu return error; 889*91f16700Schasinglulu } 890*91f16700Schasinglulu 891*91f16700Schasinglulu start_time = get_timer_val(0); 892*91f16700Schasinglulu while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { 893*91f16700Schasinglulu /* send CMD13 to check card status */ 894*91f16700Schasinglulu error = esdhc_send_cmd(mmc, 895*91f16700Schasinglulu CMD_SEND_STATUS, mmc->card.rca << 16); 896*91f16700Schasinglulu if (error != 0) { 897*91f16700Schasinglulu return error; 898*91f16700Schasinglulu } 899*91f16700Schasinglulu error = esdhc_wait_response(mmc, response); 900*91f16700Schasinglulu if ((error != 0) || ((response[0] & R1_ERROR) != 0)) { 901*91f16700Schasinglulu return error; 902*91f16700Schasinglulu } 903*91f16700Schasinglulu 904*91f16700Schasinglulu /* Check for the present state of card */ 905*91f16700Schasinglulu if (((response[0] >> 9U) & U(0xF)) == STATE_TRAN) { 906*91f16700Schasinglulu break; 907*91f16700Schasinglulu } 908*91f16700Schasinglulu } 909*91f16700Schasinglulu if (((response[0] >> 9U) & U(0xF)) == STATE_TRAN) { 910*91f16700Schasinglulu return 0; 911*91f16700Schasinglulu } else { 912*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 913*91f16700Schasinglulu } 914*91f16700Schasinglulu } 915*91f16700Schasinglulu 916*91f16700Schasinglulu /*************************************************************************** 917*91f16700Schasinglulu * Function : get_cid_rca_csd 918*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 919*91f16700Schasinglulu * Return : SUCCESS or Error Code 920*91f16700Schasinglulu * Description : 1. Send CMD2 (CMD_ALL_SEND_CID) 921*91f16700Schasinglulu * 2. get RCA for SD cards, set rca for mmc cards 922*91f16700Schasinglulu * Send CMD3 (CMD_SEND_RELATIVE_ADDR) 923*91f16700Schasinglulu * 3. Send CMD9 (CMD_SEND_CSD) 924*91f16700Schasinglulu * 4. Get MMC Version from CSD 925*91f16700Schasinglulu ***************************************************************************/ 926*91f16700Schasinglulu static int get_cid_rca_csd(struct mmc *mmc) 927*91f16700Schasinglulu { 928*91f16700Schasinglulu int err; 929*91f16700Schasinglulu uint32_t version; 930*91f16700Schasinglulu uint32_t response[4]; 931*91f16700Schasinglulu uint32_t mmc_version[] = {MMC_CARD_VERSION_1_2, MMC_CARD_VERSION_1_4, 932*91f16700Schasinglulu MMC_CARD_VERSION_2_X, MMC_CARD_VERSION_3_X, 933*91f16700Schasinglulu MMC_CARD_VERSION_4_X}; 934*91f16700Schasinglulu 935*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_ALL_SEND_CID, 0); 936*91f16700Schasinglulu if (err != 0) { 937*91f16700Schasinglulu return err; 938*91f16700Schasinglulu } 939*91f16700Schasinglulu err = esdhc_wait_response(mmc, response); 940*91f16700Schasinglulu if (err != 0) { 941*91f16700Schasinglulu return err; 942*91f16700Schasinglulu } 943*91f16700Schasinglulu 944*91f16700Schasinglulu /* get RCA for SD cards, set rca for mmc cards */ 945*91f16700Schasinglulu mmc->card.rca = SD_MMC_CARD_RCA; 946*91f16700Schasinglulu 947*91f16700Schasinglulu /* send RCA cmd */ 948*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_SEND_RELATIVE_ADDR, mmc->card.rca << 16); 949*91f16700Schasinglulu if (err != 0) { 950*91f16700Schasinglulu return err; 951*91f16700Schasinglulu } 952*91f16700Schasinglulu err = esdhc_wait_response(mmc, response); 953*91f16700Schasinglulu if (err != 0) { 954*91f16700Schasinglulu return err; 955*91f16700Schasinglulu } 956*91f16700Schasinglulu 957*91f16700Schasinglulu /* for SD, get the the RCA */ 958*91f16700Schasinglulu if (mmc->card.type == SD_CARD) { 959*91f16700Schasinglulu mmc->card.rca = (response[0] >> 16) & 0xFFFF; 960*91f16700Schasinglulu } 961*91f16700Schasinglulu 962*91f16700Schasinglulu /* Get the CSD (card specific data) from card. */ 963*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_SEND_CSD, mmc->card.rca << 16); 964*91f16700Schasinglulu if (err != 0) { 965*91f16700Schasinglulu return err; 966*91f16700Schasinglulu } 967*91f16700Schasinglulu err = esdhc_wait_response(mmc, response); 968*91f16700Schasinglulu if (err != 0) { 969*91f16700Schasinglulu return err; 970*91f16700Schasinglulu } 971*91f16700Schasinglulu 972*91f16700Schasinglulu version = (response[3] >> 18U) & U(0xF); 973*91f16700Schasinglulu if (mmc->card.type == MMC_CARD) { 974*91f16700Schasinglulu if (version <= MMC_CARD_VERSION_4_X) { 975*91f16700Schasinglulu mmc->card.version = mmc_version[version]; 976*91f16700Schasinglulu } else { 977*91f16700Schasinglulu mmc->card.version = MMC_CARD_VERSION_4_X; 978*91f16700Schasinglulu } 979*91f16700Schasinglulu } 980*91f16700Schasinglulu 981*91f16700Schasinglulu mmc->card.block_len = 1 << ((response[2] >> 8) & 0xF); 982*91f16700Schasinglulu 983*91f16700Schasinglulu if (mmc->card.block_len > BLOCK_LEN_512) { 984*91f16700Schasinglulu mmc->card.block_len = BLOCK_LEN_512; 985*91f16700Schasinglulu } 986*91f16700Schasinglulu 987*91f16700Schasinglulu return 0; 988*91f16700Schasinglulu } 989*91f16700Schasinglulu 990*91f16700Schasinglulu /*************************************************************************** 991*91f16700Schasinglulu * Function : identify_mmc_card 992*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 993*91f16700Schasinglulu * Return : SUCCESS or Error Code 994*91f16700Schasinglulu * Description : 1. Send Reset Command 995*91f16700Schasinglulu * 2. Send CMD1 with args to set voltage range and Sector 996*91f16700Schasinglulu * Mode. (Voltage Args = 0xFF8) 997*91f16700Schasinglulu * 3. Check the OCR Response 998*91f16700Schasinglulu ***************************************************************************/ 999*91f16700Schasinglulu static int identify_mmc_card(struct mmc *mmc) 1000*91f16700Schasinglulu { 1001*91f16700Schasinglulu uint64_t start_time; 1002*91f16700Schasinglulu uint32_t resp[4]; 1003*91f16700Schasinglulu int ret; 1004*91f16700Schasinglulu uint32_t args; 1005*91f16700Schasinglulu 1006*91f16700Schasinglulu /* card reset */ 1007*91f16700Schasinglulu ret = esdhc_send_cmd(mmc, CMD_GO_IDLE_STATE, 0U); 1008*91f16700Schasinglulu if (ret != 0) { 1009*91f16700Schasinglulu return ret; 1010*91f16700Schasinglulu } 1011*91f16700Schasinglulu ret = esdhc_wait_response(mmc, resp); 1012*91f16700Schasinglulu if (ret != 0) { 1013*91f16700Schasinglulu return ret; 1014*91f16700Schasinglulu } 1015*91f16700Schasinglulu 1016*91f16700Schasinglulu /* Send CMD1 to get the ocr value repeatedly till the card */ 1017*91f16700Schasinglulu /* busy is clear. timeout = 20sec */ 1018*91f16700Schasinglulu 1019*91f16700Schasinglulu start_time = get_timer_val(0); 1020*91f16700Schasinglulu do { 1021*91f16700Schasinglulu /* set the bits for the voltage ranges supported by host */ 1022*91f16700Schasinglulu args = mmc->voltages_caps | MMC_OCR_SECTOR_MODE; 1023*91f16700Schasinglulu ret = esdhc_send_cmd(mmc, CMD_MMC_SEND_OP_COND, args); 1024*91f16700Schasinglulu if (ret != 0) { 1025*91f16700Schasinglulu return ret; 1026*91f16700Schasinglulu } 1027*91f16700Schasinglulu ret = esdhc_wait_response(mmc, resp); 1028*91f16700Schasinglulu if (ret != 0) { 1029*91f16700Schasinglulu return ERROR_ESDHC_UNUSABLE_CARD; 1030*91f16700Schasinglulu } 1031*91f16700Schasinglulu } while (((resp[0] & MMC_OCR_BUSY) == 0U) && 1032*91f16700Schasinglulu (get_timer_val(start_time) < SD_TIMEOUT_HIGH)); 1033*91f16700Schasinglulu 1034*91f16700Schasinglulu if (get_timer_val(start_time) > SD_TIMEOUT_HIGH) { 1035*91f16700Schasinglulu return ERROR_ESDHC_UNUSABLE_CARD; 1036*91f16700Schasinglulu } 1037*91f16700Schasinglulu 1038*91f16700Schasinglulu if ((resp[0] & MMC_OCR_CCS) == MMC_OCR_CCS) { 1039*91f16700Schasinglulu mmc->card.is_high_capacity = 1; 1040*91f16700Schasinglulu } 1041*91f16700Schasinglulu 1042*91f16700Schasinglulu return MMC_CARD; 1043*91f16700Schasinglulu } 1044*91f16700Schasinglulu 1045*91f16700Schasinglulu /*************************************************************************** 1046*91f16700Schasinglulu * Function : check_for_sd_card 1047*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 1048*91f16700Schasinglulu * Return : SUCCESS or Error Code 1049*91f16700Schasinglulu * Description : 1. Send Reset Command 1050*91f16700Schasinglulu * 2. Send CMD8 with pattern 0xAA (to check for SD 2.0) 1051*91f16700Schasinglulu * 3. Send ACMD41 with args to set voltage range and HCS 1052*91f16700Schasinglulu * HCS is set only for SD Card > 2.0 1053*91f16700Schasinglulu * Voltage Caps = 0xFF8 1054*91f16700Schasinglulu * 4. Check the OCR Response 1055*91f16700Schasinglulu ***************************************************************************/ 1056*91f16700Schasinglulu static int check_for_sd_card(struct mmc *mmc) 1057*91f16700Schasinglulu { 1058*91f16700Schasinglulu uint64_t start_time; 1059*91f16700Schasinglulu uint32_t args; 1060*91f16700Schasinglulu int ret; 1061*91f16700Schasinglulu uint32_t resp[4]; 1062*91f16700Schasinglulu 1063*91f16700Schasinglulu /* Send reset command */ 1064*91f16700Schasinglulu ret = esdhc_send_cmd(mmc, CMD_GO_IDLE_STATE, 0U); 1065*91f16700Schasinglulu if (ret != 0) { 1066*91f16700Schasinglulu return ret; 1067*91f16700Schasinglulu } 1068*91f16700Schasinglulu ret = esdhc_wait_response(mmc, resp); 1069*91f16700Schasinglulu if (ret != 0) { 1070*91f16700Schasinglulu return ret; 1071*91f16700Schasinglulu } 1072*91f16700Schasinglulu 1073*91f16700Schasinglulu /* send CMD8 with pattern 0xAA */ 1074*91f16700Schasinglulu args = MMC_VDD_HIGH_VOLTAGE | 0xAA; 1075*91f16700Schasinglulu ret = esdhc_send_cmd(mmc, CMD_SEND_IF_COND, args); 1076*91f16700Schasinglulu if (ret != 0) { 1077*91f16700Schasinglulu return ret; 1078*91f16700Schasinglulu } 1079*91f16700Schasinglulu ret = esdhc_wait_response(mmc, resp); 1080*91f16700Schasinglulu if (ret == RESP_TIMEOUT) { /* sd ver 1.x or not sd */ 1081*91f16700Schasinglulu mmc->card.is_high_capacity = 0; 1082*91f16700Schasinglulu } else if ((resp[0] & U(0xFF)) == U(0xAA)) { /* ver 2.0 or later */ 1083*91f16700Schasinglulu mmc->card.version = SD_CARD_VERSION_2_0; 1084*91f16700Schasinglulu } else { 1085*91f16700Schasinglulu return NOT_SD_CARD; 1086*91f16700Schasinglulu } 1087*91f16700Schasinglulu /* Send Application command-55 to get the ocr value repeatedly till 1088*91f16700Schasinglulu * the card busy is clear. timeout = 20sec 1089*91f16700Schasinglulu */ 1090*91f16700Schasinglulu 1091*91f16700Schasinglulu start_time = get_timer_val(0); 1092*91f16700Schasinglulu do { 1093*91f16700Schasinglulu ret = esdhc_send_cmd(mmc, CMD_APP_CMD, 0U); 1094*91f16700Schasinglulu if (ret != 0) { 1095*91f16700Schasinglulu return ret; 1096*91f16700Schasinglulu } 1097*91f16700Schasinglulu ret = esdhc_wait_response(mmc, resp); 1098*91f16700Schasinglulu if (ret == COMMAND_ERROR) { 1099*91f16700Schasinglulu return ERROR_ESDHC_UNUSABLE_CARD; 1100*91f16700Schasinglulu } 1101*91f16700Schasinglulu 1102*91f16700Schasinglulu /* set the bits for the voltage ranges supported by host */ 1103*91f16700Schasinglulu args = mmc->voltages_caps; 1104*91f16700Schasinglulu if (mmc->card.version == SD_CARD_VERSION_2_0) { 1105*91f16700Schasinglulu args |= SD_OCR_HCS; 1106*91f16700Schasinglulu } 1107*91f16700Schasinglulu 1108*91f16700Schasinglulu /* Send ACMD41 to set voltage range */ 1109*91f16700Schasinglulu ret = esdhc_send_cmd(mmc, CMD_SD_SEND_OP_COND, args); 1110*91f16700Schasinglulu if (ret != 0) { 1111*91f16700Schasinglulu return ret; 1112*91f16700Schasinglulu } 1113*91f16700Schasinglulu ret = esdhc_wait_response(mmc, resp); 1114*91f16700Schasinglulu if (ret == COMMAND_ERROR) { 1115*91f16700Schasinglulu return ERROR_ESDHC_UNUSABLE_CARD; 1116*91f16700Schasinglulu } else if (ret == RESP_TIMEOUT) { 1117*91f16700Schasinglulu return NOT_SD_CARD; 1118*91f16700Schasinglulu } 1119*91f16700Schasinglulu } while (((resp[0] & MMC_OCR_BUSY) == 0U) && 1120*91f16700Schasinglulu (get_timer_val(start_time) < SD_TIMEOUT_HIGH)); 1121*91f16700Schasinglulu 1122*91f16700Schasinglulu if (get_timer_val(start_time) > SD_TIMEOUT_HIGH) { 1123*91f16700Schasinglulu INFO("SD_TIMEOUT_HIGH\n"); 1124*91f16700Schasinglulu return ERROR_ESDHC_UNUSABLE_CARD; 1125*91f16700Schasinglulu } 1126*91f16700Schasinglulu 1127*91f16700Schasinglulu /* bit set in card capacity status */ 1128*91f16700Schasinglulu if ((resp[0] & MMC_OCR_CCS) == MMC_OCR_CCS) { 1129*91f16700Schasinglulu mmc->card.is_high_capacity = 1; 1130*91f16700Schasinglulu } 1131*91f16700Schasinglulu 1132*91f16700Schasinglulu return SD_CARD; 1133*91f16700Schasinglulu } 1134*91f16700Schasinglulu 1135*91f16700Schasinglulu /*************************************************************************** 1136*91f16700Schasinglulu * Function : esdhc_emmc_init 1137*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 1138*91f16700Schasinglulu * src_emmc - Flag to Indicate SRC as emmc 1139*91f16700Schasinglulu * Return : SUCCESS or Error Code (< 0) 1140*91f16700Schasinglulu * Description : Base Function called from sd_mmc_init or emmc_init 1141*91f16700Schasinglulu ***************************************************************************/ 1142*91f16700Schasinglulu int esdhc_emmc_init(struct mmc *mmc, bool card_detect) 1143*91f16700Schasinglulu { 1144*91f16700Schasinglulu int error = 0; 1145*91f16700Schasinglulu int ret = 0; 1146*91f16700Schasinglulu 1147*91f16700Schasinglulu error = esdhc_init(mmc, card_detect); 1148*91f16700Schasinglulu if (error != 0) { 1149*91f16700Schasinglulu return error; 1150*91f16700Schasinglulu } 1151*91f16700Schasinglulu 1152*91f16700Schasinglulu mmc->card.bus_freq = CARD_IDENTIFICATION_FREQ; 1153*91f16700Schasinglulu mmc->card.rca = 0; 1154*91f16700Schasinglulu mmc->card.is_high_capacity = 0; 1155*91f16700Schasinglulu mmc->card.type = ERROR_ESDHC_UNUSABLE_CARD; 1156*91f16700Schasinglulu 1157*91f16700Schasinglulu /* Set Voltage caps as FF8 i.e all supported */ 1158*91f16700Schasinglulu /* high voltage bits 2.7 - 3.6 */ 1159*91f16700Schasinglulu mmc->voltages_caps = MMC_OCR_VDD_FF8; 1160*91f16700Schasinglulu 1161*91f16700Schasinglulu #ifdef NXP_SD_DMA_CAPABILITY 1162*91f16700Schasinglulu /* Getting host DMA capabilities. */ 1163*91f16700Schasinglulu mmc->dma_support = esdhc_in32(&mmc->esdhc_regs->hostcapblt) & 1164*91f16700Schasinglulu ESDHC_HOSTCAPBLT_DMAS; 1165*91f16700Schasinglulu #else 1166*91f16700Schasinglulu mmc->dma_support = 0; 1167*91f16700Schasinglulu #endif 1168*91f16700Schasinglulu 1169*91f16700Schasinglulu ret = NOT_SD_CARD; 1170*91f16700Schasinglulu /* If SRC is not EMMC, check for SD or MMC */ 1171*91f16700Schasinglulu ret = check_for_sd_card(mmc); 1172*91f16700Schasinglulu switch (ret) { 1173*91f16700Schasinglulu case SD_CARD: 1174*91f16700Schasinglulu mmc->card.type = SD_CARD; 1175*91f16700Schasinglulu break; 1176*91f16700Schasinglulu 1177*91f16700Schasinglulu case NOT_SD_CARD: 1178*91f16700Schasinglulu /* try for MMC card */ 1179*91f16700Schasinglulu if (identify_mmc_card(mmc) == MMC_CARD) { 1180*91f16700Schasinglulu mmc->card.type = MMC_CARD; 1181*91f16700Schasinglulu } else { 1182*91f16700Schasinglulu return ERROR_ESDHC_UNUSABLE_CARD; 1183*91f16700Schasinglulu } 1184*91f16700Schasinglulu break; 1185*91f16700Schasinglulu 1186*91f16700Schasinglulu default: 1187*91f16700Schasinglulu return ERROR_ESDHC_UNUSABLE_CARD; 1188*91f16700Schasinglulu } 1189*91f16700Schasinglulu 1190*91f16700Schasinglulu /* get CID, RCA and CSD. For MMC, set the rca */ 1191*91f16700Schasinglulu error = get_cid_rca_csd(mmc); 1192*91f16700Schasinglulu if (error != 0) { 1193*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 1194*91f16700Schasinglulu } 1195*91f16700Schasinglulu 1196*91f16700Schasinglulu /* change state to Transfer mode */ 1197*91f16700Schasinglulu error = change_state_to_transfer_state(mmc); 1198*91f16700Schasinglulu if (error != 0) { 1199*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 1200*91f16700Schasinglulu } 1201*91f16700Schasinglulu 1202*91f16700Schasinglulu /* change to high frequency if supported */ 1203*91f16700Schasinglulu if (mmc->card.type == SD_CARD) { 1204*91f16700Schasinglulu error = sd_switch_to_high_freq(mmc); 1205*91f16700Schasinglulu } else { 1206*91f16700Schasinglulu error = mmc_switch_to_high_frquency(mmc); 1207*91f16700Schasinglulu } 1208*91f16700Schasinglulu if (error != 0) { 1209*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 1210*91f16700Schasinglulu } 1211*91f16700Schasinglulu 1212*91f16700Schasinglulu /* mmc: 20000000, 26000000, 52000000 */ 1213*91f16700Schasinglulu /* sd: 25000000, 50000000 */ 1214*91f16700Schasinglulu set_speed(mmc, mmc->card.bus_freq); 1215*91f16700Schasinglulu 1216*91f16700Schasinglulu INFO("init done:\n"); 1217*91f16700Schasinglulu return 0; 1218*91f16700Schasinglulu } 1219*91f16700Schasinglulu 1220*91f16700Schasinglulu /*************************************************************************** 1221*91f16700Schasinglulu * Function : sd_mmc_init 1222*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 1223*91f16700Schasinglulu * Return : SUCCESS or Error Code 1224*91f16700Schasinglulu * Description : Base Function called via hal_init for SD/MMC 1225*91f16700Schasinglulu * initialization 1226*91f16700Schasinglulu ***************************************************************************/ 1227*91f16700Schasinglulu int sd_mmc_init(uintptr_t nxp_esdhc_addr, bool card_detect) 1228*91f16700Schasinglulu { 1229*91f16700Schasinglulu struct mmc *mmc = NULL; 1230*91f16700Schasinglulu int ret; 1231*91f16700Schasinglulu 1232*91f16700Schasinglulu mmc = &mmc_drv_data; 1233*91f16700Schasinglulu memset(mmc, 0, sizeof(struct mmc)); 1234*91f16700Schasinglulu mmc->esdhc_regs = (struct esdhc_regs *)nxp_esdhc_addr; 1235*91f16700Schasinglulu 1236*91f16700Schasinglulu INFO("esdhc_emmc_init\n"); 1237*91f16700Schasinglulu ret = esdhc_emmc_init(mmc, card_detect); 1238*91f16700Schasinglulu return ret; 1239*91f16700Schasinglulu } 1240*91f16700Schasinglulu 1241*91f16700Schasinglulu /*************************************************************************** 1242*91f16700Schasinglulu * Function : esdhc_read_block 1243*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 1244*91f16700Schasinglulu * dst - Destination Pointer 1245*91f16700Schasinglulu * block - Block Number 1246*91f16700Schasinglulu * Return : SUCCESS or Error Code 1247*91f16700Schasinglulu * Description : Read a Single block to Destination Pointer 1248*91f16700Schasinglulu * 1. Send CMD16 (CMD_SET_BLOCKLEN) with args as blocklen 1249*91f16700Schasinglulu * 2. Send CMD17 (CMD_READ_SINGLE_BLOCK) with args offset 1250*91f16700Schasinglulu ***************************************************************************/ 1251*91f16700Schasinglulu static int esdhc_read_block(struct mmc *mmc, void *dst, uint32_t block) 1252*91f16700Schasinglulu { 1253*91f16700Schasinglulu uint32_t offset; 1254*91f16700Schasinglulu int err; 1255*91f16700Schasinglulu 1256*91f16700Schasinglulu /* send cmd16 to set the block size. */ 1257*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_SET_BLOCKLEN, mmc->card.block_len); 1258*91f16700Schasinglulu if (err != 0) { 1259*91f16700Schasinglulu return err; 1260*91f16700Schasinglulu } 1261*91f16700Schasinglulu err = esdhc_wait_response(mmc, NULL); 1262*91f16700Schasinglulu if (err != 0) { 1263*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 1264*91f16700Schasinglulu } 1265*91f16700Schasinglulu 1266*91f16700Schasinglulu if (mmc->card.is_high_capacity != 0) { 1267*91f16700Schasinglulu offset = block; 1268*91f16700Schasinglulu } else { 1269*91f16700Schasinglulu offset = block * mmc->card.block_len; 1270*91f16700Schasinglulu } 1271*91f16700Schasinglulu 1272*91f16700Schasinglulu esdhc_set_data_attributes(mmc, dst, 1, mmc->card.block_len); 1273*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_READ_SINGLE_BLOCK, offset); 1274*91f16700Schasinglulu if (err != 0) { 1275*91f16700Schasinglulu return err; 1276*91f16700Schasinglulu } 1277*91f16700Schasinglulu err = esdhc_wait_response(mmc, NULL); 1278*91f16700Schasinglulu if (err != 0) { 1279*91f16700Schasinglulu return err; 1280*91f16700Schasinglulu } 1281*91f16700Schasinglulu 1282*91f16700Schasinglulu err = esdhc_read_data(mmc, dst, mmc->card.block_len); 1283*91f16700Schasinglulu 1284*91f16700Schasinglulu return err; 1285*91f16700Schasinglulu } 1286*91f16700Schasinglulu 1287*91f16700Schasinglulu /*************************************************************************** 1288*91f16700Schasinglulu * Function : esdhc_write_block 1289*91f16700Schasinglulu * Arguments : mmc - Pointer to mmc struct 1290*91f16700Schasinglulu * src - Source Pointer 1291*91f16700Schasinglulu * block - Block Number 1292*91f16700Schasinglulu * Return : SUCCESS or Error Code 1293*91f16700Schasinglulu * Description : Write a Single block from Source Pointer 1294*91f16700Schasinglulu * 1. Send CMD16 (CMD_SET_BLOCKLEN) with args as blocklen 1295*91f16700Schasinglulu * 2. Send CMD24 (CMD_WRITE_SINGLE_BLOCK) with args offset 1296*91f16700Schasinglulu ***************************************************************************/ 1297*91f16700Schasinglulu static int esdhc_write_block(struct mmc *mmc, void *src, uint32_t block) 1298*91f16700Schasinglulu { 1299*91f16700Schasinglulu uint32_t offset; 1300*91f16700Schasinglulu int err; 1301*91f16700Schasinglulu 1302*91f16700Schasinglulu /* send cmd16 to set the block size. */ 1303*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_SET_BLOCKLEN, mmc->card.block_len); 1304*91f16700Schasinglulu if (err != 0) { 1305*91f16700Schasinglulu return err; 1306*91f16700Schasinglulu } 1307*91f16700Schasinglulu err = esdhc_wait_response(mmc, NULL); 1308*91f16700Schasinglulu if (err != 0) { 1309*91f16700Schasinglulu return ERROR_ESDHC_COMMUNICATION_ERROR; 1310*91f16700Schasinglulu } 1311*91f16700Schasinglulu 1312*91f16700Schasinglulu if (mmc->card.is_high_capacity != 0) { 1313*91f16700Schasinglulu offset = block; 1314*91f16700Schasinglulu } else { 1315*91f16700Schasinglulu offset = block * mmc->card.block_len; 1316*91f16700Schasinglulu } 1317*91f16700Schasinglulu 1318*91f16700Schasinglulu esdhc_set_data_attributes(mmc, src, 1, mmc->card.block_len); 1319*91f16700Schasinglulu err = esdhc_send_cmd(mmc, CMD_WRITE_SINGLE_BLOCK, offset); 1320*91f16700Schasinglulu if (err != 0) { 1321*91f16700Schasinglulu return err; 1322*91f16700Schasinglulu } 1323*91f16700Schasinglulu err = esdhc_wait_response(mmc, NULL); 1324*91f16700Schasinglulu if (err != 0) { 1325*91f16700Schasinglulu return err; 1326*91f16700Schasinglulu } 1327*91f16700Schasinglulu 1328*91f16700Schasinglulu err = esdhc_write_data(mmc, src, mmc->card.block_len); 1329*91f16700Schasinglulu 1330*91f16700Schasinglulu return err; 1331*91f16700Schasinglulu } 1332*91f16700Schasinglulu 1333*91f16700Schasinglulu /*************************************************************************** 1334*91f16700Schasinglulu * Function : esdhc_read 1335*91f16700Schasinglulu * Arguments : src_offset - offset on sd/mmc to read from. Should be block 1336*91f16700Schasinglulu * size aligned 1337*91f16700Schasinglulu * dst - Destination Pointer 1338*91f16700Schasinglulu * size - Length of Data ( Multiple of block size) 1339*91f16700Schasinglulu * Return : SUCCESS or Error Code 1340*91f16700Schasinglulu * Description : Calls esdhc_read_block repeatedly for reading the 1341*91f16700Schasinglulu * data. 1342*91f16700Schasinglulu ***************************************************************************/ 1343*91f16700Schasinglulu int esdhc_read(struct mmc *mmc, uint32_t src_offset, uintptr_t dst, size_t size) 1344*91f16700Schasinglulu { 1345*91f16700Schasinglulu int error = 0; 1346*91f16700Schasinglulu uint32_t blk, num_blocks; 1347*91f16700Schasinglulu uint8_t *buff = (uint8_t *)dst; 1348*91f16700Schasinglulu 1349*91f16700Schasinglulu #ifdef NXP_SD_DEBUG 1350*91f16700Schasinglulu INFO("sd mmc read\n"); 1351*91f16700Schasinglulu INFO("src = %x, dst = %lxsize = %lu\n", src_offset, dst, size); 1352*91f16700Schasinglulu #endif 1353*91f16700Schasinglulu 1354*91f16700Schasinglulu /* check for size */ 1355*91f16700Schasinglulu if (size == 0) { 1356*91f16700Schasinglulu return 0; 1357*91f16700Schasinglulu } 1358*91f16700Schasinglulu 1359*91f16700Schasinglulu if ((size % mmc->card.block_len) != 0) { 1360*91f16700Schasinglulu ERROR("Size is not block aligned\n"); 1361*91f16700Schasinglulu return -1; 1362*91f16700Schasinglulu } 1363*91f16700Schasinglulu 1364*91f16700Schasinglulu if ((src_offset % mmc->card.block_len) != 0) { 1365*91f16700Schasinglulu ERROR("Size is not block aligned\n"); 1366*91f16700Schasinglulu return -1; 1367*91f16700Schasinglulu } 1368*91f16700Schasinglulu 1369*91f16700Schasinglulu /* start block */ 1370*91f16700Schasinglulu blk = src_offset / mmc->card.block_len; 1371*91f16700Schasinglulu #ifdef NXP_SD_DEBUG 1372*91f16700Schasinglulu INFO("blk = %x\n", blk); 1373*91f16700Schasinglulu #endif 1374*91f16700Schasinglulu 1375*91f16700Schasinglulu /* Number of blocks to be read */ 1376*91f16700Schasinglulu num_blocks = size / mmc->card.block_len; 1377*91f16700Schasinglulu 1378*91f16700Schasinglulu while (num_blocks) { 1379*91f16700Schasinglulu error = esdhc_read_block(mmc, buff, blk); 1380*91f16700Schasinglulu if (error != 0) { 1381*91f16700Schasinglulu ERROR("Read error = %x\n", error); 1382*91f16700Schasinglulu return error; 1383*91f16700Schasinglulu } 1384*91f16700Schasinglulu 1385*91f16700Schasinglulu buff = buff + mmc->card.block_len; 1386*91f16700Schasinglulu blk++; 1387*91f16700Schasinglulu num_blocks--; 1388*91f16700Schasinglulu } 1389*91f16700Schasinglulu 1390*91f16700Schasinglulu INFO("sd-mmc read done.\n"); 1391*91f16700Schasinglulu return error; 1392*91f16700Schasinglulu } 1393*91f16700Schasinglulu 1394*91f16700Schasinglulu /*************************************************************************** 1395*91f16700Schasinglulu * Function : esdhc_write 1396*91f16700Schasinglulu * Arguments : src - Source Pointer 1397*91f16700Schasinglulu * dst_offset - offset on sd/mmc to write to. Should be block 1398*91f16700Schasinglulu * size aligned 1399*91f16700Schasinglulu * size - Length of Data (Multiple of block size) 1400*91f16700Schasinglulu * Return : SUCCESS or Error Code 1401*91f16700Schasinglulu * Description : Calls esdhc_write_block repeatedly for writing the 1402*91f16700Schasinglulu * data. 1403*91f16700Schasinglulu ***************************************************************************/ 1404*91f16700Schasinglulu int esdhc_write(struct mmc *mmc, uintptr_t src, uint32_t dst_offset, 1405*91f16700Schasinglulu size_t size) 1406*91f16700Schasinglulu { 1407*91f16700Schasinglulu int error = 0; 1408*91f16700Schasinglulu uint32_t blk, num_blocks; 1409*91f16700Schasinglulu uint8_t *buff = (uint8_t *)src; 1410*91f16700Schasinglulu 1411*91f16700Schasinglulu #ifdef NXP_SD_DEBUG 1412*91f16700Schasinglulu INFO("sd mmc write\n"); 1413*91f16700Schasinglulu INFO("src = %x, dst = %lxsize = %lu\n", src, dst_offset, size); 1414*91f16700Schasinglulu #endif 1415*91f16700Schasinglulu 1416*91f16700Schasinglulu /* check for size */ 1417*91f16700Schasinglulu if (size == 0) { 1418*91f16700Schasinglulu return 0; 1419*91f16700Schasinglulu } 1420*91f16700Schasinglulu 1421*91f16700Schasinglulu if ((size % mmc->card.block_len) != 0) { 1422*91f16700Schasinglulu ERROR("Size is not block aligned\n"); 1423*91f16700Schasinglulu return -1; 1424*91f16700Schasinglulu } 1425*91f16700Schasinglulu 1426*91f16700Schasinglulu if ((dst_offset % mmc->card.block_len) != 0) { 1427*91f16700Schasinglulu ERROR("Size is not block aligned\n"); 1428*91f16700Schasinglulu return -1; 1429*91f16700Schasinglulu } 1430*91f16700Schasinglulu 1431*91f16700Schasinglulu /* start block */ 1432*91f16700Schasinglulu blk = dst_offset / mmc->card.block_len; 1433*91f16700Schasinglulu #ifdef NXP_SD_DEBUG 1434*91f16700Schasinglulu INFO("blk = %x\n", blk); 1435*91f16700Schasinglulu #endif 1436*91f16700Schasinglulu 1437*91f16700Schasinglulu /* Number of blocks to be written */ 1438*91f16700Schasinglulu num_blocks = size / mmc->card.block_len; 1439*91f16700Schasinglulu 1440*91f16700Schasinglulu while (num_blocks != 0U) { 1441*91f16700Schasinglulu error = esdhc_write_block(mmc, buff, blk); 1442*91f16700Schasinglulu if (error != 0U) { 1443*91f16700Schasinglulu ERROR("Write error = %x\n", error); 1444*91f16700Schasinglulu return error; 1445*91f16700Schasinglulu } 1446*91f16700Schasinglulu 1447*91f16700Schasinglulu buff = buff + mmc->card.block_len; 1448*91f16700Schasinglulu blk++; 1449*91f16700Schasinglulu num_blocks--; 1450*91f16700Schasinglulu } 1451*91f16700Schasinglulu 1452*91f16700Schasinglulu INFO("sd-mmc write done.\n"); 1453*91f16700Schasinglulu return error; 1454*91f16700Schasinglulu } 1455*91f16700Schasinglulu 1456*91f16700Schasinglulu static size_t ls_sd_emmc_read(int lba, uintptr_t buf, size_t size) 1457*91f16700Schasinglulu { 1458*91f16700Schasinglulu struct mmc *mmc = NULL; 1459*91f16700Schasinglulu int ret; 1460*91f16700Schasinglulu 1461*91f16700Schasinglulu mmc = &mmc_drv_data; 1462*91f16700Schasinglulu lba *= BLOCK_LEN_512; 1463*91f16700Schasinglulu ret = esdhc_read(mmc, lba, buf, size); 1464*91f16700Schasinglulu return ret ? 0 : size; 1465*91f16700Schasinglulu } 1466*91f16700Schasinglulu 1467*91f16700Schasinglulu static struct io_block_dev_spec ls_emmc_dev_spec = { 1468*91f16700Schasinglulu .buffer = { 1469*91f16700Schasinglulu .offset = 0, 1470*91f16700Schasinglulu .length = 0, 1471*91f16700Schasinglulu }, 1472*91f16700Schasinglulu .ops = { 1473*91f16700Schasinglulu .read = ls_sd_emmc_read, 1474*91f16700Schasinglulu }, 1475*91f16700Schasinglulu .block_size = BLOCK_LEN_512, 1476*91f16700Schasinglulu }; 1477*91f16700Schasinglulu 1478*91f16700Schasinglulu int sd_emmc_init(uintptr_t *block_dev_spec, 1479*91f16700Schasinglulu uintptr_t nxp_esdhc_addr, 1480*91f16700Schasinglulu size_t nxp_sd_block_offset, 1481*91f16700Schasinglulu size_t nxp_sd_block_size, 1482*91f16700Schasinglulu bool card_detect) 1483*91f16700Schasinglulu { 1484*91f16700Schasinglulu int ret; 1485*91f16700Schasinglulu 1486*91f16700Schasinglulu ret = sd_mmc_init(nxp_esdhc_addr, card_detect); 1487*91f16700Schasinglulu if (ret != 0) { 1488*91f16700Schasinglulu return ret; 1489*91f16700Schasinglulu } 1490*91f16700Schasinglulu 1491*91f16700Schasinglulu ls_emmc_dev_spec.buffer.offset = nxp_sd_block_offset; 1492*91f16700Schasinglulu ls_emmc_dev_spec.buffer.length = nxp_sd_block_size; 1493*91f16700Schasinglulu *block_dev_spec = (uintptr_t)&ls_emmc_dev_spec; 1494*91f16700Schasinglulu 1495*91f16700Schasinglulu return 0; 1496*91f16700Schasinglulu } 1497