12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21c6a0718SPierre Ossman /* 370f10482SPierre Ossman * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver 41c6a0718SPierre Ossman * 5b69c9058SPierre Ossman * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. 61c6a0718SPierre Ossman * 784c46a53SPierre Ossman * Thanks to the following companies for their support: 884c46a53SPierre Ossman * 984c46a53SPierre Ossman * - JMicron (hardware and technical support) 101c6a0718SPierre Ossman */ 111c6a0718SPierre Ossman 12fa091010SMasahiro Yamada #include <linux/bitfield.h> 131c6a0718SPierre Ossman #include <linux/delay.h> 1418e762e3SChunyan Zhang #include <linux/dmaengine.h> 155a436cc0SAdrian Hunter #include <linux/ktime.h> 161c6a0718SPierre Ossman #include <linux/highmem.h> 17b8c86fc5SPierre Ossman #include <linux/io.h> 1888b47679SPaul Gortmaker #include <linux/module.h> 191c6a0718SPierre Ossman #include <linux/dma-mapping.h> 205a0e3ad6STejun Heo #include <linux/slab.h> 2111763609SRalf Baechle #include <linux/scatterlist.h> 22bd9b9027SLinus Walleij #include <linux/sizes.h> 239bea3c85SMarek Szyprowski #include <linux/regulator/consumer.h> 2466fd8ad5SAdrian Hunter #include <linux/pm_runtime.h> 2592e0c44bSZach Brown #include <linux/of.h> 261c6a0718SPierre Ossman 272f730fecSPierre Ossman #include <linux/leds.h> 282f730fecSPierre Ossman 2922113efdSAries Lee #include <linux/mmc/mmc.h> 301c6a0718SPierre Ossman #include <linux/mmc/host.h> 31473b095aSAaron Lu #include <linux/mmc/card.h> 3285cc1c33SCorneliu Doban #include <linux/mmc/sdio.h> 33bec9d4e5SGuennadi Liakhovetski #include <linux/mmc/slot-gpio.h> 341c6a0718SPierre Ossman 351c6a0718SPierre Ossman #include "sdhci.h" 361c6a0718SPierre Ossman 371c6a0718SPierre Ossman #define DRIVER_NAME "sdhci" 381c6a0718SPierre Ossman 391c6a0718SPierre Ossman #define DBG(f, x...) \ 40f421865dSAdrian Hunter pr_debug("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) 411c6a0718SPierre Ossman 4285ad90e2SAdrian Hunter #define SDHCI_DUMP(f, x...) \ 4385ad90e2SAdrian Hunter pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) 4485ad90e2SAdrian Hunter 45b513ea25SArindam Nath #define MAX_TUNING_LOOP 40 46b513ea25SArindam Nath 471c6a0718SPierre Ossman static unsigned int debug_quirks = 0; 4866fd8ad5SAdrian Hunter static unsigned int debug_quirks2; 491c6a0718SPierre Ossman 5052983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); 511c6a0718SPierre Ossman 52845c939eSAdrian Hunter static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); 53a374a72bSAdrian Hunter 54d2898172SAdrian Hunter void sdhci_dumpregs(struct sdhci_host *host) 551c6a0718SPierre Ossman { 5685ad90e2SAdrian Hunter SDHCI_DUMP("============ SDHCI REGISTER DUMP ===========\n"); 571c6a0718SPierre Ossman 5885ad90e2SAdrian Hunter SDHCI_DUMP("Sys addr: 0x%08x | Version: 0x%08x\n", 594e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_DMA_ADDRESS), 604e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_HOST_VERSION)); 6185ad90e2SAdrian Hunter SDHCI_DUMP("Blk size: 0x%08x | Blk cnt: 0x%08x\n", 624e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_SIZE), 634e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_COUNT)); 6485ad90e2SAdrian Hunter SDHCI_DUMP("Argument: 0x%08x | Trn mode: 0x%08x\n", 654e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_ARGUMENT), 664e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_TRANSFER_MODE)); 6785ad90e2SAdrian Hunter SDHCI_DUMP("Present: 0x%08x | Host ctl: 0x%08x\n", 684e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_PRESENT_STATE), 694e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_HOST_CONTROL)); 7085ad90e2SAdrian Hunter SDHCI_DUMP("Power: 0x%08x | Blk gap: 0x%08x\n", 714e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_POWER_CONTROL), 724e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); 7385ad90e2SAdrian Hunter SDHCI_DUMP("Wake-up: 0x%08x | Clock: 0x%08x\n", 744e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), 754e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_CLOCK_CONTROL)); 7685ad90e2SAdrian Hunter SDHCI_DUMP("Timeout: 0x%08x | Int stat: 0x%08x\n", 774e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), 784e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_STATUS)); 7985ad90e2SAdrian Hunter SDHCI_DUMP("Int enab: 0x%08x | Sig enab: 0x%08x\n", 804e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_ENABLE), 814e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); 82869f8a69SAdrian Hunter SDHCI_DUMP("ACmd stat: 0x%08x | Slot int: 0x%08x\n", 83869f8a69SAdrian Hunter sdhci_readw(host, SDHCI_AUTO_CMD_STATUS), 844e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); 8585ad90e2SAdrian Hunter SDHCI_DUMP("Caps: 0x%08x | Caps_1: 0x%08x\n", 864e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_CAPABILITIES), 87e8120ad1SPhilip Rakity sdhci_readl(host, SDHCI_CAPABILITIES_1)); 8885ad90e2SAdrian Hunter SDHCI_DUMP("Cmd: 0x%08x | Max curr: 0x%08x\n", 89e8120ad1SPhilip Rakity sdhci_readw(host, SDHCI_COMMAND), 904e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_MAX_CURRENT)); 9185ad90e2SAdrian Hunter SDHCI_DUMP("Resp[0]: 0x%08x | Resp[1]: 0x%08x\n", 927962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE), 937962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 4)); 9485ad90e2SAdrian Hunter SDHCI_DUMP("Resp[2]: 0x%08x | Resp[3]: 0x%08x\n", 957962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 8), 967962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 12)); 9785ad90e2SAdrian Hunter SDHCI_DUMP("Host ctl2: 0x%08x\n", 98f2119df6SArindam Nath sdhci_readw(host, SDHCI_HOST_CONTROL2)); 991c6a0718SPierre Ossman 100e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_ADMA) { 10185ad90e2SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) { 10285ad90e2SAdrian Hunter SDHCI_DUMP("ADMA Err: 0x%08x | ADMA Ptr: 0x%08x%08x\n", 103c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ERROR), 104c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS_HI), 105c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS)); 10685ad90e2SAdrian Hunter } else { 10785ad90e2SAdrian Hunter SDHCI_DUMP("ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", 108c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ERROR), 109c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS)); 110e57a5f61SAdrian Hunter } 11185ad90e2SAdrian Hunter } 112be3f4ae0SBen Dooks 113d1fe0762SSarthak Garg if (host->ops->dump_vendor_regs) 114d1fe0762SSarthak Garg host->ops->dump_vendor_regs(host); 115d1fe0762SSarthak Garg 11685ad90e2SAdrian Hunter SDHCI_DUMP("============================================\n"); 1171c6a0718SPierre Ossman } 118d2898172SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_dumpregs); 1191c6a0718SPierre Ossman 1201c6a0718SPierre Ossman /*****************************************************************************\ 1211c6a0718SPierre Ossman * * 1221c6a0718SPierre Ossman * Low level functions * 1231c6a0718SPierre Ossman * * 1241c6a0718SPierre Ossman \*****************************************************************************/ 1251c6a0718SPierre Ossman 126b3f80b43SChunyan Zhang static void sdhci_do_enable_v4_mode(struct sdhci_host *host) 127b3f80b43SChunyan Zhang { 128b3f80b43SChunyan Zhang u16 ctrl2; 129b3f80b43SChunyan Zhang 13097207c12SSowjanya Komatineni ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 131b3f80b43SChunyan Zhang if (ctrl2 & SDHCI_CTRL_V4_MODE) 132b3f80b43SChunyan Zhang return; 133b3f80b43SChunyan Zhang 134b3f80b43SChunyan Zhang ctrl2 |= SDHCI_CTRL_V4_MODE; 13597207c12SSowjanya Komatineni sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 136b3f80b43SChunyan Zhang } 137b3f80b43SChunyan Zhang 138b3f80b43SChunyan Zhang /* 139b3f80b43SChunyan Zhang * This can be called before sdhci_add_host() by Vendor's host controller 140b3f80b43SChunyan Zhang * driver to enable v4 mode if supported. 141b3f80b43SChunyan Zhang */ 142b3f80b43SChunyan Zhang void sdhci_enable_v4_mode(struct sdhci_host *host) 143b3f80b43SChunyan Zhang { 144b3f80b43SChunyan Zhang host->v4_mode = true; 145b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host); 146b3f80b43SChunyan Zhang } 147b3f80b43SChunyan Zhang EXPORT_SYMBOL_GPL(sdhci_enable_v4_mode); 148b3f80b43SChunyan Zhang 14956a590dcSAdrian Hunter static inline bool sdhci_data_line_cmd(struct mmc_command *cmd) 15056a590dcSAdrian Hunter { 15156a590dcSAdrian Hunter return cmd->data || cmd->flags & MMC_RSP_BUSY; 15256a590dcSAdrian Hunter } 15356a590dcSAdrian Hunter 1547260cf5eSAnton Vorontsov static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) 1557260cf5eSAnton Vorontsov { 1565b4f1f6cSRussell King u32 present; 1577260cf5eSAnton Vorontsov 158c79396c1SAdrian Hunter if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || 159e65bb388SHaibo Chen !mmc_card_is_removable(host->mmc) || mmc_can_gpio_cd(host->mmc)) 16066fd8ad5SAdrian Hunter return; 16166fd8ad5SAdrian Hunter 1625b4f1f6cSRussell King if (enable) { 163d25928d1SShawn Guo present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 164d25928d1SShawn Guo SDHCI_CARD_PRESENT; 165d25928d1SShawn Guo 1665b4f1f6cSRussell King host->ier |= present ? SDHCI_INT_CARD_REMOVE : 1675b4f1f6cSRussell King SDHCI_INT_CARD_INSERT; 1685b4f1f6cSRussell King } else { 1695b4f1f6cSRussell King host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); 1705b4f1f6cSRussell King } 171b537f94cSRussell King 172b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 173b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 1747260cf5eSAnton Vorontsov } 1757260cf5eSAnton Vorontsov 1767260cf5eSAnton Vorontsov static void sdhci_enable_card_detection(struct sdhci_host *host) 1777260cf5eSAnton Vorontsov { 1787260cf5eSAnton Vorontsov sdhci_set_card_detection(host, true); 1797260cf5eSAnton Vorontsov } 1807260cf5eSAnton Vorontsov 1817260cf5eSAnton Vorontsov static void sdhci_disable_card_detection(struct sdhci_host *host) 1827260cf5eSAnton Vorontsov { 1837260cf5eSAnton Vorontsov sdhci_set_card_detection(host, false); 1847260cf5eSAnton Vorontsov } 1857260cf5eSAnton Vorontsov 18602d0b685SUlf Hansson static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) 18702d0b685SUlf Hansson { 18802d0b685SUlf Hansson if (host->bus_on) 18902d0b685SUlf Hansson return; 19002d0b685SUlf Hansson host->bus_on = true; 191bac53336SJisheng Zhang pm_runtime_get_noresume(mmc_dev(host->mmc)); 19202d0b685SUlf Hansson } 19302d0b685SUlf Hansson 19402d0b685SUlf Hansson static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) 19502d0b685SUlf Hansson { 19602d0b685SUlf Hansson if (!host->bus_on) 19702d0b685SUlf Hansson return; 19802d0b685SUlf Hansson host->bus_on = false; 199bac53336SJisheng Zhang pm_runtime_put_noidle(mmc_dev(host->mmc)); 20002d0b685SUlf Hansson } 20102d0b685SUlf Hansson 20203231f9bSRussell King void sdhci_reset(struct sdhci_host *host, u8 mask) 2031c6a0718SPierre Ossman { 2045a436cc0SAdrian Hunter ktime_t timeout; 205393c1a34SPhilip Rakity 2064e4141a5SAnton Vorontsov sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); 2071c6a0718SPierre Ossman 208f0710a55SAdrian Hunter if (mask & SDHCI_RESET_ALL) { 2091c6a0718SPierre Ossman host->clock = 0; 210f0710a55SAdrian Hunter /* Reset-all turns off SD Bus Power */ 211f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 212f0710a55SAdrian Hunter sdhci_runtime_pm_bus_off(host); 213f0710a55SAdrian Hunter } 2141c6a0718SPierre Ossman 2151c6a0718SPierre Ossman /* Wait max 100 ms */ 2165a436cc0SAdrian Hunter timeout = ktime_add_ms(ktime_get(), 100); 2171c6a0718SPierre Ossman 2181c6a0718SPierre Ossman /* hw clears the bit when it's done */ 219b704441eSAlek Du while (1) { 220b704441eSAlek Du bool timedout = ktime_after(ktime_get(), timeout); 221b704441eSAlek Du 222b704441eSAlek Du if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask)) 223b704441eSAlek Du break; 224b704441eSAlek Du if (timedout) { 225a3c76eb9SGirish K S pr_err("%s: Reset 0x%x never completed.\n", 2261c6a0718SPierre Ossman mmc_hostname(host->mmc), (int)mask); 227efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT); 2281c6a0718SPierre Ossman sdhci_dumpregs(host); 2291c6a0718SPierre Ossman return; 2301c6a0718SPierre Ossman } 2315a436cc0SAdrian Hunter udelay(10); 2321c6a0718SPierre Ossman } 23303231f9bSRussell King } 23403231f9bSRussell King EXPORT_SYMBOL_GPL(sdhci_reset); 235063a9dbbSAnton Vorontsov 236aa990722SAdrian Hunter static bool sdhci_do_reset(struct sdhci_host *host, u8 mask) 23703231f9bSRussell King { 23803231f9bSRussell King if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 239d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 240d3940f27SAdrian Hunter 241d3940f27SAdrian Hunter if (!mmc->ops->get_cd(mmc)) 242aa990722SAdrian Hunter return false; 24303231f9bSRussell King } 24403231f9bSRussell King 24503231f9bSRussell King host->ops->reset(host, mask); 246393c1a34SPhilip Rakity 247aa990722SAdrian Hunter return true; 248aa990722SAdrian Hunter } 249aa990722SAdrian Hunter 250aa990722SAdrian Hunter static void sdhci_reset_for_all(struct sdhci_host *host) 251aa990722SAdrian Hunter { 252aa990722SAdrian Hunter if (sdhci_do_reset(host, SDHCI_RESET_ALL)) { 2533abc1e80SShaohui Xie if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 254da91a8f9SRussell King if (host->ops->enable_dma) 2553abc1e80SShaohui Xie host->ops->enable_dma(host); 2563abc1e80SShaohui Xie } 257da91a8f9SRussell King /* Resetting the controller clears many */ 258da91a8f9SRussell King host->preset_enabled = false; 259da91a8f9SRussell King } 2601c6a0718SPierre Ossman } 2611c6a0718SPierre Ossman 2621e63d297SAdrian Hunter enum sdhci_reset_reason { 2631e63d297SAdrian Hunter SDHCI_RESET_FOR_INIT, 2641e63d297SAdrian Hunter SDHCI_RESET_FOR_REQUEST_ERROR, 2651e63d297SAdrian Hunter SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY, 2661e63d297SAdrian Hunter SDHCI_RESET_FOR_TUNING_ABORT, 2671e63d297SAdrian Hunter SDHCI_RESET_FOR_CARD_REMOVED, 2681e63d297SAdrian Hunter SDHCI_RESET_FOR_CQE_RECOVERY, 2691e63d297SAdrian Hunter }; 2701e63d297SAdrian Hunter 2711e63d297SAdrian Hunter static void sdhci_reset_for_reason(struct sdhci_host *host, enum sdhci_reset_reason reason) 2721e63d297SAdrian Hunter { 2731e63d297SAdrian Hunter switch (reason) { 2741e63d297SAdrian Hunter case SDHCI_RESET_FOR_INIT: 2751e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 2761e63d297SAdrian Hunter break; 2771e63d297SAdrian Hunter case SDHCI_RESET_FOR_REQUEST_ERROR: 2781e63d297SAdrian Hunter case SDHCI_RESET_FOR_TUNING_ABORT: 2791e63d297SAdrian Hunter case SDHCI_RESET_FOR_CARD_REMOVED: 2801e63d297SAdrian Hunter case SDHCI_RESET_FOR_CQE_RECOVERY: 2811e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD); 2821e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 2831e63d297SAdrian Hunter break; 2841e63d297SAdrian Hunter case SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY: 2851e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 2861e63d297SAdrian Hunter break; 2871e63d297SAdrian Hunter } 2881e63d297SAdrian Hunter } 2891e63d297SAdrian Hunter 2901e63d297SAdrian Hunter #define sdhci_reset_for(h, r) sdhci_reset_for_reason((h), SDHCI_RESET_FOR_##r) 2911e63d297SAdrian Hunter 292f5c1ab82SAdrian Hunter static void sdhci_set_default_irqs(struct sdhci_host *host) 2931c6a0718SPierre Ossman { 294b537f94cSRussell King host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 295b537f94cSRussell King SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | 296b537f94cSRussell King SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | 297b537f94cSRussell King SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | 298b537f94cSRussell King SDHCI_INT_RESPONSE; 299b537f94cSRussell King 300f37b20ebSDong Aisheng if (host->tuning_mode == SDHCI_TUNING_MODE_2 || 301f37b20ebSDong Aisheng host->tuning_mode == SDHCI_TUNING_MODE_3) 302f37b20ebSDong Aisheng host->ier |= SDHCI_INT_RETUNE; 303f37b20ebSDong Aisheng 304b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 305b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 306f5c1ab82SAdrian Hunter } 307f5c1ab82SAdrian Hunter 308685e444bSChunyan Zhang static void sdhci_config_dma(struct sdhci_host *host) 309685e444bSChunyan Zhang { 310685e444bSChunyan Zhang u8 ctrl; 311685e444bSChunyan Zhang u16 ctrl2; 312685e444bSChunyan Zhang 313685e444bSChunyan Zhang if (host->version < SDHCI_SPEC_200) 314685e444bSChunyan Zhang return; 315685e444bSChunyan Zhang 316685e444bSChunyan Zhang ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 317685e444bSChunyan Zhang 318685e444bSChunyan Zhang /* 319685e444bSChunyan Zhang * Always adjust the DMA selection as some controllers 320685e444bSChunyan Zhang * (e.g. JMicron) can't do PIO properly when the selection 321685e444bSChunyan Zhang * is ADMA. 322685e444bSChunyan Zhang */ 323685e444bSChunyan Zhang ctrl &= ~SDHCI_CTRL_DMA_MASK; 324685e444bSChunyan Zhang if (!(host->flags & SDHCI_REQ_USE_DMA)) 325685e444bSChunyan Zhang goto out; 326685e444bSChunyan Zhang 327685e444bSChunyan Zhang /* Note if DMA Select is zero then SDMA is selected */ 328685e444bSChunyan Zhang if (host->flags & SDHCI_USE_ADMA) 329685e444bSChunyan Zhang ctrl |= SDHCI_CTRL_ADMA32; 330685e444bSChunyan Zhang 331685e444bSChunyan Zhang if (host->flags & SDHCI_USE_64_BIT_DMA) { 332685e444bSChunyan Zhang /* 333685e444bSChunyan Zhang * If v4 mode, all supported DMA can be 64-bit addressing if 334685e444bSChunyan Zhang * controller supports 64-bit system address, otherwise only 335685e444bSChunyan Zhang * ADMA can support 64-bit addressing. 336685e444bSChunyan Zhang */ 337685e444bSChunyan Zhang if (host->v4_mode) { 338685e444bSChunyan Zhang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 339685e444bSChunyan Zhang ctrl2 |= SDHCI_CTRL_64BIT_ADDR; 340685e444bSChunyan Zhang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 341685e444bSChunyan Zhang } else if (host->flags & SDHCI_USE_ADMA) { 342685e444bSChunyan Zhang /* 343685e444bSChunyan Zhang * Don't need to undo SDHCI_CTRL_ADMA32 in order to 344685e444bSChunyan Zhang * set SDHCI_CTRL_ADMA64. 345685e444bSChunyan Zhang */ 346685e444bSChunyan Zhang ctrl |= SDHCI_CTRL_ADMA64; 347685e444bSChunyan Zhang } 348685e444bSChunyan Zhang } 349685e444bSChunyan Zhang 350685e444bSChunyan Zhang out: 351685e444bSChunyan Zhang sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 352685e444bSChunyan Zhang } 353685e444bSChunyan Zhang 354f5c1ab82SAdrian Hunter static void sdhci_init(struct sdhci_host *host, int soft) 355f5c1ab82SAdrian Hunter { 356f5c1ab82SAdrian Hunter struct mmc_host *mmc = host->mmc; 35749769d4dSHaibo Chen unsigned long flags; 358f5c1ab82SAdrian Hunter 359f5c1ab82SAdrian Hunter if (soft) 3601e63d297SAdrian Hunter sdhci_reset_for(host, INIT); 361f5c1ab82SAdrian Hunter else 362aa990722SAdrian Hunter sdhci_reset_for_all(host); 363f5c1ab82SAdrian Hunter 364b3f80b43SChunyan Zhang if (host->v4_mode) 365b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host); 366b3f80b43SChunyan Zhang 36749769d4dSHaibo Chen spin_lock_irqsave(&host->lock, flags); 368f5c1ab82SAdrian Hunter sdhci_set_default_irqs(host); 36949769d4dSHaibo Chen spin_unlock_irqrestore(&host->lock, flags); 3702f4cbb3dSNicolas Pitre 371f12e39dbSAdrian Hunter host->cqe_on = false; 372f12e39dbSAdrian Hunter 3732f4cbb3dSNicolas Pitre if (soft) { 3742f4cbb3dSNicolas Pitre /* force clock reconfiguration */ 3752f4cbb3dSNicolas Pitre host->clock = 0; 376c981cdfbSAdrian Hunter host->reinit_uhs = true; 377d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 3782f4cbb3dSNicolas Pitre } 3797260cf5eSAnton Vorontsov } 3801c6a0718SPierre Ossman 3817260cf5eSAnton Vorontsov static void sdhci_reinit(struct sdhci_host *host) 3827260cf5eSAnton Vorontsov { 383dcaac3f7SRaul E Rangel u32 cd = host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); 384dcaac3f7SRaul E Rangel 3852f4cbb3dSNicolas Pitre sdhci_init(host, 0); 3867260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 387dcaac3f7SRaul E Rangel 388dcaac3f7SRaul E Rangel /* 389dcaac3f7SRaul E Rangel * A change to the card detect bits indicates a change in present state, 390dcaac3f7SRaul E Rangel * refer sdhci_set_card_detection(). A card detect interrupt might have 391dcaac3f7SRaul E Rangel * been missed while the host controller was being reset, so trigger a 392dcaac3f7SRaul E Rangel * rescan to check. 393dcaac3f7SRaul E Rangel */ 394dcaac3f7SRaul E Rangel if (cd != (host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT))) 395dcaac3f7SRaul E Rangel mmc_detect_change(host->mmc, msecs_to_jiffies(200)); 3961c6a0718SPierre Ossman } 3971c6a0718SPierre Ossman 398061d17a6SAdrian Hunter static void __sdhci_led_activate(struct sdhci_host *host) 3991c6a0718SPierre Ossman { 4001c6a0718SPierre Ossman u8 ctrl; 4011c6a0718SPierre Ossman 402bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 403bd29f58bSAdrian Hunter return; 404bd29f58bSAdrian Hunter 4054e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 4061c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_LED; 4074e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 4081c6a0718SPierre Ossman } 4091c6a0718SPierre Ossman 410061d17a6SAdrian Hunter static void __sdhci_led_deactivate(struct sdhci_host *host) 4111c6a0718SPierre Ossman { 4121c6a0718SPierre Ossman u8 ctrl; 4131c6a0718SPierre Ossman 414bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 415bd29f58bSAdrian Hunter return; 416bd29f58bSAdrian Hunter 4174e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 4181c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_LED; 4194e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 4201c6a0718SPierre Ossman } 4211c6a0718SPierre Ossman 4224f78230fSMasahiro Yamada #if IS_REACHABLE(CONFIG_LEDS_CLASS) 4232f730fecSPierre Ossman static void sdhci_led_control(struct led_classdev *led, 4242f730fecSPierre Ossman enum led_brightness brightness) 4252f730fecSPierre Ossman { 4262f730fecSPierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 4272f730fecSPierre Ossman unsigned long flags; 4282f730fecSPierre Ossman 4292f730fecSPierre Ossman spin_lock_irqsave(&host->lock, flags); 4302f730fecSPierre Ossman 43166fd8ad5SAdrian Hunter if (host->runtime_suspended) 43266fd8ad5SAdrian Hunter goto out; 43366fd8ad5SAdrian Hunter 4342f730fecSPierre Ossman if (brightness == LED_OFF) 435061d17a6SAdrian Hunter __sdhci_led_deactivate(host); 4362f730fecSPierre Ossman else 437061d17a6SAdrian Hunter __sdhci_led_activate(host); 43866fd8ad5SAdrian Hunter out: 4392f730fecSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 4402f730fecSPierre Ossman } 441061d17a6SAdrian Hunter 442061d17a6SAdrian Hunter static int sdhci_led_register(struct sdhci_host *host) 443061d17a6SAdrian Hunter { 444061d17a6SAdrian Hunter struct mmc_host *mmc = host->mmc; 445061d17a6SAdrian Hunter 446bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 447bd29f58bSAdrian Hunter return 0; 448bd29f58bSAdrian Hunter 449061d17a6SAdrian Hunter snprintf(host->led_name, sizeof(host->led_name), 450061d17a6SAdrian Hunter "%s::", mmc_hostname(mmc)); 451061d17a6SAdrian Hunter 452061d17a6SAdrian Hunter host->led.name = host->led_name; 453061d17a6SAdrian Hunter host->led.brightness = LED_OFF; 454061d17a6SAdrian Hunter host->led.default_trigger = mmc_hostname(mmc); 455061d17a6SAdrian Hunter host->led.brightness_set = sdhci_led_control; 456061d17a6SAdrian Hunter 457061d17a6SAdrian Hunter return led_classdev_register(mmc_dev(mmc), &host->led); 458061d17a6SAdrian Hunter } 459061d17a6SAdrian Hunter 460061d17a6SAdrian Hunter static void sdhci_led_unregister(struct sdhci_host *host) 461061d17a6SAdrian Hunter { 462bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 463bd29f58bSAdrian Hunter return; 464bd29f58bSAdrian Hunter 465061d17a6SAdrian Hunter led_classdev_unregister(&host->led); 466061d17a6SAdrian Hunter } 467061d17a6SAdrian Hunter 468061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host) 469061d17a6SAdrian Hunter { 470061d17a6SAdrian Hunter } 471061d17a6SAdrian Hunter 472061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host) 473061d17a6SAdrian Hunter { 474061d17a6SAdrian Hunter } 475061d17a6SAdrian Hunter 476061d17a6SAdrian Hunter #else 477061d17a6SAdrian Hunter 478061d17a6SAdrian Hunter static inline int sdhci_led_register(struct sdhci_host *host) 479061d17a6SAdrian Hunter { 480061d17a6SAdrian Hunter return 0; 481061d17a6SAdrian Hunter } 482061d17a6SAdrian Hunter 483061d17a6SAdrian Hunter static inline void sdhci_led_unregister(struct sdhci_host *host) 484061d17a6SAdrian Hunter { 485061d17a6SAdrian Hunter } 486061d17a6SAdrian Hunter 487061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host) 488061d17a6SAdrian Hunter { 489061d17a6SAdrian Hunter __sdhci_led_activate(host); 490061d17a6SAdrian Hunter } 491061d17a6SAdrian Hunter 492061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host) 493061d17a6SAdrian Hunter { 494061d17a6SAdrian Hunter __sdhci_led_deactivate(host); 495061d17a6SAdrian Hunter } 496061d17a6SAdrian Hunter 4972f730fecSPierre Ossman #endif 4982f730fecSPierre Ossman 49997a1abaeSAdrian Hunter static void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, 50097a1abaeSAdrian Hunter unsigned long timeout) 50197a1abaeSAdrian Hunter { 50297a1abaeSAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd)) 50397a1abaeSAdrian Hunter mod_timer(&host->data_timer, timeout); 50497a1abaeSAdrian Hunter else 50597a1abaeSAdrian Hunter mod_timer(&host->timer, timeout); 50697a1abaeSAdrian Hunter } 50797a1abaeSAdrian Hunter 50897a1abaeSAdrian Hunter static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq) 50997a1abaeSAdrian Hunter { 51097a1abaeSAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd)) 51197a1abaeSAdrian Hunter del_timer(&host->data_timer); 51297a1abaeSAdrian Hunter else 51397a1abaeSAdrian Hunter del_timer(&host->timer); 51497a1abaeSAdrian Hunter } 51597a1abaeSAdrian Hunter 51697a1abaeSAdrian Hunter static inline bool sdhci_has_requests(struct sdhci_host *host) 51797a1abaeSAdrian Hunter { 51897a1abaeSAdrian Hunter return host->cmd || host->data_cmd; 51997a1abaeSAdrian Hunter } 52097a1abaeSAdrian Hunter 5211c6a0718SPierre Ossman /*****************************************************************************\ 5221c6a0718SPierre Ossman * * 5231c6a0718SPierre Ossman * Core functions * 5241c6a0718SPierre Ossman * * 5251c6a0718SPierre Ossman \*****************************************************************************/ 5261c6a0718SPierre Ossman 5271c6a0718SPierre Ossman static void sdhci_read_block_pio(struct sdhci_host *host) 5281c6a0718SPierre Ossman { 5297659150cSPierre Ossman unsigned long flags; 5307659150cSPierre Ossman size_t blksize, len, chunk; 5313f649ab7SKees Cook u32 scratch; 5327659150cSPierre Ossman u8 *buf; 5331c6a0718SPierre Ossman 5341c6a0718SPierre Ossman DBG("PIO reading\n"); 5351c6a0718SPierre Ossman 5361c6a0718SPierre Ossman blksize = host->data->blksz; 5377659150cSPierre Ossman chunk = 0; 5381c6a0718SPierre Ossman 5397659150cSPierre Ossman local_irq_save(flags); 5401c6a0718SPierre Ossman 5411c6a0718SPierre Ossman while (blksize) { 542bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter)); 5437659150cSPierre Ossman 5447659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 5457659150cSPierre Ossman 5467659150cSPierre Ossman blksize -= len; 5477659150cSPierre Ossman host->sg_miter.consumed = len; 5487659150cSPierre Ossman 5497659150cSPierre Ossman buf = host->sg_miter.addr; 5507659150cSPierre Ossman 5517659150cSPierre Ossman while (len) { 5527659150cSPierre Ossman if (chunk == 0) { 5534e4141a5SAnton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER); 5547659150cSPierre Ossman chunk = 4; 5551c6a0718SPierre Ossman } 5561c6a0718SPierre Ossman 5577659150cSPierre Ossman *buf = scratch & 0xFF; 5581c6a0718SPierre Ossman 5597659150cSPierre Ossman buf++; 5607659150cSPierre Ossman scratch >>= 8; 5617659150cSPierre Ossman chunk--; 5627659150cSPierre Ossman len--; 5637659150cSPierre Ossman } 5641c6a0718SPierre Ossman } 5651c6a0718SPierre Ossman 5667659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 5677659150cSPierre Ossman 5687659150cSPierre Ossman local_irq_restore(flags); 5691c6a0718SPierre Ossman } 5701c6a0718SPierre Ossman 5711c6a0718SPierre Ossman static void sdhci_write_block_pio(struct sdhci_host *host) 5721c6a0718SPierre Ossman { 5737659150cSPierre Ossman unsigned long flags; 5747659150cSPierre Ossman size_t blksize, len, chunk; 5757659150cSPierre Ossman u32 scratch; 5767659150cSPierre Ossman u8 *buf; 5771c6a0718SPierre Ossman 5781c6a0718SPierre Ossman DBG("PIO writing\n"); 5791c6a0718SPierre Ossman 5801c6a0718SPierre Ossman blksize = host->data->blksz; 5817659150cSPierre Ossman chunk = 0; 5827659150cSPierre Ossman scratch = 0; 5831c6a0718SPierre Ossman 5847659150cSPierre Ossman local_irq_save(flags); 5851c6a0718SPierre Ossman 5861c6a0718SPierre Ossman while (blksize) { 587bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter)); 5881c6a0718SPierre Ossman 5897659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 5901c6a0718SPierre Ossman 5917659150cSPierre Ossman blksize -= len; 5927659150cSPierre Ossman host->sg_miter.consumed = len; 5937659150cSPierre Ossman 5947659150cSPierre Ossman buf = host->sg_miter.addr; 5957659150cSPierre Ossman 5967659150cSPierre Ossman while (len) { 5977659150cSPierre Ossman scratch |= (u32)*buf << (chunk * 8); 5987659150cSPierre Ossman 5997659150cSPierre Ossman buf++; 6007659150cSPierre Ossman chunk++; 6017659150cSPierre Ossman len--; 6027659150cSPierre Ossman 6037659150cSPierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 6044e4141a5SAnton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER); 6057659150cSPierre Ossman chunk = 0; 6067659150cSPierre Ossman scratch = 0; 6077659150cSPierre Ossman } 6087659150cSPierre Ossman } 6091c6a0718SPierre Ossman } 6101c6a0718SPierre Ossman 6117659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 6121c6a0718SPierre Ossman 6137659150cSPierre Ossman local_irq_restore(flags); 6141c6a0718SPierre Ossman } 6151c6a0718SPierre Ossman 6161c6a0718SPierre Ossman static void sdhci_transfer_pio(struct sdhci_host *host) 6171c6a0718SPierre Ossman { 6181c6a0718SPierre Ossman u32 mask; 6191c6a0718SPierre Ossman 6207659150cSPierre Ossman if (host->blocks == 0) 6211c6a0718SPierre Ossman return; 6221c6a0718SPierre Ossman 6231c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 6241c6a0718SPierre Ossman mask = SDHCI_DATA_AVAILABLE; 6251c6a0718SPierre Ossman else 6261c6a0718SPierre Ossman mask = SDHCI_SPACE_AVAILABLE; 6271c6a0718SPierre Ossman 6284a3cba32SPierre Ossman /* 6294a3cba32SPierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 6304a3cba32SPierre Ossman * for transfers < 4 bytes. As long as it is just one block, 6314a3cba32SPierre Ossman * we can ignore the bits. 6324a3cba32SPierre Ossman */ 6334a3cba32SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 6344a3cba32SPierre Ossman (host->data->blocks == 1)) 6354a3cba32SPierre Ossman mask = ~0; 6364a3cba32SPierre Ossman 6374e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 6383e3bf207SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 6393e3bf207SAnton Vorontsov udelay(100); 6403e3bf207SAnton Vorontsov 6411c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 6421c6a0718SPierre Ossman sdhci_read_block_pio(host); 6431c6a0718SPierre Ossman else 6441c6a0718SPierre Ossman sdhci_write_block_pio(host); 6451c6a0718SPierre Ossman 6467659150cSPierre Ossman host->blocks--; 6477659150cSPierre Ossman if (host->blocks == 0) 6481c6a0718SPierre Ossman break; 6491c6a0718SPierre Ossman } 6501c6a0718SPierre Ossman 6511c6a0718SPierre Ossman DBG("PIO transfer complete.\n"); 6521c6a0718SPierre Ossman } 6531c6a0718SPierre Ossman 65448857d9bSRussell King static int sdhci_pre_dma_transfer(struct sdhci_host *host, 655c0999b72SRussell King struct mmc_data *data, int cookie) 65648857d9bSRussell King { 65748857d9bSRussell King int sg_count; 65848857d9bSRussell King 65994538e51SRussell King /* 66094538e51SRussell King * If the data buffers are already mapped, return the previous 66194538e51SRussell King * dma_map_sg() result. 66294538e51SRussell King */ 66394538e51SRussell King if (data->host_cookie == COOKIE_PRE_MAPPED) 66448857d9bSRussell King return data->sg_count; 66548857d9bSRussell King 666bd9b9027SLinus Walleij /* Bounce write requests to the bounce buffer */ 667bd9b9027SLinus Walleij if (host->bounce_buffer) { 668bd9b9027SLinus Walleij unsigned int length = data->blksz * data->blocks; 669bd9b9027SLinus Walleij 670bd9b9027SLinus Walleij if (length > host->bounce_buffer_size) { 671bd9b9027SLinus Walleij pr_err("%s: asked for transfer of %u bytes exceeds bounce buffer %u bytes\n", 672bd9b9027SLinus Walleij mmc_hostname(host->mmc), length, 673bd9b9027SLinus Walleij host->bounce_buffer_size); 674bd9b9027SLinus Walleij return -EIO; 675bd9b9027SLinus Walleij } 676bd9b9027SLinus Walleij if (mmc_get_dma_dir(data) == DMA_TO_DEVICE) { 677bd9b9027SLinus Walleij /* Copy the data to the bounce buffer */ 678e93577ecSAngelo Dureghello if (host->ops->copy_to_bounce_buffer) { 679e93577ecSAngelo Dureghello host->ops->copy_to_bounce_buffer(host, 680e93577ecSAngelo Dureghello data, length); 681e93577ecSAngelo Dureghello } else { 682bd9b9027SLinus Walleij sg_copy_to_buffer(data->sg, data->sg_len, 683e93577ecSAngelo Dureghello host->bounce_buffer, length); 684e93577ecSAngelo Dureghello } 685bd9b9027SLinus Walleij } 686bd9b9027SLinus Walleij /* Switch ownership to the DMA */ 687bac53336SJisheng Zhang dma_sync_single_for_device(mmc_dev(host->mmc), 688bd9b9027SLinus Walleij host->bounce_addr, 689bd9b9027SLinus Walleij host->bounce_buffer_size, 690feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 691bd9b9027SLinus Walleij /* Just a dummy value */ 692bd9b9027SLinus Walleij sg_count = 1; 693bd9b9027SLinus Walleij } else { 694bd9b9027SLinus Walleij /* Just access the data directly from memory */ 695bd9b9027SLinus Walleij sg_count = dma_map_sg(mmc_dev(host->mmc), 696bd9b9027SLinus Walleij data->sg, data->sg_len, 697bd9b9027SLinus Walleij mmc_get_dma_dir(data)); 698bd9b9027SLinus Walleij } 69948857d9bSRussell King 70048857d9bSRussell King if (sg_count == 0) 70148857d9bSRussell King return -ENOSPC; 70248857d9bSRussell King 70348857d9bSRussell King data->sg_count = sg_count; 704c0999b72SRussell King data->host_cookie = cookie; 70548857d9bSRussell King 70648857d9bSRussell King return sg_count; 70748857d9bSRussell King } 70848857d9bSRussell King 709*4438592cSAdrian Hunter static char *sdhci_kmap_atomic(struct scatterlist *sg) 7102134a922SPierre Ossman { 711482fce99SCong Wang return kmap_atomic(sg_page(sg)) + sg->offset; 7122134a922SPierre Ossman } 7132134a922SPierre Ossman 714*4438592cSAdrian Hunter static void sdhci_kunmap_atomic(void *buffer) 7152134a922SPierre Ossman { 716482fce99SCong Wang kunmap_atomic(buffer); 7172134a922SPierre Ossman } 7182134a922SPierre Ossman 71954552e49SJisheng Zhang void sdhci_adma_write_desc(struct sdhci_host *host, void **desc, 72054552e49SJisheng Zhang dma_addr_t addr, int len, unsigned int cmd) 721118cd17dSBen Dooks { 72254552e49SJisheng Zhang struct sdhci_adma2_64_desc *dma_desc = *desc; 723118cd17dSBen Dooks 724e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have these members in same position */ 7250545230fSAdrian Hunter dma_desc->cmd = cpu_to_le16(cmd); 7260545230fSAdrian Hunter dma_desc->len = cpu_to_le16(len); 72738eee2e8SMasahiro Yamada dma_desc->addr_lo = cpu_to_le32(lower_32_bits(addr)); 728e57a5f61SAdrian Hunter 729e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 73038eee2e8SMasahiro Yamada dma_desc->addr_hi = cpu_to_le32(upper_32_bits(addr)); 73154552e49SJisheng Zhang 73254552e49SJisheng Zhang *desc += host->desc_sz; 73354552e49SJisheng Zhang } 73454552e49SJisheng Zhang EXPORT_SYMBOL_GPL(sdhci_adma_write_desc); 73554552e49SJisheng Zhang 73654552e49SJisheng Zhang static inline void __sdhci_adma_write_desc(struct sdhci_host *host, 73754552e49SJisheng Zhang void **desc, dma_addr_t addr, 73854552e49SJisheng Zhang int len, unsigned int cmd) 73954552e49SJisheng Zhang { 74054552e49SJisheng Zhang if (host->ops->adma_write_desc) 74154552e49SJisheng Zhang host->ops->adma_write_desc(host, desc, addr, len, cmd); 74207be55b5SJisheng Zhang else 74354552e49SJisheng Zhang sdhci_adma_write_desc(host, desc, addr, len, cmd); 744118cd17dSBen Dooks } 745118cd17dSBen Dooks 746b5ffa674SAdrian Hunter static void sdhci_adma_mark_end(void *desc) 747b5ffa674SAdrian Hunter { 748e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 749b5ffa674SAdrian Hunter 750e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have 'cmd' in same position */ 7510545230fSAdrian Hunter dma_desc->cmd |= cpu_to_le16(ADMA2_END); 752b5ffa674SAdrian Hunter } 753b5ffa674SAdrian Hunter 75460c64762SRussell King static void sdhci_adma_table_pre(struct sdhci_host *host, 75560c64762SRussell King struct mmc_data *data, int sg_count) 7562134a922SPierre Ossman { 7572134a922SPierre Ossman struct scatterlist *sg; 758acc3ad13SRussell King dma_addr_t addr, align_addr; 759acc3ad13SRussell King void *desc, *align; 760acc3ad13SRussell King char *buffer; 761acc3ad13SRussell King int len, offset, i; 7622134a922SPierre Ossman 7632134a922SPierre Ossman /* 7642134a922SPierre Ossman * The spec does not specify endianness of descriptor table. 7652134a922SPierre Ossman * We currently guess that it is LE. 7662134a922SPierre Ossman */ 7672134a922SPierre Ossman 76860c64762SRussell King host->sg_count = sg_count; 7692134a922SPierre Ossman 7704efaa6fbSAdrian Hunter desc = host->adma_table; 7712134a922SPierre Ossman align = host->align_buffer; 7722134a922SPierre Ossman 7732134a922SPierre Ossman align_addr = host->align_addr; 7742134a922SPierre Ossman 7752134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 7762134a922SPierre Ossman addr = sg_dma_address(sg); 7772134a922SPierre Ossman len = sg_dma_len(sg); 7782134a922SPierre Ossman 7792134a922SPierre Ossman /* 780acc3ad13SRussell King * The SDHCI specification states that ADMA addresses must 781acc3ad13SRussell King * be 32-bit aligned. If they aren't, then we use a bounce 782acc3ad13SRussell King * buffer for the (up to three) bytes that screw up the 7832134a922SPierre Ossman * alignment. 7842134a922SPierre Ossman */ 78504a5ae6fSAdrian Hunter offset = (SDHCI_ADMA2_ALIGN - (addr & SDHCI_ADMA2_MASK)) & 78604a5ae6fSAdrian Hunter SDHCI_ADMA2_MASK; 7872134a922SPierre Ossman if (offset) { 7882134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 789*4438592cSAdrian Hunter buffer = sdhci_kmap_atomic(sg); 7902134a922SPierre Ossman memcpy(align, buffer, offset); 791*4438592cSAdrian Hunter sdhci_kunmap_atomic(buffer); 7922134a922SPierre Ossman } 7932134a922SPierre Ossman 794118cd17dSBen Dooks /* tran, valid */ 79554552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, align_addr, 79654552e49SJisheng Zhang offset, ADMA2_TRAN_VALID); 7972134a922SPierre Ossman 7982134a922SPierre Ossman BUG_ON(offset > 65536); 7992134a922SPierre Ossman 80004a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN; 80104a5ae6fSAdrian Hunter align_addr += SDHCI_ADMA2_ALIGN; 8022134a922SPierre Ossman 8032134a922SPierre Ossman addr += offset; 8042134a922SPierre Ossman len -= offset; 8052134a922SPierre Ossman } 8062134a922SPierre Ossman 8073d7c194bSAdrian Hunter /* 8083d7c194bSAdrian Hunter * The block layer forces a minimum segment size of PAGE_SIZE, 8093d7c194bSAdrian Hunter * so 'len' can be too big here if PAGE_SIZE >= 64KiB. Write 8103d7c194bSAdrian Hunter * multiple descriptors, noting that the ADMA table is sized 8113d7c194bSAdrian Hunter * for 4KiB chunks anyway, so it will be big enough. 8123d7c194bSAdrian Hunter */ 8133d7c194bSAdrian Hunter while (len > host->max_adma) { 8143d7c194bSAdrian Hunter int n = 32 * 1024; /* 32KiB*/ 8153d7c194bSAdrian Hunter 8163d7c194bSAdrian Hunter __sdhci_adma_write_desc(host, &desc, addr, n, ADMA2_TRAN_VALID); 8173d7c194bSAdrian Hunter addr += n; 8183d7c194bSAdrian Hunter len -= n; 8193d7c194bSAdrian Hunter } 8202134a922SPierre Ossman 821118cd17dSBen Dooks /* tran, valid */ 82254552e49SJisheng Zhang if (len) 82354552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, addr, len, 824347ea32dSAdrian Hunter ADMA2_TRAN_VALID); 8252134a922SPierre Ossman 8262134a922SPierre Ossman /* 8272134a922SPierre Ossman * If this triggers then we have a calculation bug 8282134a922SPierre Ossman * somewhere. :/ 8292134a922SPierre Ossman */ 83076fe379aSAdrian Hunter WARN_ON((desc - host->adma_table) >= host->adma_table_sz); 8312134a922SPierre Ossman } 8322134a922SPierre Ossman 83370764a90SThomas Abraham if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { 834acc3ad13SRussell King /* Mark the last descriptor as the terminating descriptor */ 8354efaa6fbSAdrian Hunter if (desc != host->adma_table) { 83676fe379aSAdrian Hunter desc -= host->desc_sz; 837b5ffa674SAdrian Hunter sdhci_adma_mark_end(desc); 83870764a90SThomas Abraham } 83970764a90SThomas Abraham } else { 840acc3ad13SRussell King /* Add a terminating entry - nop, end, valid */ 84154552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, 0, 0, ADMA2_NOP_END_VALID); 84270764a90SThomas Abraham } 8432134a922SPierre Ossman } 8442134a922SPierre Ossman 8452134a922SPierre Ossman static void sdhci_adma_table_post(struct sdhci_host *host, 8462134a922SPierre Ossman struct mmc_data *data) 8472134a922SPierre Ossman { 8482134a922SPierre Ossman struct scatterlist *sg; 8492134a922SPierre Ossman int i, size; 8501c3d5f6dSAdrian Hunter void *align; 8512134a922SPierre Ossman char *buffer; 8522134a922SPierre Ossman 85347fa9613SRussell King if (data->flags & MMC_DATA_READ) { 85447fa9613SRussell King bool has_unaligned = false; 85547fa9613SRussell King 856de0b65a7SRussell King /* Do a quick scan of the SG list for any unaligned mappings */ 857de0b65a7SRussell King for_each_sg(data->sg, sg, host->sg_count, i) 85804a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { 859de0b65a7SRussell King has_unaligned = true; 860de0b65a7SRussell King break; 861de0b65a7SRussell King } 862de0b65a7SRussell King 86347fa9613SRussell King if (has_unaligned) { 8642134a922SPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 865f55c98f7SRussell King data->sg_len, DMA_FROM_DEVICE); 8662134a922SPierre Ossman 8672134a922SPierre Ossman align = host->align_buffer; 8682134a922SPierre Ossman 8692134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 87004a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { 87104a5ae6fSAdrian Hunter size = SDHCI_ADMA2_ALIGN - 87204a5ae6fSAdrian Hunter (sg_dma_address(sg) & SDHCI_ADMA2_MASK); 8732134a922SPierre Ossman 874*4438592cSAdrian Hunter buffer = sdhci_kmap_atomic(sg); 8752134a922SPierre Ossman memcpy(buffer, align, size); 876*4438592cSAdrian Hunter sdhci_kunmap_atomic(buffer); 8772134a922SPierre Ossman 87804a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN; 8792134a922SPierre Ossman } 8802134a922SPierre Ossman } 8812134a922SPierre Ossman } 88247fa9613SRussell King } 8832134a922SPierre Ossman } 8842134a922SPierre Ossman 88538eee2e8SMasahiro Yamada static void sdhci_set_adma_addr(struct sdhci_host *host, dma_addr_t addr) 88638eee2e8SMasahiro Yamada { 88738eee2e8SMasahiro Yamada sdhci_writel(host, lower_32_bits(addr), SDHCI_ADMA_ADDRESS); 88838eee2e8SMasahiro Yamada if (host->flags & SDHCI_USE_64_BIT_DMA) 88938eee2e8SMasahiro Yamada sdhci_writel(host, upper_32_bits(addr), SDHCI_ADMA_ADDRESS_HI); 89038eee2e8SMasahiro Yamada } 89138eee2e8SMasahiro Yamada 892917a0c52SChunyan Zhang static dma_addr_t sdhci_sdma_address(struct sdhci_host *host) 893bd9b9027SLinus Walleij { 894bd9b9027SLinus Walleij if (host->bounce_buffer) 895bd9b9027SLinus Walleij return host->bounce_addr; 896bd9b9027SLinus Walleij else 897bd9b9027SLinus Walleij return sg_dma_address(host->data->sg); 898bd9b9027SLinus Walleij } 899bd9b9027SLinus Walleij 900917a0c52SChunyan Zhang static void sdhci_set_sdma_addr(struct sdhci_host *host, dma_addr_t addr) 901917a0c52SChunyan Zhang { 90238eee2e8SMasahiro Yamada if (host->v4_mode) 90338eee2e8SMasahiro Yamada sdhci_set_adma_addr(host, addr); 90438eee2e8SMasahiro Yamada else 905917a0c52SChunyan Zhang sdhci_writel(host, addr, SDHCI_DMA_ADDRESS); 906917a0c52SChunyan Zhang } 907917a0c52SChunyan Zhang 9080bb28d73SAdrian Hunter static unsigned int sdhci_target_timeout(struct sdhci_host *host, 9090bb28d73SAdrian Hunter struct mmc_command *cmd, 9100bb28d73SAdrian Hunter struct mmc_data *data) 9110bb28d73SAdrian Hunter { 9120bb28d73SAdrian Hunter unsigned int target_timeout; 9130bb28d73SAdrian Hunter 9140bb28d73SAdrian Hunter /* timeout in us */ 9150bb28d73SAdrian Hunter if (!data) { 9160bb28d73SAdrian Hunter target_timeout = cmd->busy_timeout * 1000; 9170bb28d73SAdrian Hunter } else { 9180bb28d73SAdrian Hunter target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000); 9190bb28d73SAdrian Hunter if (host->clock && data->timeout_clks) { 9200bb28d73SAdrian Hunter unsigned long long val; 9210bb28d73SAdrian Hunter 9220bb28d73SAdrian Hunter /* 9230bb28d73SAdrian Hunter * data->timeout_clks is in units of clock cycles. 9240bb28d73SAdrian Hunter * host->clock is in Hz. target_timeout is in us. 9250bb28d73SAdrian Hunter * Hence, us = 1000000 * cycles / Hz. Round up. 9260bb28d73SAdrian Hunter */ 9270bb28d73SAdrian Hunter val = 1000000ULL * data->timeout_clks; 9280bb28d73SAdrian Hunter if (do_div(val, host->clock)) 9290bb28d73SAdrian Hunter target_timeout++; 9300bb28d73SAdrian Hunter target_timeout += val; 9310bb28d73SAdrian Hunter } 9320bb28d73SAdrian Hunter } 9330bb28d73SAdrian Hunter 9340bb28d73SAdrian Hunter return target_timeout; 9350bb28d73SAdrian Hunter } 9360bb28d73SAdrian Hunter 937fc1fa1b7SKishon Vijay Abraham I static void sdhci_calc_sw_timeout(struct sdhci_host *host, 938fc1fa1b7SKishon Vijay Abraham I struct mmc_command *cmd) 939fc1fa1b7SKishon Vijay Abraham I { 940fc1fa1b7SKishon Vijay Abraham I struct mmc_data *data = cmd->data; 941fc1fa1b7SKishon Vijay Abraham I struct mmc_host *mmc = host->mmc; 942fc1fa1b7SKishon Vijay Abraham I struct mmc_ios *ios = &mmc->ios; 943fc1fa1b7SKishon Vijay Abraham I unsigned char bus_width = 1 << ios->bus_width; 944fc1fa1b7SKishon Vijay Abraham I unsigned int blksz; 945fc1fa1b7SKishon Vijay Abraham I unsigned int freq; 946fc1fa1b7SKishon Vijay Abraham I u64 target_timeout; 947fc1fa1b7SKishon Vijay Abraham I u64 transfer_time; 948fc1fa1b7SKishon Vijay Abraham I 949fc1fa1b7SKishon Vijay Abraham I target_timeout = sdhci_target_timeout(host, cmd, data); 950fc1fa1b7SKishon Vijay Abraham I target_timeout *= NSEC_PER_USEC; 951fc1fa1b7SKishon Vijay Abraham I 952fc1fa1b7SKishon Vijay Abraham I if (data) { 953fc1fa1b7SKishon Vijay Abraham I blksz = data->blksz; 954d2f025b0SJisheng Zhang freq = mmc->actual_clock ? : host->clock; 955fc1fa1b7SKishon Vijay Abraham I transfer_time = (u64)blksz * NSEC_PER_SEC * (8 / bus_width); 956fc1fa1b7SKishon Vijay Abraham I do_div(transfer_time, freq); 957fc1fa1b7SKishon Vijay Abraham I /* multiply by '2' to account for any unknowns */ 958fc1fa1b7SKishon Vijay Abraham I transfer_time = transfer_time * 2; 959fc1fa1b7SKishon Vijay Abraham I /* calculate timeout for the entire data */ 960fc1fa1b7SKishon Vijay Abraham I host->data_timeout = data->blocks * target_timeout + 961fc1fa1b7SKishon Vijay Abraham I transfer_time; 962fc1fa1b7SKishon Vijay Abraham I } else { 963fc1fa1b7SKishon Vijay Abraham I host->data_timeout = target_timeout; 964fc1fa1b7SKishon Vijay Abraham I } 965fc1fa1b7SKishon Vijay Abraham I 966fc1fa1b7SKishon Vijay Abraham I if (host->data_timeout) 967fc1fa1b7SKishon Vijay Abraham I host->data_timeout += MMC_CMD_TRANSFER_TIME; 968fc1fa1b7SKishon Vijay Abraham I } 969fc1fa1b7SKishon Vijay Abraham I 970a999fd93SAdrian Hunter static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd, 971a999fd93SAdrian Hunter bool *too_big) 9721c6a0718SPierre Ossman { 9731c6a0718SPierre Ossman u8 count; 974401059dfSBOUGH CHEN struct mmc_data *data; 9751c6a0718SPierre Ossman unsigned target_timeout, current_timeout; 9761c6a0718SPierre Ossman 9779c6bb8c6SBean Huo *too_big = false; 978a999fd93SAdrian Hunter 979ee53ab5dSPierre Ossman /* 980ee53ab5dSPierre Ossman * If the host controller provides us with an incorrect timeout 981e30314f2SSarthak Garg * value, just skip the check and use the maximum. The hardware may take 982ee53ab5dSPierre Ossman * longer to time out, but that's much better than having a too-short 983ee53ab5dSPierre Ossman * timeout value. 984ee53ab5dSPierre Ossman */ 98511a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) 986e30314f2SSarthak Garg return host->max_timeout_count; 987e538fbe8SPierre Ossman 9889c6bb8c6SBean Huo /* Unspecified command, assume max */ 989401059dfSBOUGH CHEN if (cmd == NULL) 990e30314f2SSarthak Garg return host->max_timeout_count; 991401059dfSBOUGH CHEN 992401059dfSBOUGH CHEN data = cmd->data; 993a3c7778fSAndrei Warkentin /* Unspecified timeout, assume max */ 9941d4d7744SUlf Hansson if (!data && !cmd->busy_timeout) 995e30314f2SSarthak Garg return host->max_timeout_count; 996a3c7778fSAndrei Warkentin 9971c6a0718SPierre Ossman /* timeout in us */ 9980bb28d73SAdrian Hunter target_timeout = sdhci_target_timeout(host, cmd, data); 9991c6a0718SPierre Ossman 10001c6a0718SPierre Ossman /* 10011c6a0718SPierre Ossman * Figure out needed cycles. 10021c6a0718SPierre Ossman * We do this in steps in order to fit inside a 32 bit int. 10031c6a0718SPierre Ossman * The first step is the minimum timeout, which will have a 10041c6a0718SPierre Ossman * minimum resolution of 6 bits: 10051c6a0718SPierre Ossman * (1) 2^13*1000 > 2^22, 10061c6a0718SPierre Ossman * (2) host->timeout_clk < 2^16 10071c6a0718SPierre Ossman * => 10081c6a0718SPierre Ossman * (1) / (2) > 2^6 10091c6a0718SPierre Ossman */ 10101c6a0718SPierre Ossman count = 0; 10111c6a0718SPierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 10121c6a0718SPierre Ossman while (current_timeout < target_timeout) { 10131c6a0718SPierre Ossman count++; 10141c6a0718SPierre Ossman current_timeout <<= 1; 1015e30314f2SSarthak Garg if (count > host->max_timeout_count) { 1016a999fd93SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT)) 1017f421865dSAdrian Hunter DBG("Too large timeout 0x%x requested for CMD%d!\n", 1018f421865dSAdrian Hunter count, cmd->opcode); 1019e30314f2SSarthak Garg count = host->max_timeout_count; 10209c6bb8c6SBean Huo *too_big = true; 10219c6bb8c6SBean Huo break; 10229c6bb8c6SBean Huo } 10231c6a0718SPierre Ossman } 10241c6a0718SPierre Ossman 1025ee53ab5dSPierre Ossman return count; 1026ee53ab5dSPierre Ossman } 1027ee53ab5dSPierre Ossman 10286aa943abSAnton Vorontsov static void sdhci_set_transfer_irqs(struct sdhci_host *host) 10296aa943abSAnton Vorontsov { 10306aa943abSAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 10316aa943abSAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; 10326aa943abSAnton Vorontsov 10336aa943abSAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA) 1034b537f94cSRussell King host->ier = (host->ier & ~pio_irqs) | dma_irqs; 10356aa943abSAnton Vorontsov else 1036b537f94cSRussell King host->ier = (host->ier & ~dma_irqs) | pio_irqs; 1037b537f94cSRussell King 1038af849c86SAdrian Hunter if (host->flags & (SDHCI_AUTO_CMD23 | SDHCI_AUTO_CMD12)) 1039af849c86SAdrian Hunter host->ier |= SDHCI_INT_AUTO_CMD_ERR; 1040af849c86SAdrian Hunter else 1041af849c86SAdrian Hunter host->ier &= ~SDHCI_INT_AUTO_CMD_ERR; 1042af849c86SAdrian Hunter 1043b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 1044b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 10456aa943abSAnton Vorontsov } 10466aa943abSAnton Vorontsov 10477907ebe7SFaiz Abbas void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable) 1048a999fd93SAdrian Hunter { 1049a999fd93SAdrian Hunter if (enable) 1050a999fd93SAdrian Hunter host->ier |= SDHCI_INT_DATA_TIMEOUT; 1051a999fd93SAdrian Hunter else 1052a999fd93SAdrian Hunter host->ier &= ~SDHCI_INT_DATA_TIMEOUT; 1053a999fd93SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 1054a999fd93SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 1055a999fd93SAdrian Hunter } 10567907ebe7SFaiz Abbas EXPORT_SYMBOL_GPL(sdhci_set_data_timeout_irq); 1057a999fd93SAdrian Hunter 10587d76ed77SFaiz Abbas void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) 1059ee53ab5dSPierre Ossman { 1060a999fd93SAdrian Hunter bool too_big = false; 10617d76ed77SFaiz Abbas u8 count = sdhci_calc_timeout(host, cmd, &too_big); 1062a999fd93SAdrian Hunter 1063a999fd93SAdrian Hunter if (too_big && 1064a999fd93SAdrian Hunter host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) { 1065fc1fa1b7SKishon Vijay Abraham I sdhci_calc_sw_timeout(host, cmd); 1066a999fd93SAdrian Hunter sdhci_set_data_timeout_irq(host, false); 1067a999fd93SAdrian Hunter } else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT)) { 1068a999fd93SAdrian Hunter sdhci_set_data_timeout_irq(host, true); 1069a999fd93SAdrian Hunter } 1070a999fd93SAdrian Hunter 1071b45e668aSAisheng Dong sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); 1072b45e668aSAisheng Dong } 10737d76ed77SFaiz Abbas EXPORT_SYMBOL_GPL(__sdhci_set_timeout); 10747d76ed77SFaiz Abbas 10757d76ed77SFaiz Abbas static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) 10767d76ed77SFaiz Abbas { 10777d76ed77SFaiz Abbas if (host->ops->set_timeout) 10787d76ed77SFaiz Abbas host->ops->set_timeout(host, cmd); 10797d76ed77SFaiz Abbas else 10807d76ed77SFaiz Abbas __sdhci_set_timeout(host, cmd); 1081b45e668aSAisheng Dong } 1082b45e668aSAisheng Dong 108315db1836SFaiz Abbas static void sdhci_initialize_data(struct sdhci_host *host, 108415db1836SFaiz Abbas struct mmc_data *data) 1085b45e668aSAisheng Dong { 108643dea098SAdrian Hunter WARN_ON(host->data); 108743dea098SAdrian Hunter 1088ee53ab5dSPierre Ossman /* Sanity checks */ 1089ee53ab5dSPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 1090ee53ab5dSPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 1091ee53ab5dSPierre Ossman BUG_ON(data->blocks > 65535); 1092ee53ab5dSPierre Ossman 1093ee53ab5dSPierre Ossman host->data = data; 1094ee53ab5dSPierre Ossman host->data_early = 0; 1095f6a03cbfSMikko Vinni host->data->bytes_xfered = 0; 109615db1836SFaiz Abbas } 109715db1836SFaiz Abbas 109815db1836SFaiz Abbas static inline void sdhci_set_block_info(struct sdhci_host *host, 109915db1836SFaiz Abbas struct mmc_data *data) 110015db1836SFaiz Abbas { 110115db1836SFaiz Abbas /* Set the DMA boundary value and block size */ 110215db1836SFaiz Abbas sdhci_writew(host, 110315db1836SFaiz Abbas SDHCI_MAKE_BLKSZ(host->sdma_boundary, data->blksz), 110415db1836SFaiz Abbas SDHCI_BLOCK_SIZE); 110515db1836SFaiz Abbas /* 110615db1836SFaiz Abbas * For Version 4.10 onwards, if v4 mode is enabled, 32-bit Block Count 110715db1836SFaiz Abbas * can be supported, in that case 16-bit block count register must be 0. 110815db1836SFaiz Abbas */ 110915db1836SFaiz Abbas if (host->version >= SDHCI_SPEC_410 && host->v4_mode && 111015db1836SFaiz Abbas (host->quirks2 & SDHCI_QUIRK2_USE_32BIT_BLK_CNT)) { 111115db1836SFaiz Abbas if (sdhci_readw(host, SDHCI_BLOCK_COUNT)) 111215db1836SFaiz Abbas sdhci_writew(host, 0, SDHCI_BLOCK_COUNT); 111315db1836SFaiz Abbas sdhci_writew(host, data->blocks, SDHCI_32BIT_BLK_CNT); 111415db1836SFaiz Abbas } else { 111515db1836SFaiz Abbas sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); 111615db1836SFaiz Abbas } 111715db1836SFaiz Abbas } 111815db1836SFaiz Abbas 111915db1836SFaiz Abbas static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) 112015db1836SFaiz Abbas { 112115db1836SFaiz Abbas struct mmc_data *data = cmd->data; 112215db1836SFaiz Abbas 112315db1836SFaiz Abbas sdhci_initialize_data(host, data); 1124ee53ab5dSPierre Ossman 1125fce14421SRussell King if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 1126fce14421SRussell King struct scatterlist *sg; 1127fce14421SRussell King unsigned int length_mask, offset_mask; 1128fce14421SRussell King int i; 1129fce14421SRussell King 1130c9fddbc4SPierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 1131c9fddbc4SPierre Ossman 11322134a922SPierre Ossman /* 11332134a922SPierre Ossman * FIXME: This doesn't account for merging when mapping the 11342134a922SPierre Ossman * scatterlist. 1135df953925SRussell King * 1136df953925SRussell King * The assumption here being that alignment and lengths are 1137df953925SRussell King * the same after DMA mapping to device address space. 11382134a922SPierre Ossman */ 1139a0eaf0f9SRussell King length_mask = 0; 1140df953925SRussell King offset_mask = 0; 11412134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 1142df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) { 1143a0eaf0f9SRussell King length_mask = 3; 1144df953925SRussell King /* 1145df953925SRussell King * As we use up to 3 byte chunks to work 1146df953925SRussell King * around alignment problems, we need to 1147df953925SRussell King * check the offset as well. 1148df953925SRussell King */ 1149df953925SRussell King offset_mask = 3; 1150df953925SRussell King } 11512134a922SPierre Ossman } else { 11522134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 1153a0eaf0f9SRussell King length_mask = 3; 1154df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 1155df953925SRussell King offset_mask = 3; 11562134a922SPierre Ossman } 11572134a922SPierre Ossman 1158df953925SRussell King if (unlikely(length_mask | offset_mask)) { 11592134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 1160a0eaf0f9SRussell King if (sg->length & length_mask) { 11612e4456f0SMarek Vasut DBG("Reverting to PIO because of transfer size (%d)\n", 11622134a922SPierre Ossman sg->length); 1163c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 11642134a922SPierre Ossman break; 11652134a922SPierre Ossman } 1166a0eaf0f9SRussell King if (sg->offset & offset_mask) { 11672e4456f0SMarek Vasut DBG("Reverting to PIO because of bad alignment\n"); 1168c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 11692134a922SPierre Ossman break; 11702134a922SPierre Ossman } 11712134a922SPierre Ossman } 11722134a922SPierre Ossman } 11732134a922SPierre Ossman } 11742134a922SPierre Ossman 11758f1934ceSPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 1176c0999b72SRussell King int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); 11778f1934ceSPierre Ossman 117862a7f368SJiri Slaby if (sg_cnt <= 0) { 11798f1934ceSPierre Ossman /* 11808f1934ceSPierre Ossman * This only happens when someone fed 11818f1934ceSPierre Ossman * us an invalid request. 11828f1934ceSPierre Ossman */ 11838f1934ceSPierre Ossman WARN_ON(1); 1184ebd6d357SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 118560c64762SRussell King } else if (host->flags & SDHCI_USE_ADMA) { 118660c64762SRussell King sdhci_adma_table_pre(host, data, sg_cnt); 118738eee2e8SMasahiro Yamada sdhci_set_adma_addr(host, host->adma_addr); 11888f1934ceSPierre Ossman } else { 1189719a61b4SPierre Ossman WARN_ON(sg_cnt != 1); 1190917a0c52SChunyan Zhang sdhci_set_sdma_addr(host, sdhci_sdma_address(host)); 11918f1934ceSPierre Ossman } 11928f1934ceSPierre Ossman } 11938f1934ceSPierre Ossman 1194685e444bSChunyan Zhang sdhci_config_dma(host); 1195c9fddbc4SPierre Ossman 11968f1934ceSPierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 1197da60a91dSSebastian Andrzej Siewior int flags; 1198da60a91dSSebastian Andrzej Siewior 1199da60a91dSSebastian Andrzej Siewior flags = SG_MITER_ATOMIC; 1200da60a91dSSebastian Andrzej Siewior if (host->data->flags & MMC_DATA_READ) 1201da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_TO_SG; 1202da60a91dSSebastian Andrzej Siewior else 1203da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_FROM_SG; 1204da60a91dSSebastian Andrzej Siewior sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 12057659150cSPierre Ossman host->blocks = data->blocks; 12061c6a0718SPierre Ossman } 12071c6a0718SPierre Ossman 12086aa943abSAnton Vorontsov sdhci_set_transfer_irqs(host); 12096aa943abSAnton Vorontsov 121015db1836SFaiz Abbas sdhci_set_block_info(host, data); 1211e65953d4SChunyan Zhang } 12121c6a0718SPierre Ossman 121318e762e3SChunyan Zhang #if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA) 121418e762e3SChunyan Zhang 121518e762e3SChunyan Zhang static int sdhci_external_dma_init(struct sdhci_host *host) 121618e762e3SChunyan Zhang { 121718e762e3SChunyan Zhang int ret = 0; 121818e762e3SChunyan Zhang struct mmc_host *mmc = host->mmc; 121918e762e3SChunyan Zhang 1220bac53336SJisheng Zhang host->tx_chan = dma_request_chan(mmc_dev(mmc), "tx"); 122118e762e3SChunyan Zhang if (IS_ERR(host->tx_chan)) { 122218e762e3SChunyan Zhang ret = PTR_ERR(host->tx_chan); 122318e762e3SChunyan Zhang if (ret != -EPROBE_DEFER) 122418e762e3SChunyan Zhang pr_warn("Failed to request TX DMA channel.\n"); 122518e762e3SChunyan Zhang host->tx_chan = NULL; 122618e762e3SChunyan Zhang return ret; 122718e762e3SChunyan Zhang } 122818e762e3SChunyan Zhang 1229bac53336SJisheng Zhang host->rx_chan = dma_request_chan(mmc_dev(mmc), "rx"); 123018e762e3SChunyan Zhang if (IS_ERR(host->rx_chan)) { 123118e762e3SChunyan Zhang if (host->tx_chan) { 123218e762e3SChunyan Zhang dma_release_channel(host->tx_chan); 123318e762e3SChunyan Zhang host->tx_chan = NULL; 123418e762e3SChunyan Zhang } 123518e762e3SChunyan Zhang 123618e762e3SChunyan Zhang ret = PTR_ERR(host->rx_chan); 123718e762e3SChunyan Zhang if (ret != -EPROBE_DEFER) 123818e762e3SChunyan Zhang pr_warn("Failed to request RX DMA channel.\n"); 123918e762e3SChunyan Zhang host->rx_chan = NULL; 124018e762e3SChunyan Zhang } 124118e762e3SChunyan Zhang 124218e762e3SChunyan Zhang return ret; 124318e762e3SChunyan Zhang } 124418e762e3SChunyan Zhang 124518e762e3SChunyan Zhang static struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, 124618e762e3SChunyan Zhang struct mmc_data *data) 124718e762e3SChunyan Zhang { 124818e762e3SChunyan Zhang return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan; 124918e762e3SChunyan Zhang } 125018e762e3SChunyan Zhang 125118e762e3SChunyan Zhang static int sdhci_external_dma_setup(struct sdhci_host *host, 125218e762e3SChunyan Zhang struct mmc_command *cmd) 125318e762e3SChunyan Zhang { 125418e762e3SChunyan Zhang int ret, i; 12551215c025SChunyan Zhang enum dma_transfer_direction dir; 125618e762e3SChunyan Zhang struct dma_async_tx_descriptor *desc; 125718e762e3SChunyan Zhang struct mmc_data *data = cmd->data; 125818e762e3SChunyan Zhang struct dma_chan *chan; 125918e762e3SChunyan Zhang struct dma_slave_config cfg; 126018e762e3SChunyan Zhang dma_cookie_t cookie; 126118e762e3SChunyan Zhang int sg_cnt; 126218e762e3SChunyan Zhang 126318e762e3SChunyan Zhang if (!host->mapbase) 126418e762e3SChunyan Zhang return -EINVAL; 126518e762e3SChunyan Zhang 1266522654d5STony Lindgren memset(&cfg, 0, sizeof(cfg)); 126718e762e3SChunyan Zhang cfg.src_addr = host->mapbase + SDHCI_BUFFER; 126818e762e3SChunyan Zhang cfg.dst_addr = host->mapbase + SDHCI_BUFFER; 126918e762e3SChunyan Zhang cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 127018e762e3SChunyan Zhang cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 127118e762e3SChunyan Zhang cfg.src_maxburst = data->blksz / 4; 127218e762e3SChunyan Zhang cfg.dst_maxburst = data->blksz / 4; 127318e762e3SChunyan Zhang 127418e762e3SChunyan Zhang /* Sanity check: all the SG entries must be aligned by block size. */ 127518e762e3SChunyan Zhang for (i = 0; i < data->sg_len; i++) { 127618e762e3SChunyan Zhang if ((data->sg + i)->length % data->blksz) 127718e762e3SChunyan Zhang return -EINVAL; 127818e762e3SChunyan Zhang } 127918e762e3SChunyan Zhang 128018e762e3SChunyan Zhang chan = sdhci_external_dma_channel(host, data); 128118e762e3SChunyan Zhang 128218e762e3SChunyan Zhang ret = dmaengine_slave_config(chan, &cfg); 128318e762e3SChunyan Zhang if (ret) 128418e762e3SChunyan Zhang return ret; 128518e762e3SChunyan Zhang 128618e762e3SChunyan Zhang sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); 128718e762e3SChunyan Zhang if (sg_cnt <= 0) 128818e762e3SChunyan Zhang return -EINVAL; 128918e762e3SChunyan Zhang 12901215c025SChunyan Zhang dir = data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; 12911215c025SChunyan Zhang desc = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len, dir, 129218e762e3SChunyan Zhang DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 129318e762e3SChunyan Zhang if (!desc) 129418e762e3SChunyan Zhang return -EINVAL; 129518e762e3SChunyan Zhang 129618e762e3SChunyan Zhang desc->callback = NULL; 129718e762e3SChunyan Zhang desc->callback_param = NULL; 129818e762e3SChunyan Zhang 129918e762e3SChunyan Zhang cookie = dmaengine_submit(desc); 130018e762e3SChunyan Zhang if (dma_submit_error(cookie)) 130118e762e3SChunyan Zhang ret = cookie; 130218e762e3SChunyan Zhang 130318e762e3SChunyan Zhang return ret; 130418e762e3SChunyan Zhang } 130518e762e3SChunyan Zhang 130618e762e3SChunyan Zhang static void sdhci_external_dma_release(struct sdhci_host *host) 130718e762e3SChunyan Zhang { 130818e762e3SChunyan Zhang if (host->tx_chan) { 130918e762e3SChunyan Zhang dma_release_channel(host->tx_chan); 131018e762e3SChunyan Zhang host->tx_chan = NULL; 131118e762e3SChunyan Zhang } 131218e762e3SChunyan Zhang 131318e762e3SChunyan Zhang if (host->rx_chan) { 131418e762e3SChunyan Zhang dma_release_channel(host->rx_chan); 131518e762e3SChunyan Zhang host->rx_chan = NULL; 131618e762e3SChunyan Zhang } 131718e762e3SChunyan Zhang 131818e762e3SChunyan Zhang sdhci_switch_external_dma(host, false); 131918e762e3SChunyan Zhang } 132018e762e3SChunyan Zhang 132118e762e3SChunyan Zhang static void __sdhci_external_dma_prepare_data(struct sdhci_host *host, 132218e762e3SChunyan Zhang struct mmc_command *cmd) 132318e762e3SChunyan Zhang { 132418e762e3SChunyan Zhang struct mmc_data *data = cmd->data; 132518e762e3SChunyan Zhang 132618e762e3SChunyan Zhang sdhci_initialize_data(host, data); 132718e762e3SChunyan Zhang 132818e762e3SChunyan Zhang host->flags |= SDHCI_REQ_USE_DMA; 132918e762e3SChunyan Zhang sdhci_set_transfer_irqs(host); 133018e762e3SChunyan Zhang 133118e762e3SChunyan Zhang sdhci_set_block_info(host, data); 133218e762e3SChunyan Zhang } 133318e762e3SChunyan Zhang 133418e762e3SChunyan Zhang static void sdhci_external_dma_prepare_data(struct sdhci_host *host, 133518e762e3SChunyan Zhang struct mmc_command *cmd) 133618e762e3SChunyan Zhang { 133718e762e3SChunyan Zhang if (!sdhci_external_dma_setup(host, cmd)) { 133818e762e3SChunyan Zhang __sdhci_external_dma_prepare_data(host, cmd); 133918e762e3SChunyan Zhang } else { 134018e762e3SChunyan Zhang sdhci_external_dma_release(host); 134118e762e3SChunyan Zhang pr_err("%s: Cannot use external DMA, switch to the DMA/PIO which standard SDHCI provides.\n", 134218e762e3SChunyan Zhang mmc_hostname(host->mmc)); 134318e762e3SChunyan Zhang sdhci_prepare_data(host, cmd); 134418e762e3SChunyan Zhang } 134518e762e3SChunyan Zhang } 134618e762e3SChunyan Zhang 134718e762e3SChunyan Zhang static void sdhci_external_dma_pre_transfer(struct sdhci_host *host, 134818e762e3SChunyan Zhang struct mmc_command *cmd) 134918e762e3SChunyan Zhang { 135018e762e3SChunyan Zhang struct dma_chan *chan; 135118e762e3SChunyan Zhang 135218e762e3SChunyan Zhang if (!cmd->data) 135318e762e3SChunyan Zhang return; 135418e762e3SChunyan Zhang 135518e762e3SChunyan Zhang chan = sdhci_external_dma_channel(host, cmd->data); 135618e762e3SChunyan Zhang if (chan) 135718e762e3SChunyan Zhang dma_async_issue_pending(chan); 135818e762e3SChunyan Zhang } 135918e762e3SChunyan Zhang 136018e762e3SChunyan Zhang #else 136118e762e3SChunyan Zhang 136218e762e3SChunyan Zhang static inline int sdhci_external_dma_init(struct sdhci_host *host) 136318e762e3SChunyan Zhang { 136418e762e3SChunyan Zhang return -EOPNOTSUPP; 136518e762e3SChunyan Zhang } 136618e762e3SChunyan Zhang 136718e762e3SChunyan Zhang static inline void sdhci_external_dma_release(struct sdhci_host *host) 136818e762e3SChunyan Zhang { 136918e762e3SChunyan Zhang } 137018e762e3SChunyan Zhang 137118e762e3SChunyan Zhang static inline void sdhci_external_dma_prepare_data(struct sdhci_host *host, 137218e762e3SChunyan Zhang struct mmc_command *cmd) 137318e762e3SChunyan Zhang { 137418e762e3SChunyan Zhang /* This should never happen */ 137518e762e3SChunyan Zhang WARN_ON_ONCE(1); 137618e762e3SChunyan Zhang } 137718e762e3SChunyan Zhang 137818e762e3SChunyan Zhang static inline void sdhci_external_dma_pre_transfer(struct sdhci_host *host, 137918e762e3SChunyan Zhang struct mmc_command *cmd) 138018e762e3SChunyan Zhang { 138118e762e3SChunyan Zhang } 138218e762e3SChunyan Zhang 138318e762e3SChunyan Zhang static inline struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, 138418e762e3SChunyan Zhang struct mmc_data *data) 138518e762e3SChunyan Zhang { 138618e762e3SChunyan Zhang return NULL; 138718e762e3SChunyan Zhang } 138818e762e3SChunyan Zhang 138918e762e3SChunyan Zhang #endif 139018e762e3SChunyan Zhang 139118e762e3SChunyan Zhang void sdhci_switch_external_dma(struct sdhci_host *host, bool en) 139218e762e3SChunyan Zhang { 139318e762e3SChunyan Zhang host->use_external_dma = en; 139418e762e3SChunyan Zhang } 139518e762e3SChunyan Zhang EXPORT_SYMBOL_GPL(sdhci_switch_external_dma); 139618e762e3SChunyan Zhang 13970293d501SAdrian Hunter static inline bool sdhci_auto_cmd12(struct sdhci_host *host, 13980293d501SAdrian Hunter struct mmc_request *mrq) 13990293d501SAdrian Hunter { 140020845befSAdrian Hunter return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) && 140120845befSAdrian Hunter !mrq->cap_cmd_during_tfr; 14020293d501SAdrian Hunter } 14030293d501SAdrian Hunter 1404ed633033SAdrian Hunter static inline bool sdhci_auto_cmd23(struct sdhci_host *host, 1405ed633033SAdrian Hunter struct mmc_request *mrq) 1406ed633033SAdrian Hunter { 1407ed633033SAdrian Hunter return mrq->sbc && (host->flags & SDHCI_AUTO_CMD23); 1408ed633033SAdrian Hunter } 1409ed633033SAdrian Hunter 1410ed633033SAdrian Hunter static inline bool sdhci_manual_cmd23(struct sdhci_host *host, 1411ed633033SAdrian Hunter struct mmc_request *mrq) 1412ed633033SAdrian Hunter { 1413ed633033SAdrian Hunter return mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23); 1414ed633033SAdrian Hunter } 1415ed633033SAdrian Hunter 1416427b6514SChunyan Zhang static inline void sdhci_auto_cmd_select(struct sdhci_host *host, 1417427b6514SChunyan Zhang struct mmc_command *cmd, 1418427b6514SChunyan Zhang u16 *mode) 1419427b6514SChunyan Zhang { 1420427b6514SChunyan Zhang bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) && 1421427b6514SChunyan Zhang (cmd->opcode != SD_IO_RW_EXTENDED); 1422ed633033SAdrian Hunter bool use_cmd23 = sdhci_auto_cmd23(host, cmd->mrq); 1423427b6514SChunyan Zhang u16 ctrl2; 1424427b6514SChunyan Zhang 1425427b6514SChunyan Zhang /* 1426427b6514SChunyan Zhang * In case of Version 4.10 or later, use of 'Auto CMD Auto 1427427b6514SChunyan Zhang * Select' is recommended rather than use of 'Auto CMD12 1428b3e1ea16SJisheng Zhang * Enable' or 'Auto CMD23 Enable'. We require Version 4 Mode 1429b3e1ea16SJisheng Zhang * here because some controllers (e.g sdhci-of-dwmshc) expect it. 1430427b6514SChunyan Zhang */ 1431b3e1ea16SJisheng Zhang if (host->version >= SDHCI_SPEC_410 && host->v4_mode && 1432b3e1ea16SJisheng Zhang (use_cmd12 || use_cmd23)) { 1433427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_SEL; 1434427b6514SChunyan Zhang 1435427b6514SChunyan Zhang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1436427b6514SChunyan Zhang if (use_cmd23) 1437427b6514SChunyan Zhang ctrl2 |= SDHCI_CMD23_ENABLE; 1438427b6514SChunyan Zhang else 1439427b6514SChunyan Zhang ctrl2 &= ~SDHCI_CMD23_ENABLE; 1440427b6514SChunyan Zhang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 1441427b6514SChunyan Zhang 1442427b6514SChunyan Zhang return; 1443427b6514SChunyan Zhang } 1444427b6514SChunyan Zhang 1445427b6514SChunyan Zhang /* 1446427b6514SChunyan Zhang * If we are sending CMD23, CMD12 never gets sent 1447427b6514SChunyan Zhang * on successful completion (so no Auto-CMD12). 1448427b6514SChunyan Zhang */ 1449427b6514SChunyan Zhang if (use_cmd12) 1450427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_CMD12; 1451427b6514SChunyan Zhang else if (use_cmd23) 1452427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_CMD23; 1453427b6514SChunyan Zhang } 1454427b6514SChunyan Zhang 14551c6a0718SPierre Ossman static void sdhci_set_transfer_mode(struct sdhci_host *host, 1456e89d456fSAndrei Warkentin struct mmc_command *cmd) 14571c6a0718SPierre Ossman { 1458d3fc5d71SVincent Yang u16 mode = 0; 1459e89d456fSAndrei Warkentin struct mmc_data *data = cmd->data; 14601c6a0718SPierre Ossman 14612b558c13SDong Aisheng if (data == NULL) { 14629b8ffea6SVincent Wan if (host->quirks2 & 14639b8ffea6SVincent Wan SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) { 14640086fc21Sernest.zhang /* must not clear SDHCI_TRANSFER_MODE when tuning */ 14650086fc21Sernest.zhang if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) 14669b8ffea6SVincent Wan sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); 14679b8ffea6SVincent Wan } else { 14682b558c13SDong Aisheng /* clear Auto CMD settings for no data CMDs */ 14692b558c13SDong Aisheng mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); 14702b558c13SDong Aisheng sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | 14712b558c13SDong Aisheng SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); 14729b8ffea6SVincent Wan } 14731c6a0718SPierre Ossman return; 14742b558c13SDong Aisheng } 14751c6a0718SPierre Ossman 1476e538fbe8SPierre Ossman WARN_ON(!host->data); 1477e538fbe8SPierre Ossman 1478d3fc5d71SVincent Yang if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE)) 14791c6a0718SPierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 1480d3fc5d71SVincent Yang 1481e89d456fSAndrei Warkentin if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { 1482d3fc5d71SVincent Yang mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI; 1483427b6514SChunyan Zhang sdhci_auto_cmd_select(host, cmd, &mode); 1484ed633033SAdrian Hunter if (sdhci_auto_cmd23(host, cmd->mrq)) 1485a4c73abaSAdrian Hunter sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2); 1486c4512f79SJerry Huang } 14878edf6371SAndrei Warkentin 14881c6a0718SPierre Ossman if (data->flags & MMC_DATA_READ) 14891c6a0718SPierre Ossman mode |= SDHCI_TRNS_READ; 1490c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 14911c6a0718SPierre Ossman mode |= SDHCI_TRNS_DMA; 14921c6a0718SPierre Ossman 14934e4141a5SAnton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); 14941c6a0718SPierre Ossman } 14951c6a0718SPierre Ossman 14960cc563ceSAdrian Hunter static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) 14970cc563ceSAdrian Hunter { 14980cc563ceSAdrian Hunter return (!(host->flags & SDHCI_DEVICE_DEAD) && 14990cc563ceSAdrian Hunter ((mrq->cmd && mrq->cmd->error) || 15000cc563ceSAdrian Hunter (mrq->sbc && mrq->sbc->error) || 15014bf78099SAdrian Hunter (mrq->data && mrq->data->stop && mrq->data->stop->error) || 15020cc563ceSAdrian Hunter (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))); 15030cc563ceSAdrian Hunter } 15040cc563ceSAdrian Hunter 150515db1836SFaiz Abbas static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq) 15064e9f8fe5SAdrian Hunter { 15074e9f8fe5SAdrian Hunter int i; 15084e9f8fe5SAdrian Hunter 15094e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 15104e9f8fe5SAdrian Hunter if (host->mrqs_done[i] == mrq) { 15114e9f8fe5SAdrian Hunter WARN_ON(1); 15124e9f8fe5SAdrian Hunter return; 15134e9f8fe5SAdrian Hunter } 15144e9f8fe5SAdrian Hunter } 15154e9f8fe5SAdrian Hunter 15164e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 15174e9f8fe5SAdrian Hunter if (!host->mrqs_done[i]) { 15184e9f8fe5SAdrian Hunter host->mrqs_done[i] = mrq; 15194e9f8fe5SAdrian Hunter break; 15204e9f8fe5SAdrian Hunter } 15214e9f8fe5SAdrian Hunter } 15224e9f8fe5SAdrian Hunter 15234e9f8fe5SAdrian Hunter WARN_ON(i >= SDHCI_MAX_MRQS); 152415db1836SFaiz Abbas } 152515db1836SFaiz Abbas 152615db1836SFaiz Abbas static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) 152715db1836SFaiz Abbas { 152815db1836SFaiz Abbas if (host->cmd && host->cmd->mrq == mrq) 152915db1836SFaiz Abbas host->cmd = NULL; 153015db1836SFaiz Abbas 153115db1836SFaiz Abbas if (host->data_cmd && host->data_cmd->mrq == mrq) 153215db1836SFaiz Abbas host->data_cmd = NULL; 153315db1836SFaiz Abbas 1534845c939eSAdrian Hunter if (host->deferred_cmd && host->deferred_cmd->mrq == mrq) 1535845c939eSAdrian Hunter host->deferred_cmd = NULL; 1536845c939eSAdrian Hunter 153715db1836SFaiz Abbas if (host->data && host->data->mrq == mrq) 153815db1836SFaiz Abbas host->data = NULL; 153915db1836SFaiz Abbas 154015db1836SFaiz Abbas if (sdhci_needs_reset(host, mrq)) 154115db1836SFaiz Abbas host->pending_reset = true; 154215db1836SFaiz Abbas 154315db1836SFaiz Abbas sdhci_set_mrq_done(host, mrq); 15444e9f8fe5SAdrian Hunter 1545e9a07299SAdrian Hunter sdhci_del_timer(host, mrq); 1546e9a07299SAdrian Hunter 1547e9a07299SAdrian Hunter if (!sdhci_has_requests(host)) 1548e9a07299SAdrian Hunter sdhci_led_deactivate(host); 15494e9f8fe5SAdrian Hunter } 15504e9f8fe5SAdrian Hunter 1551a6d3bdd5SAdrian Hunter static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) 1552a6d3bdd5SAdrian Hunter { 15534e9f8fe5SAdrian Hunter __sdhci_finish_mrq(host, mrq); 15542e72ab9bSAdrian Hunter 1555c07a48c2SAdrian Hunter queue_work(host->complete_wq, &host->complete_work); 1556a6d3bdd5SAdrian Hunter } 1557a6d3bdd5SAdrian Hunter 1558845c939eSAdrian Hunter static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) 15591c6a0718SPierre Ossman { 156033a57adbSAdrian Hunter struct mmc_command *data_cmd = host->data_cmd; 156133a57adbSAdrian Hunter struct mmc_data *data = host->data; 15621c6a0718SPierre Ossman 15631c6a0718SPierre Ossman host->data = NULL; 15647c89a3d9SAdrian Hunter host->data_cmd = NULL; 15651c6a0718SPierre Ossman 15664bf78099SAdrian Hunter /* 15674bf78099SAdrian Hunter * The controller needs a reset of internal state machines upon error 15684bf78099SAdrian Hunter * conditions. 15694bf78099SAdrian Hunter */ 15704bf78099SAdrian Hunter if (data->error) { 15714bf78099SAdrian Hunter if (!host->cmd || host->cmd == data_cmd) 15721e63d297SAdrian Hunter sdhci_reset_for(host, REQUEST_ERROR); 15731e63d297SAdrian Hunter else 15741e63d297SAdrian Hunter sdhci_reset_for(host, REQUEST_ERROR_DATA_ONLY); 15754bf78099SAdrian Hunter } 15764bf78099SAdrian Hunter 1577add8913dSRussell King if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) == 1578add8913dSRussell King (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) 15792134a922SPierre Ossman sdhci_adma_table_post(host, data); 1580f55c98f7SRussell King 15811c6a0718SPierre Ossman /* 1582c9b74c5bSPierre Ossman * The specification states that the block count register must 1583c9b74c5bSPierre Ossman * be updated, but it does not specify at what point in the 1584c9b74c5bSPierre Ossman * data flow. That makes the register entirely useless to read 1585c9b74c5bSPierre Ossman * back so we have to assume that nothing made it to the card 1586c9b74c5bSPierre Ossman * in the event of an error. 15871c6a0718SPierre Ossman */ 1588c9b74c5bSPierre Ossman if (data->error) 1589c9b74c5bSPierre Ossman data->bytes_xfered = 0; 15901c6a0718SPierre Ossman else 1591c9b74c5bSPierre Ossman data->bytes_xfered = data->blksz * data->blocks; 15921c6a0718SPierre Ossman 1593e89d456fSAndrei Warkentin /* 1594e89d456fSAndrei Warkentin * Need to send CMD12 if - 1595fdbbe6cfSYangbo Lu * a) open-ended multiblock transfer not using auto CMD12 (no CMD23) 1596e89d456fSAndrei Warkentin * b) error in multiblock transfer 1597e89d456fSAndrei Warkentin */ 1598e89d456fSAndrei Warkentin if (data->stop && 1599fdbbe6cfSYangbo Lu ((!data->mrq->sbc && !sdhci_auto_cmd12(host, data->mrq)) || 1600fdbbe6cfSYangbo Lu data->error)) { 160120845befSAdrian Hunter /* 160220845befSAdrian Hunter * 'cap_cmd_during_tfr' request must not use the command line 160320845befSAdrian Hunter * after mmc_command_done() has been called. It is upper layer's 160420845befSAdrian Hunter * responsibility to send the stop command if required. 160520845befSAdrian Hunter */ 160620845befSAdrian Hunter if (data->mrq->cap_cmd_during_tfr) { 160719d2f695SAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 160820845befSAdrian Hunter } else { 16098842fd17SAdrian Hunter /* Avoid triggering warning in sdhci_send_command() */ 16108842fd17SAdrian Hunter host->cmd = NULL; 1611845c939eSAdrian Hunter if (!sdhci_send_command(host, data->stop)) { 1612845c939eSAdrian Hunter if (sw_data_timeout) { 1613845c939eSAdrian Hunter /* 1614845c939eSAdrian Hunter * This is anyway a sw data timeout, so 1615845c939eSAdrian Hunter * give up now. 1616845c939eSAdrian Hunter */ 1617845c939eSAdrian Hunter data->stop->error = -EIO; 1618845c939eSAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 1619845c939eSAdrian Hunter } else { 1620845c939eSAdrian Hunter WARN_ON(host->deferred_cmd); 1621845c939eSAdrian Hunter host->deferred_cmd = data->stop; 1622845c939eSAdrian Hunter } 1623845c939eSAdrian Hunter } 162420845befSAdrian Hunter } 1625a6d3bdd5SAdrian Hunter } else { 162619d2f695SAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 1627a6d3bdd5SAdrian Hunter } 16281c6a0718SPierre Ossman } 16291c6a0718SPierre Ossman 1630845c939eSAdrian Hunter static void sdhci_finish_data(struct sdhci_host *host) 1631845c939eSAdrian Hunter { 1632845c939eSAdrian Hunter __sdhci_finish_data(host, false); 1633845c939eSAdrian Hunter } 1634845c939eSAdrian Hunter 1635845c939eSAdrian Hunter static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 16361c6a0718SPierre Ossman { 16371c6a0718SPierre Ossman int flags; 16381c6a0718SPierre Ossman u32 mask; 16391c6a0718SPierre Ossman unsigned long timeout; 16401c6a0718SPierre Ossman 16411c6a0718SPierre Ossman WARN_ON(host->cmd); 16421c6a0718SPierre Ossman 164396776200SRussell King /* Initially, a command has no error */ 164496776200SRussell King cmd->error = 0; 164596776200SRussell King 1646fc605f1dSAdrian Hunter if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && 1647fc605f1dSAdrian Hunter cmd->opcode == MMC_STOP_TRANSMISSION) 1648fc605f1dSAdrian Hunter cmd->flags |= MMC_RSP_BUSY; 1649fc605f1dSAdrian Hunter 16501c6a0718SPierre Ossman mask = SDHCI_CMD_INHIBIT; 165156a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) 16521c6a0718SPierre Ossman mask |= SDHCI_DATA_INHIBIT; 16531c6a0718SPierre Ossman 16541c6a0718SPierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 16551c6a0718SPierre Ossman though they might use busy signaling */ 1656a4c73abaSAdrian Hunter if (cmd->mrq->data && (cmd == cmd->mrq->data->stop)) 16571c6a0718SPierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 16581c6a0718SPierre Ossman 1659845c939eSAdrian Hunter if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) 1660845c939eSAdrian Hunter return false; 16611c6a0718SPierre Ossman 16621c6a0718SPierre Ossman host->cmd = cmd; 166315db1836SFaiz Abbas host->data_timeout = 0; 166456a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) { 16657c89a3d9SAdrian Hunter WARN_ON(host->data_cmd); 16667c89a3d9SAdrian Hunter host->data_cmd = cmd; 166715db1836SFaiz Abbas sdhci_set_timeout(host, cmd); 16687c89a3d9SAdrian Hunter } 16691c6a0718SPierre Ossman 167018e762e3SChunyan Zhang if (cmd->data) { 167118e762e3SChunyan Zhang if (host->use_external_dma) 167218e762e3SChunyan Zhang sdhci_external_dma_prepare_data(host, cmd); 167318e762e3SChunyan Zhang else 1674a3c7778fSAndrei Warkentin sdhci_prepare_data(host, cmd); 167518e762e3SChunyan Zhang } 16761c6a0718SPierre Ossman 16774e4141a5SAnton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); 16781c6a0718SPierre Ossman 1679e89d456fSAndrei Warkentin sdhci_set_transfer_mode(host, cmd); 16801c6a0718SPierre Ossman 16811c6a0718SPierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 1682845c939eSAdrian Hunter WARN_ONCE(1, "Unsupported response type!\n"); 1683845c939eSAdrian Hunter /* 1684845c939eSAdrian Hunter * This does not happen in practice because 136-bit response 1685845c939eSAdrian Hunter * commands never have busy waiting, so rather than complicate 1686845c939eSAdrian Hunter * the error path, just remove busy waiting and continue. 1687845c939eSAdrian Hunter */ 1688845c939eSAdrian Hunter cmd->flags &= ~MMC_RSP_BUSY; 16891c6a0718SPierre Ossman } 16901c6a0718SPierre Ossman 16911c6a0718SPierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 16921c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_NONE; 16931c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_136) 16941c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_LONG; 16951c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 16961c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 16971c6a0718SPierre Ossman else 16981c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT; 16991c6a0718SPierre Ossman 17001c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_CRC) 17011c6a0718SPierre Ossman flags |= SDHCI_CMD_CRC; 17021c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 17031c6a0718SPierre Ossman flags |= SDHCI_CMD_INDEX; 1704b513ea25SArindam Nath 1705b513ea25SArindam Nath /* CMD19 is special in that the Data Present Select should be set */ 1706069c9f14SGirish K S if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK || 1707069c9f14SGirish K S cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) 17081c6a0718SPierre Ossman flags |= SDHCI_CMD_DATA; 17091c6a0718SPierre Ossman 1710fc1fa1b7SKishon Vijay Abraham I timeout = jiffies; 1711fc1fa1b7SKishon Vijay Abraham I if (host->data_timeout) 1712fc1fa1b7SKishon Vijay Abraham I timeout += nsecs_to_jiffies(host->data_timeout); 1713fc1fa1b7SKishon Vijay Abraham I else if (!cmd->data && cmd->busy_timeout > 9000) 1714fc1fa1b7SKishon Vijay Abraham I timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; 1715fc1fa1b7SKishon Vijay Abraham I else 1716fc1fa1b7SKishon Vijay Abraham I timeout += 10 * HZ; 1717fc1fa1b7SKishon Vijay Abraham I sdhci_mod_timer(host, cmd->mrq, timeout); 1718fc1fa1b7SKishon Vijay Abraham I 171918e762e3SChunyan Zhang if (host->use_external_dma) 172018e762e3SChunyan Zhang sdhci_external_dma_pre_transfer(host, cmd); 172118e762e3SChunyan Zhang 17224e4141a5SAnton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 1723845c939eSAdrian Hunter 1724845c939eSAdrian Hunter return true; 17251c6a0718SPierre Ossman } 17261c6a0718SPierre Ossman 1727e872f1e2SAdrian Hunter static bool sdhci_present_error(struct sdhci_host *host, 1728e872f1e2SAdrian Hunter struct mmc_command *cmd, bool present) 1729e872f1e2SAdrian Hunter { 1730e872f1e2SAdrian Hunter if (!present || host->flags & SDHCI_DEVICE_DEAD) { 1731e872f1e2SAdrian Hunter cmd->error = -ENOMEDIUM; 1732e872f1e2SAdrian Hunter return true; 1733e872f1e2SAdrian Hunter } 1734e872f1e2SAdrian Hunter 1735e872f1e2SAdrian Hunter return false; 1736e872f1e2SAdrian Hunter } 1737e872f1e2SAdrian Hunter 1738845c939eSAdrian Hunter static bool sdhci_send_command_retry(struct sdhci_host *host, 1739845c939eSAdrian Hunter struct mmc_command *cmd, 1740845c939eSAdrian Hunter unsigned long flags) 1741845c939eSAdrian Hunter __releases(host->lock) 1742845c939eSAdrian Hunter __acquires(host->lock) 1743845c939eSAdrian Hunter { 1744845c939eSAdrian Hunter struct mmc_command *deferred_cmd = host->deferred_cmd; 1745845c939eSAdrian Hunter int timeout = 10; /* Approx. 10 ms */ 1746845c939eSAdrian Hunter bool present; 1747845c939eSAdrian Hunter 1748845c939eSAdrian Hunter while (!sdhci_send_command(host, cmd)) { 1749845c939eSAdrian Hunter if (!timeout--) { 1750845c939eSAdrian Hunter pr_err("%s: Controller never released inhibit bit(s).\n", 1751845c939eSAdrian Hunter mmc_hostname(host->mmc)); 1752efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT); 1753845c939eSAdrian Hunter sdhci_dumpregs(host); 1754845c939eSAdrian Hunter cmd->error = -EIO; 1755845c939eSAdrian Hunter return false; 1756845c939eSAdrian Hunter } 1757845c939eSAdrian Hunter 1758845c939eSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 1759845c939eSAdrian Hunter 1760845c939eSAdrian Hunter usleep_range(1000, 1250); 1761845c939eSAdrian Hunter 1762845c939eSAdrian Hunter present = host->mmc->ops->get_cd(host->mmc); 1763845c939eSAdrian Hunter 1764845c939eSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 1765845c939eSAdrian Hunter 1766845c939eSAdrian Hunter /* A deferred command might disappear, handle that */ 1767845c939eSAdrian Hunter if (cmd == deferred_cmd && cmd != host->deferred_cmd) 1768845c939eSAdrian Hunter return true; 1769845c939eSAdrian Hunter 1770845c939eSAdrian Hunter if (sdhci_present_error(host, cmd, present)) 1771845c939eSAdrian Hunter return false; 1772845c939eSAdrian Hunter } 1773845c939eSAdrian Hunter 1774845c939eSAdrian Hunter if (cmd == host->deferred_cmd) 1775845c939eSAdrian Hunter host->deferred_cmd = NULL; 1776845c939eSAdrian Hunter 1777845c939eSAdrian Hunter return true; 1778845c939eSAdrian Hunter } 1779845c939eSAdrian Hunter 17804a5fc119SAdrian Hunter static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) 17814a5fc119SAdrian Hunter { 17824a5fc119SAdrian Hunter int i, reg; 17834a5fc119SAdrian Hunter 17844a5fc119SAdrian Hunter for (i = 0; i < 4; i++) { 17854a5fc119SAdrian Hunter reg = SDHCI_RESPONSE + (3 - i) * 4; 17864a5fc119SAdrian Hunter cmd->resp[i] = sdhci_readl(host, reg); 17874a5fc119SAdrian Hunter } 17884a5fc119SAdrian Hunter 17891284c248SKishon Vijay Abraham I if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC) 17901284c248SKishon Vijay Abraham I return; 17911284c248SKishon Vijay Abraham I 17924a5fc119SAdrian Hunter /* CRC is stripped so we need to do some shifting */ 17934a5fc119SAdrian Hunter for (i = 0; i < 4; i++) { 17944a5fc119SAdrian Hunter cmd->resp[i] <<= 8; 17954a5fc119SAdrian Hunter if (i != 3) 17964a5fc119SAdrian Hunter cmd->resp[i] |= cmd->resp[i + 1] >> 24; 17974a5fc119SAdrian Hunter } 17984a5fc119SAdrian Hunter } 17994a5fc119SAdrian Hunter 18001c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *host) 18011c6a0718SPierre Ossman { 1802e0a5640aSAdrian Hunter struct mmc_command *cmd = host->cmd; 18031c6a0718SPierre Ossman 1804e0a5640aSAdrian Hunter host->cmd = NULL; 1805e0a5640aSAdrian Hunter 1806e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_PRESENT) { 1807e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_136) { 18084a5fc119SAdrian Hunter sdhci_read_rsp_136(host, cmd); 18091c6a0718SPierre Ossman } else { 1810e0a5640aSAdrian Hunter cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); 18111c6a0718SPierre Ossman } 18121c6a0718SPierre Ossman } 18131c6a0718SPierre Ossman 181420845befSAdrian Hunter if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd) 181520845befSAdrian Hunter mmc_command_done(host->mmc, cmd->mrq); 181620845befSAdrian Hunter 18176bde8681SAdrian Hunter /* 18186bde8681SAdrian Hunter * The host can send and interrupt when the busy state has 18196bde8681SAdrian Hunter * ended, allowing us to wait without wasting CPU cycles. 18206bde8681SAdrian Hunter * The busy signal uses DAT0 so this is similar to waiting 18216bde8681SAdrian Hunter * for data to complete. 18226bde8681SAdrian Hunter * 18236bde8681SAdrian Hunter * Note: The 1.0 specification is a bit ambiguous about this 18246bde8681SAdrian Hunter * feature so there might be some problems with older 18256bde8681SAdrian Hunter * controllers. 18266bde8681SAdrian Hunter */ 1827e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_BUSY) { 1828e0a5640aSAdrian Hunter if (cmd->data) { 18296bde8681SAdrian Hunter DBG("Cannot wait for busy signal when also doing a data transfer"); 18306bde8681SAdrian Hunter } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && 1831ea968023SAdrian Hunter cmd == host->data_cmd) { 1832ea968023SAdrian Hunter /* Command complete before busy is ended */ 18336bde8681SAdrian Hunter return; 18346bde8681SAdrian Hunter } 18356bde8681SAdrian Hunter } 18366bde8681SAdrian Hunter 1837e89d456fSAndrei Warkentin /* Finished CMD23, now send actual command. */ 1838a4c73abaSAdrian Hunter if (cmd == cmd->mrq->sbc) { 1839845c939eSAdrian Hunter if (!sdhci_send_command(host, cmd->mrq->cmd)) { 1840845c939eSAdrian Hunter WARN_ON(host->deferred_cmd); 1841845c939eSAdrian Hunter host->deferred_cmd = cmd->mrq->cmd; 1842845c939eSAdrian Hunter } 1843e89d456fSAndrei Warkentin } else { 1844e89d456fSAndrei Warkentin 1845e89d456fSAndrei Warkentin /* Processed actual command. */ 1846e538fbe8SPierre Ossman if (host->data && host->data_early) 1847e538fbe8SPierre Ossman sdhci_finish_data(host); 1848e538fbe8SPierre Ossman 1849e0a5640aSAdrian Hunter if (!cmd->data) 185019d2f695SAdrian Hunter __sdhci_finish_mrq(host, cmd->mrq); 18511c6a0718SPierre Ossman } 1852e89d456fSAndrei Warkentin } 18531c6a0718SPierre Ossman 185452983382SKevin Liu static u16 sdhci_get_preset_value(struct sdhci_host *host) 185552983382SKevin Liu { 1856d975f121SRussell King u16 preset = 0; 185752983382SKevin Liu 1858d975f121SRussell King switch (host->timing) { 1859d0244847SAl Cooper case MMC_TIMING_MMC_HS: 1860d0244847SAl Cooper case MMC_TIMING_SD_HS: 1861d0244847SAl Cooper preset = sdhci_readw(host, SDHCI_PRESET_FOR_HIGH_SPEED); 1862d0244847SAl Cooper break; 1863d975f121SRussell King case MMC_TIMING_UHS_SDR12: 186452983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); 186552983382SKevin Liu break; 1866d975f121SRussell King case MMC_TIMING_UHS_SDR25: 186752983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25); 186852983382SKevin Liu break; 1869d975f121SRussell King case MMC_TIMING_UHS_SDR50: 187052983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50); 187152983382SKevin Liu break; 1872d975f121SRussell King case MMC_TIMING_UHS_SDR104: 1873d975f121SRussell King case MMC_TIMING_MMC_HS200: 187452983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104); 187552983382SKevin Liu break; 1876d975f121SRussell King case MMC_TIMING_UHS_DDR50: 18770dafa60eSJisheng Zhang case MMC_TIMING_MMC_DDR52: 187852983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50); 187952983382SKevin Liu break; 1880e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400: 1881e9fb05d5SAdrian Hunter preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400); 1882e9fb05d5SAdrian Hunter break; 188352983382SKevin Liu default: 188452983382SKevin Liu pr_warn("%s: Invalid UHS-I mode selected\n", 188552983382SKevin Liu mmc_hostname(host->mmc)); 188652983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); 188752983382SKevin Liu break; 188852983382SKevin Liu } 188952983382SKevin Liu return preset; 189052983382SKevin Liu } 189152983382SKevin Liu 1892fb9ee047SLudovic Desroches u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, 1893fb9ee047SLudovic Desroches unsigned int *actual_clock) 18941c6a0718SPierre Ossman { 1895c3ed3877SArindam Nath int div = 0; /* Initialized for compiler warning */ 1896df16219fSGiuseppe CAVALLARO int real_div = div, clk_mul = 1; 1897c3ed3877SArindam Nath u16 clk = 0; 18985497159cSludovic.desroches@atmel.com bool switch_base_clk = false; 18991c6a0718SPierre Ossman 190085105c53SZhangfei Gao if (host->version >= SDHCI_SPEC_300) { 1901da91a8f9SRussell King if (host->preset_enabled) { 190252983382SKevin Liu u16 pre_val; 190352983382SKevin Liu 190452983382SKevin Liu clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 190552983382SKevin Liu pre_val = sdhci_get_preset_value(host); 1906fa091010SMasahiro Yamada div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val); 190752983382SKevin Liu if (host->clk_mul && 1908fa091010SMasahiro Yamada (pre_val & SDHCI_PRESET_CLKGEN_SEL)) { 190952983382SKevin Liu clk = SDHCI_PROG_CLOCK_MODE; 191052983382SKevin Liu real_div = div + 1; 191152983382SKevin Liu clk_mul = host->clk_mul; 191252983382SKevin Liu } else { 191352983382SKevin Liu real_div = max_t(int, 1, div << 1); 191452983382SKevin Liu } 191552983382SKevin Liu goto clock_set; 191652983382SKevin Liu } 191752983382SKevin Liu 1918c3ed3877SArindam Nath /* 1919c3ed3877SArindam Nath * Check if the Host Controller supports Programmable Clock 1920c3ed3877SArindam Nath * Mode. 1921c3ed3877SArindam Nath */ 1922c3ed3877SArindam Nath if (host->clk_mul) { 1923c3ed3877SArindam Nath for (div = 1; div <= 1024; div++) { 192452983382SKevin Liu if ((host->max_clk * host->clk_mul / div) 192552983382SKevin Liu <= clock) 1926c3ed3877SArindam Nath break; 1927c3ed3877SArindam Nath } 19285497159cSludovic.desroches@atmel.com if ((host->max_clk * host->clk_mul / div) <= clock) { 1929c3ed3877SArindam Nath /* 1930c3ed3877SArindam Nath * Set Programmable Clock Mode in the Clock 1931c3ed3877SArindam Nath * Control register. 1932c3ed3877SArindam Nath */ 1933c3ed3877SArindam Nath clk = SDHCI_PROG_CLOCK_MODE; 1934df16219fSGiuseppe CAVALLARO real_div = div; 1935df16219fSGiuseppe CAVALLARO clk_mul = host->clk_mul; 1936c3ed3877SArindam Nath div--; 1937c3ed3877SArindam Nath } else { 19385497159cSludovic.desroches@atmel.com /* 19395497159cSludovic.desroches@atmel.com * Divisor can be too small to reach clock 19405497159cSludovic.desroches@atmel.com * speed requirement. Then use the base clock. 19415497159cSludovic.desroches@atmel.com */ 19425497159cSludovic.desroches@atmel.com switch_base_clk = true; 19435497159cSludovic.desroches@atmel.com } 19445497159cSludovic.desroches@atmel.com } 19455497159cSludovic.desroches@atmel.com 19465497159cSludovic.desroches@atmel.com if (!host->clk_mul || switch_base_clk) { 194785105c53SZhangfei Gao /* Version 3.00 divisors must be a multiple of 2. */ 194885105c53SZhangfei Gao if (host->max_clk <= clock) 194985105c53SZhangfei Gao div = 1; 195085105c53SZhangfei Gao else { 1951c3ed3877SArindam Nath for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; 1952c3ed3877SArindam Nath div += 2) { 195385105c53SZhangfei Gao if ((host->max_clk / div) <= clock) 195485105c53SZhangfei Gao break; 195585105c53SZhangfei Gao } 195685105c53SZhangfei Gao } 1957df16219fSGiuseppe CAVALLARO real_div = div; 1958c3ed3877SArindam Nath div >>= 1; 1959d1955c3aSSuneel Garapati if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN) 1960d1955c3aSSuneel Garapati && !div && host->max_clk <= 25000000) 1961d1955c3aSSuneel Garapati div = 1; 1962c3ed3877SArindam Nath } 196385105c53SZhangfei Gao } else { 196485105c53SZhangfei Gao /* Version 2.00 divisors must be a power of 2. */ 19650397526dSZhangfei Gao for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { 19661c6a0718SPierre Ossman if ((host->max_clk / div) <= clock) 19671c6a0718SPierre Ossman break; 19681c6a0718SPierre Ossman } 1969df16219fSGiuseppe CAVALLARO real_div = div; 19701c6a0718SPierre Ossman div >>= 1; 1971c3ed3877SArindam Nath } 19721c6a0718SPierre Ossman 197352983382SKevin Liu clock_set: 197403d6f5ffSAisheng Dong if (real_div) 1975fb9ee047SLudovic Desroches *actual_clock = (host->max_clk * clk_mul) / real_div; 1976c3ed3877SArindam Nath clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 197785105c53SZhangfei Gao clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 197885105c53SZhangfei Gao << SDHCI_DIVIDER_HI_SHIFT; 1979fb9ee047SLudovic Desroches 1980fb9ee047SLudovic Desroches return clk; 1981fb9ee047SLudovic Desroches } 1982fb9ee047SLudovic Desroches EXPORT_SYMBOL_GPL(sdhci_calc_clk); 1983fb9ee047SLudovic Desroches 1984fec79673SRitesh Harjani void sdhci_enable_clk(struct sdhci_host *host, u16 clk) 1985fb9ee047SLudovic Desroches { 19865a436cc0SAdrian Hunter ktime_t timeout; 1987fb9ee047SLudovic Desroches 19881c6a0718SPierre Ossman clk |= SDHCI_CLOCK_INT_EN; 19894e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 19901c6a0718SPierre Ossman 19914a9e0d1aSBen Chuang /* Wait max 150 ms */ 19924a9e0d1aSBen Chuang timeout = ktime_add_ms(ktime_get(), 150); 1993b704441eSAlek Du while (1) { 1994b704441eSAlek Du bool timedout = ktime_after(ktime_get(), timeout); 1995b704441eSAlek Du 1996b704441eSAlek Du clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1997b704441eSAlek Du if (clk & SDHCI_CLOCK_INT_STABLE) 1998b704441eSAlek Du break; 1999b704441eSAlek Du if (timedout) { 20002e4456f0SMarek Vasut pr_err("%s: Internal clock never stabilised.\n", 20012e4456f0SMarek Vasut mmc_hostname(host->mmc)); 2002efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT); 20031c6a0718SPierre Ossman sdhci_dumpregs(host); 20041c6a0718SPierre Ossman return; 20051c6a0718SPierre Ossman } 20065a436cc0SAdrian Hunter udelay(10); 20071c6a0718SPierre Ossman } 20081c6a0718SPierre Ossman 20091beabbdbSBen Chuang if (host->version >= SDHCI_SPEC_410 && host->v4_mode) { 20101beabbdbSBen Chuang clk |= SDHCI_CLOCK_PLL_EN; 20111beabbdbSBen Chuang clk &= ~SDHCI_CLOCK_INT_STABLE; 20121beabbdbSBen Chuang sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 20131beabbdbSBen Chuang 20141beabbdbSBen Chuang /* Wait max 150 ms */ 20151beabbdbSBen Chuang timeout = ktime_add_ms(ktime_get(), 150); 20161beabbdbSBen Chuang while (1) { 20171beabbdbSBen Chuang bool timedout = ktime_after(ktime_get(), timeout); 20181beabbdbSBen Chuang 20191beabbdbSBen Chuang clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 20201beabbdbSBen Chuang if (clk & SDHCI_CLOCK_INT_STABLE) 20211beabbdbSBen Chuang break; 20221beabbdbSBen Chuang if (timedout) { 20231beabbdbSBen Chuang pr_err("%s: PLL clock never stabilised.\n", 20241beabbdbSBen Chuang mmc_hostname(host->mmc)); 2025efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT); 20261beabbdbSBen Chuang sdhci_dumpregs(host); 20271beabbdbSBen Chuang return; 20281beabbdbSBen Chuang } 20291beabbdbSBen Chuang udelay(10); 20301beabbdbSBen Chuang } 20311beabbdbSBen Chuang } 20321beabbdbSBen Chuang 20331c6a0718SPierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 20344e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 20351c6a0718SPierre Ossman } 2036fec79673SRitesh Harjani EXPORT_SYMBOL_GPL(sdhci_enable_clk); 2037fec79673SRitesh Harjani 2038fec79673SRitesh Harjani void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 2039fec79673SRitesh Harjani { 2040fec79673SRitesh Harjani u16 clk; 2041fec79673SRitesh Harjani 2042fec79673SRitesh Harjani host->mmc->actual_clock = 0; 2043fec79673SRitesh Harjani 2044fec79673SRitesh Harjani sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 2045fec79673SRitesh Harjani 2046fec79673SRitesh Harjani if (clock == 0) 2047fec79673SRitesh Harjani return; 2048fec79673SRitesh Harjani 2049fec79673SRitesh Harjani clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 2050fec79673SRitesh Harjani sdhci_enable_clk(host, clk); 2051fec79673SRitesh Harjani } 20521771059cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_clock); 20531c6a0718SPierre Ossman 20541dceb041SAdrian Hunter static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, 205524fbb3caSRussell King unsigned short vdd) 20561c6a0718SPierre Ossman { 20573a48edc4STim Kryger struct mmc_host *mmc = host->mmc; 20581dceb041SAdrian Hunter 20591dceb041SAdrian Hunter mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); 20601dceb041SAdrian Hunter 20611dceb041SAdrian Hunter if (mode != MMC_POWER_OFF) 20621dceb041SAdrian Hunter sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL); 20631dceb041SAdrian Hunter else 20641dceb041SAdrian Hunter sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 20651dceb041SAdrian Hunter } 20661dceb041SAdrian Hunter 2067606d3131SAdrian Hunter void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, 20681dceb041SAdrian Hunter unsigned short vdd) 20691dceb041SAdrian Hunter { 20708364248aSGiuseppe Cavallaro u8 pwr = 0; 20711c6a0718SPierre Ossman 207224fbb3caSRussell King if (mode != MMC_POWER_OFF) { 207324fbb3caSRussell King switch (1 << vdd) { 2074ae628903SPierre Ossman case MMC_VDD_165_195: 20752a609abeSAndy Shevchenko /* 20762a609abeSAndy Shevchenko * Without a regulator, SDHCI does not support 2.0v 20772a609abeSAndy Shevchenko * so we only get here if the driver deliberately 20782a609abeSAndy Shevchenko * added the 2.0v range to ocr_avail. Map it to 1.8v 20792a609abeSAndy Shevchenko * for the purpose of turning on the power. 20802a609abeSAndy Shevchenko */ 20812a609abeSAndy Shevchenko case MMC_VDD_20_21: 2082ae628903SPierre Ossman pwr = SDHCI_POWER_180; 2083ae628903SPierre Ossman break; 2084ae628903SPierre Ossman case MMC_VDD_29_30: 2085ae628903SPierre Ossman case MMC_VDD_30_31: 2086ae628903SPierre Ossman pwr = SDHCI_POWER_300; 2087ae628903SPierre Ossman break; 2088ae628903SPierre Ossman case MMC_VDD_32_33: 2089ae628903SPierre Ossman case MMC_VDD_33_34: 20904217d07bSShawn Guo /* 20914217d07bSShawn Guo * 3.4 ~ 3.6V are valid only for those platforms where it's 20924217d07bSShawn Guo * known that the voltage range is supported by hardware. 20934217d07bSShawn Guo */ 20944217d07bSShawn Guo case MMC_VDD_34_35: 20954217d07bSShawn Guo case MMC_VDD_35_36: 2096ae628903SPierre Ossman pwr = SDHCI_POWER_330; 2097ae628903SPierre Ossman break; 2098ae628903SPierre Ossman default: 20999d5de93fSAdrian Hunter WARN(1, "%s: Invalid vdd %#x\n", 21009d5de93fSAdrian Hunter mmc_hostname(host->mmc), vdd); 21019d5de93fSAdrian Hunter break; 2102ae628903SPierre Ossman } 2103ae628903SPierre Ossman } 2104ae628903SPierre Ossman 2105ae628903SPierre Ossman if (host->pwr == pwr) 2106e921a8b6SRussell King return; 21071c6a0718SPierre Ossman 2108ae628903SPierre Ossman host->pwr = pwr; 2109ae628903SPierre Ossman 2110ae628903SPierre Ossman if (pwr == 0) { 21114e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 2112f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 2113f0710a55SAdrian Hunter sdhci_runtime_pm_bus_off(host); 2114e921a8b6SRussell King } else { 21151c6a0718SPierre Ossman /* 21161c6a0718SPierre Ossman * Spec says that we should clear the power reg before setting 21171c6a0718SPierre Ossman * a new value. Some controllers don't seem to like this though. 21181c6a0718SPierre Ossman */ 2119b8c86fc5SPierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 21204e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 21211c6a0718SPierre Ossman 2122e08c1694SAndres Salomon /* 2123e921a8b6SRussell King * At least the Marvell CaFe chip gets confused if we set the 2124e921a8b6SRussell King * voltage and set turn on power at the same time, so set the 2125e921a8b6SRussell King * voltage first. 2126e08c1694SAndres Salomon */ 212711a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) 21284e4141a5SAnton Vorontsov sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 21291c6a0718SPierre Ossman 2130ae628903SPierre Ossman pwr |= SDHCI_POWER_ON; 2131ae628903SPierre Ossman 2132ae628903SPierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 2133557b0697SHarald Welte 2134f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 2135f0710a55SAdrian Hunter sdhci_runtime_pm_bus_on(host); 2136f0710a55SAdrian Hunter 2137557b0697SHarald Welte /* 2138e921a8b6SRussell King * Some controllers need an extra 10ms delay of 10ms before 2139e921a8b6SRussell King * they can apply clock after applying power 2140557b0697SHarald Welte */ 214111a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) 2142557b0697SHarald Welte mdelay(10); 2143e921a8b6SRussell King } 2144918f4cbdSJisheng Zhang } 2145606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power_noreg); 21461dceb041SAdrian Hunter 2147606d3131SAdrian Hunter void sdhci_set_power(struct sdhci_host *host, unsigned char mode, 21481dceb041SAdrian Hunter unsigned short vdd) 21491dceb041SAdrian Hunter { 2150606d3131SAdrian Hunter if (IS_ERR(host->mmc->supply.vmmc)) 2151606d3131SAdrian Hunter sdhci_set_power_noreg(host, mode, vdd); 21521dceb041SAdrian Hunter else 2153606d3131SAdrian Hunter sdhci_set_power_reg(host, mode, vdd); 21541c6a0718SPierre Ossman } 2155606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power); 21561c6a0718SPierre Ossman 21576c92ae1eSNicolas Saenz Julienne /* 21586c92ae1eSNicolas Saenz Julienne * Some controllers need to configure a valid bus voltage on their power 21596c92ae1eSNicolas Saenz Julienne * register regardless of whether an external regulator is taking care of power 21606c92ae1eSNicolas Saenz Julienne * supply. This helper function takes care of it if set as the controller's 21616c92ae1eSNicolas Saenz Julienne * sdhci_ops.set_power callback. 21626c92ae1eSNicolas Saenz Julienne */ 21636c92ae1eSNicolas Saenz Julienne void sdhci_set_power_and_bus_voltage(struct sdhci_host *host, 21646c92ae1eSNicolas Saenz Julienne unsigned char mode, 21656c92ae1eSNicolas Saenz Julienne unsigned short vdd) 21666c92ae1eSNicolas Saenz Julienne { 21676c92ae1eSNicolas Saenz Julienne if (!IS_ERR(host->mmc->supply.vmmc)) { 21686c92ae1eSNicolas Saenz Julienne struct mmc_host *mmc = host->mmc; 21696c92ae1eSNicolas Saenz Julienne 21706c92ae1eSNicolas Saenz Julienne mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); 21716c92ae1eSNicolas Saenz Julienne } 21726c92ae1eSNicolas Saenz Julienne sdhci_set_power_noreg(host, mode, vdd); 21736c92ae1eSNicolas Saenz Julienne } 21746c92ae1eSNicolas Saenz Julienne EXPORT_SYMBOL_GPL(sdhci_set_power_and_bus_voltage); 21756c92ae1eSNicolas Saenz Julienne 21761c6a0718SPierre Ossman /*****************************************************************************\ 21771c6a0718SPierre Ossman * * 21781c6a0718SPierre Ossman * MMC callbacks * 21791c6a0718SPierre Ossman * * 21801c6a0718SPierre Ossman \*****************************************************************************/ 21811c6a0718SPierre Ossman 2182d462c1b4SAapo Vienamo void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 21831c6a0718SPierre Ossman { 2184e872f1e2SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2185e872f1e2SAdrian Hunter struct mmc_command *cmd; 21861c6a0718SPierre Ossman unsigned long flags; 2187e872f1e2SAdrian Hunter bool present; 21881c6a0718SPierre Ossman 218904e079cfSScott Branden /* Firstly check card presence */ 21908d28b7a7SAdrian Hunter present = mmc->ops->get_cd(mmc); 21912836766aSKrzysztof Kozlowski 21921c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 21931c6a0718SPierre Ossman 2194061d17a6SAdrian Hunter sdhci_led_activate(host); 2195e89d456fSAndrei Warkentin 2196e872f1e2SAdrian Hunter if (sdhci_present_error(host, mrq->cmd, present)) 2197e872f1e2SAdrian Hunter goto out_finish; 21981c6a0718SPierre Ossman 2199e872f1e2SAdrian Hunter cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; 2200e872f1e2SAdrian Hunter 2201845c939eSAdrian Hunter if (!sdhci_send_command_retry(host, cmd, flags)) 2202845c939eSAdrian Hunter goto out_finish; 2203e872f1e2SAdrian Hunter 2204e872f1e2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2205e872f1e2SAdrian Hunter 2206e872f1e2SAdrian Hunter return; 2207e872f1e2SAdrian Hunter 2208e872f1e2SAdrian Hunter out_finish: 2209e872f1e2SAdrian Hunter sdhci_finish_mrq(host, mrq); 22101c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 22111c6a0718SPierre Ossman } 2212d462c1b4SAapo Vienamo EXPORT_SYMBOL_GPL(sdhci_request); 22131c6a0718SPierre Ossman 221448ef8a2aSBaolin Wang int sdhci_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq) 221548ef8a2aSBaolin Wang { 221648ef8a2aSBaolin Wang struct sdhci_host *host = mmc_priv(mmc); 221748ef8a2aSBaolin Wang struct mmc_command *cmd; 221848ef8a2aSBaolin Wang unsigned long flags; 221948ef8a2aSBaolin Wang int ret = 0; 222048ef8a2aSBaolin Wang 222148ef8a2aSBaolin Wang spin_lock_irqsave(&host->lock, flags); 222248ef8a2aSBaolin Wang 222348ef8a2aSBaolin Wang if (sdhci_present_error(host, mrq->cmd, true)) { 222448ef8a2aSBaolin Wang sdhci_finish_mrq(host, mrq); 222548ef8a2aSBaolin Wang goto out_finish; 222648ef8a2aSBaolin Wang } 222748ef8a2aSBaolin Wang 222848ef8a2aSBaolin Wang cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; 222948ef8a2aSBaolin Wang 223048ef8a2aSBaolin Wang /* 223148ef8a2aSBaolin Wang * The HSQ may send a command in interrupt context without polling 223248ef8a2aSBaolin Wang * the busy signaling, which means we should return BUSY if controller 223348ef8a2aSBaolin Wang * has not released inhibit bits to allow HSQ trying to send request 223448ef8a2aSBaolin Wang * again in non-atomic context. So we should not finish this request 223548ef8a2aSBaolin Wang * here. 223648ef8a2aSBaolin Wang */ 223748ef8a2aSBaolin Wang if (!sdhci_send_command(host, cmd)) 223848ef8a2aSBaolin Wang ret = -EBUSY; 223948ef8a2aSBaolin Wang else 224048ef8a2aSBaolin Wang sdhci_led_activate(host); 224148ef8a2aSBaolin Wang 224248ef8a2aSBaolin Wang out_finish: 224348ef8a2aSBaolin Wang spin_unlock_irqrestore(&host->lock, flags); 224448ef8a2aSBaolin Wang return ret; 224548ef8a2aSBaolin Wang } 224648ef8a2aSBaolin Wang EXPORT_SYMBOL_GPL(sdhci_request_atomic); 224748ef8a2aSBaolin Wang 22482317f56cSRussell King void sdhci_set_bus_width(struct sdhci_host *host, int width) 22492317f56cSRussell King { 22502317f56cSRussell King u8 ctrl; 22512317f56cSRussell King 22522317f56cSRussell King ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 22532317f56cSRussell King if (width == MMC_BUS_WIDTH_8) { 22542317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS; 22552317f56cSRussell King ctrl |= SDHCI_CTRL_8BITBUS; 22562317f56cSRussell King } else { 225798f94ea6SMichał Mirosław if (host->mmc->caps & MMC_CAP_8_BIT_DATA) 22582317f56cSRussell King ctrl &= ~SDHCI_CTRL_8BITBUS; 22592317f56cSRussell King if (width == MMC_BUS_WIDTH_4) 22602317f56cSRussell King ctrl |= SDHCI_CTRL_4BITBUS; 22612317f56cSRussell King else 22622317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS; 22632317f56cSRussell King } 22642317f56cSRussell King sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 22652317f56cSRussell King } 22662317f56cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_bus_width); 22672317f56cSRussell King 226896d7b78cSRussell King void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) 226996d7b78cSRussell King { 227096d7b78cSRussell King u16 ctrl_2; 227196d7b78cSRussell King 227296d7b78cSRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 227396d7b78cSRussell King /* Select Bus Speed Mode for host */ 227496d7b78cSRussell King ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 227596d7b78cSRussell King if ((timing == MMC_TIMING_MMC_HS200) || 227696d7b78cSRussell King (timing == MMC_TIMING_UHS_SDR104)) 227796d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR104; 227896d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR12) 227996d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR12; 228007bcc411SFaiz Abbas else if (timing == MMC_TIMING_UHS_SDR25) 228196d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 228296d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR50) 228396d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR50; 228496d7b78cSRussell King else if ((timing == MMC_TIMING_UHS_DDR50) || 228596d7b78cSRussell King (timing == MMC_TIMING_MMC_DDR52)) 228696d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_DDR50; 2287e9fb05d5SAdrian Hunter else if (timing == MMC_TIMING_MMC_HS400) 2288e9fb05d5SAdrian Hunter ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */ 228996d7b78cSRussell King sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 229096d7b78cSRussell King } 229196d7b78cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); 229296d7b78cSRussell King 2293c981cdfbSAdrian Hunter static bool sdhci_timing_has_preset(unsigned char timing) 2294c981cdfbSAdrian Hunter { 2295c981cdfbSAdrian Hunter switch (timing) { 2296c981cdfbSAdrian Hunter case MMC_TIMING_UHS_SDR12: 2297c981cdfbSAdrian Hunter case MMC_TIMING_UHS_SDR25: 2298c981cdfbSAdrian Hunter case MMC_TIMING_UHS_SDR50: 2299c981cdfbSAdrian Hunter case MMC_TIMING_UHS_SDR104: 2300c981cdfbSAdrian Hunter case MMC_TIMING_UHS_DDR50: 2301c981cdfbSAdrian Hunter case MMC_TIMING_MMC_DDR52: 2302c981cdfbSAdrian Hunter return true; 2303c981cdfbSAdrian Hunter }; 2304c981cdfbSAdrian Hunter return false; 2305c981cdfbSAdrian Hunter } 2306c981cdfbSAdrian Hunter 2307c981cdfbSAdrian Hunter static bool sdhci_preset_needed(struct sdhci_host *host, unsigned char timing) 2308c981cdfbSAdrian Hunter { 2309c981cdfbSAdrian Hunter return !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && 2310c981cdfbSAdrian Hunter sdhci_timing_has_preset(timing); 2311c981cdfbSAdrian Hunter } 2312c981cdfbSAdrian Hunter 2313c981cdfbSAdrian Hunter static bool sdhci_presetable_values_change(struct sdhci_host *host, struct mmc_ios *ios) 2314c981cdfbSAdrian Hunter { 2315c981cdfbSAdrian Hunter /* 2316c981cdfbSAdrian Hunter * Preset Values are: Driver Strength, Clock Generator and SDCLK/RCLK 2317c981cdfbSAdrian Hunter * Frequency. Check if preset values need to be enabled, or the Driver 2318c981cdfbSAdrian Hunter * Strength needs updating. Note, clock changes are handled separately. 2319c981cdfbSAdrian Hunter */ 2320c981cdfbSAdrian Hunter return !host->preset_enabled && 2321c981cdfbSAdrian Hunter (sdhci_preset_needed(host, ios->timing) || host->drv_type != ios->drv_type); 2322c981cdfbSAdrian Hunter } 2323c981cdfbSAdrian Hunter 23246a6d4cebSHu Ziji void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 23251c6a0718SPierre Ossman { 2326ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 2327c981cdfbSAdrian Hunter bool reinit_uhs = host->reinit_uhs; 2328c981cdfbSAdrian Hunter bool turning_on_clk = false; 23291c6a0718SPierre Ossman u8 ctrl; 23301c6a0718SPierre Ossman 2331c981cdfbSAdrian Hunter host->reinit_uhs = false; 2332c981cdfbSAdrian Hunter 233384ec048bSAdrian Hunter if (ios->power_mode == MMC_POWER_UNDEFINED) 233484ec048bSAdrian Hunter return; 233584ec048bSAdrian Hunter 2336ceb6143bSAdrian Hunter if (host->flags & SDHCI_DEVICE_DEAD) { 23373a48edc4STim Kryger if (!IS_ERR(mmc->supply.vmmc) && 23383a48edc4STim Kryger ios->power_mode == MMC_POWER_OFF) 23394e743f1fSMarkus Mayer mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 2340ceb6143bSAdrian Hunter return; 2341ceb6143bSAdrian Hunter } 23421e72859eSPierre Ossman 23431c6a0718SPierre Ossman /* 23441c6a0718SPierre Ossman * Reset the chip on each power off. 23451c6a0718SPierre Ossman * Should clear out any weird states. 23461c6a0718SPierre Ossman */ 23471c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 23484e4141a5SAnton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 23497260cf5eSAnton Vorontsov sdhci_reinit(host); 23501c6a0718SPierre Ossman } 23511c6a0718SPierre Ossman 235252983382SKevin Liu if (host->version >= SDHCI_SPEC_300 && 2353372c4634SDong Aisheng (ios->power_mode == MMC_POWER_UP) && 2354372c4634SDong Aisheng !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) 235552983382SKevin Liu sdhci_enable_preset_value(host, false); 235652983382SKevin Liu 2357373073efSRussell King if (!ios->clock || ios->clock != host->clock) { 2358c981cdfbSAdrian Hunter turning_on_clk = ios->clock && !host->clock; 2359c981cdfbSAdrian Hunter 23601771059cSRussell King host->ops->set_clock(host, ios->clock); 2361373073efSRussell King host->clock = ios->clock; 236203d6f5ffSAisheng Dong 236303d6f5ffSAisheng Dong if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && 236403d6f5ffSAisheng Dong host->clock) { 2365d2f025b0SJisheng Zhang host->timeout_clk = mmc->actual_clock ? 2366d2f025b0SJisheng Zhang mmc->actual_clock / 1000 : 236703d6f5ffSAisheng Dong host->clock / 1000; 2368d2f025b0SJisheng Zhang mmc->max_busy_timeout = 236903d6f5ffSAisheng Dong host->ops->get_max_timeout_count ? 237003d6f5ffSAisheng Dong host->ops->get_max_timeout_count(host) : 237103d6f5ffSAisheng Dong 1 << 27; 2372d2f025b0SJisheng Zhang mmc->max_busy_timeout /= host->timeout_clk; 237303d6f5ffSAisheng Dong } 2374373073efSRussell King } 23751c6a0718SPierre Ossman 2376606d3131SAdrian Hunter if (host->ops->set_power) 2377606d3131SAdrian Hunter host->ops->set_power(host, ios->power_mode, ios->vdd); 2378606d3131SAdrian Hunter else 2379606d3131SAdrian Hunter sdhci_set_power(host, ios->power_mode, ios->vdd); 23801c6a0718SPierre Ossman 2381643a81ffSPhilip Rakity if (host->ops->platform_send_init_74_clocks) 2382643a81ffSPhilip Rakity host->ops->platform_send_init_74_clocks(host, ios->power_mode); 2383643a81ffSPhilip Rakity 23842317f56cSRussell King host->ops->set_bus_width(host, ios->bus_width); 238515ec4461SPhilip Rakity 2386c981cdfbSAdrian Hunter /* 2387c981cdfbSAdrian Hunter * Special case to avoid multiple clock changes during voltage 2388c981cdfbSAdrian Hunter * switching. 2389c981cdfbSAdrian Hunter */ 2390c981cdfbSAdrian Hunter if (!reinit_uhs && 2391c981cdfbSAdrian Hunter turning_on_clk && 2392c981cdfbSAdrian Hunter host->timing == ios->timing && 2393c981cdfbSAdrian Hunter host->version >= SDHCI_SPEC_300 && 2394c981cdfbSAdrian Hunter !sdhci_presetable_values_change(host, ios)) 2395c981cdfbSAdrian Hunter return; 2396c981cdfbSAdrian Hunter 239715ec4461SPhilip Rakity ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 23981c6a0718SPierre Ossman 2399501639bfSyangbo lu if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) { 2400501639bfSyangbo lu if (ios->timing == MMC_TIMING_SD_HS || 2401273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS || 2402273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS400 || 2403273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS200 || 2404273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_DDR52 || 2405273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR50 || 2406273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR104 || 2407273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_DDR50 || 2408273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR25) 24091c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_HISPD; 24101c6a0718SPierre Ossman else 24111c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 2412501639bfSyangbo lu } 24131c6a0718SPierre Ossman 2414d6d50a15SArindam Nath if (host->version >= SDHCI_SPEC_300) { 241549c468fcSArindam Nath u16 clk, ctrl_2; 241649c468fcSArindam Nath 2417da91a8f9SRussell King if (!host->preset_enabled) { 2418758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2419d6d50a15SArindam Nath /* 2420d6d50a15SArindam Nath * We only need to set Driver Strength if the 2421d6d50a15SArindam Nath * preset value enable is not set. 2422d6d50a15SArindam Nath */ 2423da91a8f9SRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2424d6d50a15SArindam Nath ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; 2425d6d50a15SArindam Nath if (ios->drv_type == MMC_SET_DRIVER_TYPE_A) 2426d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; 242743e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_B) 242843e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B; 2429d6d50a15SArindam Nath else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C) 2430d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C; 243143e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D) 243243e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D; 243343e943a0SPetri Gynther else { 24342e4456f0SMarek Vasut pr_warn("%s: invalid driver type, default to driver type B\n", 24352e4456f0SMarek Vasut mmc_hostname(mmc)); 243643e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B; 243743e943a0SPetri Gynther } 2438d6d50a15SArindam Nath 2439d6d50a15SArindam Nath sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 2440c981cdfbSAdrian Hunter host->drv_type = ios->drv_type; 2441758535c4SArindam Nath } else { 2442758535c4SArindam Nath /* 2443758535c4SArindam Nath * According to SDHC Spec v3.00, if the Preset Value 2444758535c4SArindam Nath * Enable in the Host Control 2 register is set, we 2445758535c4SArindam Nath * need to reset SD Clock Enable before changing High 2446758535c4SArindam Nath * Speed Enable to avoid generating clock gliches. 2447758535c4SArindam Nath */ 2448758535c4SArindam Nath 2449758535c4SArindam Nath /* Reset SD Clock Enable */ 2450758535c4SArindam Nath clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 2451758535c4SArindam Nath clk &= ~SDHCI_CLOCK_CARD_EN; 2452758535c4SArindam Nath sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 2453758535c4SArindam Nath 2454758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2455758535c4SArindam Nath 2456758535c4SArindam Nath /* Re-enable SD Clock */ 24571771059cSRussell King host->ops->set_clock(host, host->clock); 2458d6d50a15SArindam Nath } 245949c468fcSArindam Nath 24606322cdd0SPhilip Rakity /* Reset SD Clock Enable */ 24616322cdd0SPhilip Rakity clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 24626322cdd0SPhilip Rakity clk &= ~SDHCI_CLOCK_CARD_EN; 24636322cdd0SPhilip Rakity sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 24646322cdd0SPhilip Rakity 24656322cdd0SPhilip Rakity host->ops->set_uhs_signaling(host, ios->timing); 2466d975f121SRussell King host->timing = ios->timing; 246749c468fcSArindam Nath 2468c981cdfbSAdrian Hunter if (sdhci_preset_needed(host, ios->timing)) { 246952983382SKevin Liu u16 preset; 247052983382SKevin Liu 247152983382SKevin Liu sdhci_enable_preset_value(host, true); 247252983382SKevin Liu preset = sdhci_get_preset_value(host); 2473fa091010SMasahiro Yamada ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK, 2474fa091010SMasahiro Yamada preset); 2475c981cdfbSAdrian Hunter host->drv_type = ios->drv_type; 247652983382SKevin Liu } 247752983382SKevin Liu 247849c468fcSArindam Nath /* Re-enable SD Clock */ 24791771059cSRussell King host->ops->set_clock(host, host->clock); 2480758535c4SArindam Nath } else 2481758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 24821c6a0718SPierre Ossman } 24836a6d4cebSHu Ziji EXPORT_SYMBOL_GPL(sdhci_set_ios); 24841c6a0718SPierre Ossman 2485ded97e0bSDong Aisheng static int sdhci_get_cd(struct mmc_host *mmc) 248666fd8ad5SAdrian Hunter { 248766fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2488ded97e0bSDong Aisheng int gpio_cd = mmc_gpio_get_cd(mmc); 248994144a46SKevin Liu 249094144a46SKevin Liu if (host->flags & SDHCI_DEVICE_DEAD) 249194144a46SKevin Liu return 0; 249294144a46SKevin Liu 249388af5655SIvan T. Ivanov /* If nonremovable, assume that the card is always present. */ 2494d2f025b0SJisheng Zhang if (!mmc_card_is_removable(mmc)) 249594144a46SKevin Liu return 1; 249694144a46SKevin Liu 249788af5655SIvan T. Ivanov /* 249888af5655SIvan T. Ivanov * Try slot gpio detect, if defined it take precedence 249988af5655SIvan T. Ivanov * over build in controller functionality 250088af5655SIvan T. Ivanov */ 2501287980e4SArnd Bergmann if (gpio_cd >= 0) 250294144a46SKevin Liu return !!gpio_cd; 250394144a46SKevin Liu 250488af5655SIvan T. Ivanov /* If polling, assume that the card is always present. */ 250588af5655SIvan T. Ivanov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 250688af5655SIvan T. Ivanov return 1; 250788af5655SIvan T. Ivanov 250894144a46SKevin Liu /* Host native card detect */ 250994144a46SKevin Liu return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); 251094144a46SKevin Liu } 251194144a46SKevin Liu 25122caa11bcSAndy Shevchenko int sdhci_get_cd_nogpio(struct mmc_host *mmc) 25132caa11bcSAndy Shevchenko { 25142caa11bcSAndy Shevchenko struct sdhci_host *host = mmc_priv(mmc); 25152caa11bcSAndy Shevchenko unsigned long flags; 25162caa11bcSAndy Shevchenko int ret = 0; 25172caa11bcSAndy Shevchenko 25182caa11bcSAndy Shevchenko spin_lock_irqsave(&host->lock, flags); 25192caa11bcSAndy Shevchenko 25202caa11bcSAndy Shevchenko if (host->flags & SDHCI_DEVICE_DEAD) 25212caa11bcSAndy Shevchenko goto out; 25222caa11bcSAndy Shevchenko 25232caa11bcSAndy Shevchenko ret = !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); 25242caa11bcSAndy Shevchenko out: 25252caa11bcSAndy Shevchenko spin_unlock_irqrestore(&host->lock, flags); 25262caa11bcSAndy Shevchenko 25272caa11bcSAndy Shevchenko return ret; 25282caa11bcSAndy Shevchenko } 25292caa11bcSAndy Shevchenko EXPORT_SYMBOL_GPL(sdhci_get_cd_nogpio); 25302caa11bcSAndy Shevchenko 253166fd8ad5SAdrian Hunter static int sdhci_check_ro(struct sdhci_host *host) 25321c6a0718SPierre Ossman { 25331c6a0718SPierre Ossman unsigned long flags; 25342dfb579cSWolfram Sang int is_readonly; 25351c6a0718SPierre Ossman 25361c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 25371c6a0718SPierre Ossman 25381e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 25392dfb579cSWolfram Sang is_readonly = 0; 25402dfb579cSWolfram Sang else if (host->ops->get_ro) 25412dfb579cSWolfram Sang is_readonly = host->ops->get_ro(host); 25426d5cd068SThomas Petazzoni else if (mmc_can_gpio_ro(host->mmc)) 25436d5cd068SThomas Petazzoni is_readonly = mmc_gpio_get_ro(host->mmc); 25441e72859eSPierre Ossman else 25452dfb579cSWolfram Sang is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) 25462dfb579cSWolfram Sang & SDHCI_WRITE_PROTECT); 25471c6a0718SPierre Ossman 25481c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 25491c6a0718SPierre Ossman 25502dfb579cSWolfram Sang /* This quirk needs to be replaced by a callback-function later */ 25512dfb579cSWolfram Sang return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? 25522dfb579cSWolfram Sang !is_readonly : is_readonly; 25531c6a0718SPierre Ossman } 25541c6a0718SPierre Ossman 255582b0e23aSTakashi Iwai #define SAMPLE_COUNT 5 255682b0e23aSTakashi Iwai 2557ded97e0bSDong Aisheng static int sdhci_get_ro(struct mmc_host *mmc) 255882b0e23aSTakashi Iwai { 2559ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 256082b0e23aSTakashi Iwai int i, ro_count; 256182b0e23aSTakashi Iwai 256282b0e23aSTakashi Iwai if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT)) 256366fd8ad5SAdrian Hunter return sdhci_check_ro(host); 256482b0e23aSTakashi Iwai 256582b0e23aSTakashi Iwai ro_count = 0; 256682b0e23aSTakashi Iwai for (i = 0; i < SAMPLE_COUNT; i++) { 256766fd8ad5SAdrian Hunter if (sdhci_check_ro(host)) { 256882b0e23aSTakashi Iwai if (++ro_count > SAMPLE_COUNT / 2) 256982b0e23aSTakashi Iwai return 1; 257082b0e23aSTakashi Iwai } 257182b0e23aSTakashi Iwai msleep(30); 257282b0e23aSTakashi Iwai } 257382b0e23aSTakashi Iwai return 0; 257482b0e23aSTakashi Iwai } 257582b0e23aSTakashi Iwai 257620758b66SAdrian Hunter static void sdhci_hw_reset(struct mmc_host *mmc) 257720758b66SAdrian Hunter { 257820758b66SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 257920758b66SAdrian Hunter 258020758b66SAdrian Hunter if (host->ops && host->ops->hw_reset) 258120758b66SAdrian Hunter host->ops->hw_reset(host); 258220758b66SAdrian Hunter } 258320758b66SAdrian Hunter 258466fd8ad5SAdrian Hunter static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable) 258566fd8ad5SAdrian Hunter { 2586be138554SRussell King if (!(host->flags & SDHCI_DEVICE_DEAD)) { 258766fd8ad5SAdrian Hunter if (enable) 2588b537f94cSRussell King host->ier |= SDHCI_INT_CARD_INT; 25897260cf5eSAnton Vorontsov else 2590b537f94cSRussell King host->ier &= ~SDHCI_INT_CARD_INT; 2591b537f94cSRussell King 2592b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2593b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 259466fd8ad5SAdrian Hunter } 2595ef104333SRussell King } 2596f75979b7SPierre Ossman 25972f05b6abSHu Ziji void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 259866fd8ad5SAdrian Hunter { 259966fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 260066fd8ad5SAdrian Hunter unsigned long flags; 260166fd8ad5SAdrian Hunter 2602923713b3SHans de Goede if (enable) 2603bac53336SJisheng Zhang pm_runtime_get_noresume(mmc_dev(mmc)); 2604923713b3SHans de Goede 260566fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 260666fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, enable); 2607f75979b7SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 2608923713b3SHans de Goede 2609923713b3SHans de Goede if (!enable) 2610bac53336SJisheng Zhang pm_runtime_put_noidle(mmc_dev(mmc)); 2611f75979b7SPierre Ossman } 26122f05b6abSHu Ziji EXPORT_SYMBOL_GPL(sdhci_enable_sdio_irq); 2613f75979b7SPierre Ossman 261489f3c365SAdrian Hunter static void sdhci_ack_sdio_irq(struct mmc_host *mmc) 261589f3c365SAdrian Hunter { 261689f3c365SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 261789f3c365SAdrian Hunter unsigned long flags; 261889f3c365SAdrian Hunter 261989f3c365SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 262089f3c365SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true); 262189f3c365SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 262289f3c365SAdrian Hunter } 262389f3c365SAdrian Hunter 2624c376ea9eSHu Ziji int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, 262521f5998fSFabio Estevam struct mmc_ios *ios) 2626f2119df6SArindam Nath { 2627ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 262820b92a30SKevin Liu u16 ctrl; 26296231f3deSPhilip Rakity int ret; 2630f2119df6SArindam Nath 263120b92a30SKevin Liu /* 263220b92a30SKevin Liu * Signal Voltage Switching is only applicable for Host Controllers 263320b92a30SKevin Liu * v3.00 and above. 263420b92a30SKevin Liu */ 263520b92a30SKevin Liu if (host->version < SDHCI_SPEC_300) 263620b92a30SKevin Liu return 0; 263720b92a30SKevin Liu 263820b92a30SKevin Liu ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 263920b92a30SKevin Liu 264021f5998fSFabio Estevam switch (ios->signal_voltage) { 264120b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_330: 26428cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_330)) 26438cb851a4SAdrian Hunter return -EINVAL; 2644f2119df6SArindam Nath /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ 2645f2119df6SArindam Nath ctrl &= ~SDHCI_CTRL_VDD_180; 2646f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2647f2119df6SArindam Nath 26483a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2649761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 26509cbe0fc8SMarek Vasut if (ret < 0) { 26516606110dSJoe Perches pr_warn("%s: Switching to 3.3V signalling voltage failed\n", 26526606110dSJoe Perches mmc_hostname(mmc)); 26536231f3deSPhilip Rakity return -EIO; 26546231f3deSPhilip Rakity } 26556231f3deSPhilip Rakity } 2656f2119df6SArindam Nath /* Wait for 5ms */ 2657f2119df6SArindam Nath usleep_range(5000, 5500); 2658f2119df6SArindam Nath 2659f2119df6SArindam Nath /* 3.3V regulator output should be stable within 5 ms */ 2660f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2661f2119df6SArindam Nath if (!(ctrl & SDHCI_CTRL_VDD_180)) 2662f2119df6SArindam Nath return 0; 26636231f3deSPhilip Rakity 2664b0b19ce6SFabio Estevam pr_warn("%s: 3.3V regulator output did not become stable\n", 26654e743f1fSMarkus Mayer mmc_hostname(mmc)); 26666231f3deSPhilip Rakity 266720b92a30SKevin Liu return -EAGAIN; 266820b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_180: 26698cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_180)) 26708cb851a4SAdrian Hunter return -EINVAL; 26713a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2672761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 26739cbe0fc8SMarek Vasut if (ret < 0) { 26746606110dSJoe Perches pr_warn("%s: Switching to 1.8V signalling voltage failed\n", 26756606110dSJoe Perches mmc_hostname(mmc)); 2676f2119df6SArindam Nath return -EIO; 2677f2119df6SArindam Nath } 267820b92a30SKevin Liu } 26796231f3deSPhilip Rakity 2680f2119df6SArindam Nath /* 2681f2119df6SArindam Nath * Enable 1.8V Signal Enable in the Host Control2 2682f2119df6SArindam Nath * register 2683f2119df6SArindam Nath */ 2684f2119df6SArindam Nath ctrl |= SDHCI_CTRL_VDD_180; 2685f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2686f2119df6SArindam Nath 26879d967a61SVincent Yang /* Some controller need to do more when switching */ 26889d967a61SVincent Yang if (host->ops->voltage_switch) 26899d967a61SVincent Yang host->ops->voltage_switch(host); 26909d967a61SVincent Yang 269120b92a30SKevin Liu /* 1.8V regulator output should be stable within 5 ms */ 2692f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 269320b92a30SKevin Liu if (ctrl & SDHCI_CTRL_VDD_180) 2694f2119df6SArindam Nath return 0; 2695f2119df6SArindam Nath 2696b0b19ce6SFabio Estevam pr_warn("%s: 1.8V regulator output did not become stable\n", 26974e743f1fSMarkus Mayer mmc_hostname(mmc)); 26986231f3deSPhilip Rakity 2699f2119df6SArindam Nath return -EAGAIN; 270020b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_120: 27018cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_120)) 27028cb851a4SAdrian Hunter return -EINVAL; 27033a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2704761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 27059cbe0fc8SMarek Vasut if (ret < 0) { 27066606110dSJoe Perches pr_warn("%s: Switching to 1.2V signalling voltage failed\n", 27076606110dSJoe Perches mmc_hostname(mmc)); 270820b92a30SKevin Liu return -EIO; 27096231f3deSPhilip Rakity } 271020b92a30SKevin Liu } 27116231f3deSPhilip Rakity return 0; 271220b92a30SKevin Liu default: 2713f2119df6SArindam Nath /* No signal voltage switch required */ 2714f2119df6SArindam Nath return 0; 2715f2119df6SArindam Nath } 271620b92a30SKevin Liu } 2717c376ea9eSHu Ziji EXPORT_SYMBOL_GPL(sdhci_start_signal_voltage_switch); 2718f2119df6SArindam Nath 271920b92a30SKevin Liu static int sdhci_card_busy(struct mmc_host *mmc) 272020b92a30SKevin Liu { 272120b92a30SKevin Liu struct sdhci_host *host = mmc_priv(mmc); 272220b92a30SKevin Liu u32 present_state; 272320b92a30SKevin Liu 2724e613cc47SAdrian Hunter /* Check whether DAT[0] is 0 */ 272520b92a30SKevin Liu present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); 272620b92a30SKevin Liu 2727e613cc47SAdrian Hunter return !(present_state & SDHCI_DATA_0_LVL_MASK); 272820b92a30SKevin Liu } 272920b92a30SKevin Liu 2730b5540ce1SAdrian Hunter static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) 2731b5540ce1SAdrian Hunter { 2732b5540ce1SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2733b5540ce1SAdrian Hunter unsigned long flags; 2734b5540ce1SAdrian Hunter 2735b5540ce1SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2736b5540ce1SAdrian Hunter host->flags |= SDHCI_HS400_TUNING; 2737b5540ce1SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2738b5540ce1SAdrian Hunter 2739b5540ce1SAdrian Hunter return 0; 2740b5540ce1SAdrian Hunter } 2741b5540ce1SAdrian Hunter 27426663c419Sernest.zhang void sdhci_start_tuning(struct sdhci_host *host) 2743da4bc4f2SAdrian Hunter { 2744da4bc4f2SAdrian Hunter u16 ctrl; 2745da4bc4f2SAdrian Hunter 2746da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2747da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_EXEC_TUNING; 2748da4bc4f2SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND) 2749da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_TUNED_CLK; 2750da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2751da4bc4f2SAdrian Hunter 2752da4bc4f2SAdrian Hunter /* 2753da4bc4f2SAdrian Hunter * As per the Host Controller spec v3.00, tuning command 2754da4bc4f2SAdrian Hunter * generates Buffer Read Ready interrupt, so enable that. 2755da4bc4f2SAdrian Hunter * 2756da4bc4f2SAdrian Hunter * Note: The spec clearly says that when tuning sequence 2757da4bc4f2SAdrian Hunter * is being performed, the controller does not generate 2758da4bc4f2SAdrian Hunter * interrupts other than Buffer Read Ready interrupt. But 2759da4bc4f2SAdrian Hunter * to make sure we don't hit a controller bug, we _only_ 2760da4bc4f2SAdrian Hunter * enable Buffer Read Ready interrupt here. 2761da4bc4f2SAdrian Hunter */ 2762da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); 2763da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); 2764da4bc4f2SAdrian Hunter } 27656663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_start_tuning); 2766da4bc4f2SAdrian Hunter 27676663c419Sernest.zhang void sdhci_end_tuning(struct sdhci_host *host) 2768da4bc4f2SAdrian Hunter { 2769da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2770da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 2771da4bc4f2SAdrian Hunter } 27726663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_end_tuning); 2773da4bc4f2SAdrian Hunter 27746663c419Sernest.zhang void sdhci_reset_tuning(struct sdhci_host *host) 2775da4bc4f2SAdrian Hunter { 2776da4bc4f2SAdrian Hunter u16 ctrl; 2777da4bc4f2SAdrian Hunter 2778da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2779da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_TUNED_CLK; 2780da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_EXEC_TUNING; 2781da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2782da4bc4f2SAdrian Hunter } 27836663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_reset_tuning); 2784da4bc4f2SAdrian Hunter 27857353788cSBen Chuang void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) 2786da4bc4f2SAdrian Hunter { 2787da4bc4f2SAdrian Hunter sdhci_reset_tuning(host); 2788da4bc4f2SAdrian Hunter 27891e63d297SAdrian Hunter sdhci_reset_for(host, TUNING_ABORT); 2790da4bc4f2SAdrian Hunter 2791da4bc4f2SAdrian Hunter sdhci_end_tuning(host); 2792da4bc4f2SAdrian Hunter 279321adc2e4SWolfram Sang mmc_send_abort_tuning(host->mmc, opcode); 2794da4bc4f2SAdrian Hunter } 27957353788cSBen Chuang EXPORT_SYMBOL_GPL(sdhci_abort_tuning); 2796da4bc4f2SAdrian Hunter 2797da4bc4f2SAdrian Hunter /* 2798da4bc4f2SAdrian Hunter * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI 2799da4bc4f2SAdrian Hunter * tuning command does not have a data payload (or rather the hardware does it 2800da4bc4f2SAdrian Hunter * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command 2801da4bc4f2SAdrian Hunter * interrupt setup is different to other commands and there is no timeout 2802da4bc4f2SAdrian Hunter * interrupt so special handling is needed. 2803da4bc4f2SAdrian Hunter */ 28046663c419Sernest.zhang void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) 2805da4bc4f2SAdrian Hunter { 2806da4bc4f2SAdrian Hunter struct mmc_host *mmc = host->mmc; 2807c7836d15SMasahiro Yamada struct mmc_command cmd = {}; 2808c7836d15SMasahiro Yamada struct mmc_request mrq = {}; 28092a85ef25SAdrian Hunter unsigned long flags; 2810c846a00fSSrinivas Kandagatla u32 b = host->sdma_boundary; 28112a85ef25SAdrian Hunter 28122a85ef25SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2813da4bc4f2SAdrian Hunter 2814da4bc4f2SAdrian Hunter cmd.opcode = opcode; 2815da4bc4f2SAdrian Hunter cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 2816da4bc4f2SAdrian Hunter cmd.mrq = &mrq; 2817da4bc4f2SAdrian Hunter 2818da4bc4f2SAdrian Hunter mrq.cmd = &cmd; 2819da4bc4f2SAdrian Hunter /* 2820da4bc4f2SAdrian Hunter * In response to CMD19, the card sends 64 bytes of tuning 2821da4bc4f2SAdrian Hunter * block to the Host Controller. So we set the block size 2822da4bc4f2SAdrian Hunter * to 64 here. 2823da4bc4f2SAdrian Hunter */ 282485336109SAdrian Hunter if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200 && 282585336109SAdrian Hunter mmc->ios.bus_width == MMC_BUS_WIDTH_8) 2826c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 128), SDHCI_BLOCK_SIZE); 282785336109SAdrian Hunter else 2828c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 64), SDHCI_BLOCK_SIZE); 2829da4bc4f2SAdrian Hunter 2830da4bc4f2SAdrian Hunter /* 2831da4bc4f2SAdrian Hunter * The tuning block is sent by the card to the host controller. 2832da4bc4f2SAdrian Hunter * So we set the TRNS_READ bit in the Transfer Mode register. 2833da4bc4f2SAdrian Hunter * This also takes care of setting DMA Enable and Multi Block 2834da4bc4f2SAdrian Hunter * Select in the same register to 0. 2835da4bc4f2SAdrian Hunter */ 2836da4bc4f2SAdrian Hunter sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); 2837da4bc4f2SAdrian Hunter 2838845c939eSAdrian Hunter if (!sdhci_send_command_retry(host, &cmd, flags)) { 2839845c939eSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2840845c939eSAdrian Hunter host->tuning_done = 0; 2841845c939eSAdrian Hunter return; 2842845c939eSAdrian Hunter } 2843da4bc4f2SAdrian Hunter 2844da4bc4f2SAdrian Hunter host->cmd = NULL; 2845da4bc4f2SAdrian Hunter 2846da4bc4f2SAdrian Hunter sdhci_del_timer(host, &mrq); 2847da4bc4f2SAdrian Hunter 2848da4bc4f2SAdrian Hunter host->tuning_done = 0; 2849da4bc4f2SAdrian Hunter 2850da4bc4f2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2851da4bc4f2SAdrian Hunter 2852da4bc4f2SAdrian Hunter /* Wait for Buffer Read Ready interrupt */ 2853da4bc4f2SAdrian Hunter wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1), 2854da4bc4f2SAdrian Hunter msecs_to_jiffies(50)); 2855da4bc4f2SAdrian Hunter 2856da4bc4f2SAdrian Hunter } 28576663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_send_tuning); 2858da4bc4f2SAdrian Hunter 28597d8bb1f4SYinbo Zhu static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) 28606b11e70bSAdrian Hunter { 28616b11e70bSAdrian Hunter int i; 28626b11e70bSAdrian Hunter 28636b11e70bSAdrian Hunter /* 28646b11e70bSAdrian Hunter * Issue opcode repeatedly till Execute Tuning is set to 0 or the number 28651d8cd065SSowjanya Komatineni * of loops reaches tuning loop count. 28666b11e70bSAdrian Hunter */ 28671d8cd065SSowjanya Komatineni for (i = 0; i < host->tuning_loop_count; i++) { 28686b11e70bSAdrian Hunter u16 ctrl; 28696b11e70bSAdrian Hunter 28702a85ef25SAdrian Hunter sdhci_send_tuning(host, opcode); 28716b11e70bSAdrian Hunter 28726b11e70bSAdrian Hunter if (!host->tuning_done) { 2873811ba676SFaiz Abbas pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n", 28746b11e70bSAdrian Hunter mmc_hostname(host->mmc)); 28752a85ef25SAdrian Hunter sdhci_abort_tuning(host, opcode); 28767d8bb1f4SYinbo Zhu return -ETIMEDOUT; 28776b11e70bSAdrian Hunter } 28786b11e70bSAdrian Hunter 28792b06e159SBOUGH CHEN /* Spec does not require a delay between tuning cycles */ 28802b06e159SBOUGH CHEN if (host->tuning_delay > 0) 28812b06e159SBOUGH CHEN mdelay(host->tuning_delay); 28822b06e159SBOUGH CHEN 28836b11e70bSAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 28846b11e70bSAdrian Hunter if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { 28856b11e70bSAdrian Hunter if (ctrl & SDHCI_CTRL_TUNED_CLK) 28867d8bb1f4SYinbo Zhu return 0; /* Success! */ 28876b11e70bSAdrian Hunter break; 28886b11e70bSAdrian Hunter } 28896b11e70bSAdrian Hunter 28906b11e70bSAdrian Hunter } 28916b11e70bSAdrian Hunter 28926b11e70bSAdrian Hunter pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", 28936b11e70bSAdrian Hunter mmc_hostname(host->mmc)); 28946b11e70bSAdrian Hunter sdhci_reset_tuning(host); 28957d8bb1f4SYinbo Zhu return -EAGAIN; 28966b11e70bSAdrian Hunter } 28976b11e70bSAdrian Hunter 289885a882c2SMasahiro Yamada int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) 2899b513ea25SArindam Nath { 29004b6f37d3SRussell King struct sdhci_host *host = mmc_priv(mmc); 2901b513ea25SArindam Nath int err = 0; 290238e40bf5SAdrian Hunter unsigned int tuning_count = 0; 2903b5540ce1SAdrian Hunter bool hs400_tuning; 2904b513ea25SArindam Nath 2905b5540ce1SAdrian Hunter hs400_tuning = host->flags & SDHCI_HS400_TUNING; 2906b5540ce1SAdrian Hunter 290738e40bf5SAdrian Hunter if (host->tuning_mode == SDHCI_TUNING_MODE_1) 290838e40bf5SAdrian Hunter tuning_count = host->tuning_count; 290938e40bf5SAdrian Hunter 2910b513ea25SArindam Nath /* 29119faac7b9SWeijun Yang * The Host Controller needs tuning in case of SDR104 and DDR50 29129faac7b9SWeijun Yang * mode, and for SDR50 mode when Use Tuning for SDR50 is set in 29139faac7b9SWeijun Yang * the Capabilities register. 2914069c9f14SGirish K S * If the Host Controller supports the HS200 mode then the 2915069c9f14SGirish K S * tuning function has to be executed. 2916b513ea25SArindam Nath */ 29174b6f37d3SRussell King switch (host->timing) { 2918b5540ce1SAdrian Hunter /* HS400 tuning is done in HS200 mode */ 2919e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400: 2920b5540ce1SAdrian Hunter err = -EINVAL; 29212a85ef25SAdrian Hunter goto out; 2922b5540ce1SAdrian Hunter 29234b6f37d3SRussell King case MMC_TIMING_MMC_HS200: 2924b5540ce1SAdrian Hunter /* 2925b5540ce1SAdrian Hunter * Periodic re-tuning for HS400 is not expected to be needed, so 2926b5540ce1SAdrian Hunter * disable it here. 2927b5540ce1SAdrian Hunter */ 2928b5540ce1SAdrian Hunter if (hs400_tuning) 2929b5540ce1SAdrian Hunter tuning_count = 0; 2930b5540ce1SAdrian Hunter break; 2931b5540ce1SAdrian Hunter 29324b6f37d3SRussell King case MMC_TIMING_UHS_SDR104: 29339faac7b9SWeijun Yang case MMC_TIMING_UHS_DDR50: 29344b6f37d3SRussell King break; 2935069c9f14SGirish K S 29364b6f37d3SRussell King case MMC_TIMING_UHS_SDR50: 29374228b213SAdrian Hunter if (host->flags & SDHCI_SDR50_NEEDS_TUNING) 29384b6f37d3SRussell King break; 2939df561f66SGustavo A. R. Silva fallthrough; 29404b6f37d3SRussell King 29414b6f37d3SRussell King default: 29422a85ef25SAdrian Hunter goto out; 2943b513ea25SArindam Nath } 2944b513ea25SArindam Nath 294545251812SDong Aisheng if (host->ops->platform_execute_tuning) { 29468a8fa879SRitesh Harjani err = host->ops->platform_execute_tuning(host, opcode); 29472a85ef25SAdrian Hunter goto out; 294845251812SDong Aisheng } 294945251812SDong Aisheng 2950d2f025b0SJisheng Zhang mmc->retune_period = tuning_count; 29516b11e70bSAdrian Hunter 295283b600b8SAdrian Hunter if (host->tuning_delay < 0) 295383b600b8SAdrian Hunter host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK; 295483b600b8SAdrian Hunter 2955da4bc4f2SAdrian Hunter sdhci_start_tuning(host); 2956b513ea25SArindam Nath 29577d8bb1f4SYinbo Zhu host->tuning_err = __sdhci_execute_tuning(host, opcode); 2958cf2b5eeaSArindam Nath 2959da4bc4f2SAdrian Hunter sdhci_end_tuning(host); 29602a85ef25SAdrian Hunter out: 29618a8fa879SRitesh Harjani host->flags &= ~SDHCI_HS400_TUNING; 29626b11e70bSAdrian Hunter 2963b513ea25SArindam Nath return err; 2964b513ea25SArindam Nath } 296585a882c2SMasahiro Yamada EXPORT_SYMBOL_GPL(sdhci_execute_tuning); 2966b513ea25SArindam Nath 296752983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) 29684d55c5a1SArindam Nath { 29694d55c5a1SArindam Nath /* Host Controller v3.00 defines preset value registers */ 29704d55c5a1SArindam Nath if (host->version < SDHCI_SPEC_300) 29714d55c5a1SArindam Nath return; 29724d55c5a1SArindam Nath 29734d55c5a1SArindam Nath /* 29744d55c5a1SArindam Nath * We only enable or disable Preset Value if they are not already 29754d55c5a1SArindam Nath * enabled or disabled respectively. Otherwise, we bail out. 29764d55c5a1SArindam Nath */ 2977da91a8f9SRussell King if (host->preset_enabled != enable) { 2978da91a8f9SRussell King u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2979da91a8f9SRussell King 2980da91a8f9SRussell King if (enable) 29814d55c5a1SArindam Nath ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; 2982da91a8f9SRussell King else 29834d55c5a1SArindam Nath ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; 2984da91a8f9SRussell King 29854d55c5a1SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2986da91a8f9SRussell King 2987da91a8f9SRussell King if (enable) 2988da91a8f9SRussell King host->flags |= SDHCI_PV_ENABLED; 2989da91a8f9SRussell King else 299066fd8ad5SAdrian Hunter host->flags &= ~SDHCI_PV_ENABLED; 2991da91a8f9SRussell King 2992da91a8f9SRussell King host->preset_enabled = enable; 29934d55c5a1SArindam Nath } 299466fd8ad5SAdrian Hunter } 299566fd8ad5SAdrian Hunter 2996348487cbSHaibo Chen static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, 2997348487cbSHaibo Chen int err) 2998348487cbSHaibo Chen { 2999348487cbSHaibo Chen struct mmc_data *data = mrq->data; 3000348487cbSHaibo Chen 3001f48f039cSRussell King if (data->host_cookie != COOKIE_UNMAPPED) 3002d2f025b0SJisheng Zhang dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, 3003feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 3004771a3dc2SRussell King 3005d31911b9SHaibo Chen data->host_cookie = COOKIE_UNMAPPED; 3006348487cbSHaibo Chen } 3007348487cbSHaibo Chen 3008d3c6aac3SLinus Walleij static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) 3009348487cbSHaibo Chen { 3010348487cbSHaibo Chen struct sdhci_host *host = mmc_priv(mmc); 3011348487cbSHaibo Chen 3012d31911b9SHaibo Chen mrq->data->host_cookie = COOKIE_UNMAPPED; 3013348487cbSHaibo Chen 3014bd9b9027SLinus Walleij /* 3015bd9b9027SLinus Walleij * No pre-mapping in the pre hook if we're using the bounce buffer, 3016bd9b9027SLinus Walleij * for that we would need two bounce buffers since one buffer is 3017bd9b9027SLinus Walleij * in flight when this is getting called. 3018bd9b9027SLinus Walleij */ 3019bd9b9027SLinus Walleij if (host->flags & SDHCI_REQ_USE_DMA && !host->bounce_buffer) 302094538e51SRussell King sdhci_pre_dma_transfer(host, mrq->data, COOKIE_PRE_MAPPED); 3021348487cbSHaibo Chen } 3022348487cbSHaibo Chen 30235d0d11c5SAdrian Hunter static void sdhci_error_out_mrqs(struct sdhci_host *host, int err) 30245d0d11c5SAdrian Hunter { 30255d0d11c5SAdrian Hunter if (host->data_cmd) { 30265d0d11c5SAdrian Hunter host->data_cmd->error = err; 30275d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq); 30285d0d11c5SAdrian Hunter } 30295d0d11c5SAdrian Hunter 30305d0d11c5SAdrian Hunter if (host->cmd) { 30315d0d11c5SAdrian Hunter host->cmd->error = err; 30325d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 30335d0d11c5SAdrian Hunter } 30345d0d11c5SAdrian Hunter } 30355d0d11c5SAdrian Hunter 303671e69211SGuennadi Liakhovetski static void sdhci_card_event(struct mmc_host *mmc) 30371c6a0718SPierre Ossman { 303871e69211SGuennadi Liakhovetski struct sdhci_host *host = mmc_priv(mmc); 30391c6a0718SPierre Ossman unsigned long flags; 30402836766aSKrzysztof Kozlowski int present; 30411c6a0718SPierre Ossman 3042722e1280SChristian Daudt /* First check if client has provided their own card event */ 3043722e1280SChristian Daudt if (host->ops->card_event) 3044722e1280SChristian Daudt host->ops->card_event(host); 3045722e1280SChristian Daudt 3046d3940f27SAdrian Hunter present = mmc->ops->get_cd(mmc); 30472836766aSKrzysztof Kozlowski 30481c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 30491c6a0718SPierre Ossman 30505d0d11c5SAdrian Hunter /* Check sdhci_has_requests() first in case we are runtime suspended */ 30515d0d11c5SAdrian Hunter if (sdhci_has_requests(host) && !present) { 3052a3c76eb9SGirish K S pr_err("%s: Card removed during transfer!\n", 3053d2f025b0SJisheng Zhang mmc_hostname(mmc)); 3054a3c76eb9SGirish K S pr_err("%s: Resetting controller.\n", 3055d2f025b0SJisheng Zhang mmc_hostname(mmc)); 30561c6a0718SPierre Ossman 30571e63d297SAdrian Hunter sdhci_reset_for(host, CARD_REMOVED); 30581c6a0718SPierre Ossman 30595d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM); 30601c6a0718SPierre Ossman } 30611c6a0718SPierre Ossman 30621c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 306371e69211SGuennadi Liakhovetski } 306471e69211SGuennadi Liakhovetski 306571e69211SGuennadi Liakhovetski static const struct mmc_host_ops sdhci_ops = { 306671e69211SGuennadi Liakhovetski .request = sdhci_request, 3067348487cbSHaibo Chen .post_req = sdhci_post_req, 3068348487cbSHaibo Chen .pre_req = sdhci_pre_req, 306971e69211SGuennadi Liakhovetski .set_ios = sdhci_set_ios, 307094144a46SKevin Liu .get_cd = sdhci_get_cd, 307171e69211SGuennadi Liakhovetski .get_ro = sdhci_get_ro, 307232f18e59SWolfram Sang .card_hw_reset = sdhci_hw_reset, 307371e69211SGuennadi Liakhovetski .enable_sdio_irq = sdhci_enable_sdio_irq, 307489f3c365SAdrian Hunter .ack_sdio_irq = sdhci_ack_sdio_irq, 307571e69211SGuennadi Liakhovetski .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, 3076b5540ce1SAdrian Hunter .prepare_hs400_tuning = sdhci_prepare_hs400_tuning, 307771e69211SGuennadi Liakhovetski .execute_tuning = sdhci_execute_tuning, 307871e69211SGuennadi Liakhovetski .card_event = sdhci_card_event, 307920b92a30SKevin Liu .card_busy = sdhci_card_busy, 308071e69211SGuennadi Liakhovetski }; 308171e69211SGuennadi Liakhovetski 308271e69211SGuennadi Liakhovetski /*****************************************************************************\ 308371e69211SGuennadi Liakhovetski * * 3084c07a48c2SAdrian Hunter * Request done * 308571e69211SGuennadi Liakhovetski * * 308671e69211SGuennadi Liakhovetski \*****************************************************************************/ 308771e69211SGuennadi Liakhovetski 30884e9f8fe5SAdrian Hunter static bool sdhci_request_done(struct sdhci_host *host) 30891c6a0718SPierre Ossman { 30901c6a0718SPierre Ossman unsigned long flags; 30911c6a0718SPierre Ossman struct mmc_request *mrq; 30924e9f8fe5SAdrian Hunter int i; 30931c6a0718SPierre Ossman 309466fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 309566fd8ad5SAdrian Hunter 30964e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 30974e9f8fe5SAdrian Hunter mrq = host->mrqs_done[i]; 30986ebebeabSAdrian Hunter if (mrq) 30994e9f8fe5SAdrian Hunter break; 31004e9f8fe5SAdrian Hunter } 31011c6a0718SPierre Ossman 31024e9f8fe5SAdrian Hunter if (!mrq) { 31034e9f8fe5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 31044e9f8fe5SAdrian Hunter return true; 31054e9f8fe5SAdrian Hunter } 31061c6a0718SPierre Ossman 31071c6a0718SPierre Ossman /* 310821e35e89SPradeep P V K * The controller needs a reset of internal state machines 310921e35e89SPradeep P V K * upon error conditions. 311021e35e89SPradeep P V K */ 311121e35e89SPradeep P V K if (sdhci_needs_reset(host, mrq)) { 311221e35e89SPradeep P V K /* 311321e35e89SPradeep P V K * Do not finish until command and data lines are available for 311421e35e89SPradeep P V K * reset. Note there can only be one other mrq, so it cannot 311521e35e89SPradeep P V K * also be in mrqs_done, otherwise host->cmd and host->data_cmd 311621e35e89SPradeep P V K * would both be null. 311721e35e89SPradeep P V K */ 311821e35e89SPradeep P V K if (host->cmd || host->data_cmd) { 311921e35e89SPradeep P V K spin_unlock_irqrestore(&host->lock, flags); 312021e35e89SPradeep P V K return true; 312121e35e89SPradeep P V K } 312221e35e89SPradeep P V K 312321e35e89SPradeep P V K /* Some controllers need this kick or reset won't work here */ 312421e35e89SPradeep P V K if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) 312521e35e89SPradeep P V K /* This is to force an update */ 312621e35e89SPradeep P V K host->ops->set_clock(host, host->clock); 312721e35e89SPradeep P V K 31281e63d297SAdrian Hunter sdhci_reset_for(host, REQUEST_ERROR); 312921e35e89SPradeep P V K 313021e35e89SPradeep P V K host->pending_reset = false; 313121e35e89SPradeep P V K } 313221e35e89SPradeep P V K 313321e35e89SPradeep P V K /* 3134054cedffSRussell King * Always unmap the data buffers if they were mapped by 3135054cedffSRussell King * sdhci_prepare_data() whenever we finish with a request. 3136054cedffSRussell King * This avoids leaking DMA mappings on error. 3137054cedffSRussell King */ 3138054cedffSRussell King if (host->flags & SDHCI_REQ_USE_DMA) { 3139054cedffSRussell King struct mmc_data *data = mrq->data; 3140054cedffSRussell King 314118e762e3SChunyan Zhang if (host->use_external_dma && data && 314218e762e3SChunyan Zhang (mrq->cmd->error || data->error)) { 314318e762e3SChunyan Zhang struct dma_chan *chan = sdhci_external_dma_channel(host, data); 314418e762e3SChunyan Zhang 314518e762e3SChunyan Zhang host->mrqs_done[i] = NULL; 314618e762e3SChunyan Zhang spin_unlock_irqrestore(&host->lock, flags); 314718e762e3SChunyan Zhang dmaengine_terminate_sync(chan); 314818e762e3SChunyan Zhang spin_lock_irqsave(&host->lock, flags); 314918e762e3SChunyan Zhang sdhci_set_mrq_done(host, mrq); 315018e762e3SChunyan Zhang } 315118e762e3SChunyan Zhang 3152054cedffSRussell King if (data && data->host_cookie == COOKIE_MAPPED) { 3153bd9b9027SLinus Walleij if (host->bounce_buffer) { 3154bd9b9027SLinus Walleij /* 3155bd9b9027SLinus Walleij * On reads, copy the bounced data into the 3156bd9b9027SLinus Walleij * sglist 3157bd9b9027SLinus Walleij */ 3158bd9b9027SLinus Walleij if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) { 3159bd9b9027SLinus Walleij unsigned int length = data->bytes_xfered; 3160bd9b9027SLinus Walleij 3161bd9b9027SLinus Walleij if (length > host->bounce_buffer_size) { 3162bd9b9027SLinus Walleij pr_err("%s: bounce buffer is %u bytes but DMA claims to have transferred %u bytes\n", 3163bd9b9027SLinus Walleij mmc_hostname(host->mmc), 3164bd9b9027SLinus Walleij host->bounce_buffer_size, 3165bd9b9027SLinus Walleij data->bytes_xfered); 3166bd9b9027SLinus Walleij /* Cap it down and continue */ 3167bd9b9027SLinus Walleij length = host->bounce_buffer_size; 3168bd9b9027SLinus Walleij } 3169bd9b9027SLinus Walleij dma_sync_single_for_cpu( 3170bac53336SJisheng Zhang mmc_dev(host->mmc), 3171bd9b9027SLinus Walleij host->bounce_addr, 3172bd9b9027SLinus Walleij host->bounce_buffer_size, 3173bd9b9027SLinus Walleij DMA_FROM_DEVICE); 3174bd9b9027SLinus Walleij sg_copy_from_buffer(data->sg, 3175bd9b9027SLinus Walleij data->sg_len, 3176bd9b9027SLinus Walleij host->bounce_buffer, 3177bd9b9027SLinus Walleij length); 3178bd9b9027SLinus Walleij } else { 3179bd9b9027SLinus Walleij /* No copying, just switch ownership */ 3180bd9b9027SLinus Walleij dma_sync_single_for_cpu( 3181bac53336SJisheng Zhang mmc_dev(host->mmc), 3182bd9b9027SLinus Walleij host->bounce_addr, 3183bd9b9027SLinus Walleij host->bounce_buffer_size, 3184feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 3185bd9b9027SLinus Walleij } 3186bd9b9027SLinus Walleij } else { 3187bd9b9027SLinus Walleij /* Unmap the raw data */ 3188bd9b9027SLinus Walleij dma_unmap_sg(mmc_dev(host->mmc), data->sg, 3189bd9b9027SLinus Walleij data->sg_len, 3190bd9b9027SLinus Walleij mmc_get_dma_dir(data)); 3191bd9b9027SLinus Walleij } 3192054cedffSRussell King data->host_cookie = COOKIE_UNMAPPED; 3193054cedffSRussell King } 3194054cedffSRussell King } 3195054cedffSRussell King 31966ebebeabSAdrian Hunter host->mrqs_done[i] = NULL; 31976ebebeabSAdrian Hunter 31981c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 31991c6a0718SPierre Ossman 32001774b002SBaolin Wang if (host->ops->request_done) 32011774b002SBaolin Wang host->ops->request_done(host, mrq); 32021774b002SBaolin Wang else 32031c6a0718SPierre Ossman mmc_request_done(host->mmc, mrq); 32044e9f8fe5SAdrian Hunter 32054e9f8fe5SAdrian Hunter return false; 32064e9f8fe5SAdrian Hunter } 32074e9f8fe5SAdrian Hunter 3208c07a48c2SAdrian Hunter static void sdhci_complete_work(struct work_struct *work) 32094e9f8fe5SAdrian Hunter { 3210c07a48c2SAdrian Hunter struct sdhci_host *host = container_of(work, struct sdhci_host, 3211c07a48c2SAdrian Hunter complete_work); 32124e9f8fe5SAdrian Hunter 32134e9f8fe5SAdrian Hunter while (!sdhci_request_done(host)) 32144e9f8fe5SAdrian Hunter ; 32151c6a0718SPierre Ossman } 32161c6a0718SPierre Ossman 32172ee4f620SKees Cook static void sdhci_timeout_timer(struct timer_list *t) 32181c6a0718SPierre Ossman { 32191c6a0718SPierre Ossman struct sdhci_host *host; 32201c6a0718SPierre Ossman unsigned long flags; 32211c6a0718SPierre Ossman 32222ee4f620SKees Cook host = from_timer(host, t, timer); 32231c6a0718SPierre Ossman 32241c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 32251c6a0718SPierre Ossman 3226d7422fb4SAdrian Hunter if (host->cmd && !sdhci_data_line_cmd(host->cmd)) { 3227d7422fb4SAdrian Hunter pr_err("%s: Timeout waiting for hardware cmd interrupt.\n", 3228d7422fb4SAdrian Hunter mmc_hostname(host->mmc)); 3229efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, REQ_TIMEOUT); 3230d7422fb4SAdrian Hunter sdhci_dumpregs(host); 3231d7422fb4SAdrian Hunter 3232d7422fb4SAdrian Hunter host->cmd->error = -ETIMEDOUT; 3233d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 3234d7422fb4SAdrian Hunter } 3235d7422fb4SAdrian Hunter 3236d7422fb4SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3237d7422fb4SAdrian Hunter } 3238d7422fb4SAdrian Hunter 32392ee4f620SKees Cook static void sdhci_timeout_data_timer(struct timer_list *t) 3240d7422fb4SAdrian Hunter { 3241d7422fb4SAdrian Hunter struct sdhci_host *host; 3242d7422fb4SAdrian Hunter unsigned long flags; 3243d7422fb4SAdrian Hunter 32442ee4f620SKees Cook host = from_timer(host, t, data_timer); 3245d7422fb4SAdrian Hunter 3246d7422fb4SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3247d7422fb4SAdrian Hunter 3248d7422fb4SAdrian Hunter if (host->data || host->data_cmd || 3249d7422fb4SAdrian Hunter (host->cmd && sdhci_data_line_cmd(host->cmd))) { 32502e4456f0SMarek Vasut pr_err("%s: Timeout waiting for hardware interrupt.\n", 32512e4456f0SMarek Vasut mmc_hostname(host->mmc)); 3252efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, REQ_TIMEOUT); 32531c6a0718SPierre Ossman sdhci_dumpregs(host); 32541c6a0718SPierre Ossman 32551c6a0718SPierre Ossman if (host->data) { 325617b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 3257845c939eSAdrian Hunter __sdhci_finish_data(host, true); 3258c07a48c2SAdrian Hunter queue_work(host->complete_wq, &host->complete_work); 3259d7422fb4SAdrian Hunter } else if (host->data_cmd) { 3260d7422fb4SAdrian Hunter host->data_cmd->error = -ETIMEDOUT; 3261d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq); 32621c6a0718SPierre Ossman } else { 326317b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 3264d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 32651c6a0718SPierre Ossman } 32661c6a0718SPierre Ossman } 32671c6a0718SPierre Ossman 32681c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 32691c6a0718SPierre Ossman } 32701c6a0718SPierre Ossman 32711c6a0718SPierre Ossman /*****************************************************************************\ 32721c6a0718SPierre Ossman * * 32731c6a0718SPierre Ossman * Interrupt handling * 32741c6a0718SPierre Ossman * * 32751c6a0718SPierre Ossman \*****************************************************************************/ 32761c6a0718SPierre Ossman 32774bf78099SAdrian Hunter static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) 32781c6a0718SPierre Ossman { 3279af849c86SAdrian Hunter /* Handle auto-CMD12 error */ 3280af849c86SAdrian Hunter if (intmask & SDHCI_INT_AUTO_CMD_ERR && host->data_cmd) { 3281af849c86SAdrian Hunter struct mmc_request *mrq = host->data_cmd->mrq; 3282af849c86SAdrian Hunter u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); 3283af849c86SAdrian Hunter int data_err_bit = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? 3284af849c86SAdrian Hunter SDHCI_INT_DATA_TIMEOUT : 3285af849c86SAdrian Hunter SDHCI_INT_DATA_CRC; 3286af849c86SAdrian Hunter 3287af849c86SAdrian Hunter /* Treat auto-CMD12 error the same as data error */ 3288af849c86SAdrian Hunter if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) { 3289af849c86SAdrian Hunter *intmask_p |= data_err_bit; 3290af849c86SAdrian Hunter return; 3291af849c86SAdrian Hunter } 3292af849c86SAdrian Hunter } 3293af849c86SAdrian Hunter 32941c6a0718SPierre Ossman if (!host->cmd) { 3295ed1563deSAdrian Hunter /* 3296ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data 3297ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more 3298ed1563deSAdrian Hunter * interrupts, so ignore them in that case. 3299ed1563deSAdrian Hunter */ 3300ed1563deSAdrian Hunter if (host->pending_reset) 3301ed1563deSAdrian Hunter return; 33022e4456f0SMarek Vasut pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", 3303b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 3304efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ); 33051c6a0718SPierre Ossman sdhci_dumpregs(host); 33061c6a0718SPierre Ossman return; 33071c6a0718SPierre Ossman } 33081c6a0718SPierre Ossman 3309ec014cbaSRussell King if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | 3310ec014cbaSRussell King SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { 3311efe8f5c9SShaik Sajida Bhanu if (intmask & SDHCI_INT_TIMEOUT) { 331217b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 3313efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_TIMEOUT); 3314efe8f5c9SShaik Sajida Bhanu } else { 331517b0429dSPierre Ossman host->cmd->error = -EILSEQ; 3316efe8f5c9SShaik Sajida Bhanu if (!mmc_op_tuning(host->cmd->opcode)) 3317efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_CRC); 3318efe8f5c9SShaik Sajida Bhanu } 33194bf78099SAdrian Hunter /* Treat data command CRC error the same as data CRC error */ 332071fcbda0SRussell King if (host->cmd->data && 332171fcbda0SRussell King (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == 332271fcbda0SRussell King SDHCI_INT_CRC) { 332371fcbda0SRussell King host->cmd = NULL; 33244bf78099SAdrian Hunter *intmask_p |= SDHCI_INT_DATA_CRC; 332571fcbda0SRussell King return; 332671fcbda0SRussell King } 332771fcbda0SRussell King 332819d2f695SAdrian Hunter __sdhci_finish_mrq(host, host->cmd->mrq); 3329e809517fSPierre Ossman return; 3330e809517fSPierre Ossman } 3331e809517fSPierre Ossman 3332af849c86SAdrian Hunter /* Handle auto-CMD23 error */ 3333af849c86SAdrian Hunter if (intmask & SDHCI_INT_AUTO_CMD_ERR) { 3334af849c86SAdrian Hunter struct mmc_request *mrq = host->cmd->mrq; 3335af849c86SAdrian Hunter u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); 3336af849c86SAdrian Hunter int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? 3337af849c86SAdrian Hunter -ETIMEDOUT : 3338af849c86SAdrian Hunter -EILSEQ; 3339af849c86SAdrian Hunter 3340efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, AUTO_CMD); 3341efe8f5c9SShaik Sajida Bhanu 334238929d4fSChanWoo Lee if (sdhci_auto_cmd23(host, mrq)) { 3343af849c86SAdrian Hunter mrq->sbc->error = err; 334419d2f695SAdrian Hunter __sdhci_finish_mrq(host, mrq); 3345af849c86SAdrian Hunter return; 3346af849c86SAdrian Hunter } 3347af849c86SAdrian Hunter } 3348af849c86SAdrian Hunter 3349e809517fSPierre Ossman if (intmask & SDHCI_INT_RESPONSE) 335043b58b36SPierre Ossman sdhci_finish_command(host); 33511c6a0718SPierre Ossman } 33521c6a0718SPierre Ossman 335308621b18SAdrian Hunter static void sdhci_adma_show_error(struct sdhci_host *host) 33546882a8c0SBen Dooks { 33551c3d5f6dSAdrian Hunter void *desc = host->adma_table; 3356d1c536e3SRussell King dma_addr_t dma = host->adma_addr; 33576882a8c0SBen Dooks 33586882a8c0SBen Dooks sdhci_dumpregs(host); 33596882a8c0SBen Dooks 33606882a8c0SBen Dooks while (true) { 3361e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 33626882a8c0SBen Dooks 3363e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 3364d1c536e3SRussell King SDHCI_DUMP("%08llx: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", 3365d1c536e3SRussell King (unsigned long long)dma, 3366d1c536e3SRussell King le32_to_cpu(dma_desc->addr_hi), 3367e57a5f61SAdrian Hunter le32_to_cpu(dma_desc->addr_lo), 3368e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->len), 3369e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->cmd)); 3370e57a5f61SAdrian Hunter else 3371d1c536e3SRussell King SDHCI_DUMP("%08llx: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", 3372d1c536e3SRussell King (unsigned long long)dma, 3373d1c536e3SRussell King le32_to_cpu(dma_desc->addr_lo), 33740545230fSAdrian Hunter le16_to_cpu(dma_desc->len), 33750545230fSAdrian Hunter le16_to_cpu(dma_desc->cmd)); 33766882a8c0SBen Dooks 337776fe379aSAdrian Hunter desc += host->desc_sz; 3378d1c536e3SRussell King dma += host->desc_sz; 33796882a8c0SBen Dooks 33800545230fSAdrian Hunter if (dma_desc->cmd & cpu_to_le16(ADMA2_END)) 33816882a8c0SBen Dooks break; 33826882a8c0SBen Dooks } 33836882a8c0SBen Dooks } 33846882a8c0SBen Dooks 33851c6a0718SPierre Ossman static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 33861c6a0718SPierre Ossman { 3387069c9f14SGirish K S u32 command; 33881c6a0718SPierre Ossman 3389f4ff24f8SHaibo Chen /* 3390f4ff24f8SHaibo Chen * CMD19 generates _only_ Buffer Read Ready interrupt if 3391f4ff24f8SHaibo Chen * use sdhci_send_tuning. 3392f4ff24f8SHaibo Chen * Need to exclude this case: PIO mode and use mmc_send_tuning, 3393f4ff24f8SHaibo Chen * If not, sdhci_transfer_pio will never be called, make the 3394f4ff24f8SHaibo Chen * SDHCI_INT_DATA_AVAIL always there, stuck in irq storm. 3395f4ff24f8SHaibo Chen */ 3396f4ff24f8SHaibo Chen if (intmask & SDHCI_INT_DATA_AVAIL && !host->data) { 3397069c9f14SGirish K S command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)); 3398069c9f14SGirish K S if (command == MMC_SEND_TUNING_BLOCK || 3399069c9f14SGirish K S command == MMC_SEND_TUNING_BLOCK_HS200) { 3400b513ea25SArindam Nath host->tuning_done = 1; 3401b513ea25SArindam Nath wake_up(&host->buf_ready_int); 3402b513ea25SArindam Nath return; 3403b513ea25SArindam Nath } 3404b513ea25SArindam Nath } 3405b513ea25SArindam Nath 34061c6a0718SPierre Ossman if (!host->data) { 34077c89a3d9SAdrian Hunter struct mmc_command *data_cmd = host->data_cmd; 34087c89a3d9SAdrian Hunter 34091c6a0718SPierre Ossman /* 3410e809517fSPierre Ossman * The "data complete" interrupt is also used to 3411e809517fSPierre Ossman * indicate that a busy state has ended. See comment 3412e809517fSPierre Ossman * above in sdhci_cmd_irq(). 34131c6a0718SPierre Ossman */ 34147c89a3d9SAdrian Hunter if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) { 3415c5abd5e8SMatthieu CASTET if (intmask & SDHCI_INT_DATA_TIMEOUT) { 341669b962a6SAdrian Hunter host->data_cmd = NULL; 34177c89a3d9SAdrian Hunter data_cmd->error = -ETIMEDOUT; 3418efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_TIMEOUT); 341919d2f695SAdrian Hunter __sdhci_finish_mrq(host, data_cmd->mrq); 3420c5abd5e8SMatthieu CASTET return; 3421c5abd5e8SMatthieu CASTET } 3422e809517fSPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 342369b962a6SAdrian Hunter host->data_cmd = NULL; 3424e99783a4SChanho Min /* 3425e99783a4SChanho Min * Some cards handle busy-end interrupt 3426e99783a4SChanho Min * before the command completed, so make 3427e99783a4SChanho Min * sure we do things in the proper order. 3428e99783a4SChanho Min */ 3429ea968023SAdrian Hunter if (host->cmd == data_cmd) 3430ea968023SAdrian Hunter return; 3431ea968023SAdrian Hunter 343219d2f695SAdrian Hunter __sdhci_finish_mrq(host, data_cmd->mrq); 34331c6a0718SPierre Ossman return; 3434e809517fSPierre Ossman } 3435e809517fSPierre Ossman } 34361c6a0718SPierre Ossman 3437ed1563deSAdrian Hunter /* 3438ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data 3439ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more 3440ed1563deSAdrian Hunter * interrupts, so ignore them in that case. 3441ed1563deSAdrian Hunter */ 3442ed1563deSAdrian Hunter if (host->pending_reset) 3443ed1563deSAdrian Hunter return; 3444ed1563deSAdrian Hunter 34452e4456f0SMarek Vasut pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n", 3446b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 3447efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ); 34481c6a0718SPierre Ossman sdhci_dumpregs(host); 34491c6a0718SPierre Ossman 34501c6a0718SPierre Ossman return; 34511c6a0718SPierre Ossman } 34521c6a0718SPierre Ossman 3453efe8f5c9SShaik Sajida Bhanu if (intmask & SDHCI_INT_DATA_TIMEOUT) { 345417b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 3455efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_TIMEOUT); 3456efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_DATA_END_BIT) { 345722113efdSAries Lee host->data->error = -EILSEQ; 3458efe8f5c9SShaik Sajida Bhanu if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) 3459efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_CRC); 3460efe8f5c9SShaik Sajida Bhanu } else if ((intmask & SDHCI_INT_DATA_CRC) && 346122113efdSAries Lee SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) 3462efe8f5c9SShaik Sajida Bhanu != MMC_BUS_TEST_R) { 346317b0429dSPierre Ossman host->data->error = -EILSEQ; 3464efe8f5c9SShaik Sajida Bhanu if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) 3465efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_CRC); 3466efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_ADMA_ERROR) { 3467d1c536e3SRussell King pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), 3468d1c536e3SRussell King intmask); 346908621b18SAdrian Hunter sdhci_adma_show_error(host); 3470efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, ADMA); 34712134a922SPierre Ossman host->data->error = -EIO; 3472a4071fbbSHaijun Zhang if (host->ops->adma_workaround) 3473a4071fbbSHaijun Zhang host->ops->adma_workaround(host, intmask); 34746882a8c0SBen Dooks } 34751c6a0718SPierre Ossman 347617b0429dSPierre Ossman if (host->data->error) 34771c6a0718SPierre Ossman sdhci_finish_data(host); 34781c6a0718SPierre Ossman else { 34791c6a0718SPierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 34801c6a0718SPierre Ossman sdhci_transfer_pio(host); 34811c6a0718SPierre Ossman 34826ba736a1SPierre Ossman /* 34836ba736a1SPierre Ossman * We currently don't do anything fancy with DMA 34846ba736a1SPierre Ossman * boundaries, but as we can't disable the feature 34856ba736a1SPierre Ossman * we need to at least restart the transfer. 3486f6a03cbfSMikko Vinni * 3487f6a03cbfSMikko Vinni * According to the spec sdhci_readl(host, SDHCI_DMA_ADDRESS) 3488f6a03cbfSMikko Vinni * should return a valid address to continue from, but as 3489f6a03cbfSMikko Vinni * some controllers are faulty, don't trust them. 34906ba736a1SPierre Ossman */ 3491f6a03cbfSMikko Vinni if (intmask & SDHCI_INT_DMA_END) { 3492917a0c52SChunyan Zhang dma_addr_t dmastart, dmanow; 3493bd9b9027SLinus Walleij 3494bd9b9027SLinus Walleij dmastart = sdhci_sdma_address(host); 3495f6a03cbfSMikko Vinni dmanow = dmastart + host->data->bytes_xfered; 3496f6a03cbfSMikko Vinni /* 3497f6a03cbfSMikko Vinni * Force update to the next DMA block boundary. 3498f6a03cbfSMikko Vinni */ 3499f6a03cbfSMikko Vinni dmanow = (dmanow & 3500917a0c52SChunyan Zhang ~((dma_addr_t)SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 3501f6a03cbfSMikko Vinni SDHCI_DEFAULT_BOUNDARY_SIZE; 3502f6a03cbfSMikko Vinni host->data->bytes_xfered = dmanow - dmastart; 3503917a0c52SChunyan Zhang DBG("DMA base %pad, transferred 0x%06x bytes, next %pad\n", 3504917a0c52SChunyan Zhang &dmastart, host->data->bytes_xfered, &dmanow); 3505917a0c52SChunyan Zhang sdhci_set_sdma_addr(host, dmanow); 3506f6a03cbfSMikko Vinni } 35076ba736a1SPierre Ossman 3508e538fbe8SPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 35097c89a3d9SAdrian Hunter if (host->cmd == host->data_cmd) { 3510e538fbe8SPierre Ossman /* 3511e538fbe8SPierre Ossman * Data managed to finish before the 3512e538fbe8SPierre Ossman * command completed. Make sure we do 3513e538fbe8SPierre Ossman * things in the proper order. 3514e538fbe8SPierre Ossman */ 3515e538fbe8SPierre Ossman host->data_early = 1; 3516e538fbe8SPierre Ossman } else { 35171c6a0718SPierre Ossman sdhci_finish_data(host); 35181c6a0718SPierre Ossman } 35191c6a0718SPierre Ossman } 3520e538fbe8SPierre Ossman } 3521e538fbe8SPierre Ossman } 35221c6a0718SPierre Ossman 352319d2f695SAdrian Hunter static inline bool sdhci_defer_done(struct sdhci_host *host, 352419d2f695SAdrian Hunter struct mmc_request *mrq) 352519d2f695SAdrian Hunter { 352619d2f695SAdrian Hunter struct mmc_data *data = mrq->data; 352719d2f695SAdrian Hunter 35284730831cSBaolin Wang return host->pending_reset || host->always_defer_done || 352919d2f695SAdrian Hunter ((host->flags & SDHCI_REQ_USE_DMA) && data && 353019d2f695SAdrian Hunter data->host_cookie == COOKIE_MAPPED); 353119d2f695SAdrian Hunter } 353219d2f695SAdrian Hunter 35331c6a0718SPierre Ossman static irqreturn_t sdhci_irq(int irq, void *dev_id) 35341c6a0718SPierre Ossman { 353519d2f695SAdrian Hunter struct mmc_request *mrqs_done[SDHCI_MAX_MRQS] = {0}; 3536781e989cSRussell King irqreturn_t result = IRQ_NONE; 35371c6a0718SPierre Ossman struct sdhci_host *host = dev_id; 353841005003SRussell King u32 intmask, mask, unexpected = 0; 3539781e989cSRussell King int max_loops = 16; 354019d2f695SAdrian Hunter int i; 35411c6a0718SPierre Ossman 35421c6a0718SPierre Ossman spin_lock(&host->lock); 35431c6a0718SPierre Ossman 3544af5d2b7bSUlf Hansson if (host->runtime_suspended) { 354566fd8ad5SAdrian Hunter spin_unlock(&host->lock); 3546655bca76SAdrian Hunter return IRQ_NONE; 354766fd8ad5SAdrian Hunter } 354866fd8ad5SAdrian Hunter 35494e4141a5SAnton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS); 35501c6a0718SPierre Ossman if (!intmask || intmask == 0xffffffff) { 35511c6a0718SPierre Ossman result = IRQ_NONE; 35521c6a0718SPierre Ossman goto out; 35531c6a0718SPierre Ossman } 35541c6a0718SPierre Ossman 355541005003SRussell King do { 3556f12e39dbSAdrian Hunter DBG("IRQ status 0x%08x\n", intmask); 3557f12e39dbSAdrian Hunter 3558f12e39dbSAdrian Hunter if (host->ops->irq) { 3559f12e39dbSAdrian Hunter intmask = host->ops->irq(host, intmask); 3560f12e39dbSAdrian Hunter if (!intmask) 3561f12e39dbSAdrian Hunter goto cont; 3562f12e39dbSAdrian Hunter } 3563f12e39dbSAdrian Hunter 356441005003SRussell King /* Clear selected interrupts. */ 356541005003SRussell King mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 356641005003SRussell King SDHCI_INT_BUS_POWER); 356741005003SRussell King sdhci_writel(host, mask, SDHCI_INT_STATUS); 356841005003SRussell King 35691c6a0718SPierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 3570d25928d1SShawn Guo u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 3571d25928d1SShawn Guo SDHCI_CARD_PRESENT; 3572d25928d1SShawn Guo 3573d25928d1SShawn Guo /* 357441005003SRussell King * There is a observation on i.mx esdhc. INSERT 357541005003SRussell King * bit will be immediately set again when it gets 357641005003SRussell King * cleared, if a card is inserted. We have to mask 357741005003SRussell King * the irq to prevent interrupt storm which will 357841005003SRussell King * freeze the system. And the REMOVE gets the 357941005003SRussell King * same situation. 3580d25928d1SShawn Guo * 358141005003SRussell King * More testing are needed here to ensure it works 358241005003SRussell King * for other platforms though. 3583d25928d1SShawn Guo */ 3584b537f94cSRussell King host->ier &= ~(SDHCI_INT_CARD_INSERT | 3585d25928d1SShawn Guo SDHCI_INT_CARD_REMOVE); 3586b537f94cSRussell King host->ier |= present ? SDHCI_INT_CARD_REMOVE : 3587b537f94cSRussell King SDHCI_INT_CARD_INSERT; 3588b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3589b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 3590d25928d1SShawn Guo 35914e4141a5SAnton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | 35924e4141a5SAnton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); 35933560db8eSRussell King 35943560db8eSRussell King host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT | 35953560db8eSRussell King SDHCI_INT_CARD_REMOVE); 35963560db8eSRussell King result = IRQ_WAKE_THREAD; 35971c6a0718SPierre Ossman } 35981c6a0718SPierre Ossman 359941005003SRussell King if (intmask & SDHCI_INT_CMD_MASK) 36004bf78099SAdrian Hunter sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask); 36011c6a0718SPierre Ossman 360241005003SRussell King if (intmask & SDHCI_INT_DATA_MASK) 36031c6a0718SPierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 36041c6a0718SPierre Ossman 360541005003SRussell King if (intmask & SDHCI_INT_BUS_POWER) 3606a3c76eb9SGirish K S pr_err("%s: Card is consuming too much power!\n", 36071c6a0718SPierre Ossman mmc_hostname(host->mmc)); 36081c6a0718SPierre Ossman 3609f37b20ebSDong Aisheng if (intmask & SDHCI_INT_RETUNE) 3610f37b20ebSDong Aisheng mmc_retune_needed(host->mmc); 3611f37b20ebSDong Aisheng 3612161e6d44SGabriel Krisman Bertazi if ((intmask & SDHCI_INT_CARD_INT) && 3613161e6d44SGabriel Krisman Bertazi (host->ier & SDHCI_INT_CARD_INT)) { 3614781e989cSRussell King sdhci_enable_sdio_irq_nolock(host, false); 361589f3c365SAdrian Hunter sdio_signal_irq(host->mmc); 3616781e989cSRussell King } 3617f75979b7SPierre Ossman 361841005003SRussell King intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | 361941005003SRussell King SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 362041005003SRussell King SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | 3621f37b20ebSDong Aisheng SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT); 3622f75979b7SPierre Ossman 36231c6a0718SPierre Ossman if (intmask) { 36246379b237SAlexander Stein unexpected |= intmask; 36254e4141a5SAnton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS); 36261c6a0718SPierre Ossman } 3627f12e39dbSAdrian Hunter cont: 3628781e989cSRussell King if (result == IRQ_NONE) 36291c6a0718SPierre Ossman result = IRQ_HANDLED; 36301c6a0718SPierre Ossman 36316379b237SAlexander Stein intmask = sdhci_readl(host, SDHCI_INT_STATUS); 363241005003SRussell King } while (intmask && --max_loops); 363319d2f695SAdrian Hunter 363419d2f695SAdrian Hunter /* Determine if mrqs can be completed immediately */ 363519d2f695SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 363619d2f695SAdrian Hunter struct mmc_request *mrq = host->mrqs_done[i]; 363719d2f695SAdrian Hunter 363819d2f695SAdrian Hunter if (!mrq) 363919d2f695SAdrian Hunter continue; 364019d2f695SAdrian Hunter 364119d2f695SAdrian Hunter if (sdhci_defer_done(host, mrq)) { 3642c07a48c2SAdrian Hunter result = IRQ_WAKE_THREAD; 364319d2f695SAdrian Hunter } else { 364419d2f695SAdrian Hunter mrqs_done[i] = mrq; 364519d2f695SAdrian Hunter host->mrqs_done[i] = NULL; 364619d2f695SAdrian Hunter } 364719d2f695SAdrian Hunter } 36481c6a0718SPierre Ossman out: 3649845c939eSAdrian Hunter if (host->deferred_cmd) 3650845c939eSAdrian Hunter result = IRQ_WAKE_THREAD; 3651845c939eSAdrian Hunter 36521c6a0718SPierre Ossman spin_unlock(&host->lock); 36531c6a0718SPierre Ossman 365419d2f695SAdrian Hunter /* Process mrqs ready for immediate completion */ 365519d2f695SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 36561774b002SBaolin Wang if (!mrqs_done[i]) 36571774b002SBaolin Wang continue; 36581774b002SBaolin Wang 36591774b002SBaolin Wang if (host->ops->request_done) 36601774b002SBaolin Wang host->ops->request_done(host, mrqs_done[i]); 36611774b002SBaolin Wang else 366219d2f695SAdrian Hunter mmc_request_done(host->mmc, mrqs_done[i]); 366319d2f695SAdrian Hunter } 366419d2f695SAdrian Hunter 36656379b237SAlexander Stein if (unexpected) { 36666379b237SAlexander Stein pr_err("%s: Unexpected interrupt 0x%08x.\n", 36676379b237SAlexander Stein mmc_hostname(host->mmc), unexpected); 3668efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ); 36696379b237SAlexander Stein sdhci_dumpregs(host); 36706379b237SAlexander Stein } 3671f75979b7SPierre Ossman 36721c6a0718SPierre Ossman return result; 36731c6a0718SPierre Ossman } 36741c6a0718SPierre Ossman 3675781e989cSRussell King static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) 3676781e989cSRussell King { 3677781e989cSRussell King struct sdhci_host *host = dev_id; 3678845c939eSAdrian Hunter struct mmc_command *cmd; 3679781e989cSRussell King unsigned long flags; 3680781e989cSRussell King u32 isr; 3681781e989cSRussell King 3682c07a48c2SAdrian Hunter while (!sdhci_request_done(host)) 3683c07a48c2SAdrian Hunter ; 3684c07a48c2SAdrian Hunter 3685781e989cSRussell King spin_lock_irqsave(&host->lock, flags); 3686845c939eSAdrian Hunter 3687781e989cSRussell King isr = host->thread_isr; 3688781e989cSRussell King host->thread_isr = 0; 3689845c939eSAdrian Hunter 3690845c939eSAdrian Hunter cmd = host->deferred_cmd; 3691845c939eSAdrian Hunter if (cmd && !sdhci_send_command_retry(host, cmd, flags)) 3692845c939eSAdrian Hunter sdhci_finish_mrq(host, cmd->mrq); 3693845c939eSAdrian Hunter 3694781e989cSRussell King spin_unlock_irqrestore(&host->lock, flags); 3695781e989cSRussell King 36963560db8eSRussell King if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 3697d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 3698d3940f27SAdrian Hunter 3699d3940f27SAdrian Hunter mmc->ops->card_event(mmc); 3700d3940f27SAdrian Hunter mmc_detect_change(mmc, msecs_to_jiffies(200)); 37013560db8eSRussell King } 37023560db8eSRussell King 3703c07a48c2SAdrian Hunter return IRQ_HANDLED; 3704781e989cSRussell King } 3705781e989cSRussell King 37061c6a0718SPierre Ossman /*****************************************************************************\ 37071c6a0718SPierre Ossman * * 37081c6a0718SPierre Ossman * Suspend/resume * 37091c6a0718SPierre Ossman * * 37101c6a0718SPierre Ossman \*****************************************************************************/ 37111c6a0718SPierre Ossman 37121c6a0718SPierre Ossman #ifdef CONFIG_PM 37139c316b38SAdrian Hunter 37149c316b38SAdrian Hunter static bool sdhci_cd_irq_can_wakeup(struct sdhci_host *host) 37159c316b38SAdrian Hunter { 37169c316b38SAdrian Hunter return mmc_card_is_removable(host->mmc) && 37179c316b38SAdrian Hunter !(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 37189c316b38SAdrian Hunter !mmc_can_gpio_cd(host->mmc); 37199c316b38SAdrian Hunter } 37209c316b38SAdrian Hunter 372184d62605SLudovic Desroches /* 372284d62605SLudovic Desroches * To enable wakeup events, the corresponding events have to be enabled in 372384d62605SLudovic Desroches * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal 372484d62605SLudovic Desroches * Table' in the SD Host Controller Standard Specification. 372584d62605SLudovic Desroches * It is useless to restore SDHCI_INT_ENABLE state in 372684d62605SLudovic Desroches * sdhci_disable_irq_wakeups() since it will be set by 372784d62605SLudovic Desroches * sdhci_enable_card_detection() or sdhci_init(). 372884d62605SLudovic Desroches */ 372958e79b60SAdrian Hunter static bool sdhci_enable_irq_wakeups(struct sdhci_host *host) 3730ad080d79SKevin Liu { 373181b14543SAdrian Hunter u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE | 373281b14543SAdrian Hunter SDHCI_WAKE_ON_INT; 373381b14543SAdrian Hunter u32 irq_val = 0; 373481b14543SAdrian Hunter u8 wake_val = 0; 3735ad080d79SKevin Liu u8 val; 373681b14543SAdrian Hunter 37379c316b38SAdrian Hunter if (sdhci_cd_irq_can_wakeup(host)) { 373881b14543SAdrian Hunter wake_val |= SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE; 373981b14543SAdrian Hunter irq_val |= SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE; 374081b14543SAdrian Hunter } 374181b14543SAdrian Hunter 3742d5d568faSAdrian Hunter if (mmc_card_wake_sdio_irq(host->mmc)) { 374381b14543SAdrian Hunter wake_val |= SDHCI_WAKE_ON_INT; 374481b14543SAdrian Hunter irq_val |= SDHCI_INT_CARD_INT; 3745d5d568faSAdrian Hunter } 3746d5d568faSAdrian Hunter 3747d5d568faSAdrian Hunter if (!irq_val) 3748d5d568faSAdrian Hunter return false; 3749ad080d79SKevin Liu 3750ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 375181b14543SAdrian Hunter val &= ~mask; 375281b14543SAdrian Hunter val |= wake_val; 3753ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 375481b14543SAdrian Hunter 375584d62605SLudovic Desroches sdhci_writel(host, irq_val, SDHCI_INT_ENABLE); 375658e79b60SAdrian Hunter 375758e79b60SAdrian Hunter host->irq_wake_enabled = !enable_irq_wake(host->irq); 375858e79b60SAdrian Hunter 375958e79b60SAdrian Hunter return host->irq_wake_enabled; 3760ad080d79SKevin Liu } 3761ad080d79SKevin Liu 37620b10f478SFabio Estevam static void sdhci_disable_irq_wakeups(struct sdhci_host *host) 3763ad080d79SKevin Liu { 3764ad080d79SKevin Liu u8 val; 3765ad080d79SKevin Liu u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE 3766ad080d79SKevin Liu | SDHCI_WAKE_ON_INT; 3767ad080d79SKevin Liu 3768ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 3769ad080d79SKevin Liu val &= ~mask; 3770ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 377158e79b60SAdrian Hunter 377258e79b60SAdrian Hunter disable_irq_wake(host->irq); 377358e79b60SAdrian Hunter 377458e79b60SAdrian Hunter host->irq_wake_enabled = false; 3775ad080d79SKevin Liu } 37761c6a0718SPierre Ossman 377729495aa0SManuel Lauss int sdhci_suspend_host(struct sdhci_host *host) 37781c6a0718SPierre Ossman { 37797260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 37807260cf5eSAnton Vorontsov 378166c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc); 3782cf2b5eeaSArindam Nath 378358e79b60SAdrian Hunter if (!device_may_wakeup(mmc_dev(host->mmc)) || 378458e79b60SAdrian Hunter !sdhci_enable_irq_wakeups(host)) { 3785b537f94cSRussell King host->ier = 0; 3786b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 3787b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 3788b8c86fc5SPierre Ossman free_irq(host->irq, host); 3789ad080d79SKevin Liu } 379058e79b60SAdrian Hunter 37914ee14ec6SUlf Hansson return 0; 3792b8c86fc5SPierre Ossman } 3793b8c86fc5SPierre Ossman 3794b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_suspend_host); 3795b8c86fc5SPierre Ossman 3796b8c86fc5SPierre Ossman int sdhci_resume_host(struct sdhci_host *host) 3797b8c86fc5SPierre Ossman { 3798d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 37994ee14ec6SUlf Hansson int ret = 0; 3800b8c86fc5SPierre Ossman 3801a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 3802b8c86fc5SPierre Ossman if (host->ops->enable_dma) 3803b8c86fc5SPierre Ossman host->ops->enable_dma(host); 3804b8c86fc5SPierre Ossman } 3805b8c86fc5SPierre Ossman 3806d2f025b0SJisheng Zhang if ((mmc->pm_flags & MMC_PM_KEEP_POWER) && 38076308d290SAdrian Hunter (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) { 38086308d290SAdrian Hunter /* Card keeps power but host controller does not */ 38096308d290SAdrian Hunter sdhci_init(host, 0); 38106308d290SAdrian Hunter host->pwr = 0; 38116308d290SAdrian Hunter host->clock = 0; 3812c981cdfbSAdrian Hunter host->reinit_uhs = true; 3813d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 38146308d290SAdrian Hunter } else { 3815d2f025b0SJisheng Zhang sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER)); 38166308d290SAdrian Hunter } 3817b8c86fc5SPierre Ossman 381858e79b60SAdrian Hunter if (host->irq_wake_enabled) { 381958e79b60SAdrian Hunter sdhci_disable_irq_wakeups(host); 382058e79b60SAdrian Hunter } else { 382114a7b416SHaibo Chen ret = request_threaded_irq(host->irq, sdhci_irq, 382214a7b416SHaibo Chen sdhci_thread_irq, IRQF_SHARED, 3823d2f025b0SJisheng Zhang mmc_hostname(mmc), host); 382414a7b416SHaibo Chen if (ret) 382514a7b416SHaibo Chen return ret; 382614a7b416SHaibo Chen } 382714a7b416SHaibo Chen 38287260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 38297260cf5eSAnton Vorontsov 38302f4cbb3dSNicolas Pitre return ret; 38311c6a0718SPierre Ossman } 38321c6a0718SPierre Ossman 3833b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_resume_host); 383466fd8ad5SAdrian Hunter 383566fd8ad5SAdrian Hunter int sdhci_runtime_suspend_host(struct sdhci_host *host) 383666fd8ad5SAdrian Hunter { 383766fd8ad5SAdrian Hunter unsigned long flags; 383866fd8ad5SAdrian Hunter 383966c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc); 384066fd8ad5SAdrian Hunter 384166fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3842b537f94cSRussell King host->ier &= SDHCI_INT_CARD_INT; 3843b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3844b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 384566fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 384666fd8ad5SAdrian Hunter 3847781e989cSRussell King synchronize_hardirq(host->irq); 384866fd8ad5SAdrian Hunter 384966fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 385066fd8ad5SAdrian Hunter host->runtime_suspended = true; 385166fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 385266fd8ad5SAdrian Hunter 38538a125badSMarkus Pargmann return 0; 385466fd8ad5SAdrian Hunter } 385566fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host); 385666fd8ad5SAdrian Hunter 3857c6303c5dSBaolin Wang int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset) 385866fd8ad5SAdrian Hunter { 3859d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 386066fd8ad5SAdrian Hunter unsigned long flags; 38618a125badSMarkus Pargmann int host_flags = host->flags; 386266fd8ad5SAdrian Hunter 386366fd8ad5SAdrian Hunter if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 386466fd8ad5SAdrian Hunter if (host->ops->enable_dma) 386566fd8ad5SAdrian Hunter host->ops->enable_dma(host); 386666fd8ad5SAdrian Hunter } 386766fd8ad5SAdrian Hunter 3868c6303c5dSBaolin Wang sdhci_init(host, soft_reset); 386966fd8ad5SAdrian Hunter 387070bc85adSZhoujie Wu if (mmc->ios.power_mode != MMC_POWER_UNDEFINED && 387170bc85adSZhoujie Wu mmc->ios.power_mode != MMC_POWER_OFF) { 387266fd8ad5SAdrian Hunter /* Force clock and power re-program */ 387366fd8ad5SAdrian Hunter host->pwr = 0; 387466fd8ad5SAdrian Hunter host->clock = 0; 3875c981cdfbSAdrian Hunter host->reinit_uhs = true; 3876d3940f27SAdrian Hunter mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios); 3877d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 387866fd8ad5SAdrian Hunter 387952983382SKevin Liu if ((host_flags & SDHCI_PV_ENABLED) && 388052983382SKevin Liu !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { 388152983382SKevin Liu spin_lock_irqsave(&host->lock, flags); 388252983382SKevin Liu sdhci_enable_preset_value(host, true); 388352983382SKevin Liu spin_unlock_irqrestore(&host->lock, flags); 388452983382SKevin Liu } 388566fd8ad5SAdrian Hunter 3886086b0ddbSAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HS400_ES) && 3887086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe) 3888086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios); 388984ec048bSAdrian Hunter } 3890086b0ddbSAdrian Hunter 389166fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 389266fd8ad5SAdrian Hunter 389366fd8ad5SAdrian Hunter host->runtime_suspended = false; 389466fd8ad5SAdrian Hunter 389566fd8ad5SAdrian Hunter /* Enable SDIO IRQ */ 38960e62614bSUlf Hansson if (sdio_irq_claimed(mmc)) 389766fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true); 389866fd8ad5SAdrian Hunter 389966fd8ad5SAdrian Hunter /* Enable Card Detection */ 390066fd8ad5SAdrian Hunter sdhci_enable_card_detection(host); 390166fd8ad5SAdrian Hunter 390266fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 390366fd8ad5SAdrian Hunter 39048a125badSMarkus Pargmann return 0; 390566fd8ad5SAdrian Hunter } 390666fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host); 390766fd8ad5SAdrian Hunter 3908162d6f98SRafael J. Wysocki #endif /* CONFIG_PM */ 390966fd8ad5SAdrian Hunter 39101c6a0718SPierre Ossman /*****************************************************************************\ 39111c6a0718SPierre Ossman * * 3912f12e39dbSAdrian Hunter * Command Queue Engine (CQE) helpers * 3913f12e39dbSAdrian Hunter * * 3914f12e39dbSAdrian Hunter \*****************************************************************************/ 3915f12e39dbSAdrian Hunter 3916f12e39dbSAdrian Hunter void sdhci_cqe_enable(struct mmc_host *mmc) 3917f12e39dbSAdrian Hunter { 3918f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 3919f12e39dbSAdrian Hunter unsigned long flags; 3920f12e39dbSAdrian Hunter u8 ctrl; 3921f12e39dbSAdrian Hunter 3922f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3923f12e39dbSAdrian Hunter 3924f12e39dbSAdrian Hunter ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 3925f12e39dbSAdrian Hunter ctrl &= ~SDHCI_CTRL_DMA_MASK; 39264c4faff6SSowjanya Komatineni /* 39274c4faff6SSowjanya Komatineni * Host from V4.10 supports ADMA3 DMA type. 39284c4faff6SSowjanya Komatineni * ADMA3 performs integrated descriptor which is more suitable 39294c4faff6SSowjanya Komatineni * for cmd queuing to fetch both command and transfer descriptors. 39304c4faff6SSowjanya Komatineni */ 39314c4faff6SSowjanya Komatineni if (host->v4_mode && (host->caps1 & SDHCI_CAN_DO_ADMA3)) 39324c4faff6SSowjanya Komatineni ctrl |= SDHCI_CTRL_ADMA3; 39334c4faff6SSowjanya Komatineni else if (host->flags & SDHCI_USE_64_BIT_DMA) 3934f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA64; 3935f12e39dbSAdrian Hunter else 3936f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA32; 3937f12e39dbSAdrian Hunter sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 3938f12e39dbSAdrian Hunter 3939c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(host->sdma_boundary, 512), 3940f12e39dbSAdrian Hunter SDHCI_BLOCK_SIZE); 3941f12e39dbSAdrian Hunter 3942f12e39dbSAdrian Hunter /* Set maximum timeout */ 3943401059dfSBOUGH CHEN sdhci_set_timeout(host, NULL); 3944f12e39dbSAdrian Hunter 3945f12e39dbSAdrian Hunter host->ier = host->cqe_ier; 3946f12e39dbSAdrian Hunter 3947f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3948f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 3949f12e39dbSAdrian Hunter 3950f12e39dbSAdrian Hunter host->cqe_on = true; 3951f12e39dbSAdrian Hunter 3952f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE on, IRQ mask %#x, IRQ status %#x\n", 3953f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier, 3954f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS)); 3955f12e39dbSAdrian Hunter 3956f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3957f12e39dbSAdrian Hunter } 3958f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_enable); 3959f12e39dbSAdrian Hunter 3960f12e39dbSAdrian Hunter void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery) 3961f12e39dbSAdrian Hunter { 3962f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 3963f12e39dbSAdrian Hunter unsigned long flags; 3964f12e39dbSAdrian Hunter 3965f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3966f12e39dbSAdrian Hunter 3967f12e39dbSAdrian Hunter sdhci_set_default_irqs(host); 3968f12e39dbSAdrian Hunter 3969f12e39dbSAdrian Hunter host->cqe_on = false; 3970f12e39dbSAdrian Hunter 39711e63d297SAdrian Hunter if (recovery) 39721e63d297SAdrian Hunter sdhci_reset_for(host, CQE_RECOVERY); 3973f12e39dbSAdrian Hunter 3974f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE off, IRQ mask %#x, IRQ status %#x\n", 3975f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier, 3976f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS)); 3977f12e39dbSAdrian Hunter 3978f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3979f12e39dbSAdrian Hunter } 3980f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_disable); 3981f12e39dbSAdrian Hunter 3982f12e39dbSAdrian Hunter bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, 3983f12e39dbSAdrian Hunter int *data_error) 3984f12e39dbSAdrian Hunter { 3985f12e39dbSAdrian Hunter u32 mask; 3986f12e39dbSAdrian Hunter 3987f12e39dbSAdrian Hunter if (!host->cqe_on) 3988f12e39dbSAdrian Hunter return false; 3989f12e39dbSAdrian Hunter 3990efe8f5c9SShaik Sajida Bhanu if (intmask & (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC)) { 3991f12e39dbSAdrian Hunter *cmd_error = -EILSEQ; 3992faded9b5SWenchao Chen if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) 3993efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_CRC); 3994efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_TIMEOUT) { 3995f12e39dbSAdrian Hunter *cmd_error = -ETIMEDOUT; 3996efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_TIMEOUT); 3997efe8f5c9SShaik Sajida Bhanu } else 3998f12e39dbSAdrian Hunter *cmd_error = 0; 3999f12e39dbSAdrian Hunter 4000efe8f5c9SShaik Sajida Bhanu if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) { 4001f12e39dbSAdrian Hunter *data_error = -EILSEQ; 4002faded9b5SWenchao Chen if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) 4003efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_CRC); 4004efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_DATA_TIMEOUT) { 4005f12e39dbSAdrian Hunter *data_error = -ETIMEDOUT; 4006efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_TIMEOUT); 4007efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_ADMA_ERROR) { 4008f12e39dbSAdrian Hunter *data_error = -EIO; 4009efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, ADMA); 4010efe8f5c9SShaik Sajida Bhanu } else 4011f12e39dbSAdrian Hunter *data_error = 0; 4012f12e39dbSAdrian Hunter 4013f12e39dbSAdrian Hunter /* Clear selected interrupts. */ 4014f12e39dbSAdrian Hunter mask = intmask & host->cqe_ier; 4015f12e39dbSAdrian Hunter sdhci_writel(host, mask, SDHCI_INT_STATUS); 4016f12e39dbSAdrian Hunter 4017f12e39dbSAdrian Hunter if (intmask & SDHCI_INT_BUS_POWER) 4018f12e39dbSAdrian Hunter pr_err("%s: Card is consuming too much power!\n", 4019f12e39dbSAdrian Hunter mmc_hostname(host->mmc)); 4020f12e39dbSAdrian Hunter 4021f12e39dbSAdrian Hunter intmask &= ~(host->cqe_ier | SDHCI_INT_ERROR); 4022f12e39dbSAdrian Hunter if (intmask) { 4023f12e39dbSAdrian Hunter sdhci_writel(host, intmask, SDHCI_INT_STATUS); 4024f12e39dbSAdrian Hunter pr_err("%s: CQE: Unexpected interrupt 0x%08x.\n", 4025f12e39dbSAdrian Hunter mmc_hostname(host->mmc), intmask); 4026efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ); 4027f12e39dbSAdrian Hunter sdhci_dumpregs(host); 4028f12e39dbSAdrian Hunter } 4029f12e39dbSAdrian Hunter 4030f12e39dbSAdrian Hunter return true; 4031f12e39dbSAdrian Hunter } 4032f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_irq); 4033f12e39dbSAdrian Hunter 4034f12e39dbSAdrian Hunter /*****************************************************************************\ 4035f12e39dbSAdrian Hunter * * 4036b8c86fc5SPierre Ossman * Device allocation/registration * 40371c6a0718SPierre Ossman * * 40381c6a0718SPierre Ossman \*****************************************************************************/ 40391c6a0718SPierre Ossman 4040b8c86fc5SPierre Ossman struct sdhci_host *sdhci_alloc_host(struct device *dev, 4041b8c86fc5SPierre Ossman size_t priv_size) 40421c6a0718SPierre Ossman { 40431c6a0718SPierre Ossman struct mmc_host *mmc; 40441c6a0718SPierre Ossman struct sdhci_host *host; 40451c6a0718SPierre Ossman 4046b8c86fc5SPierre Ossman WARN_ON(dev == NULL); 40471c6a0718SPierre Ossman 4048b8c86fc5SPierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 40491c6a0718SPierre Ossman if (!mmc) 4050b8c86fc5SPierre Ossman return ERR_PTR(-ENOMEM); 40511c6a0718SPierre Ossman 40521c6a0718SPierre Ossman host = mmc_priv(mmc); 40531c6a0718SPierre Ossman host->mmc = mmc; 4054bf60e592SAdrian Hunter host->mmc_host_ops = sdhci_ops; 4055bf60e592SAdrian Hunter mmc->ops = &host->mmc_host_ops; 40561c6a0718SPierre Ossman 40578cb851a4SAdrian Hunter host->flags = SDHCI_SIGNALING_330; 40588cb851a4SAdrian Hunter 4059f12e39dbSAdrian Hunter host->cqe_ier = SDHCI_CQE_INT_MASK; 4060f12e39dbSAdrian Hunter host->cqe_err_ier = SDHCI_CQE_INT_ERR_MASK; 4061f12e39dbSAdrian Hunter 406283b600b8SAdrian Hunter host->tuning_delay = -1; 40631d8cd065SSowjanya Komatineni host->tuning_loop_count = MAX_TUNING_LOOP; 406483b600b8SAdrian Hunter 4065c846a00fSSrinivas Kandagatla host->sdma_boundary = SDHCI_DEFAULT_BOUNDARY_ARG; 4066c846a00fSSrinivas Kandagatla 4067e93be38aSJisheng Zhang /* 4068e93be38aSJisheng Zhang * The DMA table descriptor count is calculated as the maximum 4069e93be38aSJisheng Zhang * number of segments times 2, to allow for an alignment 4070e93be38aSJisheng Zhang * descriptor for each segment, plus 1 for a nop end descriptor. 4071e93be38aSJisheng Zhang */ 4072e93be38aSJisheng Zhang host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1; 40733d7c194bSAdrian Hunter host->max_adma = 65536; 4074e93be38aSJisheng Zhang 4075e30314f2SSarthak Garg host->max_timeout_count = 0xE; 4076e30314f2SSarthak Garg 4077b8c86fc5SPierre Ossman return host; 40781c6a0718SPierre Ossman } 40791c6a0718SPierre Ossman 4080b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_alloc_host); 4081b8c86fc5SPierre Ossman 40827b91369bSAlexandre Courbot static int sdhci_set_dma_mask(struct sdhci_host *host) 40837b91369bSAlexandre Courbot { 40847b91369bSAlexandre Courbot struct mmc_host *mmc = host->mmc; 40857b91369bSAlexandre Courbot struct device *dev = mmc_dev(mmc); 40867b91369bSAlexandre Courbot int ret = -EINVAL; 40877b91369bSAlexandre Courbot 40887b91369bSAlexandre Courbot if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) 40897b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA; 40907b91369bSAlexandre Courbot 40917b91369bSAlexandre Courbot /* Try 64-bit mask if hardware is capable of it */ 40927b91369bSAlexandre Courbot if (host->flags & SDHCI_USE_64_BIT_DMA) { 40937b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 40947b91369bSAlexandre Courbot if (ret) { 40957b91369bSAlexandre Courbot pr_warn("%s: Failed to set 64-bit DMA mask.\n", 40967b91369bSAlexandre Courbot mmc_hostname(mmc)); 40977b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA; 40987b91369bSAlexandre Courbot } 40997b91369bSAlexandre Courbot } 41007b91369bSAlexandre Courbot 41017b91369bSAlexandre Courbot /* 32-bit mask as default & fallback */ 41027b91369bSAlexandre Courbot if (ret) { 41037b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); 41047b91369bSAlexandre Courbot if (ret) 41057b91369bSAlexandre Courbot pr_warn("%s: Failed to set 32-bit DMA mask.\n", 41067b91369bSAlexandre Courbot mmc_hostname(mmc)); 41077b91369bSAlexandre Courbot } 41087b91369bSAlexandre Courbot 41097b91369bSAlexandre Courbot return ret; 41107b91369bSAlexandre Courbot } 41117b91369bSAlexandre Courbot 41128784edc8SMasahiro Yamada void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver, 41138784edc8SMasahiro Yamada const u32 *caps, const u32 *caps1) 41146132a3bfSAdrian Hunter { 41156132a3bfSAdrian Hunter u16 v; 411692e0c44bSZach Brown u64 dt_caps_mask = 0; 411792e0c44bSZach Brown u64 dt_caps = 0; 41186132a3bfSAdrian Hunter 41196132a3bfSAdrian Hunter if (host->read_caps) 41206132a3bfSAdrian Hunter return; 41216132a3bfSAdrian Hunter 41226132a3bfSAdrian Hunter host->read_caps = true; 41236132a3bfSAdrian Hunter 41246132a3bfSAdrian Hunter if (debug_quirks) 41256132a3bfSAdrian Hunter host->quirks = debug_quirks; 41266132a3bfSAdrian Hunter 41276132a3bfSAdrian Hunter if (debug_quirks2) 41286132a3bfSAdrian Hunter host->quirks2 = debug_quirks2; 41296132a3bfSAdrian Hunter 4130aa990722SAdrian Hunter sdhci_reset_for_all(host); 41316132a3bfSAdrian Hunter 4132b3f80b43SChunyan Zhang if (host->v4_mode) 4133b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host); 4134b3f80b43SChunyan Zhang 4135cb80a7e9SJeremy Linton device_property_read_u64(mmc_dev(host->mmc), 4136cb80a7e9SJeremy Linton "sdhci-caps-mask", &dt_caps_mask); 4137cb80a7e9SJeremy Linton device_property_read_u64(mmc_dev(host->mmc), 4138cb80a7e9SJeremy Linton "sdhci-caps", &dt_caps); 413992e0c44bSZach Brown 41406132a3bfSAdrian Hunter v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION); 41416132a3bfSAdrian Hunter host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; 41426132a3bfSAdrian Hunter 41436132a3bfSAdrian Hunter if (host->quirks & SDHCI_QUIRK_MISSING_CAPS) 41446132a3bfSAdrian Hunter return; 41456132a3bfSAdrian Hunter 414692e0c44bSZach Brown if (caps) { 414792e0c44bSZach Brown host->caps = *caps; 414892e0c44bSZach Brown } else { 414992e0c44bSZach Brown host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); 415092e0c44bSZach Brown host->caps &= ~lower_32_bits(dt_caps_mask); 415192e0c44bSZach Brown host->caps |= lower_32_bits(dt_caps); 415292e0c44bSZach Brown } 41536132a3bfSAdrian Hunter 41546132a3bfSAdrian Hunter if (host->version < SDHCI_SPEC_300) 41556132a3bfSAdrian Hunter return; 41566132a3bfSAdrian Hunter 415792e0c44bSZach Brown if (caps1) { 415892e0c44bSZach Brown host->caps1 = *caps1; 415992e0c44bSZach Brown } else { 416092e0c44bSZach Brown host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); 416192e0c44bSZach Brown host->caps1 &= ~upper_32_bits(dt_caps_mask); 416292e0c44bSZach Brown host->caps1 |= upper_32_bits(dt_caps); 416392e0c44bSZach Brown } 41646132a3bfSAdrian Hunter } 41656132a3bfSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_read_caps); 41666132a3bfSAdrian Hunter 4167a68dd9a0SChunyan Zhang static void sdhci_allocate_bounce_buffer(struct sdhci_host *host) 4168bd9b9027SLinus Walleij { 4169bd9b9027SLinus Walleij struct mmc_host *mmc = host->mmc; 4170bd9b9027SLinus Walleij unsigned int max_blocks; 4171bd9b9027SLinus Walleij unsigned int bounce_size; 4172bd9b9027SLinus Walleij int ret; 4173bd9b9027SLinus Walleij 4174bd9b9027SLinus Walleij /* 4175bd9b9027SLinus Walleij * Cap the bounce buffer at 64KB. Using a bigger bounce buffer 4176bd9b9027SLinus Walleij * has diminishing returns, this is probably because SD/MMC 4177bd9b9027SLinus Walleij * cards are usually optimized to handle this size of requests. 4178bd9b9027SLinus Walleij */ 4179bd9b9027SLinus Walleij bounce_size = SZ_64K; 4180bd9b9027SLinus Walleij /* 4181bd9b9027SLinus Walleij * Adjust downwards to maximum request size if this is less 4182bd9b9027SLinus Walleij * than our segment size, else hammer down the maximum 4183bd9b9027SLinus Walleij * request size to the maximum buffer size. 4184bd9b9027SLinus Walleij */ 4185bd9b9027SLinus Walleij if (mmc->max_req_size < bounce_size) 4186bd9b9027SLinus Walleij bounce_size = mmc->max_req_size; 4187bd9b9027SLinus Walleij max_blocks = bounce_size / 512; 4188bd9b9027SLinus Walleij 4189bd9b9027SLinus Walleij /* 4190bd9b9027SLinus Walleij * When we just support one segment, we can get significant 4191bd9b9027SLinus Walleij * speedups by the help of a bounce buffer to group scattered 4192bd9b9027SLinus Walleij * reads/writes together. 4193bd9b9027SLinus Walleij */ 4194bac53336SJisheng Zhang host->bounce_buffer = devm_kmalloc(mmc_dev(mmc), 4195bd9b9027SLinus Walleij bounce_size, 4196bd9b9027SLinus Walleij GFP_KERNEL); 4197bd9b9027SLinus Walleij if (!host->bounce_buffer) { 4198bd9b9027SLinus Walleij pr_err("%s: failed to allocate %u bytes for bounce buffer, falling back to single segments\n", 4199bd9b9027SLinus Walleij mmc_hostname(mmc), 4200bd9b9027SLinus Walleij bounce_size); 4201bd9b9027SLinus Walleij /* 4202bd9b9027SLinus Walleij * Exiting with zero here makes sure we proceed with 4203bd9b9027SLinus Walleij * mmc->max_segs == 1. 4204bd9b9027SLinus Walleij */ 4205a68dd9a0SChunyan Zhang return; 4206bd9b9027SLinus Walleij } 4207bd9b9027SLinus Walleij 4208bac53336SJisheng Zhang host->bounce_addr = dma_map_single(mmc_dev(mmc), 4209bd9b9027SLinus Walleij host->bounce_buffer, 4210bd9b9027SLinus Walleij bounce_size, 4211bd9b9027SLinus Walleij DMA_BIDIRECTIONAL); 4212bac53336SJisheng Zhang ret = dma_mapping_error(mmc_dev(mmc), host->bounce_addr); 421349036ba8STakashi Iwai if (ret) { 421449036ba8STakashi Iwai devm_kfree(mmc_dev(mmc), host->bounce_buffer); 421549036ba8STakashi Iwai host->bounce_buffer = NULL; 4216bd9b9027SLinus Walleij /* Again fall back to max_segs == 1 */ 4217a68dd9a0SChunyan Zhang return; 421849036ba8STakashi Iwai } 421949036ba8STakashi Iwai 4220bd9b9027SLinus Walleij host->bounce_buffer_size = bounce_size; 4221bd9b9027SLinus Walleij 4222bd9b9027SLinus Walleij /* Lie about this since we're bouncing */ 4223bd9b9027SLinus Walleij mmc->max_segs = max_blocks; 4224bd9b9027SLinus Walleij mmc->max_seg_size = bounce_size; 4225bd9b9027SLinus Walleij mmc->max_req_size = bounce_size; 4226bd9b9027SLinus Walleij 4227bd9b9027SLinus Walleij pr_info("%s bounce up to %u segments into one, max segment size %u bytes\n", 4228bd9b9027SLinus Walleij mmc_hostname(mmc), max_blocks, bounce_size); 4229bd9b9027SLinus Walleij } 4230bd9b9027SLinus Walleij 4231685e444bSChunyan Zhang static inline bool sdhci_can_64bit_dma(struct sdhci_host *host) 4232685e444bSChunyan Zhang { 4233685e444bSChunyan Zhang /* 4234685e444bSChunyan Zhang * According to SD Host Controller spec v4.10, bit[27] added from 4235685e444bSChunyan Zhang * version 4.10 in Capabilities Register is used as 64-bit System 4236685e444bSChunyan Zhang * Address support for V4 mode. 4237685e444bSChunyan Zhang */ 4238685e444bSChunyan Zhang if (host->version >= SDHCI_SPEC_410 && host->v4_mode) 4239685e444bSChunyan Zhang return host->caps & SDHCI_CAN_64BIT_V4; 4240685e444bSChunyan Zhang 4241685e444bSChunyan Zhang return host->caps & SDHCI_CAN_64BIT; 4242685e444bSChunyan Zhang } 4243685e444bSChunyan Zhang 424452f5336dSAdrian Hunter int sdhci_setup_host(struct sdhci_host *host) 4245b8c86fc5SPierre Ossman { 4246b8c86fc5SPierre Ossman struct mmc_host *mmc; 4247f2119df6SArindam Nath u32 max_current_caps; 4248f2119df6SArindam Nath unsigned int ocr_avail; 4249f5fa92e5SAdrian Hunter unsigned int override_timeout_clk; 425059241757SDong Aisheng u32 max_clk; 4251907be2a6SDan Carpenter int ret = 0; 42520fcb031eSVijay Viswanath bool enable_vqmmc = false; 4253b8c86fc5SPierre Ossman 4254b8c86fc5SPierre Ossman WARN_ON(host == NULL); 4255b8c86fc5SPierre Ossman if (host == NULL) 4256b8c86fc5SPierre Ossman return -EINVAL; 4257b8c86fc5SPierre Ossman 4258b8c86fc5SPierre Ossman mmc = host->mmc; 4259b8c86fc5SPierre Ossman 4260efba142bSJon Hunter /* 4261efba142bSJon Hunter * If there are external regulators, get them. Note this must be done 4262efba142bSJon Hunter * early before resetting the host and reading the capabilities so that 4263efba142bSJon Hunter * the host can take the appropriate action if regulators are not 4264efba142bSJon Hunter * available. 4265efba142bSJon Hunter */ 42660fcb031eSVijay Viswanath if (!mmc->supply.vqmmc) { 4267efba142bSJon Hunter ret = mmc_regulator_get_supply(mmc); 42682a63303dSWolfram Sang if (ret) 4269efba142bSJon Hunter return ret; 42700fcb031eSVijay Viswanath enable_vqmmc = true; 42710fcb031eSVijay Viswanath } 4272efba142bSJon Hunter 427306ebc601SShawn Lin DBG("Version: 0x%08x | Present: 0x%08x\n", 427406ebc601SShawn Lin sdhci_readw(host, SDHCI_HOST_VERSION), 427506ebc601SShawn Lin sdhci_readl(host, SDHCI_PRESENT_STATE)); 427606ebc601SShawn Lin DBG("Caps: 0x%08x | Caps_1: 0x%08x\n", 427706ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES), 427806ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES_1)); 427906ebc601SShawn Lin 42806132a3bfSAdrian Hunter sdhci_read_caps(host); 4281b8c86fc5SPierre Ossman 4282f5fa92e5SAdrian Hunter override_timeout_clk = host->timeout_clk; 4283f5fa92e5SAdrian Hunter 428418da1990SChunyan Zhang if (host->version > SDHCI_SPEC_420) { 42852e4456f0SMarek Vasut pr_err("%s: Unknown controller version (%d). You may experience problems.\n", 42862e4456f0SMarek Vasut mmc_hostname(mmc), host->version); 42871c6a0718SPierre Ossman } 42881c6a0718SPierre Ossman 4289b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 4290a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 429128da3589SAdrian Hunter else if (!(host->caps & SDHCI_CAN_DO_SDMA)) 4292a13abc7bSRichard Röjfors DBG("Controller doesn't have SDMA capability\n"); 42931c6a0718SPierre Ossman else 4294a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 42951c6a0718SPierre Ossman 4296b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 4297a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA)) { 4298cee687ceSRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 4299a13abc7bSRichard Röjfors host->flags &= ~SDHCI_USE_SDMA; 43007c168e3dSFeng Tang } 43017c168e3dSFeng Tang 4302f2119df6SArindam Nath if ((host->version >= SDHCI_SPEC_200) && 430328da3589SAdrian Hunter (host->caps & SDHCI_CAN_DO_ADMA2)) 43042134a922SPierre Ossman host->flags |= SDHCI_USE_ADMA; 43052134a922SPierre Ossman 43062134a922SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 43072134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 43082134a922SPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 43092134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 43102134a922SPierre Ossman } 43112134a922SPierre Ossman 4312685e444bSChunyan Zhang if (sdhci_can_64bit_dma(host)) 4313e57a5f61SAdrian Hunter host->flags |= SDHCI_USE_64_BIT_DMA; 4314e57a5f61SAdrian Hunter 431518e762e3SChunyan Zhang if (host->use_external_dma) { 431618e762e3SChunyan Zhang ret = sdhci_external_dma_init(host); 431718e762e3SChunyan Zhang if (ret == -EPROBE_DEFER) 431818e762e3SChunyan Zhang goto unreg; 431918e762e3SChunyan Zhang /* 432018e762e3SChunyan Zhang * Fall back to use the DMA/PIO integrated in standard SDHCI 432118e762e3SChunyan Zhang * instead of external DMA devices. 432218e762e3SChunyan Zhang */ 432318e762e3SChunyan Zhang else if (ret) 432418e762e3SChunyan Zhang sdhci_switch_external_dma(host, false); 432518e762e3SChunyan Zhang /* Disable internal DMA sources */ 432618e762e3SChunyan Zhang else 432718e762e3SChunyan Zhang host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 432818e762e3SChunyan Zhang } 432918e762e3SChunyan Zhang 4330a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 43314ee7dde4SAdrian Hunter if (host->ops->set_dma_mask) 43324ee7dde4SAdrian Hunter ret = host->ops->set_dma_mask(host); 43334ee7dde4SAdrian Hunter else 43347b91369bSAlexandre Courbot ret = sdhci_set_dma_mask(host); 43357b91369bSAlexandre Courbot 43367b91369bSAlexandre Courbot if (!ret && host->ops->enable_dma) 43377b91369bSAlexandre Courbot ret = host->ops->enable_dma(host); 43387b91369bSAlexandre Courbot 43397b91369bSAlexandre Courbot if (ret) { 43406606110dSJoe Perches pr_warn("%s: No suitable DMA available - falling back to PIO\n", 4341b8c86fc5SPierre Ossman mmc_hostname(mmc)); 43427b91369bSAlexandre Courbot host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 43437b91369bSAlexandre Courbot 43447b91369bSAlexandre Courbot ret = 0; 43451c6a0718SPierre Ossman } 4346b8c86fc5SPierre Ossman } 43471c6a0718SPierre Ossman 4348917a0c52SChunyan Zhang /* SDMA does not support 64-bit DMA if v4 mode not set */ 4349917a0c52SChunyan Zhang if ((host->flags & SDHCI_USE_64_BIT_DMA) && !host->v4_mode) 4350e57a5f61SAdrian Hunter host->flags &= ~SDHCI_USE_SDMA; 4351e57a5f61SAdrian Hunter 43522134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 4353e66e61cbSRussell King dma_addr_t dma; 4354e66e61cbSRussell King void *buf; 4355e66e61cbSRussell King 4356a663f64bSVeerabhadrarao Badiganti if (!(host->flags & SDHCI_USE_64_BIT_DMA)) 4357a663f64bSVeerabhadrarao Badiganti host->alloc_desc_sz = SDHCI_ADMA2_32_DESC_SZ; 4358a663f64bSVeerabhadrarao Badiganti else if (!host->alloc_desc_sz) 4359a663f64bSVeerabhadrarao Badiganti host->alloc_desc_sz = SDHCI_ADMA2_64_DESC_SZ(host); 4360a663f64bSVeerabhadrarao Badiganti 4361a663f64bSVeerabhadrarao Badiganti host->desc_sz = host->alloc_desc_sz; 4362a663f64bSVeerabhadrarao Badiganti host->adma_table_sz = host->adma_table_cnt * host->desc_sz; 4363e66e61cbSRussell King 436404a5ae6fSAdrian Hunter host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN; 4365685e444bSChunyan Zhang /* 4366685e444bSChunyan Zhang * Use zalloc to zero the reserved high 32-bits of 128-bit 4367685e444bSChunyan Zhang * descriptors so that they never need to be written. 4368685e444bSChunyan Zhang */ 4369750afb08SLuis Chamberlain buf = dma_alloc_coherent(mmc_dev(mmc), 4370750afb08SLuis Chamberlain host->align_buffer_sz + host->adma_table_sz, 4371750afb08SLuis Chamberlain &dma, GFP_KERNEL); 4372e66e61cbSRussell King if (!buf) { 43736606110dSJoe Perches pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", 43742134a922SPierre Ossman mmc_hostname(mmc)); 43752134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 4376e66e61cbSRussell King } else if ((dma + host->align_buffer_sz) & 4377e66e61cbSRussell King (SDHCI_ADMA2_DESC_ALIGN - 1)) { 43786606110dSJoe Perches pr_warn("%s: unable to allocate aligned ADMA descriptor\n", 4379d1e49f77SRussell King mmc_hostname(mmc)); 4380d1e49f77SRussell King host->flags &= ~SDHCI_USE_ADMA; 4381e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 4382e66e61cbSRussell King host->adma_table_sz, buf, dma); 4383e66e61cbSRussell King } else { 4384e66e61cbSRussell King host->align_buffer = buf; 4385e66e61cbSRussell King host->align_addr = dma; 4386edd63fccSRussell King 4387e66e61cbSRussell King host->adma_table = buf + host->align_buffer_sz; 4388e66e61cbSRussell King host->adma_addr = dma + host->align_buffer_sz; 4389e66e61cbSRussell King } 43902134a922SPierre Ossman } 43912134a922SPierre Ossman 43927659150cSPierre Ossman /* 43937659150cSPierre Ossman * If we use DMA, then it's up to the caller to set the DMA 43947659150cSPierre Ossman * mask, but PIO does not need the hw shim so we set a new 43957659150cSPierre Ossman * mask here in that case. 43967659150cSPierre Ossman */ 4397a13abc7bSRichard Röjfors if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) { 43987659150cSPierre Ossman host->dma_mask = DMA_BIT_MASK(64); 43994e743f1fSMarkus Mayer mmc_dev(mmc)->dma_mask = &host->dma_mask; 44007659150cSPierre Ossman } 44011c6a0718SPierre Ossman 4402c4687d5fSZhangfei Gao if (host->version >= SDHCI_SPEC_300) 4403a8e809ecSMasahiro Yamada host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps); 4404c4687d5fSZhangfei Gao else 4405a8e809ecSMasahiro Yamada host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps); 4406c4687d5fSZhangfei Gao 44074240ff0aSBen Dooks host->max_clk *= 1000000; 4408f27f47efSAnton Vorontsov if (host->max_clk == 0 || host->quirks & 4409f27f47efSAnton Vorontsov SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { 44104240ff0aSBen Dooks if (!host->ops->get_max_clock) { 44112e4456f0SMarek Vasut pr_err("%s: Hardware doesn't specify base clock frequency.\n", 44122e4456f0SMarek Vasut mmc_hostname(mmc)); 4413eb5c20deSAdrian Hunter ret = -ENODEV; 4414eb5c20deSAdrian Hunter goto undma; 44151c6a0718SPierre Ossman } 44164240ff0aSBen Dooks host->max_clk = host->ops->get_max_clock(host); 44174240ff0aSBen Dooks } 44181c6a0718SPierre Ossman 44191c6a0718SPierre Ossman /* 4420c3ed3877SArindam Nath * In case of Host Controller v3.00, find out whether clock 4421c3ed3877SArindam Nath * multiplier is supported. 4422c3ed3877SArindam Nath */ 4423a8e809ecSMasahiro Yamada host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1); 4424c3ed3877SArindam Nath 4425c3ed3877SArindam Nath /* 4426c3ed3877SArindam Nath * In case the value in Clock Multiplier is 0, then programmable 4427c3ed3877SArindam Nath * clock mode is not supported, otherwise the actual clock 4428c3ed3877SArindam Nath * multiplier is one more than the value of Clock Multiplier 4429c3ed3877SArindam Nath * in the Capabilities Register. 4430c3ed3877SArindam Nath */ 4431c3ed3877SArindam Nath if (host->clk_mul) 4432c3ed3877SArindam Nath host->clk_mul += 1; 4433c3ed3877SArindam Nath 4434c3ed3877SArindam Nath /* 44351c6a0718SPierre Ossman * Set host parameters. 44361c6a0718SPierre Ossman */ 443759241757SDong Aisheng max_clk = host->max_clk; 443859241757SDong Aisheng 4439ce5f036bSMarek Szyprowski if (host->ops->get_min_clock) 4440a9e58f25SAnton Vorontsov mmc->f_min = host->ops->get_min_clock(host); 4441c3ed3877SArindam Nath else if (host->version >= SDHCI_SPEC_300) { 44422a187d03SMichał Mirosław if (host->clk_mul) 444359241757SDong Aisheng max_clk = host->max_clk * host->clk_mul; 44442a187d03SMichał Mirosław /* 44452a187d03SMichał Mirosław * Divided Clock Mode minimum clock rate is always less than 44462a187d03SMichał Mirosław * Programmable Clock Mode minimum clock rate. 44472a187d03SMichał Mirosław */ 44480397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; 4449c3ed3877SArindam Nath } else 44500397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; 445115ec4461SPhilip Rakity 4452d310ae49SAdrian Hunter if (!mmc->f_max || mmc->f_max > max_clk) 445359241757SDong Aisheng mmc->f_max = max_clk; 445459241757SDong Aisheng 445528aab053SAisheng Dong if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { 4456a8e809ecSMasahiro Yamada host->timeout_clk = FIELD_GET(SDHCI_TIMEOUT_CLK_MASK, host->caps); 44578cc35289SShawn Lin 44588cc35289SShawn Lin if (host->caps & SDHCI_TIMEOUT_CLK_UNIT) 44598cc35289SShawn Lin host->timeout_clk *= 1000; 44608cc35289SShawn Lin 4461272308caSAndy Shevchenko if (host->timeout_clk == 0) { 44628cc35289SShawn Lin if (!host->ops->get_timeout_clock) { 446328aab053SAisheng Dong pr_err("%s: Hardware doesn't specify timeout clock frequency.\n", 446428aab053SAisheng Dong mmc_hostname(mmc)); 4465eb5c20deSAdrian Hunter ret = -ENODEV; 4466eb5c20deSAdrian Hunter goto undma; 4467272308caSAndy Shevchenko } 446828aab053SAisheng Dong 44698cc35289SShawn Lin host->timeout_clk = 44708cc35289SShawn Lin DIV_ROUND_UP(host->ops->get_timeout_clock(host), 44718cc35289SShawn Lin 1000); 44728cc35289SShawn Lin } 4473272308caSAndy Shevchenko 447499513624SAdrian Hunter if (override_timeout_clk) 447599513624SAdrian Hunter host->timeout_clk = override_timeout_clk; 447699513624SAdrian Hunter 4477a6ff5aebSAisheng Dong mmc->max_busy_timeout = host->ops->get_max_timeout_count ? 4478a6ff5aebSAisheng Dong host->ops->get_max_timeout_count(host) : 1 << 27; 4479a6ff5aebSAisheng Dong mmc->max_busy_timeout /= host->timeout_clk; 448028aab053SAisheng Dong } 448158d1246dSAdrian Hunter 4482a999fd93SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT && 4483a999fd93SAdrian Hunter !host->ops->get_max_timeout_count) 4484a999fd93SAdrian Hunter mmc->max_busy_timeout = 0; 4485a999fd93SAdrian Hunter 44861be64c79SUlf Hansson mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_CMD23; 4487781e989cSRussell King mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; 4488e89d456fSAndrei Warkentin 4489e89d456fSAndrei Warkentin if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) 4490e89d456fSAndrei Warkentin host->flags |= SDHCI_AUTO_CMD12; 44915fe23c7fSAnton Vorontsov 44927ed71a9dSChunyan Zhang /* 44937ed71a9dSChunyan Zhang * For v3 mode, Auto-CMD23 stuff only works in ADMA or PIO. 44947ed71a9dSChunyan Zhang * For v4 mode, SDMA may use Auto-CMD23 as well. 44957ed71a9dSChunyan Zhang */ 44964f3d3e9bSAndrei Warkentin if ((host->version >= SDHCI_SPEC_300) && 44978edf6371SAndrei Warkentin ((host->flags & SDHCI_USE_ADMA) || 44987ed71a9dSChunyan Zhang !(host->flags & SDHCI_USE_SDMA) || host->v4_mode) && 44993bfa6f03SScott Branden !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN)) { 45008edf6371SAndrei Warkentin host->flags |= SDHCI_AUTO_CMD23; 4501f421865dSAdrian Hunter DBG("Auto-CMD23 available\n"); 45028edf6371SAndrei Warkentin } else { 4503f421865dSAdrian Hunter DBG("Auto-CMD23 unavailable\n"); 45048edf6371SAndrei Warkentin } 45058edf6371SAndrei Warkentin 450615ec4461SPhilip Rakity /* 450715ec4461SPhilip Rakity * A controller may support 8-bit width, but the board itself 450815ec4461SPhilip Rakity * might not have the pins brought out. Boards that support 450915ec4461SPhilip Rakity * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in 451015ec4461SPhilip Rakity * their platform code before calling sdhci_add_host(), and we 451115ec4461SPhilip Rakity * won't assume 8-bit width for hosts without that CAP. 451215ec4461SPhilip Rakity */ 45135fe23c7fSAnton Vorontsov if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) 451415ec4461SPhilip Rakity mmc->caps |= MMC_CAP_4_BIT_DATA; 45151c6a0718SPierre Ossman 451663ef5d8cSJerry Huang if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) 451763ef5d8cSJerry Huang mmc->caps &= ~MMC_CAP_CMD23; 451863ef5d8cSJerry Huang 451928da3589SAdrian Hunter if (host->caps & SDHCI_CAN_DO_HISPD) 4520a29e7e18SZhangfei Gao mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; 45211c6a0718SPierre Ossman 4522176d1ed4SJaehoon Chung if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 4523860951c5SJaehoon Chung mmc_card_is_removable(mmc) && 4524d2f025b0SJisheng Zhang mmc_gpio_get_cd(mmc) < 0) 452568d1fb7eSAnton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL; 452668d1fb7eSAnton Vorontsov 45273a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 45280fcb031eSVijay Viswanath if (enable_vqmmc) { 45293a48edc4STim Kryger ret = regulator_enable(mmc->supply.vqmmc); 45300fcb031eSVijay Viswanath host->sdhci_core_to_disable_vqmmc = !ret; 45310fcb031eSVijay Viswanath } 45321b5190c2SStefan Agner 45331b5190c2SStefan Agner /* If vqmmc provides no 1.8V signalling, then there's no UHS */ 45343a48edc4STim Kryger if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000, 4535cec2e216SKevin Liu 1950000)) 453628da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | 45378363c374SKevin Liu SDHCI_SUPPORT_SDR50 | 45386231f3deSPhilip Rakity SDHCI_SUPPORT_DDR50); 45391b5190c2SStefan Agner 45401b5190c2SStefan Agner /* In eMMC case vqmmc might be a fixed 1.8V regulator */ 45411b5190c2SStefan Agner if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000, 45421b5190c2SStefan Agner 3600000)) 45431b5190c2SStefan Agner host->flags &= ~SDHCI_SIGNALING_330; 45441b5190c2SStefan Agner 4545a3361abaSChris Ball if (ret) { 4546a3361abaSChris Ball pr_warn("%s: Failed to enable vqmmc regulator: %d\n", 4547a3361abaSChris Ball mmc_hostname(mmc), ret); 45484bb74313SAdrian Hunter mmc->supply.vqmmc = ERR_PTR(-EINVAL); 4549a3361abaSChris Ball } 45503debc24fSVeerabhadrarao Badiganti 45518363c374SKevin Liu } 45526231f3deSPhilip Rakity 455328da3589SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) { 455428da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | 45556a66180aSDaniel Drake SDHCI_SUPPORT_DDR50); 4556c16bc9a7SKishon Vijay Abraham I /* 4557c16bc9a7SKishon Vijay Abraham I * The SDHCI controller in a SoC might support HS200/HS400 4558c16bc9a7SKishon Vijay Abraham I * (indicated using mmc-hs200-1_8v/mmc-hs400-1_8v dt property), 4559c16bc9a7SKishon Vijay Abraham I * but if the board is modeled such that the IO lines are not 4560c16bc9a7SKishon Vijay Abraham I * connected to 1.8v then HS200/HS400 cannot be supported. 4561c16bc9a7SKishon Vijay Abraham I * Disable HS200/HS400 if the board does not have 1.8v connected 4562c16bc9a7SKishon Vijay Abraham I * to the IO lines. (Applicable for other modes in 1.8v) 4563c16bc9a7SKishon Vijay Abraham I */ 4564c16bc9a7SKishon Vijay Abraham I mmc->caps2 &= ~(MMC_CAP2_HSX00_1_8V | MMC_CAP2_HS400_ES); 4565c16bc9a7SKishon Vijay Abraham I mmc->caps &= ~(MMC_CAP_1_8V_DDR | MMC_CAP_UHS); 456628da3589SAdrian Hunter } 45676a66180aSDaniel Drake 45684188bba0SAl Cooper /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ 456928da3589SAdrian Hunter if (host->caps1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | 45704188bba0SAl Cooper SDHCI_SUPPORT_DDR50)) 4571f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; 4572f2119df6SArindam Nath 4573f2119df6SArindam Nath /* SDR104 supports also implies SDR50 support */ 457428da3589SAdrian Hunter if (host->caps1 & SDHCI_SUPPORT_SDR104) { 4575f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; 4576156e14b1SGiuseppe CAVALLARO /* SD3.0: SDR104 is supported so (for eMMC) the caps2 4577156e14b1SGiuseppe CAVALLARO * field can be promoted to support HS200. 4578156e14b1SGiuseppe CAVALLARO */ 4579549c0b18SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) 4580156e14b1SGiuseppe CAVALLARO mmc->caps2 |= MMC_CAP2_HS200; 458128da3589SAdrian Hunter } else if (host->caps1 & SDHCI_SUPPORT_SDR50) { 4582f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR50; 458328da3589SAdrian Hunter } 4584f2119df6SArindam Nath 4585e9fb05d5SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 && 458628da3589SAdrian Hunter (host->caps1 & SDHCI_SUPPORT_HS400)) 4587e9fb05d5SAdrian Hunter mmc->caps2 |= MMC_CAP2_HS400; 4588e9fb05d5SAdrian Hunter 4589549c0b18SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) && 4590549c0b18SAdrian Hunter (IS_ERR(mmc->supply.vqmmc) || 4591549c0b18SAdrian Hunter !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000, 4592549c0b18SAdrian Hunter 1300000))) 4593549c0b18SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V; 4594549c0b18SAdrian Hunter 459528da3589SAdrian Hunter if ((host->caps1 & SDHCI_SUPPORT_DDR50) && 45969107ebbfSMicky Ching !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) 4597f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_DDR50; 4598f2119df6SArindam Nath 4599069c9f14SGirish K S /* Does the host need tuning for SDR50? */ 460028da3589SAdrian Hunter if (host->caps1 & SDHCI_USE_SDR50_TUNING) 4601b513ea25SArindam Nath host->flags |= SDHCI_SDR50_NEEDS_TUNING; 4602b513ea25SArindam Nath 4603d6d50a15SArindam Nath /* Driver Type(s) (A, C, D) supported by the host */ 460428da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_A) 4605d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_A; 460628da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_C) 4607d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_C; 460828da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_D) 4609d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_D; 4610d6d50a15SArindam Nath 4611cf2b5eeaSArindam Nath /* Initial value for re-tuning timer count */ 4612a8e809ecSMasahiro Yamada host->tuning_count = FIELD_GET(SDHCI_RETUNING_TIMER_COUNT_MASK, 4613a8e809ecSMasahiro Yamada host->caps1); 4614cf2b5eeaSArindam Nath 4615cf2b5eeaSArindam Nath /* 4616cf2b5eeaSArindam Nath * In case Re-tuning Timer is not disabled, the actual value of 4617cf2b5eeaSArindam Nath * re-tuning timer will be 2 ^ (n - 1). 4618cf2b5eeaSArindam Nath */ 4619cf2b5eeaSArindam Nath if (host->tuning_count) 4620cf2b5eeaSArindam Nath host->tuning_count = 1 << (host->tuning_count - 1); 4621cf2b5eeaSArindam Nath 4622cf2b5eeaSArindam Nath /* Re-tuning mode supported by the Host Controller */ 4623a8e809ecSMasahiro Yamada host->tuning_mode = FIELD_GET(SDHCI_RETUNING_MODE_MASK, host->caps1); 4624cf2b5eeaSArindam Nath 46258f230f45STakashi Iwai ocr_avail = 0; 4626bad37e1aSPhilip Rakity 4627f2119df6SArindam Nath /* 4628f2119df6SArindam Nath * According to SD Host Controller spec v3.00, if the Host System 4629f2119df6SArindam Nath * can afford more than 150mA, Host Driver should set XPC to 1. Also 4630f2119df6SArindam Nath * the value is meaningful only if Voltage Support in the Capabilities 4631f2119df6SArindam Nath * register is set. The actual current value is 4 times the register 4632f2119df6SArindam Nath * value. 4633f2119df6SArindam Nath */ 4634f2119df6SArindam Nath max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); 46353a48edc4STim Kryger if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) { 4636ae906037SChuanxiao.Dong int curr = regulator_get_current_limit(mmc->supply.vmmc); 4637bad37e1aSPhilip Rakity if (curr > 0) { 4638bad37e1aSPhilip Rakity 4639bad37e1aSPhilip Rakity /* convert to SDHCI_MAX_CURRENT format */ 4640bad37e1aSPhilip Rakity curr = curr/1000; /* convert to mA */ 4641bad37e1aSPhilip Rakity curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER; 4642bad37e1aSPhilip Rakity 4643bad37e1aSPhilip Rakity curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT); 4644bad37e1aSPhilip Rakity max_current_caps = 4645804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, curr) | 4646804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, curr) | 4647804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, curr); 4648bad37e1aSPhilip Rakity } 4649bad37e1aSPhilip Rakity } 4650f2119df6SArindam Nath 465128da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_330) { 46528f230f45STakashi Iwai ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; 4653f2119df6SArindam Nath 4654804a65b3SMasahiro Yamada mmc->max_current_330 = FIELD_GET(SDHCI_MAX_CURRENT_330_MASK, 4655804a65b3SMasahiro Yamada max_current_caps) * 4656f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4657f2119df6SArindam Nath } 465828da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_300) { 46598f230f45STakashi Iwai ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; 4660f2119df6SArindam Nath 4661804a65b3SMasahiro Yamada mmc->max_current_300 = FIELD_GET(SDHCI_MAX_CURRENT_300_MASK, 4662804a65b3SMasahiro Yamada max_current_caps) * 4663f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4664f2119df6SArindam Nath } 466528da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_180) { 46668f230f45STakashi Iwai ocr_avail |= MMC_VDD_165_195; 46678f230f45STakashi Iwai 4668804a65b3SMasahiro Yamada mmc->max_current_180 = FIELD_GET(SDHCI_MAX_CURRENT_180_MASK, 4669804a65b3SMasahiro Yamada max_current_caps) * 4670f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4671f2119df6SArindam Nath } 4672f2119df6SArindam Nath 46735fd26c7eSUlf Hansson /* If OCR set by host, use it instead. */ 46745fd26c7eSUlf Hansson if (host->ocr_mask) 46755fd26c7eSUlf Hansson ocr_avail = host->ocr_mask; 46765fd26c7eSUlf Hansson 46775fd26c7eSUlf Hansson /* If OCR set by external regulators, give it highest prio. */ 46783a48edc4STim Kryger if (mmc->ocr_avail) 467952221610STim Kryger ocr_avail = mmc->ocr_avail; 46803a48edc4STim Kryger 46818f230f45STakashi Iwai mmc->ocr_avail = ocr_avail; 46828f230f45STakashi Iwai mmc->ocr_avail_sdio = ocr_avail; 46838f230f45STakashi Iwai if (host->ocr_avail_sdio) 46848f230f45STakashi Iwai mmc->ocr_avail_sdio &= host->ocr_avail_sdio; 46858f230f45STakashi Iwai mmc->ocr_avail_sd = ocr_avail; 46868f230f45STakashi Iwai if (host->ocr_avail_sd) 46878f230f45STakashi Iwai mmc->ocr_avail_sd &= host->ocr_avail_sd; 46888f230f45STakashi Iwai else /* normal SD controllers don't support 1.8V */ 46898f230f45STakashi Iwai mmc->ocr_avail_sd &= ~MMC_VDD_165_195; 46908f230f45STakashi Iwai mmc->ocr_avail_mmc = ocr_avail; 46918f230f45STakashi Iwai if (host->ocr_avail_mmc) 46928f230f45STakashi Iwai mmc->ocr_avail_mmc &= host->ocr_avail_mmc; 46931c6a0718SPierre Ossman 46941c6a0718SPierre Ossman if (mmc->ocr_avail == 0) { 46952e4456f0SMarek Vasut pr_err("%s: Hardware doesn't report any support voltages.\n", 46962e4456f0SMarek Vasut mmc_hostname(mmc)); 4697eb5c20deSAdrian Hunter ret = -ENODEV; 4698eb5c20deSAdrian Hunter goto unreg; 46991c6a0718SPierre Ossman } 47001c6a0718SPierre Ossman 47018cb851a4SAdrian Hunter if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | 47028cb851a4SAdrian Hunter MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | 47038cb851a4SAdrian Hunter MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) || 47048cb851a4SAdrian Hunter (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V))) 47058cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_180; 47068cb851a4SAdrian Hunter 47078cb851a4SAdrian Hunter if (mmc->caps2 & MMC_CAP2_HSX00_1_2V) 47088cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_120; 47098cb851a4SAdrian Hunter 47101c6a0718SPierre Ossman spin_lock_init(&host->lock); 47111c6a0718SPierre Ossman 47121c6a0718SPierre Ossman /* 4713ac00531dSAdrian Hunter * Maximum number of sectors in one transfer. Limited by SDMA boundary 4714ac00531dSAdrian Hunter * size (512KiB). Note some tuning modes impose a 4MiB limit, but this 4715ac00531dSAdrian Hunter * is less anyway. 47161c6a0718SPierre Ossman */ 47171c6a0718SPierre Ossman mmc->max_req_size = 524288; 47181c6a0718SPierre Ossman 47191c6a0718SPierre Ossman /* 4720250dcd11SUlf Hansson * Maximum number of segments. Depends on if the hardware 4721250dcd11SUlf Hansson * can do scatter/gather or not. 4722250dcd11SUlf Hansson */ 4723250dcd11SUlf Hansson if (host->flags & SDHCI_USE_ADMA) { 4724250dcd11SUlf Hansson mmc->max_segs = SDHCI_MAX_SEGS; 4725250dcd11SUlf Hansson } else if (host->flags & SDHCI_USE_SDMA) { 4726250dcd11SUlf Hansson mmc->max_segs = 1; 472766e8d3b8SChristoph Hellwig mmc->max_req_size = min_t(size_t, mmc->max_req_size, 472866e8d3b8SChristoph Hellwig dma_max_mapping_size(mmc_dev(mmc))); 4729250dcd11SUlf Hansson } else { /* PIO */ 4730250dcd11SUlf Hansson mmc->max_segs = SDHCI_MAX_SEGS; 4731250dcd11SUlf Hansson } 4732250dcd11SUlf Hansson 4733250dcd11SUlf Hansson /* 47341c6a0718SPierre Ossman * Maximum segment size. Could be one segment with the maximum number 47352134a922SPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 47362134a922SPierre Ossman * be larger than 64 KiB though. 47371c6a0718SPierre Ossman */ 473830652aa3SOlof Johansson if (host->flags & SDHCI_USE_ADMA) { 47393d7c194bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) { 47403d7c194bSAdrian Hunter host->max_adma = 65532; /* 32-bit alignment */ 474130652aa3SOlof Johansson mmc->max_seg_size = 65535; 47423d7c194bSAdrian Hunter } else { 474330652aa3SOlof Johansson mmc->max_seg_size = 65536; 47443d7c194bSAdrian Hunter } 474530652aa3SOlof Johansson } else { 47461c6a0718SPierre Ossman mmc->max_seg_size = mmc->max_req_size; 474730652aa3SOlof Johansson } 47481c6a0718SPierre Ossman 47491c6a0718SPierre Ossman /* 47501c6a0718SPierre Ossman * Maximum block size. This varies from controller to controller and 47511c6a0718SPierre Ossman * is specified in the capabilities register. 47521c6a0718SPierre Ossman */ 47530633f654SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { 47540633f654SAnton Vorontsov mmc->max_blk_size = 2; 47550633f654SAnton Vorontsov } else { 475628da3589SAdrian Hunter mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >> 47570633f654SAnton Vorontsov SDHCI_MAX_BLOCK_SHIFT; 47581c6a0718SPierre Ossman if (mmc->max_blk_size >= 3) { 47596606110dSJoe Perches pr_warn("%s: Invalid maximum block size, assuming 512 bytes\n", 47606606110dSJoe Perches mmc_hostname(mmc)); 47610633f654SAnton Vorontsov mmc->max_blk_size = 0; 47620633f654SAnton Vorontsov } 47630633f654SAnton Vorontsov } 47640633f654SAnton Vorontsov 47651c6a0718SPierre Ossman mmc->max_blk_size = 512 << mmc->max_blk_size; 47661c6a0718SPierre Ossman 47671c6a0718SPierre Ossman /* 47681c6a0718SPierre Ossman * Maximum block count. 47691c6a0718SPierre Ossman */ 47701388eefdSBen Dooks mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; 47711c6a0718SPierre Ossman 4772a68dd9a0SChunyan Zhang if (mmc->max_segs == 1) 4773bd9b9027SLinus Walleij /* This may alter mmc->*_blk_* parameters */ 4774a68dd9a0SChunyan Zhang sdhci_allocate_bounce_buffer(host); 4775bd9b9027SLinus Walleij 477652f5336dSAdrian Hunter return 0; 477752f5336dSAdrian Hunter 477852f5336dSAdrian Hunter unreg: 47790fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 478052f5336dSAdrian Hunter regulator_disable(mmc->supply.vqmmc); 478152f5336dSAdrian Hunter undma: 478252f5336dSAdrian Hunter if (host->align_buffer) 478352f5336dSAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 478452f5336dSAdrian Hunter host->adma_table_sz, host->align_buffer, 478552f5336dSAdrian Hunter host->align_addr); 478652f5336dSAdrian Hunter host->adma_table = NULL; 478752f5336dSAdrian Hunter host->align_buffer = NULL; 478852f5336dSAdrian Hunter 478952f5336dSAdrian Hunter return ret; 479052f5336dSAdrian Hunter } 479152f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_setup_host); 479252f5336dSAdrian Hunter 47934180ffa8SAdrian Hunter void sdhci_cleanup_host(struct sdhci_host *host) 47944180ffa8SAdrian Hunter { 47954180ffa8SAdrian Hunter struct mmc_host *mmc = host->mmc; 47964180ffa8SAdrian Hunter 47970fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 47984180ffa8SAdrian Hunter regulator_disable(mmc->supply.vqmmc); 47994180ffa8SAdrian Hunter 48004180ffa8SAdrian Hunter if (host->align_buffer) 48014180ffa8SAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 48024180ffa8SAdrian Hunter host->adma_table_sz, host->align_buffer, 48034180ffa8SAdrian Hunter host->align_addr); 480418e762e3SChunyan Zhang 480518e762e3SChunyan Zhang if (host->use_external_dma) 480618e762e3SChunyan Zhang sdhci_external_dma_release(host); 480718e762e3SChunyan Zhang 48084180ffa8SAdrian Hunter host->adma_table = NULL; 48094180ffa8SAdrian Hunter host->align_buffer = NULL; 48104180ffa8SAdrian Hunter } 48114180ffa8SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cleanup_host); 48124180ffa8SAdrian Hunter 481352f5336dSAdrian Hunter int __sdhci_add_host(struct sdhci_host *host) 481452f5336dSAdrian Hunter { 4815c07a48c2SAdrian Hunter unsigned int flags = WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI; 481652f5336dSAdrian Hunter struct mmc_host *mmc = host->mmc; 481752f5336dSAdrian Hunter int ret; 481852f5336dSAdrian Hunter 48192b17b8d7SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_CQE) && 48202b17b8d7SAdrian Hunter (host->quirks & SDHCI_QUIRK_BROKEN_CQE)) { 48212b17b8d7SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_CQE; 48222b17b8d7SAdrian Hunter mmc->cqe_ops = NULL; 48232b17b8d7SAdrian Hunter } 48242b17b8d7SAdrian Hunter 4825c07a48c2SAdrian Hunter host->complete_wq = alloc_workqueue("sdhci", flags, 0); 4826c07a48c2SAdrian Hunter if (!host->complete_wq) 4827c07a48c2SAdrian Hunter return -ENOMEM; 4828c07a48c2SAdrian Hunter 4829c07a48c2SAdrian Hunter INIT_WORK(&host->complete_work, sdhci_complete_work); 48301c6a0718SPierre Ossman 48312ee4f620SKees Cook timer_setup(&host->timer, sdhci_timeout_timer, 0); 48322ee4f620SKees Cook timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0); 48331c6a0718SPierre Ossman 4834b513ea25SArindam Nath init_waitqueue_head(&host->buf_ready_int); 4835b513ea25SArindam Nath 48362af502caSShawn Guo sdhci_init(host, 0); 48372af502caSShawn Guo 4838781e989cSRussell King ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, 4839781e989cSRussell King IRQF_SHARED, mmc_hostname(mmc), host); 48400fc81ee3SMark Brown if (ret) { 48410fc81ee3SMark Brown pr_err("%s: Failed to request IRQ %d: %d\n", 48420fc81ee3SMark Brown mmc_hostname(mmc), host->irq, ret); 4843c07a48c2SAdrian Hunter goto unwq; 48440fc81ee3SMark Brown } 48451c6a0718SPierre Ossman 4846061d17a6SAdrian Hunter ret = sdhci_led_register(host); 48470fc81ee3SMark Brown if (ret) { 48480fc81ee3SMark Brown pr_err("%s: Failed to register LED device: %d\n", 48490fc81ee3SMark Brown mmc_hostname(mmc), ret); 4850eb5c20deSAdrian Hunter goto unirq; 48510fc81ee3SMark Brown } 48522f730fecSPierre Ossman 4853eb5c20deSAdrian Hunter ret = mmc_add_host(mmc); 4854eb5c20deSAdrian Hunter if (ret) 4855eb5c20deSAdrian Hunter goto unled; 48561c6a0718SPierre Ossman 4857a3c76eb9SGirish K S pr_info("%s: SDHCI controller on %s [%s] using %s\n", 4858d1b26863SKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), 485918e762e3SChunyan Zhang host->use_external_dma ? "External DMA" : 4860e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_ADMA) ? 4861e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" : 4862a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); 48631c6a0718SPierre Ossman 48647260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 48657260cf5eSAnton Vorontsov 48661c6a0718SPierre Ossman return 0; 48671c6a0718SPierre Ossman 4868eb5c20deSAdrian Hunter unled: 4869061d17a6SAdrian Hunter sdhci_led_unregister(host); 4870eb5c20deSAdrian Hunter unirq: 4871aa990722SAdrian Hunter sdhci_reset_for_all(host); 4872b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 4873b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 48742f730fecSPierre Ossman free_irq(host->irq, host); 4875c07a48c2SAdrian Hunter unwq: 4876c07a48c2SAdrian Hunter destroy_workqueue(host->complete_wq); 487752f5336dSAdrian Hunter 48781c6a0718SPierre Ossman return ret; 48791c6a0718SPierre Ossman } 488052f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_add_host); 48811c6a0718SPierre Ossman 488252f5336dSAdrian Hunter int sdhci_add_host(struct sdhci_host *host) 488352f5336dSAdrian Hunter { 488452f5336dSAdrian Hunter int ret; 488552f5336dSAdrian Hunter 488652f5336dSAdrian Hunter ret = sdhci_setup_host(host); 488752f5336dSAdrian Hunter if (ret) 488852f5336dSAdrian Hunter return ret; 488952f5336dSAdrian Hunter 48904180ffa8SAdrian Hunter ret = __sdhci_add_host(host); 48914180ffa8SAdrian Hunter if (ret) 48924180ffa8SAdrian Hunter goto cleanup; 48934180ffa8SAdrian Hunter 48944180ffa8SAdrian Hunter return 0; 48954180ffa8SAdrian Hunter 48964180ffa8SAdrian Hunter cleanup: 48974180ffa8SAdrian Hunter sdhci_cleanup_host(host); 48984180ffa8SAdrian Hunter 48994180ffa8SAdrian Hunter return ret; 490052f5336dSAdrian Hunter } 4901b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_add_host); 4902b8c86fc5SPierre Ossman 49031e72859eSPierre Ossman void sdhci_remove_host(struct sdhci_host *host, int dead) 49041c6a0718SPierre Ossman { 49053a48edc4STim Kryger struct mmc_host *mmc = host->mmc; 49061e72859eSPierre Ossman unsigned long flags; 49071e72859eSPierre Ossman 49081e72859eSPierre Ossman if (dead) { 49091e72859eSPierre Ossman spin_lock_irqsave(&host->lock, flags); 49101e72859eSPierre Ossman 49111e72859eSPierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 49121e72859eSPierre Ossman 49135d0d11c5SAdrian Hunter if (sdhci_has_requests(host)) { 4914a3c76eb9SGirish K S pr_err("%s: Controller removed during " 49154e743f1fSMarkus Mayer " transfer!\n", mmc_hostname(mmc)); 49165d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM); 49171e72859eSPierre Ossman } 49181e72859eSPierre Ossman 49191e72859eSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 49201e72859eSPierre Ossman } 49211e72859eSPierre Ossman 49227260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 49237260cf5eSAnton Vorontsov 49244e743f1fSMarkus Mayer mmc_remove_host(mmc); 49251c6a0718SPierre Ossman 4926061d17a6SAdrian Hunter sdhci_led_unregister(host); 49272f730fecSPierre Ossman 49281e72859eSPierre Ossman if (!dead) 4929aa990722SAdrian Hunter sdhci_reset_for_all(host); 49301c6a0718SPierre Ossman 4931b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 4932b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 49331c6a0718SPierre Ossman free_irq(host->irq, host); 49341c6a0718SPierre Ossman 49351c6a0718SPierre Ossman del_timer_sync(&host->timer); 4936d7422fb4SAdrian Hunter del_timer_sync(&host->data_timer); 49371c6a0718SPierre Ossman 4938c07a48c2SAdrian Hunter destroy_workqueue(host->complete_wq); 49392134a922SPierre Ossman 49400fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 49413a48edc4STim Kryger regulator_disable(mmc->supply.vqmmc); 49426231f3deSPhilip Rakity 4943edd63fccSRussell King if (host->align_buffer) 4944e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 4945e66e61cbSRussell King host->adma_table_sz, host->align_buffer, 4946e66e61cbSRussell King host->align_addr); 49472134a922SPierre Ossman 494818e762e3SChunyan Zhang if (host->use_external_dma) 494918e762e3SChunyan Zhang sdhci_external_dma_release(host); 495018e762e3SChunyan Zhang 49514efaa6fbSAdrian Hunter host->adma_table = NULL; 49522134a922SPierre Ossman host->align_buffer = NULL; 49531c6a0718SPierre Ossman } 49541c6a0718SPierre Ossman 4955b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_remove_host); 4956b8c86fc5SPierre Ossman 4957b8c86fc5SPierre Ossman void sdhci_free_host(struct sdhci_host *host) 49581c6a0718SPierre Ossman { 4959b8c86fc5SPierre Ossman mmc_free_host(host->mmc); 49601c6a0718SPierre Ossman } 49611c6a0718SPierre Ossman 4962b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_free_host); 49631c6a0718SPierre Ossman 49641c6a0718SPierre Ossman /*****************************************************************************\ 49651c6a0718SPierre Ossman * * 49661c6a0718SPierre Ossman * Driver init/exit * 49671c6a0718SPierre Ossman * * 49681c6a0718SPierre Ossman \*****************************************************************************/ 49691c6a0718SPierre Ossman 49701c6a0718SPierre Ossman static int __init sdhci_drv_init(void) 49711c6a0718SPierre Ossman { 4972a3c76eb9SGirish K S pr_info(DRIVER_NAME 49731c6a0718SPierre Ossman ": Secure Digital Host Controller Interface driver\n"); 4974a3c76eb9SGirish K S pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 49751c6a0718SPierre Ossman 4976b8c86fc5SPierre Ossman return 0; 49771c6a0718SPierre Ossman } 49781c6a0718SPierre Ossman 49791c6a0718SPierre Ossman static void __exit sdhci_drv_exit(void) 49801c6a0718SPierre Ossman { 49811c6a0718SPierre Ossman } 49821c6a0718SPierre Ossman 49831c6a0718SPierre Ossman module_init(sdhci_drv_init); 49841c6a0718SPierre Ossman module_exit(sdhci_drv_exit); 49851c6a0718SPierre Ossman 49861c6a0718SPierre Ossman module_param(debug_quirks, uint, 0444); 498766fd8ad5SAdrian Hunter module_param(debug_quirks2, uint, 0444); 49881c6a0718SPierre Ossman 498932710e8fSPierre Ossman MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); 4990b8c86fc5SPierre Ossman MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 49911c6a0718SPierre Ossman MODULE_LICENSE("GPL"); 49921c6a0718SPierre Ossman 49931c6a0718SPierre Ossman MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 499466fd8ad5SAdrian Hunter MODULE_PARM_DESC(debug_quirks2, "Force certain other quirks."); 4995