@@ -574,6 +574,14 @@ config MMC_SDHCI_CADENCE
If unsure, say N.
+config MMC_SDHCI_CADENCE_DEBUG
+ bool "Debug support for the Cadence SD/SDIO/eMMC controller"
+ depends on MMC_SDHCI_CADENCE
+ default n
+ help
+ This enables additional debug messages from cadence SDHCI
+ driver.
+
config MMC_SDHCI_AM654
bool "SDHCI Controller on TI's Am654 devices"
depends on ARCH_K3
@@ -18,6 +18,11 @@
#include <linux/libfdt.h>
#include <mmc.h>
#include <sdhci.h>
+#ifdef CONFIG_MMC_SDHCI_CADENCE_DEBUG
+#define DEBUG_DRV(fmt, ...) \
+ if (1) \
+ printf(fmt, ##__VA_ARGS__)
+#endif
#define SDHCI_CDNS_SD6_MAXCLK 200000000
@@ -492,6 +497,72 @@ static u32 sdhci_cdns_sd6_read_phy_reg(struct sdhci_cdns_plat *plat,
return readl(plat->hrs_addr + SDHCI_CDNS_HRS05);
}
+#ifdef CONFIG_MMC_SDHCI_CADENCE_DEBUG
+void sdhci_cdns_sd6_dump(struct sdhci_cdns_plat *plat)
+{
+ int i;
+
+ for (i = 0; i < 14; i++)
+ DEBUG_DRV("HRS%d 0x%x\n", i, readl(plat->hrs_addr + (i * 4)));
+
+ for (i = 0; i < 27; i++)
+ DEBUG_DRV("SRS%d 0x%x\n", i, readl(plat->hrs_addr + 0x200 + (i * 4)));
+
+ DEBUG_DRV("SDHCI_CDNS_SD6_PHY_DLL_SLAVE 0x%x\n",
+ sdhci_cdns_sd6_read_phy_reg(plat, SDHCI_CDNS_SD6_PHY_DLL_SLAVE));
+ DEBUG_DRV("SDHCI_CDNS_SD6_PHY_CTRL 0x%x\n",
+ sdhci_cdns_sd6_read_phy_reg(plat, SDHCI_CDNS_SD6_PHY_CTRL));
+ DEBUG_DRV("SDHCI_CDNS_SD6_PHY_DLL_MASTER 0x%x\n",
+ sdhci_cdns_sd6_read_phy_reg(plat, SDHCI_CDNS_SD6_PHY_DLL_MASTER));
+ DEBUG_DRV("SDHCI_CDNS_SD6_PHY_GATE_LPBK 0x%x\n",
+ sdhci_cdns_sd6_read_phy_reg(plat, SDHCI_CDNS_SD6_PHY_GATE_LPBK));
+ DEBUG_DRV("SDHCI_CDNS_SD6_PHY_DQS_TIMING 0x%x\n",
+ sdhci_cdns_sd6_read_phy_reg(plat, SDHCI_CDNS_SD6_PHY_DQS_TIMING));
+}
+
+static void sdhci_cdns_sd6_phy_dump(struct sdhci_cdns_sd6_phy *phy)
+{
+ DEBUG_DRV("sdhci_cdns_sd6_phy_init mode %d t_sdclk %d\n", phy->mode, phy->t_sdclk);
+ DEBUG_DRV("cp_clk_wr_delay %d\n", phy->settings.cp_clk_wr_delay);
+ DEBUG_DRV("cp_clk_wrdqs_delay %d\n", phy->settings.cp_clk_wrdqs_delay);
+ DEBUG_DRV("cp_data_select_oe_end %d\n", phy->settings.cp_data_select_oe_end);
+ DEBUG_DRV("cp_dll_bypass_mode %d\n", phy->settings.cp_dll_bypass_mode);
+ DEBUG_DRV("cp_dll_locked_mode %d\n", phy->settings.cp_dll_locked_mode);
+ DEBUG_DRV("cp_dll_start_point %d\n", phy->settings.cp_dll_start_point);
+ DEBUG_DRV("cp_io_mask_always_on %d\n", phy->settings.cp_io_mask_always_on);
+ DEBUG_DRV("cp_io_mask_end %d\n", phy->settings.cp_io_mask_end);
+ DEBUG_DRV("cp_io_mask_start %d\n", phy->settings.cp_io_mask_start);
+ DEBUG_DRV("cp_rd_del_sel %d\n", phy->settings.cp_rd_del_sel);
+ DEBUG_DRV("cp_read_dqs_cmd_delay %d\n", phy->settings.cp_read_dqs_cmd_delay);
+ DEBUG_DRV("cp_read_dqs_delay %d\n", phy->settings.cp_read_dqs_delay);
+ DEBUG_DRV("cp_sw_half_cycle_shift %d\n", phy->settings.cp_sw_half_cycle_shift);
+ DEBUG_DRV("cp_sync_method %d\n", phy->settings.cp_sync_method);
+ DEBUG_DRV("cp_use_ext_lpbk_dqs %d\n", phy->settings.cp_use_ext_lpbk_dqs);
+ DEBUG_DRV("cp_use_lpbk_dqs %d\n", phy->settings.cp_use_lpbk_dqs);
+ DEBUG_DRV("cp_use_phony_dqs %d\n", phy->settings.cp_use_phony_dqs);
+ DEBUG_DRV("cp_use_phony_dqs_cmd %d\n", phy->settings.cp_use_phony_dqs_cmd);
+ DEBUG_DRV("sdhc_extended_rd_mode %d\n", phy->settings.sdhc_extended_rd_mode);
+ DEBUG_DRV("sdhc_extended_wr_mode %d\n", phy->settings.sdhc_extended_wr_mode);
+ DEBUG_DRV("sdhc_hcsdclkadj %d\n", phy->settings.sdhc_hcsdclkadj);
+ DEBUG_DRV("sdhc_idelay_val %d\n", phy->settings.sdhc_idelay_val);
+ DEBUG_DRV("sdhc_rdcmd_en %d\n", phy->settings.sdhc_rdcmd_en);
+ DEBUG_DRV("sdhc_rddata_en %d\n", phy->settings.sdhc_rddata_en);
+ DEBUG_DRV("sdhc_rw_compensate %d\n", phy->settings.sdhc_rw_compensate);
+ DEBUG_DRV("sdhc_sdcfsh %d\n", phy->settings.sdhc_sdcfsh);
+ DEBUG_DRV("sdhc_sdcfsl %d\n", phy->settings.sdhc_sdcfsl);
+ DEBUG_DRV("sdhc_wrcmd0_dly %d %d\n", phy->settings.sdhc_wrcmd0_dly,
+ phy->settings.sdhc_wrcmd0_sdclk_dly);
+ DEBUG_DRV("sdhc_wrcmd1_dly %d %d\n", phy->settings.sdhc_wrcmd1_dly,
+ phy->settings.sdhc_wrcmd1_sdclk_dly);
+ DEBUG_DRV("sdhc_wrdata0_dly %d %d\n", phy->settings.sdhc_wrdata0_dly,
+ phy->settings.sdhc_wrdata0_sdclk_dly);
+
+ DEBUG_DRV("sdhc_wrdata1_dly %d %d\n", phy->settings.sdhc_wrdata1_dly,
+ phy->settings.sdhc_wrdata1_sdclk_dly);
+ DEBUG_DRV("hs200_tune_val %d\n", phy->settings.hs200_tune_val);
+}
+#endif
+
static void sdhci_cdns_sd6_writel(struct sdhci_host *host, u32 val, int reg)
{
writel(val, host->ioaddr + reg);
@@ -579,6 +650,16 @@ static void sdhci_cdns_set_emmc_mode(struct sdhci_cdns_plat *priv, u32 mode)
}
#endif
+#ifdef CONFIG_MMC_SDHCI_CADENCE_DEBUG
+static u32 sdhci_cdns_get_emmc_mode(struct sdhci_cdns_plat *priv)
+{
+ u32 tmp;
+
+ tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
+ return FIELD_GET(SDHCI_CDNS_HRS06_MODE, tmp);
+}
+#endif
+
void sdhci_cdns_sd6_fullsw_reset(struct sdhci_cdns_plat *plat)
{
u32 regval;
@@ -1334,6 +1415,18 @@ static int sdhci_cdns_sd6_phy_update_timings(struct sdhci_cdns_plat *plat)
return 0;
}
+#ifdef CONFIG_MMC_SDHCI_CADENCE_DEBUG
+void dump_sdhci_regs(struct sdhci_host *host)
+{
+ struct udevice *dev = host->mmc->dev;
+ struct sdhci_cdns_plat *plat = dev_get_plat(dev);
+ struct sdhci_cdns_sd6_phy *phy = plat->priv;
+
+ sdhci_cdns_sd6_phy_dump(phy);
+ sdhci_cdns_sd6_dump(plat);
+}
+#endif
+
static void sdhci_cdns_sd6_set_clock(struct sdhci_host *host, unsigned int div)
{
struct udevice *dev = host->mmc->dev;
@@ -1359,6 +1452,10 @@ static void sdhci_cdns_sd6_set_clock(struct sdhci_host *host, unsigned int div)
if (sdhci_cdns_sd6_phy_init(dev, plat))
debug("%s: phy init failed\n", __func__);
+#ifdef CONFIG_MMC_SDHCI_CADENCE_DEBUG
+ dump_sdhci_regs(host);
+ DEBUG_DRV("%s sdhci mode %d\n", __func__, sdhci_cdns_get_emmc_mode(plat));
+#endif
}
static int sdhci_cdns_sd6_plat_init(struct udevice *dev, struct sdhci_cdns_plat *plat)