1*ad71d45eSYann Gautier /* 2*ad71d45eSYann Gautier * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3*ad71d45eSYann Gautier * 4*ad71d45eSYann Gautier * SPDX-License-Identifier: BSD-3-Clause 5*ad71d45eSYann Gautier */ 6*ad71d45eSYann Gautier 7*ad71d45eSYann Gautier /* Define a simple and generic interface to access eMMC and SD-card devices. */ 8*ad71d45eSYann Gautier 9*ad71d45eSYann Gautier #include <arch_helpers.h> 10*ad71d45eSYann Gautier #include <assert.h> 11*ad71d45eSYann Gautier #include <debug.h> 12*ad71d45eSYann Gautier #include <errno.h> 13*ad71d45eSYann Gautier #include <mmc.h> 14*ad71d45eSYann Gautier #include <stdbool.h> 15*ad71d45eSYann Gautier #include <string.h> 16*ad71d45eSYann Gautier #include <utils.h> 17*ad71d45eSYann Gautier 18*ad71d45eSYann Gautier #define MMC_DEFAULT_MAX_RETRIES 5 19*ad71d45eSYann Gautier #define SEND_OP_COND_MAX_RETRIES 100 20*ad71d45eSYann Gautier 21*ad71d45eSYann Gautier #define MULT_BY_512K_SHIFT 19 22*ad71d45eSYann Gautier 23*ad71d45eSYann Gautier static const struct mmc_ops *ops; 24*ad71d45eSYann Gautier static unsigned int mmc_ocr_value; 25*ad71d45eSYann Gautier static struct mmc_csd_emmc mmc_csd; 26*ad71d45eSYann Gautier static unsigned char mmc_ext_csd[512] __aligned(4); 27*ad71d45eSYann Gautier static unsigned int mmc_flags; 28*ad71d45eSYann Gautier static struct mmc_device_info *mmc_dev_info; 29*ad71d45eSYann Gautier static unsigned int rca; 30*ad71d45eSYann Gautier 31*ad71d45eSYann Gautier static const unsigned char tran_speed_base[16] = { 32*ad71d45eSYann Gautier 0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80 33*ad71d45eSYann Gautier }; 34*ad71d45eSYann Gautier 35*ad71d45eSYann Gautier static const unsigned char sd_tran_speed_base[16] = { 36*ad71d45eSYann Gautier 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 37*ad71d45eSYann Gautier }; 38*ad71d45eSYann Gautier 39*ad71d45eSYann Gautier static bool is_cmd23_enabled(void) 40*ad71d45eSYann Gautier { 41*ad71d45eSYann Gautier return ((mmc_flags & MMC_FLAG_CMD23) != 0U); 42*ad71d45eSYann Gautier } 43*ad71d45eSYann Gautier 44*ad71d45eSYann Gautier static int mmc_send_cmd(unsigned int idx, unsigned int arg, 45*ad71d45eSYann Gautier unsigned int r_type, unsigned int *r_data) 46*ad71d45eSYann Gautier { 47*ad71d45eSYann Gautier struct mmc_cmd cmd; 48*ad71d45eSYann Gautier int ret; 49*ad71d45eSYann Gautier 50*ad71d45eSYann Gautier zeromem(&cmd, sizeof(struct mmc_cmd)); 51*ad71d45eSYann Gautier 52*ad71d45eSYann Gautier cmd.cmd_idx = idx; 53*ad71d45eSYann Gautier cmd.cmd_arg = arg; 54*ad71d45eSYann Gautier cmd.resp_type = r_type; 55*ad71d45eSYann Gautier 56*ad71d45eSYann Gautier ret = ops->send_cmd(&cmd); 57*ad71d45eSYann Gautier 58*ad71d45eSYann Gautier if ((ret == 0) && (r_data != NULL)) { 59*ad71d45eSYann Gautier int i; 60*ad71d45eSYann Gautier 61*ad71d45eSYann Gautier for (i = 0; i < 4; i++) { 62*ad71d45eSYann Gautier *r_data = cmd.resp_data[i]; 63*ad71d45eSYann Gautier r_data++; 64*ad71d45eSYann Gautier } 65*ad71d45eSYann Gautier } 66*ad71d45eSYann Gautier 67*ad71d45eSYann Gautier if (ret != 0) { 68*ad71d45eSYann Gautier VERBOSE("Send command %u error: %d\n", idx, ret); 69*ad71d45eSYann Gautier } 70*ad71d45eSYann Gautier 71*ad71d45eSYann Gautier return ret; 72*ad71d45eSYann Gautier } 73*ad71d45eSYann Gautier 74*ad71d45eSYann Gautier static int mmc_device_state(void) 75*ad71d45eSYann Gautier { 76*ad71d45eSYann Gautier int retries = MMC_DEFAULT_MAX_RETRIES; 77*ad71d45eSYann Gautier unsigned int resp_data[4]; 78*ad71d45eSYann Gautier 79*ad71d45eSYann Gautier do { 80*ad71d45eSYann Gautier int ret; 81*ad71d45eSYann Gautier 82*ad71d45eSYann Gautier if (retries == 0) { 83*ad71d45eSYann Gautier ERROR("CMD13 failed after %d retries\n", 84*ad71d45eSYann Gautier MMC_DEFAULT_MAX_RETRIES); 85*ad71d45eSYann Gautier return -EIO; 86*ad71d45eSYann Gautier } 87*ad71d45eSYann Gautier 88*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET, 89*ad71d45eSYann Gautier MMC_RESPONSE_R(1), &resp_data[0]); 90*ad71d45eSYann Gautier if (ret != 0) { 91*ad71d45eSYann Gautier return ret; 92*ad71d45eSYann Gautier } 93*ad71d45eSYann Gautier 94*ad71d45eSYann Gautier if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) { 95*ad71d45eSYann Gautier return -EIO; 96*ad71d45eSYann Gautier } 97*ad71d45eSYann Gautier 98*ad71d45eSYann Gautier retries--; 99*ad71d45eSYann Gautier } while ((resp_data[0] & STATUS_READY_FOR_DATA) == 0U); 100*ad71d45eSYann Gautier 101*ad71d45eSYann Gautier return MMC_GET_STATE(resp_data[0]); 102*ad71d45eSYann Gautier } 103*ad71d45eSYann Gautier 104*ad71d45eSYann Gautier static int mmc_set_ext_csd(unsigned int ext_cmd, unsigned int value) 105*ad71d45eSYann Gautier { 106*ad71d45eSYann Gautier int ret; 107*ad71d45eSYann Gautier 108*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(6), 109*ad71d45eSYann Gautier EXTCSD_WRITE_BYTES | EXTCSD_CMD(ext_cmd) | 110*ad71d45eSYann Gautier EXTCSD_VALUE(value) | EXTCSD_CMD_SET_NORMAL, 111*ad71d45eSYann Gautier 0, NULL); 112*ad71d45eSYann Gautier if (ret != 0) { 113*ad71d45eSYann Gautier return ret; 114*ad71d45eSYann Gautier } 115*ad71d45eSYann Gautier 116*ad71d45eSYann Gautier do { 117*ad71d45eSYann Gautier ret = mmc_device_state(); 118*ad71d45eSYann Gautier if (ret < 0) { 119*ad71d45eSYann Gautier return ret; 120*ad71d45eSYann Gautier } 121*ad71d45eSYann Gautier } while (ret == MMC_STATE_PRG); 122*ad71d45eSYann Gautier 123*ad71d45eSYann Gautier return 0; 124*ad71d45eSYann Gautier } 125*ad71d45eSYann Gautier 126*ad71d45eSYann Gautier static int mmc_sd_switch(unsigned int bus_width) 127*ad71d45eSYann Gautier { 128*ad71d45eSYann Gautier int ret; 129*ad71d45eSYann Gautier int retries = MMC_DEFAULT_MAX_RETRIES; 130*ad71d45eSYann Gautier unsigned int scr[2] = { 0 }; 131*ad71d45eSYann Gautier unsigned int bus_width_arg = 0; 132*ad71d45eSYann Gautier 133*ad71d45eSYann Gautier ret = ops->prepare(0, (uintptr_t)&scr, sizeof(scr)); 134*ad71d45eSYann Gautier if (ret != 0) { 135*ad71d45eSYann Gautier return ret; 136*ad71d45eSYann Gautier } 137*ad71d45eSYann Gautier 138*ad71d45eSYann Gautier /* CMD55: Application Specific Command */ 139*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET, 140*ad71d45eSYann Gautier MMC_RESPONSE_R(1), NULL); 141*ad71d45eSYann Gautier if (ret != 0) { 142*ad71d45eSYann Gautier return ret; 143*ad71d45eSYann Gautier } 144*ad71d45eSYann Gautier 145*ad71d45eSYann Gautier /* ACMD51: SEND_SCR */ 146*ad71d45eSYann Gautier do { 147*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_ACMD(51), 0, MMC_RESPONSE_R(1), NULL); 148*ad71d45eSYann Gautier if ((ret != 0) && (retries == 0)) { 149*ad71d45eSYann Gautier ERROR("ACMD51 failed after %d retries (ret=%d)\n", 150*ad71d45eSYann Gautier MMC_DEFAULT_MAX_RETRIES, ret); 151*ad71d45eSYann Gautier return ret; 152*ad71d45eSYann Gautier } 153*ad71d45eSYann Gautier 154*ad71d45eSYann Gautier retries--; 155*ad71d45eSYann Gautier } while (ret != 0); 156*ad71d45eSYann Gautier 157*ad71d45eSYann Gautier ret = ops->read(0, (uintptr_t)&scr, sizeof(scr)); 158*ad71d45eSYann Gautier if (ret != 0) { 159*ad71d45eSYann Gautier return ret; 160*ad71d45eSYann Gautier } 161*ad71d45eSYann Gautier 162*ad71d45eSYann Gautier if (((scr[0] & SD_SCR_BUS_WIDTH_4) != 0U) && 163*ad71d45eSYann Gautier (bus_width == MMC_BUS_WIDTH_4)) { 164*ad71d45eSYann Gautier bus_width_arg = 2; 165*ad71d45eSYann Gautier } 166*ad71d45eSYann Gautier 167*ad71d45eSYann Gautier /* CMD55: Application Specific Command */ 168*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET, 169*ad71d45eSYann Gautier MMC_RESPONSE_R(1), NULL); 170*ad71d45eSYann Gautier if (ret != 0) { 171*ad71d45eSYann Gautier return ret; 172*ad71d45eSYann Gautier } 173*ad71d45eSYann Gautier 174*ad71d45eSYann Gautier /* ACMD6: SET_BUS_WIDTH */ 175*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_ACMD(6), bus_width_arg, MMC_RESPONSE_R(1), NULL); 176*ad71d45eSYann Gautier if (ret != 0) { 177*ad71d45eSYann Gautier return ret; 178*ad71d45eSYann Gautier } 179*ad71d45eSYann Gautier 180*ad71d45eSYann Gautier do { 181*ad71d45eSYann Gautier ret = mmc_device_state(); 182*ad71d45eSYann Gautier if (ret < 0) { 183*ad71d45eSYann Gautier return ret; 184*ad71d45eSYann Gautier } 185*ad71d45eSYann Gautier } while (ret == MMC_STATE_PRG); 186*ad71d45eSYann Gautier 187*ad71d45eSYann Gautier return 0; 188*ad71d45eSYann Gautier } 189*ad71d45eSYann Gautier 190*ad71d45eSYann Gautier static int mmc_set_ios(unsigned int clk, unsigned int bus_width) 191*ad71d45eSYann Gautier { 192*ad71d45eSYann Gautier int ret; 193*ad71d45eSYann Gautier unsigned int width = bus_width; 194*ad71d45eSYann Gautier 195*ad71d45eSYann Gautier if (mmc_dev_info->mmc_dev_type != MMC_IS_EMMC) { 196*ad71d45eSYann Gautier if (width == MMC_BUS_WIDTH_8) { 197*ad71d45eSYann Gautier WARN("Wrong bus config for SD-card, force to 4\n"); 198*ad71d45eSYann Gautier width = MMC_BUS_WIDTH_4; 199*ad71d45eSYann Gautier } 200*ad71d45eSYann Gautier ret = mmc_sd_switch(width); 201*ad71d45eSYann Gautier if (ret != 0) { 202*ad71d45eSYann Gautier return ret; 203*ad71d45eSYann Gautier } 204*ad71d45eSYann Gautier } else if (mmc_csd.spec_vers == 4U) { 205*ad71d45eSYann Gautier ret = mmc_set_ext_csd(CMD_EXTCSD_BUS_WIDTH, 206*ad71d45eSYann Gautier (unsigned int)width); 207*ad71d45eSYann Gautier if (ret != 0) { 208*ad71d45eSYann Gautier return ret; 209*ad71d45eSYann Gautier } 210*ad71d45eSYann Gautier } else { 211*ad71d45eSYann Gautier VERBOSE("Wrong MMC type or spec version\n"); 212*ad71d45eSYann Gautier } 213*ad71d45eSYann Gautier 214*ad71d45eSYann Gautier return ops->set_ios(clk, width); 215*ad71d45eSYann Gautier } 216*ad71d45eSYann Gautier 217*ad71d45eSYann Gautier static int mmc_fill_device_info(void) 218*ad71d45eSYann Gautier { 219*ad71d45eSYann Gautier unsigned long long c_size; 220*ad71d45eSYann Gautier unsigned int speed_idx; 221*ad71d45eSYann Gautier unsigned int nb_blocks; 222*ad71d45eSYann Gautier unsigned int freq_unit; 223*ad71d45eSYann Gautier int ret; 224*ad71d45eSYann Gautier struct mmc_csd_sd_v2 *csd_sd_v2; 225*ad71d45eSYann Gautier 226*ad71d45eSYann Gautier switch (mmc_dev_info->mmc_dev_type) { 227*ad71d45eSYann Gautier case MMC_IS_EMMC: 228*ad71d45eSYann Gautier mmc_dev_info->block_size = MMC_BLOCK_SIZE; 229*ad71d45eSYann Gautier 230*ad71d45eSYann Gautier ret = ops->prepare(0, (uintptr_t)&mmc_ext_csd, 231*ad71d45eSYann Gautier sizeof(mmc_ext_csd)); 232*ad71d45eSYann Gautier if (ret != 0) { 233*ad71d45eSYann Gautier return ret; 234*ad71d45eSYann Gautier } 235*ad71d45eSYann Gautier 236*ad71d45eSYann Gautier /* MMC CMD8: SEND_EXT_CSD */ 237*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(8), 0, MMC_RESPONSE_R(1), NULL); 238*ad71d45eSYann Gautier if (ret != 0) { 239*ad71d45eSYann Gautier return ret; 240*ad71d45eSYann Gautier } 241*ad71d45eSYann Gautier 242*ad71d45eSYann Gautier ret = ops->read(0, (uintptr_t)&mmc_ext_csd, 243*ad71d45eSYann Gautier sizeof(mmc_ext_csd)); 244*ad71d45eSYann Gautier if (ret != 0) { 245*ad71d45eSYann Gautier return ret; 246*ad71d45eSYann Gautier } 247*ad71d45eSYann Gautier 248*ad71d45eSYann Gautier nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) | 249*ad71d45eSYann Gautier (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) | 250*ad71d45eSYann Gautier (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) | 251*ad71d45eSYann Gautier (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 3] << 24); 252*ad71d45eSYann Gautier 253*ad71d45eSYann Gautier mmc_dev_info->device_size = (unsigned long long)nb_blocks * 254*ad71d45eSYann Gautier mmc_dev_info->block_size; 255*ad71d45eSYann Gautier 256*ad71d45eSYann Gautier break; 257*ad71d45eSYann Gautier 258*ad71d45eSYann Gautier case MMC_IS_SD: 259*ad71d45eSYann Gautier /* 260*ad71d45eSYann Gautier * Use the same mmc_csd struct, as required fields here 261*ad71d45eSYann Gautier * (READ_BL_LEN, C_SIZE, CSIZE_MULT) are common with eMMC. 262*ad71d45eSYann Gautier */ 263*ad71d45eSYann Gautier mmc_dev_info->block_size = BIT_32(mmc_csd.read_bl_len); 264*ad71d45eSYann Gautier 265*ad71d45eSYann Gautier c_size = ((unsigned long long)mmc_csd.c_size_high << 2U) | 266*ad71d45eSYann Gautier (unsigned long long)mmc_csd.c_size_low; 267*ad71d45eSYann Gautier assert(c_size != 0xFFFU); 268*ad71d45eSYann Gautier 269*ad71d45eSYann Gautier mmc_dev_info->device_size = (c_size + 1U) * 270*ad71d45eSYann Gautier BIT_64(mmc_csd.c_size_mult + 2U) * 271*ad71d45eSYann Gautier mmc_dev_info->block_size; 272*ad71d45eSYann Gautier 273*ad71d45eSYann Gautier break; 274*ad71d45eSYann Gautier 275*ad71d45eSYann Gautier case MMC_IS_SD_HC: 276*ad71d45eSYann Gautier assert(mmc_csd.csd_structure == 1U); 277*ad71d45eSYann Gautier 278*ad71d45eSYann Gautier mmc_dev_info->block_size = MMC_BLOCK_SIZE; 279*ad71d45eSYann Gautier 280*ad71d45eSYann Gautier /* Need to use mmc_csd_sd_v2 struct */ 281*ad71d45eSYann Gautier csd_sd_v2 = (struct mmc_csd_sd_v2 *)&mmc_csd; 282*ad71d45eSYann Gautier c_size = ((unsigned long long)csd_sd_v2->c_size_high << 16) | 283*ad71d45eSYann Gautier (unsigned long long)csd_sd_v2->c_size_low; 284*ad71d45eSYann Gautier 285*ad71d45eSYann Gautier mmc_dev_info->device_size = (c_size + 1U) << MULT_BY_512K_SHIFT; 286*ad71d45eSYann Gautier 287*ad71d45eSYann Gautier break; 288*ad71d45eSYann Gautier 289*ad71d45eSYann Gautier default: 290*ad71d45eSYann Gautier ret = -EINVAL; 291*ad71d45eSYann Gautier break; 292*ad71d45eSYann Gautier } 293*ad71d45eSYann Gautier 294*ad71d45eSYann Gautier if (ret != 0) { 295*ad71d45eSYann Gautier return ret; 296*ad71d45eSYann Gautier } 297*ad71d45eSYann Gautier 298*ad71d45eSYann Gautier speed_idx = (mmc_csd.tran_speed & CSD_TRAN_SPEED_MULT_MASK) >> 299*ad71d45eSYann Gautier CSD_TRAN_SPEED_MULT_SHIFT; 300*ad71d45eSYann Gautier 301*ad71d45eSYann Gautier assert(speed_idx > 0U); 302*ad71d45eSYann Gautier 303*ad71d45eSYann Gautier if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { 304*ad71d45eSYann Gautier mmc_dev_info->max_bus_freq = tran_speed_base[speed_idx]; 305*ad71d45eSYann Gautier } else { 306*ad71d45eSYann Gautier mmc_dev_info->max_bus_freq = sd_tran_speed_base[speed_idx]; 307*ad71d45eSYann Gautier } 308*ad71d45eSYann Gautier 309*ad71d45eSYann Gautier freq_unit = mmc_csd.tran_speed & CSD_TRAN_SPEED_UNIT_MASK; 310*ad71d45eSYann Gautier while (freq_unit != 0U) { 311*ad71d45eSYann Gautier mmc_dev_info->max_bus_freq *= 10U; 312*ad71d45eSYann Gautier --freq_unit; 313*ad71d45eSYann Gautier } 314*ad71d45eSYann Gautier 315*ad71d45eSYann Gautier mmc_dev_info->max_bus_freq *= 10000U; 316*ad71d45eSYann Gautier 317*ad71d45eSYann Gautier return 0; 318*ad71d45eSYann Gautier } 319*ad71d45eSYann Gautier 320*ad71d45eSYann Gautier static int sd_send_op_cond(void) 321*ad71d45eSYann Gautier { 322*ad71d45eSYann Gautier int retries = SEND_OP_COND_MAX_RETRIES; 323*ad71d45eSYann Gautier unsigned int resp_data[4]; 324*ad71d45eSYann Gautier 325*ad71d45eSYann Gautier do { 326*ad71d45eSYann Gautier int ret; 327*ad71d45eSYann Gautier 328*ad71d45eSYann Gautier if (retries == 0) { 329*ad71d45eSYann Gautier ERROR("ACMD41 failed after %d retries\n", 330*ad71d45eSYann Gautier SEND_OP_COND_MAX_RETRIES); 331*ad71d45eSYann Gautier return -EIO; 332*ad71d45eSYann Gautier } 333*ad71d45eSYann Gautier 334*ad71d45eSYann Gautier /* CMD55: Application Specific Command */ 335*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(55), 0, MMC_RESPONSE_R(1), NULL); 336*ad71d45eSYann Gautier if (ret != 0) { 337*ad71d45eSYann Gautier return ret; 338*ad71d45eSYann Gautier } 339*ad71d45eSYann Gautier 340*ad71d45eSYann Gautier /* ACMD41: SD_SEND_OP_COND */ 341*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS, MMC_RESPONSE_R(3), 342*ad71d45eSYann Gautier &resp_data[0]); 343*ad71d45eSYann Gautier if (ret != 0) { 344*ad71d45eSYann Gautier return ret; 345*ad71d45eSYann Gautier } 346*ad71d45eSYann Gautier 347*ad71d45eSYann Gautier retries--; 348*ad71d45eSYann Gautier } while ((resp_data[0] & OCR_POWERUP) == 0U); 349*ad71d45eSYann Gautier 350*ad71d45eSYann Gautier mmc_ocr_value = resp_data[0]; 351*ad71d45eSYann Gautier 352*ad71d45eSYann Gautier if ((mmc_ocr_value & OCR_HCS) != 0U) { 353*ad71d45eSYann Gautier mmc_dev_info->mmc_dev_type = MMC_IS_SD_HC; 354*ad71d45eSYann Gautier } else { 355*ad71d45eSYann Gautier mmc_dev_info->mmc_dev_type = MMC_IS_SD; 356*ad71d45eSYann Gautier } 357*ad71d45eSYann Gautier 358*ad71d45eSYann Gautier return 0; 359*ad71d45eSYann Gautier } 360*ad71d45eSYann Gautier 361*ad71d45eSYann Gautier static int mmc_send_op_cond(void) 362*ad71d45eSYann Gautier { 363*ad71d45eSYann Gautier int ret; 364*ad71d45eSYann Gautier int retries = SEND_OP_COND_MAX_RETRIES; 365*ad71d45eSYann Gautier unsigned int resp_data[4]; 366*ad71d45eSYann Gautier 367*ad71d45eSYann Gautier /* CMD0: reset to IDLE */ 368*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL); 369*ad71d45eSYann Gautier if (ret != 0) { 370*ad71d45eSYann Gautier return ret; 371*ad71d45eSYann Gautier } 372*ad71d45eSYann Gautier 373*ad71d45eSYann Gautier do { 374*ad71d45eSYann Gautier if (retries == 0) { 375*ad71d45eSYann Gautier ERROR("CMD1 failed after %d retries\n", 376*ad71d45eSYann Gautier SEND_OP_COND_MAX_RETRIES); 377*ad71d45eSYann Gautier return -EIO; 378*ad71d45eSYann Gautier } 379*ad71d45eSYann Gautier 380*ad71d45eSYann Gautier /* CMD1: get OCR register (SEND_OP_COND) */ 381*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE | 382*ad71d45eSYann Gautier OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7, 383*ad71d45eSYann Gautier MMC_RESPONSE_R(3), &resp_data[0]); 384*ad71d45eSYann Gautier if (ret != 0) { 385*ad71d45eSYann Gautier return ret; 386*ad71d45eSYann Gautier } 387*ad71d45eSYann Gautier 388*ad71d45eSYann Gautier retries--; 389*ad71d45eSYann Gautier } while ((resp_data[0] & OCR_POWERUP) == 0U); 390*ad71d45eSYann Gautier 391*ad71d45eSYann Gautier mmc_ocr_value = resp_data[0]; 392*ad71d45eSYann Gautier 393*ad71d45eSYann Gautier return 0; 394*ad71d45eSYann Gautier } 395*ad71d45eSYann Gautier 396*ad71d45eSYann Gautier static int mmc_enumerate(unsigned int clk, unsigned int bus_width) 397*ad71d45eSYann Gautier { 398*ad71d45eSYann Gautier int ret; 399*ad71d45eSYann Gautier unsigned int resp_data[4]; 400*ad71d45eSYann Gautier 401*ad71d45eSYann Gautier ops->init(); 402*ad71d45eSYann Gautier 403*ad71d45eSYann Gautier /* CMD0: reset to IDLE */ 404*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL); 405*ad71d45eSYann Gautier if (ret != 0) { 406*ad71d45eSYann Gautier return ret; 407*ad71d45eSYann Gautier } 408*ad71d45eSYann Gautier 409*ad71d45eSYann Gautier /* CMD8: Send Interface Condition Command */ 410*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(8), VHS_2_7_3_6_V | CMD8_CHECK_PATTERN, 411*ad71d45eSYann Gautier MMC_RESPONSE_R(7), &resp_data[0]); 412*ad71d45eSYann Gautier 413*ad71d45eSYann Gautier if ((ret == 0) && ((resp_data[0] & 0xffU) == CMD8_CHECK_PATTERN)) { 414*ad71d45eSYann Gautier ret = sd_send_op_cond(); 415*ad71d45eSYann Gautier } else { 416*ad71d45eSYann Gautier ret = mmc_send_op_cond(); 417*ad71d45eSYann Gautier } 418*ad71d45eSYann Gautier if (ret != 0) { 419*ad71d45eSYann Gautier return ret; 420*ad71d45eSYann Gautier } 421*ad71d45eSYann Gautier 422*ad71d45eSYann Gautier /* CMD2: Card Identification */ 423*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(2), 0, MMC_RESPONSE_R(2), NULL); 424*ad71d45eSYann Gautier if (ret != 0) { 425*ad71d45eSYann Gautier return ret; 426*ad71d45eSYann Gautier } 427*ad71d45eSYann Gautier 428*ad71d45eSYann Gautier /* CMD3: Set Relative Address */ 429*ad71d45eSYann Gautier if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { 430*ad71d45eSYann Gautier rca = MMC_FIX_RCA; 431*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(3), rca << RCA_SHIFT_OFFSET, 432*ad71d45eSYann Gautier MMC_RESPONSE_R(1), NULL); 433*ad71d45eSYann Gautier if (ret != 0) { 434*ad71d45eSYann Gautier return ret; 435*ad71d45eSYann Gautier } 436*ad71d45eSYann Gautier } else { 437*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(3), 0, 438*ad71d45eSYann Gautier MMC_RESPONSE_R(6), &resp_data[0]); 439*ad71d45eSYann Gautier if (ret != 0) { 440*ad71d45eSYann Gautier return ret; 441*ad71d45eSYann Gautier } 442*ad71d45eSYann Gautier 443*ad71d45eSYann Gautier rca = (resp_data[0] & 0xFFFF0000U) >> 16; 444*ad71d45eSYann Gautier } 445*ad71d45eSYann Gautier 446*ad71d45eSYann Gautier /* CMD9: CSD Register */ 447*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(9), rca << RCA_SHIFT_OFFSET, 448*ad71d45eSYann Gautier MMC_RESPONSE_R(2), &resp_data[0]); 449*ad71d45eSYann Gautier if (ret != 0) { 450*ad71d45eSYann Gautier return ret; 451*ad71d45eSYann Gautier } 452*ad71d45eSYann Gautier 453*ad71d45eSYann Gautier memcpy(&mmc_csd, &resp_data, sizeof(resp_data)); 454*ad71d45eSYann Gautier 455*ad71d45eSYann Gautier /* CMD7: Select Card */ 456*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(7), rca << RCA_SHIFT_OFFSET, 457*ad71d45eSYann Gautier MMC_RESPONSE_R(1), NULL); 458*ad71d45eSYann Gautier if (ret != 0) { 459*ad71d45eSYann Gautier return ret; 460*ad71d45eSYann Gautier } 461*ad71d45eSYann Gautier 462*ad71d45eSYann Gautier do { 463*ad71d45eSYann Gautier ret = mmc_device_state(); 464*ad71d45eSYann Gautier if (ret < 0) { 465*ad71d45eSYann Gautier return ret; 466*ad71d45eSYann Gautier } 467*ad71d45eSYann Gautier } while (ret != MMC_STATE_TRAN); 468*ad71d45eSYann Gautier 469*ad71d45eSYann Gautier ret = mmc_fill_device_info(); 470*ad71d45eSYann Gautier if (ret != 0) { 471*ad71d45eSYann Gautier return ret; 472*ad71d45eSYann Gautier } 473*ad71d45eSYann Gautier 474*ad71d45eSYann Gautier return mmc_set_ios(clk, bus_width); 475*ad71d45eSYann Gautier } 476*ad71d45eSYann Gautier 477*ad71d45eSYann Gautier size_t mmc_read_blocks(unsigned int lba, uintptr_t buf, size_t size) 478*ad71d45eSYann Gautier { 479*ad71d45eSYann Gautier int ret; 480*ad71d45eSYann Gautier unsigned int cmd_idx, cmd_arg; 481*ad71d45eSYann Gautier 482*ad71d45eSYann Gautier assert((ops != NULL) && 483*ad71d45eSYann Gautier (ops->read != NULL) && 484*ad71d45eSYann Gautier (size != 0U) && 485*ad71d45eSYann Gautier ((size & MMC_BLOCK_MASK) == 0U)); 486*ad71d45eSYann Gautier 487*ad71d45eSYann Gautier ret = ops->prepare(lba, buf, size); 488*ad71d45eSYann Gautier if (ret != 0) { 489*ad71d45eSYann Gautier return 0; 490*ad71d45eSYann Gautier } 491*ad71d45eSYann Gautier 492*ad71d45eSYann Gautier if (is_cmd23_enabled()) { 493*ad71d45eSYann Gautier /* Set block count */ 494*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE, 495*ad71d45eSYann Gautier MMC_RESPONSE_R(1), NULL); 496*ad71d45eSYann Gautier if (ret != 0) { 497*ad71d45eSYann Gautier return 0; 498*ad71d45eSYann Gautier } 499*ad71d45eSYann Gautier 500*ad71d45eSYann Gautier cmd_idx = MMC_CMD(18); 501*ad71d45eSYann Gautier } else { 502*ad71d45eSYann Gautier if (size > MMC_BLOCK_SIZE) { 503*ad71d45eSYann Gautier cmd_idx = MMC_CMD(18); 504*ad71d45eSYann Gautier } else { 505*ad71d45eSYann Gautier cmd_idx = MMC_CMD(17); 506*ad71d45eSYann Gautier } 507*ad71d45eSYann Gautier } 508*ad71d45eSYann Gautier 509*ad71d45eSYann Gautier if (((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) && 510*ad71d45eSYann Gautier (mmc_dev_info->mmc_dev_type != MMC_IS_SD_HC)) { 511*ad71d45eSYann Gautier cmd_arg = lba * MMC_BLOCK_SIZE; 512*ad71d45eSYann Gautier } else { 513*ad71d45eSYann Gautier cmd_arg = lba; 514*ad71d45eSYann Gautier } 515*ad71d45eSYann Gautier 516*ad71d45eSYann Gautier ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R(1), NULL); 517*ad71d45eSYann Gautier if (ret != 0) { 518*ad71d45eSYann Gautier return 0; 519*ad71d45eSYann Gautier } 520*ad71d45eSYann Gautier 521*ad71d45eSYann Gautier ret = ops->read(lba, buf, size); 522*ad71d45eSYann Gautier if (ret != 0) { 523*ad71d45eSYann Gautier return 0; 524*ad71d45eSYann Gautier } 525*ad71d45eSYann Gautier 526*ad71d45eSYann Gautier /* Wait buffer empty */ 527*ad71d45eSYann Gautier do { 528*ad71d45eSYann Gautier ret = mmc_device_state(); 529*ad71d45eSYann Gautier if (ret < 0) { 530*ad71d45eSYann Gautier return 0; 531*ad71d45eSYann Gautier } 532*ad71d45eSYann Gautier } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_DATA)); 533*ad71d45eSYann Gautier 534*ad71d45eSYann Gautier if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) { 535*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(12), 0, 0, NULL); 536*ad71d45eSYann Gautier if (ret != 0) { 537*ad71d45eSYann Gautier return 0; 538*ad71d45eSYann Gautier } 539*ad71d45eSYann Gautier } 540*ad71d45eSYann Gautier 541*ad71d45eSYann Gautier return size; 542*ad71d45eSYann Gautier } 543*ad71d45eSYann Gautier 544*ad71d45eSYann Gautier size_t mmc_write_blocks(unsigned int lba, const uintptr_t buf, size_t size) 545*ad71d45eSYann Gautier { 546*ad71d45eSYann Gautier int ret; 547*ad71d45eSYann Gautier unsigned int cmd_idx, cmd_arg; 548*ad71d45eSYann Gautier 549*ad71d45eSYann Gautier assert((ops != NULL) && 550*ad71d45eSYann Gautier (ops->write != NULL) && 551*ad71d45eSYann Gautier (size != 0U) && 552*ad71d45eSYann Gautier ((buf & MMC_BLOCK_MASK) == 0U) && 553*ad71d45eSYann Gautier ((size & MMC_BLOCK_MASK) == 0U)); 554*ad71d45eSYann Gautier 555*ad71d45eSYann Gautier ret = ops->prepare(lba, buf, size); 556*ad71d45eSYann Gautier if (ret != 0) { 557*ad71d45eSYann Gautier return 0; 558*ad71d45eSYann Gautier } 559*ad71d45eSYann Gautier 560*ad71d45eSYann Gautier if (is_cmd23_enabled()) { 561*ad71d45eSYann Gautier /* Set block count */ 562*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE, 563*ad71d45eSYann Gautier MMC_RESPONSE_R(1), NULL); 564*ad71d45eSYann Gautier if (ret != 0) { 565*ad71d45eSYann Gautier return 0; 566*ad71d45eSYann Gautier } 567*ad71d45eSYann Gautier 568*ad71d45eSYann Gautier cmd_idx = MMC_CMD(25); 569*ad71d45eSYann Gautier } else { 570*ad71d45eSYann Gautier if (size > MMC_BLOCK_SIZE) { 571*ad71d45eSYann Gautier cmd_idx = MMC_CMD(25); 572*ad71d45eSYann Gautier } else { 573*ad71d45eSYann Gautier cmd_idx = MMC_CMD(24); 574*ad71d45eSYann Gautier } 575*ad71d45eSYann Gautier } 576*ad71d45eSYann Gautier 577*ad71d45eSYann Gautier if ((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) { 578*ad71d45eSYann Gautier cmd_arg = lba * MMC_BLOCK_SIZE; 579*ad71d45eSYann Gautier } else { 580*ad71d45eSYann Gautier cmd_arg = lba; 581*ad71d45eSYann Gautier } 582*ad71d45eSYann Gautier 583*ad71d45eSYann Gautier ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R(1), NULL); 584*ad71d45eSYann Gautier if (ret != 0) { 585*ad71d45eSYann Gautier return 0; 586*ad71d45eSYann Gautier } 587*ad71d45eSYann Gautier 588*ad71d45eSYann Gautier ret = ops->write(lba, buf, size); 589*ad71d45eSYann Gautier if (ret != 0) { 590*ad71d45eSYann Gautier return 0; 591*ad71d45eSYann Gautier } 592*ad71d45eSYann Gautier 593*ad71d45eSYann Gautier /* Wait buffer empty */ 594*ad71d45eSYann Gautier do { 595*ad71d45eSYann Gautier ret = mmc_device_state(); 596*ad71d45eSYann Gautier if (ret < 0) { 597*ad71d45eSYann Gautier return 0; 598*ad71d45eSYann Gautier } 599*ad71d45eSYann Gautier } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_RCV)); 600*ad71d45eSYann Gautier 601*ad71d45eSYann Gautier if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) { 602*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(12), 0, 0, NULL); 603*ad71d45eSYann Gautier if (ret != 0) { 604*ad71d45eSYann Gautier return 0; 605*ad71d45eSYann Gautier } 606*ad71d45eSYann Gautier } 607*ad71d45eSYann Gautier 608*ad71d45eSYann Gautier return size; 609*ad71d45eSYann Gautier } 610*ad71d45eSYann Gautier 611*ad71d45eSYann Gautier size_t mmc_erase_blocks(unsigned int lba, size_t size) 612*ad71d45eSYann Gautier { 613*ad71d45eSYann Gautier int ret; 614*ad71d45eSYann Gautier 615*ad71d45eSYann Gautier assert(ops != NULL); 616*ad71d45eSYann Gautier assert((size != 0U) && ((size & MMC_BLOCK_MASK) == 0U)); 617*ad71d45eSYann Gautier 618*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(35), lba, MMC_RESPONSE_R(1), NULL); 619*ad71d45eSYann Gautier if (ret != 0) { 620*ad71d45eSYann Gautier return 0; 621*ad71d45eSYann Gautier } 622*ad71d45eSYann Gautier 623*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(36), lba + (size / MMC_BLOCK_SIZE) - 1U, 624*ad71d45eSYann Gautier MMC_RESPONSE_R(1), NULL); 625*ad71d45eSYann Gautier if (ret != 0) { 626*ad71d45eSYann Gautier return 0; 627*ad71d45eSYann Gautier } 628*ad71d45eSYann Gautier 629*ad71d45eSYann Gautier ret = mmc_send_cmd(MMC_CMD(38), lba, MMC_RESPONSE_R(0x1B), NULL); 630*ad71d45eSYann Gautier if (ret != 0) { 631*ad71d45eSYann Gautier return 0; 632*ad71d45eSYann Gautier } 633*ad71d45eSYann Gautier 634*ad71d45eSYann Gautier do { 635*ad71d45eSYann Gautier ret = mmc_device_state(); 636*ad71d45eSYann Gautier if (ret < 0) { 637*ad71d45eSYann Gautier return 0; 638*ad71d45eSYann Gautier } 639*ad71d45eSYann Gautier } while (ret != MMC_STATE_TRAN); 640*ad71d45eSYann Gautier 641*ad71d45eSYann Gautier return size; 642*ad71d45eSYann Gautier } 643*ad71d45eSYann Gautier 644*ad71d45eSYann Gautier static inline void mmc_rpmb_enable(void) 645*ad71d45eSYann Gautier { 646*ad71d45eSYann Gautier mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG, 647*ad71d45eSYann Gautier PART_CFG_BOOT_PARTITION1_ENABLE | 648*ad71d45eSYann Gautier PART_CFG_PARTITION1_ACCESS); 649*ad71d45eSYann Gautier } 650*ad71d45eSYann Gautier 651*ad71d45eSYann Gautier static inline void mmc_rpmb_disable(void) 652*ad71d45eSYann Gautier { 653*ad71d45eSYann Gautier mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG, 654*ad71d45eSYann Gautier PART_CFG_BOOT_PARTITION1_ENABLE); 655*ad71d45eSYann Gautier } 656*ad71d45eSYann Gautier 657*ad71d45eSYann Gautier size_t mmc_rpmb_read_blocks(unsigned int lba, uintptr_t buf, size_t size) 658*ad71d45eSYann Gautier { 659*ad71d45eSYann Gautier size_t size_read; 660*ad71d45eSYann Gautier 661*ad71d45eSYann Gautier mmc_rpmb_enable(); 662*ad71d45eSYann Gautier size_read = mmc_read_blocks(lba, buf, size); 663*ad71d45eSYann Gautier mmc_rpmb_disable(); 664*ad71d45eSYann Gautier 665*ad71d45eSYann Gautier return size_read; 666*ad71d45eSYann Gautier } 667*ad71d45eSYann Gautier 668*ad71d45eSYann Gautier size_t mmc_rpmb_write_blocks(unsigned int lba, const uintptr_t buf, size_t size) 669*ad71d45eSYann Gautier { 670*ad71d45eSYann Gautier size_t size_written; 671*ad71d45eSYann Gautier 672*ad71d45eSYann Gautier mmc_rpmb_enable(); 673*ad71d45eSYann Gautier size_written = mmc_write_blocks(lba, buf, size); 674*ad71d45eSYann Gautier mmc_rpmb_disable(); 675*ad71d45eSYann Gautier 676*ad71d45eSYann Gautier return size_written; 677*ad71d45eSYann Gautier } 678*ad71d45eSYann Gautier 679*ad71d45eSYann Gautier size_t mmc_rpmb_erase_blocks(unsigned int lba, size_t size) 680*ad71d45eSYann Gautier { 681*ad71d45eSYann Gautier size_t size_erased; 682*ad71d45eSYann Gautier 683*ad71d45eSYann Gautier mmc_rpmb_enable(); 684*ad71d45eSYann Gautier size_erased = mmc_erase_blocks(lba, size); 685*ad71d45eSYann Gautier mmc_rpmb_disable(); 686*ad71d45eSYann Gautier 687*ad71d45eSYann Gautier return size_erased; 688*ad71d45eSYann Gautier } 689*ad71d45eSYann Gautier 690*ad71d45eSYann Gautier int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk, 691*ad71d45eSYann Gautier unsigned int width, unsigned int flags, 692*ad71d45eSYann Gautier struct mmc_device_info *device_info) 693*ad71d45eSYann Gautier { 694*ad71d45eSYann Gautier assert((ops_ptr != NULL) && 695*ad71d45eSYann Gautier (ops_ptr->init != NULL) && 696*ad71d45eSYann Gautier (ops_ptr->send_cmd != NULL) && 697*ad71d45eSYann Gautier (ops_ptr->set_ios != NULL) && 698*ad71d45eSYann Gautier (ops_ptr->prepare != NULL) && 699*ad71d45eSYann Gautier (ops_ptr->read != NULL) && 700*ad71d45eSYann Gautier (ops_ptr->write != NULL) && 701*ad71d45eSYann Gautier (device_info != NULL) && 702*ad71d45eSYann Gautier (clk != 0) && 703*ad71d45eSYann Gautier ((width == MMC_BUS_WIDTH_1) || 704*ad71d45eSYann Gautier (width == MMC_BUS_WIDTH_4) || 705*ad71d45eSYann Gautier (width == MMC_BUS_WIDTH_8) || 706*ad71d45eSYann Gautier (width == MMC_BUS_WIDTH_DDR_4) || 707*ad71d45eSYann Gautier (width == MMC_BUS_WIDTH_DDR_8))); 708*ad71d45eSYann Gautier 709*ad71d45eSYann Gautier ops = ops_ptr; 710*ad71d45eSYann Gautier mmc_flags = flags; 711*ad71d45eSYann Gautier mmc_dev_info = device_info; 712*ad71d45eSYann Gautier 713*ad71d45eSYann Gautier return mmc_enumerate(clk, width); 714*ad71d45eSYann Gautier } 715