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