diff options
| -rw-r--r-- | drivers/cadence/combo_phy/cdns_combo_phy.c | 17 | ||||
| -rw-r--r-- | drivers/cadence/emmc/cdns_sdmmc.c | 75 | ||||
| -rw-r--r-- | include/drivers/cadence/cdns_combo_phy.h | 1 | ||||
| -rw-r--r-- | include/drivers/cadence/cdns_sdmmc.h | 12 |
4 files changed, 65 insertions, 40 deletions
diff --git a/drivers/cadence/combo_phy/cdns_combo_phy.c b/drivers/cadence/combo_phy/cdns_combo_phy.c index f00d0c100..87f176f9c 100644 --- a/drivers/cadence/combo_phy/cdns_combo_phy.c +++ b/drivers/cadence/combo_phy/cdns_combo_phy.c @@ -64,20 +64,3 @@ int cdns_sd_card_detect(void) return 0; } - -int cdns_emmc_card_reset(void) -{ - uint32_t _status = 0; - - /* Reset embedded card */ - mmio_write_32(SDMMC_CDN(SRS10), (7 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP) | _status); - mdelay(68680); /* ~68680us */ - mmio_write_32(SDMMC_CDN(SRS10), (7 << SDMMC_CDN_BVS) | (0 << SDMMC_CDN_BP)); - udelay(340); /* ~340us */ - - /* Turn on supply voltage */ - /* BVS = 7, BP = 1, BP2 only in UHS2 mode */ - mmio_write_32(SDMMC_CDN(SRS10), (7 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP) | _status); - - return 0; -} diff --git a/drivers/cadence/emmc/cdns_sdmmc.c b/drivers/cadence/emmc/cdns_sdmmc.c index 1dd81f8ed..b984cf5d4 100644 --- a/drivers/cadence/emmc/cdns_sdmmc.c +++ b/drivers/cadence/emmc/cdns_sdmmc.c @@ -427,20 +427,23 @@ void sd_host_oper_mode(enum sd_opr_modes opr_mode) } } -void card_reset(bool power_enable) +void cdns_sdmmc_card_reset(void) { uint32_t reg_value = 0; - /* Reading SRS10 value before writing */ + /* Power off: per SDHCI/JEDEC spec, BVS must be cleared when BP=0 */ reg_value = mmio_read_32(cdns_params.reg_base + SDHC_CDNS_SRS10); + reg_value &= ~((7 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP)); + mmio_write_32(cdns_params.reg_base + SDHC_CDNS_SRS10, reg_value); + mdelay(20); - if (power_enable == true) { - reg_value &= ~((7 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP)); - reg_value = ((1 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP)); - } else { - reg_value &= ~((7 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP)); - } + /* + * BVS=0b111 = 3.3V ; BVS=0b101 = 1.8V + * Using 3.3V for High Speed(SD)/legacy(eMMC) protocol. + */ + reg_value |= ((7 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP)); mmio_write_32(cdns_params.reg_base + SDHC_CDNS_SRS10, reg_value); + mdelay(50); } void high_speed_enable(bool mode) @@ -501,14 +504,8 @@ void sdmmc_host_init(bool uhs2_enable) /** need to implement*/ } - /* Card reset */ - - card_reset(1); - udelay(2500); - card_reset(0); - udelay(2500); - card_reset(1); - udelay(2500); + /* Card reset - for both eMMC and SD card */ + cdns_sdmmc_card_reset(); /* Enable Interrupt Flags*/ mmio_write_32((cdns_params.reg_base + SDHC_CDNS_SRS13), ~0); @@ -558,7 +555,7 @@ int cdns_send_cmd(struct mmc_cmd *cmd) timeout = TIMEOUT; do { udelay(100); - if (--timeout <= 0) { + if (--timeout == 0) { udelay(50); NOTICE("Timeout occur data and cmd line %x\n", mmio_read_32(cdns_params.reg_base + SDHC_CDNS_SRS09)); @@ -622,10 +619,42 @@ int cdns_send_cmd(struct mmc_cmd *cmd) timeout = TIMEOUT; + /* Wait for command completion or error */ do { udelay(CDNS_TIMEOUT); status = mmio_read_32(cdns_params.reg_base + SDHC_CDNS_SRS12); - } while (((status & (INT_CMD_DONE | ERROR_INT)) == 0) && (timeout-- > 0)); + if (--timeout == 0) { + ERROR("Command %u timeout waiting for response\n", + cmd->cmd_idx); + break; + } + } while (((status & (INT_CMD_DONE | ERROR_INT)) == 0)); + + /* For data commands, wait for Data Transfer Over (DTO) or data ready */ + if ((cmd_flags & DATA_PRESENT) != 0U) { + timeout = TIMEOUT; + do { + udelay(100); + status = mmio_read_32(cdns_params.reg_base + + SDHC_CDNS_SRS12); + if (--timeout == 0) { + ERROR("Command %u timeout waiting for data\n", + cmd->cmd_idx); + ERROR("SRS12=0x%08x SRS09=0x%08x\n", + mmio_read_32(cdns_params.reg_base + + SDHC_CDNS_SRS12), + mmio_read_32(cdns_params.reg_base + + SDHC_CDNS_SRS09)); + break; + } + /* + * In ADMA2 mode the controller raises Transfer Complete (bit 1) + * when the DMA finishes, TRAN_COMP. + */ + } while (((status & + (INT_DTO | INT_TXDR | INT_RXDR | TRAN_COMP)) == 0) && + ((status & ERROR_INT) == 0)); + } mmio_write_32(cdns_params.reg_base + SDHC_CDNS_SRS12, (SRS_12_CC_EN)); status_check = mmio_read_32(cdns_params.reg_base + SDHC_CDNS_SRS12) & 0xffff8000; @@ -735,17 +764,23 @@ int cdns_mmc_init(struct cdns_sdmmc_params *params, memcpy(&cdns_params, params, sizeof(struct cdns_sdmmc_params)); + /* + * Set device type before cdns_sd_host_init() so sdmmc_host_init() + * can branch between eMMC and SD card reset sequences. + */ + cdns_params.cdn_sdmmc_dev_type = info->mmc_dev_type; + cdns_set_sdmmc_var(&sdmmc_combo_phy_reg, &sdmmc_sdhc_reg); result = cdns_sd_host_init(&sdmmc_combo_phy_reg, &sdmmc_sdhc_reg); if (result < 0) { return result; } - cdns_params.cdn_sdmmc_dev_type = info->mmc_dev_type; cdns_params.cdn_sdmmc_dev_mode = SD_DS; + /* Select operating clock based on detected device type */ result = mmc_init(&cdns_sdmmc_ops, params->clk_rate, params->bus_width, - params->flags, info); + params->flags, info); return result; } diff --git a/include/drivers/cadence/cdns_combo_phy.h b/include/drivers/cadence/cdns_combo_phy.h index 4d3a75394..8dddbee16 100644 --- a/include/drivers/cadence/cdns_combo_phy.h +++ b/include/drivers/cadence/cdns_combo_phy.h @@ -234,6 +234,5 @@ struct cdns_sdmmc_combo_phy { int cdns_sdmmc_write_phy_reg(uint32_t phy_reg_addr, uint32_t phy_reg_addr_value, uint32_t phy_reg_data, uint32_t phy_reg_data_value); int cdns_sd_card_detect(void); -int cdns_emmc_card_reset(void); #endif
\ No newline at end of file diff --git a/include/drivers/cadence/cdns_sdmmc.h b/include/drivers/cadence/cdns_sdmmc.h index f4485ca8d..69ee5a1c9 100644 --- a/include/drivers/cadence/cdns_sdmmc.h +++ b/include/drivers/cadence/cdns_sdmmc.h @@ -12,6 +12,8 @@ #include <drivers/cadence/cdns_combo_phy.h> #include <drivers/mmc.h> +#include <platform_def.h> + #if MMC_DEVICE_TYPE == 0 #define CONFIG_DMA_ADDR_T_64BIT 0 #endif @@ -446,10 +448,16 @@ #define CONFIG_CDNS_DESC_COUNT 8 /* - * To accommodate SDMCLK set to 200MHz - * TODO: To support various clock range + * SD card, according to SD Host Controller Simplified Specification + * will be using High Speed default 50MHz as we have enabled HS mode. + * eMMC, according to JEDEC JESD84-B51, will be using legacy default + * 26MHz for max compatibility. */ +#if MMC_DEVICE_TYPE == 1 #define SDEMMC_SDCLK 50000000U +#else +#define SDEMMC_SDCLK 26000000U +#endif enum sd_opcode { SD_GO_IDLE_STATE = 0, |
