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 262*1e63d297SAdrian Hunter enum sdhci_reset_reason { 263*1e63d297SAdrian Hunter SDHCI_RESET_FOR_INIT, 264*1e63d297SAdrian Hunter SDHCI_RESET_FOR_REQUEST_ERROR, 265*1e63d297SAdrian Hunter SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY, 266*1e63d297SAdrian Hunter SDHCI_RESET_FOR_TUNING_ABORT, 267*1e63d297SAdrian Hunter SDHCI_RESET_FOR_CARD_REMOVED, 268*1e63d297SAdrian Hunter SDHCI_RESET_FOR_CQE_RECOVERY, 269*1e63d297SAdrian Hunter }; 270*1e63d297SAdrian Hunter 271*1e63d297SAdrian Hunter static void sdhci_reset_for_reason(struct sdhci_host *host, enum sdhci_reset_reason reason) 272*1e63d297SAdrian Hunter { 273*1e63d297SAdrian Hunter switch (reason) { 274*1e63d297SAdrian Hunter case SDHCI_RESET_FOR_INIT: 275*1e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 276*1e63d297SAdrian Hunter break; 277*1e63d297SAdrian Hunter case SDHCI_RESET_FOR_REQUEST_ERROR: 278*1e63d297SAdrian Hunter case SDHCI_RESET_FOR_TUNING_ABORT: 279*1e63d297SAdrian Hunter case SDHCI_RESET_FOR_CARD_REMOVED: 280*1e63d297SAdrian Hunter case SDHCI_RESET_FOR_CQE_RECOVERY: 281*1e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD); 282*1e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 283*1e63d297SAdrian Hunter break; 284*1e63d297SAdrian Hunter case SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY: 285*1e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 286*1e63d297SAdrian Hunter break; 287*1e63d297SAdrian Hunter } 288*1e63d297SAdrian Hunter } 289*1e63d297SAdrian Hunter 290*1e63d297SAdrian Hunter #define sdhci_reset_for(h, r) sdhci_reset_for_reason((h), SDHCI_RESET_FOR_##r) 291*1e63d297SAdrian 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) 360*1e63d297SAdrian 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; 376d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 3772f4cbb3dSNicolas Pitre } 3787260cf5eSAnton Vorontsov } 3791c6a0718SPierre Ossman 3807260cf5eSAnton Vorontsov static void sdhci_reinit(struct sdhci_host *host) 3817260cf5eSAnton Vorontsov { 382dcaac3f7SRaul E Rangel u32 cd = host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); 383dcaac3f7SRaul E Rangel 3842f4cbb3dSNicolas Pitre sdhci_init(host, 0); 3857260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 386dcaac3f7SRaul E Rangel 387dcaac3f7SRaul E Rangel /* 388dcaac3f7SRaul E Rangel * A change to the card detect bits indicates a change in present state, 389dcaac3f7SRaul E Rangel * refer sdhci_set_card_detection(). A card detect interrupt might have 390dcaac3f7SRaul E Rangel * been missed while the host controller was being reset, so trigger a 391dcaac3f7SRaul E Rangel * rescan to check. 392dcaac3f7SRaul E Rangel */ 393dcaac3f7SRaul E Rangel if (cd != (host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT))) 394dcaac3f7SRaul E Rangel mmc_detect_change(host->mmc, msecs_to_jiffies(200)); 3951c6a0718SPierre Ossman } 3961c6a0718SPierre Ossman 397061d17a6SAdrian Hunter static void __sdhci_led_activate(struct sdhci_host *host) 3981c6a0718SPierre Ossman { 3991c6a0718SPierre Ossman u8 ctrl; 4001c6a0718SPierre Ossman 401bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 402bd29f58bSAdrian Hunter return; 403bd29f58bSAdrian Hunter 4044e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 4051c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_LED; 4064e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 4071c6a0718SPierre Ossman } 4081c6a0718SPierre Ossman 409061d17a6SAdrian Hunter static void __sdhci_led_deactivate(struct sdhci_host *host) 4101c6a0718SPierre Ossman { 4111c6a0718SPierre Ossman u8 ctrl; 4121c6a0718SPierre Ossman 413bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 414bd29f58bSAdrian Hunter return; 415bd29f58bSAdrian Hunter 4164e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 4171c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_LED; 4184e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 4191c6a0718SPierre Ossman } 4201c6a0718SPierre Ossman 4214f78230fSMasahiro Yamada #if IS_REACHABLE(CONFIG_LEDS_CLASS) 4222f730fecSPierre Ossman static void sdhci_led_control(struct led_classdev *led, 4232f730fecSPierre Ossman enum led_brightness brightness) 4242f730fecSPierre Ossman { 4252f730fecSPierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 4262f730fecSPierre Ossman unsigned long flags; 4272f730fecSPierre Ossman 4282f730fecSPierre Ossman spin_lock_irqsave(&host->lock, flags); 4292f730fecSPierre Ossman 43066fd8ad5SAdrian Hunter if (host->runtime_suspended) 43166fd8ad5SAdrian Hunter goto out; 43266fd8ad5SAdrian Hunter 4332f730fecSPierre Ossman if (brightness == LED_OFF) 434061d17a6SAdrian Hunter __sdhci_led_deactivate(host); 4352f730fecSPierre Ossman else 436061d17a6SAdrian Hunter __sdhci_led_activate(host); 43766fd8ad5SAdrian Hunter out: 4382f730fecSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 4392f730fecSPierre Ossman } 440061d17a6SAdrian Hunter 441061d17a6SAdrian Hunter static int sdhci_led_register(struct sdhci_host *host) 442061d17a6SAdrian Hunter { 443061d17a6SAdrian Hunter struct mmc_host *mmc = host->mmc; 444061d17a6SAdrian Hunter 445bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 446bd29f58bSAdrian Hunter return 0; 447bd29f58bSAdrian Hunter 448061d17a6SAdrian Hunter snprintf(host->led_name, sizeof(host->led_name), 449061d17a6SAdrian Hunter "%s::", mmc_hostname(mmc)); 450061d17a6SAdrian Hunter 451061d17a6SAdrian Hunter host->led.name = host->led_name; 452061d17a6SAdrian Hunter host->led.brightness = LED_OFF; 453061d17a6SAdrian Hunter host->led.default_trigger = mmc_hostname(mmc); 454061d17a6SAdrian Hunter host->led.brightness_set = sdhci_led_control; 455061d17a6SAdrian Hunter 456061d17a6SAdrian Hunter return led_classdev_register(mmc_dev(mmc), &host->led); 457061d17a6SAdrian Hunter } 458061d17a6SAdrian Hunter 459061d17a6SAdrian Hunter static void sdhci_led_unregister(struct sdhci_host *host) 460061d17a6SAdrian Hunter { 461bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 462bd29f58bSAdrian Hunter return; 463bd29f58bSAdrian Hunter 464061d17a6SAdrian Hunter led_classdev_unregister(&host->led); 465061d17a6SAdrian Hunter } 466061d17a6SAdrian Hunter 467061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host) 468061d17a6SAdrian Hunter { 469061d17a6SAdrian Hunter } 470061d17a6SAdrian Hunter 471061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host) 472061d17a6SAdrian Hunter { 473061d17a6SAdrian Hunter } 474061d17a6SAdrian Hunter 475061d17a6SAdrian Hunter #else 476061d17a6SAdrian Hunter 477061d17a6SAdrian Hunter static inline int sdhci_led_register(struct sdhci_host *host) 478061d17a6SAdrian Hunter { 479061d17a6SAdrian Hunter return 0; 480061d17a6SAdrian Hunter } 481061d17a6SAdrian Hunter 482061d17a6SAdrian Hunter static inline void sdhci_led_unregister(struct sdhci_host *host) 483061d17a6SAdrian Hunter { 484061d17a6SAdrian Hunter } 485061d17a6SAdrian Hunter 486061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host) 487061d17a6SAdrian Hunter { 488061d17a6SAdrian Hunter __sdhci_led_activate(host); 489061d17a6SAdrian Hunter } 490061d17a6SAdrian Hunter 491061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host) 492061d17a6SAdrian Hunter { 493061d17a6SAdrian Hunter __sdhci_led_deactivate(host); 494061d17a6SAdrian Hunter } 495061d17a6SAdrian Hunter 4962f730fecSPierre Ossman #endif 4972f730fecSPierre Ossman 49897a1abaeSAdrian Hunter static void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, 49997a1abaeSAdrian Hunter unsigned long timeout) 50097a1abaeSAdrian Hunter { 50197a1abaeSAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd)) 50297a1abaeSAdrian Hunter mod_timer(&host->data_timer, timeout); 50397a1abaeSAdrian Hunter else 50497a1abaeSAdrian Hunter mod_timer(&host->timer, timeout); 50597a1abaeSAdrian Hunter } 50697a1abaeSAdrian Hunter 50797a1abaeSAdrian Hunter static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq) 50897a1abaeSAdrian Hunter { 50997a1abaeSAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd)) 51097a1abaeSAdrian Hunter del_timer(&host->data_timer); 51197a1abaeSAdrian Hunter else 51297a1abaeSAdrian Hunter del_timer(&host->timer); 51397a1abaeSAdrian Hunter } 51497a1abaeSAdrian Hunter 51597a1abaeSAdrian Hunter static inline bool sdhci_has_requests(struct sdhci_host *host) 51697a1abaeSAdrian Hunter { 51797a1abaeSAdrian Hunter return host->cmd || host->data_cmd; 51897a1abaeSAdrian Hunter } 51997a1abaeSAdrian Hunter 5201c6a0718SPierre Ossman /*****************************************************************************\ 5211c6a0718SPierre Ossman * * 5221c6a0718SPierre Ossman * Core functions * 5231c6a0718SPierre Ossman * * 5241c6a0718SPierre Ossman \*****************************************************************************/ 5251c6a0718SPierre Ossman 5261c6a0718SPierre Ossman static void sdhci_read_block_pio(struct sdhci_host *host) 5271c6a0718SPierre Ossman { 5287659150cSPierre Ossman unsigned long flags; 5297659150cSPierre Ossman size_t blksize, len, chunk; 5303f649ab7SKees Cook u32 scratch; 5317659150cSPierre Ossman u8 *buf; 5321c6a0718SPierre Ossman 5331c6a0718SPierre Ossman DBG("PIO reading\n"); 5341c6a0718SPierre Ossman 5351c6a0718SPierre Ossman blksize = host->data->blksz; 5367659150cSPierre Ossman chunk = 0; 5371c6a0718SPierre Ossman 5387659150cSPierre Ossman local_irq_save(flags); 5391c6a0718SPierre Ossman 5401c6a0718SPierre Ossman while (blksize) { 541bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter)); 5427659150cSPierre Ossman 5437659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 5447659150cSPierre Ossman 5457659150cSPierre Ossman blksize -= len; 5467659150cSPierre Ossman host->sg_miter.consumed = len; 5477659150cSPierre Ossman 5487659150cSPierre Ossman buf = host->sg_miter.addr; 5497659150cSPierre Ossman 5507659150cSPierre Ossman while (len) { 5517659150cSPierre Ossman if (chunk == 0) { 5524e4141a5SAnton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER); 5537659150cSPierre Ossman chunk = 4; 5541c6a0718SPierre Ossman } 5551c6a0718SPierre Ossman 5567659150cSPierre Ossman *buf = scratch & 0xFF; 5571c6a0718SPierre Ossman 5587659150cSPierre Ossman buf++; 5597659150cSPierre Ossman scratch >>= 8; 5607659150cSPierre Ossman chunk--; 5617659150cSPierre Ossman len--; 5627659150cSPierre Ossman } 5631c6a0718SPierre Ossman } 5641c6a0718SPierre Ossman 5657659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 5667659150cSPierre Ossman 5677659150cSPierre Ossman local_irq_restore(flags); 5681c6a0718SPierre Ossman } 5691c6a0718SPierre Ossman 5701c6a0718SPierre Ossman static void sdhci_write_block_pio(struct sdhci_host *host) 5711c6a0718SPierre Ossman { 5727659150cSPierre Ossman unsigned long flags; 5737659150cSPierre Ossman size_t blksize, len, chunk; 5747659150cSPierre Ossman u32 scratch; 5757659150cSPierre Ossman u8 *buf; 5761c6a0718SPierre Ossman 5771c6a0718SPierre Ossman DBG("PIO writing\n"); 5781c6a0718SPierre Ossman 5791c6a0718SPierre Ossman blksize = host->data->blksz; 5807659150cSPierre Ossman chunk = 0; 5817659150cSPierre Ossman scratch = 0; 5821c6a0718SPierre Ossman 5837659150cSPierre Ossman local_irq_save(flags); 5841c6a0718SPierre Ossman 5851c6a0718SPierre Ossman while (blksize) { 586bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter)); 5871c6a0718SPierre Ossman 5887659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 5891c6a0718SPierre Ossman 5907659150cSPierre Ossman blksize -= len; 5917659150cSPierre Ossman host->sg_miter.consumed = len; 5927659150cSPierre Ossman 5937659150cSPierre Ossman buf = host->sg_miter.addr; 5947659150cSPierre Ossman 5957659150cSPierre Ossman while (len) { 5967659150cSPierre Ossman scratch |= (u32)*buf << (chunk * 8); 5977659150cSPierre Ossman 5987659150cSPierre Ossman buf++; 5997659150cSPierre Ossman chunk++; 6007659150cSPierre Ossman len--; 6017659150cSPierre Ossman 6027659150cSPierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 6034e4141a5SAnton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER); 6047659150cSPierre Ossman chunk = 0; 6057659150cSPierre Ossman scratch = 0; 6067659150cSPierre Ossman } 6077659150cSPierre Ossman } 6081c6a0718SPierre Ossman } 6091c6a0718SPierre Ossman 6107659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 6111c6a0718SPierre Ossman 6127659150cSPierre Ossman local_irq_restore(flags); 6131c6a0718SPierre Ossman } 6141c6a0718SPierre Ossman 6151c6a0718SPierre Ossman static void sdhci_transfer_pio(struct sdhci_host *host) 6161c6a0718SPierre Ossman { 6171c6a0718SPierre Ossman u32 mask; 6181c6a0718SPierre Ossman 6197659150cSPierre Ossman if (host->blocks == 0) 6201c6a0718SPierre Ossman return; 6211c6a0718SPierre Ossman 6221c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 6231c6a0718SPierre Ossman mask = SDHCI_DATA_AVAILABLE; 6241c6a0718SPierre Ossman else 6251c6a0718SPierre Ossman mask = SDHCI_SPACE_AVAILABLE; 6261c6a0718SPierre Ossman 6274a3cba32SPierre Ossman /* 6284a3cba32SPierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 6294a3cba32SPierre Ossman * for transfers < 4 bytes. As long as it is just one block, 6304a3cba32SPierre Ossman * we can ignore the bits. 6314a3cba32SPierre Ossman */ 6324a3cba32SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 6334a3cba32SPierre Ossman (host->data->blocks == 1)) 6344a3cba32SPierre Ossman mask = ~0; 6354a3cba32SPierre Ossman 6364e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 6373e3bf207SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 6383e3bf207SAnton Vorontsov udelay(100); 6393e3bf207SAnton Vorontsov 6401c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 6411c6a0718SPierre Ossman sdhci_read_block_pio(host); 6421c6a0718SPierre Ossman else 6431c6a0718SPierre Ossman sdhci_write_block_pio(host); 6441c6a0718SPierre Ossman 6457659150cSPierre Ossman host->blocks--; 6467659150cSPierre Ossman if (host->blocks == 0) 6471c6a0718SPierre Ossman break; 6481c6a0718SPierre Ossman } 6491c6a0718SPierre Ossman 6501c6a0718SPierre Ossman DBG("PIO transfer complete.\n"); 6511c6a0718SPierre Ossman } 6521c6a0718SPierre Ossman 65348857d9bSRussell King static int sdhci_pre_dma_transfer(struct sdhci_host *host, 654c0999b72SRussell King struct mmc_data *data, int cookie) 65548857d9bSRussell King { 65648857d9bSRussell King int sg_count; 65748857d9bSRussell King 65894538e51SRussell King /* 65994538e51SRussell King * If the data buffers are already mapped, return the previous 66094538e51SRussell King * dma_map_sg() result. 66194538e51SRussell King */ 66294538e51SRussell King if (data->host_cookie == COOKIE_PRE_MAPPED) 66348857d9bSRussell King return data->sg_count; 66448857d9bSRussell King 665bd9b9027SLinus Walleij /* Bounce write requests to the bounce buffer */ 666bd9b9027SLinus Walleij if (host->bounce_buffer) { 667bd9b9027SLinus Walleij unsigned int length = data->blksz * data->blocks; 668bd9b9027SLinus Walleij 669bd9b9027SLinus Walleij if (length > host->bounce_buffer_size) { 670bd9b9027SLinus Walleij pr_err("%s: asked for transfer of %u bytes exceeds bounce buffer %u bytes\n", 671bd9b9027SLinus Walleij mmc_hostname(host->mmc), length, 672bd9b9027SLinus Walleij host->bounce_buffer_size); 673bd9b9027SLinus Walleij return -EIO; 674bd9b9027SLinus Walleij } 675bd9b9027SLinus Walleij if (mmc_get_dma_dir(data) == DMA_TO_DEVICE) { 676bd9b9027SLinus Walleij /* Copy the data to the bounce buffer */ 677e93577ecSAngelo Dureghello if (host->ops->copy_to_bounce_buffer) { 678e93577ecSAngelo Dureghello host->ops->copy_to_bounce_buffer(host, 679e93577ecSAngelo Dureghello data, length); 680e93577ecSAngelo Dureghello } else { 681bd9b9027SLinus Walleij sg_copy_to_buffer(data->sg, data->sg_len, 682e93577ecSAngelo Dureghello host->bounce_buffer, length); 683e93577ecSAngelo Dureghello } 684bd9b9027SLinus Walleij } 685bd9b9027SLinus Walleij /* Switch ownership to the DMA */ 686bac53336SJisheng Zhang dma_sync_single_for_device(mmc_dev(host->mmc), 687bd9b9027SLinus Walleij host->bounce_addr, 688bd9b9027SLinus Walleij host->bounce_buffer_size, 689feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 690bd9b9027SLinus Walleij /* Just a dummy value */ 691bd9b9027SLinus Walleij sg_count = 1; 692bd9b9027SLinus Walleij } else { 693bd9b9027SLinus Walleij /* Just access the data directly from memory */ 694bd9b9027SLinus Walleij sg_count = dma_map_sg(mmc_dev(host->mmc), 695bd9b9027SLinus Walleij data->sg, data->sg_len, 696bd9b9027SLinus Walleij mmc_get_dma_dir(data)); 697bd9b9027SLinus Walleij } 69848857d9bSRussell King 69948857d9bSRussell King if (sg_count == 0) 70048857d9bSRussell King return -ENOSPC; 70148857d9bSRussell King 70248857d9bSRussell King data->sg_count = sg_count; 703c0999b72SRussell King data->host_cookie = cookie; 70448857d9bSRussell King 70548857d9bSRussell King return sg_count; 70648857d9bSRussell King } 70748857d9bSRussell King 7082134a922SPierre Ossman static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) 7092134a922SPierre Ossman { 7102134a922SPierre Ossman local_irq_save(*flags); 711482fce99SCong Wang return kmap_atomic(sg_page(sg)) + sg->offset; 7122134a922SPierre Ossman } 7132134a922SPierre Ossman 7142134a922SPierre Ossman static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) 7152134a922SPierre Ossman { 716482fce99SCong Wang kunmap_atomic(buffer); 7172134a922SPierre Ossman local_irq_restore(*flags); 7182134a922SPierre Ossman } 7192134a922SPierre Ossman 72054552e49SJisheng Zhang void sdhci_adma_write_desc(struct sdhci_host *host, void **desc, 72154552e49SJisheng Zhang dma_addr_t addr, int len, unsigned int cmd) 722118cd17dSBen Dooks { 72354552e49SJisheng Zhang struct sdhci_adma2_64_desc *dma_desc = *desc; 724118cd17dSBen Dooks 725e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have these members in same position */ 7260545230fSAdrian Hunter dma_desc->cmd = cpu_to_le16(cmd); 7270545230fSAdrian Hunter dma_desc->len = cpu_to_le16(len); 72838eee2e8SMasahiro Yamada dma_desc->addr_lo = cpu_to_le32(lower_32_bits(addr)); 729e57a5f61SAdrian Hunter 730e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 73138eee2e8SMasahiro Yamada dma_desc->addr_hi = cpu_to_le32(upper_32_bits(addr)); 73254552e49SJisheng Zhang 73354552e49SJisheng Zhang *desc += host->desc_sz; 73454552e49SJisheng Zhang } 73554552e49SJisheng Zhang EXPORT_SYMBOL_GPL(sdhci_adma_write_desc); 73654552e49SJisheng Zhang 73754552e49SJisheng Zhang static inline void __sdhci_adma_write_desc(struct sdhci_host *host, 73854552e49SJisheng Zhang void **desc, dma_addr_t addr, 73954552e49SJisheng Zhang int len, unsigned int cmd) 74054552e49SJisheng Zhang { 74154552e49SJisheng Zhang if (host->ops->adma_write_desc) 74254552e49SJisheng Zhang host->ops->adma_write_desc(host, desc, addr, len, cmd); 74307be55b5SJisheng Zhang else 74454552e49SJisheng Zhang sdhci_adma_write_desc(host, desc, addr, len, cmd); 745118cd17dSBen Dooks } 746118cd17dSBen Dooks 747b5ffa674SAdrian Hunter static void sdhci_adma_mark_end(void *desc) 748b5ffa674SAdrian Hunter { 749e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 750b5ffa674SAdrian Hunter 751e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have 'cmd' in same position */ 7520545230fSAdrian Hunter dma_desc->cmd |= cpu_to_le16(ADMA2_END); 753b5ffa674SAdrian Hunter } 754b5ffa674SAdrian Hunter 75560c64762SRussell King static void sdhci_adma_table_pre(struct sdhci_host *host, 75660c64762SRussell King struct mmc_data *data, int sg_count) 7572134a922SPierre Ossman { 7582134a922SPierre Ossman struct scatterlist *sg; 7592134a922SPierre Ossman unsigned long flags; 760acc3ad13SRussell King dma_addr_t addr, align_addr; 761acc3ad13SRussell King void *desc, *align; 762acc3ad13SRussell King char *buffer; 763acc3ad13SRussell King int len, offset, i; 7642134a922SPierre Ossman 7652134a922SPierre Ossman /* 7662134a922SPierre Ossman * The spec does not specify endianness of descriptor table. 7672134a922SPierre Ossman * We currently guess that it is LE. 7682134a922SPierre Ossman */ 7692134a922SPierre Ossman 77060c64762SRussell King host->sg_count = sg_count; 7712134a922SPierre Ossman 7724efaa6fbSAdrian Hunter desc = host->adma_table; 7732134a922SPierre Ossman align = host->align_buffer; 7742134a922SPierre Ossman 7752134a922SPierre Ossman align_addr = host->align_addr; 7762134a922SPierre Ossman 7772134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 7782134a922SPierre Ossman addr = sg_dma_address(sg); 7792134a922SPierre Ossman len = sg_dma_len(sg); 7802134a922SPierre Ossman 7812134a922SPierre Ossman /* 782acc3ad13SRussell King * The SDHCI specification states that ADMA addresses must 783acc3ad13SRussell King * be 32-bit aligned. If they aren't, then we use a bounce 784acc3ad13SRussell King * buffer for the (up to three) bytes that screw up the 7852134a922SPierre Ossman * alignment. 7862134a922SPierre Ossman */ 78704a5ae6fSAdrian Hunter offset = (SDHCI_ADMA2_ALIGN - (addr & SDHCI_ADMA2_MASK)) & 78804a5ae6fSAdrian Hunter SDHCI_ADMA2_MASK; 7892134a922SPierre Ossman if (offset) { 7902134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 7912134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 7922134a922SPierre Ossman memcpy(align, buffer, offset); 7932134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 7942134a922SPierre Ossman } 7952134a922SPierre Ossman 796118cd17dSBen Dooks /* tran, valid */ 79754552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, align_addr, 79854552e49SJisheng Zhang offset, ADMA2_TRAN_VALID); 7992134a922SPierre Ossman 8002134a922SPierre Ossman BUG_ON(offset > 65536); 8012134a922SPierre Ossman 80204a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN; 80304a5ae6fSAdrian Hunter align_addr += SDHCI_ADMA2_ALIGN; 8042134a922SPierre Ossman 8052134a922SPierre Ossman addr += offset; 8062134a922SPierre Ossman len -= offset; 8072134a922SPierre Ossman } 8082134a922SPierre Ossman 8093d7c194bSAdrian Hunter /* 8103d7c194bSAdrian Hunter * The block layer forces a minimum segment size of PAGE_SIZE, 8113d7c194bSAdrian Hunter * so 'len' can be too big here if PAGE_SIZE >= 64KiB. Write 8123d7c194bSAdrian Hunter * multiple descriptors, noting that the ADMA table is sized 8133d7c194bSAdrian Hunter * for 4KiB chunks anyway, so it will be big enough. 8143d7c194bSAdrian Hunter */ 8153d7c194bSAdrian Hunter while (len > host->max_adma) { 8163d7c194bSAdrian Hunter int n = 32 * 1024; /* 32KiB*/ 8173d7c194bSAdrian Hunter 8183d7c194bSAdrian Hunter __sdhci_adma_write_desc(host, &desc, addr, n, ADMA2_TRAN_VALID); 8193d7c194bSAdrian Hunter addr += n; 8203d7c194bSAdrian Hunter len -= n; 8213d7c194bSAdrian Hunter } 8222134a922SPierre Ossman 823118cd17dSBen Dooks /* tran, valid */ 82454552e49SJisheng Zhang if (len) 82554552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, addr, len, 826347ea32dSAdrian Hunter ADMA2_TRAN_VALID); 8272134a922SPierre Ossman 8282134a922SPierre Ossman /* 8292134a922SPierre Ossman * If this triggers then we have a calculation bug 8302134a922SPierre Ossman * somewhere. :/ 8312134a922SPierre Ossman */ 83276fe379aSAdrian Hunter WARN_ON((desc - host->adma_table) >= host->adma_table_sz); 8332134a922SPierre Ossman } 8342134a922SPierre Ossman 83570764a90SThomas Abraham if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { 836acc3ad13SRussell King /* Mark the last descriptor as the terminating descriptor */ 8374efaa6fbSAdrian Hunter if (desc != host->adma_table) { 83876fe379aSAdrian Hunter desc -= host->desc_sz; 839b5ffa674SAdrian Hunter sdhci_adma_mark_end(desc); 84070764a90SThomas Abraham } 84170764a90SThomas Abraham } else { 842acc3ad13SRussell King /* Add a terminating entry - nop, end, valid */ 84354552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, 0, 0, ADMA2_NOP_END_VALID); 84470764a90SThomas Abraham } 8452134a922SPierre Ossman } 8462134a922SPierre Ossman 8472134a922SPierre Ossman static void sdhci_adma_table_post(struct sdhci_host *host, 8482134a922SPierre Ossman struct mmc_data *data) 8492134a922SPierre Ossman { 8502134a922SPierre Ossman struct scatterlist *sg; 8512134a922SPierre Ossman int i, size; 8521c3d5f6dSAdrian Hunter void *align; 8532134a922SPierre Ossman char *buffer; 8542134a922SPierre Ossman unsigned long flags; 8552134a922SPierre Ossman 85647fa9613SRussell King if (data->flags & MMC_DATA_READ) { 85747fa9613SRussell King bool has_unaligned = false; 85847fa9613SRussell King 859de0b65a7SRussell King /* Do a quick scan of the SG list for any unaligned mappings */ 860de0b65a7SRussell King for_each_sg(data->sg, sg, host->sg_count, i) 86104a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { 862de0b65a7SRussell King has_unaligned = true; 863de0b65a7SRussell King break; 864de0b65a7SRussell King } 865de0b65a7SRussell King 86647fa9613SRussell King if (has_unaligned) { 8672134a922SPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 868f55c98f7SRussell King data->sg_len, DMA_FROM_DEVICE); 8692134a922SPierre Ossman 8702134a922SPierre Ossman align = host->align_buffer; 8712134a922SPierre Ossman 8722134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 87304a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { 87404a5ae6fSAdrian Hunter size = SDHCI_ADMA2_ALIGN - 87504a5ae6fSAdrian Hunter (sg_dma_address(sg) & SDHCI_ADMA2_MASK); 8762134a922SPierre Ossman 8772134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 8782134a922SPierre Ossman memcpy(buffer, align, size); 8792134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 8802134a922SPierre Ossman 88104a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN; 8822134a922SPierre Ossman } 8832134a922SPierre Ossman } 8842134a922SPierre Ossman } 88547fa9613SRussell King } 8862134a922SPierre Ossman } 8872134a922SPierre Ossman 88838eee2e8SMasahiro Yamada static void sdhci_set_adma_addr(struct sdhci_host *host, dma_addr_t addr) 88938eee2e8SMasahiro Yamada { 89038eee2e8SMasahiro Yamada sdhci_writel(host, lower_32_bits(addr), SDHCI_ADMA_ADDRESS); 89138eee2e8SMasahiro Yamada if (host->flags & SDHCI_USE_64_BIT_DMA) 89238eee2e8SMasahiro Yamada sdhci_writel(host, upper_32_bits(addr), SDHCI_ADMA_ADDRESS_HI); 89338eee2e8SMasahiro Yamada } 89438eee2e8SMasahiro Yamada 895917a0c52SChunyan Zhang static dma_addr_t sdhci_sdma_address(struct sdhci_host *host) 896bd9b9027SLinus Walleij { 897bd9b9027SLinus Walleij if (host->bounce_buffer) 898bd9b9027SLinus Walleij return host->bounce_addr; 899bd9b9027SLinus Walleij else 900bd9b9027SLinus Walleij return sg_dma_address(host->data->sg); 901bd9b9027SLinus Walleij } 902bd9b9027SLinus Walleij 903917a0c52SChunyan Zhang static void sdhci_set_sdma_addr(struct sdhci_host *host, dma_addr_t addr) 904917a0c52SChunyan Zhang { 90538eee2e8SMasahiro Yamada if (host->v4_mode) 90638eee2e8SMasahiro Yamada sdhci_set_adma_addr(host, addr); 90738eee2e8SMasahiro Yamada else 908917a0c52SChunyan Zhang sdhci_writel(host, addr, SDHCI_DMA_ADDRESS); 909917a0c52SChunyan Zhang } 910917a0c52SChunyan Zhang 9110bb28d73SAdrian Hunter static unsigned int sdhci_target_timeout(struct sdhci_host *host, 9120bb28d73SAdrian Hunter struct mmc_command *cmd, 9130bb28d73SAdrian Hunter struct mmc_data *data) 9140bb28d73SAdrian Hunter { 9150bb28d73SAdrian Hunter unsigned int target_timeout; 9160bb28d73SAdrian Hunter 9170bb28d73SAdrian Hunter /* timeout in us */ 9180bb28d73SAdrian Hunter if (!data) { 9190bb28d73SAdrian Hunter target_timeout = cmd->busy_timeout * 1000; 9200bb28d73SAdrian Hunter } else { 9210bb28d73SAdrian Hunter target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000); 9220bb28d73SAdrian Hunter if (host->clock && data->timeout_clks) { 9230bb28d73SAdrian Hunter unsigned long long val; 9240bb28d73SAdrian Hunter 9250bb28d73SAdrian Hunter /* 9260bb28d73SAdrian Hunter * data->timeout_clks is in units of clock cycles. 9270bb28d73SAdrian Hunter * host->clock is in Hz. target_timeout is in us. 9280bb28d73SAdrian Hunter * Hence, us = 1000000 * cycles / Hz. Round up. 9290bb28d73SAdrian Hunter */ 9300bb28d73SAdrian Hunter val = 1000000ULL * data->timeout_clks; 9310bb28d73SAdrian Hunter if (do_div(val, host->clock)) 9320bb28d73SAdrian Hunter target_timeout++; 9330bb28d73SAdrian Hunter target_timeout += val; 9340bb28d73SAdrian Hunter } 9350bb28d73SAdrian Hunter } 9360bb28d73SAdrian Hunter 9370bb28d73SAdrian Hunter return target_timeout; 9380bb28d73SAdrian Hunter } 9390bb28d73SAdrian Hunter 940fc1fa1b7SKishon Vijay Abraham I static void sdhci_calc_sw_timeout(struct sdhci_host *host, 941fc1fa1b7SKishon Vijay Abraham I struct mmc_command *cmd) 942fc1fa1b7SKishon Vijay Abraham I { 943fc1fa1b7SKishon Vijay Abraham I struct mmc_data *data = cmd->data; 944fc1fa1b7SKishon Vijay Abraham I struct mmc_host *mmc = host->mmc; 945fc1fa1b7SKishon Vijay Abraham I struct mmc_ios *ios = &mmc->ios; 946fc1fa1b7SKishon Vijay Abraham I unsigned char bus_width = 1 << ios->bus_width; 947fc1fa1b7SKishon Vijay Abraham I unsigned int blksz; 948fc1fa1b7SKishon Vijay Abraham I unsigned int freq; 949fc1fa1b7SKishon Vijay Abraham I u64 target_timeout; 950fc1fa1b7SKishon Vijay Abraham I u64 transfer_time; 951fc1fa1b7SKishon Vijay Abraham I 952fc1fa1b7SKishon Vijay Abraham I target_timeout = sdhci_target_timeout(host, cmd, data); 953fc1fa1b7SKishon Vijay Abraham I target_timeout *= NSEC_PER_USEC; 954fc1fa1b7SKishon Vijay Abraham I 955fc1fa1b7SKishon Vijay Abraham I if (data) { 956fc1fa1b7SKishon Vijay Abraham I blksz = data->blksz; 957d2f025b0SJisheng Zhang freq = mmc->actual_clock ? : host->clock; 958fc1fa1b7SKishon Vijay Abraham I transfer_time = (u64)blksz * NSEC_PER_SEC * (8 / bus_width); 959fc1fa1b7SKishon Vijay Abraham I do_div(transfer_time, freq); 960fc1fa1b7SKishon Vijay Abraham I /* multiply by '2' to account for any unknowns */ 961fc1fa1b7SKishon Vijay Abraham I transfer_time = transfer_time * 2; 962fc1fa1b7SKishon Vijay Abraham I /* calculate timeout for the entire data */ 963fc1fa1b7SKishon Vijay Abraham I host->data_timeout = data->blocks * target_timeout + 964fc1fa1b7SKishon Vijay Abraham I transfer_time; 965fc1fa1b7SKishon Vijay Abraham I } else { 966fc1fa1b7SKishon Vijay Abraham I host->data_timeout = target_timeout; 967fc1fa1b7SKishon Vijay Abraham I } 968fc1fa1b7SKishon Vijay Abraham I 969fc1fa1b7SKishon Vijay Abraham I if (host->data_timeout) 970fc1fa1b7SKishon Vijay Abraham I host->data_timeout += MMC_CMD_TRANSFER_TIME; 971fc1fa1b7SKishon Vijay Abraham I } 972fc1fa1b7SKishon Vijay Abraham I 973a999fd93SAdrian Hunter static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd, 974a999fd93SAdrian Hunter bool *too_big) 9751c6a0718SPierre Ossman { 9761c6a0718SPierre Ossman u8 count; 977401059dfSBOUGH CHEN struct mmc_data *data; 9781c6a0718SPierre Ossman unsigned target_timeout, current_timeout; 9791c6a0718SPierre Ossman 9809c6bb8c6SBean Huo *too_big = false; 981a999fd93SAdrian Hunter 982ee53ab5dSPierre Ossman /* 983ee53ab5dSPierre Ossman * If the host controller provides us with an incorrect timeout 984e30314f2SSarthak Garg * value, just skip the check and use the maximum. The hardware may take 985ee53ab5dSPierre Ossman * longer to time out, but that's much better than having a too-short 986ee53ab5dSPierre Ossman * timeout value. 987ee53ab5dSPierre Ossman */ 98811a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) 989e30314f2SSarthak Garg return host->max_timeout_count; 990e538fbe8SPierre Ossman 9919c6bb8c6SBean Huo /* Unspecified command, assume max */ 992401059dfSBOUGH CHEN if (cmd == NULL) 993e30314f2SSarthak Garg return host->max_timeout_count; 994401059dfSBOUGH CHEN 995401059dfSBOUGH CHEN data = cmd->data; 996a3c7778fSAndrei Warkentin /* Unspecified timeout, assume max */ 9971d4d7744SUlf Hansson if (!data && !cmd->busy_timeout) 998e30314f2SSarthak Garg return host->max_timeout_count; 999a3c7778fSAndrei Warkentin 10001c6a0718SPierre Ossman /* timeout in us */ 10010bb28d73SAdrian Hunter target_timeout = sdhci_target_timeout(host, cmd, data); 10021c6a0718SPierre Ossman 10031c6a0718SPierre Ossman /* 10041c6a0718SPierre Ossman * Figure out needed cycles. 10051c6a0718SPierre Ossman * We do this in steps in order to fit inside a 32 bit int. 10061c6a0718SPierre Ossman * The first step is the minimum timeout, which will have a 10071c6a0718SPierre Ossman * minimum resolution of 6 bits: 10081c6a0718SPierre Ossman * (1) 2^13*1000 > 2^22, 10091c6a0718SPierre Ossman * (2) host->timeout_clk < 2^16 10101c6a0718SPierre Ossman * => 10111c6a0718SPierre Ossman * (1) / (2) > 2^6 10121c6a0718SPierre Ossman */ 10131c6a0718SPierre Ossman count = 0; 10141c6a0718SPierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 10151c6a0718SPierre Ossman while (current_timeout < target_timeout) { 10161c6a0718SPierre Ossman count++; 10171c6a0718SPierre Ossman current_timeout <<= 1; 1018e30314f2SSarthak Garg if (count > host->max_timeout_count) { 1019a999fd93SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT)) 1020f421865dSAdrian Hunter DBG("Too large timeout 0x%x requested for CMD%d!\n", 1021f421865dSAdrian Hunter count, cmd->opcode); 1022e30314f2SSarthak Garg count = host->max_timeout_count; 10239c6bb8c6SBean Huo *too_big = true; 10249c6bb8c6SBean Huo break; 10259c6bb8c6SBean Huo } 10261c6a0718SPierre Ossman } 10271c6a0718SPierre Ossman 1028ee53ab5dSPierre Ossman return count; 1029ee53ab5dSPierre Ossman } 1030ee53ab5dSPierre Ossman 10316aa943abSAnton Vorontsov static void sdhci_set_transfer_irqs(struct sdhci_host *host) 10326aa943abSAnton Vorontsov { 10336aa943abSAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 10346aa943abSAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; 10356aa943abSAnton Vorontsov 10366aa943abSAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA) 1037b537f94cSRussell King host->ier = (host->ier & ~pio_irqs) | dma_irqs; 10386aa943abSAnton Vorontsov else 1039b537f94cSRussell King host->ier = (host->ier & ~dma_irqs) | pio_irqs; 1040b537f94cSRussell King 1041af849c86SAdrian Hunter if (host->flags & (SDHCI_AUTO_CMD23 | SDHCI_AUTO_CMD12)) 1042af849c86SAdrian Hunter host->ier |= SDHCI_INT_AUTO_CMD_ERR; 1043af849c86SAdrian Hunter else 1044af849c86SAdrian Hunter host->ier &= ~SDHCI_INT_AUTO_CMD_ERR; 1045af849c86SAdrian Hunter 1046b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 1047b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 10486aa943abSAnton Vorontsov } 10496aa943abSAnton Vorontsov 10507907ebe7SFaiz Abbas void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable) 1051a999fd93SAdrian Hunter { 1052a999fd93SAdrian Hunter if (enable) 1053a999fd93SAdrian Hunter host->ier |= SDHCI_INT_DATA_TIMEOUT; 1054a999fd93SAdrian Hunter else 1055a999fd93SAdrian Hunter host->ier &= ~SDHCI_INT_DATA_TIMEOUT; 1056a999fd93SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 1057a999fd93SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 1058a999fd93SAdrian Hunter } 10597907ebe7SFaiz Abbas EXPORT_SYMBOL_GPL(sdhci_set_data_timeout_irq); 1060a999fd93SAdrian Hunter 10617d76ed77SFaiz Abbas void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) 1062ee53ab5dSPierre Ossman { 1063a999fd93SAdrian Hunter bool too_big = false; 10647d76ed77SFaiz Abbas u8 count = sdhci_calc_timeout(host, cmd, &too_big); 1065a999fd93SAdrian Hunter 1066a999fd93SAdrian Hunter if (too_big && 1067a999fd93SAdrian Hunter host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) { 1068fc1fa1b7SKishon Vijay Abraham I sdhci_calc_sw_timeout(host, cmd); 1069a999fd93SAdrian Hunter sdhci_set_data_timeout_irq(host, false); 1070a999fd93SAdrian Hunter } else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT)) { 1071a999fd93SAdrian Hunter sdhci_set_data_timeout_irq(host, true); 1072a999fd93SAdrian Hunter } 1073a999fd93SAdrian Hunter 1074b45e668aSAisheng Dong sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); 1075b45e668aSAisheng Dong } 10767d76ed77SFaiz Abbas EXPORT_SYMBOL_GPL(__sdhci_set_timeout); 10777d76ed77SFaiz Abbas 10787d76ed77SFaiz Abbas static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) 10797d76ed77SFaiz Abbas { 10807d76ed77SFaiz Abbas if (host->ops->set_timeout) 10817d76ed77SFaiz Abbas host->ops->set_timeout(host, cmd); 10827d76ed77SFaiz Abbas else 10837d76ed77SFaiz Abbas __sdhci_set_timeout(host, cmd); 1084b45e668aSAisheng Dong } 1085b45e668aSAisheng Dong 108615db1836SFaiz Abbas static void sdhci_initialize_data(struct sdhci_host *host, 108715db1836SFaiz Abbas struct mmc_data *data) 1088b45e668aSAisheng Dong { 108943dea098SAdrian Hunter WARN_ON(host->data); 109043dea098SAdrian Hunter 1091ee53ab5dSPierre Ossman /* Sanity checks */ 1092ee53ab5dSPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 1093ee53ab5dSPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 1094ee53ab5dSPierre Ossman BUG_ON(data->blocks > 65535); 1095ee53ab5dSPierre Ossman 1096ee53ab5dSPierre Ossman host->data = data; 1097ee53ab5dSPierre Ossman host->data_early = 0; 1098f6a03cbfSMikko Vinni host->data->bytes_xfered = 0; 109915db1836SFaiz Abbas } 110015db1836SFaiz Abbas 110115db1836SFaiz Abbas static inline void sdhci_set_block_info(struct sdhci_host *host, 110215db1836SFaiz Abbas struct mmc_data *data) 110315db1836SFaiz Abbas { 110415db1836SFaiz Abbas /* Set the DMA boundary value and block size */ 110515db1836SFaiz Abbas sdhci_writew(host, 110615db1836SFaiz Abbas SDHCI_MAKE_BLKSZ(host->sdma_boundary, data->blksz), 110715db1836SFaiz Abbas SDHCI_BLOCK_SIZE); 110815db1836SFaiz Abbas /* 110915db1836SFaiz Abbas * For Version 4.10 onwards, if v4 mode is enabled, 32-bit Block Count 111015db1836SFaiz Abbas * can be supported, in that case 16-bit block count register must be 0. 111115db1836SFaiz Abbas */ 111215db1836SFaiz Abbas if (host->version >= SDHCI_SPEC_410 && host->v4_mode && 111315db1836SFaiz Abbas (host->quirks2 & SDHCI_QUIRK2_USE_32BIT_BLK_CNT)) { 111415db1836SFaiz Abbas if (sdhci_readw(host, SDHCI_BLOCK_COUNT)) 111515db1836SFaiz Abbas sdhci_writew(host, 0, SDHCI_BLOCK_COUNT); 111615db1836SFaiz Abbas sdhci_writew(host, data->blocks, SDHCI_32BIT_BLK_CNT); 111715db1836SFaiz Abbas } else { 111815db1836SFaiz Abbas sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); 111915db1836SFaiz Abbas } 112015db1836SFaiz Abbas } 112115db1836SFaiz Abbas 112215db1836SFaiz Abbas static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) 112315db1836SFaiz Abbas { 112415db1836SFaiz Abbas struct mmc_data *data = cmd->data; 112515db1836SFaiz Abbas 112615db1836SFaiz Abbas sdhci_initialize_data(host, data); 1127ee53ab5dSPierre Ossman 1128fce14421SRussell King if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 1129fce14421SRussell King struct scatterlist *sg; 1130fce14421SRussell King unsigned int length_mask, offset_mask; 1131fce14421SRussell King int i; 1132fce14421SRussell King 1133c9fddbc4SPierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 1134c9fddbc4SPierre Ossman 11352134a922SPierre Ossman /* 11362134a922SPierre Ossman * FIXME: This doesn't account for merging when mapping the 11372134a922SPierre Ossman * scatterlist. 1138df953925SRussell King * 1139df953925SRussell King * The assumption here being that alignment and lengths are 1140df953925SRussell King * the same after DMA mapping to device address space. 11412134a922SPierre Ossman */ 1142a0eaf0f9SRussell King length_mask = 0; 1143df953925SRussell King offset_mask = 0; 11442134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 1145df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) { 1146a0eaf0f9SRussell King length_mask = 3; 1147df953925SRussell King /* 1148df953925SRussell King * As we use up to 3 byte chunks to work 1149df953925SRussell King * around alignment problems, we need to 1150df953925SRussell King * check the offset as well. 1151df953925SRussell King */ 1152df953925SRussell King offset_mask = 3; 1153df953925SRussell King } 11542134a922SPierre Ossman } else { 11552134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 1156a0eaf0f9SRussell King length_mask = 3; 1157df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 1158df953925SRussell King offset_mask = 3; 11592134a922SPierre Ossman } 11602134a922SPierre Ossman 1161df953925SRussell King if (unlikely(length_mask | offset_mask)) { 11622134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 1163a0eaf0f9SRussell King if (sg->length & length_mask) { 11642e4456f0SMarek Vasut DBG("Reverting to PIO because of transfer size (%d)\n", 11652134a922SPierre Ossman sg->length); 1166c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 11672134a922SPierre Ossman break; 11682134a922SPierre Ossman } 1169a0eaf0f9SRussell King if (sg->offset & offset_mask) { 11702e4456f0SMarek Vasut DBG("Reverting to PIO because of bad alignment\n"); 1171c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 11722134a922SPierre Ossman break; 11732134a922SPierre Ossman } 11742134a922SPierre Ossman } 11752134a922SPierre Ossman } 11762134a922SPierre Ossman } 11772134a922SPierre Ossman 11788f1934ceSPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 1179c0999b72SRussell King int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); 11808f1934ceSPierre Ossman 118162a7f368SJiri Slaby if (sg_cnt <= 0) { 11828f1934ceSPierre Ossman /* 11838f1934ceSPierre Ossman * This only happens when someone fed 11848f1934ceSPierre Ossman * us an invalid request. 11858f1934ceSPierre Ossman */ 11868f1934ceSPierre Ossman WARN_ON(1); 1187ebd6d357SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 118860c64762SRussell King } else if (host->flags & SDHCI_USE_ADMA) { 118960c64762SRussell King sdhci_adma_table_pre(host, data, sg_cnt); 119038eee2e8SMasahiro Yamada sdhci_set_adma_addr(host, host->adma_addr); 11918f1934ceSPierre Ossman } else { 1192719a61b4SPierre Ossman WARN_ON(sg_cnt != 1); 1193917a0c52SChunyan Zhang sdhci_set_sdma_addr(host, sdhci_sdma_address(host)); 11948f1934ceSPierre Ossman } 11958f1934ceSPierre Ossman } 11968f1934ceSPierre Ossman 1197685e444bSChunyan Zhang sdhci_config_dma(host); 1198c9fddbc4SPierre Ossman 11998f1934ceSPierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 1200da60a91dSSebastian Andrzej Siewior int flags; 1201da60a91dSSebastian Andrzej Siewior 1202da60a91dSSebastian Andrzej Siewior flags = SG_MITER_ATOMIC; 1203da60a91dSSebastian Andrzej Siewior if (host->data->flags & MMC_DATA_READ) 1204da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_TO_SG; 1205da60a91dSSebastian Andrzej Siewior else 1206da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_FROM_SG; 1207da60a91dSSebastian Andrzej Siewior sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 12087659150cSPierre Ossman host->blocks = data->blocks; 12091c6a0718SPierre Ossman } 12101c6a0718SPierre Ossman 12116aa943abSAnton Vorontsov sdhci_set_transfer_irqs(host); 12126aa943abSAnton Vorontsov 121315db1836SFaiz Abbas sdhci_set_block_info(host, data); 1214e65953d4SChunyan Zhang } 12151c6a0718SPierre Ossman 121618e762e3SChunyan Zhang #if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA) 121718e762e3SChunyan Zhang 121818e762e3SChunyan Zhang static int sdhci_external_dma_init(struct sdhci_host *host) 121918e762e3SChunyan Zhang { 122018e762e3SChunyan Zhang int ret = 0; 122118e762e3SChunyan Zhang struct mmc_host *mmc = host->mmc; 122218e762e3SChunyan Zhang 1223bac53336SJisheng Zhang host->tx_chan = dma_request_chan(mmc_dev(mmc), "tx"); 122418e762e3SChunyan Zhang if (IS_ERR(host->tx_chan)) { 122518e762e3SChunyan Zhang ret = PTR_ERR(host->tx_chan); 122618e762e3SChunyan Zhang if (ret != -EPROBE_DEFER) 122718e762e3SChunyan Zhang pr_warn("Failed to request TX DMA channel.\n"); 122818e762e3SChunyan Zhang host->tx_chan = NULL; 122918e762e3SChunyan Zhang return ret; 123018e762e3SChunyan Zhang } 123118e762e3SChunyan Zhang 1232bac53336SJisheng Zhang host->rx_chan = dma_request_chan(mmc_dev(mmc), "rx"); 123318e762e3SChunyan Zhang if (IS_ERR(host->rx_chan)) { 123418e762e3SChunyan Zhang if (host->tx_chan) { 123518e762e3SChunyan Zhang dma_release_channel(host->tx_chan); 123618e762e3SChunyan Zhang host->tx_chan = NULL; 123718e762e3SChunyan Zhang } 123818e762e3SChunyan Zhang 123918e762e3SChunyan Zhang ret = PTR_ERR(host->rx_chan); 124018e762e3SChunyan Zhang if (ret != -EPROBE_DEFER) 124118e762e3SChunyan Zhang pr_warn("Failed to request RX DMA channel.\n"); 124218e762e3SChunyan Zhang host->rx_chan = NULL; 124318e762e3SChunyan Zhang } 124418e762e3SChunyan Zhang 124518e762e3SChunyan Zhang return ret; 124618e762e3SChunyan Zhang } 124718e762e3SChunyan Zhang 124818e762e3SChunyan Zhang static struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, 124918e762e3SChunyan Zhang struct mmc_data *data) 125018e762e3SChunyan Zhang { 125118e762e3SChunyan Zhang return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan; 125218e762e3SChunyan Zhang } 125318e762e3SChunyan Zhang 125418e762e3SChunyan Zhang static int sdhci_external_dma_setup(struct sdhci_host *host, 125518e762e3SChunyan Zhang struct mmc_command *cmd) 125618e762e3SChunyan Zhang { 125718e762e3SChunyan Zhang int ret, i; 12581215c025SChunyan Zhang enum dma_transfer_direction dir; 125918e762e3SChunyan Zhang struct dma_async_tx_descriptor *desc; 126018e762e3SChunyan Zhang struct mmc_data *data = cmd->data; 126118e762e3SChunyan Zhang struct dma_chan *chan; 126218e762e3SChunyan Zhang struct dma_slave_config cfg; 126318e762e3SChunyan Zhang dma_cookie_t cookie; 126418e762e3SChunyan Zhang int sg_cnt; 126518e762e3SChunyan Zhang 126618e762e3SChunyan Zhang if (!host->mapbase) 126718e762e3SChunyan Zhang return -EINVAL; 126818e762e3SChunyan Zhang 1269522654d5STony Lindgren memset(&cfg, 0, sizeof(cfg)); 127018e762e3SChunyan Zhang cfg.src_addr = host->mapbase + SDHCI_BUFFER; 127118e762e3SChunyan Zhang cfg.dst_addr = host->mapbase + SDHCI_BUFFER; 127218e762e3SChunyan Zhang cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 127318e762e3SChunyan Zhang cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 127418e762e3SChunyan Zhang cfg.src_maxburst = data->blksz / 4; 127518e762e3SChunyan Zhang cfg.dst_maxburst = data->blksz / 4; 127618e762e3SChunyan Zhang 127718e762e3SChunyan Zhang /* Sanity check: all the SG entries must be aligned by block size. */ 127818e762e3SChunyan Zhang for (i = 0; i < data->sg_len; i++) { 127918e762e3SChunyan Zhang if ((data->sg + i)->length % data->blksz) 128018e762e3SChunyan Zhang return -EINVAL; 128118e762e3SChunyan Zhang } 128218e762e3SChunyan Zhang 128318e762e3SChunyan Zhang chan = sdhci_external_dma_channel(host, data); 128418e762e3SChunyan Zhang 128518e762e3SChunyan Zhang ret = dmaengine_slave_config(chan, &cfg); 128618e762e3SChunyan Zhang if (ret) 128718e762e3SChunyan Zhang return ret; 128818e762e3SChunyan Zhang 128918e762e3SChunyan Zhang sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); 129018e762e3SChunyan Zhang if (sg_cnt <= 0) 129118e762e3SChunyan Zhang return -EINVAL; 129218e762e3SChunyan Zhang 12931215c025SChunyan Zhang dir = data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; 12941215c025SChunyan Zhang desc = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len, dir, 129518e762e3SChunyan Zhang DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 129618e762e3SChunyan Zhang if (!desc) 129718e762e3SChunyan Zhang return -EINVAL; 129818e762e3SChunyan Zhang 129918e762e3SChunyan Zhang desc->callback = NULL; 130018e762e3SChunyan Zhang desc->callback_param = NULL; 130118e762e3SChunyan Zhang 130218e762e3SChunyan Zhang cookie = dmaengine_submit(desc); 130318e762e3SChunyan Zhang if (dma_submit_error(cookie)) 130418e762e3SChunyan Zhang ret = cookie; 130518e762e3SChunyan Zhang 130618e762e3SChunyan Zhang return ret; 130718e762e3SChunyan Zhang } 130818e762e3SChunyan Zhang 130918e762e3SChunyan Zhang static void sdhci_external_dma_release(struct sdhci_host *host) 131018e762e3SChunyan Zhang { 131118e762e3SChunyan Zhang if (host->tx_chan) { 131218e762e3SChunyan Zhang dma_release_channel(host->tx_chan); 131318e762e3SChunyan Zhang host->tx_chan = NULL; 131418e762e3SChunyan Zhang } 131518e762e3SChunyan Zhang 131618e762e3SChunyan Zhang if (host->rx_chan) { 131718e762e3SChunyan Zhang dma_release_channel(host->rx_chan); 131818e762e3SChunyan Zhang host->rx_chan = NULL; 131918e762e3SChunyan Zhang } 132018e762e3SChunyan Zhang 132118e762e3SChunyan Zhang sdhci_switch_external_dma(host, false); 132218e762e3SChunyan Zhang } 132318e762e3SChunyan Zhang 132418e762e3SChunyan Zhang static void __sdhci_external_dma_prepare_data(struct sdhci_host *host, 132518e762e3SChunyan Zhang struct mmc_command *cmd) 132618e762e3SChunyan Zhang { 132718e762e3SChunyan Zhang struct mmc_data *data = cmd->data; 132818e762e3SChunyan Zhang 132918e762e3SChunyan Zhang sdhci_initialize_data(host, data); 133018e762e3SChunyan Zhang 133118e762e3SChunyan Zhang host->flags |= SDHCI_REQ_USE_DMA; 133218e762e3SChunyan Zhang sdhci_set_transfer_irqs(host); 133318e762e3SChunyan Zhang 133418e762e3SChunyan Zhang sdhci_set_block_info(host, data); 133518e762e3SChunyan Zhang } 133618e762e3SChunyan Zhang 133718e762e3SChunyan Zhang static void sdhci_external_dma_prepare_data(struct sdhci_host *host, 133818e762e3SChunyan Zhang struct mmc_command *cmd) 133918e762e3SChunyan Zhang { 134018e762e3SChunyan Zhang if (!sdhci_external_dma_setup(host, cmd)) { 134118e762e3SChunyan Zhang __sdhci_external_dma_prepare_data(host, cmd); 134218e762e3SChunyan Zhang } else { 134318e762e3SChunyan Zhang sdhci_external_dma_release(host); 134418e762e3SChunyan Zhang pr_err("%s: Cannot use external DMA, switch to the DMA/PIO which standard SDHCI provides.\n", 134518e762e3SChunyan Zhang mmc_hostname(host->mmc)); 134618e762e3SChunyan Zhang sdhci_prepare_data(host, cmd); 134718e762e3SChunyan Zhang } 134818e762e3SChunyan Zhang } 134918e762e3SChunyan Zhang 135018e762e3SChunyan Zhang static void sdhci_external_dma_pre_transfer(struct sdhci_host *host, 135118e762e3SChunyan Zhang struct mmc_command *cmd) 135218e762e3SChunyan Zhang { 135318e762e3SChunyan Zhang struct dma_chan *chan; 135418e762e3SChunyan Zhang 135518e762e3SChunyan Zhang if (!cmd->data) 135618e762e3SChunyan Zhang return; 135718e762e3SChunyan Zhang 135818e762e3SChunyan Zhang chan = sdhci_external_dma_channel(host, cmd->data); 135918e762e3SChunyan Zhang if (chan) 136018e762e3SChunyan Zhang dma_async_issue_pending(chan); 136118e762e3SChunyan Zhang } 136218e762e3SChunyan Zhang 136318e762e3SChunyan Zhang #else 136418e762e3SChunyan Zhang 136518e762e3SChunyan Zhang static inline int sdhci_external_dma_init(struct sdhci_host *host) 136618e762e3SChunyan Zhang { 136718e762e3SChunyan Zhang return -EOPNOTSUPP; 136818e762e3SChunyan Zhang } 136918e762e3SChunyan Zhang 137018e762e3SChunyan Zhang static inline void sdhci_external_dma_release(struct sdhci_host *host) 137118e762e3SChunyan Zhang { 137218e762e3SChunyan Zhang } 137318e762e3SChunyan Zhang 137418e762e3SChunyan Zhang static inline void sdhci_external_dma_prepare_data(struct sdhci_host *host, 137518e762e3SChunyan Zhang struct mmc_command *cmd) 137618e762e3SChunyan Zhang { 137718e762e3SChunyan Zhang /* This should never happen */ 137818e762e3SChunyan Zhang WARN_ON_ONCE(1); 137918e762e3SChunyan Zhang } 138018e762e3SChunyan Zhang 138118e762e3SChunyan Zhang static inline void sdhci_external_dma_pre_transfer(struct sdhci_host *host, 138218e762e3SChunyan Zhang struct mmc_command *cmd) 138318e762e3SChunyan Zhang { 138418e762e3SChunyan Zhang } 138518e762e3SChunyan Zhang 138618e762e3SChunyan Zhang static inline struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, 138718e762e3SChunyan Zhang struct mmc_data *data) 138818e762e3SChunyan Zhang { 138918e762e3SChunyan Zhang return NULL; 139018e762e3SChunyan Zhang } 139118e762e3SChunyan Zhang 139218e762e3SChunyan Zhang #endif 139318e762e3SChunyan Zhang 139418e762e3SChunyan Zhang void sdhci_switch_external_dma(struct sdhci_host *host, bool en) 139518e762e3SChunyan Zhang { 139618e762e3SChunyan Zhang host->use_external_dma = en; 139718e762e3SChunyan Zhang } 139818e762e3SChunyan Zhang EXPORT_SYMBOL_GPL(sdhci_switch_external_dma); 139918e762e3SChunyan Zhang 14000293d501SAdrian Hunter static inline bool sdhci_auto_cmd12(struct sdhci_host *host, 14010293d501SAdrian Hunter struct mmc_request *mrq) 14020293d501SAdrian Hunter { 140320845befSAdrian Hunter return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) && 140420845befSAdrian Hunter !mrq->cap_cmd_during_tfr; 14050293d501SAdrian Hunter } 14060293d501SAdrian Hunter 1407ed633033SAdrian Hunter static inline bool sdhci_auto_cmd23(struct sdhci_host *host, 1408ed633033SAdrian Hunter struct mmc_request *mrq) 1409ed633033SAdrian Hunter { 1410ed633033SAdrian Hunter return mrq->sbc && (host->flags & SDHCI_AUTO_CMD23); 1411ed633033SAdrian Hunter } 1412ed633033SAdrian Hunter 1413ed633033SAdrian Hunter static inline bool sdhci_manual_cmd23(struct sdhci_host *host, 1414ed633033SAdrian Hunter struct mmc_request *mrq) 1415ed633033SAdrian Hunter { 1416ed633033SAdrian Hunter return mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23); 1417ed633033SAdrian Hunter } 1418ed633033SAdrian Hunter 1419427b6514SChunyan Zhang static inline void sdhci_auto_cmd_select(struct sdhci_host *host, 1420427b6514SChunyan Zhang struct mmc_command *cmd, 1421427b6514SChunyan Zhang u16 *mode) 1422427b6514SChunyan Zhang { 1423427b6514SChunyan Zhang bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) && 1424427b6514SChunyan Zhang (cmd->opcode != SD_IO_RW_EXTENDED); 1425ed633033SAdrian Hunter bool use_cmd23 = sdhci_auto_cmd23(host, cmd->mrq); 1426427b6514SChunyan Zhang u16 ctrl2; 1427427b6514SChunyan Zhang 1428427b6514SChunyan Zhang /* 1429427b6514SChunyan Zhang * In case of Version 4.10 or later, use of 'Auto CMD Auto 1430427b6514SChunyan Zhang * Select' is recommended rather than use of 'Auto CMD12 1431b3e1ea16SJisheng Zhang * Enable' or 'Auto CMD23 Enable'. We require Version 4 Mode 1432b3e1ea16SJisheng Zhang * here because some controllers (e.g sdhci-of-dwmshc) expect it. 1433427b6514SChunyan Zhang */ 1434b3e1ea16SJisheng Zhang if (host->version >= SDHCI_SPEC_410 && host->v4_mode && 1435b3e1ea16SJisheng Zhang (use_cmd12 || use_cmd23)) { 1436427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_SEL; 1437427b6514SChunyan Zhang 1438427b6514SChunyan Zhang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1439427b6514SChunyan Zhang if (use_cmd23) 1440427b6514SChunyan Zhang ctrl2 |= SDHCI_CMD23_ENABLE; 1441427b6514SChunyan Zhang else 1442427b6514SChunyan Zhang ctrl2 &= ~SDHCI_CMD23_ENABLE; 1443427b6514SChunyan Zhang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 1444427b6514SChunyan Zhang 1445427b6514SChunyan Zhang return; 1446427b6514SChunyan Zhang } 1447427b6514SChunyan Zhang 1448427b6514SChunyan Zhang /* 1449427b6514SChunyan Zhang * If we are sending CMD23, CMD12 never gets sent 1450427b6514SChunyan Zhang * on successful completion (so no Auto-CMD12). 1451427b6514SChunyan Zhang */ 1452427b6514SChunyan Zhang if (use_cmd12) 1453427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_CMD12; 1454427b6514SChunyan Zhang else if (use_cmd23) 1455427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_CMD23; 1456427b6514SChunyan Zhang } 1457427b6514SChunyan Zhang 14581c6a0718SPierre Ossman static void sdhci_set_transfer_mode(struct sdhci_host *host, 1459e89d456fSAndrei Warkentin struct mmc_command *cmd) 14601c6a0718SPierre Ossman { 1461d3fc5d71SVincent Yang u16 mode = 0; 1462e89d456fSAndrei Warkentin struct mmc_data *data = cmd->data; 14631c6a0718SPierre Ossman 14642b558c13SDong Aisheng if (data == NULL) { 14659b8ffea6SVincent Wan if (host->quirks2 & 14669b8ffea6SVincent Wan SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) { 14670086fc21Sernest.zhang /* must not clear SDHCI_TRANSFER_MODE when tuning */ 14680086fc21Sernest.zhang if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) 14699b8ffea6SVincent Wan sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); 14709b8ffea6SVincent Wan } else { 14712b558c13SDong Aisheng /* clear Auto CMD settings for no data CMDs */ 14722b558c13SDong Aisheng mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); 14732b558c13SDong Aisheng sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | 14742b558c13SDong Aisheng SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); 14759b8ffea6SVincent Wan } 14761c6a0718SPierre Ossman return; 14772b558c13SDong Aisheng } 14781c6a0718SPierre Ossman 1479e538fbe8SPierre Ossman WARN_ON(!host->data); 1480e538fbe8SPierre Ossman 1481d3fc5d71SVincent Yang if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE)) 14821c6a0718SPierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 1483d3fc5d71SVincent Yang 1484e89d456fSAndrei Warkentin if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { 1485d3fc5d71SVincent Yang mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI; 1486427b6514SChunyan Zhang sdhci_auto_cmd_select(host, cmd, &mode); 1487ed633033SAdrian Hunter if (sdhci_auto_cmd23(host, cmd->mrq)) 1488a4c73abaSAdrian Hunter sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2); 1489c4512f79SJerry Huang } 14908edf6371SAndrei Warkentin 14911c6a0718SPierre Ossman if (data->flags & MMC_DATA_READ) 14921c6a0718SPierre Ossman mode |= SDHCI_TRNS_READ; 1493c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 14941c6a0718SPierre Ossman mode |= SDHCI_TRNS_DMA; 14951c6a0718SPierre Ossman 14964e4141a5SAnton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); 14971c6a0718SPierre Ossman } 14981c6a0718SPierre Ossman 14990cc563ceSAdrian Hunter static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) 15000cc563ceSAdrian Hunter { 15010cc563ceSAdrian Hunter return (!(host->flags & SDHCI_DEVICE_DEAD) && 15020cc563ceSAdrian Hunter ((mrq->cmd && mrq->cmd->error) || 15030cc563ceSAdrian Hunter (mrq->sbc && mrq->sbc->error) || 15044bf78099SAdrian Hunter (mrq->data && mrq->data->stop && mrq->data->stop->error) || 15050cc563ceSAdrian Hunter (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))); 15060cc563ceSAdrian Hunter } 15070cc563ceSAdrian Hunter 150815db1836SFaiz Abbas static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq) 15094e9f8fe5SAdrian Hunter { 15104e9f8fe5SAdrian Hunter int i; 15114e9f8fe5SAdrian Hunter 15124e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 15134e9f8fe5SAdrian Hunter if (host->mrqs_done[i] == mrq) { 15144e9f8fe5SAdrian Hunter WARN_ON(1); 15154e9f8fe5SAdrian Hunter return; 15164e9f8fe5SAdrian Hunter } 15174e9f8fe5SAdrian Hunter } 15184e9f8fe5SAdrian Hunter 15194e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 15204e9f8fe5SAdrian Hunter if (!host->mrqs_done[i]) { 15214e9f8fe5SAdrian Hunter host->mrqs_done[i] = mrq; 15224e9f8fe5SAdrian Hunter break; 15234e9f8fe5SAdrian Hunter } 15244e9f8fe5SAdrian Hunter } 15254e9f8fe5SAdrian Hunter 15264e9f8fe5SAdrian Hunter WARN_ON(i >= SDHCI_MAX_MRQS); 152715db1836SFaiz Abbas } 152815db1836SFaiz Abbas 152915db1836SFaiz Abbas static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) 153015db1836SFaiz Abbas { 153115db1836SFaiz Abbas if (host->cmd && host->cmd->mrq == mrq) 153215db1836SFaiz Abbas host->cmd = NULL; 153315db1836SFaiz Abbas 153415db1836SFaiz Abbas if (host->data_cmd && host->data_cmd->mrq == mrq) 153515db1836SFaiz Abbas host->data_cmd = NULL; 153615db1836SFaiz Abbas 1537845c939eSAdrian Hunter if (host->deferred_cmd && host->deferred_cmd->mrq == mrq) 1538845c939eSAdrian Hunter host->deferred_cmd = NULL; 1539845c939eSAdrian Hunter 154015db1836SFaiz Abbas if (host->data && host->data->mrq == mrq) 154115db1836SFaiz Abbas host->data = NULL; 154215db1836SFaiz Abbas 154315db1836SFaiz Abbas if (sdhci_needs_reset(host, mrq)) 154415db1836SFaiz Abbas host->pending_reset = true; 154515db1836SFaiz Abbas 154615db1836SFaiz Abbas sdhci_set_mrq_done(host, mrq); 15474e9f8fe5SAdrian Hunter 1548e9a07299SAdrian Hunter sdhci_del_timer(host, mrq); 1549e9a07299SAdrian Hunter 1550e9a07299SAdrian Hunter if (!sdhci_has_requests(host)) 1551e9a07299SAdrian Hunter sdhci_led_deactivate(host); 15524e9f8fe5SAdrian Hunter } 15534e9f8fe5SAdrian Hunter 1554a6d3bdd5SAdrian Hunter static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) 1555a6d3bdd5SAdrian Hunter { 15564e9f8fe5SAdrian Hunter __sdhci_finish_mrq(host, mrq); 15572e72ab9bSAdrian Hunter 1558c07a48c2SAdrian Hunter queue_work(host->complete_wq, &host->complete_work); 1559a6d3bdd5SAdrian Hunter } 1560a6d3bdd5SAdrian Hunter 1561845c939eSAdrian Hunter static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) 15621c6a0718SPierre Ossman { 156333a57adbSAdrian Hunter struct mmc_command *data_cmd = host->data_cmd; 156433a57adbSAdrian Hunter struct mmc_data *data = host->data; 15651c6a0718SPierre Ossman 15661c6a0718SPierre Ossman host->data = NULL; 15677c89a3d9SAdrian Hunter host->data_cmd = NULL; 15681c6a0718SPierre Ossman 15694bf78099SAdrian Hunter /* 15704bf78099SAdrian Hunter * The controller needs a reset of internal state machines upon error 15714bf78099SAdrian Hunter * conditions. 15724bf78099SAdrian Hunter */ 15734bf78099SAdrian Hunter if (data->error) { 15744bf78099SAdrian Hunter if (!host->cmd || host->cmd == data_cmd) 1575*1e63d297SAdrian Hunter sdhci_reset_for(host, REQUEST_ERROR); 1576*1e63d297SAdrian Hunter else 1577*1e63d297SAdrian Hunter sdhci_reset_for(host, REQUEST_ERROR_DATA_ONLY); 15784bf78099SAdrian Hunter } 15794bf78099SAdrian Hunter 1580add8913dSRussell King if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) == 1581add8913dSRussell King (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) 15822134a922SPierre Ossman sdhci_adma_table_post(host, data); 1583f55c98f7SRussell King 15841c6a0718SPierre Ossman /* 1585c9b74c5bSPierre Ossman * The specification states that the block count register must 1586c9b74c5bSPierre Ossman * be updated, but it does not specify at what point in the 1587c9b74c5bSPierre Ossman * data flow. That makes the register entirely useless to read 1588c9b74c5bSPierre Ossman * back so we have to assume that nothing made it to the card 1589c9b74c5bSPierre Ossman * in the event of an error. 15901c6a0718SPierre Ossman */ 1591c9b74c5bSPierre Ossman if (data->error) 1592c9b74c5bSPierre Ossman data->bytes_xfered = 0; 15931c6a0718SPierre Ossman else 1594c9b74c5bSPierre Ossman data->bytes_xfered = data->blksz * data->blocks; 15951c6a0718SPierre Ossman 1596e89d456fSAndrei Warkentin /* 1597e89d456fSAndrei Warkentin * Need to send CMD12 if - 1598fdbbe6cfSYangbo Lu * a) open-ended multiblock transfer not using auto CMD12 (no CMD23) 1599e89d456fSAndrei Warkentin * b) error in multiblock transfer 1600e89d456fSAndrei Warkentin */ 1601e89d456fSAndrei Warkentin if (data->stop && 1602fdbbe6cfSYangbo Lu ((!data->mrq->sbc && !sdhci_auto_cmd12(host, data->mrq)) || 1603fdbbe6cfSYangbo Lu data->error)) { 160420845befSAdrian Hunter /* 160520845befSAdrian Hunter * 'cap_cmd_during_tfr' request must not use the command line 160620845befSAdrian Hunter * after mmc_command_done() has been called. It is upper layer's 160720845befSAdrian Hunter * responsibility to send the stop command if required. 160820845befSAdrian Hunter */ 160920845befSAdrian Hunter if (data->mrq->cap_cmd_during_tfr) { 161019d2f695SAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 161120845befSAdrian Hunter } else { 16128842fd17SAdrian Hunter /* Avoid triggering warning in sdhci_send_command() */ 16138842fd17SAdrian Hunter host->cmd = NULL; 1614845c939eSAdrian Hunter if (!sdhci_send_command(host, data->stop)) { 1615845c939eSAdrian Hunter if (sw_data_timeout) { 1616845c939eSAdrian Hunter /* 1617845c939eSAdrian Hunter * This is anyway a sw data timeout, so 1618845c939eSAdrian Hunter * give up now. 1619845c939eSAdrian Hunter */ 1620845c939eSAdrian Hunter data->stop->error = -EIO; 1621845c939eSAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 1622845c939eSAdrian Hunter } else { 1623845c939eSAdrian Hunter WARN_ON(host->deferred_cmd); 1624845c939eSAdrian Hunter host->deferred_cmd = data->stop; 1625845c939eSAdrian Hunter } 1626845c939eSAdrian Hunter } 162720845befSAdrian Hunter } 1628a6d3bdd5SAdrian Hunter } else { 162919d2f695SAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 1630a6d3bdd5SAdrian Hunter } 16311c6a0718SPierre Ossman } 16321c6a0718SPierre Ossman 1633845c939eSAdrian Hunter static void sdhci_finish_data(struct sdhci_host *host) 1634845c939eSAdrian Hunter { 1635845c939eSAdrian Hunter __sdhci_finish_data(host, false); 1636845c939eSAdrian Hunter } 1637845c939eSAdrian Hunter 1638845c939eSAdrian Hunter static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 16391c6a0718SPierre Ossman { 16401c6a0718SPierre Ossman int flags; 16411c6a0718SPierre Ossman u32 mask; 16421c6a0718SPierre Ossman unsigned long timeout; 16431c6a0718SPierre Ossman 16441c6a0718SPierre Ossman WARN_ON(host->cmd); 16451c6a0718SPierre Ossman 164696776200SRussell King /* Initially, a command has no error */ 164796776200SRussell King cmd->error = 0; 164896776200SRussell King 1649fc605f1dSAdrian Hunter if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && 1650fc605f1dSAdrian Hunter cmd->opcode == MMC_STOP_TRANSMISSION) 1651fc605f1dSAdrian Hunter cmd->flags |= MMC_RSP_BUSY; 1652fc605f1dSAdrian Hunter 16531c6a0718SPierre Ossman mask = SDHCI_CMD_INHIBIT; 165456a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) 16551c6a0718SPierre Ossman mask |= SDHCI_DATA_INHIBIT; 16561c6a0718SPierre Ossman 16571c6a0718SPierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 16581c6a0718SPierre Ossman though they might use busy signaling */ 1659a4c73abaSAdrian Hunter if (cmd->mrq->data && (cmd == cmd->mrq->data->stop)) 16601c6a0718SPierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 16611c6a0718SPierre Ossman 1662845c939eSAdrian Hunter if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) 1663845c939eSAdrian Hunter return false; 16641c6a0718SPierre Ossman 16651c6a0718SPierre Ossman host->cmd = cmd; 166615db1836SFaiz Abbas host->data_timeout = 0; 166756a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) { 16687c89a3d9SAdrian Hunter WARN_ON(host->data_cmd); 16697c89a3d9SAdrian Hunter host->data_cmd = cmd; 167015db1836SFaiz Abbas sdhci_set_timeout(host, cmd); 16717c89a3d9SAdrian Hunter } 16721c6a0718SPierre Ossman 167318e762e3SChunyan Zhang if (cmd->data) { 167418e762e3SChunyan Zhang if (host->use_external_dma) 167518e762e3SChunyan Zhang sdhci_external_dma_prepare_data(host, cmd); 167618e762e3SChunyan Zhang else 1677a3c7778fSAndrei Warkentin sdhci_prepare_data(host, cmd); 167818e762e3SChunyan Zhang } 16791c6a0718SPierre Ossman 16804e4141a5SAnton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); 16811c6a0718SPierre Ossman 1682e89d456fSAndrei Warkentin sdhci_set_transfer_mode(host, cmd); 16831c6a0718SPierre Ossman 16841c6a0718SPierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 1685845c939eSAdrian Hunter WARN_ONCE(1, "Unsupported response type!\n"); 1686845c939eSAdrian Hunter /* 1687845c939eSAdrian Hunter * This does not happen in practice because 136-bit response 1688845c939eSAdrian Hunter * commands never have busy waiting, so rather than complicate 1689845c939eSAdrian Hunter * the error path, just remove busy waiting and continue. 1690845c939eSAdrian Hunter */ 1691845c939eSAdrian Hunter cmd->flags &= ~MMC_RSP_BUSY; 16921c6a0718SPierre Ossman } 16931c6a0718SPierre Ossman 16941c6a0718SPierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 16951c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_NONE; 16961c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_136) 16971c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_LONG; 16981c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 16991c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 17001c6a0718SPierre Ossman else 17011c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT; 17021c6a0718SPierre Ossman 17031c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_CRC) 17041c6a0718SPierre Ossman flags |= SDHCI_CMD_CRC; 17051c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 17061c6a0718SPierre Ossman flags |= SDHCI_CMD_INDEX; 1707b513ea25SArindam Nath 1708b513ea25SArindam Nath /* CMD19 is special in that the Data Present Select should be set */ 1709069c9f14SGirish K S if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK || 1710069c9f14SGirish K S cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) 17111c6a0718SPierre Ossman flags |= SDHCI_CMD_DATA; 17121c6a0718SPierre Ossman 1713fc1fa1b7SKishon Vijay Abraham I timeout = jiffies; 1714fc1fa1b7SKishon Vijay Abraham I if (host->data_timeout) 1715fc1fa1b7SKishon Vijay Abraham I timeout += nsecs_to_jiffies(host->data_timeout); 1716fc1fa1b7SKishon Vijay Abraham I else if (!cmd->data && cmd->busy_timeout > 9000) 1717fc1fa1b7SKishon Vijay Abraham I timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; 1718fc1fa1b7SKishon Vijay Abraham I else 1719fc1fa1b7SKishon Vijay Abraham I timeout += 10 * HZ; 1720fc1fa1b7SKishon Vijay Abraham I sdhci_mod_timer(host, cmd->mrq, timeout); 1721fc1fa1b7SKishon Vijay Abraham I 172218e762e3SChunyan Zhang if (host->use_external_dma) 172318e762e3SChunyan Zhang sdhci_external_dma_pre_transfer(host, cmd); 172418e762e3SChunyan Zhang 17254e4141a5SAnton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 1726845c939eSAdrian Hunter 1727845c939eSAdrian Hunter return true; 17281c6a0718SPierre Ossman } 17291c6a0718SPierre Ossman 1730e872f1e2SAdrian Hunter static bool sdhci_present_error(struct sdhci_host *host, 1731e872f1e2SAdrian Hunter struct mmc_command *cmd, bool present) 1732e872f1e2SAdrian Hunter { 1733e872f1e2SAdrian Hunter if (!present || host->flags & SDHCI_DEVICE_DEAD) { 1734e872f1e2SAdrian Hunter cmd->error = -ENOMEDIUM; 1735e872f1e2SAdrian Hunter return true; 1736e872f1e2SAdrian Hunter } 1737e872f1e2SAdrian Hunter 1738e872f1e2SAdrian Hunter return false; 1739e872f1e2SAdrian Hunter } 1740e872f1e2SAdrian Hunter 1741845c939eSAdrian Hunter static bool sdhci_send_command_retry(struct sdhci_host *host, 1742845c939eSAdrian Hunter struct mmc_command *cmd, 1743845c939eSAdrian Hunter unsigned long flags) 1744845c939eSAdrian Hunter __releases(host->lock) 1745845c939eSAdrian Hunter __acquires(host->lock) 1746845c939eSAdrian Hunter { 1747845c939eSAdrian Hunter struct mmc_command *deferred_cmd = host->deferred_cmd; 1748845c939eSAdrian Hunter int timeout = 10; /* Approx. 10 ms */ 1749845c939eSAdrian Hunter bool present; 1750845c939eSAdrian Hunter 1751845c939eSAdrian Hunter while (!sdhci_send_command(host, cmd)) { 1752845c939eSAdrian Hunter if (!timeout--) { 1753845c939eSAdrian Hunter pr_err("%s: Controller never released inhibit bit(s).\n", 1754845c939eSAdrian Hunter mmc_hostname(host->mmc)); 1755efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT); 1756845c939eSAdrian Hunter sdhci_dumpregs(host); 1757845c939eSAdrian Hunter cmd->error = -EIO; 1758845c939eSAdrian Hunter return false; 1759845c939eSAdrian Hunter } 1760845c939eSAdrian Hunter 1761845c939eSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 1762845c939eSAdrian Hunter 1763845c939eSAdrian Hunter usleep_range(1000, 1250); 1764845c939eSAdrian Hunter 1765845c939eSAdrian Hunter present = host->mmc->ops->get_cd(host->mmc); 1766845c939eSAdrian Hunter 1767845c939eSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 1768845c939eSAdrian Hunter 1769845c939eSAdrian Hunter /* A deferred command might disappear, handle that */ 1770845c939eSAdrian Hunter if (cmd == deferred_cmd && cmd != host->deferred_cmd) 1771845c939eSAdrian Hunter return true; 1772845c939eSAdrian Hunter 1773845c939eSAdrian Hunter if (sdhci_present_error(host, cmd, present)) 1774845c939eSAdrian Hunter return false; 1775845c939eSAdrian Hunter } 1776845c939eSAdrian Hunter 1777845c939eSAdrian Hunter if (cmd == host->deferred_cmd) 1778845c939eSAdrian Hunter host->deferred_cmd = NULL; 1779845c939eSAdrian Hunter 1780845c939eSAdrian Hunter return true; 1781845c939eSAdrian Hunter } 1782845c939eSAdrian Hunter 17834a5fc119SAdrian Hunter static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) 17844a5fc119SAdrian Hunter { 17854a5fc119SAdrian Hunter int i, reg; 17864a5fc119SAdrian Hunter 17874a5fc119SAdrian Hunter for (i = 0; i < 4; i++) { 17884a5fc119SAdrian Hunter reg = SDHCI_RESPONSE + (3 - i) * 4; 17894a5fc119SAdrian Hunter cmd->resp[i] = sdhci_readl(host, reg); 17904a5fc119SAdrian Hunter } 17914a5fc119SAdrian Hunter 17921284c248SKishon Vijay Abraham I if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC) 17931284c248SKishon Vijay Abraham I return; 17941284c248SKishon Vijay Abraham I 17954a5fc119SAdrian Hunter /* CRC is stripped so we need to do some shifting */ 17964a5fc119SAdrian Hunter for (i = 0; i < 4; i++) { 17974a5fc119SAdrian Hunter cmd->resp[i] <<= 8; 17984a5fc119SAdrian Hunter if (i != 3) 17994a5fc119SAdrian Hunter cmd->resp[i] |= cmd->resp[i + 1] >> 24; 18004a5fc119SAdrian Hunter } 18014a5fc119SAdrian Hunter } 18024a5fc119SAdrian Hunter 18031c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *host) 18041c6a0718SPierre Ossman { 1805e0a5640aSAdrian Hunter struct mmc_command *cmd = host->cmd; 18061c6a0718SPierre Ossman 1807e0a5640aSAdrian Hunter host->cmd = NULL; 1808e0a5640aSAdrian Hunter 1809e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_PRESENT) { 1810e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_136) { 18114a5fc119SAdrian Hunter sdhci_read_rsp_136(host, cmd); 18121c6a0718SPierre Ossman } else { 1813e0a5640aSAdrian Hunter cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); 18141c6a0718SPierre Ossman } 18151c6a0718SPierre Ossman } 18161c6a0718SPierre Ossman 181720845befSAdrian Hunter if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd) 181820845befSAdrian Hunter mmc_command_done(host->mmc, cmd->mrq); 181920845befSAdrian Hunter 18206bde8681SAdrian Hunter /* 18216bde8681SAdrian Hunter * The host can send and interrupt when the busy state has 18226bde8681SAdrian Hunter * ended, allowing us to wait without wasting CPU cycles. 18236bde8681SAdrian Hunter * The busy signal uses DAT0 so this is similar to waiting 18246bde8681SAdrian Hunter * for data to complete. 18256bde8681SAdrian Hunter * 18266bde8681SAdrian Hunter * Note: The 1.0 specification is a bit ambiguous about this 18276bde8681SAdrian Hunter * feature so there might be some problems with older 18286bde8681SAdrian Hunter * controllers. 18296bde8681SAdrian Hunter */ 1830e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_BUSY) { 1831e0a5640aSAdrian Hunter if (cmd->data) { 18326bde8681SAdrian Hunter DBG("Cannot wait for busy signal when also doing a data transfer"); 18336bde8681SAdrian Hunter } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && 1834ea968023SAdrian Hunter cmd == host->data_cmd) { 1835ea968023SAdrian Hunter /* Command complete before busy is ended */ 18366bde8681SAdrian Hunter return; 18376bde8681SAdrian Hunter } 18386bde8681SAdrian Hunter } 18396bde8681SAdrian Hunter 1840e89d456fSAndrei Warkentin /* Finished CMD23, now send actual command. */ 1841a4c73abaSAdrian Hunter if (cmd == cmd->mrq->sbc) { 1842845c939eSAdrian Hunter if (!sdhci_send_command(host, cmd->mrq->cmd)) { 1843845c939eSAdrian Hunter WARN_ON(host->deferred_cmd); 1844845c939eSAdrian Hunter host->deferred_cmd = cmd->mrq->cmd; 1845845c939eSAdrian Hunter } 1846e89d456fSAndrei Warkentin } else { 1847e89d456fSAndrei Warkentin 1848e89d456fSAndrei Warkentin /* Processed actual command. */ 1849e538fbe8SPierre Ossman if (host->data && host->data_early) 1850e538fbe8SPierre Ossman sdhci_finish_data(host); 1851e538fbe8SPierre Ossman 1852e0a5640aSAdrian Hunter if (!cmd->data) 185319d2f695SAdrian Hunter __sdhci_finish_mrq(host, cmd->mrq); 18541c6a0718SPierre Ossman } 1855e89d456fSAndrei Warkentin } 18561c6a0718SPierre Ossman 185752983382SKevin Liu static u16 sdhci_get_preset_value(struct sdhci_host *host) 185852983382SKevin Liu { 1859d975f121SRussell King u16 preset = 0; 186052983382SKevin Liu 1861d975f121SRussell King switch (host->timing) { 1862d0244847SAl Cooper case MMC_TIMING_MMC_HS: 1863d0244847SAl Cooper case MMC_TIMING_SD_HS: 1864d0244847SAl Cooper preset = sdhci_readw(host, SDHCI_PRESET_FOR_HIGH_SPEED); 1865d0244847SAl Cooper break; 1866d975f121SRussell King case MMC_TIMING_UHS_SDR12: 186752983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); 186852983382SKevin Liu break; 1869d975f121SRussell King case MMC_TIMING_UHS_SDR25: 187052983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25); 187152983382SKevin Liu break; 1872d975f121SRussell King case MMC_TIMING_UHS_SDR50: 187352983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50); 187452983382SKevin Liu break; 1875d975f121SRussell King case MMC_TIMING_UHS_SDR104: 1876d975f121SRussell King case MMC_TIMING_MMC_HS200: 187752983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104); 187852983382SKevin Liu break; 1879d975f121SRussell King case MMC_TIMING_UHS_DDR50: 18800dafa60eSJisheng Zhang case MMC_TIMING_MMC_DDR52: 188152983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50); 188252983382SKevin Liu break; 1883e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400: 1884e9fb05d5SAdrian Hunter preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400); 1885e9fb05d5SAdrian Hunter break; 188652983382SKevin Liu default: 188752983382SKevin Liu pr_warn("%s: Invalid UHS-I mode selected\n", 188852983382SKevin Liu mmc_hostname(host->mmc)); 188952983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); 189052983382SKevin Liu break; 189152983382SKevin Liu } 189252983382SKevin Liu return preset; 189352983382SKevin Liu } 189452983382SKevin Liu 1895fb9ee047SLudovic Desroches u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, 1896fb9ee047SLudovic Desroches unsigned int *actual_clock) 18971c6a0718SPierre Ossman { 1898c3ed3877SArindam Nath int div = 0; /* Initialized for compiler warning */ 1899df16219fSGiuseppe CAVALLARO int real_div = div, clk_mul = 1; 1900c3ed3877SArindam Nath u16 clk = 0; 19015497159cSludovic.desroches@atmel.com bool switch_base_clk = false; 19021c6a0718SPierre Ossman 190385105c53SZhangfei Gao if (host->version >= SDHCI_SPEC_300) { 1904da91a8f9SRussell King if (host->preset_enabled) { 190552983382SKevin Liu u16 pre_val; 190652983382SKevin Liu 190752983382SKevin Liu clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 190852983382SKevin Liu pre_val = sdhci_get_preset_value(host); 1909fa091010SMasahiro Yamada div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val); 191052983382SKevin Liu if (host->clk_mul && 1911fa091010SMasahiro Yamada (pre_val & SDHCI_PRESET_CLKGEN_SEL)) { 191252983382SKevin Liu clk = SDHCI_PROG_CLOCK_MODE; 191352983382SKevin Liu real_div = div + 1; 191452983382SKevin Liu clk_mul = host->clk_mul; 191552983382SKevin Liu } else { 191652983382SKevin Liu real_div = max_t(int, 1, div << 1); 191752983382SKevin Liu } 191852983382SKevin Liu goto clock_set; 191952983382SKevin Liu } 192052983382SKevin Liu 1921c3ed3877SArindam Nath /* 1922c3ed3877SArindam Nath * Check if the Host Controller supports Programmable Clock 1923c3ed3877SArindam Nath * Mode. 1924c3ed3877SArindam Nath */ 1925c3ed3877SArindam Nath if (host->clk_mul) { 1926c3ed3877SArindam Nath for (div = 1; div <= 1024; div++) { 192752983382SKevin Liu if ((host->max_clk * host->clk_mul / div) 192852983382SKevin Liu <= clock) 1929c3ed3877SArindam Nath break; 1930c3ed3877SArindam Nath } 19315497159cSludovic.desroches@atmel.com if ((host->max_clk * host->clk_mul / div) <= clock) { 1932c3ed3877SArindam Nath /* 1933c3ed3877SArindam Nath * Set Programmable Clock Mode in the Clock 1934c3ed3877SArindam Nath * Control register. 1935c3ed3877SArindam Nath */ 1936c3ed3877SArindam Nath clk = SDHCI_PROG_CLOCK_MODE; 1937df16219fSGiuseppe CAVALLARO real_div = div; 1938df16219fSGiuseppe CAVALLARO clk_mul = host->clk_mul; 1939c3ed3877SArindam Nath div--; 1940c3ed3877SArindam Nath } else { 19415497159cSludovic.desroches@atmel.com /* 19425497159cSludovic.desroches@atmel.com * Divisor can be too small to reach clock 19435497159cSludovic.desroches@atmel.com * speed requirement. Then use the base clock. 19445497159cSludovic.desroches@atmel.com */ 19455497159cSludovic.desroches@atmel.com switch_base_clk = true; 19465497159cSludovic.desroches@atmel.com } 19475497159cSludovic.desroches@atmel.com } 19485497159cSludovic.desroches@atmel.com 19495497159cSludovic.desroches@atmel.com if (!host->clk_mul || switch_base_clk) { 195085105c53SZhangfei Gao /* Version 3.00 divisors must be a multiple of 2. */ 195185105c53SZhangfei Gao if (host->max_clk <= clock) 195285105c53SZhangfei Gao div = 1; 195385105c53SZhangfei Gao else { 1954c3ed3877SArindam Nath for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; 1955c3ed3877SArindam Nath div += 2) { 195685105c53SZhangfei Gao if ((host->max_clk / div) <= clock) 195785105c53SZhangfei Gao break; 195885105c53SZhangfei Gao } 195985105c53SZhangfei Gao } 1960df16219fSGiuseppe CAVALLARO real_div = div; 1961c3ed3877SArindam Nath div >>= 1; 1962d1955c3aSSuneel Garapati if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN) 1963d1955c3aSSuneel Garapati && !div && host->max_clk <= 25000000) 1964d1955c3aSSuneel Garapati div = 1; 1965c3ed3877SArindam Nath } 196685105c53SZhangfei Gao } else { 196785105c53SZhangfei Gao /* Version 2.00 divisors must be a power of 2. */ 19680397526dSZhangfei Gao for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { 19691c6a0718SPierre Ossman if ((host->max_clk / div) <= clock) 19701c6a0718SPierre Ossman break; 19711c6a0718SPierre Ossman } 1972df16219fSGiuseppe CAVALLARO real_div = div; 19731c6a0718SPierre Ossman div >>= 1; 1974c3ed3877SArindam Nath } 19751c6a0718SPierre Ossman 197652983382SKevin Liu clock_set: 197703d6f5ffSAisheng Dong if (real_div) 1978fb9ee047SLudovic Desroches *actual_clock = (host->max_clk * clk_mul) / real_div; 1979c3ed3877SArindam Nath clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 198085105c53SZhangfei Gao clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 198185105c53SZhangfei Gao << SDHCI_DIVIDER_HI_SHIFT; 1982fb9ee047SLudovic Desroches 1983fb9ee047SLudovic Desroches return clk; 1984fb9ee047SLudovic Desroches } 1985fb9ee047SLudovic Desroches EXPORT_SYMBOL_GPL(sdhci_calc_clk); 1986fb9ee047SLudovic Desroches 1987fec79673SRitesh Harjani void sdhci_enable_clk(struct sdhci_host *host, u16 clk) 1988fb9ee047SLudovic Desroches { 19895a436cc0SAdrian Hunter ktime_t timeout; 1990fb9ee047SLudovic Desroches 19911c6a0718SPierre Ossman clk |= SDHCI_CLOCK_INT_EN; 19924e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 19931c6a0718SPierre Ossman 19944a9e0d1aSBen Chuang /* Wait max 150 ms */ 19954a9e0d1aSBen Chuang timeout = ktime_add_ms(ktime_get(), 150); 1996b704441eSAlek Du while (1) { 1997b704441eSAlek Du bool timedout = ktime_after(ktime_get(), timeout); 1998b704441eSAlek Du 1999b704441eSAlek Du clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 2000b704441eSAlek Du if (clk & SDHCI_CLOCK_INT_STABLE) 2001b704441eSAlek Du break; 2002b704441eSAlek Du if (timedout) { 20032e4456f0SMarek Vasut pr_err("%s: Internal clock never stabilised.\n", 20042e4456f0SMarek Vasut mmc_hostname(host->mmc)); 2005efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT); 20061c6a0718SPierre Ossman sdhci_dumpregs(host); 20071c6a0718SPierre Ossman return; 20081c6a0718SPierre Ossman } 20095a436cc0SAdrian Hunter udelay(10); 20101c6a0718SPierre Ossman } 20111c6a0718SPierre Ossman 20121beabbdbSBen Chuang if (host->version >= SDHCI_SPEC_410 && host->v4_mode) { 20131beabbdbSBen Chuang clk |= SDHCI_CLOCK_PLL_EN; 20141beabbdbSBen Chuang clk &= ~SDHCI_CLOCK_INT_STABLE; 20151beabbdbSBen Chuang sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 20161beabbdbSBen Chuang 20171beabbdbSBen Chuang /* Wait max 150 ms */ 20181beabbdbSBen Chuang timeout = ktime_add_ms(ktime_get(), 150); 20191beabbdbSBen Chuang while (1) { 20201beabbdbSBen Chuang bool timedout = ktime_after(ktime_get(), timeout); 20211beabbdbSBen Chuang 20221beabbdbSBen Chuang clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 20231beabbdbSBen Chuang if (clk & SDHCI_CLOCK_INT_STABLE) 20241beabbdbSBen Chuang break; 20251beabbdbSBen Chuang if (timedout) { 20261beabbdbSBen Chuang pr_err("%s: PLL clock never stabilised.\n", 20271beabbdbSBen Chuang mmc_hostname(host->mmc)); 2028efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT); 20291beabbdbSBen Chuang sdhci_dumpregs(host); 20301beabbdbSBen Chuang return; 20311beabbdbSBen Chuang } 20321beabbdbSBen Chuang udelay(10); 20331beabbdbSBen Chuang } 20341beabbdbSBen Chuang } 20351beabbdbSBen Chuang 20361c6a0718SPierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 20374e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 20381c6a0718SPierre Ossman } 2039fec79673SRitesh Harjani EXPORT_SYMBOL_GPL(sdhci_enable_clk); 2040fec79673SRitesh Harjani 2041fec79673SRitesh Harjani void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 2042fec79673SRitesh Harjani { 2043fec79673SRitesh Harjani u16 clk; 2044fec79673SRitesh Harjani 2045fec79673SRitesh Harjani host->mmc->actual_clock = 0; 2046fec79673SRitesh Harjani 2047fec79673SRitesh Harjani sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 2048fec79673SRitesh Harjani 2049fec79673SRitesh Harjani if (clock == 0) 2050fec79673SRitesh Harjani return; 2051fec79673SRitesh Harjani 2052fec79673SRitesh Harjani clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 2053fec79673SRitesh Harjani sdhci_enable_clk(host, clk); 2054fec79673SRitesh Harjani } 20551771059cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_clock); 20561c6a0718SPierre Ossman 20571dceb041SAdrian Hunter static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, 205824fbb3caSRussell King unsigned short vdd) 20591c6a0718SPierre Ossman { 20603a48edc4STim Kryger struct mmc_host *mmc = host->mmc; 20611dceb041SAdrian Hunter 20621dceb041SAdrian Hunter mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); 20631dceb041SAdrian Hunter 20641dceb041SAdrian Hunter if (mode != MMC_POWER_OFF) 20651dceb041SAdrian Hunter sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL); 20661dceb041SAdrian Hunter else 20671dceb041SAdrian Hunter sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 20681dceb041SAdrian Hunter } 20691dceb041SAdrian Hunter 2070606d3131SAdrian Hunter void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, 20711dceb041SAdrian Hunter unsigned short vdd) 20721dceb041SAdrian Hunter { 20738364248aSGiuseppe Cavallaro u8 pwr = 0; 20741c6a0718SPierre Ossman 207524fbb3caSRussell King if (mode != MMC_POWER_OFF) { 207624fbb3caSRussell King switch (1 << vdd) { 2077ae628903SPierre Ossman case MMC_VDD_165_195: 20782a609abeSAndy Shevchenko /* 20792a609abeSAndy Shevchenko * Without a regulator, SDHCI does not support 2.0v 20802a609abeSAndy Shevchenko * so we only get here if the driver deliberately 20812a609abeSAndy Shevchenko * added the 2.0v range to ocr_avail. Map it to 1.8v 20822a609abeSAndy Shevchenko * for the purpose of turning on the power. 20832a609abeSAndy Shevchenko */ 20842a609abeSAndy Shevchenko case MMC_VDD_20_21: 2085ae628903SPierre Ossman pwr = SDHCI_POWER_180; 2086ae628903SPierre Ossman break; 2087ae628903SPierre Ossman case MMC_VDD_29_30: 2088ae628903SPierre Ossman case MMC_VDD_30_31: 2089ae628903SPierre Ossman pwr = SDHCI_POWER_300; 2090ae628903SPierre Ossman break; 2091ae628903SPierre Ossman case MMC_VDD_32_33: 2092ae628903SPierre Ossman case MMC_VDD_33_34: 20934217d07bSShawn Guo /* 20944217d07bSShawn Guo * 3.4 ~ 3.6V are valid only for those platforms where it's 20954217d07bSShawn Guo * known that the voltage range is supported by hardware. 20964217d07bSShawn Guo */ 20974217d07bSShawn Guo case MMC_VDD_34_35: 20984217d07bSShawn Guo case MMC_VDD_35_36: 2099ae628903SPierre Ossman pwr = SDHCI_POWER_330; 2100ae628903SPierre Ossman break; 2101ae628903SPierre Ossman default: 21029d5de93fSAdrian Hunter WARN(1, "%s: Invalid vdd %#x\n", 21039d5de93fSAdrian Hunter mmc_hostname(host->mmc), vdd); 21049d5de93fSAdrian Hunter break; 2105ae628903SPierre Ossman } 2106ae628903SPierre Ossman } 2107ae628903SPierre Ossman 2108ae628903SPierre Ossman if (host->pwr == pwr) 2109e921a8b6SRussell King return; 21101c6a0718SPierre Ossman 2111ae628903SPierre Ossman host->pwr = pwr; 2112ae628903SPierre Ossman 2113ae628903SPierre Ossman if (pwr == 0) { 21144e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 2115f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 2116f0710a55SAdrian Hunter sdhci_runtime_pm_bus_off(host); 2117e921a8b6SRussell King } else { 21181c6a0718SPierre Ossman /* 21191c6a0718SPierre Ossman * Spec says that we should clear the power reg before setting 21201c6a0718SPierre Ossman * a new value. Some controllers don't seem to like this though. 21211c6a0718SPierre Ossman */ 2122b8c86fc5SPierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 21234e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 21241c6a0718SPierre Ossman 2125e08c1694SAndres Salomon /* 2126e921a8b6SRussell King * At least the Marvell CaFe chip gets confused if we set the 2127e921a8b6SRussell King * voltage and set turn on power at the same time, so set the 2128e921a8b6SRussell King * voltage first. 2129e08c1694SAndres Salomon */ 213011a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) 21314e4141a5SAnton Vorontsov sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 21321c6a0718SPierre Ossman 2133ae628903SPierre Ossman pwr |= SDHCI_POWER_ON; 2134ae628903SPierre Ossman 2135ae628903SPierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 2136557b0697SHarald Welte 2137f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 2138f0710a55SAdrian Hunter sdhci_runtime_pm_bus_on(host); 2139f0710a55SAdrian Hunter 2140557b0697SHarald Welte /* 2141e921a8b6SRussell King * Some controllers need an extra 10ms delay of 10ms before 2142e921a8b6SRussell King * they can apply clock after applying power 2143557b0697SHarald Welte */ 214411a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) 2145557b0697SHarald Welte mdelay(10); 2146e921a8b6SRussell King } 2147918f4cbdSJisheng Zhang } 2148606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power_noreg); 21491dceb041SAdrian Hunter 2150606d3131SAdrian Hunter void sdhci_set_power(struct sdhci_host *host, unsigned char mode, 21511dceb041SAdrian Hunter unsigned short vdd) 21521dceb041SAdrian Hunter { 2153606d3131SAdrian Hunter if (IS_ERR(host->mmc->supply.vmmc)) 2154606d3131SAdrian Hunter sdhci_set_power_noreg(host, mode, vdd); 21551dceb041SAdrian Hunter else 2156606d3131SAdrian Hunter sdhci_set_power_reg(host, mode, vdd); 21571c6a0718SPierre Ossman } 2158606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power); 21591c6a0718SPierre Ossman 21606c92ae1eSNicolas Saenz Julienne /* 21616c92ae1eSNicolas Saenz Julienne * Some controllers need to configure a valid bus voltage on their power 21626c92ae1eSNicolas Saenz Julienne * register regardless of whether an external regulator is taking care of power 21636c92ae1eSNicolas Saenz Julienne * supply. This helper function takes care of it if set as the controller's 21646c92ae1eSNicolas Saenz Julienne * sdhci_ops.set_power callback. 21656c92ae1eSNicolas Saenz Julienne */ 21666c92ae1eSNicolas Saenz Julienne void sdhci_set_power_and_bus_voltage(struct sdhci_host *host, 21676c92ae1eSNicolas Saenz Julienne unsigned char mode, 21686c92ae1eSNicolas Saenz Julienne unsigned short vdd) 21696c92ae1eSNicolas Saenz Julienne { 21706c92ae1eSNicolas Saenz Julienne if (!IS_ERR(host->mmc->supply.vmmc)) { 21716c92ae1eSNicolas Saenz Julienne struct mmc_host *mmc = host->mmc; 21726c92ae1eSNicolas Saenz Julienne 21736c92ae1eSNicolas Saenz Julienne mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); 21746c92ae1eSNicolas Saenz Julienne } 21756c92ae1eSNicolas Saenz Julienne sdhci_set_power_noreg(host, mode, vdd); 21766c92ae1eSNicolas Saenz Julienne } 21776c92ae1eSNicolas Saenz Julienne EXPORT_SYMBOL_GPL(sdhci_set_power_and_bus_voltage); 21786c92ae1eSNicolas Saenz Julienne 21791c6a0718SPierre Ossman /*****************************************************************************\ 21801c6a0718SPierre Ossman * * 21811c6a0718SPierre Ossman * MMC callbacks * 21821c6a0718SPierre Ossman * * 21831c6a0718SPierre Ossman \*****************************************************************************/ 21841c6a0718SPierre Ossman 2185d462c1b4SAapo Vienamo void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 21861c6a0718SPierre Ossman { 2187e872f1e2SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2188e872f1e2SAdrian Hunter struct mmc_command *cmd; 21891c6a0718SPierre Ossman unsigned long flags; 2190e872f1e2SAdrian Hunter bool present; 21911c6a0718SPierre Ossman 219204e079cfSScott Branden /* Firstly check card presence */ 21938d28b7a7SAdrian Hunter present = mmc->ops->get_cd(mmc); 21942836766aSKrzysztof Kozlowski 21951c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 21961c6a0718SPierre Ossman 2197061d17a6SAdrian Hunter sdhci_led_activate(host); 2198e89d456fSAndrei Warkentin 2199e872f1e2SAdrian Hunter if (sdhci_present_error(host, mrq->cmd, present)) 2200e872f1e2SAdrian Hunter goto out_finish; 22011c6a0718SPierre Ossman 2202e872f1e2SAdrian Hunter cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; 2203e872f1e2SAdrian Hunter 2204845c939eSAdrian Hunter if (!sdhci_send_command_retry(host, cmd, flags)) 2205845c939eSAdrian Hunter goto out_finish; 2206e872f1e2SAdrian Hunter 2207e872f1e2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2208e872f1e2SAdrian Hunter 2209e872f1e2SAdrian Hunter return; 2210e872f1e2SAdrian Hunter 2211e872f1e2SAdrian Hunter out_finish: 2212e872f1e2SAdrian Hunter sdhci_finish_mrq(host, mrq); 22131c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 22141c6a0718SPierre Ossman } 2215d462c1b4SAapo Vienamo EXPORT_SYMBOL_GPL(sdhci_request); 22161c6a0718SPierre Ossman 221748ef8a2aSBaolin Wang int sdhci_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq) 221848ef8a2aSBaolin Wang { 221948ef8a2aSBaolin Wang struct sdhci_host *host = mmc_priv(mmc); 222048ef8a2aSBaolin Wang struct mmc_command *cmd; 222148ef8a2aSBaolin Wang unsigned long flags; 222248ef8a2aSBaolin Wang int ret = 0; 222348ef8a2aSBaolin Wang 222448ef8a2aSBaolin Wang spin_lock_irqsave(&host->lock, flags); 222548ef8a2aSBaolin Wang 222648ef8a2aSBaolin Wang if (sdhci_present_error(host, mrq->cmd, true)) { 222748ef8a2aSBaolin Wang sdhci_finish_mrq(host, mrq); 222848ef8a2aSBaolin Wang goto out_finish; 222948ef8a2aSBaolin Wang } 223048ef8a2aSBaolin Wang 223148ef8a2aSBaolin Wang cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; 223248ef8a2aSBaolin Wang 223348ef8a2aSBaolin Wang /* 223448ef8a2aSBaolin Wang * The HSQ may send a command in interrupt context without polling 223548ef8a2aSBaolin Wang * the busy signaling, which means we should return BUSY if controller 223648ef8a2aSBaolin Wang * has not released inhibit bits to allow HSQ trying to send request 223748ef8a2aSBaolin Wang * again in non-atomic context. So we should not finish this request 223848ef8a2aSBaolin Wang * here. 223948ef8a2aSBaolin Wang */ 224048ef8a2aSBaolin Wang if (!sdhci_send_command(host, cmd)) 224148ef8a2aSBaolin Wang ret = -EBUSY; 224248ef8a2aSBaolin Wang else 224348ef8a2aSBaolin Wang sdhci_led_activate(host); 224448ef8a2aSBaolin Wang 224548ef8a2aSBaolin Wang out_finish: 224648ef8a2aSBaolin Wang spin_unlock_irqrestore(&host->lock, flags); 224748ef8a2aSBaolin Wang return ret; 224848ef8a2aSBaolin Wang } 224948ef8a2aSBaolin Wang EXPORT_SYMBOL_GPL(sdhci_request_atomic); 225048ef8a2aSBaolin Wang 22512317f56cSRussell King void sdhci_set_bus_width(struct sdhci_host *host, int width) 22522317f56cSRussell King { 22532317f56cSRussell King u8 ctrl; 22542317f56cSRussell King 22552317f56cSRussell King ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 22562317f56cSRussell King if (width == MMC_BUS_WIDTH_8) { 22572317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS; 22582317f56cSRussell King ctrl |= SDHCI_CTRL_8BITBUS; 22592317f56cSRussell King } else { 226098f94ea6SMichał Mirosław if (host->mmc->caps & MMC_CAP_8_BIT_DATA) 22612317f56cSRussell King ctrl &= ~SDHCI_CTRL_8BITBUS; 22622317f56cSRussell King if (width == MMC_BUS_WIDTH_4) 22632317f56cSRussell King ctrl |= SDHCI_CTRL_4BITBUS; 22642317f56cSRussell King else 22652317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS; 22662317f56cSRussell King } 22672317f56cSRussell King sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 22682317f56cSRussell King } 22692317f56cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_bus_width); 22702317f56cSRussell King 227196d7b78cSRussell King void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) 227296d7b78cSRussell King { 227396d7b78cSRussell King u16 ctrl_2; 227496d7b78cSRussell King 227596d7b78cSRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 227696d7b78cSRussell King /* Select Bus Speed Mode for host */ 227796d7b78cSRussell King ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 227896d7b78cSRussell King if ((timing == MMC_TIMING_MMC_HS200) || 227996d7b78cSRussell King (timing == MMC_TIMING_UHS_SDR104)) 228096d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR104; 228196d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR12) 228296d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR12; 228307bcc411SFaiz Abbas else if (timing == MMC_TIMING_UHS_SDR25) 228496d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 228596d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR50) 228696d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR50; 228796d7b78cSRussell King else if ((timing == MMC_TIMING_UHS_DDR50) || 228896d7b78cSRussell King (timing == MMC_TIMING_MMC_DDR52)) 228996d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_DDR50; 2290e9fb05d5SAdrian Hunter else if (timing == MMC_TIMING_MMC_HS400) 2291e9fb05d5SAdrian Hunter ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */ 229296d7b78cSRussell King sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 229396d7b78cSRussell King } 229496d7b78cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); 229596d7b78cSRussell King 22966a6d4cebSHu Ziji void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 22971c6a0718SPierre Ossman { 2298ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 22991c6a0718SPierre Ossman u8 ctrl; 23001c6a0718SPierre Ossman 230184ec048bSAdrian Hunter if (ios->power_mode == MMC_POWER_UNDEFINED) 230284ec048bSAdrian Hunter return; 230384ec048bSAdrian Hunter 2304ceb6143bSAdrian Hunter if (host->flags & SDHCI_DEVICE_DEAD) { 23053a48edc4STim Kryger if (!IS_ERR(mmc->supply.vmmc) && 23063a48edc4STim Kryger ios->power_mode == MMC_POWER_OFF) 23074e743f1fSMarkus Mayer mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 2308ceb6143bSAdrian Hunter return; 2309ceb6143bSAdrian Hunter } 23101e72859eSPierre Ossman 23111c6a0718SPierre Ossman /* 23121c6a0718SPierre Ossman * Reset the chip on each power off. 23131c6a0718SPierre Ossman * Should clear out any weird states. 23141c6a0718SPierre Ossman */ 23151c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 23164e4141a5SAnton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 23177260cf5eSAnton Vorontsov sdhci_reinit(host); 23181c6a0718SPierre Ossman } 23191c6a0718SPierre Ossman 232052983382SKevin Liu if (host->version >= SDHCI_SPEC_300 && 2321372c4634SDong Aisheng (ios->power_mode == MMC_POWER_UP) && 2322372c4634SDong Aisheng !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) 232352983382SKevin Liu sdhci_enable_preset_value(host, false); 232452983382SKevin Liu 2325373073efSRussell King if (!ios->clock || ios->clock != host->clock) { 23261771059cSRussell King host->ops->set_clock(host, ios->clock); 2327373073efSRussell King host->clock = ios->clock; 232803d6f5ffSAisheng Dong 232903d6f5ffSAisheng Dong if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && 233003d6f5ffSAisheng Dong host->clock) { 2331d2f025b0SJisheng Zhang host->timeout_clk = mmc->actual_clock ? 2332d2f025b0SJisheng Zhang mmc->actual_clock / 1000 : 233303d6f5ffSAisheng Dong host->clock / 1000; 2334d2f025b0SJisheng Zhang mmc->max_busy_timeout = 233503d6f5ffSAisheng Dong host->ops->get_max_timeout_count ? 233603d6f5ffSAisheng Dong host->ops->get_max_timeout_count(host) : 233703d6f5ffSAisheng Dong 1 << 27; 2338d2f025b0SJisheng Zhang mmc->max_busy_timeout /= host->timeout_clk; 233903d6f5ffSAisheng Dong } 2340373073efSRussell King } 23411c6a0718SPierre Ossman 2342606d3131SAdrian Hunter if (host->ops->set_power) 2343606d3131SAdrian Hunter host->ops->set_power(host, ios->power_mode, ios->vdd); 2344606d3131SAdrian Hunter else 2345606d3131SAdrian Hunter sdhci_set_power(host, ios->power_mode, ios->vdd); 23461c6a0718SPierre Ossman 2347643a81ffSPhilip Rakity if (host->ops->platform_send_init_74_clocks) 2348643a81ffSPhilip Rakity host->ops->platform_send_init_74_clocks(host, ios->power_mode); 2349643a81ffSPhilip Rakity 23502317f56cSRussell King host->ops->set_bus_width(host, ios->bus_width); 235115ec4461SPhilip Rakity 235215ec4461SPhilip Rakity ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 23531c6a0718SPierre Ossman 2354501639bfSyangbo lu if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) { 2355501639bfSyangbo lu if (ios->timing == MMC_TIMING_SD_HS || 2356273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS || 2357273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS400 || 2358273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS200 || 2359273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_DDR52 || 2360273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR50 || 2361273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR104 || 2362273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_DDR50 || 2363273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR25) 23641c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_HISPD; 23651c6a0718SPierre Ossman else 23661c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 2367501639bfSyangbo lu } 23681c6a0718SPierre Ossman 2369d6d50a15SArindam Nath if (host->version >= SDHCI_SPEC_300) { 237049c468fcSArindam Nath u16 clk, ctrl_2; 237149c468fcSArindam Nath 2372da91a8f9SRussell King if (!host->preset_enabled) { 2373758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2374d6d50a15SArindam Nath /* 2375d6d50a15SArindam Nath * We only need to set Driver Strength if the 2376d6d50a15SArindam Nath * preset value enable is not set. 2377d6d50a15SArindam Nath */ 2378da91a8f9SRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2379d6d50a15SArindam Nath ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; 2380d6d50a15SArindam Nath if (ios->drv_type == MMC_SET_DRIVER_TYPE_A) 2381d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; 238243e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_B) 238343e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B; 2384d6d50a15SArindam Nath else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C) 2385d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C; 238643e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D) 238743e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D; 238843e943a0SPetri Gynther else { 23892e4456f0SMarek Vasut pr_warn("%s: invalid driver type, default to driver type B\n", 23902e4456f0SMarek Vasut mmc_hostname(mmc)); 239143e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B; 239243e943a0SPetri Gynther } 2393d6d50a15SArindam Nath 2394d6d50a15SArindam Nath sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 2395758535c4SArindam Nath } else { 2396758535c4SArindam Nath /* 2397758535c4SArindam Nath * According to SDHC Spec v3.00, if the Preset Value 2398758535c4SArindam Nath * Enable in the Host Control 2 register is set, we 2399758535c4SArindam Nath * need to reset SD Clock Enable before changing High 2400758535c4SArindam Nath * Speed Enable to avoid generating clock gliches. 2401758535c4SArindam Nath */ 2402758535c4SArindam Nath 2403758535c4SArindam Nath /* Reset SD Clock Enable */ 2404758535c4SArindam Nath clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 2405758535c4SArindam Nath clk &= ~SDHCI_CLOCK_CARD_EN; 2406758535c4SArindam Nath sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 2407758535c4SArindam Nath 2408758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2409758535c4SArindam Nath 2410758535c4SArindam Nath /* Re-enable SD Clock */ 24111771059cSRussell King host->ops->set_clock(host, host->clock); 2412d6d50a15SArindam Nath } 241349c468fcSArindam Nath 24146322cdd0SPhilip Rakity /* Reset SD Clock Enable */ 24156322cdd0SPhilip Rakity clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 24166322cdd0SPhilip Rakity clk &= ~SDHCI_CLOCK_CARD_EN; 24176322cdd0SPhilip Rakity sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 24186322cdd0SPhilip Rakity 24196322cdd0SPhilip Rakity host->ops->set_uhs_signaling(host, ios->timing); 2420d975f121SRussell King host->timing = ios->timing; 242149c468fcSArindam Nath 242252983382SKevin Liu if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && 242352983382SKevin Liu ((ios->timing == MMC_TIMING_UHS_SDR12) || 242452983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR25) || 242552983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR50) || 242652983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR104) || 24270dafa60eSJisheng Zhang (ios->timing == MMC_TIMING_UHS_DDR50) || 24280dafa60eSJisheng Zhang (ios->timing == MMC_TIMING_MMC_DDR52))) { 242952983382SKevin Liu u16 preset; 243052983382SKevin Liu 243152983382SKevin Liu sdhci_enable_preset_value(host, true); 243252983382SKevin Liu preset = sdhci_get_preset_value(host); 2433fa091010SMasahiro Yamada ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK, 2434fa091010SMasahiro Yamada preset); 243552983382SKevin Liu } 243652983382SKevin Liu 243749c468fcSArindam Nath /* Re-enable SD Clock */ 24381771059cSRussell King host->ops->set_clock(host, host->clock); 2439758535c4SArindam Nath } else 2440758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 24411c6a0718SPierre Ossman } 24426a6d4cebSHu Ziji EXPORT_SYMBOL_GPL(sdhci_set_ios); 24431c6a0718SPierre Ossman 2444ded97e0bSDong Aisheng static int sdhci_get_cd(struct mmc_host *mmc) 244566fd8ad5SAdrian Hunter { 244666fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2447ded97e0bSDong Aisheng int gpio_cd = mmc_gpio_get_cd(mmc); 244894144a46SKevin Liu 244994144a46SKevin Liu if (host->flags & SDHCI_DEVICE_DEAD) 245094144a46SKevin Liu return 0; 245194144a46SKevin Liu 245288af5655SIvan T. Ivanov /* If nonremovable, assume that the card is always present. */ 2453d2f025b0SJisheng Zhang if (!mmc_card_is_removable(mmc)) 245494144a46SKevin Liu return 1; 245594144a46SKevin Liu 245688af5655SIvan T. Ivanov /* 245788af5655SIvan T. Ivanov * Try slot gpio detect, if defined it take precedence 245888af5655SIvan T. Ivanov * over build in controller functionality 245988af5655SIvan T. Ivanov */ 2460287980e4SArnd Bergmann if (gpio_cd >= 0) 246194144a46SKevin Liu return !!gpio_cd; 246294144a46SKevin Liu 246388af5655SIvan T. Ivanov /* If polling, assume that the card is always present. */ 246488af5655SIvan T. Ivanov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 246588af5655SIvan T. Ivanov return 1; 246688af5655SIvan T. Ivanov 246794144a46SKevin Liu /* Host native card detect */ 246894144a46SKevin Liu return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); 246994144a46SKevin Liu } 247094144a46SKevin Liu 24712caa11bcSAndy Shevchenko int sdhci_get_cd_nogpio(struct mmc_host *mmc) 24722caa11bcSAndy Shevchenko { 24732caa11bcSAndy Shevchenko struct sdhci_host *host = mmc_priv(mmc); 24742caa11bcSAndy Shevchenko unsigned long flags; 24752caa11bcSAndy Shevchenko int ret = 0; 24762caa11bcSAndy Shevchenko 24772caa11bcSAndy Shevchenko spin_lock_irqsave(&host->lock, flags); 24782caa11bcSAndy Shevchenko 24792caa11bcSAndy Shevchenko if (host->flags & SDHCI_DEVICE_DEAD) 24802caa11bcSAndy Shevchenko goto out; 24812caa11bcSAndy Shevchenko 24822caa11bcSAndy Shevchenko ret = !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); 24832caa11bcSAndy Shevchenko out: 24842caa11bcSAndy Shevchenko spin_unlock_irqrestore(&host->lock, flags); 24852caa11bcSAndy Shevchenko 24862caa11bcSAndy Shevchenko return ret; 24872caa11bcSAndy Shevchenko } 24882caa11bcSAndy Shevchenko EXPORT_SYMBOL_GPL(sdhci_get_cd_nogpio); 24892caa11bcSAndy Shevchenko 249066fd8ad5SAdrian Hunter static int sdhci_check_ro(struct sdhci_host *host) 24911c6a0718SPierre Ossman { 24921c6a0718SPierre Ossman unsigned long flags; 24932dfb579cSWolfram Sang int is_readonly; 24941c6a0718SPierre Ossman 24951c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 24961c6a0718SPierre Ossman 24971e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 24982dfb579cSWolfram Sang is_readonly = 0; 24992dfb579cSWolfram Sang else if (host->ops->get_ro) 25002dfb579cSWolfram Sang is_readonly = host->ops->get_ro(host); 25016d5cd068SThomas Petazzoni else if (mmc_can_gpio_ro(host->mmc)) 25026d5cd068SThomas Petazzoni is_readonly = mmc_gpio_get_ro(host->mmc); 25031e72859eSPierre Ossman else 25042dfb579cSWolfram Sang is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) 25052dfb579cSWolfram Sang & SDHCI_WRITE_PROTECT); 25061c6a0718SPierre Ossman 25071c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 25081c6a0718SPierre Ossman 25092dfb579cSWolfram Sang /* This quirk needs to be replaced by a callback-function later */ 25102dfb579cSWolfram Sang return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? 25112dfb579cSWolfram Sang !is_readonly : is_readonly; 25121c6a0718SPierre Ossman } 25131c6a0718SPierre Ossman 251482b0e23aSTakashi Iwai #define SAMPLE_COUNT 5 251582b0e23aSTakashi Iwai 2516ded97e0bSDong Aisheng static int sdhci_get_ro(struct mmc_host *mmc) 251782b0e23aSTakashi Iwai { 2518ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 251982b0e23aSTakashi Iwai int i, ro_count; 252082b0e23aSTakashi Iwai 252182b0e23aSTakashi Iwai if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT)) 252266fd8ad5SAdrian Hunter return sdhci_check_ro(host); 252382b0e23aSTakashi Iwai 252482b0e23aSTakashi Iwai ro_count = 0; 252582b0e23aSTakashi Iwai for (i = 0; i < SAMPLE_COUNT; i++) { 252666fd8ad5SAdrian Hunter if (sdhci_check_ro(host)) { 252782b0e23aSTakashi Iwai if (++ro_count > SAMPLE_COUNT / 2) 252882b0e23aSTakashi Iwai return 1; 252982b0e23aSTakashi Iwai } 253082b0e23aSTakashi Iwai msleep(30); 253182b0e23aSTakashi Iwai } 253282b0e23aSTakashi Iwai return 0; 253382b0e23aSTakashi Iwai } 253482b0e23aSTakashi Iwai 253520758b66SAdrian Hunter static void sdhci_hw_reset(struct mmc_host *mmc) 253620758b66SAdrian Hunter { 253720758b66SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 253820758b66SAdrian Hunter 253920758b66SAdrian Hunter if (host->ops && host->ops->hw_reset) 254020758b66SAdrian Hunter host->ops->hw_reset(host); 254120758b66SAdrian Hunter } 254220758b66SAdrian Hunter 254366fd8ad5SAdrian Hunter static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable) 254466fd8ad5SAdrian Hunter { 2545be138554SRussell King if (!(host->flags & SDHCI_DEVICE_DEAD)) { 254666fd8ad5SAdrian Hunter if (enable) 2547b537f94cSRussell King host->ier |= SDHCI_INT_CARD_INT; 25487260cf5eSAnton Vorontsov else 2549b537f94cSRussell King host->ier &= ~SDHCI_INT_CARD_INT; 2550b537f94cSRussell King 2551b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2552b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 255366fd8ad5SAdrian Hunter } 2554ef104333SRussell King } 2555f75979b7SPierre Ossman 25562f05b6abSHu Ziji void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 255766fd8ad5SAdrian Hunter { 255866fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 255966fd8ad5SAdrian Hunter unsigned long flags; 256066fd8ad5SAdrian Hunter 2561923713b3SHans de Goede if (enable) 2562bac53336SJisheng Zhang pm_runtime_get_noresume(mmc_dev(mmc)); 2563923713b3SHans de Goede 256466fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 256566fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, enable); 2566f75979b7SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 2567923713b3SHans de Goede 2568923713b3SHans de Goede if (!enable) 2569bac53336SJisheng Zhang pm_runtime_put_noidle(mmc_dev(mmc)); 2570f75979b7SPierre Ossman } 25712f05b6abSHu Ziji EXPORT_SYMBOL_GPL(sdhci_enable_sdio_irq); 2572f75979b7SPierre Ossman 257389f3c365SAdrian Hunter static void sdhci_ack_sdio_irq(struct mmc_host *mmc) 257489f3c365SAdrian Hunter { 257589f3c365SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 257689f3c365SAdrian Hunter unsigned long flags; 257789f3c365SAdrian Hunter 257889f3c365SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 257989f3c365SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true); 258089f3c365SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 258189f3c365SAdrian Hunter } 258289f3c365SAdrian Hunter 2583c376ea9eSHu Ziji int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, 258421f5998fSFabio Estevam struct mmc_ios *ios) 2585f2119df6SArindam Nath { 2586ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 258720b92a30SKevin Liu u16 ctrl; 25886231f3deSPhilip Rakity int ret; 2589f2119df6SArindam Nath 259020b92a30SKevin Liu /* 259120b92a30SKevin Liu * Signal Voltage Switching is only applicable for Host Controllers 259220b92a30SKevin Liu * v3.00 and above. 259320b92a30SKevin Liu */ 259420b92a30SKevin Liu if (host->version < SDHCI_SPEC_300) 259520b92a30SKevin Liu return 0; 259620b92a30SKevin Liu 259720b92a30SKevin Liu ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 259820b92a30SKevin Liu 259921f5998fSFabio Estevam switch (ios->signal_voltage) { 260020b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_330: 26018cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_330)) 26028cb851a4SAdrian Hunter return -EINVAL; 2603f2119df6SArindam Nath /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ 2604f2119df6SArindam Nath ctrl &= ~SDHCI_CTRL_VDD_180; 2605f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2606f2119df6SArindam Nath 26073a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2608761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 26099cbe0fc8SMarek Vasut if (ret < 0) { 26106606110dSJoe Perches pr_warn("%s: Switching to 3.3V signalling voltage failed\n", 26116606110dSJoe Perches mmc_hostname(mmc)); 26126231f3deSPhilip Rakity return -EIO; 26136231f3deSPhilip Rakity } 26146231f3deSPhilip Rakity } 2615f2119df6SArindam Nath /* Wait for 5ms */ 2616f2119df6SArindam Nath usleep_range(5000, 5500); 2617f2119df6SArindam Nath 2618f2119df6SArindam Nath /* 3.3V regulator output should be stable within 5 ms */ 2619f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2620f2119df6SArindam Nath if (!(ctrl & SDHCI_CTRL_VDD_180)) 2621f2119df6SArindam Nath return 0; 26226231f3deSPhilip Rakity 2623b0b19ce6SFabio Estevam pr_warn("%s: 3.3V regulator output did not become stable\n", 26244e743f1fSMarkus Mayer mmc_hostname(mmc)); 26256231f3deSPhilip Rakity 262620b92a30SKevin Liu return -EAGAIN; 262720b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_180: 26288cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_180)) 26298cb851a4SAdrian Hunter return -EINVAL; 26303a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2631761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 26329cbe0fc8SMarek Vasut if (ret < 0) { 26336606110dSJoe Perches pr_warn("%s: Switching to 1.8V signalling voltage failed\n", 26346606110dSJoe Perches mmc_hostname(mmc)); 2635f2119df6SArindam Nath return -EIO; 2636f2119df6SArindam Nath } 263720b92a30SKevin Liu } 26386231f3deSPhilip Rakity 2639f2119df6SArindam Nath /* 2640f2119df6SArindam Nath * Enable 1.8V Signal Enable in the Host Control2 2641f2119df6SArindam Nath * register 2642f2119df6SArindam Nath */ 2643f2119df6SArindam Nath ctrl |= SDHCI_CTRL_VDD_180; 2644f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2645f2119df6SArindam Nath 26469d967a61SVincent Yang /* Some controller need to do more when switching */ 26479d967a61SVincent Yang if (host->ops->voltage_switch) 26489d967a61SVincent Yang host->ops->voltage_switch(host); 26499d967a61SVincent Yang 265020b92a30SKevin Liu /* 1.8V regulator output should be stable within 5 ms */ 2651f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 265220b92a30SKevin Liu if (ctrl & SDHCI_CTRL_VDD_180) 2653f2119df6SArindam Nath return 0; 2654f2119df6SArindam Nath 2655b0b19ce6SFabio Estevam pr_warn("%s: 1.8V regulator output did not become stable\n", 26564e743f1fSMarkus Mayer mmc_hostname(mmc)); 26576231f3deSPhilip Rakity 2658f2119df6SArindam Nath return -EAGAIN; 265920b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_120: 26608cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_120)) 26618cb851a4SAdrian Hunter return -EINVAL; 26623a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2663761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 26649cbe0fc8SMarek Vasut if (ret < 0) { 26656606110dSJoe Perches pr_warn("%s: Switching to 1.2V signalling voltage failed\n", 26666606110dSJoe Perches mmc_hostname(mmc)); 266720b92a30SKevin Liu return -EIO; 26686231f3deSPhilip Rakity } 266920b92a30SKevin Liu } 26706231f3deSPhilip Rakity return 0; 267120b92a30SKevin Liu default: 2672f2119df6SArindam Nath /* No signal voltage switch required */ 2673f2119df6SArindam Nath return 0; 2674f2119df6SArindam Nath } 267520b92a30SKevin Liu } 2676c376ea9eSHu Ziji EXPORT_SYMBOL_GPL(sdhci_start_signal_voltage_switch); 2677f2119df6SArindam Nath 267820b92a30SKevin Liu static int sdhci_card_busy(struct mmc_host *mmc) 267920b92a30SKevin Liu { 268020b92a30SKevin Liu struct sdhci_host *host = mmc_priv(mmc); 268120b92a30SKevin Liu u32 present_state; 268220b92a30SKevin Liu 2683e613cc47SAdrian Hunter /* Check whether DAT[0] is 0 */ 268420b92a30SKevin Liu present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); 268520b92a30SKevin Liu 2686e613cc47SAdrian Hunter return !(present_state & SDHCI_DATA_0_LVL_MASK); 268720b92a30SKevin Liu } 268820b92a30SKevin Liu 2689b5540ce1SAdrian Hunter static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) 2690b5540ce1SAdrian Hunter { 2691b5540ce1SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2692b5540ce1SAdrian Hunter unsigned long flags; 2693b5540ce1SAdrian Hunter 2694b5540ce1SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2695b5540ce1SAdrian Hunter host->flags |= SDHCI_HS400_TUNING; 2696b5540ce1SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2697b5540ce1SAdrian Hunter 2698b5540ce1SAdrian Hunter return 0; 2699b5540ce1SAdrian Hunter } 2700b5540ce1SAdrian Hunter 27016663c419Sernest.zhang void sdhci_start_tuning(struct sdhci_host *host) 2702da4bc4f2SAdrian Hunter { 2703da4bc4f2SAdrian Hunter u16 ctrl; 2704da4bc4f2SAdrian Hunter 2705da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2706da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_EXEC_TUNING; 2707da4bc4f2SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND) 2708da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_TUNED_CLK; 2709da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2710da4bc4f2SAdrian Hunter 2711da4bc4f2SAdrian Hunter /* 2712da4bc4f2SAdrian Hunter * As per the Host Controller spec v3.00, tuning command 2713da4bc4f2SAdrian Hunter * generates Buffer Read Ready interrupt, so enable that. 2714da4bc4f2SAdrian Hunter * 2715da4bc4f2SAdrian Hunter * Note: The spec clearly says that when tuning sequence 2716da4bc4f2SAdrian Hunter * is being performed, the controller does not generate 2717da4bc4f2SAdrian Hunter * interrupts other than Buffer Read Ready interrupt. But 2718da4bc4f2SAdrian Hunter * to make sure we don't hit a controller bug, we _only_ 2719da4bc4f2SAdrian Hunter * enable Buffer Read Ready interrupt here. 2720da4bc4f2SAdrian Hunter */ 2721da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); 2722da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); 2723da4bc4f2SAdrian Hunter } 27246663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_start_tuning); 2725da4bc4f2SAdrian Hunter 27266663c419Sernest.zhang void sdhci_end_tuning(struct sdhci_host *host) 2727da4bc4f2SAdrian Hunter { 2728da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2729da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 2730da4bc4f2SAdrian Hunter } 27316663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_end_tuning); 2732da4bc4f2SAdrian Hunter 27336663c419Sernest.zhang void sdhci_reset_tuning(struct sdhci_host *host) 2734da4bc4f2SAdrian Hunter { 2735da4bc4f2SAdrian Hunter u16 ctrl; 2736da4bc4f2SAdrian Hunter 2737da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2738da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_TUNED_CLK; 2739da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_EXEC_TUNING; 2740da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2741da4bc4f2SAdrian Hunter } 27426663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_reset_tuning); 2743da4bc4f2SAdrian Hunter 27447353788cSBen Chuang void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) 2745da4bc4f2SAdrian Hunter { 2746da4bc4f2SAdrian Hunter sdhci_reset_tuning(host); 2747da4bc4f2SAdrian Hunter 2748*1e63d297SAdrian Hunter sdhci_reset_for(host, TUNING_ABORT); 2749da4bc4f2SAdrian Hunter 2750da4bc4f2SAdrian Hunter sdhci_end_tuning(host); 2751da4bc4f2SAdrian Hunter 275221adc2e4SWolfram Sang mmc_send_abort_tuning(host->mmc, opcode); 2753da4bc4f2SAdrian Hunter } 27547353788cSBen Chuang EXPORT_SYMBOL_GPL(sdhci_abort_tuning); 2755da4bc4f2SAdrian Hunter 2756da4bc4f2SAdrian Hunter /* 2757da4bc4f2SAdrian Hunter * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI 2758da4bc4f2SAdrian Hunter * tuning command does not have a data payload (or rather the hardware does it 2759da4bc4f2SAdrian Hunter * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command 2760da4bc4f2SAdrian Hunter * interrupt setup is different to other commands and there is no timeout 2761da4bc4f2SAdrian Hunter * interrupt so special handling is needed. 2762da4bc4f2SAdrian Hunter */ 27636663c419Sernest.zhang void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) 2764da4bc4f2SAdrian Hunter { 2765da4bc4f2SAdrian Hunter struct mmc_host *mmc = host->mmc; 2766c7836d15SMasahiro Yamada struct mmc_command cmd = {}; 2767c7836d15SMasahiro Yamada struct mmc_request mrq = {}; 27682a85ef25SAdrian Hunter unsigned long flags; 2769c846a00fSSrinivas Kandagatla u32 b = host->sdma_boundary; 27702a85ef25SAdrian Hunter 27712a85ef25SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2772da4bc4f2SAdrian Hunter 2773da4bc4f2SAdrian Hunter cmd.opcode = opcode; 2774da4bc4f2SAdrian Hunter cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 2775da4bc4f2SAdrian Hunter cmd.mrq = &mrq; 2776da4bc4f2SAdrian Hunter 2777da4bc4f2SAdrian Hunter mrq.cmd = &cmd; 2778da4bc4f2SAdrian Hunter /* 2779da4bc4f2SAdrian Hunter * In response to CMD19, the card sends 64 bytes of tuning 2780da4bc4f2SAdrian Hunter * block to the Host Controller. So we set the block size 2781da4bc4f2SAdrian Hunter * to 64 here. 2782da4bc4f2SAdrian Hunter */ 278385336109SAdrian Hunter if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200 && 278485336109SAdrian Hunter mmc->ios.bus_width == MMC_BUS_WIDTH_8) 2785c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 128), SDHCI_BLOCK_SIZE); 278685336109SAdrian Hunter else 2787c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 64), SDHCI_BLOCK_SIZE); 2788da4bc4f2SAdrian Hunter 2789da4bc4f2SAdrian Hunter /* 2790da4bc4f2SAdrian Hunter * The tuning block is sent by the card to the host controller. 2791da4bc4f2SAdrian Hunter * So we set the TRNS_READ bit in the Transfer Mode register. 2792da4bc4f2SAdrian Hunter * This also takes care of setting DMA Enable and Multi Block 2793da4bc4f2SAdrian Hunter * Select in the same register to 0. 2794da4bc4f2SAdrian Hunter */ 2795da4bc4f2SAdrian Hunter sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); 2796da4bc4f2SAdrian Hunter 2797845c939eSAdrian Hunter if (!sdhci_send_command_retry(host, &cmd, flags)) { 2798845c939eSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2799845c939eSAdrian Hunter host->tuning_done = 0; 2800845c939eSAdrian Hunter return; 2801845c939eSAdrian Hunter } 2802da4bc4f2SAdrian Hunter 2803da4bc4f2SAdrian Hunter host->cmd = NULL; 2804da4bc4f2SAdrian Hunter 2805da4bc4f2SAdrian Hunter sdhci_del_timer(host, &mrq); 2806da4bc4f2SAdrian Hunter 2807da4bc4f2SAdrian Hunter host->tuning_done = 0; 2808da4bc4f2SAdrian Hunter 2809da4bc4f2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2810da4bc4f2SAdrian Hunter 2811da4bc4f2SAdrian Hunter /* Wait for Buffer Read Ready interrupt */ 2812da4bc4f2SAdrian Hunter wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1), 2813da4bc4f2SAdrian Hunter msecs_to_jiffies(50)); 2814da4bc4f2SAdrian Hunter 2815da4bc4f2SAdrian Hunter } 28166663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_send_tuning); 2817da4bc4f2SAdrian Hunter 28187d8bb1f4SYinbo Zhu static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) 28196b11e70bSAdrian Hunter { 28206b11e70bSAdrian Hunter int i; 28216b11e70bSAdrian Hunter 28226b11e70bSAdrian Hunter /* 28236b11e70bSAdrian Hunter * Issue opcode repeatedly till Execute Tuning is set to 0 or the number 28241d8cd065SSowjanya Komatineni * of loops reaches tuning loop count. 28256b11e70bSAdrian Hunter */ 28261d8cd065SSowjanya Komatineni for (i = 0; i < host->tuning_loop_count; i++) { 28276b11e70bSAdrian Hunter u16 ctrl; 28286b11e70bSAdrian Hunter 28292a85ef25SAdrian Hunter sdhci_send_tuning(host, opcode); 28306b11e70bSAdrian Hunter 28316b11e70bSAdrian Hunter if (!host->tuning_done) { 2832811ba676SFaiz Abbas pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n", 28336b11e70bSAdrian Hunter mmc_hostname(host->mmc)); 28342a85ef25SAdrian Hunter sdhci_abort_tuning(host, opcode); 28357d8bb1f4SYinbo Zhu return -ETIMEDOUT; 28366b11e70bSAdrian Hunter } 28376b11e70bSAdrian Hunter 28382b06e159SBOUGH CHEN /* Spec does not require a delay between tuning cycles */ 28392b06e159SBOUGH CHEN if (host->tuning_delay > 0) 28402b06e159SBOUGH CHEN mdelay(host->tuning_delay); 28412b06e159SBOUGH CHEN 28426b11e70bSAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 28436b11e70bSAdrian Hunter if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { 28446b11e70bSAdrian Hunter if (ctrl & SDHCI_CTRL_TUNED_CLK) 28457d8bb1f4SYinbo Zhu return 0; /* Success! */ 28466b11e70bSAdrian Hunter break; 28476b11e70bSAdrian Hunter } 28486b11e70bSAdrian Hunter 28496b11e70bSAdrian Hunter } 28506b11e70bSAdrian Hunter 28516b11e70bSAdrian Hunter pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", 28526b11e70bSAdrian Hunter mmc_hostname(host->mmc)); 28536b11e70bSAdrian Hunter sdhci_reset_tuning(host); 28547d8bb1f4SYinbo Zhu return -EAGAIN; 28556b11e70bSAdrian Hunter } 28566b11e70bSAdrian Hunter 285785a882c2SMasahiro Yamada int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) 2858b513ea25SArindam Nath { 28594b6f37d3SRussell King struct sdhci_host *host = mmc_priv(mmc); 2860b513ea25SArindam Nath int err = 0; 286138e40bf5SAdrian Hunter unsigned int tuning_count = 0; 2862b5540ce1SAdrian Hunter bool hs400_tuning; 2863b513ea25SArindam Nath 2864b5540ce1SAdrian Hunter hs400_tuning = host->flags & SDHCI_HS400_TUNING; 2865b5540ce1SAdrian Hunter 286638e40bf5SAdrian Hunter if (host->tuning_mode == SDHCI_TUNING_MODE_1) 286738e40bf5SAdrian Hunter tuning_count = host->tuning_count; 286838e40bf5SAdrian Hunter 2869b513ea25SArindam Nath /* 28709faac7b9SWeijun Yang * The Host Controller needs tuning in case of SDR104 and DDR50 28719faac7b9SWeijun Yang * mode, and for SDR50 mode when Use Tuning for SDR50 is set in 28729faac7b9SWeijun Yang * the Capabilities register. 2873069c9f14SGirish K S * If the Host Controller supports the HS200 mode then the 2874069c9f14SGirish K S * tuning function has to be executed. 2875b513ea25SArindam Nath */ 28764b6f37d3SRussell King switch (host->timing) { 2877b5540ce1SAdrian Hunter /* HS400 tuning is done in HS200 mode */ 2878e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400: 2879b5540ce1SAdrian Hunter err = -EINVAL; 28802a85ef25SAdrian Hunter goto out; 2881b5540ce1SAdrian Hunter 28824b6f37d3SRussell King case MMC_TIMING_MMC_HS200: 2883b5540ce1SAdrian Hunter /* 2884b5540ce1SAdrian Hunter * Periodic re-tuning for HS400 is not expected to be needed, so 2885b5540ce1SAdrian Hunter * disable it here. 2886b5540ce1SAdrian Hunter */ 2887b5540ce1SAdrian Hunter if (hs400_tuning) 2888b5540ce1SAdrian Hunter tuning_count = 0; 2889b5540ce1SAdrian Hunter break; 2890b5540ce1SAdrian Hunter 28914b6f37d3SRussell King case MMC_TIMING_UHS_SDR104: 28929faac7b9SWeijun Yang case MMC_TIMING_UHS_DDR50: 28934b6f37d3SRussell King break; 2894069c9f14SGirish K S 28954b6f37d3SRussell King case MMC_TIMING_UHS_SDR50: 28964228b213SAdrian Hunter if (host->flags & SDHCI_SDR50_NEEDS_TUNING) 28974b6f37d3SRussell King break; 2898df561f66SGustavo A. R. Silva fallthrough; 28994b6f37d3SRussell King 29004b6f37d3SRussell King default: 29012a85ef25SAdrian Hunter goto out; 2902b513ea25SArindam Nath } 2903b513ea25SArindam Nath 290445251812SDong Aisheng if (host->ops->platform_execute_tuning) { 29058a8fa879SRitesh Harjani err = host->ops->platform_execute_tuning(host, opcode); 29062a85ef25SAdrian Hunter goto out; 290745251812SDong Aisheng } 290845251812SDong Aisheng 2909d2f025b0SJisheng Zhang mmc->retune_period = tuning_count; 29106b11e70bSAdrian Hunter 291183b600b8SAdrian Hunter if (host->tuning_delay < 0) 291283b600b8SAdrian Hunter host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK; 291383b600b8SAdrian Hunter 2914da4bc4f2SAdrian Hunter sdhci_start_tuning(host); 2915b513ea25SArindam Nath 29167d8bb1f4SYinbo Zhu host->tuning_err = __sdhci_execute_tuning(host, opcode); 2917cf2b5eeaSArindam Nath 2918da4bc4f2SAdrian Hunter sdhci_end_tuning(host); 29192a85ef25SAdrian Hunter out: 29208a8fa879SRitesh Harjani host->flags &= ~SDHCI_HS400_TUNING; 29216b11e70bSAdrian Hunter 2922b513ea25SArindam Nath return err; 2923b513ea25SArindam Nath } 292485a882c2SMasahiro Yamada EXPORT_SYMBOL_GPL(sdhci_execute_tuning); 2925b513ea25SArindam Nath 292652983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) 29274d55c5a1SArindam Nath { 29284d55c5a1SArindam Nath /* Host Controller v3.00 defines preset value registers */ 29294d55c5a1SArindam Nath if (host->version < SDHCI_SPEC_300) 29304d55c5a1SArindam Nath return; 29314d55c5a1SArindam Nath 29324d55c5a1SArindam Nath /* 29334d55c5a1SArindam Nath * We only enable or disable Preset Value if they are not already 29344d55c5a1SArindam Nath * enabled or disabled respectively. Otherwise, we bail out. 29354d55c5a1SArindam Nath */ 2936da91a8f9SRussell King if (host->preset_enabled != enable) { 2937da91a8f9SRussell King u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2938da91a8f9SRussell King 2939da91a8f9SRussell King if (enable) 29404d55c5a1SArindam Nath ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; 2941da91a8f9SRussell King else 29424d55c5a1SArindam Nath ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; 2943da91a8f9SRussell King 29444d55c5a1SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2945da91a8f9SRussell King 2946da91a8f9SRussell King if (enable) 2947da91a8f9SRussell King host->flags |= SDHCI_PV_ENABLED; 2948da91a8f9SRussell King else 294966fd8ad5SAdrian Hunter host->flags &= ~SDHCI_PV_ENABLED; 2950da91a8f9SRussell King 2951da91a8f9SRussell King host->preset_enabled = enable; 29524d55c5a1SArindam Nath } 295366fd8ad5SAdrian Hunter } 295466fd8ad5SAdrian Hunter 2955348487cbSHaibo Chen static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, 2956348487cbSHaibo Chen int err) 2957348487cbSHaibo Chen { 2958348487cbSHaibo Chen struct mmc_data *data = mrq->data; 2959348487cbSHaibo Chen 2960f48f039cSRussell King if (data->host_cookie != COOKIE_UNMAPPED) 2961d2f025b0SJisheng Zhang dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, 2962feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 2963771a3dc2SRussell King 2964d31911b9SHaibo Chen data->host_cookie = COOKIE_UNMAPPED; 2965348487cbSHaibo Chen } 2966348487cbSHaibo Chen 2967d3c6aac3SLinus Walleij static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) 2968348487cbSHaibo Chen { 2969348487cbSHaibo Chen struct sdhci_host *host = mmc_priv(mmc); 2970348487cbSHaibo Chen 2971d31911b9SHaibo Chen mrq->data->host_cookie = COOKIE_UNMAPPED; 2972348487cbSHaibo Chen 2973bd9b9027SLinus Walleij /* 2974bd9b9027SLinus Walleij * No pre-mapping in the pre hook if we're using the bounce buffer, 2975bd9b9027SLinus Walleij * for that we would need two bounce buffers since one buffer is 2976bd9b9027SLinus Walleij * in flight when this is getting called. 2977bd9b9027SLinus Walleij */ 2978bd9b9027SLinus Walleij if (host->flags & SDHCI_REQ_USE_DMA && !host->bounce_buffer) 297994538e51SRussell King sdhci_pre_dma_transfer(host, mrq->data, COOKIE_PRE_MAPPED); 2980348487cbSHaibo Chen } 2981348487cbSHaibo Chen 29825d0d11c5SAdrian Hunter static void sdhci_error_out_mrqs(struct sdhci_host *host, int err) 29835d0d11c5SAdrian Hunter { 29845d0d11c5SAdrian Hunter if (host->data_cmd) { 29855d0d11c5SAdrian Hunter host->data_cmd->error = err; 29865d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq); 29875d0d11c5SAdrian Hunter } 29885d0d11c5SAdrian Hunter 29895d0d11c5SAdrian Hunter if (host->cmd) { 29905d0d11c5SAdrian Hunter host->cmd->error = err; 29915d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 29925d0d11c5SAdrian Hunter } 29935d0d11c5SAdrian Hunter } 29945d0d11c5SAdrian Hunter 299571e69211SGuennadi Liakhovetski static void sdhci_card_event(struct mmc_host *mmc) 29961c6a0718SPierre Ossman { 299771e69211SGuennadi Liakhovetski struct sdhci_host *host = mmc_priv(mmc); 29981c6a0718SPierre Ossman unsigned long flags; 29992836766aSKrzysztof Kozlowski int present; 30001c6a0718SPierre Ossman 3001722e1280SChristian Daudt /* First check if client has provided their own card event */ 3002722e1280SChristian Daudt if (host->ops->card_event) 3003722e1280SChristian Daudt host->ops->card_event(host); 3004722e1280SChristian Daudt 3005d3940f27SAdrian Hunter present = mmc->ops->get_cd(mmc); 30062836766aSKrzysztof Kozlowski 30071c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 30081c6a0718SPierre Ossman 30095d0d11c5SAdrian Hunter /* Check sdhci_has_requests() first in case we are runtime suspended */ 30105d0d11c5SAdrian Hunter if (sdhci_has_requests(host) && !present) { 3011a3c76eb9SGirish K S pr_err("%s: Card removed during transfer!\n", 3012d2f025b0SJisheng Zhang mmc_hostname(mmc)); 3013a3c76eb9SGirish K S pr_err("%s: Resetting controller.\n", 3014d2f025b0SJisheng Zhang mmc_hostname(mmc)); 30151c6a0718SPierre Ossman 3016*1e63d297SAdrian Hunter sdhci_reset_for(host, CARD_REMOVED); 30171c6a0718SPierre Ossman 30185d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM); 30191c6a0718SPierre Ossman } 30201c6a0718SPierre Ossman 30211c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 302271e69211SGuennadi Liakhovetski } 302371e69211SGuennadi Liakhovetski 302471e69211SGuennadi Liakhovetski static const struct mmc_host_ops sdhci_ops = { 302571e69211SGuennadi Liakhovetski .request = sdhci_request, 3026348487cbSHaibo Chen .post_req = sdhci_post_req, 3027348487cbSHaibo Chen .pre_req = sdhci_pre_req, 302871e69211SGuennadi Liakhovetski .set_ios = sdhci_set_ios, 302994144a46SKevin Liu .get_cd = sdhci_get_cd, 303071e69211SGuennadi Liakhovetski .get_ro = sdhci_get_ro, 303132f18e59SWolfram Sang .card_hw_reset = sdhci_hw_reset, 303271e69211SGuennadi Liakhovetski .enable_sdio_irq = sdhci_enable_sdio_irq, 303389f3c365SAdrian Hunter .ack_sdio_irq = sdhci_ack_sdio_irq, 303471e69211SGuennadi Liakhovetski .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, 3035b5540ce1SAdrian Hunter .prepare_hs400_tuning = sdhci_prepare_hs400_tuning, 303671e69211SGuennadi Liakhovetski .execute_tuning = sdhci_execute_tuning, 303771e69211SGuennadi Liakhovetski .card_event = sdhci_card_event, 303820b92a30SKevin Liu .card_busy = sdhci_card_busy, 303971e69211SGuennadi Liakhovetski }; 304071e69211SGuennadi Liakhovetski 304171e69211SGuennadi Liakhovetski /*****************************************************************************\ 304271e69211SGuennadi Liakhovetski * * 3043c07a48c2SAdrian Hunter * Request done * 304471e69211SGuennadi Liakhovetski * * 304571e69211SGuennadi Liakhovetski \*****************************************************************************/ 304671e69211SGuennadi Liakhovetski 30474e9f8fe5SAdrian Hunter static bool sdhci_request_done(struct sdhci_host *host) 30481c6a0718SPierre Ossman { 30491c6a0718SPierre Ossman unsigned long flags; 30501c6a0718SPierre Ossman struct mmc_request *mrq; 30514e9f8fe5SAdrian Hunter int i; 30521c6a0718SPierre Ossman 305366fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 305466fd8ad5SAdrian Hunter 30554e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 30564e9f8fe5SAdrian Hunter mrq = host->mrqs_done[i]; 30576ebebeabSAdrian Hunter if (mrq) 30584e9f8fe5SAdrian Hunter break; 30594e9f8fe5SAdrian Hunter } 30601c6a0718SPierre Ossman 30614e9f8fe5SAdrian Hunter if (!mrq) { 30624e9f8fe5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 30634e9f8fe5SAdrian Hunter return true; 30644e9f8fe5SAdrian Hunter } 30651c6a0718SPierre Ossman 30661c6a0718SPierre Ossman /* 306721e35e89SPradeep P V K * The controller needs a reset of internal state machines 306821e35e89SPradeep P V K * upon error conditions. 306921e35e89SPradeep P V K */ 307021e35e89SPradeep P V K if (sdhci_needs_reset(host, mrq)) { 307121e35e89SPradeep P V K /* 307221e35e89SPradeep P V K * Do not finish until command and data lines are available for 307321e35e89SPradeep P V K * reset. Note there can only be one other mrq, so it cannot 307421e35e89SPradeep P V K * also be in mrqs_done, otherwise host->cmd and host->data_cmd 307521e35e89SPradeep P V K * would both be null. 307621e35e89SPradeep P V K */ 307721e35e89SPradeep P V K if (host->cmd || host->data_cmd) { 307821e35e89SPradeep P V K spin_unlock_irqrestore(&host->lock, flags); 307921e35e89SPradeep P V K return true; 308021e35e89SPradeep P V K } 308121e35e89SPradeep P V K 308221e35e89SPradeep P V K /* Some controllers need this kick or reset won't work here */ 308321e35e89SPradeep P V K if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) 308421e35e89SPradeep P V K /* This is to force an update */ 308521e35e89SPradeep P V K host->ops->set_clock(host, host->clock); 308621e35e89SPradeep P V K 3087*1e63d297SAdrian Hunter sdhci_reset_for(host, REQUEST_ERROR); 308821e35e89SPradeep P V K 308921e35e89SPradeep P V K host->pending_reset = false; 309021e35e89SPradeep P V K } 309121e35e89SPradeep P V K 309221e35e89SPradeep P V K /* 3093054cedffSRussell King * Always unmap the data buffers if they were mapped by 3094054cedffSRussell King * sdhci_prepare_data() whenever we finish with a request. 3095054cedffSRussell King * This avoids leaking DMA mappings on error. 3096054cedffSRussell King */ 3097054cedffSRussell King if (host->flags & SDHCI_REQ_USE_DMA) { 3098054cedffSRussell King struct mmc_data *data = mrq->data; 3099054cedffSRussell King 310018e762e3SChunyan Zhang if (host->use_external_dma && data && 310118e762e3SChunyan Zhang (mrq->cmd->error || data->error)) { 310218e762e3SChunyan Zhang struct dma_chan *chan = sdhci_external_dma_channel(host, data); 310318e762e3SChunyan Zhang 310418e762e3SChunyan Zhang host->mrqs_done[i] = NULL; 310518e762e3SChunyan Zhang spin_unlock_irqrestore(&host->lock, flags); 310618e762e3SChunyan Zhang dmaengine_terminate_sync(chan); 310718e762e3SChunyan Zhang spin_lock_irqsave(&host->lock, flags); 310818e762e3SChunyan Zhang sdhci_set_mrq_done(host, mrq); 310918e762e3SChunyan Zhang } 311018e762e3SChunyan Zhang 3111054cedffSRussell King if (data && data->host_cookie == COOKIE_MAPPED) { 3112bd9b9027SLinus Walleij if (host->bounce_buffer) { 3113bd9b9027SLinus Walleij /* 3114bd9b9027SLinus Walleij * On reads, copy the bounced data into the 3115bd9b9027SLinus Walleij * sglist 3116bd9b9027SLinus Walleij */ 3117bd9b9027SLinus Walleij if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) { 3118bd9b9027SLinus Walleij unsigned int length = data->bytes_xfered; 3119bd9b9027SLinus Walleij 3120bd9b9027SLinus Walleij if (length > host->bounce_buffer_size) { 3121bd9b9027SLinus Walleij pr_err("%s: bounce buffer is %u bytes but DMA claims to have transferred %u bytes\n", 3122bd9b9027SLinus Walleij mmc_hostname(host->mmc), 3123bd9b9027SLinus Walleij host->bounce_buffer_size, 3124bd9b9027SLinus Walleij data->bytes_xfered); 3125bd9b9027SLinus Walleij /* Cap it down and continue */ 3126bd9b9027SLinus Walleij length = host->bounce_buffer_size; 3127bd9b9027SLinus Walleij } 3128bd9b9027SLinus Walleij dma_sync_single_for_cpu( 3129bac53336SJisheng Zhang mmc_dev(host->mmc), 3130bd9b9027SLinus Walleij host->bounce_addr, 3131bd9b9027SLinus Walleij host->bounce_buffer_size, 3132bd9b9027SLinus Walleij DMA_FROM_DEVICE); 3133bd9b9027SLinus Walleij sg_copy_from_buffer(data->sg, 3134bd9b9027SLinus Walleij data->sg_len, 3135bd9b9027SLinus Walleij host->bounce_buffer, 3136bd9b9027SLinus Walleij length); 3137bd9b9027SLinus Walleij } else { 3138bd9b9027SLinus Walleij /* No copying, just switch ownership */ 3139bd9b9027SLinus Walleij dma_sync_single_for_cpu( 3140bac53336SJisheng Zhang mmc_dev(host->mmc), 3141bd9b9027SLinus Walleij host->bounce_addr, 3142bd9b9027SLinus Walleij host->bounce_buffer_size, 3143feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 3144bd9b9027SLinus Walleij } 3145bd9b9027SLinus Walleij } else { 3146bd9b9027SLinus Walleij /* Unmap the raw data */ 3147bd9b9027SLinus Walleij dma_unmap_sg(mmc_dev(host->mmc), data->sg, 3148bd9b9027SLinus Walleij data->sg_len, 3149bd9b9027SLinus Walleij mmc_get_dma_dir(data)); 3150bd9b9027SLinus Walleij } 3151054cedffSRussell King data->host_cookie = COOKIE_UNMAPPED; 3152054cedffSRussell King } 3153054cedffSRussell King } 3154054cedffSRussell King 31556ebebeabSAdrian Hunter host->mrqs_done[i] = NULL; 31566ebebeabSAdrian Hunter 31571c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 31581c6a0718SPierre Ossman 31591774b002SBaolin Wang if (host->ops->request_done) 31601774b002SBaolin Wang host->ops->request_done(host, mrq); 31611774b002SBaolin Wang else 31621c6a0718SPierre Ossman mmc_request_done(host->mmc, mrq); 31634e9f8fe5SAdrian Hunter 31644e9f8fe5SAdrian Hunter return false; 31654e9f8fe5SAdrian Hunter } 31664e9f8fe5SAdrian Hunter 3167c07a48c2SAdrian Hunter static void sdhci_complete_work(struct work_struct *work) 31684e9f8fe5SAdrian Hunter { 3169c07a48c2SAdrian Hunter struct sdhci_host *host = container_of(work, struct sdhci_host, 3170c07a48c2SAdrian Hunter complete_work); 31714e9f8fe5SAdrian Hunter 31724e9f8fe5SAdrian Hunter while (!sdhci_request_done(host)) 31734e9f8fe5SAdrian Hunter ; 31741c6a0718SPierre Ossman } 31751c6a0718SPierre Ossman 31762ee4f620SKees Cook static void sdhci_timeout_timer(struct timer_list *t) 31771c6a0718SPierre Ossman { 31781c6a0718SPierre Ossman struct sdhci_host *host; 31791c6a0718SPierre Ossman unsigned long flags; 31801c6a0718SPierre Ossman 31812ee4f620SKees Cook host = from_timer(host, t, timer); 31821c6a0718SPierre Ossman 31831c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 31841c6a0718SPierre Ossman 3185d7422fb4SAdrian Hunter if (host->cmd && !sdhci_data_line_cmd(host->cmd)) { 3186d7422fb4SAdrian Hunter pr_err("%s: Timeout waiting for hardware cmd interrupt.\n", 3187d7422fb4SAdrian Hunter mmc_hostname(host->mmc)); 3188efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, REQ_TIMEOUT); 3189d7422fb4SAdrian Hunter sdhci_dumpregs(host); 3190d7422fb4SAdrian Hunter 3191d7422fb4SAdrian Hunter host->cmd->error = -ETIMEDOUT; 3192d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 3193d7422fb4SAdrian Hunter } 3194d7422fb4SAdrian Hunter 3195d7422fb4SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3196d7422fb4SAdrian Hunter } 3197d7422fb4SAdrian Hunter 31982ee4f620SKees Cook static void sdhci_timeout_data_timer(struct timer_list *t) 3199d7422fb4SAdrian Hunter { 3200d7422fb4SAdrian Hunter struct sdhci_host *host; 3201d7422fb4SAdrian Hunter unsigned long flags; 3202d7422fb4SAdrian Hunter 32032ee4f620SKees Cook host = from_timer(host, t, data_timer); 3204d7422fb4SAdrian Hunter 3205d7422fb4SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3206d7422fb4SAdrian Hunter 3207d7422fb4SAdrian Hunter if (host->data || host->data_cmd || 3208d7422fb4SAdrian Hunter (host->cmd && sdhci_data_line_cmd(host->cmd))) { 32092e4456f0SMarek Vasut pr_err("%s: Timeout waiting for hardware interrupt.\n", 32102e4456f0SMarek Vasut mmc_hostname(host->mmc)); 3211efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, REQ_TIMEOUT); 32121c6a0718SPierre Ossman sdhci_dumpregs(host); 32131c6a0718SPierre Ossman 32141c6a0718SPierre Ossman if (host->data) { 321517b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 3216845c939eSAdrian Hunter __sdhci_finish_data(host, true); 3217c07a48c2SAdrian Hunter queue_work(host->complete_wq, &host->complete_work); 3218d7422fb4SAdrian Hunter } else if (host->data_cmd) { 3219d7422fb4SAdrian Hunter host->data_cmd->error = -ETIMEDOUT; 3220d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq); 32211c6a0718SPierre Ossman } else { 322217b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 3223d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 32241c6a0718SPierre Ossman } 32251c6a0718SPierre Ossman } 32261c6a0718SPierre Ossman 32271c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 32281c6a0718SPierre Ossman } 32291c6a0718SPierre Ossman 32301c6a0718SPierre Ossman /*****************************************************************************\ 32311c6a0718SPierre Ossman * * 32321c6a0718SPierre Ossman * Interrupt handling * 32331c6a0718SPierre Ossman * * 32341c6a0718SPierre Ossman \*****************************************************************************/ 32351c6a0718SPierre Ossman 32364bf78099SAdrian Hunter static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) 32371c6a0718SPierre Ossman { 3238af849c86SAdrian Hunter /* Handle auto-CMD12 error */ 3239af849c86SAdrian Hunter if (intmask & SDHCI_INT_AUTO_CMD_ERR && host->data_cmd) { 3240af849c86SAdrian Hunter struct mmc_request *mrq = host->data_cmd->mrq; 3241af849c86SAdrian Hunter u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); 3242af849c86SAdrian Hunter int data_err_bit = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? 3243af849c86SAdrian Hunter SDHCI_INT_DATA_TIMEOUT : 3244af849c86SAdrian Hunter SDHCI_INT_DATA_CRC; 3245af849c86SAdrian Hunter 3246af849c86SAdrian Hunter /* Treat auto-CMD12 error the same as data error */ 3247af849c86SAdrian Hunter if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) { 3248af849c86SAdrian Hunter *intmask_p |= data_err_bit; 3249af849c86SAdrian Hunter return; 3250af849c86SAdrian Hunter } 3251af849c86SAdrian Hunter } 3252af849c86SAdrian Hunter 32531c6a0718SPierre Ossman if (!host->cmd) { 3254ed1563deSAdrian Hunter /* 3255ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data 3256ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more 3257ed1563deSAdrian Hunter * interrupts, so ignore them in that case. 3258ed1563deSAdrian Hunter */ 3259ed1563deSAdrian Hunter if (host->pending_reset) 3260ed1563deSAdrian Hunter return; 32612e4456f0SMarek Vasut pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", 3262b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 3263efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ); 32641c6a0718SPierre Ossman sdhci_dumpregs(host); 32651c6a0718SPierre Ossman return; 32661c6a0718SPierre Ossman } 32671c6a0718SPierre Ossman 3268ec014cbaSRussell King if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | 3269ec014cbaSRussell King SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { 3270efe8f5c9SShaik Sajida Bhanu if (intmask & SDHCI_INT_TIMEOUT) { 327117b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 3272efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_TIMEOUT); 3273efe8f5c9SShaik Sajida Bhanu } else { 327417b0429dSPierre Ossman host->cmd->error = -EILSEQ; 3275efe8f5c9SShaik Sajida Bhanu if (!mmc_op_tuning(host->cmd->opcode)) 3276efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_CRC); 3277efe8f5c9SShaik Sajida Bhanu } 32784bf78099SAdrian Hunter /* Treat data command CRC error the same as data CRC error */ 327971fcbda0SRussell King if (host->cmd->data && 328071fcbda0SRussell King (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == 328171fcbda0SRussell King SDHCI_INT_CRC) { 328271fcbda0SRussell King host->cmd = NULL; 32834bf78099SAdrian Hunter *intmask_p |= SDHCI_INT_DATA_CRC; 328471fcbda0SRussell King return; 328571fcbda0SRussell King } 328671fcbda0SRussell King 328719d2f695SAdrian Hunter __sdhci_finish_mrq(host, host->cmd->mrq); 3288e809517fSPierre Ossman return; 3289e809517fSPierre Ossman } 3290e809517fSPierre Ossman 3291af849c86SAdrian Hunter /* Handle auto-CMD23 error */ 3292af849c86SAdrian Hunter if (intmask & SDHCI_INT_AUTO_CMD_ERR) { 3293af849c86SAdrian Hunter struct mmc_request *mrq = host->cmd->mrq; 3294af849c86SAdrian Hunter u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); 3295af849c86SAdrian Hunter int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? 3296af849c86SAdrian Hunter -ETIMEDOUT : 3297af849c86SAdrian Hunter -EILSEQ; 3298af849c86SAdrian Hunter 3299efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, AUTO_CMD); 3300efe8f5c9SShaik Sajida Bhanu 330138929d4fSChanWoo Lee if (sdhci_auto_cmd23(host, mrq)) { 3302af849c86SAdrian Hunter mrq->sbc->error = err; 330319d2f695SAdrian Hunter __sdhci_finish_mrq(host, mrq); 3304af849c86SAdrian Hunter return; 3305af849c86SAdrian Hunter } 3306af849c86SAdrian Hunter } 3307af849c86SAdrian Hunter 3308e809517fSPierre Ossman if (intmask & SDHCI_INT_RESPONSE) 330943b58b36SPierre Ossman sdhci_finish_command(host); 33101c6a0718SPierre Ossman } 33111c6a0718SPierre Ossman 331208621b18SAdrian Hunter static void sdhci_adma_show_error(struct sdhci_host *host) 33136882a8c0SBen Dooks { 33141c3d5f6dSAdrian Hunter void *desc = host->adma_table; 3315d1c536e3SRussell King dma_addr_t dma = host->adma_addr; 33166882a8c0SBen Dooks 33176882a8c0SBen Dooks sdhci_dumpregs(host); 33186882a8c0SBen Dooks 33196882a8c0SBen Dooks while (true) { 3320e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 33216882a8c0SBen Dooks 3322e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 3323d1c536e3SRussell King SDHCI_DUMP("%08llx: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", 3324d1c536e3SRussell King (unsigned long long)dma, 3325d1c536e3SRussell King le32_to_cpu(dma_desc->addr_hi), 3326e57a5f61SAdrian Hunter le32_to_cpu(dma_desc->addr_lo), 3327e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->len), 3328e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->cmd)); 3329e57a5f61SAdrian Hunter else 3330d1c536e3SRussell King SDHCI_DUMP("%08llx: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", 3331d1c536e3SRussell King (unsigned long long)dma, 3332d1c536e3SRussell King le32_to_cpu(dma_desc->addr_lo), 33330545230fSAdrian Hunter le16_to_cpu(dma_desc->len), 33340545230fSAdrian Hunter le16_to_cpu(dma_desc->cmd)); 33356882a8c0SBen Dooks 333676fe379aSAdrian Hunter desc += host->desc_sz; 3337d1c536e3SRussell King dma += host->desc_sz; 33386882a8c0SBen Dooks 33390545230fSAdrian Hunter if (dma_desc->cmd & cpu_to_le16(ADMA2_END)) 33406882a8c0SBen Dooks break; 33416882a8c0SBen Dooks } 33426882a8c0SBen Dooks } 33436882a8c0SBen Dooks 33441c6a0718SPierre Ossman static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 33451c6a0718SPierre Ossman { 3346069c9f14SGirish K S u32 command; 33471c6a0718SPierre Ossman 3348f4ff24f8SHaibo Chen /* 3349f4ff24f8SHaibo Chen * CMD19 generates _only_ Buffer Read Ready interrupt if 3350f4ff24f8SHaibo Chen * use sdhci_send_tuning. 3351f4ff24f8SHaibo Chen * Need to exclude this case: PIO mode and use mmc_send_tuning, 3352f4ff24f8SHaibo Chen * If not, sdhci_transfer_pio will never be called, make the 3353f4ff24f8SHaibo Chen * SDHCI_INT_DATA_AVAIL always there, stuck in irq storm. 3354f4ff24f8SHaibo Chen */ 3355f4ff24f8SHaibo Chen if (intmask & SDHCI_INT_DATA_AVAIL && !host->data) { 3356069c9f14SGirish K S command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)); 3357069c9f14SGirish K S if (command == MMC_SEND_TUNING_BLOCK || 3358069c9f14SGirish K S command == MMC_SEND_TUNING_BLOCK_HS200) { 3359b513ea25SArindam Nath host->tuning_done = 1; 3360b513ea25SArindam Nath wake_up(&host->buf_ready_int); 3361b513ea25SArindam Nath return; 3362b513ea25SArindam Nath } 3363b513ea25SArindam Nath } 3364b513ea25SArindam Nath 33651c6a0718SPierre Ossman if (!host->data) { 33667c89a3d9SAdrian Hunter struct mmc_command *data_cmd = host->data_cmd; 33677c89a3d9SAdrian Hunter 33681c6a0718SPierre Ossman /* 3369e809517fSPierre Ossman * The "data complete" interrupt is also used to 3370e809517fSPierre Ossman * indicate that a busy state has ended. See comment 3371e809517fSPierre Ossman * above in sdhci_cmd_irq(). 33721c6a0718SPierre Ossman */ 33737c89a3d9SAdrian Hunter if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) { 3374c5abd5e8SMatthieu CASTET if (intmask & SDHCI_INT_DATA_TIMEOUT) { 337569b962a6SAdrian Hunter host->data_cmd = NULL; 33767c89a3d9SAdrian Hunter data_cmd->error = -ETIMEDOUT; 3377efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_TIMEOUT); 337819d2f695SAdrian Hunter __sdhci_finish_mrq(host, data_cmd->mrq); 3379c5abd5e8SMatthieu CASTET return; 3380c5abd5e8SMatthieu CASTET } 3381e809517fSPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 338269b962a6SAdrian Hunter host->data_cmd = NULL; 3383e99783a4SChanho Min /* 3384e99783a4SChanho Min * Some cards handle busy-end interrupt 3385e99783a4SChanho Min * before the command completed, so make 3386e99783a4SChanho Min * sure we do things in the proper order. 3387e99783a4SChanho Min */ 3388ea968023SAdrian Hunter if (host->cmd == data_cmd) 3389ea968023SAdrian Hunter return; 3390ea968023SAdrian Hunter 339119d2f695SAdrian Hunter __sdhci_finish_mrq(host, data_cmd->mrq); 33921c6a0718SPierre Ossman return; 3393e809517fSPierre Ossman } 3394e809517fSPierre Ossman } 33951c6a0718SPierre Ossman 3396ed1563deSAdrian Hunter /* 3397ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data 3398ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more 3399ed1563deSAdrian Hunter * interrupts, so ignore them in that case. 3400ed1563deSAdrian Hunter */ 3401ed1563deSAdrian Hunter if (host->pending_reset) 3402ed1563deSAdrian Hunter return; 3403ed1563deSAdrian Hunter 34042e4456f0SMarek Vasut pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n", 3405b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 3406efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ); 34071c6a0718SPierre Ossman sdhci_dumpregs(host); 34081c6a0718SPierre Ossman 34091c6a0718SPierre Ossman return; 34101c6a0718SPierre Ossman } 34111c6a0718SPierre Ossman 3412efe8f5c9SShaik Sajida Bhanu if (intmask & SDHCI_INT_DATA_TIMEOUT) { 341317b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 3414efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_TIMEOUT); 3415efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_DATA_END_BIT) { 341622113efdSAries Lee host->data->error = -EILSEQ; 3417efe8f5c9SShaik Sajida Bhanu if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) 3418efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_CRC); 3419efe8f5c9SShaik Sajida Bhanu } else if ((intmask & SDHCI_INT_DATA_CRC) && 342022113efdSAries Lee SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) 3421efe8f5c9SShaik Sajida Bhanu != MMC_BUS_TEST_R) { 342217b0429dSPierre Ossman host->data->error = -EILSEQ; 3423efe8f5c9SShaik Sajida Bhanu if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) 3424efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_CRC); 3425efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_ADMA_ERROR) { 3426d1c536e3SRussell King pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), 3427d1c536e3SRussell King intmask); 342808621b18SAdrian Hunter sdhci_adma_show_error(host); 3429efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, ADMA); 34302134a922SPierre Ossman host->data->error = -EIO; 3431a4071fbbSHaijun Zhang if (host->ops->adma_workaround) 3432a4071fbbSHaijun Zhang host->ops->adma_workaround(host, intmask); 34336882a8c0SBen Dooks } 34341c6a0718SPierre Ossman 343517b0429dSPierre Ossman if (host->data->error) 34361c6a0718SPierre Ossman sdhci_finish_data(host); 34371c6a0718SPierre Ossman else { 34381c6a0718SPierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 34391c6a0718SPierre Ossman sdhci_transfer_pio(host); 34401c6a0718SPierre Ossman 34416ba736a1SPierre Ossman /* 34426ba736a1SPierre Ossman * We currently don't do anything fancy with DMA 34436ba736a1SPierre Ossman * boundaries, but as we can't disable the feature 34446ba736a1SPierre Ossman * we need to at least restart the transfer. 3445f6a03cbfSMikko Vinni * 3446f6a03cbfSMikko Vinni * According to the spec sdhci_readl(host, SDHCI_DMA_ADDRESS) 3447f6a03cbfSMikko Vinni * should return a valid address to continue from, but as 3448f6a03cbfSMikko Vinni * some controllers are faulty, don't trust them. 34496ba736a1SPierre Ossman */ 3450f6a03cbfSMikko Vinni if (intmask & SDHCI_INT_DMA_END) { 3451917a0c52SChunyan Zhang dma_addr_t dmastart, dmanow; 3452bd9b9027SLinus Walleij 3453bd9b9027SLinus Walleij dmastart = sdhci_sdma_address(host); 3454f6a03cbfSMikko Vinni dmanow = dmastart + host->data->bytes_xfered; 3455f6a03cbfSMikko Vinni /* 3456f6a03cbfSMikko Vinni * Force update to the next DMA block boundary. 3457f6a03cbfSMikko Vinni */ 3458f6a03cbfSMikko Vinni dmanow = (dmanow & 3459917a0c52SChunyan Zhang ~((dma_addr_t)SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 3460f6a03cbfSMikko Vinni SDHCI_DEFAULT_BOUNDARY_SIZE; 3461f6a03cbfSMikko Vinni host->data->bytes_xfered = dmanow - dmastart; 3462917a0c52SChunyan Zhang DBG("DMA base %pad, transferred 0x%06x bytes, next %pad\n", 3463917a0c52SChunyan Zhang &dmastart, host->data->bytes_xfered, &dmanow); 3464917a0c52SChunyan Zhang sdhci_set_sdma_addr(host, dmanow); 3465f6a03cbfSMikko Vinni } 34666ba736a1SPierre Ossman 3467e538fbe8SPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 34687c89a3d9SAdrian Hunter if (host->cmd == host->data_cmd) { 3469e538fbe8SPierre Ossman /* 3470e538fbe8SPierre Ossman * Data managed to finish before the 3471e538fbe8SPierre Ossman * command completed. Make sure we do 3472e538fbe8SPierre Ossman * things in the proper order. 3473e538fbe8SPierre Ossman */ 3474e538fbe8SPierre Ossman host->data_early = 1; 3475e538fbe8SPierre Ossman } else { 34761c6a0718SPierre Ossman sdhci_finish_data(host); 34771c6a0718SPierre Ossman } 34781c6a0718SPierre Ossman } 3479e538fbe8SPierre Ossman } 3480e538fbe8SPierre Ossman } 34811c6a0718SPierre Ossman 348219d2f695SAdrian Hunter static inline bool sdhci_defer_done(struct sdhci_host *host, 348319d2f695SAdrian Hunter struct mmc_request *mrq) 348419d2f695SAdrian Hunter { 348519d2f695SAdrian Hunter struct mmc_data *data = mrq->data; 348619d2f695SAdrian Hunter 34874730831cSBaolin Wang return host->pending_reset || host->always_defer_done || 348819d2f695SAdrian Hunter ((host->flags & SDHCI_REQ_USE_DMA) && data && 348919d2f695SAdrian Hunter data->host_cookie == COOKIE_MAPPED); 349019d2f695SAdrian Hunter } 349119d2f695SAdrian Hunter 34921c6a0718SPierre Ossman static irqreturn_t sdhci_irq(int irq, void *dev_id) 34931c6a0718SPierre Ossman { 349419d2f695SAdrian Hunter struct mmc_request *mrqs_done[SDHCI_MAX_MRQS] = {0}; 3495781e989cSRussell King irqreturn_t result = IRQ_NONE; 34961c6a0718SPierre Ossman struct sdhci_host *host = dev_id; 349741005003SRussell King u32 intmask, mask, unexpected = 0; 3498781e989cSRussell King int max_loops = 16; 349919d2f695SAdrian Hunter int i; 35001c6a0718SPierre Ossman 35011c6a0718SPierre Ossman spin_lock(&host->lock); 35021c6a0718SPierre Ossman 3503af5d2b7bSUlf Hansson if (host->runtime_suspended) { 350466fd8ad5SAdrian Hunter spin_unlock(&host->lock); 3505655bca76SAdrian Hunter return IRQ_NONE; 350666fd8ad5SAdrian Hunter } 350766fd8ad5SAdrian Hunter 35084e4141a5SAnton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS); 35091c6a0718SPierre Ossman if (!intmask || intmask == 0xffffffff) { 35101c6a0718SPierre Ossman result = IRQ_NONE; 35111c6a0718SPierre Ossman goto out; 35121c6a0718SPierre Ossman } 35131c6a0718SPierre Ossman 351441005003SRussell King do { 3515f12e39dbSAdrian Hunter DBG("IRQ status 0x%08x\n", intmask); 3516f12e39dbSAdrian Hunter 3517f12e39dbSAdrian Hunter if (host->ops->irq) { 3518f12e39dbSAdrian Hunter intmask = host->ops->irq(host, intmask); 3519f12e39dbSAdrian Hunter if (!intmask) 3520f12e39dbSAdrian Hunter goto cont; 3521f12e39dbSAdrian Hunter } 3522f12e39dbSAdrian Hunter 352341005003SRussell King /* Clear selected interrupts. */ 352441005003SRussell King mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 352541005003SRussell King SDHCI_INT_BUS_POWER); 352641005003SRussell King sdhci_writel(host, mask, SDHCI_INT_STATUS); 352741005003SRussell King 35281c6a0718SPierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 3529d25928d1SShawn Guo u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 3530d25928d1SShawn Guo SDHCI_CARD_PRESENT; 3531d25928d1SShawn Guo 3532d25928d1SShawn Guo /* 353341005003SRussell King * There is a observation on i.mx esdhc. INSERT 353441005003SRussell King * bit will be immediately set again when it gets 353541005003SRussell King * cleared, if a card is inserted. We have to mask 353641005003SRussell King * the irq to prevent interrupt storm which will 353741005003SRussell King * freeze the system. And the REMOVE gets the 353841005003SRussell King * same situation. 3539d25928d1SShawn Guo * 354041005003SRussell King * More testing are needed here to ensure it works 354141005003SRussell King * for other platforms though. 3542d25928d1SShawn Guo */ 3543b537f94cSRussell King host->ier &= ~(SDHCI_INT_CARD_INSERT | 3544d25928d1SShawn Guo SDHCI_INT_CARD_REMOVE); 3545b537f94cSRussell King host->ier |= present ? SDHCI_INT_CARD_REMOVE : 3546b537f94cSRussell King SDHCI_INT_CARD_INSERT; 3547b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3548b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 3549d25928d1SShawn Guo 35504e4141a5SAnton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | 35514e4141a5SAnton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); 35523560db8eSRussell King 35533560db8eSRussell King host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT | 35543560db8eSRussell King SDHCI_INT_CARD_REMOVE); 35553560db8eSRussell King result = IRQ_WAKE_THREAD; 35561c6a0718SPierre Ossman } 35571c6a0718SPierre Ossman 355841005003SRussell King if (intmask & SDHCI_INT_CMD_MASK) 35594bf78099SAdrian Hunter sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask); 35601c6a0718SPierre Ossman 356141005003SRussell King if (intmask & SDHCI_INT_DATA_MASK) 35621c6a0718SPierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 35631c6a0718SPierre Ossman 356441005003SRussell King if (intmask & SDHCI_INT_BUS_POWER) 3565a3c76eb9SGirish K S pr_err("%s: Card is consuming too much power!\n", 35661c6a0718SPierre Ossman mmc_hostname(host->mmc)); 35671c6a0718SPierre Ossman 3568f37b20ebSDong Aisheng if (intmask & SDHCI_INT_RETUNE) 3569f37b20ebSDong Aisheng mmc_retune_needed(host->mmc); 3570f37b20ebSDong Aisheng 3571161e6d44SGabriel Krisman Bertazi if ((intmask & SDHCI_INT_CARD_INT) && 3572161e6d44SGabriel Krisman Bertazi (host->ier & SDHCI_INT_CARD_INT)) { 3573781e989cSRussell King sdhci_enable_sdio_irq_nolock(host, false); 357489f3c365SAdrian Hunter sdio_signal_irq(host->mmc); 3575781e989cSRussell King } 3576f75979b7SPierre Ossman 357741005003SRussell King intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | 357841005003SRussell King SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 357941005003SRussell King SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | 3580f37b20ebSDong Aisheng SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT); 3581f75979b7SPierre Ossman 35821c6a0718SPierre Ossman if (intmask) { 35836379b237SAlexander Stein unexpected |= intmask; 35844e4141a5SAnton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS); 35851c6a0718SPierre Ossman } 3586f12e39dbSAdrian Hunter cont: 3587781e989cSRussell King if (result == IRQ_NONE) 35881c6a0718SPierre Ossman result = IRQ_HANDLED; 35891c6a0718SPierre Ossman 35906379b237SAlexander Stein intmask = sdhci_readl(host, SDHCI_INT_STATUS); 359141005003SRussell King } while (intmask && --max_loops); 359219d2f695SAdrian Hunter 359319d2f695SAdrian Hunter /* Determine if mrqs can be completed immediately */ 359419d2f695SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 359519d2f695SAdrian Hunter struct mmc_request *mrq = host->mrqs_done[i]; 359619d2f695SAdrian Hunter 359719d2f695SAdrian Hunter if (!mrq) 359819d2f695SAdrian Hunter continue; 359919d2f695SAdrian Hunter 360019d2f695SAdrian Hunter if (sdhci_defer_done(host, mrq)) { 3601c07a48c2SAdrian Hunter result = IRQ_WAKE_THREAD; 360219d2f695SAdrian Hunter } else { 360319d2f695SAdrian Hunter mrqs_done[i] = mrq; 360419d2f695SAdrian Hunter host->mrqs_done[i] = NULL; 360519d2f695SAdrian Hunter } 360619d2f695SAdrian Hunter } 36071c6a0718SPierre Ossman out: 3608845c939eSAdrian Hunter if (host->deferred_cmd) 3609845c939eSAdrian Hunter result = IRQ_WAKE_THREAD; 3610845c939eSAdrian Hunter 36111c6a0718SPierre Ossman spin_unlock(&host->lock); 36121c6a0718SPierre Ossman 361319d2f695SAdrian Hunter /* Process mrqs ready for immediate completion */ 361419d2f695SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 36151774b002SBaolin Wang if (!mrqs_done[i]) 36161774b002SBaolin Wang continue; 36171774b002SBaolin Wang 36181774b002SBaolin Wang if (host->ops->request_done) 36191774b002SBaolin Wang host->ops->request_done(host, mrqs_done[i]); 36201774b002SBaolin Wang else 362119d2f695SAdrian Hunter mmc_request_done(host->mmc, mrqs_done[i]); 362219d2f695SAdrian Hunter } 362319d2f695SAdrian Hunter 36246379b237SAlexander Stein if (unexpected) { 36256379b237SAlexander Stein pr_err("%s: Unexpected interrupt 0x%08x.\n", 36266379b237SAlexander Stein mmc_hostname(host->mmc), unexpected); 3627efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ); 36286379b237SAlexander Stein sdhci_dumpregs(host); 36296379b237SAlexander Stein } 3630f75979b7SPierre Ossman 36311c6a0718SPierre Ossman return result; 36321c6a0718SPierre Ossman } 36331c6a0718SPierre Ossman 3634781e989cSRussell King static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) 3635781e989cSRussell King { 3636781e989cSRussell King struct sdhci_host *host = dev_id; 3637845c939eSAdrian Hunter struct mmc_command *cmd; 3638781e989cSRussell King unsigned long flags; 3639781e989cSRussell King u32 isr; 3640781e989cSRussell King 3641c07a48c2SAdrian Hunter while (!sdhci_request_done(host)) 3642c07a48c2SAdrian Hunter ; 3643c07a48c2SAdrian Hunter 3644781e989cSRussell King spin_lock_irqsave(&host->lock, flags); 3645845c939eSAdrian Hunter 3646781e989cSRussell King isr = host->thread_isr; 3647781e989cSRussell King host->thread_isr = 0; 3648845c939eSAdrian Hunter 3649845c939eSAdrian Hunter cmd = host->deferred_cmd; 3650845c939eSAdrian Hunter if (cmd && !sdhci_send_command_retry(host, cmd, flags)) 3651845c939eSAdrian Hunter sdhci_finish_mrq(host, cmd->mrq); 3652845c939eSAdrian Hunter 3653781e989cSRussell King spin_unlock_irqrestore(&host->lock, flags); 3654781e989cSRussell King 36553560db8eSRussell King if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 3656d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 3657d3940f27SAdrian Hunter 3658d3940f27SAdrian Hunter mmc->ops->card_event(mmc); 3659d3940f27SAdrian Hunter mmc_detect_change(mmc, msecs_to_jiffies(200)); 36603560db8eSRussell King } 36613560db8eSRussell King 3662c07a48c2SAdrian Hunter return IRQ_HANDLED; 3663781e989cSRussell King } 3664781e989cSRussell King 36651c6a0718SPierre Ossman /*****************************************************************************\ 36661c6a0718SPierre Ossman * * 36671c6a0718SPierre Ossman * Suspend/resume * 36681c6a0718SPierre Ossman * * 36691c6a0718SPierre Ossman \*****************************************************************************/ 36701c6a0718SPierre Ossman 36711c6a0718SPierre Ossman #ifdef CONFIG_PM 36729c316b38SAdrian Hunter 36739c316b38SAdrian Hunter static bool sdhci_cd_irq_can_wakeup(struct sdhci_host *host) 36749c316b38SAdrian Hunter { 36759c316b38SAdrian Hunter return mmc_card_is_removable(host->mmc) && 36769c316b38SAdrian Hunter !(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 36779c316b38SAdrian Hunter !mmc_can_gpio_cd(host->mmc); 36789c316b38SAdrian Hunter } 36799c316b38SAdrian Hunter 368084d62605SLudovic Desroches /* 368184d62605SLudovic Desroches * To enable wakeup events, the corresponding events have to be enabled in 368284d62605SLudovic Desroches * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal 368384d62605SLudovic Desroches * Table' in the SD Host Controller Standard Specification. 368484d62605SLudovic Desroches * It is useless to restore SDHCI_INT_ENABLE state in 368584d62605SLudovic Desroches * sdhci_disable_irq_wakeups() since it will be set by 368684d62605SLudovic Desroches * sdhci_enable_card_detection() or sdhci_init(). 368784d62605SLudovic Desroches */ 368858e79b60SAdrian Hunter static bool sdhci_enable_irq_wakeups(struct sdhci_host *host) 3689ad080d79SKevin Liu { 369081b14543SAdrian Hunter u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE | 369181b14543SAdrian Hunter SDHCI_WAKE_ON_INT; 369281b14543SAdrian Hunter u32 irq_val = 0; 369381b14543SAdrian Hunter u8 wake_val = 0; 3694ad080d79SKevin Liu u8 val; 369581b14543SAdrian Hunter 36969c316b38SAdrian Hunter if (sdhci_cd_irq_can_wakeup(host)) { 369781b14543SAdrian Hunter wake_val |= SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE; 369881b14543SAdrian Hunter irq_val |= SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE; 369981b14543SAdrian Hunter } 370081b14543SAdrian Hunter 3701d5d568faSAdrian Hunter if (mmc_card_wake_sdio_irq(host->mmc)) { 370281b14543SAdrian Hunter wake_val |= SDHCI_WAKE_ON_INT; 370381b14543SAdrian Hunter irq_val |= SDHCI_INT_CARD_INT; 3704d5d568faSAdrian Hunter } 3705d5d568faSAdrian Hunter 3706d5d568faSAdrian Hunter if (!irq_val) 3707d5d568faSAdrian Hunter return false; 3708ad080d79SKevin Liu 3709ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 371081b14543SAdrian Hunter val &= ~mask; 371181b14543SAdrian Hunter val |= wake_val; 3712ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 371381b14543SAdrian Hunter 371484d62605SLudovic Desroches sdhci_writel(host, irq_val, SDHCI_INT_ENABLE); 371558e79b60SAdrian Hunter 371658e79b60SAdrian Hunter host->irq_wake_enabled = !enable_irq_wake(host->irq); 371758e79b60SAdrian Hunter 371858e79b60SAdrian Hunter return host->irq_wake_enabled; 3719ad080d79SKevin Liu } 3720ad080d79SKevin Liu 37210b10f478SFabio Estevam static void sdhci_disable_irq_wakeups(struct sdhci_host *host) 3722ad080d79SKevin Liu { 3723ad080d79SKevin Liu u8 val; 3724ad080d79SKevin Liu u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE 3725ad080d79SKevin Liu | SDHCI_WAKE_ON_INT; 3726ad080d79SKevin Liu 3727ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 3728ad080d79SKevin Liu val &= ~mask; 3729ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 373058e79b60SAdrian Hunter 373158e79b60SAdrian Hunter disable_irq_wake(host->irq); 373258e79b60SAdrian Hunter 373358e79b60SAdrian Hunter host->irq_wake_enabled = false; 3734ad080d79SKevin Liu } 37351c6a0718SPierre Ossman 373629495aa0SManuel Lauss int sdhci_suspend_host(struct sdhci_host *host) 37371c6a0718SPierre Ossman { 37387260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 37397260cf5eSAnton Vorontsov 374066c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc); 3741cf2b5eeaSArindam Nath 374258e79b60SAdrian Hunter if (!device_may_wakeup(mmc_dev(host->mmc)) || 374358e79b60SAdrian Hunter !sdhci_enable_irq_wakeups(host)) { 3744b537f94cSRussell King host->ier = 0; 3745b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 3746b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 3747b8c86fc5SPierre Ossman free_irq(host->irq, host); 3748ad080d79SKevin Liu } 374958e79b60SAdrian Hunter 37504ee14ec6SUlf Hansson return 0; 3751b8c86fc5SPierre Ossman } 3752b8c86fc5SPierre Ossman 3753b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_suspend_host); 3754b8c86fc5SPierre Ossman 3755b8c86fc5SPierre Ossman int sdhci_resume_host(struct sdhci_host *host) 3756b8c86fc5SPierre Ossman { 3757d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 37584ee14ec6SUlf Hansson int ret = 0; 3759b8c86fc5SPierre Ossman 3760a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 3761b8c86fc5SPierre Ossman if (host->ops->enable_dma) 3762b8c86fc5SPierre Ossman host->ops->enable_dma(host); 3763b8c86fc5SPierre Ossman } 3764b8c86fc5SPierre Ossman 3765d2f025b0SJisheng Zhang if ((mmc->pm_flags & MMC_PM_KEEP_POWER) && 37666308d290SAdrian Hunter (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) { 37676308d290SAdrian Hunter /* Card keeps power but host controller does not */ 37686308d290SAdrian Hunter sdhci_init(host, 0); 37696308d290SAdrian Hunter host->pwr = 0; 37706308d290SAdrian Hunter host->clock = 0; 3771d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 37726308d290SAdrian Hunter } else { 3773d2f025b0SJisheng Zhang sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER)); 37746308d290SAdrian Hunter } 3775b8c86fc5SPierre Ossman 377658e79b60SAdrian Hunter if (host->irq_wake_enabled) { 377758e79b60SAdrian Hunter sdhci_disable_irq_wakeups(host); 377858e79b60SAdrian Hunter } else { 377914a7b416SHaibo Chen ret = request_threaded_irq(host->irq, sdhci_irq, 378014a7b416SHaibo Chen sdhci_thread_irq, IRQF_SHARED, 3781d2f025b0SJisheng Zhang mmc_hostname(mmc), host); 378214a7b416SHaibo Chen if (ret) 378314a7b416SHaibo Chen return ret; 378414a7b416SHaibo Chen } 378514a7b416SHaibo Chen 37867260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 37877260cf5eSAnton Vorontsov 37882f4cbb3dSNicolas Pitre return ret; 37891c6a0718SPierre Ossman } 37901c6a0718SPierre Ossman 3791b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_resume_host); 379266fd8ad5SAdrian Hunter 379366fd8ad5SAdrian Hunter int sdhci_runtime_suspend_host(struct sdhci_host *host) 379466fd8ad5SAdrian Hunter { 379566fd8ad5SAdrian Hunter unsigned long flags; 379666fd8ad5SAdrian Hunter 379766c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc); 379866fd8ad5SAdrian Hunter 379966fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3800b537f94cSRussell King host->ier &= SDHCI_INT_CARD_INT; 3801b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3802b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 380366fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 380466fd8ad5SAdrian Hunter 3805781e989cSRussell King synchronize_hardirq(host->irq); 380666fd8ad5SAdrian Hunter 380766fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 380866fd8ad5SAdrian Hunter host->runtime_suspended = true; 380966fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 381066fd8ad5SAdrian Hunter 38118a125badSMarkus Pargmann return 0; 381266fd8ad5SAdrian Hunter } 381366fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host); 381466fd8ad5SAdrian Hunter 3815c6303c5dSBaolin Wang int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset) 381666fd8ad5SAdrian Hunter { 3817d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 381866fd8ad5SAdrian Hunter unsigned long flags; 38198a125badSMarkus Pargmann int host_flags = host->flags; 382066fd8ad5SAdrian Hunter 382166fd8ad5SAdrian Hunter if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 382266fd8ad5SAdrian Hunter if (host->ops->enable_dma) 382366fd8ad5SAdrian Hunter host->ops->enable_dma(host); 382466fd8ad5SAdrian Hunter } 382566fd8ad5SAdrian Hunter 3826c6303c5dSBaolin Wang sdhci_init(host, soft_reset); 382766fd8ad5SAdrian Hunter 382870bc85adSZhoujie Wu if (mmc->ios.power_mode != MMC_POWER_UNDEFINED && 382970bc85adSZhoujie Wu mmc->ios.power_mode != MMC_POWER_OFF) { 383066fd8ad5SAdrian Hunter /* Force clock and power re-program */ 383166fd8ad5SAdrian Hunter host->pwr = 0; 383266fd8ad5SAdrian Hunter host->clock = 0; 3833d3940f27SAdrian Hunter mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios); 3834d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 383566fd8ad5SAdrian Hunter 383652983382SKevin Liu if ((host_flags & SDHCI_PV_ENABLED) && 383752983382SKevin Liu !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { 383852983382SKevin Liu spin_lock_irqsave(&host->lock, flags); 383952983382SKevin Liu sdhci_enable_preset_value(host, true); 384052983382SKevin Liu spin_unlock_irqrestore(&host->lock, flags); 384152983382SKevin Liu } 384266fd8ad5SAdrian Hunter 3843086b0ddbSAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HS400_ES) && 3844086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe) 3845086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios); 384684ec048bSAdrian Hunter } 3847086b0ddbSAdrian Hunter 384866fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 384966fd8ad5SAdrian Hunter 385066fd8ad5SAdrian Hunter host->runtime_suspended = false; 385166fd8ad5SAdrian Hunter 385266fd8ad5SAdrian Hunter /* Enable SDIO IRQ */ 38530e62614bSUlf Hansson if (sdio_irq_claimed(mmc)) 385466fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true); 385566fd8ad5SAdrian Hunter 385666fd8ad5SAdrian Hunter /* Enable Card Detection */ 385766fd8ad5SAdrian Hunter sdhci_enable_card_detection(host); 385866fd8ad5SAdrian Hunter 385966fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 386066fd8ad5SAdrian Hunter 38618a125badSMarkus Pargmann return 0; 386266fd8ad5SAdrian Hunter } 386366fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host); 386466fd8ad5SAdrian Hunter 3865162d6f98SRafael J. Wysocki #endif /* CONFIG_PM */ 386666fd8ad5SAdrian Hunter 38671c6a0718SPierre Ossman /*****************************************************************************\ 38681c6a0718SPierre Ossman * * 3869f12e39dbSAdrian Hunter * Command Queue Engine (CQE) helpers * 3870f12e39dbSAdrian Hunter * * 3871f12e39dbSAdrian Hunter \*****************************************************************************/ 3872f12e39dbSAdrian Hunter 3873f12e39dbSAdrian Hunter void sdhci_cqe_enable(struct mmc_host *mmc) 3874f12e39dbSAdrian Hunter { 3875f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 3876f12e39dbSAdrian Hunter unsigned long flags; 3877f12e39dbSAdrian Hunter u8 ctrl; 3878f12e39dbSAdrian Hunter 3879f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3880f12e39dbSAdrian Hunter 3881f12e39dbSAdrian Hunter ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 3882f12e39dbSAdrian Hunter ctrl &= ~SDHCI_CTRL_DMA_MASK; 38834c4faff6SSowjanya Komatineni /* 38844c4faff6SSowjanya Komatineni * Host from V4.10 supports ADMA3 DMA type. 38854c4faff6SSowjanya Komatineni * ADMA3 performs integrated descriptor which is more suitable 38864c4faff6SSowjanya Komatineni * for cmd queuing to fetch both command and transfer descriptors. 38874c4faff6SSowjanya Komatineni */ 38884c4faff6SSowjanya Komatineni if (host->v4_mode && (host->caps1 & SDHCI_CAN_DO_ADMA3)) 38894c4faff6SSowjanya Komatineni ctrl |= SDHCI_CTRL_ADMA3; 38904c4faff6SSowjanya Komatineni else if (host->flags & SDHCI_USE_64_BIT_DMA) 3891f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA64; 3892f12e39dbSAdrian Hunter else 3893f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA32; 3894f12e39dbSAdrian Hunter sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 3895f12e39dbSAdrian Hunter 3896c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(host->sdma_boundary, 512), 3897f12e39dbSAdrian Hunter SDHCI_BLOCK_SIZE); 3898f12e39dbSAdrian Hunter 3899f12e39dbSAdrian Hunter /* Set maximum timeout */ 3900401059dfSBOUGH CHEN sdhci_set_timeout(host, NULL); 3901f12e39dbSAdrian Hunter 3902f12e39dbSAdrian Hunter host->ier = host->cqe_ier; 3903f12e39dbSAdrian Hunter 3904f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3905f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 3906f12e39dbSAdrian Hunter 3907f12e39dbSAdrian Hunter host->cqe_on = true; 3908f12e39dbSAdrian Hunter 3909f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE on, IRQ mask %#x, IRQ status %#x\n", 3910f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier, 3911f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS)); 3912f12e39dbSAdrian Hunter 3913f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3914f12e39dbSAdrian Hunter } 3915f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_enable); 3916f12e39dbSAdrian Hunter 3917f12e39dbSAdrian Hunter void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery) 3918f12e39dbSAdrian Hunter { 3919f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 3920f12e39dbSAdrian Hunter unsigned long flags; 3921f12e39dbSAdrian Hunter 3922f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3923f12e39dbSAdrian Hunter 3924f12e39dbSAdrian Hunter sdhci_set_default_irqs(host); 3925f12e39dbSAdrian Hunter 3926f12e39dbSAdrian Hunter host->cqe_on = false; 3927f12e39dbSAdrian Hunter 3928*1e63d297SAdrian Hunter if (recovery) 3929*1e63d297SAdrian Hunter sdhci_reset_for(host, CQE_RECOVERY); 3930f12e39dbSAdrian Hunter 3931f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE off, IRQ mask %#x, IRQ status %#x\n", 3932f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier, 3933f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS)); 3934f12e39dbSAdrian Hunter 3935f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3936f12e39dbSAdrian Hunter } 3937f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_disable); 3938f12e39dbSAdrian Hunter 3939f12e39dbSAdrian Hunter bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, 3940f12e39dbSAdrian Hunter int *data_error) 3941f12e39dbSAdrian Hunter { 3942f12e39dbSAdrian Hunter u32 mask; 3943f12e39dbSAdrian Hunter 3944f12e39dbSAdrian Hunter if (!host->cqe_on) 3945f12e39dbSAdrian Hunter return false; 3946f12e39dbSAdrian Hunter 3947efe8f5c9SShaik Sajida Bhanu if (intmask & (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC)) { 3948f12e39dbSAdrian Hunter *cmd_error = -EILSEQ; 3949faded9b5SWenchao Chen if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) 3950efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_CRC); 3951efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_TIMEOUT) { 3952f12e39dbSAdrian Hunter *cmd_error = -ETIMEDOUT; 3953efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_TIMEOUT); 3954efe8f5c9SShaik Sajida Bhanu } else 3955f12e39dbSAdrian Hunter *cmd_error = 0; 3956f12e39dbSAdrian Hunter 3957efe8f5c9SShaik Sajida Bhanu if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) { 3958f12e39dbSAdrian Hunter *data_error = -EILSEQ; 3959faded9b5SWenchao Chen if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) 3960efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_CRC); 3961efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_DATA_TIMEOUT) { 3962f12e39dbSAdrian Hunter *data_error = -ETIMEDOUT; 3963efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_TIMEOUT); 3964efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_ADMA_ERROR) { 3965f12e39dbSAdrian Hunter *data_error = -EIO; 3966efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, ADMA); 3967efe8f5c9SShaik Sajida Bhanu } else 3968f12e39dbSAdrian Hunter *data_error = 0; 3969f12e39dbSAdrian Hunter 3970f12e39dbSAdrian Hunter /* Clear selected interrupts. */ 3971f12e39dbSAdrian Hunter mask = intmask & host->cqe_ier; 3972f12e39dbSAdrian Hunter sdhci_writel(host, mask, SDHCI_INT_STATUS); 3973f12e39dbSAdrian Hunter 3974f12e39dbSAdrian Hunter if (intmask & SDHCI_INT_BUS_POWER) 3975f12e39dbSAdrian Hunter pr_err("%s: Card is consuming too much power!\n", 3976f12e39dbSAdrian Hunter mmc_hostname(host->mmc)); 3977f12e39dbSAdrian Hunter 3978f12e39dbSAdrian Hunter intmask &= ~(host->cqe_ier | SDHCI_INT_ERROR); 3979f12e39dbSAdrian Hunter if (intmask) { 3980f12e39dbSAdrian Hunter sdhci_writel(host, intmask, SDHCI_INT_STATUS); 3981f12e39dbSAdrian Hunter pr_err("%s: CQE: Unexpected interrupt 0x%08x.\n", 3982f12e39dbSAdrian Hunter mmc_hostname(host->mmc), intmask); 3983efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ); 3984f12e39dbSAdrian Hunter sdhci_dumpregs(host); 3985f12e39dbSAdrian Hunter } 3986f12e39dbSAdrian Hunter 3987f12e39dbSAdrian Hunter return true; 3988f12e39dbSAdrian Hunter } 3989f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_irq); 3990f12e39dbSAdrian Hunter 3991f12e39dbSAdrian Hunter /*****************************************************************************\ 3992f12e39dbSAdrian Hunter * * 3993b8c86fc5SPierre Ossman * Device allocation/registration * 39941c6a0718SPierre Ossman * * 39951c6a0718SPierre Ossman \*****************************************************************************/ 39961c6a0718SPierre Ossman 3997b8c86fc5SPierre Ossman struct sdhci_host *sdhci_alloc_host(struct device *dev, 3998b8c86fc5SPierre Ossman size_t priv_size) 39991c6a0718SPierre Ossman { 40001c6a0718SPierre Ossman struct mmc_host *mmc; 40011c6a0718SPierre Ossman struct sdhci_host *host; 40021c6a0718SPierre Ossman 4003b8c86fc5SPierre Ossman WARN_ON(dev == NULL); 40041c6a0718SPierre Ossman 4005b8c86fc5SPierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 40061c6a0718SPierre Ossman if (!mmc) 4007b8c86fc5SPierre Ossman return ERR_PTR(-ENOMEM); 40081c6a0718SPierre Ossman 40091c6a0718SPierre Ossman host = mmc_priv(mmc); 40101c6a0718SPierre Ossman host->mmc = mmc; 4011bf60e592SAdrian Hunter host->mmc_host_ops = sdhci_ops; 4012bf60e592SAdrian Hunter mmc->ops = &host->mmc_host_ops; 40131c6a0718SPierre Ossman 40148cb851a4SAdrian Hunter host->flags = SDHCI_SIGNALING_330; 40158cb851a4SAdrian Hunter 4016f12e39dbSAdrian Hunter host->cqe_ier = SDHCI_CQE_INT_MASK; 4017f12e39dbSAdrian Hunter host->cqe_err_ier = SDHCI_CQE_INT_ERR_MASK; 4018f12e39dbSAdrian Hunter 401983b600b8SAdrian Hunter host->tuning_delay = -1; 40201d8cd065SSowjanya Komatineni host->tuning_loop_count = MAX_TUNING_LOOP; 402183b600b8SAdrian Hunter 4022c846a00fSSrinivas Kandagatla host->sdma_boundary = SDHCI_DEFAULT_BOUNDARY_ARG; 4023c846a00fSSrinivas Kandagatla 4024e93be38aSJisheng Zhang /* 4025e93be38aSJisheng Zhang * The DMA table descriptor count is calculated as the maximum 4026e93be38aSJisheng Zhang * number of segments times 2, to allow for an alignment 4027e93be38aSJisheng Zhang * descriptor for each segment, plus 1 for a nop end descriptor. 4028e93be38aSJisheng Zhang */ 4029e93be38aSJisheng Zhang host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1; 40303d7c194bSAdrian Hunter host->max_adma = 65536; 4031e93be38aSJisheng Zhang 4032e30314f2SSarthak Garg host->max_timeout_count = 0xE; 4033e30314f2SSarthak Garg 4034b8c86fc5SPierre Ossman return host; 40351c6a0718SPierre Ossman } 40361c6a0718SPierre Ossman 4037b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_alloc_host); 4038b8c86fc5SPierre Ossman 40397b91369bSAlexandre Courbot static int sdhci_set_dma_mask(struct sdhci_host *host) 40407b91369bSAlexandre Courbot { 40417b91369bSAlexandre Courbot struct mmc_host *mmc = host->mmc; 40427b91369bSAlexandre Courbot struct device *dev = mmc_dev(mmc); 40437b91369bSAlexandre Courbot int ret = -EINVAL; 40447b91369bSAlexandre Courbot 40457b91369bSAlexandre Courbot if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) 40467b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA; 40477b91369bSAlexandre Courbot 40487b91369bSAlexandre Courbot /* Try 64-bit mask if hardware is capable of it */ 40497b91369bSAlexandre Courbot if (host->flags & SDHCI_USE_64_BIT_DMA) { 40507b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 40517b91369bSAlexandre Courbot if (ret) { 40527b91369bSAlexandre Courbot pr_warn("%s: Failed to set 64-bit DMA mask.\n", 40537b91369bSAlexandre Courbot mmc_hostname(mmc)); 40547b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA; 40557b91369bSAlexandre Courbot } 40567b91369bSAlexandre Courbot } 40577b91369bSAlexandre Courbot 40587b91369bSAlexandre Courbot /* 32-bit mask as default & fallback */ 40597b91369bSAlexandre Courbot if (ret) { 40607b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); 40617b91369bSAlexandre Courbot if (ret) 40627b91369bSAlexandre Courbot pr_warn("%s: Failed to set 32-bit DMA mask.\n", 40637b91369bSAlexandre Courbot mmc_hostname(mmc)); 40647b91369bSAlexandre Courbot } 40657b91369bSAlexandre Courbot 40667b91369bSAlexandre Courbot return ret; 40677b91369bSAlexandre Courbot } 40687b91369bSAlexandre Courbot 40698784edc8SMasahiro Yamada void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver, 40708784edc8SMasahiro Yamada const u32 *caps, const u32 *caps1) 40716132a3bfSAdrian Hunter { 40726132a3bfSAdrian Hunter u16 v; 407392e0c44bSZach Brown u64 dt_caps_mask = 0; 407492e0c44bSZach Brown u64 dt_caps = 0; 40756132a3bfSAdrian Hunter 40766132a3bfSAdrian Hunter if (host->read_caps) 40776132a3bfSAdrian Hunter return; 40786132a3bfSAdrian Hunter 40796132a3bfSAdrian Hunter host->read_caps = true; 40806132a3bfSAdrian Hunter 40816132a3bfSAdrian Hunter if (debug_quirks) 40826132a3bfSAdrian Hunter host->quirks = debug_quirks; 40836132a3bfSAdrian Hunter 40846132a3bfSAdrian Hunter if (debug_quirks2) 40856132a3bfSAdrian Hunter host->quirks2 = debug_quirks2; 40866132a3bfSAdrian Hunter 4087aa990722SAdrian Hunter sdhci_reset_for_all(host); 40886132a3bfSAdrian Hunter 4089b3f80b43SChunyan Zhang if (host->v4_mode) 4090b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host); 4091b3f80b43SChunyan Zhang 4092cb80a7e9SJeremy Linton device_property_read_u64(mmc_dev(host->mmc), 4093cb80a7e9SJeremy Linton "sdhci-caps-mask", &dt_caps_mask); 4094cb80a7e9SJeremy Linton device_property_read_u64(mmc_dev(host->mmc), 4095cb80a7e9SJeremy Linton "sdhci-caps", &dt_caps); 409692e0c44bSZach Brown 40976132a3bfSAdrian Hunter v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION); 40986132a3bfSAdrian Hunter host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; 40996132a3bfSAdrian Hunter 41006132a3bfSAdrian Hunter if (host->quirks & SDHCI_QUIRK_MISSING_CAPS) 41016132a3bfSAdrian Hunter return; 41026132a3bfSAdrian Hunter 410392e0c44bSZach Brown if (caps) { 410492e0c44bSZach Brown host->caps = *caps; 410592e0c44bSZach Brown } else { 410692e0c44bSZach Brown host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); 410792e0c44bSZach Brown host->caps &= ~lower_32_bits(dt_caps_mask); 410892e0c44bSZach Brown host->caps |= lower_32_bits(dt_caps); 410992e0c44bSZach Brown } 41106132a3bfSAdrian Hunter 41116132a3bfSAdrian Hunter if (host->version < SDHCI_SPEC_300) 41126132a3bfSAdrian Hunter return; 41136132a3bfSAdrian Hunter 411492e0c44bSZach Brown if (caps1) { 411592e0c44bSZach Brown host->caps1 = *caps1; 411692e0c44bSZach Brown } else { 411792e0c44bSZach Brown host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); 411892e0c44bSZach Brown host->caps1 &= ~upper_32_bits(dt_caps_mask); 411992e0c44bSZach Brown host->caps1 |= upper_32_bits(dt_caps); 412092e0c44bSZach Brown } 41216132a3bfSAdrian Hunter } 41226132a3bfSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_read_caps); 41236132a3bfSAdrian Hunter 4124a68dd9a0SChunyan Zhang static void sdhci_allocate_bounce_buffer(struct sdhci_host *host) 4125bd9b9027SLinus Walleij { 4126bd9b9027SLinus Walleij struct mmc_host *mmc = host->mmc; 4127bd9b9027SLinus Walleij unsigned int max_blocks; 4128bd9b9027SLinus Walleij unsigned int bounce_size; 4129bd9b9027SLinus Walleij int ret; 4130bd9b9027SLinus Walleij 4131bd9b9027SLinus Walleij /* 4132bd9b9027SLinus Walleij * Cap the bounce buffer at 64KB. Using a bigger bounce buffer 4133bd9b9027SLinus Walleij * has diminishing returns, this is probably because SD/MMC 4134bd9b9027SLinus Walleij * cards are usually optimized to handle this size of requests. 4135bd9b9027SLinus Walleij */ 4136bd9b9027SLinus Walleij bounce_size = SZ_64K; 4137bd9b9027SLinus Walleij /* 4138bd9b9027SLinus Walleij * Adjust downwards to maximum request size if this is less 4139bd9b9027SLinus Walleij * than our segment size, else hammer down the maximum 4140bd9b9027SLinus Walleij * request size to the maximum buffer size. 4141bd9b9027SLinus Walleij */ 4142bd9b9027SLinus Walleij if (mmc->max_req_size < bounce_size) 4143bd9b9027SLinus Walleij bounce_size = mmc->max_req_size; 4144bd9b9027SLinus Walleij max_blocks = bounce_size / 512; 4145bd9b9027SLinus Walleij 4146bd9b9027SLinus Walleij /* 4147bd9b9027SLinus Walleij * When we just support one segment, we can get significant 4148bd9b9027SLinus Walleij * speedups by the help of a bounce buffer to group scattered 4149bd9b9027SLinus Walleij * reads/writes together. 4150bd9b9027SLinus Walleij */ 4151bac53336SJisheng Zhang host->bounce_buffer = devm_kmalloc(mmc_dev(mmc), 4152bd9b9027SLinus Walleij bounce_size, 4153bd9b9027SLinus Walleij GFP_KERNEL); 4154bd9b9027SLinus Walleij if (!host->bounce_buffer) { 4155bd9b9027SLinus Walleij pr_err("%s: failed to allocate %u bytes for bounce buffer, falling back to single segments\n", 4156bd9b9027SLinus Walleij mmc_hostname(mmc), 4157bd9b9027SLinus Walleij bounce_size); 4158bd9b9027SLinus Walleij /* 4159bd9b9027SLinus Walleij * Exiting with zero here makes sure we proceed with 4160bd9b9027SLinus Walleij * mmc->max_segs == 1. 4161bd9b9027SLinus Walleij */ 4162a68dd9a0SChunyan Zhang return; 4163bd9b9027SLinus Walleij } 4164bd9b9027SLinus Walleij 4165bac53336SJisheng Zhang host->bounce_addr = dma_map_single(mmc_dev(mmc), 4166bd9b9027SLinus Walleij host->bounce_buffer, 4167bd9b9027SLinus Walleij bounce_size, 4168bd9b9027SLinus Walleij DMA_BIDIRECTIONAL); 4169bac53336SJisheng Zhang ret = dma_mapping_error(mmc_dev(mmc), host->bounce_addr); 417049036ba8STakashi Iwai if (ret) { 417149036ba8STakashi Iwai devm_kfree(mmc_dev(mmc), host->bounce_buffer); 417249036ba8STakashi Iwai host->bounce_buffer = NULL; 4173bd9b9027SLinus Walleij /* Again fall back to max_segs == 1 */ 4174a68dd9a0SChunyan Zhang return; 417549036ba8STakashi Iwai } 417649036ba8STakashi Iwai 4177bd9b9027SLinus Walleij host->bounce_buffer_size = bounce_size; 4178bd9b9027SLinus Walleij 4179bd9b9027SLinus Walleij /* Lie about this since we're bouncing */ 4180bd9b9027SLinus Walleij mmc->max_segs = max_blocks; 4181bd9b9027SLinus Walleij mmc->max_seg_size = bounce_size; 4182bd9b9027SLinus Walleij mmc->max_req_size = bounce_size; 4183bd9b9027SLinus Walleij 4184bd9b9027SLinus Walleij pr_info("%s bounce up to %u segments into one, max segment size %u bytes\n", 4185bd9b9027SLinus Walleij mmc_hostname(mmc), max_blocks, bounce_size); 4186bd9b9027SLinus Walleij } 4187bd9b9027SLinus Walleij 4188685e444bSChunyan Zhang static inline bool sdhci_can_64bit_dma(struct sdhci_host *host) 4189685e444bSChunyan Zhang { 4190685e444bSChunyan Zhang /* 4191685e444bSChunyan Zhang * According to SD Host Controller spec v4.10, bit[27] added from 4192685e444bSChunyan Zhang * version 4.10 in Capabilities Register is used as 64-bit System 4193685e444bSChunyan Zhang * Address support for V4 mode. 4194685e444bSChunyan Zhang */ 4195685e444bSChunyan Zhang if (host->version >= SDHCI_SPEC_410 && host->v4_mode) 4196685e444bSChunyan Zhang return host->caps & SDHCI_CAN_64BIT_V4; 4197685e444bSChunyan Zhang 4198685e444bSChunyan Zhang return host->caps & SDHCI_CAN_64BIT; 4199685e444bSChunyan Zhang } 4200685e444bSChunyan Zhang 420152f5336dSAdrian Hunter int sdhci_setup_host(struct sdhci_host *host) 4202b8c86fc5SPierre Ossman { 4203b8c86fc5SPierre Ossman struct mmc_host *mmc; 4204f2119df6SArindam Nath u32 max_current_caps; 4205f2119df6SArindam Nath unsigned int ocr_avail; 4206f5fa92e5SAdrian Hunter unsigned int override_timeout_clk; 420759241757SDong Aisheng u32 max_clk; 4208907be2a6SDan Carpenter int ret = 0; 42090fcb031eSVijay Viswanath bool enable_vqmmc = false; 4210b8c86fc5SPierre Ossman 4211b8c86fc5SPierre Ossman WARN_ON(host == NULL); 4212b8c86fc5SPierre Ossman if (host == NULL) 4213b8c86fc5SPierre Ossman return -EINVAL; 4214b8c86fc5SPierre Ossman 4215b8c86fc5SPierre Ossman mmc = host->mmc; 4216b8c86fc5SPierre Ossman 4217efba142bSJon Hunter /* 4218efba142bSJon Hunter * If there are external regulators, get them. Note this must be done 4219efba142bSJon Hunter * early before resetting the host and reading the capabilities so that 4220efba142bSJon Hunter * the host can take the appropriate action if regulators are not 4221efba142bSJon Hunter * available. 4222efba142bSJon Hunter */ 42230fcb031eSVijay Viswanath if (!mmc->supply.vqmmc) { 4224efba142bSJon Hunter ret = mmc_regulator_get_supply(mmc); 42252a63303dSWolfram Sang if (ret) 4226efba142bSJon Hunter return ret; 42270fcb031eSVijay Viswanath enable_vqmmc = true; 42280fcb031eSVijay Viswanath } 4229efba142bSJon Hunter 423006ebc601SShawn Lin DBG("Version: 0x%08x | Present: 0x%08x\n", 423106ebc601SShawn Lin sdhci_readw(host, SDHCI_HOST_VERSION), 423206ebc601SShawn Lin sdhci_readl(host, SDHCI_PRESENT_STATE)); 423306ebc601SShawn Lin DBG("Caps: 0x%08x | Caps_1: 0x%08x\n", 423406ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES), 423506ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES_1)); 423606ebc601SShawn Lin 42376132a3bfSAdrian Hunter sdhci_read_caps(host); 4238b8c86fc5SPierre Ossman 4239f5fa92e5SAdrian Hunter override_timeout_clk = host->timeout_clk; 4240f5fa92e5SAdrian Hunter 424118da1990SChunyan Zhang if (host->version > SDHCI_SPEC_420) { 42422e4456f0SMarek Vasut pr_err("%s: Unknown controller version (%d). You may experience problems.\n", 42432e4456f0SMarek Vasut mmc_hostname(mmc), host->version); 42441c6a0718SPierre Ossman } 42451c6a0718SPierre Ossman 4246b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 4247a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 424828da3589SAdrian Hunter else if (!(host->caps & SDHCI_CAN_DO_SDMA)) 4249a13abc7bSRichard Röjfors DBG("Controller doesn't have SDMA capability\n"); 42501c6a0718SPierre Ossman else 4251a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 42521c6a0718SPierre Ossman 4253b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 4254a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA)) { 4255cee687ceSRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 4256a13abc7bSRichard Röjfors host->flags &= ~SDHCI_USE_SDMA; 42577c168e3dSFeng Tang } 42587c168e3dSFeng Tang 4259f2119df6SArindam Nath if ((host->version >= SDHCI_SPEC_200) && 426028da3589SAdrian Hunter (host->caps & SDHCI_CAN_DO_ADMA2)) 42612134a922SPierre Ossman host->flags |= SDHCI_USE_ADMA; 42622134a922SPierre Ossman 42632134a922SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 42642134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 42652134a922SPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 42662134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 42672134a922SPierre Ossman } 42682134a922SPierre Ossman 4269685e444bSChunyan Zhang if (sdhci_can_64bit_dma(host)) 4270e57a5f61SAdrian Hunter host->flags |= SDHCI_USE_64_BIT_DMA; 4271e57a5f61SAdrian Hunter 427218e762e3SChunyan Zhang if (host->use_external_dma) { 427318e762e3SChunyan Zhang ret = sdhci_external_dma_init(host); 427418e762e3SChunyan Zhang if (ret == -EPROBE_DEFER) 427518e762e3SChunyan Zhang goto unreg; 427618e762e3SChunyan Zhang /* 427718e762e3SChunyan Zhang * Fall back to use the DMA/PIO integrated in standard SDHCI 427818e762e3SChunyan Zhang * instead of external DMA devices. 427918e762e3SChunyan Zhang */ 428018e762e3SChunyan Zhang else if (ret) 428118e762e3SChunyan Zhang sdhci_switch_external_dma(host, false); 428218e762e3SChunyan Zhang /* Disable internal DMA sources */ 428318e762e3SChunyan Zhang else 428418e762e3SChunyan Zhang host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 428518e762e3SChunyan Zhang } 428618e762e3SChunyan Zhang 4287a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 42884ee7dde4SAdrian Hunter if (host->ops->set_dma_mask) 42894ee7dde4SAdrian Hunter ret = host->ops->set_dma_mask(host); 42904ee7dde4SAdrian Hunter else 42917b91369bSAlexandre Courbot ret = sdhci_set_dma_mask(host); 42927b91369bSAlexandre Courbot 42937b91369bSAlexandre Courbot if (!ret && host->ops->enable_dma) 42947b91369bSAlexandre Courbot ret = host->ops->enable_dma(host); 42957b91369bSAlexandre Courbot 42967b91369bSAlexandre Courbot if (ret) { 42976606110dSJoe Perches pr_warn("%s: No suitable DMA available - falling back to PIO\n", 4298b8c86fc5SPierre Ossman mmc_hostname(mmc)); 42997b91369bSAlexandre Courbot host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 43007b91369bSAlexandre Courbot 43017b91369bSAlexandre Courbot ret = 0; 43021c6a0718SPierre Ossman } 4303b8c86fc5SPierre Ossman } 43041c6a0718SPierre Ossman 4305917a0c52SChunyan Zhang /* SDMA does not support 64-bit DMA if v4 mode not set */ 4306917a0c52SChunyan Zhang if ((host->flags & SDHCI_USE_64_BIT_DMA) && !host->v4_mode) 4307e57a5f61SAdrian Hunter host->flags &= ~SDHCI_USE_SDMA; 4308e57a5f61SAdrian Hunter 43092134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 4310e66e61cbSRussell King dma_addr_t dma; 4311e66e61cbSRussell King void *buf; 4312e66e61cbSRussell King 4313a663f64bSVeerabhadrarao Badiganti if (!(host->flags & SDHCI_USE_64_BIT_DMA)) 4314a663f64bSVeerabhadrarao Badiganti host->alloc_desc_sz = SDHCI_ADMA2_32_DESC_SZ; 4315a663f64bSVeerabhadrarao Badiganti else if (!host->alloc_desc_sz) 4316a663f64bSVeerabhadrarao Badiganti host->alloc_desc_sz = SDHCI_ADMA2_64_DESC_SZ(host); 4317a663f64bSVeerabhadrarao Badiganti 4318a663f64bSVeerabhadrarao Badiganti host->desc_sz = host->alloc_desc_sz; 4319a663f64bSVeerabhadrarao Badiganti host->adma_table_sz = host->adma_table_cnt * host->desc_sz; 4320e66e61cbSRussell King 432104a5ae6fSAdrian Hunter host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN; 4322685e444bSChunyan Zhang /* 4323685e444bSChunyan Zhang * Use zalloc to zero the reserved high 32-bits of 128-bit 4324685e444bSChunyan Zhang * descriptors so that they never need to be written. 4325685e444bSChunyan Zhang */ 4326750afb08SLuis Chamberlain buf = dma_alloc_coherent(mmc_dev(mmc), 4327750afb08SLuis Chamberlain host->align_buffer_sz + host->adma_table_sz, 4328750afb08SLuis Chamberlain &dma, GFP_KERNEL); 4329e66e61cbSRussell King if (!buf) { 43306606110dSJoe Perches pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", 43312134a922SPierre Ossman mmc_hostname(mmc)); 43322134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 4333e66e61cbSRussell King } else if ((dma + host->align_buffer_sz) & 4334e66e61cbSRussell King (SDHCI_ADMA2_DESC_ALIGN - 1)) { 43356606110dSJoe Perches pr_warn("%s: unable to allocate aligned ADMA descriptor\n", 4336d1e49f77SRussell King mmc_hostname(mmc)); 4337d1e49f77SRussell King host->flags &= ~SDHCI_USE_ADMA; 4338e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 4339e66e61cbSRussell King host->adma_table_sz, buf, dma); 4340e66e61cbSRussell King } else { 4341e66e61cbSRussell King host->align_buffer = buf; 4342e66e61cbSRussell King host->align_addr = dma; 4343edd63fccSRussell King 4344e66e61cbSRussell King host->adma_table = buf + host->align_buffer_sz; 4345e66e61cbSRussell King host->adma_addr = dma + host->align_buffer_sz; 4346e66e61cbSRussell King } 43472134a922SPierre Ossman } 43482134a922SPierre Ossman 43497659150cSPierre Ossman /* 43507659150cSPierre Ossman * If we use DMA, then it's up to the caller to set the DMA 43517659150cSPierre Ossman * mask, but PIO does not need the hw shim so we set a new 43527659150cSPierre Ossman * mask here in that case. 43537659150cSPierre Ossman */ 4354a13abc7bSRichard Röjfors if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) { 43557659150cSPierre Ossman host->dma_mask = DMA_BIT_MASK(64); 43564e743f1fSMarkus Mayer mmc_dev(mmc)->dma_mask = &host->dma_mask; 43577659150cSPierre Ossman } 43581c6a0718SPierre Ossman 4359c4687d5fSZhangfei Gao if (host->version >= SDHCI_SPEC_300) 4360a8e809ecSMasahiro Yamada host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps); 4361c4687d5fSZhangfei Gao else 4362a8e809ecSMasahiro Yamada host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps); 4363c4687d5fSZhangfei Gao 43644240ff0aSBen Dooks host->max_clk *= 1000000; 4365f27f47efSAnton Vorontsov if (host->max_clk == 0 || host->quirks & 4366f27f47efSAnton Vorontsov SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { 43674240ff0aSBen Dooks if (!host->ops->get_max_clock) { 43682e4456f0SMarek Vasut pr_err("%s: Hardware doesn't specify base clock frequency.\n", 43692e4456f0SMarek Vasut mmc_hostname(mmc)); 4370eb5c20deSAdrian Hunter ret = -ENODEV; 4371eb5c20deSAdrian Hunter goto undma; 43721c6a0718SPierre Ossman } 43734240ff0aSBen Dooks host->max_clk = host->ops->get_max_clock(host); 43744240ff0aSBen Dooks } 43751c6a0718SPierre Ossman 43761c6a0718SPierre Ossman /* 4377c3ed3877SArindam Nath * In case of Host Controller v3.00, find out whether clock 4378c3ed3877SArindam Nath * multiplier is supported. 4379c3ed3877SArindam Nath */ 4380a8e809ecSMasahiro Yamada host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1); 4381c3ed3877SArindam Nath 4382c3ed3877SArindam Nath /* 4383c3ed3877SArindam Nath * In case the value in Clock Multiplier is 0, then programmable 4384c3ed3877SArindam Nath * clock mode is not supported, otherwise the actual clock 4385c3ed3877SArindam Nath * multiplier is one more than the value of Clock Multiplier 4386c3ed3877SArindam Nath * in the Capabilities Register. 4387c3ed3877SArindam Nath */ 4388c3ed3877SArindam Nath if (host->clk_mul) 4389c3ed3877SArindam Nath host->clk_mul += 1; 4390c3ed3877SArindam Nath 4391c3ed3877SArindam Nath /* 43921c6a0718SPierre Ossman * Set host parameters. 43931c6a0718SPierre Ossman */ 439459241757SDong Aisheng max_clk = host->max_clk; 439559241757SDong Aisheng 4396ce5f036bSMarek Szyprowski if (host->ops->get_min_clock) 4397a9e58f25SAnton Vorontsov mmc->f_min = host->ops->get_min_clock(host); 4398c3ed3877SArindam Nath else if (host->version >= SDHCI_SPEC_300) { 43992a187d03SMichał Mirosław if (host->clk_mul) 440059241757SDong Aisheng max_clk = host->max_clk * host->clk_mul; 44012a187d03SMichał Mirosław /* 44022a187d03SMichał Mirosław * Divided Clock Mode minimum clock rate is always less than 44032a187d03SMichał Mirosław * Programmable Clock Mode minimum clock rate. 44042a187d03SMichał Mirosław */ 44050397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; 4406c3ed3877SArindam Nath } else 44070397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; 440815ec4461SPhilip Rakity 4409d310ae49SAdrian Hunter if (!mmc->f_max || mmc->f_max > max_clk) 441059241757SDong Aisheng mmc->f_max = max_clk; 441159241757SDong Aisheng 441228aab053SAisheng Dong if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { 4413a8e809ecSMasahiro Yamada host->timeout_clk = FIELD_GET(SDHCI_TIMEOUT_CLK_MASK, host->caps); 44148cc35289SShawn Lin 44158cc35289SShawn Lin if (host->caps & SDHCI_TIMEOUT_CLK_UNIT) 44168cc35289SShawn Lin host->timeout_clk *= 1000; 44178cc35289SShawn Lin 4418272308caSAndy Shevchenko if (host->timeout_clk == 0) { 44198cc35289SShawn Lin if (!host->ops->get_timeout_clock) { 442028aab053SAisheng Dong pr_err("%s: Hardware doesn't specify timeout clock frequency.\n", 442128aab053SAisheng Dong mmc_hostname(mmc)); 4422eb5c20deSAdrian Hunter ret = -ENODEV; 4423eb5c20deSAdrian Hunter goto undma; 4424272308caSAndy Shevchenko } 442528aab053SAisheng Dong 44268cc35289SShawn Lin host->timeout_clk = 44278cc35289SShawn Lin DIV_ROUND_UP(host->ops->get_timeout_clock(host), 44288cc35289SShawn Lin 1000); 44298cc35289SShawn Lin } 4430272308caSAndy Shevchenko 443199513624SAdrian Hunter if (override_timeout_clk) 443299513624SAdrian Hunter host->timeout_clk = override_timeout_clk; 443399513624SAdrian Hunter 4434a6ff5aebSAisheng Dong mmc->max_busy_timeout = host->ops->get_max_timeout_count ? 4435a6ff5aebSAisheng Dong host->ops->get_max_timeout_count(host) : 1 << 27; 4436a6ff5aebSAisheng Dong mmc->max_busy_timeout /= host->timeout_clk; 443728aab053SAisheng Dong } 443858d1246dSAdrian Hunter 4439a999fd93SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT && 4440a999fd93SAdrian Hunter !host->ops->get_max_timeout_count) 4441a999fd93SAdrian Hunter mmc->max_busy_timeout = 0; 4442a999fd93SAdrian Hunter 44431be64c79SUlf Hansson mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_CMD23; 4444781e989cSRussell King mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; 4445e89d456fSAndrei Warkentin 4446e89d456fSAndrei Warkentin if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) 4447e89d456fSAndrei Warkentin host->flags |= SDHCI_AUTO_CMD12; 44485fe23c7fSAnton Vorontsov 44497ed71a9dSChunyan Zhang /* 44507ed71a9dSChunyan Zhang * For v3 mode, Auto-CMD23 stuff only works in ADMA or PIO. 44517ed71a9dSChunyan Zhang * For v4 mode, SDMA may use Auto-CMD23 as well. 44527ed71a9dSChunyan Zhang */ 44534f3d3e9bSAndrei Warkentin if ((host->version >= SDHCI_SPEC_300) && 44548edf6371SAndrei Warkentin ((host->flags & SDHCI_USE_ADMA) || 44557ed71a9dSChunyan Zhang !(host->flags & SDHCI_USE_SDMA) || host->v4_mode) && 44563bfa6f03SScott Branden !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN)) { 44578edf6371SAndrei Warkentin host->flags |= SDHCI_AUTO_CMD23; 4458f421865dSAdrian Hunter DBG("Auto-CMD23 available\n"); 44598edf6371SAndrei Warkentin } else { 4460f421865dSAdrian Hunter DBG("Auto-CMD23 unavailable\n"); 44618edf6371SAndrei Warkentin } 44628edf6371SAndrei Warkentin 446315ec4461SPhilip Rakity /* 446415ec4461SPhilip Rakity * A controller may support 8-bit width, but the board itself 446515ec4461SPhilip Rakity * might not have the pins brought out. Boards that support 446615ec4461SPhilip Rakity * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in 446715ec4461SPhilip Rakity * their platform code before calling sdhci_add_host(), and we 446815ec4461SPhilip Rakity * won't assume 8-bit width for hosts without that CAP. 446915ec4461SPhilip Rakity */ 44705fe23c7fSAnton Vorontsov if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) 447115ec4461SPhilip Rakity mmc->caps |= MMC_CAP_4_BIT_DATA; 44721c6a0718SPierre Ossman 447363ef5d8cSJerry Huang if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) 447463ef5d8cSJerry Huang mmc->caps &= ~MMC_CAP_CMD23; 447563ef5d8cSJerry Huang 447628da3589SAdrian Hunter if (host->caps & SDHCI_CAN_DO_HISPD) 4477a29e7e18SZhangfei Gao mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; 44781c6a0718SPierre Ossman 4479176d1ed4SJaehoon Chung if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 4480860951c5SJaehoon Chung mmc_card_is_removable(mmc) && 4481d2f025b0SJisheng Zhang mmc_gpio_get_cd(mmc) < 0) 448268d1fb7eSAnton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL; 448368d1fb7eSAnton Vorontsov 44843a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 44850fcb031eSVijay Viswanath if (enable_vqmmc) { 44863a48edc4STim Kryger ret = regulator_enable(mmc->supply.vqmmc); 44870fcb031eSVijay Viswanath host->sdhci_core_to_disable_vqmmc = !ret; 44880fcb031eSVijay Viswanath } 44891b5190c2SStefan Agner 44901b5190c2SStefan Agner /* If vqmmc provides no 1.8V signalling, then there's no UHS */ 44913a48edc4STim Kryger if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000, 4492cec2e216SKevin Liu 1950000)) 449328da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | 44948363c374SKevin Liu SDHCI_SUPPORT_SDR50 | 44956231f3deSPhilip Rakity SDHCI_SUPPORT_DDR50); 44961b5190c2SStefan Agner 44971b5190c2SStefan Agner /* In eMMC case vqmmc might be a fixed 1.8V regulator */ 44981b5190c2SStefan Agner if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000, 44991b5190c2SStefan Agner 3600000)) 45001b5190c2SStefan Agner host->flags &= ~SDHCI_SIGNALING_330; 45011b5190c2SStefan Agner 4502a3361abaSChris Ball if (ret) { 4503a3361abaSChris Ball pr_warn("%s: Failed to enable vqmmc regulator: %d\n", 4504a3361abaSChris Ball mmc_hostname(mmc), ret); 45054bb74313SAdrian Hunter mmc->supply.vqmmc = ERR_PTR(-EINVAL); 4506a3361abaSChris Ball } 45073debc24fSVeerabhadrarao Badiganti 45088363c374SKevin Liu } 45096231f3deSPhilip Rakity 451028da3589SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) { 451128da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | 45126a66180aSDaniel Drake SDHCI_SUPPORT_DDR50); 4513c16bc9a7SKishon Vijay Abraham I /* 4514c16bc9a7SKishon Vijay Abraham I * The SDHCI controller in a SoC might support HS200/HS400 4515c16bc9a7SKishon Vijay Abraham I * (indicated using mmc-hs200-1_8v/mmc-hs400-1_8v dt property), 4516c16bc9a7SKishon Vijay Abraham I * but if the board is modeled such that the IO lines are not 4517c16bc9a7SKishon Vijay Abraham I * connected to 1.8v then HS200/HS400 cannot be supported. 4518c16bc9a7SKishon Vijay Abraham I * Disable HS200/HS400 if the board does not have 1.8v connected 4519c16bc9a7SKishon Vijay Abraham I * to the IO lines. (Applicable for other modes in 1.8v) 4520c16bc9a7SKishon Vijay Abraham I */ 4521c16bc9a7SKishon Vijay Abraham I mmc->caps2 &= ~(MMC_CAP2_HSX00_1_8V | MMC_CAP2_HS400_ES); 4522c16bc9a7SKishon Vijay Abraham I mmc->caps &= ~(MMC_CAP_1_8V_DDR | MMC_CAP_UHS); 452328da3589SAdrian Hunter } 45246a66180aSDaniel Drake 45254188bba0SAl Cooper /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ 452628da3589SAdrian Hunter if (host->caps1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | 45274188bba0SAl Cooper SDHCI_SUPPORT_DDR50)) 4528f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; 4529f2119df6SArindam Nath 4530f2119df6SArindam Nath /* SDR104 supports also implies SDR50 support */ 453128da3589SAdrian Hunter if (host->caps1 & SDHCI_SUPPORT_SDR104) { 4532f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; 4533156e14b1SGiuseppe CAVALLARO /* SD3.0: SDR104 is supported so (for eMMC) the caps2 4534156e14b1SGiuseppe CAVALLARO * field can be promoted to support HS200. 4535156e14b1SGiuseppe CAVALLARO */ 4536549c0b18SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) 4537156e14b1SGiuseppe CAVALLARO mmc->caps2 |= MMC_CAP2_HS200; 453828da3589SAdrian Hunter } else if (host->caps1 & SDHCI_SUPPORT_SDR50) { 4539f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR50; 454028da3589SAdrian Hunter } 4541f2119df6SArindam Nath 4542e9fb05d5SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 && 454328da3589SAdrian Hunter (host->caps1 & SDHCI_SUPPORT_HS400)) 4544e9fb05d5SAdrian Hunter mmc->caps2 |= MMC_CAP2_HS400; 4545e9fb05d5SAdrian Hunter 4546549c0b18SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) && 4547549c0b18SAdrian Hunter (IS_ERR(mmc->supply.vqmmc) || 4548549c0b18SAdrian Hunter !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000, 4549549c0b18SAdrian Hunter 1300000))) 4550549c0b18SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V; 4551549c0b18SAdrian Hunter 455228da3589SAdrian Hunter if ((host->caps1 & SDHCI_SUPPORT_DDR50) && 45539107ebbfSMicky Ching !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) 4554f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_DDR50; 4555f2119df6SArindam Nath 4556069c9f14SGirish K S /* Does the host need tuning for SDR50? */ 455728da3589SAdrian Hunter if (host->caps1 & SDHCI_USE_SDR50_TUNING) 4558b513ea25SArindam Nath host->flags |= SDHCI_SDR50_NEEDS_TUNING; 4559b513ea25SArindam Nath 4560d6d50a15SArindam Nath /* Driver Type(s) (A, C, D) supported by the host */ 456128da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_A) 4562d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_A; 456328da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_C) 4564d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_C; 456528da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_D) 4566d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_D; 4567d6d50a15SArindam Nath 4568cf2b5eeaSArindam Nath /* Initial value for re-tuning timer count */ 4569a8e809ecSMasahiro Yamada host->tuning_count = FIELD_GET(SDHCI_RETUNING_TIMER_COUNT_MASK, 4570a8e809ecSMasahiro Yamada host->caps1); 4571cf2b5eeaSArindam Nath 4572cf2b5eeaSArindam Nath /* 4573cf2b5eeaSArindam Nath * In case Re-tuning Timer is not disabled, the actual value of 4574cf2b5eeaSArindam Nath * re-tuning timer will be 2 ^ (n - 1). 4575cf2b5eeaSArindam Nath */ 4576cf2b5eeaSArindam Nath if (host->tuning_count) 4577cf2b5eeaSArindam Nath host->tuning_count = 1 << (host->tuning_count - 1); 4578cf2b5eeaSArindam Nath 4579cf2b5eeaSArindam Nath /* Re-tuning mode supported by the Host Controller */ 4580a8e809ecSMasahiro Yamada host->tuning_mode = FIELD_GET(SDHCI_RETUNING_MODE_MASK, host->caps1); 4581cf2b5eeaSArindam Nath 45828f230f45STakashi Iwai ocr_avail = 0; 4583bad37e1aSPhilip Rakity 4584f2119df6SArindam Nath /* 4585f2119df6SArindam Nath * According to SD Host Controller spec v3.00, if the Host System 4586f2119df6SArindam Nath * can afford more than 150mA, Host Driver should set XPC to 1. Also 4587f2119df6SArindam Nath * the value is meaningful only if Voltage Support in the Capabilities 4588f2119df6SArindam Nath * register is set. The actual current value is 4 times the register 4589f2119df6SArindam Nath * value. 4590f2119df6SArindam Nath */ 4591f2119df6SArindam Nath max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); 45923a48edc4STim Kryger if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) { 4593ae906037SChuanxiao.Dong int curr = regulator_get_current_limit(mmc->supply.vmmc); 4594bad37e1aSPhilip Rakity if (curr > 0) { 4595bad37e1aSPhilip Rakity 4596bad37e1aSPhilip Rakity /* convert to SDHCI_MAX_CURRENT format */ 4597bad37e1aSPhilip Rakity curr = curr/1000; /* convert to mA */ 4598bad37e1aSPhilip Rakity curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER; 4599bad37e1aSPhilip Rakity 4600bad37e1aSPhilip Rakity curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT); 4601bad37e1aSPhilip Rakity max_current_caps = 4602804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, curr) | 4603804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, curr) | 4604804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, curr); 4605bad37e1aSPhilip Rakity } 4606bad37e1aSPhilip Rakity } 4607f2119df6SArindam Nath 460828da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_330) { 46098f230f45STakashi Iwai ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; 4610f2119df6SArindam Nath 4611804a65b3SMasahiro Yamada mmc->max_current_330 = FIELD_GET(SDHCI_MAX_CURRENT_330_MASK, 4612804a65b3SMasahiro Yamada max_current_caps) * 4613f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4614f2119df6SArindam Nath } 461528da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_300) { 46168f230f45STakashi Iwai ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; 4617f2119df6SArindam Nath 4618804a65b3SMasahiro Yamada mmc->max_current_300 = FIELD_GET(SDHCI_MAX_CURRENT_300_MASK, 4619804a65b3SMasahiro Yamada max_current_caps) * 4620f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4621f2119df6SArindam Nath } 462228da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_180) { 46238f230f45STakashi Iwai ocr_avail |= MMC_VDD_165_195; 46248f230f45STakashi Iwai 4625804a65b3SMasahiro Yamada mmc->max_current_180 = FIELD_GET(SDHCI_MAX_CURRENT_180_MASK, 4626804a65b3SMasahiro Yamada max_current_caps) * 4627f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4628f2119df6SArindam Nath } 4629f2119df6SArindam Nath 46305fd26c7eSUlf Hansson /* If OCR set by host, use it instead. */ 46315fd26c7eSUlf Hansson if (host->ocr_mask) 46325fd26c7eSUlf Hansson ocr_avail = host->ocr_mask; 46335fd26c7eSUlf Hansson 46345fd26c7eSUlf Hansson /* If OCR set by external regulators, give it highest prio. */ 46353a48edc4STim Kryger if (mmc->ocr_avail) 463652221610STim Kryger ocr_avail = mmc->ocr_avail; 46373a48edc4STim Kryger 46388f230f45STakashi Iwai mmc->ocr_avail = ocr_avail; 46398f230f45STakashi Iwai mmc->ocr_avail_sdio = ocr_avail; 46408f230f45STakashi Iwai if (host->ocr_avail_sdio) 46418f230f45STakashi Iwai mmc->ocr_avail_sdio &= host->ocr_avail_sdio; 46428f230f45STakashi Iwai mmc->ocr_avail_sd = ocr_avail; 46438f230f45STakashi Iwai if (host->ocr_avail_sd) 46448f230f45STakashi Iwai mmc->ocr_avail_sd &= host->ocr_avail_sd; 46458f230f45STakashi Iwai else /* normal SD controllers don't support 1.8V */ 46468f230f45STakashi Iwai mmc->ocr_avail_sd &= ~MMC_VDD_165_195; 46478f230f45STakashi Iwai mmc->ocr_avail_mmc = ocr_avail; 46488f230f45STakashi Iwai if (host->ocr_avail_mmc) 46498f230f45STakashi Iwai mmc->ocr_avail_mmc &= host->ocr_avail_mmc; 46501c6a0718SPierre Ossman 46511c6a0718SPierre Ossman if (mmc->ocr_avail == 0) { 46522e4456f0SMarek Vasut pr_err("%s: Hardware doesn't report any support voltages.\n", 46532e4456f0SMarek Vasut mmc_hostname(mmc)); 4654eb5c20deSAdrian Hunter ret = -ENODEV; 4655eb5c20deSAdrian Hunter goto unreg; 46561c6a0718SPierre Ossman } 46571c6a0718SPierre Ossman 46588cb851a4SAdrian Hunter if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | 46598cb851a4SAdrian Hunter MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | 46608cb851a4SAdrian Hunter MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) || 46618cb851a4SAdrian Hunter (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V))) 46628cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_180; 46638cb851a4SAdrian Hunter 46648cb851a4SAdrian Hunter if (mmc->caps2 & MMC_CAP2_HSX00_1_2V) 46658cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_120; 46668cb851a4SAdrian Hunter 46671c6a0718SPierre Ossman spin_lock_init(&host->lock); 46681c6a0718SPierre Ossman 46691c6a0718SPierre Ossman /* 4670ac00531dSAdrian Hunter * Maximum number of sectors in one transfer. Limited by SDMA boundary 4671ac00531dSAdrian Hunter * size (512KiB). Note some tuning modes impose a 4MiB limit, but this 4672ac00531dSAdrian Hunter * is less anyway. 46731c6a0718SPierre Ossman */ 46741c6a0718SPierre Ossman mmc->max_req_size = 524288; 46751c6a0718SPierre Ossman 46761c6a0718SPierre Ossman /* 4677250dcd11SUlf Hansson * Maximum number of segments. Depends on if the hardware 4678250dcd11SUlf Hansson * can do scatter/gather or not. 4679250dcd11SUlf Hansson */ 4680250dcd11SUlf Hansson if (host->flags & SDHCI_USE_ADMA) { 4681250dcd11SUlf Hansson mmc->max_segs = SDHCI_MAX_SEGS; 4682250dcd11SUlf Hansson } else if (host->flags & SDHCI_USE_SDMA) { 4683250dcd11SUlf Hansson mmc->max_segs = 1; 468466e8d3b8SChristoph Hellwig mmc->max_req_size = min_t(size_t, mmc->max_req_size, 468566e8d3b8SChristoph Hellwig dma_max_mapping_size(mmc_dev(mmc))); 4686250dcd11SUlf Hansson } else { /* PIO */ 4687250dcd11SUlf Hansson mmc->max_segs = SDHCI_MAX_SEGS; 4688250dcd11SUlf Hansson } 4689250dcd11SUlf Hansson 4690250dcd11SUlf Hansson /* 46911c6a0718SPierre Ossman * Maximum segment size. Could be one segment with the maximum number 46922134a922SPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 46932134a922SPierre Ossman * be larger than 64 KiB though. 46941c6a0718SPierre Ossman */ 469530652aa3SOlof Johansson if (host->flags & SDHCI_USE_ADMA) { 46963d7c194bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) { 46973d7c194bSAdrian Hunter host->max_adma = 65532; /* 32-bit alignment */ 469830652aa3SOlof Johansson mmc->max_seg_size = 65535; 46993d7c194bSAdrian Hunter } else { 470030652aa3SOlof Johansson mmc->max_seg_size = 65536; 47013d7c194bSAdrian Hunter } 470230652aa3SOlof Johansson } else { 47031c6a0718SPierre Ossman mmc->max_seg_size = mmc->max_req_size; 470430652aa3SOlof Johansson } 47051c6a0718SPierre Ossman 47061c6a0718SPierre Ossman /* 47071c6a0718SPierre Ossman * Maximum block size. This varies from controller to controller and 47081c6a0718SPierre Ossman * is specified in the capabilities register. 47091c6a0718SPierre Ossman */ 47100633f654SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { 47110633f654SAnton Vorontsov mmc->max_blk_size = 2; 47120633f654SAnton Vorontsov } else { 471328da3589SAdrian Hunter mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >> 47140633f654SAnton Vorontsov SDHCI_MAX_BLOCK_SHIFT; 47151c6a0718SPierre Ossman if (mmc->max_blk_size >= 3) { 47166606110dSJoe Perches pr_warn("%s: Invalid maximum block size, assuming 512 bytes\n", 47176606110dSJoe Perches mmc_hostname(mmc)); 47180633f654SAnton Vorontsov mmc->max_blk_size = 0; 47190633f654SAnton Vorontsov } 47200633f654SAnton Vorontsov } 47210633f654SAnton Vorontsov 47221c6a0718SPierre Ossman mmc->max_blk_size = 512 << mmc->max_blk_size; 47231c6a0718SPierre Ossman 47241c6a0718SPierre Ossman /* 47251c6a0718SPierre Ossman * Maximum block count. 47261c6a0718SPierre Ossman */ 47271388eefdSBen Dooks mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; 47281c6a0718SPierre Ossman 4729a68dd9a0SChunyan Zhang if (mmc->max_segs == 1) 4730bd9b9027SLinus Walleij /* This may alter mmc->*_blk_* parameters */ 4731a68dd9a0SChunyan Zhang sdhci_allocate_bounce_buffer(host); 4732bd9b9027SLinus Walleij 473352f5336dSAdrian Hunter return 0; 473452f5336dSAdrian Hunter 473552f5336dSAdrian Hunter unreg: 47360fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 473752f5336dSAdrian Hunter regulator_disable(mmc->supply.vqmmc); 473852f5336dSAdrian Hunter undma: 473952f5336dSAdrian Hunter if (host->align_buffer) 474052f5336dSAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 474152f5336dSAdrian Hunter host->adma_table_sz, host->align_buffer, 474252f5336dSAdrian Hunter host->align_addr); 474352f5336dSAdrian Hunter host->adma_table = NULL; 474452f5336dSAdrian Hunter host->align_buffer = NULL; 474552f5336dSAdrian Hunter 474652f5336dSAdrian Hunter return ret; 474752f5336dSAdrian Hunter } 474852f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_setup_host); 474952f5336dSAdrian Hunter 47504180ffa8SAdrian Hunter void sdhci_cleanup_host(struct sdhci_host *host) 47514180ffa8SAdrian Hunter { 47524180ffa8SAdrian Hunter struct mmc_host *mmc = host->mmc; 47534180ffa8SAdrian Hunter 47540fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 47554180ffa8SAdrian Hunter regulator_disable(mmc->supply.vqmmc); 47564180ffa8SAdrian Hunter 47574180ffa8SAdrian Hunter if (host->align_buffer) 47584180ffa8SAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 47594180ffa8SAdrian Hunter host->adma_table_sz, host->align_buffer, 47604180ffa8SAdrian Hunter host->align_addr); 476118e762e3SChunyan Zhang 476218e762e3SChunyan Zhang if (host->use_external_dma) 476318e762e3SChunyan Zhang sdhci_external_dma_release(host); 476418e762e3SChunyan Zhang 47654180ffa8SAdrian Hunter host->adma_table = NULL; 47664180ffa8SAdrian Hunter host->align_buffer = NULL; 47674180ffa8SAdrian Hunter } 47684180ffa8SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cleanup_host); 47694180ffa8SAdrian Hunter 477052f5336dSAdrian Hunter int __sdhci_add_host(struct sdhci_host *host) 477152f5336dSAdrian Hunter { 4772c07a48c2SAdrian Hunter unsigned int flags = WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI; 477352f5336dSAdrian Hunter struct mmc_host *mmc = host->mmc; 477452f5336dSAdrian Hunter int ret; 477552f5336dSAdrian Hunter 47762b17b8d7SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_CQE) && 47772b17b8d7SAdrian Hunter (host->quirks & SDHCI_QUIRK_BROKEN_CQE)) { 47782b17b8d7SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_CQE; 47792b17b8d7SAdrian Hunter mmc->cqe_ops = NULL; 47802b17b8d7SAdrian Hunter } 47812b17b8d7SAdrian Hunter 4782c07a48c2SAdrian Hunter host->complete_wq = alloc_workqueue("sdhci", flags, 0); 4783c07a48c2SAdrian Hunter if (!host->complete_wq) 4784c07a48c2SAdrian Hunter return -ENOMEM; 4785c07a48c2SAdrian Hunter 4786c07a48c2SAdrian Hunter INIT_WORK(&host->complete_work, sdhci_complete_work); 47871c6a0718SPierre Ossman 47882ee4f620SKees Cook timer_setup(&host->timer, sdhci_timeout_timer, 0); 47892ee4f620SKees Cook timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0); 47901c6a0718SPierre Ossman 4791b513ea25SArindam Nath init_waitqueue_head(&host->buf_ready_int); 4792b513ea25SArindam Nath 47932af502caSShawn Guo sdhci_init(host, 0); 47942af502caSShawn Guo 4795781e989cSRussell King ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, 4796781e989cSRussell King IRQF_SHARED, mmc_hostname(mmc), host); 47970fc81ee3SMark Brown if (ret) { 47980fc81ee3SMark Brown pr_err("%s: Failed to request IRQ %d: %d\n", 47990fc81ee3SMark Brown mmc_hostname(mmc), host->irq, ret); 4800c07a48c2SAdrian Hunter goto unwq; 48010fc81ee3SMark Brown } 48021c6a0718SPierre Ossman 4803061d17a6SAdrian Hunter ret = sdhci_led_register(host); 48040fc81ee3SMark Brown if (ret) { 48050fc81ee3SMark Brown pr_err("%s: Failed to register LED device: %d\n", 48060fc81ee3SMark Brown mmc_hostname(mmc), ret); 4807eb5c20deSAdrian Hunter goto unirq; 48080fc81ee3SMark Brown } 48092f730fecSPierre Ossman 4810eb5c20deSAdrian Hunter ret = mmc_add_host(mmc); 4811eb5c20deSAdrian Hunter if (ret) 4812eb5c20deSAdrian Hunter goto unled; 48131c6a0718SPierre Ossman 4814a3c76eb9SGirish K S pr_info("%s: SDHCI controller on %s [%s] using %s\n", 4815d1b26863SKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), 481618e762e3SChunyan Zhang host->use_external_dma ? "External DMA" : 4817e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_ADMA) ? 4818e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" : 4819a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); 48201c6a0718SPierre Ossman 48217260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 48227260cf5eSAnton Vorontsov 48231c6a0718SPierre Ossman return 0; 48241c6a0718SPierre Ossman 4825eb5c20deSAdrian Hunter unled: 4826061d17a6SAdrian Hunter sdhci_led_unregister(host); 4827eb5c20deSAdrian Hunter unirq: 4828aa990722SAdrian Hunter sdhci_reset_for_all(host); 4829b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 4830b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 48312f730fecSPierre Ossman free_irq(host->irq, host); 4832c07a48c2SAdrian Hunter unwq: 4833c07a48c2SAdrian Hunter destroy_workqueue(host->complete_wq); 483452f5336dSAdrian Hunter 48351c6a0718SPierre Ossman return ret; 48361c6a0718SPierre Ossman } 483752f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_add_host); 48381c6a0718SPierre Ossman 483952f5336dSAdrian Hunter int sdhci_add_host(struct sdhci_host *host) 484052f5336dSAdrian Hunter { 484152f5336dSAdrian Hunter int ret; 484252f5336dSAdrian Hunter 484352f5336dSAdrian Hunter ret = sdhci_setup_host(host); 484452f5336dSAdrian Hunter if (ret) 484552f5336dSAdrian Hunter return ret; 484652f5336dSAdrian Hunter 48474180ffa8SAdrian Hunter ret = __sdhci_add_host(host); 48484180ffa8SAdrian Hunter if (ret) 48494180ffa8SAdrian Hunter goto cleanup; 48504180ffa8SAdrian Hunter 48514180ffa8SAdrian Hunter return 0; 48524180ffa8SAdrian Hunter 48534180ffa8SAdrian Hunter cleanup: 48544180ffa8SAdrian Hunter sdhci_cleanup_host(host); 48554180ffa8SAdrian Hunter 48564180ffa8SAdrian Hunter return ret; 485752f5336dSAdrian Hunter } 4858b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_add_host); 4859b8c86fc5SPierre Ossman 48601e72859eSPierre Ossman void sdhci_remove_host(struct sdhci_host *host, int dead) 48611c6a0718SPierre Ossman { 48623a48edc4STim Kryger struct mmc_host *mmc = host->mmc; 48631e72859eSPierre Ossman unsigned long flags; 48641e72859eSPierre Ossman 48651e72859eSPierre Ossman if (dead) { 48661e72859eSPierre Ossman spin_lock_irqsave(&host->lock, flags); 48671e72859eSPierre Ossman 48681e72859eSPierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 48691e72859eSPierre Ossman 48705d0d11c5SAdrian Hunter if (sdhci_has_requests(host)) { 4871a3c76eb9SGirish K S pr_err("%s: Controller removed during " 48724e743f1fSMarkus Mayer " transfer!\n", mmc_hostname(mmc)); 48735d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM); 48741e72859eSPierre Ossman } 48751e72859eSPierre Ossman 48761e72859eSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 48771e72859eSPierre Ossman } 48781e72859eSPierre Ossman 48797260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 48807260cf5eSAnton Vorontsov 48814e743f1fSMarkus Mayer mmc_remove_host(mmc); 48821c6a0718SPierre Ossman 4883061d17a6SAdrian Hunter sdhci_led_unregister(host); 48842f730fecSPierre Ossman 48851e72859eSPierre Ossman if (!dead) 4886aa990722SAdrian Hunter sdhci_reset_for_all(host); 48871c6a0718SPierre Ossman 4888b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 4889b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 48901c6a0718SPierre Ossman free_irq(host->irq, host); 48911c6a0718SPierre Ossman 48921c6a0718SPierre Ossman del_timer_sync(&host->timer); 4893d7422fb4SAdrian Hunter del_timer_sync(&host->data_timer); 48941c6a0718SPierre Ossman 4895c07a48c2SAdrian Hunter destroy_workqueue(host->complete_wq); 48962134a922SPierre Ossman 48970fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 48983a48edc4STim Kryger regulator_disable(mmc->supply.vqmmc); 48996231f3deSPhilip Rakity 4900edd63fccSRussell King if (host->align_buffer) 4901e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 4902e66e61cbSRussell King host->adma_table_sz, host->align_buffer, 4903e66e61cbSRussell King host->align_addr); 49042134a922SPierre Ossman 490518e762e3SChunyan Zhang if (host->use_external_dma) 490618e762e3SChunyan Zhang sdhci_external_dma_release(host); 490718e762e3SChunyan Zhang 49084efaa6fbSAdrian Hunter host->adma_table = NULL; 49092134a922SPierre Ossman host->align_buffer = NULL; 49101c6a0718SPierre Ossman } 49111c6a0718SPierre Ossman 4912b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_remove_host); 4913b8c86fc5SPierre Ossman 4914b8c86fc5SPierre Ossman void sdhci_free_host(struct sdhci_host *host) 49151c6a0718SPierre Ossman { 4916b8c86fc5SPierre Ossman mmc_free_host(host->mmc); 49171c6a0718SPierre Ossman } 49181c6a0718SPierre Ossman 4919b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_free_host); 49201c6a0718SPierre Ossman 49211c6a0718SPierre Ossman /*****************************************************************************\ 49221c6a0718SPierre Ossman * * 49231c6a0718SPierre Ossman * Driver init/exit * 49241c6a0718SPierre Ossman * * 49251c6a0718SPierre Ossman \*****************************************************************************/ 49261c6a0718SPierre Ossman 49271c6a0718SPierre Ossman static int __init sdhci_drv_init(void) 49281c6a0718SPierre Ossman { 4929a3c76eb9SGirish K S pr_info(DRIVER_NAME 49301c6a0718SPierre Ossman ": Secure Digital Host Controller Interface driver\n"); 4931a3c76eb9SGirish K S pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 49321c6a0718SPierre Ossman 4933b8c86fc5SPierre Ossman return 0; 49341c6a0718SPierre Ossman } 49351c6a0718SPierre Ossman 49361c6a0718SPierre Ossman static void __exit sdhci_drv_exit(void) 49371c6a0718SPierre Ossman { 49381c6a0718SPierre Ossman } 49391c6a0718SPierre Ossman 49401c6a0718SPierre Ossman module_init(sdhci_drv_init); 49411c6a0718SPierre Ossman module_exit(sdhci_drv_exit); 49421c6a0718SPierre Ossman 49431c6a0718SPierre Ossman module_param(debug_quirks, uint, 0444); 494466fd8ad5SAdrian Hunter module_param(debug_quirks2, uint, 0444); 49451c6a0718SPierre Ossman 494632710e8fSPierre Ossman MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); 4947b8c86fc5SPierre Ossman MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 49481c6a0718SPierre Ossman MODULE_LICENSE("GPL"); 49491c6a0718SPierre Ossman 49501c6a0718SPierre Ossman MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 495166fd8ad5SAdrian Hunter MODULE_PARM_DESC(debug_quirks2, "Force certain other quirks."); 4952