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; 19102d0b685SUlf Hansson pm_runtime_get_noresume(host->mmc->parent); 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; 19902d0b685SUlf Hansson pm_runtime_put_noidle(host->mmc->parent); 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); 2271c6a0718SPierre Ossman sdhci_dumpregs(host); 2281c6a0718SPierre Ossman return; 2291c6a0718SPierre Ossman } 2305a436cc0SAdrian Hunter udelay(10); 2311c6a0718SPierre Ossman } 23203231f9bSRussell King } 23303231f9bSRussell King EXPORT_SYMBOL_GPL(sdhci_reset); 234063a9dbbSAnton Vorontsov 23503231f9bSRussell King static void sdhci_do_reset(struct sdhci_host *host, u8 mask) 23603231f9bSRussell King { 23703231f9bSRussell King if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 238d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 239d3940f27SAdrian Hunter 240d3940f27SAdrian Hunter if (!mmc->ops->get_cd(mmc)) 24103231f9bSRussell King return; 24203231f9bSRussell King } 24303231f9bSRussell King 24403231f9bSRussell King host->ops->reset(host, mask); 245393c1a34SPhilip Rakity 246da91a8f9SRussell King if (mask & SDHCI_RESET_ALL) { 2473abc1e80SShaohui Xie if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 248da91a8f9SRussell King if (host->ops->enable_dma) 2493abc1e80SShaohui Xie host->ops->enable_dma(host); 2503abc1e80SShaohui Xie } 251da91a8f9SRussell King 252da91a8f9SRussell King /* Resetting the controller clears many */ 253da91a8f9SRussell King host->preset_enabled = false; 254da91a8f9SRussell King } 2551c6a0718SPierre Ossman } 2561c6a0718SPierre Ossman 257f5c1ab82SAdrian Hunter static void sdhci_set_default_irqs(struct sdhci_host *host) 2581c6a0718SPierre Ossman { 259b537f94cSRussell King host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 260b537f94cSRussell King SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | 261b537f94cSRussell King SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | 262b537f94cSRussell King SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | 263b537f94cSRussell King SDHCI_INT_RESPONSE; 264b537f94cSRussell King 265f37b20ebSDong Aisheng if (host->tuning_mode == SDHCI_TUNING_MODE_2 || 266f37b20ebSDong Aisheng host->tuning_mode == SDHCI_TUNING_MODE_3) 267f37b20ebSDong Aisheng host->ier |= SDHCI_INT_RETUNE; 268f37b20ebSDong Aisheng 269b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 270b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 271f5c1ab82SAdrian Hunter } 272f5c1ab82SAdrian Hunter 273685e444bSChunyan Zhang static void sdhci_config_dma(struct sdhci_host *host) 274685e444bSChunyan Zhang { 275685e444bSChunyan Zhang u8 ctrl; 276685e444bSChunyan Zhang u16 ctrl2; 277685e444bSChunyan Zhang 278685e444bSChunyan Zhang if (host->version < SDHCI_SPEC_200) 279685e444bSChunyan Zhang return; 280685e444bSChunyan Zhang 281685e444bSChunyan Zhang ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 282685e444bSChunyan Zhang 283685e444bSChunyan Zhang /* 284685e444bSChunyan Zhang * Always adjust the DMA selection as some controllers 285685e444bSChunyan Zhang * (e.g. JMicron) can't do PIO properly when the selection 286685e444bSChunyan Zhang * is ADMA. 287685e444bSChunyan Zhang */ 288685e444bSChunyan Zhang ctrl &= ~SDHCI_CTRL_DMA_MASK; 289685e444bSChunyan Zhang if (!(host->flags & SDHCI_REQ_USE_DMA)) 290685e444bSChunyan Zhang goto out; 291685e444bSChunyan Zhang 292685e444bSChunyan Zhang /* Note if DMA Select is zero then SDMA is selected */ 293685e444bSChunyan Zhang if (host->flags & SDHCI_USE_ADMA) 294685e444bSChunyan Zhang ctrl |= SDHCI_CTRL_ADMA32; 295685e444bSChunyan Zhang 296685e444bSChunyan Zhang if (host->flags & SDHCI_USE_64_BIT_DMA) { 297685e444bSChunyan Zhang /* 298685e444bSChunyan Zhang * If v4 mode, all supported DMA can be 64-bit addressing if 299685e444bSChunyan Zhang * controller supports 64-bit system address, otherwise only 300685e444bSChunyan Zhang * ADMA can support 64-bit addressing. 301685e444bSChunyan Zhang */ 302685e444bSChunyan Zhang if (host->v4_mode) { 303685e444bSChunyan Zhang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 304685e444bSChunyan Zhang ctrl2 |= SDHCI_CTRL_64BIT_ADDR; 305685e444bSChunyan Zhang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 306685e444bSChunyan Zhang } else if (host->flags & SDHCI_USE_ADMA) { 307685e444bSChunyan Zhang /* 308685e444bSChunyan Zhang * Don't need to undo SDHCI_CTRL_ADMA32 in order to 309685e444bSChunyan Zhang * set SDHCI_CTRL_ADMA64. 310685e444bSChunyan Zhang */ 311685e444bSChunyan Zhang ctrl |= SDHCI_CTRL_ADMA64; 312685e444bSChunyan Zhang } 313685e444bSChunyan Zhang } 314685e444bSChunyan Zhang 315685e444bSChunyan Zhang out: 316685e444bSChunyan Zhang sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 317685e444bSChunyan Zhang } 318685e444bSChunyan Zhang 319f5c1ab82SAdrian Hunter static void sdhci_init(struct sdhci_host *host, int soft) 320f5c1ab82SAdrian Hunter { 321f5c1ab82SAdrian Hunter struct mmc_host *mmc = host->mmc; 32249769d4dSHaibo Chen unsigned long flags; 323f5c1ab82SAdrian Hunter 324f5c1ab82SAdrian Hunter if (soft) 325f5c1ab82SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 326f5c1ab82SAdrian Hunter else 327f5c1ab82SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_ALL); 328f5c1ab82SAdrian Hunter 329b3f80b43SChunyan Zhang if (host->v4_mode) 330b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host); 331b3f80b43SChunyan Zhang 33249769d4dSHaibo Chen spin_lock_irqsave(&host->lock, flags); 333f5c1ab82SAdrian Hunter sdhci_set_default_irqs(host); 33449769d4dSHaibo Chen spin_unlock_irqrestore(&host->lock, flags); 3352f4cbb3dSNicolas Pitre 336f12e39dbSAdrian Hunter host->cqe_on = false; 337f12e39dbSAdrian Hunter 3382f4cbb3dSNicolas Pitre if (soft) { 3392f4cbb3dSNicolas Pitre /* force clock reconfiguration */ 3402f4cbb3dSNicolas Pitre host->clock = 0; 341d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 3422f4cbb3dSNicolas Pitre } 3437260cf5eSAnton Vorontsov } 3441c6a0718SPierre Ossman 3457260cf5eSAnton Vorontsov static void sdhci_reinit(struct sdhci_host *host) 3467260cf5eSAnton Vorontsov { 347dcaac3f7SRaul E Rangel u32 cd = host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); 348dcaac3f7SRaul E Rangel 3492f4cbb3dSNicolas Pitre sdhci_init(host, 0); 3507260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 351dcaac3f7SRaul E Rangel 352dcaac3f7SRaul E Rangel /* 353dcaac3f7SRaul E Rangel * A change to the card detect bits indicates a change in present state, 354dcaac3f7SRaul E Rangel * refer sdhci_set_card_detection(). A card detect interrupt might have 355dcaac3f7SRaul E Rangel * been missed while the host controller was being reset, so trigger a 356dcaac3f7SRaul E Rangel * rescan to check. 357dcaac3f7SRaul E Rangel */ 358dcaac3f7SRaul E Rangel if (cd != (host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT))) 359dcaac3f7SRaul E Rangel mmc_detect_change(host->mmc, msecs_to_jiffies(200)); 3601c6a0718SPierre Ossman } 3611c6a0718SPierre Ossman 362061d17a6SAdrian Hunter static void __sdhci_led_activate(struct sdhci_host *host) 3631c6a0718SPierre Ossman { 3641c6a0718SPierre Ossman u8 ctrl; 3651c6a0718SPierre Ossman 366bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 367bd29f58bSAdrian Hunter return; 368bd29f58bSAdrian Hunter 3694e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 3701c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_LED; 3714e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 3721c6a0718SPierre Ossman } 3731c6a0718SPierre Ossman 374061d17a6SAdrian Hunter static void __sdhci_led_deactivate(struct sdhci_host *host) 3751c6a0718SPierre Ossman { 3761c6a0718SPierre Ossman u8 ctrl; 3771c6a0718SPierre Ossman 378bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 379bd29f58bSAdrian Hunter return; 380bd29f58bSAdrian Hunter 3814e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 3821c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_LED; 3834e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 3841c6a0718SPierre Ossman } 3851c6a0718SPierre Ossman 3864f78230fSMasahiro Yamada #if IS_REACHABLE(CONFIG_LEDS_CLASS) 3872f730fecSPierre Ossman static void sdhci_led_control(struct led_classdev *led, 3882f730fecSPierre Ossman enum led_brightness brightness) 3892f730fecSPierre Ossman { 3902f730fecSPierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 3912f730fecSPierre Ossman unsigned long flags; 3922f730fecSPierre Ossman 3932f730fecSPierre Ossman spin_lock_irqsave(&host->lock, flags); 3942f730fecSPierre Ossman 39566fd8ad5SAdrian Hunter if (host->runtime_suspended) 39666fd8ad5SAdrian Hunter goto out; 39766fd8ad5SAdrian Hunter 3982f730fecSPierre Ossman if (brightness == LED_OFF) 399061d17a6SAdrian Hunter __sdhci_led_deactivate(host); 4002f730fecSPierre Ossman else 401061d17a6SAdrian Hunter __sdhci_led_activate(host); 40266fd8ad5SAdrian Hunter out: 4032f730fecSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 4042f730fecSPierre Ossman } 405061d17a6SAdrian Hunter 406061d17a6SAdrian Hunter static int sdhci_led_register(struct sdhci_host *host) 407061d17a6SAdrian Hunter { 408061d17a6SAdrian Hunter struct mmc_host *mmc = host->mmc; 409061d17a6SAdrian Hunter 410bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 411bd29f58bSAdrian Hunter return 0; 412bd29f58bSAdrian Hunter 413061d17a6SAdrian Hunter snprintf(host->led_name, sizeof(host->led_name), 414061d17a6SAdrian Hunter "%s::", mmc_hostname(mmc)); 415061d17a6SAdrian Hunter 416061d17a6SAdrian Hunter host->led.name = host->led_name; 417061d17a6SAdrian Hunter host->led.brightness = LED_OFF; 418061d17a6SAdrian Hunter host->led.default_trigger = mmc_hostname(mmc); 419061d17a6SAdrian Hunter host->led.brightness_set = sdhci_led_control; 420061d17a6SAdrian Hunter 421061d17a6SAdrian Hunter return led_classdev_register(mmc_dev(mmc), &host->led); 422061d17a6SAdrian Hunter } 423061d17a6SAdrian Hunter 424061d17a6SAdrian Hunter static void sdhci_led_unregister(struct sdhci_host *host) 425061d17a6SAdrian Hunter { 426bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 427bd29f58bSAdrian Hunter return; 428bd29f58bSAdrian Hunter 429061d17a6SAdrian Hunter led_classdev_unregister(&host->led); 430061d17a6SAdrian Hunter } 431061d17a6SAdrian Hunter 432061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host) 433061d17a6SAdrian Hunter { 434061d17a6SAdrian Hunter } 435061d17a6SAdrian Hunter 436061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host) 437061d17a6SAdrian Hunter { 438061d17a6SAdrian Hunter } 439061d17a6SAdrian Hunter 440061d17a6SAdrian Hunter #else 441061d17a6SAdrian Hunter 442061d17a6SAdrian Hunter static inline int sdhci_led_register(struct sdhci_host *host) 443061d17a6SAdrian Hunter { 444061d17a6SAdrian Hunter return 0; 445061d17a6SAdrian Hunter } 446061d17a6SAdrian Hunter 447061d17a6SAdrian Hunter static inline void sdhci_led_unregister(struct sdhci_host *host) 448061d17a6SAdrian Hunter { 449061d17a6SAdrian Hunter } 450061d17a6SAdrian Hunter 451061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host) 452061d17a6SAdrian Hunter { 453061d17a6SAdrian Hunter __sdhci_led_activate(host); 454061d17a6SAdrian Hunter } 455061d17a6SAdrian Hunter 456061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host) 457061d17a6SAdrian Hunter { 458061d17a6SAdrian Hunter __sdhci_led_deactivate(host); 459061d17a6SAdrian Hunter } 460061d17a6SAdrian Hunter 4612f730fecSPierre Ossman #endif 4622f730fecSPierre Ossman 46397a1abaeSAdrian Hunter static void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, 46497a1abaeSAdrian Hunter unsigned long timeout) 46597a1abaeSAdrian Hunter { 46697a1abaeSAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd)) 46797a1abaeSAdrian Hunter mod_timer(&host->data_timer, timeout); 46897a1abaeSAdrian Hunter else 46997a1abaeSAdrian Hunter mod_timer(&host->timer, timeout); 47097a1abaeSAdrian Hunter } 47197a1abaeSAdrian Hunter 47297a1abaeSAdrian Hunter static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq) 47397a1abaeSAdrian Hunter { 47497a1abaeSAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd)) 47597a1abaeSAdrian Hunter del_timer(&host->data_timer); 47697a1abaeSAdrian Hunter else 47797a1abaeSAdrian Hunter del_timer(&host->timer); 47897a1abaeSAdrian Hunter } 47997a1abaeSAdrian Hunter 48097a1abaeSAdrian Hunter static inline bool sdhci_has_requests(struct sdhci_host *host) 48197a1abaeSAdrian Hunter { 48297a1abaeSAdrian Hunter return host->cmd || host->data_cmd; 48397a1abaeSAdrian Hunter } 48497a1abaeSAdrian Hunter 4851c6a0718SPierre Ossman /*****************************************************************************\ 4861c6a0718SPierre Ossman * * 4871c6a0718SPierre Ossman * Core functions * 4881c6a0718SPierre Ossman * * 4891c6a0718SPierre Ossman \*****************************************************************************/ 4901c6a0718SPierre Ossman 4911c6a0718SPierre Ossman static void sdhci_read_block_pio(struct sdhci_host *host) 4921c6a0718SPierre Ossman { 4937659150cSPierre Ossman unsigned long flags; 4947659150cSPierre Ossman size_t blksize, len, chunk; 4953f649ab7SKees Cook u32 scratch; 4967659150cSPierre Ossman u8 *buf; 4971c6a0718SPierre Ossman 4981c6a0718SPierre Ossman DBG("PIO reading\n"); 4991c6a0718SPierre Ossman 5001c6a0718SPierre Ossman blksize = host->data->blksz; 5017659150cSPierre Ossman chunk = 0; 5021c6a0718SPierre Ossman 5037659150cSPierre Ossman local_irq_save(flags); 5041c6a0718SPierre Ossman 5051c6a0718SPierre Ossman while (blksize) { 506bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter)); 5077659150cSPierre Ossman 5087659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 5097659150cSPierre Ossman 5107659150cSPierre Ossman blksize -= len; 5117659150cSPierre Ossman host->sg_miter.consumed = len; 5127659150cSPierre Ossman 5137659150cSPierre Ossman buf = host->sg_miter.addr; 5147659150cSPierre Ossman 5157659150cSPierre Ossman while (len) { 5167659150cSPierre Ossman if (chunk == 0) { 5174e4141a5SAnton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER); 5187659150cSPierre Ossman chunk = 4; 5191c6a0718SPierre Ossman } 5201c6a0718SPierre Ossman 5217659150cSPierre Ossman *buf = scratch & 0xFF; 5221c6a0718SPierre Ossman 5237659150cSPierre Ossman buf++; 5247659150cSPierre Ossman scratch >>= 8; 5257659150cSPierre Ossman chunk--; 5267659150cSPierre Ossman len--; 5277659150cSPierre Ossman } 5281c6a0718SPierre Ossman } 5291c6a0718SPierre Ossman 5307659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 5317659150cSPierre Ossman 5327659150cSPierre Ossman local_irq_restore(flags); 5331c6a0718SPierre Ossman } 5341c6a0718SPierre Ossman 5351c6a0718SPierre Ossman static void sdhci_write_block_pio(struct sdhci_host *host) 5361c6a0718SPierre Ossman { 5377659150cSPierre Ossman unsigned long flags; 5387659150cSPierre Ossman size_t blksize, len, chunk; 5397659150cSPierre Ossman u32 scratch; 5407659150cSPierre Ossman u8 *buf; 5411c6a0718SPierre Ossman 5421c6a0718SPierre Ossman DBG("PIO writing\n"); 5431c6a0718SPierre Ossman 5441c6a0718SPierre Ossman blksize = host->data->blksz; 5457659150cSPierre Ossman chunk = 0; 5467659150cSPierre Ossman scratch = 0; 5471c6a0718SPierre Ossman 5487659150cSPierre Ossman local_irq_save(flags); 5491c6a0718SPierre Ossman 5501c6a0718SPierre Ossman while (blksize) { 551bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter)); 5521c6a0718SPierre Ossman 5537659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 5541c6a0718SPierre Ossman 5557659150cSPierre Ossman blksize -= len; 5567659150cSPierre Ossman host->sg_miter.consumed = len; 5577659150cSPierre Ossman 5587659150cSPierre Ossman buf = host->sg_miter.addr; 5597659150cSPierre Ossman 5607659150cSPierre Ossman while (len) { 5617659150cSPierre Ossman scratch |= (u32)*buf << (chunk * 8); 5627659150cSPierre Ossman 5637659150cSPierre Ossman buf++; 5647659150cSPierre Ossman chunk++; 5657659150cSPierre Ossman len--; 5667659150cSPierre Ossman 5677659150cSPierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 5684e4141a5SAnton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER); 5697659150cSPierre Ossman chunk = 0; 5707659150cSPierre Ossman scratch = 0; 5717659150cSPierre Ossman } 5727659150cSPierre Ossman } 5731c6a0718SPierre Ossman } 5741c6a0718SPierre Ossman 5757659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 5761c6a0718SPierre Ossman 5777659150cSPierre Ossman local_irq_restore(flags); 5781c6a0718SPierre Ossman } 5791c6a0718SPierre Ossman 5801c6a0718SPierre Ossman static void sdhci_transfer_pio(struct sdhci_host *host) 5811c6a0718SPierre Ossman { 5821c6a0718SPierre Ossman u32 mask; 5831c6a0718SPierre Ossman 5847659150cSPierre Ossman if (host->blocks == 0) 5851c6a0718SPierre Ossman return; 5861c6a0718SPierre Ossman 5871c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 5881c6a0718SPierre Ossman mask = SDHCI_DATA_AVAILABLE; 5891c6a0718SPierre Ossman else 5901c6a0718SPierre Ossman mask = SDHCI_SPACE_AVAILABLE; 5911c6a0718SPierre Ossman 5924a3cba32SPierre Ossman /* 5934a3cba32SPierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 5944a3cba32SPierre Ossman * for transfers < 4 bytes. As long as it is just one block, 5954a3cba32SPierre Ossman * we can ignore the bits. 5964a3cba32SPierre Ossman */ 5974a3cba32SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 5984a3cba32SPierre Ossman (host->data->blocks == 1)) 5994a3cba32SPierre Ossman mask = ~0; 6004a3cba32SPierre Ossman 6014e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 6023e3bf207SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 6033e3bf207SAnton Vorontsov udelay(100); 6043e3bf207SAnton Vorontsov 6051c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 6061c6a0718SPierre Ossman sdhci_read_block_pio(host); 6071c6a0718SPierre Ossman else 6081c6a0718SPierre Ossman sdhci_write_block_pio(host); 6091c6a0718SPierre Ossman 6107659150cSPierre Ossman host->blocks--; 6117659150cSPierre Ossman if (host->blocks == 0) 6121c6a0718SPierre Ossman break; 6131c6a0718SPierre Ossman } 6141c6a0718SPierre Ossman 6151c6a0718SPierre Ossman DBG("PIO transfer complete.\n"); 6161c6a0718SPierre Ossman } 6171c6a0718SPierre Ossman 61848857d9bSRussell King static int sdhci_pre_dma_transfer(struct sdhci_host *host, 619c0999b72SRussell King struct mmc_data *data, int cookie) 62048857d9bSRussell King { 62148857d9bSRussell King int sg_count; 62248857d9bSRussell King 62394538e51SRussell King /* 62494538e51SRussell King * If the data buffers are already mapped, return the previous 62594538e51SRussell King * dma_map_sg() result. 62694538e51SRussell King */ 62794538e51SRussell King if (data->host_cookie == COOKIE_PRE_MAPPED) 62848857d9bSRussell King return data->sg_count; 62948857d9bSRussell King 630bd9b9027SLinus Walleij /* Bounce write requests to the bounce buffer */ 631bd9b9027SLinus Walleij if (host->bounce_buffer) { 632bd9b9027SLinus Walleij unsigned int length = data->blksz * data->blocks; 633bd9b9027SLinus Walleij 634bd9b9027SLinus Walleij if (length > host->bounce_buffer_size) { 635bd9b9027SLinus Walleij pr_err("%s: asked for transfer of %u bytes exceeds bounce buffer %u bytes\n", 636bd9b9027SLinus Walleij mmc_hostname(host->mmc), length, 637bd9b9027SLinus Walleij host->bounce_buffer_size); 638bd9b9027SLinus Walleij return -EIO; 639bd9b9027SLinus Walleij } 640bd9b9027SLinus Walleij if (mmc_get_dma_dir(data) == DMA_TO_DEVICE) { 641bd9b9027SLinus Walleij /* Copy the data to the bounce buffer */ 642e93577ecSAngelo Dureghello if (host->ops->copy_to_bounce_buffer) { 643e93577ecSAngelo Dureghello host->ops->copy_to_bounce_buffer(host, 644e93577ecSAngelo Dureghello data, length); 645e93577ecSAngelo Dureghello } else { 646bd9b9027SLinus Walleij sg_copy_to_buffer(data->sg, data->sg_len, 647e93577ecSAngelo Dureghello host->bounce_buffer, length); 648e93577ecSAngelo Dureghello } 649bd9b9027SLinus Walleij } 650bd9b9027SLinus Walleij /* Switch ownership to the DMA */ 651bd9b9027SLinus Walleij dma_sync_single_for_device(host->mmc->parent, 652bd9b9027SLinus Walleij host->bounce_addr, 653bd9b9027SLinus Walleij host->bounce_buffer_size, 654feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 655bd9b9027SLinus Walleij /* Just a dummy value */ 656bd9b9027SLinus Walleij sg_count = 1; 657bd9b9027SLinus Walleij } else { 658bd9b9027SLinus Walleij /* Just access the data directly from memory */ 659bd9b9027SLinus Walleij sg_count = dma_map_sg(mmc_dev(host->mmc), 660bd9b9027SLinus Walleij data->sg, data->sg_len, 661bd9b9027SLinus Walleij mmc_get_dma_dir(data)); 662bd9b9027SLinus Walleij } 66348857d9bSRussell King 66448857d9bSRussell King if (sg_count == 0) 66548857d9bSRussell King return -ENOSPC; 66648857d9bSRussell King 66748857d9bSRussell King data->sg_count = sg_count; 668c0999b72SRussell King data->host_cookie = cookie; 66948857d9bSRussell King 67048857d9bSRussell King return sg_count; 67148857d9bSRussell King } 67248857d9bSRussell King 6732134a922SPierre Ossman static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) 6742134a922SPierre Ossman { 6752134a922SPierre Ossman local_irq_save(*flags); 676482fce99SCong Wang return kmap_atomic(sg_page(sg)) + sg->offset; 6772134a922SPierre Ossman } 6782134a922SPierre Ossman 6792134a922SPierre Ossman static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) 6802134a922SPierre Ossman { 681482fce99SCong Wang kunmap_atomic(buffer); 6822134a922SPierre Ossman local_irq_restore(*flags); 6832134a922SPierre Ossman } 6842134a922SPierre Ossman 68554552e49SJisheng Zhang void sdhci_adma_write_desc(struct sdhci_host *host, void **desc, 68654552e49SJisheng Zhang dma_addr_t addr, int len, unsigned int cmd) 687118cd17dSBen Dooks { 68854552e49SJisheng Zhang struct sdhci_adma2_64_desc *dma_desc = *desc; 689118cd17dSBen Dooks 690e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have these members in same position */ 6910545230fSAdrian Hunter dma_desc->cmd = cpu_to_le16(cmd); 6920545230fSAdrian Hunter dma_desc->len = cpu_to_le16(len); 69338eee2e8SMasahiro Yamada dma_desc->addr_lo = cpu_to_le32(lower_32_bits(addr)); 694e57a5f61SAdrian Hunter 695e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 69638eee2e8SMasahiro Yamada dma_desc->addr_hi = cpu_to_le32(upper_32_bits(addr)); 69754552e49SJisheng Zhang 69854552e49SJisheng Zhang *desc += host->desc_sz; 69954552e49SJisheng Zhang } 70054552e49SJisheng Zhang EXPORT_SYMBOL_GPL(sdhci_adma_write_desc); 70154552e49SJisheng Zhang 70254552e49SJisheng Zhang static inline void __sdhci_adma_write_desc(struct sdhci_host *host, 70354552e49SJisheng Zhang void **desc, dma_addr_t addr, 70454552e49SJisheng Zhang int len, unsigned int cmd) 70554552e49SJisheng Zhang { 70654552e49SJisheng Zhang if (host->ops->adma_write_desc) 70754552e49SJisheng Zhang host->ops->adma_write_desc(host, desc, addr, len, cmd); 70807be55b5SJisheng Zhang else 70954552e49SJisheng Zhang sdhci_adma_write_desc(host, desc, addr, len, cmd); 710118cd17dSBen Dooks } 711118cd17dSBen Dooks 712b5ffa674SAdrian Hunter static void sdhci_adma_mark_end(void *desc) 713b5ffa674SAdrian Hunter { 714e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 715b5ffa674SAdrian Hunter 716e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have 'cmd' in same position */ 7170545230fSAdrian Hunter dma_desc->cmd |= cpu_to_le16(ADMA2_END); 718b5ffa674SAdrian Hunter } 719b5ffa674SAdrian Hunter 72060c64762SRussell King static void sdhci_adma_table_pre(struct sdhci_host *host, 72160c64762SRussell King struct mmc_data *data, int sg_count) 7222134a922SPierre Ossman { 7232134a922SPierre Ossman struct scatterlist *sg; 7242134a922SPierre Ossman unsigned long flags; 725acc3ad13SRussell King dma_addr_t addr, align_addr; 726acc3ad13SRussell King void *desc, *align; 727acc3ad13SRussell King char *buffer; 728acc3ad13SRussell King int len, offset, i; 7292134a922SPierre Ossman 7302134a922SPierre Ossman /* 7312134a922SPierre Ossman * The spec does not specify endianness of descriptor table. 7322134a922SPierre Ossman * We currently guess that it is LE. 7332134a922SPierre Ossman */ 7342134a922SPierre Ossman 73560c64762SRussell King host->sg_count = sg_count; 7362134a922SPierre Ossman 7374efaa6fbSAdrian Hunter desc = host->adma_table; 7382134a922SPierre Ossman align = host->align_buffer; 7392134a922SPierre Ossman 7402134a922SPierre Ossman align_addr = host->align_addr; 7412134a922SPierre Ossman 7422134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 7432134a922SPierre Ossman addr = sg_dma_address(sg); 7442134a922SPierre Ossman len = sg_dma_len(sg); 7452134a922SPierre Ossman 7462134a922SPierre Ossman /* 747acc3ad13SRussell King * The SDHCI specification states that ADMA addresses must 748acc3ad13SRussell King * be 32-bit aligned. If they aren't, then we use a bounce 749acc3ad13SRussell King * buffer for the (up to three) bytes that screw up the 7502134a922SPierre Ossman * alignment. 7512134a922SPierre Ossman */ 75204a5ae6fSAdrian Hunter offset = (SDHCI_ADMA2_ALIGN - (addr & SDHCI_ADMA2_MASK)) & 75304a5ae6fSAdrian Hunter SDHCI_ADMA2_MASK; 7542134a922SPierre Ossman if (offset) { 7552134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 7562134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 7572134a922SPierre Ossman memcpy(align, buffer, offset); 7582134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 7592134a922SPierre Ossman } 7602134a922SPierre Ossman 761118cd17dSBen Dooks /* tran, valid */ 76254552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, align_addr, 76354552e49SJisheng Zhang offset, ADMA2_TRAN_VALID); 7642134a922SPierre Ossman 7652134a922SPierre Ossman BUG_ON(offset > 65536); 7662134a922SPierre Ossman 76704a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN; 76804a5ae6fSAdrian Hunter align_addr += SDHCI_ADMA2_ALIGN; 7692134a922SPierre Ossman 7702134a922SPierre Ossman addr += offset; 7712134a922SPierre Ossman len -= offset; 7722134a922SPierre Ossman } 7732134a922SPierre Ossman 7742134a922SPierre Ossman BUG_ON(len > 65536); 7752134a922SPierre Ossman 776118cd17dSBen Dooks /* tran, valid */ 77754552e49SJisheng Zhang if (len) 77854552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, addr, len, 779347ea32dSAdrian Hunter ADMA2_TRAN_VALID); 7802134a922SPierre Ossman 7812134a922SPierre Ossman /* 7822134a922SPierre Ossman * If this triggers then we have a calculation bug 7832134a922SPierre Ossman * somewhere. :/ 7842134a922SPierre Ossman */ 78576fe379aSAdrian Hunter WARN_ON((desc - host->adma_table) >= host->adma_table_sz); 7862134a922SPierre Ossman } 7872134a922SPierre Ossman 78870764a90SThomas Abraham if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { 789acc3ad13SRussell King /* Mark the last descriptor as the terminating descriptor */ 7904efaa6fbSAdrian Hunter if (desc != host->adma_table) { 79176fe379aSAdrian Hunter desc -= host->desc_sz; 792b5ffa674SAdrian Hunter sdhci_adma_mark_end(desc); 79370764a90SThomas Abraham } 79470764a90SThomas Abraham } else { 795acc3ad13SRussell King /* Add a terminating entry - nop, end, valid */ 79654552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, 0, 0, ADMA2_NOP_END_VALID); 79770764a90SThomas Abraham } 7982134a922SPierre Ossman } 7992134a922SPierre Ossman 8002134a922SPierre Ossman static void sdhci_adma_table_post(struct sdhci_host *host, 8012134a922SPierre Ossman struct mmc_data *data) 8022134a922SPierre Ossman { 8032134a922SPierre Ossman struct scatterlist *sg; 8042134a922SPierre Ossman int i, size; 8051c3d5f6dSAdrian Hunter void *align; 8062134a922SPierre Ossman char *buffer; 8072134a922SPierre Ossman unsigned long flags; 8082134a922SPierre Ossman 80947fa9613SRussell King if (data->flags & MMC_DATA_READ) { 81047fa9613SRussell King bool has_unaligned = false; 81147fa9613SRussell King 812de0b65a7SRussell King /* Do a quick scan of the SG list for any unaligned mappings */ 813de0b65a7SRussell King for_each_sg(data->sg, sg, host->sg_count, i) 81404a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { 815de0b65a7SRussell King has_unaligned = true; 816de0b65a7SRussell King break; 817de0b65a7SRussell King } 818de0b65a7SRussell King 81947fa9613SRussell King if (has_unaligned) { 8202134a922SPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 821f55c98f7SRussell King data->sg_len, DMA_FROM_DEVICE); 8222134a922SPierre Ossman 8232134a922SPierre Ossman align = host->align_buffer; 8242134a922SPierre Ossman 8252134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 82604a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { 82704a5ae6fSAdrian Hunter size = SDHCI_ADMA2_ALIGN - 82804a5ae6fSAdrian Hunter (sg_dma_address(sg) & SDHCI_ADMA2_MASK); 8292134a922SPierre Ossman 8302134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 8312134a922SPierre Ossman memcpy(buffer, align, size); 8322134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 8332134a922SPierre Ossman 83404a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN; 8352134a922SPierre Ossman } 8362134a922SPierre Ossman } 8372134a922SPierre Ossman } 83847fa9613SRussell King } 8392134a922SPierre Ossman } 8402134a922SPierre Ossman 84138eee2e8SMasahiro Yamada static void sdhci_set_adma_addr(struct sdhci_host *host, dma_addr_t addr) 84238eee2e8SMasahiro Yamada { 84338eee2e8SMasahiro Yamada sdhci_writel(host, lower_32_bits(addr), SDHCI_ADMA_ADDRESS); 84438eee2e8SMasahiro Yamada if (host->flags & SDHCI_USE_64_BIT_DMA) 84538eee2e8SMasahiro Yamada sdhci_writel(host, upper_32_bits(addr), SDHCI_ADMA_ADDRESS_HI); 84638eee2e8SMasahiro Yamada } 84738eee2e8SMasahiro Yamada 848917a0c52SChunyan Zhang static dma_addr_t sdhci_sdma_address(struct sdhci_host *host) 849bd9b9027SLinus Walleij { 850bd9b9027SLinus Walleij if (host->bounce_buffer) 851bd9b9027SLinus Walleij return host->bounce_addr; 852bd9b9027SLinus Walleij else 853bd9b9027SLinus Walleij return sg_dma_address(host->data->sg); 854bd9b9027SLinus Walleij } 855bd9b9027SLinus Walleij 856917a0c52SChunyan Zhang static void sdhci_set_sdma_addr(struct sdhci_host *host, dma_addr_t addr) 857917a0c52SChunyan Zhang { 85838eee2e8SMasahiro Yamada if (host->v4_mode) 85938eee2e8SMasahiro Yamada sdhci_set_adma_addr(host, addr); 86038eee2e8SMasahiro Yamada else 861917a0c52SChunyan Zhang sdhci_writel(host, addr, SDHCI_DMA_ADDRESS); 862917a0c52SChunyan Zhang } 863917a0c52SChunyan Zhang 8640bb28d73SAdrian Hunter static unsigned int sdhci_target_timeout(struct sdhci_host *host, 8650bb28d73SAdrian Hunter struct mmc_command *cmd, 8660bb28d73SAdrian Hunter struct mmc_data *data) 8670bb28d73SAdrian Hunter { 8680bb28d73SAdrian Hunter unsigned int target_timeout; 8690bb28d73SAdrian Hunter 8700bb28d73SAdrian Hunter /* timeout in us */ 8710bb28d73SAdrian Hunter if (!data) { 8720bb28d73SAdrian Hunter target_timeout = cmd->busy_timeout * 1000; 8730bb28d73SAdrian Hunter } else { 8740bb28d73SAdrian Hunter target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000); 8750bb28d73SAdrian Hunter if (host->clock && data->timeout_clks) { 8760bb28d73SAdrian Hunter unsigned long long val; 8770bb28d73SAdrian Hunter 8780bb28d73SAdrian Hunter /* 8790bb28d73SAdrian Hunter * data->timeout_clks is in units of clock cycles. 8800bb28d73SAdrian Hunter * host->clock is in Hz. target_timeout is in us. 8810bb28d73SAdrian Hunter * Hence, us = 1000000 * cycles / Hz. Round up. 8820bb28d73SAdrian Hunter */ 8830bb28d73SAdrian Hunter val = 1000000ULL * data->timeout_clks; 8840bb28d73SAdrian Hunter if (do_div(val, host->clock)) 8850bb28d73SAdrian Hunter target_timeout++; 8860bb28d73SAdrian Hunter target_timeout += val; 8870bb28d73SAdrian Hunter } 8880bb28d73SAdrian Hunter } 8890bb28d73SAdrian Hunter 8900bb28d73SAdrian Hunter return target_timeout; 8910bb28d73SAdrian Hunter } 8920bb28d73SAdrian Hunter 893fc1fa1b7SKishon Vijay Abraham I static void sdhci_calc_sw_timeout(struct sdhci_host *host, 894fc1fa1b7SKishon Vijay Abraham I struct mmc_command *cmd) 895fc1fa1b7SKishon Vijay Abraham I { 896fc1fa1b7SKishon Vijay Abraham I struct mmc_data *data = cmd->data; 897fc1fa1b7SKishon Vijay Abraham I struct mmc_host *mmc = host->mmc; 898fc1fa1b7SKishon Vijay Abraham I struct mmc_ios *ios = &mmc->ios; 899fc1fa1b7SKishon Vijay Abraham I unsigned char bus_width = 1 << ios->bus_width; 900fc1fa1b7SKishon Vijay Abraham I unsigned int blksz; 901fc1fa1b7SKishon Vijay Abraham I unsigned int freq; 902fc1fa1b7SKishon Vijay Abraham I u64 target_timeout; 903fc1fa1b7SKishon Vijay Abraham I u64 transfer_time; 904fc1fa1b7SKishon Vijay Abraham I 905fc1fa1b7SKishon Vijay Abraham I target_timeout = sdhci_target_timeout(host, cmd, data); 906fc1fa1b7SKishon Vijay Abraham I target_timeout *= NSEC_PER_USEC; 907fc1fa1b7SKishon Vijay Abraham I 908fc1fa1b7SKishon Vijay Abraham I if (data) { 909fc1fa1b7SKishon Vijay Abraham I blksz = data->blksz; 910fc1fa1b7SKishon Vijay Abraham I freq = host->mmc->actual_clock ? : host->clock; 911fc1fa1b7SKishon Vijay Abraham I transfer_time = (u64)blksz * NSEC_PER_SEC * (8 / bus_width); 912fc1fa1b7SKishon Vijay Abraham I do_div(transfer_time, freq); 913fc1fa1b7SKishon Vijay Abraham I /* multiply by '2' to account for any unknowns */ 914fc1fa1b7SKishon Vijay Abraham I transfer_time = transfer_time * 2; 915fc1fa1b7SKishon Vijay Abraham I /* calculate timeout for the entire data */ 916fc1fa1b7SKishon Vijay Abraham I host->data_timeout = data->blocks * target_timeout + 917fc1fa1b7SKishon Vijay Abraham I transfer_time; 918fc1fa1b7SKishon Vijay Abraham I } else { 919fc1fa1b7SKishon Vijay Abraham I host->data_timeout = target_timeout; 920fc1fa1b7SKishon Vijay Abraham I } 921fc1fa1b7SKishon Vijay Abraham I 922fc1fa1b7SKishon Vijay Abraham I if (host->data_timeout) 923fc1fa1b7SKishon Vijay Abraham I host->data_timeout += MMC_CMD_TRANSFER_TIME; 924fc1fa1b7SKishon Vijay Abraham I } 925fc1fa1b7SKishon Vijay Abraham I 926a999fd93SAdrian Hunter static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd, 927a999fd93SAdrian Hunter bool *too_big) 9281c6a0718SPierre Ossman { 9291c6a0718SPierre Ossman u8 count; 930401059dfSBOUGH CHEN struct mmc_data *data; 9311c6a0718SPierre Ossman unsigned target_timeout, current_timeout; 9321c6a0718SPierre Ossman 933a999fd93SAdrian Hunter *too_big = true; 934a999fd93SAdrian Hunter 935ee53ab5dSPierre Ossman /* 936ee53ab5dSPierre Ossman * If the host controller provides us with an incorrect timeout 937ee53ab5dSPierre Ossman * value, just skip the check and use 0xE. The hardware may take 938ee53ab5dSPierre Ossman * longer to time out, but that's much better than having a too-short 939ee53ab5dSPierre Ossman * timeout value. 940ee53ab5dSPierre Ossman */ 94111a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) 942ee53ab5dSPierre Ossman return 0xE; 943e538fbe8SPierre Ossman 944401059dfSBOUGH CHEN /* Unspecified command, asume max */ 945401059dfSBOUGH CHEN if (cmd == NULL) 946401059dfSBOUGH CHEN return 0xE; 947401059dfSBOUGH CHEN 948401059dfSBOUGH CHEN data = cmd->data; 949a3c7778fSAndrei Warkentin /* Unspecified timeout, assume max */ 9501d4d7744SUlf Hansson if (!data && !cmd->busy_timeout) 951a3c7778fSAndrei Warkentin return 0xE; 952a3c7778fSAndrei Warkentin 9531c6a0718SPierre Ossman /* timeout in us */ 9540bb28d73SAdrian Hunter target_timeout = sdhci_target_timeout(host, cmd, data); 9551c6a0718SPierre Ossman 9561c6a0718SPierre Ossman /* 9571c6a0718SPierre Ossman * Figure out needed cycles. 9581c6a0718SPierre Ossman * We do this in steps in order to fit inside a 32 bit int. 9591c6a0718SPierre Ossman * The first step is the minimum timeout, which will have a 9601c6a0718SPierre Ossman * minimum resolution of 6 bits: 9611c6a0718SPierre Ossman * (1) 2^13*1000 > 2^22, 9621c6a0718SPierre Ossman * (2) host->timeout_clk < 2^16 9631c6a0718SPierre Ossman * => 9641c6a0718SPierre Ossman * (1) / (2) > 2^6 9651c6a0718SPierre Ossman */ 9661c6a0718SPierre Ossman count = 0; 9671c6a0718SPierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 9681c6a0718SPierre Ossman while (current_timeout < target_timeout) { 9691c6a0718SPierre Ossman count++; 9701c6a0718SPierre Ossman current_timeout <<= 1; 9711c6a0718SPierre Ossman if (count >= 0xF) 9721c6a0718SPierre Ossman break; 9731c6a0718SPierre Ossman } 9741c6a0718SPierre Ossman 9751c6a0718SPierre Ossman if (count >= 0xF) { 976a999fd93SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT)) 977f421865dSAdrian Hunter DBG("Too large timeout 0x%x requested for CMD%d!\n", 978f421865dSAdrian Hunter count, cmd->opcode); 9791c6a0718SPierre Ossman count = 0xE; 980a999fd93SAdrian Hunter } else { 981a999fd93SAdrian Hunter *too_big = false; 9821c6a0718SPierre Ossman } 9831c6a0718SPierre Ossman 984ee53ab5dSPierre Ossman return count; 985ee53ab5dSPierre Ossman } 986ee53ab5dSPierre Ossman 9876aa943abSAnton Vorontsov static void sdhci_set_transfer_irqs(struct sdhci_host *host) 9886aa943abSAnton Vorontsov { 9896aa943abSAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 9906aa943abSAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; 9916aa943abSAnton Vorontsov 9926aa943abSAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA) 993b537f94cSRussell King host->ier = (host->ier & ~pio_irqs) | dma_irqs; 9946aa943abSAnton Vorontsov else 995b537f94cSRussell King host->ier = (host->ier & ~dma_irqs) | pio_irqs; 996b537f94cSRussell King 997af849c86SAdrian Hunter if (host->flags & (SDHCI_AUTO_CMD23 | SDHCI_AUTO_CMD12)) 998af849c86SAdrian Hunter host->ier |= SDHCI_INT_AUTO_CMD_ERR; 999af849c86SAdrian Hunter else 1000af849c86SAdrian Hunter host->ier &= ~SDHCI_INT_AUTO_CMD_ERR; 1001af849c86SAdrian Hunter 1002b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 1003b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 10046aa943abSAnton Vorontsov } 10056aa943abSAnton Vorontsov 10067907ebe7SFaiz Abbas void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable) 1007a999fd93SAdrian Hunter { 1008a999fd93SAdrian Hunter if (enable) 1009a999fd93SAdrian Hunter host->ier |= SDHCI_INT_DATA_TIMEOUT; 1010a999fd93SAdrian Hunter else 1011a999fd93SAdrian Hunter host->ier &= ~SDHCI_INT_DATA_TIMEOUT; 1012a999fd93SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 1013a999fd93SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 1014a999fd93SAdrian Hunter } 10157907ebe7SFaiz Abbas EXPORT_SYMBOL_GPL(sdhci_set_data_timeout_irq); 1016a999fd93SAdrian Hunter 10177d76ed77SFaiz Abbas void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) 1018ee53ab5dSPierre Ossman { 1019a999fd93SAdrian Hunter bool too_big = false; 10207d76ed77SFaiz Abbas u8 count = sdhci_calc_timeout(host, cmd, &too_big); 1021a999fd93SAdrian Hunter 1022a999fd93SAdrian Hunter if (too_big && 1023a999fd93SAdrian Hunter host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) { 1024fc1fa1b7SKishon Vijay Abraham I sdhci_calc_sw_timeout(host, cmd); 1025a999fd93SAdrian Hunter sdhci_set_data_timeout_irq(host, false); 1026a999fd93SAdrian Hunter } else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT)) { 1027a999fd93SAdrian Hunter sdhci_set_data_timeout_irq(host, true); 1028a999fd93SAdrian Hunter } 1029a999fd93SAdrian Hunter 1030b45e668aSAisheng Dong sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); 1031b45e668aSAisheng Dong } 10327d76ed77SFaiz Abbas EXPORT_SYMBOL_GPL(__sdhci_set_timeout); 10337d76ed77SFaiz Abbas 10347d76ed77SFaiz Abbas static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) 10357d76ed77SFaiz Abbas { 10367d76ed77SFaiz Abbas if (host->ops->set_timeout) 10377d76ed77SFaiz Abbas host->ops->set_timeout(host, cmd); 10387d76ed77SFaiz Abbas else 10397d76ed77SFaiz Abbas __sdhci_set_timeout(host, cmd); 1040b45e668aSAisheng Dong } 1041b45e668aSAisheng Dong 104215db1836SFaiz Abbas static void sdhci_initialize_data(struct sdhci_host *host, 104315db1836SFaiz Abbas struct mmc_data *data) 1044b45e668aSAisheng Dong { 104543dea098SAdrian Hunter WARN_ON(host->data); 104643dea098SAdrian Hunter 1047ee53ab5dSPierre Ossman /* Sanity checks */ 1048ee53ab5dSPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 1049ee53ab5dSPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 1050ee53ab5dSPierre Ossman BUG_ON(data->blocks > 65535); 1051ee53ab5dSPierre Ossman 1052ee53ab5dSPierre Ossman host->data = data; 1053ee53ab5dSPierre Ossman host->data_early = 0; 1054f6a03cbfSMikko Vinni host->data->bytes_xfered = 0; 105515db1836SFaiz Abbas } 105615db1836SFaiz Abbas 105715db1836SFaiz Abbas static inline void sdhci_set_block_info(struct sdhci_host *host, 105815db1836SFaiz Abbas struct mmc_data *data) 105915db1836SFaiz Abbas { 106015db1836SFaiz Abbas /* Set the DMA boundary value and block size */ 106115db1836SFaiz Abbas sdhci_writew(host, 106215db1836SFaiz Abbas SDHCI_MAKE_BLKSZ(host->sdma_boundary, data->blksz), 106315db1836SFaiz Abbas SDHCI_BLOCK_SIZE); 106415db1836SFaiz Abbas /* 106515db1836SFaiz Abbas * For Version 4.10 onwards, if v4 mode is enabled, 32-bit Block Count 106615db1836SFaiz Abbas * can be supported, in that case 16-bit block count register must be 0. 106715db1836SFaiz Abbas */ 106815db1836SFaiz Abbas if (host->version >= SDHCI_SPEC_410 && host->v4_mode && 106915db1836SFaiz Abbas (host->quirks2 & SDHCI_QUIRK2_USE_32BIT_BLK_CNT)) { 107015db1836SFaiz Abbas if (sdhci_readw(host, SDHCI_BLOCK_COUNT)) 107115db1836SFaiz Abbas sdhci_writew(host, 0, SDHCI_BLOCK_COUNT); 107215db1836SFaiz Abbas sdhci_writew(host, data->blocks, SDHCI_32BIT_BLK_CNT); 107315db1836SFaiz Abbas } else { 107415db1836SFaiz Abbas sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); 107515db1836SFaiz Abbas } 107615db1836SFaiz Abbas } 107715db1836SFaiz Abbas 107815db1836SFaiz Abbas static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) 107915db1836SFaiz Abbas { 108015db1836SFaiz Abbas struct mmc_data *data = cmd->data; 108115db1836SFaiz Abbas 108215db1836SFaiz Abbas sdhci_initialize_data(host, data); 1083ee53ab5dSPierre Ossman 1084fce14421SRussell King if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 1085fce14421SRussell King struct scatterlist *sg; 1086fce14421SRussell King unsigned int length_mask, offset_mask; 1087fce14421SRussell King int i; 1088fce14421SRussell King 1089c9fddbc4SPierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 1090c9fddbc4SPierre Ossman 10912134a922SPierre Ossman /* 10922134a922SPierre Ossman * FIXME: This doesn't account for merging when mapping the 10932134a922SPierre Ossman * scatterlist. 1094df953925SRussell King * 1095df953925SRussell King * The assumption here being that alignment and lengths are 1096df953925SRussell King * the same after DMA mapping to device address space. 10972134a922SPierre Ossman */ 1098a0eaf0f9SRussell King length_mask = 0; 1099df953925SRussell King offset_mask = 0; 11002134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 1101df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) { 1102a0eaf0f9SRussell King length_mask = 3; 1103df953925SRussell King /* 1104df953925SRussell King * As we use up to 3 byte chunks to work 1105df953925SRussell King * around alignment problems, we need to 1106df953925SRussell King * check the offset as well. 1107df953925SRussell King */ 1108df953925SRussell King offset_mask = 3; 1109df953925SRussell King } 11102134a922SPierre Ossman } else { 11112134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 1112a0eaf0f9SRussell King length_mask = 3; 1113df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 1114df953925SRussell King offset_mask = 3; 11152134a922SPierre Ossman } 11162134a922SPierre Ossman 1117df953925SRussell King if (unlikely(length_mask | offset_mask)) { 11182134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 1119a0eaf0f9SRussell King if (sg->length & length_mask) { 11202e4456f0SMarek Vasut DBG("Reverting to PIO because of transfer size (%d)\n", 11212134a922SPierre Ossman sg->length); 1122c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 11232134a922SPierre Ossman break; 11242134a922SPierre Ossman } 1125a0eaf0f9SRussell King if (sg->offset & offset_mask) { 11262e4456f0SMarek Vasut DBG("Reverting to PIO because of bad alignment\n"); 1127c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 11282134a922SPierre Ossman break; 11292134a922SPierre Ossman } 11302134a922SPierre Ossman } 11312134a922SPierre Ossman } 11322134a922SPierre Ossman } 11332134a922SPierre Ossman 11348f1934ceSPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 1135c0999b72SRussell King int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); 11368f1934ceSPierre Ossman 113762a7f368SJiri Slaby if (sg_cnt <= 0) { 11388f1934ceSPierre Ossman /* 11398f1934ceSPierre Ossman * This only happens when someone fed 11408f1934ceSPierre Ossman * us an invalid request. 11418f1934ceSPierre Ossman */ 11428f1934ceSPierre Ossman WARN_ON(1); 1143ebd6d357SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 114460c64762SRussell King } else if (host->flags & SDHCI_USE_ADMA) { 114560c64762SRussell King sdhci_adma_table_pre(host, data, sg_cnt); 114638eee2e8SMasahiro Yamada sdhci_set_adma_addr(host, host->adma_addr); 11478f1934ceSPierre Ossman } else { 1148719a61b4SPierre Ossman WARN_ON(sg_cnt != 1); 1149917a0c52SChunyan Zhang sdhci_set_sdma_addr(host, sdhci_sdma_address(host)); 11508f1934ceSPierre Ossman } 11518f1934ceSPierre Ossman } 11528f1934ceSPierre Ossman 1153685e444bSChunyan Zhang sdhci_config_dma(host); 1154c9fddbc4SPierre Ossman 11558f1934ceSPierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 1156da60a91dSSebastian Andrzej Siewior int flags; 1157da60a91dSSebastian Andrzej Siewior 1158da60a91dSSebastian Andrzej Siewior flags = SG_MITER_ATOMIC; 1159da60a91dSSebastian Andrzej Siewior if (host->data->flags & MMC_DATA_READ) 1160da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_TO_SG; 1161da60a91dSSebastian Andrzej Siewior else 1162da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_FROM_SG; 1163da60a91dSSebastian Andrzej Siewior sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 11647659150cSPierre Ossman host->blocks = data->blocks; 11651c6a0718SPierre Ossman } 11661c6a0718SPierre Ossman 11676aa943abSAnton Vorontsov sdhci_set_transfer_irqs(host); 11686aa943abSAnton Vorontsov 116915db1836SFaiz Abbas sdhci_set_block_info(host, data); 1170e65953d4SChunyan Zhang } 11711c6a0718SPierre Ossman 117218e762e3SChunyan Zhang #if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA) 117318e762e3SChunyan Zhang 117418e762e3SChunyan Zhang static int sdhci_external_dma_init(struct sdhci_host *host) 117518e762e3SChunyan Zhang { 117618e762e3SChunyan Zhang int ret = 0; 117718e762e3SChunyan Zhang struct mmc_host *mmc = host->mmc; 117818e762e3SChunyan Zhang 117918e762e3SChunyan Zhang host->tx_chan = dma_request_chan(mmc->parent, "tx"); 118018e762e3SChunyan Zhang if (IS_ERR(host->tx_chan)) { 118118e762e3SChunyan Zhang ret = PTR_ERR(host->tx_chan); 118218e762e3SChunyan Zhang if (ret != -EPROBE_DEFER) 118318e762e3SChunyan Zhang pr_warn("Failed to request TX DMA channel.\n"); 118418e762e3SChunyan Zhang host->tx_chan = NULL; 118518e762e3SChunyan Zhang return ret; 118618e762e3SChunyan Zhang } 118718e762e3SChunyan Zhang 118818e762e3SChunyan Zhang host->rx_chan = dma_request_chan(mmc->parent, "rx"); 118918e762e3SChunyan Zhang if (IS_ERR(host->rx_chan)) { 119018e762e3SChunyan Zhang if (host->tx_chan) { 119118e762e3SChunyan Zhang dma_release_channel(host->tx_chan); 119218e762e3SChunyan Zhang host->tx_chan = NULL; 119318e762e3SChunyan Zhang } 119418e762e3SChunyan Zhang 119518e762e3SChunyan Zhang ret = PTR_ERR(host->rx_chan); 119618e762e3SChunyan Zhang if (ret != -EPROBE_DEFER) 119718e762e3SChunyan Zhang pr_warn("Failed to request RX DMA channel.\n"); 119818e762e3SChunyan Zhang host->rx_chan = NULL; 119918e762e3SChunyan Zhang } 120018e762e3SChunyan Zhang 120118e762e3SChunyan Zhang return ret; 120218e762e3SChunyan Zhang } 120318e762e3SChunyan Zhang 120418e762e3SChunyan Zhang static struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, 120518e762e3SChunyan Zhang struct mmc_data *data) 120618e762e3SChunyan Zhang { 120718e762e3SChunyan Zhang return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan; 120818e762e3SChunyan Zhang } 120918e762e3SChunyan Zhang 121018e762e3SChunyan Zhang static int sdhci_external_dma_setup(struct sdhci_host *host, 121118e762e3SChunyan Zhang struct mmc_command *cmd) 121218e762e3SChunyan Zhang { 121318e762e3SChunyan Zhang int ret, i; 12141215c025SChunyan Zhang enum dma_transfer_direction dir; 121518e762e3SChunyan Zhang struct dma_async_tx_descriptor *desc; 121618e762e3SChunyan Zhang struct mmc_data *data = cmd->data; 121718e762e3SChunyan Zhang struct dma_chan *chan; 121818e762e3SChunyan Zhang struct dma_slave_config cfg; 121918e762e3SChunyan Zhang dma_cookie_t cookie; 122018e762e3SChunyan Zhang int sg_cnt; 122118e762e3SChunyan Zhang 122218e762e3SChunyan Zhang if (!host->mapbase) 122318e762e3SChunyan Zhang return -EINVAL; 122418e762e3SChunyan Zhang 122518e762e3SChunyan Zhang cfg.src_addr = host->mapbase + SDHCI_BUFFER; 122618e762e3SChunyan Zhang cfg.dst_addr = host->mapbase + SDHCI_BUFFER; 122718e762e3SChunyan Zhang cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 122818e762e3SChunyan Zhang cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 122918e762e3SChunyan Zhang cfg.src_maxburst = data->blksz / 4; 123018e762e3SChunyan Zhang cfg.dst_maxburst = data->blksz / 4; 123118e762e3SChunyan Zhang 123218e762e3SChunyan Zhang /* Sanity check: all the SG entries must be aligned by block size. */ 123318e762e3SChunyan Zhang for (i = 0; i < data->sg_len; i++) { 123418e762e3SChunyan Zhang if ((data->sg + i)->length % data->blksz) 123518e762e3SChunyan Zhang return -EINVAL; 123618e762e3SChunyan Zhang } 123718e762e3SChunyan Zhang 123818e762e3SChunyan Zhang chan = sdhci_external_dma_channel(host, data); 123918e762e3SChunyan Zhang 124018e762e3SChunyan Zhang ret = dmaengine_slave_config(chan, &cfg); 124118e762e3SChunyan Zhang if (ret) 124218e762e3SChunyan Zhang return ret; 124318e762e3SChunyan Zhang 124418e762e3SChunyan Zhang sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); 124518e762e3SChunyan Zhang if (sg_cnt <= 0) 124618e762e3SChunyan Zhang return -EINVAL; 124718e762e3SChunyan Zhang 12481215c025SChunyan Zhang dir = data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; 12491215c025SChunyan Zhang desc = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len, dir, 125018e762e3SChunyan Zhang DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 125118e762e3SChunyan Zhang if (!desc) 125218e762e3SChunyan Zhang return -EINVAL; 125318e762e3SChunyan Zhang 125418e762e3SChunyan Zhang desc->callback = NULL; 125518e762e3SChunyan Zhang desc->callback_param = NULL; 125618e762e3SChunyan Zhang 125718e762e3SChunyan Zhang cookie = dmaengine_submit(desc); 125818e762e3SChunyan Zhang if (dma_submit_error(cookie)) 125918e762e3SChunyan Zhang ret = cookie; 126018e762e3SChunyan Zhang 126118e762e3SChunyan Zhang return ret; 126218e762e3SChunyan Zhang } 126318e762e3SChunyan Zhang 126418e762e3SChunyan Zhang static void sdhci_external_dma_release(struct sdhci_host *host) 126518e762e3SChunyan Zhang { 126618e762e3SChunyan Zhang if (host->tx_chan) { 126718e762e3SChunyan Zhang dma_release_channel(host->tx_chan); 126818e762e3SChunyan Zhang host->tx_chan = NULL; 126918e762e3SChunyan Zhang } 127018e762e3SChunyan Zhang 127118e762e3SChunyan Zhang if (host->rx_chan) { 127218e762e3SChunyan Zhang dma_release_channel(host->rx_chan); 127318e762e3SChunyan Zhang host->rx_chan = NULL; 127418e762e3SChunyan Zhang } 127518e762e3SChunyan Zhang 127618e762e3SChunyan Zhang sdhci_switch_external_dma(host, false); 127718e762e3SChunyan Zhang } 127818e762e3SChunyan Zhang 127918e762e3SChunyan Zhang static void __sdhci_external_dma_prepare_data(struct sdhci_host *host, 128018e762e3SChunyan Zhang struct mmc_command *cmd) 128118e762e3SChunyan Zhang { 128218e762e3SChunyan Zhang struct mmc_data *data = cmd->data; 128318e762e3SChunyan Zhang 128418e762e3SChunyan Zhang sdhci_initialize_data(host, data); 128518e762e3SChunyan Zhang 128618e762e3SChunyan Zhang host->flags |= SDHCI_REQ_USE_DMA; 128718e762e3SChunyan Zhang sdhci_set_transfer_irqs(host); 128818e762e3SChunyan Zhang 128918e762e3SChunyan Zhang sdhci_set_block_info(host, data); 129018e762e3SChunyan Zhang } 129118e762e3SChunyan Zhang 129218e762e3SChunyan Zhang static void sdhci_external_dma_prepare_data(struct sdhci_host *host, 129318e762e3SChunyan Zhang struct mmc_command *cmd) 129418e762e3SChunyan Zhang { 129518e762e3SChunyan Zhang if (!sdhci_external_dma_setup(host, cmd)) { 129618e762e3SChunyan Zhang __sdhci_external_dma_prepare_data(host, cmd); 129718e762e3SChunyan Zhang } else { 129818e762e3SChunyan Zhang sdhci_external_dma_release(host); 129918e762e3SChunyan Zhang pr_err("%s: Cannot use external DMA, switch to the DMA/PIO which standard SDHCI provides.\n", 130018e762e3SChunyan Zhang mmc_hostname(host->mmc)); 130118e762e3SChunyan Zhang sdhci_prepare_data(host, cmd); 130218e762e3SChunyan Zhang } 130318e762e3SChunyan Zhang } 130418e762e3SChunyan Zhang 130518e762e3SChunyan Zhang static void sdhci_external_dma_pre_transfer(struct sdhci_host *host, 130618e762e3SChunyan Zhang struct mmc_command *cmd) 130718e762e3SChunyan Zhang { 130818e762e3SChunyan Zhang struct dma_chan *chan; 130918e762e3SChunyan Zhang 131018e762e3SChunyan Zhang if (!cmd->data) 131118e762e3SChunyan Zhang return; 131218e762e3SChunyan Zhang 131318e762e3SChunyan Zhang chan = sdhci_external_dma_channel(host, cmd->data); 131418e762e3SChunyan Zhang if (chan) 131518e762e3SChunyan Zhang dma_async_issue_pending(chan); 131618e762e3SChunyan Zhang } 131718e762e3SChunyan Zhang 131818e762e3SChunyan Zhang #else 131918e762e3SChunyan Zhang 132018e762e3SChunyan Zhang static inline int sdhci_external_dma_init(struct sdhci_host *host) 132118e762e3SChunyan Zhang { 132218e762e3SChunyan Zhang return -EOPNOTSUPP; 132318e762e3SChunyan Zhang } 132418e762e3SChunyan Zhang 132518e762e3SChunyan Zhang static inline void sdhci_external_dma_release(struct sdhci_host *host) 132618e762e3SChunyan Zhang { 132718e762e3SChunyan Zhang } 132818e762e3SChunyan Zhang 132918e762e3SChunyan Zhang static inline void sdhci_external_dma_prepare_data(struct sdhci_host *host, 133018e762e3SChunyan Zhang struct mmc_command *cmd) 133118e762e3SChunyan Zhang { 133218e762e3SChunyan Zhang /* This should never happen */ 133318e762e3SChunyan Zhang WARN_ON_ONCE(1); 133418e762e3SChunyan Zhang } 133518e762e3SChunyan Zhang 133618e762e3SChunyan Zhang static inline void sdhci_external_dma_pre_transfer(struct sdhci_host *host, 133718e762e3SChunyan Zhang struct mmc_command *cmd) 133818e762e3SChunyan Zhang { 133918e762e3SChunyan Zhang } 134018e762e3SChunyan Zhang 134118e762e3SChunyan Zhang static inline struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, 134218e762e3SChunyan Zhang struct mmc_data *data) 134318e762e3SChunyan Zhang { 134418e762e3SChunyan Zhang return NULL; 134518e762e3SChunyan Zhang } 134618e762e3SChunyan Zhang 134718e762e3SChunyan Zhang #endif 134818e762e3SChunyan Zhang 134918e762e3SChunyan Zhang void sdhci_switch_external_dma(struct sdhci_host *host, bool en) 135018e762e3SChunyan Zhang { 135118e762e3SChunyan Zhang host->use_external_dma = en; 135218e762e3SChunyan Zhang } 135318e762e3SChunyan Zhang EXPORT_SYMBOL_GPL(sdhci_switch_external_dma); 135418e762e3SChunyan Zhang 13550293d501SAdrian Hunter static inline bool sdhci_auto_cmd12(struct sdhci_host *host, 13560293d501SAdrian Hunter struct mmc_request *mrq) 13570293d501SAdrian Hunter { 135820845befSAdrian Hunter return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) && 135920845befSAdrian Hunter !mrq->cap_cmd_during_tfr; 13600293d501SAdrian Hunter } 13610293d501SAdrian Hunter 1362ed633033SAdrian Hunter static inline bool sdhci_auto_cmd23(struct sdhci_host *host, 1363ed633033SAdrian Hunter struct mmc_request *mrq) 1364ed633033SAdrian Hunter { 1365ed633033SAdrian Hunter return mrq->sbc && (host->flags & SDHCI_AUTO_CMD23); 1366ed633033SAdrian Hunter } 1367ed633033SAdrian Hunter 1368ed633033SAdrian Hunter static inline bool sdhci_manual_cmd23(struct sdhci_host *host, 1369ed633033SAdrian Hunter struct mmc_request *mrq) 1370ed633033SAdrian Hunter { 1371ed633033SAdrian Hunter return mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23); 1372ed633033SAdrian Hunter } 1373ed633033SAdrian Hunter 1374427b6514SChunyan Zhang static inline void sdhci_auto_cmd_select(struct sdhci_host *host, 1375427b6514SChunyan Zhang struct mmc_command *cmd, 1376427b6514SChunyan Zhang u16 *mode) 1377427b6514SChunyan Zhang { 1378427b6514SChunyan Zhang bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) && 1379427b6514SChunyan Zhang (cmd->opcode != SD_IO_RW_EXTENDED); 1380ed633033SAdrian Hunter bool use_cmd23 = sdhci_auto_cmd23(host, cmd->mrq); 1381427b6514SChunyan Zhang u16 ctrl2; 1382427b6514SChunyan Zhang 1383427b6514SChunyan Zhang /* 1384427b6514SChunyan Zhang * In case of Version 4.10 or later, use of 'Auto CMD Auto 1385427b6514SChunyan Zhang * Select' is recommended rather than use of 'Auto CMD12 1386b3e1ea16SJisheng Zhang * Enable' or 'Auto CMD23 Enable'. We require Version 4 Mode 1387b3e1ea16SJisheng Zhang * here because some controllers (e.g sdhci-of-dwmshc) expect it. 1388427b6514SChunyan Zhang */ 1389b3e1ea16SJisheng Zhang if (host->version >= SDHCI_SPEC_410 && host->v4_mode && 1390b3e1ea16SJisheng Zhang (use_cmd12 || use_cmd23)) { 1391427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_SEL; 1392427b6514SChunyan Zhang 1393427b6514SChunyan Zhang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1394427b6514SChunyan Zhang if (use_cmd23) 1395427b6514SChunyan Zhang ctrl2 |= SDHCI_CMD23_ENABLE; 1396427b6514SChunyan Zhang else 1397427b6514SChunyan Zhang ctrl2 &= ~SDHCI_CMD23_ENABLE; 1398427b6514SChunyan Zhang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 1399427b6514SChunyan Zhang 1400427b6514SChunyan Zhang return; 1401427b6514SChunyan Zhang } 1402427b6514SChunyan Zhang 1403427b6514SChunyan Zhang /* 1404427b6514SChunyan Zhang * If we are sending CMD23, CMD12 never gets sent 1405427b6514SChunyan Zhang * on successful completion (so no Auto-CMD12). 1406427b6514SChunyan Zhang */ 1407427b6514SChunyan Zhang if (use_cmd12) 1408427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_CMD12; 1409427b6514SChunyan Zhang else if (use_cmd23) 1410427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_CMD23; 1411427b6514SChunyan Zhang } 1412427b6514SChunyan Zhang 14131c6a0718SPierre Ossman static void sdhci_set_transfer_mode(struct sdhci_host *host, 1414e89d456fSAndrei Warkentin struct mmc_command *cmd) 14151c6a0718SPierre Ossman { 1416d3fc5d71SVincent Yang u16 mode = 0; 1417e89d456fSAndrei Warkentin struct mmc_data *data = cmd->data; 14181c6a0718SPierre Ossman 14192b558c13SDong Aisheng if (data == NULL) { 14209b8ffea6SVincent Wan if (host->quirks2 & 14219b8ffea6SVincent Wan SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) { 14220086fc21Sernest.zhang /* must not clear SDHCI_TRANSFER_MODE when tuning */ 14230086fc21Sernest.zhang if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) 14249b8ffea6SVincent Wan sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); 14259b8ffea6SVincent Wan } else { 14262b558c13SDong Aisheng /* clear Auto CMD settings for no data CMDs */ 14272b558c13SDong Aisheng mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); 14282b558c13SDong Aisheng sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | 14292b558c13SDong Aisheng SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); 14309b8ffea6SVincent Wan } 14311c6a0718SPierre Ossman return; 14322b558c13SDong Aisheng } 14331c6a0718SPierre Ossman 1434e538fbe8SPierre Ossman WARN_ON(!host->data); 1435e538fbe8SPierre Ossman 1436d3fc5d71SVincent Yang if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE)) 14371c6a0718SPierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 1438d3fc5d71SVincent Yang 1439e89d456fSAndrei Warkentin if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { 1440d3fc5d71SVincent Yang mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI; 1441427b6514SChunyan Zhang sdhci_auto_cmd_select(host, cmd, &mode); 1442ed633033SAdrian Hunter if (sdhci_auto_cmd23(host, cmd->mrq)) 1443a4c73abaSAdrian Hunter sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2); 1444c4512f79SJerry Huang } 14458edf6371SAndrei Warkentin 14461c6a0718SPierre Ossman if (data->flags & MMC_DATA_READ) 14471c6a0718SPierre Ossman mode |= SDHCI_TRNS_READ; 1448c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 14491c6a0718SPierre Ossman mode |= SDHCI_TRNS_DMA; 14501c6a0718SPierre Ossman 14514e4141a5SAnton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); 14521c6a0718SPierre Ossman } 14531c6a0718SPierre Ossman 14540cc563ceSAdrian Hunter static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) 14550cc563ceSAdrian Hunter { 14560cc563ceSAdrian Hunter return (!(host->flags & SDHCI_DEVICE_DEAD) && 14570cc563ceSAdrian Hunter ((mrq->cmd && mrq->cmd->error) || 14580cc563ceSAdrian Hunter (mrq->sbc && mrq->sbc->error) || 14594bf78099SAdrian Hunter (mrq->data && mrq->data->stop && mrq->data->stop->error) || 14600cc563ceSAdrian Hunter (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))); 14610cc563ceSAdrian Hunter } 14620cc563ceSAdrian Hunter 146315db1836SFaiz Abbas static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq) 14644e9f8fe5SAdrian Hunter { 14654e9f8fe5SAdrian Hunter int i; 14664e9f8fe5SAdrian Hunter 14674e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 14684e9f8fe5SAdrian Hunter if (host->mrqs_done[i] == mrq) { 14694e9f8fe5SAdrian Hunter WARN_ON(1); 14704e9f8fe5SAdrian Hunter return; 14714e9f8fe5SAdrian Hunter } 14724e9f8fe5SAdrian Hunter } 14734e9f8fe5SAdrian Hunter 14744e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 14754e9f8fe5SAdrian Hunter if (!host->mrqs_done[i]) { 14764e9f8fe5SAdrian Hunter host->mrqs_done[i] = mrq; 14774e9f8fe5SAdrian Hunter break; 14784e9f8fe5SAdrian Hunter } 14794e9f8fe5SAdrian Hunter } 14804e9f8fe5SAdrian Hunter 14814e9f8fe5SAdrian Hunter WARN_ON(i >= SDHCI_MAX_MRQS); 148215db1836SFaiz Abbas } 148315db1836SFaiz Abbas 148415db1836SFaiz Abbas static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) 148515db1836SFaiz Abbas { 148615db1836SFaiz Abbas if (host->cmd && host->cmd->mrq == mrq) 148715db1836SFaiz Abbas host->cmd = NULL; 148815db1836SFaiz Abbas 148915db1836SFaiz Abbas if (host->data_cmd && host->data_cmd->mrq == mrq) 149015db1836SFaiz Abbas host->data_cmd = NULL; 149115db1836SFaiz Abbas 1492845c939eSAdrian Hunter if (host->deferred_cmd && host->deferred_cmd->mrq == mrq) 1493845c939eSAdrian Hunter host->deferred_cmd = NULL; 1494845c939eSAdrian Hunter 149515db1836SFaiz Abbas if (host->data && host->data->mrq == mrq) 149615db1836SFaiz Abbas host->data = NULL; 149715db1836SFaiz Abbas 149815db1836SFaiz Abbas if (sdhci_needs_reset(host, mrq)) 149915db1836SFaiz Abbas host->pending_reset = true; 150015db1836SFaiz Abbas 150115db1836SFaiz Abbas sdhci_set_mrq_done(host, mrq); 15024e9f8fe5SAdrian Hunter 1503e9a07299SAdrian Hunter sdhci_del_timer(host, mrq); 1504e9a07299SAdrian Hunter 1505e9a07299SAdrian Hunter if (!sdhci_has_requests(host)) 1506e9a07299SAdrian Hunter sdhci_led_deactivate(host); 15074e9f8fe5SAdrian Hunter } 15084e9f8fe5SAdrian Hunter 1509a6d3bdd5SAdrian Hunter static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) 1510a6d3bdd5SAdrian Hunter { 15114e9f8fe5SAdrian Hunter __sdhci_finish_mrq(host, mrq); 15122e72ab9bSAdrian Hunter 1513c07a48c2SAdrian Hunter queue_work(host->complete_wq, &host->complete_work); 1514a6d3bdd5SAdrian Hunter } 1515a6d3bdd5SAdrian Hunter 1516845c939eSAdrian Hunter static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) 15171c6a0718SPierre Ossman { 151833a57adbSAdrian Hunter struct mmc_command *data_cmd = host->data_cmd; 151933a57adbSAdrian Hunter struct mmc_data *data = host->data; 15201c6a0718SPierre Ossman 15211c6a0718SPierre Ossman host->data = NULL; 15227c89a3d9SAdrian Hunter host->data_cmd = NULL; 15231c6a0718SPierre Ossman 15244bf78099SAdrian Hunter /* 15254bf78099SAdrian Hunter * The controller needs a reset of internal state machines upon error 15264bf78099SAdrian Hunter * conditions. 15274bf78099SAdrian Hunter */ 15284bf78099SAdrian Hunter if (data->error) { 15294bf78099SAdrian Hunter if (!host->cmd || host->cmd == data_cmd) 15304bf78099SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD); 15314bf78099SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 15324bf78099SAdrian Hunter } 15334bf78099SAdrian Hunter 1534add8913dSRussell King if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) == 1535add8913dSRussell King (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) 15362134a922SPierre Ossman sdhci_adma_table_post(host, data); 1537f55c98f7SRussell King 15381c6a0718SPierre Ossman /* 1539c9b74c5bSPierre Ossman * The specification states that the block count register must 1540c9b74c5bSPierre Ossman * be updated, but it does not specify at what point in the 1541c9b74c5bSPierre Ossman * data flow. That makes the register entirely useless to read 1542c9b74c5bSPierre Ossman * back so we have to assume that nothing made it to the card 1543c9b74c5bSPierre Ossman * in the event of an error. 15441c6a0718SPierre Ossman */ 1545c9b74c5bSPierre Ossman if (data->error) 1546c9b74c5bSPierre Ossman data->bytes_xfered = 0; 15471c6a0718SPierre Ossman else 1548c9b74c5bSPierre Ossman data->bytes_xfered = data->blksz * data->blocks; 15491c6a0718SPierre Ossman 1550e89d456fSAndrei Warkentin /* 1551e89d456fSAndrei Warkentin * Need to send CMD12 if - 1552fdbbe6cfSYangbo Lu * a) open-ended multiblock transfer not using auto CMD12 (no CMD23) 1553e89d456fSAndrei Warkentin * b) error in multiblock transfer 1554e89d456fSAndrei Warkentin */ 1555e89d456fSAndrei Warkentin if (data->stop && 1556fdbbe6cfSYangbo Lu ((!data->mrq->sbc && !sdhci_auto_cmd12(host, data->mrq)) || 1557fdbbe6cfSYangbo Lu data->error)) { 155820845befSAdrian Hunter /* 155920845befSAdrian Hunter * 'cap_cmd_during_tfr' request must not use the command line 156020845befSAdrian Hunter * after mmc_command_done() has been called. It is upper layer's 156120845befSAdrian Hunter * responsibility to send the stop command if required. 156220845befSAdrian Hunter */ 156320845befSAdrian Hunter if (data->mrq->cap_cmd_during_tfr) { 156419d2f695SAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 156520845befSAdrian Hunter } else { 15668842fd17SAdrian Hunter /* Avoid triggering warning in sdhci_send_command() */ 15678842fd17SAdrian Hunter host->cmd = NULL; 1568845c939eSAdrian Hunter if (!sdhci_send_command(host, data->stop)) { 1569845c939eSAdrian Hunter if (sw_data_timeout) { 1570845c939eSAdrian Hunter /* 1571845c939eSAdrian Hunter * This is anyway a sw data timeout, so 1572845c939eSAdrian Hunter * give up now. 1573845c939eSAdrian Hunter */ 1574845c939eSAdrian Hunter data->stop->error = -EIO; 1575845c939eSAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 1576845c939eSAdrian Hunter } else { 1577845c939eSAdrian Hunter WARN_ON(host->deferred_cmd); 1578845c939eSAdrian Hunter host->deferred_cmd = data->stop; 1579845c939eSAdrian Hunter } 1580845c939eSAdrian Hunter } 158120845befSAdrian Hunter } 1582a6d3bdd5SAdrian Hunter } else { 158319d2f695SAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 1584a6d3bdd5SAdrian Hunter } 15851c6a0718SPierre Ossman } 15861c6a0718SPierre Ossman 1587845c939eSAdrian Hunter static void sdhci_finish_data(struct sdhci_host *host) 1588845c939eSAdrian Hunter { 1589845c939eSAdrian Hunter __sdhci_finish_data(host, false); 1590845c939eSAdrian Hunter } 1591845c939eSAdrian Hunter 1592845c939eSAdrian Hunter static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 15931c6a0718SPierre Ossman { 15941c6a0718SPierre Ossman int flags; 15951c6a0718SPierre Ossman u32 mask; 15961c6a0718SPierre Ossman unsigned long timeout; 15971c6a0718SPierre Ossman 15981c6a0718SPierre Ossman WARN_ON(host->cmd); 15991c6a0718SPierre Ossman 160096776200SRussell King /* Initially, a command has no error */ 160196776200SRussell King cmd->error = 0; 160296776200SRussell King 1603fc605f1dSAdrian Hunter if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && 1604fc605f1dSAdrian Hunter cmd->opcode == MMC_STOP_TRANSMISSION) 1605fc605f1dSAdrian Hunter cmd->flags |= MMC_RSP_BUSY; 1606fc605f1dSAdrian Hunter 16071c6a0718SPierre Ossman mask = SDHCI_CMD_INHIBIT; 160856a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) 16091c6a0718SPierre Ossman mask |= SDHCI_DATA_INHIBIT; 16101c6a0718SPierre Ossman 16111c6a0718SPierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 16121c6a0718SPierre Ossman though they might use busy signaling */ 1613a4c73abaSAdrian Hunter if (cmd->mrq->data && (cmd == cmd->mrq->data->stop)) 16141c6a0718SPierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 16151c6a0718SPierre Ossman 1616845c939eSAdrian Hunter if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) 1617845c939eSAdrian Hunter return false; 16181c6a0718SPierre Ossman 16191c6a0718SPierre Ossman host->cmd = cmd; 162015db1836SFaiz Abbas host->data_timeout = 0; 162156a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) { 16227c89a3d9SAdrian Hunter WARN_ON(host->data_cmd); 16237c89a3d9SAdrian Hunter host->data_cmd = cmd; 162415db1836SFaiz Abbas sdhci_set_timeout(host, cmd); 16257c89a3d9SAdrian Hunter } 16261c6a0718SPierre Ossman 162718e762e3SChunyan Zhang if (cmd->data) { 162818e762e3SChunyan Zhang if (host->use_external_dma) 162918e762e3SChunyan Zhang sdhci_external_dma_prepare_data(host, cmd); 163018e762e3SChunyan Zhang else 1631a3c7778fSAndrei Warkentin sdhci_prepare_data(host, cmd); 163218e762e3SChunyan Zhang } 16331c6a0718SPierre Ossman 16344e4141a5SAnton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); 16351c6a0718SPierre Ossman 1636e89d456fSAndrei Warkentin sdhci_set_transfer_mode(host, cmd); 16371c6a0718SPierre Ossman 16381c6a0718SPierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 1639845c939eSAdrian Hunter WARN_ONCE(1, "Unsupported response type!\n"); 1640845c939eSAdrian Hunter /* 1641845c939eSAdrian Hunter * This does not happen in practice because 136-bit response 1642845c939eSAdrian Hunter * commands never have busy waiting, so rather than complicate 1643845c939eSAdrian Hunter * the error path, just remove busy waiting and continue. 1644845c939eSAdrian Hunter */ 1645845c939eSAdrian Hunter cmd->flags &= ~MMC_RSP_BUSY; 16461c6a0718SPierre Ossman } 16471c6a0718SPierre Ossman 16481c6a0718SPierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 16491c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_NONE; 16501c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_136) 16511c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_LONG; 16521c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 16531c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 16541c6a0718SPierre Ossman else 16551c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT; 16561c6a0718SPierre Ossman 16571c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_CRC) 16581c6a0718SPierre Ossman flags |= SDHCI_CMD_CRC; 16591c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 16601c6a0718SPierre Ossman flags |= SDHCI_CMD_INDEX; 1661b513ea25SArindam Nath 1662b513ea25SArindam Nath /* CMD19 is special in that the Data Present Select should be set */ 1663069c9f14SGirish K S if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK || 1664069c9f14SGirish K S cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) 16651c6a0718SPierre Ossman flags |= SDHCI_CMD_DATA; 16661c6a0718SPierre Ossman 1667fc1fa1b7SKishon Vijay Abraham I timeout = jiffies; 1668fc1fa1b7SKishon Vijay Abraham I if (host->data_timeout) 1669fc1fa1b7SKishon Vijay Abraham I timeout += nsecs_to_jiffies(host->data_timeout); 1670fc1fa1b7SKishon Vijay Abraham I else if (!cmd->data && cmd->busy_timeout > 9000) 1671fc1fa1b7SKishon Vijay Abraham I timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; 1672fc1fa1b7SKishon Vijay Abraham I else 1673fc1fa1b7SKishon Vijay Abraham I timeout += 10 * HZ; 1674fc1fa1b7SKishon Vijay Abraham I sdhci_mod_timer(host, cmd->mrq, timeout); 1675fc1fa1b7SKishon Vijay Abraham I 167618e762e3SChunyan Zhang if (host->use_external_dma) 167718e762e3SChunyan Zhang sdhci_external_dma_pre_transfer(host, cmd); 167818e762e3SChunyan Zhang 16794e4141a5SAnton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 1680845c939eSAdrian Hunter 1681845c939eSAdrian Hunter return true; 16821c6a0718SPierre Ossman } 16831c6a0718SPierre Ossman 1684e872f1e2SAdrian Hunter static bool sdhci_present_error(struct sdhci_host *host, 1685e872f1e2SAdrian Hunter struct mmc_command *cmd, bool present) 1686e872f1e2SAdrian Hunter { 1687e872f1e2SAdrian Hunter if (!present || host->flags & SDHCI_DEVICE_DEAD) { 1688e872f1e2SAdrian Hunter cmd->error = -ENOMEDIUM; 1689e872f1e2SAdrian Hunter return true; 1690e872f1e2SAdrian Hunter } 1691e872f1e2SAdrian Hunter 1692e872f1e2SAdrian Hunter return false; 1693e872f1e2SAdrian Hunter } 1694e872f1e2SAdrian Hunter 1695845c939eSAdrian Hunter static bool sdhci_send_command_retry(struct sdhci_host *host, 1696845c939eSAdrian Hunter struct mmc_command *cmd, 1697845c939eSAdrian Hunter unsigned long flags) 1698845c939eSAdrian Hunter __releases(host->lock) 1699845c939eSAdrian Hunter __acquires(host->lock) 1700845c939eSAdrian Hunter { 1701845c939eSAdrian Hunter struct mmc_command *deferred_cmd = host->deferred_cmd; 1702845c939eSAdrian Hunter int timeout = 10; /* Approx. 10 ms */ 1703845c939eSAdrian Hunter bool present; 1704845c939eSAdrian Hunter 1705845c939eSAdrian Hunter while (!sdhci_send_command(host, cmd)) { 1706845c939eSAdrian Hunter if (!timeout--) { 1707845c939eSAdrian Hunter pr_err("%s: Controller never released inhibit bit(s).\n", 1708845c939eSAdrian Hunter mmc_hostname(host->mmc)); 1709845c939eSAdrian Hunter sdhci_dumpregs(host); 1710845c939eSAdrian Hunter cmd->error = -EIO; 1711845c939eSAdrian Hunter return false; 1712845c939eSAdrian Hunter } 1713845c939eSAdrian Hunter 1714845c939eSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 1715845c939eSAdrian Hunter 1716845c939eSAdrian Hunter usleep_range(1000, 1250); 1717845c939eSAdrian Hunter 1718845c939eSAdrian Hunter present = host->mmc->ops->get_cd(host->mmc); 1719845c939eSAdrian Hunter 1720845c939eSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 1721845c939eSAdrian Hunter 1722845c939eSAdrian Hunter /* A deferred command might disappear, handle that */ 1723845c939eSAdrian Hunter if (cmd == deferred_cmd && cmd != host->deferred_cmd) 1724845c939eSAdrian Hunter return true; 1725845c939eSAdrian Hunter 1726845c939eSAdrian Hunter if (sdhci_present_error(host, cmd, present)) 1727845c939eSAdrian Hunter return false; 1728845c939eSAdrian Hunter } 1729845c939eSAdrian Hunter 1730845c939eSAdrian Hunter if (cmd == host->deferred_cmd) 1731845c939eSAdrian Hunter host->deferred_cmd = NULL; 1732845c939eSAdrian Hunter 1733845c939eSAdrian Hunter return true; 1734845c939eSAdrian Hunter } 1735845c939eSAdrian Hunter 17364a5fc119SAdrian Hunter static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) 17374a5fc119SAdrian Hunter { 17384a5fc119SAdrian Hunter int i, reg; 17394a5fc119SAdrian Hunter 17404a5fc119SAdrian Hunter for (i = 0; i < 4; i++) { 17414a5fc119SAdrian Hunter reg = SDHCI_RESPONSE + (3 - i) * 4; 17424a5fc119SAdrian Hunter cmd->resp[i] = sdhci_readl(host, reg); 17434a5fc119SAdrian Hunter } 17444a5fc119SAdrian Hunter 17451284c248SKishon Vijay Abraham I if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC) 17461284c248SKishon Vijay Abraham I return; 17471284c248SKishon Vijay Abraham I 17484a5fc119SAdrian Hunter /* CRC is stripped so we need to do some shifting */ 17494a5fc119SAdrian Hunter for (i = 0; i < 4; i++) { 17504a5fc119SAdrian Hunter cmd->resp[i] <<= 8; 17514a5fc119SAdrian Hunter if (i != 3) 17524a5fc119SAdrian Hunter cmd->resp[i] |= cmd->resp[i + 1] >> 24; 17534a5fc119SAdrian Hunter } 17544a5fc119SAdrian Hunter } 17554a5fc119SAdrian Hunter 17561c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *host) 17571c6a0718SPierre Ossman { 1758e0a5640aSAdrian Hunter struct mmc_command *cmd = host->cmd; 17591c6a0718SPierre Ossman 1760e0a5640aSAdrian Hunter host->cmd = NULL; 1761e0a5640aSAdrian Hunter 1762e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_PRESENT) { 1763e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_136) { 17644a5fc119SAdrian Hunter sdhci_read_rsp_136(host, cmd); 17651c6a0718SPierre Ossman } else { 1766e0a5640aSAdrian Hunter cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); 17671c6a0718SPierre Ossman } 17681c6a0718SPierre Ossman } 17691c6a0718SPierre Ossman 177020845befSAdrian Hunter if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd) 177120845befSAdrian Hunter mmc_command_done(host->mmc, cmd->mrq); 177220845befSAdrian Hunter 17736bde8681SAdrian Hunter /* 17746bde8681SAdrian Hunter * The host can send and interrupt when the busy state has 17756bde8681SAdrian Hunter * ended, allowing us to wait without wasting CPU cycles. 17766bde8681SAdrian Hunter * The busy signal uses DAT0 so this is similar to waiting 17776bde8681SAdrian Hunter * for data to complete. 17786bde8681SAdrian Hunter * 17796bde8681SAdrian Hunter * Note: The 1.0 specification is a bit ambiguous about this 17806bde8681SAdrian Hunter * feature so there might be some problems with older 17816bde8681SAdrian Hunter * controllers. 17826bde8681SAdrian Hunter */ 1783e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_BUSY) { 1784e0a5640aSAdrian Hunter if (cmd->data) { 17856bde8681SAdrian Hunter DBG("Cannot wait for busy signal when also doing a data transfer"); 17866bde8681SAdrian Hunter } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && 1787ea968023SAdrian Hunter cmd == host->data_cmd) { 1788ea968023SAdrian Hunter /* Command complete before busy is ended */ 17896bde8681SAdrian Hunter return; 17906bde8681SAdrian Hunter } 17916bde8681SAdrian Hunter } 17926bde8681SAdrian Hunter 1793e89d456fSAndrei Warkentin /* Finished CMD23, now send actual command. */ 1794a4c73abaSAdrian Hunter if (cmd == cmd->mrq->sbc) { 1795845c939eSAdrian Hunter if (!sdhci_send_command(host, cmd->mrq->cmd)) { 1796845c939eSAdrian Hunter WARN_ON(host->deferred_cmd); 1797845c939eSAdrian Hunter host->deferred_cmd = cmd->mrq->cmd; 1798845c939eSAdrian Hunter } 1799e89d456fSAndrei Warkentin } else { 1800e89d456fSAndrei Warkentin 1801e89d456fSAndrei Warkentin /* Processed actual command. */ 1802e538fbe8SPierre Ossman if (host->data && host->data_early) 1803e538fbe8SPierre Ossman sdhci_finish_data(host); 1804e538fbe8SPierre Ossman 1805e0a5640aSAdrian Hunter if (!cmd->data) 180619d2f695SAdrian Hunter __sdhci_finish_mrq(host, cmd->mrq); 18071c6a0718SPierre Ossman } 1808e89d456fSAndrei Warkentin } 18091c6a0718SPierre Ossman 181052983382SKevin Liu static u16 sdhci_get_preset_value(struct sdhci_host *host) 181152983382SKevin Liu { 1812d975f121SRussell King u16 preset = 0; 181352983382SKevin Liu 1814d975f121SRussell King switch (host->timing) { 1815d975f121SRussell King case MMC_TIMING_UHS_SDR12: 181652983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); 181752983382SKevin Liu break; 1818d975f121SRussell King case MMC_TIMING_UHS_SDR25: 181952983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25); 182052983382SKevin Liu break; 1821d975f121SRussell King case MMC_TIMING_UHS_SDR50: 182252983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50); 182352983382SKevin Liu break; 1824d975f121SRussell King case MMC_TIMING_UHS_SDR104: 1825d975f121SRussell King case MMC_TIMING_MMC_HS200: 182652983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104); 182752983382SKevin Liu break; 1828d975f121SRussell King case MMC_TIMING_UHS_DDR50: 18290dafa60eSJisheng Zhang case MMC_TIMING_MMC_DDR52: 183052983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50); 183152983382SKevin Liu break; 1832e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400: 1833e9fb05d5SAdrian Hunter preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400); 1834e9fb05d5SAdrian Hunter break; 183552983382SKevin Liu default: 183652983382SKevin Liu pr_warn("%s: Invalid UHS-I mode selected\n", 183752983382SKevin Liu mmc_hostname(host->mmc)); 183852983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); 183952983382SKevin Liu break; 184052983382SKevin Liu } 184152983382SKevin Liu return preset; 184252983382SKevin Liu } 184352983382SKevin Liu 1844fb9ee047SLudovic Desroches u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, 1845fb9ee047SLudovic Desroches unsigned int *actual_clock) 18461c6a0718SPierre Ossman { 1847c3ed3877SArindam Nath int div = 0; /* Initialized for compiler warning */ 1848df16219fSGiuseppe CAVALLARO int real_div = div, clk_mul = 1; 1849c3ed3877SArindam Nath u16 clk = 0; 18505497159cSludovic.desroches@atmel.com bool switch_base_clk = false; 18511c6a0718SPierre Ossman 185285105c53SZhangfei Gao if (host->version >= SDHCI_SPEC_300) { 1853da91a8f9SRussell King if (host->preset_enabled) { 185452983382SKevin Liu u16 pre_val; 185552983382SKevin Liu 185652983382SKevin Liu clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 185752983382SKevin Liu pre_val = sdhci_get_preset_value(host); 1858fa091010SMasahiro Yamada div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val); 185952983382SKevin Liu if (host->clk_mul && 1860fa091010SMasahiro Yamada (pre_val & SDHCI_PRESET_CLKGEN_SEL)) { 186152983382SKevin Liu clk = SDHCI_PROG_CLOCK_MODE; 186252983382SKevin Liu real_div = div + 1; 186352983382SKevin Liu clk_mul = host->clk_mul; 186452983382SKevin Liu } else { 186552983382SKevin Liu real_div = max_t(int, 1, div << 1); 186652983382SKevin Liu } 186752983382SKevin Liu goto clock_set; 186852983382SKevin Liu } 186952983382SKevin Liu 1870c3ed3877SArindam Nath /* 1871c3ed3877SArindam Nath * Check if the Host Controller supports Programmable Clock 1872c3ed3877SArindam Nath * Mode. 1873c3ed3877SArindam Nath */ 1874c3ed3877SArindam Nath if (host->clk_mul) { 1875c3ed3877SArindam Nath for (div = 1; div <= 1024; div++) { 187652983382SKevin Liu if ((host->max_clk * host->clk_mul / div) 187752983382SKevin Liu <= clock) 1878c3ed3877SArindam Nath break; 1879c3ed3877SArindam Nath } 18805497159cSludovic.desroches@atmel.com if ((host->max_clk * host->clk_mul / div) <= clock) { 1881c3ed3877SArindam Nath /* 1882c3ed3877SArindam Nath * Set Programmable Clock Mode in the Clock 1883c3ed3877SArindam Nath * Control register. 1884c3ed3877SArindam Nath */ 1885c3ed3877SArindam Nath clk = SDHCI_PROG_CLOCK_MODE; 1886df16219fSGiuseppe CAVALLARO real_div = div; 1887df16219fSGiuseppe CAVALLARO clk_mul = host->clk_mul; 1888c3ed3877SArindam Nath div--; 1889c3ed3877SArindam Nath } else { 18905497159cSludovic.desroches@atmel.com /* 18915497159cSludovic.desroches@atmel.com * Divisor can be too small to reach clock 18925497159cSludovic.desroches@atmel.com * speed requirement. Then use the base clock. 18935497159cSludovic.desroches@atmel.com */ 18945497159cSludovic.desroches@atmel.com switch_base_clk = true; 18955497159cSludovic.desroches@atmel.com } 18965497159cSludovic.desroches@atmel.com } 18975497159cSludovic.desroches@atmel.com 18985497159cSludovic.desroches@atmel.com if (!host->clk_mul || switch_base_clk) { 189985105c53SZhangfei Gao /* Version 3.00 divisors must be a multiple of 2. */ 190085105c53SZhangfei Gao if (host->max_clk <= clock) 190185105c53SZhangfei Gao div = 1; 190285105c53SZhangfei Gao else { 1903c3ed3877SArindam Nath for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; 1904c3ed3877SArindam Nath div += 2) { 190585105c53SZhangfei Gao if ((host->max_clk / div) <= clock) 190685105c53SZhangfei Gao break; 190785105c53SZhangfei Gao } 190885105c53SZhangfei Gao } 1909df16219fSGiuseppe CAVALLARO real_div = div; 1910c3ed3877SArindam Nath div >>= 1; 1911d1955c3aSSuneel Garapati if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN) 1912d1955c3aSSuneel Garapati && !div && host->max_clk <= 25000000) 1913d1955c3aSSuneel Garapati div = 1; 1914c3ed3877SArindam Nath } 191585105c53SZhangfei Gao } else { 191685105c53SZhangfei Gao /* Version 2.00 divisors must be a power of 2. */ 19170397526dSZhangfei Gao for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { 19181c6a0718SPierre Ossman if ((host->max_clk / div) <= clock) 19191c6a0718SPierre Ossman break; 19201c6a0718SPierre Ossman } 1921df16219fSGiuseppe CAVALLARO real_div = div; 19221c6a0718SPierre Ossman div >>= 1; 1923c3ed3877SArindam Nath } 19241c6a0718SPierre Ossman 192552983382SKevin Liu clock_set: 192603d6f5ffSAisheng Dong if (real_div) 1927fb9ee047SLudovic Desroches *actual_clock = (host->max_clk * clk_mul) / real_div; 1928c3ed3877SArindam Nath clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 192985105c53SZhangfei Gao clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 193085105c53SZhangfei Gao << SDHCI_DIVIDER_HI_SHIFT; 1931fb9ee047SLudovic Desroches 1932fb9ee047SLudovic Desroches return clk; 1933fb9ee047SLudovic Desroches } 1934fb9ee047SLudovic Desroches EXPORT_SYMBOL_GPL(sdhci_calc_clk); 1935fb9ee047SLudovic Desroches 1936fec79673SRitesh Harjani void sdhci_enable_clk(struct sdhci_host *host, u16 clk) 1937fb9ee047SLudovic Desroches { 19385a436cc0SAdrian Hunter ktime_t timeout; 1939fb9ee047SLudovic Desroches 19401c6a0718SPierre Ossman clk |= SDHCI_CLOCK_INT_EN; 19414e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 19421c6a0718SPierre Ossman 19434a9e0d1aSBen Chuang /* Wait max 150 ms */ 19444a9e0d1aSBen Chuang timeout = ktime_add_ms(ktime_get(), 150); 1945b704441eSAlek Du while (1) { 1946b704441eSAlek Du bool timedout = ktime_after(ktime_get(), timeout); 1947b704441eSAlek Du 1948b704441eSAlek Du clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1949b704441eSAlek Du if (clk & SDHCI_CLOCK_INT_STABLE) 1950b704441eSAlek Du break; 1951b704441eSAlek Du if (timedout) { 19522e4456f0SMarek Vasut pr_err("%s: Internal clock never stabilised.\n", 19532e4456f0SMarek Vasut mmc_hostname(host->mmc)); 19541c6a0718SPierre Ossman sdhci_dumpregs(host); 19551c6a0718SPierre Ossman return; 19561c6a0718SPierre Ossman } 19575a436cc0SAdrian Hunter udelay(10); 19581c6a0718SPierre Ossman } 19591c6a0718SPierre Ossman 19601beabbdbSBen Chuang if (host->version >= SDHCI_SPEC_410 && host->v4_mode) { 19611beabbdbSBen Chuang clk |= SDHCI_CLOCK_PLL_EN; 19621beabbdbSBen Chuang clk &= ~SDHCI_CLOCK_INT_STABLE; 19631beabbdbSBen Chuang sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 19641beabbdbSBen Chuang 19651beabbdbSBen Chuang /* Wait max 150 ms */ 19661beabbdbSBen Chuang timeout = ktime_add_ms(ktime_get(), 150); 19671beabbdbSBen Chuang while (1) { 19681beabbdbSBen Chuang bool timedout = ktime_after(ktime_get(), timeout); 19691beabbdbSBen Chuang 19701beabbdbSBen Chuang clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 19711beabbdbSBen Chuang if (clk & SDHCI_CLOCK_INT_STABLE) 19721beabbdbSBen Chuang break; 19731beabbdbSBen Chuang if (timedout) { 19741beabbdbSBen Chuang pr_err("%s: PLL clock never stabilised.\n", 19751beabbdbSBen Chuang mmc_hostname(host->mmc)); 19761beabbdbSBen Chuang sdhci_dumpregs(host); 19771beabbdbSBen Chuang return; 19781beabbdbSBen Chuang } 19791beabbdbSBen Chuang udelay(10); 19801beabbdbSBen Chuang } 19811beabbdbSBen Chuang } 19821beabbdbSBen Chuang 19831c6a0718SPierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 19844e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 19851c6a0718SPierre Ossman } 1986fec79673SRitesh Harjani EXPORT_SYMBOL_GPL(sdhci_enable_clk); 1987fec79673SRitesh Harjani 1988fec79673SRitesh Harjani void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 1989fec79673SRitesh Harjani { 1990fec79673SRitesh Harjani u16 clk; 1991fec79673SRitesh Harjani 1992fec79673SRitesh Harjani host->mmc->actual_clock = 0; 1993fec79673SRitesh Harjani 1994fec79673SRitesh Harjani sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 1995fec79673SRitesh Harjani 1996fec79673SRitesh Harjani if (clock == 0) 1997fec79673SRitesh Harjani return; 1998fec79673SRitesh Harjani 1999fec79673SRitesh Harjani clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 2000fec79673SRitesh Harjani sdhci_enable_clk(host, clk); 2001fec79673SRitesh Harjani } 20021771059cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_clock); 20031c6a0718SPierre Ossman 20041dceb041SAdrian Hunter static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, 200524fbb3caSRussell King unsigned short vdd) 20061c6a0718SPierre Ossman { 20073a48edc4STim Kryger struct mmc_host *mmc = host->mmc; 20081dceb041SAdrian Hunter 20091dceb041SAdrian Hunter mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); 20101dceb041SAdrian Hunter 20111dceb041SAdrian Hunter if (mode != MMC_POWER_OFF) 20121dceb041SAdrian Hunter sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL); 20131dceb041SAdrian Hunter else 20141dceb041SAdrian Hunter sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 20151dceb041SAdrian Hunter } 20161dceb041SAdrian Hunter 2017606d3131SAdrian Hunter void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, 20181dceb041SAdrian Hunter unsigned short vdd) 20191dceb041SAdrian Hunter { 20208364248aSGiuseppe Cavallaro u8 pwr = 0; 20211c6a0718SPierre Ossman 202224fbb3caSRussell King if (mode != MMC_POWER_OFF) { 202324fbb3caSRussell King switch (1 << vdd) { 2024ae628903SPierre Ossman case MMC_VDD_165_195: 20252a609abeSAndy Shevchenko /* 20262a609abeSAndy Shevchenko * Without a regulator, SDHCI does not support 2.0v 20272a609abeSAndy Shevchenko * so we only get here if the driver deliberately 20282a609abeSAndy Shevchenko * added the 2.0v range to ocr_avail. Map it to 1.8v 20292a609abeSAndy Shevchenko * for the purpose of turning on the power. 20302a609abeSAndy Shevchenko */ 20312a609abeSAndy Shevchenko case MMC_VDD_20_21: 2032ae628903SPierre Ossman pwr = SDHCI_POWER_180; 2033ae628903SPierre Ossman break; 2034ae628903SPierre Ossman case MMC_VDD_29_30: 2035ae628903SPierre Ossman case MMC_VDD_30_31: 2036ae628903SPierre Ossman pwr = SDHCI_POWER_300; 2037ae628903SPierre Ossman break; 2038ae628903SPierre Ossman case MMC_VDD_32_33: 2039ae628903SPierre Ossman case MMC_VDD_33_34: 2040ae628903SPierre Ossman pwr = SDHCI_POWER_330; 2041ae628903SPierre Ossman break; 2042ae628903SPierre Ossman default: 20439d5de93fSAdrian Hunter WARN(1, "%s: Invalid vdd %#x\n", 20449d5de93fSAdrian Hunter mmc_hostname(host->mmc), vdd); 20459d5de93fSAdrian Hunter break; 2046ae628903SPierre Ossman } 2047ae628903SPierre Ossman } 2048ae628903SPierre Ossman 2049ae628903SPierre Ossman if (host->pwr == pwr) 2050e921a8b6SRussell King return; 20511c6a0718SPierre Ossman 2052ae628903SPierre Ossman host->pwr = pwr; 2053ae628903SPierre Ossman 2054ae628903SPierre Ossman if (pwr == 0) { 20554e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 2056f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 2057f0710a55SAdrian Hunter sdhci_runtime_pm_bus_off(host); 2058e921a8b6SRussell King } else { 20591c6a0718SPierre Ossman /* 20601c6a0718SPierre Ossman * Spec says that we should clear the power reg before setting 20611c6a0718SPierre Ossman * a new value. Some controllers don't seem to like this though. 20621c6a0718SPierre Ossman */ 2063b8c86fc5SPierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 20644e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 20651c6a0718SPierre Ossman 2066e08c1694SAndres Salomon /* 2067e921a8b6SRussell King * At least the Marvell CaFe chip gets confused if we set the 2068e921a8b6SRussell King * voltage and set turn on power at the same time, so set the 2069e921a8b6SRussell King * voltage first. 2070e08c1694SAndres Salomon */ 207111a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) 20724e4141a5SAnton Vorontsov sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 20731c6a0718SPierre Ossman 2074ae628903SPierre Ossman pwr |= SDHCI_POWER_ON; 2075ae628903SPierre Ossman 2076ae628903SPierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 2077557b0697SHarald Welte 2078f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 2079f0710a55SAdrian Hunter sdhci_runtime_pm_bus_on(host); 2080f0710a55SAdrian Hunter 2081557b0697SHarald Welte /* 2082e921a8b6SRussell King * Some controllers need an extra 10ms delay of 10ms before 2083e921a8b6SRussell King * they can apply clock after applying power 2084557b0697SHarald Welte */ 208511a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) 2086557b0697SHarald Welte mdelay(10); 2087e921a8b6SRussell King } 2088918f4cbdSJisheng Zhang } 2089606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power_noreg); 20901dceb041SAdrian Hunter 2091606d3131SAdrian Hunter void sdhci_set_power(struct sdhci_host *host, unsigned char mode, 20921dceb041SAdrian Hunter unsigned short vdd) 20931dceb041SAdrian Hunter { 2094606d3131SAdrian Hunter if (IS_ERR(host->mmc->supply.vmmc)) 2095606d3131SAdrian Hunter sdhci_set_power_noreg(host, mode, vdd); 20961dceb041SAdrian Hunter else 2097606d3131SAdrian Hunter sdhci_set_power_reg(host, mode, vdd); 20981c6a0718SPierre Ossman } 2099606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power); 21001c6a0718SPierre Ossman 21016c92ae1eSNicolas Saenz Julienne /* 21026c92ae1eSNicolas Saenz Julienne * Some controllers need to configure a valid bus voltage on their power 21036c92ae1eSNicolas Saenz Julienne * register regardless of whether an external regulator is taking care of power 21046c92ae1eSNicolas Saenz Julienne * supply. This helper function takes care of it if set as the controller's 21056c92ae1eSNicolas Saenz Julienne * sdhci_ops.set_power callback. 21066c92ae1eSNicolas Saenz Julienne */ 21076c92ae1eSNicolas Saenz Julienne void sdhci_set_power_and_bus_voltage(struct sdhci_host *host, 21086c92ae1eSNicolas Saenz Julienne unsigned char mode, 21096c92ae1eSNicolas Saenz Julienne unsigned short vdd) 21106c92ae1eSNicolas Saenz Julienne { 21116c92ae1eSNicolas Saenz Julienne if (!IS_ERR(host->mmc->supply.vmmc)) { 21126c92ae1eSNicolas Saenz Julienne struct mmc_host *mmc = host->mmc; 21136c92ae1eSNicolas Saenz Julienne 21146c92ae1eSNicolas Saenz Julienne mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); 21156c92ae1eSNicolas Saenz Julienne } 21166c92ae1eSNicolas Saenz Julienne sdhci_set_power_noreg(host, mode, vdd); 21176c92ae1eSNicolas Saenz Julienne } 21186c92ae1eSNicolas Saenz Julienne EXPORT_SYMBOL_GPL(sdhci_set_power_and_bus_voltage); 21196c92ae1eSNicolas Saenz Julienne 21201c6a0718SPierre Ossman /*****************************************************************************\ 21211c6a0718SPierre Ossman * * 21221c6a0718SPierre Ossman * MMC callbacks * 21231c6a0718SPierre Ossman * * 21241c6a0718SPierre Ossman \*****************************************************************************/ 21251c6a0718SPierre Ossman 2126d462c1b4SAapo Vienamo void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 21271c6a0718SPierre Ossman { 2128e872f1e2SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2129e872f1e2SAdrian Hunter struct mmc_command *cmd; 21301c6a0718SPierre Ossman unsigned long flags; 2131e872f1e2SAdrian Hunter bool present; 21321c6a0718SPierre Ossman 213304e079cfSScott Branden /* Firstly check card presence */ 21348d28b7a7SAdrian Hunter present = mmc->ops->get_cd(mmc); 21352836766aSKrzysztof Kozlowski 21361c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 21371c6a0718SPierre Ossman 2138061d17a6SAdrian Hunter sdhci_led_activate(host); 2139e89d456fSAndrei Warkentin 2140e872f1e2SAdrian Hunter if (sdhci_present_error(host, mrq->cmd, present)) 2141e872f1e2SAdrian Hunter goto out_finish; 21421c6a0718SPierre Ossman 2143e872f1e2SAdrian Hunter cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; 2144e872f1e2SAdrian Hunter 2145845c939eSAdrian Hunter if (!sdhci_send_command_retry(host, cmd, flags)) 2146845c939eSAdrian Hunter goto out_finish; 2147e872f1e2SAdrian Hunter 2148e872f1e2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2149e872f1e2SAdrian Hunter 2150e872f1e2SAdrian Hunter return; 2151e872f1e2SAdrian Hunter 2152e872f1e2SAdrian Hunter out_finish: 2153e872f1e2SAdrian Hunter sdhci_finish_mrq(host, mrq); 21541c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 21551c6a0718SPierre Ossman } 2156d462c1b4SAapo Vienamo EXPORT_SYMBOL_GPL(sdhci_request); 21571c6a0718SPierre Ossman 215848ef8a2aSBaolin Wang int sdhci_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq) 215948ef8a2aSBaolin Wang { 216048ef8a2aSBaolin Wang struct sdhci_host *host = mmc_priv(mmc); 216148ef8a2aSBaolin Wang struct mmc_command *cmd; 216248ef8a2aSBaolin Wang unsigned long flags; 216348ef8a2aSBaolin Wang int ret = 0; 216448ef8a2aSBaolin Wang 216548ef8a2aSBaolin Wang spin_lock_irqsave(&host->lock, flags); 216648ef8a2aSBaolin Wang 216748ef8a2aSBaolin Wang if (sdhci_present_error(host, mrq->cmd, true)) { 216848ef8a2aSBaolin Wang sdhci_finish_mrq(host, mrq); 216948ef8a2aSBaolin Wang goto out_finish; 217048ef8a2aSBaolin Wang } 217148ef8a2aSBaolin Wang 217248ef8a2aSBaolin Wang cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; 217348ef8a2aSBaolin Wang 217448ef8a2aSBaolin Wang /* 217548ef8a2aSBaolin Wang * The HSQ may send a command in interrupt context without polling 217648ef8a2aSBaolin Wang * the busy signaling, which means we should return BUSY if controller 217748ef8a2aSBaolin Wang * has not released inhibit bits to allow HSQ trying to send request 217848ef8a2aSBaolin Wang * again in non-atomic context. So we should not finish this request 217948ef8a2aSBaolin Wang * here. 218048ef8a2aSBaolin Wang */ 218148ef8a2aSBaolin Wang if (!sdhci_send_command(host, cmd)) 218248ef8a2aSBaolin Wang ret = -EBUSY; 218348ef8a2aSBaolin Wang else 218448ef8a2aSBaolin Wang sdhci_led_activate(host); 218548ef8a2aSBaolin Wang 218648ef8a2aSBaolin Wang out_finish: 218748ef8a2aSBaolin Wang spin_unlock_irqrestore(&host->lock, flags); 218848ef8a2aSBaolin Wang return ret; 218948ef8a2aSBaolin Wang } 219048ef8a2aSBaolin Wang EXPORT_SYMBOL_GPL(sdhci_request_atomic); 219148ef8a2aSBaolin Wang 21922317f56cSRussell King void sdhci_set_bus_width(struct sdhci_host *host, int width) 21932317f56cSRussell King { 21942317f56cSRussell King u8 ctrl; 21952317f56cSRussell King 21962317f56cSRussell King ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 21972317f56cSRussell King if (width == MMC_BUS_WIDTH_8) { 21982317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS; 21992317f56cSRussell King ctrl |= SDHCI_CTRL_8BITBUS; 22002317f56cSRussell King } else { 220198f94ea6SMichał Mirosław if (host->mmc->caps & MMC_CAP_8_BIT_DATA) 22022317f56cSRussell King ctrl &= ~SDHCI_CTRL_8BITBUS; 22032317f56cSRussell King if (width == MMC_BUS_WIDTH_4) 22042317f56cSRussell King ctrl |= SDHCI_CTRL_4BITBUS; 22052317f56cSRussell King else 22062317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS; 22072317f56cSRussell King } 22082317f56cSRussell King sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 22092317f56cSRussell King } 22102317f56cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_bus_width); 22112317f56cSRussell King 221296d7b78cSRussell King void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) 221396d7b78cSRussell King { 221496d7b78cSRussell King u16 ctrl_2; 221596d7b78cSRussell King 221696d7b78cSRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 221796d7b78cSRussell King /* Select Bus Speed Mode for host */ 221896d7b78cSRussell King ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 221996d7b78cSRussell King if ((timing == MMC_TIMING_MMC_HS200) || 222096d7b78cSRussell King (timing == MMC_TIMING_UHS_SDR104)) 222196d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR104; 222296d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR12) 222396d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR12; 222407bcc411SFaiz Abbas else if (timing == MMC_TIMING_UHS_SDR25) 222596d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 222696d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR50) 222796d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR50; 222896d7b78cSRussell King else if ((timing == MMC_TIMING_UHS_DDR50) || 222996d7b78cSRussell King (timing == MMC_TIMING_MMC_DDR52)) 223096d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_DDR50; 2231e9fb05d5SAdrian Hunter else if (timing == MMC_TIMING_MMC_HS400) 2232e9fb05d5SAdrian Hunter ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */ 223396d7b78cSRussell King sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 223496d7b78cSRussell King } 223596d7b78cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); 223696d7b78cSRussell King 22376a6d4cebSHu Ziji void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 22381c6a0718SPierre Ossman { 2239ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 22401c6a0718SPierre Ossman u8 ctrl; 22411c6a0718SPierre Ossman 224284ec048bSAdrian Hunter if (ios->power_mode == MMC_POWER_UNDEFINED) 224384ec048bSAdrian Hunter return; 224484ec048bSAdrian Hunter 2245ceb6143bSAdrian Hunter if (host->flags & SDHCI_DEVICE_DEAD) { 22463a48edc4STim Kryger if (!IS_ERR(mmc->supply.vmmc) && 22473a48edc4STim Kryger ios->power_mode == MMC_POWER_OFF) 22484e743f1fSMarkus Mayer mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 2249ceb6143bSAdrian Hunter return; 2250ceb6143bSAdrian Hunter } 22511e72859eSPierre Ossman 22521c6a0718SPierre Ossman /* 22531c6a0718SPierre Ossman * Reset the chip on each power off. 22541c6a0718SPierre Ossman * Should clear out any weird states. 22551c6a0718SPierre Ossman */ 22561c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 22574e4141a5SAnton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 22587260cf5eSAnton Vorontsov sdhci_reinit(host); 22591c6a0718SPierre Ossman } 22601c6a0718SPierre Ossman 226152983382SKevin Liu if (host->version >= SDHCI_SPEC_300 && 2262372c4634SDong Aisheng (ios->power_mode == MMC_POWER_UP) && 2263372c4634SDong Aisheng !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) 226452983382SKevin Liu sdhci_enable_preset_value(host, false); 226552983382SKevin Liu 2266373073efSRussell King if (!ios->clock || ios->clock != host->clock) { 22671771059cSRussell King host->ops->set_clock(host, ios->clock); 2268373073efSRussell King host->clock = ios->clock; 226903d6f5ffSAisheng Dong 227003d6f5ffSAisheng Dong if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && 227103d6f5ffSAisheng Dong host->clock) { 227203d6f5ffSAisheng Dong host->timeout_clk = host->mmc->actual_clock ? 227303d6f5ffSAisheng Dong host->mmc->actual_clock / 1000 : 227403d6f5ffSAisheng Dong host->clock / 1000; 227503d6f5ffSAisheng Dong host->mmc->max_busy_timeout = 227603d6f5ffSAisheng Dong host->ops->get_max_timeout_count ? 227703d6f5ffSAisheng Dong host->ops->get_max_timeout_count(host) : 227803d6f5ffSAisheng Dong 1 << 27; 227903d6f5ffSAisheng Dong host->mmc->max_busy_timeout /= host->timeout_clk; 228003d6f5ffSAisheng Dong } 2281373073efSRussell King } 22821c6a0718SPierre Ossman 2283606d3131SAdrian Hunter if (host->ops->set_power) 2284606d3131SAdrian Hunter host->ops->set_power(host, ios->power_mode, ios->vdd); 2285606d3131SAdrian Hunter else 2286606d3131SAdrian Hunter sdhci_set_power(host, ios->power_mode, ios->vdd); 22871c6a0718SPierre Ossman 2288643a81ffSPhilip Rakity if (host->ops->platform_send_init_74_clocks) 2289643a81ffSPhilip Rakity host->ops->platform_send_init_74_clocks(host, ios->power_mode); 2290643a81ffSPhilip Rakity 22912317f56cSRussell King host->ops->set_bus_width(host, ios->bus_width); 229215ec4461SPhilip Rakity 229315ec4461SPhilip Rakity ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 22941c6a0718SPierre Ossman 2295501639bfSyangbo lu if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) { 2296501639bfSyangbo lu if (ios->timing == MMC_TIMING_SD_HS || 2297273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS || 2298273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS400 || 2299273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS200 || 2300273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_DDR52 || 2301273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR50 || 2302273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR104 || 2303273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_DDR50 || 2304273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR25) 23051c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_HISPD; 23061c6a0718SPierre Ossman else 23071c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 2308501639bfSyangbo lu } 23091c6a0718SPierre Ossman 2310d6d50a15SArindam Nath if (host->version >= SDHCI_SPEC_300) { 231149c468fcSArindam Nath u16 clk, ctrl_2; 231249c468fcSArindam Nath 2313da91a8f9SRussell King if (!host->preset_enabled) { 2314758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2315d6d50a15SArindam Nath /* 2316d6d50a15SArindam Nath * We only need to set Driver Strength if the 2317d6d50a15SArindam Nath * preset value enable is not set. 2318d6d50a15SArindam Nath */ 2319da91a8f9SRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2320d6d50a15SArindam Nath ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; 2321d6d50a15SArindam Nath if (ios->drv_type == MMC_SET_DRIVER_TYPE_A) 2322d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; 232343e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_B) 232443e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B; 2325d6d50a15SArindam Nath else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C) 2326d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C; 232743e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D) 232843e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D; 232943e943a0SPetri Gynther else { 23302e4456f0SMarek Vasut pr_warn("%s: invalid driver type, default to driver type B\n", 23312e4456f0SMarek Vasut mmc_hostname(mmc)); 233243e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B; 233343e943a0SPetri Gynther } 2334d6d50a15SArindam Nath 2335d6d50a15SArindam Nath sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 2336758535c4SArindam Nath } else { 2337758535c4SArindam Nath /* 2338758535c4SArindam Nath * According to SDHC Spec v3.00, if the Preset Value 2339758535c4SArindam Nath * Enable in the Host Control 2 register is set, we 2340758535c4SArindam Nath * need to reset SD Clock Enable before changing High 2341758535c4SArindam Nath * Speed Enable to avoid generating clock gliches. 2342758535c4SArindam Nath */ 2343758535c4SArindam Nath 2344758535c4SArindam Nath /* Reset SD Clock Enable */ 2345758535c4SArindam Nath clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 2346758535c4SArindam Nath clk &= ~SDHCI_CLOCK_CARD_EN; 2347758535c4SArindam Nath sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 2348758535c4SArindam Nath 2349758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2350758535c4SArindam Nath 2351758535c4SArindam Nath /* Re-enable SD Clock */ 23521771059cSRussell King host->ops->set_clock(host, host->clock); 2353d6d50a15SArindam Nath } 235449c468fcSArindam Nath 23556322cdd0SPhilip Rakity /* Reset SD Clock Enable */ 23566322cdd0SPhilip Rakity clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 23576322cdd0SPhilip Rakity clk &= ~SDHCI_CLOCK_CARD_EN; 23586322cdd0SPhilip Rakity sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 23596322cdd0SPhilip Rakity 23606322cdd0SPhilip Rakity host->ops->set_uhs_signaling(host, ios->timing); 2361d975f121SRussell King host->timing = ios->timing; 236249c468fcSArindam Nath 236352983382SKevin Liu if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && 236452983382SKevin Liu ((ios->timing == MMC_TIMING_UHS_SDR12) || 236552983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR25) || 236652983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR50) || 236752983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR104) || 23680dafa60eSJisheng Zhang (ios->timing == MMC_TIMING_UHS_DDR50) || 23690dafa60eSJisheng Zhang (ios->timing == MMC_TIMING_MMC_DDR52))) { 237052983382SKevin Liu u16 preset; 237152983382SKevin Liu 237252983382SKevin Liu sdhci_enable_preset_value(host, true); 237352983382SKevin Liu preset = sdhci_get_preset_value(host); 2374fa091010SMasahiro Yamada ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK, 2375fa091010SMasahiro Yamada preset); 237652983382SKevin Liu } 237752983382SKevin Liu 237849c468fcSArindam Nath /* Re-enable SD Clock */ 23791771059cSRussell King host->ops->set_clock(host, host->clock); 2380758535c4SArindam Nath } else 2381758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2382d6d50a15SArindam Nath 2383b8352260SLeandro Dorileo /* 2384b8352260SLeandro Dorileo * Some (ENE) controllers go apeshit on some ios operation, 2385b8352260SLeandro Dorileo * signalling timeout and CRC errors even on CMD0. Resetting 2386b8352260SLeandro Dorileo * it on each ios seems to solve the problem. 2387b8352260SLeandro Dorileo */ 2388b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 238903231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 23901c6a0718SPierre Ossman } 23916a6d4cebSHu Ziji EXPORT_SYMBOL_GPL(sdhci_set_ios); 23921c6a0718SPierre Ossman 2393ded97e0bSDong Aisheng static int sdhci_get_cd(struct mmc_host *mmc) 239466fd8ad5SAdrian Hunter { 239566fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2396ded97e0bSDong Aisheng int gpio_cd = mmc_gpio_get_cd(mmc); 239794144a46SKevin Liu 239894144a46SKevin Liu if (host->flags & SDHCI_DEVICE_DEAD) 239994144a46SKevin Liu return 0; 240094144a46SKevin Liu 240188af5655SIvan T. Ivanov /* If nonremovable, assume that the card is always present. */ 2402860951c5SJaehoon Chung if (!mmc_card_is_removable(host->mmc)) 240394144a46SKevin Liu return 1; 240494144a46SKevin Liu 240588af5655SIvan T. Ivanov /* 240688af5655SIvan T. Ivanov * Try slot gpio detect, if defined it take precedence 240788af5655SIvan T. Ivanov * over build in controller functionality 240888af5655SIvan T. Ivanov */ 2409287980e4SArnd Bergmann if (gpio_cd >= 0) 241094144a46SKevin Liu return !!gpio_cd; 241194144a46SKevin Liu 241288af5655SIvan T. Ivanov /* If polling, assume that the card is always present. */ 241388af5655SIvan T. Ivanov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 241488af5655SIvan T. Ivanov return 1; 241588af5655SIvan T. Ivanov 241694144a46SKevin Liu /* Host native card detect */ 241794144a46SKevin Liu return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); 241894144a46SKevin Liu } 241994144a46SKevin Liu 242066fd8ad5SAdrian Hunter static int sdhci_check_ro(struct sdhci_host *host) 24211c6a0718SPierre Ossman { 24221c6a0718SPierre Ossman unsigned long flags; 24232dfb579cSWolfram Sang int is_readonly; 24241c6a0718SPierre Ossman 24251c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 24261c6a0718SPierre Ossman 24271e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 24282dfb579cSWolfram Sang is_readonly = 0; 24292dfb579cSWolfram Sang else if (host->ops->get_ro) 24302dfb579cSWolfram Sang is_readonly = host->ops->get_ro(host); 24316d5cd068SThomas Petazzoni else if (mmc_can_gpio_ro(host->mmc)) 24326d5cd068SThomas Petazzoni is_readonly = mmc_gpio_get_ro(host->mmc); 24331e72859eSPierre Ossman else 24342dfb579cSWolfram Sang is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) 24352dfb579cSWolfram Sang & SDHCI_WRITE_PROTECT); 24361c6a0718SPierre Ossman 24371c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 24381c6a0718SPierre Ossman 24392dfb579cSWolfram Sang /* This quirk needs to be replaced by a callback-function later */ 24402dfb579cSWolfram Sang return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? 24412dfb579cSWolfram Sang !is_readonly : is_readonly; 24421c6a0718SPierre Ossman } 24431c6a0718SPierre Ossman 244482b0e23aSTakashi Iwai #define SAMPLE_COUNT 5 244582b0e23aSTakashi Iwai 2446ded97e0bSDong Aisheng static int sdhci_get_ro(struct mmc_host *mmc) 244782b0e23aSTakashi Iwai { 2448ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 244982b0e23aSTakashi Iwai int i, ro_count; 245082b0e23aSTakashi Iwai 245182b0e23aSTakashi Iwai if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT)) 245266fd8ad5SAdrian Hunter return sdhci_check_ro(host); 245382b0e23aSTakashi Iwai 245482b0e23aSTakashi Iwai ro_count = 0; 245582b0e23aSTakashi Iwai for (i = 0; i < SAMPLE_COUNT; i++) { 245666fd8ad5SAdrian Hunter if (sdhci_check_ro(host)) { 245782b0e23aSTakashi Iwai if (++ro_count > SAMPLE_COUNT / 2) 245882b0e23aSTakashi Iwai return 1; 245982b0e23aSTakashi Iwai } 246082b0e23aSTakashi Iwai msleep(30); 246182b0e23aSTakashi Iwai } 246282b0e23aSTakashi Iwai return 0; 246382b0e23aSTakashi Iwai } 246482b0e23aSTakashi Iwai 246520758b66SAdrian Hunter static void sdhci_hw_reset(struct mmc_host *mmc) 246620758b66SAdrian Hunter { 246720758b66SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 246820758b66SAdrian Hunter 246920758b66SAdrian Hunter if (host->ops && host->ops->hw_reset) 247020758b66SAdrian Hunter host->ops->hw_reset(host); 247120758b66SAdrian Hunter } 247220758b66SAdrian Hunter 247366fd8ad5SAdrian Hunter static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable) 247466fd8ad5SAdrian Hunter { 2475be138554SRussell King if (!(host->flags & SDHCI_DEVICE_DEAD)) { 247666fd8ad5SAdrian Hunter if (enable) 2477b537f94cSRussell King host->ier |= SDHCI_INT_CARD_INT; 24787260cf5eSAnton Vorontsov else 2479b537f94cSRussell King host->ier &= ~SDHCI_INT_CARD_INT; 2480b537f94cSRussell King 2481b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2482b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 248366fd8ad5SAdrian Hunter } 2484ef104333SRussell King } 2485f75979b7SPierre Ossman 24862f05b6abSHu Ziji void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 248766fd8ad5SAdrian Hunter { 248866fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 248966fd8ad5SAdrian Hunter unsigned long flags; 249066fd8ad5SAdrian Hunter 2491923713b3SHans de Goede if (enable) 2492923713b3SHans de Goede pm_runtime_get_noresume(host->mmc->parent); 2493923713b3SHans de Goede 249466fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 249566fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, enable); 2496f75979b7SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 2497923713b3SHans de Goede 2498923713b3SHans de Goede if (!enable) 2499923713b3SHans de Goede pm_runtime_put_noidle(host->mmc->parent); 2500f75979b7SPierre Ossman } 25012f05b6abSHu Ziji EXPORT_SYMBOL_GPL(sdhci_enable_sdio_irq); 2502f75979b7SPierre Ossman 250389f3c365SAdrian Hunter static void sdhci_ack_sdio_irq(struct mmc_host *mmc) 250489f3c365SAdrian Hunter { 250589f3c365SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 250689f3c365SAdrian Hunter unsigned long flags; 250789f3c365SAdrian Hunter 250889f3c365SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 250989f3c365SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true); 251089f3c365SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 251189f3c365SAdrian Hunter } 251289f3c365SAdrian Hunter 2513c376ea9eSHu Ziji int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, 251421f5998fSFabio Estevam struct mmc_ios *ios) 2515f2119df6SArindam Nath { 2516ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 251720b92a30SKevin Liu u16 ctrl; 25186231f3deSPhilip Rakity int ret; 2519f2119df6SArindam Nath 252020b92a30SKevin Liu /* 252120b92a30SKevin Liu * Signal Voltage Switching is only applicable for Host Controllers 252220b92a30SKevin Liu * v3.00 and above. 252320b92a30SKevin Liu */ 252420b92a30SKevin Liu if (host->version < SDHCI_SPEC_300) 252520b92a30SKevin Liu return 0; 252620b92a30SKevin Liu 252720b92a30SKevin Liu ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 252820b92a30SKevin Liu 252921f5998fSFabio Estevam switch (ios->signal_voltage) { 253020b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_330: 25318cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_330)) 25328cb851a4SAdrian Hunter return -EINVAL; 2533f2119df6SArindam Nath /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ 2534f2119df6SArindam Nath ctrl &= ~SDHCI_CTRL_VDD_180; 2535f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2536f2119df6SArindam Nath 25373a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2538761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 25399cbe0fc8SMarek Vasut if (ret < 0) { 25406606110dSJoe Perches pr_warn("%s: Switching to 3.3V signalling voltage failed\n", 25416606110dSJoe Perches mmc_hostname(mmc)); 25426231f3deSPhilip Rakity return -EIO; 25436231f3deSPhilip Rakity } 25446231f3deSPhilip Rakity } 2545f2119df6SArindam Nath /* Wait for 5ms */ 2546f2119df6SArindam Nath usleep_range(5000, 5500); 2547f2119df6SArindam Nath 2548f2119df6SArindam Nath /* 3.3V regulator output should be stable within 5 ms */ 2549f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2550f2119df6SArindam Nath if (!(ctrl & SDHCI_CTRL_VDD_180)) 2551f2119df6SArindam Nath return 0; 25526231f3deSPhilip Rakity 2553b0b19ce6SFabio Estevam pr_warn("%s: 3.3V regulator output did not become stable\n", 25544e743f1fSMarkus Mayer mmc_hostname(mmc)); 25556231f3deSPhilip Rakity 255620b92a30SKevin Liu return -EAGAIN; 255720b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_180: 25588cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_180)) 25598cb851a4SAdrian Hunter return -EINVAL; 25603a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2561761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 25629cbe0fc8SMarek Vasut if (ret < 0) { 25636606110dSJoe Perches pr_warn("%s: Switching to 1.8V signalling voltage failed\n", 25646606110dSJoe Perches mmc_hostname(mmc)); 2565f2119df6SArindam Nath return -EIO; 2566f2119df6SArindam Nath } 256720b92a30SKevin Liu } 25686231f3deSPhilip Rakity 2569f2119df6SArindam Nath /* 2570f2119df6SArindam Nath * Enable 1.8V Signal Enable in the Host Control2 2571f2119df6SArindam Nath * register 2572f2119df6SArindam Nath */ 2573f2119df6SArindam Nath ctrl |= SDHCI_CTRL_VDD_180; 2574f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2575f2119df6SArindam Nath 25769d967a61SVincent Yang /* Some controller need to do more when switching */ 25779d967a61SVincent Yang if (host->ops->voltage_switch) 25789d967a61SVincent Yang host->ops->voltage_switch(host); 25799d967a61SVincent Yang 258020b92a30SKevin Liu /* 1.8V regulator output should be stable within 5 ms */ 2581f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 258220b92a30SKevin Liu if (ctrl & SDHCI_CTRL_VDD_180) 2583f2119df6SArindam Nath return 0; 2584f2119df6SArindam Nath 2585b0b19ce6SFabio Estevam pr_warn("%s: 1.8V regulator output did not become stable\n", 25864e743f1fSMarkus Mayer mmc_hostname(mmc)); 25876231f3deSPhilip Rakity 2588f2119df6SArindam Nath return -EAGAIN; 258920b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_120: 25908cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_120)) 25918cb851a4SAdrian Hunter return -EINVAL; 25923a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2593761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 25949cbe0fc8SMarek Vasut if (ret < 0) { 25956606110dSJoe Perches pr_warn("%s: Switching to 1.2V signalling voltage failed\n", 25966606110dSJoe Perches mmc_hostname(mmc)); 259720b92a30SKevin Liu return -EIO; 25986231f3deSPhilip Rakity } 259920b92a30SKevin Liu } 26006231f3deSPhilip Rakity return 0; 260120b92a30SKevin Liu default: 2602f2119df6SArindam Nath /* No signal voltage switch required */ 2603f2119df6SArindam Nath return 0; 2604f2119df6SArindam Nath } 260520b92a30SKevin Liu } 2606c376ea9eSHu Ziji EXPORT_SYMBOL_GPL(sdhci_start_signal_voltage_switch); 2607f2119df6SArindam Nath 260820b92a30SKevin Liu static int sdhci_card_busy(struct mmc_host *mmc) 260920b92a30SKevin Liu { 261020b92a30SKevin Liu struct sdhci_host *host = mmc_priv(mmc); 261120b92a30SKevin Liu u32 present_state; 261220b92a30SKevin Liu 2613e613cc47SAdrian Hunter /* Check whether DAT[0] is 0 */ 261420b92a30SKevin Liu present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); 261520b92a30SKevin Liu 2616e613cc47SAdrian Hunter return !(present_state & SDHCI_DATA_0_LVL_MASK); 261720b92a30SKevin Liu } 261820b92a30SKevin Liu 2619b5540ce1SAdrian Hunter static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) 2620b5540ce1SAdrian Hunter { 2621b5540ce1SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2622b5540ce1SAdrian Hunter unsigned long flags; 2623b5540ce1SAdrian Hunter 2624b5540ce1SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2625b5540ce1SAdrian Hunter host->flags |= SDHCI_HS400_TUNING; 2626b5540ce1SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2627b5540ce1SAdrian Hunter 2628b5540ce1SAdrian Hunter return 0; 2629b5540ce1SAdrian Hunter } 2630b5540ce1SAdrian Hunter 26316663c419Sernest.zhang void sdhci_start_tuning(struct sdhci_host *host) 2632da4bc4f2SAdrian Hunter { 2633da4bc4f2SAdrian Hunter u16 ctrl; 2634da4bc4f2SAdrian Hunter 2635da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2636da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_EXEC_TUNING; 2637da4bc4f2SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND) 2638da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_TUNED_CLK; 2639da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2640da4bc4f2SAdrian Hunter 2641da4bc4f2SAdrian Hunter /* 2642da4bc4f2SAdrian Hunter * As per the Host Controller spec v3.00, tuning command 2643da4bc4f2SAdrian Hunter * generates Buffer Read Ready interrupt, so enable that. 2644da4bc4f2SAdrian Hunter * 2645da4bc4f2SAdrian Hunter * Note: The spec clearly says that when tuning sequence 2646da4bc4f2SAdrian Hunter * is being performed, the controller does not generate 2647da4bc4f2SAdrian Hunter * interrupts other than Buffer Read Ready interrupt. But 2648da4bc4f2SAdrian Hunter * to make sure we don't hit a controller bug, we _only_ 2649da4bc4f2SAdrian Hunter * enable Buffer Read Ready interrupt here. 2650da4bc4f2SAdrian Hunter */ 2651da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); 2652da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); 2653da4bc4f2SAdrian Hunter } 26546663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_start_tuning); 2655da4bc4f2SAdrian Hunter 26566663c419Sernest.zhang void sdhci_end_tuning(struct sdhci_host *host) 2657da4bc4f2SAdrian Hunter { 2658da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2659da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 2660da4bc4f2SAdrian Hunter } 26616663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_end_tuning); 2662da4bc4f2SAdrian Hunter 26636663c419Sernest.zhang void sdhci_reset_tuning(struct sdhci_host *host) 2664da4bc4f2SAdrian Hunter { 2665da4bc4f2SAdrian Hunter u16 ctrl; 2666da4bc4f2SAdrian Hunter 2667da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2668da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_TUNED_CLK; 2669da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_EXEC_TUNING; 2670da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2671da4bc4f2SAdrian Hunter } 26726663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_reset_tuning); 2673da4bc4f2SAdrian Hunter 26747353788cSBen Chuang void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) 2675da4bc4f2SAdrian Hunter { 2676da4bc4f2SAdrian Hunter sdhci_reset_tuning(host); 2677da4bc4f2SAdrian Hunter 2678da4bc4f2SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD); 2679da4bc4f2SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 2680da4bc4f2SAdrian Hunter 2681da4bc4f2SAdrian Hunter sdhci_end_tuning(host); 2682da4bc4f2SAdrian Hunter 2683da4bc4f2SAdrian Hunter mmc_abort_tuning(host->mmc, opcode); 2684da4bc4f2SAdrian Hunter } 26857353788cSBen Chuang EXPORT_SYMBOL_GPL(sdhci_abort_tuning); 2686da4bc4f2SAdrian Hunter 2687da4bc4f2SAdrian Hunter /* 2688da4bc4f2SAdrian Hunter * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI 2689da4bc4f2SAdrian Hunter * tuning command does not have a data payload (or rather the hardware does it 2690da4bc4f2SAdrian Hunter * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command 2691da4bc4f2SAdrian Hunter * interrupt setup is different to other commands and there is no timeout 2692da4bc4f2SAdrian Hunter * interrupt so special handling is needed. 2693da4bc4f2SAdrian Hunter */ 26946663c419Sernest.zhang void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) 2695da4bc4f2SAdrian Hunter { 2696da4bc4f2SAdrian Hunter struct mmc_host *mmc = host->mmc; 2697c7836d15SMasahiro Yamada struct mmc_command cmd = {}; 2698c7836d15SMasahiro Yamada struct mmc_request mrq = {}; 26992a85ef25SAdrian Hunter unsigned long flags; 2700c846a00fSSrinivas Kandagatla u32 b = host->sdma_boundary; 27012a85ef25SAdrian Hunter 27022a85ef25SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2703da4bc4f2SAdrian Hunter 2704da4bc4f2SAdrian Hunter cmd.opcode = opcode; 2705da4bc4f2SAdrian Hunter cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 2706da4bc4f2SAdrian Hunter cmd.mrq = &mrq; 2707da4bc4f2SAdrian Hunter 2708da4bc4f2SAdrian Hunter mrq.cmd = &cmd; 2709da4bc4f2SAdrian Hunter /* 2710da4bc4f2SAdrian Hunter * In response to CMD19, the card sends 64 bytes of tuning 2711da4bc4f2SAdrian Hunter * block to the Host Controller. So we set the block size 2712da4bc4f2SAdrian Hunter * to 64 here. 2713da4bc4f2SAdrian Hunter */ 271485336109SAdrian Hunter if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200 && 271585336109SAdrian Hunter mmc->ios.bus_width == MMC_BUS_WIDTH_8) 2716c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 128), SDHCI_BLOCK_SIZE); 271785336109SAdrian Hunter else 2718c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 64), SDHCI_BLOCK_SIZE); 2719da4bc4f2SAdrian Hunter 2720da4bc4f2SAdrian Hunter /* 2721da4bc4f2SAdrian Hunter * The tuning block is sent by the card to the host controller. 2722da4bc4f2SAdrian Hunter * So we set the TRNS_READ bit in the Transfer Mode register. 2723da4bc4f2SAdrian Hunter * This also takes care of setting DMA Enable and Multi Block 2724da4bc4f2SAdrian Hunter * Select in the same register to 0. 2725da4bc4f2SAdrian Hunter */ 2726da4bc4f2SAdrian Hunter sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); 2727da4bc4f2SAdrian Hunter 2728845c939eSAdrian Hunter if (!sdhci_send_command_retry(host, &cmd, flags)) { 2729845c939eSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2730845c939eSAdrian Hunter host->tuning_done = 0; 2731845c939eSAdrian Hunter return; 2732845c939eSAdrian Hunter } 2733da4bc4f2SAdrian Hunter 2734da4bc4f2SAdrian Hunter host->cmd = NULL; 2735da4bc4f2SAdrian Hunter 2736da4bc4f2SAdrian Hunter sdhci_del_timer(host, &mrq); 2737da4bc4f2SAdrian Hunter 2738da4bc4f2SAdrian Hunter host->tuning_done = 0; 2739da4bc4f2SAdrian Hunter 2740da4bc4f2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2741da4bc4f2SAdrian Hunter 2742da4bc4f2SAdrian Hunter /* Wait for Buffer Read Ready interrupt */ 2743da4bc4f2SAdrian Hunter wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1), 2744da4bc4f2SAdrian Hunter msecs_to_jiffies(50)); 2745da4bc4f2SAdrian Hunter 2746da4bc4f2SAdrian Hunter } 27476663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_send_tuning); 2748da4bc4f2SAdrian Hunter 27497d8bb1f4SYinbo Zhu static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) 27506b11e70bSAdrian Hunter { 27516b11e70bSAdrian Hunter int i; 27526b11e70bSAdrian Hunter 27536b11e70bSAdrian Hunter /* 27546b11e70bSAdrian Hunter * Issue opcode repeatedly till Execute Tuning is set to 0 or the number 27551d8cd065SSowjanya Komatineni * of loops reaches tuning loop count. 27566b11e70bSAdrian Hunter */ 27571d8cd065SSowjanya Komatineni for (i = 0; i < host->tuning_loop_count; i++) { 27586b11e70bSAdrian Hunter u16 ctrl; 27596b11e70bSAdrian Hunter 27602a85ef25SAdrian Hunter sdhci_send_tuning(host, opcode); 27616b11e70bSAdrian Hunter 27626b11e70bSAdrian Hunter if (!host->tuning_done) { 2763811ba676SFaiz Abbas pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n", 27646b11e70bSAdrian Hunter mmc_hostname(host->mmc)); 27652a85ef25SAdrian Hunter sdhci_abort_tuning(host, opcode); 27667d8bb1f4SYinbo Zhu return -ETIMEDOUT; 27676b11e70bSAdrian Hunter } 27686b11e70bSAdrian Hunter 27692b06e159SBOUGH CHEN /* Spec does not require a delay between tuning cycles */ 27702b06e159SBOUGH CHEN if (host->tuning_delay > 0) 27712b06e159SBOUGH CHEN mdelay(host->tuning_delay); 27722b06e159SBOUGH CHEN 27736b11e70bSAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 27746b11e70bSAdrian Hunter if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { 27756b11e70bSAdrian Hunter if (ctrl & SDHCI_CTRL_TUNED_CLK) 27767d8bb1f4SYinbo Zhu return 0; /* Success! */ 27776b11e70bSAdrian Hunter break; 27786b11e70bSAdrian Hunter } 27796b11e70bSAdrian Hunter 27806b11e70bSAdrian Hunter } 27816b11e70bSAdrian Hunter 27826b11e70bSAdrian Hunter pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", 27836b11e70bSAdrian Hunter mmc_hostname(host->mmc)); 27846b11e70bSAdrian Hunter sdhci_reset_tuning(host); 27857d8bb1f4SYinbo Zhu return -EAGAIN; 27866b11e70bSAdrian Hunter } 27876b11e70bSAdrian Hunter 278885a882c2SMasahiro Yamada int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) 2789b513ea25SArindam Nath { 27904b6f37d3SRussell King struct sdhci_host *host = mmc_priv(mmc); 2791b513ea25SArindam Nath int err = 0; 279238e40bf5SAdrian Hunter unsigned int tuning_count = 0; 2793b5540ce1SAdrian Hunter bool hs400_tuning; 2794b513ea25SArindam Nath 2795b5540ce1SAdrian Hunter hs400_tuning = host->flags & SDHCI_HS400_TUNING; 2796b5540ce1SAdrian Hunter 279738e40bf5SAdrian Hunter if (host->tuning_mode == SDHCI_TUNING_MODE_1) 279838e40bf5SAdrian Hunter tuning_count = host->tuning_count; 279938e40bf5SAdrian Hunter 2800b513ea25SArindam Nath /* 28019faac7b9SWeijun Yang * The Host Controller needs tuning in case of SDR104 and DDR50 28029faac7b9SWeijun Yang * mode, and for SDR50 mode when Use Tuning for SDR50 is set in 28039faac7b9SWeijun Yang * the Capabilities register. 2804069c9f14SGirish K S * If the Host Controller supports the HS200 mode then the 2805069c9f14SGirish K S * tuning function has to be executed. 2806b513ea25SArindam Nath */ 28074b6f37d3SRussell King switch (host->timing) { 2808b5540ce1SAdrian Hunter /* HS400 tuning is done in HS200 mode */ 2809e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400: 2810b5540ce1SAdrian Hunter err = -EINVAL; 28112a85ef25SAdrian Hunter goto out; 2812b5540ce1SAdrian Hunter 28134b6f37d3SRussell King case MMC_TIMING_MMC_HS200: 2814b5540ce1SAdrian Hunter /* 2815b5540ce1SAdrian Hunter * Periodic re-tuning for HS400 is not expected to be needed, so 2816b5540ce1SAdrian Hunter * disable it here. 2817b5540ce1SAdrian Hunter */ 2818b5540ce1SAdrian Hunter if (hs400_tuning) 2819b5540ce1SAdrian Hunter tuning_count = 0; 2820b5540ce1SAdrian Hunter break; 2821b5540ce1SAdrian Hunter 28224b6f37d3SRussell King case MMC_TIMING_UHS_SDR104: 28239faac7b9SWeijun Yang case MMC_TIMING_UHS_DDR50: 28244b6f37d3SRussell King break; 2825069c9f14SGirish K S 28264b6f37d3SRussell King case MMC_TIMING_UHS_SDR50: 28274228b213SAdrian Hunter if (host->flags & SDHCI_SDR50_NEEDS_TUNING) 28284b6f37d3SRussell King break; 2829df561f66SGustavo A. R. Silva fallthrough; 28304b6f37d3SRussell King 28314b6f37d3SRussell King default: 28322a85ef25SAdrian Hunter goto out; 2833b513ea25SArindam Nath } 2834b513ea25SArindam Nath 283545251812SDong Aisheng if (host->ops->platform_execute_tuning) { 28368a8fa879SRitesh Harjani err = host->ops->platform_execute_tuning(host, opcode); 28372a85ef25SAdrian Hunter goto out; 283845251812SDong Aisheng } 283945251812SDong Aisheng 28406b11e70bSAdrian Hunter host->mmc->retune_period = tuning_count; 28416b11e70bSAdrian Hunter 284283b600b8SAdrian Hunter if (host->tuning_delay < 0) 284383b600b8SAdrian Hunter host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK; 284483b600b8SAdrian Hunter 2845da4bc4f2SAdrian Hunter sdhci_start_tuning(host); 2846b513ea25SArindam Nath 28477d8bb1f4SYinbo Zhu host->tuning_err = __sdhci_execute_tuning(host, opcode); 2848cf2b5eeaSArindam Nath 2849da4bc4f2SAdrian Hunter sdhci_end_tuning(host); 28502a85ef25SAdrian Hunter out: 28518a8fa879SRitesh Harjani host->flags &= ~SDHCI_HS400_TUNING; 28526b11e70bSAdrian Hunter 2853b513ea25SArindam Nath return err; 2854b513ea25SArindam Nath } 285585a882c2SMasahiro Yamada EXPORT_SYMBOL_GPL(sdhci_execute_tuning); 2856b513ea25SArindam Nath 285752983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) 28584d55c5a1SArindam Nath { 28594d55c5a1SArindam Nath /* Host Controller v3.00 defines preset value registers */ 28604d55c5a1SArindam Nath if (host->version < SDHCI_SPEC_300) 28614d55c5a1SArindam Nath return; 28624d55c5a1SArindam Nath 28634d55c5a1SArindam Nath /* 28644d55c5a1SArindam Nath * We only enable or disable Preset Value if they are not already 28654d55c5a1SArindam Nath * enabled or disabled respectively. Otherwise, we bail out. 28664d55c5a1SArindam Nath */ 2867da91a8f9SRussell King if (host->preset_enabled != enable) { 2868da91a8f9SRussell King u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2869da91a8f9SRussell King 2870da91a8f9SRussell King if (enable) 28714d55c5a1SArindam Nath ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; 2872da91a8f9SRussell King else 28734d55c5a1SArindam Nath ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; 2874da91a8f9SRussell King 28754d55c5a1SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2876da91a8f9SRussell King 2877da91a8f9SRussell King if (enable) 2878da91a8f9SRussell King host->flags |= SDHCI_PV_ENABLED; 2879da91a8f9SRussell King else 288066fd8ad5SAdrian Hunter host->flags &= ~SDHCI_PV_ENABLED; 2881da91a8f9SRussell King 2882da91a8f9SRussell King host->preset_enabled = enable; 28834d55c5a1SArindam Nath } 288466fd8ad5SAdrian Hunter } 288566fd8ad5SAdrian Hunter 2886348487cbSHaibo Chen static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, 2887348487cbSHaibo Chen int err) 2888348487cbSHaibo Chen { 2889348487cbSHaibo Chen struct sdhci_host *host = mmc_priv(mmc); 2890348487cbSHaibo Chen struct mmc_data *data = mrq->data; 2891348487cbSHaibo Chen 2892f48f039cSRussell King if (data->host_cookie != COOKIE_UNMAPPED) 2893348487cbSHaibo Chen dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 2894feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 2895771a3dc2SRussell King 2896d31911b9SHaibo Chen data->host_cookie = COOKIE_UNMAPPED; 2897348487cbSHaibo Chen } 2898348487cbSHaibo Chen 2899d3c6aac3SLinus Walleij static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) 2900348487cbSHaibo Chen { 2901348487cbSHaibo Chen struct sdhci_host *host = mmc_priv(mmc); 2902348487cbSHaibo Chen 2903d31911b9SHaibo Chen mrq->data->host_cookie = COOKIE_UNMAPPED; 2904348487cbSHaibo Chen 2905bd9b9027SLinus Walleij /* 2906bd9b9027SLinus Walleij * No pre-mapping in the pre hook if we're using the bounce buffer, 2907bd9b9027SLinus Walleij * for that we would need two bounce buffers since one buffer is 2908bd9b9027SLinus Walleij * in flight when this is getting called. 2909bd9b9027SLinus Walleij */ 2910bd9b9027SLinus Walleij if (host->flags & SDHCI_REQ_USE_DMA && !host->bounce_buffer) 291194538e51SRussell King sdhci_pre_dma_transfer(host, mrq->data, COOKIE_PRE_MAPPED); 2912348487cbSHaibo Chen } 2913348487cbSHaibo Chen 29145d0d11c5SAdrian Hunter static void sdhci_error_out_mrqs(struct sdhci_host *host, int err) 29155d0d11c5SAdrian Hunter { 29165d0d11c5SAdrian Hunter if (host->data_cmd) { 29175d0d11c5SAdrian Hunter host->data_cmd->error = err; 29185d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq); 29195d0d11c5SAdrian Hunter } 29205d0d11c5SAdrian Hunter 29215d0d11c5SAdrian Hunter if (host->cmd) { 29225d0d11c5SAdrian Hunter host->cmd->error = err; 29235d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 29245d0d11c5SAdrian Hunter } 29255d0d11c5SAdrian Hunter } 29265d0d11c5SAdrian Hunter 292771e69211SGuennadi Liakhovetski static void sdhci_card_event(struct mmc_host *mmc) 29281c6a0718SPierre Ossman { 292971e69211SGuennadi Liakhovetski struct sdhci_host *host = mmc_priv(mmc); 29301c6a0718SPierre Ossman unsigned long flags; 29312836766aSKrzysztof Kozlowski int present; 29321c6a0718SPierre Ossman 2933722e1280SChristian Daudt /* First check if client has provided their own card event */ 2934722e1280SChristian Daudt if (host->ops->card_event) 2935722e1280SChristian Daudt host->ops->card_event(host); 2936722e1280SChristian Daudt 2937d3940f27SAdrian Hunter present = mmc->ops->get_cd(mmc); 29382836766aSKrzysztof Kozlowski 29391c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 29401c6a0718SPierre Ossman 29415d0d11c5SAdrian Hunter /* Check sdhci_has_requests() first in case we are runtime suspended */ 29425d0d11c5SAdrian Hunter if (sdhci_has_requests(host) && !present) { 2943a3c76eb9SGirish K S pr_err("%s: Card removed during transfer!\n", 29441c6a0718SPierre Ossman mmc_hostname(host->mmc)); 2945a3c76eb9SGirish K S pr_err("%s: Resetting controller.\n", 29461c6a0718SPierre Ossman mmc_hostname(host->mmc)); 29471c6a0718SPierre Ossman 294803231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_CMD); 294903231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_DATA); 29501c6a0718SPierre Ossman 29515d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM); 29521c6a0718SPierre Ossman } 29531c6a0718SPierre Ossman 29541c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 295571e69211SGuennadi Liakhovetski } 295671e69211SGuennadi Liakhovetski 295771e69211SGuennadi Liakhovetski static const struct mmc_host_ops sdhci_ops = { 295871e69211SGuennadi Liakhovetski .request = sdhci_request, 2959348487cbSHaibo Chen .post_req = sdhci_post_req, 2960348487cbSHaibo Chen .pre_req = sdhci_pre_req, 296171e69211SGuennadi Liakhovetski .set_ios = sdhci_set_ios, 296294144a46SKevin Liu .get_cd = sdhci_get_cd, 296371e69211SGuennadi Liakhovetski .get_ro = sdhci_get_ro, 296471e69211SGuennadi Liakhovetski .hw_reset = sdhci_hw_reset, 296571e69211SGuennadi Liakhovetski .enable_sdio_irq = sdhci_enable_sdio_irq, 296689f3c365SAdrian Hunter .ack_sdio_irq = sdhci_ack_sdio_irq, 296771e69211SGuennadi Liakhovetski .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, 2968b5540ce1SAdrian Hunter .prepare_hs400_tuning = sdhci_prepare_hs400_tuning, 296971e69211SGuennadi Liakhovetski .execute_tuning = sdhci_execute_tuning, 297071e69211SGuennadi Liakhovetski .card_event = sdhci_card_event, 297120b92a30SKevin Liu .card_busy = sdhci_card_busy, 297271e69211SGuennadi Liakhovetski }; 297371e69211SGuennadi Liakhovetski 297471e69211SGuennadi Liakhovetski /*****************************************************************************\ 297571e69211SGuennadi Liakhovetski * * 2976c07a48c2SAdrian Hunter * Request done * 297771e69211SGuennadi Liakhovetski * * 297871e69211SGuennadi Liakhovetski \*****************************************************************************/ 297971e69211SGuennadi Liakhovetski 29804e9f8fe5SAdrian Hunter static bool sdhci_request_done(struct sdhci_host *host) 29811c6a0718SPierre Ossman { 29821c6a0718SPierre Ossman unsigned long flags; 29831c6a0718SPierre Ossman struct mmc_request *mrq; 29844e9f8fe5SAdrian Hunter int i; 29851c6a0718SPierre Ossman 298666fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 298766fd8ad5SAdrian Hunter 29884e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 29894e9f8fe5SAdrian Hunter mrq = host->mrqs_done[i]; 29906ebebeabSAdrian Hunter if (mrq) 29914e9f8fe5SAdrian Hunter break; 29924e9f8fe5SAdrian Hunter } 29931c6a0718SPierre Ossman 29944e9f8fe5SAdrian Hunter if (!mrq) { 29954e9f8fe5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 29964e9f8fe5SAdrian Hunter return true; 29974e9f8fe5SAdrian Hunter } 29981c6a0718SPierre Ossman 29991c6a0718SPierre Ossman /* 3000*21e35e89SPradeep P V K * The controller needs a reset of internal state machines 3001*21e35e89SPradeep P V K * upon error conditions. 3002*21e35e89SPradeep P V K */ 3003*21e35e89SPradeep P V K if (sdhci_needs_reset(host, mrq)) { 3004*21e35e89SPradeep P V K /* 3005*21e35e89SPradeep P V K * Do not finish until command and data lines are available for 3006*21e35e89SPradeep P V K * reset. Note there can only be one other mrq, so it cannot 3007*21e35e89SPradeep P V K * also be in mrqs_done, otherwise host->cmd and host->data_cmd 3008*21e35e89SPradeep P V K * would both be null. 3009*21e35e89SPradeep P V K */ 3010*21e35e89SPradeep P V K if (host->cmd || host->data_cmd) { 3011*21e35e89SPradeep P V K spin_unlock_irqrestore(&host->lock, flags); 3012*21e35e89SPradeep P V K return true; 3013*21e35e89SPradeep P V K } 3014*21e35e89SPradeep P V K 3015*21e35e89SPradeep P V K /* Some controllers need this kick or reset won't work here */ 3016*21e35e89SPradeep P V K if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) 3017*21e35e89SPradeep P V K /* This is to force an update */ 3018*21e35e89SPradeep P V K host->ops->set_clock(host, host->clock); 3019*21e35e89SPradeep P V K 3020*21e35e89SPradeep P V K /* 3021*21e35e89SPradeep P V K * Spec says we should do both at the same time, but Ricoh 3022*21e35e89SPradeep P V K * controllers do not like that. 3023*21e35e89SPradeep P V K */ 3024*21e35e89SPradeep P V K sdhci_do_reset(host, SDHCI_RESET_CMD); 3025*21e35e89SPradeep P V K sdhci_do_reset(host, SDHCI_RESET_DATA); 3026*21e35e89SPradeep P V K 3027*21e35e89SPradeep P V K host->pending_reset = false; 3028*21e35e89SPradeep P V K } 3029*21e35e89SPradeep P V K 3030*21e35e89SPradeep P V K /* 3031054cedffSRussell King * Always unmap the data buffers if they were mapped by 3032054cedffSRussell King * sdhci_prepare_data() whenever we finish with a request. 3033054cedffSRussell King * This avoids leaking DMA mappings on error. 3034054cedffSRussell King */ 3035054cedffSRussell King if (host->flags & SDHCI_REQ_USE_DMA) { 3036054cedffSRussell King struct mmc_data *data = mrq->data; 3037054cedffSRussell King 303818e762e3SChunyan Zhang if (host->use_external_dma && data && 303918e762e3SChunyan Zhang (mrq->cmd->error || data->error)) { 304018e762e3SChunyan Zhang struct dma_chan *chan = sdhci_external_dma_channel(host, data); 304118e762e3SChunyan Zhang 304218e762e3SChunyan Zhang host->mrqs_done[i] = NULL; 304318e762e3SChunyan Zhang spin_unlock_irqrestore(&host->lock, flags); 304418e762e3SChunyan Zhang dmaengine_terminate_sync(chan); 304518e762e3SChunyan Zhang spin_lock_irqsave(&host->lock, flags); 304618e762e3SChunyan Zhang sdhci_set_mrq_done(host, mrq); 304718e762e3SChunyan Zhang } 304818e762e3SChunyan Zhang 3049054cedffSRussell King if (data && data->host_cookie == COOKIE_MAPPED) { 3050bd9b9027SLinus Walleij if (host->bounce_buffer) { 3051bd9b9027SLinus Walleij /* 3052bd9b9027SLinus Walleij * On reads, copy the bounced data into the 3053bd9b9027SLinus Walleij * sglist 3054bd9b9027SLinus Walleij */ 3055bd9b9027SLinus Walleij if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) { 3056bd9b9027SLinus Walleij unsigned int length = data->bytes_xfered; 3057bd9b9027SLinus Walleij 3058bd9b9027SLinus Walleij if (length > host->bounce_buffer_size) { 3059bd9b9027SLinus Walleij pr_err("%s: bounce buffer is %u bytes but DMA claims to have transferred %u bytes\n", 3060bd9b9027SLinus Walleij mmc_hostname(host->mmc), 3061bd9b9027SLinus Walleij host->bounce_buffer_size, 3062bd9b9027SLinus Walleij data->bytes_xfered); 3063bd9b9027SLinus Walleij /* Cap it down and continue */ 3064bd9b9027SLinus Walleij length = host->bounce_buffer_size; 3065bd9b9027SLinus Walleij } 3066bd9b9027SLinus Walleij dma_sync_single_for_cpu( 3067bd9b9027SLinus Walleij host->mmc->parent, 3068bd9b9027SLinus Walleij host->bounce_addr, 3069bd9b9027SLinus Walleij host->bounce_buffer_size, 3070bd9b9027SLinus Walleij DMA_FROM_DEVICE); 3071bd9b9027SLinus Walleij sg_copy_from_buffer(data->sg, 3072bd9b9027SLinus Walleij data->sg_len, 3073bd9b9027SLinus Walleij host->bounce_buffer, 3074bd9b9027SLinus Walleij length); 3075bd9b9027SLinus Walleij } else { 3076bd9b9027SLinus Walleij /* No copying, just switch ownership */ 3077bd9b9027SLinus Walleij dma_sync_single_for_cpu( 3078bd9b9027SLinus Walleij host->mmc->parent, 3079bd9b9027SLinus Walleij host->bounce_addr, 3080bd9b9027SLinus Walleij host->bounce_buffer_size, 3081feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 3082bd9b9027SLinus Walleij } 3083bd9b9027SLinus Walleij } else { 3084bd9b9027SLinus Walleij /* Unmap the raw data */ 3085bd9b9027SLinus Walleij dma_unmap_sg(mmc_dev(host->mmc), data->sg, 3086bd9b9027SLinus Walleij data->sg_len, 3087bd9b9027SLinus Walleij mmc_get_dma_dir(data)); 3088bd9b9027SLinus Walleij } 3089054cedffSRussell King data->host_cookie = COOKIE_UNMAPPED; 3090054cedffSRussell King } 3091054cedffSRussell King } 3092054cedffSRussell King 30936ebebeabSAdrian Hunter host->mrqs_done[i] = NULL; 30946ebebeabSAdrian Hunter 30951c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 30961c6a0718SPierre Ossman 30971774b002SBaolin Wang if (host->ops->request_done) 30981774b002SBaolin Wang host->ops->request_done(host, mrq); 30991774b002SBaolin Wang else 31001c6a0718SPierre Ossman mmc_request_done(host->mmc, mrq); 31014e9f8fe5SAdrian Hunter 31024e9f8fe5SAdrian Hunter return false; 31034e9f8fe5SAdrian Hunter } 31044e9f8fe5SAdrian Hunter 3105c07a48c2SAdrian Hunter static void sdhci_complete_work(struct work_struct *work) 31064e9f8fe5SAdrian Hunter { 3107c07a48c2SAdrian Hunter struct sdhci_host *host = container_of(work, struct sdhci_host, 3108c07a48c2SAdrian Hunter complete_work); 31094e9f8fe5SAdrian Hunter 31104e9f8fe5SAdrian Hunter while (!sdhci_request_done(host)) 31114e9f8fe5SAdrian Hunter ; 31121c6a0718SPierre Ossman } 31131c6a0718SPierre Ossman 31142ee4f620SKees Cook static void sdhci_timeout_timer(struct timer_list *t) 31151c6a0718SPierre Ossman { 31161c6a0718SPierre Ossman struct sdhci_host *host; 31171c6a0718SPierre Ossman unsigned long flags; 31181c6a0718SPierre Ossman 31192ee4f620SKees Cook host = from_timer(host, t, timer); 31201c6a0718SPierre Ossman 31211c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 31221c6a0718SPierre Ossman 3123d7422fb4SAdrian Hunter if (host->cmd && !sdhci_data_line_cmd(host->cmd)) { 3124d7422fb4SAdrian Hunter pr_err("%s: Timeout waiting for hardware cmd interrupt.\n", 3125d7422fb4SAdrian Hunter mmc_hostname(host->mmc)); 3126d7422fb4SAdrian Hunter sdhci_dumpregs(host); 3127d7422fb4SAdrian Hunter 3128d7422fb4SAdrian Hunter host->cmd->error = -ETIMEDOUT; 3129d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 3130d7422fb4SAdrian Hunter } 3131d7422fb4SAdrian Hunter 3132d7422fb4SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3133d7422fb4SAdrian Hunter } 3134d7422fb4SAdrian Hunter 31352ee4f620SKees Cook static void sdhci_timeout_data_timer(struct timer_list *t) 3136d7422fb4SAdrian Hunter { 3137d7422fb4SAdrian Hunter struct sdhci_host *host; 3138d7422fb4SAdrian Hunter unsigned long flags; 3139d7422fb4SAdrian Hunter 31402ee4f620SKees Cook host = from_timer(host, t, data_timer); 3141d7422fb4SAdrian Hunter 3142d7422fb4SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3143d7422fb4SAdrian Hunter 3144d7422fb4SAdrian Hunter if (host->data || host->data_cmd || 3145d7422fb4SAdrian Hunter (host->cmd && sdhci_data_line_cmd(host->cmd))) { 31462e4456f0SMarek Vasut pr_err("%s: Timeout waiting for hardware interrupt.\n", 31472e4456f0SMarek Vasut mmc_hostname(host->mmc)); 31481c6a0718SPierre Ossman sdhci_dumpregs(host); 31491c6a0718SPierre Ossman 31501c6a0718SPierre Ossman if (host->data) { 315117b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 3152845c939eSAdrian Hunter __sdhci_finish_data(host, true); 3153c07a48c2SAdrian Hunter queue_work(host->complete_wq, &host->complete_work); 3154d7422fb4SAdrian Hunter } else if (host->data_cmd) { 3155d7422fb4SAdrian Hunter host->data_cmd->error = -ETIMEDOUT; 3156d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq); 31571c6a0718SPierre Ossman } else { 315817b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 3159d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 31601c6a0718SPierre Ossman } 31611c6a0718SPierre Ossman } 31621c6a0718SPierre Ossman 31631c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 31641c6a0718SPierre Ossman } 31651c6a0718SPierre Ossman 31661c6a0718SPierre Ossman /*****************************************************************************\ 31671c6a0718SPierre Ossman * * 31681c6a0718SPierre Ossman * Interrupt handling * 31691c6a0718SPierre Ossman * * 31701c6a0718SPierre Ossman \*****************************************************************************/ 31711c6a0718SPierre Ossman 31724bf78099SAdrian Hunter static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) 31731c6a0718SPierre Ossman { 3174af849c86SAdrian Hunter /* Handle auto-CMD12 error */ 3175af849c86SAdrian Hunter if (intmask & SDHCI_INT_AUTO_CMD_ERR && host->data_cmd) { 3176af849c86SAdrian Hunter struct mmc_request *mrq = host->data_cmd->mrq; 3177af849c86SAdrian Hunter u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); 3178af849c86SAdrian Hunter int data_err_bit = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? 3179af849c86SAdrian Hunter SDHCI_INT_DATA_TIMEOUT : 3180af849c86SAdrian Hunter SDHCI_INT_DATA_CRC; 3181af849c86SAdrian Hunter 3182af849c86SAdrian Hunter /* Treat auto-CMD12 error the same as data error */ 3183af849c86SAdrian Hunter if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) { 3184af849c86SAdrian Hunter *intmask_p |= data_err_bit; 3185af849c86SAdrian Hunter return; 3186af849c86SAdrian Hunter } 3187af849c86SAdrian Hunter } 3188af849c86SAdrian Hunter 31891c6a0718SPierre Ossman if (!host->cmd) { 3190ed1563deSAdrian Hunter /* 3191ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data 3192ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more 3193ed1563deSAdrian Hunter * interrupts, so ignore them in that case. 3194ed1563deSAdrian Hunter */ 3195ed1563deSAdrian Hunter if (host->pending_reset) 3196ed1563deSAdrian Hunter return; 31972e4456f0SMarek Vasut pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", 3198b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 31991c6a0718SPierre Ossman sdhci_dumpregs(host); 32001c6a0718SPierre Ossman return; 32011c6a0718SPierre Ossman } 32021c6a0718SPierre Ossman 3203ec014cbaSRussell King if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | 3204ec014cbaSRussell King SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { 32051c6a0718SPierre Ossman if (intmask & SDHCI_INT_TIMEOUT) 320617b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 3207ec014cbaSRussell King else 320817b0429dSPierre Ossman host->cmd->error = -EILSEQ; 32091c6a0718SPierre Ossman 32104bf78099SAdrian Hunter /* Treat data command CRC error the same as data CRC error */ 321171fcbda0SRussell King if (host->cmd->data && 321271fcbda0SRussell King (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == 321371fcbda0SRussell King SDHCI_INT_CRC) { 321471fcbda0SRussell King host->cmd = NULL; 32154bf78099SAdrian Hunter *intmask_p |= SDHCI_INT_DATA_CRC; 321671fcbda0SRussell King return; 321771fcbda0SRussell King } 321871fcbda0SRussell King 321919d2f695SAdrian Hunter __sdhci_finish_mrq(host, host->cmd->mrq); 3220e809517fSPierre Ossman return; 3221e809517fSPierre Ossman } 3222e809517fSPierre Ossman 3223af849c86SAdrian Hunter /* Handle auto-CMD23 error */ 3224af849c86SAdrian Hunter if (intmask & SDHCI_INT_AUTO_CMD_ERR) { 3225af849c86SAdrian Hunter struct mmc_request *mrq = host->cmd->mrq; 3226af849c86SAdrian Hunter u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); 3227af849c86SAdrian Hunter int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? 3228af849c86SAdrian Hunter -ETIMEDOUT : 3229af849c86SAdrian Hunter -EILSEQ; 3230af849c86SAdrian Hunter 3231af849c86SAdrian Hunter if (mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { 3232af849c86SAdrian Hunter mrq->sbc->error = err; 323319d2f695SAdrian Hunter __sdhci_finish_mrq(host, mrq); 3234af849c86SAdrian Hunter return; 3235af849c86SAdrian Hunter } 3236af849c86SAdrian Hunter } 3237af849c86SAdrian Hunter 3238e809517fSPierre Ossman if (intmask & SDHCI_INT_RESPONSE) 323943b58b36SPierre Ossman sdhci_finish_command(host); 32401c6a0718SPierre Ossman } 32411c6a0718SPierre Ossman 324208621b18SAdrian Hunter static void sdhci_adma_show_error(struct sdhci_host *host) 32436882a8c0SBen Dooks { 32441c3d5f6dSAdrian Hunter void *desc = host->adma_table; 3245d1c536e3SRussell King dma_addr_t dma = host->adma_addr; 32466882a8c0SBen Dooks 32476882a8c0SBen Dooks sdhci_dumpregs(host); 32486882a8c0SBen Dooks 32496882a8c0SBen Dooks while (true) { 3250e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 32516882a8c0SBen Dooks 3252e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 3253d1c536e3SRussell King SDHCI_DUMP("%08llx: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", 3254d1c536e3SRussell King (unsigned long long)dma, 3255d1c536e3SRussell King le32_to_cpu(dma_desc->addr_hi), 3256e57a5f61SAdrian Hunter le32_to_cpu(dma_desc->addr_lo), 3257e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->len), 3258e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->cmd)); 3259e57a5f61SAdrian Hunter else 3260d1c536e3SRussell King SDHCI_DUMP("%08llx: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", 3261d1c536e3SRussell King (unsigned long long)dma, 3262d1c536e3SRussell King le32_to_cpu(dma_desc->addr_lo), 32630545230fSAdrian Hunter le16_to_cpu(dma_desc->len), 32640545230fSAdrian Hunter le16_to_cpu(dma_desc->cmd)); 32656882a8c0SBen Dooks 326676fe379aSAdrian Hunter desc += host->desc_sz; 3267d1c536e3SRussell King dma += host->desc_sz; 32686882a8c0SBen Dooks 32690545230fSAdrian Hunter if (dma_desc->cmd & cpu_to_le16(ADMA2_END)) 32706882a8c0SBen Dooks break; 32716882a8c0SBen Dooks } 32726882a8c0SBen Dooks } 32736882a8c0SBen Dooks 32741c6a0718SPierre Ossman static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 32751c6a0718SPierre Ossman { 3276069c9f14SGirish K S u32 command; 32771c6a0718SPierre Ossman 3278b513ea25SArindam Nath /* CMD19 generates _only_ Buffer Read Ready interrupt */ 3279b513ea25SArindam Nath if (intmask & SDHCI_INT_DATA_AVAIL) { 3280069c9f14SGirish K S command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)); 3281069c9f14SGirish K S if (command == MMC_SEND_TUNING_BLOCK || 3282069c9f14SGirish K S command == MMC_SEND_TUNING_BLOCK_HS200) { 3283b513ea25SArindam Nath host->tuning_done = 1; 3284b513ea25SArindam Nath wake_up(&host->buf_ready_int); 3285b513ea25SArindam Nath return; 3286b513ea25SArindam Nath } 3287b513ea25SArindam Nath } 3288b513ea25SArindam Nath 32891c6a0718SPierre Ossman if (!host->data) { 32907c89a3d9SAdrian Hunter struct mmc_command *data_cmd = host->data_cmd; 32917c89a3d9SAdrian Hunter 32921c6a0718SPierre Ossman /* 3293e809517fSPierre Ossman * The "data complete" interrupt is also used to 3294e809517fSPierre Ossman * indicate that a busy state has ended. See comment 3295e809517fSPierre Ossman * above in sdhci_cmd_irq(). 32961c6a0718SPierre Ossman */ 32977c89a3d9SAdrian Hunter if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) { 3298c5abd5e8SMatthieu CASTET if (intmask & SDHCI_INT_DATA_TIMEOUT) { 329969b962a6SAdrian Hunter host->data_cmd = NULL; 33007c89a3d9SAdrian Hunter data_cmd->error = -ETIMEDOUT; 330119d2f695SAdrian Hunter __sdhci_finish_mrq(host, data_cmd->mrq); 3302c5abd5e8SMatthieu CASTET return; 3303c5abd5e8SMatthieu CASTET } 3304e809517fSPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 330569b962a6SAdrian Hunter host->data_cmd = NULL; 3306e99783a4SChanho Min /* 3307e99783a4SChanho Min * Some cards handle busy-end interrupt 3308e99783a4SChanho Min * before the command completed, so make 3309e99783a4SChanho Min * sure we do things in the proper order. 3310e99783a4SChanho Min */ 3311ea968023SAdrian Hunter if (host->cmd == data_cmd) 3312ea968023SAdrian Hunter return; 3313ea968023SAdrian Hunter 331419d2f695SAdrian Hunter __sdhci_finish_mrq(host, data_cmd->mrq); 33151c6a0718SPierre Ossman return; 3316e809517fSPierre Ossman } 3317e809517fSPierre Ossman } 33181c6a0718SPierre Ossman 3319ed1563deSAdrian Hunter /* 3320ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data 3321ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more 3322ed1563deSAdrian Hunter * interrupts, so ignore them in that case. 3323ed1563deSAdrian Hunter */ 3324ed1563deSAdrian Hunter if (host->pending_reset) 3325ed1563deSAdrian Hunter return; 3326ed1563deSAdrian Hunter 33272e4456f0SMarek Vasut pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n", 3328b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 33291c6a0718SPierre Ossman sdhci_dumpregs(host); 33301c6a0718SPierre Ossman 33311c6a0718SPierre Ossman return; 33321c6a0718SPierre Ossman } 33331c6a0718SPierre Ossman 33341c6a0718SPierre Ossman if (intmask & SDHCI_INT_DATA_TIMEOUT) 333517b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 333622113efdSAries Lee else if (intmask & SDHCI_INT_DATA_END_BIT) 333722113efdSAries Lee host->data->error = -EILSEQ; 333822113efdSAries Lee else if ((intmask & SDHCI_INT_DATA_CRC) && 333922113efdSAries Lee SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) 334022113efdSAries Lee != MMC_BUS_TEST_R) 334117b0429dSPierre Ossman host->data->error = -EILSEQ; 33426882a8c0SBen Dooks else if (intmask & SDHCI_INT_ADMA_ERROR) { 3343d1c536e3SRussell King pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), 3344d1c536e3SRussell King intmask); 334508621b18SAdrian Hunter sdhci_adma_show_error(host); 33462134a922SPierre Ossman host->data->error = -EIO; 3347a4071fbbSHaijun Zhang if (host->ops->adma_workaround) 3348a4071fbbSHaijun Zhang host->ops->adma_workaround(host, intmask); 33496882a8c0SBen Dooks } 33501c6a0718SPierre Ossman 335117b0429dSPierre Ossman if (host->data->error) 33521c6a0718SPierre Ossman sdhci_finish_data(host); 33531c6a0718SPierre Ossman else { 33541c6a0718SPierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 33551c6a0718SPierre Ossman sdhci_transfer_pio(host); 33561c6a0718SPierre Ossman 33576ba736a1SPierre Ossman /* 33586ba736a1SPierre Ossman * We currently don't do anything fancy with DMA 33596ba736a1SPierre Ossman * boundaries, but as we can't disable the feature 33606ba736a1SPierre Ossman * we need to at least restart the transfer. 3361f6a03cbfSMikko Vinni * 3362f6a03cbfSMikko Vinni * According to the spec sdhci_readl(host, SDHCI_DMA_ADDRESS) 3363f6a03cbfSMikko Vinni * should return a valid address to continue from, but as 3364f6a03cbfSMikko Vinni * some controllers are faulty, don't trust them. 33656ba736a1SPierre Ossman */ 3366f6a03cbfSMikko Vinni if (intmask & SDHCI_INT_DMA_END) { 3367917a0c52SChunyan Zhang dma_addr_t dmastart, dmanow; 3368bd9b9027SLinus Walleij 3369bd9b9027SLinus Walleij dmastart = sdhci_sdma_address(host); 3370f6a03cbfSMikko Vinni dmanow = dmastart + host->data->bytes_xfered; 3371f6a03cbfSMikko Vinni /* 3372f6a03cbfSMikko Vinni * Force update to the next DMA block boundary. 3373f6a03cbfSMikko Vinni */ 3374f6a03cbfSMikko Vinni dmanow = (dmanow & 3375917a0c52SChunyan Zhang ~((dma_addr_t)SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 3376f6a03cbfSMikko Vinni SDHCI_DEFAULT_BOUNDARY_SIZE; 3377f6a03cbfSMikko Vinni host->data->bytes_xfered = dmanow - dmastart; 3378917a0c52SChunyan Zhang DBG("DMA base %pad, transferred 0x%06x bytes, next %pad\n", 3379917a0c52SChunyan Zhang &dmastart, host->data->bytes_xfered, &dmanow); 3380917a0c52SChunyan Zhang sdhci_set_sdma_addr(host, dmanow); 3381f6a03cbfSMikko Vinni } 33826ba736a1SPierre Ossman 3383e538fbe8SPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 33847c89a3d9SAdrian Hunter if (host->cmd == host->data_cmd) { 3385e538fbe8SPierre Ossman /* 3386e538fbe8SPierre Ossman * Data managed to finish before the 3387e538fbe8SPierre Ossman * command completed. Make sure we do 3388e538fbe8SPierre Ossman * things in the proper order. 3389e538fbe8SPierre Ossman */ 3390e538fbe8SPierre Ossman host->data_early = 1; 3391e538fbe8SPierre Ossman } else { 33921c6a0718SPierre Ossman sdhci_finish_data(host); 33931c6a0718SPierre Ossman } 33941c6a0718SPierre Ossman } 3395e538fbe8SPierre Ossman } 3396e538fbe8SPierre Ossman } 33971c6a0718SPierre Ossman 339819d2f695SAdrian Hunter static inline bool sdhci_defer_done(struct sdhci_host *host, 339919d2f695SAdrian Hunter struct mmc_request *mrq) 340019d2f695SAdrian Hunter { 340119d2f695SAdrian Hunter struct mmc_data *data = mrq->data; 340219d2f695SAdrian Hunter 34034730831cSBaolin Wang return host->pending_reset || host->always_defer_done || 340419d2f695SAdrian Hunter ((host->flags & SDHCI_REQ_USE_DMA) && data && 340519d2f695SAdrian Hunter data->host_cookie == COOKIE_MAPPED); 340619d2f695SAdrian Hunter } 340719d2f695SAdrian Hunter 34081c6a0718SPierre Ossman static irqreturn_t sdhci_irq(int irq, void *dev_id) 34091c6a0718SPierre Ossman { 341019d2f695SAdrian Hunter struct mmc_request *mrqs_done[SDHCI_MAX_MRQS] = {0}; 3411781e989cSRussell King irqreturn_t result = IRQ_NONE; 34121c6a0718SPierre Ossman struct sdhci_host *host = dev_id; 341341005003SRussell King u32 intmask, mask, unexpected = 0; 3414781e989cSRussell King int max_loops = 16; 341519d2f695SAdrian Hunter int i; 34161c6a0718SPierre Ossman 34171c6a0718SPierre Ossman spin_lock(&host->lock); 34181c6a0718SPierre Ossman 3419af5d2b7bSUlf Hansson if (host->runtime_suspended) { 342066fd8ad5SAdrian Hunter spin_unlock(&host->lock); 3421655bca76SAdrian Hunter return IRQ_NONE; 342266fd8ad5SAdrian Hunter } 342366fd8ad5SAdrian Hunter 34244e4141a5SAnton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS); 34251c6a0718SPierre Ossman if (!intmask || intmask == 0xffffffff) { 34261c6a0718SPierre Ossman result = IRQ_NONE; 34271c6a0718SPierre Ossman goto out; 34281c6a0718SPierre Ossman } 34291c6a0718SPierre Ossman 343041005003SRussell King do { 3431f12e39dbSAdrian Hunter DBG("IRQ status 0x%08x\n", intmask); 3432f12e39dbSAdrian Hunter 3433f12e39dbSAdrian Hunter if (host->ops->irq) { 3434f12e39dbSAdrian Hunter intmask = host->ops->irq(host, intmask); 3435f12e39dbSAdrian Hunter if (!intmask) 3436f12e39dbSAdrian Hunter goto cont; 3437f12e39dbSAdrian Hunter } 3438f12e39dbSAdrian Hunter 343941005003SRussell King /* Clear selected interrupts. */ 344041005003SRussell King mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 344141005003SRussell King SDHCI_INT_BUS_POWER); 344241005003SRussell King sdhci_writel(host, mask, SDHCI_INT_STATUS); 344341005003SRussell King 34441c6a0718SPierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 3445d25928d1SShawn Guo u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 3446d25928d1SShawn Guo SDHCI_CARD_PRESENT; 3447d25928d1SShawn Guo 3448d25928d1SShawn Guo /* 344941005003SRussell King * There is a observation on i.mx esdhc. INSERT 345041005003SRussell King * bit will be immediately set again when it gets 345141005003SRussell King * cleared, if a card is inserted. We have to mask 345241005003SRussell King * the irq to prevent interrupt storm which will 345341005003SRussell King * freeze the system. And the REMOVE gets the 345441005003SRussell King * same situation. 3455d25928d1SShawn Guo * 345641005003SRussell King * More testing are needed here to ensure it works 345741005003SRussell King * for other platforms though. 3458d25928d1SShawn Guo */ 3459b537f94cSRussell King host->ier &= ~(SDHCI_INT_CARD_INSERT | 3460d25928d1SShawn Guo SDHCI_INT_CARD_REMOVE); 3461b537f94cSRussell King host->ier |= present ? SDHCI_INT_CARD_REMOVE : 3462b537f94cSRussell King SDHCI_INT_CARD_INSERT; 3463b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3464b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 3465d25928d1SShawn Guo 34664e4141a5SAnton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | 34674e4141a5SAnton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); 34683560db8eSRussell King 34693560db8eSRussell King host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT | 34703560db8eSRussell King SDHCI_INT_CARD_REMOVE); 34713560db8eSRussell King result = IRQ_WAKE_THREAD; 34721c6a0718SPierre Ossman } 34731c6a0718SPierre Ossman 347441005003SRussell King if (intmask & SDHCI_INT_CMD_MASK) 34754bf78099SAdrian Hunter sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask); 34761c6a0718SPierre Ossman 347741005003SRussell King if (intmask & SDHCI_INT_DATA_MASK) 34781c6a0718SPierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 34791c6a0718SPierre Ossman 348041005003SRussell King if (intmask & SDHCI_INT_BUS_POWER) 3481a3c76eb9SGirish K S pr_err("%s: Card is consuming too much power!\n", 34821c6a0718SPierre Ossman mmc_hostname(host->mmc)); 34831c6a0718SPierre Ossman 3484f37b20ebSDong Aisheng if (intmask & SDHCI_INT_RETUNE) 3485f37b20ebSDong Aisheng mmc_retune_needed(host->mmc); 3486f37b20ebSDong Aisheng 3487161e6d44SGabriel Krisman Bertazi if ((intmask & SDHCI_INT_CARD_INT) && 3488161e6d44SGabriel Krisman Bertazi (host->ier & SDHCI_INT_CARD_INT)) { 3489781e989cSRussell King sdhci_enable_sdio_irq_nolock(host, false); 349089f3c365SAdrian Hunter sdio_signal_irq(host->mmc); 3491781e989cSRussell King } 3492f75979b7SPierre Ossman 349341005003SRussell King intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | 349441005003SRussell King SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 349541005003SRussell King SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | 3496f37b20ebSDong Aisheng SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT); 3497f75979b7SPierre Ossman 34981c6a0718SPierre Ossman if (intmask) { 34996379b237SAlexander Stein unexpected |= intmask; 35004e4141a5SAnton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS); 35011c6a0718SPierre Ossman } 3502f12e39dbSAdrian Hunter cont: 3503781e989cSRussell King if (result == IRQ_NONE) 35041c6a0718SPierre Ossman result = IRQ_HANDLED; 35051c6a0718SPierre Ossman 35066379b237SAlexander Stein intmask = sdhci_readl(host, SDHCI_INT_STATUS); 350741005003SRussell King } while (intmask && --max_loops); 350819d2f695SAdrian Hunter 350919d2f695SAdrian Hunter /* Determine if mrqs can be completed immediately */ 351019d2f695SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 351119d2f695SAdrian Hunter struct mmc_request *mrq = host->mrqs_done[i]; 351219d2f695SAdrian Hunter 351319d2f695SAdrian Hunter if (!mrq) 351419d2f695SAdrian Hunter continue; 351519d2f695SAdrian Hunter 351619d2f695SAdrian Hunter if (sdhci_defer_done(host, mrq)) { 3517c07a48c2SAdrian Hunter result = IRQ_WAKE_THREAD; 351819d2f695SAdrian Hunter } else { 351919d2f695SAdrian Hunter mrqs_done[i] = mrq; 352019d2f695SAdrian Hunter host->mrqs_done[i] = NULL; 352119d2f695SAdrian Hunter } 352219d2f695SAdrian Hunter } 35231c6a0718SPierre Ossman out: 3524845c939eSAdrian Hunter if (host->deferred_cmd) 3525845c939eSAdrian Hunter result = IRQ_WAKE_THREAD; 3526845c939eSAdrian Hunter 35271c6a0718SPierre Ossman spin_unlock(&host->lock); 35281c6a0718SPierre Ossman 352919d2f695SAdrian Hunter /* Process mrqs ready for immediate completion */ 353019d2f695SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 35311774b002SBaolin Wang if (!mrqs_done[i]) 35321774b002SBaolin Wang continue; 35331774b002SBaolin Wang 35341774b002SBaolin Wang if (host->ops->request_done) 35351774b002SBaolin Wang host->ops->request_done(host, mrqs_done[i]); 35361774b002SBaolin Wang else 353719d2f695SAdrian Hunter mmc_request_done(host->mmc, mrqs_done[i]); 353819d2f695SAdrian Hunter } 353919d2f695SAdrian Hunter 35406379b237SAlexander Stein if (unexpected) { 35416379b237SAlexander Stein pr_err("%s: Unexpected interrupt 0x%08x.\n", 35426379b237SAlexander Stein mmc_hostname(host->mmc), unexpected); 35436379b237SAlexander Stein sdhci_dumpregs(host); 35446379b237SAlexander Stein } 3545f75979b7SPierre Ossman 35461c6a0718SPierre Ossman return result; 35471c6a0718SPierre Ossman } 35481c6a0718SPierre Ossman 3549781e989cSRussell King static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) 3550781e989cSRussell King { 3551781e989cSRussell King struct sdhci_host *host = dev_id; 3552845c939eSAdrian Hunter struct mmc_command *cmd; 3553781e989cSRussell King unsigned long flags; 3554781e989cSRussell King u32 isr; 3555781e989cSRussell King 3556c07a48c2SAdrian Hunter while (!sdhci_request_done(host)) 3557c07a48c2SAdrian Hunter ; 3558c07a48c2SAdrian Hunter 3559781e989cSRussell King spin_lock_irqsave(&host->lock, flags); 3560845c939eSAdrian Hunter 3561781e989cSRussell King isr = host->thread_isr; 3562781e989cSRussell King host->thread_isr = 0; 3563845c939eSAdrian Hunter 3564845c939eSAdrian Hunter cmd = host->deferred_cmd; 3565845c939eSAdrian Hunter if (cmd && !sdhci_send_command_retry(host, cmd, flags)) 3566845c939eSAdrian Hunter sdhci_finish_mrq(host, cmd->mrq); 3567845c939eSAdrian Hunter 3568781e989cSRussell King spin_unlock_irqrestore(&host->lock, flags); 3569781e989cSRussell King 35703560db8eSRussell King if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 3571d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 3572d3940f27SAdrian Hunter 3573d3940f27SAdrian Hunter mmc->ops->card_event(mmc); 3574d3940f27SAdrian Hunter mmc_detect_change(mmc, msecs_to_jiffies(200)); 35753560db8eSRussell King } 35763560db8eSRussell King 3577c07a48c2SAdrian Hunter return IRQ_HANDLED; 3578781e989cSRussell King } 3579781e989cSRussell King 35801c6a0718SPierre Ossman /*****************************************************************************\ 35811c6a0718SPierre Ossman * * 35821c6a0718SPierre Ossman * Suspend/resume * 35831c6a0718SPierre Ossman * * 35841c6a0718SPierre Ossman \*****************************************************************************/ 35851c6a0718SPierre Ossman 35861c6a0718SPierre Ossman #ifdef CONFIG_PM 35879c316b38SAdrian Hunter 35889c316b38SAdrian Hunter static bool sdhci_cd_irq_can_wakeup(struct sdhci_host *host) 35899c316b38SAdrian Hunter { 35909c316b38SAdrian Hunter return mmc_card_is_removable(host->mmc) && 35919c316b38SAdrian Hunter !(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 35929c316b38SAdrian Hunter !mmc_can_gpio_cd(host->mmc); 35939c316b38SAdrian Hunter } 35949c316b38SAdrian Hunter 359584d62605SLudovic Desroches /* 359684d62605SLudovic Desroches * To enable wakeup events, the corresponding events have to be enabled in 359784d62605SLudovic Desroches * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal 359884d62605SLudovic Desroches * Table' in the SD Host Controller Standard Specification. 359984d62605SLudovic Desroches * It is useless to restore SDHCI_INT_ENABLE state in 360084d62605SLudovic Desroches * sdhci_disable_irq_wakeups() since it will be set by 360184d62605SLudovic Desroches * sdhci_enable_card_detection() or sdhci_init(). 360284d62605SLudovic Desroches */ 360358e79b60SAdrian Hunter static bool sdhci_enable_irq_wakeups(struct sdhci_host *host) 3604ad080d79SKevin Liu { 360581b14543SAdrian Hunter u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE | 360681b14543SAdrian Hunter SDHCI_WAKE_ON_INT; 360781b14543SAdrian Hunter u32 irq_val = 0; 360881b14543SAdrian Hunter u8 wake_val = 0; 3609ad080d79SKevin Liu u8 val; 361081b14543SAdrian Hunter 36119c316b38SAdrian Hunter if (sdhci_cd_irq_can_wakeup(host)) { 361281b14543SAdrian Hunter wake_val |= SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE; 361381b14543SAdrian Hunter irq_val |= SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE; 361481b14543SAdrian Hunter } 361581b14543SAdrian Hunter 3616d5d568faSAdrian Hunter if (mmc_card_wake_sdio_irq(host->mmc)) { 361781b14543SAdrian Hunter wake_val |= SDHCI_WAKE_ON_INT; 361881b14543SAdrian Hunter irq_val |= SDHCI_INT_CARD_INT; 3619d5d568faSAdrian Hunter } 3620d5d568faSAdrian Hunter 3621d5d568faSAdrian Hunter if (!irq_val) 3622d5d568faSAdrian Hunter return false; 3623ad080d79SKevin Liu 3624ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 362581b14543SAdrian Hunter val &= ~mask; 362681b14543SAdrian Hunter val |= wake_val; 3627ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 362881b14543SAdrian Hunter 362984d62605SLudovic Desroches sdhci_writel(host, irq_val, SDHCI_INT_ENABLE); 363058e79b60SAdrian Hunter 363158e79b60SAdrian Hunter host->irq_wake_enabled = !enable_irq_wake(host->irq); 363258e79b60SAdrian Hunter 363358e79b60SAdrian Hunter return host->irq_wake_enabled; 3634ad080d79SKevin Liu } 3635ad080d79SKevin Liu 36360b10f478SFabio Estevam static void sdhci_disable_irq_wakeups(struct sdhci_host *host) 3637ad080d79SKevin Liu { 3638ad080d79SKevin Liu u8 val; 3639ad080d79SKevin Liu u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE 3640ad080d79SKevin Liu | SDHCI_WAKE_ON_INT; 3641ad080d79SKevin Liu 3642ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 3643ad080d79SKevin Liu val &= ~mask; 3644ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 364558e79b60SAdrian Hunter 364658e79b60SAdrian Hunter disable_irq_wake(host->irq); 364758e79b60SAdrian Hunter 364858e79b60SAdrian Hunter host->irq_wake_enabled = false; 3649ad080d79SKevin Liu } 36501c6a0718SPierre Ossman 365129495aa0SManuel Lauss int sdhci_suspend_host(struct sdhci_host *host) 36521c6a0718SPierre Ossman { 36537260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 36547260cf5eSAnton Vorontsov 365566c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc); 3656cf2b5eeaSArindam Nath 365758e79b60SAdrian Hunter if (!device_may_wakeup(mmc_dev(host->mmc)) || 365858e79b60SAdrian Hunter !sdhci_enable_irq_wakeups(host)) { 3659b537f94cSRussell King host->ier = 0; 3660b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 3661b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 3662b8c86fc5SPierre Ossman free_irq(host->irq, host); 3663ad080d79SKevin Liu } 366458e79b60SAdrian Hunter 36654ee14ec6SUlf Hansson return 0; 3666b8c86fc5SPierre Ossman } 3667b8c86fc5SPierre Ossman 3668b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_suspend_host); 3669b8c86fc5SPierre Ossman 3670b8c86fc5SPierre Ossman int sdhci_resume_host(struct sdhci_host *host) 3671b8c86fc5SPierre Ossman { 3672d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 36734ee14ec6SUlf Hansson int ret = 0; 3674b8c86fc5SPierre Ossman 3675a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 3676b8c86fc5SPierre Ossman if (host->ops->enable_dma) 3677b8c86fc5SPierre Ossman host->ops->enable_dma(host); 3678b8c86fc5SPierre Ossman } 3679b8c86fc5SPierre Ossman 36806308d290SAdrian Hunter if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) && 36816308d290SAdrian Hunter (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) { 36826308d290SAdrian Hunter /* Card keeps power but host controller does not */ 36836308d290SAdrian Hunter sdhci_init(host, 0); 36846308d290SAdrian Hunter host->pwr = 0; 36856308d290SAdrian Hunter host->clock = 0; 3686d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 36876308d290SAdrian Hunter } else { 36882f4cbb3dSNicolas Pitre sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); 36896308d290SAdrian Hunter } 3690b8c86fc5SPierre Ossman 369158e79b60SAdrian Hunter if (host->irq_wake_enabled) { 369258e79b60SAdrian Hunter sdhci_disable_irq_wakeups(host); 369358e79b60SAdrian Hunter } else { 369414a7b416SHaibo Chen ret = request_threaded_irq(host->irq, sdhci_irq, 369514a7b416SHaibo Chen sdhci_thread_irq, IRQF_SHARED, 369614a7b416SHaibo Chen mmc_hostname(host->mmc), host); 369714a7b416SHaibo Chen if (ret) 369814a7b416SHaibo Chen return ret; 369914a7b416SHaibo Chen } 370014a7b416SHaibo Chen 37017260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 37027260cf5eSAnton Vorontsov 37032f4cbb3dSNicolas Pitre return ret; 37041c6a0718SPierre Ossman } 37051c6a0718SPierre Ossman 3706b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_resume_host); 370766fd8ad5SAdrian Hunter 370866fd8ad5SAdrian Hunter int sdhci_runtime_suspend_host(struct sdhci_host *host) 370966fd8ad5SAdrian Hunter { 371066fd8ad5SAdrian Hunter unsigned long flags; 371166fd8ad5SAdrian Hunter 371266c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc); 371366fd8ad5SAdrian Hunter 371466fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3715b537f94cSRussell King host->ier &= SDHCI_INT_CARD_INT; 3716b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3717b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 371866fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 371966fd8ad5SAdrian Hunter 3720781e989cSRussell King synchronize_hardirq(host->irq); 372166fd8ad5SAdrian Hunter 372266fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 372366fd8ad5SAdrian Hunter host->runtime_suspended = true; 372466fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 372566fd8ad5SAdrian Hunter 37268a125badSMarkus Pargmann return 0; 372766fd8ad5SAdrian Hunter } 372866fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host); 372966fd8ad5SAdrian Hunter 3730c6303c5dSBaolin Wang int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset) 373166fd8ad5SAdrian Hunter { 3732d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 373366fd8ad5SAdrian Hunter unsigned long flags; 37348a125badSMarkus Pargmann int host_flags = host->flags; 373566fd8ad5SAdrian Hunter 373666fd8ad5SAdrian Hunter if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 373766fd8ad5SAdrian Hunter if (host->ops->enable_dma) 373866fd8ad5SAdrian Hunter host->ops->enable_dma(host); 373966fd8ad5SAdrian Hunter } 374066fd8ad5SAdrian Hunter 3741c6303c5dSBaolin Wang sdhci_init(host, soft_reset); 374266fd8ad5SAdrian Hunter 374370bc85adSZhoujie Wu if (mmc->ios.power_mode != MMC_POWER_UNDEFINED && 374470bc85adSZhoujie Wu mmc->ios.power_mode != MMC_POWER_OFF) { 374566fd8ad5SAdrian Hunter /* Force clock and power re-program */ 374666fd8ad5SAdrian Hunter host->pwr = 0; 374766fd8ad5SAdrian Hunter host->clock = 0; 3748d3940f27SAdrian Hunter mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios); 3749d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 375066fd8ad5SAdrian Hunter 375152983382SKevin Liu if ((host_flags & SDHCI_PV_ENABLED) && 375252983382SKevin Liu !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { 375352983382SKevin Liu spin_lock_irqsave(&host->lock, flags); 375452983382SKevin Liu sdhci_enable_preset_value(host, true); 375552983382SKevin Liu spin_unlock_irqrestore(&host->lock, flags); 375652983382SKevin Liu } 375766fd8ad5SAdrian Hunter 3758086b0ddbSAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HS400_ES) && 3759086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe) 3760086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios); 376184ec048bSAdrian Hunter } 3762086b0ddbSAdrian Hunter 376366fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 376466fd8ad5SAdrian Hunter 376566fd8ad5SAdrian Hunter host->runtime_suspended = false; 376666fd8ad5SAdrian Hunter 376766fd8ad5SAdrian Hunter /* Enable SDIO IRQ */ 37680e62614bSUlf Hansson if (sdio_irq_claimed(mmc)) 376966fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true); 377066fd8ad5SAdrian Hunter 377166fd8ad5SAdrian Hunter /* Enable Card Detection */ 377266fd8ad5SAdrian Hunter sdhci_enable_card_detection(host); 377366fd8ad5SAdrian Hunter 377466fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 377566fd8ad5SAdrian Hunter 37768a125badSMarkus Pargmann return 0; 377766fd8ad5SAdrian Hunter } 377866fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host); 377966fd8ad5SAdrian Hunter 3780162d6f98SRafael J. Wysocki #endif /* CONFIG_PM */ 378166fd8ad5SAdrian Hunter 37821c6a0718SPierre Ossman /*****************************************************************************\ 37831c6a0718SPierre Ossman * * 3784f12e39dbSAdrian Hunter * Command Queue Engine (CQE) helpers * 3785f12e39dbSAdrian Hunter * * 3786f12e39dbSAdrian Hunter \*****************************************************************************/ 3787f12e39dbSAdrian Hunter 3788f12e39dbSAdrian Hunter void sdhci_cqe_enable(struct mmc_host *mmc) 3789f12e39dbSAdrian Hunter { 3790f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 3791f12e39dbSAdrian Hunter unsigned long flags; 3792f12e39dbSAdrian Hunter u8 ctrl; 3793f12e39dbSAdrian Hunter 3794f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3795f12e39dbSAdrian Hunter 3796f12e39dbSAdrian Hunter ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 3797f12e39dbSAdrian Hunter ctrl &= ~SDHCI_CTRL_DMA_MASK; 37984c4faff6SSowjanya Komatineni /* 37994c4faff6SSowjanya Komatineni * Host from V4.10 supports ADMA3 DMA type. 38004c4faff6SSowjanya Komatineni * ADMA3 performs integrated descriptor which is more suitable 38014c4faff6SSowjanya Komatineni * for cmd queuing to fetch both command and transfer descriptors. 38024c4faff6SSowjanya Komatineni */ 38034c4faff6SSowjanya Komatineni if (host->v4_mode && (host->caps1 & SDHCI_CAN_DO_ADMA3)) 38044c4faff6SSowjanya Komatineni ctrl |= SDHCI_CTRL_ADMA3; 38054c4faff6SSowjanya Komatineni else if (host->flags & SDHCI_USE_64_BIT_DMA) 3806f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA64; 3807f12e39dbSAdrian Hunter else 3808f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA32; 3809f12e39dbSAdrian Hunter sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 3810f12e39dbSAdrian Hunter 3811c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(host->sdma_boundary, 512), 3812f12e39dbSAdrian Hunter SDHCI_BLOCK_SIZE); 3813f12e39dbSAdrian Hunter 3814f12e39dbSAdrian Hunter /* Set maximum timeout */ 3815401059dfSBOUGH CHEN sdhci_set_timeout(host, NULL); 3816f12e39dbSAdrian Hunter 3817f12e39dbSAdrian Hunter host->ier = host->cqe_ier; 3818f12e39dbSAdrian Hunter 3819f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3820f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 3821f12e39dbSAdrian Hunter 3822f12e39dbSAdrian Hunter host->cqe_on = true; 3823f12e39dbSAdrian Hunter 3824f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE on, IRQ mask %#x, IRQ status %#x\n", 3825f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier, 3826f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS)); 3827f12e39dbSAdrian Hunter 3828f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3829f12e39dbSAdrian Hunter } 3830f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_enable); 3831f12e39dbSAdrian Hunter 3832f12e39dbSAdrian Hunter void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery) 3833f12e39dbSAdrian Hunter { 3834f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 3835f12e39dbSAdrian Hunter unsigned long flags; 3836f12e39dbSAdrian Hunter 3837f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3838f12e39dbSAdrian Hunter 3839f12e39dbSAdrian Hunter sdhci_set_default_irqs(host); 3840f12e39dbSAdrian Hunter 3841f12e39dbSAdrian Hunter host->cqe_on = false; 3842f12e39dbSAdrian Hunter 3843f12e39dbSAdrian Hunter if (recovery) { 3844f12e39dbSAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD); 3845f12e39dbSAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 3846f12e39dbSAdrian Hunter } 3847f12e39dbSAdrian Hunter 3848f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE off, IRQ mask %#x, IRQ status %#x\n", 3849f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier, 3850f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS)); 3851f12e39dbSAdrian Hunter 3852f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3853f12e39dbSAdrian Hunter } 3854f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_disable); 3855f12e39dbSAdrian Hunter 3856f12e39dbSAdrian Hunter bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, 3857f12e39dbSAdrian Hunter int *data_error) 3858f12e39dbSAdrian Hunter { 3859f12e39dbSAdrian Hunter u32 mask; 3860f12e39dbSAdrian Hunter 3861f12e39dbSAdrian Hunter if (!host->cqe_on) 3862f12e39dbSAdrian Hunter return false; 3863f12e39dbSAdrian Hunter 3864f12e39dbSAdrian Hunter if (intmask & (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC)) 3865f12e39dbSAdrian Hunter *cmd_error = -EILSEQ; 3866f12e39dbSAdrian Hunter else if (intmask & SDHCI_INT_TIMEOUT) 3867f12e39dbSAdrian Hunter *cmd_error = -ETIMEDOUT; 3868f12e39dbSAdrian Hunter else 3869f12e39dbSAdrian Hunter *cmd_error = 0; 3870f12e39dbSAdrian Hunter 3871f12e39dbSAdrian Hunter if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) 3872f12e39dbSAdrian Hunter *data_error = -EILSEQ; 3873f12e39dbSAdrian Hunter else if (intmask & SDHCI_INT_DATA_TIMEOUT) 3874f12e39dbSAdrian Hunter *data_error = -ETIMEDOUT; 3875f12e39dbSAdrian Hunter else if (intmask & SDHCI_INT_ADMA_ERROR) 3876f12e39dbSAdrian Hunter *data_error = -EIO; 3877f12e39dbSAdrian Hunter else 3878f12e39dbSAdrian Hunter *data_error = 0; 3879f12e39dbSAdrian Hunter 3880f12e39dbSAdrian Hunter /* Clear selected interrupts. */ 3881f12e39dbSAdrian Hunter mask = intmask & host->cqe_ier; 3882f12e39dbSAdrian Hunter sdhci_writel(host, mask, SDHCI_INT_STATUS); 3883f12e39dbSAdrian Hunter 3884f12e39dbSAdrian Hunter if (intmask & SDHCI_INT_BUS_POWER) 3885f12e39dbSAdrian Hunter pr_err("%s: Card is consuming too much power!\n", 3886f12e39dbSAdrian Hunter mmc_hostname(host->mmc)); 3887f12e39dbSAdrian Hunter 3888f12e39dbSAdrian Hunter intmask &= ~(host->cqe_ier | SDHCI_INT_ERROR); 3889f12e39dbSAdrian Hunter if (intmask) { 3890f12e39dbSAdrian Hunter sdhci_writel(host, intmask, SDHCI_INT_STATUS); 3891f12e39dbSAdrian Hunter pr_err("%s: CQE: Unexpected interrupt 0x%08x.\n", 3892f12e39dbSAdrian Hunter mmc_hostname(host->mmc), intmask); 3893f12e39dbSAdrian Hunter sdhci_dumpregs(host); 3894f12e39dbSAdrian Hunter } 3895f12e39dbSAdrian Hunter 3896f12e39dbSAdrian Hunter return true; 3897f12e39dbSAdrian Hunter } 3898f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_irq); 3899f12e39dbSAdrian Hunter 3900f12e39dbSAdrian Hunter /*****************************************************************************\ 3901f12e39dbSAdrian Hunter * * 3902b8c86fc5SPierre Ossman * Device allocation/registration * 39031c6a0718SPierre Ossman * * 39041c6a0718SPierre Ossman \*****************************************************************************/ 39051c6a0718SPierre Ossman 3906b8c86fc5SPierre Ossman struct sdhci_host *sdhci_alloc_host(struct device *dev, 3907b8c86fc5SPierre Ossman size_t priv_size) 39081c6a0718SPierre Ossman { 39091c6a0718SPierre Ossman struct mmc_host *mmc; 39101c6a0718SPierre Ossman struct sdhci_host *host; 39111c6a0718SPierre Ossman 3912b8c86fc5SPierre Ossman WARN_ON(dev == NULL); 39131c6a0718SPierre Ossman 3914b8c86fc5SPierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 39151c6a0718SPierre Ossman if (!mmc) 3916b8c86fc5SPierre Ossman return ERR_PTR(-ENOMEM); 39171c6a0718SPierre Ossman 39181c6a0718SPierre Ossman host = mmc_priv(mmc); 39191c6a0718SPierre Ossman host->mmc = mmc; 3920bf60e592SAdrian Hunter host->mmc_host_ops = sdhci_ops; 3921bf60e592SAdrian Hunter mmc->ops = &host->mmc_host_ops; 39221c6a0718SPierre Ossman 39238cb851a4SAdrian Hunter host->flags = SDHCI_SIGNALING_330; 39248cb851a4SAdrian Hunter 3925f12e39dbSAdrian Hunter host->cqe_ier = SDHCI_CQE_INT_MASK; 3926f12e39dbSAdrian Hunter host->cqe_err_ier = SDHCI_CQE_INT_ERR_MASK; 3927f12e39dbSAdrian Hunter 392883b600b8SAdrian Hunter host->tuning_delay = -1; 39291d8cd065SSowjanya Komatineni host->tuning_loop_count = MAX_TUNING_LOOP; 393083b600b8SAdrian Hunter 3931c846a00fSSrinivas Kandagatla host->sdma_boundary = SDHCI_DEFAULT_BOUNDARY_ARG; 3932c846a00fSSrinivas Kandagatla 3933e93be38aSJisheng Zhang /* 3934e93be38aSJisheng Zhang * The DMA table descriptor count is calculated as the maximum 3935e93be38aSJisheng Zhang * number of segments times 2, to allow for an alignment 3936e93be38aSJisheng Zhang * descriptor for each segment, plus 1 for a nop end descriptor. 3937e93be38aSJisheng Zhang */ 3938e93be38aSJisheng Zhang host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1; 3939e93be38aSJisheng Zhang 3940b8c86fc5SPierre Ossman return host; 39411c6a0718SPierre Ossman } 39421c6a0718SPierre Ossman 3943b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_alloc_host); 3944b8c86fc5SPierre Ossman 39457b91369bSAlexandre Courbot static int sdhci_set_dma_mask(struct sdhci_host *host) 39467b91369bSAlexandre Courbot { 39477b91369bSAlexandre Courbot struct mmc_host *mmc = host->mmc; 39487b91369bSAlexandre Courbot struct device *dev = mmc_dev(mmc); 39497b91369bSAlexandre Courbot int ret = -EINVAL; 39507b91369bSAlexandre Courbot 39517b91369bSAlexandre Courbot if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) 39527b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA; 39537b91369bSAlexandre Courbot 39547b91369bSAlexandre Courbot /* Try 64-bit mask if hardware is capable of it */ 39557b91369bSAlexandre Courbot if (host->flags & SDHCI_USE_64_BIT_DMA) { 39567b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 39577b91369bSAlexandre Courbot if (ret) { 39587b91369bSAlexandre Courbot pr_warn("%s: Failed to set 64-bit DMA mask.\n", 39597b91369bSAlexandre Courbot mmc_hostname(mmc)); 39607b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA; 39617b91369bSAlexandre Courbot } 39627b91369bSAlexandre Courbot } 39637b91369bSAlexandre Courbot 39647b91369bSAlexandre Courbot /* 32-bit mask as default & fallback */ 39657b91369bSAlexandre Courbot if (ret) { 39667b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); 39677b91369bSAlexandre Courbot if (ret) 39687b91369bSAlexandre Courbot pr_warn("%s: Failed to set 32-bit DMA mask.\n", 39697b91369bSAlexandre Courbot mmc_hostname(mmc)); 39707b91369bSAlexandre Courbot } 39717b91369bSAlexandre Courbot 39727b91369bSAlexandre Courbot return ret; 39737b91369bSAlexandre Courbot } 39747b91369bSAlexandre Courbot 39758784edc8SMasahiro Yamada void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver, 39768784edc8SMasahiro Yamada const u32 *caps, const u32 *caps1) 39776132a3bfSAdrian Hunter { 39786132a3bfSAdrian Hunter u16 v; 397992e0c44bSZach Brown u64 dt_caps_mask = 0; 398092e0c44bSZach Brown u64 dt_caps = 0; 39816132a3bfSAdrian Hunter 39826132a3bfSAdrian Hunter if (host->read_caps) 39836132a3bfSAdrian Hunter return; 39846132a3bfSAdrian Hunter 39856132a3bfSAdrian Hunter host->read_caps = true; 39866132a3bfSAdrian Hunter 39876132a3bfSAdrian Hunter if (debug_quirks) 39886132a3bfSAdrian Hunter host->quirks = debug_quirks; 39896132a3bfSAdrian Hunter 39906132a3bfSAdrian Hunter if (debug_quirks2) 39916132a3bfSAdrian Hunter host->quirks2 = debug_quirks2; 39926132a3bfSAdrian Hunter 39936132a3bfSAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_ALL); 39946132a3bfSAdrian Hunter 3995b3f80b43SChunyan Zhang if (host->v4_mode) 3996b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host); 3997b3f80b43SChunyan Zhang 3998cb80a7e9SJeremy Linton device_property_read_u64(mmc_dev(host->mmc), 3999cb80a7e9SJeremy Linton "sdhci-caps-mask", &dt_caps_mask); 4000cb80a7e9SJeremy Linton device_property_read_u64(mmc_dev(host->mmc), 4001cb80a7e9SJeremy Linton "sdhci-caps", &dt_caps); 400292e0c44bSZach Brown 40036132a3bfSAdrian Hunter v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION); 40046132a3bfSAdrian Hunter host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; 40056132a3bfSAdrian Hunter 40066132a3bfSAdrian Hunter if (host->quirks & SDHCI_QUIRK_MISSING_CAPS) 40076132a3bfSAdrian Hunter return; 40086132a3bfSAdrian Hunter 400992e0c44bSZach Brown if (caps) { 401092e0c44bSZach Brown host->caps = *caps; 401192e0c44bSZach Brown } else { 401292e0c44bSZach Brown host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); 401392e0c44bSZach Brown host->caps &= ~lower_32_bits(dt_caps_mask); 401492e0c44bSZach Brown host->caps |= lower_32_bits(dt_caps); 401592e0c44bSZach Brown } 40166132a3bfSAdrian Hunter 40176132a3bfSAdrian Hunter if (host->version < SDHCI_SPEC_300) 40186132a3bfSAdrian Hunter return; 40196132a3bfSAdrian Hunter 402092e0c44bSZach Brown if (caps1) { 402192e0c44bSZach Brown host->caps1 = *caps1; 402292e0c44bSZach Brown } else { 402392e0c44bSZach Brown host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); 402492e0c44bSZach Brown host->caps1 &= ~upper_32_bits(dt_caps_mask); 402592e0c44bSZach Brown host->caps1 |= upper_32_bits(dt_caps); 402692e0c44bSZach Brown } 40276132a3bfSAdrian Hunter } 40286132a3bfSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_read_caps); 40296132a3bfSAdrian Hunter 4030a68dd9a0SChunyan Zhang static void sdhci_allocate_bounce_buffer(struct sdhci_host *host) 4031bd9b9027SLinus Walleij { 4032bd9b9027SLinus Walleij struct mmc_host *mmc = host->mmc; 4033bd9b9027SLinus Walleij unsigned int max_blocks; 4034bd9b9027SLinus Walleij unsigned int bounce_size; 4035bd9b9027SLinus Walleij int ret; 4036bd9b9027SLinus Walleij 4037bd9b9027SLinus Walleij /* 4038bd9b9027SLinus Walleij * Cap the bounce buffer at 64KB. Using a bigger bounce buffer 4039bd9b9027SLinus Walleij * has diminishing returns, this is probably because SD/MMC 4040bd9b9027SLinus Walleij * cards are usually optimized to handle this size of requests. 4041bd9b9027SLinus Walleij */ 4042bd9b9027SLinus Walleij bounce_size = SZ_64K; 4043bd9b9027SLinus Walleij /* 4044bd9b9027SLinus Walleij * Adjust downwards to maximum request size if this is less 4045bd9b9027SLinus Walleij * than our segment size, else hammer down the maximum 4046bd9b9027SLinus Walleij * request size to the maximum buffer size. 4047bd9b9027SLinus Walleij */ 4048bd9b9027SLinus Walleij if (mmc->max_req_size < bounce_size) 4049bd9b9027SLinus Walleij bounce_size = mmc->max_req_size; 4050bd9b9027SLinus Walleij max_blocks = bounce_size / 512; 4051bd9b9027SLinus Walleij 4052bd9b9027SLinus Walleij /* 4053bd9b9027SLinus Walleij * When we just support one segment, we can get significant 4054bd9b9027SLinus Walleij * speedups by the help of a bounce buffer to group scattered 4055bd9b9027SLinus Walleij * reads/writes together. 4056bd9b9027SLinus Walleij */ 4057bd9b9027SLinus Walleij host->bounce_buffer = devm_kmalloc(mmc->parent, 4058bd9b9027SLinus Walleij bounce_size, 4059bd9b9027SLinus Walleij GFP_KERNEL); 4060bd9b9027SLinus Walleij if (!host->bounce_buffer) { 4061bd9b9027SLinus Walleij pr_err("%s: failed to allocate %u bytes for bounce buffer, falling back to single segments\n", 4062bd9b9027SLinus Walleij mmc_hostname(mmc), 4063bd9b9027SLinus Walleij bounce_size); 4064bd9b9027SLinus Walleij /* 4065bd9b9027SLinus Walleij * Exiting with zero here makes sure we proceed with 4066bd9b9027SLinus Walleij * mmc->max_segs == 1. 4067bd9b9027SLinus Walleij */ 4068a68dd9a0SChunyan Zhang return; 4069bd9b9027SLinus Walleij } 4070bd9b9027SLinus Walleij 4071bd9b9027SLinus Walleij host->bounce_addr = dma_map_single(mmc->parent, 4072bd9b9027SLinus Walleij host->bounce_buffer, 4073bd9b9027SLinus Walleij bounce_size, 4074bd9b9027SLinus Walleij DMA_BIDIRECTIONAL); 4075bd9b9027SLinus Walleij ret = dma_mapping_error(mmc->parent, host->bounce_addr); 4076bd9b9027SLinus Walleij if (ret) 4077bd9b9027SLinus Walleij /* Again fall back to max_segs == 1 */ 4078a68dd9a0SChunyan Zhang return; 4079bd9b9027SLinus Walleij host->bounce_buffer_size = bounce_size; 4080bd9b9027SLinus Walleij 4081bd9b9027SLinus Walleij /* Lie about this since we're bouncing */ 4082bd9b9027SLinus Walleij mmc->max_segs = max_blocks; 4083bd9b9027SLinus Walleij mmc->max_seg_size = bounce_size; 4084bd9b9027SLinus Walleij mmc->max_req_size = bounce_size; 4085bd9b9027SLinus Walleij 4086bd9b9027SLinus Walleij pr_info("%s bounce up to %u segments into one, max segment size %u bytes\n", 4087bd9b9027SLinus Walleij mmc_hostname(mmc), max_blocks, bounce_size); 4088bd9b9027SLinus Walleij } 4089bd9b9027SLinus Walleij 4090685e444bSChunyan Zhang static inline bool sdhci_can_64bit_dma(struct sdhci_host *host) 4091685e444bSChunyan Zhang { 4092685e444bSChunyan Zhang /* 4093685e444bSChunyan Zhang * According to SD Host Controller spec v4.10, bit[27] added from 4094685e444bSChunyan Zhang * version 4.10 in Capabilities Register is used as 64-bit System 4095685e444bSChunyan Zhang * Address support for V4 mode. 4096685e444bSChunyan Zhang */ 4097685e444bSChunyan Zhang if (host->version >= SDHCI_SPEC_410 && host->v4_mode) 4098685e444bSChunyan Zhang return host->caps & SDHCI_CAN_64BIT_V4; 4099685e444bSChunyan Zhang 4100685e444bSChunyan Zhang return host->caps & SDHCI_CAN_64BIT; 4101685e444bSChunyan Zhang } 4102685e444bSChunyan Zhang 410352f5336dSAdrian Hunter int sdhci_setup_host(struct sdhci_host *host) 4104b8c86fc5SPierre Ossman { 4105b8c86fc5SPierre Ossman struct mmc_host *mmc; 4106f2119df6SArindam Nath u32 max_current_caps; 4107f2119df6SArindam Nath unsigned int ocr_avail; 4108f5fa92e5SAdrian Hunter unsigned int override_timeout_clk; 410959241757SDong Aisheng u32 max_clk; 4110907be2a6SDan Carpenter int ret = 0; 41110fcb031eSVijay Viswanath bool enable_vqmmc = false; 4112b8c86fc5SPierre Ossman 4113b8c86fc5SPierre Ossman WARN_ON(host == NULL); 4114b8c86fc5SPierre Ossman if (host == NULL) 4115b8c86fc5SPierre Ossman return -EINVAL; 4116b8c86fc5SPierre Ossman 4117b8c86fc5SPierre Ossman mmc = host->mmc; 4118b8c86fc5SPierre Ossman 4119efba142bSJon Hunter /* 4120efba142bSJon Hunter * If there are external regulators, get them. Note this must be done 4121efba142bSJon Hunter * early before resetting the host and reading the capabilities so that 4122efba142bSJon Hunter * the host can take the appropriate action if regulators are not 4123efba142bSJon Hunter * available. 4124efba142bSJon Hunter */ 41250fcb031eSVijay Viswanath if (!mmc->supply.vqmmc) { 4126efba142bSJon Hunter ret = mmc_regulator_get_supply(mmc); 41272a63303dSWolfram Sang if (ret) 4128efba142bSJon Hunter return ret; 41290fcb031eSVijay Viswanath enable_vqmmc = true; 41300fcb031eSVijay Viswanath } 4131efba142bSJon Hunter 413206ebc601SShawn Lin DBG("Version: 0x%08x | Present: 0x%08x\n", 413306ebc601SShawn Lin sdhci_readw(host, SDHCI_HOST_VERSION), 413406ebc601SShawn Lin sdhci_readl(host, SDHCI_PRESENT_STATE)); 413506ebc601SShawn Lin DBG("Caps: 0x%08x | Caps_1: 0x%08x\n", 413606ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES), 413706ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES_1)); 413806ebc601SShawn Lin 41396132a3bfSAdrian Hunter sdhci_read_caps(host); 4140b8c86fc5SPierre Ossman 4141f5fa92e5SAdrian Hunter override_timeout_clk = host->timeout_clk; 4142f5fa92e5SAdrian Hunter 414318da1990SChunyan Zhang if (host->version > SDHCI_SPEC_420) { 41442e4456f0SMarek Vasut pr_err("%s: Unknown controller version (%d). You may experience problems.\n", 41452e4456f0SMarek Vasut mmc_hostname(mmc), host->version); 41461c6a0718SPierre Ossman } 41471c6a0718SPierre Ossman 4148b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 4149a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 415028da3589SAdrian Hunter else if (!(host->caps & SDHCI_CAN_DO_SDMA)) 4151a13abc7bSRichard Röjfors DBG("Controller doesn't have SDMA capability\n"); 41521c6a0718SPierre Ossman else 4153a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 41541c6a0718SPierre Ossman 4155b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 4156a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA)) { 4157cee687ceSRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 4158a13abc7bSRichard Röjfors host->flags &= ~SDHCI_USE_SDMA; 41597c168e3dSFeng Tang } 41607c168e3dSFeng Tang 4161f2119df6SArindam Nath if ((host->version >= SDHCI_SPEC_200) && 416228da3589SAdrian Hunter (host->caps & SDHCI_CAN_DO_ADMA2)) 41632134a922SPierre Ossman host->flags |= SDHCI_USE_ADMA; 41642134a922SPierre Ossman 41652134a922SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 41662134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 41672134a922SPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 41682134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 41692134a922SPierre Ossman } 41702134a922SPierre Ossman 4171685e444bSChunyan Zhang if (sdhci_can_64bit_dma(host)) 4172e57a5f61SAdrian Hunter host->flags |= SDHCI_USE_64_BIT_DMA; 4173e57a5f61SAdrian Hunter 417418e762e3SChunyan Zhang if (host->use_external_dma) { 417518e762e3SChunyan Zhang ret = sdhci_external_dma_init(host); 417618e762e3SChunyan Zhang if (ret == -EPROBE_DEFER) 417718e762e3SChunyan Zhang goto unreg; 417818e762e3SChunyan Zhang /* 417918e762e3SChunyan Zhang * Fall back to use the DMA/PIO integrated in standard SDHCI 418018e762e3SChunyan Zhang * instead of external DMA devices. 418118e762e3SChunyan Zhang */ 418218e762e3SChunyan Zhang else if (ret) 418318e762e3SChunyan Zhang sdhci_switch_external_dma(host, false); 418418e762e3SChunyan Zhang /* Disable internal DMA sources */ 418518e762e3SChunyan Zhang else 418618e762e3SChunyan Zhang host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 418718e762e3SChunyan Zhang } 418818e762e3SChunyan Zhang 4189a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 41904ee7dde4SAdrian Hunter if (host->ops->set_dma_mask) 41914ee7dde4SAdrian Hunter ret = host->ops->set_dma_mask(host); 41924ee7dde4SAdrian Hunter else 41937b91369bSAlexandre Courbot ret = sdhci_set_dma_mask(host); 41947b91369bSAlexandre Courbot 41957b91369bSAlexandre Courbot if (!ret && host->ops->enable_dma) 41967b91369bSAlexandre Courbot ret = host->ops->enable_dma(host); 41977b91369bSAlexandre Courbot 41987b91369bSAlexandre Courbot if (ret) { 41996606110dSJoe Perches pr_warn("%s: No suitable DMA available - falling back to PIO\n", 4200b8c86fc5SPierre Ossman mmc_hostname(mmc)); 42017b91369bSAlexandre Courbot host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 42027b91369bSAlexandre Courbot 42037b91369bSAlexandre Courbot ret = 0; 42041c6a0718SPierre Ossman } 4205b8c86fc5SPierre Ossman } 42061c6a0718SPierre Ossman 4207917a0c52SChunyan Zhang /* SDMA does not support 64-bit DMA if v4 mode not set */ 4208917a0c52SChunyan Zhang if ((host->flags & SDHCI_USE_64_BIT_DMA) && !host->v4_mode) 4209e57a5f61SAdrian Hunter host->flags &= ~SDHCI_USE_SDMA; 4210e57a5f61SAdrian Hunter 42112134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 4212e66e61cbSRussell King dma_addr_t dma; 4213e66e61cbSRussell King void *buf; 4214e66e61cbSRussell King 4215a663f64bSVeerabhadrarao Badiganti if (!(host->flags & SDHCI_USE_64_BIT_DMA)) 4216a663f64bSVeerabhadrarao Badiganti host->alloc_desc_sz = SDHCI_ADMA2_32_DESC_SZ; 4217a663f64bSVeerabhadrarao Badiganti else if (!host->alloc_desc_sz) 4218a663f64bSVeerabhadrarao Badiganti host->alloc_desc_sz = SDHCI_ADMA2_64_DESC_SZ(host); 4219a663f64bSVeerabhadrarao Badiganti 4220a663f64bSVeerabhadrarao Badiganti host->desc_sz = host->alloc_desc_sz; 4221a663f64bSVeerabhadrarao Badiganti host->adma_table_sz = host->adma_table_cnt * host->desc_sz; 4222e66e61cbSRussell King 422304a5ae6fSAdrian Hunter host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN; 4224685e444bSChunyan Zhang /* 4225685e444bSChunyan Zhang * Use zalloc to zero the reserved high 32-bits of 128-bit 4226685e444bSChunyan Zhang * descriptors so that they never need to be written. 4227685e444bSChunyan Zhang */ 4228750afb08SLuis Chamberlain buf = dma_alloc_coherent(mmc_dev(mmc), 4229750afb08SLuis Chamberlain host->align_buffer_sz + host->adma_table_sz, 4230750afb08SLuis Chamberlain &dma, GFP_KERNEL); 4231e66e61cbSRussell King if (!buf) { 42326606110dSJoe Perches pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", 42332134a922SPierre Ossman mmc_hostname(mmc)); 42342134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 4235e66e61cbSRussell King } else if ((dma + host->align_buffer_sz) & 4236e66e61cbSRussell King (SDHCI_ADMA2_DESC_ALIGN - 1)) { 42376606110dSJoe Perches pr_warn("%s: unable to allocate aligned ADMA descriptor\n", 4238d1e49f77SRussell King mmc_hostname(mmc)); 4239d1e49f77SRussell King host->flags &= ~SDHCI_USE_ADMA; 4240e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 4241e66e61cbSRussell King host->adma_table_sz, buf, dma); 4242e66e61cbSRussell King } else { 4243e66e61cbSRussell King host->align_buffer = buf; 4244e66e61cbSRussell King host->align_addr = dma; 4245edd63fccSRussell King 4246e66e61cbSRussell King host->adma_table = buf + host->align_buffer_sz; 4247e66e61cbSRussell King host->adma_addr = dma + host->align_buffer_sz; 4248e66e61cbSRussell King } 42492134a922SPierre Ossman } 42502134a922SPierre Ossman 42517659150cSPierre Ossman /* 42527659150cSPierre Ossman * If we use DMA, then it's up to the caller to set the DMA 42537659150cSPierre Ossman * mask, but PIO does not need the hw shim so we set a new 42547659150cSPierre Ossman * mask here in that case. 42557659150cSPierre Ossman */ 4256a13abc7bSRichard Röjfors if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) { 42577659150cSPierre Ossman host->dma_mask = DMA_BIT_MASK(64); 42584e743f1fSMarkus Mayer mmc_dev(mmc)->dma_mask = &host->dma_mask; 42597659150cSPierre Ossman } 42601c6a0718SPierre Ossman 4261c4687d5fSZhangfei Gao if (host->version >= SDHCI_SPEC_300) 4262a8e809ecSMasahiro Yamada host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps); 4263c4687d5fSZhangfei Gao else 4264a8e809ecSMasahiro Yamada host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps); 4265c4687d5fSZhangfei Gao 42664240ff0aSBen Dooks host->max_clk *= 1000000; 4267f27f47efSAnton Vorontsov if (host->max_clk == 0 || host->quirks & 4268f27f47efSAnton Vorontsov SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { 42694240ff0aSBen Dooks if (!host->ops->get_max_clock) { 42702e4456f0SMarek Vasut pr_err("%s: Hardware doesn't specify base clock frequency.\n", 42712e4456f0SMarek Vasut mmc_hostname(mmc)); 4272eb5c20deSAdrian Hunter ret = -ENODEV; 4273eb5c20deSAdrian Hunter goto undma; 42741c6a0718SPierre Ossman } 42754240ff0aSBen Dooks host->max_clk = host->ops->get_max_clock(host); 42764240ff0aSBen Dooks } 42771c6a0718SPierre Ossman 42781c6a0718SPierre Ossman /* 4279c3ed3877SArindam Nath * In case of Host Controller v3.00, find out whether clock 4280c3ed3877SArindam Nath * multiplier is supported. 4281c3ed3877SArindam Nath */ 4282a8e809ecSMasahiro Yamada host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1); 4283c3ed3877SArindam Nath 4284c3ed3877SArindam Nath /* 4285c3ed3877SArindam Nath * In case the value in Clock Multiplier is 0, then programmable 4286c3ed3877SArindam Nath * clock mode is not supported, otherwise the actual clock 4287c3ed3877SArindam Nath * multiplier is one more than the value of Clock Multiplier 4288c3ed3877SArindam Nath * in the Capabilities Register. 4289c3ed3877SArindam Nath */ 4290c3ed3877SArindam Nath if (host->clk_mul) 4291c3ed3877SArindam Nath host->clk_mul += 1; 4292c3ed3877SArindam Nath 4293c3ed3877SArindam Nath /* 42941c6a0718SPierre Ossman * Set host parameters. 42951c6a0718SPierre Ossman */ 429659241757SDong Aisheng max_clk = host->max_clk; 429759241757SDong Aisheng 4298ce5f036bSMarek Szyprowski if (host->ops->get_min_clock) 4299a9e58f25SAnton Vorontsov mmc->f_min = host->ops->get_min_clock(host); 4300c3ed3877SArindam Nath else if (host->version >= SDHCI_SPEC_300) { 43012a187d03SMichał Mirosław if (host->clk_mul) 430259241757SDong Aisheng max_clk = host->max_clk * host->clk_mul; 43032a187d03SMichał Mirosław /* 43042a187d03SMichał Mirosław * Divided Clock Mode minimum clock rate is always less than 43052a187d03SMichał Mirosław * Programmable Clock Mode minimum clock rate. 43062a187d03SMichał Mirosław */ 43070397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; 4308c3ed3877SArindam Nath } else 43090397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; 431015ec4461SPhilip Rakity 4311d310ae49SAdrian Hunter if (!mmc->f_max || mmc->f_max > max_clk) 431259241757SDong Aisheng mmc->f_max = max_clk; 431359241757SDong Aisheng 431428aab053SAisheng Dong if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { 4315a8e809ecSMasahiro Yamada host->timeout_clk = FIELD_GET(SDHCI_TIMEOUT_CLK_MASK, host->caps); 43168cc35289SShawn Lin 43178cc35289SShawn Lin if (host->caps & SDHCI_TIMEOUT_CLK_UNIT) 43188cc35289SShawn Lin host->timeout_clk *= 1000; 43198cc35289SShawn Lin 4320272308caSAndy Shevchenko if (host->timeout_clk == 0) { 43218cc35289SShawn Lin if (!host->ops->get_timeout_clock) { 432228aab053SAisheng Dong pr_err("%s: Hardware doesn't specify timeout clock frequency.\n", 432328aab053SAisheng Dong mmc_hostname(mmc)); 4324eb5c20deSAdrian Hunter ret = -ENODEV; 4325eb5c20deSAdrian Hunter goto undma; 4326272308caSAndy Shevchenko } 432728aab053SAisheng Dong 43288cc35289SShawn Lin host->timeout_clk = 43298cc35289SShawn Lin DIV_ROUND_UP(host->ops->get_timeout_clock(host), 43308cc35289SShawn Lin 1000); 43318cc35289SShawn Lin } 4332272308caSAndy Shevchenko 433399513624SAdrian Hunter if (override_timeout_clk) 433499513624SAdrian Hunter host->timeout_clk = override_timeout_clk; 433599513624SAdrian Hunter 4336a6ff5aebSAisheng Dong mmc->max_busy_timeout = host->ops->get_max_timeout_count ? 4337a6ff5aebSAisheng Dong host->ops->get_max_timeout_count(host) : 1 << 27; 4338a6ff5aebSAisheng Dong mmc->max_busy_timeout /= host->timeout_clk; 433928aab053SAisheng Dong } 434058d1246dSAdrian Hunter 4341a999fd93SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT && 4342a999fd93SAdrian Hunter !host->ops->get_max_timeout_count) 4343a999fd93SAdrian Hunter mmc->max_busy_timeout = 0; 4344a999fd93SAdrian Hunter 43451be64c79SUlf Hansson mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_CMD23; 4346781e989cSRussell King mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; 4347e89d456fSAndrei Warkentin 4348e89d456fSAndrei Warkentin if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) 4349e89d456fSAndrei Warkentin host->flags |= SDHCI_AUTO_CMD12; 43505fe23c7fSAnton Vorontsov 43517ed71a9dSChunyan Zhang /* 43527ed71a9dSChunyan Zhang * For v3 mode, Auto-CMD23 stuff only works in ADMA or PIO. 43537ed71a9dSChunyan Zhang * For v4 mode, SDMA may use Auto-CMD23 as well. 43547ed71a9dSChunyan Zhang */ 43554f3d3e9bSAndrei Warkentin if ((host->version >= SDHCI_SPEC_300) && 43568edf6371SAndrei Warkentin ((host->flags & SDHCI_USE_ADMA) || 43577ed71a9dSChunyan Zhang !(host->flags & SDHCI_USE_SDMA) || host->v4_mode) && 43583bfa6f03SScott Branden !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN)) { 43598edf6371SAndrei Warkentin host->flags |= SDHCI_AUTO_CMD23; 4360f421865dSAdrian Hunter DBG("Auto-CMD23 available\n"); 43618edf6371SAndrei Warkentin } else { 4362f421865dSAdrian Hunter DBG("Auto-CMD23 unavailable\n"); 43638edf6371SAndrei Warkentin } 43648edf6371SAndrei Warkentin 436515ec4461SPhilip Rakity /* 436615ec4461SPhilip Rakity * A controller may support 8-bit width, but the board itself 436715ec4461SPhilip Rakity * might not have the pins brought out. Boards that support 436815ec4461SPhilip Rakity * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in 436915ec4461SPhilip Rakity * their platform code before calling sdhci_add_host(), and we 437015ec4461SPhilip Rakity * won't assume 8-bit width for hosts without that CAP. 437115ec4461SPhilip Rakity */ 43725fe23c7fSAnton Vorontsov if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) 437315ec4461SPhilip Rakity mmc->caps |= MMC_CAP_4_BIT_DATA; 43741c6a0718SPierre Ossman 437563ef5d8cSJerry Huang if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) 437663ef5d8cSJerry Huang mmc->caps &= ~MMC_CAP_CMD23; 437763ef5d8cSJerry Huang 437828da3589SAdrian Hunter if (host->caps & SDHCI_CAN_DO_HISPD) 4379a29e7e18SZhangfei Gao mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; 43801c6a0718SPierre Ossman 4381176d1ed4SJaehoon Chung if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 4382860951c5SJaehoon Chung mmc_card_is_removable(mmc) && 4383287980e4SArnd Bergmann mmc_gpio_get_cd(host->mmc) < 0) 438468d1fb7eSAnton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL; 438568d1fb7eSAnton Vorontsov 43863a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 43870fcb031eSVijay Viswanath if (enable_vqmmc) { 43883a48edc4STim Kryger ret = regulator_enable(mmc->supply.vqmmc); 43890fcb031eSVijay Viswanath host->sdhci_core_to_disable_vqmmc = !ret; 43900fcb031eSVijay Viswanath } 43911b5190c2SStefan Agner 43921b5190c2SStefan Agner /* If vqmmc provides no 1.8V signalling, then there's no UHS */ 43933a48edc4STim Kryger if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000, 4394cec2e216SKevin Liu 1950000)) 439528da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | 43968363c374SKevin Liu SDHCI_SUPPORT_SDR50 | 43976231f3deSPhilip Rakity SDHCI_SUPPORT_DDR50); 43981b5190c2SStefan Agner 43991b5190c2SStefan Agner /* In eMMC case vqmmc might be a fixed 1.8V regulator */ 44001b5190c2SStefan Agner if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000, 44011b5190c2SStefan Agner 3600000)) 44021b5190c2SStefan Agner host->flags &= ~SDHCI_SIGNALING_330; 44031b5190c2SStefan Agner 4404a3361abaSChris Ball if (ret) { 4405a3361abaSChris Ball pr_warn("%s: Failed to enable vqmmc regulator: %d\n", 4406a3361abaSChris Ball mmc_hostname(mmc), ret); 44074bb74313SAdrian Hunter mmc->supply.vqmmc = ERR_PTR(-EINVAL); 4408a3361abaSChris Ball } 44093debc24fSVeerabhadrarao Badiganti 44108363c374SKevin Liu } 44116231f3deSPhilip Rakity 441228da3589SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) { 441328da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | 44146a66180aSDaniel Drake SDHCI_SUPPORT_DDR50); 4415c16bc9a7SKishon Vijay Abraham I /* 4416c16bc9a7SKishon Vijay Abraham I * The SDHCI controller in a SoC might support HS200/HS400 4417c16bc9a7SKishon Vijay Abraham I * (indicated using mmc-hs200-1_8v/mmc-hs400-1_8v dt property), 4418c16bc9a7SKishon Vijay Abraham I * but if the board is modeled such that the IO lines are not 4419c16bc9a7SKishon Vijay Abraham I * connected to 1.8v then HS200/HS400 cannot be supported. 4420c16bc9a7SKishon Vijay Abraham I * Disable HS200/HS400 if the board does not have 1.8v connected 4421c16bc9a7SKishon Vijay Abraham I * to the IO lines. (Applicable for other modes in 1.8v) 4422c16bc9a7SKishon Vijay Abraham I */ 4423c16bc9a7SKishon Vijay Abraham I mmc->caps2 &= ~(MMC_CAP2_HSX00_1_8V | MMC_CAP2_HS400_ES); 4424c16bc9a7SKishon Vijay Abraham I mmc->caps &= ~(MMC_CAP_1_8V_DDR | MMC_CAP_UHS); 442528da3589SAdrian Hunter } 44266a66180aSDaniel Drake 44274188bba0SAl Cooper /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ 442828da3589SAdrian Hunter if (host->caps1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | 44294188bba0SAl Cooper SDHCI_SUPPORT_DDR50)) 4430f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; 4431f2119df6SArindam Nath 4432f2119df6SArindam Nath /* SDR104 supports also implies SDR50 support */ 443328da3589SAdrian Hunter if (host->caps1 & SDHCI_SUPPORT_SDR104) { 4434f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; 4435156e14b1SGiuseppe CAVALLARO /* SD3.0: SDR104 is supported so (for eMMC) the caps2 4436156e14b1SGiuseppe CAVALLARO * field can be promoted to support HS200. 4437156e14b1SGiuseppe CAVALLARO */ 4438549c0b18SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) 4439156e14b1SGiuseppe CAVALLARO mmc->caps2 |= MMC_CAP2_HS200; 444028da3589SAdrian Hunter } else if (host->caps1 & SDHCI_SUPPORT_SDR50) { 4441f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR50; 444228da3589SAdrian Hunter } 4443f2119df6SArindam Nath 4444e9fb05d5SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 && 444528da3589SAdrian Hunter (host->caps1 & SDHCI_SUPPORT_HS400)) 4446e9fb05d5SAdrian Hunter mmc->caps2 |= MMC_CAP2_HS400; 4447e9fb05d5SAdrian Hunter 4448549c0b18SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) && 4449549c0b18SAdrian Hunter (IS_ERR(mmc->supply.vqmmc) || 4450549c0b18SAdrian Hunter !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000, 4451549c0b18SAdrian Hunter 1300000))) 4452549c0b18SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V; 4453549c0b18SAdrian Hunter 445428da3589SAdrian Hunter if ((host->caps1 & SDHCI_SUPPORT_DDR50) && 44559107ebbfSMicky Ching !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) 4456f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_DDR50; 4457f2119df6SArindam Nath 4458069c9f14SGirish K S /* Does the host need tuning for SDR50? */ 445928da3589SAdrian Hunter if (host->caps1 & SDHCI_USE_SDR50_TUNING) 4460b513ea25SArindam Nath host->flags |= SDHCI_SDR50_NEEDS_TUNING; 4461b513ea25SArindam Nath 4462d6d50a15SArindam Nath /* Driver Type(s) (A, C, D) supported by the host */ 446328da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_A) 4464d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_A; 446528da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_C) 4466d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_C; 446728da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_D) 4468d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_D; 4469d6d50a15SArindam Nath 4470cf2b5eeaSArindam Nath /* Initial value for re-tuning timer count */ 4471a8e809ecSMasahiro Yamada host->tuning_count = FIELD_GET(SDHCI_RETUNING_TIMER_COUNT_MASK, 4472a8e809ecSMasahiro Yamada host->caps1); 4473cf2b5eeaSArindam Nath 4474cf2b5eeaSArindam Nath /* 4475cf2b5eeaSArindam Nath * In case Re-tuning Timer is not disabled, the actual value of 4476cf2b5eeaSArindam Nath * re-tuning timer will be 2 ^ (n - 1). 4477cf2b5eeaSArindam Nath */ 4478cf2b5eeaSArindam Nath if (host->tuning_count) 4479cf2b5eeaSArindam Nath host->tuning_count = 1 << (host->tuning_count - 1); 4480cf2b5eeaSArindam Nath 4481cf2b5eeaSArindam Nath /* Re-tuning mode supported by the Host Controller */ 4482a8e809ecSMasahiro Yamada host->tuning_mode = FIELD_GET(SDHCI_RETUNING_MODE_MASK, host->caps1); 4483cf2b5eeaSArindam Nath 44848f230f45STakashi Iwai ocr_avail = 0; 4485bad37e1aSPhilip Rakity 4486f2119df6SArindam Nath /* 4487f2119df6SArindam Nath * According to SD Host Controller spec v3.00, if the Host System 4488f2119df6SArindam Nath * can afford more than 150mA, Host Driver should set XPC to 1. Also 4489f2119df6SArindam Nath * the value is meaningful only if Voltage Support in the Capabilities 4490f2119df6SArindam Nath * register is set. The actual current value is 4 times the register 4491f2119df6SArindam Nath * value. 4492f2119df6SArindam Nath */ 4493f2119df6SArindam Nath max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); 44943a48edc4STim Kryger if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) { 4495ae906037SChuanxiao.Dong int curr = regulator_get_current_limit(mmc->supply.vmmc); 4496bad37e1aSPhilip Rakity if (curr > 0) { 4497bad37e1aSPhilip Rakity 4498bad37e1aSPhilip Rakity /* convert to SDHCI_MAX_CURRENT format */ 4499bad37e1aSPhilip Rakity curr = curr/1000; /* convert to mA */ 4500bad37e1aSPhilip Rakity curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER; 4501bad37e1aSPhilip Rakity 4502bad37e1aSPhilip Rakity curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT); 4503bad37e1aSPhilip Rakity max_current_caps = 4504804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, curr) | 4505804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, curr) | 4506804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, curr); 4507bad37e1aSPhilip Rakity } 4508bad37e1aSPhilip Rakity } 4509f2119df6SArindam Nath 451028da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_330) { 45118f230f45STakashi Iwai ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; 4512f2119df6SArindam Nath 4513804a65b3SMasahiro Yamada mmc->max_current_330 = FIELD_GET(SDHCI_MAX_CURRENT_330_MASK, 4514804a65b3SMasahiro Yamada max_current_caps) * 4515f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4516f2119df6SArindam Nath } 451728da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_300) { 45188f230f45STakashi Iwai ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; 4519f2119df6SArindam Nath 4520804a65b3SMasahiro Yamada mmc->max_current_300 = FIELD_GET(SDHCI_MAX_CURRENT_300_MASK, 4521804a65b3SMasahiro Yamada max_current_caps) * 4522f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4523f2119df6SArindam Nath } 452428da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_180) { 45258f230f45STakashi Iwai ocr_avail |= MMC_VDD_165_195; 45268f230f45STakashi Iwai 4527804a65b3SMasahiro Yamada mmc->max_current_180 = FIELD_GET(SDHCI_MAX_CURRENT_180_MASK, 4528804a65b3SMasahiro Yamada max_current_caps) * 4529f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4530f2119df6SArindam Nath } 4531f2119df6SArindam Nath 45325fd26c7eSUlf Hansson /* If OCR set by host, use it instead. */ 45335fd26c7eSUlf Hansson if (host->ocr_mask) 45345fd26c7eSUlf Hansson ocr_avail = host->ocr_mask; 45355fd26c7eSUlf Hansson 45365fd26c7eSUlf Hansson /* If OCR set by external regulators, give it highest prio. */ 45373a48edc4STim Kryger if (mmc->ocr_avail) 453852221610STim Kryger ocr_avail = mmc->ocr_avail; 45393a48edc4STim Kryger 45408f230f45STakashi Iwai mmc->ocr_avail = ocr_avail; 45418f230f45STakashi Iwai mmc->ocr_avail_sdio = ocr_avail; 45428f230f45STakashi Iwai if (host->ocr_avail_sdio) 45438f230f45STakashi Iwai mmc->ocr_avail_sdio &= host->ocr_avail_sdio; 45448f230f45STakashi Iwai mmc->ocr_avail_sd = ocr_avail; 45458f230f45STakashi Iwai if (host->ocr_avail_sd) 45468f230f45STakashi Iwai mmc->ocr_avail_sd &= host->ocr_avail_sd; 45478f230f45STakashi Iwai else /* normal SD controllers don't support 1.8V */ 45488f230f45STakashi Iwai mmc->ocr_avail_sd &= ~MMC_VDD_165_195; 45498f230f45STakashi Iwai mmc->ocr_avail_mmc = ocr_avail; 45508f230f45STakashi Iwai if (host->ocr_avail_mmc) 45518f230f45STakashi Iwai mmc->ocr_avail_mmc &= host->ocr_avail_mmc; 45521c6a0718SPierre Ossman 45531c6a0718SPierre Ossman if (mmc->ocr_avail == 0) { 45542e4456f0SMarek Vasut pr_err("%s: Hardware doesn't report any support voltages.\n", 45552e4456f0SMarek Vasut mmc_hostname(mmc)); 4556eb5c20deSAdrian Hunter ret = -ENODEV; 4557eb5c20deSAdrian Hunter goto unreg; 45581c6a0718SPierre Ossman } 45591c6a0718SPierre Ossman 45608cb851a4SAdrian Hunter if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | 45618cb851a4SAdrian Hunter MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | 45628cb851a4SAdrian Hunter MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) || 45638cb851a4SAdrian Hunter (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V))) 45648cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_180; 45658cb851a4SAdrian Hunter 45668cb851a4SAdrian Hunter if (mmc->caps2 & MMC_CAP2_HSX00_1_2V) 45678cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_120; 45688cb851a4SAdrian Hunter 45691c6a0718SPierre Ossman spin_lock_init(&host->lock); 45701c6a0718SPierre Ossman 45711c6a0718SPierre Ossman /* 4572ac00531dSAdrian Hunter * Maximum number of sectors in one transfer. Limited by SDMA boundary 4573ac00531dSAdrian Hunter * size (512KiB). Note some tuning modes impose a 4MiB limit, but this 4574ac00531dSAdrian Hunter * is less anyway. 45751c6a0718SPierre Ossman */ 45761c6a0718SPierre Ossman mmc->max_req_size = 524288; 45771c6a0718SPierre Ossman 45781c6a0718SPierre Ossman /* 4579250dcd11SUlf Hansson * Maximum number of segments. Depends on if the hardware 4580250dcd11SUlf Hansson * can do scatter/gather or not. 4581250dcd11SUlf Hansson */ 4582250dcd11SUlf Hansson if (host->flags & SDHCI_USE_ADMA) { 4583250dcd11SUlf Hansson mmc->max_segs = SDHCI_MAX_SEGS; 4584250dcd11SUlf Hansson } else if (host->flags & SDHCI_USE_SDMA) { 4585250dcd11SUlf Hansson mmc->max_segs = 1; 458666e8d3b8SChristoph Hellwig mmc->max_req_size = min_t(size_t, mmc->max_req_size, 458766e8d3b8SChristoph Hellwig dma_max_mapping_size(mmc_dev(mmc))); 4588250dcd11SUlf Hansson } else { /* PIO */ 4589250dcd11SUlf Hansson mmc->max_segs = SDHCI_MAX_SEGS; 4590250dcd11SUlf Hansson } 4591250dcd11SUlf Hansson 4592250dcd11SUlf Hansson /* 45931c6a0718SPierre Ossman * Maximum segment size. Could be one segment with the maximum number 45942134a922SPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 45952134a922SPierre Ossman * be larger than 64 KiB though. 45961c6a0718SPierre Ossman */ 459730652aa3SOlof Johansson if (host->flags & SDHCI_USE_ADMA) { 459830652aa3SOlof Johansson if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) 459930652aa3SOlof Johansson mmc->max_seg_size = 65535; 46002134a922SPierre Ossman else 460130652aa3SOlof Johansson mmc->max_seg_size = 65536; 460230652aa3SOlof Johansson } else { 46031c6a0718SPierre Ossman mmc->max_seg_size = mmc->max_req_size; 460430652aa3SOlof Johansson } 46051c6a0718SPierre Ossman 46061c6a0718SPierre Ossman /* 46071c6a0718SPierre Ossman * Maximum block size. This varies from controller to controller and 46081c6a0718SPierre Ossman * is specified in the capabilities register. 46091c6a0718SPierre Ossman */ 46100633f654SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { 46110633f654SAnton Vorontsov mmc->max_blk_size = 2; 46120633f654SAnton Vorontsov } else { 461328da3589SAdrian Hunter mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >> 46140633f654SAnton Vorontsov SDHCI_MAX_BLOCK_SHIFT; 46151c6a0718SPierre Ossman if (mmc->max_blk_size >= 3) { 46166606110dSJoe Perches pr_warn("%s: Invalid maximum block size, assuming 512 bytes\n", 46176606110dSJoe Perches mmc_hostname(mmc)); 46180633f654SAnton Vorontsov mmc->max_blk_size = 0; 46190633f654SAnton Vorontsov } 46200633f654SAnton Vorontsov } 46210633f654SAnton Vorontsov 46221c6a0718SPierre Ossman mmc->max_blk_size = 512 << mmc->max_blk_size; 46231c6a0718SPierre Ossman 46241c6a0718SPierre Ossman /* 46251c6a0718SPierre Ossman * Maximum block count. 46261c6a0718SPierre Ossman */ 46271388eefdSBen Dooks mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; 46281c6a0718SPierre Ossman 4629a68dd9a0SChunyan Zhang if (mmc->max_segs == 1) 4630bd9b9027SLinus Walleij /* This may alter mmc->*_blk_* parameters */ 4631a68dd9a0SChunyan Zhang sdhci_allocate_bounce_buffer(host); 4632bd9b9027SLinus Walleij 463352f5336dSAdrian Hunter return 0; 463452f5336dSAdrian Hunter 463552f5336dSAdrian Hunter unreg: 46360fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 463752f5336dSAdrian Hunter regulator_disable(mmc->supply.vqmmc); 463852f5336dSAdrian Hunter undma: 463952f5336dSAdrian Hunter if (host->align_buffer) 464052f5336dSAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 464152f5336dSAdrian Hunter host->adma_table_sz, host->align_buffer, 464252f5336dSAdrian Hunter host->align_addr); 464352f5336dSAdrian Hunter host->adma_table = NULL; 464452f5336dSAdrian Hunter host->align_buffer = NULL; 464552f5336dSAdrian Hunter 464652f5336dSAdrian Hunter return ret; 464752f5336dSAdrian Hunter } 464852f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_setup_host); 464952f5336dSAdrian Hunter 46504180ffa8SAdrian Hunter void sdhci_cleanup_host(struct sdhci_host *host) 46514180ffa8SAdrian Hunter { 46524180ffa8SAdrian Hunter struct mmc_host *mmc = host->mmc; 46534180ffa8SAdrian Hunter 46540fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 46554180ffa8SAdrian Hunter regulator_disable(mmc->supply.vqmmc); 46564180ffa8SAdrian Hunter 46574180ffa8SAdrian Hunter if (host->align_buffer) 46584180ffa8SAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 46594180ffa8SAdrian Hunter host->adma_table_sz, host->align_buffer, 46604180ffa8SAdrian Hunter host->align_addr); 466118e762e3SChunyan Zhang 466218e762e3SChunyan Zhang if (host->use_external_dma) 466318e762e3SChunyan Zhang sdhci_external_dma_release(host); 466418e762e3SChunyan Zhang 46654180ffa8SAdrian Hunter host->adma_table = NULL; 46664180ffa8SAdrian Hunter host->align_buffer = NULL; 46674180ffa8SAdrian Hunter } 46684180ffa8SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cleanup_host); 46694180ffa8SAdrian Hunter 467052f5336dSAdrian Hunter int __sdhci_add_host(struct sdhci_host *host) 467152f5336dSAdrian Hunter { 4672c07a48c2SAdrian Hunter unsigned int flags = WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI; 467352f5336dSAdrian Hunter struct mmc_host *mmc = host->mmc; 467452f5336dSAdrian Hunter int ret; 467552f5336dSAdrian Hunter 46762b17b8d7SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_CQE) && 46772b17b8d7SAdrian Hunter (host->quirks & SDHCI_QUIRK_BROKEN_CQE)) { 46782b17b8d7SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_CQE; 46792b17b8d7SAdrian Hunter mmc->cqe_ops = NULL; 46802b17b8d7SAdrian Hunter } 46812b17b8d7SAdrian Hunter 4682c07a48c2SAdrian Hunter host->complete_wq = alloc_workqueue("sdhci", flags, 0); 4683c07a48c2SAdrian Hunter if (!host->complete_wq) 4684c07a48c2SAdrian Hunter return -ENOMEM; 4685c07a48c2SAdrian Hunter 4686c07a48c2SAdrian Hunter INIT_WORK(&host->complete_work, sdhci_complete_work); 46871c6a0718SPierre Ossman 46882ee4f620SKees Cook timer_setup(&host->timer, sdhci_timeout_timer, 0); 46892ee4f620SKees Cook timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0); 46901c6a0718SPierre Ossman 4691b513ea25SArindam Nath init_waitqueue_head(&host->buf_ready_int); 4692b513ea25SArindam Nath 46932af502caSShawn Guo sdhci_init(host, 0); 46942af502caSShawn Guo 4695781e989cSRussell King ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, 4696781e989cSRussell King IRQF_SHARED, mmc_hostname(mmc), host); 46970fc81ee3SMark Brown if (ret) { 46980fc81ee3SMark Brown pr_err("%s: Failed to request IRQ %d: %d\n", 46990fc81ee3SMark Brown mmc_hostname(mmc), host->irq, ret); 4700c07a48c2SAdrian Hunter goto unwq; 47010fc81ee3SMark Brown } 47021c6a0718SPierre Ossman 4703061d17a6SAdrian Hunter ret = sdhci_led_register(host); 47040fc81ee3SMark Brown if (ret) { 47050fc81ee3SMark Brown pr_err("%s: Failed to register LED device: %d\n", 47060fc81ee3SMark Brown mmc_hostname(mmc), ret); 4707eb5c20deSAdrian Hunter goto unirq; 47080fc81ee3SMark Brown } 47092f730fecSPierre Ossman 4710eb5c20deSAdrian Hunter ret = mmc_add_host(mmc); 4711eb5c20deSAdrian Hunter if (ret) 4712eb5c20deSAdrian Hunter goto unled; 47131c6a0718SPierre Ossman 4714a3c76eb9SGirish K S pr_info("%s: SDHCI controller on %s [%s] using %s\n", 4715d1b26863SKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), 471618e762e3SChunyan Zhang host->use_external_dma ? "External DMA" : 4717e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_ADMA) ? 4718e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" : 4719a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); 47201c6a0718SPierre Ossman 47217260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 47227260cf5eSAnton Vorontsov 47231c6a0718SPierre Ossman return 0; 47241c6a0718SPierre Ossman 4725eb5c20deSAdrian Hunter unled: 4726061d17a6SAdrian Hunter sdhci_led_unregister(host); 4727eb5c20deSAdrian Hunter unirq: 472803231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_ALL); 4729b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 4730b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 47312f730fecSPierre Ossman free_irq(host->irq, host); 4732c07a48c2SAdrian Hunter unwq: 4733c07a48c2SAdrian Hunter destroy_workqueue(host->complete_wq); 473452f5336dSAdrian Hunter 47351c6a0718SPierre Ossman return ret; 47361c6a0718SPierre Ossman } 473752f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_add_host); 47381c6a0718SPierre Ossman 473952f5336dSAdrian Hunter int sdhci_add_host(struct sdhci_host *host) 474052f5336dSAdrian Hunter { 474152f5336dSAdrian Hunter int ret; 474252f5336dSAdrian Hunter 474352f5336dSAdrian Hunter ret = sdhci_setup_host(host); 474452f5336dSAdrian Hunter if (ret) 474552f5336dSAdrian Hunter return ret; 474652f5336dSAdrian Hunter 47474180ffa8SAdrian Hunter ret = __sdhci_add_host(host); 47484180ffa8SAdrian Hunter if (ret) 47494180ffa8SAdrian Hunter goto cleanup; 47504180ffa8SAdrian Hunter 47514180ffa8SAdrian Hunter return 0; 47524180ffa8SAdrian Hunter 47534180ffa8SAdrian Hunter cleanup: 47544180ffa8SAdrian Hunter sdhci_cleanup_host(host); 47554180ffa8SAdrian Hunter 47564180ffa8SAdrian Hunter return ret; 475752f5336dSAdrian Hunter } 4758b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_add_host); 4759b8c86fc5SPierre Ossman 47601e72859eSPierre Ossman void sdhci_remove_host(struct sdhci_host *host, int dead) 47611c6a0718SPierre Ossman { 47623a48edc4STim Kryger struct mmc_host *mmc = host->mmc; 47631e72859eSPierre Ossman unsigned long flags; 47641e72859eSPierre Ossman 47651e72859eSPierre Ossman if (dead) { 47661e72859eSPierre Ossman spin_lock_irqsave(&host->lock, flags); 47671e72859eSPierre Ossman 47681e72859eSPierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 47691e72859eSPierre Ossman 47705d0d11c5SAdrian Hunter if (sdhci_has_requests(host)) { 4771a3c76eb9SGirish K S pr_err("%s: Controller removed during " 47724e743f1fSMarkus Mayer " transfer!\n", mmc_hostname(mmc)); 47735d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM); 47741e72859eSPierre Ossman } 47751e72859eSPierre Ossman 47761e72859eSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 47771e72859eSPierre Ossman } 47781e72859eSPierre Ossman 47797260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 47807260cf5eSAnton Vorontsov 47814e743f1fSMarkus Mayer mmc_remove_host(mmc); 47821c6a0718SPierre Ossman 4783061d17a6SAdrian Hunter sdhci_led_unregister(host); 47842f730fecSPierre Ossman 47851e72859eSPierre Ossman if (!dead) 478603231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_ALL); 47871c6a0718SPierre Ossman 4788b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 4789b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 47901c6a0718SPierre Ossman free_irq(host->irq, host); 47911c6a0718SPierre Ossman 47921c6a0718SPierre Ossman del_timer_sync(&host->timer); 4793d7422fb4SAdrian Hunter del_timer_sync(&host->data_timer); 47941c6a0718SPierre Ossman 4795c07a48c2SAdrian Hunter destroy_workqueue(host->complete_wq); 47962134a922SPierre Ossman 47970fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 47983a48edc4STim Kryger regulator_disable(mmc->supply.vqmmc); 47996231f3deSPhilip Rakity 4800edd63fccSRussell King if (host->align_buffer) 4801e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 4802e66e61cbSRussell King host->adma_table_sz, host->align_buffer, 4803e66e61cbSRussell King host->align_addr); 48042134a922SPierre Ossman 480518e762e3SChunyan Zhang if (host->use_external_dma) 480618e762e3SChunyan Zhang sdhci_external_dma_release(host); 480718e762e3SChunyan Zhang 48084efaa6fbSAdrian Hunter host->adma_table = NULL; 48092134a922SPierre Ossman host->align_buffer = NULL; 48101c6a0718SPierre Ossman } 48111c6a0718SPierre Ossman 4812b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_remove_host); 4813b8c86fc5SPierre Ossman 4814b8c86fc5SPierre Ossman void sdhci_free_host(struct sdhci_host *host) 48151c6a0718SPierre Ossman { 4816b8c86fc5SPierre Ossman mmc_free_host(host->mmc); 48171c6a0718SPierre Ossman } 48181c6a0718SPierre Ossman 4819b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_free_host); 48201c6a0718SPierre Ossman 48211c6a0718SPierre Ossman /*****************************************************************************\ 48221c6a0718SPierre Ossman * * 48231c6a0718SPierre Ossman * Driver init/exit * 48241c6a0718SPierre Ossman * * 48251c6a0718SPierre Ossman \*****************************************************************************/ 48261c6a0718SPierre Ossman 48271c6a0718SPierre Ossman static int __init sdhci_drv_init(void) 48281c6a0718SPierre Ossman { 4829a3c76eb9SGirish K S pr_info(DRIVER_NAME 48301c6a0718SPierre Ossman ": Secure Digital Host Controller Interface driver\n"); 4831a3c76eb9SGirish K S pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 48321c6a0718SPierre Ossman 4833b8c86fc5SPierre Ossman return 0; 48341c6a0718SPierre Ossman } 48351c6a0718SPierre Ossman 48361c6a0718SPierre Ossman static void __exit sdhci_drv_exit(void) 48371c6a0718SPierre Ossman { 48381c6a0718SPierre Ossman } 48391c6a0718SPierre Ossman 48401c6a0718SPierre Ossman module_init(sdhci_drv_init); 48411c6a0718SPierre Ossman module_exit(sdhci_drv_exit); 48421c6a0718SPierre Ossman 48431c6a0718SPierre Ossman module_param(debug_quirks, uint, 0444); 484466fd8ad5SAdrian Hunter module_param(debug_quirks2, uint, 0444); 48451c6a0718SPierre Ossman 484632710e8fSPierre Ossman MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); 4847b8c86fc5SPierre Ossman MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 48481c6a0718SPierre Ossman MODULE_LICENSE("GPL"); 48491c6a0718SPierre Ossman 48501c6a0718SPierre Ossman MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 485166fd8ad5SAdrian Hunter MODULE_PARM_DESC(debug_quirks2, "Force certain other quirks."); 4852