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> 23250dcd11SUlf Hansson #include <linux/swiotlb.h> 249bea3c85SMarek Szyprowski #include <linux/regulator/consumer.h> 2566fd8ad5SAdrian Hunter #include <linux/pm_runtime.h> 2692e0c44bSZach Brown #include <linux/of.h> 271c6a0718SPierre Ossman 282f730fecSPierre Ossman #include <linux/leds.h> 292f730fecSPierre Ossman 3022113efdSAries Lee #include <linux/mmc/mmc.h> 311c6a0718SPierre Ossman #include <linux/mmc/host.h> 32473b095aSAaron Lu #include <linux/mmc/card.h> 3385cc1c33SCorneliu Doban #include <linux/mmc/sdio.h> 34bec9d4e5SGuennadi Liakhovetski #include <linux/mmc/slot-gpio.h> 351c6a0718SPierre Ossman 361c6a0718SPierre Ossman #include "sdhci.h" 371c6a0718SPierre Ossman 381c6a0718SPierre Ossman #define DRIVER_NAME "sdhci" 391c6a0718SPierre Ossman 401c6a0718SPierre Ossman #define DBG(f, x...) \ 41f421865dSAdrian Hunter pr_debug("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) 421c6a0718SPierre Ossman 4385ad90e2SAdrian Hunter #define SDHCI_DUMP(f, x...) \ 4485ad90e2SAdrian Hunter pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) 4585ad90e2SAdrian Hunter 46b513ea25SArindam Nath #define MAX_TUNING_LOOP 40 47b513ea25SArindam Nath 481c6a0718SPierre Ossman static unsigned int debug_quirks = 0; 4966fd8ad5SAdrian Hunter static unsigned int debug_quirks2; 501c6a0718SPierre Ossman 5152983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); 521c6a0718SPierre Ossman 53845c939eSAdrian Hunter static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); 54a374a72bSAdrian Hunter 55d2898172SAdrian Hunter void sdhci_dumpregs(struct sdhci_host *host) 561c6a0718SPierre Ossman { 5785ad90e2SAdrian Hunter SDHCI_DUMP("============ SDHCI REGISTER DUMP ===========\n"); 581c6a0718SPierre Ossman 5985ad90e2SAdrian Hunter SDHCI_DUMP("Sys addr: 0x%08x | Version: 0x%08x\n", 604e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_DMA_ADDRESS), 614e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_HOST_VERSION)); 6285ad90e2SAdrian Hunter SDHCI_DUMP("Blk size: 0x%08x | Blk cnt: 0x%08x\n", 634e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_SIZE), 644e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_COUNT)); 6585ad90e2SAdrian Hunter SDHCI_DUMP("Argument: 0x%08x | Trn mode: 0x%08x\n", 664e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_ARGUMENT), 674e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_TRANSFER_MODE)); 6885ad90e2SAdrian Hunter SDHCI_DUMP("Present: 0x%08x | Host ctl: 0x%08x\n", 694e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_PRESENT_STATE), 704e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_HOST_CONTROL)); 7185ad90e2SAdrian Hunter SDHCI_DUMP("Power: 0x%08x | Blk gap: 0x%08x\n", 724e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_POWER_CONTROL), 734e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); 7485ad90e2SAdrian Hunter SDHCI_DUMP("Wake-up: 0x%08x | Clock: 0x%08x\n", 754e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), 764e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_CLOCK_CONTROL)); 7785ad90e2SAdrian Hunter SDHCI_DUMP("Timeout: 0x%08x | Int stat: 0x%08x\n", 784e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), 794e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_STATUS)); 8085ad90e2SAdrian Hunter SDHCI_DUMP("Int enab: 0x%08x | Sig enab: 0x%08x\n", 814e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_ENABLE), 824e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); 83869f8a69SAdrian Hunter SDHCI_DUMP("ACmd stat: 0x%08x | Slot int: 0x%08x\n", 84869f8a69SAdrian Hunter sdhci_readw(host, SDHCI_AUTO_CMD_STATUS), 854e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); 8685ad90e2SAdrian Hunter SDHCI_DUMP("Caps: 0x%08x | Caps_1: 0x%08x\n", 874e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_CAPABILITIES), 88e8120ad1SPhilip Rakity sdhci_readl(host, SDHCI_CAPABILITIES_1)); 8985ad90e2SAdrian Hunter SDHCI_DUMP("Cmd: 0x%08x | Max curr: 0x%08x\n", 90e8120ad1SPhilip Rakity sdhci_readw(host, SDHCI_COMMAND), 914e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_MAX_CURRENT)); 9285ad90e2SAdrian Hunter SDHCI_DUMP("Resp[0]: 0x%08x | Resp[1]: 0x%08x\n", 937962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE), 947962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 4)); 9585ad90e2SAdrian Hunter SDHCI_DUMP("Resp[2]: 0x%08x | Resp[3]: 0x%08x\n", 967962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 8), 977962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 12)); 9885ad90e2SAdrian Hunter SDHCI_DUMP("Host ctl2: 0x%08x\n", 99f2119df6SArindam Nath sdhci_readw(host, SDHCI_HOST_CONTROL2)); 1001c6a0718SPierre Ossman 101e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_ADMA) { 10285ad90e2SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) { 10385ad90e2SAdrian Hunter SDHCI_DUMP("ADMA Err: 0x%08x | ADMA Ptr: 0x%08x%08x\n", 104c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ERROR), 105c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS_HI), 106c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS)); 10785ad90e2SAdrian Hunter } else { 10885ad90e2SAdrian Hunter SDHCI_DUMP("ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n", 109c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ERROR), 110c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS)); 111e57a5f61SAdrian Hunter } 11285ad90e2SAdrian Hunter } 113be3f4ae0SBen Dooks 114d1fe0762SSarthak Garg if (host->ops->dump_vendor_regs) 115d1fe0762SSarthak Garg host->ops->dump_vendor_regs(host); 116d1fe0762SSarthak Garg 11785ad90e2SAdrian Hunter SDHCI_DUMP("============================================\n"); 1181c6a0718SPierre Ossman } 119d2898172SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_dumpregs); 1201c6a0718SPierre Ossman 1211c6a0718SPierre Ossman /*****************************************************************************\ 1221c6a0718SPierre Ossman * * 1231c6a0718SPierre Ossman * Low level functions * 1241c6a0718SPierre Ossman * * 1251c6a0718SPierre Ossman \*****************************************************************************/ 1261c6a0718SPierre Ossman 127b3f80b43SChunyan Zhang static void sdhci_do_enable_v4_mode(struct sdhci_host *host) 128b3f80b43SChunyan Zhang { 129b3f80b43SChunyan Zhang u16 ctrl2; 130b3f80b43SChunyan Zhang 13197207c12SSowjanya Komatineni ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 132b3f80b43SChunyan Zhang if (ctrl2 & SDHCI_CTRL_V4_MODE) 133b3f80b43SChunyan Zhang return; 134b3f80b43SChunyan Zhang 135b3f80b43SChunyan Zhang ctrl2 |= SDHCI_CTRL_V4_MODE; 13697207c12SSowjanya Komatineni sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 137b3f80b43SChunyan Zhang } 138b3f80b43SChunyan Zhang 139b3f80b43SChunyan Zhang /* 140b3f80b43SChunyan Zhang * This can be called before sdhci_add_host() by Vendor's host controller 141b3f80b43SChunyan Zhang * driver to enable v4 mode if supported. 142b3f80b43SChunyan Zhang */ 143b3f80b43SChunyan Zhang void sdhci_enable_v4_mode(struct sdhci_host *host) 144b3f80b43SChunyan Zhang { 145b3f80b43SChunyan Zhang host->v4_mode = true; 146b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host); 147b3f80b43SChunyan Zhang } 148b3f80b43SChunyan Zhang EXPORT_SYMBOL_GPL(sdhci_enable_v4_mode); 149b3f80b43SChunyan Zhang 15056a590dcSAdrian Hunter static inline bool sdhci_data_line_cmd(struct mmc_command *cmd) 15156a590dcSAdrian Hunter { 15256a590dcSAdrian Hunter return cmd->data || cmd->flags & MMC_RSP_BUSY; 15356a590dcSAdrian Hunter } 15456a590dcSAdrian Hunter 1557260cf5eSAnton Vorontsov static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) 1567260cf5eSAnton Vorontsov { 1575b4f1f6cSRussell King u32 present; 1587260cf5eSAnton Vorontsov 159c79396c1SAdrian Hunter if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || 160e65bb388SHaibo Chen !mmc_card_is_removable(host->mmc) || mmc_can_gpio_cd(host->mmc)) 16166fd8ad5SAdrian Hunter return; 16266fd8ad5SAdrian Hunter 1635b4f1f6cSRussell King if (enable) { 164d25928d1SShawn Guo present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 165d25928d1SShawn Guo SDHCI_CARD_PRESENT; 166d25928d1SShawn Guo 1675b4f1f6cSRussell King host->ier |= present ? SDHCI_INT_CARD_REMOVE : 1685b4f1f6cSRussell King SDHCI_INT_CARD_INSERT; 1695b4f1f6cSRussell King } else { 1705b4f1f6cSRussell King host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); 1715b4f1f6cSRussell King } 172b537f94cSRussell King 173b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 174b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 1757260cf5eSAnton Vorontsov } 1767260cf5eSAnton Vorontsov 1777260cf5eSAnton Vorontsov static void sdhci_enable_card_detection(struct sdhci_host *host) 1787260cf5eSAnton Vorontsov { 1797260cf5eSAnton Vorontsov sdhci_set_card_detection(host, true); 1807260cf5eSAnton Vorontsov } 1817260cf5eSAnton Vorontsov 1827260cf5eSAnton Vorontsov static void sdhci_disable_card_detection(struct sdhci_host *host) 1837260cf5eSAnton Vorontsov { 1847260cf5eSAnton Vorontsov sdhci_set_card_detection(host, false); 1857260cf5eSAnton Vorontsov } 1867260cf5eSAnton Vorontsov 18702d0b685SUlf Hansson static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) 18802d0b685SUlf Hansson { 18902d0b685SUlf Hansson if (host->bus_on) 19002d0b685SUlf Hansson return; 19102d0b685SUlf Hansson host->bus_on = true; 19202d0b685SUlf Hansson pm_runtime_get_noresume(host->mmc->parent); 19302d0b685SUlf Hansson } 19402d0b685SUlf Hansson 19502d0b685SUlf Hansson static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) 19602d0b685SUlf Hansson { 19702d0b685SUlf Hansson if (!host->bus_on) 19802d0b685SUlf Hansson return; 19902d0b685SUlf Hansson host->bus_on = false; 20002d0b685SUlf Hansson pm_runtime_put_noidle(host->mmc->parent); 20102d0b685SUlf Hansson } 20202d0b685SUlf Hansson 20303231f9bSRussell King void sdhci_reset(struct sdhci_host *host, u8 mask) 2041c6a0718SPierre Ossman { 2055a436cc0SAdrian Hunter ktime_t timeout; 206393c1a34SPhilip Rakity 2074e4141a5SAnton Vorontsov sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); 2081c6a0718SPierre Ossman 209f0710a55SAdrian Hunter if (mask & SDHCI_RESET_ALL) { 2101c6a0718SPierre Ossman host->clock = 0; 211f0710a55SAdrian Hunter /* Reset-all turns off SD Bus Power */ 212f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 213f0710a55SAdrian Hunter sdhci_runtime_pm_bus_off(host); 214f0710a55SAdrian Hunter } 2151c6a0718SPierre Ossman 2161c6a0718SPierre Ossman /* Wait max 100 ms */ 2175a436cc0SAdrian Hunter timeout = ktime_add_ms(ktime_get(), 100); 2181c6a0718SPierre Ossman 2191c6a0718SPierre Ossman /* hw clears the bit when it's done */ 220b704441eSAlek Du while (1) { 221b704441eSAlek Du bool timedout = ktime_after(ktime_get(), timeout); 222b704441eSAlek Du 223b704441eSAlek Du if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask)) 224b704441eSAlek Du break; 225b704441eSAlek Du if (timedout) { 226a3c76eb9SGirish K S pr_err("%s: Reset 0x%x never completed.\n", 2271c6a0718SPierre Ossman mmc_hostname(host->mmc), (int)mask); 2281c6a0718SPierre Ossman sdhci_dumpregs(host); 2291c6a0718SPierre Ossman return; 2301c6a0718SPierre Ossman } 2315a436cc0SAdrian Hunter udelay(10); 2321c6a0718SPierre Ossman } 23303231f9bSRussell King } 23403231f9bSRussell King EXPORT_SYMBOL_GPL(sdhci_reset); 235063a9dbbSAnton Vorontsov 23603231f9bSRussell King static void sdhci_do_reset(struct sdhci_host *host, u8 mask) 23703231f9bSRussell King { 23803231f9bSRussell King if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { 239d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 240d3940f27SAdrian Hunter 241d3940f27SAdrian Hunter if (!mmc->ops->get_cd(mmc)) 24203231f9bSRussell King return; 24303231f9bSRussell King } 24403231f9bSRussell King 24503231f9bSRussell King host->ops->reset(host, mask); 246393c1a34SPhilip Rakity 247da91a8f9SRussell King if (mask & SDHCI_RESET_ALL) { 2483abc1e80SShaohui Xie if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 249da91a8f9SRussell King if (host->ops->enable_dma) 2503abc1e80SShaohui Xie host->ops->enable_dma(host); 2513abc1e80SShaohui Xie } 252da91a8f9SRussell King 253da91a8f9SRussell King /* Resetting the controller clears many */ 254da91a8f9SRussell King host->preset_enabled = false; 255da91a8f9SRussell King } 2561c6a0718SPierre Ossman } 2571c6a0718SPierre Ossman 258f5c1ab82SAdrian Hunter static void sdhci_set_default_irqs(struct sdhci_host *host) 2591c6a0718SPierre Ossman { 260b537f94cSRussell King host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 261b537f94cSRussell King SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | 262b537f94cSRussell King SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | 263b537f94cSRussell King SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | 264b537f94cSRussell King SDHCI_INT_RESPONSE; 265b537f94cSRussell King 266f37b20ebSDong Aisheng if (host->tuning_mode == SDHCI_TUNING_MODE_2 || 267f37b20ebSDong Aisheng host->tuning_mode == SDHCI_TUNING_MODE_3) 268f37b20ebSDong Aisheng host->ier |= SDHCI_INT_RETUNE; 269f37b20ebSDong Aisheng 270b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 271b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 272f5c1ab82SAdrian Hunter } 273f5c1ab82SAdrian Hunter 274685e444bSChunyan Zhang static void sdhci_config_dma(struct sdhci_host *host) 275685e444bSChunyan Zhang { 276685e444bSChunyan Zhang u8 ctrl; 277685e444bSChunyan Zhang u16 ctrl2; 278685e444bSChunyan Zhang 279685e444bSChunyan Zhang if (host->version < SDHCI_SPEC_200) 280685e444bSChunyan Zhang return; 281685e444bSChunyan Zhang 282685e444bSChunyan Zhang ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 283685e444bSChunyan Zhang 284685e444bSChunyan Zhang /* 285685e444bSChunyan Zhang * Always adjust the DMA selection as some controllers 286685e444bSChunyan Zhang * (e.g. JMicron) can't do PIO properly when the selection 287685e444bSChunyan Zhang * is ADMA. 288685e444bSChunyan Zhang */ 289685e444bSChunyan Zhang ctrl &= ~SDHCI_CTRL_DMA_MASK; 290685e444bSChunyan Zhang if (!(host->flags & SDHCI_REQ_USE_DMA)) 291685e444bSChunyan Zhang goto out; 292685e444bSChunyan Zhang 293685e444bSChunyan Zhang /* Note if DMA Select is zero then SDMA is selected */ 294685e444bSChunyan Zhang if (host->flags & SDHCI_USE_ADMA) 295685e444bSChunyan Zhang ctrl |= SDHCI_CTRL_ADMA32; 296685e444bSChunyan Zhang 297685e444bSChunyan Zhang if (host->flags & SDHCI_USE_64_BIT_DMA) { 298685e444bSChunyan Zhang /* 299685e444bSChunyan Zhang * If v4 mode, all supported DMA can be 64-bit addressing if 300685e444bSChunyan Zhang * controller supports 64-bit system address, otherwise only 301685e444bSChunyan Zhang * ADMA can support 64-bit addressing. 302685e444bSChunyan Zhang */ 303685e444bSChunyan Zhang if (host->v4_mode) { 304685e444bSChunyan Zhang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 305685e444bSChunyan Zhang ctrl2 |= SDHCI_CTRL_64BIT_ADDR; 306685e444bSChunyan Zhang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 307685e444bSChunyan Zhang } else if (host->flags & SDHCI_USE_ADMA) { 308685e444bSChunyan Zhang /* 309685e444bSChunyan Zhang * Don't need to undo SDHCI_CTRL_ADMA32 in order to 310685e444bSChunyan Zhang * set SDHCI_CTRL_ADMA64. 311685e444bSChunyan Zhang */ 312685e444bSChunyan Zhang ctrl |= SDHCI_CTRL_ADMA64; 313685e444bSChunyan Zhang } 314685e444bSChunyan Zhang } 315685e444bSChunyan Zhang 316685e444bSChunyan Zhang out: 317685e444bSChunyan Zhang sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 318685e444bSChunyan Zhang } 319685e444bSChunyan Zhang 320f5c1ab82SAdrian Hunter static void sdhci_init(struct sdhci_host *host, int soft) 321f5c1ab82SAdrian Hunter { 322f5c1ab82SAdrian Hunter struct mmc_host *mmc = host->mmc; 32349769d4dSHaibo Chen unsigned long flags; 324f5c1ab82SAdrian Hunter 325f5c1ab82SAdrian Hunter if (soft) 326f5c1ab82SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 327f5c1ab82SAdrian Hunter else 328f5c1ab82SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_ALL); 329f5c1ab82SAdrian Hunter 330b3f80b43SChunyan Zhang if (host->v4_mode) 331b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host); 332b3f80b43SChunyan Zhang 33349769d4dSHaibo Chen spin_lock_irqsave(&host->lock, flags); 334f5c1ab82SAdrian Hunter sdhci_set_default_irqs(host); 33549769d4dSHaibo Chen spin_unlock_irqrestore(&host->lock, flags); 3362f4cbb3dSNicolas Pitre 337f12e39dbSAdrian Hunter host->cqe_on = false; 338f12e39dbSAdrian Hunter 3392f4cbb3dSNicolas Pitre if (soft) { 3402f4cbb3dSNicolas Pitre /* force clock reconfiguration */ 3412f4cbb3dSNicolas Pitre host->clock = 0; 342d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 3432f4cbb3dSNicolas Pitre } 3447260cf5eSAnton Vorontsov } 3451c6a0718SPierre Ossman 3467260cf5eSAnton Vorontsov static void sdhci_reinit(struct sdhci_host *host) 3477260cf5eSAnton Vorontsov { 348dcaac3f7SRaul E Rangel u32 cd = host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); 349dcaac3f7SRaul E Rangel 3502f4cbb3dSNicolas Pitre sdhci_init(host, 0); 3517260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 352dcaac3f7SRaul E Rangel 353dcaac3f7SRaul E Rangel /* 354dcaac3f7SRaul E Rangel * A change to the card detect bits indicates a change in present state, 355dcaac3f7SRaul E Rangel * refer sdhci_set_card_detection(). A card detect interrupt might have 356dcaac3f7SRaul E Rangel * been missed while the host controller was being reset, so trigger a 357dcaac3f7SRaul E Rangel * rescan to check. 358dcaac3f7SRaul E Rangel */ 359dcaac3f7SRaul E Rangel if (cd != (host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT))) 360dcaac3f7SRaul E Rangel mmc_detect_change(host->mmc, msecs_to_jiffies(200)); 3611c6a0718SPierre Ossman } 3621c6a0718SPierre Ossman 363061d17a6SAdrian Hunter static void __sdhci_led_activate(struct sdhci_host *host) 3641c6a0718SPierre Ossman { 3651c6a0718SPierre Ossman u8 ctrl; 3661c6a0718SPierre Ossman 367bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 368bd29f58bSAdrian Hunter return; 369bd29f58bSAdrian Hunter 3704e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 3711c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_LED; 3724e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 3731c6a0718SPierre Ossman } 3741c6a0718SPierre Ossman 375061d17a6SAdrian Hunter static void __sdhci_led_deactivate(struct sdhci_host *host) 3761c6a0718SPierre Ossman { 3771c6a0718SPierre Ossman u8 ctrl; 3781c6a0718SPierre Ossman 379bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 380bd29f58bSAdrian Hunter return; 381bd29f58bSAdrian Hunter 3824e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 3831c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_LED; 3844e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 3851c6a0718SPierre Ossman } 3861c6a0718SPierre Ossman 3874f78230fSMasahiro Yamada #if IS_REACHABLE(CONFIG_LEDS_CLASS) 3882f730fecSPierre Ossman static void sdhci_led_control(struct led_classdev *led, 3892f730fecSPierre Ossman enum led_brightness brightness) 3902f730fecSPierre Ossman { 3912f730fecSPierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led); 3922f730fecSPierre Ossman unsigned long flags; 3932f730fecSPierre Ossman 3942f730fecSPierre Ossman spin_lock_irqsave(&host->lock, flags); 3952f730fecSPierre Ossman 39666fd8ad5SAdrian Hunter if (host->runtime_suspended) 39766fd8ad5SAdrian Hunter goto out; 39866fd8ad5SAdrian Hunter 3992f730fecSPierre Ossman if (brightness == LED_OFF) 400061d17a6SAdrian Hunter __sdhci_led_deactivate(host); 4012f730fecSPierre Ossman else 402061d17a6SAdrian Hunter __sdhci_led_activate(host); 40366fd8ad5SAdrian Hunter out: 4042f730fecSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 4052f730fecSPierre Ossman } 406061d17a6SAdrian Hunter 407061d17a6SAdrian Hunter static int sdhci_led_register(struct sdhci_host *host) 408061d17a6SAdrian Hunter { 409061d17a6SAdrian Hunter struct mmc_host *mmc = host->mmc; 410061d17a6SAdrian Hunter 411bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 412bd29f58bSAdrian Hunter return 0; 413bd29f58bSAdrian Hunter 414061d17a6SAdrian Hunter snprintf(host->led_name, sizeof(host->led_name), 415061d17a6SAdrian Hunter "%s::", mmc_hostname(mmc)); 416061d17a6SAdrian Hunter 417061d17a6SAdrian Hunter host->led.name = host->led_name; 418061d17a6SAdrian Hunter host->led.brightness = LED_OFF; 419061d17a6SAdrian Hunter host->led.default_trigger = mmc_hostname(mmc); 420061d17a6SAdrian Hunter host->led.brightness_set = sdhci_led_control; 421061d17a6SAdrian Hunter 422061d17a6SAdrian Hunter return led_classdev_register(mmc_dev(mmc), &host->led); 423061d17a6SAdrian Hunter } 424061d17a6SAdrian Hunter 425061d17a6SAdrian Hunter static void sdhci_led_unregister(struct sdhci_host *host) 426061d17a6SAdrian Hunter { 427bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED) 428bd29f58bSAdrian Hunter return; 429bd29f58bSAdrian Hunter 430061d17a6SAdrian Hunter led_classdev_unregister(&host->led); 431061d17a6SAdrian Hunter } 432061d17a6SAdrian Hunter 433061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host) 434061d17a6SAdrian Hunter { 435061d17a6SAdrian Hunter } 436061d17a6SAdrian Hunter 437061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host) 438061d17a6SAdrian Hunter { 439061d17a6SAdrian Hunter } 440061d17a6SAdrian Hunter 441061d17a6SAdrian Hunter #else 442061d17a6SAdrian Hunter 443061d17a6SAdrian Hunter static inline int sdhci_led_register(struct sdhci_host *host) 444061d17a6SAdrian Hunter { 445061d17a6SAdrian Hunter return 0; 446061d17a6SAdrian Hunter } 447061d17a6SAdrian Hunter 448061d17a6SAdrian Hunter static inline void sdhci_led_unregister(struct sdhci_host *host) 449061d17a6SAdrian Hunter { 450061d17a6SAdrian Hunter } 451061d17a6SAdrian Hunter 452061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host) 453061d17a6SAdrian Hunter { 454061d17a6SAdrian Hunter __sdhci_led_activate(host); 455061d17a6SAdrian Hunter } 456061d17a6SAdrian Hunter 457061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host) 458061d17a6SAdrian Hunter { 459061d17a6SAdrian Hunter __sdhci_led_deactivate(host); 460061d17a6SAdrian Hunter } 461061d17a6SAdrian Hunter 4622f730fecSPierre Ossman #endif 4632f730fecSPierre Ossman 46497a1abaeSAdrian Hunter static void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, 46597a1abaeSAdrian Hunter unsigned long timeout) 46697a1abaeSAdrian Hunter { 46797a1abaeSAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd)) 46897a1abaeSAdrian Hunter mod_timer(&host->data_timer, timeout); 46997a1abaeSAdrian Hunter else 47097a1abaeSAdrian Hunter mod_timer(&host->timer, timeout); 47197a1abaeSAdrian Hunter } 47297a1abaeSAdrian Hunter 47397a1abaeSAdrian Hunter static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq) 47497a1abaeSAdrian Hunter { 47597a1abaeSAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd)) 47697a1abaeSAdrian Hunter del_timer(&host->data_timer); 47797a1abaeSAdrian Hunter else 47897a1abaeSAdrian Hunter del_timer(&host->timer); 47997a1abaeSAdrian Hunter } 48097a1abaeSAdrian Hunter 48197a1abaeSAdrian Hunter static inline bool sdhci_has_requests(struct sdhci_host *host) 48297a1abaeSAdrian Hunter { 48397a1abaeSAdrian Hunter return host->cmd || host->data_cmd; 48497a1abaeSAdrian Hunter } 48597a1abaeSAdrian Hunter 4861c6a0718SPierre Ossman /*****************************************************************************\ 4871c6a0718SPierre Ossman * * 4881c6a0718SPierre Ossman * Core functions * 4891c6a0718SPierre Ossman * * 4901c6a0718SPierre Ossman \*****************************************************************************/ 4911c6a0718SPierre Ossman 4921c6a0718SPierre Ossman static void sdhci_read_block_pio(struct sdhci_host *host) 4931c6a0718SPierre Ossman { 4947659150cSPierre Ossman unsigned long flags; 4957659150cSPierre Ossman size_t blksize, len, chunk; 4967244b85bSSteven Noonan u32 uninitialized_var(scratch); 4977659150cSPierre Ossman u8 *buf; 4981c6a0718SPierre Ossman 4991c6a0718SPierre Ossman DBG("PIO reading\n"); 5001c6a0718SPierre Ossman 5011c6a0718SPierre Ossman blksize = host->data->blksz; 5027659150cSPierre Ossman chunk = 0; 5031c6a0718SPierre Ossman 5047659150cSPierre Ossman local_irq_save(flags); 5051c6a0718SPierre Ossman 5061c6a0718SPierre Ossman while (blksize) { 507bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter)); 5087659150cSPierre Ossman 5097659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 5107659150cSPierre Ossman 5117659150cSPierre Ossman blksize -= len; 5127659150cSPierre Ossman host->sg_miter.consumed = len; 5137659150cSPierre Ossman 5147659150cSPierre Ossman buf = host->sg_miter.addr; 5157659150cSPierre Ossman 5167659150cSPierre Ossman while (len) { 5177659150cSPierre Ossman if (chunk == 0) { 5184e4141a5SAnton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER); 5197659150cSPierre Ossman chunk = 4; 5201c6a0718SPierre Ossman } 5211c6a0718SPierre Ossman 5227659150cSPierre Ossman *buf = scratch & 0xFF; 5231c6a0718SPierre Ossman 5247659150cSPierre Ossman buf++; 5257659150cSPierre Ossman scratch >>= 8; 5267659150cSPierre Ossman chunk--; 5277659150cSPierre Ossman len--; 5287659150cSPierre Ossman } 5291c6a0718SPierre Ossman } 5301c6a0718SPierre Ossman 5317659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 5327659150cSPierre Ossman 5337659150cSPierre Ossman local_irq_restore(flags); 5341c6a0718SPierre Ossman } 5351c6a0718SPierre Ossman 5361c6a0718SPierre Ossman static void sdhci_write_block_pio(struct sdhci_host *host) 5371c6a0718SPierre Ossman { 5387659150cSPierre Ossman unsigned long flags; 5397659150cSPierre Ossman size_t blksize, len, chunk; 5407659150cSPierre Ossman u32 scratch; 5417659150cSPierre Ossman u8 *buf; 5421c6a0718SPierre Ossman 5431c6a0718SPierre Ossman DBG("PIO writing\n"); 5441c6a0718SPierre Ossman 5451c6a0718SPierre Ossman blksize = host->data->blksz; 5467659150cSPierre Ossman chunk = 0; 5477659150cSPierre Ossman scratch = 0; 5481c6a0718SPierre Ossman 5497659150cSPierre Ossman local_irq_save(flags); 5501c6a0718SPierre Ossman 5511c6a0718SPierre Ossman while (blksize) { 552bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter)); 5531c6a0718SPierre Ossman 5547659150cSPierre Ossman len = min(host->sg_miter.length, blksize); 5551c6a0718SPierre Ossman 5567659150cSPierre Ossman blksize -= len; 5577659150cSPierre Ossman host->sg_miter.consumed = len; 5587659150cSPierre Ossman 5597659150cSPierre Ossman buf = host->sg_miter.addr; 5607659150cSPierre Ossman 5617659150cSPierre Ossman while (len) { 5627659150cSPierre Ossman scratch |= (u32)*buf << (chunk * 8); 5637659150cSPierre Ossman 5647659150cSPierre Ossman buf++; 5657659150cSPierre Ossman chunk++; 5667659150cSPierre Ossman len--; 5677659150cSPierre Ossman 5687659150cSPierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) { 5694e4141a5SAnton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER); 5707659150cSPierre Ossman chunk = 0; 5717659150cSPierre Ossman scratch = 0; 5727659150cSPierre Ossman } 5737659150cSPierre Ossman } 5741c6a0718SPierre Ossman } 5751c6a0718SPierre Ossman 5767659150cSPierre Ossman sg_miter_stop(&host->sg_miter); 5771c6a0718SPierre Ossman 5787659150cSPierre Ossman local_irq_restore(flags); 5791c6a0718SPierre Ossman } 5801c6a0718SPierre Ossman 5811c6a0718SPierre Ossman static void sdhci_transfer_pio(struct sdhci_host *host) 5821c6a0718SPierre Ossman { 5831c6a0718SPierre Ossman u32 mask; 5841c6a0718SPierre Ossman 5857659150cSPierre Ossman if (host->blocks == 0) 5861c6a0718SPierre Ossman return; 5871c6a0718SPierre Ossman 5881c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 5891c6a0718SPierre Ossman mask = SDHCI_DATA_AVAILABLE; 5901c6a0718SPierre Ossman else 5911c6a0718SPierre Ossman mask = SDHCI_SPACE_AVAILABLE; 5921c6a0718SPierre Ossman 5934a3cba32SPierre Ossman /* 5944a3cba32SPierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits 5954a3cba32SPierre Ossman * for transfers < 4 bytes. As long as it is just one block, 5964a3cba32SPierre Ossman * we can ignore the bits. 5974a3cba32SPierre Ossman */ 5984a3cba32SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && 5994a3cba32SPierre Ossman (host->data->blocks == 1)) 6004a3cba32SPierre Ossman mask = ~0; 6014a3cba32SPierre Ossman 6024e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { 6033e3bf207SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) 6043e3bf207SAnton Vorontsov udelay(100); 6053e3bf207SAnton Vorontsov 6061c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ) 6071c6a0718SPierre Ossman sdhci_read_block_pio(host); 6081c6a0718SPierre Ossman else 6091c6a0718SPierre Ossman sdhci_write_block_pio(host); 6101c6a0718SPierre Ossman 6117659150cSPierre Ossman host->blocks--; 6127659150cSPierre Ossman if (host->blocks == 0) 6131c6a0718SPierre Ossman break; 6141c6a0718SPierre Ossman } 6151c6a0718SPierre Ossman 6161c6a0718SPierre Ossman DBG("PIO transfer complete.\n"); 6171c6a0718SPierre Ossman } 6181c6a0718SPierre Ossman 61948857d9bSRussell King static int sdhci_pre_dma_transfer(struct sdhci_host *host, 620c0999b72SRussell King struct mmc_data *data, int cookie) 62148857d9bSRussell King { 62248857d9bSRussell King int sg_count; 62348857d9bSRussell King 62494538e51SRussell King /* 62594538e51SRussell King * If the data buffers are already mapped, return the previous 62694538e51SRussell King * dma_map_sg() result. 62794538e51SRussell King */ 62894538e51SRussell King if (data->host_cookie == COOKIE_PRE_MAPPED) 62948857d9bSRussell King return data->sg_count; 63048857d9bSRussell King 631bd9b9027SLinus Walleij /* Bounce write requests to the bounce buffer */ 632bd9b9027SLinus Walleij if (host->bounce_buffer) { 633bd9b9027SLinus Walleij unsigned int length = data->blksz * data->blocks; 634bd9b9027SLinus Walleij 635bd9b9027SLinus Walleij if (length > host->bounce_buffer_size) { 636bd9b9027SLinus Walleij pr_err("%s: asked for transfer of %u bytes exceeds bounce buffer %u bytes\n", 637bd9b9027SLinus Walleij mmc_hostname(host->mmc), length, 638bd9b9027SLinus Walleij host->bounce_buffer_size); 639bd9b9027SLinus Walleij return -EIO; 640bd9b9027SLinus Walleij } 641bd9b9027SLinus Walleij if (mmc_get_dma_dir(data) == DMA_TO_DEVICE) { 642bd9b9027SLinus Walleij /* Copy the data to the bounce buffer */ 643e93577ecSAngelo Dureghello if (host->ops->copy_to_bounce_buffer) { 644e93577ecSAngelo Dureghello host->ops->copy_to_bounce_buffer(host, 645e93577ecSAngelo Dureghello data, length); 646e93577ecSAngelo Dureghello } else { 647bd9b9027SLinus Walleij sg_copy_to_buffer(data->sg, data->sg_len, 648e93577ecSAngelo Dureghello host->bounce_buffer, length); 649e93577ecSAngelo Dureghello } 650bd9b9027SLinus Walleij } 651bd9b9027SLinus Walleij /* Switch ownership to the DMA */ 652bd9b9027SLinus Walleij dma_sync_single_for_device(host->mmc->parent, 653bd9b9027SLinus Walleij host->bounce_addr, 654bd9b9027SLinus Walleij host->bounce_buffer_size, 655feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 656bd9b9027SLinus Walleij /* Just a dummy value */ 657bd9b9027SLinus Walleij sg_count = 1; 658bd9b9027SLinus Walleij } else { 659bd9b9027SLinus Walleij /* Just access the data directly from memory */ 660bd9b9027SLinus Walleij sg_count = dma_map_sg(mmc_dev(host->mmc), 661bd9b9027SLinus Walleij data->sg, data->sg_len, 662bd9b9027SLinus Walleij mmc_get_dma_dir(data)); 663bd9b9027SLinus Walleij } 66448857d9bSRussell King 66548857d9bSRussell King if (sg_count == 0) 66648857d9bSRussell King return -ENOSPC; 66748857d9bSRussell King 66848857d9bSRussell King data->sg_count = sg_count; 669c0999b72SRussell King data->host_cookie = cookie; 67048857d9bSRussell King 67148857d9bSRussell King return sg_count; 67248857d9bSRussell King } 67348857d9bSRussell King 6742134a922SPierre Ossman static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) 6752134a922SPierre Ossman { 6762134a922SPierre Ossman local_irq_save(*flags); 677482fce99SCong Wang return kmap_atomic(sg_page(sg)) + sg->offset; 6782134a922SPierre Ossman } 6792134a922SPierre Ossman 6802134a922SPierre Ossman static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) 6812134a922SPierre Ossman { 682482fce99SCong Wang kunmap_atomic(buffer); 6832134a922SPierre Ossman local_irq_restore(*flags); 6842134a922SPierre Ossman } 6852134a922SPierre Ossman 68654552e49SJisheng Zhang void sdhci_adma_write_desc(struct sdhci_host *host, void **desc, 68754552e49SJisheng Zhang dma_addr_t addr, int len, unsigned int cmd) 688118cd17dSBen Dooks { 68954552e49SJisheng Zhang struct sdhci_adma2_64_desc *dma_desc = *desc; 690118cd17dSBen Dooks 691e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have these members in same position */ 6920545230fSAdrian Hunter dma_desc->cmd = cpu_to_le16(cmd); 6930545230fSAdrian Hunter dma_desc->len = cpu_to_le16(len); 69438eee2e8SMasahiro Yamada dma_desc->addr_lo = cpu_to_le32(lower_32_bits(addr)); 695e57a5f61SAdrian Hunter 696e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 69738eee2e8SMasahiro Yamada dma_desc->addr_hi = cpu_to_le32(upper_32_bits(addr)); 69854552e49SJisheng Zhang 69954552e49SJisheng Zhang *desc += host->desc_sz; 70054552e49SJisheng Zhang } 70154552e49SJisheng Zhang EXPORT_SYMBOL_GPL(sdhci_adma_write_desc); 70254552e49SJisheng Zhang 70354552e49SJisheng Zhang static inline void __sdhci_adma_write_desc(struct sdhci_host *host, 70454552e49SJisheng Zhang void **desc, dma_addr_t addr, 70554552e49SJisheng Zhang int len, unsigned int cmd) 70654552e49SJisheng Zhang { 70754552e49SJisheng Zhang if (host->ops->adma_write_desc) 70854552e49SJisheng Zhang host->ops->adma_write_desc(host, desc, addr, len, cmd); 70907be55b5SJisheng Zhang else 71054552e49SJisheng Zhang sdhci_adma_write_desc(host, desc, addr, len, cmd); 711118cd17dSBen Dooks } 712118cd17dSBen Dooks 713b5ffa674SAdrian Hunter static void sdhci_adma_mark_end(void *desc) 714b5ffa674SAdrian Hunter { 715e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 716b5ffa674SAdrian Hunter 717e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have 'cmd' in same position */ 7180545230fSAdrian Hunter dma_desc->cmd |= cpu_to_le16(ADMA2_END); 719b5ffa674SAdrian Hunter } 720b5ffa674SAdrian Hunter 72160c64762SRussell King static void sdhci_adma_table_pre(struct sdhci_host *host, 72260c64762SRussell King struct mmc_data *data, int sg_count) 7232134a922SPierre Ossman { 7242134a922SPierre Ossman struct scatterlist *sg; 7252134a922SPierre Ossman unsigned long flags; 726acc3ad13SRussell King dma_addr_t addr, align_addr; 727acc3ad13SRussell King void *desc, *align; 728acc3ad13SRussell King char *buffer; 729acc3ad13SRussell King int len, offset, i; 7302134a922SPierre Ossman 7312134a922SPierre Ossman /* 7322134a922SPierre Ossman * The spec does not specify endianness of descriptor table. 7332134a922SPierre Ossman * We currently guess that it is LE. 7342134a922SPierre Ossman */ 7352134a922SPierre Ossman 73660c64762SRussell King host->sg_count = sg_count; 7372134a922SPierre Ossman 7384efaa6fbSAdrian Hunter desc = host->adma_table; 7392134a922SPierre Ossman align = host->align_buffer; 7402134a922SPierre Ossman 7412134a922SPierre Ossman align_addr = host->align_addr; 7422134a922SPierre Ossman 7432134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 7442134a922SPierre Ossman addr = sg_dma_address(sg); 7452134a922SPierre Ossman len = sg_dma_len(sg); 7462134a922SPierre Ossman 7472134a922SPierre Ossman /* 748acc3ad13SRussell King * The SDHCI specification states that ADMA addresses must 749acc3ad13SRussell King * be 32-bit aligned. If they aren't, then we use a bounce 750acc3ad13SRussell King * buffer for the (up to three) bytes that screw up the 7512134a922SPierre Ossman * alignment. 7522134a922SPierre Ossman */ 75304a5ae6fSAdrian Hunter offset = (SDHCI_ADMA2_ALIGN - (addr & SDHCI_ADMA2_MASK)) & 75404a5ae6fSAdrian Hunter SDHCI_ADMA2_MASK; 7552134a922SPierre Ossman if (offset) { 7562134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) { 7572134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 7582134a922SPierre Ossman memcpy(align, buffer, offset); 7592134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 7602134a922SPierre Ossman } 7612134a922SPierre Ossman 762118cd17dSBen Dooks /* tran, valid */ 76354552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, align_addr, 76454552e49SJisheng Zhang offset, ADMA2_TRAN_VALID); 7652134a922SPierre Ossman 7662134a922SPierre Ossman BUG_ON(offset > 65536); 7672134a922SPierre Ossman 76804a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN; 76904a5ae6fSAdrian Hunter align_addr += SDHCI_ADMA2_ALIGN; 7702134a922SPierre Ossman 7712134a922SPierre Ossman addr += offset; 7722134a922SPierre Ossman len -= offset; 7732134a922SPierre Ossman } 7742134a922SPierre Ossman 7752134a922SPierre Ossman BUG_ON(len > 65536); 7762134a922SPierre Ossman 777118cd17dSBen Dooks /* tran, valid */ 77854552e49SJisheng Zhang if (len) 77954552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, addr, len, 780347ea32dSAdrian Hunter ADMA2_TRAN_VALID); 7812134a922SPierre Ossman 7822134a922SPierre Ossman /* 7832134a922SPierre Ossman * If this triggers then we have a calculation bug 7842134a922SPierre Ossman * somewhere. :/ 7852134a922SPierre Ossman */ 78676fe379aSAdrian Hunter WARN_ON((desc - host->adma_table) >= host->adma_table_sz); 7872134a922SPierre Ossman } 7882134a922SPierre Ossman 78970764a90SThomas Abraham if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { 790acc3ad13SRussell King /* Mark the last descriptor as the terminating descriptor */ 7914efaa6fbSAdrian Hunter if (desc != host->adma_table) { 79276fe379aSAdrian Hunter desc -= host->desc_sz; 793b5ffa674SAdrian Hunter sdhci_adma_mark_end(desc); 79470764a90SThomas Abraham } 79570764a90SThomas Abraham } else { 796acc3ad13SRussell King /* Add a terminating entry - nop, end, valid */ 79754552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, 0, 0, ADMA2_NOP_END_VALID); 79870764a90SThomas Abraham } 7992134a922SPierre Ossman } 8002134a922SPierre Ossman 8012134a922SPierre Ossman static void sdhci_adma_table_post(struct sdhci_host *host, 8022134a922SPierre Ossman struct mmc_data *data) 8032134a922SPierre Ossman { 8042134a922SPierre Ossman struct scatterlist *sg; 8052134a922SPierre Ossman int i, size; 8061c3d5f6dSAdrian Hunter void *align; 8072134a922SPierre Ossman char *buffer; 8082134a922SPierre Ossman unsigned long flags; 8092134a922SPierre Ossman 81047fa9613SRussell King if (data->flags & MMC_DATA_READ) { 81147fa9613SRussell King bool has_unaligned = false; 81247fa9613SRussell King 813de0b65a7SRussell King /* Do a quick scan of the SG list for any unaligned mappings */ 814de0b65a7SRussell King for_each_sg(data->sg, sg, host->sg_count, i) 81504a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { 816de0b65a7SRussell King has_unaligned = true; 817de0b65a7SRussell King break; 818de0b65a7SRussell King } 819de0b65a7SRussell King 82047fa9613SRussell King if (has_unaligned) { 8212134a922SPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, 822f55c98f7SRussell King data->sg_len, DMA_FROM_DEVICE); 8232134a922SPierre Ossman 8242134a922SPierre Ossman align = host->align_buffer; 8252134a922SPierre Ossman 8262134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) { 82704a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { 82804a5ae6fSAdrian Hunter size = SDHCI_ADMA2_ALIGN - 82904a5ae6fSAdrian Hunter (sg_dma_address(sg) & SDHCI_ADMA2_MASK); 8302134a922SPierre Ossman 8312134a922SPierre Ossman buffer = sdhci_kmap_atomic(sg, &flags); 8322134a922SPierre Ossman memcpy(buffer, align, size); 8332134a922SPierre Ossman sdhci_kunmap_atomic(buffer, &flags); 8342134a922SPierre Ossman 83504a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN; 8362134a922SPierre Ossman } 8372134a922SPierre Ossman } 8382134a922SPierre Ossman } 83947fa9613SRussell King } 8402134a922SPierre Ossman } 8412134a922SPierre Ossman 84238eee2e8SMasahiro Yamada static void sdhci_set_adma_addr(struct sdhci_host *host, dma_addr_t addr) 84338eee2e8SMasahiro Yamada { 84438eee2e8SMasahiro Yamada sdhci_writel(host, lower_32_bits(addr), SDHCI_ADMA_ADDRESS); 84538eee2e8SMasahiro Yamada if (host->flags & SDHCI_USE_64_BIT_DMA) 84638eee2e8SMasahiro Yamada sdhci_writel(host, upper_32_bits(addr), SDHCI_ADMA_ADDRESS_HI); 84738eee2e8SMasahiro Yamada } 84838eee2e8SMasahiro Yamada 849917a0c52SChunyan Zhang static dma_addr_t sdhci_sdma_address(struct sdhci_host *host) 850bd9b9027SLinus Walleij { 851bd9b9027SLinus Walleij if (host->bounce_buffer) 852bd9b9027SLinus Walleij return host->bounce_addr; 853bd9b9027SLinus Walleij else 854bd9b9027SLinus Walleij return sg_dma_address(host->data->sg); 855bd9b9027SLinus Walleij } 856bd9b9027SLinus Walleij 857917a0c52SChunyan Zhang static void sdhci_set_sdma_addr(struct sdhci_host *host, dma_addr_t addr) 858917a0c52SChunyan Zhang { 85938eee2e8SMasahiro Yamada if (host->v4_mode) 86038eee2e8SMasahiro Yamada sdhci_set_adma_addr(host, addr); 86138eee2e8SMasahiro Yamada else 862917a0c52SChunyan Zhang sdhci_writel(host, addr, SDHCI_DMA_ADDRESS); 863917a0c52SChunyan Zhang } 864917a0c52SChunyan Zhang 8650bb28d73SAdrian Hunter static unsigned int sdhci_target_timeout(struct sdhci_host *host, 8660bb28d73SAdrian Hunter struct mmc_command *cmd, 8670bb28d73SAdrian Hunter struct mmc_data *data) 8680bb28d73SAdrian Hunter { 8690bb28d73SAdrian Hunter unsigned int target_timeout; 8700bb28d73SAdrian Hunter 8710bb28d73SAdrian Hunter /* timeout in us */ 8720bb28d73SAdrian Hunter if (!data) { 8730bb28d73SAdrian Hunter target_timeout = cmd->busy_timeout * 1000; 8740bb28d73SAdrian Hunter } else { 8750bb28d73SAdrian Hunter target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000); 8760bb28d73SAdrian Hunter if (host->clock && data->timeout_clks) { 8770bb28d73SAdrian Hunter unsigned long long val; 8780bb28d73SAdrian Hunter 8790bb28d73SAdrian Hunter /* 8800bb28d73SAdrian Hunter * data->timeout_clks is in units of clock cycles. 8810bb28d73SAdrian Hunter * host->clock is in Hz. target_timeout is in us. 8820bb28d73SAdrian Hunter * Hence, us = 1000000 * cycles / Hz. Round up. 8830bb28d73SAdrian Hunter */ 8840bb28d73SAdrian Hunter val = 1000000ULL * data->timeout_clks; 8850bb28d73SAdrian Hunter if (do_div(val, host->clock)) 8860bb28d73SAdrian Hunter target_timeout++; 8870bb28d73SAdrian Hunter target_timeout += val; 8880bb28d73SAdrian Hunter } 8890bb28d73SAdrian Hunter } 8900bb28d73SAdrian Hunter 8910bb28d73SAdrian Hunter return target_timeout; 8920bb28d73SAdrian Hunter } 8930bb28d73SAdrian Hunter 894fc1fa1b7SKishon Vijay Abraham I static void sdhci_calc_sw_timeout(struct sdhci_host *host, 895fc1fa1b7SKishon Vijay Abraham I struct mmc_command *cmd) 896fc1fa1b7SKishon Vijay Abraham I { 897fc1fa1b7SKishon Vijay Abraham I struct mmc_data *data = cmd->data; 898fc1fa1b7SKishon Vijay Abraham I struct mmc_host *mmc = host->mmc; 899fc1fa1b7SKishon Vijay Abraham I struct mmc_ios *ios = &mmc->ios; 900fc1fa1b7SKishon Vijay Abraham I unsigned char bus_width = 1 << ios->bus_width; 901fc1fa1b7SKishon Vijay Abraham I unsigned int blksz; 902fc1fa1b7SKishon Vijay Abraham I unsigned int freq; 903fc1fa1b7SKishon Vijay Abraham I u64 target_timeout; 904fc1fa1b7SKishon Vijay Abraham I u64 transfer_time; 905fc1fa1b7SKishon Vijay Abraham I 906fc1fa1b7SKishon Vijay Abraham I target_timeout = sdhci_target_timeout(host, cmd, data); 907fc1fa1b7SKishon Vijay Abraham I target_timeout *= NSEC_PER_USEC; 908fc1fa1b7SKishon Vijay Abraham I 909fc1fa1b7SKishon Vijay Abraham I if (data) { 910fc1fa1b7SKishon Vijay Abraham I blksz = data->blksz; 911fc1fa1b7SKishon Vijay Abraham I freq = host->mmc->actual_clock ? : host->clock; 912fc1fa1b7SKishon Vijay Abraham I transfer_time = (u64)blksz * NSEC_PER_SEC * (8 / bus_width); 913fc1fa1b7SKishon Vijay Abraham I do_div(transfer_time, freq); 914fc1fa1b7SKishon Vijay Abraham I /* multiply by '2' to account for any unknowns */ 915fc1fa1b7SKishon Vijay Abraham I transfer_time = transfer_time * 2; 916fc1fa1b7SKishon Vijay Abraham I /* calculate timeout for the entire data */ 917fc1fa1b7SKishon Vijay Abraham I host->data_timeout = data->blocks * target_timeout + 918fc1fa1b7SKishon Vijay Abraham I transfer_time; 919fc1fa1b7SKishon Vijay Abraham I } else { 920fc1fa1b7SKishon Vijay Abraham I host->data_timeout = target_timeout; 921fc1fa1b7SKishon Vijay Abraham I } 922fc1fa1b7SKishon Vijay Abraham I 923fc1fa1b7SKishon Vijay Abraham I if (host->data_timeout) 924fc1fa1b7SKishon Vijay Abraham I host->data_timeout += MMC_CMD_TRANSFER_TIME; 925fc1fa1b7SKishon Vijay Abraham I } 926fc1fa1b7SKishon Vijay Abraham I 927a999fd93SAdrian Hunter static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd, 928a999fd93SAdrian Hunter bool *too_big) 9291c6a0718SPierre Ossman { 9301c6a0718SPierre Ossman u8 count; 931401059dfSBOUGH CHEN struct mmc_data *data; 9321c6a0718SPierre Ossman unsigned target_timeout, current_timeout; 9331c6a0718SPierre Ossman 934a999fd93SAdrian Hunter *too_big = true; 935a999fd93SAdrian Hunter 936ee53ab5dSPierre Ossman /* 937ee53ab5dSPierre Ossman * If the host controller provides us with an incorrect timeout 938ee53ab5dSPierre Ossman * value, just skip the check and use 0xE. The hardware may take 939ee53ab5dSPierre Ossman * longer to time out, but that's much better than having a too-short 940ee53ab5dSPierre Ossman * timeout value. 941ee53ab5dSPierre Ossman */ 94211a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) 943ee53ab5dSPierre Ossman return 0xE; 944e538fbe8SPierre Ossman 945401059dfSBOUGH CHEN /* Unspecified command, asume max */ 946401059dfSBOUGH CHEN if (cmd == NULL) 947401059dfSBOUGH CHEN return 0xE; 948401059dfSBOUGH CHEN 949401059dfSBOUGH CHEN data = cmd->data; 950a3c7778fSAndrei Warkentin /* Unspecified timeout, assume max */ 9511d4d7744SUlf Hansson if (!data && !cmd->busy_timeout) 952a3c7778fSAndrei Warkentin return 0xE; 953a3c7778fSAndrei Warkentin 9541c6a0718SPierre Ossman /* timeout in us */ 9550bb28d73SAdrian Hunter target_timeout = sdhci_target_timeout(host, cmd, data); 9561c6a0718SPierre Ossman 9571c6a0718SPierre Ossman /* 9581c6a0718SPierre Ossman * Figure out needed cycles. 9591c6a0718SPierre Ossman * We do this in steps in order to fit inside a 32 bit int. 9601c6a0718SPierre Ossman * The first step is the minimum timeout, which will have a 9611c6a0718SPierre Ossman * minimum resolution of 6 bits: 9621c6a0718SPierre Ossman * (1) 2^13*1000 > 2^22, 9631c6a0718SPierre Ossman * (2) host->timeout_clk < 2^16 9641c6a0718SPierre Ossman * => 9651c6a0718SPierre Ossman * (1) / (2) > 2^6 9661c6a0718SPierre Ossman */ 9671c6a0718SPierre Ossman count = 0; 9681c6a0718SPierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk; 9691c6a0718SPierre Ossman while (current_timeout < target_timeout) { 9701c6a0718SPierre Ossman count++; 9711c6a0718SPierre Ossman current_timeout <<= 1; 9721c6a0718SPierre Ossman if (count >= 0xF) 9731c6a0718SPierre Ossman break; 9741c6a0718SPierre Ossman } 9751c6a0718SPierre Ossman 9761c6a0718SPierre Ossman if (count >= 0xF) { 977a999fd93SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT)) 978f421865dSAdrian Hunter DBG("Too large timeout 0x%x requested for CMD%d!\n", 979f421865dSAdrian Hunter count, cmd->opcode); 9801c6a0718SPierre Ossman count = 0xE; 981a999fd93SAdrian Hunter } else { 982a999fd93SAdrian Hunter *too_big = false; 9831c6a0718SPierre Ossman } 9841c6a0718SPierre Ossman 985ee53ab5dSPierre Ossman return count; 986ee53ab5dSPierre Ossman } 987ee53ab5dSPierre Ossman 9886aa943abSAnton Vorontsov static void sdhci_set_transfer_irqs(struct sdhci_host *host) 9896aa943abSAnton Vorontsov { 9906aa943abSAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; 9916aa943abSAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; 9926aa943abSAnton Vorontsov 9936aa943abSAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA) 994b537f94cSRussell King host->ier = (host->ier & ~pio_irqs) | dma_irqs; 9956aa943abSAnton Vorontsov else 996b537f94cSRussell King host->ier = (host->ier & ~dma_irqs) | pio_irqs; 997b537f94cSRussell King 998af849c86SAdrian Hunter if (host->flags & (SDHCI_AUTO_CMD23 | SDHCI_AUTO_CMD12)) 999af849c86SAdrian Hunter host->ier |= SDHCI_INT_AUTO_CMD_ERR; 1000af849c86SAdrian Hunter else 1001af849c86SAdrian Hunter host->ier &= ~SDHCI_INT_AUTO_CMD_ERR; 1002af849c86SAdrian Hunter 1003b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 1004b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 10056aa943abSAnton Vorontsov } 10066aa943abSAnton Vorontsov 10077907ebe7SFaiz Abbas void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable) 1008a999fd93SAdrian Hunter { 1009a999fd93SAdrian Hunter if (enable) 1010a999fd93SAdrian Hunter host->ier |= SDHCI_INT_DATA_TIMEOUT; 1011a999fd93SAdrian Hunter else 1012a999fd93SAdrian Hunter host->ier &= ~SDHCI_INT_DATA_TIMEOUT; 1013a999fd93SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 1014a999fd93SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 1015a999fd93SAdrian Hunter } 10167907ebe7SFaiz Abbas EXPORT_SYMBOL_GPL(sdhci_set_data_timeout_irq); 1017a999fd93SAdrian Hunter 10187d76ed77SFaiz Abbas void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) 1019ee53ab5dSPierre Ossman { 1020a999fd93SAdrian Hunter bool too_big = false; 10217d76ed77SFaiz Abbas u8 count = sdhci_calc_timeout(host, cmd, &too_big); 1022a999fd93SAdrian Hunter 1023a999fd93SAdrian Hunter if (too_big && 1024a999fd93SAdrian Hunter host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) { 1025fc1fa1b7SKishon Vijay Abraham I sdhci_calc_sw_timeout(host, cmd); 1026a999fd93SAdrian Hunter sdhci_set_data_timeout_irq(host, false); 1027a999fd93SAdrian Hunter } else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT)) { 1028a999fd93SAdrian Hunter sdhci_set_data_timeout_irq(host, true); 1029a999fd93SAdrian Hunter } 1030a999fd93SAdrian Hunter 1031b45e668aSAisheng Dong sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); 1032b45e668aSAisheng Dong } 10337d76ed77SFaiz Abbas EXPORT_SYMBOL_GPL(__sdhci_set_timeout); 10347d76ed77SFaiz Abbas 10357d76ed77SFaiz Abbas static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) 10367d76ed77SFaiz Abbas { 10377d76ed77SFaiz Abbas if (host->ops->set_timeout) 10387d76ed77SFaiz Abbas host->ops->set_timeout(host, cmd); 10397d76ed77SFaiz Abbas else 10407d76ed77SFaiz Abbas __sdhci_set_timeout(host, cmd); 1041b45e668aSAisheng Dong } 1042b45e668aSAisheng Dong 104315db1836SFaiz Abbas static void sdhci_initialize_data(struct sdhci_host *host, 104415db1836SFaiz Abbas struct mmc_data *data) 1045b45e668aSAisheng Dong { 104643dea098SAdrian Hunter WARN_ON(host->data); 104743dea098SAdrian Hunter 1048ee53ab5dSPierre Ossman /* Sanity checks */ 1049ee53ab5dSPierre Ossman BUG_ON(data->blksz * data->blocks > 524288); 1050ee53ab5dSPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size); 1051ee53ab5dSPierre Ossman BUG_ON(data->blocks > 65535); 1052ee53ab5dSPierre Ossman 1053ee53ab5dSPierre Ossman host->data = data; 1054ee53ab5dSPierre Ossman host->data_early = 0; 1055f6a03cbfSMikko Vinni host->data->bytes_xfered = 0; 105615db1836SFaiz Abbas } 105715db1836SFaiz Abbas 105815db1836SFaiz Abbas static inline void sdhci_set_block_info(struct sdhci_host *host, 105915db1836SFaiz Abbas struct mmc_data *data) 106015db1836SFaiz Abbas { 106115db1836SFaiz Abbas /* Set the DMA boundary value and block size */ 106215db1836SFaiz Abbas sdhci_writew(host, 106315db1836SFaiz Abbas SDHCI_MAKE_BLKSZ(host->sdma_boundary, data->blksz), 106415db1836SFaiz Abbas SDHCI_BLOCK_SIZE); 106515db1836SFaiz Abbas /* 106615db1836SFaiz Abbas * For Version 4.10 onwards, if v4 mode is enabled, 32-bit Block Count 106715db1836SFaiz Abbas * can be supported, in that case 16-bit block count register must be 0. 106815db1836SFaiz Abbas */ 106915db1836SFaiz Abbas if (host->version >= SDHCI_SPEC_410 && host->v4_mode && 107015db1836SFaiz Abbas (host->quirks2 & SDHCI_QUIRK2_USE_32BIT_BLK_CNT)) { 107115db1836SFaiz Abbas if (sdhci_readw(host, SDHCI_BLOCK_COUNT)) 107215db1836SFaiz Abbas sdhci_writew(host, 0, SDHCI_BLOCK_COUNT); 107315db1836SFaiz Abbas sdhci_writew(host, data->blocks, SDHCI_32BIT_BLK_CNT); 107415db1836SFaiz Abbas } else { 107515db1836SFaiz Abbas sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); 107615db1836SFaiz Abbas } 107715db1836SFaiz Abbas } 107815db1836SFaiz Abbas 107915db1836SFaiz Abbas static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) 108015db1836SFaiz Abbas { 108115db1836SFaiz Abbas struct mmc_data *data = cmd->data; 108215db1836SFaiz Abbas 108315db1836SFaiz Abbas sdhci_initialize_data(host, data); 1084ee53ab5dSPierre Ossman 1085fce14421SRussell King if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 1086fce14421SRussell King struct scatterlist *sg; 1087fce14421SRussell King unsigned int length_mask, offset_mask; 1088fce14421SRussell King int i; 1089fce14421SRussell King 1090c9fddbc4SPierre Ossman host->flags |= SDHCI_REQ_USE_DMA; 1091c9fddbc4SPierre Ossman 10922134a922SPierre Ossman /* 10932134a922SPierre Ossman * FIXME: This doesn't account for merging when mapping the 10942134a922SPierre Ossman * scatterlist. 1095df953925SRussell King * 1096df953925SRussell King * The assumption here being that alignment and lengths are 1097df953925SRussell King * the same after DMA mapping to device address space. 10982134a922SPierre Ossman */ 1099a0eaf0f9SRussell King length_mask = 0; 1100df953925SRussell King offset_mask = 0; 11012134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 1102df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) { 1103a0eaf0f9SRussell King length_mask = 3; 1104df953925SRussell King /* 1105df953925SRussell King * As we use up to 3 byte chunks to work 1106df953925SRussell King * around alignment problems, we need to 1107df953925SRussell King * check the offset as well. 1108df953925SRussell King */ 1109df953925SRussell King offset_mask = 3; 1110df953925SRussell King } 11112134a922SPierre Ossman } else { 11122134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) 1113a0eaf0f9SRussell King length_mask = 3; 1114df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) 1115df953925SRussell King offset_mask = 3; 11162134a922SPierre Ossman } 11172134a922SPierre Ossman 1118df953925SRussell King if (unlikely(length_mask | offset_mask)) { 11192134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) { 1120a0eaf0f9SRussell King if (sg->length & length_mask) { 11212e4456f0SMarek Vasut DBG("Reverting to PIO because of transfer size (%d)\n", 11222134a922SPierre Ossman sg->length); 1123c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 11242134a922SPierre Ossman break; 11252134a922SPierre Ossman } 1126a0eaf0f9SRussell King if (sg->offset & offset_mask) { 11272e4456f0SMarek Vasut DBG("Reverting to PIO because of bad alignment\n"); 1128c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 11292134a922SPierre Ossman break; 11302134a922SPierre Ossman } 11312134a922SPierre Ossman } 11322134a922SPierre Ossman } 11332134a922SPierre Ossman } 11342134a922SPierre Ossman 11358f1934ceSPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) { 1136c0999b72SRussell King int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); 11378f1934ceSPierre Ossman 113862a7f368SJiri Slaby if (sg_cnt <= 0) { 11398f1934ceSPierre Ossman /* 11408f1934ceSPierre Ossman * This only happens when someone fed 11418f1934ceSPierre Ossman * us an invalid request. 11428f1934ceSPierre Ossman */ 11438f1934ceSPierre Ossman WARN_ON(1); 1144ebd6d357SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA; 114560c64762SRussell King } else if (host->flags & SDHCI_USE_ADMA) { 114660c64762SRussell King sdhci_adma_table_pre(host, data, sg_cnt); 114738eee2e8SMasahiro Yamada sdhci_set_adma_addr(host, host->adma_addr); 11488f1934ceSPierre Ossman } else { 1149719a61b4SPierre Ossman WARN_ON(sg_cnt != 1); 1150917a0c52SChunyan Zhang sdhci_set_sdma_addr(host, sdhci_sdma_address(host)); 11518f1934ceSPierre Ossman } 11528f1934ceSPierre Ossman } 11538f1934ceSPierre Ossman 1154685e444bSChunyan Zhang sdhci_config_dma(host); 1155c9fddbc4SPierre Ossman 11568f1934ceSPierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) { 1157da60a91dSSebastian Andrzej Siewior int flags; 1158da60a91dSSebastian Andrzej Siewior 1159da60a91dSSebastian Andrzej Siewior flags = SG_MITER_ATOMIC; 1160da60a91dSSebastian Andrzej Siewior if (host->data->flags & MMC_DATA_READ) 1161da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_TO_SG; 1162da60a91dSSebastian Andrzej Siewior else 1163da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_FROM_SG; 1164da60a91dSSebastian Andrzej Siewior sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 11657659150cSPierre Ossman host->blocks = data->blocks; 11661c6a0718SPierre Ossman } 11671c6a0718SPierre Ossman 11686aa943abSAnton Vorontsov sdhci_set_transfer_irqs(host); 11696aa943abSAnton Vorontsov 117015db1836SFaiz Abbas sdhci_set_block_info(host, data); 1171e65953d4SChunyan Zhang } 11721c6a0718SPierre Ossman 117318e762e3SChunyan Zhang #if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA) 117418e762e3SChunyan Zhang 117518e762e3SChunyan Zhang static int sdhci_external_dma_init(struct sdhci_host *host) 117618e762e3SChunyan Zhang { 117718e762e3SChunyan Zhang int ret = 0; 117818e762e3SChunyan Zhang struct mmc_host *mmc = host->mmc; 117918e762e3SChunyan Zhang 118018e762e3SChunyan Zhang host->tx_chan = dma_request_chan(mmc->parent, "tx"); 118118e762e3SChunyan Zhang if (IS_ERR(host->tx_chan)) { 118218e762e3SChunyan Zhang ret = PTR_ERR(host->tx_chan); 118318e762e3SChunyan Zhang if (ret != -EPROBE_DEFER) 118418e762e3SChunyan Zhang pr_warn("Failed to request TX DMA channel.\n"); 118518e762e3SChunyan Zhang host->tx_chan = NULL; 118618e762e3SChunyan Zhang return ret; 118718e762e3SChunyan Zhang } 118818e762e3SChunyan Zhang 118918e762e3SChunyan Zhang host->rx_chan = dma_request_chan(mmc->parent, "rx"); 119018e762e3SChunyan Zhang if (IS_ERR(host->rx_chan)) { 119118e762e3SChunyan Zhang if (host->tx_chan) { 119218e762e3SChunyan Zhang dma_release_channel(host->tx_chan); 119318e762e3SChunyan Zhang host->tx_chan = NULL; 119418e762e3SChunyan Zhang } 119518e762e3SChunyan Zhang 119618e762e3SChunyan Zhang ret = PTR_ERR(host->rx_chan); 119718e762e3SChunyan Zhang if (ret != -EPROBE_DEFER) 119818e762e3SChunyan Zhang pr_warn("Failed to request RX DMA channel.\n"); 119918e762e3SChunyan Zhang host->rx_chan = NULL; 120018e762e3SChunyan Zhang } 120118e762e3SChunyan Zhang 120218e762e3SChunyan Zhang return ret; 120318e762e3SChunyan Zhang } 120418e762e3SChunyan Zhang 120518e762e3SChunyan Zhang static struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, 120618e762e3SChunyan Zhang struct mmc_data *data) 120718e762e3SChunyan Zhang { 120818e762e3SChunyan Zhang return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan; 120918e762e3SChunyan Zhang } 121018e762e3SChunyan Zhang 121118e762e3SChunyan Zhang static int sdhci_external_dma_setup(struct sdhci_host *host, 121218e762e3SChunyan Zhang struct mmc_command *cmd) 121318e762e3SChunyan Zhang { 121418e762e3SChunyan Zhang int ret, i; 12151215c025SChunyan Zhang enum dma_transfer_direction dir; 121618e762e3SChunyan Zhang struct dma_async_tx_descriptor *desc; 121718e762e3SChunyan Zhang struct mmc_data *data = cmd->data; 121818e762e3SChunyan Zhang struct dma_chan *chan; 121918e762e3SChunyan Zhang struct dma_slave_config cfg; 122018e762e3SChunyan Zhang dma_cookie_t cookie; 122118e762e3SChunyan Zhang int sg_cnt; 122218e762e3SChunyan Zhang 122318e762e3SChunyan Zhang if (!host->mapbase) 122418e762e3SChunyan Zhang return -EINVAL; 122518e762e3SChunyan Zhang 122618e762e3SChunyan Zhang cfg.src_addr = host->mapbase + SDHCI_BUFFER; 122718e762e3SChunyan Zhang cfg.dst_addr = host->mapbase + SDHCI_BUFFER; 122818e762e3SChunyan Zhang cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 122918e762e3SChunyan Zhang cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 123018e762e3SChunyan Zhang cfg.src_maxburst = data->blksz / 4; 123118e762e3SChunyan Zhang cfg.dst_maxburst = data->blksz / 4; 123218e762e3SChunyan Zhang 123318e762e3SChunyan Zhang /* Sanity check: all the SG entries must be aligned by block size. */ 123418e762e3SChunyan Zhang for (i = 0; i < data->sg_len; i++) { 123518e762e3SChunyan Zhang if ((data->sg + i)->length % data->blksz) 123618e762e3SChunyan Zhang return -EINVAL; 123718e762e3SChunyan Zhang } 123818e762e3SChunyan Zhang 123918e762e3SChunyan Zhang chan = sdhci_external_dma_channel(host, data); 124018e762e3SChunyan Zhang 124118e762e3SChunyan Zhang ret = dmaengine_slave_config(chan, &cfg); 124218e762e3SChunyan Zhang if (ret) 124318e762e3SChunyan Zhang return ret; 124418e762e3SChunyan Zhang 124518e762e3SChunyan Zhang sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); 124618e762e3SChunyan Zhang if (sg_cnt <= 0) 124718e762e3SChunyan Zhang return -EINVAL; 124818e762e3SChunyan Zhang 12491215c025SChunyan Zhang dir = data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; 12501215c025SChunyan Zhang desc = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len, dir, 125118e762e3SChunyan Zhang DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 125218e762e3SChunyan Zhang if (!desc) 125318e762e3SChunyan Zhang return -EINVAL; 125418e762e3SChunyan Zhang 125518e762e3SChunyan Zhang desc->callback = NULL; 125618e762e3SChunyan Zhang desc->callback_param = NULL; 125718e762e3SChunyan Zhang 125818e762e3SChunyan Zhang cookie = dmaengine_submit(desc); 125918e762e3SChunyan Zhang if (dma_submit_error(cookie)) 126018e762e3SChunyan Zhang ret = cookie; 126118e762e3SChunyan Zhang 126218e762e3SChunyan Zhang return ret; 126318e762e3SChunyan Zhang } 126418e762e3SChunyan Zhang 126518e762e3SChunyan Zhang static void sdhci_external_dma_release(struct sdhci_host *host) 126618e762e3SChunyan Zhang { 126718e762e3SChunyan Zhang if (host->tx_chan) { 126818e762e3SChunyan Zhang dma_release_channel(host->tx_chan); 126918e762e3SChunyan Zhang host->tx_chan = NULL; 127018e762e3SChunyan Zhang } 127118e762e3SChunyan Zhang 127218e762e3SChunyan Zhang if (host->rx_chan) { 127318e762e3SChunyan Zhang dma_release_channel(host->rx_chan); 127418e762e3SChunyan Zhang host->rx_chan = NULL; 127518e762e3SChunyan Zhang } 127618e762e3SChunyan Zhang 127718e762e3SChunyan Zhang sdhci_switch_external_dma(host, false); 127818e762e3SChunyan Zhang } 127918e762e3SChunyan Zhang 128018e762e3SChunyan Zhang static void __sdhci_external_dma_prepare_data(struct sdhci_host *host, 128118e762e3SChunyan Zhang struct mmc_command *cmd) 128218e762e3SChunyan Zhang { 128318e762e3SChunyan Zhang struct mmc_data *data = cmd->data; 128418e762e3SChunyan Zhang 128518e762e3SChunyan Zhang sdhci_initialize_data(host, data); 128618e762e3SChunyan Zhang 128718e762e3SChunyan Zhang host->flags |= SDHCI_REQ_USE_DMA; 128818e762e3SChunyan Zhang sdhci_set_transfer_irqs(host); 128918e762e3SChunyan Zhang 129018e762e3SChunyan Zhang sdhci_set_block_info(host, data); 129118e762e3SChunyan Zhang } 129218e762e3SChunyan Zhang 129318e762e3SChunyan Zhang static void sdhci_external_dma_prepare_data(struct sdhci_host *host, 129418e762e3SChunyan Zhang struct mmc_command *cmd) 129518e762e3SChunyan Zhang { 129618e762e3SChunyan Zhang if (!sdhci_external_dma_setup(host, cmd)) { 129718e762e3SChunyan Zhang __sdhci_external_dma_prepare_data(host, cmd); 129818e762e3SChunyan Zhang } else { 129918e762e3SChunyan Zhang sdhci_external_dma_release(host); 130018e762e3SChunyan Zhang pr_err("%s: Cannot use external DMA, switch to the DMA/PIO which standard SDHCI provides.\n", 130118e762e3SChunyan Zhang mmc_hostname(host->mmc)); 130218e762e3SChunyan Zhang sdhci_prepare_data(host, cmd); 130318e762e3SChunyan Zhang } 130418e762e3SChunyan Zhang } 130518e762e3SChunyan Zhang 130618e762e3SChunyan Zhang static void sdhci_external_dma_pre_transfer(struct sdhci_host *host, 130718e762e3SChunyan Zhang struct mmc_command *cmd) 130818e762e3SChunyan Zhang { 130918e762e3SChunyan Zhang struct dma_chan *chan; 131018e762e3SChunyan Zhang 131118e762e3SChunyan Zhang if (!cmd->data) 131218e762e3SChunyan Zhang return; 131318e762e3SChunyan Zhang 131418e762e3SChunyan Zhang chan = sdhci_external_dma_channel(host, cmd->data); 131518e762e3SChunyan Zhang if (chan) 131618e762e3SChunyan Zhang dma_async_issue_pending(chan); 131718e762e3SChunyan Zhang } 131818e762e3SChunyan Zhang 131918e762e3SChunyan Zhang #else 132018e762e3SChunyan Zhang 132118e762e3SChunyan Zhang static inline int sdhci_external_dma_init(struct sdhci_host *host) 132218e762e3SChunyan Zhang { 132318e762e3SChunyan Zhang return -EOPNOTSUPP; 132418e762e3SChunyan Zhang } 132518e762e3SChunyan Zhang 132618e762e3SChunyan Zhang static inline void sdhci_external_dma_release(struct sdhci_host *host) 132718e762e3SChunyan Zhang { 132818e762e3SChunyan Zhang } 132918e762e3SChunyan Zhang 133018e762e3SChunyan Zhang static inline void sdhci_external_dma_prepare_data(struct sdhci_host *host, 133118e762e3SChunyan Zhang struct mmc_command *cmd) 133218e762e3SChunyan Zhang { 133318e762e3SChunyan Zhang /* This should never happen */ 133418e762e3SChunyan Zhang WARN_ON_ONCE(1); 133518e762e3SChunyan Zhang } 133618e762e3SChunyan Zhang 133718e762e3SChunyan Zhang static inline void sdhci_external_dma_pre_transfer(struct sdhci_host *host, 133818e762e3SChunyan Zhang struct mmc_command *cmd) 133918e762e3SChunyan Zhang { 134018e762e3SChunyan Zhang } 134118e762e3SChunyan Zhang 134218e762e3SChunyan Zhang static inline struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, 134318e762e3SChunyan Zhang struct mmc_data *data) 134418e762e3SChunyan Zhang { 134518e762e3SChunyan Zhang return NULL; 134618e762e3SChunyan Zhang } 134718e762e3SChunyan Zhang 134818e762e3SChunyan Zhang #endif 134918e762e3SChunyan Zhang 135018e762e3SChunyan Zhang void sdhci_switch_external_dma(struct sdhci_host *host, bool en) 135118e762e3SChunyan Zhang { 135218e762e3SChunyan Zhang host->use_external_dma = en; 135318e762e3SChunyan Zhang } 135418e762e3SChunyan Zhang EXPORT_SYMBOL_GPL(sdhci_switch_external_dma); 135518e762e3SChunyan Zhang 13560293d501SAdrian Hunter static inline bool sdhci_auto_cmd12(struct sdhci_host *host, 13570293d501SAdrian Hunter struct mmc_request *mrq) 13580293d501SAdrian Hunter { 135920845befSAdrian Hunter return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) && 136020845befSAdrian Hunter !mrq->cap_cmd_during_tfr; 13610293d501SAdrian Hunter } 13620293d501SAdrian Hunter 1363ed633033SAdrian Hunter static inline bool sdhci_auto_cmd23(struct sdhci_host *host, 1364ed633033SAdrian Hunter struct mmc_request *mrq) 1365ed633033SAdrian Hunter { 1366ed633033SAdrian Hunter return mrq->sbc && (host->flags & SDHCI_AUTO_CMD23); 1367ed633033SAdrian Hunter } 1368ed633033SAdrian Hunter 1369ed633033SAdrian Hunter static inline bool sdhci_manual_cmd23(struct sdhci_host *host, 1370ed633033SAdrian Hunter struct mmc_request *mrq) 1371ed633033SAdrian Hunter { 1372ed633033SAdrian Hunter return mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23); 1373ed633033SAdrian Hunter } 1374ed633033SAdrian Hunter 1375427b6514SChunyan Zhang static inline void sdhci_auto_cmd_select(struct sdhci_host *host, 1376427b6514SChunyan Zhang struct mmc_command *cmd, 1377427b6514SChunyan Zhang u16 *mode) 1378427b6514SChunyan Zhang { 1379427b6514SChunyan Zhang bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) && 1380427b6514SChunyan Zhang (cmd->opcode != SD_IO_RW_EXTENDED); 1381ed633033SAdrian Hunter bool use_cmd23 = sdhci_auto_cmd23(host, cmd->mrq); 1382427b6514SChunyan Zhang u16 ctrl2; 1383427b6514SChunyan Zhang 1384427b6514SChunyan Zhang /* 1385427b6514SChunyan Zhang * In case of Version 4.10 or later, use of 'Auto CMD Auto 1386427b6514SChunyan Zhang * Select' is recommended rather than use of 'Auto CMD12 1387427b6514SChunyan Zhang * Enable' or 'Auto CMD23 Enable'. 1388427b6514SChunyan Zhang */ 1389427b6514SChunyan Zhang if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) { 1390427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_SEL; 1391427b6514SChunyan Zhang 1392427b6514SChunyan Zhang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1393427b6514SChunyan Zhang if (use_cmd23) 1394427b6514SChunyan Zhang ctrl2 |= SDHCI_CMD23_ENABLE; 1395427b6514SChunyan Zhang else 1396427b6514SChunyan Zhang ctrl2 &= ~SDHCI_CMD23_ENABLE; 1397427b6514SChunyan Zhang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 1398427b6514SChunyan Zhang 1399427b6514SChunyan Zhang return; 1400427b6514SChunyan Zhang } 1401427b6514SChunyan Zhang 1402427b6514SChunyan Zhang /* 1403427b6514SChunyan Zhang * If we are sending CMD23, CMD12 never gets sent 1404427b6514SChunyan Zhang * on successful completion (so no Auto-CMD12). 1405427b6514SChunyan Zhang */ 1406427b6514SChunyan Zhang if (use_cmd12) 1407427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_CMD12; 1408427b6514SChunyan Zhang else if (use_cmd23) 1409427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_CMD23; 1410427b6514SChunyan Zhang } 1411427b6514SChunyan Zhang 14121c6a0718SPierre Ossman static void sdhci_set_transfer_mode(struct sdhci_host *host, 1413e89d456fSAndrei Warkentin struct mmc_command *cmd) 14141c6a0718SPierre Ossman { 1415d3fc5d71SVincent Yang u16 mode = 0; 1416e89d456fSAndrei Warkentin struct mmc_data *data = cmd->data; 14171c6a0718SPierre Ossman 14182b558c13SDong Aisheng if (data == NULL) { 14199b8ffea6SVincent Wan if (host->quirks2 & 14209b8ffea6SVincent Wan SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) { 14210086fc21Sernest.zhang /* must not clear SDHCI_TRANSFER_MODE when tuning */ 14220086fc21Sernest.zhang if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) 14239b8ffea6SVincent Wan sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); 14249b8ffea6SVincent Wan } else { 14252b558c13SDong Aisheng /* clear Auto CMD settings for no data CMDs */ 14262b558c13SDong Aisheng mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); 14272b558c13SDong Aisheng sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | 14282b558c13SDong Aisheng SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); 14299b8ffea6SVincent Wan } 14301c6a0718SPierre Ossman return; 14312b558c13SDong Aisheng } 14321c6a0718SPierre Ossman 1433e538fbe8SPierre Ossman WARN_ON(!host->data); 1434e538fbe8SPierre Ossman 1435d3fc5d71SVincent Yang if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE)) 14361c6a0718SPierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN; 1437d3fc5d71SVincent Yang 1438e89d456fSAndrei Warkentin if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { 1439d3fc5d71SVincent Yang mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI; 1440427b6514SChunyan Zhang sdhci_auto_cmd_select(host, cmd, &mode); 1441ed633033SAdrian Hunter if (sdhci_auto_cmd23(host, cmd->mrq)) 1442a4c73abaSAdrian Hunter sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2); 1443c4512f79SJerry Huang } 14448edf6371SAndrei Warkentin 14451c6a0718SPierre Ossman if (data->flags & MMC_DATA_READ) 14461c6a0718SPierre Ossman mode |= SDHCI_TRNS_READ; 1447c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) 14481c6a0718SPierre Ossman mode |= SDHCI_TRNS_DMA; 14491c6a0718SPierre Ossman 14504e4141a5SAnton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); 14511c6a0718SPierre Ossman } 14521c6a0718SPierre Ossman 14530cc563ceSAdrian Hunter static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) 14540cc563ceSAdrian Hunter { 14550cc563ceSAdrian Hunter return (!(host->flags & SDHCI_DEVICE_DEAD) && 14560cc563ceSAdrian Hunter ((mrq->cmd && mrq->cmd->error) || 14570cc563ceSAdrian Hunter (mrq->sbc && mrq->sbc->error) || 14584bf78099SAdrian Hunter (mrq->data && mrq->data->stop && mrq->data->stop->error) || 14590cc563ceSAdrian Hunter (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))); 14600cc563ceSAdrian Hunter } 14610cc563ceSAdrian Hunter 146215db1836SFaiz Abbas static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq) 14634e9f8fe5SAdrian Hunter { 14644e9f8fe5SAdrian Hunter int i; 14654e9f8fe5SAdrian Hunter 14664e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 14674e9f8fe5SAdrian Hunter if (host->mrqs_done[i] == mrq) { 14684e9f8fe5SAdrian Hunter WARN_ON(1); 14694e9f8fe5SAdrian Hunter return; 14704e9f8fe5SAdrian Hunter } 14714e9f8fe5SAdrian Hunter } 14724e9f8fe5SAdrian Hunter 14734e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 14744e9f8fe5SAdrian Hunter if (!host->mrqs_done[i]) { 14754e9f8fe5SAdrian Hunter host->mrqs_done[i] = mrq; 14764e9f8fe5SAdrian Hunter break; 14774e9f8fe5SAdrian Hunter } 14784e9f8fe5SAdrian Hunter } 14794e9f8fe5SAdrian Hunter 14804e9f8fe5SAdrian Hunter WARN_ON(i >= SDHCI_MAX_MRQS); 148115db1836SFaiz Abbas } 148215db1836SFaiz Abbas 148315db1836SFaiz Abbas static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) 148415db1836SFaiz Abbas { 148515db1836SFaiz Abbas if (host->cmd && host->cmd->mrq == mrq) 148615db1836SFaiz Abbas host->cmd = NULL; 148715db1836SFaiz Abbas 148815db1836SFaiz Abbas if (host->data_cmd && host->data_cmd->mrq == mrq) 148915db1836SFaiz Abbas host->data_cmd = NULL; 149015db1836SFaiz Abbas 1491845c939eSAdrian Hunter if (host->deferred_cmd && host->deferred_cmd->mrq == mrq) 1492845c939eSAdrian Hunter host->deferred_cmd = NULL; 1493845c939eSAdrian Hunter 149415db1836SFaiz Abbas if (host->data && host->data->mrq == mrq) 149515db1836SFaiz Abbas host->data = NULL; 149615db1836SFaiz Abbas 149715db1836SFaiz Abbas if (sdhci_needs_reset(host, mrq)) 149815db1836SFaiz Abbas host->pending_reset = true; 149915db1836SFaiz Abbas 150015db1836SFaiz Abbas sdhci_set_mrq_done(host, mrq); 15014e9f8fe5SAdrian Hunter 1502e9a07299SAdrian Hunter sdhci_del_timer(host, mrq); 1503e9a07299SAdrian Hunter 1504e9a07299SAdrian Hunter if (!sdhci_has_requests(host)) 1505e9a07299SAdrian Hunter sdhci_led_deactivate(host); 15064e9f8fe5SAdrian Hunter } 15074e9f8fe5SAdrian Hunter 1508a6d3bdd5SAdrian Hunter static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) 1509a6d3bdd5SAdrian Hunter { 15104e9f8fe5SAdrian Hunter __sdhci_finish_mrq(host, mrq); 15112e72ab9bSAdrian Hunter 1512c07a48c2SAdrian Hunter queue_work(host->complete_wq, &host->complete_work); 1513a6d3bdd5SAdrian Hunter } 1514a6d3bdd5SAdrian Hunter 1515845c939eSAdrian Hunter static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) 15161c6a0718SPierre Ossman { 151733a57adbSAdrian Hunter struct mmc_command *data_cmd = host->data_cmd; 151833a57adbSAdrian Hunter struct mmc_data *data = host->data; 15191c6a0718SPierre Ossman 15201c6a0718SPierre Ossman host->data = NULL; 15217c89a3d9SAdrian Hunter host->data_cmd = NULL; 15221c6a0718SPierre Ossman 15234bf78099SAdrian Hunter /* 15244bf78099SAdrian Hunter * The controller needs a reset of internal state machines upon error 15254bf78099SAdrian Hunter * conditions. 15264bf78099SAdrian Hunter */ 15274bf78099SAdrian Hunter if (data->error) { 15284bf78099SAdrian Hunter if (!host->cmd || host->cmd == data_cmd) 15294bf78099SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD); 15304bf78099SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 15314bf78099SAdrian Hunter } 15324bf78099SAdrian Hunter 1533add8913dSRussell King if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) == 1534add8913dSRussell King (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) 15352134a922SPierre Ossman sdhci_adma_table_post(host, data); 1536f55c98f7SRussell King 15371c6a0718SPierre Ossman /* 1538c9b74c5bSPierre Ossman * The specification states that the block count register must 1539c9b74c5bSPierre Ossman * be updated, but it does not specify at what point in the 1540c9b74c5bSPierre Ossman * data flow. That makes the register entirely useless to read 1541c9b74c5bSPierre Ossman * back so we have to assume that nothing made it to the card 1542c9b74c5bSPierre Ossman * in the event of an error. 15431c6a0718SPierre Ossman */ 1544c9b74c5bSPierre Ossman if (data->error) 1545c9b74c5bSPierre Ossman data->bytes_xfered = 0; 15461c6a0718SPierre Ossman else 1547c9b74c5bSPierre Ossman data->bytes_xfered = data->blksz * data->blocks; 15481c6a0718SPierre Ossman 1549e89d456fSAndrei Warkentin /* 1550e89d456fSAndrei Warkentin * Need to send CMD12 if - 1551fdbbe6cfSYangbo Lu * a) open-ended multiblock transfer not using auto CMD12 (no CMD23) 1552e89d456fSAndrei Warkentin * b) error in multiblock transfer 1553e89d456fSAndrei Warkentin */ 1554e89d456fSAndrei Warkentin if (data->stop && 1555fdbbe6cfSYangbo Lu ((!data->mrq->sbc && !sdhci_auto_cmd12(host, data->mrq)) || 1556fdbbe6cfSYangbo Lu data->error)) { 155720845befSAdrian Hunter /* 155820845befSAdrian Hunter * 'cap_cmd_during_tfr' request must not use the command line 155920845befSAdrian Hunter * after mmc_command_done() has been called. It is upper layer's 156020845befSAdrian Hunter * responsibility to send the stop command if required. 156120845befSAdrian Hunter */ 156220845befSAdrian Hunter if (data->mrq->cap_cmd_during_tfr) { 156319d2f695SAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 156420845befSAdrian Hunter } else { 15658842fd17SAdrian Hunter /* Avoid triggering warning in sdhci_send_command() */ 15668842fd17SAdrian Hunter host->cmd = NULL; 1567845c939eSAdrian Hunter if (!sdhci_send_command(host, data->stop)) { 1568845c939eSAdrian Hunter if (sw_data_timeout) { 1569845c939eSAdrian Hunter /* 1570845c939eSAdrian Hunter * This is anyway a sw data timeout, so 1571845c939eSAdrian Hunter * give up now. 1572845c939eSAdrian Hunter */ 1573845c939eSAdrian Hunter data->stop->error = -EIO; 1574845c939eSAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 1575845c939eSAdrian Hunter } else { 1576845c939eSAdrian Hunter WARN_ON(host->deferred_cmd); 1577845c939eSAdrian Hunter host->deferred_cmd = data->stop; 1578845c939eSAdrian Hunter } 1579845c939eSAdrian Hunter } 158020845befSAdrian Hunter } 1581a6d3bdd5SAdrian Hunter } else { 158219d2f695SAdrian Hunter __sdhci_finish_mrq(host, data->mrq); 1583a6d3bdd5SAdrian Hunter } 15841c6a0718SPierre Ossman } 15851c6a0718SPierre Ossman 1586845c939eSAdrian Hunter static void sdhci_finish_data(struct sdhci_host *host) 1587845c939eSAdrian Hunter { 1588845c939eSAdrian Hunter __sdhci_finish_data(host, false); 1589845c939eSAdrian Hunter } 1590845c939eSAdrian Hunter 1591845c939eSAdrian Hunter static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 15921c6a0718SPierre Ossman { 15931c6a0718SPierre Ossman int flags; 15941c6a0718SPierre Ossman u32 mask; 15951c6a0718SPierre Ossman unsigned long timeout; 15961c6a0718SPierre Ossman 15971c6a0718SPierre Ossman WARN_ON(host->cmd); 15981c6a0718SPierre Ossman 159996776200SRussell King /* Initially, a command has no error */ 160096776200SRussell King cmd->error = 0; 160196776200SRussell King 1602fc605f1dSAdrian Hunter if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && 1603fc605f1dSAdrian Hunter cmd->opcode == MMC_STOP_TRANSMISSION) 1604fc605f1dSAdrian Hunter cmd->flags |= MMC_RSP_BUSY; 1605fc605f1dSAdrian Hunter 16061c6a0718SPierre Ossman mask = SDHCI_CMD_INHIBIT; 160756a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) 16081c6a0718SPierre Ossman mask |= SDHCI_DATA_INHIBIT; 16091c6a0718SPierre Ossman 16101c6a0718SPierre Ossman /* We shouldn't wait for data inihibit for stop commands, even 16111c6a0718SPierre Ossman though they might use busy signaling */ 1612a4c73abaSAdrian Hunter if (cmd->mrq->data && (cmd == cmd->mrq->data->stop)) 16131c6a0718SPierre Ossman mask &= ~SDHCI_DATA_INHIBIT; 16141c6a0718SPierre Ossman 1615845c939eSAdrian Hunter if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) 1616845c939eSAdrian Hunter return false; 16171c6a0718SPierre Ossman 16181c6a0718SPierre Ossman host->cmd = cmd; 161915db1836SFaiz Abbas host->data_timeout = 0; 162056a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) { 16217c89a3d9SAdrian Hunter WARN_ON(host->data_cmd); 16227c89a3d9SAdrian Hunter host->data_cmd = cmd; 162315db1836SFaiz Abbas sdhci_set_timeout(host, cmd); 16247c89a3d9SAdrian Hunter } 16251c6a0718SPierre Ossman 162618e762e3SChunyan Zhang if (cmd->data) { 162718e762e3SChunyan Zhang if (host->use_external_dma) 162818e762e3SChunyan Zhang sdhci_external_dma_prepare_data(host, cmd); 162918e762e3SChunyan Zhang else 1630a3c7778fSAndrei Warkentin sdhci_prepare_data(host, cmd); 163118e762e3SChunyan Zhang } 16321c6a0718SPierre Ossman 16334e4141a5SAnton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); 16341c6a0718SPierre Ossman 1635e89d456fSAndrei Warkentin sdhci_set_transfer_mode(host, cmd); 16361c6a0718SPierre Ossman 16371c6a0718SPierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { 1638845c939eSAdrian Hunter WARN_ONCE(1, "Unsupported response type!\n"); 1639845c939eSAdrian Hunter /* 1640845c939eSAdrian Hunter * This does not happen in practice because 136-bit response 1641845c939eSAdrian Hunter * commands never have busy waiting, so rather than complicate 1642845c939eSAdrian Hunter * the error path, just remove busy waiting and continue. 1643845c939eSAdrian Hunter */ 1644845c939eSAdrian Hunter cmd->flags &= ~MMC_RSP_BUSY; 16451c6a0718SPierre Ossman } 16461c6a0718SPierre Ossman 16471c6a0718SPierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT)) 16481c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_NONE; 16491c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_136) 16501c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_LONG; 16511c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_BUSY) 16521c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY; 16531c6a0718SPierre Ossman else 16541c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT; 16551c6a0718SPierre Ossman 16561c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_CRC) 16571c6a0718SPierre Ossman flags |= SDHCI_CMD_CRC; 16581c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_OPCODE) 16591c6a0718SPierre Ossman flags |= SDHCI_CMD_INDEX; 1660b513ea25SArindam Nath 1661b513ea25SArindam Nath /* CMD19 is special in that the Data Present Select should be set */ 1662069c9f14SGirish K S if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK || 1663069c9f14SGirish K S cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) 16641c6a0718SPierre Ossman flags |= SDHCI_CMD_DATA; 16651c6a0718SPierre Ossman 1666fc1fa1b7SKishon Vijay Abraham I timeout = jiffies; 1667fc1fa1b7SKishon Vijay Abraham I if (host->data_timeout) 1668fc1fa1b7SKishon Vijay Abraham I timeout += nsecs_to_jiffies(host->data_timeout); 1669fc1fa1b7SKishon Vijay Abraham I else if (!cmd->data && cmd->busy_timeout > 9000) 1670fc1fa1b7SKishon Vijay Abraham I timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; 1671fc1fa1b7SKishon Vijay Abraham I else 1672fc1fa1b7SKishon Vijay Abraham I timeout += 10 * HZ; 1673fc1fa1b7SKishon Vijay Abraham I sdhci_mod_timer(host, cmd->mrq, timeout); 1674fc1fa1b7SKishon Vijay Abraham I 167518e762e3SChunyan Zhang if (host->use_external_dma) 167618e762e3SChunyan Zhang sdhci_external_dma_pre_transfer(host, cmd); 167718e762e3SChunyan Zhang 16784e4141a5SAnton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 1679845c939eSAdrian Hunter 1680845c939eSAdrian Hunter return true; 16811c6a0718SPierre Ossman } 16821c6a0718SPierre Ossman 1683e872f1e2SAdrian Hunter static bool sdhci_present_error(struct sdhci_host *host, 1684e872f1e2SAdrian Hunter struct mmc_command *cmd, bool present) 1685e872f1e2SAdrian Hunter { 1686e872f1e2SAdrian Hunter if (!present || host->flags & SDHCI_DEVICE_DEAD) { 1687e872f1e2SAdrian Hunter cmd->error = -ENOMEDIUM; 1688e872f1e2SAdrian Hunter return true; 1689e872f1e2SAdrian Hunter } 1690e872f1e2SAdrian Hunter 1691e872f1e2SAdrian Hunter return false; 1692e872f1e2SAdrian Hunter } 1693e872f1e2SAdrian Hunter 1694845c939eSAdrian Hunter static bool sdhci_send_command_retry(struct sdhci_host *host, 1695845c939eSAdrian Hunter struct mmc_command *cmd, 1696845c939eSAdrian Hunter unsigned long flags) 1697845c939eSAdrian Hunter __releases(host->lock) 1698845c939eSAdrian Hunter __acquires(host->lock) 1699845c939eSAdrian Hunter { 1700845c939eSAdrian Hunter struct mmc_command *deferred_cmd = host->deferred_cmd; 1701845c939eSAdrian Hunter int timeout = 10; /* Approx. 10 ms */ 1702845c939eSAdrian Hunter bool present; 1703845c939eSAdrian Hunter 1704845c939eSAdrian Hunter while (!sdhci_send_command(host, cmd)) { 1705845c939eSAdrian Hunter if (!timeout--) { 1706845c939eSAdrian Hunter pr_err("%s: Controller never released inhibit bit(s).\n", 1707845c939eSAdrian Hunter mmc_hostname(host->mmc)); 1708845c939eSAdrian Hunter sdhci_dumpregs(host); 1709845c939eSAdrian Hunter cmd->error = -EIO; 1710845c939eSAdrian Hunter return false; 1711845c939eSAdrian Hunter } 1712845c939eSAdrian Hunter 1713845c939eSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 1714845c939eSAdrian Hunter 1715845c939eSAdrian Hunter usleep_range(1000, 1250); 1716845c939eSAdrian Hunter 1717845c939eSAdrian Hunter present = host->mmc->ops->get_cd(host->mmc); 1718845c939eSAdrian Hunter 1719845c939eSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 1720845c939eSAdrian Hunter 1721845c939eSAdrian Hunter /* A deferred command might disappear, handle that */ 1722845c939eSAdrian Hunter if (cmd == deferred_cmd && cmd != host->deferred_cmd) 1723845c939eSAdrian Hunter return true; 1724845c939eSAdrian Hunter 1725845c939eSAdrian Hunter if (sdhci_present_error(host, cmd, present)) 1726845c939eSAdrian Hunter return false; 1727845c939eSAdrian Hunter } 1728845c939eSAdrian Hunter 1729845c939eSAdrian Hunter if (cmd == host->deferred_cmd) 1730845c939eSAdrian Hunter host->deferred_cmd = NULL; 1731845c939eSAdrian Hunter 1732845c939eSAdrian Hunter return true; 1733845c939eSAdrian Hunter } 1734845c939eSAdrian Hunter 17354a5fc119SAdrian Hunter static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) 17364a5fc119SAdrian Hunter { 17374a5fc119SAdrian Hunter int i, reg; 17384a5fc119SAdrian Hunter 17394a5fc119SAdrian Hunter for (i = 0; i < 4; i++) { 17404a5fc119SAdrian Hunter reg = SDHCI_RESPONSE + (3 - i) * 4; 17414a5fc119SAdrian Hunter cmd->resp[i] = sdhci_readl(host, reg); 17424a5fc119SAdrian Hunter } 17434a5fc119SAdrian Hunter 17441284c248SKishon Vijay Abraham I if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC) 17451284c248SKishon Vijay Abraham I return; 17461284c248SKishon Vijay Abraham I 17474a5fc119SAdrian Hunter /* CRC is stripped so we need to do some shifting */ 17484a5fc119SAdrian Hunter for (i = 0; i < 4; i++) { 17494a5fc119SAdrian Hunter cmd->resp[i] <<= 8; 17504a5fc119SAdrian Hunter if (i != 3) 17514a5fc119SAdrian Hunter cmd->resp[i] |= cmd->resp[i + 1] >> 24; 17524a5fc119SAdrian Hunter } 17534a5fc119SAdrian Hunter } 17544a5fc119SAdrian Hunter 17551c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *host) 17561c6a0718SPierre Ossman { 1757e0a5640aSAdrian Hunter struct mmc_command *cmd = host->cmd; 17581c6a0718SPierre Ossman 1759e0a5640aSAdrian Hunter host->cmd = NULL; 1760e0a5640aSAdrian Hunter 1761e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_PRESENT) { 1762e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_136) { 17634a5fc119SAdrian Hunter sdhci_read_rsp_136(host, cmd); 17641c6a0718SPierre Ossman } else { 1765e0a5640aSAdrian Hunter cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); 17661c6a0718SPierre Ossman } 17671c6a0718SPierre Ossman } 17681c6a0718SPierre Ossman 176920845befSAdrian Hunter if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd) 177020845befSAdrian Hunter mmc_command_done(host->mmc, cmd->mrq); 177120845befSAdrian Hunter 17726bde8681SAdrian Hunter /* 17736bde8681SAdrian Hunter * The host can send and interrupt when the busy state has 17746bde8681SAdrian Hunter * ended, allowing us to wait without wasting CPU cycles. 17756bde8681SAdrian Hunter * The busy signal uses DAT0 so this is similar to waiting 17766bde8681SAdrian Hunter * for data to complete. 17776bde8681SAdrian Hunter * 17786bde8681SAdrian Hunter * Note: The 1.0 specification is a bit ambiguous about this 17796bde8681SAdrian Hunter * feature so there might be some problems with older 17806bde8681SAdrian Hunter * controllers. 17816bde8681SAdrian Hunter */ 1782e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_BUSY) { 1783e0a5640aSAdrian Hunter if (cmd->data) { 17846bde8681SAdrian Hunter DBG("Cannot wait for busy signal when also doing a data transfer"); 17856bde8681SAdrian Hunter } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && 1786ea968023SAdrian Hunter cmd == host->data_cmd) { 1787ea968023SAdrian Hunter /* Command complete before busy is ended */ 17886bde8681SAdrian Hunter return; 17896bde8681SAdrian Hunter } 17906bde8681SAdrian Hunter } 17916bde8681SAdrian Hunter 1792e89d456fSAndrei Warkentin /* Finished CMD23, now send actual command. */ 1793a4c73abaSAdrian Hunter if (cmd == cmd->mrq->sbc) { 1794845c939eSAdrian Hunter if (!sdhci_send_command(host, cmd->mrq->cmd)) { 1795845c939eSAdrian Hunter WARN_ON(host->deferred_cmd); 1796845c939eSAdrian Hunter host->deferred_cmd = cmd->mrq->cmd; 1797845c939eSAdrian Hunter } 1798e89d456fSAndrei Warkentin } else { 1799e89d456fSAndrei Warkentin 1800e89d456fSAndrei Warkentin /* Processed actual command. */ 1801e538fbe8SPierre Ossman if (host->data && host->data_early) 1802e538fbe8SPierre Ossman sdhci_finish_data(host); 1803e538fbe8SPierre Ossman 1804e0a5640aSAdrian Hunter if (!cmd->data) 180519d2f695SAdrian Hunter __sdhci_finish_mrq(host, cmd->mrq); 18061c6a0718SPierre Ossman } 1807e89d456fSAndrei Warkentin } 18081c6a0718SPierre Ossman 180952983382SKevin Liu static u16 sdhci_get_preset_value(struct sdhci_host *host) 181052983382SKevin Liu { 1811d975f121SRussell King u16 preset = 0; 181252983382SKevin Liu 1813d975f121SRussell King switch (host->timing) { 1814d975f121SRussell King case MMC_TIMING_UHS_SDR12: 181552983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); 181652983382SKevin Liu break; 1817d975f121SRussell King case MMC_TIMING_UHS_SDR25: 181852983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25); 181952983382SKevin Liu break; 1820d975f121SRussell King case MMC_TIMING_UHS_SDR50: 182152983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50); 182252983382SKevin Liu break; 1823d975f121SRussell King case MMC_TIMING_UHS_SDR104: 1824d975f121SRussell King case MMC_TIMING_MMC_HS200: 182552983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104); 182652983382SKevin Liu break; 1827d975f121SRussell King case MMC_TIMING_UHS_DDR50: 18280dafa60eSJisheng Zhang case MMC_TIMING_MMC_DDR52: 182952983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50); 183052983382SKevin Liu break; 1831e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400: 1832e9fb05d5SAdrian Hunter preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400); 1833e9fb05d5SAdrian Hunter break; 183452983382SKevin Liu default: 183552983382SKevin Liu pr_warn("%s: Invalid UHS-I mode selected\n", 183652983382SKevin Liu mmc_hostname(host->mmc)); 183752983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); 183852983382SKevin Liu break; 183952983382SKevin Liu } 184052983382SKevin Liu return preset; 184152983382SKevin Liu } 184252983382SKevin Liu 1843fb9ee047SLudovic Desroches u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, 1844fb9ee047SLudovic Desroches unsigned int *actual_clock) 18451c6a0718SPierre Ossman { 1846c3ed3877SArindam Nath int div = 0; /* Initialized for compiler warning */ 1847df16219fSGiuseppe CAVALLARO int real_div = div, clk_mul = 1; 1848c3ed3877SArindam Nath u16 clk = 0; 18495497159cSludovic.desroches@atmel.com bool switch_base_clk = false; 18501c6a0718SPierre Ossman 185185105c53SZhangfei Gao if (host->version >= SDHCI_SPEC_300) { 1852da91a8f9SRussell King if (host->preset_enabled) { 185352983382SKevin Liu u16 pre_val; 185452983382SKevin Liu 185552983382SKevin Liu clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 185652983382SKevin Liu pre_val = sdhci_get_preset_value(host); 1857fa091010SMasahiro Yamada div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val); 185852983382SKevin Liu if (host->clk_mul && 1859fa091010SMasahiro Yamada (pre_val & SDHCI_PRESET_CLKGEN_SEL)) { 186052983382SKevin Liu clk = SDHCI_PROG_CLOCK_MODE; 186152983382SKevin Liu real_div = div + 1; 186252983382SKevin Liu clk_mul = host->clk_mul; 186352983382SKevin Liu } else { 186452983382SKevin Liu real_div = max_t(int, 1, div << 1); 186552983382SKevin Liu } 186652983382SKevin Liu goto clock_set; 186752983382SKevin Liu } 186852983382SKevin Liu 1869c3ed3877SArindam Nath /* 1870c3ed3877SArindam Nath * Check if the Host Controller supports Programmable Clock 1871c3ed3877SArindam Nath * Mode. 1872c3ed3877SArindam Nath */ 1873c3ed3877SArindam Nath if (host->clk_mul) { 1874c3ed3877SArindam Nath for (div = 1; div <= 1024; div++) { 187552983382SKevin Liu if ((host->max_clk * host->clk_mul / div) 187652983382SKevin Liu <= clock) 1877c3ed3877SArindam Nath break; 1878c3ed3877SArindam Nath } 18795497159cSludovic.desroches@atmel.com if ((host->max_clk * host->clk_mul / div) <= clock) { 1880c3ed3877SArindam Nath /* 1881c3ed3877SArindam Nath * Set Programmable Clock Mode in the Clock 1882c3ed3877SArindam Nath * Control register. 1883c3ed3877SArindam Nath */ 1884c3ed3877SArindam Nath clk = SDHCI_PROG_CLOCK_MODE; 1885df16219fSGiuseppe CAVALLARO real_div = div; 1886df16219fSGiuseppe CAVALLARO clk_mul = host->clk_mul; 1887c3ed3877SArindam Nath div--; 1888c3ed3877SArindam Nath } else { 18895497159cSludovic.desroches@atmel.com /* 18905497159cSludovic.desroches@atmel.com * Divisor can be too small to reach clock 18915497159cSludovic.desroches@atmel.com * speed requirement. Then use the base clock. 18925497159cSludovic.desroches@atmel.com */ 18935497159cSludovic.desroches@atmel.com switch_base_clk = true; 18945497159cSludovic.desroches@atmel.com } 18955497159cSludovic.desroches@atmel.com } 18965497159cSludovic.desroches@atmel.com 18975497159cSludovic.desroches@atmel.com if (!host->clk_mul || switch_base_clk) { 189885105c53SZhangfei Gao /* Version 3.00 divisors must be a multiple of 2. */ 189985105c53SZhangfei Gao if (host->max_clk <= clock) 190085105c53SZhangfei Gao div = 1; 190185105c53SZhangfei Gao else { 1902c3ed3877SArindam Nath for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; 1903c3ed3877SArindam Nath div += 2) { 190485105c53SZhangfei Gao if ((host->max_clk / div) <= clock) 190585105c53SZhangfei Gao break; 190685105c53SZhangfei Gao } 190785105c53SZhangfei Gao } 1908df16219fSGiuseppe CAVALLARO real_div = div; 1909c3ed3877SArindam Nath div >>= 1; 1910d1955c3aSSuneel Garapati if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN) 1911d1955c3aSSuneel Garapati && !div && host->max_clk <= 25000000) 1912d1955c3aSSuneel Garapati div = 1; 1913c3ed3877SArindam Nath } 191485105c53SZhangfei Gao } else { 191585105c53SZhangfei Gao /* Version 2.00 divisors must be a power of 2. */ 19160397526dSZhangfei Gao for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { 19171c6a0718SPierre Ossman if ((host->max_clk / div) <= clock) 19181c6a0718SPierre Ossman break; 19191c6a0718SPierre Ossman } 1920df16219fSGiuseppe CAVALLARO real_div = div; 19211c6a0718SPierre Ossman div >>= 1; 1922c3ed3877SArindam Nath } 19231c6a0718SPierre Ossman 192452983382SKevin Liu clock_set: 192503d6f5ffSAisheng Dong if (real_div) 1926fb9ee047SLudovic Desroches *actual_clock = (host->max_clk * clk_mul) / real_div; 1927c3ed3877SArindam Nath clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 192885105c53SZhangfei Gao clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 192985105c53SZhangfei Gao << SDHCI_DIVIDER_HI_SHIFT; 1930fb9ee047SLudovic Desroches 1931fb9ee047SLudovic Desroches return clk; 1932fb9ee047SLudovic Desroches } 1933fb9ee047SLudovic Desroches EXPORT_SYMBOL_GPL(sdhci_calc_clk); 1934fb9ee047SLudovic Desroches 1935fec79673SRitesh Harjani void sdhci_enable_clk(struct sdhci_host *host, u16 clk) 1936fb9ee047SLudovic Desroches { 19375a436cc0SAdrian Hunter ktime_t timeout; 1938fb9ee047SLudovic Desroches 19391c6a0718SPierre Ossman clk |= SDHCI_CLOCK_INT_EN; 19404e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 19411c6a0718SPierre Ossman 19424a9e0d1aSBen Chuang /* Wait max 150 ms */ 19434a9e0d1aSBen Chuang timeout = ktime_add_ms(ktime_get(), 150); 1944b704441eSAlek Du while (1) { 1945b704441eSAlek Du bool timedout = ktime_after(ktime_get(), timeout); 1946b704441eSAlek Du 1947b704441eSAlek Du clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1948b704441eSAlek Du if (clk & SDHCI_CLOCK_INT_STABLE) 1949b704441eSAlek Du break; 1950b704441eSAlek Du if (timedout) { 19512e4456f0SMarek Vasut pr_err("%s: Internal clock never stabilised.\n", 19522e4456f0SMarek Vasut mmc_hostname(host->mmc)); 19531c6a0718SPierre Ossman sdhci_dumpregs(host); 19541c6a0718SPierre Ossman return; 19551c6a0718SPierre Ossman } 19565a436cc0SAdrian Hunter udelay(10); 19571c6a0718SPierre Ossman } 19581c6a0718SPierre Ossman 19591beabbdbSBen Chuang if (host->version >= SDHCI_SPEC_410 && host->v4_mode) { 19601beabbdbSBen Chuang clk |= SDHCI_CLOCK_PLL_EN; 19611beabbdbSBen Chuang clk &= ~SDHCI_CLOCK_INT_STABLE; 19621beabbdbSBen Chuang sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 19631beabbdbSBen Chuang 19641beabbdbSBen Chuang /* Wait max 150 ms */ 19651beabbdbSBen Chuang timeout = ktime_add_ms(ktime_get(), 150); 19661beabbdbSBen Chuang while (1) { 19671beabbdbSBen Chuang bool timedout = ktime_after(ktime_get(), timeout); 19681beabbdbSBen Chuang 19691beabbdbSBen Chuang clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 19701beabbdbSBen Chuang if (clk & SDHCI_CLOCK_INT_STABLE) 19711beabbdbSBen Chuang break; 19721beabbdbSBen Chuang if (timedout) { 19731beabbdbSBen Chuang pr_err("%s: PLL clock never stabilised.\n", 19741beabbdbSBen Chuang mmc_hostname(host->mmc)); 19751beabbdbSBen Chuang sdhci_dumpregs(host); 19761beabbdbSBen Chuang return; 19771beabbdbSBen Chuang } 19781beabbdbSBen Chuang udelay(10); 19791beabbdbSBen Chuang } 19801beabbdbSBen Chuang } 19811beabbdbSBen Chuang 19821c6a0718SPierre Ossman clk |= SDHCI_CLOCK_CARD_EN; 19834e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 19841c6a0718SPierre Ossman } 1985fec79673SRitesh Harjani EXPORT_SYMBOL_GPL(sdhci_enable_clk); 1986fec79673SRitesh Harjani 1987fec79673SRitesh Harjani void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 1988fec79673SRitesh Harjani { 1989fec79673SRitesh Harjani u16 clk; 1990fec79673SRitesh Harjani 1991fec79673SRitesh Harjani host->mmc->actual_clock = 0; 1992fec79673SRitesh Harjani 1993fec79673SRitesh Harjani sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 1994fec79673SRitesh Harjani 1995fec79673SRitesh Harjani if (clock == 0) 1996fec79673SRitesh Harjani return; 1997fec79673SRitesh Harjani 1998fec79673SRitesh Harjani clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 1999fec79673SRitesh Harjani sdhci_enable_clk(host, clk); 2000fec79673SRitesh Harjani } 20011771059cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_clock); 20021c6a0718SPierre Ossman 20031dceb041SAdrian Hunter static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, 200424fbb3caSRussell King unsigned short vdd) 20051c6a0718SPierre Ossman { 20063a48edc4STim Kryger struct mmc_host *mmc = host->mmc; 20071dceb041SAdrian Hunter 20081dceb041SAdrian Hunter mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); 20091dceb041SAdrian Hunter 20101dceb041SAdrian Hunter if (mode != MMC_POWER_OFF) 20111dceb041SAdrian Hunter sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL); 20121dceb041SAdrian Hunter else 20131dceb041SAdrian Hunter sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 20141dceb041SAdrian Hunter } 20151dceb041SAdrian Hunter 2016606d3131SAdrian Hunter void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, 20171dceb041SAdrian Hunter unsigned short vdd) 20181dceb041SAdrian Hunter { 20198364248aSGiuseppe Cavallaro u8 pwr = 0; 20201c6a0718SPierre Ossman 202124fbb3caSRussell King if (mode != MMC_POWER_OFF) { 202224fbb3caSRussell King switch (1 << vdd) { 2023ae628903SPierre Ossman case MMC_VDD_165_195: 20242a609abeSAndy Shevchenko /* 20252a609abeSAndy Shevchenko * Without a regulator, SDHCI does not support 2.0v 20262a609abeSAndy Shevchenko * so we only get here if the driver deliberately 20272a609abeSAndy Shevchenko * added the 2.0v range to ocr_avail. Map it to 1.8v 20282a609abeSAndy Shevchenko * for the purpose of turning on the power. 20292a609abeSAndy Shevchenko */ 20302a609abeSAndy Shevchenko case MMC_VDD_20_21: 2031ae628903SPierre Ossman pwr = SDHCI_POWER_180; 2032ae628903SPierre Ossman break; 2033ae628903SPierre Ossman case MMC_VDD_29_30: 2034ae628903SPierre Ossman case MMC_VDD_30_31: 2035ae628903SPierre Ossman pwr = SDHCI_POWER_300; 2036ae628903SPierre Ossman break; 2037ae628903SPierre Ossman case MMC_VDD_32_33: 2038ae628903SPierre Ossman case MMC_VDD_33_34: 2039ae628903SPierre Ossman pwr = SDHCI_POWER_330; 2040ae628903SPierre Ossman break; 2041ae628903SPierre Ossman default: 20429d5de93fSAdrian Hunter WARN(1, "%s: Invalid vdd %#x\n", 20439d5de93fSAdrian Hunter mmc_hostname(host->mmc), vdd); 20449d5de93fSAdrian Hunter break; 2045ae628903SPierre Ossman } 2046ae628903SPierre Ossman } 2047ae628903SPierre Ossman 2048ae628903SPierre Ossman if (host->pwr == pwr) 2049e921a8b6SRussell King return; 20501c6a0718SPierre Ossman 2051ae628903SPierre Ossman host->pwr = pwr; 2052ae628903SPierre Ossman 2053ae628903SPierre Ossman if (pwr == 0) { 20544e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 2055f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 2056f0710a55SAdrian Hunter sdhci_runtime_pm_bus_off(host); 2057e921a8b6SRussell King } else { 20581c6a0718SPierre Ossman /* 20591c6a0718SPierre Ossman * Spec says that we should clear the power reg before setting 20601c6a0718SPierre Ossman * a new value. Some controllers don't seem to like this though. 20611c6a0718SPierre Ossman */ 2062b8c86fc5SPierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) 20634e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 20641c6a0718SPierre Ossman 2065e08c1694SAndres Salomon /* 2066e921a8b6SRussell King * At least the Marvell CaFe chip gets confused if we set the 2067e921a8b6SRussell King * voltage and set turn on power at the same time, so set the 2068e921a8b6SRussell King * voltage first. 2069e08c1694SAndres Salomon */ 207011a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) 20714e4141a5SAnton Vorontsov sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 20721c6a0718SPierre Ossman 2073ae628903SPierre Ossman pwr |= SDHCI_POWER_ON; 2074ae628903SPierre Ossman 2075ae628903SPierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 2076557b0697SHarald Welte 2077f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) 2078f0710a55SAdrian Hunter sdhci_runtime_pm_bus_on(host); 2079f0710a55SAdrian Hunter 2080557b0697SHarald Welte /* 2081e921a8b6SRussell King * Some controllers need an extra 10ms delay of 10ms before 2082e921a8b6SRussell King * they can apply clock after applying power 2083557b0697SHarald Welte */ 208411a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) 2085557b0697SHarald Welte mdelay(10); 2086e921a8b6SRussell King } 2087918f4cbdSJisheng Zhang } 2088606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power_noreg); 20891dceb041SAdrian Hunter 2090606d3131SAdrian Hunter void sdhci_set_power(struct sdhci_host *host, unsigned char mode, 20911dceb041SAdrian Hunter unsigned short vdd) 20921dceb041SAdrian Hunter { 2093606d3131SAdrian Hunter if (IS_ERR(host->mmc->supply.vmmc)) 2094606d3131SAdrian Hunter sdhci_set_power_noreg(host, mode, vdd); 20951dceb041SAdrian Hunter else 2096606d3131SAdrian Hunter sdhci_set_power_reg(host, mode, vdd); 20971c6a0718SPierre Ossman } 2098606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power); 20991c6a0718SPierre Ossman 21006c92ae1eSNicolas Saenz Julienne /* 21016c92ae1eSNicolas Saenz Julienne * Some controllers need to configure a valid bus voltage on their power 21026c92ae1eSNicolas Saenz Julienne * register regardless of whether an external regulator is taking care of power 21036c92ae1eSNicolas Saenz Julienne * supply. This helper function takes care of it if set as the controller's 21046c92ae1eSNicolas Saenz Julienne * sdhci_ops.set_power callback. 21056c92ae1eSNicolas Saenz Julienne */ 21066c92ae1eSNicolas Saenz Julienne void sdhci_set_power_and_bus_voltage(struct sdhci_host *host, 21076c92ae1eSNicolas Saenz Julienne unsigned char mode, 21086c92ae1eSNicolas Saenz Julienne unsigned short vdd) 21096c92ae1eSNicolas Saenz Julienne { 21106c92ae1eSNicolas Saenz Julienne if (!IS_ERR(host->mmc->supply.vmmc)) { 21116c92ae1eSNicolas Saenz Julienne struct mmc_host *mmc = host->mmc; 21126c92ae1eSNicolas Saenz Julienne 21136c92ae1eSNicolas Saenz Julienne mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); 21146c92ae1eSNicolas Saenz Julienne } 21156c92ae1eSNicolas Saenz Julienne sdhci_set_power_noreg(host, mode, vdd); 21166c92ae1eSNicolas Saenz Julienne } 21176c92ae1eSNicolas Saenz Julienne EXPORT_SYMBOL_GPL(sdhci_set_power_and_bus_voltage); 21186c92ae1eSNicolas Saenz Julienne 21191c6a0718SPierre Ossman /*****************************************************************************\ 21201c6a0718SPierre Ossman * * 21211c6a0718SPierre Ossman * MMC callbacks * 21221c6a0718SPierre Ossman * * 21231c6a0718SPierre Ossman \*****************************************************************************/ 21241c6a0718SPierre Ossman 2125d462c1b4SAapo Vienamo void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) 21261c6a0718SPierre Ossman { 2127e872f1e2SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2128e872f1e2SAdrian Hunter struct mmc_command *cmd; 21291c6a0718SPierre Ossman unsigned long flags; 2130e872f1e2SAdrian Hunter bool present; 21311c6a0718SPierre Ossman 213204e079cfSScott Branden /* Firstly check card presence */ 21338d28b7a7SAdrian Hunter present = mmc->ops->get_cd(mmc); 21342836766aSKrzysztof Kozlowski 21351c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 21361c6a0718SPierre Ossman 2137061d17a6SAdrian Hunter sdhci_led_activate(host); 2138e89d456fSAndrei Warkentin 2139e872f1e2SAdrian Hunter if (sdhci_present_error(host, mrq->cmd, present)) 2140e872f1e2SAdrian Hunter goto out_finish; 21411c6a0718SPierre Ossman 2142e872f1e2SAdrian Hunter cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; 2143e872f1e2SAdrian Hunter 2144845c939eSAdrian Hunter if (!sdhci_send_command_retry(host, cmd, flags)) 2145845c939eSAdrian Hunter goto out_finish; 2146e872f1e2SAdrian Hunter 2147e872f1e2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2148e872f1e2SAdrian Hunter 2149e872f1e2SAdrian Hunter return; 2150e872f1e2SAdrian Hunter 2151e872f1e2SAdrian Hunter out_finish: 2152e872f1e2SAdrian Hunter sdhci_finish_mrq(host, mrq); 21531c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 21541c6a0718SPierre Ossman } 2155d462c1b4SAapo Vienamo EXPORT_SYMBOL_GPL(sdhci_request); 21561c6a0718SPierre Ossman 215748ef8a2aSBaolin Wang int sdhci_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq) 215848ef8a2aSBaolin Wang { 215948ef8a2aSBaolin Wang struct sdhci_host *host = mmc_priv(mmc); 216048ef8a2aSBaolin Wang struct mmc_command *cmd; 216148ef8a2aSBaolin Wang unsigned long flags; 216248ef8a2aSBaolin Wang int ret = 0; 216348ef8a2aSBaolin Wang 216448ef8a2aSBaolin Wang spin_lock_irqsave(&host->lock, flags); 216548ef8a2aSBaolin Wang 216648ef8a2aSBaolin Wang if (sdhci_present_error(host, mrq->cmd, true)) { 216748ef8a2aSBaolin Wang sdhci_finish_mrq(host, mrq); 216848ef8a2aSBaolin Wang goto out_finish; 216948ef8a2aSBaolin Wang } 217048ef8a2aSBaolin Wang 217148ef8a2aSBaolin Wang cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; 217248ef8a2aSBaolin Wang 217348ef8a2aSBaolin Wang /* 217448ef8a2aSBaolin Wang * The HSQ may send a command in interrupt context without polling 217548ef8a2aSBaolin Wang * the busy signaling, which means we should return BUSY if controller 217648ef8a2aSBaolin Wang * has not released inhibit bits to allow HSQ trying to send request 217748ef8a2aSBaolin Wang * again in non-atomic context. So we should not finish this request 217848ef8a2aSBaolin Wang * here. 217948ef8a2aSBaolin Wang */ 218048ef8a2aSBaolin Wang if (!sdhci_send_command(host, cmd)) 218148ef8a2aSBaolin Wang ret = -EBUSY; 218248ef8a2aSBaolin Wang else 218348ef8a2aSBaolin Wang sdhci_led_activate(host); 218448ef8a2aSBaolin Wang 218548ef8a2aSBaolin Wang out_finish: 218648ef8a2aSBaolin Wang spin_unlock_irqrestore(&host->lock, flags); 218748ef8a2aSBaolin Wang return ret; 218848ef8a2aSBaolin Wang } 218948ef8a2aSBaolin Wang EXPORT_SYMBOL_GPL(sdhci_request_atomic); 219048ef8a2aSBaolin Wang 21912317f56cSRussell King void sdhci_set_bus_width(struct sdhci_host *host, int width) 21922317f56cSRussell King { 21932317f56cSRussell King u8 ctrl; 21942317f56cSRussell King 21952317f56cSRussell King ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 21962317f56cSRussell King if (width == MMC_BUS_WIDTH_8) { 21972317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS; 21982317f56cSRussell King ctrl |= SDHCI_CTRL_8BITBUS; 21992317f56cSRussell King } else { 220098f94ea6SMichał Mirosław if (host->mmc->caps & MMC_CAP_8_BIT_DATA) 22012317f56cSRussell King ctrl &= ~SDHCI_CTRL_8BITBUS; 22022317f56cSRussell King if (width == MMC_BUS_WIDTH_4) 22032317f56cSRussell King ctrl |= SDHCI_CTRL_4BITBUS; 22042317f56cSRussell King else 22052317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS; 22062317f56cSRussell King } 22072317f56cSRussell King sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 22082317f56cSRussell King } 22092317f56cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_bus_width); 22102317f56cSRussell King 221196d7b78cSRussell King void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) 221296d7b78cSRussell King { 221396d7b78cSRussell King u16 ctrl_2; 221496d7b78cSRussell King 221596d7b78cSRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 221696d7b78cSRussell King /* Select Bus Speed Mode for host */ 221796d7b78cSRussell King ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 221896d7b78cSRussell King if ((timing == MMC_TIMING_MMC_HS200) || 221996d7b78cSRussell King (timing == MMC_TIMING_UHS_SDR104)) 222096d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR104; 222196d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR12) 222296d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR12; 222307bcc411SFaiz Abbas else if (timing == MMC_TIMING_UHS_SDR25) 222496d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 222596d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR50) 222696d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR50; 222796d7b78cSRussell King else if ((timing == MMC_TIMING_UHS_DDR50) || 222896d7b78cSRussell King (timing == MMC_TIMING_MMC_DDR52)) 222996d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_DDR50; 2230e9fb05d5SAdrian Hunter else if (timing == MMC_TIMING_MMC_HS400) 2231e9fb05d5SAdrian Hunter ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */ 223296d7b78cSRussell King sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 223396d7b78cSRussell King } 223496d7b78cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); 223596d7b78cSRussell King 22366a6d4cebSHu Ziji void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 22371c6a0718SPierre Ossman { 2238ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 22391c6a0718SPierre Ossman u8 ctrl; 22401c6a0718SPierre Ossman 224184ec048bSAdrian Hunter if (ios->power_mode == MMC_POWER_UNDEFINED) 224284ec048bSAdrian Hunter return; 224384ec048bSAdrian Hunter 2244ceb6143bSAdrian Hunter if (host->flags & SDHCI_DEVICE_DEAD) { 22453a48edc4STim Kryger if (!IS_ERR(mmc->supply.vmmc) && 22463a48edc4STim Kryger ios->power_mode == MMC_POWER_OFF) 22474e743f1fSMarkus Mayer mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 2248ceb6143bSAdrian Hunter return; 2249ceb6143bSAdrian Hunter } 22501e72859eSPierre Ossman 22511c6a0718SPierre Ossman /* 22521c6a0718SPierre Ossman * Reset the chip on each power off. 22531c6a0718SPierre Ossman * Should clear out any weird states. 22541c6a0718SPierre Ossman */ 22551c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) { 22564e4141a5SAnton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 22577260cf5eSAnton Vorontsov sdhci_reinit(host); 22581c6a0718SPierre Ossman } 22591c6a0718SPierre Ossman 226052983382SKevin Liu if (host->version >= SDHCI_SPEC_300 && 2261372c4634SDong Aisheng (ios->power_mode == MMC_POWER_UP) && 2262372c4634SDong Aisheng !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) 226352983382SKevin Liu sdhci_enable_preset_value(host, false); 226452983382SKevin Liu 2265373073efSRussell King if (!ios->clock || ios->clock != host->clock) { 22661771059cSRussell King host->ops->set_clock(host, ios->clock); 2267373073efSRussell King host->clock = ios->clock; 226803d6f5ffSAisheng Dong 226903d6f5ffSAisheng Dong if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && 227003d6f5ffSAisheng Dong host->clock) { 227103d6f5ffSAisheng Dong host->timeout_clk = host->mmc->actual_clock ? 227203d6f5ffSAisheng Dong host->mmc->actual_clock / 1000 : 227303d6f5ffSAisheng Dong host->clock / 1000; 227403d6f5ffSAisheng Dong host->mmc->max_busy_timeout = 227503d6f5ffSAisheng Dong host->ops->get_max_timeout_count ? 227603d6f5ffSAisheng Dong host->ops->get_max_timeout_count(host) : 227703d6f5ffSAisheng Dong 1 << 27; 227803d6f5ffSAisheng Dong host->mmc->max_busy_timeout /= host->timeout_clk; 227903d6f5ffSAisheng Dong } 2280373073efSRussell King } 22811c6a0718SPierre Ossman 2282606d3131SAdrian Hunter if (host->ops->set_power) 2283606d3131SAdrian Hunter host->ops->set_power(host, ios->power_mode, ios->vdd); 2284606d3131SAdrian Hunter else 2285606d3131SAdrian Hunter sdhci_set_power(host, ios->power_mode, ios->vdd); 22861c6a0718SPierre Ossman 2287643a81ffSPhilip Rakity if (host->ops->platform_send_init_74_clocks) 2288643a81ffSPhilip Rakity host->ops->platform_send_init_74_clocks(host, ios->power_mode); 2289643a81ffSPhilip Rakity 22902317f56cSRussell King host->ops->set_bus_width(host, ios->bus_width); 229115ec4461SPhilip Rakity 229215ec4461SPhilip Rakity ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 22931c6a0718SPierre Ossman 2294501639bfSyangbo lu if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) { 2295501639bfSyangbo lu if (ios->timing == MMC_TIMING_SD_HS || 2296273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS || 2297273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS400 || 2298273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS200 || 2299273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_DDR52 || 2300273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR50 || 2301273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR104 || 2302273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_DDR50 || 2303273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR25) 23041c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_HISPD; 23051c6a0718SPierre Ossman else 23061c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_HISPD; 2307501639bfSyangbo lu } 23081c6a0718SPierre Ossman 2309d6d50a15SArindam Nath if (host->version >= SDHCI_SPEC_300) { 231049c468fcSArindam Nath u16 clk, ctrl_2; 231149c468fcSArindam Nath 2312da91a8f9SRussell King if (!host->preset_enabled) { 2313758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2314d6d50a15SArindam Nath /* 2315d6d50a15SArindam Nath * We only need to set Driver Strength if the 2316d6d50a15SArindam Nath * preset value enable is not set. 2317d6d50a15SArindam Nath */ 2318da91a8f9SRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2319d6d50a15SArindam Nath ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; 2320d6d50a15SArindam Nath if (ios->drv_type == MMC_SET_DRIVER_TYPE_A) 2321d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; 232243e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_B) 232343e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B; 2324d6d50a15SArindam Nath else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C) 2325d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C; 232643e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D) 232743e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D; 232843e943a0SPetri Gynther else { 23292e4456f0SMarek Vasut pr_warn("%s: invalid driver type, default to driver type B\n", 23302e4456f0SMarek Vasut mmc_hostname(mmc)); 233143e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B; 233243e943a0SPetri Gynther } 2333d6d50a15SArindam Nath 2334d6d50a15SArindam Nath sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 2335758535c4SArindam Nath } else { 2336758535c4SArindam Nath /* 2337758535c4SArindam Nath * According to SDHC Spec v3.00, if the Preset Value 2338758535c4SArindam Nath * Enable in the Host Control 2 register is set, we 2339758535c4SArindam Nath * need to reset SD Clock Enable before changing High 2340758535c4SArindam Nath * Speed Enable to avoid generating clock gliches. 2341758535c4SArindam Nath */ 2342758535c4SArindam Nath 2343758535c4SArindam Nath /* Reset SD Clock Enable */ 2344758535c4SArindam Nath clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 2345758535c4SArindam Nath clk &= ~SDHCI_CLOCK_CARD_EN; 2346758535c4SArindam Nath sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 2347758535c4SArindam Nath 2348758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2349758535c4SArindam Nath 2350758535c4SArindam Nath /* Re-enable SD Clock */ 23511771059cSRussell King host->ops->set_clock(host, host->clock); 2352d6d50a15SArindam Nath } 235349c468fcSArindam Nath 23546322cdd0SPhilip Rakity /* Reset SD Clock Enable */ 23556322cdd0SPhilip Rakity clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 23566322cdd0SPhilip Rakity clk &= ~SDHCI_CLOCK_CARD_EN; 23576322cdd0SPhilip Rakity sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 23586322cdd0SPhilip Rakity 23596322cdd0SPhilip Rakity host->ops->set_uhs_signaling(host, ios->timing); 2360d975f121SRussell King host->timing = ios->timing; 236149c468fcSArindam Nath 236252983382SKevin Liu if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && 236352983382SKevin Liu ((ios->timing == MMC_TIMING_UHS_SDR12) || 236452983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR25) || 236552983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR50) || 236652983382SKevin Liu (ios->timing == MMC_TIMING_UHS_SDR104) || 23670dafa60eSJisheng Zhang (ios->timing == MMC_TIMING_UHS_DDR50) || 23680dafa60eSJisheng Zhang (ios->timing == MMC_TIMING_MMC_DDR52))) { 236952983382SKevin Liu u16 preset; 237052983382SKevin Liu 237152983382SKevin Liu sdhci_enable_preset_value(host, true); 237252983382SKevin Liu preset = sdhci_get_preset_value(host); 2373fa091010SMasahiro Yamada ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK, 2374fa091010SMasahiro Yamada preset); 237552983382SKevin Liu } 237652983382SKevin Liu 237749c468fcSArindam Nath /* Re-enable SD Clock */ 23781771059cSRussell King host->ops->set_clock(host, host->clock); 2379758535c4SArindam Nath } else 2380758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 2381d6d50a15SArindam Nath 2382b8352260SLeandro Dorileo /* 2383b8352260SLeandro Dorileo * Some (ENE) controllers go apeshit on some ios operation, 2384b8352260SLeandro Dorileo * signalling timeout and CRC errors even on CMD0. Resetting 2385b8352260SLeandro Dorileo * it on each ios seems to solve the problem. 2386b8352260SLeandro Dorileo */ 2387b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 238803231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 23891c6a0718SPierre Ossman } 23906a6d4cebSHu Ziji EXPORT_SYMBOL_GPL(sdhci_set_ios); 23911c6a0718SPierre Ossman 2392ded97e0bSDong Aisheng static int sdhci_get_cd(struct mmc_host *mmc) 239366fd8ad5SAdrian Hunter { 239466fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2395ded97e0bSDong Aisheng int gpio_cd = mmc_gpio_get_cd(mmc); 239694144a46SKevin Liu 239794144a46SKevin Liu if (host->flags & SDHCI_DEVICE_DEAD) 239894144a46SKevin Liu return 0; 239994144a46SKevin Liu 240088af5655SIvan T. Ivanov /* If nonremovable, assume that the card is always present. */ 2401860951c5SJaehoon Chung if (!mmc_card_is_removable(host->mmc)) 240294144a46SKevin Liu return 1; 240394144a46SKevin Liu 240488af5655SIvan T. Ivanov /* 240588af5655SIvan T. Ivanov * Try slot gpio detect, if defined it take precedence 240688af5655SIvan T. Ivanov * over build in controller functionality 240788af5655SIvan T. Ivanov */ 2408287980e4SArnd Bergmann if (gpio_cd >= 0) 240994144a46SKevin Liu return !!gpio_cd; 241094144a46SKevin Liu 241188af5655SIvan T. Ivanov /* If polling, assume that the card is always present. */ 241288af5655SIvan T. Ivanov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) 241388af5655SIvan T. Ivanov return 1; 241488af5655SIvan T. Ivanov 241594144a46SKevin Liu /* Host native card detect */ 241694144a46SKevin Liu return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); 241794144a46SKevin Liu } 241894144a46SKevin Liu 241966fd8ad5SAdrian Hunter static int sdhci_check_ro(struct sdhci_host *host) 24201c6a0718SPierre Ossman { 24211c6a0718SPierre Ossman unsigned long flags; 24222dfb579cSWolfram Sang int is_readonly; 24231c6a0718SPierre Ossman 24241c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 24251c6a0718SPierre Ossman 24261e72859eSPierre Ossman if (host->flags & SDHCI_DEVICE_DEAD) 24272dfb579cSWolfram Sang is_readonly = 0; 24282dfb579cSWolfram Sang else if (host->ops->get_ro) 24292dfb579cSWolfram Sang is_readonly = host->ops->get_ro(host); 24306d5cd068SThomas Petazzoni else if (mmc_can_gpio_ro(host->mmc)) 24316d5cd068SThomas Petazzoni is_readonly = mmc_gpio_get_ro(host->mmc); 24321e72859eSPierre Ossman else 24332dfb579cSWolfram Sang is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) 24342dfb579cSWolfram Sang & SDHCI_WRITE_PROTECT); 24351c6a0718SPierre Ossman 24361c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 24371c6a0718SPierre Ossman 24382dfb579cSWolfram Sang /* This quirk needs to be replaced by a callback-function later */ 24392dfb579cSWolfram Sang return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? 24402dfb579cSWolfram Sang !is_readonly : is_readonly; 24411c6a0718SPierre Ossman } 24421c6a0718SPierre Ossman 244382b0e23aSTakashi Iwai #define SAMPLE_COUNT 5 244482b0e23aSTakashi Iwai 2445ded97e0bSDong Aisheng static int sdhci_get_ro(struct mmc_host *mmc) 244682b0e23aSTakashi Iwai { 2447ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 244882b0e23aSTakashi Iwai int i, ro_count; 244982b0e23aSTakashi Iwai 245082b0e23aSTakashi Iwai if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT)) 245166fd8ad5SAdrian Hunter return sdhci_check_ro(host); 245282b0e23aSTakashi Iwai 245382b0e23aSTakashi Iwai ro_count = 0; 245482b0e23aSTakashi Iwai for (i = 0; i < SAMPLE_COUNT; i++) { 245566fd8ad5SAdrian Hunter if (sdhci_check_ro(host)) { 245682b0e23aSTakashi Iwai if (++ro_count > SAMPLE_COUNT / 2) 245782b0e23aSTakashi Iwai return 1; 245882b0e23aSTakashi Iwai } 245982b0e23aSTakashi Iwai msleep(30); 246082b0e23aSTakashi Iwai } 246182b0e23aSTakashi Iwai return 0; 246282b0e23aSTakashi Iwai } 246382b0e23aSTakashi Iwai 246420758b66SAdrian Hunter static void sdhci_hw_reset(struct mmc_host *mmc) 246520758b66SAdrian Hunter { 246620758b66SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 246720758b66SAdrian Hunter 246820758b66SAdrian Hunter if (host->ops && host->ops->hw_reset) 246920758b66SAdrian Hunter host->ops->hw_reset(host); 247020758b66SAdrian Hunter } 247120758b66SAdrian Hunter 247266fd8ad5SAdrian Hunter static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable) 247366fd8ad5SAdrian Hunter { 2474be138554SRussell King if (!(host->flags & SDHCI_DEVICE_DEAD)) { 247566fd8ad5SAdrian Hunter if (enable) 2476b537f94cSRussell King host->ier |= SDHCI_INT_CARD_INT; 24777260cf5eSAnton Vorontsov else 2478b537f94cSRussell King host->ier &= ~SDHCI_INT_CARD_INT; 2479b537f94cSRussell King 2480b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2481b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 248266fd8ad5SAdrian Hunter } 2483ef104333SRussell King } 2484f75979b7SPierre Ossman 24852f05b6abSHu Ziji void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) 248666fd8ad5SAdrian Hunter { 248766fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 248866fd8ad5SAdrian Hunter unsigned long flags; 248966fd8ad5SAdrian Hunter 2490923713b3SHans de Goede if (enable) 2491923713b3SHans de Goede pm_runtime_get_noresume(host->mmc->parent); 2492923713b3SHans de Goede 249366fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 249466fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, enable); 2495f75979b7SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 2496923713b3SHans de Goede 2497923713b3SHans de Goede if (!enable) 2498923713b3SHans de Goede pm_runtime_put_noidle(host->mmc->parent); 2499f75979b7SPierre Ossman } 25002f05b6abSHu Ziji EXPORT_SYMBOL_GPL(sdhci_enable_sdio_irq); 2501f75979b7SPierre Ossman 250289f3c365SAdrian Hunter static void sdhci_ack_sdio_irq(struct mmc_host *mmc) 250389f3c365SAdrian Hunter { 250489f3c365SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 250589f3c365SAdrian Hunter unsigned long flags; 250689f3c365SAdrian Hunter 250789f3c365SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 250889f3c365SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true); 250989f3c365SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 251089f3c365SAdrian Hunter } 251189f3c365SAdrian Hunter 2512c376ea9eSHu Ziji int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, 251321f5998fSFabio Estevam struct mmc_ios *ios) 2514f2119df6SArindam Nath { 2515ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc); 251620b92a30SKevin Liu u16 ctrl; 25176231f3deSPhilip Rakity int ret; 2518f2119df6SArindam Nath 251920b92a30SKevin Liu /* 252020b92a30SKevin Liu * Signal Voltage Switching is only applicable for Host Controllers 252120b92a30SKevin Liu * v3.00 and above. 252220b92a30SKevin Liu */ 252320b92a30SKevin Liu if (host->version < SDHCI_SPEC_300) 252420b92a30SKevin Liu return 0; 252520b92a30SKevin Liu 252620b92a30SKevin Liu ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 252720b92a30SKevin Liu 252821f5998fSFabio Estevam switch (ios->signal_voltage) { 252920b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_330: 25308cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_330)) 25318cb851a4SAdrian Hunter return -EINVAL; 2532f2119df6SArindam Nath /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ 2533f2119df6SArindam Nath ctrl &= ~SDHCI_CTRL_VDD_180; 2534f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2535f2119df6SArindam Nath 25363a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2537761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 25389cbe0fc8SMarek Vasut if (ret < 0) { 25396606110dSJoe Perches pr_warn("%s: Switching to 3.3V signalling voltage failed\n", 25406606110dSJoe Perches mmc_hostname(mmc)); 25416231f3deSPhilip Rakity return -EIO; 25426231f3deSPhilip Rakity } 25436231f3deSPhilip Rakity } 2544f2119df6SArindam Nath /* Wait for 5ms */ 2545f2119df6SArindam Nath usleep_range(5000, 5500); 2546f2119df6SArindam Nath 2547f2119df6SArindam Nath /* 3.3V regulator output should be stable within 5 ms */ 2548f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2549f2119df6SArindam Nath if (!(ctrl & SDHCI_CTRL_VDD_180)) 2550f2119df6SArindam Nath return 0; 25516231f3deSPhilip Rakity 2552b0b19ce6SFabio Estevam pr_warn("%s: 3.3V regulator output did not become stable\n", 25534e743f1fSMarkus Mayer mmc_hostname(mmc)); 25546231f3deSPhilip Rakity 255520b92a30SKevin Liu return -EAGAIN; 255620b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_180: 25578cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_180)) 25588cb851a4SAdrian Hunter return -EINVAL; 25593a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2560761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 25619cbe0fc8SMarek Vasut if (ret < 0) { 25626606110dSJoe Perches pr_warn("%s: Switching to 1.8V signalling voltage failed\n", 25636606110dSJoe Perches mmc_hostname(mmc)); 2564f2119df6SArindam Nath return -EIO; 2565f2119df6SArindam Nath } 256620b92a30SKevin Liu } 25676231f3deSPhilip Rakity 2568f2119df6SArindam Nath /* 2569f2119df6SArindam Nath * Enable 1.8V Signal Enable in the Host Control2 2570f2119df6SArindam Nath * register 2571f2119df6SArindam Nath */ 2572f2119df6SArindam Nath ctrl |= SDHCI_CTRL_VDD_180; 2573f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2574f2119df6SArindam Nath 25759d967a61SVincent Yang /* Some controller need to do more when switching */ 25769d967a61SVincent Yang if (host->ops->voltage_switch) 25779d967a61SVincent Yang host->ops->voltage_switch(host); 25789d967a61SVincent Yang 257920b92a30SKevin Liu /* 1.8V regulator output should be stable within 5 ms */ 2580f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 258120b92a30SKevin Liu if (ctrl & SDHCI_CTRL_VDD_180) 2582f2119df6SArindam Nath return 0; 2583f2119df6SArindam Nath 2584b0b19ce6SFabio Estevam pr_warn("%s: 1.8V regulator output did not become stable\n", 25854e743f1fSMarkus Mayer mmc_hostname(mmc)); 25866231f3deSPhilip Rakity 2587f2119df6SArindam Nath return -EAGAIN; 258820b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_120: 25898cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_120)) 25908cb851a4SAdrian Hunter return -EINVAL; 25913a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 2592761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios); 25939cbe0fc8SMarek Vasut if (ret < 0) { 25946606110dSJoe Perches pr_warn("%s: Switching to 1.2V signalling voltage failed\n", 25956606110dSJoe Perches mmc_hostname(mmc)); 259620b92a30SKevin Liu return -EIO; 25976231f3deSPhilip Rakity } 259820b92a30SKevin Liu } 25996231f3deSPhilip Rakity return 0; 260020b92a30SKevin Liu default: 2601f2119df6SArindam Nath /* No signal voltage switch required */ 2602f2119df6SArindam Nath return 0; 2603f2119df6SArindam Nath } 260420b92a30SKevin Liu } 2605c376ea9eSHu Ziji EXPORT_SYMBOL_GPL(sdhci_start_signal_voltage_switch); 2606f2119df6SArindam Nath 260720b92a30SKevin Liu static int sdhci_card_busy(struct mmc_host *mmc) 260820b92a30SKevin Liu { 260920b92a30SKevin Liu struct sdhci_host *host = mmc_priv(mmc); 261020b92a30SKevin Liu u32 present_state; 261120b92a30SKevin Liu 2612e613cc47SAdrian Hunter /* Check whether DAT[0] is 0 */ 261320b92a30SKevin Liu present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); 261420b92a30SKevin Liu 2615e613cc47SAdrian Hunter return !(present_state & SDHCI_DATA_0_LVL_MASK); 261620b92a30SKevin Liu } 261720b92a30SKevin Liu 2618b5540ce1SAdrian Hunter static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) 2619b5540ce1SAdrian Hunter { 2620b5540ce1SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 2621b5540ce1SAdrian Hunter unsigned long flags; 2622b5540ce1SAdrian Hunter 2623b5540ce1SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2624b5540ce1SAdrian Hunter host->flags |= SDHCI_HS400_TUNING; 2625b5540ce1SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2626b5540ce1SAdrian Hunter 2627b5540ce1SAdrian Hunter return 0; 2628b5540ce1SAdrian Hunter } 2629b5540ce1SAdrian Hunter 26306663c419Sernest.zhang void sdhci_start_tuning(struct sdhci_host *host) 2631da4bc4f2SAdrian Hunter { 2632da4bc4f2SAdrian Hunter u16 ctrl; 2633da4bc4f2SAdrian Hunter 2634da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2635da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_EXEC_TUNING; 2636da4bc4f2SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND) 2637da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_TUNED_CLK; 2638da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2639da4bc4f2SAdrian Hunter 2640da4bc4f2SAdrian Hunter /* 2641da4bc4f2SAdrian Hunter * As per the Host Controller spec v3.00, tuning command 2642da4bc4f2SAdrian Hunter * generates Buffer Read Ready interrupt, so enable that. 2643da4bc4f2SAdrian Hunter * 2644da4bc4f2SAdrian Hunter * Note: The spec clearly says that when tuning sequence 2645da4bc4f2SAdrian Hunter * is being performed, the controller does not generate 2646da4bc4f2SAdrian Hunter * interrupts other than Buffer Read Ready interrupt. But 2647da4bc4f2SAdrian Hunter * to make sure we don't hit a controller bug, we _only_ 2648da4bc4f2SAdrian Hunter * enable Buffer Read Ready interrupt here. 2649da4bc4f2SAdrian Hunter */ 2650da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); 2651da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); 2652da4bc4f2SAdrian Hunter } 26536663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_start_tuning); 2654da4bc4f2SAdrian Hunter 26556663c419Sernest.zhang void sdhci_end_tuning(struct sdhci_host *host) 2656da4bc4f2SAdrian Hunter { 2657da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 2658da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 2659da4bc4f2SAdrian Hunter } 26606663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_end_tuning); 2661da4bc4f2SAdrian Hunter 26626663c419Sernest.zhang void sdhci_reset_tuning(struct sdhci_host *host) 2663da4bc4f2SAdrian Hunter { 2664da4bc4f2SAdrian Hunter u16 ctrl; 2665da4bc4f2SAdrian Hunter 2666da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2667da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_TUNED_CLK; 2668da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_EXEC_TUNING; 2669da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2670da4bc4f2SAdrian Hunter } 26716663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_reset_tuning); 2672da4bc4f2SAdrian Hunter 26737353788cSBen Chuang void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) 2674da4bc4f2SAdrian Hunter { 2675da4bc4f2SAdrian Hunter sdhci_reset_tuning(host); 2676da4bc4f2SAdrian Hunter 2677da4bc4f2SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD); 2678da4bc4f2SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 2679da4bc4f2SAdrian Hunter 2680da4bc4f2SAdrian Hunter sdhci_end_tuning(host); 2681da4bc4f2SAdrian Hunter 2682da4bc4f2SAdrian Hunter mmc_abort_tuning(host->mmc, opcode); 2683da4bc4f2SAdrian Hunter } 26847353788cSBen Chuang EXPORT_SYMBOL_GPL(sdhci_abort_tuning); 2685da4bc4f2SAdrian Hunter 2686da4bc4f2SAdrian Hunter /* 2687da4bc4f2SAdrian Hunter * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI 2688da4bc4f2SAdrian Hunter * tuning command does not have a data payload (or rather the hardware does it 2689da4bc4f2SAdrian Hunter * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command 2690da4bc4f2SAdrian Hunter * interrupt setup is different to other commands and there is no timeout 2691da4bc4f2SAdrian Hunter * interrupt so special handling is needed. 2692da4bc4f2SAdrian Hunter */ 26936663c419Sernest.zhang void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) 2694da4bc4f2SAdrian Hunter { 2695da4bc4f2SAdrian Hunter struct mmc_host *mmc = host->mmc; 2696c7836d15SMasahiro Yamada struct mmc_command cmd = {}; 2697c7836d15SMasahiro Yamada struct mmc_request mrq = {}; 26982a85ef25SAdrian Hunter unsigned long flags; 2699c846a00fSSrinivas Kandagatla u32 b = host->sdma_boundary; 27002a85ef25SAdrian Hunter 27012a85ef25SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 2702da4bc4f2SAdrian Hunter 2703da4bc4f2SAdrian Hunter cmd.opcode = opcode; 2704da4bc4f2SAdrian Hunter cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 2705da4bc4f2SAdrian Hunter cmd.mrq = &mrq; 2706da4bc4f2SAdrian Hunter 2707da4bc4f2SAdrian Hunter mrq.cmd = &cmd; 2708da4bc4f2SAdrian Hunter /* 2709da4bc4f2SAdrian Hunter * In response to CMD19, the card sends 64 bytes of tuning 2710da4bc4f2SAdrian Hunter * block to the Host Controller. So we set the block size 2711da4bc4f2SAdrian Hunter * to 64 here. 2712da4bc4f2SAdrian Hunter */ 271385336109SAdrian Hunter if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200 && 271485336109SAdrian Hunter mmc->ios.bus_width == MMC_BUS_WIDTH_8) 2715c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 128), SDHCI_BLOCK_SIZE); 271685336109SAdrian Hunter else 2717c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 64), SDHCI_BLOCK_SIZE); 2718da4bc4f2SAdrian Hunter 2719da4bc4f2SAdrian Hunter /* 2720da4bc4f2SAdrian Hunter * The tuning block is sent by the card to the host controller. 2721da4bc4f2SAdrian Hunter * So we set the TRNS_READ bit in the Transfer Mode register. 2722da4bc4f2SAdrian Hunter * This also takes care of setting DMA Enable and Multi Block 2723da4bc4f2SAdrian Hunter * Select in the same register to 0. 2724da4bc4f2SAdrian Hunter */ 2725da4bc4f2SAdrian Hunter sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); 2726da4bc4f2SAdrian Hunter 2727845c939eSAdrian Hunter if (!sdhci_send_command_retry(host, &cmd, flags)) { 2728845c939eSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2729845c939eSAdrian Hunter host->tuning_done = 0; 2730845c939eSAdrian Hunter return; 2731845c939eSAdrian Hunter } 2732da4bc4f2SAdrian Hunter 2733da4bc4f2SAdrian Hunter host->cmd = NULL; 2734da4bc4f2SAdrian Hunter 2735da4bc4f2SAdrian Hunter sdhci_del_timer(host, &mrq); 2736da4bc4f2SAdrian Hunter 2737da4bc4f2SAdrian Hunter host->tuning_done = 0; 2738da4bc4f2SAdrian Hunter 2739da4bc4f2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 2740da4bc4f2SAdrian Hunter 2741da4bc4f2SAdrian Hunter /* Wait for Buffer Read Ready interrupt */ 2742da4bc4f2SAdrian Hunter wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1), 2743da4bc4f2SAdrian Hunter msecs_to_jiffies(50)); 2744da4bc4f2SAdrian Hunter 2745da4bc4f2SAdrian Hunter } 27466663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_send_tuning); 2747da4bc4f2SAdrian Hunter 27487d8bb1f4SYinbo Zhu static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) 27496b11e70bSAdrian Hunter { 27506b11e70bSAdrian Hunter int i; 27516b11e70bSAdrian Hunter 27526b11e70bSAdrian Hunter /* 27536b11e70bSAdrian Hunter * Issue opcode repeatedly till Execute Tuning is set to 0 or the number 27541d8cd065SSowjanya Komatineni * of loops reaches tuning loop count. 27556b11e70bSAdrian Hunter */ 27561d8cd065SSowjanya Komatineni for (i = 0; i < host->tuning_loop_count; i++) { 27576b11e70bSAdrian Hunter u16 ctrl; 27586b11e70bSAdrian Hunter 27592a85ef25SAdrian Hunter sdhci_send_tuning(host, opcode); 27606b11e70bSAdrian Hunter 27616b11e70bSAdrian Hunter if (!host->tuning_done) { 2762811ba676SFaiz Abbas pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n", 27636b11e70bSAdrian Hunter mmc_hostname(host->mmc)); 27642a85ef25SAdrian Hunter sdhci_abort_tuning(host, opcode); 27657d8bb1f4SYinbo Zhu return -ETIMEDOUT; 27666b11e70bSAdrian Hunter } 27676b11e70bSAdrian Hunter 27682b06e159SBOUGH CHEN /* Spec does not require a delay between tuning cycles */ 27692b06e159SBOUGH CHEN if (host->tuning_delay > 0) 27702b06e159SBOUGH CHEN mdelay(host->tuning_delay); 27712b06e159SBOUGH CHEN 27726b11e70bSAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 27736b11e70bSAdrian Hunter if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { 27746b11e70bSAdrian Hunter if (ctrl & SDHCI_CTRL_TUNED_CLK) 27757d8bb1f4SYinbo Zhu return 0; /* Success! */ 27766b11e70bSAdrian Hunter break; 27776b11e70bSAdrian Hunter } 27786b11e70bSAdrian Hunter 27796b11e70bSAdrian Hunter } 27806b11e70bSAdrian Hunter 27816b11e70bSAdrian Hunter pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", 27826b11e70bSAdrian Hunter mmc_hostname(host->mmc)); 27836b11e70bSAdrian Hunter sdhci_reset_tuning(host); 27847d8bb1f4SYinbo Zhu return -EAGAIN; 27856b11e70bSAdrian Hunter } 27866b11e70bSAdrian Hunter 278785a882c2SMasahiro Yamada int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) 2788b513ea25SArindam Nath { 27894b6f37d3SRussell King struct sdhci_host *host = mmc_priv(mmc); 2790b513ea25SArindam Nath int err = 0; 279138e40bf5SAdrian Hunter unsigned int tuning_count = 0; 2792b5540ce1SAdrian Hunter bool hs400_tuning; 2793b513ea25SArindam Nath 2794b5540ce1SAdrian Hunter hs400_tuning = host->flags & SDHCI_HS400_TUNING; 2795b5540ce1SAdrian Hunter 279638e40bf5SAdrian Hunter if (host->tuning_mode == SDHCI_TUNING_MODE_1) 279738e40bf5SAdrian Hunter tuning_count = host->tuning_count; 279838e40bf5SAdrian Hunter 2799b513ea25SArindam Nath /* 28009faac7b9SWeijun Yang * The Host Controller needs tuning in case of SDR104 and DDR50 28019faac7b9SWeijun Yang * mode, and for SDR50 mode when Use Tuning for SDR50 is set in 28029faac7b9SWeijun Yang * the Capabilities register. 2803069c9f14SGirish K S * If the Host Controller supports the HS200 mode then the 2804069c9f14SGirish K S * tuning function has to be executed. 2805b513ea25SArindam Nath */ 28064b6f37d3SRussell King switch (host->timing) { 2807b5540ce1SAdrian Hunter /* HS400 tuning is done in HS200 mode */ 2808e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400: 2809b5540ce1SAdrian Hunter err = -EINVAL; 28102a85ef25SAdrian Hunter goto out; 2811b5540ce1SAdrian Hunter 28124b6f37d3SRussell King case MMC_TIMING_MMC_HS200: 2813b5540ce1SAdrian Hunter /* 2814b5540ce1SAdrian Hunter * Periodic re-tuning for HS400 is not expected to be needed, so 2815b5540ce1SAdrian Hunter * disable it here. 2816b5540ce1SAdrian Hunter */ 2817b5540ce1SAdrian Hunter if (hs400_tuning) 2818b5540ce1SAdrian Hunter tuning_count = 0; 2819b5540ce1SAdrian Hunter break; 2820b5540ce1SAdrian Hunter 28214b6f37d3SRussell King case MMC_TIMING_UHS_SDR104: 28229faac7b9SWeijun Yang case MMC_TIMING_UHS_DDR50: 28234b6f37d3SRussell King break; 2824069c9f14SGirish K S 28254b6f37d3SRussell King case MMC_TIMING_UHS_SDR50: 28264228b213SAdrian Hunter if (host->flags & SDHCI_SDR50_NEEDS_TUNING) 28274b6f37d3SRussell King break; 28284b6f37d3SRussell King /* FALLTHROUGH */ 28294b6f37d3SRussell King 28304b6f37d3SRussell King default: 28312a85ef25SAdrian Hunter goto out; 2832b513ea25SArindam Nath } 2833b513ea25SArindam Nath 283445251812SDong Aisheng if (host->ops->platform_execute_tuning) { 28358a8fa879SRitesh Harjani err = host->ops->platform_execute_tuning(host, opcode); 28362a85ef25SAdrian Hunter goto out; 283745251812SDong Aisheng } 283845251812SDong Aisheng 28396b11e70bSAdrian Hunter host->mmc->retune_period = tuning_count; 28406b11e70bSAdrian Hunter 284183b600b8SAdrian Hunter if (host->tuning_delay < 0) 284283b600b8SAdrian Hunter host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK; 284383b600b8SAdrian Hunter 2844da4bc4f2SAdrian Hunter sdhci_start_tuning(host); 2845b513ea25SArindam Nath 28467d8bb1f4SYinbo Zhu host->tuning_err = __sdhci_execute_tuning(host, opcode); 2847cf2b5eeaSArindam Nath 2848da4bc4f2SAdrian Hunter sdhci_end_tuning(host); 28492a85ef25SAdrian Hunter out: 28508a8fa879SRitesh Harjani host->flags &= ~SDHCI_HS400_TUNING; 28516b11e70bSAdrian Hunter 2852b513ea25SArindam Nath return err; 2853b513ea25SArindam Nath } 285485a882c2SMasahiro Yamada EXPORT_SYMBOL_GPL(sdhci_execute_tuning); 2855b513ea25SArindam Nath 285652983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) 28574d55c5a1SArindam Nath { 28584d55c5a1SArindam Nath /* Host Controller v3.00 defines preset value registers */ 28594d55c5a1SArindam Nath if (host->version < SDHCI_SPEC_300) 28604d55c5a1SArindam Nath return; 28614d55c5a1SArindam Nath 28624d55c5a1SArindam Nath /* 28634d55c5a1SArindam Nath * We only enable or disable Preset Value if they are not already 28644d55c5a1SArindam Nath * enabled or disabled respectively. Otherwise, we bail out. 28654d55c5a1SArindam Nath */ 2866da91a8f9SRussell King if (host->preset_enabled != enable) { 2867da91a8f9SRussell King u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 2868da91a8f9SRussell King 2869da91a8f9SRussell King if (enable) 28704d55c5a1SArindam Nath ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; 2871da91a8f9SRussell King else 28724d55c5a1SArindam Nath ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; 2873da91a8f9SRussell King 28744d55c5a1SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 2875da91a8f9SRussell King 2876da91a8f9SRussell King if (enable) 2877da91a8f9SRussell King host->flags |= SDHCI_PV_ENABLED; 2878da91a8f9SRussell King else 287966fd8ad5SAdrian Hunter host->flags &= ~SDHCI_PV_ENABLED; 2880da91a8f9SRussell King 2881da91a8f9SRussell King host->preset_enabled = enable; 28824d55c5a1SArindam Nath } 288366fd8ad5SAdrian Hunter } 288466fd8ad5SAdrian Hunter 2885348487cbSHaibo Chen static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, 2886348487cbSHaibo Chen int err) 2887348487cbSHaibo Chen { 2888348487cbSHaibo Chen struct sdhci_host *host = mmc_priv(mmc); 2889348487cbSHaibo Chen struct mmc_data *data = mrq->data; 2890348487cbSHaibo Chen 2891f48f039cSRussell King if (data->host_cookie != COOKIE_UNMAPPED) 2892348487cbSHaibo Chen dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 2893feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 2894771a3dc2SRussell King 2895d31911b9SHaibo Chen data->host_cookie = COOKIE_UNMAPPED; 2896348487cbSHaibo Chen } 2897348487cbSHaibo Chen 2898d3c6aac3SLinus Walleij static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) 2899348487cbSHaibo Chen { 2900348487cbSHaibo Chen struct sdhci_host *host = mmc_priv(mmc); 2901348487cbSHaibo Chen 2902d31911b9SHaibo Chen mrq->data->host_cookie = COOKIE_UNMAPPED; 2903348487cbSHaibo Chen 2904bd9b9027SLinus Walleij /* 2905bd9b9027SLinus Walleij * No pre-mapping in the pre hook if we're using the bounce buffer, 2906bd9b9027SLinus Walleij * for that we would need two bounce buffers since one buffer is 2907bd9b9027SLinus Walleij * in flight when this is getting called. 2908bd9b9027SLinus Walleij */ 2909bd9b9027SLinus Walleij if (host->flags & SDHCI_REQ_USE_DMA && !host->bounce_buffer) 291094538e51SRussell King sdhci_pre_dma_transfer(host, mrq->data, COOKIE_PRE_MAPPED); 2911348487cbSHaibo Chen } 2912348487cbSHaibo Chen 29135d0d11c5SAdrian Hunter static void sdhci_error_out_mrqs(struct sdhci_host *host, int err) 29145d0d11c5SAdrian Hunter { 29155d0d11c5SAdrian Hunter if (host->data_cmd) { 29165d0d11c5SAdrian Hunter host->data_cmd->error = err; 29175d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq); 29185d0d11c5SAdrian Hunter } 29195d0d11c5SAdrian Hunter 29205d0d11c5SAdrian Hunter if (host->cmd) { 29215d0d11c5SAdrian Hunter host->cmd->error = err; 29225d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 29235d0d11c5SAdrian Hunter } 29245d0d11c5SAdrian Hunter } 29255d0d11c5SAdrian Hunter 292671e69211SGuennadi Liakhovetski static void sdhci_card_event(struct mmc_host *mmc) 29271c6a0718SPierre Ossman { 292871e69211SGuennadi Liakhovetski struct sdhci_host *host = mmc_priv(mmc); 29291c6a0718SPierre Ossman unsigned long flags; 29302836766aSKrzysztof Kozlowski int present; 29311c6a0718SPierre Ossman 2932722e1280SChristian Daudt /* First check if client has provided their own card event */ 2933722e1280SChristian Daudt if (host->ops->card_event) 2934722e1280SChristian Daudt host->ops->card_event(host); 2935722e1280SChristian Daudt 2936d3940f27SAdrian Hunter present = mmc->ops->get_cd(mmc); 29372836766aSKrzysztof Kozlowski 29381c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 29391c6a0718SPierre Ossman 29405d0d11c5SAdrian Hunter /* Check sdhci_has_requests() first in case we are runtime suspended */ 29415d0d11c5SAdrian Hunter if (sdhci_has_requests(host) && !present) { 2942a3c76eb9SGirish K S pr_err("%s: Card removed during transfer!\n", 29431c6a0718SPierre Ossman mmc_hostname(host->mmc)); 2944a3c76eb9SGirish K S pr_err("%s: Resetting controller.\n", 29451c6a0718SPierre Ossman mmc_hostname(host->mmc)); 29461c6a0718SPierre Ossman 294703231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_CMD); 294803231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_DATA); 29491c6a0718SPierre Ossman 29505d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM); 29511c6a0718SPierre Ossman } 29521c6a0718SPierre Ossman 29531c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 295471e69211SGuennadi Liakhovetski } 295571e69211SGuennadi Liakhovetski 295671e69211SGuennadi Liakhovetski static const struct mmc_host_ops sdhci_ops = { 295771e69211SGuennadi Liakhovetski .request = sdhci_request, 2958348487cbSHaibo Chen .post_req = sdhci_post_req, 2959348487cbSHaibo Chen .pre_req = sdhci_pre_req, 296071e69211SGuennadi Liakhovetski .set_ios = sdhci_set_ios, 296194144a46SKevin Liu .get_cd = sdhci_get_cd, 296271e69211SGuennadi Liakhovetski .get_ro = sdhci_get_ro, 296371e69211SGuennadi Liakhovetski .hw_reset = sdhci_hw_reset, 296471e69211SGuennadi Liakhovetski .enable_sdio_irq = sdhci_enable_sdio_irq, 296589f3c365SAdrian Hunter .ack_sdio_irq = sdhci_ack_sdio_irq, 296671e69211SGuennadi Liakhovetski .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, 2967b5540ce1SAdrian Hunter .prepare_hs400_tuning = sdhci_prepare_hs400_tuning, 296871e69211SGuennadi Liakhovetski .execute_tuning = sdhci_execute_tuning, 296971e69211SGuennadi Liakhovetski .card_event = sdhci_card_event, 297020b92a30SKevin Liu .card_busy = sdhci_card_busy, 297171e69211SGuennadi Liakhovetski }; 297271e69211SGuennadi Liakhovetski 297371e69211SGuennadi Liakhovetski /*****************************************************************************\ 297471e69211SGuennadi Liakhovetski * * 2975c07a48c2SAdrian Hunter * Request done * 297671e69211SGuennadi Liakhovetski * * 297771e69211SGuennadi Liakhovetski \*****************************************************************************/ 297871e69211SGuennadi Liakhovetski 29794e9f8fe5SAdrian Hunter static bool sdhci_request_done(struct sdhci_host *host) 29801c6a0718SPierre Ossman { 29811c6a0718SPierre Ossman unsigned long flags; 29821c6a0718SPierre Ossman struct mmc_request *mrq; 29834e9f8fe5SAdrian Hunter int i; 29841c6a0718SPierre Ossman 298566fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 298666fd8ad5SAdrian Hunter 29874e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 29884e9f8fe5SAdrian Hunter mrq = host->mrqs_done[i]; 29896ebebeabSAdrian Hunter if (mrq) 29904e9f8fe5SAdrian Hunter break; 29914e9f8fe5SAdrian Hunter } 29921c6a0718SPierre Ossman 29934e9f8fe5SAdrian Hunter if (!mrq) { 29944e9f8fe5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 29954e9f8fe5SAdrian Hunter return true; 29964e9f8fe5SAdrian Hunter } 29971c6a0718SPierre Ossman 29981c6a0718SPierre Ossman /* 2999054cedffSRussell King * Always unmap the data buffers if they were mapped by 3000054cedffSRussell King * sdhci_prepare_data() whenever we finish with a request. 3001054cedffSRussell King * This avoids leaking DMA mappings on error. 3002054cedffSRussell King */ 3003054cedffSRussell King if (host->flags & SDHCI_REQ_USE_DMA) { 3004054cedffSRussell King struct mmc_data *data = mrq->data; 3005054cedffSRussell King 300618e762e3SChunyan Zhang if (host->use_external_dma && data && 300718e762e3SChunyan Zhang (mrq->cmd->error || data->error)) { 300818e762e3SChunyan Zhang struct dma_chan *chan = sdhci_external_dma_channel(host, data); 300918e762e3SChunyan Zhang 301018e762e3SChunyan Zhang host->mrqs_done[i] = NULL; 301118e762e3SChunyan Zhang spin_unlock_irqrestore(&host->lock, flags); 301218e762e3SChunyan Zhang dmaengine_terminate_sync(chan); 301318e762e3SChunyan Zhang spin_lock_irqsave(&host->lock, flags); 301418e762e3SChunyan Zhang sdhci_set_mrq_done(host, mrq); 301518e762e3SChunyan Zhang } 301618e762e3SChunyan Zhang 3017054cedffSRussell King if (data && data->host_cookie == COOKIE_MAPPED) { 3018bd9b9027SLinus Walleij if (host->bounce_buffer) { 3019bd9b9027SLinus Walleij /* 3020bd9b9027SLinus Walleij * On reads, copy the bounced data into the 3021bd9b9027SLinus Walleij * sglist 3022bd9b9027SLinus Walleij */ 3023bd9b9027SLinus Walleij if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) { 3024bd9b9027SLinus Walleij unsigned int length = data->bytes_xfered; 3025bd9b9027SLinus Walleij 3026bd9b9027SLinus Walleij if (length > host->bounce_buffer_size) { 3027bd9b9027SLinus Walleij pr_err("%s: bounce buffer is %u bytes but DMA claims to have transferred %u bytes\n", 3028bd9b9027SLinus Walleij mmc_hostname(host->mmc), 3029bd9b9027SLinus Walleij host->bounce_buffer_size, 3030bd9b9027SLinus Walleij data->bytes_xfered); 3031bd9b9027SLinus Walleij /* Cap it down and continue */ 3032bd9b9027SLinus Walleij length = host->bounce_buffer_size; 3033bd9b9027SLinus Walleij } 3034bd9b9027SLinus Walleij dma_sync_single_for_cpu( 3035bd9b9027SLinus Walleij host->mmc->parent, 3036bd9b9027SLinus Walleij host->bounce_addr, 3037bd9b9027SLinus Walleij host->bounce_buffer_size, 3038bd9b9027SLinus Walleij DMA_FROM_DEVICE); 3039bd9b9027SLinus Walleij sg_copy_from_buffer(data->sg, 3040bd9b9027SLinus Walleij data->sg_len, 3041bd9b9027SLinus Walleij host->bounce_buffer, 3042bd9b9027SLinus Walleij length); 3043bd9b9027SLinus Walleij } else { 3044bd9b9027SLinus Walleij /* No copying, just switch ownership */ 3045bd9b9027SLinus Walleij dma_sync_single_for_cpu( 3046bd9b9027SLinus Walleij host->mmc->parent, 3047bd9b9027SLinus Walleij host->bounce_addr, 3048bd9b9027SLinus Walleij host->bounce_buffer_size, 3049feeef096SHeiner Kallweit mmc_get_dma_dir(data)); 3050bd9b9027SLinus Walleij } 3051bd9b9027SLinus Walleij } else { 3052bd9b9027SLinus Walleij /* Unmap the raw data */ 3053bd9b9027SLinus Walleij dma_unmap_sg(mmc_dev(host->mmc), data->sg, 3054bd9b9027SLinus Walleij data->sg_len, 3055bd9b9027SLinus Walleij mmc_get_dma_dir(data)); 3056bd9b9027SLinus Walleij } 3057054cedffSRussell King data->host_cookie = COOKIE_UNMAPPED; 3058054cedffSRussell King } 3059054cedffSRussell King } 3060054cedffSRussell King 3061054cedffSRussell King /* 30621c6a0718SPierre Ossman * The controller needs a reset of internal state machines 30631c6a0718SPierre Ossman * upon error conditions. 30641c6a0718SPierre Ossman */ 30650cc563ceSAdrian Hunter if (sdhci_needs_reset(host, mrq)) { 30666ebebeabSAdrian Hunter /* 30676ebebeabSAdrian Hunter * Do not finish until command and data lines are available for 30686ebebeabSAdrian Hunter * reset. Note there can only be one other mrq, so it cannot 30696ebebeabSAdrian Hunter * also be in mrqs_done, otherwise host->cmd and host->data_cmd 30706ebebeabSAdrian Hunter * would both be null. 30716ebebeabSAdrian Hunter */ 30726ebebeabSAdrian Hunter if (host->cmd || host->data_cmd) { 30736ebebeabSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 30746ebebeabSAdrian Hunter return true; 30756ebebeabSAdrian Hunter } 30766ebebeabSAdrian Hunter 30771c6a0718SPierre Ossman /* Some controllers need this kick or reset won't work here */ 30788213af3bSAndy Shevchenko if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) 30791c6a0718SPierre Ossman /* This is to force an update */ 30801771059cSRussell King host->ops->set_clock(host, host->clock); 30811c6a0718SPierre Ossman 30821c6a0718SPierre Ossman /* Spec says we should do both at the same time, but Ricoh 30831c6a0718SPierre Ossman controllers do not like that. */ 308403231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_CMD); 308503231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_DATA); 3086ed1563deSAdrian Hunter 3087ed1563deSAdrian Hunter host->pending_reset = false; 30881c6a0718SPierre Ossman } 30891c6a0718SPierre Ossman 30906ebebeabSAdrian Hunter host->mrqs_done[i] = NULL; 30916ebebeabSAdrian Hunter 30921c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 30931c6a0718SPierre Ossman 30941774b002SBaolin Wang if (host->ops->request_done) 30951774b002SBaolin Wang host->ops->request_done(host, mrq); 30961774b002SBaolin Wang else 30971c6a0718SPierre Ossman mmc_request_done(host->mmc, mrq); 30984e9f8fe5SAdrian Hunter 30994e9f8fe5SAdrian Hunter return false; 31004e9f8fe5SAdrian Hunter } 31014e9f8fe5SAdrian Hunter 3102c07a48c2SAdrian Hunter static void sdhci_complete_work(struct work_struct *work) 31034e9f8fe5SAdrian Hunter { 3104c07a48c2SAdrian Hunter struct sdhci_host *host = container_of(work, struct sdhci_host, 3105c07a48c2SAdrian Hunter complete_work); 31064e9f8fe5SAdrian Hunter 31074e9f8fe5SAdrian Hunter while (!sdhci_request_done(host)) 31084e9f8fe5SAdrian Hunter ; 31091c6a0718SPierre Ossman } 31101c6a0718SPierre Ossman 31112ee4f620SKees Cook static void sdhci_timeout_timer(struct timer_list *t) 31121c6a0718SPierre Ossman { 31131c6a0718SPierre Ossman struct sdhci_host *host; 31141c6a0718SPierre Ossman unsigned long flags; 31151c6a0718SPierre Ossman 31162ee4f620SKees Cook host = from_timer(host, t, timer); 31171c6a0718SPierre Ossman 31181c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 31191c6a0718SPierre Ossman 3120d7422fb4SAdrian Hunter if (host->cmd && !sdhci_data_line_cmd(host->cmd)) { 3121d7422fb4SAdrian Hunter pr_err("%s: Timeout waiting for hardware cmd interrupt.\n", 3122d7422fb4SAdrian Hunter mmc_hostname(host->mmc)); 3123d7422fb4SAdrian Hunter sdhci_dumpregs(host); 3124d7422fb4SAdrian Hunter 3125d7422fb4SAdrian Hunter host->cmd->error = -ETIMEDOUT; 3126d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 3127d7422fb4SAdrian Hunter } 3128d7422fb4SAdrian Hunter 3129d7422fb4SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3130d7422fb4SAdrian Hunter } 3131d7422fb4SAdrian Hunter 31322ee4f620SKees Cook static void sdhci_timeout_data_timer(struct timer_list *t) 3133d7422fb4SAdrian Hunter { 3134d7422fb4SAdrian Hunter struct sdhci_host *host; 3135d7422fb4SAdrian Hunter unsigned long flags; 3136d7422fb4SAdrian Hunter 31372ee4f620SKees Cook host = from_timer(host, t, data_timer); 3138d7422fb4SAdrian Hunter 3139d7422fb4SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3140d7422fb4SAdrian Hunter 3141d7422fb4SAdrian Hunter if (host->data || host->data_cmd || 3142d7422fb4SAdrian Hunter (host->cmd && sdhci_data_line_cmd(host->cmd))) { 31432e4456f0SMarek Vasut pr_err("%s: Timeout waiting for hardware interrupt.\n", 31442e4456f0SMarek Vasut mmc_hostname(host->mmc)); 31451c6a0718SPierre Ossman sdhci_dumpregs(host); 31461c6a0718SPierre Ossman 31471c6a0718SPierre Ossman if (host->data) { 314817b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 3149845c939eSAdrian Hunter __sdhci_finish_data(host, true); 3150c07a48c2SAdrian Hunter queue_work(host->complete_wq, &host->complete_work); 3151d7422fb4SAdrian Hunter } else if (host->data_cmd) { 3152d7422fb4SAdrian Hunter host->data_cmd->error = -ETIMEDOUT; 3153d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq); 31541c6a0718SPierre Ossman } else { 315517b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 3156d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq); 31571c6a0718SPierre Ossman } 31581c6a0718SPierre Ossman } 31591c6a0718SPierre Ossman 31601c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 31611c6a0718SPierre Ossman } 31621c6a0718SPierre Ossman 31631c6a0718SPierre Ossman /*****************************************************************************\ 31641c6a0718SPierre Ossman * * 31651c6a0718SPierre Ossman * Interrupt handling * 31661c6a0718SPierre Ossman * * 31671c6a0718SPierre Ossman \*****************************************************************************/ 31681c6a0718SPierre Ossman 31694bf78099SAdrian Hunter static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) 31701c6a0718SPierre Ossman { 3171af849c86SAdrian Hunter /* Handle auto-CMD12 error */ 3172af849c86SAdrian Hunter if (intmask & SDHCI_INT_AUTO_CMD_ERR && host->data_cmd) { 3173af849c86SAdrian Hunter struct mmc_request *mrq = host->data_cmd->mrq; 3174af849c86SAdrian Hunter u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); 3175af849c86SAdrian Hunter int data_err_bit = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? 3176af849c86SAdrian Hunter SDHCI_INT_DATA_TIMEOUT : 3177af849c86SAdrian Hunter SDHCI_INT_DATA_CRC; 3178af849c86SAdrian Hunter 3179af849c86SAdrian Hunter /* Treat auto-CMD12 error the same as data error */ 3180af849c86SAdrian Hunter if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) { 3181af849c86SAdrian Hunter *intmask_p |= data_err_bit; 3182af849c86SAdrian Hunter return; 3183af849c86SAdrian Hunter } 3184af849c86SAdrian Hunter } 3185af849c86SAdrian Hunter 31861c6a0718SPierre Ossman if (!host->cmd) { 3187ed1563deSAdrian Hunter /* 3188ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data 3189ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more 3190ed1563deSAdrian Hunter * interrupts, so ignore them in that case. 3191ed1563deSAdrian Hunter */ 3192ed1563deSAdrian Hunter if (host->pending_reset) 3193ed1563deSAdrian Hunter return; 31942e4456f0SMarek Vasut pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", 3195b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 31961c6a0718SPierre Ossman sdhci_dumpregs(host); 31971c6a0718SPierre Ossman return; 31981c6a0718SPierre Ossman } 31991c6a0718SPierre Ossman 3200ec014cbaSRussell King if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | 3201ec014cbaSRussell King SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { 32021c6a0718SPierre Ossman if (intmask & SDHCI_INT_TIMEOUT) 320317b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT; 3204ec014cbaSRussell King else 320517b0429dSPierre Ossman host->cmd->error = -EILSEQ; 32061c6a0718SPierre Ossman 32074bf78099SAdrian Hunter /* Treat data command CRC error the same as data CRC error */ 320871fcbda0SRussell King if (host->cmd->data && 320971fcbda0SRussell King (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == 321071fcbda0SRussell King SDHCI_INT_CRC) { 321171fcbda0SRussell King host->cmd = NULL; 32124bf78099SAdrian Hunter *intmask_p |= SDHCI_INT_DATA_CRC; 321371fcbda0SRussell King return; 321471fcbda0SRussell King } 321571fcbda0SRussell King 321619d2f695SAdrian Hunter __sdhci_finish_mrq(host, host->cmd->mrq); 3217e809517fSPierre Ossman return; 3218e809517fSPierre Ossman } 3219e809517fSPierre Ossman 3220af849c86SAdrian Hunter /* Handle auto-CMD23 error */ 3221af849c86SAdrian Hunter if (intmask & SDHCI_INT_AUTO_CMD_ERR) { 3222af849c86SAdrian Hunter struct mmc_request *mrq = host->cmd->mrq; 3223af849c86SAdrian Hunter u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); 3224af849c86SAdrian Hunter int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? 3225af849c86SAdrian Hunter -ETIMEDOUT : 3226af849c86SAdrian Hunter -EILSEQ; 3227af849c86SAdrian Hunter 3228af849c86SAdrian Hunter if (mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { 3229af849c86SAdrian Hunter mrq->sbc->error = err; 323019d2f695SAdrian Hunter __sdhci_finish_mrq(host, mrq); 3231af849c86SAdrian Hunter return; 3232af849c86SAdrian Hunter } 3233af849c86SAdrian Hunter } 3234af849c86SAdrian Hunter 3235e809517fSPierre Ossman if (intmask & SDHCI_INT_RESPONSE) 323643b58b36SPierre Ossman sdhci_finish_command(host); 32371c6a0718SPierre Ossman } 32381c6a0718SPierre Ossman 323908621b18SAdrian Hunter static void sdhci_adma_show_error(struct sdhci_host *host) 32406882a8c0SBen Dooks { 32411c3d5f6dSAdrian Hunter void *desc = host->adma_table; 3242d1c536e3SRussell King dma_addr_t dma = host->adma_addr; 32436882a8c0SBen Dooks 32446882a8c0SBen Dooks sdhci_dumpregs(host); 32456882a8c0SBen Dooks 32466882a8c0SBen Dooks while (true) { 3247e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc; 32486882a8c0SBen Dooks 3249e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) 3250d1c536e3SRussell King SDHCI_DUMP("%08llx: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", 3251d1c536e3SRussell King (unsigned long long)dma, 3252d1c536e3SRussell King le32_to_cpu(dma_desc->addr_hi), 3253e57a5f61SAdrian Hunter le32_to_cpu(dma_desc->addr_lo), 3254e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->len), 3255e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->cmd)); 3256e57a5f61SAdrian Hunter else 3257d1c536e3SRussell King SDHCI_DUMP("%08llx: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", 3258d1c536e3SRussell King (unsigned long long)dma, 3259d1c536e3SRussell King le32_to_cpu(dma_desc->addr_lo), 32600545230fSAdrian Hunter le16_to_cpu(dma_desc->len), 32610545230fSAdrian Hunter le16_to_cpu(dma_desc->cmd)); 32626882a8c0SBen Dooks 326376fe379aSAdrian Hunter desc += host->desc_sz; 3264d1c536e3SRussell King dma += host->desc_sz; 32656882a8c0SBen Dooks 32660545230fSAdrian Hunter if (dma_desc->cmd & cpu_to_le16(ADMA2_END)) 32676882a8c0SBen Dooks break; 32686882a8c0SBen Dooks } 32696882a8c0SBen Dooks } 32706882a8c0SBen Dooks 32711c6a0718SPierre Ossman static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 32721c6a0718SPierre Ossman { 3273069c9f14SGirish K S u32 command; 32741c6a0718SPierre Ossman 3275b513ea25SArindam Nath /* CMD19 generates _only_ Buffer Read Ready interrupt */ 3276b513ea25SArindam Nath if (intmask & SDHCI_INT_DATA_AVAIL) { 3277069c9f14SGirish K S command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)); 3278069c9f14SGirish K S if (command == MMC_SEND_TUNING_BLOCK || 3279069c9f14SGirish K S command == MMC_SEND_TUNING_BLOCK_HS200) { 3280b513ea25SArindam Nath host->tuning_done = 1; 3281b513ea25SArindam Nath wake_up(&host->buf_ready_int); 3282b513ea25SArindam Nath return; 3283b513ea25SArindam Nath } 3284b513ea25SArindam Nath } 3285b513ea25SArindam Nath 32861c6a0718SPierre Ossman if (!host->data) { 32877c89a3d9SAdrian Hunter struct mmc_command *data_cmd = host->data_cmd; 32887c89a3d9SAdrian Hunter 32891c6a0718SPierre Ossman /* 3290e809517fSPierre Ossman * The "data complete" interrupt is also used to 3291e809517fSPierre Ossman * indicate that a busy state has ended. See comment 3292e809517fSPierre Ossman * above in sdhci_cmd_irq(). 32931c6a0718SPierre Ossman */ 32947c89a3d9SAdrian Hunter if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) { 3295c5abd5e8SMatthieu CASTET if (intmask & SDHCI_INT_DATA_TIMEOUT) { 329669b962a6SAdrian Hunter host->data_cmd = NULL; 32977c89a3d9SAdrian Hunter data_cmd->error = -ETIMEDOUT; 329819d2f695SAdrian Hunter __sdhci_finish_mrq(host, data_cmd->mrq); 3299c5abd5e8SMatthieu CASTET return; 3300c5abd5e8SMatthieu CASTET } 3301e809517fSPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 330269b962a6SAdrian Hunter host->data_cmd = NULL; 3303e99783a4SChanho Min /* 3304e99783a4SChanho Min * Some cards handle busy-end interrupt 3305e99783a4SChanho Min * before the command completed, so make 3306e99783a4SChanho Min * sure we do things in the proper order. 3307e99783a4SChanho Min */ 3308ea968023SAdrian Hunter if (host->cmd == data_cmd) 3309ea968023SAdrian Hunter return; 3310ea968023SAdrian Hunter 331119d2f695SAdrian Hunter __sdhci_finish_mrq(host, data_cmd->mrq); 33121c6a0718SPierre Ossman return; 3313e809517fSPierre Ossman } 3314e809517fSPierre Ossman } 33151c6a0718SPierre Ossman 3316ed1563deSAdrian Hunter /* 3317ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data 3318ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more 3319ed1563deSAdrian Hunter * interrupts, so ignore them in that case. 3320ed1563deSAdrian Hunter */ 3321ed1563deSAdrian Hunter if (host->pending_reset) 3322ed1563deSAdrian Hunter return; 3323ed1563deSAdrian Hunter 33242e4456f0SMarek Vasut pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n", 3325b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask); 33261c6a0718SPierre Ossman sdhci_dumpregs(host); 33271c6a0718SPierre Ossman 33281c6a0718SPierre Ossman return; 33291c6a0718SPierre Ossman } 33301c6a0718SPierre Ossman 33311c6a0718SPierre Ossman if (intmask & SDHCI_INT_DATA_TIMEOUT) 333217b0429dSPierre Ossman host->data->error = -ETIMEDOUT; 333322113efdSAries Lee else if (intmask & SDHCI_INT_DATA_END_BIT) 333422113efdSAries Lee host->data->error = -EILSEQ; 333522113efdSAries Lee else if ((intmask & SDHCI_INT_DATA_CRC) && 333622113efdSAries Lee SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) 333722113efdSAries Lee != MMC_BUS_TEST_R) 333817b0429dSPierre Ossman host->data->error = -EILSEQ; 33396882a8c0SBen Dooks else if (intmask & SDHCI_INT_ADMA_ERROR) { 3340d1c536e3SRussell King pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), 3341d1c536e3SRussell King intmask); 334208621b18SAdrian Hunter sdhci_adma_show_error(host); 33432134a922SPierre Ossman host->data->error = -EIO; 3344a4071fbbSHaijun Zhang if (host->ops->adma_workaround) 3345a4071fbbSHaijun Zhang host->ops->adma_workaround(host, intmask); 33466882a8c0SBen Dooks } 33471c6a0718SPierre Ossman 334817b0429dSPierre Ossman if (host->data->error) 33491c6a0718SPierre Ossman sdhci_finish_data(host); 33501c6a0718SPierre Ossman else { 33511c6a0718SPierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) 33521c6a0718SPierre Ossman sdhci_transfer_pio(host); 33531c6a0718SPierre Ossman 33546ba736a1SPierre Ossman /* 33556ba736a1SPierre Ossman * We currently don't do anything fancy with DMA 33566ba736a1SPierre Ossman * boundaries, but as we can't disable the feature 33576ba736a1SPierre Ossman * we need to at least restart the transfer. 3358f6a03cbfSMikko Vinni * 3359f6a03cbfSMikko Vinni * According to the spec sdhci_readl(host, SDHCI_DMA_ADDRESS) 3360f6a03cbfSMikko Vinni * should return a valid address to continue from, but as 3361f6a03cbfSMikko Vinni * some controllers are faulty, don't trust them. 33626ba736a1SPierre Ossman */ 3363f6a03cbfSMikko Vinni if (intmask & SDHCI_INT_DMA_END) { 3364917a0c52SChunyan Zhang dma_addr_t dmastart, dmanow; 3365bd9b9027SLinus Walleij 3366bd9b9027SLinus Walleij dmastart = sdhci_sdma_address(host); 3367f6a03cbfSMikko Vinni dmanow = dmastart + host->data->bytes_xfered; 3368f6a03cbfSMikko Vinni /* 3369f6a03cbfSMikko Vinni * Force update to the next DMA block boundary. 3370f6a03cbfSMikko Vinni */ 3371f6a03cbfSMikko Vinni dmanow = (dmanow & 3372917a0c52SChunyan Zhang ~((dma_addr_t)SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 3373f6a03cbfSMikko Vinni SDHCI_DEFAULT_BOUNDARY_SIZE; 3374f6a03cbfSMikko Vinni host->data->bytes_xfered = dmanow - dmastart; 3375917a0c52SChunyan Zhang DBG("DMA base %pad, transferred 0x%06x bytes, next %pad\n", 3376917a0c52SChunyan Zhang &dmastart, host->data->bytes_xfered, &dmanow); 3377917a0c52SChunyan Zhang sdhci_set_sdma_addr(host, dmanow); 3378f6a03cbfSMikko Vinni } 33796ba736a1SPierre Ossman 3380e538fbe8SPierre Ossman if (intmask & SDHCI_INT_DATA_END) { 33817c89a3d9SAdrian Hunter if (host->cmd == host->data_cmd) { 3382e538fbe8SPierre Ossman /* 3383e538fbe8SPierre Ossman * Data managed to finish before the 3384e538fbe8SPierre Ossman * command completed. Make sure we do 3385e538fbe8SPierre Ossman * things in the proper order. 3386e538fbe8SPierre Ossman */ 3387e538fbe8SPierre Ossman host->data_early = 1; 3388e538fbe8SPierre Ossman } else { 33891c6a0718SPierre Ossman sdhci_finish_data(host); 33901c6a0718SPierre Ossman } 33911c6a0718SPierre Ossman } 3392e538fbe8SPierre Ossman } 3393e538fbe8SPierre Ossman } 33941c6a0718SPierre Ossman 339519d2f695SAdrian Hunter static inline bool sdhci_defer_done(struct sdhci_host *host, 339619d2f695SAdrian Hunter struct mmc_request *mrq) 339719d2f695SAdrian Hunter { 339819d2f695SAdrian Hunter struct mmc_data *data = mrq->data; 339919d2f695SAdrian Hunter 34004730831cSBaolin Wang return host->pending_reset || host->always_defer_done || 340119d2f695SAdrian Hunter ((host->flags & SDHCI_REQ_USE_DMA) && data && 340219d2f695SAdrian Hunter data->host_cookie == COOKIE_MAPPED); 340319d2f695SAdrian Hunter } 340419d2f695SAdrian Hunter 34051c6a0718SPierre Ossman static irqreturn_t sdhci_irq(int irq, void *dev_id) 34061c6a0718SPierre Ossman { 340719d2f695SAdrian Hunter struct mmc_request *mrqs_done[SDHCI_MAX_MRQS] = {0}; 3408781e989cSRussell King irqreturn_t result = IRQ_NONE; 34091c6a0718SPierre Ossman struct sdhci_host *host = dev_id; 341041005003SRussell King u32 intmask, mask, unexpected = 0; 3411781e989cSRussell King int max_loops = 16; 341219d2f695SAdrian Hunter int i; 34131c6a0718SPierre Ossman 34141c6a0718SPierre Ossman spin_lock(&host->lock); 34151c6a0718SPierre Ossman 3416af5d2b7bSUlf Hansson if (host->runtime_suspended) { 341766fd8ad5SAdrian Hunter spin_unlock(&host->lock); 3418655bca76SAdrian Hunter return IRQ_NONE; 341966fd8ad5SAdrian Hunter } 342066fd8ad5SAdrian Hunter 34214e4141a5SAnton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS); 34221c6a0718SPierre Ossman if (!intmask || intmask == 0xffffffff) { 34231c6a0718SPierre Ossman result = IRQ_NONE; 34241c6a0718SPierre Ossman goto out; 34251c6a0718SPierre Ossman } 34261c6a0718SPierre Ossman 342741005003SRussell King do { 3428f12e39dbSAdrian Hunter DBG("IRQ status 0x%08x\n", intmask); 3429f12e39dbSAdrian Hunter 3430f12e39dbSAdrian Hunter if (host->ops->irq) { 3431f12e39dbSAdrian Hunter intmask = host->ops->irq(host, intmask); 3432f12e39dbSAdrian Hunter if (!intmask) 3433f12e39dbSAdrian Hunter goto cont; 3434f12e39dbSAdrian Hunter } 3435f12e39dbSAdrian Hunter 343641005003SRussell King /* Clear selected interrupts. */ 343741005003SRussell King mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 343841005003SRussell King SDHCI_INT_BUS_POWER); 343941005003SRussell King sdhci_writel(host, mask, SDHCI_INT_STATUS); 344041005003SRussell King 34411c6a0718SPierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 3442d25928d1SShawn Guo u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) & 3443d25928d1SShawn Guo SDHCI_CARD_PRESENT; 3444d25928d1SShawn Guo 3445d25928d1SShawn Guo /* 344641005003SRussell King * There is a observation on i.mx esdhc. INSERT 344741005003SRussell King * bit will be immediately set again when it gets 344841005003SRussell King * cleared, if a card is inserted. We have to mask 344941005003SRussell King * the irq to prevent interrupt storm which will 345041005003SRussell King * freeze the system. And the REMOVE gets the 345141005003SRussell King * same situation. 3452d25928d1SShawn Guo * 345341005003SRussell King * More testing are needed here to ensure it works 345441005003SRussell King * for other platforms though. 3455d25928d1SShawn Guo */ 3456b537f94cSRussell King host->ier &= ~(SDHCI_INT_CARD_INSERT | 3457d25928d1SShawn Guo SDHCI_INT_CARD_REMOVE); 3458b537f94cSRussell King host->ier |= present ? SDHCI_INT_CARD_REMOVE : 3459b537f94cSRussell King SDHCI_INT_CARD_INSERT; 3460b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3461b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 3462d25928d1SShawn Guo 34634e4141a5SAnton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | 34644e4141a5SAnton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); 34653560db8eSRussell King 34663560db8eSRussell King host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT | 34673560db8eSRussell King SDHCI_INT_CARD_REMOVE); 34683560db8eSRussell King result = IRQ_WAKE_THREAD; 34691c6a0718SPierre Ossman } 34701c6a0718SPierre Ossman 347141005003SRussell King if (intmask & SDHCI_INT_CMD_MASK) 34724bf78099SAdrian Hunter sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask); 34731c6a0718SPierre Ossman 347441005003SRussell King if (intmask & SDHCI_INT_DATA_MASK) 34751c6a0718SPierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); 34761c6a0718SPierre Ossman 347741005003SRussell King if (intmask & SDHCI_INT_BUS_POWER) 3478a3c76eb9SGirish K S pr_err("%s: Card is consuming too much power!\n", 34791c6a0718SPierre Ossman mmc_hostname(host->mmc)); 34801c6a0718SPierre Ossman 3481f37b20ebSDong Aisheng if (intmask & SDHCI_INT_RETUNE) 3482f37b20ebSDong Aisheng mmc_retune_needed(host->mmc); 3483f37b20ebSDong Aisheng 3484161e6d44SGabriel Krisman Bertazi if ((intmask & SDHCI_INT_CARD_INT) && 3485161e6d44SGabriel Krisman Bertazi (host->ier & SDHCI_INT_CARD_INT)) { 3486781e989cSRussell King sdhci_enable_sdio_irq_nolock(host, false); 348789f3c365SAdrian Hunter sdio_signal_irq(host->mmc); 3488781e989cSRussell King } 3489f75979b7SPierre Ossman 349041005003SRussell King intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | 349141005003SRussell King SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 349241005003SRussell King SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | 3493f37b20ebSDong Aisheng SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT); 3494f75979b7SPierre Ossman 34951c6a0718SPierre Ossman if (intmask) { 34966379b237SAlexander Stein unexpected |= intmask; 34974e4141a5SAnton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS); 34981c6a0718SPierre Ossman } 3499f12e39dbSAdrian Hunter cont: 3500781e989cSRussell King if (result == IRQ_NONE) 35011c6a0718SPierre Ossman result = IRQ_HANDLED; 35021c6a0718SPierre Ossman 35036379b237SAlexander Stein intmask = sdhci_readl(host, SDHCI_INT_STATUS); 350441005003SRussell King } while (intmask && --max_loops); 350519d2f695SAdrian Hunter 350619d2f695SAdrian Hunter /* Determine if mrqs can be completed immediately */ 350719d2f695SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 350819d2f695SAdrian Hunter struct mmc_request *mrq = host->mrqs_done[i]; 350919d2f695SAdrian Hunter 351019d2f695SAdrian Hunter if (!mrq) 351119d2f695SAdrian Hunter continue; 351219d2f695SAdrian Hunter 351319d2f695SAdrian Hunter if (sdhci_defer_done(host, mrq)) { 3514c07a48c2SAdrian Hunter result = IRQ_WAKE_THREAD; 351519d2f695SAdrian Hunter } else { 351619d2f695SAdrian Hunter mrqs_done[i] = mrq; 351719d2f695SAdrian Hunter host->mrqs_done[i] = NULL; 351819d2f695SAdrian Hunter } 351919d2f695SAdrian Hunter } 35201c6a0718SPierre Ossman out: 3521845c939eSAdrian Hunter if (host->deferred_cmd) 3522845c939eSAdrian Hunter result = IRQ_WAKE_THREAD; 3523845c939eSAdrian Hunter 35241c6a0718SPierre Ossman spin_unlock(&host->lock); 35251c6a0718SPierre Ossman 352619d2f695SAdrian Hunter /* Process mrqs ready for immediate completion */ 352719d2f695SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) { 35281774b002SBaolin Wang if (!mrqs_done[i]) 35291774b002SBaolin Wang continue; 35301774b002SBaolin Wang 35311774b002SBaolin Wang if (host->ops->request_done) 35321774b002SBaolin Wang host->ops->request_done(host, mrqs_done[i]); 35331774b002SBaolin Wang else 353419d2f695SAdrian Hunter mmc_request_done(host->mmc, mrqs_done[i]); 353519d2f695SAdrian Hunter } 353619d2f695SAdrian Hunter 35376379b237SAlexander Stein if (unexpected) { 35386379b237SAlexander Stein pr_err("%s: Unexpected interrupt 0x%08x.\n", 35396379b237SAlexander Stein mmc_hostname(host->mmc), unexpected); 35406379b237SAlexander Stein sdhci_dumpregs(host); 35416379b237SAlexander Stein } 3542f75979b7SPierre Ossman 35431c6a0718SPierre Ossman return result; 35441c6a0718SPierre Ossman } 35451c6a0718SPierre Ossman 3546781e989cSRussell King static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) 3547781e989cSRussell King { 3548781e989cSRussell King struct sdhci_host *host = dev_id; 3549845c939eSAdrian Hunter struct mmc_command *cmd; 3550781e989cSRussell King unsigned long flags; 3551781e989cSRussell King u32 isr; 3552781e989cSRussell King 3553c07a48c2SAdrian Hunter while (!sdhci_request_done(host)) 3554c07a48c2SAdrian Hunter ; 3555c07a48c2SAdrian Hunter 3556781e989cSRussell King spin_lock_irqsave(&host->lock, flags); 3557845c939eSAdrian Hunter 3558781e989cSRussell King isr = host->thread_isr; 3559781e989cSRussell King host->thread_isr = 0; 3560845c939eSAdrian Hunter 3561845c939eSAdrian Hunter cmd = host->deferred_cmd; 3562845c939eSAdrian Hunter if (cmd && !sdhci_send_command_retry(host, cmd, flags)) 3563845c939eSAdrian Hunter sdhci_finish_mrq(host, cmd->mrq); 3564845c939eSAdrian Hunter 3565781e989cSRussell King spin_unlock_irqrestore(&host->lock, flags); 3566781e989cSRussell King 35673560db8eSRussell King if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 3568d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 3569d3940f27SAdrian Hunter 3570d3940f27SAdrian Hunter mmc->ops->card_event(mmc); 3571d3940f27SAdrian Hunter mmc_detect_change(mmc, msecs_to_jiffies(200)); 35723560db8eSRussell King } 35733560db8eSRussell King 3574c07a48c2SAdrian Hunter return IRQ_HANDLED; 3575781e989cSRussell King } 3576781e989cSRussell King 35771c6a0718SPierre Ossman /*****************************************************************************\ 35781c6a0718SPierre Ossman * * 35791c6a0718SPierre Ossman * Suspend/resume * 35801c6a0718SPierre Ossman * * 35811c6a0718SPierre Ossman \*****************************************************************************/ 35821c6a0718SPierre Ossman 35831c6a0718SPierre Ossman #ifdef CONFIG_PM 35849c316b38SAdrian Hunter 35859c316b38SAdrian Hunter static bool sdhci_cd_irq_can_wakeup(struct sdhci_host *host) 35869c316b38SAdrian Hunter { 35879c316b38SAdrian Hunter return mmc_card_is_removable(host->mmc) && 35889c316b38SAdrian Hunter !(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 35899c316b38SAdrian Hunter !mmc_can_gpio_cd(host->mmc); 35909c316b38SAdrian Hunter } 35919c316b38SAdrian Hunter 359284d62605SLudovic Desroches /* 359384d62605SLudovic Desroches * To enable wakeup events, the corresponding events have to be enabled in 359484d62605SLudovic Desroches * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal 359584d62605SLudovic Desroches * Table' in the SD Host Controller Standard Specification. 359684d62605SLudovic Desroches * It is useless to restore SDHCI_INT_ENABLE state in 359784d62605SLudovic Desroches * sdhci_disable_irq_wakeups() since it will be set by 359884d62605SLudovic Desroches * sdhci_enable_card_detection() or sdhci_init(). 359984d62605SLudovic Desroches */ 360058e79b60SAdrian Hunter static bool sdhci_enable_irq_wakeups(struct sdhci_host *host) 3601ad080d79SKevin Liu { 360281b14543SAdrian Hunter u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE | 360381b14543SAdrian Hunter SDHCI_WAKE_ON_INT; 360481b14543SAdrian Hunter u32 irq_val = 0; 360581b14543SAdrian Hunter u8 wake_val = 0; 3606ad080d79SKevin Liu u8 val; 360781b14543SAdrian Hunter 36089c316b38SAdrian Hunter if (sdhci_cd_irq_can_wakeup(host)) { 360981b14543SAdrian Hunter wake_val |= SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE; 361081b14543SAdrian Hunter irq_val |= SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE; 361181b14543SAdrian Hunter } 361281b14543SAdrian Hunter 3613d5d568faSAdrian Hunter if (mmc_card_wake_sdio_irq(host->mmc)) { 361481b14543SAdrian Hunter wake_val |= SDHCI_WAKE_ON_INT; 361581b14543SAdrian Hunter irq_val |= SDHCI_INT_CARD_INT; 3616d5d568faSAdrian Hunter } 3617d5d568faSAdrian Hunter 3618d5d568faSAdrian Hunter if (!irq_val) 3619d5d568faSAdrian Hunter return false; 3620ad080d79SKevin Liu 3621ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 362281b14543SAdrian Hunter val &= ~mask; 362381b14543SAdrian Hunter val |= wake_val; 3624ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 362581b14543SAdrian Hunter 362684d62605SLudovic Desroches sdhci_writel(host, irq_val, SDHCI_INT_ENABLE); 362758e79b60SAdrian Hunter 362858e79b60SAdrian Hunter host->irq_wake_enabled = !enable_irq_wake(host->irq); 362958e79b60SAdrian Hunter 363058e79b60SAdrian Hunter return host->irq_wake_enabled; 3631ad080d79SKevin Liu } 3632ad080d79SKevin Liu 36330b10f478SFabio Estevam static void sdhci_disable_irq_wakeups(struct sdhci_host *host) 3634ad080d79SKevin Liu { 3635ad080d79SKevin Liu u8 val; 3636ad080d79SKevin Liu u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE 3637ad080d79SKevin Liu | SDHCI_WAKE_ON_INT; 3638ad080d79SKevin Liu 3639ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); 3640ad080d79SKevin Liu val &= ~mask; 3641ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); 364258e79b60SAdrian Hunter 364358e79b60SAdrian Hunter disable_irq_wake(host->irq); 364458e79b60SAdrian Hunter 364558e79b60SAdrian Hunter host->irq_wake_enabled = false; 3646ad080d79SKevin Liu } 36471c6a0718SPierre Ossman 364829495aa0SManuel Lauss int sdhci_suspend_host(struct sdhci_host *host) 36491c6a0718SPierre Ossman { 36507260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 36517260cf5eSAnton Vorontsov 365266c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc); 3653cf2b5eeaSArindam Nath 365458e79b60SAdrian Hunter if (!device_may_wakeup(mmc_dev(host->mmc)) || 365558e79b60SAdrian Hunter !sdhci_enable_irq_wakeups(host)) { 3656b537f94cSRussell King host->ier = 0; 3657b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 3658b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 3659b8c86fc5SPierre Ossman free_irq(host->irq, host); 3660ad080d79SKevin Liu } 366158e79b60SAdrian Hunter 36624ee14ec6SUlf Hansson return 0; 3663b8c86fc5SPierre Ossman } 3664b8c86fc5SPierre Ossman 3665b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_suspend_host); 3666b8c86fc5SPierre Ossman 3667b8c86fc5SPierre Ossman int sdhci_resume_host(struct sdhci_host *host) 3668b8c86fc5SPierre Ossman { 3669d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 36704ee14ec6SUlf Hansson int ret = 0; 3671b8c86fc5SPierre Ossman 3672a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 3673b8c86fc5SPierre Ossman if (host->ops->enable_dma) 3674b8c86fc5SPierre Ossman host->ops->enable_dma(host); 3675b8c86fc5SPierre Ossman } 3676b8c86fc5SPierre Ossman 36776308d290SAdrian Hunter if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) && 36786308d290SAdrian Hunter (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) { 36796308d290SAdrian Hunter /* Card keeps power but host controller does not */ 36806308d290SAdrian Hunter sdhci_init(host, 0); 36816308d290SAdrian Hunter host->pwr = 0; 36826308d290SAdrian Hunter host->clock = 0; 3683d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 36846308d290SAdrian Hunter } else { 36852f4cbb3dSNicolas Pitre sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); 36866308d290SAdrian Hunter } 3687b8c86fc5SPierre Ossman 368858e79b60SAdrian Hunter if (host->irq_wake_enabled) { 368958e79b60SAdrian Hunter sdhci_disable_irq_wakeups(host); 369058e79b60SAdrian Hunter } else { 369114a7b416SHaibo Chen ret = request_threaded_irq(host->irq, sdhci_irq, 369214a7b416SHaibo Chen sdhci_thread_irq, IRQF_SHARED, 369314a7b416SHaibo Chen mmc_hostname(host->mmc), host); 369414a7b416SHaibo Chen if (ret) 369514a7b416SHaibo Chen return ret; 369614a7b416SHaibo Chen } 369714a7b416SHaibo Chen 36987260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 36997260cf5eSAnton Vorontsov 37002f4cbb3dSNicolas Pitre return ret; 37011c6a0718SPierre Ossman } 37021c6a0718SPierre Ossman 3703b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_resume_host); 370466fd8ad5SAdrian Hunter 370566fd8ad5SAdrian Hunter int sdhci_runtime_suspend_host(struct sdhci_host *host) 370666fd8ad5SAdrian Hunter { 370766fd8ad5SAdrian Hunter unsigned long flags; 370866fd8ad5SAdrian Hunter 370966c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc); 371066fd8ad5SAdrian Hunter 371166fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3712b537f94cSRussell King host->ier &= SDHCI_INT_CARD_INT; 3713b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3714b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 371566fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 371666fd8ad5SAdrian Hunter 3717781e989cSRussell King synchronize_hardirq(host->irq); 371866fd8ad5SAdrian Hunter 371966fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 372066fd8ad5SAdrian Hunter host->runtime_suspended = true; 372166fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 372266fd8ad5SAdrian Hunter 37238a125badSMarkus Pargmann return 0; 372466fd8ad5SAdrian Hunter } 372566fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host); 372666fd8ad5SAdrian Hunter 3727c6303c5dSBaolin Wang int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset) 372866fd8ad5SAdrian Hunter { 3729d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc; 373066fd8ad5SAdrian Hunter unsigned long flags; 37318a125badSMarkus Pargmann int host_flags = host->flags; 373266fd8ad5SAdrian Hunter 373366fd8ad5SAdrian Hunter if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 373466fd8ad5SAdrian Hunter if (host->ops->enable_dma) 373566fd8ad5SAdrian Hunter host->ops->enable_dma(host); 373666fd8ad5SAdrian Hunter } 373766fd8ad5SAdrian Hunter 3738c6303c5dSBaolin Wang sdhci_init(host, soft_reset); 373966fd8ad5SAdrian Hunter 374070bc85adSZhoujie Wu if (mmc->ios.power_mode != MMC_POWER_UNDEFINED && 374170bc85adSZhoujie Wu mmc->ios.power_mode != MMC_POWER_OFF) { 374266fd8ad5SAdrian Hunter /* Force clock and power re-program */ 374366fd8ad5SAdrian Hunter host->pwr = 0; 374466fd8ad5SAdrian Hunter host->clock = 0; 3745d3940f27SAdrian Hunter mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios); 3746d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios); 374766fd8ad5SAdrian Hunter 374852983382SKevin Liu if ((host_flags & SDHCI_PV_ENABLED) && 374952983382SKevin Liu !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { 375052983382SKevin Liu spin_lock_irqsave(&host->lock, flags); 375152983382SKevin Liu sdhci_enable_preset_value(host, true); 375252983382SKevin Liu spin_unlock_irqrestore(&host->lock, flags); 375352983382SKevin Liu } 375466fd8ad5SAdrian Hunter 3755086b0ddbSAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HS400_ES) && 3756086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe) 3757086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios); 375884ec048bSAdrian Hunter } 3759086b0ddbSAdrian Hunter 376066fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags); 376166fd8ad5SAdrian Hunter 376266fd8ad5SAdrian Hunter host->runtime_suspended = false; 376366fd8ad5SAdrian Hunter 376466fd8ad5SAdrian Hunter /* Enable SDIO IRQ */ 37650e62614bSUlf Hansson if (sdio_irq_claimed(mmc)) 376666fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true); 376766fd8ad5SAdrian Hunter 376866fd8ad5SAdrian Hunter /* Enable Card Detection */ 376966fd8ad5SAdrian Hunter sdhci_enable_card_detection(host); 377066fd8ad5SAdrian Hunter 377166fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 377266fd8ad5SAdrian Hunter 37738a125badSMarkus Pargmann return 0; 377466fd8ad5SAdrian Hunter } 377566fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host); 377666fd8ad5SAdrian Hunter 3777162d6f98SRafael J. Wysocki #endif /* CONFIG_PM */ 377866fd8ad5SAdrian Hunter 37791c6a0718SPierre Ossman /*****************************************************************************\ 37801c6a0718SPierre Ossman * * 3781f12e39dbSAdrian Hunter * Command Queue Engine (CQE) helpers * 3782f12e39dbSAdrian Hunter * * 3783f12e39dbSAdrian Hunter \*****************************************************************************/ 3784f12e39dbSAdrian Hunter 3785f12e39dbSAdrian Hunter void sdhci_cqe_enable(struct mmc_host *mmc) 3786f12e39dbSAdrian Hunter { 3787f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 3788f12e39dbSAdrian Hunter unsigned long flags; 3789f12e39dbSAdrian Hunter u8 ctrl; 3790f12e39dbSAdrian Hunter 3791f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3792f12e39dbSAdrian Hunter 3793f12e39dbSAdrian Hunter ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 3794f12e39dbSAdrian Hunter ctrl &= ~SDHCI_CTRL_DMA_MASK; 37954c4faff6SSowjanya Komatineni /* 37964c4faff6SSowjanya Komatineni * Host from V4.10 supports ADMA3 DMA type. 37974c4faff6SSowjanya Komatineni * ADMA3 performs integrated descriptor which is more suitable 37984c4faff6SSowjanya Komatineni * for cmd queuing to fetch both command and transfer descriptors. 37994c4faff6SSowjanya Komatineni */ 38004c4faff6SSowjanya Komatineni if (host->v4_mode && (host->caps1 & SDHCI_CAN_DO_ADMA3)) 38014c4faff6SSowjanya Komatineni ctrl |= SDHCI_CTRL_ADMA3; 38024c4faff6SSowjanya Komatineni else if (host->flags & SDHCI_USE_64_BIT_DMA) 3803f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA64; 3804f12e39dbSAdrian Hunter else 3805f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA32; 3806f12e39dbSAdrian Hunter sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 3807f12e39dbSAdrian Hunter 3808c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(host->sdma_boundary, 512), 3809f12e39dbSAdrian Hunter SDHCI_BLOCK_SIZE); 3810f12e39dbSAdrian Hunter 3811f12e39dbSAdrian Hunter /* Set maximum timeout */ 3812401059dfSBOUGH CHEN sdhci_set_timeout(host, NULL); 3813f12e39dbSAdrian Hunter 3814f12e39dbSAdrian Hunter host->ier = host->cqe_ier; 3815f12e39dbSAdrian Hunter 3816f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 3817f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 3818f12e39dbSAdrian Hunter 3819f12e39dbSAdrian Hunter host->cqe_on = true; 3820f12e39dbSAdrian Hunter 3821f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE on, IRQ mask %#x, IRQ status %#x\n", 3822f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier, 3823f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS)); 3824f12e39dbSAdrian Hunter 3825f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3826f12e39dbSAdrian Hunter } 3827f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_enable); 3828f12e39dbSAdrian Hunter 3829f12e39dbSAdrian Hunter void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery) 3830f12e39dbSAdrian Hunter { 3831f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc); 3832f12e39dbSAdrian Hunter unsigned long flags; 3833f12e39dbSAdrian Hunter 3834f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags); 3835f12e39dbSAdrian Hunter 3836f12e39dbSAdrian Hunter sdhci_set_default_irqs(host); 3837f12e39dbSAdrian Hunter 3838f12e39dbSAdrian Hunter host->cqe_on = false; 3839f12e39dbSAdrian Hunter 3840f12e39dbSAdrian Hunter if (recovery) { 3841f12e39dbSAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD); 3842f12e39dbSAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA); 3843f12e39dbSAdrian Hunter } 3844f12e39dbSAdrian Hunter 3845f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE off, IRQ mask %#x, IRQ status %#x\n", 3846f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier, 3847f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS)); 3848f12e39dbSAdrian Hunter 3849f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags); 3850f12e39dbSAdrian Hunter } 3851f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_disable); 3852f12e39dbSAdrian Hunter 3853f12e39dbSAdrian Hunter bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, 3854f12e39dbSAdrian Hunter int *data_error) 3855f12e39dbSAdrian Hunter { 3856f12e39dbSAdrian Hunter u32 mask; 3857f12e39dbSAdrian Hunter 3858f12e39dbSAdrian Hunter if (!host->cqe_on) 3859f12e39dbSAdrian Hunter return false; 3860f12e39dbSAdrian Hunter 3861f12e39dbSAdrian Hunter if (intmask & (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC)) 3862f12e39dbSAdrian Hunter *cmd_error = -EILSEQ; 3863f12e39dbSAdrian Hunter else if (intmask & SDHCI_INT_TIMEOUT) 3864f12e39dbSAdrian Hunter *cmd_error = -ETIMEDOUT; 3865f12e39dbSAdrian Hunter else 3866f12e39dbSAdrian Hunter *cmd_error = 0; 3867f12e39dbSAdrian Hunter 3868f12e39dbSAdrian Hunter if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) 3869f12e39dbSAdrian Hunter *data_error = -EILSEQ; 3870f12e39dbSAdrian Hunter else if (intmask & SDHCI_INT_DATA_TIMEOUT) 3871f12e39dbSAdrian Hunter *data_error = -ETIMEDOUT; 3872f12e39dbSAdrian Hunter else if (intmask & SDHCI_INT_ADMA_ERROR) 3873f12e39dbSAdrian Hunter *data_error = -EIO; 3874f12e39dbSAdrian Hunter else 3875f12e39dbSAdrian Hunter *data_error = 0; 3876f12e39dbSAdrian Hunter 3877f12e39dbSAdrian Hunter /* Clear selected interrupts. */ 3878f12e39dbSAdrian Hunter mask = intmask & host->cqe_ier; 3879f12e39dbSAdrian Hunter sdhci_writel(host, mask, SDHCI_INT_STATUS); 3880f12e39dbSAdrian Hunter 3881f12e39dbSAdrian Hunter if (intmask & SDHCI_INT_BUS_POWER) 3882f12e39dbSAdrian Hunter pr_err("%s: Card is consuming too much power!\n", 3883f12e39dbSAdrian Hunter mmc_hostname(host->mmc)); 3884f12e39dbSAdrian Hunter 3885f12e39dbSAdrian Hunter intmask &= ~(host->cqe_ier | SDHCI_INT_ERROR); 3886f12e39dbSAdrian Hunter if (intmask) { 3887f12e39dbSAdrian Hunter sdhci_writel(host, intmask, SDHCI_INT_STATUS); 3888f12e39dbSAdrian Hunter pr_err("%s: CQE: Unexpected interrupt 0x%08x.\n", 3889f12e39dbSAdrian Hunter mmc_hostname(host->mmc), intmask); 3890f12e39dbSAdrian Hunter sdhci_dumpregs(host); 3891f12e39dbSAdrian Hunter } 3892f12e39dbSAdrian Hunter 3893f12e39dbSAdrian Hunter return true; 3894f12e39dbSAdrian Hunter } 3895f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_irq); 3896f12e39dbSAdrian Hunter 3897f12e39dbSAdrian Hunter /*****************************************************************************\ 3898f12e39dbSAdrian Hunter * * 3899b8c86fc5SPierre Ossman * Device allocation/registration * 39001c6a0718SPierre Ossman * * 39011c6a0718SPierre Ossman \*****************************************************************************/ 39021c6a0718SPierre Ossman 3903b8c86fc5SPierre Ossman struct sdhci_host *sdhci_alloc_host(struct device *dev, 3904b8c86fc5SPierre Ossman size_t priv_size) 39051c6a0718SPierre Ossman { 39061c6a0718SPierre Ossman struct mmc_host *mmc; 39071c6a0718SPierre Ossman struct sdhci_host *host; 39081c6a0718SPierre Ossman 3909b8c86fc5SPierre Ossman WARN_ON(dev == NULL); 39101c6a0718SPierre Ossman 3911b8c86fc5SPierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); 39121c6a0718SPierre Ossman if (!mmc) 3913b8c86fc5SPierre Ossman return ERR_PTR(-ENOMEM); 39141c6a0718SPierre Ossman 39151c6a0718SPierre Ossman host = mmc_priv(mmc); 39161c6a0718SPierre Ossman host->mmc = mmc; 3917bf60e592SAdrian Hunter host->mmc_host_ops = sdhci_ops; 3918bf60e592SAdrian Hunter mmc->ops = &host->mmc_host_ops; 39191c6a0718SPierre Ossman 39208cb851a4SAdrian Hunter host->flags = SDHCI_SIGNALING_330; 39218cb851a4SAdrian Hunter 3922f12e39dbSAdrian Hunter host->cqe_ier = SDHCI_CQE_INT_MASK; 3923f12e39dbSAdrian Hunter host->cqe_err_ier = SDHCI_CQE_INT_ERR_MASK; 3924f12e39dbSAdrian Hunter 392583b600b8SAdrian Hunter host->tuning_delay = -1; 39261d8cd065SSowjanya Komatineni host->tuning_loop_count = MAX_TUNING_LOOP; 392783b600b8SAdrian Hunter 3928c846a00fSSrinivas Kandagatla host->sdma_boundary = SDHCI_DEFAULT_BOUNDARY_ARG; 3929c846a00fSSrinivas Kandagatla 3930e93be38aSJisheng Zhang /* 3931e93be38aSJisheng Zhang * The DMA table descriptor count is calculated as the maximum 3932e93be38aSJisheng Zhang * number of segments times 2, to allow for an alignment 3933e93be38aSJisheng Zhang * descriptor for each segment, plus 1 for a nop end descriptor. 3934e93be38aSJisheng Zhang */ 3935e93be38aSJisheng Zhang host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1; 3936e93be38aSJisheng Zhang 3937b8c86fc5SPierre Ossman return host; 39381c6a0718SPierre Ossman } 39391c6a0718SPierre Ossman 3940b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_alloc_host); 3941b8c86fc5SPierre Ossman 39427b91369bSAlexandre Courbot static int sdhci_set_dma_mask(struct sdhci_host *host) 39437b91369bSAlexandre Courbot { 39447b91369bSAlexandre Courbot struct mmc_host *mmc = host->mmc; 39457b91369bSAlexandre Courbot struct device *dev = mmc_dev(mmc); 39467b91369bSAlexandre Courbot int ret = -EINVAL; 39477b91369bSAlexandre Courbot 39487b91369bSAlexandre Courbot if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) 39497b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA; 39507b91369bSAlexandre Courbot 39517b91369bSAlexandre Courbot /* Try 64-bit mask if hardware is capable of it */ 39527b91369bSAlexandre Courbot if (host->flags & SDHCI_USE_64_BIT_DMA) { 39537b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 39547b91369bSAlexandre Courbot if (ret) { 39557b91369bSAlexandre Courbot pr_warn("%s: Failed to set 64-bit DMA mask.\n", 39567b91369bSAlexandre Courbot mmc_hostname(mmc)); 39577b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA; 39587b91369bSAlexandre Courbot } 39597b91369bSAlexandre Courbot } 39607b91369bSAlexandre Courbot 39617b91369bSAlexandre Courbot /* 32-bit mask as default & fallback */ 39627b91369bSAlexandre Courbot if (ret) { 39637b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); 39647b91369bSAlexandre Courbot if (ret) 39657b91369bSAlexandre Courbot pr_warn("%s: Failed to set 32-bit DMA mask.\n", 39667b91369bSAlexandre Courbot mmc_hostname(mmc)); 39677b91369bSAlexandre Courbot } 39687b91369bSAlexandre Courbot 39697b91369bSAlexandre Courbot return ret; 39707b91369bSAlexandre Courbot } 39717b91369bSAlexandre Courbot 39728784edc8SMasahiro Yamada void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver, 39738784edc8SMasahiro Yamada const u32 *caps, const u32 *caps1) 39746132a3bfSAdrian Hunter { 39756132a3bfSAdrian Hunter u16 v; 397692e0c44bSZach Brown u64 dt_caps_mask = 0; 397792e0c44bSZach Brown u64 dt_caps = 0; 39786132a3bfSAdrian Hunter 39796132a3bfSAdrian Hunter if (host->read_caps) 39806132a3bfSAdrian Hunter return; 39816132a3bfSAdrian Hunter 39826132a3bfSAdrian Hunter host->read_caps = true; 39836132a3bfSAdrian Hunter 39846132a3bfSAdrian Hunter if (debug_quirks) 39856132a3bfSAdrian Hunter host->quirks = debug_quirks; 39866132a3bfSAdrian Hunter 39876132a3bfSAdrian Hunter if (debug_quirks2) 39886132a3bfSAdrian Hunter host->quirks2 = debug_quirks2; 39896132a3bfSAdrian Hunter 39906132a3bfSAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_ALL); 39916132a3bfSAdrian Hunter 3992b3f80b43SChunyan Zhang if (host->v4_mode) 3993b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host); 3994b3f80b43SChunyan Zhang 399592e0c44bSZach Brown of_property_read_u64(mmc_dev(host->mmc)->of_node, 399692e0c44bSZach Brown "sdhci-caps-mask", &dt_caps_mask); 399792e0c44bSZach Brown of_property_read_u64(mmc_dev(host->mmc)->of_node, 399892e0c44bSZach Brown "sdhci-caps", &dt_caps); 399992e0c44bSZach Brown 40006132a3bfSAdrian Hunter v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION); 40016132a3bfSAdrian Hunter host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; 40026132a3bfSAdrian Hunter 40036132a3bfSAdrian Hunter if (host->quirks & SDHCI_QUIRK_MISSING_CAPS) 40046132a3bfSAdrian Hunter return; 40056132a3bfSAdrian Hunter 400692e0c44bSZach Brown if (caps) { 400792e0c44bSZach Brown host->caps = *caps; 400892e0c44bSZach Brown } else { 400992e0c44bSZach Brown host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); 401092e0c44bSZach Brown host->caps &= ~lower_32_bits(dt_caps_mask); 401192e0c44bSZach Brown host->caps |= lower_32_bits(dt_caps); 401292e0c44bSZach Brown } 40136132a3bfSAdrian Hunter 40146132a3bfSAdrian Hunter if (host->version < SDHCI_SPEC_300) 40156132a3bfSAdrian Hunter return; 40166132a3bfSAdrian Hunter 401792e0c44bSZach Brown if (caps1) { 401892e0c44bSZach Brown host->caps1 = *caps1; 401992e0c44bSZach Brown } else { 402092e0c44bSZach Brown host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); 402192e0c44bSZach Brown host->caps1 &= ~upper_32_bits(dt_caps_mask); 402292e0c44bSZach Brown host->caps1 |= upper_32_bits(dt_caps); 402392e0c44bSZach Brown } 40246132a3bfSAdrian Hunter } 40256132a3bfSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_read_caps); 40266132a3bfSAdrian Hunter 4027a68dd9a0SChunyan Zhang static void sdhci_allocate_bounce_buffer(struct sdhci_host *host) 4028bd9b9027SLinus Walleij { 4029bd9b9027SLinus Walleij struct mmc_host *mmc = host->mmc; 4030bd9b9027SLinus Walleij unsigned int max_blocks; 4031bd9b9027SLinus Walleij unsigned int bounce_size; 4032bd9b9027SLinus Walleij int ret; 4033bd9b9027SLinus Walleij 4034bd9b9027SLinus Walleij /* 4035bd9b9027SLinus Walleij * Cap the bounce buffer at 64KB. Using a bigger bounce buffer 4036bd9b9027SLinus Walleij * has diminishing returns, this is probably because SD/MMC 4037bd9b9027SLinus Walleij * cards are usually optimized to handle this size of requests. 4038bd9b9027SLinus Walleij */ 4039bd9b9027SLinus Walleij bounce_size = SZ_64K; 4040bd9b9027SLinus Walleij /* 4041bd9b9027SLinus Walleij * Adjust downwards to maximum request size if this is less 4042bd9b9027SLinus Walleij * than our segment size, else hammer down the maximum 4043bd9b9027SLinus Walleij * request size to the maximum buffer size. 4044bd9b9027SLinus Walleij */ 4045bd9b9027SLinus Walleij if (mmc->max_req_size < bounce_size) 4046bd9b9027SLinus Walleij bounce_size = mmc->max_req_size; 4047bd9b9027SLinus Walleij max_blocks = bounce_size / 512; 4048bd9b9027SLinus Walleij 4049bd9b9027SLinus Walleij /* 4050bd9b9027SLinus Walleij * When we just support one segment, we can get significant 4051bd9b9027SLinus Walleij * speedups by the help of a bounce buffer to group scattered 4052bd9b9027SLinus Walleij * reads/writes together. 4053bd9b9027SLinus Walleij */ 4054bd9b9027SLinus Walleij host->bounce_buffer = devm_kmalloc(mmc->parent, 4055bd9b9027SLinus Walleij bounce_size, 4056bd9b9027SLinus Walleij GFP_KERNEL); 4057bd9b9027SLinus Walleij if (!host->bounce_buffer) { 4058bd9b9027SLinus Walleij pr_err("%s: failed to allocate %u bytes for bounce buffer, falling back to single segments\n", 4059bd9b9027SLinus Walleij mmc_hostname(mmc), 4060bd9b9027SLinus Walleij bounce_size); 4061bd9b9027SLinus Walleij /* 4062bd9b9027SLinus Walleij * Exiting with zero here makes sure we proceed with 4063bd9b9027SLinus Walleij * mmc->max_segs == 1. 4064bd9b9027SLinus Walleij */ 4065a68dd9a0SChunyan Zhang return; 4066bd9b9027SLinus Walleij } 4067bd9b9027SLinus Walleij 4068bd9b9027SLinus Walleij host->bounce_addr = dma_map_single(mmc->parent, 4069bd9b9027SLinus Walleij host->bounce_buffer, 4070bd9b9027SLinus Walleij bounce_size, 4071bd9b9027SLinus Walleij DMA_BIDIRECTIONAL); 4072bd9b9027SLinus Walleij ret = dma_mapping_error(mmc->parent, host->bounce_addr); 4073bd9b9027SLinus Walleij if (ret) 4074bd9b9027SLinus Walleij /* Again fall back to max_segs == 1 */ 4075a68dd9a0SChunyan Zhang return; 4076bd9b9027SLinus Walleij host->bounce_buffer_size = bounce_size; 4077bd9b9027SLinus Walleij 4078bd9b9027SLinus Walleij /* Lie about this since we're bouncing */ 4079bd9b9027SLinus Walleij mmc->max_segs = max_blocks; 4080bd9b9027SLinus Walleij mmc->max_seg_size = bounce_size; 4081bd9b9027SLinus Walleij mmc->max_req_size = bounce_size; 4082bd9b9027SLinus Walleij 4083bd9b9027SLinus Walleij pr_info("%s bounce up to %u segments into one, max segment size %u bytes\n", 4084bd9b9027SLinus Walleij mmc_hostname(mmc), max_blocks, bounce_size); 4085bd9b9027SLinus Walleij } 4086bd9b9027SLinus Walleij 4087685e444bSChunyan Zhang static inline bool sdhci_can_64bit_dma(struct sdhci_host *host) 4088685e444bSChunyan Zhang { 4089685e444bSChunyan Zhang /* 4090685e444bSChunyan Zhang * According to SD Host Controller spec v4.10, bit[27] added from 4091685e444bSChunyan Zhang * version 4.10 in Capabilities Register is used as 64-bit System 4092685e444bSChunyan Zhang * Address support for V4 mode. 4093685e444bSChunyan Zhang */ 4094685e444bSChunyan Zhang if (host->version >= SDHCI_SPEC_410 && host->v4_mode) 4095685e444bSChunyan Zhang return host->caps & SDHCI_CAN_64BIT_V4; 4096685e444bSChunyan Zhang 4097685e444bSChunyan Zhang return host->caps & SDHCI_CAN_64BIT; 4098685e444bSChunyan Zhang } 4099685e444bSChunyan Zhang 410052f5336dSAdrian Hunter int sdhci_setup_host(struct sdhci_host *host) 4101b8c86fc5SPierre Ossman { 4102b8c86fc5SPierre Ossman struct mmc_host *mmc; 4103f2119df6SArindam Nath u32 max_current_caps; 4104f2119df6SArindam Nath unsigned int ocr_avail; 4105f5fa92e5SAdrian Hunter unsigned int override_timeout_clk; 410659241757SDong Aisheng u32 max_clk; 4107b8c86fc5SPierre Ossman int ret; 41080fcb031eSVijay Viswanath bool enable_vqmmc = false; 4109b8c86fc5SPierre Ossman 4110b8c86fc5SPierre Ossman WARN_ON(host == NULL); 4111b8c86fc5SPierre Ossman if (host == NULL) 4112b8c86fc5SPierre Ossman return -EINVAL; 4113b8c86fc5SPierre Ossman 4114b8c86fc5SPierre Ossman mmc = host->mmc; 4115b8c86fc5SPierre Ossman 4116efba142bSJon Hunter /* 4117efba142bSJon Hunter * If there are external regulators, get them. Note this must be done 4118efba142bSJon Hunter * early before resetting the host and reading the capabilities so that 4119efba142bSJon Hunter * the host can take the appropriate action if regulators are not 4120efba142bSJon Hunter * available. 4121efba142bSJon Hunter */ 41220fcb031eSVijay Viswanath if (!mmc->supply.vqmmc) { 4123efba142bSJon Hunter ret = mmc_regulator_get_supply(mmc); 41242a63303dSWolfram Sang if (ret) 4125efba142bSJon Hunter return ret; 41260fcb031eSVijay Viswanath enable_vqmmc = true; 41270fcb031eSVijay Viswanath } 4128efba142bSJon Hunter 412906ebc601SShawn Lin DBG("Version: 0x%08x | Present: 0x%08x\n", 413006ebc601SShawn Lin sdhci_readw(host, SDHCI_HOST_VERSION), 413106ebc601SShawn Lin sdhci_readl(host, SDHCI_PRESENT_STATE)); 413206ebc601SShawn Lin DBG("Caps: 0x%08x | Caps_1: 0x%08x\n", 413306ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES), 413406ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES_1)); 413506ebc601SShawn Lin 41366132a3bfSAdrian Hunter sdhci_read_caps(host); 4137b8c86fc5SPierre Ossman 4138f5fa92e5SAdrian Hunter override_timeout_clk = host->timeout_clk; 4139f5fa92e5SAdrian Hunter 414018da1990SChunyan Zhang if (host->version > SDHCI_SPEC_420) { 41412e4456f0SMarek Vasut pr_err("%s: Unknown controller version (%d). You may experience problems.\n", 41422e4456f0SMarek Vasut mmc_hostname(mmc), host->version); 41431c6a0718SPierre Ossman } 41441c6a0718SPierre Ossman 4145b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA) 4146a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 414728da3589SAdrian Hunter else if (!(host->caps & SDHCI_CAN_DO_SDMA)) 4148a13abc7bSRichard Röjfors DBG("Controller doesn't have SDMA capability\n"); 41491c6a0718SPierre Ossman else 4150a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA; 41511c6a0718SPierre Ossman 4152b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && 4153a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA)) { 4154cee687ceSRolf Eike Beer DBG("Disabling DMA as it is marked broken\n"); 4155a13abc7bSRichard Röjfors host->flags &= ~SDHCI_USE_SDMA; 41567c168e3dSFeng Tang } 41577c168e3dSFeng Tang 4158f2119df6SArindam Nath if ((host->version >= SDHCI_SPEC_200) && 415928da3589SAdrian Hunter (host->caps & SDHCI_CAN_DO_ADMA2)) 41602134a922SPierre Ossman host->flags |= SDHCI_USE_ADMA; 41612134a922SPierre Ossman 41622134a922SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && 41632134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) { 41642134a922SPierre Ossman DBG("Disabling ADMA as it is marked broken\n"); 41652134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 41662134a922SPierre Ossman } 41672134a922SPierre Ossman 4168685e444bSChunyan Zhang if (sdhci_can_64bit_dma(host)) 4169e57a5f61SAdrian Hunter host->flags |= SDHCI_USE_64_BIT_DMA; 4170e57a5f61SAdrian Hunter 417118e762e3SChunyan Zhang if (host->use_external_dma) { 417218e762e3SChunyan Zhang ret = sdhci_external_dma_init(host); 417318e762e3SChunyan Zhang if (ret == -EPROBE_DEFER) 417418e762e3SChunyan Zhang goto unreg; 417518e762e3SChunyan Zhang /* 417618e762e3SChunyan Zhang * Fall back to use the DMA/PIO integrated in standard SDHCI 417718e762e3SChunyan Zhang * instead of external DMA devices. 417818e762e3SChunyan Zhang */ 417918e762e3SChunyan Zhang else if (ret) 418018e762e3SChunyan Zhang sdhci_switch_external_dma(host, false); 418118e762e3SChunyan Zhang /* Disable internal DMA sources */ 418218e762e3SChunyan Zhang else 418318e762e3SChunyan Zhang host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 418418e762e3SChunyan Zhang } 418518e762e3SChunyan Zhang 4186a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { 41874ee7dde4SAdrian Hunter if (host->ops->set_dma_mask) 41884ee7dde4SAdrian Hunter ret = host->ops->set_dma_mask(host); 41894ee7dde4SAdrian Hunter else 41907b91369bSAlexandre Courbot ret = sdhci_set_dma_mask(host); 41917b91369bSAlexandre Courbot 41927b91369bSAlexandre Courbot if (!ret && host->ops->enable_dma) 41937b91369bSAlexandre Courbot ret = host->ops->enable_dma(host); 41947b91369bSAlexandre Courbot 41957b91369bSAlexandre Courbot if (ret) { 41966606110dSJoe Perches pr_warn("%s: No suitable DMA available - falling back to PIO\n", 4197b8c86fc5SPierre Ossman mmc_hostname(mmc)); 41987b91369bSAlexandre Courbot host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); 41997b91369bSAlexandre Courbot 42007b91369bSAlexandre Courbot ret = 0; 42011c6a0718SPierre Ossman } 4202b8c86fc5SPierre Ossman } 42031c6a0718SPierre Ossman 4204917a0c52SChunyan Zhang /* SDMA does not support 64-bit DMA if v4 mode not set */ 4205917a0c52SChunyan Zhang if ((host->flags & SDHCI_USE_64_BIT_DMA) && !host->v4_mode) 4206e57a5f61SAdrian Hunter host->flags &= ~SDHCI_USE_SDMA; 4207e57a5f61SAdrian Hunter 42082134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) { 4209e66e61cbSRussell King dma_addr_t dma; 4210e66e61cbSRussell King void *buf; 4211e66e61cbSRussell King 4212a663f64bSVeerabhadrarao Badiganti if (!(host->flags & SDHCI_USE_64_BIT_DMA)) 4213a663f64bSVeerabhadrarao Badiganti host->alloc_desc_sz = SDHCI_ADMA2_32_DESC_SZ; 4214a663f64bSVeerabhadrarao Badiganti else if (!host->alloc_desc_sz) 4215a663f64bSVeerabhadrarao Badiganti host->alloc_desc_sz = SDHCI_ADMA2_64_DESC_SZ(host); 4216a663f64bSVeerabhadrarao Badiganti 4217a663f64bSVeerabhadrarao Badiganti host->desc_sz = host->alloc_desc_sz; 4218a663f64bSVeerabhadrarao Badiganti host->adma_table_sz = host->adma_table_cnt * host->desc_sz; 4219e66e61cbSRussell King 422004a5ae6fSAdrian Hunter host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN; 4221685e444bSChunyan Zhang /* 4222685e444bSChunyan Zhang * Use zalloc to zero the reserved high 32-bits of 128-bit 4223685e444bSChunyan Zhang * descriptors so that they never need to be written. 4224685e444bSChunyan Zhang */ 4225750afb08SLuis Chamberlain buf = dma_alloc_coherent(mmc_dev(mmc), 4226750afb08SLuis Chamberlain host->align_buffer_sz + host->adma_table_sz, 4227750afb08SLuis Chamberlain &dma, GFP_KERNEL); 4228e66e61cbSRussell King if (!buf) { 42296606110dSJoe Perches pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", 42302134a922SPierre Ossman mmc_hostname(mmc)); 42312134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA; 4232e66e61cbSRussell King } else if ((dma + host->align_buffer_sz) & 4233e66e61cbSRussell King (SDHCI_ADMA2_DESC_ALIGN - 1)) { 42346606110dSJoe Perches pr_warn("%s: unable to allocate aligned ADMA descriptor\n", 4235d1e49f77SRussell King mmc_hostname(mmc)); 4236d1e49f77SRussell King host->flags &= ~SDHCI_USE_ADMA; 4237e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 4238e66e61cbSRussell King host->adma_table_sz, buf, dma); 4239e66e61cbSRussell King } else { 4240e66e61cbSRussell King host->align_buffer = buf; 4241e66e61cbSRussell King host->align_addr = dma; 4242edd63fccSRussell King 4243e66e61cbSRussell King host->adma_table = buf + host->align_buffer_sz; 4244e66e61cbSRussell King host->adma_addr = dma + host->align_buffer_sz; 4245e66e61cbSRussell King } 42462134a922SPierre Ossman } 42472134a922SPierre Ossman 42487659150cSPierre Ossman /* 42497659150cSPierre Ossman * If we use DMA, then it's up to the caller to set the DMA 42507659150cSPierre Ossman * mask, but PIO does not need the hw shim so we set a new 42517659150cSPierre Ossman * mask here in that case. 42527659150cSPierre Ossman */ 4253a13abc7bSRichard Röjfors if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) { 42547659150cSPierre Ossman host->dma_mask = DMA_BIT_MASK(64); 42554e743f1fSMarkus Mayer mmc_dev(mmc)->dma_mask = &host->dma_mask; 42567659150cSPierre Ossman } 42571c6a0718SPierre Ossman 4258c4687d5fSZhangfei Gao if (host->version >= SDHCI_SPEC_300) 4259a8e809ecSMasahiro Yamada host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps); 4260c4687d5fSZhangfei Gao else 4261a8e809ecSMasahiro Yamada host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps); 4262c4687d5fSZhangfei Gao 42634240ff0aSBen Dooks host->max_clk *= 1000000; 4264f27f47efSAnton Vorontsov if (host->max_clk == 0 || host->quirks & 4265f27f47efSAnton Vorontsov SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { 42664240ff0aSBen Dooks if (!host->ops->get_max_clock) { 42672e4456f0SMarek Vasut pr_err("%s: Hardware doesn't specify base clock frequency.\n", 42682e4456f0SMarek Vasut mmc_hostname(mmc)); 4269eb5c20deSAdrian Hunter ret = -ENODEV; 4270eb5c20deSAdrian Hunter goto undma; 42711c6a0718SPierre Ossman } 42724240ff0aSBen Dooks host->max_clk = host->ops->get_max_clock(host); 42734240ff0aSBen Dooks } 42741c6a0718SPierre Ossman 42751c6a0718SPierre Ossman /* 4276c3ed3877SArindam Nath * In case of Host Controller v3.00, find out whether clock 4277c3ed3877SArindam Nath * multiplier is supported. 4278c3ed3877SArindam Nath */ 4279a8e809ecSMasahiro Yamada host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1); 4280c3ed3877SArindam Nath 4281c3ed3877SArindam Nath /* 4282c3ed3877SArindam Nath * In case the value in Clock Multiplier is 0, then programmable 4283c3ed3877SArindam Nath * clock mode is not supported, otherwise the actual clock 4284c3ed3877SArindam Nath * multiplier is one more than the value of Clock Multiplier 4285c3ed3877SArindam Nath * in the Capabilities Register. 4286c3ed3877SArindam Nath */ 4287c3ed3877SArindam Nath if (host->clk_mul) 4288c3ed3877SArindam Nath host->clk_mul += 1; 4289c3ed3877SArindam Nath 4290c3ed3877SArindam Nath /* 42911c6a0718SPierre Ossman * Set host parameters. 42921c6a0718SPierre Ossman */ 429359241757SDong Aisheng max_clk = host->max_clk; 429459241757SDong Aisheng 4295ce5f036bSMarek Szyprowski if (host->ops->get_min_clock) 4296a9e58f25SAnton Vorontsov mmc->f_min = host->ops->get_min_clock(host); 4297c3ed3877SArindam Nath else if (host->version >= SDHCI_SPEC_300) { 42982a187d03SMichał Mirosław if (host->clk_mul) 429959241757SDong Aisheng max_clk = host->max_clk * host->clk_mul; 43002a187d03SMichał Mirosław /* 43012a187d03SMichał Mirosław * Divided Clock Mode minimum clock rate is always less than 43022a187d03SMichał Mirosław * Programmable Clock Mode minimum clock rate. 43032a187d03SMichał Mirosław */ 43040397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; 4305c3ed3877SArindam Nath } else 43060397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; 430715ec4461SPhilip Rakity 4308d310ae49SAdrian Hunter if (!mmc->f_max || mmc->f_max > max_clk) 430959241757SDong Aisheng mmc->f_max = max_clk; 431059241757SDong Aisheng 431128aab053SAisheng Dong if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { 4312a8e809ecSMasahiro Yamada host->timeout_clk = FIELD_GET(SDHCI_TIMEOUT_CLK_MASK, host->caps); 43138cc35289SShawn Lin 43148cc35289SShawn Lin if (host->caps & SDHCI_TIMEOUT_CLK_UNIT) 43158cc35289SShawn Lin host->timeout_clk *= 1000; 43168cc35289SShawn Lin 4317272308caSAndy Shevchenko if (host->timeout_clk == 0) { 43188cc35289SShawn Lin if (!host->ops->get_timeout_clock) { 431928aab053SAisheng Dong pr_err("%s: Hardware doesn't specify timeout clock frequency.\n", 432028aab053SAisheng Dong mmc_hostname(mmc)); 4321eb5c20deSAdrian Hunter ret = -ENODEV; 4322eb5c20deSAdrian Hunter goto undma; 4323272308caSAndy Shevchenko } 432428aab053SAisheng Dong 43258cc35289SShawn Lin host->timeout_clk = 43268cc35289SShawn Lin DIV_ROUND_UP(host->ops->get_timeout_clock(host), 43278cc35289SShawn Lin 1000); 43288cc35289SShawn Lin } 4329272308caSAndy Shevchenko 433099513624SAdrian Hunter if (override_timeout_clk) 433199513624SAdrian Hunter host->timeout_clk = override_timeout_clk; 433299513624SAdrian Hunter 4333a6ff5aebSAisheng Dong mmc->max_busy_timeout = host->ops->get_max_timeout_count ? 4334a6ff5aebSAisheng Dong host->ops->get_max_timeout_count(host) : 1 << 27; 4335a6ff5aebSAisheng Dong mmc->max_busy_timeout /= host->timeout_clk; 433628aab053SAisheng Dong } 433758d1246dSAdrian Hunter 4338a999fd93SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT && 4339a999fd93SAdrian Hunter !host->ops->get_max_timeout_count) 4340a999fd93SAdrian Hunter mmc->max_busy_timeout = 0; 4341a999fd93SAdrian Hunter 43421be64c79SUlf Hansson mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_CMD23; 4343781e989cSRussell King mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; 4344e89d456fSAndrei Warkentin 4345e89d456fSAndrei Warkentin if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) 4346e89d456fSAndrei Warkentin host->flags |= SDHCI_AUTO_CMD12; 43475fe23c7fSAnton Vorontsov 43487ed71a9dSChunyan Zhang /* 43497ed71a9dSChunyan Zhang * For v3 mode, Auto-CMD23 stuff only works in ADMA or PIO. 43507ed71a9dSChunyan Zhang * For v4 mode, SDMA may use Auto-CMD23 as well. 43517ed71a9dSChunyan Zhang */ 43524f3d3e9bSAndrei Warkentin if ((host->version >= SDHCI_SPEC_300) && 43538edf6371SAndrei Warkentin ((host->flags & SDHCI_USE_ADMA) || 43547ed71a9dSChunyan Zhang !(host->flags & SDHCI_USE_SDMA) || host->v4_mode) && 43553bfa6f03SScott Branden !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN)) { 43568edf6371SAndrei Warkentin host->flags |= SDHCI_AUTO_CMD23; 4357f421865dSAdrian Hunter DBG("Auto-CMD23 available\n"); 43588edf6371SAndrei Warkentin } else { 4359f421865dSAdrian Hunter DBG("Auto-CMD23 unavailable\n"); 43608edf6371SAndrei Warkentin } 43618edf6371SAndrei Warkentin 436215ec4461SPhilip Rakity /* 436315ec4461SPhilip Rakity * A controller may support 8-bit width, but the board itself 436415ec4461SPhilip Rakity * might not have the pins brought out. Boards that support 436515ec4461SPhilip Rakity * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in 436615ec4461SPhilip Rakity * their platform code before calling sdhci_add_host(), and we 436715ec4461SPhilip Rakity * won't assume 8-bit width for hosts without that CAP. 436815ec4461SPhilip Rakity */ 43695fe23c7fSAnton Vorontsov if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) 437015ec4461SPhilip Rakity mmc->caps |= MMC_CAP_4_BIT_DATA; 43711c6a0718SPierre Ossman 437263ef5d8cSJerry Huang if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) 437363ef5d8cSJerry Huang mmc->caps &= ~MMC_CAP_CMD23; 437463ef5d8cSJerry Huang 437528da3589SAdrian Hunter if (host->caps & SDHCI_CAN_DO_HISPD) 4376a29e7e18SZhangfei Gao mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; 43771c6a0718SPierre Ossman 4378176d1ed4SJaehoon Chung if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && 4379860951c5SJaehoon Chung mmc_card_is_removable(mmc) && 4380287980e4SArnd Bergmann mmc_gpio_get_cd(host->mmc) < 0) 438168d1fb7eSAnton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL; 438268d1fb7eSAnton Vorontsov 43833a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) { 43840fcb031eSVijay Viswanath if (enable_vqmmc) { 43853a48edc4STim Kryger ret = regulator_enable(mmc->supply.vqmmc); 43860fcb031eSVijay Viswanath host->sdhci_core_to_disable_vqmmc = !ret; 43870fcb031eSVijay Viswanath } 43881b5190c2SStefan Agner 43891b5190c2SStefan Agner /* If vqmmc provides no 1.8V signalling, then there's no UHS */ 43903a48edc4STim Kryger if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000, 4391cec2e216SKevin Liu 1950000)) 439228da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | 43938363c374SKevin Liu SDHCI_SUPPORT_SDR50 | 43946231f3deSPhilip Rakity SDHCI_SUPPORT_DDR50); 43951b5190c2SStefan Agner 43961b5190c2SStefan Agner /* In eMMC case vqmmc might be a fixed 1.8V regulator */ 43971b5190c2SStefan Agner if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000, 43981b5190c2SStefan Agner 3600000)) 43991b5190c2SStefan Agner host->flags &= ~SDHCI_SIGNALING_330; 44003debc24fSVeerabhadrarao Badiganti 44013debc24fSVeerabhadrarao Badiganti if (ret) { 44023debc24fSVeerabhadrarao Badiganti pr_warn("%s: Failed to enable vqmmc regulator: %d\n", 44033debc24fSVeerabhadrarao Badiganti mmc_hostname(mmc), ret); 44043debc24fSVeerabhadrarao Badiganti mmc->supply.vqmmc = ERR_PTR(-EINVAL); 44053debc24fSVeerabhadrarao Badiganti } 44063debc24fSVeerabhadrarao Badiganti 44078363c374SKevin Liu } 44086231f3deSPhilip Rakity 440928da3589SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) { 441028da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | 44116a66180aSDaniel Drake SDHCI_SUPPORT_DDR50); 4412c16bc9a7SKishon Vijay Abraham I /* 4413c16bc9a7SKishon Vijay Abraham I * The SDHCI controller in a SoC might support HS200/HS400 4414c16bc9a7SKishon Vijay Abraham I * (indicated using mmc-hs200-1_8v/mmc-hs400-1_8v dt property), 4415c16bc9a7SKishon Vijay Abraham I * but if the board is modeled such that the IO lines are not 4416c16bc9a7SKishon Vijay Abraham I * connected to 1.8v then HS200/HS400 cannot be supported. 4417c16bc9a7SKishon Vijay Abraham I * Disable HS200/HS400 if the board does not have 1.8v connected 4418c16bc9a7SKishon Vijay Abraham I * to the IO lines. (Applicable for other modes in 1.8v) 4419c16bc9a7SKishon Vijay Abraham I */ 4420c16bc9a7SKishon Vijay Abraham I mmc->caps2 &= ~(MMC_CAP2_HSX00_1_8V | MMC_CAP2_HS400_ES); 4421c16bc9a7SKishon Vijay Abraham I mmc->caps &= ~(MMC_CAP_1_8V_DDR | MMC_CAP_UHS); 442228da3589SAdrian Hunter } 44236a66180aSDaniel Drake 44244188bba0SAl Cooper /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ 442528da3589SAdrian Hunter if (host->caps1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | 44264188bba0SAl Cooper SDHCI_SUPPORT_DDR50)) 4427f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; 4428f2119df6SArindam Nath 4429f2119df6SArindam Nath /* SDR104 supports also implies SDR50 support */ 443028da3589SAdrian Hunter if (host->caps1 & SDHCI_SUPPORT_SDR104) { 4431f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; 4432156e14b1SGiuseppe CAVALLARO /* SD3.0: SDR104 is supported so (for eMMC) the caps2 4433156e14b1SGiuseppe CAVALLARO * field can be promoted to support HS200. 4434156e14b1SGiuseppe CAVALLARO */ 4435549c0b18SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) 4436156e14b1SGiuseppe CAVALLARO mmc->caps2 |= MMC_CAP2_HS200; 443728da3589SAdrian Hunter } else if (host->caps1 & SDHCI_SUPPORT_SDR50) { 4438f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR50; 443928da3589SAdrian Hunter } 4440f2119df6SArindam Nath 4441e9fb05d5SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 && 444228da3589SAdrian Hunter (host->caps1 & SDHCI_SUPPORT_HS400)) 4443e9fb05d5SAdrian Hunter mmc->caps2 |= MMC_CAP2_HS400; 4444e9fb05d5SAdrian Hunter 4445549c0b18SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) && 4446549c0b18SAdrian Hunter (IS_ERR(mmc->supply.vqmmc) || 4447549c0b18SAdrian Hunter !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000, 4448549c0b18SAdrian Hunter 1300000))) 4449549c0b18SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V; 4450549c0b18SAdrian Hunter 445128da3589SAdrian Hunter if ((host->caps1 & SDHCI_SUPPORT_DDR50) && 44529107ebbfSMicky Ching !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) 4453f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_DDR50; 4454f2119df6SArindam Nath 4455069c9f14SGirish K S /* Does the host need tuning for SDR50? */ 445628da3589SAdrian Hunter if (host->caps1 & SDHCI_USE_SDR50_TUNING) 4457b513ea25SArindam Nath host->flags |= SDHCI_SDR50_NEEDS_TUNING; 4458b513ea25SArindam Nath 4459d6d50a15SArindam Nath /* Driver Type(s) (A, C, D) supported by the host */ 446028da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_A) 4461d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_A; 446228da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_C) 4463d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_C; 446428da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_D) 4465d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_D; 4466d6d50a15SArindam Nath 4467cf2b5eeaSArindam Nath /* Initial value for re-tuning timer count */ 4468a8e809ecSMasahiro Yamada host->tuning_count = FIELD_GET(SDHCI_RETUNING_TIMER_COUNT_MASK, 4469a8e809ecSMasahiro Yamada host->caps1); 4470cf2b5eeaSArindam Nath 4471cf2b5eeaSArindam Nath /* 4472cf2b5eeaSArindam Nath * In case Re-tuning Timer is not disabled, the actual value of 4473cf2b5eeaSArindam Nath * re-tuning timer will be 2 ^ (n - 1). 4474cf2b5eeaSArindam Nath */ 4475cf2b5eeaSArindam Nath if (host->tuning_count) 4476cf2b5eeaSArindam Nath host->tuning_count = 1 << (host->tuning_count - 1); 4477cf2b5eeaSArindam Nath 4478cf2b5eeaSArindam Nath /* Re-tuning mode supported by the Host Controller */ 4479a8e809ecSMasahiro Yamada host->tuning_mode = FIELD_GET(SDHCI_RETUNING_MODE_MASK, host->caps1); 4480cf2b5eeaSArindam Nath 44818f230f45STakashi Iwai ocr_avail = 0; 4482bad37e1aSPhilip Rakity 4483f2119df6SArindam Nath /* 4484f2119df6SArindam Nath * According to SD Host Controller spec v3.00, if the Host System 4485f2119df6SArindam Nath * can afford more than 150mA, Host Driver should set XPC to 1. Also 4486f2119df6SArindam Nath * the value is meaningful only if Voltage Support in the Capabilities 4487f2119df6SArindam Nath * register is set. The actual current value is 4 times the register 4488f2119df6SArindam Nath * value. 4489f2119df6SArindam Nath */ 4490f2119df6SArindam Nath max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); 44913a48edc4STim Kryger if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) { 4492ae906037SChuanxiao.Dong int curr = regulator_get_current_limit(mmc->supply.vmmc); 4493bad37e1aSPhilip Rakity if (curr > 0) { 4494bad37e1aSPhilip Rakity 4495bad37e1aSPhilip Rakity /* convert to SDHCI_MAX_CURRENT format */ 4496bad37e1aSPhilip Rakity curr = curr/1000; /* convert to mA */ 4497bad37e1aSPhilip Rakity curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER; 4498bad37e1aSPhilip Rakity 4499bad37e1aSPhilip Rakity curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT); 4500bad37e1aSPhilip Rakity max_current_caps = 4501804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, curr) | 4502804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, curr) | 4503804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, curr); 4504bad37e1aSPhilip Rakity } 4505bad37e1aSPhilip Rakity } 4506f2119df6SArindam Nath 450728da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_330) { 45088f230f45STakashi Iwai ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; 4509f2119df6SArindam Nath 4510804a65b3SMasahiro Yamada mmc->max_current_330 = FIELD_GET(SDHCI_MAX_CURRENT_330_MASK, 4511804a65b3SMasahiro Yamada max_current_caps) * 4512f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4513f2119df6SArindam Nath } 451428da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_300) { 45158f230f45STakashi Iwai ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; 4516f2119df6SArindam Nath 4517804a65b3SMasahiro Yamada mmc->max_current_300 = FIELD_GET(SDHCI_MAX_CURRENT_300_MASK, 4518804a65b3SMasahiro Yamada max_current_caps) * 4519f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4520f2119df6SArindam Nath } 452128da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_180) { 45228f230f45STakashi Iwai ocr_avail |= MMC_VDD_165_195; 45238f230f45STakashi Iwai 4524804a65b3SMasahiro Yamada mmc->max_current_180 = FIELD_GET(SDHCI_MAX_CURRENT_180_MASK, 4525804a65b3SMasahiro Yamada max_current_caps) * 4526f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER; 4527f2119df6SArindam Nath } 4528f2119df6SArindam Nath 45295fd26c7eSUlf Hansson /* If OCR set by host, use it instead. */ 45305fd26c7eSUlf Hansson if (host->ocr_mask) 45315fd26c7eSUlf Hansson ocr_avail = host->ocr_mask; 45325fd26c7eSUlf Hansson 45335fd26c7eSUlf Hansson /* If OCR set by external regulators, give it highest prio. */ 45343a48edc4STim Kryger if (mmc->ocr_avail) 453552221610STim Kryger ocr_avail = mmc->ocr_avail; 45363a48edc4STim Kryger 45378f230f45STakashi Iwai mmc->ocr_avail = ocr_avail; 45388f230f45STakashi Iwai mmc->ocr_avail_sdio = ocr_avail; 45398f230f45STakashi Iwai if (host->ocr_avail_sdio) 45408f230f45STakashi Iwai mmc->ocr_avail_sdio &= host->ocr_avail_sdio; 45418f230f45STakashi Iwai mmc->ocr_avail_sd = ocr_avail; 45428f230f45STakashi Iwai if (host->ocr_avail_sd) 45438f230f45STakashi Iwai mmc->ocr_avail_sd &= host->ocr_avail_sd; 45448f230f45STakashi Iwai else /* normal SD controllers don't support 1.8V */ 45458f230f45STakashi Iwai mmc->ocr_avail_sd &= ~MMC_VDD_165_195; 45468f230f45STakashi Iwai mmc->ocr_avail_mmc = ocr_avail; 45478f230f45STakashi Iwai if (host->ocr_avail_mmc) 45488f230f45STakashi Iwai mmc->ocr_avail_mmc &= host->ocr_avail_mmc; 45491c6a0718SPierre Ossman 45501c6a0718SPierre Ossman if (mmc->ocr_avail == 0) { 45512e4456f0SMarek Vasut pr_err("%s: Hardware doesn't report any support voltages.\n", 45522e4456f0SMarek Vasut mmc_hostname(mmc)); 4553eb5c20deSAdrian Hunter ret = -ENODEV; 4554eb5c20deSAdrian Hunter goto unreg; 45551c6a0718SPierre Ossman } 45561c6a0718SPierre Ossman 45578cb851a4SAdrian Hunter if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | 45588cb851a4SAdrian Hunter MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | 45598cb851a4SAdrian Hunter MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) || 45608cb851a4SAdrian Hunter (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V))) 45618cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_180; 45628cb851a4SAdrian Hunter 45638cb851a4SAdrian Hunter if (mmc->caps2 & MMC_CAP2_HSX00_1_2V) 45648cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_120; 45658cb851a4SAdrian Hunter 45661c6a0718SPierre Ossman spin_lock_init(&host->lock); 45671c6a0718SPierre Ossman 45681c6a0718SPierre Ossman /* 4569ac00531dSAdrian Hunter * Maximum number of sectors in one transfer. Limited by SDMA boundary 4570ac00531dSAdrian Hunter * size (512KiB). Note some tuning modes impose a 4MiB limit, but this 4571ac00531dSAdrian Hunter * is less anyway. 45721c6a0718SPierre Ossman */ 45731c6a0718SPierre Ossman mmc->max_req_size = 524288; 45741c6a0718SPierre Ossman 45751c6a0718SPierre Ossman /* 4576250dcd11SUlf Hansson * Maximum number of segments. Depends on if the hardware 4577250dcd11SUlf Hansson * can do scatter/gather or not. 4578250dcd11SUlf Hansson */ 4579250dcd11SUlf Hansson if (host->flags & SDHCI_USE_ADMA) { 4580250dcd11SUlf Hansson mmc->max_segs = SDHCI_MAX_SEGS; 4581250dcd11SUlf Hansson } else if (host->flags & SDHCI_USE_SDMA) { 4582250dcd11SUlf Hansson mmc->max_segs = 1; 4583250dcd11SUlf Hansson if (swiotlb_max_segment()) { 4584250dcd11SUlf Hansson unsigned int max_req_size = (1 << IO_TLB_SHIFT) * 4585250dcd11SUlf Hansson IO_TLB_SEGSIZE; 4586250dcd11SUlf Hansson mmc->max_req_size = min(mmc->max_req_size, 4587250dcd11SUlf Hansson max_req_size); 4588250dcd11SUlf Hansson } 4589250dcd11SUlf Hansson } else { /* PIO */ 4590250dcd11SUlf Hansson mmc->max_segs = SDHCI_MAX_SEGS; 4591250dcd11SUlf Hansson } 4592250dcd11SUlf Hansson 4593250dcd11SUlf Hansson /* 45941c6a0718SPierre Ossman * Maximum segment size. Could be one segment with the maximum number 45952134a922SPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot 45962134a922SPierre Ossman * be larger than 64 KiB though. 45971c6a0718SPierre Ossman */ 459830652aa3SOlof Johansson if (host->flags & SDHCI_USE_ADMA) { 459930652aa3SOlof Johansson if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) 460030652aa3SOlof Johansson mmc->max_seg_size = 65535; 46012134a922SPierre Ossman else 460230652aa3SOlof Johansson mmc->max_seg_size = 65536; 460330652aa3SOlof Johansson } else { 46041c6a0718SPierre Ossman mmc->max_seg_size = mmc->max_req_size; 460530652aa3SOlof Johansson } 46061c6a0718SPierre Ossman 46071c6a0718SPierre Ossman /* 46081c6a0718SPierre Ossman * Maximum block size. This varies from controller to controller and 46091c6a0718SPierre Ossman * is specified in the capabilities register. 46101c6a0718SPierre Ossman */ 46110633f654SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { 46120633f654SAnton Vorontsov mmc->max_blk_size = 2; 46130633f654SAnton Vorontsov } else { 461428da3589SAdrian Hunter mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >> 46150633f654SAnton Vorontsov SDHCI_MAX_BLOCK_SHIFT; 46161c6a0718SPierre Ossman if (mmc->max_blk_size >= 3) { 46176606110dSJoe Perches pr_warn("%s: Invalid maximum block size, assuming 512 bytes\n", 46186606110dSJoe Perches mmc_hostname(mmc)); 46190633f654SAnton Vorontsov mmc->max_blk_size = 0; 46200633f654SAnton Vorontsov } 46210633f654SAnton Vorontsov } 46220633f654SAnton Vorontsov 46231c6a0718SPierre Ossman mmc->max_blk_size = 512 << mmc->max_blk_size; 46241c6a0718SPierre Ossman 46251c6a0718SPierre Ossman /* 46261c6a0718SPierre Ossman * Maximum block count. 46271c6a0718SPierre Ossman */ 46281388eefdSBen Dooks mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; 46291c6a0718SPierre Ossman 4630a68dd9a0SChunyan Zhang if (mmc->max_segs == 1) 4631bd9b9027SLinus Walleij /* This may alter mmc->*_blk_* parameters */ 4632a68dd9a0SChunyan Zhang sdhci_allocate_bounce_buffer(host); 4633bd9b9027SLinus Walleij 463452f5336dSAdrian Hunter return 0; 463552f5336dSAdrian Hunter 463652f5336dSAdrian Hunter unreg: 46370fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 463852f5336dSAdrian Hunter regulator_disable(mmc->supply.vqmmc); 463952f5336dSAdrian Hunter undma: 464052f5336dSAdrian Hunter if (host->align_buffer) 464152f5336dSAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 464252f5336dSAdrian Hunter host->adma_table_sz, host->align_buffer, 464352f5336dSAdrian Hunter host->align_addr); 464452f5336dSAdrian Hunter host->adma_table = NULL; 464552f5336dSAdrian Hunter host->align_buffer = NULL; 464652f5336dSAdrian Hunter 464752f5336dSAdrian Hunter return ret; 464852f5336dSAdrian Hunter } 464952f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_setup_host); 465052f5336dSAdrian Hunter 46514180ffa8SAdrian Hunter void sdhci_cleanup_host(struct sdhci_host *host) 46524180ffa8SAdrian Hunter { 46534180ffa8SAdrian Hunter struct mmc_host *mmc = host->mmc; 46544180ffa8SAdrian Hunter 46550fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 46564180ffa8SAdrian Hunter regulator_disable(mmc->supply.vqmmc); 46574180ffa8SAdrian Hunter 46584180ffa8SAdrian Hunter if (host->align_buffer) 46594180ffa8SAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 46604180ffa8SAdrian Hunter host->adma_table_sz, host->align_buffer, 46614180ffa8SAdrian Hunter host->align_addr); 466218e762e3SChunyan Zhang 466318e762e3SChunyan Zhang if (host->use_external_dma) 466418e762e3SChunyan Zhang sdhci_external_dma_release(host); 466518e762e3SChunyan Zhang 46664180ffa8SAdrian Hunter host->adma_table = NULL; 46674180ffa8SAdrian Hunter host->align_buffer = NULL; 46684180ffa8SAdrian Hunter } 46694180ffa8SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cleanup_host); 46704180ffa8SAdrian Hunter 467152f5336dSAdrian Hunter int __sdhci_add_host(struct sdhci_host *host) 467252f5336dSAdrian Hunter { 4673c07a48c2SAdrian Hunter unsigned int flags = WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI; 467452f5336dSAdrian Hunter struct mmc_host *mmc = host->mmc; 467552f5336dSAdrian Hunter int ret; 467652f5336dSAdrian Hunter 46772b17b8d7SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_CQE) && 46782b17b8d7SAdrian Hunter (host->quirks & SDHCI_QUIRK_BROKEN_CQE)) { 46792b17b8d7SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_CQE; 46802b17b8d7SAdrian Hunter mmc->cqe_ops = NULL; 46812b17b8d7SAdrian Hunter } 46822b17b8d7SAdrian Hunter 4683c07a48c2SAdrian Hunter host->complete_wq = alloc_workqueue("sdhci", flags, 0); 4684c07a48c2SAdrian Hunter if (!host->complete_wq) 4685c07a48c2SAdrian Hunter return -ENOMEM; 4686c07a48c2SAdrian Hunter 4687c07a48c2SAdrian Hunter INIT_WORK(&host->complete_work, sdhci_complete_work); 46881c6a0718SPierre Ossman 46892ee4f620SKees Cook timer_setup(&host->timer, sdhci_timeout_timer, 0); 46902ee4f620SKees Cook timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0); 46911c6a0718SPierre Ossman 4692b513ea25SArindam Nath init_waitqueue_head(&host->buf_ready_int); 4693b513ea25SArindam Nath 46942af502caSShawn Guo sdhci_init(host, 0); 46952af502caSShawn Guo 4696781e989cSRussell King ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, 4697781e989cSRussell King IRQF_SHARED, mmc_hostname(mmc), host); 46980fc81ee3SMark Brown if (ret) { 46990fc81ee3SMark Brown pr_err("%s: Failed to request IRQ %d: %d\n", 47000fc81ee3SMark Brown mmc_hostname(mmc), host->irq, ret); 4701c07a48c2SAdrian Hunter goto unwq; 47020fc81ee3SMark Brown } 47031c6a0718SPierre Ossman 4704061d17a6SAdrian Hunter ret = sdhci_led_register(host); 47050fc81ee3SMark Brown if (ret) { 47060fc81ee3SMark Brown pr_err("%s: Failed to register LED device: %d\n", 47070fc81ee3SMark Brown mmc_hostname(mmc), ret); 4708eb5c20deSAdrian Hunter goto unirq; 47090fc81ee3SMark Brown } 47102f730fecSPierre Ossman 4711eb5c20deSAdrian Hunter ret = mmc_add_host(mmc); 4712eb5c20deSAdrian Hunter if (ret) 4713eb5c20deSAdrian Hunter goto unled; 47141c6a0718SPierre Ossman 4715a3c76eb9SGirish K S pr_info("%s: SDHCI controller on %s [%s] using %s\n", 4716d1b26863SKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), 471718e762e3SChunyan Zhang host->use_external_dma ? "External DMA" : 4718e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_ADMA) ? 4719e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" : 4720a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); 47211c6a0718SPierre Ossman 47227260cf5eSAnton Vorontsov sdhci_enable_card_detection(host); 47237260cf5eSAnton Vorontsov 47241c6a0718SPierre Ossman return 0; 47251c6a0718SPierre Ossman 4726eb5c20deSAdrian Hunter unled: 4727061d17a6SAdrian Hunter sdhci_led_unregister(host); 4728eb5c20deSAdrian Hunter unirq: 472903231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_ALL); 4730b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 4731b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 47322f730fecSPierre Ossman free_irq(host->irq, host); 4733c07a48c2SAdrian Hunter unwq: 4734c07a48c2SAdrian Hunter destroy_workqueue(host->complete_wq); 473552f5336dSAdrian Hunter 47361c6a0718SPierre Ossman return ret; 47371c6a0718SPierre Ossman } 473852f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_add_host); 47391c6a0718SPierre Ossman 474052f5336dSAdrian Hunter int sdhci_add_host(struct sdhci_host *host) 474152f5336dSAdrian Hunter { 474252f5336dSAdrian Hunter int ret; 474352f5336dSAdrian Hunter 474452f5336dSAdrian Hunter ret = sdhci_setup_host(host); 474552f5336dSAdrian Hunter if (ret) 474652f5336dSAdrian Hunter return ret; 474752f5336dSAdrian Hunter 47484180ffa8SAdrian Hunter ret = __sdhci_add_host(host); 47494180ffa8SAdrian Hunter if (ret) 47504180ffa8SAdrian Hunter goto cleanup; 47514180ffa8SAdrian Hunter 47524180ffa8SAdrian Hunter return 0; 47534180ffa8SAdrian Hunter 47544180ffa8SAdrian Hunter cleanup: 47554180ffa8SAdrian Hunter sdhci_cleanup_host(host); 47564180ffa8SAdrian Hunter 47574180ffa8SAdrian Hunter return ret; 475852f5336dSAdrian Hunter } 4759b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_add_host); 4760b8c86fc5SPierre Ossman 47611e72859eSPierre Ossman void sdhci_remove_host(struct sdhci_host *host, int dead) 47621c6a0718SPierre Ossman { 47633a48edc4STim Kryger struct mmc_host *mmc = host->mmc; 47641e72859eSPierre Ossman unsigned long flags; 47651e72859eSPierre Ossman 47661e72859eSPierre Ossman if (dead) { 47671e72859eSPierre Ossman spin_lock_irqsave(&host->lock, flags); 47681e72859eSPierre Ossman 47691e72859eSPierre Ossman host->flags |= SDHCI_DEVICE_DEAD; 47701e72859eSPierre Ossman 47715d0d11c5SAdrian Hunter if (sdhci_has_requests(host)) { 4772a3c76eb9SGirish K S pr_err("%s: Controller removed during " 47734e743f1fSMarkus Mayer " transfer!\n", mmc_hostname(mmc)); 47745d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM); 47751e72859eSPierre Ossman } 47761e72859eSPierre Ossman 47771e72859eSPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 47781e72859eSPierre Ossman } 47791e72859eSPierre Ossman 47807260cf5eSAnton Vorontsov sdhci_disable_card_detection(host); 47817260cf5eSAnton Vorontsov 47824e743f1fSMarkus Mayer mmc_remove_host(mmc); 47831c6a0718SPierre Ossman 4784061d17a6SAdrian Hunter sdhci_led_unregister(host); 47852f730fecSPierre Ossman 47861e72859eSPierre Ossman if (!dead) 478703231f9bSRussell King sdhci_do_reset(host, SDHCI_RESET_ALL); 47881c6a0718SPierre Ossman 4789b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE); 4790b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); 47911c6a0718SPierre Ossman free_irq(host->irq, host); 47921c6a0718SPierre Ossman 47931c6a0718SPierre Ossman del_timer_sync(&host->timer); 4794d7422fb4SAdrian Hunter del_timer_sync(&host->data_timer); 47951c6a0718SPierre Ossman 4796c07a48c2SAdrian Hunter destroy_workqueue(host->complete_wq); 47972134a922SPierre Ossman 47980fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc) 47993a48edc4STim Kryger regulator_disable(mmc->supply.vqmmc); 48006231f3deSPhilip Rakity 4801edd63fccSRussell King if (host->align_buffer) 4802e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + 4803e66e61cbSRussell King host->adma_table_sz, host->align_buffer, 4804e66e61cbSRussell King host->align_addr); 48052134a922SPierre Ossman 480618e762e3SChunyan Zhang if (host->use_external_dma) 480718e762e3SChunyan Zhang sdhci_external_dma_release(host); 480818e762e3SChunyan Zhang 48094efaa6fbSAdrian Hunter host->adma_table = NULL; 48102134a922SPierre Ossman host->align_buffer = NULL; 48111c6a0718SPierre Ossman } 48121c6a0718SPierre Ossman 4813b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_remove_host); 4814b8c86fc5SPierre Ossman 4815b8c86fc5SPierre Ossman void sdhci_free_host(struct sdhci_host *host) 48161c6a0718SPierre Ossman { 4817b8c86fc5SPierre Ossman mmc_free_host(host->mmc); 48181c6a0718SPierre Ossman } 48191c6a0718SPierre Ossman 4820b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_free_host); 48211c6a0718SPierre Ossman 48221c6a0718SPierre Ossman /*****************************************************************************\ 48231c6a0718SPierre Ossman * * 48241c6a0718SPierre Ossman * Driver init/exit * 48251c6a0718SPierre Ossman * * 48261c6a0718SPierre Ossman \*****************************************************************************/ 48271c6a0718SPierre Ossman 48281c6a0718SPierre Ossman static int __init sdhci_drv_init(void) 48291c6a0718SPierre Ossman { 4830a3c76eb9SGirish K S pr_info(DRIVER_NAME 48311c6a0718SPierre Ossman ": Secure Digital Host Controller Interface driver\n"); 4832a3c76eb9SGirish K S pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); 48331c6a0718SPierre Ossman 4834b8c86fc5SPierre Ossman return 0; 48351c6a0718SPierre Ossman } 48361c6a0718SPierre Ossman 48371c6a0718SPierre Ossman static void __exit sdhci_drv_exit(void) 48381c6a0718SPierre Ossman { 48391c6a0718SPierre Ossman } 48401c6a0718SPierre Ossman 48411c6a0718SPierre Ossman module_init(sdhci_drv_init); 48421c6a0718SPierre Ossman module_exit(sdhci_drv_exit); 48431c6a0718SPierre Ossman 48441c6a0718SPierre Ossman module_param(debug_quirks, uint, 0444); 484566fd8ad5SAdrian Hunter module_param(debug_quirks2, uint, 0444); 48461c6a0718SPierre Ossman 484732710e8fSPierre Ossman MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); 4848b8c86fc5SPierre Ossman MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); 48491c6a0718SPierre Ossman MODULE_LICENSE("GPL"); 48501c6a0718SPierre Ossman 48511c6a0718SPierre Ossman MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); 485266fd8ad5SAdrian Hunter MODULE_PARM_DESC(debug_quirks2, "Force certain other quirks."); 4853