summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLucas Stach <dev@lynxeye.de>2014-05-14 22:45:40 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2014-05-15 14:17:12 +0200
commitce41b642998f64815f364f5d10df952503fd426e (patch)
tree0a4c41dc46403c37ee19de0e1f6b128482b930e3 /drivers
parent1fc137d4cdd462e47a9f2c55c3649cf608df6482 (diff)
downloadbarebox-ce41b642998f64815f364f5d10df952503fd426e.tar.gz
barebox-ce41b642998f64815f364f5d10df952503fd426e.tar.xz
mci: tegra: apply pad autocalibration on T30
Needed for SD cards connected to sdmmc1 or sdmmc3 to work properly. Signed-off-by: Lucas Stach <dev@lynxeye.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mci/tegra-sdmmc.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/mci/tegra-sdmmc.c b/drivers/mci/tegra-sdmmc.c
index 0ea0b5ca4a..634515705f 100644
--- a/drivers/mci/tegra-sdmmc.c
+++ b/drivers/mci/tegra-sdmmc.c
@@ -59,6 +59,14 @@
#define TEGRA_SDMMC_INT_SIG_EN 0x038
#define TEGRA_SDMMC_INT_SIG_EN_XFER_COMPLETE (1 << 1)
+#define TEGRA_SDMMC_SDMEMCOMPPADCTRL 0x1e0
+#define TEGRA_SDMMC_SDMEMCOMPPADCTRL_VREF_SEL_SHIFT 0
+
+#define TEGRA_SDMMC_AUTO_CAL_CONFIG 0x1e4
+#define TEGRA_SDMMC_AUTO_CAL_CONFIG_PU_OFFSET_SHIFT 0
+#define TEGRA_SDMMC_AUTO_CAL_CONFIG_PD_OFFSET_SHIFT 8
+#define TEGRA_SDMMC_AUTO_CAL_CONFIG_ENABLE (1 << 29)
+
struct tegra_sdmmc_host {
struct mci_host mci;
void __iomem *regs;
@@ -333,6 +341,23 @@ static int tegra_sdmmc_init(struct mci_host *mci, struct device_d *dev)
val |= TEGRA_SDMMC_PWR_CNTL_33_V | TEGRA_SDMMC_PWR_CNTL_SD_BUS;
writel(val, regs + TEGRA_SDMMC_PWR_CNTL);
+ /* sdmmc1 and sdmmc3 on T30 need a bit of padctrl init */
+ if (of_device_is_compatible(mci->hw_dev->device_node,
+ "nvidia,tegra30-sdhci") &&
+ ((u32)regs == 0x78000000 || (u32)regs == 78000400)) {
+ val = readl(regs + TEGRA_SDMMC_SDMEMCOMPPADCTRL);
+ val &= 0xfffffff0;
+ val |= 0x7 << TEGRA_SDMMC_SDMEMCOMPPADCTRL_VREF_SEL_SHIFT;
+ writel(val, regs + TEGRA_SDMMC_SDMEMCOMPPADCTRL);
+
+ val = readl(regs + TEGRA_SDMMC_AUTO_CAL_CONFIG);
+ val &= 0xffff0000;
+ val |= (0x62 << TEGRA_SDMMC_AUTO_CAL_CONFIG_PU_OFFSET_SHIFT) |
+ (0x70 << TEGRA_SDMMC_AUTO_CAL_CONFIG_PD_OFFSET_SHIFT) |
+ TEGRA_SDMMC_AUTO_CAL_CONFIG_ENABLE;
+ writel(val, regs + TEGRA_SDMMC_AUTO_CAL_CONFIG);
+ }
+
/* setup signaling */
writel(0xffffffff, regs + TEGRA_SDMMC_INT_STAT_EN);
writel(0xffffffff, regs + TEGRA_SDMMC_INT_SIG_EN);