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> 2420567be9SThierry Reding #include <linux/reset.h> 2503d2bfc8SOlof Johansson #include <linux/mmc/card.h> 2603d2bfc8SOlof Johansson #include <linux/mmc/host.h> 27c3c2384cSLucas Stach #include <linux/mmc/mmc.h> 280aacd23fSJoseph Lo #include <linux/mmc/slot-gpio.h> 292391b340SMylene JOSSERAND #include <linux/gpio/consumer.h> 3003d2bfc8SOlof Johansson 3103d2bfc8SOlof Johansson #include "sdhci-pltfm.h" 3203d2bfc8SOlof Johansson 33ca5879d3SPavan Kunapuli /* Tegra SDHOST controller vendor register definitions */ 3474cd42bcSLucas Stach #define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100 35c3c2384cSLucas Stach #define SDHCI_CLOCK_CTRL_TAP_MASK 0x00ff0000 36c3c2384cSLucas Stach #define SDHCI_CLOCK_CTRL_TAP_SHIFT 16 37c3c2384cSLucas Stach #define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE BIT(5) 3874cd42bcSLucas Stach #define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDE BIT(3) 3974cd42bcSLucas Stach #define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE BIT(2) 4074cd42bcSLucas Stach 41ca5879d3SPavan Kunapuli #define SDHCI_TEGRA_VENDOR_MISC_CTRL 0x120 423145351aSAndrew Bresticker #define SDHCI_MISC_CTRL_ENABLE_SDR104 0x8 433145351aSAndrew Bresticker #define SDHCI_MISC_CTRL_ENABLE_SDR50 0x10 44ca5879d3SPavan Kunapuli #define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20 453145351aSAndrew Bresticker #define SDHCI_MISC_CTRL_ENABLE_DDR50 0x200 46ca5879d3SPavan Kunapuli 47e5c63d91SLucas Stach #define SDHCI_TEGRA_AUTO_CAL_CONFIG 0x1e4 48e5c63d91SLucas Stach #define SDHCI_AUTO_CAL_START BIT(31) 49e5c63d91SLucas Stach #define SDHCI_AUTO_CAL_ENABLE BIT(29) 50e5c63d91SLucas Stach 513e44a1a7SStephen Warren #define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0) 523e44a1a7SStephen Warren #define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1) 53ca5879d3SPavan Kunapuli #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2) 547ad2ed1dSLucas Stach #define NVQUIRK_ENABLE_SDR50 BIT(3) 557ad2ed1dSLucas Stach #define NVQUIRK_ENABLE_SDR104 BIT(4) 567ad2ed1dSLucas Stach #define NVQUIRK_ENABLE_DDR50 BIT(5) 57e5c63d91SLucas Stach #define NVQUIRK_HAS_PADCALIB BIT(6) 583e44a1a7SStephen Warren 593e44a1a7SStephen Warren struct sdhci_tegra_soc_data { 601db5eebfSLars-Peter Clausen const struct sdhci_pltfm_data *pdata; 613e44a1a7SStephen Warren u32 nvquirks; 623e44a1a7SStephen Warren }; 633e44a1a7SStephen Warren 643e44a1a7SStephen Warren struct sdhci_tegra { 653e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data; 662391b340SMylene JOSSERAND struct gpio_desc *power_gpio; 67a8e326a9SLucas Stach bool ddr_signaling; 68e5c63d91SLucas Stach bool pad_calib_required; 6920567be9SThierry Reding 7020567be9SThierry Reding struct reset_control *rst; 713e44a1a7SStephen Warren }; 723e44a1a7SStephen Warren 7303d2bfc8SOlof Johansson static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) 7403d2bfc8SOlof Johansson { 753e44a1a7SStephen Warren struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 760734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 773e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 783e44a1a7SStephen Warren 793e44a1a7SStephen Warren if (unlikely((soc_data->nvquirks & NVQUIRK_FORCE_SDHCI_SPEC_200) && 803e44a1a7SStephen Warren (reg == SDHCI_HOST_VERSION))) { 8103d2bfc8SOlof Johansson /* Erratum: Version register is invalid in HW. */ 8203d2bfc8SOlof Johansson return SDHCI_SPEC_200; 8303d2bfc8SOlof Johansson } 8403d2bfc8SOlof Johansson 8503d2bfc8SOlof Johansson return readw(host->ioaddr + reg); 8603d2bfc8SOlof Johansson } 8703d2bfc8SOlof Johansson 88352ee868SPavan Kunapuli static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg) 89352ee868SPavan Kunapuli { 90352ee868SPavan Kunapuli struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 91352ee868SPavan Kunapuli 92352ee868SPavan Kunapuli switch (reg) { 93352ee868SPavan Kunapuli case SDHCI_TRANSFER_MODE: 94352ee868SPavan Kunapuli /* 95352ee868SPavan Kunapuli * Postpone this write, we must do it together with a 96352ee868SPavan Kunapuli * command write that is down below. 97352ee868SPavan Kunapuli */ 98352ee868SPavan Kunapuli pltfm_host->xfer_mode_shadow = val; 99352ee868SPavan Kunapuli return; 100352ee868SPavan Kunapuli case SDHCI_COMMAND: 101352ee868SPavan Kunapuli writel((val << 16) | pltfm_host->xfer_mode_shadow, 102352ee868SPavan Kunapuli host->ioaddr + SDHCI_TRANSFER_MODE); 103352ee868SPavan Kunapuli return; 104352ee868SPavan Kunapuli } 105352ee868SPavan Kunapuli 106352ee868SPavan Kunapuli writew(val, host->ioaddr + reg); 107352ee868SPavan Kunapuli } 108352ee868SPavan Kunapuli 10903d2bfc8SOlof Johansson static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) 11003d2bfc8SOlof Johansson { 1113e44a1a7SStephen Warren struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1120734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 1133e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 1143e44a1a7SStephen Warren 11503d2bfc8SOlof Johansson /* Seems like we're getting spurious timeout and crc errors, so 11603d2bfc8SOlof Johansson * disable signalling of them. In case of real errors software 11703d2bfc8SOlof Johansson * timers should take care of eventually detecting them. 11803d2bfc8SOlof Johansson */ 11903d2bfc8SOlof Johansson if (unlikely(reg == SDHCI_SIGNAL_ENABLE)) 12003d2bfc8SOlof Johansson val &= ~(SDHCI_INT_TIMEOUT|SDHCI_INT_CRC); 12103d2bfc8SOlof Johansson 12203d2bfc8SOlof Johansson writel(val, host->ioaddr + reg); 12303d2bfc8SOlof Johansson 1243e44a1a7SStephen Warren if (unlikely((soc_data->nvquirks & NVQUIRK_ENABLE_BLOCK_GAP_DET) && 1253e44a1a7SStephen Warren (reg == SDHCI_INT_ENABLE))) { 12603d2bfc8SOlof Johansson /* Erratum: Must enable block gap interrupt detection */ 12703d2bfc8SOlof Johansson u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); 12803d2bfc8SOlof Johansson if (val & SDHCI_INT_CARD_INT) 12903d2bfc8SOlof Johansson gap_ctrl |= 0x8; 13003d2bfc8SOlof Johansson else 13103d2bfc8SOlof Johansson gap_ctrl &= ~0x8; 13203d2bfc8SOlof Johansson writeb(gap_ctrl, host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); 13303d2bfc8SOlof Johansson } 13403d2bfc8SOlof Johansson } 13503d2bfc8SOlof Johansson 1363e44a1a7SStephen Warren static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host) 13703d2bfc8SOlof Johansson { 1380aacd23fSJoseph Lo return mmc_gpio_get_ro(host->mmc); 13903d2bfc8SOlof Johansson } 14003d2bfc8SOlof Johansson 14103231f9bSRussell King static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) 142ca5879d3SPavan Kunapuli { 143ca5879d3SPavan Kunapuli struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1440734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 145ca5879d3SPavan Kunapuli const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 14674cd42bcSLucas Stach u32 misc_ctrl, clk_ctrl; 147ca5879d3SPavan Kunapuli 14803231f9bSRussell King sdhci_reset(host, mask); 14903231f9bSRussell King 150ca5879d3SPavan Kunapuli if (!(mask & SDHCI_RESET_ALL)) 151ca5879d3SPavan Kunapuli return; 152ca5879d3SPavan Kunapuli 1531b84def8SLucas Stach misc_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL); 1544f6aa326SJon Hunter clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 1554f6aa326SJon Hunter 1564f6aa326SJon Hunter misc_ctrl &= ~(SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 | 1574f6aa326SJon Hunter SDHCI_MISC_CTRL_ENABLE_SDR50 | 1584f6aa326SJon Hunter SDHCI_MISC_CTRL_ENABLE_DDR50 | 1594f6aa326SJon Hunter SDHCI_MISC_CTRL_ENABLE_SDR104); 1604f6aa326SJon Hunter 1614f6aa326SJon Hunter clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE; 1624f6aa326SJon Hunter 1634f6aa326SJon Hunter /* 1644f6aa326SJon Hunter * If the board does not define a regulator for the SDHCI 1654f6aa326SJon Hunter * IO voltage, then don't advertise support for UHS modes 1664f6aa326SJon Hunter * even if the device supports it because the IO voltage 1674f6aa326SJon Hunter * cannot be configured. 1684f6aa326SJon Hunter */ 1694f6aa326SJon Hunter if (!IS_ERR(host->mmc->supply.vqmmc)) { 170ca5879d3SPavan Kunapuli /* Erratum: Enable SDHCI spec v3.00 support */ 1713145351aSAndrew Bresticker if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) 172ca5879d3SPavan Kunapuli misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300; 1737ad2ed1dSLucas Stach /* Advertise UHS modes as supported by host */ 1747ad2ed1dSLucas Stach if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50) 1757ad2ed1dSLucas Stach misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR50; 1767ad2ed1dSLucas Stach if (soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) 1777ad2ed1dSLucas Stach misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50; 1787ad2ed1dSLucas Stach if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104) 1797ad2ed1dSLucas Stach misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104; 1807ad2ed1dSLucas Stach if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50) 181c3c2384cSLucas Stach clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE; 1824f6aa326SJon Hunter } 1834f6aa326SJon Hunter 1844f6aa326SJon Hunter sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL); 18574cd42bcSLucas Stach sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 18674cd42bcSLucas Stach 187e5c63d91SLucas Stach if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) 188e5c63d91SLucas Stach tegra_host->pad_calib_required = true; 189e5c63d91SLucas Stach 190a8e326a9SLucas Stach tegra_host->ddr_signaling = false; 191ca5879d3SPavan Kunapuli } 192ca5879d3SPavan Kunapuli 193e5c63d91SLucas Stach static void tegra_sdhci_pad_autocalib(struct sdhci_host *host) 194e5c63d91SLucas Stach { 195e5c63d91SLucas Stach u32 val; 196e5c63d91SLucas Stach 197e5c63d91SLucas Stach mdelay(1); 198e5c63d91SLucas Stach 199e5c63d91SLucas Stach val = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG); 200e5c63d91SLucas Stach val |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START; 201e5c63d91SLucas Stach sdhci_writel(host,val, SDHCI_TEGRA_AUTO_CAL_CONFIG); 202e5c63d91SLucas Stach } 203e5c63d91SLucas Stach 204a8e326a9SLucas Stach static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 205a8e326a9SLucas Stach { 206a8e326a9SLucas Stach struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 2070734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 208a8e326a9SLucas Stach unsigned long host_clk; 209a8e326a9SLucas Stach 210a8e326a9SLucas Stach if (!clock) 2113491b690SLucas Stach return sdhci_set_clock(host, clock); 212a8e326a9SLucas Stach 21357d1654eSAapo Vienamo /* 21457d1654eSAapo Vienamo * In DDR50/52 modes the Tegra SDHCI controllers require the SDHCI 21557d1654eSAapo Vienamo * divider to be configured to divided the host clock by two. The SDHCI 21657d1654eSAapo Vienamo * clock divider is calculated as part of sdhci_set_clock() by 21757d1654eSAapo Vienamo * sdhci_calc_clk(). The divider is calculated from host->max_clk and 21857d1654eSAapo Vienamo * the requested clock rate. 21957d1654eSAapo Vienamo * 22057d1654eSAapo Vienamo * By setting the host->max_clk to clock * 2 the divider calculation 22157d1654eSAapo Vienamo * will always result in the correct value for DDR50/52 modes, 22257d1654eSAapo Vienamo * regardless of clock rate rounding, which may happen if the value 22357d1654eSAapo Vienamo * from clk_get_rate() is used. 22457d1654eSAapo Vienamo */ 225a8e326a9SLucas Stach host_clk = tegra_host->ddr_signaling ? clock * 2 : clock; 226a8e326a9SLucas Stach clk_set_rate(pltfm_host->clk, host_clk); 22757d1654eSAapo Vienamo if (tegra_host->ddr_signaling) 22857d1654eSAapo Vienamo host->max_clk = host_clk; 22957d1654eSAapo Vienamo else 230a8e326a9SLucas Stach host->max_clk = clk_get_rate(pltfm_host->clk); 231a8e326a9SLucas Stach 232e5c63d91SLucas Stach sdhci_set_clock(host, clock); 233e5c63d91SLucas Stach 234e5c63d91SLucas Stach if (tegra_host->pad_calib_required) { 235e5c63d91SLucas Stach tegra_sdhci_pad_autocalib(host); 236e5c63d91SLucas Stach tegra_host->pad_calib_required = false; 237e5c63d91SLucas Stach } 238a8e326a9SLucas Stach } 239a8e326a9SLucas Stach 240a8e326a9SLucas Stach static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host, 241a8e326a9SLucas Stach unsigned timing) 242a8e326a9SLucas Stach { 243a8e326a9SLucas Stach struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 2440734e79cSJisheng Zhang struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 245a8e326a9SLucas Stach 246e300149eSStefan Agner if (timing == MMC_TIMING_UHS_DDR50 || 247e300149eSStefan Agner timing == MMC_TIMING_MMC_DDR52) 248a8e326a9SLucas Stach tegra_host->ddr_signaling = true; 249a8e326a9SLucas Stach 250cf56c819SAapo Vienamo sdhci_set_uhs_signaling(host, timing); 251a8e326a9SLucas Stach } 252a8e326a9SLucas Stach 25344350993SAapo Vienamo static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host) 25444350993SAapo Vienamo { 25544350993SAapo Vienamo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 25644350993SAapo Vienamo 25744350993SAapo Vienamo return clk_round_rate(pltfm_host->clk, UINT_MAX); 25844350993SAapo Vienamo } 25944350993SAapo Vienamo 260c3c2384cSLucas Stach static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap) 261c3c2384cSLucas Stach { 262c3c2384cSLucas Stach u32 reg; 263c3c2384cSLucas Stach 264c3c2384cSLucas Stach reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 265c3c2384cSLucas Stach reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK; 266c3c2384cSLucas Stach reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT; 267c3c2384cSLucas Stach sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); 268c3c2384cSLucas Stach } 269c3c2384cSLucas Stach 270c3c2384cSLucas Stach static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) 271c3c2384cSLucas Stach { 272c3c2384cSLucas Stach unsigned int min, max; 273c3c2384cSLucas Stach 274c3c2384cSLucas Stach /* 275c3c2384cSLucas Stach * Start search for minimum tap value at 10, as smaller values are 276c3c2384cSLucas Stach * may wrongly be reported as working but fail at higher speeds, 277c3c2384cSLucas Stach * according to the TRM. 278c3c2384cSLucas Stach */ 279c3c2384cSLucas Stach min = 10; 280c3c2384cSLucas Stach while (min < 255) { 281c3c2384cSLucas Stach tegra_sdhci_set_tap(host, min); 282c3c2384cSLucas Stach if (!mmc_send_tuning(host->mmc, opcode, NULL)) 283c3c2384cSLucas Stach break; 284c3c2384cSLucas Stach min++; 285c3c2384cSLucas Stach } 286c3c2384cSLucas Stach 287c3c2384cSLucas Stach /* Find the maximum tap value that still passes. */ 288c3c2384cSLucas Stach max = min + 1; 289c3c2384cSLucas Stach while (max < 255) { 290c3c2384cSLucas Stach tegra_sdhci_set_tap(host, max); 291c3c2384cSLucas Stach if (mmc_send_tuning(host->mmc, opcode, NULL)) { 292c3c2384cSLucas Stach max--; 293c3c2384cSLucas Stach break; 294c3c2384cSLucas Stach } 295c3c2384cSLucas Stach max++; 296c3c2384cSLucas Stach } 297c3c2384cSLucas Stach 298c3c2384cSLucas Stach /* The TRM states the ideal tap value is at 75% in the passing range. */ 299c3c2384cSLucas Stach tegra_sdhci_set_tap(host, min + ((max - min) * 3 / 4)); 300c3c2384cSLucas Stach 301c3c2384cSLucas Stach return mmc_send_tuning(host->mmc, opcode, NULL); 302c3c2384cSLucas Stach } 303c3c2384cSLucas Stach 304e5c63d91SLucas Stach static void tegra_sdhci_voltage_switch(struct sdhci_host *host) 305e5c63d91SLucas Stach { 306e5c63d91SLucas Stach struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 307e5c63d91SLucas Stach struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 308e5c63d91SLucas Stach const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 309e5c63d91SLucas Stach 310e5c63d91SLucas Stach if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) 311e5c63d91SLucas Stach tegra_host->pad_calib_required = true; 312e5c63d91SLucas Stach } 313e5c63d91SLucas Stach 314c915568dSLars-Peter Clausen static const struct sdhci_ops tegra_sdhci_ops = { 31585d6509dSShawn Guo .get_ro = tegra_sdhci_get_ro, 31685d6509dSShawn Guo .read_w = tegra_sdhci_readw, 31785d6509dSShawn Guo .write_l = tegra_sdhci_writel, 318a8e326a9SLucas Stach .set_clock = tegra_sdhci_set_clock, 31914b04c6aSMichał Mirosław .set_bus_width = sdhci_set_bus_width, 32003231f9bSRussell King .reset = tegra_sdhci_reset, 321c3c2384cSLucas Stach .platform_execute_tuning = tegra_sdhci_execute_tuning, 322a8e326a9SLucas Stach .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, 323e5c63d91SLucas Stach .voltage_switch = tegra_sdhci_voltage_switch, 32444350993SAapo Vienamo .get_max_clock = tegra_sdhci_get_max_clock, 32585d6509dSShawn Guo }; 32603d2bfc8SOlof Johansson 3271db5eebfSLars-Peter Clausen static const struct sdhci_pltfm_data sdhci_tegra20_pdata = { 32885d6509dSShawn Guo .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 32985d6509dSShawn Guo SDHCI_QUIRK_SINGLE_POWER_WRITE | 33085d6509dSShawn Guo SDHCI_QUIRK_NO_HISPD_BIT | 331f9260355SAndrew Bresticker SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 332f9260355SAndrew Bresticker SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 33385d6509dSShawn Guo .ops = &tegra_sdhci_ops, 33485d6509dSShawn Guo }; 33585d6509dSShawn Guo 336d49d19c2SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra20 = { 3373e44a1a7SStephen Warren .pdata = &sdhci_tegra20_pdata, 3383e44a1a7SStephen Warren .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 | 3393e44a1a7SStephen Warren NVQUIRK_ENABLE_BLOCK_GAP_DET, 3403e44a1a7SStephen Warren }; 3413e44a1a7SStephen Warren 3421db5eebfSLars-Peter Clausen static const struct sdhci_pltfm_data sdhci_tegra30_pdata = { 3433e44a1a7SStephen Warren .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 3443e44a1a7SStephen Warren SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 3453e44a1a7SStephen Warren SDHCI_QUIRK_SINGLE_POWER_WRITE | 3463e44a1a7SStephen Warren SDHCI_QUIRK_NO_HISPD_BIT | 347f9260355SAndrew Bresticker SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 348f9260355SAndrew Bresticker SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 349127407e3SStefan Agner .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 350726df1d5SStefan Agner SDHCI_QUIRK2_BROKEN_HS200 | 351726df1d5SStefan Agner /* 352726df1d5SStefan Agner * Auto-CMD23 leads to "Got command interrupt 0x00010000 even 353726df1d5SStefan Agner * though no command operation was in progress." 354726df1d5SStefan Agner * 355726df1d5SStefan Agner * The exact reason is unknown, as the same hardware seems 356726df1d5SStefan Agner * to support Auto CMD23 on a downstream 3.1 kernel. 357726df1d5SStefan Agner */ 358726df1d5SStefan Agner SDHCI_QUIRK2_ACMD23_BROKEN, 3593e44a1a7SStephen Warren .ops = &tegra_sdhci_ops, 3603e44a1a7SStephen Warren }; 3613e44a1a7SStephen Warren 362d49d19c2SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra30 = { 3633e44a1a7SStephen Warren .pdata = &sdhci_tegra30_pdata, 3643145351aSAndrew Bresticker .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 | 3657ad2ed1dSLucas Stach NVQUIRK_ENABLE_SDR50 | 366e5c63d91SLucas Stach NVQUIRK_ENABLE_SDR104 | 367e5c63d91SLucas Stach NVQUIRK_HAS_PADCALIB, 3683e44a1a7SStephen Warren }; 3693e44a1a7SStephen Warren 37001df7ecdSRhyland Klein static const struct sdhci_ops tegra114_sdhci_ops = { 37101df7ecdSRhyland Klein .get_ro = tegra_sdhci_get_ro, 37201df7ecdSRhyland Klein .read_w = tegra_sdhci_readw, 37301df7ecdSRhyland Klein .write_w = tegra_sdhci_writew, 37401df7ecdSRhyland Klein .write_l = tegra_sdhci_writel, 375a8e326a9SLucas Stach .set_clock = tegra_sdhci_set_clock, 37614b04c6aSMichał Mirosław .set_bus_width = sdhci_set_bus_width, 37701df7ecdSRhyland Klein .reset = tegra_sdhci_reset, 378c3c2384cSLucas Stach .platform_execute_tuning = tegra_sdhci_execute_tuning, 379a8e326a9SLucas Stach .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, 380e5c63d91SLucas Stach .voltage_switch = tegra_sdhci_voltage_switch, 38144350993SAapo Vienamo .get_max_clock = tegra_sdhci_get_max_clock, 38201df7ecdSRhyland Klein }; 38301df7ecdSRhyland Klein 3841db5eebfSLars-Peter Clausen static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { 3855ebf2552SRhyland Klein .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 3865ebf2552SRhyland Klein SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 3875ebf2552SRhyland Klein SDHCI_QUIRK_SINGLE_POWER_WRITE | 3885ebf2552SRhyland Klein SDHCI_QUIRK_NO_HISPD_BIT | 389f9260355SAndrew Bresticker SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 390f9260355SAndrew Bresticker SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 391a8e326a9SLucas Stach .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, 39201df7ecdSRhyland Klein .ops = &tegra114_sdhci_ops, 3935ebf2552SRhyland Klein }; 3945ebf2552SRhyland Klein 395d49d19c2SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra114 = { 3965ebf2552SRhyland Klein .pdata = &sdhci_tegra114_pdata, 3977bf037d6SJon Hunter }; 3987bf037d6SJon Hunter 3994ae12588SThierry Reding static const struct sdhci_pltfm_data sdhci_tegra124_pdata = { 4004ae12588SThierry Reding .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 4014ae12588SThierry Reding SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 4024ae12588SThierry Reding SDHCI_QUIRK_SINGLE_POWER_WRITE | 4034ae12588SThierry Reding SDHCI_QUIRK_NO_HISPD_BIT | 4044ae12588SThierry Reding SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 4054ae12588SThierry Reding SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 4064ae12588SThierry Reding .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 4074ae12588SThierry Reding /* 4084ae12588SThierry Reding * The TRM states that the SD/MMC controller found on 4094ae12588SThierry Reding * Tegra124 can address 34 bits (the maximum supported by 4104ae12588SThierry Reding * the Tegra memory controller), but tests show that DMA 4114ae12588SThierry Reding * to or from above 4 GiB doesn't work. This is possibly 4124ae12588SThierry Reding * caused by missing programming, though it's not obvious 4134ae12588SThierry Reding * what sequence is required. Mark 64-bit DMA broken for 4144ae12588SThierry Reding * now to fix this for existing users (e.g. Nyan boards). 4154ae12588SThierry Reding */ 4164ae12588SThierry Reding SDHCI_QUIRK2_BROKEN_64_BIT_DMA, 4174ae12588SThierry Reding .ops = &tegra114_sdhci_ops, 4184ae12588SThierry Reding }; 4194ae12588SThierry Reding 4204ae12588SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra124 = { 4214ae12588SThierry Reding .pdata = &sdhci_tegra124_pdata, 4224ae12588SThierry Reding }; 4234ae12588SThierry Reding 424b5a84ecfSThierry Reding static const struct sdhci_pltfm_data sdhci_tegra210_pdata = { 425b5a84ecfSThierry Reding .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 426b5a84ecfSThierry Reding SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 427b5a84ecfSThierry Reding SDHCI_QUIRK_SINGLE_POWER_WRITE | 428b5a84ecfSThierry Reding SDHCI_QUIRK_NO_HISPD_BIT | 429a8e326a9SLucas Stach SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 430a8e326a9SLucas Stach SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 431a8e326a9SLucas Stach .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, 432b5a84ecfSThierry Reding .ops = &tegra114_sdhci_ops, 433b5a84ecfSThierry Reding }; 434b5a84ecfSThierry Reding 435b5a84ecfSThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra210 = { 436b5a84ecfSThierry Reding .pdata = &sdhci_tegra210_pdata, 437b5a84ecfSThierry Reding }; 438b5a84ecfSThierry Reding 4394346b7c7SThierry Reding static const struct sdhci_pltfm_data sdhci_tegra186_pdata = { 4404346b7c7SThierry Reding .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 4414346b7c7SThierry Reding SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 4424346b7c7SThierry Reding SDHCI_QUIRK_SINGLE_POWER_WRITE | 4434346b7c7SThierry Reding SDHCI_QUIRK_NO_HISPD_BIT | 4444346b7c7SThierry Reding SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 4454346b7c7SThierry Reding SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 44668481a7eSKrishna Reddy .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 44768481a7eSKrishna Reddy /* SDHCI controllers on Tegra186 support 40-bit addressing. 44868481a7eSKrishna Reddy * IOVA addresses are 48-bit wide on Tegra186. 44968481a7eSKrishna Reddy * With 64-bit dma mask used for SDHCI, accesses can 45068481a7eSKrishna Reddy * be broken. Disable 64-bit dma, which would fall back 45168481a7eSKrishna Reddy * to 32-bit dma mask. Ideally 40-bit dma mask would work, 45268481a7eSKrishna Reddy * But it is not supported as of now. 45368481a7eSKrishna Reddy */ 45468481a7eSKrishna Reddy SDHCI_QUIRK2_BROKEN_64_BIT_DMA, 4554346b7c7SThierry Reding .ops = &tegra114_sdhci_ops, 4564346b7c7SThierry Reding }; 4574346b7c7SThierry Reding 4584346b7c7SThierry Reding static const struct sdhci_tegra_soc_data soc_data_tegra186 = { 4594346b7c7SThierry Reding .pdata = &sdhci_tegra186_pdata, 4604346b7c7SThierry Reding }; 4614346b7c7SThierry Reding 462498d83e7SBill Pemberton static const struct of_device_id sdhci_tegra_dt_match[] = { 4634346b7c7SThierry Reding { .compatible = "nvidia,tegra186-sdhci", .data = &soc_data_tegra186 }, 464b5a84ecfSThierry Reding { .compatible = "nvidia,tegra210-sdhci", .data = &soc_data_tegra210 }, 4654ae12588SThierry Reding { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra124 }, 4665ebf2552SRhyland Klein { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, 4673e44a1a7SStephen Warren { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, 4683e44a1a7SStephen Warren { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, 469275173b2SGrant Likely {} 470275173b2SGrant Likely }; 471e4404fabSArnd Bergmann MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); 472275173b2SGrant Likely 473c3be1efdSBill Pemberton static int sdhci_tegra_probe(struct platform_device *pdev) 47403d2bfc8SOlof Johansson { 4753e44a1a7SStephen Warren const struct of_device_id *match; 4763e44a1a7SStephen Warren const struct sdhci_tegra_soc_data *soc_data; 4773e44a1a7SStephen Warren struct sdhci_host *host; 47885d6509dSShawn Guo struct sdhci_pltfm_host *pltfm_host; 4793e44a1a7SStephen Warren struct sdhci_tegra *tegra_host; 48003d2bfc8SOlof Johansson struct clk *clk; 48103d2bfc8SOlof Johansson int rc; 48203d2bfc8SOlof Johansson 4833e44a1a7SStephen Warren match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); 484b37f9d98SJoseph Lo if (!match) 485b37f9d98SJoseph Lo return -EINVAL; 4863e44a1a7SStephen Warren soc_data = match->data; 4873e44a1a7SStephen Warren 4880734e79cSJisheng Zhang host = sdhci_pltfm_init(pdev, soc_data->pdata, sizeof(*tegra_host)); 48985d6509dSShawn Guo if (IS_ERR(host)) 49085d6509dSShawn Guo return PTR_ERR(host); 49185d6509dSShawn Guo pltfm_host = sdhci_priv(host); 49285d6509dSShawn Guo 4930734e79cSJisheng Zhang tegra_host = sdhci_pltfm_priv(pltfm_host); 494a8e326a9SLucas Stach tegra_host->ddr_signaling = false; 495e5c63d91SLucas Stach tegra_host->pad_calib_required = false; 4963e44a1a7SStephen Warren tegra_host->soc_data = soc_data; 497275173b2SGrant Likely 4982391b340SMylene JOSSERAND rc = mmc_of_parse(host->mmc); 49947caa84fSSimon Baatz if (rc) 50047caa84fSSimon Baatz goto err_parse_dt; 5010e786102SStephen Warren 5027ad2ed1dSLucas Stach if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) 503c3c2384cSLucas Stach host->mmc->caps |= MMC_CAP_1_8V_DDR; 504c3c2384cSLucas Stach 5052391b340SMylene JOSSERAND tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power", 5062391b340SMylene JOSSERAND GPIOD_OUT_HIGH); 5072391b340SMylene JOSSERAND if (IS_ERR(tegra_host->power_gpio)) { 5082391b340SMylene JOSSERAND rc = PTR_ERR(tegra_host->power_gpio); 50985d6509dSShawn Guo goto err_power_req; 51003d2bfc8SOlof Johansson } 51103d2bfc8SOlof Johansson 512e4f79d9cSKevin Hao clk = devm_clk_get(mmc_dev(host->mmc), NULL); 51303d2bfc8SOlof Johansson if (IS_ERR(clk)) { 51403d2bfc8SOlof Johansson dev_err(mmc_dev(host->mmc), "clk err\n"); 51503d2bfc8SOlof Johansson rc = PTR_ERR(clk); 51685d6509dSShawn Guo goto err_clk_get; 51703d2bfc8SOlof Johansson } 5181e674bc6SPrashant Gaikwad clk_prepare_enable(clk); 51903d2bfc8SOlof Johansson pltfm_host->clk = clk; 52003d2bfc8SOlof Johansson 5212cd6c49dSPhilipp Zabel tegra_host->rst = devm_reset_control_get_exclusive(&pdev->dev, 5222cd6c49dSPhilipp Zabel "sdhci"); 52320567be9SThierry Reding if (IS_ERR(tegra_host->rst)) { 52420567be9SThierry Reding rc = PTR_ERR(tegra_host->rst); 52520567be9SThierry Reding dev_err(&pdev->dev, "failed to get reset control: %d\n", rc); 52620567be9SThierry Reding goto err_rst_get; 52720567be9SThierry Reding } 52820567be9SThierry Reding 52920567be9SThierry Reding rc = reset_control_assert(tegra_host->rst); 53020567be9SThierry Reding if (rc) 53120567be9SThierry Reding goto err_rst_get; 53220567be9SThierry Reding 53320567be9SThierry Reding usleep_range(2000, 4000); 53420567be9SThierry Reding 53520567be9SThierry Reding rc = reset_control_deassert(tegra_host->rst); 53620567be9SThierry Reding if (rc) 53720567be9SThierry Reding goto err_rst_get; 53820567be9SThierry Reding 53920567be9SThierry Reding usleep_range(2000, 4000); 54020567be9SThierry Reding 54185d6509dSShawn Guo rc = sdhci_add_host(host); 54285d6509dSShawn Guo if (rc) 54385d6509dSShawn Guo goto err_add_host; 54485d6509dSShawn Guo 54503d2bfc8SOlof Johansson return 0; 54603d2bfc8SOlof Johansson 54785d6509dSShawn Guo err_add_host: 54820567be9SThierry Reding reset_control_assert(tegra_host->rst); 54920567be9SThierry Reding err_rst_get: 5501e674bc6SPrashant Gaikwad clk_disable_unprepare(pltfm_host->clk); 55185d6509dSShawn Guo err_clk_get: 55285d6509dSShawn Guo err_power_req: 55347caa84fSSimon Baatz err_parse_dt: 55485d6509dSShawn Guo sdhci_pltfm_free(pdev); 55503d2bfc8SOlof Johansson return rc; 55603d2bfc8SOlof Johansson } 55703d2bfc8SOlof Johansson 55820567be9SThierry Reding static int sdhci_tegra_remove(struct platform_device *pdev) 55920567be9SThierry Reding { 56020567be9SThierry Reding struct sdhci_host *host = platform_get_drvdata(pdev); 56120567be9SThierry Reding struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 56220567be9SThierry Reding struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); 56320567be9SThierry Reding 56420567be9SThierry Reding sdhci_remove_host(host, 0); 56520567be9SThierry Reding 56620567be9SThierry Reding reset_control_assert(tegra_host->rst); 56720567be9SThierry Reding usleep_range(2000, 4000); 56820567be9SThierry Reding clk_disable_unprepare(pltfm_host->clk); 56920567be9SThierry Reding 57020567be9SThierry Reding sdhci_pltfm_free(pdev); 57120567be9SThierry Reding 57220567be9SThierry Reding return 0; 57320567be9SThierry Reding } 57420567be9SThierry Reding 57585d6509dSShawn Guo static struct platform_driver sdhci_tegra_driver = { 57685d6509dSShawn Guo .driver = { 57785d6509dSShawn Guo .name = "sdhci-tegra", 578275173b2SGrant Likely .of_match_table = sdhci_tegra_dt_match, 579fa243f64SUlf Hansson .pm = &sdhci_pltfm_pmops, 58085d6509dSShawn Guo }, 58185d6509dSShawn Guo .probe = sdhci_tegra_probe, 58220567be9SThierry Reding .remove = sdhci_tegra_remove, 58303d2bfc8SOlof Johansson }; 58403d2bfc8SOlof Johansson 585d1f81a64SAxel Lin module_platform_driver(sdhci_tegra_driver); 58685d6509dSShawn Guo 58785d6509dSShawn Guo MODULE_DESCRIPTION("SDHCI driver for Tegra"); 58885d6509dSShawn Guo MODULE_AUTHOR("Google, Inc."); 58985d6509dSShawn Guo MODULE_LICENSE("GPL v2"); 590