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> 1903d2bfc8SOlof Johansson #include <linux/platform_device.h> 2003d2bfc8SOlof Johansson #include <linux/clk.h> 2103d2bfc8SOlof Johansson #include <linux/io.h> 2255cd65e4SStephen Warren #include <linux/of.h> 233e44a1a7SStephen Warren #include <linux/of_device.h> 2486ac2f8bSAapo Vienamo #include <linux/pinctrl/consumer.h> 2586ac2f8bSAapo Vienamo #include <linux/regulator/consumer.h> 2620567be9SThierry Reding #include <linux/reset.h> 2703d2bfc8SOlof Johansson #include <linux/mmc/card.h> 2803d2bfc8SOlof Johansson #include <linux/mmc/host.h> 29c3c2384cSLucas Stach #include <linux/mmc/mmc.h> 300aacd23fSJoseph Lo #include <linux/mmc/slot-gpio.h> 312391b340SMylene JOSSERAND #include <linux/gpio/consumer.h> 3203d2bfc8SOlof Johansson 3303d2bfc8SOlof Johansson #include "sdhci-pltfm.h" 3403d2bfc8SOlof Johansson 35ca5879d3SPavan Kunapuli /* Tegra SDHOST controller vendor register definitions */ 3674cd42bcSLucas Stach #define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100 37c3c2384cSLucas Stach #define SDHCI_CLOCK_CTRL_TAP_MASK 0x00ff0000 38c3c2384cSLucas Stach #define SDHCI_CLOCK_CTRL_TAP_SHIFT 16 39c3c2384cSLucas Stach #define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE BIT(5) 4074cd42bcSLucas Stach #define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDE BIT(3) 4174cd42bcSLucas Stach #define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE BIT(2) 4274cd42bcSLucas Stach 43ca5879d3SPavan Kunapuli #define SDHCI_TEGRA_VENDOR_MISC_CTRL 0x120 443145351aSAndrew Bresticker #define SDHCI_MISC_CTRL_ENABLE_SDR104 0x8 453145351aSAndrew Bresticker #define SDHCI_MISC_CTRL_ENABLE_SDR50 0x10 46ca5879d3SPavan Kunapuli #define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20 473145351aSAndrew Bresticker #define SDHCI_MISC_CTRL_ENABLE_DDR50 0x200 48ca5879d3SPavan Kunapuli 49e5c63d91SLucas Stach #define SDHCI_TEGRA_AUTO_CAL_CONFIG 0x1e4 50e5c63d91SLucas Stach #define SDHCI_AUTO_CAL_START BIT(31) 51e5c63d91SLucas Stach #define SDHCI_AUTO_CAL_ENABLE BIT(29) 52e5c63d91SLucas Stach 533e44a1a7SStephen Warren #define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0) 543e44a1a7SStephen Warren #define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1) 55ca5879d3SPavan Kunapuli #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2) 567ad2ed1dSLucas Stach #define NVQUIRK_ENABLE_SDR50 BIT(3) 577ad2ed1dSLucas Stach #define NVQUIRK_ENABLE_SDR104 BIT(4) 587ad2ed1dSLucas Stach #define NVQUIRK_ENABLE_DDR50 BIT(5) 59e5c63d91SLucas Stach #define NVQUIRK_HAS_PADCALIB BIT(6) 6086ac2f8bSAapo Vienamo #define NVQUIRK_NEEDS_PAD_CONTROL BIT(7) 613e44a1a7SStephen Warren 623e44a1a7SStephen Warren struct sdhci_tegra_soc_data { 631db5eebfSLars-Peter Clausen const struct sdhci_pltfm_data *pdata; 643e44a1a7SStephen Warren u32 nvquirks; 653e44a1a7SStephen Warren }; 663e44a1a7SStephen Warren 673e44a1a7SStephen Warren struct sdhci_tegra { 683e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data; 692391b340SMylene JOSSERAND struct gpio_desc *power_gpio; 70a8e326a9SLucas Stach bool ddr_signaling; 71e5c63d91SLucas Stach bool pad_calib_required; 7286ac2f8bSAapo Vienamo bool pad_control_available; 7320567be9SThierry Reding 7420567be9SThierry Reding struct reset_control *rst; 7586ac2f8bSAapo Vienamo struct pinctrl *pinctrl_sdmmc; 7686ac2f8bSAapo Vienamo struct pinctrl_state *pinctrl_state_3v3; 7786ac2f8bSAapo Vienamo struct pinctrl_state *pinctrl_state_1v8; 783e44a1a7SStephen Warren }; 793e44a1a7SStephen Warren 8003d2bfc8SOlof Johansson static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) 8103d2bfc8SOlof Johansson { 823e44a1a7SStephen Warren struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 830734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 843e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 853e44a1a7SStephen Warren 863e44a1a7SStephen Warren if (unlikely((soc_data->nvquirks & NVQUIRK_FORCE_SDHCI_SPEC_200) && 873e44a1a7SStephen Warren (reg == SDHCI_HOST_VERSION))) { 8803d2bfc8SOlof Johansson /* Erratum: Version register is invalid in HW. */ 8903d2bfc8SOlof Johansson return SDHCI_SPEC_200; 9003d2bfc8SOlof Johansson } 9103d2bfc8SOlof Johansson 9203d2bfc8SOlof Johansson return readw(host->ioaddr + reg); 9303d2bfc8SOlof Johansson } 9403d2bfc8SOlof Johansson 95352ee868SPavan Kunapuli static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg) 96352ee868SPavan Kunapuli { 97352ee868SPavan Kunapuli struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 98352ee868SPavan Kunapuli 99352ee868SPavan Kunapuli switch (reg) { 100352ee868SPavan Kunapuli case SDHCI_TRANSFER_MODE: 101352ee868SPavan Kunapuli /* 102352ee868SPavan Kunapuli * Postpone this write, we must do it together with a 103352ee868SPavan Kunapuli * command write that is down below. 104352ee868SPavan Kunapuli */ 105352ee868SPavan Kunapuli pltfm_host->xfer_mode_shadow = val; 106352ee868SPavan Kunapuli return; 107352ee868SPavan Kunapuli case SDHCI_COMMAND: 108352ee868SPavan Kunapuli writel((val << 16) | pltfm_host->xfer_mode_shadow, 109352ee868SPavan Kunapuli host->ioaddr + SDHCI_TRANSFER_MODE); 110352ee868SPavan Kunapuli return; 111352ee868SPavan Kunapuli } 112352ee868SPavan Kunapuli 113352ee868SPavan Kunapuli writew(val, host->ioaddr + reg); 114352ee868SPavan Kunapuli } 115352ee868SPavan Kunapuli 11603d2bfc8SOlof Johansson static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) 11703d2bfc8SOlof Johansson { 1183e44a1a7SStephen Warren struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1190734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 1203e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 1213e44a1a7SStephen Warren 12203d2bfc8SOlof Johansson /* Seems like we're getting spurious timeout and crc errors, so 12303d2bfc8SOlof Johansson * disable signalling of them. In case of real errors software 12403d2bfc8SOlof Johansson * timers should take care of eventually detecting them. 12503d2bfc8SOlof Johansson */ 12603d2bfc8SOlof Johansson if (unlikely(reg == SDHCI_SIGNAL_ENABLE)) 12703d2bfc8SOlof Johansson val &= ~(SDHCI_INT_TIMEOUT|SDHCI_INT_CRC); 12803d2bfc8SOlof Johansson 12903d2bfc8SOlof Johansson writel(val, host->ioaddr + reg); 13003d2bfc8SOlof Johansson 1313e44a1a7SStephen Warren if (unlikely((soc_data->nvquirks & NVQUIRK_ENABLE_BLOCK_GAP_DET) && 1323e44a1a7SStephen Warren (reg == SDHCI_INT_ENABLE))) { 13303d2bfc8SOlof Johansson /* Erratum: Must enable block gap interrupt detection */ 13403d2bfc8SOlof Johansson u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); 13503d2bfc8SOlof Johansson if (val & SDHCI_INT_CARD_INT) 13603d2bfc8SOlof Johansson gap_ctrl |= 0x8; 13703d2bfc8SOlof Johansson else 13803d2bfc8SOlof Johansson gap_ctrl &= ~0x8; 13903d2bfc8SOlof Johansson writeb(gap_ctrl, host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); 14003d2bfc8SOlof Johansson } 14103d2bfc8SOlof Johansson } 14203d2bfc8SOlof Johansson 1433e44a1a7SStephen Warren static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host) 14403d2bfc8SOlof Johansson { 1450aacd23fSJoseph Lo return mmc_gpio_get_ro(host->mmc); 14603d2bfc8SOlof Johansson } 14703d2bfc8SOlof Johansson 14886ac2f8bSAapo Vienamo static bool tegra_sdhci_is_pad_and_regulator_valid(struct sdhci_host *host) 14986ac2f8bSAapo Vienamo { 15086ac2f8bSAapo Vienamo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 15186ac2f8bSAapo Vienamo struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 15286ac2f8bSAapo Vienamo int has_1v8, has_3v3; 15386ac2f8bSAapo Vienamo 15486ac2f8bSAapo Vienamo /* 15586ac2f8bSAapo Vienamo * The SoCs which have NVQUIRK_NEEDS_PAD_CONTROL require software pad 15686ac2f8bSAapo Vienamo * voltage configuration in order to perform voltage switching. This 15786ac2f8bSAapo Vienamo * means that valid pinctrl info is required on SDHCI instances capable 15886ac2f8bSAapo Vienamo * of performing voltage switching. Whether or not an SDHCI instance is 15986ac2f8bSAapo Vienamo * capable of voltage switching is determined based on the regulator. 16086ac2f8bSAapo Vienamo */ 16186ac2f8bSAapo Vienamo 16286ac2f8bSAapo Vienamo if (!(tegra_host->soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL)) 16386ac2f8bSAapo Vienamo return true; 16486ac2f8bSAapo Vienamo 16586ac2f8bSAapo Vienamo if (IS_ERR(host->mmc->supply.vqmmc)) 16686ac2f8bSAapo Vienamo return false; 16786ac2f8bSAapo Vienamo 16886ac2f8bSAapo Vienamo has_1v8 = regulator_is_supported_voltage(host->mmc->supply.vqmmc, 16986ac2f8bSAapo Vienamo 1700000, 1950000); 17086ac2f8bSAapo Vienamo 17186ac2f8bSAapo Vienamo has_3v3 = regulator_is_supported_voltage(host->mmc->supply.vqmmc, 17286ac2f8bSAapo Vienamo 2700000, 3600000); 17386ac2f8bSAapo Vienamo 17486ac2f8bSAapo Vienamo if (has_1v8 == 1 && has_3v3 == 1) 17586ac2f8bSAapo Vienamo return tegra_host->pad_control_available; 17686ac2f8bSAapo Vienamo 17786ac2f8bSAapo Vienamo /* Fixed voltage, no pad control required. */ 17886ac2f8bSAapo Vienamo return true; 17986ac2f8bSAapo Vienamo } 18086ac2f8bSAapo Vienamo 18103231f9bSRussell King static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) 182ca5879d3SPavan Kunapuli { 183ca5879d3SPavan Kunapuli struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1840734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 185ca5879d3SPavan Kunapuli const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 18674cd42bcSLucas Stach u32 misc_ctrl, clk_ctrl; 187ca5879d3SPavan Kunapuli 18803231f9bSRussell King sdhci_reset(host, mask); 18903231f9bSRussell King 190ca5879d3SPavan Kunapuli if (!(mask & SDHCI_RESET_ALL)) 191ca5879d3SPavan Kunapuli return; 192ca5879d3SPavan Kunapuli 1931b84def8SLucas Stach misc_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL); 1944f6aa326SJon Hunter clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 1954f6aa326SJon Hunter 1964f6aa326SJon Hunter misc_ctrl &= ~(SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 | 1974f6aa326SJon Hunter SDHCI_MISC_CTRL_ENABLE_SDR50 | 1984f6aa326SJon Hunter SDHCI_MISC_CTRL_ENABLE_DDR50 | 1994f6aa326SJon Hunter SDHCI_MISC_CTRL_ENABLE_SDR104); 2004f6aa326SJon Hunter 2014f6aa326SJon Hunter clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE; 2024f6aa326SJon Hunter 20386ac2f8bSAapo Vienamo if (tegra_sdhci_is_pad_and_regulator_valid(host)) { 204ca5879d3SPavan Kunapuli /* Erratum: Enable SDHCI spec v3.00 support */ 2053145351aSAndrew Bresticker if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) 206ca5879d3SPavan Kunapuli misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300; 2077ad2ed1dSLucas Stach /* Advertise UHS modes as supported by host */ 2087ad2ed1dSLucas Stach if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50) 2097ad2ed1dSLucas Stach misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR50; 2107ad2ed1dSLucas Stach if (soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) 2117ad2ed1dSLucas Stach misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50; 2127ad2ed1dSLucas Stach if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104) 2137ad2ed1dSLucas Stach misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104; 2147ad2ed1dSLucas Stach if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50) 215c3c2384cSLucas Stach clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE; 2164f6aa326SJon Hunter } 2174f6aa326SJon Hunter 2184f6aa326SJon Hunter sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL); 21974cd42bcSLucas Stach sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 22074cd42bcSLucas Stach 221e5c63d91SLucas Stach if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) 222e5c63d91SLucas Stach tegra_host->pad_calib_required = true; 223e5c63d91SLucas Stach 224a8e326a9SLucas Stach tegra_host->ddr_signaling = false; 225ca5879d3SPavan Kunapuli } 226ca5879d3SPavan Kunapuli 227e5c63d91SLucas Stach static void tegra_sdhci_pad_autocalib(struct sdhci_host *host) 228e5c63d91SLucas Stach { 229e5c63d91SLucas Stach u32 val; 230e5c63d91SLucas Stach 231e5c63d91SLucas Stach mdelay(1); 232e5c63d91SLucas Stach 233e5c63d91SLucas Stach val = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG); 234e5c63d91SLucas Stach val |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START; 235e5c63d91SLucas Stach sdhci_writel(host,val, SDHCI_TEGRA_AUTO_CAL_CONFIG); 236e5c63d91SLucas Stach } 237e5c63d91SLucas Stach 238a8e326a9SLucas Stach static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 239a8e326a9SLucas Stach { 240a8e326a9SLucas Stach struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 2410734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 242a8e326a9SLucas Stach unsigned long host_clk; 243a8e326a9SLucas Stach 244a8e326a9SLucas Stach if (!clock) 2453491b690SLucas Stach return sdhci_set_clock(host, clock); 246a8e326a9SLucas Stach 24757d1654eSAapo Vienamo /* 24857d1654eSAapo Vienamo * In DDR50/52 modes the Tegra SDHCI controllers require the SDHCI 24957d1654eSAapo Vienamo * divider to be configured to divided the host clock by two. The SDHCI 25057d1654eSAapo Vienamo * clock divider is calculated as part of sdhci_set_clock() by 25157d1654eSAapo Vienamo * sdhci_calc_clk(). The divider is calculated from host->max_clk and 25257d1654eSAapo Vienamo * the requested clock rate. 25357d1654eSAapo Vienamo * 25457d1654eSAapo Vienamo * By setting the host->max_clk to clock * 2 the divider calculation 25557d1654eSAapo Vienamo * will always result in the correct value for DDR50/52 modes, 25657d1654eSAapo Vienamo * regardless of clock rate rounding, which may happen if the value 25757d1654eSAapo Vienamo * from clk_get_rate() is used. 25857d1654eSAapo Vienamo */ 259a8e326a9SLucas Stach host_clk = tegra_host->ddr_signaling ? clock * 2 : clock; 260a8e326a9SLucas Stach clk_set_rate(pltfm_host->clk, host_clk); 26157d1654eSAapo Vienamo if (tegra_host->ddr_signaling) 26257d1654eSAapo Vienamo host->max_clk = host_clk; 26357d1654eSAapo Vienamo else 264a8e326a9SLucas Stach host->max_clk = clk_get_rate(pltfm_host->clk); 265a8e326a9SLucas Stach 266e5c63d91SLucas Stach sdhci_set_clock(host, clock); 267e5c63d91SLucas Stach 268e5c63d91SLucas Stach if (tegra_host->pad_calib_required) { 269e5c63d91SLucas Stach tegra_sdhci_pad_autocalib(host); 270e5c63d91SLucas Stach tegra_host->pad_calib_required = false; 271e5c63d91SLucas Stach } 272a8e326a9SLucas Stach } 273a8e326a9SLucas Stach 274a8e326a9SLucas Stach static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host, 275a8e326a9SLucas Stach unsigned timing) 276a8e326a9SLucas Stach { 277a8e326a9SLucas Stach struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 2780734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 279a8e326a9SLucas Stach 280e300149eSStefan Agner if (timing == MMC_TIMING_UHS_DDR50 || 281e300149eSStefan Agner timing == MMC_TIMING_MMC_DDR52) 282a8e326a9SLucas Stach tegra_host->ddr_signaling = true; 283a8e326a9SLucas Stach 284cf56c819SAapo Vienamo sdhci_set_uhs_signaling(host, timing); 285a8e326a9SLucas Stach } 286a8e326a9SLucas Stach 28744350993SAapo Vienamo static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host) 28844350993SAapo Vienamo { 28944350993SAapo Vienamo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 29044350993SAapo Vienamo 29144350993SAapo Vienamo return clk_round_rate(pltfm_host->clk, UINT_MAX); 29244350993SAapo Vienamo } 29344350993SAapo Vienamo 294c3c2384cSLucas Stach static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap) 295c3c2384cSLucas Stach { 296c3c2384cSLucas Stach u32 reg; 297c3c2384cSLucas Stach 298c3c2384cSLucas Stach reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 299c3c2384cSLucas Stach reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK; 300c3c2384cSLucas Stach reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT; 301c3c2384cSLucas Stach sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 302c3c2384cSLucas Stach } 303c3c2384cSLucas Stach 304c3c2384cSLucas Stach static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) 305c3c2384cSLucas Stach { 306c3c2384cSLucas Stach unsigned int min, max; 307c3c2384cSLucas Stach 308c3c2384cSLucas Stach /* 309c3c2384cSLucas Stach * Start search for minimum tap value at 10, as smaller values are 310c3c2384cSLucas Stach * may wrongly be reported as working but fail at higher speeds, 311c3c2384cSLucas Stach * according to the TRM. 312c3c2384cSLucas Stach */ 313c3c2384cSLucas Stach min = 10; 314c3c2384cSLucas Stach while (min < 255) { 315c3c2384cSLucas Stach tegra_sdhci_set_tap(host, min); 316c3c2384cSLucas Stach if (!mmc_send_tuning(host->mmc, opcode, NULL)) 317c3c2384cSLucas Stach break; 318c3c2384cSLucas Stach min++; 319c3c2384cSLucas Stach } 320c3c2384cSLucas Stach 321c3c2384cSLucas Stach /* Find the maximum tap value that still passes. */ 322c3c2384cSLucas Stach max = min + 1; 323c3c2384cSLucas Stach while (max < 255) { 324c3c2384cSLucas Stach tegra_sdhci_set_tap(host, max); 325c3c2384cSLucas Stach if (mmc_send_tuning(host->mmc, opcode, NULL)) { 326c3c2384cSLucas Stach max--; 327c3c2384cSLucas Stach break; 328c3c2384cSLucas Stach } 329c3c2384cSLucas Stach max++; 330c3c2384cSLucas Stach } 331c3c2384cSLucas Stach 332c3c2384cSLucas Stach /* The TRM states the ideal tap value is at 75% in the passing range. */ 333c3c2384cSLucas Stach tegra_sdhci_set_tap(host, min + ((max - min) * 3 / 4)); 334c3c2384cSLucas Stach 335c3c2384cSLucas Stach return mmc_send_tuning(host->mmc, opcode, NULL); 336c3c2384cSLucas Stach } 337c3c2384cSLucas Stach 33886ac2f8bSAapo Vienamo static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage) 33986ac2f8bSAapo Vienamo { 34086ac2f8bSAapo Vienamo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 34186ac2f8bSAapo Vienamo struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 34286ac2f8bSAapo Vienamo int ret; 34386ac2f8bSAapo Vienamo 34486ac2f8bSAapo Vienamo if (!tegra_host->pad_control_available) 34586ac2f8bSAapo Vienamo return 0; 34686ac2f8bSAapo Vienamo 34786ac2f8bSAapo Vienamo if (voltage == MMC_SIGNAL_VOLTAGE_180) { 34886ac2f8bSAapo Vienamo ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, 34986ac2f8bSAapo Vienamo tegra_host->pinctrl_state_1v8); 35086ac2f8bSAapo Vienamo if (ret < 0) 35186ac2f8bSAapo Vienamo dev_err(mmc_dev(host->mmc), 35286ac2f8bSAapo Vienamo "setting 1.8V failed, ret: %d\n", ret); 35386ac2f8bSAapo Vienamo } else { 35486ac2f8bSAapo Vienamo ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc, 35586ac2f8bSAapo Vienamo tegra_host->pinctrl_state_3v3); 35686ac2f8bSAapo Vienamo if (ret < 0) 35786ac2f8bSAapo Vienamo dev_err(mmc_dev(host->mmc), 35886ac2f8bSAapo Vienamo "setting 3.3V failed, ret: %d\n", ret); 35986ac2f8bSAapo Vienamo } 36086ac2f8bSAapo Vienamo 36186ac2f8bSAapo Vienamo return ret; 36286ac2f8bSAapo Vienamo } 36386ac2f8bSAapo Vienamo 36486ac2f8bSAapo Vienamo static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc, 36586ac2f8bSAapo Vienamo struct mmc_ios *ios) 36686ac2f8bSAapo Vienamo { 36786ac2f8bSAapo Vienamo struct sdhci_host *host = mmc_priv(mmc); 36886ac2f8bSAapo Vienamo int ret = 0; 36986ac2f8bSAapo Vienamo 37086ac2f8bSAapo Vienamo if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { 37186ac2f8bSAapo Vienamo ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage); 37286ac2f8bSAapo Vienamo if (ret < 0) 37386ac2f8bSAapo Vienamo return ret; 37486ac2f8bSAapo Vienamo ret = sdhci_start_signal_voltage_switch(mmc, ios); 37586ac2f8bSAapo Vienamo } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { 37686ac2f8bSAapo Vienamo ret = sdhci_start_signal_voltage_switch(mmc, ios); 37786ac2f8bSAapo Vienamo if (ret < 0) 37886ac2f8bSAapo Vienamo return ret; 37986ac2f8bSAapo Vienamo ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage); 38086ac2f8bSAapo Vienamo } 38186ac2f8bSAapo Vienamo 38286ac2f8bSAapo Vienamo return ret; 38386ac2f8bSAapo Vienamo } 38486ac2f8bSAapo Vienamo 38586ac2f8bSAapo Vienamo static int tegra_sdhci_init_pinctrl_info(struct device *dev, 38686ac2f8bSAapo Vienamo struct sdhci_tegra *tegra_host) 38786ac2f8bSAapo Vienamo { 38886ac2f8bSAapo Vienamo tegra_host->pinctrl_sdmmc = devm_pinctrl_get(dev); 38986ac2f8bSAapo Vienamo if (IS_ERR(tegra_host->pinctrl_sdmmc)) { 39086ac2f8bSAapo Vienamo dev_dbg(dev, "No pinctrl info, err: %ld\n", 39186ac2f8bSAapo Vienamo PTR_ERR(tegra_host->pinctrl_sdmmc)); 39286ac2f8bSAapo Vienamo return -1; 39386ac2f8bSAapo Vienamo } 39486ac2f8bSAapo Vienamo 39586ac2f8bSAapo Vienamo tegra_host->pinctrl_state_3v3 = 39686ac2f8bSAapo Vienamo pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-3v3"); 39786ac2f8bSAapo Vienamo if (IS_ERR(tegra_host->pinctrl_state_3v3)) { 39886ac2f8bSAapo Vienamo dev_warn(dev, "Missing 3.3V pad state, err: %ld\n", 39986ac2f8bSAapo Vienamo PTR_ERR(tegra_host->pinctrl_state_3v3)); 40086ac2f8bSAapo Vienamo return -1; 40186ac2f8bSAapo Vienamo } 40286ac2f8bSAapo Vienamo 40386ac2f8bSAapo Vienamo tegra_host->pinctrl_state_1v8 = 40486ac2f8bSAapo Vienamo pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-1v8"); 40586ac2f8bSAapo Vienamo if (IS_ERR(tegra_host->pinctrl_state_1v8)) { 40686ac2f8bSAapo Vienamo dev_warn(dev, "Missing 1.8V pad state, err: %ld\n", 40786ac2f8bSAapo Vienamo PTR_ERR(tegra_host->pinctrl_state_3v3)); 40886ac2f8bSAapo Vienamo return -1; 40986ac2f8bSAapo Vienamo } 41086ac2f8bSAapo Vienamo 41186ac2f8bSAapo Vienamo tegra_host->pad_control_available = true; 41286ac2f8bSAapo Vienamo 41386ac2f8bSAapo Vienamo return 0; 41486ac2f8bSAapo Vienamo } 41586ac2f8bSAapo Vienamo 416e5c63d91SLucas Stach static void tegra_sdhci_voltage_switch(struct sdhci_host *host) 417e5c63d91SLucas Stach { 418e5c63d91SLucas Stach struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 419e5c63d91SLucas Stach struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 420e5c63d91SLucas Stach const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 421e5c63d91SLucas Stach 422e5c63d91SLucas Stach if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) 423e5c63d91SLucas Stach tegra_host->pad_calib_required = true; 424e5c63d91SLucas Stach } 425e5c63d91SLucas Stach 426c915568dSLars-Peter Clausen static const struct sdhci_ops tegra_sdhci_ops = { 42785d6509dSShawn Guo .get_ro = tegra_sdhci_get_ro, 42885d6509dSShawn Guo .read_w = tegra_sdhci_readw, 42985d6509dSShawn Guo .write_l = tegra_sdhci_writel, 430a8e326a9SLucas Stach .set_clock = tegra_sdhci_set_clock, 43114b04c6aSMichał Mirosław .set_bus_width = sdhci_set_bus_width, 43203231f9bSRussell King .reset = tegra_sdhci_reset, 433c3c2384cSLucas Stach .platform_execute_tuning = tegra_sdhci_execute_tuning, 434a8e326a9SLucas Stach .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, 435e5c63d91SLucas Stach .voltage_switch = tegra_sdhci_voltage_switch, 43644350993SAapo Vienamo .get_max_clock = tegra_sdhci_get_max_clock, 43785d6509dSShawn Guo }; 43803d2bfc8SOlof Johansson 4391db5eebfSLars-Peter Clausen static const struct sdhci_pltfm_data sdhci_tegra20_pdata = { 44085d6509dSShawn Guo .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 44185d6509dSShawn Guo SDHCI_QUIRK_SINGLE_POWER_WRITE | 44285d6509dSShawn Guo SDHCI_QUIRK_NO_HISPD_BIT | 443f9260355SAndrew Bresticker SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 444f9260355SAndrew Bresticker SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 44585d6509dSShawn Guo .ops = &tegra_sdhci_ops, 44685d6509dSShawn Guo }; 44785d6509dSShawn Guo 448d49d19c2SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra20 = { 4493e44a1a7SStephen Warren .pdata = &sdhci_tegra20_pdata, 4503e44a1a7SStephen Warren .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 | 4513e44a1a7SStephen Warren NVQUIRK_ENABLE_BLOCK_GAP_DET, 4523e44a1a7SStephen Warren }; 4533e44a1a7SStephen Warren 4541db5eebfSLars-Peter Clausen static const struct sdhci_pltfm_data sdhci_tegra30_pdata = { 4553e44a1a7SStephen Warren .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 4563e44a1a7SStephen Warren SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 4573e44a1a7SStephen Warren SDHCI_QUIRK_SINGLE_POWER_WRITE | 4583e44a1a7SStephen Warren SDHCI_QUIRK_NO_HISPD_BIT | 459f9260355SAndrew Bresticker SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 460f9260355SAndrew Bresticker SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 461127407e3SStefan Agner .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 462726df1d5SStefan Agner SDHCI_QUIRK2_BROKEN_HS200 | 463726df1d5SStefan Agner /* 464726df1d5SStefan Agner * Auto-CMD23 leads to "Got command interrupt 0x00010000 even 465726df1d5SStefan Agner * though no command operation was in progress." 466726df1d5SStefan Agner * 467726df1d5SStefan Agner * The exact reason is unknown, as the same hardware seems 468726df1d5SStefan Agner * to support Auto CMD23 on a downstream 3.1 kernel. 469726df1d5SStefan Agner */ 470726df1d5SStefan Agner SDHCI_QUIRK2_ACMD23_BROKEN, 4713e44a1a7SStephen Warren .ops = &tegra_sdhci_ops, 4723e44a1a7SStephen Warren }; 4733e44a1a7SStephen Warren 474d49d19c2SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra30 = { 4753e44a1a7SStephen Warren .pdata = &sdhci_tegra30_pdata, 4763145351aSAndrew Bresticker .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 | 4777ad2ed1dSLucas Stach NVQUIRK_ENABLE_SDR50 | 478e5c63d91SLucas Stach NVQUIRK_ENABLE_SDR104 | 479e5c63d91SLucas Stach NVQUIRK_HAS_PADCALIB, 4803e44a1a7SStephen Warren }; 4813e44a1a7SStephen Warren 48201df7ecdSRhyland Klein static const struct sdhci_ops tegra114_sdhci_ops = { 48301df7ecdSRhyland Klein .get_ro = tegra_sdhci_get_ro, 48401df7ecdSRhyland Klein .read_w = tegra_sdhci_readw, 48501df7ecdSRhyland Klein .write_w = tegra_sdhci_writew, 48601df7ecdSRhyland Klein .write_l = tegra_sdhci_writel, 487a8e326a9SLucas Stach .set_clock = tegra_sdhci_set_clock, 48814b04c6aSMichał Mirosław .set_bus_width = sdhci_set_bus_width, 48901df7ecdSRhyland Klein .reset = tegra_sdhci_reset, 490c3c2384cSLucas Stach .platform_execute_tuning = tegra_sdhci_execute_tuning, 491a8e326a9SLucas Stach .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, 492e5c63d91SLucas Stach .voltage_switch = tegra_sdhci_voltage_switch, 49344350993SAapo Vienamo .get_max_clock = tegra_sdhci_get_max_clock, 49401df7ecdSRhyland Klein }; 49501df7ecdSRhyland Klein 4961db5eebfSLars-Peter Clausen static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { 4975ebf2552SRhyland Klein .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 4985ebf2552SRhyland Klein SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 4995ebf2552SRhyland Klein SDHCI_QUIRK_SINGLE_POWER_WRITE | 5005ebf2552SRhyland Klein SDHCI_QUIRK_NO_HISPD_BIT | 501f9260355SAndrew Bresticker SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 502f9260355SAndrew Bresticker SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 503a8e326a9SLucas Stach .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, 50401df7ecdSRhyland Klein .ops = &tegra114_sdhci_ops, 5055ebf2552SRhyland Klein }; 5065ebf2552SRhyland Klein 507d49d19c2SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra114 = { 5085ebf2552SRhyland Klein .pdata = &sdhci_tegra114_pdata, 5097bf037d6SJon Hunter }; 5107bf037d6SJon Hunter 5114ae12588SThierry Reding static const struct sdhci_pltfm_data sdhci_tegra124_pdata = { 5124ae12588SThierry Reding .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 5134ae12588SThierry Reding SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 5144ae12588SThierry Reding SDHCI_QUIRK_SINGLE_POWER_WRITE | 5154ae12588SThierry Reding SDHCI_QUIRK_NO_HISPD_BIT | 5164ae12588SThierry Reding SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 5174ae12588SThierry Reding SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 5184ae12588SThierry Reding .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 5194ae12588SThierry Reding /* 5204ae12588SThierry Reding * The TRM states that the SD/MMC controller found on 5214ae12588SThierry Reding * Tegra124 can address 34 bits (the maximum supported by 5224ae12588SThierry Reding * the Tegra memory controller), but tests show that DMA 5234ae12588SThierry Reding * to or from above 4 GiB doesn't work. This is possibly 5244ae12588SThierry Reding * caused by missing programming, though it's not obvious 5254ae12588SThierry Reding * what sequence is required. Mark 64-bit DMA broken for 5264ae12588SThierry Reding * now to fix this for existing users (e.g. Nyan boards). 5274ae12588SThierry Reding */ 5284ae12588SThierry Reding SDHCI_QUIRK2_BROKEN_64_BIT_DMA, 5294ae12588SThierry Reding .ops = &tegra114_sdhci_ops, 5304ae12588SThierry Reding }; 5314ae12588SThierry Reding 5324ae12588SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra124 = { 5334ae12588SThierry Reding .pdata = &sdhci_tegra124_pdata, 5344ae12588SThierry Reding }; 5354ae12588SThierry Reding 536b5a84ecfSThierry Reding static const struct sdhci_pltfm_data sdhci_tegra210_pdata = { 537b5a84ecfSThierry Reding .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 538b5a84ecfSThierry Reding SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 539b5a84ecfSThierry Reding SDHCI_QUIRK_SINGLE_POWER_WRITE | 540b5a84ecfSThierry Reding SDHCI_QUIRK_NO_HISPD_BIT | 541a8e326a9SLucas Stach SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 542a8e326a9SLucas Stach SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 543a8e326a9SLucas Stach .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, 544b5a84ecfSThierry Reding .ops = &tegra114_sdhci_ops, 545b5a84ecfSThierry Reding }; 546b5a84ecfSThierry Reding 547b5a84ecfSThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra210 = { 548b5a84ecfSThierry Reding .pdata = &sdhci_tegra210_pdata, 54986ac2f8bSAapo Vienamo .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL, 550b5a84ecfSThierry Reding }; 551b5a84ecfSThierry Reding 5524346b7c7SThierry Reding static const struct sdhci_pltfm_data sdhci_tegra186_pdata = { 5534346b7c7SThierry Reding .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 5544346b7c7SThierry Reding SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 5554346b7c7SThierry Reding SDHCI_QUIRK_SINGLE_POWER_WRITE | 5564346b7c7SThierry Reding SDHCI_QUIRK_NO_HISPD_BIT | 5574346b7c7SThierry Reding SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 5584346b7c7SThierry Reding SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 55968481a7eSKrishna Reddy .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 56068481a7eSKrishna Reddy /* SDHCI controllers on Tegra186 support 40-bit addressing. 56168481a7eSKrishna Reddy * IOVA addresses are 48-bit wide on Tegra186. 56268481a7eSKrishna Reddy * With 64-bit dma mask used for SDHCI, accesses can 56368481a7eSKrishna Reddy * be broken. Disable 64-bit dma, which would fall back 56468481a7eSKrishna Reddy * to 32-bit dma mask. Ideally 40-bit dma mask would work, 56568481a7eSKrishna Reddy * But it is not supported as of now. 56668481a7eSKrishna Reddy */ 56768481a7eSKrishna Reddy SDHCI_QUIRK2_BROKEN_64_BIT_DMA, 5684346b7c7SThierry Reding .ops = &tegra114_sdhci_ops, 5694346b7c7SThierry Reding }; 5704346b7c7SThierry Reding 5714346b7c7SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra186 = { 5724346b7c7SThierry Reding .pdata = &sdhci_tegra186_pdata, 57386ac2f8bSAapo Vienamo .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL, 5744346b7c7SThierry Reding }; 5754346b7c7SThierry Reding 576498d83e7SBill Pemberton static const struct of_device_id sdhci_tegra_dt_match[] = { 5774346b7c7SThierry Reding { .compatible = "nvidia,tegra186-sdhci", .data = &soc_data_tegra186 }, 578b5a84ecfSThierry Reding { .compatible = "nvidia,tegra210-sdhci", .data = &soc_data_tegra210 }, 5794ae12588SThierry Reding { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra124 }, 5805ebf2552SRhyland Klein { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, 5813e44a1a7SStephen Warren { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, 5823e44a1a7SStephen Warren { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, 583275173b2SGrant Likely {} 584275173b2SGrant Likely }; 585e4404fabSArnd Bergmann MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); 586275173b2SGrant Likely 587c3be1efdSBill Pemberton static int sdhci_tegra_probe(struct platform_device *pdev) 58803d2bfc8SOlof Johansson { 5893e44a1a7SStephen Warren const struct of_device_id *match; 5903e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data; 5913e44a1a7SStephen Warren struct sdhci_host *host; 59285d6509dSShawn Guo struct sdhci_pltfm_host *pltfm_host; 5933e44a1a7SStephen Warren struct sdhci_tegra *tegra_host; 59403d2bfc8SOlof Johansson struct clk *clk; 59503d2bfc8SOlof Johansson int rc; 59603d2bfc8SOlof Johansson 5973e44a1a7SStephen Warren match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); 598b37f9d98SJoseph Lo if (!match) 599b37f9d98SJoseph Lo return -EINVAL; 6003e44a1a7SStephen Warren soc_data = match->data; 6013e44a1a7SStephen Warren 6020734e79cSJisheng Zhang host = sdhci_pltfm_init(pdev, soc_data->pdata, sizeof(*tegra_host)); 60385d6509dSShawn Guo if (IS_ERR(host)) 60485d6509dSShawn Guo return PTR_ERR(host); 60585d6509dSShawn Guo pltfm_host = sdhci_priv(host); 60685d6509dSShawn Guo 6070734e79cSJisheng Zhang tegra_host = sdhci_pltfm_priv(pltfm_host); 608a8e326a9SLucas Stach tegra_host->ddr_signaling = false; 609e5c63d91SLucas Stach tegra_host->pad_calib_required = false; 61086ac2f8bSAapo Vienamo tegra_host->pad_control_available = false; 6113e44a1a7SStephen Warren tegra_host->soc_data = soc_data; 612275173b2SGrant Likely 61386ac2f8bSAapo Vienamo if (soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL) { 61486ac2f8bSAapo Vienamo rc = tegra_sdhci_init_pinctrl_info(&pdev->dev, tegra_host); 61586ac2f8bSAapo Vienamo if (rc == 0) 61686ac2f8bSAapo Vienamo host->mmc_host_ops.start_signal_voltage_switch = 61786ac2f8bSAapo Vienamo sdhci_tegra_start_signal_voltage_switch; 61886ac2f8bSAapo Vienamo } 61986ac2f8bSAapo Vienamo 6202391b340SMylene JOSSERAND rc = mmc_of_parse(host->mmc); 62147caa84fSSimon Baatz if (rc) 62247caa84fSSimon Baatz goto err_parse_dt; 6230e786102SStephen Warren 6247ad2ed1dSLucas Stach if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) 625c3c2384cSLucas Stach host->mmc->caps |= MMC_CAP_1_8V_DDR; 626c3c2384cSLucas Stach 6272391b340SMylene JOSSERAND tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power", 6282391b340SMylene JOSSERAND GPIOD_OUT_HIGH); 6292391b340SMylene JOSSERAND if (IS_ERR(tegra_host->power_gpio)) { 6302391b340SMylene JOSSERAND rc = PTR_ERR(tegra_host->power_gpio); 63185d6509dSShawn Guo goto err_power_req; 63203d2bfc8SOlof Johansson } 63303d2bfc8SOlof Johansson 634e4f79d9cSKevin Hao clk = devm_clk_get(mmc_dev(host->mmc), NULL); 63503d2bfc8SOlof Johansson if (IS_ERR(clk)) { 63603d2bfc8SOlof Johansson dev_err(mmc_dev(host->mmc), "clk err\n"); 63703d2bfc8SOlof Johansson rc = PTR_ERR(clk); 63885d6509dSShawn Guo goto err_clk_get; 63903d2bfc8SOlof Johansson } 6401e674bc6SPrashant Gaikwad clk_prepare_enable(clk); 64103d2bfc8SOlof Johansson pltfm_host->clk = clk; 64203d2bfc8SOlof Johansson 6432cd6c49dSPhilipp Zabel tegra_host->rst = devm_reset_control_get_exclusive(&pdev->dev, 6442cd6c49dSPhilipp Zabel "sdhci"); 64520567be9SThierry Reding if (IS_ERR(tegra_host->rst)) { 64620567be9SThierry Reding rc = PTR_ERR(tegra_host->rst); 64720567be9SThierry Reding dev_err(&pdev->dev, "failed to get reset control: %d\n", rc); 64820567be9SThierry Reding goto err_rst_get; 64920567be9SThierry Reding } 65020567be9SThierry Reding 65120567be9SThierry Reding rc = reset_control_assert(tegra_host->rst); 65220567be9SThierry Reding if (rc) 65320567be9SThierry Reding goto err_rst_get; 65420567be9SThierry Reding 65520567be9SThierry Reding usleep_range(2000, 4000); 65620567be9SThierry Reding 65720567be9SThierry Reding rc = reset_control_deassert(tegra_host->rst); 65820567be9SThierry Reding if (rc) 65920567be9SThierry Reding goto err_rst_get; 66020567be9SThierry Reding 66120567be9SThierry Reding usleep_range(2000, 4000); 66220567be9SThierry Reding 66385d6509dSShawn Guo rc = sdhci_add_host(host); 66485d6509dSShawn Guo if (rc) 66585d6509dSShawn Guo goto err_add_host; 66685d6509dSShawn Guo 66703d2bfc8SOlof Johansson return 0; 66803d2bfc8SOlof Johansson 66985d6509dSShawn Guo err_add_host: 67020567be9SThierry Reding reset_control_assert(tegra_host->rst); 67120567be9SThierry Reding err_rst_get: 6721e674bc6SPrashant Gaikwad clk_disable_unprepare(pltfm_host->clk); 67385d6509dSShawn Guo err_clk_get: 67485d6509dSShawn Guo err_power_req: 67547caa84fSSimon Baatz err_parse_dt: 67685d6509dSShawn Guo sdhci_pltfm_free(pdev); 67703d2bfc8SOlof Johansson return rc; 67803d2bfc8SOlof Johansson } 67903d2bfc8SOlof Johansson 68020567be9SThierry Reding static int sdhci_tegra_remove(struct platform_device *pdev) 68120567be9SThierry Reding { 68220567be9SThierry Reding struct sdhci_host *host = platform_get_drvdata(pdev); 68320567be9SThierry Reding struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 68420567be9SThierry Reding struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 68520567be9SThierry Reding 68620567be9SThierry Reding sdhci_remove_host(host, 0); 68720567be9SThierry Reding 68820567be9SThierry Reding reset_control_assert(tegra_host->rst); 68920567be9SThierry Reding usleep_range(2000, 4000); 69020567be9SThierry Reding clk_disable_unprepare(pltfm_host->clk); 69120567be9SThierry Reding 69220567be9SThierry Reding sdhci_pltfm_free(pdev); 69320567be9SThierry Reding 69420567be9SThierry Reding return 0; 69520567be9SThierry Reding } 69620567be9SThierry Reding 69785d6509dSShawn Guo static struct platform_driver sdhci_tegra_driver = { 69885d6509dSShawn Guo .driver = { 69985d6509dSShawn Guo .name = "sdhci-tegra", 700275173b2SGrant Likely .of_match_table = sdhci_tegra_dt_match, 701fa243f64SUlf Hansson .pm = &sdhci_pltfm_pmops, 70285d6509dSShawn Guo }, 70385d6509dSShawn Guo .probe = sdhci_tegra_probe, 70420567be9SThierry Reding .remove = sdhci_tegra_remove, 70503d2bfc8SOlof Johansson }; 70603d2bfc8SOlof Johansson 707d1f81a64SAxel Lin module_platform_driver(sdhci_tegra_driver); 70885d6509dSShawn Guo 70985d6509dSShawn Guo MODULE_DESCRIPTION("SDHCI driver for Tegra"); 71085d6509dSShawn Guo MODULE_AUTHOR("Google, Inc."); 71185d6509dSShawn Guo MODULE_LICENSE("GPL v2"); 712