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 <stddef.h> 11*91f16700Schasinglulu #include <string.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <arch_helpers.h> 14*91f16700Schasinglulu #include <common/debug.h> 15*91f16700Schasinglulu #include <drivers/cadence/cdns_sdmmc.h> 16*91f16700Schasinglulu #include <drivers/delay_timer.h> 17*91f16700Schasinglulu #include <drivers/mmc.h> 18*91f16700Schasinglulu #include <lib/mmio.h> 19*91f16700Schasinglulu #include <lib/utils.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu /* Card busy and present */ 22*91f16700Schasinglulu #define CARD_BUSY 1 23*91f16700Schasinglulu #define CARD_NOT_BUSY 0 24*91f16700Schasinglulu 25*91f16700Schasinglulu /* 500 ms delay to read the RINST register */ 26*91f16700Schasinglulu #define DELAY_MS_SRS_READ 500 27*91f16700Schasinglulu #define DELAY_RES 10 28*91f16700Schasinglulu 29*91f16700Schasinglulu /* SRS12 error mask */ 30*91f16700Schasinglulu #define SRS12_ERR_MASK 0xFFFF8000 31*91f16700Schasinglulu 32*91f16700Schasinglulu /* Check DV dfi_init val=0 */ 33*91f16700Schasinglulu #define IO_MASK_END_DATA 0x0 34*91f16700Schasinglulu 35*91f16700Schasinglulu /* Check DV dfi_init val=2; DDR Mode */ 36*91f16700Schasinglulu #define IO_MASK_END_DATA_DDR 0x2 37*91f16700Schasinglulu #define IO_MASK_START_DATA 0x0 38*91f16700Schasinglulu #define DATA_SELECT_OE_END_DATA 0x1 39*91f16700Schasinglulu 40*91f16700Schasinglulu #define TIMEOUT 100000 41*91f16700Schasinglulu 42*91f16700Schasinglulu /* General define */ 43*91f16700Schasinglulu #define SDHC_REG_MASK UINT_MAX 44*91f16700Schasinglulu #define SD_HOST_BLOCK_SIZE 0x200 45*91f16700Schasinglulu #define DTCVVAL_DEFAULT_VAL 0xE 46*91f16700Schasinglulu #define CDMMC_DMA_MAX_BUFFER_SIZE 64*1024 47*91f16700Schasinglulu #define CDNSMMC_ADDRESS_MASK U(0x0f) 48*91f16700Schasinglulu #define CONFIG_CDNS_DESC_COUNT 8 49*91f16700Schasinglulu 50*91f16700Schasinglulu void cdns_init(void); 51*91f16700Schasinglulu int cdns_send_cmd(struct mmc_cmd *cmd); 52*91f16700Schasinglulu int cdns_set_ios(unsigned int clk, unsigned int width); 53*91f16700Schasinglulu int cdns_prepare(int lba, uintptr_t buf, size_t size); 54*91f16700Schasinglulu int cdns_read(int lba, uintptr_t buf, size_t size); 55*91f16700Schasinglulu int cdns_write(int lba, uintptr_t buf, size_t size); 56*91f16700Schasinglulu 57*91f16700Schasinglulu const struct mmc_ops cdns_sdmmc_ops = { 58*91f16700Schasinglulu .init = cdns_init, 59*91f16700Schasinglulu .send_cmd = cdns_send_cmd, 60*91f16700Schasinglulu .set_ios = cdns_set_ios, 61*91f16700Schasinglulu .prepare = cdns_prepare, 62*91f16700Schasinglulu .read = cdns_read, 63*91f16700Schasinglulu .write = cdns_write, 64*91f16700Schasinglulu }; 65*91f16700Schasinglulu 66*91f16700Schasinglulu struct cdns_sdmmc_params cdns_params; 67*91f16700Schasinglulu struct cdns_sdmmc_combo_phy sdmmc_combo_phy_reg; 68*91f16700Schasinglulu struct cdns_sdmmc_sdhc sdmmc_sdhc_reg; 69*91f16700Schasinglulu #ifdef CONFIG_DMA_ADDR_T_64BIT 70*91f16700Schasinglulu struct cdns_idmac_desc cdns_desc[CONFIG_CDNS_DESC_COUNT]; 71*91f16700Schasinglulu #else 72*91f16700Schasinglulu struct cdns_idmac_desc cdns_desc[CONFIG_CDNS_DESC_COUNT] __aligned(32); 73*91f16700Schasinglulu #endif 74*91f16700Schasinglulu 75*91f16700Schasinglulu bool data_cmd; 76*91f16700Schasinglulu 77*91f16700Schasinglulu int cdns_wait_ics(uint16_t timeout, uint32_t cdn_srs_res) 78*91f16700Schasinglulu { 79*91f16700Schasinglulu /* Clock for sdmclk and sdclk */ 80*91f16700Schasinglulu uint32_t count = 0; 81*91f16700Schasinglulu uint32_t data = 0; 82*91f16700Schasinglulu 83*91f16700Schasinglulu /* Wait status command response ready */ 84*91f16700Schasinglulu do { 85*91f16700Schasinglulu data = mmio_read_32(cdn_srs_res); 86*91f16700Schasinglulu count++; 87*91f16700Schasinglulu if (count >= timeout) { 88*91f16700Schasinglulu return -ETIMEDOUT; 89*91f16700Schasinglulu } 90*91f16700Schasinglulu } while ((data & (1 << SDMMC_CDN_ICS)) == 0); 91*91f16700Schasinglulu 92*91f16700Schasinglulu return 0; 93*91f16700Schasinglulu } 94*91f16700Schasinglulu 95*91f16700Schasinglulu int cdns_busy(void) 96*91f16700Schasinglulu { 97*91f16700Schasinglulu unsigned int data; 98*91f16700Schasinglulu 99*91f16700Schasinglulu data = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS09); 100*91f16700Schasinglulu return (data & STATUS_DATA_BUSY) ? CARD_BUSY : CARD_NOT_BUSY; 101*91f16700Schasinglulu } 102*91f16700Schasinglulu 103*91f16700Schasinglulu int cdns_vol_reset(void) 104*91f16700Schasinglulu { 105*91f16700Schasinglulu /* Reset embedded card */ 106*91f16700Schasinglulu mmio_write_32((MMC_REG_BASE + SDHC_CDNS_SRS10), (7 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP)); 107*91f16700Schasinglulu udelay(250); 108*91f16700Schasinglulu mmio_write_32((MMC_REG_BASE + SDHC_CDNS_SRS10), (7 << SDMMC_CDN_BVS) | (0 << SDMMC_CDN_BP)); 109*91f16700Schasinglulu udelay(500); 110*91f16700Schasinglulu 111*91f16700Schasinglulu /* Turn on supply voltage */ 112*91f16700Schasinglulu /* BVS = 7, BP = 1, BP2 only in UHS2 mode */ 113*91f16700Schasinglulu mmio_write_32((MMC_REG_BASE + SDHC_CDNS_SRS10), (7 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP)); 114*91f16700Schasinglulu udelay(250); 115*91f16700Schasinglulu return 0; 116*91f16700Schasinglulu } 117*91f16700Schasinglulu 118*91f16700Schasinglulu void cdns_set_sdmmc_var(struct cdns_sdmmc_combo_phy *combo_phy_reg, 119*91f16700Schasinglulu struct cdns_sdmmc_sdhc *sdhc_reg) 120*91f16700Schasinglulu { 121*91f16700Schasinglulu /* Values are taken by the reference of cadence IP documents */ 122*91f16700Schasinglulu combo_phy_reg->cp_clk_wr_delay = 0; 123*91f16700Schasinglulu combo_phy_reg->cp_clk_wrdqs_delay = 0; 124*91f16700Schasinglulu combo_phy_reg->cp_data_select_oe_end = 0; 125*91f16700Schasinglulu combo_phy_reg->cp_dll_bypass_mode = 1; 126*91f16700Schasinglulu combo_phy_reg->cp_dll_locked_mode = 0; 127*91f16700Schasinglulu combo_phy_reg->cp_dll_start_point = 0; 128*91f16700Schasinglulu combo_phy_reg->cp_gate_cfg_always_on = 1; 129*91f16700Schasinglulu combo_phy_reg->cp_io_mask_always_on = 0; 130*91f16700Schasinglulu combo_phy_reg->cp_io_mask_end = 0; 131*91f16700Schasinglulu combo_phy_reg->cp_io_mask_start = 0; 132*91f16700Schasinglulu combo_phy_reg->cp_rd_del_sel = 52; 133*91f16700Schasinglulu combo_phy_reg->cp_read_dqs_cmd_delay = 0; 134*91f16700Schasinglulu combo_phy_reg->cp_read_dqs_delay = 0; 135*91f16700Schasinglulu combo_phy_reg->cp_sw_half_cycle_shift = 0; 136*91f16700Schasinglulu combo_phy_reg->cp_sync_method = 1; 137*91f16700Schasinglulu combo_phy_reg->cp_underrun_suppress = 1; 138*91f16700Schasinglulu combo_phy_reg->cp_use_ext_lpbk_dqs = 1; 139*91f16700Schasinglulu combo_phy_reg->cp_use_lpbk_dqs = 1; 140*91f16700Schasinglulu combo_phy_reg->cp_use_phony_dqs = 1; 141*91f16700Schasinglulu combo_phy_reg->cp_use_phony_dqs_cmd = 1; 142*91f16700Schasinglulu 143*91f16700Schasinglulu sdhc_reg->sdhc_extended_rd_mode = 1; 144*91f16700Schasinglulu sdhc_reg->sdhc_extended_wr_mode = 1; 145*91f16700Schasinglulu sdhc_reg->sdhc_hcsdclkadj = 0; 146*91f16700Schasinglulu sdhc_reg->sdhc_idelay_val = 0; 147*91f16700Schasinglulu sdhc_reg->sdhc_rdcmd_en = 1; 148*91f16700Schasinglulu sdhc_reg->sdhc_rddata_en = 1; 149*91f16700Schasinglulu sdhc_reg->sdhc_rw_compensate = 9; 150*91f16700Schasinglulu sdhc_reg->sdhc_sdcfsh = 0; 151*91f16700Schasinglulu sdhc_reg->sdhc_sdcfsl = 1; 152*91f16700Schasinglulu sdhc_reg->sdhc_wrcmd0_dly = 1; 153*91f16700Schasinglulu sdhc_reg->sdhc_wrcmd0_sdclk_dly = 0; 154*91f16700Schasinglulu sdhc_reg->sdhc_wrcmd1_dly = 0; 155*91f16700Schasinglulu sdhc_reg->sdhc_wrcmd1_sdclk_dly = 0; 156*91f16700Schasinglulu sdhc_reg->sdhc_wrdata0_dly = 1; 157*91f16700Schasinglulu sdhc_reg->sdhc_wrdata0_sdclk_dly = 0; 158*91f16700Schasinglulu sdhc_reg->sdhc_wrdata1_dly = 0; 159*91f16700Schasinglulu sdhc_reg->sdhc_wrdata1_sdclk_dly = 0; 160*91f16700Schasinglulu } 161*91f16700Schasinglulu 162*91f16700Schasinglulu static int cdns_program_phy_reg(struct cdns_sdmmc_combo_phy *combo_phy_reg, 163*91f16700Schasinglulu struct cdns_sdmmc_sdhc *sdhc_reg) 164*91f16700Schasinglulu { 165*91f16700Schasinglulu uint32_t value = 0; 166*91f16700Schasinglulu int ret = 0; 167*91f16700Schasinglulu 168*91f16700Schasinglulu /* program PHY_DQS_TIMING_REG */ 169*91f16700Schasinglulu value = (CP_USE_EXT_LPBK_DQS(combo_phy_reg->cp_use_ext_lpbk_dqs)) | 170*91f16700Schasinglulu (CP_USE_LPBK_DQS(combo_phy_reg->cp_use_lpbk_dqs)) | 171*91f16700Schasinglulu (CP_USE_PHONY_DQS(combo_phy_reg->cp_use_phony_dqs)) | 172*91f16700Schasinglulu (CP_USE_PHONY_DQS_CMD(combo_phy_reg->cp_use_phony_dqs_cmd)); 173*91f16700Schasinglulu ret = cdns_sdmmc_write_phy_reg(MMC_REG_BASE + SDHC_CDNS_HRS04, 174*91f16700Schasinglulu COMBO_PHY_REG + PHY_DQS_TIMING_REG, MMC_REG_BASE + 175*91f16700Schasinglulu SDHC_CDNS_HRS05, value); 176*91f16700Schasinglulu if (ret != 0) { 177*91f16700Schasinglulu return ret; 178*91f16700Schasinglulu } 179*91f16700Schasinglulu 180*91f16700Schasinglulu /* program PHY_GATE_LPBK_CTRL_REG */ 181*91f16700Schasinglulu value = (CP_SYNC_METHOD(combo_phy_reg->cp_sync_method)) | 182*91f16700Schasinglulu (CP_SW_HALF_CYCLE_SHIFT(combo_phy_reg->cp_sw_half_cycle_shift)) | 183*91f16700Schasinglulu (CP_RD_DEL_SEL(combo_phy_reg->cp_rd_del_sel)) | 184*91f16700Schasinglulu (CP_UNDERRUN_SUPPRESS(combo_phy_reg->cp_underrun_suppress)) | 185*91f16700Schasinglulu (CP_GATE_CFG_ALWAYS_ON(combo_phy_reg->cp_gate_cfg_always_on)); 186*91f16700Schasinglulu ret = cdns_sdmmc_write_phy_reg(MMC_REG_BASE + SDHC_CDNS_HRS04, 187*91f16700Schasinglulu COMBO_PHY_REG + PHY_GATE_LPBK_CTRL_REG, MMC_REG_BASE + 188*91f16700Schasinglulu SDHC_CDNS_HRS05, value); 189*91f16700Schasinglulu if (ret != 0) { 190*91f16700Schasinglulu return ret; 191*91f16700Schasinglulu } 192*91f16700Schasinglulu 193*91f16700Schasinglulu /* program PHY_DLL_MASTER_CTRL_REG */ 194*91f16700Schasinglulu value = (CP_DLL_BYPASS_MODE(combo_phy_reg->cp_dll_bypass_mode)) 195*91f16700Schasinglulu | (CP_DLL_START_POINT(combo_phy_reg->cp_dll_start_point)); 196*91f16700Schasinglulu ret = cdns_sdmmc_write_phy_reg(MMC_REG_BASE + SDHC_CDNS_HRS04, 197*91f16700Schasinglulu COMBO_PHY_REG + PHY_DLL_MASTER_CTRL_REG, MMC_REG_BASE 198*91f16700Schasinglulu + SDHC_CDNS_HRS05, value); 199*91f16700Schasinglulu if (ret != 0) { 200*91f16700Schasinglulu return ret; 201*91f16700Schasinglulu } 202*91f16700Schasinglulu 203*91f16700Schasinglulu /* program PHY_DLL_SLAVE_CTRL_REG */ 204*91f16700Schasinglulu value = (CP_READ_DQS_CMD_DELAY(combo_phy_reg->cp_read_dqs_cmd_delay)) 205*91f16700Schasinglulu | (CP_CLK_WRDQS_DELAY(combo_phy_reg->cp_clk_wrdqs_delay)) 206*91f16700Schasinglulu | (CP_CLK_WR_DELAY(combo_phy_reg->cp_clk_wr_delay)) 207*91f16700Schasinglulu | (CP_READ_DQS_DELAY(combo_phy_reg->cp_read_dqs_delay)); 208*91f16700Schasinglulu ret = cdns_sdmmc_write_phy_reg(MMC_REG_BASE + SDHC_CDNS_HRS04, 209*91f16700Schasinglulu COMBO_PHY_REG + PHY_DLL_SLAVE_CTRL_REG, MMC_REG_BASE 210*91f16700Schasinglulu + SDHC_CDNS_HRS05, value); 211*91f16700Schasinglulu if (ret != 0) { 212*91f16700Schasinglulu return ret; 213*91f16700Schasinglulu } 214*91f16700Schasinglulu 215*91f16700Schasinglulu /* program PHY_CTRL_REG */ 216*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS04, COMBO_PHY_REG 217*91f16700Schasinglulu + PHY_CTRL_REG); 218*91f16700Schasinglulu value = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS05); 219*91f16700Schasinglulu 220*91f16700Schasinglulu /* phony_dqs_timing=0 */ 221*91f16700Schasinglulu value &= ~(CP_PHONY_DQS_TIMING_MASK << CP_PHONY_DQS_TIMING_SHIFT); 222*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS05, value); 223*91f16700Schasinglulu 224*91f16700Schasinglulu /* switch off DLL_RESET */ 225*91f16700Schasinglulu do { 226*91f16700Schasinglulu value = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS09); 227*91f16700Schasinglulu value |= SDHC_PHY_SW_RESET; 228*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS09, value); 229*91f16700Schasinglulu value = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS09); 230*91f16700Schasinglulu /* polling PHY_INIT_COMPLETE */ 231*91f16700Schasinglulu } while ((value & SDHC_PHY_INIT_COMPLETE) != SDHC_PHY_INIT_COMPLETE); 232*91f16700Schasinglulu 233*91f16700Schasinglulu /* program PHY_DQ_TIMING_REG */ 234*91f16700Schasinglulu combo_phy_reg->cp_io_mask_end = 0U; 235*91f16700Schasinglulu value = (CP_IO_MASK_ALWAYS_ON(combo_phy_reg->cp_io_mask_always_on)) 236*91f16700Schasinglulu | (CP_IO_MASK_END(combo_phy_reg->cp_io_mask_end)) 237*91f16700Schasinglulu | (CP_IO_MASK_START(combo_phy_reg->cp_io_mask_start)) 238*91f16700Schasinglulu | (CP_DATA_SELECT_OE_END(combo_phy_reg->cp_data_select_oe_end)); 239*91f16700Schasinglulu 240*91f16700Schasinglulu ret = cdns_sdmmc_write_phy_reg(MMC_REG_BASE + SDHC_CDNS_HRS04, 241*91f16700Schasinglulu COMBO_PHY_REG + PHY_DQ_TIMING_REG, MMC_REG_BASE 242*91f16700Schasinglulu + SDHC_CDNS_HRS05, value); 243*91f16700Schasinglulu if (ret != 0) { 244*91f16700Schasinglulu return ret; 245*91f16700Schasinglulu } 246*91f16700Schasinglulu return 0; 247*91f16700Schasinglulu } 248*91f16700Schasinglulu 249*91f16700Schasinglulu int cdns_read(int lba, uintptr_t buf, size_t size) 250*91f16700Schasinglulu { 251*91f16700Schasinglulu inv_dcache_range(buf, size); 252*91f16700Schasinglulu 253*91f16700Schasinglulu return 0; 254*91f16700Schasinglulu } 255*91f16700Schasinglulu 256*91f16700Schasinglulu void cdns_init(void) 257*91f16700Schasinglulu { 258*91f16700Schasinglulu /* Dummy function pointer for cdns_init. */ 259*91f16700Schasinglulu } 260*91f16700Schasinglulu 261*91f16700Schasinglulu int cdns_prepare(int dma_start_addr, uintptr_t dma_buff, size_t size) 262*91f16700Schasinglulu { 263*91f16700Schasinglulu data_cmd = true; 264*91f16700Schasinglulu struct cdns_idmac_desc *desc; 265*91f16700Schasinglulu uint32_t desc_cnt, i; 266*91f16700Schasinglulu uint64_t desc_base; 267*91f16700Schasinglulu 268*91f16700Schasinglulu assert(((dma_buff & CDNSMMC_ADDRESS_MASK) == 0) && 269*91f16700Schasinglulu (cdns_params.desc_size > 0) && 270*91f16700Schasinglulu ((MMC_REG_BASE & MMC_BLOCK_MASK) == 0) && 271*91f16700Schasinglulu ((cdns_params.desc_base & MMC_BLOCK_MASK) == 0) && 272*91f16700Schasinglulu ((cdns_params.desc_size & MMC_BLOCK_MASK) == 0)); 273*91f16700Schasinglulu 274*91f16700Schasinglulu flush_dcache_range(dma_buff, size); 275*91f16700Schasinglulu 276*91f16700Schasinglulu desc_cnt = (size + (CDMMC_DMA_MAX_BUFFER_SIZE) - 1) / (CDMMC_DMA_MAX_BUFFER_SIZE); 277*91f16700Schasinglulu assert(desc_cnt * sizeof(struct cdns_idmac_desc) < cdns_params.desc_size); 278*91f16700Schasinglulu 279*91f16700Schasinglulu if (desc_cnt > CONFIG_CDNS_DESC_COUNT) { 280*91f16700Schasinglulu ERROR("Requested data transfer length %ld is greater than configured length %d", 281*91f16700Schasinglulu size, (CONFIG_CDNS_DESC_COUNT * CDMMC_DMA_MAX_BUFFER_SIZE)); 282*91f16700Schasinglulu return -EINVAL; 283*91f16700Schasinglulu } 284*91f16700Schasinglulu 285*91f16700Schasinglulu desc = (struct cdns_idmac_desc *)cdns_params.desc_base; 286*91f16700Schasinglulu desc_base = (uint64_t)desc; 287*91f16700Schasinglulu i = 0; 288*91f16700Schasinglulu 289*91f16700Schasinglulu while ((i + 1) < desc_cnt) { 290*91f16700Schasinglulu desc->attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA; 291*91f16700Schasinglulu desc->reserved = 0; 292*91f16700Schasinglulu desc->len = MAX_64KB_PAGE; 293*91f16700Schasinglulu desc->addr_lo = (dma_buff & UINT_MAX) + (CDMMC_DMA_MAX_BUFFER_SIZE * i); 294*91f16700Schasinglulu #if CONFIG_DMA_ADDR_T_64BIT == 1 295*91f16700Schasinglulu desc->addr_hi = (dma_buff >> 32) & 0xffffffff; 296*91f16700Schasinglulu #endif 297*91f16700Schasinglulu size -= CDMMC_DMA_MAX_BUFFER_SIZE; 298*91f16700Schasinglulu desc++; 299*91f16700Schasinglulu i++; 300*91f16700Schasinglulu } 301*91f16700Schasinglulu 302*91f16700Schasinglulu desc->attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA | 303*91f16700Schasinglulu ADMA_DESC_ATTR_END; 304*91f16700Schasinglulu desc->reserved = 0; 305*91f16700Schasinglulu desc->len = size; 306*91f16700Schasinglulu #if CONFIG_DMA_ADDR_T_64BIT == 1 307*91f16700Schasinglulu desc->addr_lo = (dma_buff & UINT_MAX) + (CDMMC_DMA_MAX_BUFFER_SIZE * i); 308*91f16700Schasinglulu desc->addr_hi = (dma_buff >> 32) & UINT_MAX; 309*91f16700Schasinglulu #else 310*91f16700Schasinglulu desc->addr_lo = (dma_buff & UINT_MAX); 311*91f16700Schasinglulu #endif 312*91f16700Schasinglulu 313*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS22, (uint32_t)desc_base); 314*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS23, (uint32_t)(desc_base >> 32)); 315*91f16700Schasinglulu flush_dcache_range(cdns_params.desc_base, 316*91f16700Schasinglulu desc_cnt * CDMMC_DMA_MAX_BUFFER_SIZE); 317*91f16700Schasinglulu 318*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS01, 319*91f16700Schasinglulu ((512 << BLOCK_SIZE) | ((size/512) << BLK_COUNT_CT) | SDMA_BUF)); 320*91f16700Schasinglulu return 0; 321*91f16700Schasinglulu } 322*91f16700Schasinglulu 323*91f16700Schasinglulu static void cdns_host_set_clk(int clk) 324*91f16700Schasinglulu { 325*91f16700Schasinglulu uint32_t ret = 0; 326*91f16700Schasinglulu uint32_t sdclkfsval = 0; 327*91f16700Schasinglulu uint32_t dtcvval = DTCVVAL_DEFAULT_VAL; 328*91f16700Schasinglulu 329*91f16700Schasinglulu sdclkfsval = (cdns_params.clk_rate / 2000) / clk; 330*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS11, 0); 331*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS11, (dtcvval << SDMMC_CDN_DTCV) | 332*91f16700Schasinglulu (sdclkfsval << SDMMC_CDN_SDCLKFS) | (1 << SDMMC_CDN_ICE)); 333*91f16700Schasinglulu 334*91f16700Schasinglulu ret = cdns_wait_ics(5000, MMC_REG_BASE + SDHC_CDNS_SRS11); 335*91f16700Schasinglulu if (ret != 0U) { 336*91f16700Schasinglulu ERROR("Waiting SDMMC_CDN_ICS timeout"); 337*91f16700Schasinglulu } 338*91f16700Schasinglulu 339*91f16700Schasinglulu /* Enable DLL reset */ 340*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS09, mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS09) & 341*91f16700Schasinglulu ~SDHC_DLL_RESET_MASK); 342*91f16700Schasinglulu /* Set extended_wr_mode */ 343*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS09, (mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS09) 344*91f16700Schasinglulu & SDHC_EXTENDED_WR_MODE_MASK) | (1 << EXTENDED_WR_MODE)); 345*91f16700Schasinglulu /* Release DLL reset */ 346*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS09, mmio_read_32(MMC_REG_BASE 347*91f16700Schasinglulu + SDHC_CDNS_HRS09) | 1); 348*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS09, mmio_read_32(MMC_REG_BASE 349*91f16700Schasinglulu + SDHC_CDNS_HRS09) | (3 << RDCMD_EN)); 350*91f16700Schasinglulu 351*91f16700Schasinglulu do { 352*91f16700Schasinglulu mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS09); 353*91f16700Schasinglulu } while (~mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS09) & (1 << 1)); 354*91f16700Schasinglulu 355*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS11, (dtcvval << SDMMC_CDN_DTCV) | 356*91f16700Schasinglulu (sdclkfsval << SDMMC_CDN_SDCLKFS) | (1 << SDMMC_CDN_ICE) | (1 << SDMMC_CDN_SDCE)); 357*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS13, UINT_MAX); 358*91f16700Schasinglulu } 359*91f16700Schasinglulu 360*91f16700Schasinglulu int cdns_set_ios(unsigned int clk, unsigned int width) 361*91f16700Schasinglulu { 362*91f16700Schasinglulu 363*91f16700Schasinglulu switch (width) { 364*91f16700Schasinglulu case MMC_BUS_WIDTH_1: 365*91f16700Schasinglulu mmio_write_32((MMC_REG_BASE + SDHC_CDNS_SRS10), LEDC_OFF); 366*91f16700Schasinglulu break; 367*91f16700Schasinglulu case MMC_BUS_WIDTH_4: 368*91f16700Schasinglulu mmio_write_32((MMC_REG_BASE + SDHC_CDNS_SRS10), DTW_4BIT); 369*91f16700Schasinglulu break; 370*91f16700Schasinglulu case MMC_BUS_WIDTH_8: 371*91f16700Schasinglulu mmio_write_32((MMC_REG_BASE + SDHC_CDNS_SRS10), EDTW_8BIT); 372*91f16700Schasinglulu break; 373*91f16700Schasinglulu default: 374*91f16700Schasinglulu assert(0); 375*91f16700Schasinglulu break; 376*91f16700Schasinglulu } 377*91f16700Schasinglulu cdns_host_set_clk(clk); 378*91f16700Schasinglulu 379*91f16700Schasinglulu return 0; 380*91f16700Schasinglulu } 381*91f16700Schasinglulu 382*91f16700Schasinglulu int cdns_sdmmc_write_sd_host_reg(uint32_t addr, uint32_t data) 383*91f16700Schasinglulu { 384*91f16700Schasinglulu uint32_t value = 0; 385*91f16700Schasinglulu 386*91f16700Schasinglulu value = mmio_read_32(addr); 387*91f16700Schasinglulu value &= ~SDHC_REG_MASK; 388*91f16700Schasinglulu value |= data; 389*91f16700Schasinglulu mmio_write_32(addr, value); 390*91f16700Schasinglulu value = mmio_read_32(addr); 391*91f16700Schasinglulu if (value != data) { 392*91f16700Schasinglulu ERROR("SD host address is not set properly\n"); 393*91f16700Schasinglulu return -ENXIO; 394*91f16700Schasinglulu } 395*91f16700Schasinglulu 396*91f16700Schasinglulu return 0; 397*91f16700Schasinglulu } 398*91f16700Schasinglulu 399*91f16700Schasinglulu int cdns_write(int lba, uintptr_t buf, size_t size) 400*91f16700Schasinglulu { 401*91f16700Schasinglulu return 0; 402*91f16700Schasinglulu } 403*91f16700Schasinglulu 404*91f16700Schasinglulu static int cdns_init_hrs_io(struct cdns_sdmmc_combo_phy *combo_phy_reg, 405*91f16700Schasinglulu struct cdns_sdmmc_sdhc *sdhc_reg) 406*91f16700Schasinglulu { 407*91f16700Schasinglulu uint32_t value = 0; 408*91f16700Schasinglulu int ret = 0; 409*91f16700Schasinglulu 410*91f16700Schasinglulu /* program HRS09, register 42 */ 411*91f16700Schasinglulu value = (SDHC_RDDATA_EN(sdhc_reg->sdhc_rddata_en)) 412*91f16700Schasinglulu | (SDHC_RDCMD_EN(sdhc_reg->sdhc_rdcmd_en)) 413*91f16700Schasinglulu | (SDHC_EXTENDED_WR_MODE(sdhc_reg->sdhc_extended_wr_mode)) 414*91f16700Schasinglulu | (SDHC_EXTENDED_RD_MODE(sdhc_reg->sdhc_extended_rd_mode)); 415*91f16700Schasinglulu ret = cdns_sdmmc_write_sd_host_reg(MMC_REG_BASE + SDHC_CDNS_HRS09, value); 416*91f16700Schasinglulu if (ret != 0) { 417*91f16700Schasinglulu ERROR("Program HRS09 failed"); 418*91f16700Schasinglulu return ret; 419*91f16700Schasinglulu } 420*91f16700Schasinglulu 421*91f16700Schasinglulu /* program HRS10, register 43 */ 422*91f16700Schasinglulu value = (SDHC_HCSDCLKADJ(sdhc_reg->sdhc_hcsdclkadj)); 423*91f16700Schasinglulu ret = cdns_sdmmc_write_sd_host_reg(MMC_REG_BASE + SDHC_CDNS_HRS10, value); 424*91f16700Schasinglulu if (ret != 0) { 425*91f16700Schasinglulu ERROR("Program HRS10 failed"); 426*91f16700Schasinglulu return ret; 427*91f16700Schasinglulu } 428*91f16700Schasinglulu 429*91f16700Schasinglulu /* program HRS16, register 48 */ 430*91f16700Schasinglulu value = (SDHC_WRDATA1_SDCLK_DLY(sdhc_reg->sdhc_wrdata1_sdclk_dly)) 431*91f16700Schasinglulu | (SDHC_WRDATA0_SDCLK_DLY(sdhc_reg->sdhc_wrdata0_sdclk_dly)) 432*91f16700Schasinglulu | (SDHC_WRCMD1_SDCLK_DLY(sdhc_reg->sdhc_wrcmd1_sdclk_dly)) 433*91f16700Schasinglulu | (SDHC_WRCMD0_SDCLK_DLY(sdhc_reg->sdhc_wrcmd0_sdclk_dly)) 434*91f16700Schasinglulu | (SDHC_WRDATA1_DLY(sdhc_reg->sdhc_wrdata1_dly)) 435*91f16700Schasinglulu | (SDHC_WRDATA0_DLY(sdhc_reg->sdhc_wrdata0_dly)) 436*91f16700Schasinglulu | (SDHC_WRCMD1_DLY(sdhc_reg->sdhc_wrcmd1_dly)) 437*91f16700Schasinglulu | (SDHC_WRCMD0_DLY(sdhc_reg->sdhc_wrcmd0_dly)); 438*91f16700Schasinglulu ret = cdns_sdmmc_write_sd_host_reg(MMC_REG_BASE + SDHC_CDNS_HRS16, value); 439*91f16700Schasinglulu if (ret != 0) { 440*91f16700Schasinglulu ERROR("Program HRS16 failed"); 441*91f16700Schasinglulu return ret; 442*91f16700Schasinglulu } 443*91f16700Schasinglulu 444*91f16700Schasinglulu /* program HRS07, register 40 */ 445*91f16700Schasinglulu value = (SDHC_RW_COMPENSATE(sdhc_reg->sdhc_rw_compensate)) 446*91f16700Schasinglulu | (SDHC_IDELAY_VAL(sdhc_reg->sdhc_idelay_val)); 447*91f16700Schasinglulu ret = cdns_sdmmc_write_sd_host_reg(MMC_REG_BASE + SDHC_CDNS_HRS07, value); 448*91f16700Schasinglulu if (ret != 0) { 449*91f16700Schasinglulu ERROR("Program HRS07 failed"); 450*91f16700Schasinglulu return ret; 451*91f16700Schasinglulu } 452*91f16700Schasinglulu 453*91f16700Schasinglulu return ret; 454*91f16700Schasinglulu } 455*91f16700Schasinglulu 456*91f16700Schasinglulu static int cdns_hc_set_clk(struct cdns_sdmmc_params *cdn_sdmmc_dev_mode_params) 457*91f16700Schasinglulu { 458*91f16700Schasinglulu uint32_t ret = 0; 459*91f16700Schasinglulu uint32_t dtcvval, sdclkfsval; 460*91f16700Schasinglulu 461*91f16700Schasinglulu dtcvval = DTC_VAL; 462*91f16700Schasinglulu sdclkfsval = 0; 463*91f16700Schasinglulu 464*91f16700Schasinglulu if ((cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == SD_DS) || 465*91f16700Schasinglulu (cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == SD_UHS_SDR12) || 466*91f16700Schasinglulu (cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == EMMC_SDR_BC)) { 467*91f16700Schasinglulu sdclkfsval = 4; 468*91f16700Schasinglulu } else if ((cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == SD_HS) || 469*91f16700Schasinglulu (cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == SD_UHS_SDR25) || 470*91f16700Schasinglulu (cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == SD_UHS_DDR50) || 471*91f16700Schasinglulu (cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == EMMC_SDR)) { 472*91f16700Schasinglulu sdclkfsval = 2; 473*91f16700Schasinglulu } else if ((cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == SD_UHS_SDR50) || 474*91f16700Schasinglulu (cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == EMMC_DDR) || 475*91f16700Schasinglulu (cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == EMMC_HS400) || 476*91f16700Schasinglulu (cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == EMMC_HS400es)) { 477*91f16700Schasinglulu sdclkfsval = 1; 478*91f16700Schasinglulu } else if ((cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == SD_UHS_SDR104) || 479*91f16700Schasinglulu (cdn_sdmmc_dev_mode_params->cdn_sdmmc_dev_mode == EMMC_HS200)) { 480*91f16700Schasinglulu sdclkfsval = 0; 481*91f16700Schasinglulu } 482*91f16700Schasinglulu 483*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS11, 0); 484*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS11, (dtcvval << SDMMC_CDN_DTCV) | 485*91f16700Schasinglulu (sdclkfsval << SDMMC_CDN_SDCLKFS) | (1 << SDMMC_CDN_ICE)); 486*91f16700Schasinglulu ret = cdns_wait_ics(5000, MMC_REG_BASE + SDHC_CDNS_SRS11); 487*91f16700Schasinglulu if (ret != 0U) { 488*91f16700Schasinglulu ERROR("Waiting SDMMC_CDN_ICS timeout"); 489*91f16700Schasinglulu return ret; 490*91f16700Schasinglulu } 491*91f16700Schasinglulu 492*91f16700Schasinglulu /* Enable DLL reset */ 493*91f16700Schasinglulu mmio_write_32((MMC_REG_BASE + SDHC_CDNS_HRS09), mmio_read_32(MMC_REG_BASE 494*91f16700Schasinglulu + SDHC_CDNS_HRS09) & ~SDHC_DLL_RESET_MASK); 495*91f16700Schasinglulu /* Set extended_wr_mode */ 496*91f16700Schasinglulu mmio_write_32((MMC_REG_BASE + SDHC_CDNS_HRS09), 497*91f16700Schasinglulu (mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS09) & SDHC_EXTENDED_WR_MODE_MASK) | 498*91f16700Schasinglulu (1 << EXTENDED_WR_MODE)); 499*91f16700Schasinglulu /* Release DLL reset */ 500*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS09, mmio_read_32(MMC_REG_BASE 501*91f16700Schasinglulu + SDHC_CDNS_HRS09) | 1); 502*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS09, mmio_read_32(MMC_REG_BASE 503*91f16700Schasinglulu + SDHC_CDNS_HRS09) | (3 << RDCMD_EN)); 504*91f16700Schasinglulu do { 505*91f16700Schasinglulu mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS09); 506*91f16700Schasinglulu } while (~mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS09) & (1 << 1)); 507*91f16700Schasinglulu 508*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS11, (dtcvval << SDMMC_CDN_DTCV) | 509*91f16700Schasinglulu (sdclkfsval << SDMMC_CDN_SDCLKFS) | (1 << SDMMC_CDN_ICE) | (1 << SDMMC_CDN_SDCE)); 510*91f16700Schasinglulu 511*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS13, UINT_MAX); 512*91f16700Schasinglulu return 0; 513*91f16700Schasinglulu } 514*91f16700Schasinglulu 515*91f16700Schasinglulu int cdns_reset(void) 516*91f16700Schasinglulu { 517*91f16700Schasinglulu uint32_t data = 0; 518*91f16700Schasinglulu uint32_t count = 0; 519*91f16700Schasinglulu uint32_t value = 0; 520*91f16700Schasinglulu 521*91f16700Schasinglulu value = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS11); 522*91f16700Schasinglulu value &= ~(0xFFFF); 523*91f16700Schasinglulu value |= 0x0; 524*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS11, value); 525*91f16700Schasinglulu udelay(500); 526*91f16700Schasinglulu 527*91f16700Schasinglulu /* Software reset */ 528*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS00, 1); 529*91f16700Schasinglulu /* Wait status command response ready */ 530*91f16700Schasinglulu do { 531*91f16700Schasinglulu data = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS00); 532*91f16700Schasinglulu count++; 533*91f16700Schasinglulu if (count >= 5000) { 534*91f16700Schasinglulu return -ETIMEDOUT; 535*91f16700Schasinglulu } 536*91f16700Schasinglulu /* Wait for HRS00.SWR */ 537*91f16700Schasinglulu } while ((data & 1) == 1); 538*91f16700Schasinglulu 539*91f16700Schasinglulu /* Step 1, switch on DLL_RESET */ 540*91f16700Schasinglulu value = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_HRS09); 541*91f16700Schasinglulu value &= ~SDHC_PHY_SW_RESET; 542*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_HRS09, value); 543*91f16700Schasinglulu 544*91f16700Schasinglulu return 0; 545*91f16700Schasinglulu } 546*91f16700Schasinglulu 547*91f16700Schasinglulu int cdns_sd_host_init(struct cdns_sdmmc_combo_phy *mmc_combo_phy_reg, 548*91f16700Schasinglulu struct cdns_sdmmc_sdhc *mmc_sdhc_reg) 549*91f16700Schasinglulu { 550*91f16700Schasinglulu int ret = 0; 551*91f16700Schasinglulu 552*91f16700Schasinglulu ret = cdns_reset(); 553*91f16700Schasinglulu if (ret != 0) { 554*91f16700Schasinglulu ERROR("Program phy reg init failed"); 555*91f16700Schasinglulu return ret; 556*91f16700Schasinglulu } 557*91f16700Schasinglulu 558*91f16700Schasinglulu ret = cdns_program_phy_reg(&sdmmc_combo_phy_reg, &sdmmc_sdhc_reg); 559*91f16700Schasinglulu if (ret != 0) { 560*91f16700Schasinglulu ERROR("Program phy reg init failed"); 561*91f16700Schasinglulu return ret; 562*91f16700Schasinglulu } 563*91f16700Schasinglulu 564*91f16700Schasinglulu ret = cdns_init_hrs_io(&sdmmc_combo_phy_reg, &sdmmc_sdhc_reg); 565*91f16700Schasinglulu if (ret != 0) { 566*91f16700Schasinglulu ERROR("Program init for HRS reg is failed"); 567*91f16700Schasinglulu return ret; 568*91f16700Schasinglulu } 569*91f16700Schasinglulu 570*91f16700Schasinglulu ret = cdns_sd_card_detect(); 571*91f16700Schasinglulu if (ret != 0) { 572*91f16700Schasinglulu ERROR("SD card does not detect"); 573*91f16700Schasinglulu return ret; 574*91f16700Schasinglulu } 575*91f16700Schasinglulu 576*91f16700Schasinglulu ret = cdns_vol_reset(); 577*91f16700Schasinglulu if (ret != 0) { 578*91f16700Schasinglulu ERROR("eMMC card reset failed"); 579*91f16700Schasinglulu return ret; 580*91f16700Schasinglulu } 581*91f16700Schasinglulu 582*91f16700Schasinglulu ret = cdns_hc_set_clk(&cdns_params); 583*91f16700Schasinglulu if (ret != 0) { 584*91f16700Schasinglulu ERROR("hc set clk failed"); 585*91f16700Schasinglulu return ret; 586*91f16700Schasinglulu } 587*91f16700Schasinglulu 588*91f16700Schasinglulu return 0; 589*91f16700Schasinglulu } 590*91f16700Schasinglulu 591*91f16700Schasinglulu void cdns_srs10_value_toggle(uint8_t write_val, uint8_t prev_val) 592*91f16700Schasinglulu { 593*91f16700Schasinglulu uint32_t data_op = 0U; 594*91f16700Schasinglulu 595*91f16700Schasinglulu data_op = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS10); 596*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS10, (data_op & (prev_val << 0))); 597*91f16700Schasinglulu mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS10); 598*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS10, data_op | (write_val << 0)); 599*91f16700Schasinglulu } 600*91f16700Schasinglulu 601*91f16700Schasinglulu void cdns_srs11_srs15_config(uint32_t srs11_val, uint32_t srs15_val) 602*91f16700Schasinglulu { 603*91f16700Schasinglulu uint32_t data = 0U; 604*91f16700Schasinglulu 605*91f16700Schasinglulu data = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS11); 606*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS11, (data | srs11_val)); 607*91f16700Schasinglulu data = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS15); 608*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS15, (data | srs15_val)); 609*91f16700Schasinglulu } 610*91f16700Schasinglulu 611*91f16700Schasinglulu int cdns_send_cmd(struct mmc_cmd *cmd) 612*91f16700Schasinglulu { 613*91f16700Schasinglulu uint32_t op = 0, ret = 0; 614*91f16700Schasinglulu uint8_t write_value = 0, prev_val = 0; 615*91f16700Schasinglulu uint32_t value; 616*91f16700Schasinglulu int32_t timeout; 617*91f16700Schasinglulu uint32_t cmd_indx; 618*91f16700Schasinglulu uint32_t status = 0, srs15_val = 0, srs11_val = 0; 619*91f16700Schasinglulu uint32_t status_check = 0; 620*91f16700Schasinglulu 621*91f16700Schasinglulu assert(cmd); 622*91f16700Schasinglulu cmd_indx = (cmd->cmd_idx) << COM_IDX; 623*91f16700Schasinglulu 624*91f16700Schasinglulu if (data_cmd) { 625*91f16700Schasinglulu switch (cmd->cmd_idx) { 626*91f16700Schasinglulu case SD_SWITCH: 627*91f16700Schasinglulu op = DATA_PRESENT; 628*91f16700Schasinglulu write_value = ADMA2_32 | DT_WIDTH; 629*91f16700Schasinglulu prev_val = ADMA2_32 | DT_WIDTH; 630*91f16700Schasinglulu cdns_srs10_value_toggle(write_value, prev_val); 631*91f16700Schasinglulu srs11_val = READ_CLK | SDMMC_CDN_ICE | SDMMC_CDN_ICS | SDMMC_CDN_SDCE; 632*91f16700Schasinglulu srs15_val = BIT_AD_64 | HV4E | V18SE; 633*91f16700Schasinglulu cdns_srs11_srs15_config(srs11_val, srs15_val); 634*91f16700Schasinglulu break; 635*91f16700Schasinglulu 636*91f16700Schasinglulu case SD_WRITE_SINGLE_BLOCK: 637*91f16700Schasinglulu case SD_READ_SINGLE_BLOCK: 638*91f16700Schasinglulu op = DATA_PRESENT; 639*91f16700Schasinglulu write_value = ADMA2_32 | HS_EN | DT_WIDTH | LEDC; 640*91f16700Schasinglulu prev_val = ADMA2_32 | HS_EN | DT_WIDTH; 641*91f16700Schasinglulu cdns_srs10_value_toggle(write_value, prev_val); 642*91f16700Schasinglulu srs15_val = PVE | BIT_AD_64 | HV4E | SDR104_MODE | V18SE; 643*91f16700Schasinglulu srs11_val = READ_CLK | SDMMC_CDN_ICE | SDMMC_CDN_ICS | SDMMC_CDN_SDCE; 644*91f16700Schasinglulu cdns_srs11_srs15_config(srs11_val, srs15_val); 645*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS00, SAAR); 646*91f16700Schasinglulu break; 647*91f16700Schasinglulu 648*91f16700Schasinglulu case SD_WRITE_MULTIPLE_BLOCK: 649*91f16700Schasinglulu case SD_READ_MULTIPLE_BLOCK: 650*91f16700Schasinglulu op = DATA_PRESENT | AUTO_CMD_EN | MULTI_BLK_READ; 651*91f16700Schasinglulu write_value = ADMA2_32 | HS_EN | DT_WIDTH | LEDC; 652*91f16700Schasinglulu prev_val = ADMA2_32 | HS_EN | DT_WIDTH; 653*91f16700Schasinglulu cdns_srs10_value_toggle(write_value, prev_val); 654*91f16700Schasinglulu srs15_val = PVE | BIT_AD_64 | HV4E | SDR104_MODE | V18SE; 655*91f16700Schasinglulu srs11_val = READ_CLK | SDMMC_CDN_ICE | SDMMC_CDN_ICS | SDMMC_CDN_SDCE; 656*91f16700Schasinglulu cdns_srs11_srs15_config(srs11_val, srs15_val); 657*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS00, SAAR); 658*91f16700Schasinglulu break; 659*91f16700Schasinglulu 660*91f16700Schasinglulu case SD_APP_SEND_SCR: 661*91f16700Schasinglulu op = DATA_PRESENT; 662*91f16700Schasinglulu write_value = ADMA2_32 | LEDC; 663*91f16700Schasinglulu prev_val = LEDC; 664*91f16700Schasinglulu cdns_srs10_value_toggle(write_value, prev_val); 665*91f16700Schasinglulu srs15_val = BIT_AD_64 | HV4E | V18SE; 666*91f16700Schasinglulu srs11_val = READ_CLK | SDMMC_CDN_ICE | SDMMC_CDN_ICS | SDMMC_CDN_SDCE; 667*91f16700Schasinglulu cdns_srs11_srs15_config(srs11_val, srs15_val); 668*91f16700Schasinglulu break; 669*91f16700Schasinglulu 670*91f16700Schasinglulu case SD_SEND_IF_COND: 671*91f16700Schasinglulu op = DATA_PRESENT | CMD_IDX_CHK_ENABLE; 672*91f16700Schasinglulu write_value = LEDC; 673*91f16700Schasinglulu prev_val = 0x0; 674*91f16700Schasinglulu cdns_srs10_value_toggle(write_value, prev_val); 675*91f16700Schasinglulu srs15_val = HV4E; 676*91f16700Schasinglulu srs11_val = READ_CLK | SDMMC_CDN_ICE | SDMMC_CDN_ICS | SDMMC_CDN_SDCE; 677*91f16700Schasinglulu cdns_srs11_srs15_config(srs11_val, srs15_val); 678*91f16700Schasinglulu break; 679*91f16700Schasinglulu 680*91f16700Schasinglulu default: 681*91f16700Schasinglulu write_value = LEDC; 682*91f16700Schasinglulu prev_val = 0x0; 683*91f16700Schasinglulu cdns_srs10_value_toggle(write_value, prev_val); 684*91f16700Schasinglulu op = 0; 685*91f16700Schasinglulu break; 686*91f16700Schasinglulu } 687*91f16700Schasinglulu } else { 688*91f16700Schasinglulu switch (cmd->cmd_idx) { 689*91f16700Schasinglulu case SD_GO_IDLE_STATE: 690*91f16700Schasinglulu write_value = LEDC; 691*91f16700Schasinglulu prev_val = 0x0; 692*91f16700Schasinglulu cdns_srs10_value_toggle(write_value, prev_val); 693*91f16700Schasinglulu srs15_val = HV4E; 694*91f16700Schasinglulu srs11_val = SDMMC_CDN_ICE | SDMMC_CDN_ICS | SDMMC_CDN_SDCE; 695*91f16700Schasinglulu cdns_srs11_srs15_config(srs11_val, srs15_val); 696*91f16700Schasinglulu break; 697*91f16700Schasinglulu 698*91f16700Schasinglulu case SD_ALL_SEND_CID: 699*91f16700Schasinglulu write_value = LEDC; 700*91f16700Schasinglulu prev_val = 0x0; 701*91f16700Schasinglulu cdns_srs10_value_toggle(write_value, prev_val); 702*91f16700Schasinglulu srs15_val = HV4E | V18SE; 703*91f16700Schasinglulu srs11_val = SDMMC_CDN_ICE | SDMMC_CDN_ICS | SDMMC_CDN_SDCE; 704*91f16700Schasinglulu cdns_srs11_srs15_config(srs11_val, srs15_val); 705*91f16700Schasinglulu break; 706*91f16700Schasinglulu 707*91f16700Schasinglulu case SD_SEND_IF_COND: 708*91f16700Schasinglulu op = CMD_IDX_CHK_ENABLE; 709*91f16700Schasinglulu write_value = LEDC; 710*91f16700Schasinglulu prev_val = 0x0; 711*91f16700Schasinglulu cdns_srs10_value_toggle(write_value, prev_val); 712*91f16700Schasinglulu srs15_val = HV4E; 713*91f16700Schasinglulu srs11_val = READ_CLK | SDMMC_CDN_ICE | SDMMC_CDN_ICS | SDMMC_CDN_SDCE; 714*91f16700Schasinglulu cdns_srs11_srs15_config(srs11_val, srs15_val); 715*91f16700Schasinglulu break; 716*91f16700Schasinglulu 717*91f16700Schasinglulu case SD_STOP_TRANSMISSION: 718*91f16700Schasinglulu op = CMD_STOP_ABORT_CMD; 719*91f16700Schasinglulu break; 720*91f16700Schasinglulu 721*91f16700Schasinglulu case SD_SEND_STATUS: 722*91f16700Schasinglulu break; 723*91f16700Schasinglulu 724*91f16700Schasinglulu case 1: 725*91f16700Schasinglulu cmd->cmd_arg = 0; 726*91f16700Schasinglulu break; 727*91f16700Schasinglulu 728*91f16700Schasinglulu case SD_SELECT_CARD: 729*91f16700Schasinglulu op = MULTI_BLK_READ; 730*91f16700Schasinglulu break; 731*91f16700Schasinglulu 732*91f16700Schasinglulu case SD_APP_CMD: 733*91f16700Schasinglulu default: 734*91f16700Schasinglulu write_value = LEDC; 735*91f16700Schasinglulu prev_val = 0x0; 736*91f16700Schasinglulu cdns_srs10_value_toggle(write_value, prev_val); 737*91f16700Schasinglulu op = 0; 738*91f16700Schasinglulu break; 739*91f16700Schasinglulu } 740*91f16700Schasinglulu } 741*91f16700Schasinglulu 742*91f16700Schasinglulu switch (cmd->resp_type) { 743*91f16700Schasinglulu case MMC_RESPONSE_NONE: 744*91f16700Schasinglulu op |= CMD_READ | MULTI_BLK_READ | DMA_ENABLED | BLK_CNT_EN; 745*91f16700Schasinglulu break; 746*91f16700Schasinglulu 747*91f16700Schasinglulu case MMC_RESPONSE_R2: 748*91f16700Schasinglulu op |= CMD_READ | MULTI_BLK_READ | DMA_ENABLED | BLK_CNT_EN | 749*91f16700Schasinglulu RES_TYPE_SEL_136 | CMD_CHECK_RESP_CRC; 750*91f16700Schasinglulu break; 751*91f16700Schasinglulu 752*91f16700Schasinglulu case MMC_RESPONSE_R3: 753*91f16700Schasinglulu op |= CMD_READ | MULTI_BLK_READ | DMA_ENABLED | BLK_CNT_EN | 754*91f16700Schasinglulu RES_TYPE_SEL_48; 755*91f16700Schasinglulu break; 756*91f16700Schasinglulu 757*91f16700Schasinglulu case MMC_RESPONSE_R1: 758*91f16700Schasinglulu if ((cmd->cmd_idx == SD_WRITE_SINGLE_BLOCK) || (cmd->cmd_idx 759*91f16700Schasinglulu == SD_WRITE_MULTIPLE_BLOCK)) { 760*91f16700Schasinglulu op |= DMA_ENABLED | BLK_CNT_EN | RES_TYPE_SEL_48 761*91f16700Schasinglulu | CMD_CHECK_RESP_CRC | CMD_IDX_CHK_ENABLE; 762*91f16700Schasinglulu } else { 763*91f16700Schasinglulu op |= DMA_ENABLED | BLK_CNT_EN | CMD_READ | RES_TYPE_SEL_48 764*91f16700Schasinglulu | CMD_CHECK_RESP_CRC | CMD_IDX_CHK_ENABLE; 765*91f16700Schasinglulu } 766*91f16700Schasinglulu break; 767*91f16700Schasinglulu 768*91f16700Schasinglulu default: 769*91f16700Schasinglulu op |= DMA_ENABLED | BLK_CNT_EN | CMD_READ | MULTI_BLK_READ | 770*91f16700Schasinglulu RES_TYPE_SEL_48 | CMD_CHECK_RESP_CRC | CMD_IDX_CHK_ENABLE; 771*91f16700Schasinglulu break; 772*91f16700Schasinglulu } 773*91f16700Schasinglulu 774*91f16700Schasinglulu timeout = TIMEOUT; 775*91f16700Schasinglulu do { 776*91f16700Schasinglulu udelay(100); 777*91f16700Schasinglulu ret = cdns_busy(); 778*91f16700Schasinglulu if (--timeout <= 0) { 779*91f16700Schasinglulu udelay(50); 780*91f16700Schasinglulu panic(); 781*91f16700Schasinglulu } 782*91f16700Schasinglulu } while (ret); 783*91f16700Schasinglulu 784*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS12, UINT_MAX); 785*91f16700Schasinglulu 786*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS02, cmd->cmd_arg); 787*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS14, 0x00000000); 788*91f16700Schasinglulu if (cmd_indx == 1) 789*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS03, SDHC_CDNS_SRS03_VALUE); 790*91f16700Schasinglulu else 791*91f16700Schasinglulu mmio_write_32(MMC_REG_BASE + SDHC_CDNS_SRS03, op | cmd_indx); 792*91f16700Schasinglulu 793*91f16700Schasinglulu timeout = TIMEOUT; 794*91f16700Schasinglulu do { 795*91f16700Schasinglulu udelay(500); 796*91f16700Schasinglulu value = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS12); 797*91f16700Schasinglulu } while (((value & (INT_CMD_DONE | ERROR_INT)) == 0) && (timeout-- > 0)); 798*91f16700Schasinglulu 799*91f16700Schasinglulu timeout = TIMEOUT; 800*91f16700Schasinglulu 801*91f16700Schasinglulu if (data_cmd) { 802*91f16700Schasinglulu data_cmd = false; 803*91f16700Schasinglulu do { 804*91f16700Schasinglulu udelay(250); 805*91f16700Schasinglulu } while (((value & TRAN_COMP) == 0) && (timeout-- > 0)); 806*91f16700Schasinglulu } 807*91f16700Schasinglulu 808*91f16700Schasinglulu status_check = value & SRS12_ERR_MASK; 809*91f16700Schasinglulu if (status_check != 0U) { 810*91f16700Schasinglulu ERROR("SD host controller send command failed, SRS12 = %x", status); 811*91f16700Schasinglulu return -1; 812*91f16700Schasinglulu } 813*91f16700Schasinglulu 814*91f16700Schasinglulu if ((op & RES_TYPE_SEL_48) || (op & RES_TYPE_SEL_136)) { 815*91f16700Schasinglulu cmd->resp_data[0] = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS04); 816*91f16700Schasinglulu if (op & RES_TYPE_SEL_136) { 817*91f16700Schasinglulu cmd->resp_data[1] = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS05); 818*91f16700Schasinglulu cmd->resp_data[2] = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS06); 819*91f16700Schasinglulu cmd->resp_data[3] = mmio_read_32(MMC_REG_BASE + SDHC_CDNS_SRS07); 820*91f16700Schasinglulu } 821*91f16700Schasinglulu } 822*91f16700Schasinglulu 823*91f16700Schasinglulu return 0; 824*91f16700Schasinglulu } 825