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