103d2bfc8SOlof Johansson /* 203d2bfc8SOlof Johansson * Copyright (C) 2010 Google, Inc. 303d2bfc8SOlof Johansson * 403d2bfc8SOlof Johansson * This software is licensed under the terms of the GNU General Public 503d2bfc8SOlof Johansson * License version 2, as published by the Free Software Foundation, and 603d2bfc8SOlof Johansson * may be copied, distributed, and modified under those terms. 703d2bfc8SOlof Johansson * 803d2bfc8SOlof Johansson * This program is distributed in the hope that it will be useful, 903d2bfc8SOlof Johansson * but WITHOUT ANY WARRANTY; without even the implied warranty of 1003d2bfc8SOlof Johansson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1103d2bfc8SOlof Johansson * GNU General Public License for more details. 1203d2bfc8SOlof Johansson * 1303d2bfc8SOlof Johansson */ 1403d2bfc8SOlof Johansson 15e5c63d91SLucas Stach #include <linux/delay.h> 1603d2bfc8SOlof Johansson #include <linux/err.h> 1796547f5dSPaul Gortmaker #include <linux/module.h> 1803d2bfc8SOlof Johansson #include <linux/init.h> 19e7c07148SAapo Vienamo #include <linux/iopoll.h> 2003d2bfc8SOlof Johansson #include <linux/platform_device.h> 2103d2bfc8SOlof Johansson #include <linux/clk.h> 2203d2bfc8SOlof Johansson #include <linux/io.h> 2355cd65e4SStephen Warren #include <linux/of.h> 243e44a1a7SStephen Warren #include <linux/of_device.h> 2586ac2f8bSAapo Vienamo #include <linux/pinctrl/consumer.h> 2686ac2f8bSAapo Vienamo #include <linux/regulator/consumer.h> 2720567be9SThierry Reding #include <linux/reset.h> 2803d2bfc8SOlof Johansson #include <linux/mmc/card.h> 2903d2bfc8SOlof Johansson #include <linux/mmc/host.h> 30c3c2384cSLucas Stach #include <linux/mmc/mmc.h> 310aacd23fSJoseph Lo #include <linux/mmc/slot-gpio.h> 322391b340SMylene JOSSERAND #include <linux/gpio/consumer.h> 3303d2bfc8SOlof Johansson 3403d2bfc8SOlof Johansson #include "sdhci-pltfm.h" 3503d2bfc8SOlof Johansson 36ca5879d3SPavan Kunapuli /* Tegra SDHOST controller vendor register definitions */ 3774cd42bcSLucas Stach #define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100 38c3c2384cSLucas Stach #define SDHCI_CLOCK_CTRL_TAP_MASK 0x00ff0000 39c3c2384cSLucas Stach #define SDHCI_CLOCK_CTRL_TAP_SHIFT 16 40c3c2384cSLucas Stach #define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE BIT(5) 4174cd42bcSLucas Stach #define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDE BIT(3) 4274cd42bcSLucas Stach #define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE BIT(2) 4374cd42bcSLucas Stach 44ca5879d3SPavan Kunapuli #define SDHCI_TEGRA_VENDOR_MISC_CTRL 0x120 453145351aSAndrew Bresticker #define SDHCI_MISC_CTRL_ENABLE_SDR104 0x8 463145351aSAndrew Bresticker #define SDHCI_MISC_CTRL_ENABLE_SDR50 0x10 47ca5879d3SPavan Kunapuli #define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20 483145351aSAndrew Bresticker #define SDHCI_MISC_CTRL_ENABLE_DDR50 0x200 49ca5879d3SPavan Kunapuli 50e5c63d91SLucas Stach #define SDHCI_TEGRA_AUTO_CAL_CONFIG 0x1e4 51e5c63d91SLucas Stach #define SDHCI_AUTO_CAL_START BIT(31) 52e5c63d91SLucas Stach #define SDHCI_AUTO_CAL_ENABLE BIT(29) 53e5c63d91SLucas Stach 549d548f11SAapo Vienamo #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL 0x1e0 559d548f11SAapo Vienamo #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK 0x0000000f 569d548f11SAapo Vienamo #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL 0x7 57212b0cf1SAapo Vienamo #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD BIT(31) 589d548f11SAapo Vienamo 59e7c07148SAapo Vienamo #define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec 60e7c07148SAapo Vienamo #define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31) 61e7c07148SAapo Vienamo 623e44a1a7SStephen Warren #define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0) 633e44a1a7SStephen Warren #define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1) 64ca5879d3SPavan Kunapuli #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2) 657ad2ed1dSLucas Stach #define NVQUIRK_ENABLE_SDR50 BIT(3) 667ad2ed1dSLucas Stach #define NVQUIRK_ENABLE_SDR104 BIT(4) 677ad2ed1dSLucas Stach #define NVQUIRK_ENABLE_DDR50 BIT(5) 68e5c63d91SLucas Stach #define NVQUIRK_HAS_PADCALIB BIT(6) 6986ac2f8bSAapo Vienamo #define NVQUIRK_NEEDS_PAD_CONTROL BIT(7) 703e44a1a7SStephen Warren 713e44a1a7SStephen Warren struct sdhci_tegra_soc_data { 721db5eebfSLars-Peter Clausen const struct sdhci_pltfm_data *pdata; 733e44a1a7SStephen Warren u32 nvquirks; 743e44a1a7SStephen Warren }; 753e44a1a7SStephen Warren 763e44a1a7SStephen Warren struct sdhci_tegra { 773e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data; 782391b340SMylene JOSSERAND struct gpio_desc *power_gpio; 79a8e326a9SLucas Stach bool ddr_signaling; 80e5c63d91SLucas Stach bool pad_calib_required; 8186ac2f8bSAapo Vienamo bool pad_control_available; 8220567be9SThierry Reding 8320567be9SThierry Reding struct reset_control *rst; 8486ac2f8bSAapo Vienamo struct pinctrl *pinctrl_sdmmc; 8586ac2f8bSAapo Vienamo struct pinctrl_state *pinctrl_state_3v3; 8686ac2f8bSAapo Vienamo struct pinctrl_state *pinctrl_state_1v8; 873e44a1a7SStephen Warren }; 883e44a1a7SStephen Warren 8903d2bfc8SOlof Johansson static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) 9003d2bfc8SOlof Johansson { 913e44a1a7SStephen Warren struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 920734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 933e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 943e44a1a7SStephen Warren 953e44a1a7SStephen Warren if (unlikely((soc_data->nvquirks & NVQUIRK_FORCE_SDHCI_SPEC_200) && 963e44a1a7SStephen Warren (reg == SDHCI_HOST_VERSION))) { 9703d2bfc8SOlof Johansson /* Erratum: Version register is invalid in HW. */ 9803d2bfc8SOlof Johansson return SDHCI_SPEC_200; 9903d2bfc8SOlof Johansson } 10003d2bfc8SOlof Johansson 10103d2bfc8SOlof Johansson return readw(host->ioaddr + reg); 10203d2bfc8SOlof Johansson } 10303d2bfc8SOlof Johansson 104352ee868SPavan Kunapuli static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg) 105352ee868SPavan Kunapuli { 106352ee868SPavan Kunapuli struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 107352ee868SPavan Kunapuli 108352ee868SPavan Kunapuli switch (reg) { 109352ee868SPavan Kunapuli case SDHCI_TRANSFER_MODE: 110352ee868SPavan Kunapuli /* 111352ee868SPavan Kunapuli * Postpone this write, we must do it together with a 112352ee868SPavan Kunapuli * command write that is down below. 113352ee868SPavan Kunapuli */ 114352ee868SPavan Kunapuli pltfm_host->xfer_mode_shadow = val; 115352ee868SPavan Kunapuli return; 116352ee868SPavan Kunapuli case SDHCI_COMMAND: 117352ee868SPavan Kunapuli writel((val << 16) | pltfm_host->xfer_mode_shadow, 118352ee868SPavan Kunapuli host->ioaddr + SDHCI_TRANSFER_MODE); 119352ee868SPavan Kunapuli return; 120352ee868SPavan Kunapuli } 121352ee868SPavan Kunapuli 122352ee868SPavan Kunapuli writew(val, host->ioaddr + reg); 123352ee868SPavan Kunapuli } 124352ee868SPavan Kunapuli 12503d2bfc8SOlof Johansson static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) 12603d2bfc8SOlof Johansson { 1273e44a1a7SStephen Warren struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1280734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 1293e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 1303e44a1a7SStephen Warren 13103d2bfc8SOlof Johansson /* Seems like we're getting spurious timeout and crc errors, so 13203d2bfc8SOlof Johansson * disable signalling of them. In case of real errors software 13303d2bfc8SOlof Johansson * timers should take care of eventually detecting them. 13403d2bfc8SOlof Johansson */ 13503d2bfc8SOlof Johansson if (unlikely(reg == SDHCI_SIGNAL_ENABLE)) 13603d2bfc8SOlof Johansson val &= ~(SDHCI_INT_TIMEOUT|SDHCI_INT_CRC); 13703d2bfc8SOlof Johansson 13803d2bfc8SOlof Johansson writel(val, host->ioaddr + reg); 13903d2bfc8SOlof Johansson 1403e44a1a7SStephen Warren if (unlikely((soc_data->nvquirks & NVQUIRK_ENABLE_BLOCK_GAP_DET) && 1413e44a1a7SStephen Warren (reg == SDHCI_INT_ENABLE))) { 14203d2bfc8SOlof Johansson /* Erratum: Must enable block gap interrupt detection */ 14303d2bfc8SOlof Johansson u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); 14403d2bfc8SOlof Johansson if (val & SDHCI_INT_CARD_INT) 14503d2bfc8SOlof Johansson gap_ctrl |= 0x8; 14603d2bfc8SOlof Johansson else 14703d2bfc8SOlof Johansson gap_ctrl &= ~0x8; 14803d2bfc8SOlof Johansson writeb(gap_ctrl, host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); 14903d2bfc8SOlof Johansson } 15003d2bfc8SOlof Johansson } 15103d2bfc8SOlof Johansson 1523e44a1a7SStephen Warren static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host) 15303d2bfc8SOlof Johansson { 1540aacd23fSJoseph Lo return mmc_gpio_get_ro(host->mmc); 15503d2bfc8SOlof Johansson } 15603d2bfc8SOlof Johansson 15786ac2f8bSAapo Vienamo static bool tegra_sdhci_is_pad_and_regulator_valid(struct sdhci_host *host) 15886ac2f8bSAapo Vienamo { 15986ac2f8bSAapo Vienamo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 16086ac2f8bSAapo Vienamo struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 16186ac2f8bSAapo Vienamo int has_1v8, has_3v3; 16286ac2f8bSAapo Vienamo 16386ac2f8bSAapo Vienamo /* 16486ac2f8bSAapo Vienamo * The SoCs which have NVQUIRK_NEEDS_PAD_CONTROL require software pad 16586ac2f8bSAapo Vienamo * voltage configuration in order to perform voltage switching. This 16686ac2f8bSAapo Vienamo * means that valid pinctrl info is required on SDHCI instances capable 16786ac2f8bSAapo Vienamo * of performing voltage switching. Whether or not an SDHCI instance is 16886ac2f8bSAapo Vienamo * capable of voltage switching is determined based on the regulator. 16986ac2f8bSAapo Vienamo */ 17086ac2f8bSAapo Vienamo 17186ac2f8bSAapo Vienamo if (!(tegra_host->soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL)) 17286ac2f8bSAapo Vienamo return true; 17386ac2f8bSAapo Vienamo 17486ac2f8bSAapo Vienamo if (IS_ERR(host->mmc->supply.vqmmc)) 17586ac2f8bSAapo Vienamo return false; 17686ac2f8bSAapo Vienamo 17786ac2f8bSAapo Vienamo has_1v8 = regulator_is_supported_voltage(host->mmc->supply.vqmmc, 17886ac2f8bSAapo Vienamo 1700000, 1950000); 17986ac2f8bSAapo Vienamo 18086ac2f8bSAapo Vienamo has_3v3 = regulator_is_supported_voltage(host->mmc->supply.vqmmc, 18186ac2f8bSAapo Vienamo 2700000, 3600000); 18286ac2f8bSAapo Vienamo 18386ac2f8bSAapo Vienamo if (has_1v8 == 1 && has_3v3 == 1) 18486ac2f8bSAapo Vienamo return tegra_host->pad_control_available; 18586ac2f8bSAapo Vienamo 18686ac2f8bSAapo Vienamo /* Fixed voltage, no pad control required. */ 18786ac2f8bSAapo Vienamo return true; 18886ac2f8bSAapo Vienamo } 18986ac2f8bSAapo Vienamo 19003231f9bSRussell King static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) 191ca5879d3SPavan Kunapuli { 192ca5879d3SPavan Kunapuli struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1930734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 194ca5879d3SPavan Kunapuli const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 1959d548f11SAapo Vienamo u32 misc_ctrl, clk_ctrl, pad_ctrl; 196ca5879d3SPavan Kunapuli 19703231f9bSRussell King sdhci_reset(host, mask); 19803231f9bSRussell King 199ca5879d3SPavan Kunapuli if (!(mask & SDHCI_RESET_ALL)) 200ca5879d3SPavan Kunapuli return; 201ca5879d3SPavan Kunapuli 2021b84def8SLucas Stach misc_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL); 2034f6aa326SJon Hunter clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 2044f6aa326SJon Hunter 2054f6aa326SJon Hunter misc_ctrl &= ~(SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 | 2064f6aa326SJon Hunter SDHCI_MISC_CTRL_ENABLE_SDR50 | 2074f6aa326SJon Hunter SDHCI_MISC_CTRL_ENABLE_DDR50 | 2084f6aa326SJon Hunter SDHCI_MISC_CTRL_ENABLE_SDR104); 2094f6aa326SJon Hunter 2104f6aa326SJon Hunter clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE; 2114f6aa326SJon Hunter 21286ac2f8bSAapo Vienamo if (tegra_sdhci_is_pad_and_regulator_valid(host)) { 213ca5879d3SPavan Kunapuli /* Erratum: Enable SDHCI spec v3.00 support */ 2143145351aSAndrew Bresticker if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) 215ca5879d3SPavan Kunapuli misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300; 2167ad2ed1dSLucas Stach /* Advertise UHS modes as supported by host */ 2177ad2ed1dSLucas Stach if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50) 2187ad2ed1dSLucas Stach misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR50; 2197ad2ed1dSLucas Stach if (soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) 2207ad2ed1dSLucas Stach misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50; 2217ad2ed1dSLucas Stach if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104) 2227ad2ed1dSLucas Stach misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104; 2237ad2ed1dSLucas Stach if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50) 224c3c2384cSLucas Stach clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE; 2254f6aa326SJon Hunter } 2264f6aa326SJon Hunter 2274f6aa326SJon Hunter sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL); 22874cd42bcSLucas Stach sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 22974cd42bcSLucas Stach 2309d548f11SAapo Vienamo if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) { 2319d548f11SAapo Vienamo pad_ctrl = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL); 2329d548f11SAapo Vienamo pad_ctrl &= ~SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK; 2339d548f11SAapo Vienamo pad_ctrl |= SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL; 2349d548f11SAapo Vienamo sdhci_writel(host, pad_ctrl, SDHCI_TEGRA_SDMEM_COMP_PADCTRL); 2359d548f11SAapo Vienamo 236e5c63d91SLucas Stach tegra_host->pad_calib_required = true; 2379d548f11SAapo Vienamo } 238e5c63d91SLucas Stach 239a8e326a9SLucas Stach tegra_host->ddr_signaling = false; 240ca5879d3SPavan Kunapuli } 241ca5879d3SPavan Kunapuli 242212b0cf1SAapo Vienamo static void tegra_sdhci_configure_cal_pad(struct sdhci_host *host, bool enable) 243212b0cf1SAapo Vienamo { 244212b0cf1SAapo Vienamo u32 val; 245212b0cf1SAapo Vienamo 246212b0cf1SAapo Vienamo /* 247212b0cf1SAapo Vienamo * Enable or disable the additional I/O pad used by the drive strength 248212b0cf1SAapo Vienamo * calibration process. 249212b0cf1SAapo Vienamo */ 250212b0cf1SAapo Vienamo val = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL); 251212b0cf1SAapo Vienamo 252212b0cf1SAapo Vienamo if (enable) 253212b0cf1SAapo Vienamo val |= SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD; 254212b0cf1SAapo Vienamo else 255212b0cf1SAapo Vienamo val &= ~SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD; 256212b0cf1SAapo Vienamo 257212b0cf1SAapo Vienamo sdhci_writel(host, val, SDHCI_TEGRA_SDMEM_COMP_PADCTRL); 258212b0cf1SAapo Vienamo 259212b0cf1SAapo Vienamo if (enable) 260212b0cf1SAapo Vienamo usleep_range(1, 2); 261212b0cf1SAapo Vienamo } 262212b0cf1SAapo Vienamo 263887bda8fSAapo Vienamo static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool enable) 264887bda8fSAapo Vienamo { 265887bda8fSAapo Vienamo bool status; 266887bda8fSAapo Vienamo u32 reg; 267887bda8fSAapo Vienamo 268887bda8fSAapo Vienamo reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 269887bda8fSAapo Vienamo status = !!(reg & SDHCI_CLOCK_CARD_EN); 270887bda8fSAapo Vienamo 271887bda8fSAapo Vienamo if (status == enable) 272887bda8fSAapo Vienamo return status; 273887bda8fSAapo Vienamo 274887bda8fSAapo Vienamo if (enable) 275887bda8fSAapo Vienamo reg |= SDHCI_CLOCK_CARD_EN; 276887bda8fSAapo Vienamo else 277887bda8fSAapo Vienamo reg &= ~SDHCI_CLOCK_CARD_EN; 278887bda8fSAapo Vienamo 279887bda8fSAapo Vienamo sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL); 280887bda8fSAapo Vienamo 281887bda8fSAapo Vienamo return status; 282887bda8fSAapo Vienamo } 283887bda8fSAapo Vienamo 284e5c63d91SLucas Stach static void tegra_sdhci_pad_autocalib(struct sdhci_host *host) 285e5c63d91SLucas Stach { 286887bda8fSAapo Vienamo bool card_clk_enabled; 287e7c07148SAapo Vienamo u32 reg; 288e7c07148SAapo Vienamo int ret; 289e5c63d91SLucas Stach 290887bda8fSAapo Vienamo card_clk_enabled = tegra_sdhci_configure_card_clk(host, false); 291887bda8fSAapo Vienamo 292212b0cf1SAapo Vienamo tegra_sdhci_configure_cal_pad(host, true); 293212b0cf1SAapo Vienamo 294e7c07148SAapo Vienamo reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG); 295e7c07148SAapo Vienamo reg |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START; 296e7c07148SAapo Vienamo sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG); 297e5c63d91SLucas Stach 298e7c07148SAapo Vienamo usleep_range(1, 2); 299e7c07148SAapo Vienamo /* 10 ms timeout */ 300e7c07148SAapo Vienamo ret = readl_poll_timeout(host->ioaddr + SDHCI_TEGRA_AUTO_CAL_STATUS, 301e7c07148SAapo Vienamo reg, !(reg & SDHCI_TEGRA_AUTO_CAL_ACTIVE), 302e7c07148SAapo Vienamo 1000, 10000); 303e7c07148SAapo Vienamo 304212b0cf1SAapo Vienamo tegra_sdhci_configure_cal_pad(host, false); 305212b0cf1SAapo Vienamo 306887bda8fSAapo Vienamo tegra_sdhci_configure_card_clk(host, card_clk_enabled); 307887bda8fSAapo Vienamo 308e7c07148SAapo Vienamo if (ret) 309e7c07148SAapo Vienamo dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n"); 310e5c63d91SLucas Stach } 311e5c63d91SLucas Stach 312a8e326a9SLucas Stach static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 313a8e326a9SLucas Stach { 314a8e326a9SLucas Stach struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 3150734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 316a8e326a9SLucas Stach unsigned long host_clk; 317a8e326a9SLucas Stach 318a8e326a9SLucas Stach if (!clock) 3193491b690SLucas Stach return sdhci_set_clock(host, clock); 320a8e326a9SLucas Stach 32157d1654eSAapo Vienamo /* 32257d1654eSAapo Vienamo * In DDR50/52 modes the Tegra SDHCI controllers require the SDHCI 32357d1654eSAapo Vienamo * divider to be configured to divided the host clock by two. The SDHCI 32457d1654eSAapo Vienamo * clock divider is calculated as part of sdhci_set_clock() by 32557d1654eSAapo Vienamo * sdhci_calc_clk(). The divider is calculated from host->max_clk and 32657d1654eSAapo Vienamo * the requested clock rate. 32757d1654eSAapo Vienamo * 32857d1654eSAapo Vienamo * By setting the host->max_clk to clock * 2 the divider calculation 32957d1654eSAapo Vienamo * will always result in the correct value for DDR50/52 modes, 33057d1654eSAapo Vienamo * regardless of clock rate rounding, which may happen if the value 33157d1654eSAapo Vienamo * from clk_get_rate() is used. 33257d1654eSAapo Vienamo */ 333a8e326a9SLucas Stach host_clk = tegra_host->ddr_signaling ? clock * 2 : clock; 334a8e326a9SLucas Stach clk_set_rate(pltfm_host->clk, host_clk); 33557d1654eSAapo Vienamo if (tegra_host->ddr_signaling) 33657d1654eSAapo Vienamo host->max_clk = host_clk; 33757d1654eSAapo Vienamo else 338a8e326a9SLucas Stach host->max_clk = clk_get_rate(pltfm_host->clk); 339a8e326a9SLucas Stach 340e5c63d91SLucas Stach sdhci_set_clock(host, clock); 341e5c63d91SLucas Stach 342e5c63d91SLucas Stach if (tegra_host->pad_calib_required) { 343e5c63d91SLucas Stach tegra_sdhci_pad_autocalib(host); 344e5c63d91SLucas Stach tegra_host->pad_calib_required = false; 345e5c63d91SLucas Stach } 346a8e326a9SLucas Stach } 347a8e326a9SLucas Stach 348a8e326a9SLucas Stach static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host, 349a8e326a9SLucas Stach unsigned timing) 350a8e326a9SLucas Stach { 351a8e326a9SLucas Stach struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 3520734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 353a8e326a9SLucas Stach 354e300149eSStefan Agner if (timing == MMC_TIMING_UHS_DDR50 || 355e300149eSStefan Agner timing == MMC_TIMING_MMC_DDR52) 356a8e326a9SLucas Stach tegra_host->ddr_signaling = true; 357a8e326a9SLucas Stach 358cf56c819SAapo Vienamo sdhci_set_uhs_signaling(host, timing); 359a8e326a9SLucas Stach } 360a8e326a9SLucas Stach 36144350993SAapo Vienamo static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host) 36244350993SAapo Vienamo { 36344350993SAapo Vienamo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 36444350993SAapo Vienamo 36544350993SAapo Vienamo return clk_round_rate(pltfm_host->clk, UINT_MAX); 36644350993SAapo Vienamo } 36744350993SAapo Vienamo 368c3c2384cSLucas Stach static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap) 369c3c2384cSLucas Stach { 370c3c2384cSLucas Stach u32 reg; 371c3c2384cSLucas Stach 372c3c2384cSLucas Stach reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 373c3c2384cSLucas Stach reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK; 374c3c2384cSLucas Stach reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT; 375c3c2384cSLucas Stach sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 376c3c2384cSLucas Stach } 377c3c2384cSLucas Stach 378c3c2384cSLucas Stach static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) 379c3c2384cSLucas Stach { 380c3c2384cSLucas Stach unsigned int min, max; 381c3c2384cSLucas Stach 382c3c2384cSLucas Stach /* 383c3c2384cSLucas Stach * Start search for minimum tap value at 10, as smaller values are 384c3c2384cSLucas Stach * may wrongly be reported as working but fail at higher speeds, 385c3c2384cSLucas Stach * according to the TRM. 386c3c2384cSLucas Stach */ 387c3c2384cSLucas Stach min = 10; 388c3c2384cSLucas Stach while (min < 255) { 389c3c2384cSLucas Stach tegra_sdhci_set_tap(host, min); 390c3c2384cSLucas Stach if (!mmc_send_tuning(host->mmc, opcode, NULL)) 391c3c2384cSLucas Stach break; 392c3c2384cSLucas Stach min++; 393c3c2384cSLucas Stach } 394c3c2384cSLucas Stach 395c3c2384cSLucas Stach /* Find the maximum tap value that still passes. */ 396c3c2384cSLucas Stach max = min + 1; 397c3c2384cSLucas Stach while (max < 255) { 398c3c2384cSLucas Stach tegra_sdhci_set_tap(host, max); 399c3c2384cSLucas Stach if (mmc_send_tuning(host->mmc, opcode, NULL)) { 400c3c2384cSLucas Stach max--; 401c3c2384cSLucas Stach break; 402c3c2384cSLucas Stach } 403c3c2384cSLucas Stach max++; 404c3c2384cSLucas Stach } 405c3c2384cSLucas Stach 406c3c2384cSLucas Stach /* The TRM states the ideal tap value is at 75% in the passing range. */ 407c3c2384cSLucas Stach tegra_sdhci_set_tap(host, min + ((max - min) * 3 / 4)); 408c3c2384cSLucas Stach 409c3c2384cSLucas Stach return mmc_send_tuning(host->mmc, opcode, NULL); 410c3c2384cSLucas Stach } 411c3c2384cSLucas Stach 41286ac2f8bSAapo Vienamo static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage) 41386ac2f8bSAapo Vienamo { 41486ac2f8bSAapo Vienamo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 41586ac2f8bSAapo Vienamo struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 41686ac2f8bSAapo Vienamo int ret; 41786ac2f8bSAapo Vienamo 41886ac2f8bSAapo Vienamo if (!tegra_host->pad_control_available) 41986ac2f8bSAapo Vienamo return 0; 42086ac2f8bSAapo Vienamo 42186ac2f8bSAapo Vienamo if (voltage == MMC_SIGNAL_VOLTAGE_180) { 42286ac2f8bSAapo Vienamo ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, 42386ac2f8bSAapo Vienamo tegra_host->pinctrl_state_1v8); 42486ac2f8bSAapo Vienamo if (ret < 0) 42586ac2f8bSAapo Vienamo dev_err(mmc_dev(host->mmc), 42686ac2f8bSAapo Vienamo "setting 1.8V failed, ret: %d\n", ret); 42786ac2f8bSAapo Vienamo } else { 42886ac2f8bSAapo Vienamo ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, 42986ac2f8bSAapo Vienamo tegra_host->pinctrl_state_3v3); 43086ac2f8bSAapo Vienamo if (ret < 0) 43186ac2f8bSAapo Vienamo dev_err(mmc_dev(host->mmc), 43286ac2f8bSAapo Vienamo "setting 3.3V failed, ret: %d\n", ret); 43386ac2f8bSAapo Vienamo } 43486ac2f8bSAapo Vienamo 43586ac2f8bSAapo Vienamo return ret; 43686ac2f8bSAapo Vienamo } 43786ac2f8bSAapo Vienamo 43886ac2f8bSAapo Vienamo static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc, 43986ac2f8bSAapo Vienamo struct mmc_ios *ios) 44086ac2f8bSAapo Vienamo { 44186ac2f8bSAapo Vienamo struct sdhci_host *host = mmc_priv(mmc); 44286ac2f8bSAapo Vienamo int ret = 0; 44386ac2f8bSAapo Vienamo 44486ac2f8bSAapo Vienamo if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { 44586ac2f8bSAapo Vienamo ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage); 44686ac2f8bSAapo Vienamo if (ret < 0) 44786ac2f8bSAapo Vienamo return ret; 44886ac2f8bSAapo Vienamo ret = sdhci_start_signal_voltage_switch(mmc, ios); 44986ac2f8bSAapo Vienamo } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { 45086ac2f8bSAapo Vienamo ret = sdhci_start_signal_voltage_switch(mmc, ios); 45186ac2f8bSAapo Vienamo if (ret < 0) 45286ac2f8bSAapo Vienamo return ret; 45386ac2f8bSAapo Vienamo ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage); 45486ac2f8bSAapo Vienamo } 45586ac2f8bSAapo Vienamo 45686ac2f8bSAapo Vienamo return ret; 45786ac2f8bSAapo Vienamo } 45886ac2f8bSAapo Vienamo 45986ac2f8bSAapo Vienamo static int tegra_sdhci_init_pinctrl_info(struct device *dev, 46086ac2f8bSAapo Vienamo struct sdhci_tegra *tegra_host) 46186ac2f8bSAapo Vienamo { 46286ac2f8bSAapo Vienamo tegra_host->pinctrl_sdmmc = devm_pinctrl_get(dev); 46386ac2f8bSAapo Vienamo if (IS_ERR(tegra_host->pinctrl_sdmmc)) { 46486ac2f8bSAapo Vienamo dev_dbg(dev, "No pinctrl info, err: %ld\n", 46586ac2f8bSAapo Vienamo PTR_ERR(tegra_host->pinctrl_sdmmc)); 46686ac2f8bSAapo Vienamo return -1; 46786ac2f8bSAapo Vienamo } 46886ac2f8bSAapo Vienamo 46986ac2f8bSAapo Vienamo tegra_host->pinctrl_state_3v3 = 47086ac2f8bSAapo Vienamo pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-3v3"); 47186ac2f8bSAapo Vienamo if (IS_ERR(tegra_host->pinctrl_state_3v3)) { 47286ac2f8bSAapo Vienamo dev_warn(dev, "Missing 3.3V pad state, err: %ld\n", 47386ac2f8bSAapo Vienamo PTR_ERR(tegra_host->pinctrl_state_3v3)); 47486ac2f8bSAapo Vienamo return -1; 47586ac2f8bSAapo Vienamo } 47686ac2f8bSAapo Vienamo 47786ac2f8bSAapo Vienamo tegra_host->pinctrl_state_1v8 = 47886ac2f8bSAapo Vienamo pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-1v8"); 47986ac2f8bSAapo Vienamo if (IS_ERR(tegra_host->pinctrl_state_1v8)) { 48086ac2f8bSAapo Vienamo dev_warn(dev, "Missing 1.8V pad state, err: %ld\n", 48186ac2f8bSAapo Vienamo PTR_ERR(tegra_host->pinctrl_state_3v3)); 48286ac2f8bSAapo Vienamo return -1; 48386ac2f8bSAapo Vienamo } 48486ac2f8bSAapo Vienamo 48586ac2f8bSAapo Vienamo tegra_host->pad_control_available = true; 48686ac2f8bSAapo Vienamo 48786ac2f8bSAapo Vienamo return 0; 48886ac2f8bSAapo Vienamo } 48986ac2f8bSAapo Vienamo 490e5c63d91SLucas Stach static void tegra_sdhci_voltage_switch(struct sdhci_host *host) 491e5c63d91SLucas Stach { 492e5c63d91SLucas Stach struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 493e5c63d91SLucas Stach struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 494e5c63d91SLucas Stach const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 495e5c63d91SLucas Stach 496e5c63d91SLucas Stach if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) 497e5c63d91SLucas Stach tegra_host->pad_calib_required = true; 498e5c63d91SLucas Stach } 499e5c63d91SLucas Stach 500c915568dSLars-Peter Clausen static const struct sdhci_ops tegra_sdhci_ops = { 50185d6509dSShawn Guo .get_ro = tegra_sdhci_get_ro, 50285d6509dSShawn Guo .read_w = tegra_sdhci_readw, 50385d6509dSShawn Guo .write_l = tegra_sdhci_writel, 504a8e326a9SLucas Stach .set_clock = tegra_sdhci_set_clock, 50514b04c6aSMichał Mirosław .set_bus_width = sdhci_set_bus_width, 50603231f9bSRussell King .reset = tegra_sdhci_reset, 507c3c2384cSLucas Stach .platform_execute_tuning = tegra_sdhci_execute_tuning, 508a8e326a9SLucas Stach .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, 509e5c63d91SLucas Stach .voltage_switch = tegra_sdhci_voltage_switch, 51044350993SAapo Vienamo .get_max_clock = tegra_sdhci_get_max_clock, 51185d6509dSShawn Guo }; 51203d2bfc8SOlof Johansson 5131db5eebfSLars-Peter Clausen static const struct sdhci_pltfm_data sdhci_tegra20_pdata = { 51485d6509dSShawn Guo .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 51585d6509dSShawn Guo SDHCI_QUIRK_SINGLE_POWER_WRITE | 51685d6509dSShawn Guo SDHCI_QUIRK_NO_HISPD_BIT | 517f9260355SAndrew Bresticker SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 518f9260355SAndrew Bresticker SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 51985d6509dSShawn Guo .ops = &tegra_sdhci_ops, 52085d6509dSShawn Guo }; 52185d6509dSShawn Guo 522d49d19c2SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra20 = { 5233e44a1a7SStephen Warren .pdata = &sdhci_tegra20_pdata, 5243e44a1a7SStephen Warren .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 | 5253e44a1a7SStephen Warren NVQUIRK_ENABLE_BLOCK_GAP_DET, 5263e44a1a7SStephen Warren }; 5273e44a1a7SStephen Warren 5281db5eebfSLars-Peter Clausen static const struct sdhci_pltfm_data sdhci_tegra30_pdata = { 5293e44a1a7SStephen Warren .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 5303e44a1a7SStephen Warren SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 5313e44a1a7SStephen Warren SDHCI_QUIRK_SINGLE_POWER_WRITE | 5323e44a1a7SStephen Warren SDHCI_QUIRK_NO_HISPD_BIT | 533f9260355SAndrew Bresticker SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 534f9260355SAndrew Bresticker SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 535127407e3SStefan Agner .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 536726df1d5SStefan Agner SDHCI_QUIRK2_BROKEN_HS200 | 537726df1d5SStefan Agner /* 538726df1d5SStefan Agner * Auto-CMD23 leads to "Got command interrupt 0x00010000 even 539726df1d5SStefan Agner * though no command operation was in progress." 540726df1d5SStefan Agner * 541726df1d5SStefan Agner * The exact reason is unknown, as the same hardware seems 542726df1d5SStefan Agner * to support Auto CMD23 on a downstream 3.1 kernel. 543726df1d5SStefan Agner */ 544726df1d5SStefan Agner SDHCI_QUIRK2_ACMD23_BROKEN, 5453e44a1a7SStephen Warren .ops = &tegra_sdhci_ops, 5463e44a1a7SStephen Warren }; 5473e44a1a7SStephen Warren 548d49d19c2SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra30 = { 5493e44a1a7SStephen Warren .pdata = &sdhci_tegra30_pdata, 5503145351aSAndrew Bresticker .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 | 5517ad2ed1dSLucas Stach NVQUIRK_ENABLE_SDR50 | 552e5c63d91SLucas Stach NVQUIRK_ENABLE_SDR104 | 553e5c63d91SLucas Stach NVQUIRK_HAS_PADCALIB, 5543e44a1a7SStephen Warren }; 5553e44a1a7SStephen Warren 55601df7ecdSRhyland Klein static const struct sdhci_ops tegra114_sdhci_ops = { 55701df7ecdSRhyland Klein .get_ro = tegra_sdhci_get_ro, 55801df7ecdSRhyland Klein .read_w = tegra_sdhci_readw, 55901df7ecdSRhyland Klein .write_w = tegra_sdhci_writew, 56001df7ecdSRhyland Klein .write_l = tegra_sdhci_writel, 561a8e326a9SLucas Stach .set_clock = tegra_sdhci_set_clock, 56214b04c6aSMichał Mirosław .set_bus_width = sdhci_set_bus_width, 56301df7ecdSRhyland Klein .reset = tegra_sdhci_reset, 564c3c2384cSLucas Stach .platform_execute_tuning = tegra_sdhci_execute_tuning, 565a8e326a9SLucas Stach .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, 566e5c63d91SLucas Stach .voltage_switch = tegra_sdhci_voltage_switch, 56744350993SAapo Vienamo .get_max_clock = tegra_sdhci_get_max_clock, 56801df7ecdSRhyland Klein }; 56901df7ecdSRhyland Klein 5701db5eebfSLars-Peter Clausen static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { 5715ebf2552SRhyland Klein .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 5725ebf2552SRhyland Klein SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 5735ebf2552SRhyland Klein SDHCI_QUIRK_SINGLE_POWER_WRITE | 5745ebf2552SRhyland Klein SDHCI_QUIRK_NO_HISPD_BIT | 575f9260355SAndrew Bresticker SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 576f9260355SAndrew Bresticker SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 577a8e326a9SLucas Stach .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, 57801df7ecdSRhyland Klein .ops = &tegra114_sdhci_ops, 5795ebf2552SRhyland Klein }; 5805ebf2552SRhyland Klein 581d49d19c2SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra114 = { 5825ebf2552SRhyland Klein .pdata = &sdhci_tegra114_pdata, 5837bf037d6SJon Hunter }; 5847bf037d6SJon Hunter 5854ae12588SThierry Reding static const struct sdhci_pltfm_data sdhci_tegra124_pdata = { 5864ae12588SThierry Reding .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 5874ae12588SThierry Reding SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 5884ae12588SThierry Reding SDHCI_QUIRK_SINGLE_POWER_WRITE | 5894ae12588SThierry Reding SDHCI_QUIRK_NO_HISPD_BIT | 5904ae12588SThierry Reding SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 5914ae12588SThierry Reding SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 5924ae12588SThierry Reding .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 5934ae12588SThierry Reding /* 5944ae12588SThierry Reding * The TRM states that the SD/MMC controller found on 5954ae12588SThierry Reding * Tegra124 can address 34 bits (the maximum supported by 5964ae12588SThierry Reding * the Tegra memory controller), but tests show that DMA 5974ae12588SThierry Reding * to or from above 4 GiB doesn't work. This is possibly 5984ae12588SThierry Reding * caused by missing programming, though it's not obvious 5994ae12588SThierry Reding * what sequence is required. Mark 64-bit DMA broken for 6004ae12588SThierry Reding * now to fix this for existing users (e.g. Nyan boards). 6014ae12588SThierry Reding */ 6024ae12588SThierry Reding SDHCI_QUIRK2_BROKEN_64_BIT_DMA, 6034ae12588SThierry Reding .ops = &tegra114_sdhci_ops, 6044ae12588SThierry Reding }; 6054ae12588SThierry Reding 6064ae12588SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra124 = { 6074ae12588SThierry Reding .pdata = &sdhci_tegra124_pdata, 6084ae12588SThierry Reding }; 6094ae12588SThierry Reding 610b5a84ecfSThierry Reding static const struct sdhci_pltfm_data sdhci_tegra210_pdata = { 611b5a84ecfSThierry Reding .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 612b5a84ecfSThierry Reding SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 613b5a84ecfSThierry Reding SDHCI_QUIRK_SINGLE_POWER_WRITE | 614b5a84ecfSThierry Reding SDHCI_QUIRK_NO_HISPD_BIT | 615a8e326a9SLucas Stach SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 616a8e326a9SLucas Stach SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 617a8e326a9SLucas Stach .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, 618b5a84ecfSThierry Reding .ops = &tegra114_sdhci_ops, 619b5a84ecfSThierry Reding }; 620b5a84ecfSThierry Reding 621b5a84ecfSThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra210 = { 622b5a84ecfSThierry Reding .pdata = &sdhci_tegra210_pdata, 62386ac2f8bSAapo Vienamo .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL, 624b5a84ecfSThierry Reding }; 625b5a84ecfSThierry Reding 6264346b7c7SThierry Reding static const struct sdhci_pltfm_data sdhci_tegra186_pdata = { 6274346b7c7SThierry Reding .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 6284346b7c7SThierry Reding SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 6294346b7c7SThierry Reding SDHCI_QUIRK_SINGLE_POWER_WRITE | 6304346b7c7SThierry Reding SDHCI_QUIRK_NO_HISPD_BIT | 6314346b7c7SThierry Reding SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 6324346b7c7SThierry Reding SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 63368481a7eSKrishna Reddy .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 63468481a7eSKrishna Reddy /* SDHCI controllers on Tegra186 support 40-bit addressing. 63568481a7eSKrishna Reddy * IOVA addresses are 48-bit wide on Tegra186. 63668481a7eSKrishna Reddy * With 64-bit dma mask used for SDHCI, accesses can 63768481a7eSKrishna Reddy * be broken. Disable 64-bit dma, which would fall back 63868481a7eSKrishna Reddy * to 32-bit dma mask. Ideally 40-bit dma mask would work, 63968481a7eSKrishna Reddy * But it is not supported as of now. 64068481a7eSKrishna Reddy */ 64168481a7eSKrishna Reddy SDHCI_QUIRK2_BROKEN_64_BIT_DMA, 6424346b7c7SThierry Reding .ops = &tegra114_sdhci_ops, 6434346b7c7SThierry Reding }; 6444346b7c7SThierry Reding 6454346b7c7SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra186 = { 6464346b7c7SThierry Reding .pdata = &sdhci_tegra186_pdata, 64786ac2f8bSAapo Vienamo .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL, 6484346b7c7SThierry Reding }; 6494346b7c7SThierry Reding 650498d83e7SBill Pemberton static const struct of_device_id sdhci_tegra_dt_match[] = { 6514346b7c7SThierry Reding { .compatible = "nvidia,tegra186-sdhci", .data = &soc_data_tegra186 }, 652b5a84ecfSThierry Reding { .compatible = "nvidia,tegra210-sdhci", .data = &soc_data_tegra210 }, 6534ae12588SThierry Reding { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra124 }, 6545ebf2552SRhyland Klein { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, 6553e44a1a7SStephen Warren { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, 6563e44a1a7SStephen Warren { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, 657275173b2SGrant Likely {} 658275173b2SGrant Likely }; 659e4404fabSArnd Bergmann MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); 660275173b2SGrant Likely 661c3be1efdSBill Pemberton static int sdhci_tegra_probe(struct platform_device *pdev) 66203d2bfc8SOlof Johansson { 6633e44a1a7SStephen Warren const struct of_device_id *match; 6643e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data; 6653e44a1a7SStephen Warren struct sdhci_host *host; 66685d6509dSShawn Guo struct sdhci_pltfm_host *pltfm_host; 6673e44a1a7SStephen Warren struct sdhci_tegra *tegra_host; 66803d2bfc8SOlof Johansson struct clk *clk; 66903d2bfc8SOlof Johansson int rc; 67003d2bfc8SOlof Johansson 6713e44a1a7SStephen Warren match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); 672b37f9d98SJoseph Lo if (!match) 673b37f9d98SJoseph Lo return -EINVAL; 6743e44a1a7SStephen Warren soc_data = match->data; 6753e44a1a7SStephen Warren 6760734e79cSJisheng Zhang host = sdhci_pltfm_init(pdev, soc_data->pdata, sizeof(*tegra_host)); 67785d6509dSShawn Guo if (IS_ERR(host)) 67885d6509dSShawn Guo return PTR_ERR(host); 67985d6509dSShawn Guo pltfm_host = sdhci_priv(host); 68085d6509dSShawn Guo 6810734e79cSJisheng Zhang tegra_host = sdhci_pltfm_priv(pltfm_host); 682a8e326a9SLucas Stach tegra_host->ddr_signaling = false; 683e5c63d91SLucas Stach tegra_host->pad_calib_required = false; 68486ac2f8bSAapo Vienamo tegra_host->pad_control_available = false; 6853e44a1a7SStephen Warren tegra_host->soc_data = soc_data; 686275173b2SGrant Likely 68786ac2f8bSAapo Vienamo if (soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL) { 68886ac2f8bSAapo Vienamo rc = tegra_sdhci_init_pinctrl_info(&pdev->dev, tegra_host); 68986ac2f8bSAapo Vienamo if (rc == 0) 69086ac2f8bSAapo Vienamo host->mmc_host_ops.start_signal_voltage_switch = 69186ac2f8bSAapo Vienamo sdhci_tegra_start_signal_voltage_switch; 69286ac2f8bSAapo Vienamo } 69386ac2f8bSAapo Vienamo 6942391b340SMylene JOSSERAND rc = mmc_of_parse(host->mmc); 69547caa84fSSimon Baatz if (rc) 69647caa84fSSimon Baatz goto err_parse_dt; 6970e786102SStephen Warren 6987ad2ed1dSLucas Stach if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) 699c3c2384cSLucas Stach host->mmc->caps |= MMC_CAP_1_8V_DDR; 700c3c2384cSLucas Stach 7012391b340SMylene JOSSERAND tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power", 7022391b340SMylene JOSSERAND GPIOD_OUT_HIGH); 7032391b340SMylene JOSSERAND if (IS_ERR(tegra_host->power_gpio)) { 7042391b340SMylene JOSSERAND rc = PTR_ERR(tegra_host->power_gpio); 70585d6509dSShawn Guo goto err_power_req; 70603d2bfc8SOlof Johansson } 70703d2bfc8SOlof Johansson 708e4f79d9cSKevin Hao clk = devm_clk_get(mmc_dev(host->mmc), NULL); 70903d2bfc8SOlof Johansson if (IS_ERR(clk)) { 71003d2bfc8SOlof Johansson dev_err(mmc_dev(host->mmc), "clk err\n"); 71103d2bfc8SOlof Johansson rc = PTR_ERR(clk); 71285d6509dSShawn Guo goto err_clk_get; 71303d2bfc8SOlof Johansson } 7141e674bc6SPrashant Gaikwad clk_prepare_enable(clk); 71503d2bfc8SOlof Johansson pltfm_host->clk = clk; 71603d2bfc8SOlof Johansson 7172cd6c49dSPhilipp Zabel tegra_host->rst = devm_reset_control_get_exclusive(&pdev->dev, 7182cd6c49dSPhilipp Zabel "sdhci"); 71920567be9SThierry Reding if (IS_ERR(tegra_host->rst)) { 72020567be9SThierry Reding rc = PTR_ERR(tegra_host->rst); 72120567be9SThierry Reding dev_err(&pdev->dev, "failed to get reset control: %d\n", rc); 72220567be9SThierry Reding goto err_rst_get; 72320567be9SThierry Reding } 72420567be9SThierry Reding 72520567be9SThierry Reding rc = reset_control_assert(tegra_host->rst); 72620567be9SThierry Reding if (rc) 72720567be9SThierry Reding goto err_rst_get; 72820567be9SThierry Reding 72920567be9SThierry Reding usleep_range(2000, 4000); 73020567be9SThierry Reding 73120567be9SThierry Reding rc = reset_control_deassert(tegra_host->rst); 73220567be9SThierry Reding if (rc) 73320567be9SThierry Reding goto err_rst_get; 73420567be9SThierry Reding 73520567be9SThierry Reding usleep_range(2000, 4000); 73620567be9SThierry Reding 73785d6509dSShawn Guo rc = sdhci_add_host(host); 73885d6509dSShawn Guo if (rc) 73985d6509dSShawn Guo goto err_add_host; 74085d6509dSShawn Guo 74103d2bfc8SOlof Johansson return 0; 74203d2bfc8SOlof Johansson 74385d6509dSShawn Guo err_add_host: 74420567be9SThierry Reding reset_control_assert(tegra_host->rst); 74520567be9SThierry Reding err_rst_get: 7461e674bc6SPrashant Gaikwad clk_disable_unprepare(pltfm_host->clk); 74785d6509dSShawn Guo err_clk_get: 74885d6509dSShawn Guo err_power_req: 74947caa84fSSimon Baatz err_parse_dt: 75085d6509dSShawn Guo sdhci_pltfm_free(pdev); 75103d2bfc8SOlof Johansson return rc; 75203d2bfc8SOlof Johansson } 75303d2bfc8SOlof Johansson 75420567be9SThierry Reding static int sdhci_tegra_remove(struct platform_device *pdev) 75520567be9SThierry Reding { 75620567be9SThierry Reding struct sdhci_host *host = platform_get_drvdata(pdev); 75720567be9SThierry Reding struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 75820567be9SThierry Reding struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 75920567be9SThierry Reding 76020567be9SThierry Reding sdhci_remove_host(host, 0); 76120567be9SThierry Reding 76220567be9SThierry Reding reset_control_assert(tegra_host->rst); 76320567be9SThierry Reding usleep_range(2000, 4000); 76420567be9SThierry Reding clk_disable_unprepare(pltfm_host->clk); 76520567be9SThierry Reding 76620567be9SThierry Reding sdhci_pltfm_free(pdev); 76720567be9SThierry Reding 76820567be9SThierry Reding return 0; 76920567be9SThierry Reding } 77020567be9SThierry Reding 77185d6509dSShawn Guo static struct platform_driver sdhci_tegra_driver = { 77285d6509dSShawn Guo .driver = { 77385d6509dSShawn Guo .name = "sdhci-tegra", 774275173b2SGrant Likely .of_match_table = sdhci_tegra_dt_match, 775fa243f64SUlf Hansson .pm = &sdhci_pltfm_pmops, 77685d6509dSShawn Guo }, 77785d6509dSShawn Guo .probe = sdhci_tegra_probe, 77820567be9SThierry Reding .remove = sdhci_tegra_remove, 77903d2bfc8SOlof Johansson }; 78003d2bfc8SOlof Johansson 781d1f81a64SAxel Lin module_platform_driver(sdhci_tegra_driver); 78285d6509dSShawn Guo 78385d6509dSShawn Guo MODULE_DESCRIPTION("SDHCI driver for Tegra"); 78485d6509dSShawn Guo MODULE_AUTHOR("Google, Inc."); 78585d6509dSShawn Guo MODULE_LICENSE("GPL v2"); 786