summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/cadence/combo_phy/cdns_combo_phy.c17
-rw-r--r--drivers/cadence/emmc/cdns_sdmmc.c75
-rw-r--r--include/drivers/cadence/cdns_combo_phy.h1
-rw-r--r--include/drivers/cadence/cdns_sdmmc.h12
-rw-r--r--plat/intel/soc/common/soc/socfpga_reset_manager.c31
-rw-r--r--plat/xilinx/common/pm_service/pm_ipi.c4
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;
}