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 | ||||
| -rw-r--r-- | plat/intel/soc/common/soc/socfpga_reset_manager.c | 31 | ||||
| -rw-r--r-- | plat/xilinx/common/pm_service/pm_ipi.c | 4 |
6 files changed, 78 insertions, 62 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, diff --git a/plat/intel/soc/common/soc/socfpga_reset_manager.c b/plat/intel/soc/common/soc/socfpga_reset_manager.c index c9145e687..e461810fa 100644 --- a/plat/intel/soc/common/soc/socfpga_reset_manager.c +++ b/plat/intel/soc/common/soc/socfpga_reset_manager.c @@ -836,35 +836,23 @@ int socfpga_bridges_enable(uint32_t mask) return ret; } -int socfpga_bridge_nongraceful_disable(uint32_t mask) +int socfpga_bridge_nongraceful_disable(uint32_t f2s_force_drain, + uint32_t f2s_respempty) { int ret = 0; - int timeout = 1000; - uint32_t brg_mask = 0; - uint32_t f2s_idlereq = 0; - uint32_t f2s_force_drain = 0; - uint32_t f2s_en = 0; - uint32_t f2s_idleack = 0; - uint32_t f2s_respempty = 0; - uint32_t f2s_cmdidle = 0; - - socfpga_f2s_bridge_mask(mask, &brg_mask, &f2s_idlereq, - &f2s_force_drain, &f2s_en, - &f2s_idleack, &f2s_respempty, &f2s_cmdidle); - - mmio_setbits_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGOUTSET0), - f2s_idlereq); + int timeout = 300; + uint32_t idle_status = 0; /* Time out Error - Bus is still active */ /* Performing a non-graceful shutdown with Force drain */ mmio_setbits_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGOUTSET0), f2s_force_drain); + udelay(5); ret = -ETIMEDOUT; - do { - /* Read response queue status to ensure it is empty */ - uint32_t idle_status; + /* Read response queue status to ensure it is empty */ + do { idle_status = mmio_read_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGINSTATUS0)); if ((idle_status & f2s_respempty) != 0U) { idle_status = mmio_read_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGINSTATUS0)); @@ -875,7 +863,7 @@ int socfpga_bridge_nongraceful_disable(uint32_t mask) } } - asm("nop"); + udelay(1000); } while (timeout-- > 0); @@ -1188,7 +1176,8 @@ int socfpga_bridges_disable(uint32_t mask) f2s_en); udelay(5); - ret = socfpga_bridge_nongraceful_disable(mask); + ret = socfpga_bridge_nongraceful_disable(f2s_force_drain, + f2s_respempty); /* Bridge reset */ #if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10 diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c index b67e44296..c3ba06b0b 100644 --- a/plat/xilinx/common/pm_service/pm_ipi.c +++ b/plat/xilinx/common/pm_service/pm_ipi.c @@ -225,7 +225,8 @@ enum pm_ret_status pm_ipi_buff_read_callb(uint32_t *value, size_t count) enum pm_ret_status ret = PM_RET_SUCCESS; if (count > (size_t)IPI_BUFFER_MAX_WORDS) { - return PM_RET_ERROR_ARGS; + ret = PM_RET_ERROR_ARGS; + goto exit_label; } for (i = 0; i < count; i++) { @@ -246,6 +247,7 @@ enum pm_ret_status pm_ipi_buff_read_callb(uint32_t *value, size_t count) memset(value, 0, local_count); } #endif +exit_label: return ret; } |
