12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21c6a0718SPierre Ossman /*
370f10482SPierre Ossman * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
41c6a0718SPierre Ossman *
5b69c9058SPierre Ossman * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
61c6a0718SPierre Ossman *
784c46a53SPierre Ossman * Thanks to the following companies for their support:
884c46a53SPierre Ossman *
984c46a53SPierre Ossman * - JMicron (hardware and technical support)
101c6a0718SPierre Ossman */
111c6a0718SPierre Ossman
12fa091010SMasahiro Yamada #include <linux/bitfield.h>
131c6a0718SPierre Ossman #include <linux/delay.h>
1418e762e3SChunyan Zhang #include <linux/dmaengine.h>
155a436cc0SAdrian Hunter #include <linux/ktime.h>
161c6a0718SPierre Ossman #include <linux/highmem.h>
17b8c86fc5SPierre Ossman #include <linux/io.h>
1888b47679SPaul Gortmaker #include <linux/module.h>
191c6a0718SPierre Ossman #include <linux/dma-mapping.h>
205a0e3ad6STejun Heo #include <linux/slab.h>
2111763609SRalf Baechle #include <linux/scatterlist.h>
22bd9b9027SLinus Walleij #include <linux/sizes.h>
239bea3c85SMarek Szyprowski #include <linux/regulator/consumer.h>
2466fd8ad5SAdrian Hunter #include <linux/pm_runtime.h>
2592e0c44bSZach Brown #include <linux/of.h>
261c6a0718SPierre Ossman
272f730fecSPierre Ossman #include <linux/leds.h>
282f730fecSPierre Ossman
2922113efdSAries Lee #include <linux/mmc/mmc.h>
301c6a0718SPierre Ossman #include <linux/mmc/host.h>
31473b095aSAaron Lu #include <linux/mmc/card.h>
3285cc1c33SCorneliu Doban #include <linux/mmc/sdio.h>
33bec9d4e5SGuennadi Liakhovetski #include <linux/mmc/slot-gpio.h>
341c6a0718SPierre Ossman
351c6a0718SPierre Ossman #include "sdhci.h"
361c6a0718SPierre Ossman
371c6a0718SPierre Ossman #define DRIVER_NAME "sdhci"
381c6a0718SPierre Ossman
391c6a0718SPierre Ossman #define DBG(f, x...) \
40f421865dSAdrian Hunter pr_debug("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x)
411c6a0718SPierre Ossman
4285ad90e2SAdrian Hunter #define SDHCI_DUMP(f, x...) \
4385ad90e2SAdrian Hunter pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x)
4485ad90e2SAdrian Hunter
45b513ea25SArindam Nath #define MAX_TUNING_LOOP 40
46b513ea25SArindam Nath
471c6a0718SPierre Ossman static unsigned int debug_quirks = 0;
4866fd8ad5SAdrian Hunter static unsigned int debug_quirks2;
491c6a0718SPierre Ossman
5052983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
511c6a0718SPierre Ossman
52845c939eSAdrian Hunter static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd);
53a374a72bSAdrian Hunter
sdhci_dumpregs(struct sdhci_host * host)54d2898172SAdrian Hunter void sdhci_dumpregs(struct sdhci_host *host)
551c6a0718SPierre Ossman {
5685ad90e2SAdrian Hunter SDHCI_DUMP("============ SDHCI REGISTER DUMP ===========\n");
571c6a0718SPierre Ossman
5885ad90e2SAdrian Hunter SDHCI_DUMP("Sys addr: 0x%08x | Version: 0x%08x\n",
594e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_DMA_ADDRESS),
604e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_HOST_VERSION));
6185ad90e2SAdrian Hunter SDHCI_DUMP("Blk size: 0x%08x | Blk cnt: 0x%08x\n",
624e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_SIZE),
634e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_BLOCK_COUNT));
6485ad90e2SAdrian Hunter SDHCI_DUMP("Argument: 0x%08x | Trn mode: 0x%08x\n",
654e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_ARGUMENT),
664e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_TRANSFER_MODE));
6785ad90e2SAdrian Hunter SDHCI_DUMP("Present: 0x%08x | Host ctl: 0x%08x\n",
684e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_PRESENT_STATE),
694e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_HOST_CONTROL));
7085ad90e2SAdrian Hunter SDHCI_DUMP("Power: 0x%08x | Blk gap: 0x%08x\n",
714e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_POWER_CONTROL),
724e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
7385ad90e2SAdrian Hunter SDHCI_DUMP("Wake-up: 0x%08x | Clock: 0x%08x\n",
744e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_WAKE_UP_CONTROL),
754e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_CLOCK_CONTROL));
7685ad90e2SAdrian Hunter SDHCI_DUMP("Timeout: 0x%08x | Int stat: 0x%08x\n",
774e4141a5SAnton Vorontsov sdhci_readb(host, SDHCI_TIMEOUT_CONTROL),
784e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_STATUS));
7985ad90e2SAdrian Hunter SDHCI_DUMP("Int enab: 0x%08x | Sig enab: 0x%08x\n",
804e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_INT_ENABLE),
814e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
82869f8a69SAdrian Hunter SDHCI_DUMP("ACmd stat: 0x%08x | Slot int: 0x%08x\n",
83869f8a69SAdrian Hunter sdhci_readw(host, SDHCI_AUTO_CMD_STATUS),
844e4141a5SAnton Vorontsov sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
8585ad90e2SAdrian Hunter SDHCI_DUMP("Caps: 0x%08x | Caps_1: 0x%08x\n",
864e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_CAPABILITIES),
87e8120ad1SPhilip Rakity sdhci_readl(host, SDHCI_CAPABILITIES_1));
8885ad90e2SAdrian Hunter SDHCI_DUMP("Cmd: 0x%08x | Max curr: 0x%08x\n",
89e8120ad1SPhilip Rakity sdhci_readw(host, SDHCI_COMMAND),
904e4141a5SAnton Vorontsov sdhci_readl(host, SDHCI_MAX_CURRENT));
9185ad90e2SAdrian Hunter SDHCI_DUMP("Resp[0]: 0x%08x | Resp[1]: 0x%08x\n",
927962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE),
937962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 4));
9485ad90e2SAdrian Hunter SDHCI_DUMP("Resp[2]: 0x%08x | Resp[3]: 0x%08x\n",
957962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 8),
967962302fSAdrian Hunter sdhci_readl(host, SDHCI_RESPONSE + 12));
9785ad90e2SAdrian Hunter SDHCI_DUMP("Host ctl2: 0x%08x\n",
98f2119df6SArindam Nath sdhci_readw(host, SDHCI_HOST_CONTROL2));
991c6a0718SPierre Ossman
100e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_ADMA) {
10185ad90e2SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA) {
10285ad90e2SAdrian Hunter SDHCI_DUMP("ADMA Err: 0x%08x | ADMA Ptr: 0x%08x%08x\n",
103c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ERROR),
104c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS_HI),
105c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS));
10685ad90e2SAdrian Hunter } else {
10785ad90e2SAdrian Hunter SDHCI_DUMP("ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
108c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ERROR),
109c71024deSAdrian Hunter sdhci_readl(host, SDHCI_ADMA_ADDRESS));
110e57a5f61SAdrian Hunter }
11185ad90e2SAdrian Hunter }
112be3f4ae0SBen Dooks
113d1fe0762SSarthak Garg if (host->ops->dump_vendor_regs)
114d1fe0762SSarthak Garg host->ops->dump_vendor_regs(host);
115d1fe0762SSarthak Garg
11685ad90e2SAdrian Hunter SDHCI_DUMP("============================================\n");
1171c6a0718SPierre Ossman }
118d2898172SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_dumpregs);
1191c6a0718SPierre Ossman
1201c6a0718SPierre Ossman /*****************************************************************************\
1211c6a0718SPierre Ossman * *
1221c6a0718SPierre Ossman * Low level functions *
1231c6a0718SPierre Ossman * *
1241c6a0718SPierre Ossman \*****************************************************************************/
1251c6a0718SPierre Ossman
sdhci_do_enable_v4_mode(struct sdhci_host * host)126b3f80b43SChunyan Zhang static void sdhci_do_enable_v4_mode(struct sdhci_host *host)
127b3f80b43SChunyan Zhang {
128b3f80b43SChunyan Zhang u16 ctrl2;
129b3f80b43SChunyan Zhang
13097207c12SSowjanya Komatineni ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
131b3f80b43SChunyan Zhang if (ctrl2 & SDHCI_CTRL_V4_MODE)
132b3f80b43SChunyan Zhang return;
133b3f80b43SChunyan Zhang
134b3f80b43SChunyan Zhang ctrl2 |= SDHCI_CTRL_V4_MODE;
13597207c12SSowjanya Komatineni sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
136b3f80b43SChunyan Zhang }
137b3f80b43SChunyan Zhang
138b3f80b43SChunyan Zhang /*
139b3f80b43SChunyan Zhang * This can be called before sdhci_add_host() by Vendor's host controller
140b3f80b43SChunyan Zhang * driver to enable v4 mode if supported.
141b3f80b43SChunyan Zhang */
sdhci_enable_v4_mode(struct sdhci_host * host)142b3f80b43SChunyan Zhang void sdhci_enable_v4_mode(struct sdhci_host *host)
143b3f80b43SChunyan Zhang {
144b3f80b43SChunyan Zhang host->v4_mode = true;
145b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host);
146b3f80b43SChunyan Zhang }
147b3f80b43SChunyan Zhang EXPORT_SYMBOL_GPL(sdhci_enable_v4_mode);
148b3f80b43SChunyan Zhang
sdhci_data_line_cmd(struct mmc_command * cmd)14956a590dcSAdrian Hunter static inline bool sdhci_data_line_cmd(struct mmc_command *cmd)
15056a590dcSAdrian Hunter {
15156a590dcSAdrian Hunter return cmd->data || cmd->flags & MMC_RSP_BUSY;
15256a590dcSAdrian Hunter }
15356a590dcSAdrian Hunter
sdhci_set_card_detection(struct sdhci_host * host,bool enable)1547260cf5eSAnton Vorontsov static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
1557260cf5eSAnton Vorontsov {
1565b4f1f6cSRussell King u32 present;
1577260cf5eSAnton Vorontsov
158c79396c1SAdrian Hunter if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
159e65bb388SHaibo Chen !mmc_card_is_removable(host->mmc) || mmc_can_gpio_cd(host->mmc))
16066fd8ad5SAdrian Hunter return;
16166fd8ad5SAdrian Hunter
1625b4f1f6cSRussell King if (enable) {
163d25928d1SShawn Guo present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
164d25928d1SShawn Guo SDHCI_CARD_PRESENT;
165d25928d1SShawn Guo
1665b4f1f6cSRussell King host->ier |= present ? SDHCI_INT_CARD_REMOVE :
1675b4f1f6cSRussell King SDHCI_INT_CARD_INSERT;
1685b4f1f6cSRussell King } else {
1695b4f1f6cSRussell King host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
1705b4f1f6cSRussell King }
171b537f94cSRussell King
172b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
173b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
1747260cf5eSAnton Vorontsov }
1757260cf5eSAnton Vorontsov
sdhci_enable_card_detection(struct sdhci_host * host)1767260cf5eSAnton Vorontsov static void sdhci_enable_card_detection(struct sdhci_host *host)
1777260cf5eSAnton Vorontsov {
1787260cf5eSAnton Vorontsov sdhci_set_card_detection(host, true);
1797260cf5eSAnton Vorontsov }
1807260cf5eSAnton Vorontsov
sdhci_disable_card_detection(struct sdhci_host * host)1817260cf5eSAnton Vorontsov static void sdhci_disable_card_detection(struct sdhci_host *host)
1827260cf5eSAnton Vorontsov {
1837260cf5eSAnton Vorontsov sdhci_set_card_detection(host, false);
1847260cf5eSAnton Vorontsov }
1857260cf5eSAnton Vorontsov
sdhci_runtime_pm_bus_on(struct sdhci_host * host)18602d0b685SUlf Hansson static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
18702d0b685SUlf Hansson {
18802d0b685SUlf Hansson if (host->bus_on)
18902d0b685SUlf Hansson return;
19002d0b685SUlf Hansson host->bus_on = true;
191bac53336SJisheng Zhang pm_runtime_get_noresume(mmc_dev(host->mmc));
19202d0b685SUlf Hansson }
19302d0b685SUlf Hansson
sdhci_runtime_pm_bus_off(struct sdhci_host * host)19402d0b685SUlf Hansson static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
19502d0b685SUlf Hansson {
19602d0b685SUlf Hansson if (!host->bus_on)
19702d0b685SUlf Hansson return;
19802d0b685SUlf Hansson host->bus_on = false;
199bac53336SJisheng Zhang pm_runtime_put_noidle(mmc_dev(host->mmc));
20002d0b685SUlf Hansson }
20102d0b685SUlf Hansson
sdhci_reset(struct sdhci_host * host,u8 mask)20203231f9bSRussell King void sdhci_reset(struct sdhci_host *host, u8 mask)
2031c6a0718SPierre Ossman {
2045a436cc0SAdrian Hunter ktime_t timeout;
205393c1a34SPhilip Rakity
2064e4141a5SAnton Vorontsov sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
2071c6a0718SPierre Ossman
208f0710a55SAdrian Hunter if (mask & SDHCI_RESET_ALL) {
2091c6a0718SPierre Ossman host->clock = 0;
210f0710a55SAdrian Hunter /* Reset-all turns off SD Bus Power */
211f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
212f0710a55SAdrian Hunter sdhci_runtime_pm_bus_off(host);
213f0710a55SAdrian Hunter }
2141c6a0718SPierre Ossman
2151c6a0718SPierre Ossman /* Wait max 100 ms */
2165a436cc0SAdrian Hunter timeout = ktime_add_ms(ktime_get(), 100);
2171c6a0718SPierre Ossman
2181c6a0718SPierre Ossman /* hw clears the bit when it's done */
219b704441eSAlek Du while (1) {
220b704441eSAlek Du bool timedout = ktime_after(ktime_get(), timeout);
221b704441eSAlek Du
222b704441eSAlek Du if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask))
223b704441eSAlek Du break;
224b704441eSAlek Du if (timedout) {
225a3c76eb9SGirish K S pr_err("%s: Reset 0x%x never completed.\n",
2261c6a0718SPierre Ossman mmc_hostname(host->mmc), (int)mask);
227efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT);
2281c6a0718SPierre Ossman sdhci_dumpregs(host);
2291c6a0718SPierre Ossman return;
2301c6a0718SPierre Ossman }
2315a436cc0SAdrian Hunter udelay(10);
2321c6a0718SPierre Ossman }
23303231f9bSRussell King }
23403231f9bSRussell King EXPORT_SYMBOL_GPL(sdhci_reset);
235063a9dbbSAnton Vorontsov
sdhci_do_reset(struct sdhci_host * host,u8 mask)236aa990722SAdrian Hunter static bool sdhci_do_reset(struct sdhci_host *host, u8 mask)
23703231f9bSRussell King {
23803231f9bSRussell King if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
239d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc;
240d3940f27SAdrian Hunter
241d3940f27SAdrian Hunter if (!mmc->ops->get_cd(mmc))
242aa990722SAdrian Hunter return false;
24303231f9bSRussell King }
24403231f9bSRussell King
24503231f9bSRussell King host->ops->reset(host, mask);
246393c1a34SPhilip Rakity
247aa990722SAdrian Hunter return true;
248aa990722SAdrian Hunter }
249aa990722SAdrian Hunter
sdhci_reset_for_all(struct sdhci_host * host)250aa990722SAdrian Hunter static void sdhci_reset_for_all(struct sdhci_host *host)
251aa990722SAdrian Hunter {
252aa990722SAdrian Hunter if (sdhci_do_reset(host, SDHCI_RESET_ALL)) {
2533abc1e80SShaohui Xie if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
254da91a8f9SRussell King if (host->ops->enable_dma)
2553abc1e80SShaohui Xie host->ops->enable_dma(host);
2563abc1e80SShaohui Xie }
257da91a8f9SRussell King /* Resetting the controller clears many */
258da91a8f9SRussell King host->preset_enabled = false;
259da91a8f9SRussell King }
2601c6a0718SPierre Ossman }
2611c6a0718SPierre Ossman
2621e63d297SAdrian Hunter enum sdhci_reset_reason {
2631e63d297SAdrian Hunter SDHCI_RESET_FOR_INIT,
2641e63d297SAdrian Hunter SDHCI_RESET_FOR_REQUEST_ERROR,
2651e63d297SAdrian Hunter SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY,
2661e63d297SAdrian Hunter SDHCI_RESET_FOR_TUNING_ABORT,
2671e63d297SAdrian Hunter SDHCI_RESET_FOR_CARD_REMOVED,
2681e63d297SAdrian Hunter SDHCI_RESET_FOR_CQE_RECOVERY,
2691e63d297SAdrian Hunter };
2701e63d297SAdrian Hunter
sdhci_reset_for_reason(struct sdhci_host * host,enum sdhci_reset_reason reason)2711e63d297SAdrian Hunter static void sdhci_reset_for_reason(struct sdhci_host *host, enum sdhci_reset_reason reason)
2721e63d297SAdrian Hunter {
273acc13958SPrathamesh Shete if (host->quirks2 & SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER) {
274acc13958SPrathamesh Shete sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
275acc13958SPrathamesh Shete return;
276acc13958SPrathamesh Shete }
277acc13958SPrathamesh Shete
2781e63d297SAdrian Hunter switch (reason) {
2791e63d297SAdrian Hunter case SDHCI_RESET_FOR_INIT:
2801e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
2811e63d297SAdrian Hunter break;
2821e63d297SAdrian Hunter case SDHCI_RESET_FOR_REQUEST_ERROR:
2831e63d297SAdrian Hunter case SDHCI_RESET_FOR_TUNING_ABORT:
2841e63d297SAdrian Hunter case SDHCI_RESET_FOR_CARD_REMOVED:
2851e63d297SAdrian Hunter case SDHCI_RESET_FOR_CQE_RECOVERY:
2861e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_CMD);
2871e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA);
2881e63d297SAdrian Hunter break;
2891e63d297SAdrian Hunter case SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY:
2901e63d297SAdrian Hunter sdhci_do_reset(host, SDHCI_RESET_DATA);
2911e63d297SAdrian Hunter break;
2921e63d297SAdrian Hunter }
2931e63d297SAdrian Hunter }
2941e63d297SAdrian Hunter
2951e63d297SAdrian Hunter #define sdhci_reset_for(h, r) sdhci_reset_for_reason((h), SDHCI_RESET_FOR_##r)
2961e63d297SAdrian Hunter
sdhci_set_default_irqs(struct sdhci_host * host)297f5c1ab82SAdrian Hunter static void sdhci_set_default_irqs(struct sdhci_host *host)
2981c6a0718SPierre Ossman {
299b537f94cSRussell King host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
300b537f94cSRussell King SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
301b537f94cSRussell King SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC |
302b537f94cSRussell King SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
303b537f94cSRussell King SDHCI_INT_RESPONSE;
304b537f94cSRussell King
305f37b20ebSDong Aisheng if (host->tuning_mode == SDHCI_TUNING_MODE_2 ||
306f37b20ebSDong Aisheng host->tuning_mode == SDHCI_TUNING_MODE_3)
307f37b20ebSDong Aisheng host->ier |= SDHCI_INT_RETUNE;
308f37b20ebSDong Aisheng
309b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
310b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
311f5c1ab82SAdrian Hunter }
312f5c1ab82SAdrian Hunter
sdhci_config_dma(struct sdhci_host * host)313685e444bSChunyan Zhang static void sdhci_config_dma(struct sdhci_host *host)
314685e444bSChunyan Zhang {
315685e444bSChunyan Zhang u8 ctrl;
316685e444bSChunyan Zhang u16 ctrl2;
317685e444bSChunyan Zhang
318685e444bSChunyan Zhang if (host->version < SDHCI_SPEC_200)
319685e444bSChunyan Zhang return;
320685e444bSChunyan Zhang
321685e444bSChunyan Zhang ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
322685e444bSChunyan Zhang
323685e444bSChunyan Zhang /*
324685e444bSChunyan Zhang * Always adjust the DMA selection as some controllers
325685e444bSChunyan Zhang * (e.g. JMicron) can't do PIO properly when the selection
326685e444bSChunyan Zhang * is ADMA.
327685e444bSChunyan Zhang */
328685e444bSChunyan Zhang ctrl &= ~SDHCI_CTRL_DMA_MASK;
329685e444bSChunyan Zhang if (!(host->flags & SDHCI_REQ_USE_DMA))
330685e444bSChunyan Zhang goto out;
331685e444bSChunyan Zhang
332685e444bSChunyan Zhang /* Note if DMA Select is zero then SDMA is selected */
333685e444bSChunyan Zhang if (host->flags & SDHCI_USE_ADMA)
334685e444bSChunyan Zhang ctrl |= SDHCI_CTRL_ADMA32;
335685e444bSChunyan Zhang
336685e444bSChunyan Zhang if (host->flags & SDHCI_USE_64_BIT_DMA) {
337685e444bSChunyan Zhang /*
338685e444bSChunyan Zhang * If v4 mode, all supported DMA can be 64-bit addressing if
339685e444bSChunyan Zhang * controller supports 64-bit system address, otherwise only
340685e444bSChunyan Zhang * ADMA can support 64-bit addressing.
341685e444bSChunyan Zhang */
342685e444bSChunyan Zhang if (host->v4_mode) {
343685e444bSChunyan Zhang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
344685e444bSChunyan Zhang ctrl2 |= SDHCI_CTRL_64BIT_ADDR;
345685e444bSChunyan Zhang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
346685e444bSChunyan Zhang } else if (host->flags & SDHCI_USE_ADMA) {
347685e444bSChunyan Zhang /*
348685e444bSChunyan Zhang * Don't need to undo SDHCI_CTRL_ADMA32 in order to
349685e444bSChunyan Zhang * set SDHCI_CTRL_ADMA64.
350685e444bSChunyan Zhang */
351685e444bSChunyan Zhang ctrl |= SDHCI_CTRL_ADMA64;
352685e444bSChunyan Zhang }
353685e444bSChunyan Zhang }
354685e444bSChunyan Zhang
355685e444bSChunyan Zhang out:
356685e444bSChunyan Zhang sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
357685e444bSChunyan Zhang }
358685e444bSChunyan Zhang
sdhci_init(struct sdhci_host * host,int soft)359f5c1ab82SAdrian Hunter static void sdhci_init(struct sdhci_host *host, int soft)
360f5c1ab82SAdrian Hunter {
361f5c1ab82SAdrian Hunter struct mmc_host *mmc = host->mmc;
36249769d4dSHaibo Chen unsigned long flags;
363f5c1ab82SAdrian Hunter
364f5c1ab82SAdrian Hunter if (soft)
3651e63d297SAdrian Hunter sdhci_reset_for(host, INIT);
366f5c1ab82SAdrian Hunter else
367aa990722SAdrian Hunter sdhci_reset_for_all(host);
368f5c1ab82SAdrian Hunter
369b3f80b43SChunyan Zhang if (host->v4_mode)
370b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host);
371b3f80b43SChunyan Zhang
37249769d4dSHaibo Chen spin_lock_irqsave(&host->lock, flags);
373f5c1ab82SAdrian Hunter sdhci_set_default_irqs(host);
37449769d4dSHaibo Chen spin_unlock_irqrestore(&host->lock, flags);
3752f4cbb3dSNicolas Pitre
376f12e39dbSAdrian Hunter host->cqe_on = false;
377f12e39dbSAdrian Hunter
3782f4cbb3dSNicolas Pitre if (soft) {
3792f4cbb3dSNicolas Pitre /* force clock reconfiguration */
3802f4cbb3dSNicolas Pitre host->clock = 0;
381c981cdfbSAdrian Hunter host->reinit_uhs = true;
382d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios);
3832f4cbb3dSNicolas Pitre }
3847260cf5eSAnton Vorontsov }
3851c6a0718SPierre Ossman
sdhci_reinit(struct sdhci_host * host)3867260cf5eSAnton Vorontsov static void sdhci_reinit(struct sdhci_host *host)
3877260cf5eSAnton Vorontsov {
388dcaac3f7SRaul E Rangel u32 cd = host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
389dcaac3f7SRaul E Rangel
3902f4cbb3dSNicolas Pitre sdhci_init(host, 0);
3917260cf5eSAnton Vorontsov sdhci_enable_card_detection(host);
392dcaac3f7SRaul E Rangel
393dcaac3f7SRaul E Rangel /*
394dcaac3f7SRaul E Rangel * A change to the card detect bits indicates a change in present state,
395dcaac3f7SRaul E Rangel * refer sdhci_set_card_detection(). A card detect interrupt might have
396dcaac3f7SRaul E Rangel * been missed while the host controller was being reset, so trigger a
397dcaac3f7SRaul E Rangel * rescan to check.
398dcaac3f7SRaul E Rangel */
399dcaac3f7SRaul E Rangel if (cd != (host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT)))
400dcaac3f7SRaul E Rangel mmc_detect_change(host->mmc, msecs_to_jiffies(200));
4011c6a0718SPierre Ossman }
4021c6a0718SPierre Ossman
__sdhci_led_activate(struct sdhci_host * host)403061d17a6SAdrian Hunter static void __sdhci_led_activate(struct sdhci_host *host)
4041c6a0718SPierre Ossman {
4051c6a0718SPierre Ossman u8 ctrl;
4061c6a0718SPierre Ossman
407bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED)
408bd29f58bSAdrian Hunter return;
409bd29f58bSAdrian Hunter
4104e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
4111c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_LED;
4124e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
4131c6a0718SPierre Ossman }
4141c6a0718SPierre Ossman
__sdhci_led_deactivate(struct sdhci_host * host)415061d17a6SAdrian Hunter static void __sdhci_led_deactivate(struct sdhci_host *host)
4161c6a0718SPierre Ossman {
4171c6a0718SPierre Ossman u8 ctrl;
4181c6a0718SPierre Ossman
419bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED)
420bd29f58bSAdrian Hunter return;
421bd29f58bSAdrian Hunter
4224e4141a5SAnton Vorontsov ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
4231c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_LED;
4244e4141a5SAnton Vorontsov sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
4251c6a0718SPierre Ossman }
4261c6a0718SPierre Ossman
4274f78230fSMasahiro Yamada #if IS_REACHABLE(CONFIG_LEDS_CLASS)
sdhci_led_control(struct led_classdev * led,enum led_brightness brightness)4282f730fecSPierre Ossman static void sdhci_led_control(struct led_classdev *led,
4292f730fecSPierre Ossman enum led_brightness brightness)
4302f730fecSPierre Ossman {
4312f730fecSPierre Ossman struct sdhci_host *host = container_of(led, struct sdhci_host, led);
4322f730fecSPierre Ossman unsigned long flags;
4332f730fecSPierre Ossman
4342f730fecSPierre Ossman spin_lock_irqsave(&host->lock, flags);
4352f730fecSPierre Ossman
43666fd8ad5SAdrian Hunter if (host->runtime_suspended)
43766fd8ad5SAdrian Hunter goto out;
43866fd8ad5SAdrian Hunter
4392f730fecSPierre Ossman if (brightness == LED_OFF)
440061d17a6SAdrian Hunter __sdhci_led_deactivate(host);
4412f730fecSPierre Ossman else
442061d17a6SAdrian Hunter __sdhci_led_activate(host);
44366fd8ad5SAdrian Hunter out:
4442f730fecSPierre Ossman spin_unlock_irqrestore(&host->lock, flags);
4452f730fecSPierre Ossman }
446061d17a6SAdrian Hunter
sdhci_led_register(struct sdhci_host * host)447061d17a6SAdrian Hunter static int sdhci_led_register(struct sdhci_host *host)
448061d17a6SAdrian Hunter {
449061d17a6SAdrian Hunter struct mmc_host *mmc = host->mmc;
450061d17a6SAdrian Hunter
451bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED)
452bd29f58bSAdrian Hunter return 0;
453bd29f58bSAdrian Hunter
454061d17a6SAdrian Hunter snprintf(host->led_name, sizeof(host->led_name),
455061d17a6SAdrian Hunter "%s::", mmc_hostname(mmc));
456061d17a6SAdrian Hunter
457061d17a6SAdrian Hunter host->led.name = host->led_name;
458061d17a6SAdrian Hunter host->led.brightness = LED_OFF;
459061d17a6SAdrian Hunter host->led.default_trigger = mmc_hostname(mmc);
460061d17a6SAdrian Hunter host->led.brightness_set = sdhci_led_control;
461061d17a6SAdrian Hunter
462061d17a6SAdrian Hunter return led_classdev_register(mmc_dev(mmc), &host->led);
463061d17a6SAdrian Hunter }
464061d17a6SAdrian Hunter
sdhci_led_unregister(struct sdhci_host * host)465061d17a6SAdrian Hunter static void sdhci_led_unregister(struct sdhci_host *host)
466061d17a6SAdrian Hunter {
467bd29f58bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_NO_LED)
468bd29f58bSAdrian Hunter return;
469bd29f58bSAdrian Hunter
470061d17a6SAdrian Hunter led_classdev_unregister(&host->led);
471061d17a6SAdrian Hunter }
472061d17a6SAdrian Hunter
sdhci_led_activate(struct sdhci_host * host)473061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host)
474061d17a6SAdrian Hunter {
475061d17a6SAdrian Hunter }
476061d17a6SAdrian Hunter
sdhci_led_deactivate(struct sdhci_host * host)477061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host)
478061d17a6SAdrian Hunter {
479061d17a6SAdrian Hunter }
480061d17a6SAdrian Hunter
481061d17a6SAdrian Hunter #else
482061d17a6SAdrian Hunter
sdhci_led_register(struct sdhci_host * host)483061d17a6SAdrian Hunter static inline int sdhci_led_register(struct sdhci_host *host)
484061d17a6SAdrian Hunter {
485061d17a6SAdrian Hunter return 0;
486061d17a6SAdrian Hunter }
487061d17a6SAdrian Hunter
sdhci_led_unregister(struct sdhci_host * host)488061d17a6SAdrian Hunter static inline void sdhci_led_unregister(struct sdhci_host *host)
489061d17a6SAdrian Hunter {
490061d17a6SAdrian Hunter }
491061d17a6SAdrian Hunter
sdhci_led_activate(struct sdhci_host * host)492061d17a6SAdrian Hunter static inline void sdhci_led_activate(struct sdhci_host *host)
493061d17a6SAdrian Hunter {
494061d17a6SAdrian Hunter __sdhci_led_activate(host);
495061d17a6SAdrian Hunter }
496061d17a6SAdrian Hunter
sdhci_led_deactivate(struct sdhci_host * host)497061d17a6SAdrian Hunter static inline void sdhci_led_deactivate(struct sdhci_host *host)
498061d17a6SAdrian Hunter {
499061d17a6SAdrian Hunter __sdhci_led_deactivate(host);
500061d17a6SAdrian Hunter }
501061d17a6SAdrian Hunter
5022f730fecSPierre Ossman #endif
5032f730fecSPierre Ossman
sdhci_mod_timer(struct sdhci_host * host,struct mmc_request * mrq,unsigned long timeout)50497a1abaeSAdrian Hunter static void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq,
50597a1abaeSAdrian Hunter unsigned long timeout)
50697a1abaeSAdrian Hunter {
50797a1abaeSAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd))
50897a1abaeSAdrian Hunter mod_timer(&host->data_timer, timeout);
50997a1abaeSAdrian Hunter else
51097a1abaeSAdrian Hunter mod_timer(&host->timer, timeout);
51197a1abaeSAdrian Hunter }
51297a1abaeSAdrian Hunter
sdhci_del_timer(struct sdhci_host * host,struct mmc_request * mrq)51397a1abaeSAdrian Hunter static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq)
51497a1abaeSAdrian Hunter {
51597a1abaeSAdrian Hunter if (sdhci_data_line_cmd(mrq->cmd))
51697a1abaeSAdrian Hunter del_timer(&host->data_timer);
51797a1abaeSAdrian Hunter else
51897a1abaeSAdrian Hunter del_timer(&host->timer);
51997a1abaeSAdrian Hunter }
52097a1abaeSAdrian Hunter
sdhci_has_requests(struct sdhci_host * host)52197a1abaeSAdrian Hunter static inline bool sdhci_has_requests(struct sdhci_host *host)
52297a1abaeSAdrian Hunter {
52397a1abaeSAdrian Hunter return host->cmd || host->data_cmd;
52497a1abaeSAdrian Hunter }
52597a1abaeSAdrian Hunter
5261c6a0718SPierre Ossman /*****************************************************************************\
5271c6a0718SPierre Ossman * *
5281c6a0718SPierre Ossman * Core functions *
5291c6a0718SPierre Ossman * *
5301c6a0718SPierre Ossman \*****************************************************************************/
5311c6a0718SPierre Ossman
sdhci_read_block_pio(struct sdhci_host * host)5321c6a0718SPierre Ossman static void sdhci_read_block_pio(struct sdhci_host *host)
5331c6a0718SPierre Ossman {
5347659150cSPierre Ossman size_t blksize, len, chunk;
5353f649ab7SKees Cook u32 scratch;
5367659150cSPierre Ossman u8 *buf;
5371c6a0718SPierre Ossman
5381c6a0718SPierre Ossman DBG("PIO reading\n");
5391c6a0718SPierre Ossman
5401c6a0718SPierre Ossman blksize = host->data->blksz;
5417659150cSPierre Ossman chunk = 0;
5421c6a0718SPierre Ossman
5431c6a0718SPierre Ossman while (blksize) {
544bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter));
5457659150cSPierre Ossman
5467659150cSPierre Ossman len = min(host->sg_miter.length, blksize);
5477659150cSPierre Ossman
5487659150cSPierre Ossman blksize -= len;
5497659150cSPierre Ossman host->sg_miter.consumed = len;
5507659150cSPierre Ossman
5517659150cSPierre Ossman buf = host->sg_miter.addr;
5527659150cSPierre Ossman
5537659150cSPierre Ossman while (len) {
5547659150cSPierre Ossman if (chunk == 0) {
5554e4141a5SAnton Vorontsov scratch = sdhci_readl(host, SDHCI_BUFFER);
5567659150cSPierre Ossman chunk = 4;
5571c6a0718SPierre Ossman }
5581c6a0718SPierre Ossman
5597659150cSPierre Ossman *buf = scratch & 0xFF;
5601c6a0718SPierre Ossman
5617659150cSPierre Ossman buf++;
5627659150cSPierre Ossman scratch >>= 8;
5637659150cSPierre Ossman chunk--;
5647659150cSPierre Ossman len--;
5657659150cSPierre Ossman }
5661c6a0718SPierre Ossman }
5671c6a0718SPierre Ossman
5687659150cSPierre Ossman sg_miter_stop(&host->sg_miter);
5691c6a0718SPierre Ossman }
5701c6a0718SPierre Ossman
sdhci_write_block_pio(struct sdhci_host * host)5711c6a0718SPierre Ossman static void sdhci_write_block_pio(struct sdhci_host *host)
5721c6a0718SPierre Ossman {
5737659150cSPierre Ossman size_t blksize, len, chunk;
5747659150cSPierre Ossman u32 scratch;
5757659150cSPierre Ossman u8 *buf;
5761c6a0718SPierre Ossman
5771c6a0718SPierre Ossman DBG("PIO writing\n");
5781c6a0718SPierre Ossman
5791c6a0718SPierre Ossman blksize = host->data->blksz;
5807659150cSPierre Ossman chunk = 0;
5817659150cSPierre Ossman scratch = 0;
5821c6a0718SPierre Ossman
5831c6a0718SPierre Ossman while (blksize) {
584bf3a35acSFabio Estevam BUG_ON(!sg_miter_next(&host->sg_miter));
5851c6a0718SPierre Ossman
5867659150cSPierre Ossman len = min(host->sg_miter.length, blksize);
5871c6a0718SPierre Ossman
5887659150cSPierre Ossman blksize -= len;
5897659150cSPierre Ossman host->sg_miter.consumed = len;
5907659150cSPierre Ossman
5917659150cSPierre Ossman buf = host->sg_miter.addr;
5927659150cSPierre Ossman
5937659150cSPierre Ossman while (len) {
5947659150cSPierre Ossman scratch |= (u32)*buf << (chunk * 8);
5957659150cSPierre Ossman
5967659150cSPierre Ossman buf++;
5977659150cSPierre Ossman chunk++;
5987659150cSPierre Ossman len--;
5997659150cSPierre Ossman
6007659150cSPierre Ossman if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
6014e4141a5SAnton Vorontsov sdhci_writel(host, scratch, SDHCI_BUFFER);
6027659150cSPierre Ossman chunk = 0;
6037659150cSPierre Ossman scratch = 0;
6047659150cSPierre Ossman }
6057659150cSPierre Ossman }
6061c6a0718SPierre Ossman }
6071c6a0718SPierre Ossman
6087659150cSPierre Ossman sg_miter_stop(&host->sg_miter);
6091c6a0718SPierre Ossman }
6101c6a0718SPierre Ossman
sdhci_transfer_pio(struct sdhci_host * host)6111c6a0718SPierre Ossman static void sdhci_transfer_pio(struct sdhci_host *host)
6121c6a0718SPierre Ossman {
6131c6a0718SPierre Ossman u32 mask;
6141c6a0718SPierre Ossman
6157659150cSPierre Ossman if (host->blocks == 0)
6161c6a0718SPierre Ossman return;
6171c6a0718SPierre Ossman
6181c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ)
6191c6a0718SPierre Ossman mask = SDHCI_DATA_AVAILABLE;
6201c6a0718SPierre Ossman else
6211c6a0718SPierre Ossman mask = SDHCI_SPACE_AVAILABLE;
6221c6a0718SPierre Ossman
6234a3cba32SPierre Ossman /*
6244a3cba32SPierre Ossman * Some controllers (JMicron JMB38x) mess up the buffer bits
6254a3cba32SPierre Ossman * for transfers < 4 bytes. As long as it is just one block,
6264a3cba32SPierre Ossman * we can ignore the bits.
6274a3cba32SPierre Ossman */
6284a3cba32SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) &&
6294a3cba32SPierre Ossman (host->data->blocks == 1))
6304a3cba32SPierre Ossman mask = ~0;
6314a3cba32SPierre Ossman
6324e4141a5SAnton Vorontsov while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
6333e3bf207SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY)
6343e3bf207SAnton Vorontsov udelay(100);
6353e3bf207SAnton Vorontsov
6361c6a0718SPierre Ossman if (host->data->flags & MMC_DATA_READ)
6371c6a0718SPierre Ossman sdhci_read_block_pio(host);
6381c6a0718SPierre Ossman else
6391c6a0718SPierre Ossman sdhci_write_block_pio(host);
6401c6a0718SPierre Ossman
6417659150cSPierre Ossman host->blocks--;
6427659150cSPierre Ossman if (host->blocks == 0)
6431c6a0718SPierre Ossman break;
6441c6a0718SPierre Ossman }
6451c6a0718SPierre Ossman
6461c6a0718SPierre Ossman DBG("PIO transfer complete.\n");
6471c6a0718SPierre Ossman }
6481c6a0718SPierre Ossman
sdhci_pre_dma_transfer(struct sdhci_host * host,struct mmc_data * data,int cookie)64948857d9bSRussell King static int sdhci_pre_dma_transfer(struct sdhci_host *host,
650c0999b72SRussell King struct mmc_data *data, int cookie)
65148857d9bSRussell King {
65248857d9bSRussell King int sg_count;
65348857d9bSRussell King
65494538e51SRussell King /*
65594538e51SRussell King * If the data buffers are already mapped, return the previous
65694538e51SRussell King * dma_map_sg() result.
65794538e51SRussell King */
65894538e51SRussell King if (data->host_cookie == COOKIE_PRE_MAPPED)
65948857d9bSRussell King return data->sg_count;
66048857d9bSRussell King
661bd9b9027SLinus Walleij /* Bounce write requests to the bounce buffer */
662bd9b9027SLinus Walleij if (host->bounce_buffer) {
663bd9b9027SLinus Walleij unsigned int length = data->blksz * data->blocks;
664bd9b9027SLinus Walleij
665bd9b9027SLinus Walleij if (length > host->bounce_buffer_size) {
666bd9b9027SLinus Walleij pr_err("%s: asked for transfer of %u bytes exceeds bounce buffer %u bytes\n",
667bd9b9027SLinus Walleij mmc_hostname(host->mmc), length,
668bd9b9027SLinus Walleij host->bounce_buffer_size);
669bd9b9027SLinus Walleij return -EIO;
670bd9b9027SLinus Walleij }
671bd9b9027SLinus Walleij if (mmc_get_dma_dir(data) == DMA_TO_DEVICE) {
672bd9b9027SLinus Walleij /* Copy the data to the bounce buffer */
673e93577ecSAngelo Dureghello if (host->ops->copy_to_bounce_buffer) {
674e93577ecSAngelo Dureghello host->ops->copy_to_bounce_buffer(host,
675e93577ecSAngelo Dureghello data, length);
676e93577ecSAngelo Dureghello } else {
677bd9b9027SLinus Walleij sg_copy_to_buffer(data->sg, data->sg_len,
678e93577ecSAngelo Dureghello host->bounce_buffer, length);
679e93577ecSAngelo Dureghello }
680bd9b9027SLinus Walleij }
681bd9b9027SLinus Walleij /* Switch ownership to the DMA */
682bac53336SJisheng Zhang dma_sync_single_for_device(mmc_dev(host->mmc),
683bd9b9027SLinus Walleij host->bounce_addr,
684bd9b9027SLinus Walleij host->bounce_buffer_size,
685feeef096SHeiner Kallweit mmc_get_dma_dir(data));
686bd9b9027SLinus Walleij /* Just a dummy value */
687bd9b9027SLinus Walleij sg_count = 1;
688bd9b9027SLinus Walleij } else {
689bd9b9027SLinus Walleij /* Just access the data directly from memory */
690bd9b9027SLinus Walleij sg_count = dma_map_sg(mmc_dev(host->mmc),
691bd9b9027SLinus Walleij data->sg, data->sg_len,
692bd9b9027SLinus Walleij mmc_get_dma_dir(data));
693bd9b9027SLinus Walleij }
69448857d9bSRussell King
69548857d9bSRussell King if (sg_count == 0)
69648857d9bSRussell King return -ENOSPC;
69748857d9bSRussell King
69848857d9bSRussell King data->sg_count = sg_count;
699c0999b72SRussell King data->host_cookie = cookie;
70048857d9bSRussell King
70148857d9bSRussell King return sg_count;
70248857d9bSRussell King }
70348857d9bSRussell King
sdhci_kmap_atomic(struct scatterlist * sg)7044438592cSAdrian Hunter static char *sdhci_kmap_atomic(struct scatterlist *sg)
7052134a922SPierre Ossman {
70647722e3fSAdrian Hunter return kmap_local_page(sg_page(sg)) + sg->offset;
7072134a922SPierre Ossman }
7082134a922SPierre Ossman
sdhci_kunmap_atomic(void * buffer)7094438592cSAdrian Hunter static void sdhci_kunmap_atomic(void *buffer)
7102134a922SPierre Ossman {
71147722e3fSAdrian Hunter kunmap_local(buffer);
7122134a922SPierre Ossman }
7132134a922SPierre Ossman
sdhci_adma_write_desc(struct sdhci_host * host,void ** desc,dma_addr_t addr,int len,unsigned int cmd)71454552e49SJisheng Zhang void sdhci_adma_write_desc(struct sdhci_host *host, void **desc,
71554552e49SJisheng Zhang dma_addr_t addr, int len, unsigned int cmd)
716118cd17dSBen Dooks {
71754552e49SJisheng Zhang struct sdhci_adma2_64_desc *dma_desc = *desc;
718118cd17dSBen Dooks
719e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have these members in same position */
7200545230fSAdrian Hunter dma_desc->cmd = cpu_to_le16(cmd);
7210545230fSAdrian Hunter dma_desc->len = cpu_to_le16(len);
72238eee2e8SMasahiro Yamada dma_desc->addr_lo = cpu_to_le32(lower_32_bits(addr));
723e57a5f61SAdrian Hunter
724e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA)
72538eee2e8SMasahiro Yamada dma_desc->addr_hi = cpu_to_le32(upper_32_bits(addr));
72654552e49SJisheng Zhang
72754552e49SJisheng Zhang *desc += host->desc_sz;
72854552e49SJisheng Zhang }
72954552e49SJisheng Zhang EXPORT_SYMBOL_GPL(sdhci_adma_write_desc);
73054552e49SJisheng Zhang
__sdhci_adma_write_desc(struct sdhci_host * host,void ** desc,dma_addr_t addr,int len,unsigned int cmd)73154552e49SJisheng Zhang static inline void __sdhci_adma_write_desc(struct sdhci_host *host,
73254552e49SJisheng Zhang void **desc, dma_addr_t addr,
73354552e49SJisheng Zhang int len, unsigned int cmd)
73454552e49SJisheng Zhang {
73554552e49SJisheng Zhang if (host->ops->adma_write_desc)
73654552e49SJisheng Zhang host->ops->adma_write_desc(host, desc, addr, len, cmd);
73707be55b5SJisheng Zhang else
73854552e49SJisheng Zhang sdhci_adma_write_desc(host, desc, addr, len, cmd);
739118cd17dSBen Dooks }
740118cd17dSBen Dooks
sdhci_adma_mark_end(void * desc)741b5ffa674SAdrian Hunter static void sdhci_adma_mark_end(void *desc)
742b5ffa674SAdrian Hunter {
743e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc;
744b5ffa674SAdrian Hunter
745e57a5f61SAdrian Hunter /* 32-bit and 64-bit descriptors have 'cmd' in same position */
7460545230fSAdrian Hunter dma_desc->cmd |= cpu_to_le16(ADMA2_END);
747b5ffa674SAdrian Hunter }
748b5ffa674SAdrian Hunter
sdhci_adma_table_pre(struct sdhci_host * host,struct mmc_data * data,int sg_count)74960c64762SRussell King static void sdhci_adma_table_pre(struct sdhci_host *host,
75060c64762SRussell King struct mmc_data *data, int sg_count)
7512134a922SPierre Ossman {
7522134a922SPierre Ossman struct scatterlist *sg;
753acc3ad13SRussell King dma_addr_t addr, align_addr;
754acc3ad13SRussell King void *desc, *align;
755acc3ad13SRussell King char *buffer;
756acc3ad13SRussell King int len, offset, i;
7572134a922SPierre Ossman
7582134a922SPierre Ossman /*
7592134a922SPierre Ossman * The spec does not specify endianness of descriptor table.
7602134a922SPierre Ossman * We currently guess that it is LE.
7612134a922SPierre Ossman */
7622134a922SPierre Ossman
76360c64762SRussell King host->sg_count = sg_count;
7642134a922SPierre Ossman
7654efaa6fbSAdrian Hunter desc = host->adma_table;
7662134a922SPierre Ossman align = host->align_buffer;
7672134a922SPierre Ossman
7682134a922SPierre Ossman align_addr = host->align_addr;
7692134a922SPierre Ossman
7702134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) {
7712134a922SPierre Ossman addr = sg_dma_address(sg);
7722134a922SPierre Ossman len = sg_dma_len(sg);
7732134a922SPierre Ossman
7742134a922SPierre Ossman /*
775acc3ad13SRussell King * The SDHCI specification states that ADMA addresses must
776acc3ad13SRussell King * be 32-bit aligned. If they aren't, then we use a bounce
777acc3ad13SRussell King * buffer for the (up to three) bytes that screw up the
7782134a922SPierre Ossman * alignment.
7792134a922SPierre Ossman */
78004a5ae6fSAdrian Hunter offset = (SDHCI_ADMA2_ALIGN - (addr & SDHCI_ADMA2_MASK)) &
78104a5ae6fSAdrian Hunter SDHCI_ADMA2_MASK;
7822134a922SPierre Ossman if (offset) {
7832134a922SPierre Ossman if (data->flags & MMC_DATA_WRITE) {
7844438592cSAdrian Hunter buffer = sdhci_kmap_atomic(sg);
7852134a922SPierre Ossman memcpy(align, buffer, offset);
7864438592cSAdrian Hunter sdhci_kunmap_atomic(buffer);
7872134a922SPierre Ossman }
7882134a922SPierre Ossman
789118cd17dSBen Dooks /* tran, valid */
79054552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, align_addr,
79154552e49SJisheng Zhang offset, ADMA2_TRAN_VALID);
7922134a922SPierre Ossman
7932134a922SPierre Ossman BUG_ON(offset > 65536);
7942134a922SPierre Ossman
79504a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN;
79604a5ae6fSAdrian Hunter align_addr += SDHCI_ADMA2_ALIGN;
7972134a922SPierre Ossman
7982134a922SPierre Ossman addr += offset;
7992134a922SPierre Ossman len -= offset;
8002134a922SPierre Ossman }
8012134a922SPierre Ossman
8023d7c194bSAdrian Hunter /*
8033d7c194bSAdrian Hunter * The block layer forces a minimum segment size of PAGE_SIZE,
8043d7c194bSAdrian Hunter * so 'len' can be too big here if PAGE_SIZE >= 64KiB. Write
8053d7c194bSAdrian Hunter * multiple descriptors, noting that the ADMA table is sized
8063d7c194bSAdrian Hunter * for 4KiB chunks anyway, so it will be big enough.
8073d7c194bSAdrian Hunter */
8083d7c194bSAdrian Hunter while (len > host->max_adma) {
8093d7c194bSAdrian Hunter int n = 32 * 1024; /* 32KiB*/
8103d7c194bSAdrian Hunter
8113d7c194bSAdrian Hunter __sdhci_adma_write_desc(host, &desc, addr, n, ADMA2_TRAN_VALID);
8123d7c194bSAdrian Hunter addr += n;
8133d7c194bSAdrian Hunter len -= n;
8143d7c194bSAdrian Hunter }
8152134a922SPierre Ossman
816118cd17dSBen Dooks /* tran, valid */
81754552e49SJisheng Zhang if (len)
81854552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, addr, len,
819347ea32dSAdrian Hunter ADMA2_TRAN_VALID);
8202134a922SPierre Ossman
8212134a922SPierre Ossman /*
8222134a922SPierre Ossman * If this triggers then we have a calculation bug
8232134a922SPierre Ossman * somewhere. :/
8242134a922SPierre Ossman */
82576fe379aSAdrian Hunter WARN_ON((desc - host->adma_table) >= host->adma_table_sz);
8262134a922SPierre Ossman }
8272134a922SPierre Ossman
82870764a90SThomas Abraham if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) {
829acc3ad13SRussell King /* Mark the last descriptor as the terminating descriptor */
8304efaa6fbSAdrian Hunter if (desc != host->adma_table) {
83176fe379aSAdrian Hunter desc -= host->desc_sz;
832b5ffa674SAdrian Hunter sdhci_adma_mark_end(desc);
83370764a90SThomas Abraham }
83470764a90SThomas Abraham } else {
835acc3ad13SRussell King /* Add a terminating entry - nop, end, valid */
83654552e49SJisheng Zhang __sdhci_adma_write_desc(host, &desc, 0, 0, ADMA2_NOP_END_VALID);
83770764a90SThomas Abraham }
8382134a922SPierre Ossman }
8392134a922SPierre Ossman
sdhci_adma_table_post(struct sdhci_host * host,struct mmc_data * data)8402134a922SPierre Ossman static void sdhci_adma_table_post(struct sdhci_host *host,
8412134a922SPierre Ossman struct mmc_data *data)
8422134a922SPierre Ossman {
8432134a922SPierre Ossman struct scatterlist *sg;
8442134a922SPierre Ossman int i, size;
8451c3d5f6dSAdrian Hunter void *align;
8462134a922SPierre Ossman char *buffer;
8472134a922SPierre Ossman
84847fa9613SRussell King if (data->flags & MMC_DATA_READ) {
84947fa9613SRussell King bool has_unaligned = false;
85047fa9613SRussell King
851de0b65a7SRussell King /* Do a quick scan of the SG list for any unaligned mappings */
852de0b65a7SRussell King for_each_sg(data->sg, sg, host->sg_count, i)
85304a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) {
854de0b65a7SRussell King has_unaligned = true;
855de0b65a7SRussell King break;
856de0b65a7SRussell King }
857de0b65a7SRussell King
85847fa9613SRussell King if (has_unaligned) {
8592134a922SPierre Ossman dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,
860f55c98f7SRussell King data->sg_len, DMA_FROM_DEVICE);
8612134a922SPierre Ossman
8622134a922SPierre Ossman align = host->align_buffer;
8632134a922SPierre Ossman
8642134a922SPierre Ossman for_each_sg(data->sg, sg, host->sg_count, i) {
86504a5ae6fSAdrian Hunter if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) {
86604a5ae6fSAdrian Hunter size = SDHCI_ADMA2_ALIGN -
86704a5ae6fSAdrian Hunter (sg_dma_address(sg) & SDHCI_ADMA2_MASK);
8682134a922SPierre Ossman
8694438592cSAdrian Hunter buffer = sdhci_kmap_atomic(sg);
8702134a922SPierre Ossman memcpy(buffer, align, size);
8714438592cSAdrian Hunter sdhci_kunmap_atomic(buffer);
8722134a922SPierre Ossman
87304a5ae6fSAdrian Hunter align += SDHCI_ADMA2_ALIGN;
8742134a922SPierre Ossman }
8752134a922SPierre Ossman }
8762134a922SPierre Ossman }
87747fa9613SRussell King }
8782134a922SPierre Ossman }
8792134a922SPierre Ossman
sdhci_set_adma_addr(struct sdhci_host * host,dma_addr_t addr)88038eee2e8SMasahiro Yamada static void sdhci_set_adma_addr(struct sdhci_host *host, dma_addr_t addr)
88138eee2e8SMasahiro Yamada {
88238eee2e8SMasahiro Yamada sdhci_writel(host, lower_32_bits(addr), SDHCI_ADMA_ADDRESS);
88338eee2e8SMasahiro Yamada if (host->flags & SDHCI_USE_64_BIT_DMA)
88438eee2e8SMasahiro Yamada sdhci_writel(host, upper_32_bits(addr), SDHCI_ADMA_ADDRESS_HI);
88538eee2e8SMasahiro Yamada }
88638eee2e8SMasahiro Yamada
sdhci_sdma_address(struct sdhci_host * host)887917a0c52SChunyan Zhang static dma_addr_t sdhci_sdma_address(struct sdhci_host *host)
888bd9b9027SLinus Walleij {
889bd9b9027SLinus Walleij if (host->bounce_buffer)
890bd9b9027SLinus Walleij return host->bounce_addr;
891bd9b9027SLinus Walleij else
892bd9b9027SLinus Walleij return sg_dma_address(host->data->sg);
893bd9b9027SLinus Walleij }
894bd9b9027SLinus Walleij
sdhci_set_sdma_addr(struct sdhci_host * host,dma_addr_t addr)895917a0c52SChunyan Zhang static void sdhci_set_sdma_addr(struct sdhci_host *host, dma_addr_t addr)
896917a0c52SChunyan Zhang {
89738eee2e8SMasahiro Yamada if (host->v4_mode)
89838eee2e8SMasahiro Yamada sdhci_set_adma_addr(host, addr);
89938eee2e8SMasahiro Yamada else
900917a0c52SChunyan Zhang sdhci_writel(host, addr, SDHCI_DMA_ADDRESS);
901917a0c52SChunyan Zhang }
902917a0c52SChunyan Zhang
sdhci_target_timeout(struct sdhci_host * host,struct mmc_command * cmd,struct mmc_data * data)9030bb28d73SAdrian Hunter static unsigned int sdhci_target_timeout(struct sdhci_host *host,
9040bb28d73SAdrian Hunter struct mmc_command *cmd,
9050bb28d73SAdrian Hunter struct mmc_data *data)
9060bb28d73SAdrian Hunter {
9070bb28d73SAdrian Hunter unsigned int target_timeout;
9080bb28d73SAdrian Hunter
9090bb28d73SAdrian Hunter /* timeout in us */
9100bb28d73SAdrian Hunter if (!data) {
9110bb28d73SAdrian Hunter target_timeout = cmd->busy_timeout * 1000;
9120bb28d73SAdrian Hunter } else {
9130bb28d73SAdrian Hunter target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000);
9140bb28d73SAdrian Hunter if (host->clock && data->timeout_clks) {
9150bb28d73SAdrian Hunter unsigned long long val;
9160bb28d73SAdrian Hunter
9170bb28d73SAdrian Hunter /*
9180bb28d73SAdrian Hunter * data->timeout_clks is in units of clock cycles.
9190bb28d73SAdrian Hunter * host->clock is in Hz. target_timeout is in us.
9200bb28d73SAdrian Hunter * Hence, us = 1000000 * cycles / Hz. Round up.
9210bb28d73SAdrian Hunter */
9220bb28d73SAdrian Hunter val = 1000000ULL * data->timeout_clks;
9230bb28d73SAdrian Hunter if (do_div(val, host->clock))
9240bb28d73SAdrian Hunter target_timeout++;
9250bb28d73SAdrian Hunter target_timeout += val;
9260bb28d73SAdrian Hunter }
9270bb28d73SAdrian Hunter }
9280bb28d73SAdrian Hunter
9290bb28d73SAdrian Hunter return target_timeout;
9300bb28d73SAdrian Hunter }
9310bb28d73SAdrian Hunter
sdhci_calc_sw_timeout(struct sdhci_host * host,struct mmc_command * cmd)932fc1fa1b7SKishon Vijay Abraham I static void sdhci_calc_sw_timeout(struct sdhci_host *host,
933fc1fa1b7SKishon Vijay Abraham I struct mmc_command *cmd)
934fc1fa1b7SKishon Vijay Abraham I {
935fc1fa1b7SKishon Vijay Abraham I struct mmc_data *data = cmd->data;
936fc1fa1b7SKishon Vijay Abraham I struct mmc_host *mmc = host->mmc;
937fc1fa1b7SKishon Vijay Abraham I struct mmc_ios *ios = &mmc->ios;
938fc1fa1b7SKishon Vijay Abraham I unsigned char bus_width = 1 << ios->bus_width;
939fc1fa1b7SKishon Vijay Abraham I unsigned int blksz;
940fc1fa1b7SKishon Vijay Abraham I unsigned int freq;
941fc1fa1b7SKishon Vijay Abraham I u64 target_timeout;
942fc1fa1b7SKishon Vijay Abraham I u64 transfer_time;
943fc1fa1b7SKishon Vijay Abraham I
944fc1fa1b7SKishon Vijay Abraham I target_timeout = sdhci_target_timeout(host, cmd, data);
945fc1fa1b7SKishon Vijay Abraham I target_timeout *= NSEC_PER_USEC;
946fc1fa1b7SKishon Vijay Abraham I
947fc1fa1b7SKishon Vijay Abraham I if (data) {
948fc1fa1b7SKishon Vijay Abraham I blksz = data->blksz;
949d2f025b0SJisheng Zhang freq = mmc->actual_clock ? : host->clock;
950fc1fa1b7SKishon Vijay Abraham I transfer_time = (u64)blksz * NSEC_PER_SEC * (8 / bus_width);
951fc1fa1b7SKishon Vijay Abraham I do_div(transfer_time, freq);
952fc1fa1b7SKishon Vijay Abraham I /* multiply by '2' to account for any unknowns */
953fc1fa1b7SKishon Vijay Abraham I transfer_time = transfer_time * 2;
954fc1fa1b7SKishon Vijay Abraham I /* calculate timeout for the entire data */
955fc1fa1b7SKishon Vijay Abraham I host->data_timeout = data->blocks * target_timeout +
956fc1fa1b7SKishon Vijay Abraham I transfer_time;
957fc1fa1b7SKishon Vijay Abraham I } else {
958fc1fa1b7SKishon Vijay Abraham I host->data_timeout = target_timeout;
959fc1fa1b7SKishon Vijay Abraham I }
960fc1fa1b7SKishon Vijay Abraham I
961fc1fa1b7SKishon Vijay Abraham I if (host->data_timeout)
962fc1fa1b7SKishon Vijay Abraham I host->data_timeout += MMC_CMD_TRANSFER_TIME;
963fc1fa1b7SKishon Vijay Abraham I }
964fc1fa1b7SKishon Vijay Abraham I
sdhci_calc_timeout(struct sdhci_host * host,struct mmc_command * cmd,bool * too_big)965a999fd93SAdrian Hunter static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
966a999fd93SAdrian Hunter bool *too_big)
9671c6a0718SPierre Ossman {
9681c6a0718SPierre Ossman u8 count;
969401059dfSBOUGH CHEN struct mmc_data *data;
9701c6a0718SPierre Ossman unsigned target_timeout, current_timeout;
9711c6a0718SPierre Ossman
9729c6bb8c6SBean Huo *too_big = false;
973a999fd93SAdrian Hunter
974ee53ab5dSPierre Ossman /*
975ee53ab5dSPierre Ossman * If the host controller provides us with an incorrect timeout
976e30314f2SSarthak Garg * value, just skip the check and use the maximum. The hardware may take
977ee53ab5dSPierre Ossman * longer to time out, but that's much better than having a too-short
978ee53ab5dSPierre Ossman * timeout value.
979ee53ab5dSPierre Ossman */
98011a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
981e30314f2SSarthak Garg return host->max_timeout_count;
982e538fbe8SPierre Ossman
9839c6bb8c6SBean Huo /* Unspecified command, assume max */
984401059dfSBOUGH CHEN if (cmd == NULL)
985e30314f2SSarthak Garg return host->max_timeout_count;
986401059dfSBOUGH CHEN
987401059dfSBOUGH CHEN data = cmd->data;
988a3c7778fSAndrei Warkentin /* Unspecified timeout, assume max */
9891d4d7744SUlf Hansson if (!data && !cmd->busy_timeout)
990e30314f2SSarthak Garg return host->max_timeout_count;
991a3c7778fSAndrei Warkentin
9921c6a0718SPierre Ossman /* timeout in us */
9930bb28d73SAdrian Hunter target_timeout = sdhci_target_timeout(host, cmd, data);
9941c6a0718SPierre Ossman
9951c6a0718SPierre Ossman /*
9961c6a0718SPierre Ossman * Figure out needed cycles.
9971c6a0718SPierre Ossman * We do this in steps in order to fit inside a 32 bit int.
9981c6a0718SPierre Ossman * The first step is the minimum timeout, which will have a
9991c6a0718SPierre Ossman * minimum resolution of 6 bits:
10001c6a0718SPierre Ossman * (1) 2^13*1000 > 2^22,
10011c6a0718SPierre Ossman * (2) host->timeout_clk < 2^16
10021c6a0718SPierre Ossman * =>
10031c6a0718SPierre Ossman * (1) / (2) > 2^6
10041c6a0718SPierre Ossman */
10051c6a0718SPierre Ossman count = 0;
10061c6a0718SPierre Ossman current_timeout = (1 << 13) * 1000 / host->timeout_clk;
10071c6a0718SPierre Ossman while (current_timeout < target_timeout) {
10081c6a0718SPierre Ossman count++;
10091c6a0718SPierre Ossman current_timeout <<= 1;
1010e30314f2SSarthak Garg if (count > host->max_timeout_count) {
1011a999fd93SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT))
1012f421865dSAdrian Hunter DBG("Too large timeout 0x%x requested for CMD%d!\n",
1013f421865dSAdrian Hunter count, cmd->opcode);
1014e30314f2SSarthak Garg count = host->max_timeout_count;
10159c6bb8c6SBean Huo *too_big = true;
10169c6bb8c6SBean Huo break;
10179c6bb8c6SBean Huo }
10181c6a0718SPierre Ossman }
10191c6a0718SPierre Ossman
1020ee53ab5dSPierre Ossman return count;
1021ee53ab5dSPierre Ossman }
1022ee53ab5dSPierre Ossman
sdhci_set_transfer_irqs(struct sdhci_host * host)10236aa943abSAnton Vorontsov static void sdhci_set_transfer_irqs(struct sdhci_host *host)
10246aa943abSAnton Vorontsov {
10256aa943abSAnton Vorontsov u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL;
10266aa943abSAnton Vorontsov u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
10276aa943abSAnton Vorontsov
10286aa943abSAnton Vorontsov if (host->flags & SDHCI_REQ_USE_DMA)
1029b537f94cSRussell King host->ier = (host->ier & ~pio_irqs) | dma_irqs;
10306aa943abSAnton Vorontsov else
1031b537f94cSRussell King host->ier = (host->ier & ~dma_irqs) | pio_irqs;
1032b537f94cSRussell King
1033af849c86SAdrian Hunter if (host->flags & (SDHCI_AUTO_CMD23 | SDHCI_AUTO_CMD12))
1034af849c86SAdrian Hunter host->ier |= SDHCI_INT_AUTO_CMD_ERR;
1035af849c86SAdrian Hunter else
1036af849c86SAdrian Hunter host->ier &= ~SDHCI_INT_AUTO_CMD_ERR;
1037af849c86SAdrian Hunter
1038b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
1039b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
10406aa943abSAnton Vorontsov }
10416aa943abSAnton Vorontsov
sdhci_set_data_timeout_irq(struct sdhci_host * host,bool enable)10427907ebe7SFaiz Abbas void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable)
1043a999fd93SAdrian Hunter {
1044a999fd93SAdrian Hunter if (enable)
1045a999fd93SAdrian Hunter host->ier |= SDHCI_INT_DATA_TIMEOUT;
1046a999fd93SAdrian Hunter else
1047a999fd93SAdrian Hunter host->ier &= ~SDHCI_INT_DATA_TIMEOUT;
1048a999fd93SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
1049a999fd93SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
1050a999fd93SAdrian Hunter }
10517907ebe7SFaiz Abbas EXPORT_SYMBOL_GPL(sdhci_set_data_timeout_irq);
1052a999fd93SAdrian Hunter
__sdhci_set_timeout(struct sdhci_host * host,struct mmc_command * cmd)10537d76ed77SFaiz Abbas void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
1054ee53ab5dSPierre Ossman {
1055a999fd93SAdrian Hunter bool too_big = false;
10567d76ed77SFaiz Abbas u8 count = sdhci_calc_timeout(host, cmd, &too_big);
1057a999fd93SAdrian Hunter
1058a999fd93SAdrian Hunter if (too_big &&
1059a999fd93SAdrian Hunter host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) {
1060fc1fa1b7SKishon Vijay Abraham I sdhci_calc_sw_timeout(host, cmd);
1061a999fd93SAdrian Hunter sdhci_set_data_timeout_irq(host, false);
1062a999fd93SAdrian Hunter } else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT)) {
1063a999fd93SAdrian Hunter sdhci_set_data_timeout_irq(host, true);
1064a999fd93SAdrian Hunter }
1065a999fd93SAdrian Hunter
1066b45e668aSAisheng Dong sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
1067b45e668aSAisheng Dong }
10687d76ed77SFaiz Abbas EXPORT_SYMBOL_GPL(__sdhci_set_timeout);
10697d76ed77SFaiz Abbas
sdhci_set_timeout(struct sdhci_host * host,struct mmc_command * cmd)10707d76ed77SFaiz Abbas static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
10717d76ed77SFaiz Abbas {
10727d76ed77SFaiz Abbas if (host->ops->set_timeout)
10737d76ed77SFaiz Abbas host->ops->set_timeout(host, cmd);
10747d76ed77SFaiz Abbas else
10757d76ed77SFaiz Abbas __sdhci_set_timeout(host, cmd);
1076b45e668aSAisheng Dong }
1077b45e668aSAisheng Dong
sdhci_initialize_data(struct sdhci_host * host,struct mmc_data * data)107815db1836SFaiz Abbas static void sdhci_initialize_data(struct sdhci_host *host,
107915db1836SFaiz Abbas struct mmc_data *data)
1080b45e668aSAisheng Dong {
108143dea098SAdrian Hunter WARN_ON(host->data);
108243dea098SAdrian Hunter
1083ee53ab5dSPierre Ossman /* Sanity checks */
1084ee53ab5dSPierre Ossman BUG_ON(data->blksz * data->blocks > 524288);
1085ee53ab5dSPierre Ossman BUG_ON(data->blksz > host->mmc->max_blk_size);
1086ee53ab5dSPierre Ossman BUG_ON(data->blocks > 65535);
1087ee53ab5dSPierre Ossman
1088ee53ab5dSPierre Ossman host->data = data;
1089ee53ab5dSPierre Ossman host->data_early = 0;
1090f6a03cbfSMikko Vinni host->data->bytes_xfered = 0;
109115db1836SFaiz Abbas }
109215db1836SFaiz Abbas
sdhci_set_block_info(struct sdhci_host * host,struct mmc_data * data)109315db1836SFaiz Abbas static inline void sdhci_set_block_info(struct sdhci_host *host,
109415db1836SFaiz Abbas struct mmc_data *data)
109515db1836SFaiz Abbas {
109615db1836SFaiz Abbas /* Set the DMA boundary value and block size */
109715db1836SFaiz Abbas sdhci_writew(host,
109815db1836SFaiz Abbas SDHCI_MAKE_BLKSZ(host->sdma_boundary, data->blksz),
109915db1836SFaiz Abbas SDHCI_BLOCK_SIZE);
110015db1836SFaiz Abbas /*
110115db1836SFaiz Abbas * For Version 4.10 onwards, if v4 mode is enabled, 32-bit Block Count
110215db1836SFaiz Abbas * can be supported, in that case 16-bit block count register must be 0.
110315db1836SFaiz Abbas */
110415db1836SFaiz Abbas if (host->version >= SDHCI_SPEC_410 && host->v4_mode &&
110515db1836SFaiz Abbas (host->quirks2 & SDHCI_QUIRK2_USE_32BIT_BLK_CNT)) {
110615db1836SFaiz Abbas if (sdhci_readw(host, SDHCI_BLOCK_COUNT))
110715db1836SFaiz Abbas sdhci_writew(host, 0, SDHCI_BLOCK_COUNT);
110815db1836SFaiz Abbas sdhci_writew(host, data->blocks, SDHCI_32BIT_BLK_CNT);
110915db1836SFaiz Abbas } else {
111015db1836SFaiz Abbas sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT);
111115db1836SFaiz Abbas }
111215db1836SFaiz Abbas }
111315db1836SFaiz Abbas
sdhci_prepare_data(struct sdhci_host * host,struct mmc_command * cmd)111415db1836SFaiz Abbas static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
111515db1836SFaiz Abbas {
111615db1836SFaiz Abbas struct mmc_data *data = cmd->data;
111715db1836SFaiz Abbas
111815db1836SFaiz Abbas sdhci_initialize_data(host, data);
1119ee53ab5dSPierre Ossman
1120fce14421SRussell King if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
1121fce14421SRussell King struct scatterlist *sg;
1122fce14421SRussell King unsigned int length_mask, offset_mask;
1123fce14421SRussell King int i;
1124fce14421SRussell King
1125c9fddbc4SPierre Ossman host->flags |= SDHCI_REQ_USE_DMA;
1126c9fddbc4SPierre Ossman
11272134a922SPierre Ossman /*
11282134a922SPierre Ossman * FIXME: This doesn't account for merging when mapping the
11292134a922SPierre Ossman * scatterlist.
1130df953925SRussell King *
1131df953925SRussell King * The assumption here being that alignment and lengths are
1132df953925SRussell King * the same after DMA mapping to device address space.
11332134a922SPierre Ossman */
1134a0eaf0f9SRussell King length_mask = 0;
1135df953925SRussell King offset_mask = 0;
11362134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) {
1137df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) {
1138a0eaf0f9SRussell King length_mask = 3;
1139df953925SRussell King /*
1140df953925SRussell King * As we use up to 3 byte chunks to work
1141df953925SRussell King * around alignment problems, we need to
1142df953925SRussell King * check the offset as well.
1143df953925SRussell King */
1144df953925SRussell King offset_mask = 3;
1145df953925SRussell King }
11462134a922SPierre Ossman } else {
11472134a922SPierre Ossman if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE)
1148a0eaf0f9SRussell King length_mask = 3;
1149df953925SRussell King if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR)
1150df953925SRussell King offset_mask = 3;
11512134a922SPierre Ossman }
11522134a922SPierre Ossman
1153df953925SRussell King if (unlikely(length_mask | offset_mask)) {
11542134a922SPierre Ossman for_each_sg(data->sg, sg, data->sg_len, i) {
1155a0eaf0f9SRussell King if (sg->length & length_mask) {
11562e4456f0SMarek Vasut DBG("Reverting to PIO because of transfer size (%d)\n",
11572134a922SPierre Ossman sg->length);
1158c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA;
11592134a922SPierre Ossman break;
11602134a922SPierre Ossman }
1161a0eaf0f9SRussell King if (sg->offset & offset_mask) {
11622e4456f0SMarek Vasut DBG("Reverting to PIO because of bad alignment\n");
1163c9fddbc4SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA;
11642134a922SPierre Ossman break;
11652134a922SPierre Ossman }
11662134a922SPierre Ossman }
11672134a922SPierre Ossman }
11682134a922SPierre Ossman }
11692134a922SPierre Ossman
117020dbd07eSChevron Li sdhci_config_dma(host);
117120dbd07eSChevron Li
11728f1934ceSPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA) {
1173c0999b72SRussell King int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED);
11748f1934ceSPierre Ossman
117562a7f368SJiri Slaby if (sg_cnt <= 0) {
11768f1934ceSPierre Ossman /*
11778f1934ceSPierre Ossman * This only happens when someone fed
11788f1934ceSPierre Ossman * us an invalid request.
11798f1934ceSPierre Ossman */
11808f1934ceSPierre Ossman WARN_ON(1);
1181ebd6d357SPierre Ossman host->flags &= ~SDHCI_REQ_USE_DMA;
118260c64762SRussell King } else if (host->flags & SDHCI_USE_ADMA) {
118360c64762SRussell King sdhci_adma_table_pre(host, data, sg_cnt);
118438eee2e8SMasahiro Yamada sdhci_set_adma_addr(host, host->adma_addr);
11858f1934ceSPierre Ossman } else {
1186719a61b4SPierre Ossman WARN_ON(sg_cnt != 1);
1187917a0c52SChunyan Zhang sdhci_set_sdma_addr(host, sdhci_sdma_address(host));
11888f1934ceSPierre Ossman }
11898f1934ceSPierre Ossman }
11908f1934ceSPierre Ossman
11918f1934ceSPierre Ossman if (!(host->flags & SDHCI_REQ_USE_DMA)) {
1192da60a91dSSebastian Andrzej Siewior int flags;
1193da60a91dSSebastian Andrzej Siewior
1194da60a91dSSebastian Andrzej Siewior flags = SG_MITER_ATOMIC;
1195da60a91dSSebastian Andrzej Siewior if (host->data->flags & MMC_DATA_READ)
1196da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_TO_SG;
1197da60a91dSSebastian Andrzej Siewior else
1198da60a91dSSebastian Andrzej Siewior flags |= SG_MITER_FROM_SG;
1199da60a91dSSebastian Andrzej Siewior sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
12007659150cSPierre Ossman host->blocks = data->blocks;
12011c6a0718SPierre Ossman }
12021c6a0718SPierre Ossman
12036aa943abSAnton Vorontsov sdhci_set_transfer_irqs(host);
12046aa943abSAnton Vorontsov
120515db1836SFaiz Abbas sdhci_set_block_info(host, data);
1206e65953d4SChunyan Zhang }
12071c6a0718SPierre Ossman
120818e762e3SChunyan Zhang #if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA)
120918e762e3SChunyan Zhang
sdhci_external_dma_init(struct sdhci_host * host)121018e762e3SChunyan Zhang static int sdhci_external_dma_init(struct sdhci_host *host)
121118e762e3SChunyan Zhang {
121218e762e3SChunyan Zhang int ret = 0;
121318e762e3SChunyan Zhang struct mmc_host *mmc = host->mmc;
121418e762e3SChunyan Zhang
1215bac53336SJisheng Zhang host->tx_chan = dma_request_chan(mmc_dev(mmc), "tx");
121618e762e3SChunyan Zhang if (IS_ERR(host->tx_chan)) {
121718e762e3SChunyan Zhang ret = PTR_ERR(host->tx_chan);
121818e762e3SChunyan Zhang if (ret != -EPROBE_DEFER)
121918e762e3SChunyan Zhang pr_warn("Failed to request TX DMA channel.\n");
122018e762e3SChunyan Zhang host->tx_chan = NULL;
122118e762e3SChunyan Zhang return ret;
122218e762e3SChunyan Zhang }
122318e762e3SChunyan Zhang
1224bac53336SJisheng Zhang host->rx_chan = dma_request_chan(mmc_dev(mmc), "rx");
122518e762e3SChunyan Zhang if (IS_ERR(host->rx_chan)) {
122618e762e3SChunyan Zhang if (host->tx_chan) {
122718e762e3SChunyan Zhang dma_release_channel(host->tx_chan);
122818e762e3SChunyan Zhang host->tx_chan = NULL;
122918e762e3SChunyan Zhang }
123018e762e3SChunyan Zhang
123118e762e3SChunyan Zhang ret = PTR_ERR(host->rx_chan);
123218e762e3SChunyan Zhang if (ret != -EPROBE_DEFER)
123318e762e3SChunyan Zhang pr_warn("Failed to request RX DMA channel.\n");
123418e762e3SChunyan Zhang host->rx_chan = NULL;
123518e762e3SChunyan Zhang }
123618e762e3SChunyan Zhang
123718e762e3SChunyan Zhang return ret;
123818e762e3SChunyan Zhang }
123918e762e3SChunyan Zhang
sdhci_external_dma_channel(struct sdhci_host * host,struct mmc_data * data)124018e762e3SChunyan Zhang static struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host,
124118e762e3SChunyan Zhang struct mmc_data *data)
124218e762e3SChunyan Zhang {
124318e762e3SChunyan Zhang return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan;
124418e762e3SChunyan Zhang }
124518e762e3SChunyan Zhang
sdhci_external_dma_setup(struct sdhci_host * host,struct mmc_command * cmd)124618e762e3SChunyan Zhang static int sdhci_external_dma_setup(struct sdhci_host *host,
124718e762e3SChunyan Zhang struct mmc_command *cmd)
124818e762e3SChunyan Zhang {
124918e762e3SChunyan Zhang int ret, i;
12501215c025SChunyan Zhang enum dma_transfer_direction dir;
125118e762e3SChunyan Zhang struct dma_async_tx_descriptor *desc;
125218e762e3SChunyan Zhang struct mmc_data *data = cmd->data;
125318e762e3SChunyan Zhang struct dma_chan *chan;
125418e762e3SChunyan Zhang struct dma_slave_config cfg;
125518e762e3SChunyan Zhang dma_cookie_t cookie;
125618e762e3SChunyan Zhang int sg_cnt;
125718e762e3SChunyan Zhang
125818e762e3SChunyan Zhang if (!host->mapbase)
125918e762e3SChunyan Zhang return -EINVAL;
126018e762e3SChunyan Zhang
1261522654d5STony Lindgren memset(&cfg, 0, sizeof(cfg));
126218e762e3SChunyan Zhang cfg.src_addr = host->mapbase + SDHCI_BUFFER;
126318e762e3SChunyan Zhang cfg.dst_addr = host->mapbase + SDHCI_BUFFER;
126418e762e3SChunyan Zhang cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
126518e762e3SChunyan Zhang cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
126618e762e3SChunyan Zhang cfg.src_maxburst = data->blksz / 4;
126718e762e3SChunyan Zhang cfg.dst_maxburst = data->blksz / 4;
126818e762e3SChunyan Zhang
126918e762e3SChunyan Zhang /* Sanity check: all the SG entries must be aligned by block size. */
127018e762e3SChunyan Zhang for (i = 0; i < data->sg_len; i++) {
127118e762e3SChunyan Zhang if ((data->sg + i)->length % data->blksz)
127218e762e3SChunyan Zhang return -EINVAL;
127318e762e3SChunyan Zhang }
127418e762e3SChunyan Zhang
127518e762e3SChunyan Zhang chan = sdhci_external_dma_channel(host, data);
127618e762e3SChunyan Zhang
127718e762e3SChunyan Zhang ret = dmaengine_slave_config(chan, &cfg);
127818e762e3SChunyan Zhang if (ret)
127918e762e3SChunyan Zhang return ret;
128018e762e3SChunyan Zhang
128118e762e3SChunyan Zhang sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED);
128218e762e3SChunyan Zhang if (sg_cnt <= 0)
128318e762e3SChunyan Zhang return -EINVAL;
128418e762e3SChunyan Zhang
12851215c025SChunyan Zhang dir = data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
12861215c025SChunyan Zhang desc = dmaengine_prep_slave_sg(chan, data->sg, data->sg_len, dir,
128718e762e3SChunyan Zhang DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
128818e762e3SChunyan Zhang if (!desc)
128918e762e3SChunyan Zhang return -EINVAL;
129018e762e3SChunyan Zhang
129118e762e3SChunyan Zhang desc->callback = NULL;
129218e762e3SChunyan Zhang desc->callback_param = NULL;
129318e762e3SChunyan Zhang
129418e762e3SChunyan Zhang cookie = dmaengine_submit(desc);
129518e762e3SChunyan Zhang if (dma_submit_error(cookie))
129618e762e3SChunyan Zhang ret = cookie;
129718e762e3SChunyan Zhang
129818e762e3SChunyan Zhang return ret;
129918e762e3SChunyan Zhang }
130018e762e3SChunyan Zhang
sdhci_external_dma_release(struct sdhci_host * host)130118e762e3SChunyan Zhang static void sdhci_external_dma_release(struct sdhci_host *host)
130218e762e3SChunyan Zhang {
130318e762e3SChunyan Zhang if (host->tx_chan) {
130418e762e3SChunyan Zhang dma_release_channel(host->tx_chan);
130518e762e3SChunyan Zhang host->tx_chan = NULL;
130618e762e3SChunyan Zhang }
130718e762e3SChunyan Zhang
130818e762e3SChunyan Zhang if (host->rx_chan) {
130918e762e3SChunyan Zhang dma_release_channel(host->rx_chan);
131018e762e3SChunyan Zhang host->rx_chan = NULL;
131118e762e3SChunyan Zhang }
131218e762e3SChunyan Zhang
131318e762e3SChunyan Zhang sdhci_switch_external_dma(host, false);
131418e762e3SChunyan Zhang }
131518e762e3SChunyan Zhang
__sdhci_external_dma_prepare_data(struct sdhci_host * host,struct mmc_command * cmd)131618e762e3SChunyan Zhang static void __sdhci_external_dma_prepare_data(struct sdhci_host *host,
131718e762e3SChunyan Zhang struct mmc_command *cmd)
131818e762e3SChunyan Zhang {
131918e762e3SChunyan Zhang struct mmc_data *data = cmd->data;
132018e762e3SChunyan Zhang
132118e762e3SChunyan Zhang sdhci_initialize_data(host, data);
132218e762e3SChunyan Zhang
132318e762e3SChunyan Zhang host->flags |= SDHCI_REQ_USE_DMA;
132418e762e3SChunyan Zhang sdhci_set_transfer_irqs(host);
132518e762e3SChunyan Zhang
132618e762e3SChunyan Zhang sdhci_set_block_info(host, data);
132718e762e3SChunyan Zhang }
132818e762e3SChunyan Zhang
sdhci_external_dma_prepare_data(struct sdhci_host * host,struct mmc_command * cmd)132918e762e3SChunyan Zhang static void sdhci_external_dma_prepare_data(struct sdhci_host *host,
133018e762e3SChunyan Zhang struct mmc_command *cmd)
133118e762e3SChunyan Zhang {
133218e762e3SChunyan Zhang if (!sdhci_external_dma_setup(host, cmd)) {
133318e762e3SChunyan Zhang __sdhci_external_dma_prepare_data(host, cmd);
133418e762e3SChunyan Zhang } else {
133518e762e3SChunyan Zhang sdhci_external_dma_release(host);
133618e762e3SChunyan Zhang pr_err("%s: Cannot use external DMA, switch to the DMA/PIO which standard SDHCI provides.\n",
133718e762e3SChunyan Zhang mmc_hostname(host->mmc));
133818e762e3SChunyan Zhang sdhci_prepare_data(host, cmd);
133918e762e3SChunyan Zhang }
134018e762e3SChunyan Zhang }
134118e762e3SChunyan Zhang
sdhci_external_dma_pre_transfer(struct sdhci_host * host,struct mmc_command * cmd)134218e762e3SChunyan Zhang static void sdhci_external_dma_pre_transfer(struct sdhci_host *host,
134318e762e3SChunyan Zhang struct mmc_command *cmd)
134418e762e3SChunyan Zhang {
134518e762e3SChunyan Zhang struct dma_chan *chan;
134618e762e3SChunyan Zhang
134718e762e3SChunyan Zhang if (!cmd->data)
134818e762e3SChunyan Zhang return;
134918e762e3SChunyan Zhang
135018e762e3SChunyan Zhang chan = sdhci_external_dma_channel(host, cmd->data);
135118e762e3SChunyan Zhang if (chan)
135218e762e3SChunyan Zhang dma_async_issue_pending(chan);
135318e762e3SChunyan Zhang }
135418e762e3SChunyan Zhang
135518e762e3SChunyan Zhang #else
135618e762e3SChunyan Zhang
sdhci_external_dma_init(struct sdhci_host * host)135718e762e3SChunyan Zhang static inline int sdhci_external_dma_init(struct sdhci_host *host)
135818e762e3SChunyan Zhang {
135918e762e3SChunyan Zhang return -EOPNOTSUPP;
136018e762e3SChunyan Zhang }
136118e762e3SChunyan Zhang
sdhci_external_dma_release(struct sdhci_host * host)136218e762e3SChunyan Zhang static inline void sdhci_external_dma_release(struct sdhci_host *host)
136318e762e3SChunyan Zhang {
136418e762e3SChunyan Zhang }
136518e762e3SChunyan Zhang
sdhci_external_dma_prepare_data(struct sdhci_host * host,struct mmc_command * cmd)136618e762e3SChunyan Zhang static inline void sdhci_external_dma_prepare_data(struct sdhci_host *host,
136718e762e3SChunyan Zhang struct mmc_command *cmd)
136818e762e3SChunyan Zhang {
136918e762e3SChunyan Zhang /* This should never happen */
137018e762e3SChunyan Zhang WARN_ON_ONCE(1);
137118e762e3SChunyan Zhang }
137218e762e3SChunyan Zhang
sdhci_external_dma_pre_transfer(struct sdhci_host * host,struct mmc_command * cmd)137318e762e3SChunyan Zhang static inline void sdhci_external_dma_pre_transfer(struct sdhci_host *host,
137418e762e3SChunyan Zhang struct mmc_command *cmd)
137518e762e3SChunyan Zhang {
137618e762e3SChunyan Zhang }
137718e762e3SChunyan Zhang
sdhci_external_dma_channel(struct sdhci_host * host,struct mmc_data * data)137818e762e3SChunyan Zhang static inline struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host,
137918e762e3SChunyan Zhang struct mmc_data *data)
138018e762e3SChunyan Zhang {
138118e762e3SChunyan Zhang return NULL;
138218e762e3SChunyan Zhang }
138318e762e3SChunyan Zhang
138418e762e3SChunyan Zhang #endif
138518e762e3SChunyan Zhang
sdhci_switch_external_dma(struct sdhci_host * host,bool en)138618e762e3SChunyan Zhang void sdhci_switch_external_dma(struct sdhci_host *host, bool en)
138718e762e3SChunyan Zhang {
138818e762e3SChunyan Zhang host->use_external_dma = en;
138918e762e3SChunyan Zhang }
139018e762e3SChunyan Zhang EXPORT_SYMBOL_GPL(sdhci_switch_external_dma);
139118e762e3SChunyan Zhang
sdhci_auto_cmd12(struct sdhci_host * host,struct mmc_request * mrq)13920293d501SAdrian Hunter static inline bool sdhci_auto_cmd12(struct sdhci_host *host,
13930293d501SAdrian Hunter struct mmc_request *mrq)
13940293d501SAdrian Hunter {
139520845befSAdrian Hunter return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) &&
139620845befSAdrian Hunter !mrq->cap_cmd_during_tfr;
13970293d501SAdrian Hunter }
13980293d501SAdrian Hunter
sdhci_auto_cmd23(struct sdhci_host * host,struct mmc_request * mrq)1399ed633033SAdrian Hunter static inline bool sdhci_auto_cmd23(struct sdhci_host *host,
1400ed633033SAdrian Hunter struct mmc_request *mrq)
1401ed633033SAdrian Hunter {
1402ed633033SAdrian Hunter return mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);
1403ed633033SAdrian Hunter }
1404ed633033SAdrian Hunter
sdhci_manual_cmd23(struct sdhci_host * host,struct mmc_request * mrq)1405ed633033SAdrian Hunter static inline bool sdhci_manual_cmd23(struct sdhci_host *host,
1406ed633033SAdrian Hunter struct mmc_request *mrq)
1407ed633033SAdrian Hunter {
1408ed633033SAdrian Hunter return mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23);
1409ed633033SAdrian Hunter }
1410ed633033SAdrian Hunter
sdhci_auto_cmd_select(struct sdhci_host * host,struct mmc_command * cmd,u16 * mode)1411427b6514SChunyan Zhang static inline void sdhci_auto_cmd_select(struct sdhci_host *host,
1412427b6514SChunyan Zhang struct mmc_command *cmd,
1413427b6514SChunyan Zhang u16 *mode)
1414427b6514SChunyan Zhang {
1415427b6514SChunyan Zhang bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) &&
1416427b6514SChunyan Zhang (cmd->opcode != SD_IO_RW_EXTENDED);
1417ed633033SAdrian Hunter bool use_cmd23 = sdhci_auto_cmd23(host, cmd->mrq);
1418427b6514SChunyan Zhang u16 ctrl2;
1419427b6514SChunyan Zhang
1420427b6514SChunyan Zhang /*
1421427b6514SChunyan Zhang * In case of Version 4.10 or later, use of 'Auto CMD Auto
1422427b6514SChunyan Zhang * Select' is recommended rather than use of 'Auto CMD12
1423b3e1ea16SJisheng Zhang * Enable' or 'Auto CMD23 Enable'. We require Version 4 Mode
1424b3e1ea16SJisheng Zhang * here because some controllers (e.g sdhci-of-dwmshc) expect it.
1425427b6514SChunyan Zhang */
1426b3e1ea16SJisheng Zhang if (host->version >= SDHCI_SPEC_410 && host->v4_mode &&
1427b3e1ea16SJisheng Zhang (use_cmd12 || use_cmd23)) {
1428427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_SEL;
1429427b6514SChunyan Zhang
1430427b6514SChunyan Zhang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
1431427b6514SChunyan Zhang if (use_cmd23)
1432427b6514SChunyan Zhang ctrl2 |= SDHCI_CMD23_ENABLE;
1433427b6514SChunyan Zhang else
1434427b6514SChunyan Zhang ctrl2 &= ~SDHCI_CMD23_ENABLE;
1435427b6514SChunyan Zhang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
1436427b6514SChunyan Zhang
1437427b6514SChunyan Zhang return;
1438427b6514SChunyan Zhang }
1439427b6514SChunyan Zhang
1440427b6514SChunyan Zhang /*
1441427b6514SChunyan Zhang * If we are sending CMD23, CMD12 never gets sent
1442427b6514SChunyan Zhang * on successful completion (so no Auto-CMD12).
1443427b6514SChunyan Zhang */
1444427b6514SChunyan Zhang if (use_cmd12)
1445427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_CMD12;
1446427b6514SChunyan Zhang else if (use_cmd23)
1447427b6514SChunyan Zhang *mode |= SDHCI_TRNS_AUTO_CMD23;
1448427b6514SChunyan Zhang }
1449427b6514SChunyan Zhang
sdhci_set_transfer_mode(struct sdhci_host * host,struct mmc_command * cmd)14501c6a0718SPierre Ossman static void sdhci_set_transfer_mode(struct sdhci_host *host,
1451e89d456fSAndrei Warkentin struct mmc_command *cmd)
14521c6a0718SPierre Ossman {
1453d3fc5d71SVincent Yang u16 mode = 0;
1454e89d456fSAndrei Warkentin struct mmc_data *data = cmd->data;
14551c6a0718SPierre Ossman
14562b558c13SDong Aisheng if (data == NULL) {
14579b8ffea6SVincent Wan if (host->quirks2 &
14589b8ffea6SVincent Wan SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) {
14590086fc21Sernest.zhang /* must not clear SDHCI_TRANSFER_MODE when tuning */
146063abdf72SCharl Liu if (!mmc_op_tuning(cmd->opcode))
14619b8ffea6SVincent Wan sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
14629b8ffea6SVincent Wan } else {
14632b558c13SDong Aisheng /* clear Auto CMD settings for no data CMDs */
14642b558c13SDong Aisheng mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
14652b558c13SDong Aisheng sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 |
14662b558c13SDong Aisheng SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);
14679b8ffea6SVincent Wan }
14681c6a0718SPierre Ossman return;
14692b558c13SDong Aisheng }
14701c6a0718SPierre Ossman
1471e538fbe8SPierre Ossman WARN_ON(!host->data);
1472e538fbe8SPierre Ossman
1473d3fc5d71SVincent Yang if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE))
14741c6a0718SPierre Ossman mode = SDHCI_TRNS_BLK_CNT_EN;
1475d3fc5d71SVincent Yang
1476e89d456fSAndrei Warkentin if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {
1477d3fc5d71SVincent Yang mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;
1478427b6514SChunyan Zhang sdhci_auto_cmd_select(host, cmd, &mode);
1479ed633033SAdrian Hunter if (sdhci_auto_cmd23(host, cmd->mrq))
1480a4c73abaSAdrian Hunter sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);
1481c4512f79SJerry Huang }
14828edf6371SAndrei Warkentin
14831c6a0718SPierre Ossman if (data->flags & MMC_DATA_READ)
14841c6a0718SPierre Ossman mode |= SDHCI_TRNS_READ;
1485c9fddbc4SPierre Ossman if (host->flags & SDHCI_REQ_USE_DMA)
14861c6a0718SPierre Ossman mode |= SDHCI_TRNS_DMA;
14871c6a0718SPierre Ossman
14884e4141a5SAnton Vorontsov sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
14891c6a0718SPierre Ossman }
14901c6a0718SPierre Ossman
sdhci_needs_reset(struct sdhci_host * host,struct mmc_request * mrq)14910cc563ceSAdrian Hunter static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq)
14920cc563ceSAdrian Hunter {
14930cc563ceSAdrian Hunter return (!(host->flags & SDHCI_DEVICE_DEAD) &&
14940cc563ceSAdrian Hunter ((mrq->cmd && mrq->cmd->error) ||
14950cc563ceSAdrian Hunter (mrq->sbc && mrq->sbc->error) ||
14964bf78099SAdrian Hunter (mrq->data && mrq->data->stop && mrq->data->stop->error) ||
14970cc563ceSAdrian Hunter (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)));
14980cc563ceSAdrian Hunter }
14990cc563ceSAdrian Hunter
sdhci_set_mrq_done(struct sdhci_host * host,struct mmc_request * mrq)150015db1836SFaiz Abbas static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq)
15014e9f8fe5SAdrian Hunter {
15024e9f8fe5SAdrian Hunter int i;
15034e9f8fe5SAdrian Hunter
15044e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) {
15054e9f8fe5SAdrian Hunter if (host->mrqs_done[i] == mrq) {
15064e9f8fe5SAdrian Hunter WARN_ON(1);
15074e9f8fe5SAdrian Hunter return;
15084e9f8fe5SAdrian Hunter }
15094e9f8fe5SAdrian Hunter }
15104e9f8fe5SAdrian Hunter
15114e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) {
15124e9f8fe5SAdrian Hunter if (!host->mrqs_done[i]) {
15134e9f8fe5SAdrian Hunter host->mrqs_done[i] = mrq;
15144e9f8fe5SAdrian Hunter break;
15154e9f8fe5SAdrian Hunter }
15164e9f8fe5SAdrian Hunter }
15174e9f8fe5SAdrian Hunter
15184e9f8fe5SAdrian Hunter WARN_ON(i >= SDHCI_MAX_MRQS);
151915db1836SFaiz Abbas }
152015db1836SFaiz Abbas
__sdhci_finish_mrq(struct sdhci_host * host,struct mmc_request * mrq)152115db1836SFaiz Abbas static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq)
152215db1836SFaiz Abbas {
152315db1836SFaiz Abbas if (host->cmd && host->cmd->mrq == mrq)
152415db1836SFaiz Abbas host->cmd = NULL;
152515db1836SFaiz Abbas
152615db1836SFaiz Abbas if (host->data_cmd && host->data_cmd->mrq == mrq)
152715db1836SFaiz Abbas host->data_cmd = NULL;
152815db1836SFaiz Abbas
1529845c939eSAdrian Hunter if (host->deferred_cmd && host->deferred_cmd->mrq == mrq)
1530845c939eSAdrian Hunter host->deferred_cmd = NULL;
1531845c939eSAdrian Hunter
153215db1836SFaiz Abbas if (host->data && host->data->mrq == mrq)
153315db1836SFaiz Abbas host->data = NULL;
153415db1836SFaiz Abbas
153515db1836SFaiz Abbas if (sdhci_needs_reset(host, mrq))
153615db1836SFaiz Abbas host->pending_reset = true;
153715db1836SFaiz Abbas
153815db1836SFaiz Abbas sdhci_set_mrq_done(host, mrq);
15394e9f8fe5SAdrian Hunter
1540e9a07299SAdrian Hunter sdhci_del_timer(host, mrq);
1541e9a07299SAdrian Hunter
1542e9a07299SAdrian Hunter if (!sdhci_has_requests(host))
1543e9a07299SAdrian Hunter sdhci_led_deactivate(host);
15444e9f8fe5SAdrian Hunter }
15454e9f8fe5SAdrian Hunter
sdhci_finish_mrq(struct sdhci_host * host,struct mmc_request * mrq)1546a6d3bdd5SAdrian Hunter static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq)
1547a6d3bdd5SAdrian Hunter {
15484e9f8fe5SAdrian Hunter __sdhci_finish_mrq(host, mrq);
15492e72ab9bSAdrian Hunter
1550c07a48c2SAdrian Hunter queue_work(host->complete_wq, &host->complete_work);
1551a6d3bdd5SAdrian Hunter }
1552a6d3bdd5SAdrian Hunter
__sdhci_finish_data(struct sdhci_host * host,bool sw_data_timeout)1553845c939eSAdrian Hunter static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout)
15541c6a0718SPierre Ossman {
155533a57adbSAdrian Hunter struct mmc_command *data_cmd = host->data_cmd;
155633a57adbSAdrian Hunter struct mmc_data *data = host->data;
15571c6a0718SPierre Ossman
15581c6a0718SPierre Ossman host->data = NULL;
15597c89a3d9SAdrian Hunter host->data_cmd = NULL;
15601c6a0718SPierre Ossman
15614bf78099SAdrian Hunter /*
15624bf78099SAdrian Hunter * The controller needs a reset of internal state machines upon error
15634bf78099SAdrian Hunter * conditions.
15644bf78099SAdrian Hunter */
15654bf78099SAdrian Hunter if (data->error) {
15664bf78099SAdrian Hunter if (!host->cmd || host->cmd == data_cmd)
15671e63d297SAdrian Hunter sdhci_reset_for(host, REQUEST_ERROR);
15681e63d297SAdrian Hunter else
15691e63d297SAdrian Hunter sdhci_reset_for(host, REQUEST_ERROR_DATA_ONLY);
15704bf78099SAdrian Hunter }
15714bf78099SAdrian Hunter
1572add8913dSRussell King if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) ==
1573add8913dSRussell King (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA))
15742134a922SPierre Ossman sdhci_adma_table_post(host, data);
1575f55c98f7SRussell King
15761c6a0718SPierre Ossman /*
1577c9b74c5bSPierre Ossman * The specification states that the block count register must
1578c9b74c5bSPierre Ossman * be updated, but it does not specify at what point in the
1579c9b74c5bSPierre Ossman * data flow. That makes the register entirely useless to read
1580c9b74c5bSPierre Ossman * back so we have to assume that nothing made it to the card
1581c9b74c5bSPierre Ossman * in the event of an error.
15821c6a0718SPierre Ossman */
1583c9b74c5bSPierre Ossman if (data->error)
1584c9b74c5bSPierre Ossman data->bytes_xfered = 0;
15851c6a0718SPierre Ossman else
1586c9b74c5bSPierre Ossman data->bytes_xfered = data->blksz * data->blocks;
15871c6a0718SPierre Ossman
1588e89d456fSAndrei Warkentin /*
1589e89d456fSAndrei Warkentin * Need to send CMD12 if -
1590fdbbe6cfSYangbo Lu * a) open-ended multiblock transfer not using auto CMD12 (no CMD23)
1591e89d456fSAndrei Warkentin * b) error in multiblock transfer
1592e89d456fSAndrei Warkentin */
1593e89d456fSAndrei Warkentin if (data->stop &&
1594fdbbe6cfSYangbo Lu ((!data->mrq->sbc && !sdhci_auto_cmd12(host, data->mrq)) ||
1595fdbbe6cfSYangbo Lu data->error)) {
159620845befSAdrian Hunter /*
159720845befSAdrian Hunter * 'cap_cmd_during_tfr' request must not use the command line
159820845befSAdrian Hunter * after mmc_command_done() has been called. It is upper layer's
159920845befSAdrian Hunter * responsibility to send the stop command if required.
160020845befSAdrian Hunter */
160120845befSAdrian Hunter if (data->mrq->cap_cmd_during_tfr) {
160219d2f695SAdrian Hunter __sdhci_finish_mrq(host, data->mrq);
160320845befSAdrian Hunter } else {
16048842fd17SAdrian Hunter /* Avoid triggering warning in sdhci_send_command() */
16058842fd17SAdrian Hunter host->cmd = NULL;
1606845c939eSAdrian Hunter if (!sdhci_send_command(host, data->stop)) {
1607845c939eSAdrian Hunter if (sw_data_timeout) {
1608845c939eSAdrian Hunter /*
1609845c939eSAdrian Hunter * This is anyway a sw data timeout, so
1610845c939eSAdrian Hunter * give up now.
1611845c939eSAdrian Hunter */
1612845c939eSAdrian Hunter data->stop->error = -EIO;
1613845c939eSAdrian Hunter __sdhci_finish_mrq(host, data->mrq);
1614845c939eSAdrian Hunter } else {
1615845c939eSAdrian Hunter WARN_ON(host->deferred_cmd);
1616845c939eSAdrian Hunter host->deferred_cmd = data->stop;
1617845c939eSAdrian Hunter }
1618845c939eSAdrian Hunter }
161920845befSAdrian Hunter }
1620a6d3bdd5SAdrian Hunter } else {
162119d2f695SAdrian Hunter __sdhci_finish_mrq(host, data->mrq);
1622a6d3bdd5SAdrian Hunter }
16231c6a0718SPierre Ossman }
16241c6a0718SPierre Ossman
sdhci_finish_data(struct sdhci_host * host)1625845c939eSAdrian Hunter static void sdhci_finish_data(struct sdhci_host *host)
1626845c939eSAdrian Hunter {
1627845c939eSAdrian Hunter __sdhci_finish_data(host, false);
1628845c939eSAdrian Hunter }
1629845c939eSAdrian Hunter
sdhci_send_command(struct sdhci_host * host,struct mmc_command * cmd)1630845c939eSAdrian Hunter static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
16311c6a0718SPierre Ossman {
16321c6a0718SPierre Ossman int flags;
16331c6a0718SPierre Ossman u32 mask;
16341c6a0718SPierre Ossman unsigned long timeout;
16351c6a0718SPierre Ossman
16361c6a0718SPierre Ossman WARN_ON(host->cmd);
16371c6a0718SPierre Ossman
163896776200SRussell King /* Initially, a command has no error */
163996776200SRussell King cmd->error = 0;
164096776200SRussell King
1641fc605f1dSAdrian Hunter if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) &&
1642fc605f1dSAdrian Hunter cmd->opcode == MMC_STOP_TRANSMISSION)
1643fc605f1dSAdrian Hunter cmd->flags |= MMC_RSP_BUSY;
1644fc605f1dSAdrian Hunter
16451c6a0718SPierre Ossman mask = SDHCI_CMD_INHIBIT;
164656a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd))
16471c6a0718SPierre Ossman mask |= SDHCI_DATA_INHIBIT;
16481c6a0718SPierre Ossman
16491c6a0718SPierre Ossman /* We shouldn't wait for data inihibit for stop commands, even
16501c6a0718SPierre Ossman though they might use busy signaling */
1651a4c73abaSAdrian Hunter if (cmd->mrq->data && (cmd == cmd->mrq->data->stop))
16521c6a0718SPierre Ossman mask &= ~SDHCI_DATA_INHIBIT;
16531c6a0718SPierre Ossman
1654845c939eSAdrian Hunter if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)
1655845c939eSAdrian Hunter return false;
16561c6a0718SPierre Ossman
16571c6a0718SPierre Ossman host->cmd = cmd;
165815db1836SFaiz Abbas host->data_timeout = 0;
165956a590dcSAdrian Hunter if (sdhci_data_line_cmd(cmd)) {
16607c89a3d9SAdrian Hunter WARN_ON(host->data_cmd);
16617c89a3d9SAdrian Hunter host->data_cmd = cmd;
166215db1836SFaiz Abbas sdhci_set_timeout(host, cmd);
16637c89a3d9SAdrian Hunter }
16641c6a0718SPierre Ossman
166518e762e3SChunyan Zhang if (cmd->data) {
166618e762e3SChunyan Zhang if (host->use_external_dma)
166718e762e3SChunyan Zhang sdhci_external_dma_prepare_data(host, cmd);
166818e762e3SChunyan Zhang else
1669a3c7778fSAndrei Warkentin sdhci_prepare_data(host, cmd);
167018e762e3SChunyan Zhang }
16711c6a0718SPierre Ossman
16724e4141a5SAnton Vorontsov sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT);
16731c6a0718SPierre Ossman
1674e89d456fSAndrei Warkentin sdhci_set_transfer_mode(host, cmd);
16751c6a0718SPierre Ossman
16761c6a0718SPierre Ossman if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
1677845c939eSAdrian Hunter WARN_ONCE(1, "Unsupported response type!\n");
1678845c939eSAdrian Hunter /*
1679845c939eSAdrian Hunter * This does not happen in practice because 136-bit response
1680845c939eSAdrian Hunter * commands never have busy waiting, so rather than complicate
1681845c939eSAdrian Hunter * the error path, just remove busy waiting and continue.
1682845c939eSAdrian Hunter */
1683845c939eSAdrian Hunter cmd->flags &= ~MMC_RSP_BUSY;
16841c6a0718SPierre Ossman }
16851c6a0718SPierre Ossman
16861c6a0718SPierre Ossman if (!(cmd->flags & MMC_RSP_PRESENT))
16871c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_NONE;
16881c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_136)
16891c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_LONG;
16901c6a0718SPierre Ossman else if (cmd->flags & MMC_RSP_BUSY)
16911c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT_BUSY;
16921c6a0718SPierre Ossman else
16931c6a0718SPierre Ossman flags = SDHCI_CMD_RESP_SHORT;
16941c6a0718SPierre Ossman
16951c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_CRC)
16961c6a0718SPierre Ossman flags |= SDHCI_CMD_CRC;
16971c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_OPCODE)
16981c6a0718SPierre Ossman flags |= SDHCI_CMD_INDEX;
1699b513ea25SArindam Nath
1700b513ea25SArindam Nath /* CMD19 is special in that the Data Present Select should be set */
1701b98e7e8dSChanWoo Lee if (cmd->data || mmc_op_tuning(cmd->opcode))
17021c6a0718SPierre Ossman flags |= SDHCI_CMD_DATA;
17031c6a0718SPierre Ossman
1704fc1fa1b7SKishon Vijay Abraham I timeout = jiffies;
1705fc1fa1b7SKishon Vijay Abraham I if (host->data_timeout)
1706fc1fa1b7SKishon Vijay Abraham I timeout += nsecs_to_jiffies(host->data_timeout);
1707fc1fa1b7SKishon Vijay Abraham I else if (!cmd->data && cmd->busy_timeout > 9000)
1708fc1fa1b7SKishon Vijay Abraham I timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ;
1709fc1fa1b7SKishon Vijay Abraham I else
1710fc1fa1b7SKishon Vijay Abraham I timeout += 10 * HZ;
1711fc1fa1b7SKishon Vijay Abraham I sdhci_mod_timer(host, cmd->mrq, timeout);
1712fc1fa1b7SKishon Vijay Abraham I
171318e762e3SChunyan Zhang if (host->use_external_dma)
171418e762e3SChunyan Zhang sdhci_external_dma_pre_transfer(host, cmd);
171518e762e3SChunyan Zhang
17164e4141a5SAnton Vorontsov sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
1717845c939eSAdrian Hunter
1718845c939eSAdrian Hunter return true;
17191c6a0718SPierre Ossman }
17201c6a0718SPierre Ossman
sdhci_present_error(struct sdhci_host * host,struct mmc_command * cmd,bool present)1721e872f1e2SAdrian Hunter static bool sdhci_present_error(struct sdhci_host *host,
1722e872f1e2SAdrian Hunter struct mmc_command *cmd, bool present)
1723e872f1e2SAdrian Hunter {
1724e872f1e2SAdrian Hunter if (!present || host->flags & SDHCI_DEVICE_DEAD) {
1725e872f1e2SAdrian Hunter cmd->error = -ENOMEDIUM;
1726e872f1e2SAdrian Hunter return true;
1727e872f1e2SAdrian Hunter }
1728e872f1e2SAdrian Hunter
1729e872f1e2SAdrian Hunter return false;
1730e872f1e2SAdrian Hunter }
1731e872f1e2SAdrian Hunter
sdhci_send_command_retry(struct sdhci_host * host,struct mmc_command * cmd,unsigned long flags)1732845c939eSAdrian Hunter static bool sdhci_send_command_retry(struct sdhci_host *host,
1733845c939eSAdrian Hunter struct mmc_command *cmd,
1734845c939eSAdrian Hunter unsigned long flags)
1735845c939eSAdrian Hunter __releases(host->lock)
1736845c939eSAdrian Hunter __acquires(host->lock)
1737845c939eSAdrian Hunter {
1738845c939eSAdrian Hunter struct mmc_command *deferred_cmd = host->deferred_cmd;
1739845c939eSAdrian Hunter int timeout = 10; /* Approx. 10 ms */
1740845c939eSAdrian Hunter bool present;
1741845c939eSAdrian Hunter
1742845c939eSAdrian Hunter while (!sdhci_send_command(host, cmd)) {
1743845c939eSAdrian Hunter if (!timeout--) {
1744845c939eSAdrian Hunter pr_err("%s: Controller never released inhibit bit(s).\n",
1745845c939eSAdrian Hunter mmc_hostname(host->mmc));
1746efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT);
1747845c939eSAdrian Hunter sdhci_dumpregs(host);
1748845c939eSAdrian Hunter cmd->error = -EIO;
1749845c939eSAdrian Hunter return false;
1750845c939eSAdrian Hunter }
1751845c939eSAdrian Hunter
1752845c939eSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
1753845c939eSAdrian Hunter
1754845c939eSAdrian Hunter usleep_range(1000, 1250);
1755845c939eSAdrian Hunter
1756845c939eSAdrian Hunter present = host->mmc->ops->get_cd(host->mmc);
1757845c939eSAdrian Hunter
1758845c939eSAdrian Hunter spin_lock_irqsave(&host->lock, flags);
1759845c939eSAdrian Hunter
1760845c939eSAdrian Hunter /* A deferred command might disappear, handle that */
1761845c939eSAdrian Hunter if (cmd == deferred_cmd && cmd != host->deferred_cmd)
1762845c939eSAdrian Hunter return true;
1763845c939eSAdrian Hunter
1764845c939eSAdrian Hunter if (sdhci_present_error(host, cmd, present))
1765845c939eSAdrian Hunter return false;
1766845c939eSAdrian Hunter }
1767845c939eSAdrian Hunter
1768845c939eSAdrian Hunter if (cmd == host->deferred_cmd)
1769845c939eSAdrian Hunter host->deferred_cmd = NULL;
1770845c939eSAdrian Hunter
1771845c939eSAdrian Hunter return true;
1772845c939eSAdrian Hunter }
1773845c939eSAdrian Hunter
sdhci_read_rsp_136(struct sdhci_host * host,struct mmc_command * cmd)17744a5fc119SAdrian Hunter static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd)
17754a5fc119SAdrian Hunter {
17764a5fc119SAdrian Hunter int i, reg;
17774a5fc119SAdrian Hunter
17784a5fc119SAdrian Hunter for (i = 0; i < 4; i++) {
17794a5fc119SAdrian Hunter reg = SDHCI_RESPONSE + (3 - i) * 4;
17804a5fc119SAdrian Hunter cmd->resp[i] = sdhci_readl(host, reg);
17814a5fc119SAdrian Hunter }
17824a5fc119SAdrian Hunter
17831284c248SKishon Vijay Abraham I if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC)
17841284c248SKishon Vijay Abraham I return;
17851284c248SKishon Vijay Abraham I
17864a5fc119SAdrian Hunter /* CRC is stripped so we need to do some shifting */
17874a5fc119SAdrian Hunter for (i = 0; i < 4; i++) {
17884a5fc119SAdrian Hunter cmd->resp[i] <<= 8;
17894a5fc119SAdrian Hunter if (i != 3)
17904a5fc119SAdrian Hunter cmd->resp[i] |= cmd->resp[i + 1] >> 24;
17914a5fc119SAdrian Hunter }
17924a5fc119SAdrian Hunter }
17934a5fc119SAdrian Hunter
sdhci_finish_command(struct sdhci_host * host)17941c6a0718SPierre Ossman static void sdhci_finish_command(struct sdhci_host *host)
17951c6a0718SPierre Ossman {
1796e0a5640aSAdrian Hunter struct mmc_command *cmd = host->cmd;
17971c6a0718SPierre Ossman
1798e0a5640aSAdrian Hunter host->cmd = NULL;
1799e0a5640aSAdrian Hunter
1800e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_PRESENT) {
1801e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_136) {
18024a5fc119SAdrian Hunter sdhci_read_rsp_136(host, cmd);
18031c6a0718SPierre Ossman } else {
1804e0a5640aSAdrian Hunter cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE);
18051c6a0718SPierre Ossman }
18061c6a0718SPierre Ossman }
18071c6a0718SPierre Ossman
180820845befSAdrian Hunter if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd)
180920845befSAdrian Hunter mmc_command_done(host->mmc, cmd->mrq);
181020845befSAdrian Hunter
18116bde8681SAdrian Hunter /*
18126bde8681SAdrian Hunter * The host can send and interrupt when the busy state has
18136bde8681SAdrian Hunter * ended, allowing us to wait without wasting CPU cycles.
18146bde8681SAdrian Hunter * The busy signal uses DAT0 so this is similar to waiting
18156bde8681SAdrian Hunter * for data to complete.
18166bde8681SAdrian Hunter *
18176bde8681SAdrian Hunter * Note: The 1.0 specification is a bit ambiguous about this
18186bde8681SAdrian Hunter * feature so there might be some problems with older
18196bde8681SAdrian Hunter * controllers.
18206bde8681SAdrian Hunter */
1821e0a5640aSAdrian Hunter if (cmd->flags & MMC_RSP_BUSY) {
1822e0a5640aSAdrian Hunter if (cmd->data) {
18236bde8681SAdrian Hunter DBG("Cannot wait for busy signal when also doing a data transfer");
18246bde8681SAdrian Hunter } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
1825ea968023SAdrian Hunter cmd == host->data_cmd) {
1826ea968023SAdrian Hunter /* Command complete before busy is ended */
18276bde8681SAdrian Hunter return;
18286bde8681SAdrian Hunter }
18296bde8681SAdrian Hunter }
18306bde8681SAdrian Hunter
1831e89d456fSAndrei Warkentin /* Finished CMD23, now send actual command. */
1832a4c73abaSAdrian Hunter if (cmd == cmd->mrq->sbc) {
1833845c939eSAdrian Hunter if (!sdhci_send_command(host, cmd->mrq->cmd)) {
1834845c939eSAdrian Hunter WARN_ON(host->deferred_cmd);
1835845c939eSAdrian Hunter host->deferred_cmd = cmd->mrq->cmd;
1836845c939eSAdrian Hunter }
1837e89d456fSAndrei Warkentin } else {
1838e89d456fSAndrei Warkentin
1839e89d456fSAndrei Warkentin /* Processed actual command. */
1840e538fbe8SPierre Ossman if (host->data && host->data_early)
1841e538fbe8SPierre Ossman sdhci_finish_data(host);
1842e538fbe8SPierre Ossman
1843e0a5640aSAdrian Hunter if (!cmd->data)
184419d2f695SAdrian Hunter __sdhci_finish_mrq(host, cmd->mrq);
18451c6a0718SPierre Ossman }
1846e89d456fSAndrei Warkentin }
18471c6a0718SPierre Ossman
sdhci_get_preset_value(struct sdhci_host * host)184852983382SKevin Liu static u16 sdhci_get_preset_value(struct sdhci_host *host)
184952983382SKevin Liu {
1850d975f121SRussell King u16 preset = 0;
185152983382SKevin Liu
1852d975f121SRussell King switch (host->timing) {
1853d0244847SAl Cooper case MMC_TIMING_MMC_HS:
1854d0244847SAl Cooper case MMC_TIMING_SD_HS:
1855d0244847SAl Cooper preset = sdhci_readw(host, SDHCI_PRESET_FOR_HIGH_SPEED);
1856d0244847SAl Cooper break;
1857d975f121SRussell King case MMC_TIMING_UHS_SDR12:
185852983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
185952983382SKevin Liu break;
1860d975f121SRussell King case MMC_TIMING_UHS_SDR25:
186152983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);
186252983382SKevin Liu break;
1863d975f121SRussell King case MMC_TIMING_UHS_SDR50:
186452983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);
186552983382SKevin Liu break;
1866d975f121SRussell King case MMC_TIMING_UHS_SDR104:
1867d975f121SRussell King case MMC_TIMING_MMC_HS200:
186852983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
186952983382SKevin Liu break;
1870d975f121SRussell King case MMC_TIMING_UHS_DDR50:
18710dafa60eSJisheng Zhang case MMC_TIMING_MMC_DDR52:
187252983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
187352983382SKevin Liu break;
1874e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400:
1875e9fb05d5SAdrian Hunter preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400);
1876e9fb05d5SAdrian Hunter break;
187752983382SKevin Liu default:
187852983382SKevin Liu pr_warn("%s: Invalid UHS-I mode selected\n",
187952983382SKevin Liu mmc_hostname(host->mmc));
188052983382SKevin Liu preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
188152983382SKevin Liu break;
188252983382SKevin Liu }
188352983382SKevin Liu return preset;
188452983382SKevin Liu }
188552983382SKevin Liu
sdhci_calc_clk(struct sdhci_host * host,unsigned int clock,unsigned int * actual_clock)1886fb9ee047SLudovic Desroches u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
1887fb9ee047SLudovic Desroches unsigned int *actual_clock)
18881c6a0718SPierre Ossman {
1889c3ed3877SArindam Nath int div = 0; /* Initialized for compiler warning */
1890df16219fSGiuseppe CAVALLARO int real_div = div, clk_mul = 1;
1891c3ed3877SArindam Nath u16 clk = 0;
18925497159cSludovic.desroches@atmel.com bool switch_base_clk = false;
18931c6a0718SPierre Ossman
189485105c53SZhangfei Gao if (host->version >= SDHCI_SPEC_300) {
1895da91a8f9SRussell King if (host->preset_enabled) {
189652983382SKevin Liu u16 pre_val;
189752983382SKevin Liu
189852983382SKevin Liu clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
189952983382SKevin Liu pre_val = sdhci_get_preset_value(host);
1900fa091010SMasahiro Yamada div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val);
190152983382SKevin Liu if (host->clk_mul &&
1902fa091010SMasahiro Yamada (pre_val & SDHCI_PRESET_CLKGEN_SEL)) {
190352983382SKevin Liu clk = SDHCI_PROG_CLOCK_MODE;
190452983382SKevin Liu real_div = div + 1;
190552983382SKevin Liu clk_mul = host->clk_mul;
190652983382SKevin Liu } else {
190752983382SKevin Liu real_div = max_t(int, 1, div << 1);
190852983382SKevin Liu }
190952983382SKevin Liu goto clock_set;
191052983382SKevin Liu }
191152983382SKevin Liu
1912c3ed3877SArindam Nath /*
1913c3ed3877SArindam Nath * Check if the Host Controller supports Programmable Clock
1914c3ed3877SArindam Nath * Mode.
1915c3ed3877SArindam Nath */
1916c3ed3877SArindam Nath if (host->clk_mul) {
1917c3ed3877SArindam Nath for (div = 1; div <= 1024; div++) {
191852983382SKevin Liu if ((host->max_clk * host->clk_mul / div)
191952983382SKevin Liu <= clock)
1920c3ed3877SArindam Nath break;
1921c3ed3877SArindam Nath }
19225497159cSludovic.desroches@atmel.com if ((host->max_clk * host->clk_mul / div) <= clock) {
1923c3ed3877SArindam Nath /*
1924c3ed3877SArindam Nath * Set Programmable Clock Mode in the Clock
1925c3ed3877SArindam Nath * Control register.
1926c3ed3877SArindam Nath */
1927c3ed3877SArindam Nath clk = SDHCI_PROG_CLOCK_MODE;
1928df16219fSGiuseppe CAVALLARO real_div = div;
1929df16219fSGiuseppe CAVALLARO clk_mul = host->clk_mul;
1930c3ed3877SArindam Nath div--;
1931c3ed3877SArindam Nath } else {
19325497159cSludovic.desroches@atmel.com /*
19335497159cSludovic.desroches@atmel.com * Divisor can be too small to reach clock
19345497159cSludovic.desroches@atmel.com * speed requirement. Then use the base clock.
19355497159cSludovic.desroches@atmel.com */
19365497159cSludovic.desroches@atmel.com switch_base_clk = true;
19375497159cSludovic.desroches@atmel.com }
19385497159cSludovic.desroches@atmel.com }
19395497159cSludovic.desroches@atmel.com
19405497159cSludovic.desroches@atmel.com if (!host->clk_mul || switch_base_clk) {
194185105c53SZhangfei Gao /* Version 3.00 divisors must be a multiple of 2. */
194285105c53SZhangfei Gao if (host->max_clk <= clock)
194385105c53SZhangfei Gao div = 1;
194485105c53SZhangfei Gao else {
1945c3ed3877SArindam Nath for (div = 2; div < SDHCI_MAX_DIV_SPEC_300;
1946c3ed3877SArindam Nath div += 2) {
194785105c53SZhangfei Gao if ((host->max_clk / div) <= clock)
194885105c53SZhangfei Gao break;
194985105c53SZhangfei Gao }
195085105c53SZhangfei Gao }
1951df16219fSGiuseppe CAVALLARO real_div = div;
1952c3ed3877SArindam Nath div >>= 1;
1953d1955c3aSSuneel Garapati if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN)
1954d1955c3aSSuneel Garapati && !div && host->max_clk <= 25000000)
1955d1955c3aSSuneel Garapati div = 1;
1956c3ed3877SArindam Nath }
195785105c53SZhangfei Gao } else {
195885105c53SZhangfei Gao /* Version 2.00 divisors must be a power of 2. */
19590397526dSZhangfei Gao for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
19601c6a0718SPierre Ossman if ((host->max_clk / div) <= clock)
19611c6a0718SPierre Ossman break;
19621c6a0718SPierre Ossman }
1963df16219fSGiuseppe CAVALLARO real_div = div;
19641c6a0718SPierre Ossman div >>= 1;
1965c3ed3877SArindam Nath }
19661c6a0718SPierre Ossman
196752983382SKevin Liu clock_set:
196803d6f5ffSAisheng Dong if (real_div)
1969fb9ee047SLudovic Desroches *actual_clock = (host->max_clk * clk_mul) / real_div;
1970c3ed3877SArindam Nath clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
197185105c53SZhangfei Gao clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
197285105c53SZhangfei Gao << SDHCI_DIVIDER_HI_SHIFT;
1973fb9ee047SLudovic Desroches
1974fb9ee047SLudovic Desroches return clk;
1975fb9ee047SLudovic Desroches }
1976fb9ee047SLudovic Desroches EXPORT_SYMBOL_GPL(sdhci_calc_clk);
1977fb9ee047SLudovic Desroches
sdhci_enable_clk(struct sdhci_host * host,u16 clk)1978fec79673SRitesh Harjani void sdhci_enable_clk(struct sdhci_host *host, u16 clk)
1979fb9ee047SLudovic Desroches {
19805a436cc0SAdrian Hunter ktime_t timeout;
1981fb9ee047SLudovic Desroches
19821c6a0718SPierre Ossman clk |= SDHCI_CLOCK_INT_EN;
19834e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
19841c6a0718SPierre Ossman
19854a9e0d1aSBen Chuang /* Wait max 150 ms */
19864a9e0d1aSBen Chuang timeout = ktime_add_ms(ktime_get(), 150);
1987b704441eSAlek Du while (1) {
1988b704441eSAlek Du bool timedout = ktime_after(ktime_get(), timeout);
1989b704441eSAlek Du
1990b704441eSAlek Du clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
1991b704441eSAlek Du if (clk & SDHCI_CLOCK_INT_STABLE)
1992b704441eSAlek Du break;
1993b704441eSAlek Du if (timedout) {
19942e4456f0SMarek Vasut pr_err("%s: Internal clock never stabilised.\n",
19952e4456f0SMarek Vasut mmc_hostname(host->mmc));
1996efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT);
19971c6a0718SPierre Ossman sdhci_dumpregs(host);
19981c6a0718SPierre Ossman return;
19991c6a0718SPierre Ossman }
20005a436cc0SAdrian Hunter udelay(10);
20011c6a0718SPierre Ossman }
20021c6a0718SPierre Ossman
20031beabbdbSBen Chuang if (host->version >= SDHCI_SPEC_410 && host->v4_mode) {
20041beabbdbSBen Chuang clk |= SDHCI_CLOCK_PLL_EN;
20051beabbdbSBen Chuang clk &= ~SDHCI_CLOCK_INT_STABLE;
20061beabbdbSBen Chuang sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
20071beabbdbSBen Chuang
20081beabbdbSBen Chuang /* Wait max 150 ms */
20091beabbdbSBen Chuang timeout = ktime_add_ms(ktime_get(), 150);
20101beabbdbSBen Chuang while (1) {
20111beabbdbSBen Chuang bool timedout = ktime_after(ktime_get(), timeout);
20121beabbdbSBen Chuang
20131beabbdbSBen Chuang clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
20141beabbdbSBen Chuang if (clk & SDHCI_CLOCK_INT_STABLE)
20151beabbdbSBen Chuang break;
20161beabbdbSBen Chuang if (timedout) {
20171beabbdbSBen Chuang pr_err("%s: PLL clock never stabilised.\n",
20181beabbdbSBen Chuang mmc_hostname(host->mmc));
2019efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CTRL_TIMEOUT);
20201beabbdbSBen Chuang sdhci_dumpregs(host);
20211beabbdbSBen Chuang return;
20221beabbdbSBen Chuang }
20231beabbdbSBen Chuang udelay(10);
20241beabbdbSBen Chuang }
20251beabbdbSBen Chuang }
20261beabbdbSBen Chuang
20271c6a0718SPierre Ossman clk |= SDHCI_CLOCK_CARD_EN;
20284e4141a5SAnton Vorontsov sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
20291c6a0718SPierre Ossman }
2030fec79673SRitesh Harjani EXPORT_SYMBOL_GPL(sdhci_enable_clk);
2031fec79673SRitesh Harjani
sdhci_set_clock(struct sdhci_host * host,unsigned int clock)2032fec79673SRitesh Harjani void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
2033fec79673SRitesh Harjani {
2034fec79673SRitesh Harjani u16 clk;
2035fec79673SRitesh Harjani
2036fec79673SRitesh Harjani host->mmc->actual_clock = 0;
2037fec79673SRitesh Harjani
2038fec79673SRitesh Harjani sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
2039fec79673SRitesh Harjani
2040fec79673SRitesh Harjani if (clock == 0)
2041fec79673SRitesh Harjani return;
2042fec79673SRitesh Harjani
2043fec79673SRitesh Harjani clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
2044fec79673SRitesh Harjani sdhci_enable_clk(host, clk);
2045fec79673SRitesh Harjani }
20461771059cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_clock);
20471c6a0718SPierre Ossman
sdhci_set_power_reg(struct sdhci_host * host,unsigned char mode,unsigned short vdd)20481dceb041SAdrian Hunter static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
204924fbb3caSRussell King unsigned short vdd)
20501c6a0718SPierre Ossman {
20513a48edc4STim Kryger struct mmc_host *mmc = host->mmc;
20521dceb041SAdrian Hunter
20531dceb041SAdrian Hunter mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
20541dceb041SAdrian Hunter
20551dceb041SAdrian Hunter if (mode != MMC_POWER_OFF)
20561dceb041SAdrian Hunter sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
20571dceb041SAdrian Hunter else
20581dceb041SAdrian Hunter sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
20591dceb041SAdrian Hunter }
20601dceb041SAdrian Hunter
sdhci_set_power_noreg(struct sdhci_host * host,unsigned char mode,unsigned short vdd)2061606d3131SAdrian Hunter void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
20621dceb041SAdrian Hunter unsigned short vdd)
20631dceb041SAdrian Hunter {
20648364248aSGiuseppe Cavallaro u8 pwr = 0;
20651c6a0718SPierre Ossman
206624fbb3caSRussell King if (mode != MMC_POWER_OFF) {
206724fbb3caSRussell King switch (1 << vdd) {
2068ae628903SPierre Ossman case MMC_VDD_165_195:
20692a609abeSAndy Shevchenko /*
20702a609abeSAndy Shevchenko * Without a regulator, SDHCI does not support 2.0v
20712a609abeSAndy Shevchenko * so we only get here if the driver deliberately
20722a609abeSAndy Shevchenko * added the 2.0v range to ocr_avail. Map it to 1.8v
20732a609abeSAndy Shevchenko * for the purpose of turning on the power.
20742a609abeSAndy Shevchenko */
20752a609abeSAndy Shevchenko case MMC_VDD_20_21:
2076ae628903SPierre Ossman pwr = SDHCI_POWER_180;
2077ae628903SPierre Ossman break;
2078ae628903SPierre Ossman case MMC_VDD_29_30:
2079ae628903SPierre Ossman case MMC_VDD_30_31:
2080ae628903SPierre Ossman pwr = SDHCI_POWER_300;
2081ae628903SPierre Ossman break;
2082ae628903SPierre Ossman case MMC_VDD_32_33:
2083ae628903SPierre Ossman case MMC_VDD_33_34:
20844217d07bSShawn Guo /*
20854217d07bSShawn Guo * 3.4 ~ 3.6V are valid only for those platforms where it's
20864217d07bSShawn Guo * known that the voltage range is supported by hardware.
20874217d07bSShawn Guo */
20884217d07bSShawn Guo case MMC_VDD_34_35:
20894217d07bSShawn Guo case MMC_VDD_35_36:
2090ae628903SPierre Ossman pwr = SDHCI_POWER_330;
2091ae628903SPierre Ossman break;
2092ae628903SPierre Ossman default:
20939d5de93fSAdrian Hunter WARN(1, "%s: Invalid vdd %#x\n",
20949d5de93fSAdrian Hunter mmc_hostname(host->mmc), vdd);
20959d5de93fSAdrian Hunter break;
2096ae628903SPierre Ossman }
2097ae628903SPierre Ossman }
2098ae628903SPierre Ossman
2099ae628903SPierre Ossman if (host->pwr == pwr)
2100e921a8b6SRussell King return;
21011c6a0718SPierre Ossman
2102ae628903SPierre Ossman host->pwr = pwr;
2103ae628903SPierre Ossman
2104ae628903SPierre Ossman if (pwr == 0) {
21054e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
2106f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
2107f0710a55SAdrian Hunter sdhci_runtime_pm_bus_off(host);
2108e921a8b6SRussell King } else {
21091c6a0718SPierre Ossman /*
21101c6a0718SPierre Ossman * Spec says that we should clear the power reg before setting
21111c6a0718SPierre Ossman * a new value. Some controllers don't seem to like this though.
21121c6a0718SPierre Ossman */
2113b8c86fc5SPierre Ossman if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
21144e4141a5SAnton Vorontsov sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
21151c6a0718SPierre Ossman
2116e08c1694SAndres Salomon /*
2117e921a8b6SRussell King * At least the Marvell CaFe chip gets confused if we set the
2118e921a8b6SRussell King * voltage and set turn on power at the same time, so set the
2119e921a8b6SRussell King * voltage first.
2120e08c1694SAndres Salomon */
212111a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
21224e4141a5SAnton Vorontsov sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
21231c6a0718SPierre Ossman
2124ae628903SPierre Ossman pwr |= SDHCI_POWER_ON;
2125ae628903SPierre Ossman
2126ae628903SPierre Ossman sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
2127557b0697SHarald Welte
2128f0710a55SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
2129f0710a55SAdrian Hunter sdhci_runtime_pm_bus_on(host);
2130f0710a55SAdrian Hunter
2131557b0697SHarald Welte /*
2132e921a8b6SRussell King * Some controllers need an extra 10ms delay of 10ms before
2133e921a8b6SRussell King * they can apply clock after applying power
2134557b0697SHarald Welte */
213511a2f1b7SPierre Ossman if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
2136557b0697SHarald Welte mdelay(10);
2137e921a8b6SRussell King }
2138918f4cbdSJisheng Zhang }
2139606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power_noreg);
21401dceb041SAdrian Hunter
sdhci_set_power(struct sdhci_host * host,unsigned char mode,unsigned short vdd)2141606d3131SAdrian Hunter void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
21421dceb041SAdrian Hunter unsigned short vdd)
21431dceb041SAdrian Hunter {
2144606d3131SAdrian Hunter if (IS_ERR(host->mmc->supply.vmmc))
2145606d3131SAdrian Hunter sdhci_set_power_noreg(host, mode, vdd);
21461dceb041SAdrian Hunter else
2147606d3131SAdrian Hunter sdhci_set_power_reg(host, mode, vdd);
21481c6a0718SPierre Ossman }
2149606d3131SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_set_power);
21501c6a0718SPierre Ossman
21516c92ae1eSNicolas Saenz Julienne /*
21526c92ae1eSNicolas Saenz Julienne * Some controllers need to configure a valid bus voltage on their power
21536c92ae1eSNicolas Saenz Julienne * register regardless of whether an external regulator is taking care of power
21546c92ae1eSNicolas Saenz Julienne * supply. This helper function takes care of it if set as the controller's
21556c92ae1eSNicolas Saenz Julienne * sdhci_ops.set_power callback.
21566c92ae1eSNicolas Saenz Julienne */
sdhci_set_power_and_bus_voltage(struct sdhci_host * host,unsigned char mode,unsigned short vdd)21576c92ae1eSNicolas Saenz Julienne void sdhci_set_power_and_bus_voltage(struct sdhci_host *host,
21586c92ae1eSNicolas Saenz Julienne unsigned char mode,
21596c92ae1eSNicolas Saenz Julienne unsigned short vdd)
21606c92ae1eSNicolas Saenz Julienne {
21616c92ae1eSNicolas Saenz Julienne if (!IS_ERR(host->mmc->supply.vmmc)) {
21626c92ae1eSNicolas Saenz Julienne struct mmc_host *mmc = host->mmc;
21636c92ae1eSNicolas Saenz Julienne
21646c92ae1eSNicolas Saenz Julienne mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
21656c92ae1eSNicolas Saenz Julienne }
21666c92ae1eSNicolas Saenz Julienne sdhci_set_power_noreg(host, mode, vdd);
21676c92ae1eSNicolas Saenz Julienne }
21686c92ae1eSNicolas Saenz Julienne EXPORT_SYMBOL_GPL(sdhci_set_power_and_bus_voltage);
21696c92ae1eSNicolas Saenz Julienne
21701c6a0718SPierre Ossman /*****************************************************************************\
21711c6a0718SPierre Ossman * *
21721c6a0718SPierre Ossman * MMC callbacks *
21731c6a0718SPierre Ossman * *
21741c6a0718SPierre Ossman \*****************************************************************************/
21751c6a0718SPierre Ossman
sdhci_request(struct mmc_host * mmc,struct mmc_request * mrq)2176d462c1b4SAapo Vienamo void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
21771c6a0718SPierre Ossman {
2178e872f1e2SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc);
2179e872f1e2SAdrian Hunter struct mmc_command *cmd;
21801c6a0718SPierre Ossman unsigned long flags;
2181e872f1e2SAdrian Hunter bool present;
21821c6a0718SPierre Ossman
218304e079cfSScott Branden /* Firstly check card presence */
21848d28b7a7SAdrian Hunter present = mmc->ops->get_cd(mmc);
21852836766aSKrzysztof Kozlowski
21861c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags);
21871c6a0718SPierre Ossman
2188061d17a6SAdrian Hunter sdhci_led_activate(host);
2189e89d456fSAndrei Warkentin
2190e872f1e2SAdrian Hunter if (sdhci_present_error(host, mrq->cmd, present))
2191e872f1e2SAdrian Hunter goto out_finish;
21921c6a0718SPierre Ossman
2193e872f1e2SAdrian Hunter cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd;
2194e872f1e2SAdrian Hunter
2195845c939eSAdrian Hunter if (!sdhci_send_command_retry(host, cmd, flags))
2196845c939eSAdrian Hunter goto out_finish;
2197e872f1e2SAdrian Hunter
2198e872f1e2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
2199e872f1e2SAdrian Hunter
2200e872f1e2SAdrian Hunter return;
2201e872f1e2SAdrian Hunter
2202e872f1e2SAdrian Hunter out_finish:
2203e872f1e2SAdrian Hunter sdhci_finish_mrq(host, mrq);
22041c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags);
22051c6a0718SPierre Ossman }
2206d462c1b4SAapo Vienamo EXPORT_SYMBOL_GPL(sdhci_request);
22071c6a0718SPierre Ossman
sdhci_request_atomic(struct mmc_host * mmc,struct mmc_request * mrq)220848ef8a2aSBaolin Wang int sdhci_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq)
220948ef8a2aSBaolin Wang {
221048ef8a2aSBaolin Wang struct sdhci_host *host = mmc_priv(mmc);
221148ef8a2aSBaolin Wang struct mmc_command *cmd;
221248ef8a2aSBaolin Wang unsigned long flags;
221348ef8a2aSBaolin Wang int ret = 0;
221448ef8a2aSBaolin Wang
221548ef8a2aSBaolin Wang spin_lock_irqsave(&host->lock, flags);
221648ef8a2aSBaolin Wang
221748ef8a2aSBaolin Wang if (sdhci_present_error(host, mrq->cmd, true)) {
221848ef8a2aSBaolin Wang sdhci_finish_mrq(host, mrq);
221948ef8a2aSBaolin Wang goto out_finish;
222048ef8a2aSBaolin Wang }
222148ef8a2aSBaolin Wang
222248ef8a2aSBaolin Wang cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd;
222348ef8a2aSBaolin Wang
222448ef8a2aSBaolin Wang /*
222548ef8a2aSBaolin Wang * The HSQ may send a command in interrupt context without polling
222648ef8a2aSBaolin Wang * the busy signaling, which means we should return BUSY if controller
222748ef8a2aSBaolin Wang * has not released inhibit bits to allow HSQ trying to send request
222848ef8a2aSBaolin Wang * again in non-atomic context. So we should not finish this request
222948ef8a2aSBaolin Wang * here.
223048ef8a2aSBaolin Wang */
223148ef8a2aSBaolin Wang if (!sdhci_send_command(host, cmd))
223248ef8a2aSBaolin Wang ret = -EBUSY;
223348ef8a2aSBaolin Wang else
223448ef8a2aSBaolin Wang sdhci_led_activate(host);
223548ef8a2aSBaolin Wang
223648ef8a2aSBaolin Wang out_finish:
223748ef8a2aSBaolin Wang spin_unlock_irqrestore(&host->lock, flags);
223848ef8a2aSBaolin Wang return ret;
223948ef8a2aSBaolin Wang }
224048ef8a2aSBaolin Wang EXPORT_SYMBOL_GPL(sdhci_request_atomic);
224148ef8a2aSBaolin Wang
sdhci_set_bus_width(struct sdhci_host * host,int width)22422317f56cSRussell King void sdhci_set_bus_width(struct sdhci_host *host, int width)
22432317f56cSRussell King {
22442317f56cSRussell King u8 ctrl;
22452317f56cSRussell King
22462317f56cSRussell King ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
22472317f56cSRussell King if (width == MMC_BUS_WIDTH_8) {
22482317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS;
22492317f56cSRussell King ctrl |= SDHCI_CTRL_8BITBUS;
22502317f56cSRussell King } else {
225198f94ea6SMichał Mirosław if (host->mmc->caps & MMC_CAP_8_BIT_DATA)
22522317f56cSRussell King ctrl &= ~SDHCI_CTRL_8BITBUS;
22532317f56cSRussell King if (width == MMC_BUS_WIDTH_4)
22542317f56cSRussell King ctrl |= SDHCI_CTRL_4BITBUS;
22552317f56cSRussell King else
22562317f56cSRussell King ctrl &= ~SDHCI_CTRL_4BITBUS;
22572317f56cSRussell King }
22582317f56cSRussell King sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
22592317f56cSRussell King }
22602317f56cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_bus_width);
22612317f56cSRussell King
sdhci_set_uhs_signaling(struct sdhci_host * host,unsigned timing)226296d7b78cSRussell King void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
226396d7b78cSRussell King {
226496d7b78cSRussell King u16 ctrl_2;
226596d7b78cSRussell King
226696d7b78cSRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
226796d7b78cSRussell King /* Select Bus Speed Mode for host */
226896d7b78cSRussell King ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
226996d7b78cSRussell King if ((timing == MMC_TIMING_MMC_HS200) ||
227096d7b78cSRussell King (timing == MMC_TIMING_UHS_SDR104))
227196d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
227296d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR12)
227396d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
227407bcc411SFaiz Abbas else if (timing == MMC_TIMING_UHS_SDR25)
227596d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
227696d7b78cSRussell King else if (timing == MMC_TIMING_UHS_SDR50)
227796d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
227896d7b78cSRussell King else if ((timing == MMC_TIMING_UHS_DDR50) ||
227996d7b78cSRussell King (timing == MMC_TIMING_MMC_DDR52))
228096d7b78cSRussell King ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
2281e9fb05d5SAdrian Hunter else if (timing == MMC_TIMING_MMC_HS400)
2282e9fb05d5SAdrian Hunter ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */
228396d7b78cSRussell King sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
228496d7b78cSRussell King }
228596d7b78cSRussell King EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
228696d7b78cSRussell King
sdhci_timing_has_preset(unsigned char timing)2287c981cdfbSAdrian Hunter static bool sdhci_timing_has_preset(unsigned char timing)
2288c981cdfbSAdrian Hunter {
2289c981cdfbSAdrian Hunter switch (timing) {
2290c981cdfbSAdrian Hunter case MMC_TIMING_UHS_SDR12:
2291c981cdfbSAdrian Hunter case MMC_TIMING_UHS_SDR25:
2292c981cdfbSAdrian Hunter case MMC_TIMING_UHS_SDR50:
2293c981cdfbSAdrian Hunter case MMC_TIMING_UHS_SDR104:
2294c981cdfbSAdrian Hunter case MMC_TIMING_UHS_DDR50:
2295c981cdfbSAdrian Hunter case MMC_TIMING_MMC_DDR52:
2296c981cdfbSAdrian Hunter return true;
2297496182a3Szhang songyi }
2298c981cdfbSAdrian Hunter return false;
2299c981cdfbSAdrian Hunter }
2300c981cdfbSAdrian Hunter
sdhci_preset_needed(struct sdhci_host * host,unsigned char timing)2301c981cdfbSAdrian Hunter static bool sdhci_preset_needed(struct sdhci_host *host, unsigned char timing)
2302c981cdfbSAdrian Hunter {
2303c981cdfbSAdrian Hunter return !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
2304c981cdfbSAdrian Hunter sdhci_timing_has_preset(timing);
2305c981cdfbSAdrian Hunter }
2306c981cdfbSAdrian Hunter
sdhci_presetable_values_change(struct sdhci_host * host,struct mmc_ios * ios)2307c981cdfbSAdrian Hunter static bool sdhci_presetable_values_change(struct sdhci_host *host, struct mmc_ios *ios)
2308c981cdfbSAdrian Hunter {
2309c981cdfbSAdrian Hunter /*
2310c981cdfbSAdrian Hunter * Preset Values are: Driver Strength, Clock Generator and SDCLK/RCLK
2311c981cdfbSAdrian Hunter * Frequency. Check if preset values need to be enabled, or the Driver
2312c981cdfbSAdrian Hunter * Strength needs updating. Note, clock changes are handled separately.
2313c981cdfbSAdrian Hunter */
2314c981cdfbSAdrian Hunter return !host->preset_enabled &&
2315c981cdfbSAdrian Hunter (sdhci_preset_needed(host, ios->timing) || host->drv_type != ios->drv_type);
2316c981cdfbSAdrian Hunter }
2317c981cdfbSAdrian Hunter
sdhci_set_ios(struct mmc_host * mmc,struct mmc_ios * ios)23186a6d4cebSHu Ziji void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
23191c6a0718SPierre Ossman {
2320ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc);
2321c981cdfbSAdrian Hunter bool reinit_uhs = host->reinit_uhs;
2322c981cdfbSAdrian Hunter bool turning_on_clk = false;
23231c6a0718SPierre Ossman u8 ctrl;
23241c6a0718SPierre Ossman
2325c981cdfbSAdrian Hunter host->reinit_uhs = false;
2326c981cdfbSAdrian Hunter
232784ec048bSAdrian Hunter if (ios->power_mode == MMC_POWER_UNDEFINED)
232884ec048bSAdrian Hunter return;
232984ec048bSAdrian Hunter
2330ceb6143bSAdrian Hunter if (host->flags & SDHCI_DEVICE_DEAD) {
23313a48edc4STim Kryger if (!IS_ERR(mmc->supply.vmmc) &&
23323a48edc4STim Kryger ios->power_mode == MMC_POWER_OFF)
23334e743f1fSMarkus Mayer mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
2334ceb6143bSAdrian Hunter return;
2335ceb6143bSAdrian Hunter }
23361e72859eSPierre Ossman
23371c6a0718SPierre Ossman /*
23381c6a0718SPierre Ossman * Reset the chip on each power off.
23391c6a0718SPierre Ossman * Should clear out any weird states.
23401c6a0718SPierre Ossman */
23411c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_OFF) {
23424e4141a5SAnton Vorontsov sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
23437260cf5eSAnton Vorontsov sdhci_reinit(host);
23441c6a0718SPierre Ossman }
23451c6a0718SPierre Ossman
234652983382SKevin Liu if (host->version >= SDHCI_SPEC_300 &&
2347372c4634SDong Aisheng (ios->power_mode == MMC_POWER_UP) &&
2348372c4634SDong Aisheng !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
234952983382SKevin Liu sdhci_enable_preset_value(host, false);
235052983382SKevin Liu
2351373073efSRussell King if (!ios->clock || ios->clock != host->clock) {
2352c981cdfbSAdrian Hunter turning_on_clk = ios->clock && !host->clock;
2353c981cdfbSAdrian Hunter
23541771059cSRussell King host->ops->set_clock(host, ios->clock);
2355373073efSRussell King host->clock = ios->clock;
235603d6f5ffSAisheng Dong
235703d6f5ffSAisheng Dong if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK &&
235803d6f5ffSAisheng Dong host->clock) {
2359d2f025b0SJisheng Zhang host->timeout_clk = mmc->actual_clock ?
2360d2f025b0SJisheng Zhang mmc->actual_clock / 1000 :
236103d6f5ffSAisheng Dong host->clock / 1000;
2362d2f025b0SJisheng Zhang mmc->max_busy_timeout =
236303d6f5ffSAisheng Dong host->ops->get_max_timeout_count ?
236403d6f5ffSAisheng Dong host->ops->get_max_timeout_count(host) :
236503d6f5ffSAisheng Dong 1 << 27;
2366d2f025b0SJisheng Zhang mmc->max_busy_timeout /= host->timeout_clk;
236703d6f5ffSAisheng Dong }
2368373073efSRussell King }
23691c6a0718SPierre Ossman
2370606d3131SAdrian Hunter if (host->ops->set_power)
2371606d3131SAdrian Hunter host->ops->set_power(host, ios->power_mode, ios->vdd);
2372606d3131SAdrian Hunter else
2373606d3131SAdrian Hunter sdhci_set_power(host, ios->power_mode, ios->vdd);
23741c6a0718SPierre Ossman
2375643a81ffSPhilip Rakity if (host->ops->platform_send_init_74_clocks)
2376643a81ffSPhilip Rakity host->ops->platform_send_init_74_clocks(host, ios->power_mode);
2377643a81ffSPhilip Rakity
23782317f56cSRussell King host->ops->set_bus_width(host, ios->bus_width);
237915ec4461SPhilip Rakity
2380c981cdfbSAdrian Hunter /*
2381c981cdfbSAdrian Hunter * Special case to avoid multiple clock changes during voltage
2382c981cdfbSAdrian Hunter * switching.
2383c981cdfbSAdrian Hunter */
2384c981cdfbSAdrian Hunter if (!reinit_uhs &&
2385c981cdfbSAdrian Hunter turning_on_clk &&
2386c981cdfbSAdrian Hunter host->timing == ios->timing &&
2387c981cdfbSAdrian Hunter host->version >= SDHCI_SPEC_300 &&
2388c981cdfbSAdrian Hunter !sdhci_presetable_values_change(host, ios))
2389c981cdfbSAdrian Hunter return;
2390c981cdfbSAdrian Hunter
239115ec4461SPhilip Rakity ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
23921c6a0718SPierre Ossman
2393501639bfSyangbo lu if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) {
2394501639bfSyangbo lu if (ios->timing == MMC_TIMING_SD_HS ||
2395273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS ||
2396273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS400 ||
2397273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_HS200 ||
2398273c5414SJaehoon Chung ios->timing == MMC_TIMING_MMC_DDR52 ||
2399273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR50 ||
2400273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR104 ||
2401273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_DDR50 ||
2402273c5414SJaehoon Chung ios->timing == MMC_TIMING_UHS_SDR25)
24031c6a0718SPierre Ossman ctrl |= SDHCI_CTRL_HISPD;
24041c6a0718SPierre Ossman else
24051c6a0718SPierre Ossman ctrl &= ~SDHCI_CTRL_HISPD;
2406501639bfSyangbo lu }
24071c6a0718SPierre Ossman
2408d6d50a15SArindam Nath if (host->version >= SDHCI_SPEC_300) {
240949c468fcSArindam Nath u16 clk, ctrl_2;
241049c468fcSArindam Nath
2411beaba9e4SAdrian Hunter /*
2412beaba9e4SAdrian Hunter * According to SDHCI Spec v3.00, if the Preset Value
2413beaba9e4SAdrian Hunter * Enable in the Host Control 2 register is set, we
2414beaba9e4SAdrian Hunter * need to reset SD Clock Enable before changing High
2415beaba9e4SAdrian Hunter * Speed Enable to avoid generating clock glitches.
2416beaba9e4SAdrian Hunter */
2417beaba9e4SAdrian Hunter clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
2418beaba9e4SAdrian Hunter if (clk & SDHCI_CLOCK_CARD_EN) {
2419beaba9e4SAdrian Hunter clk &= ~SDHCI_CLOCK_CARD_EN;
2420beaba9e4SAdrian Hunter sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
2421beaba9e4SAdrian Hunter }
2422beaba9e4SAdrian Hunter
2423758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
2424beaba9e4SAdrian Hunter
2425beaba9e4SAdrian Hunter if (!host->preset_enabled) {
2426d6d50a15SArindam Nath /*
2427d6d50a15SArindam Nath * We only need to set Driver Strength if the
2428d6d50a15SArindam Nath * preset value enable is not set.
2429d6d50a15SArindam Nath */
2430da91a8f9SRussell King ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
2431d6d50a15SArindam Nath ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
2432d6d50a15SArindam Nath if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
2433d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
243443e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_B)
243543e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
2436d6d50a15SArindam Nath else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C)
2437d6d50a15SArindam Nath ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C;
243843e943a0SPetri Gynther else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D)
243943e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D;
244043e943a0SPetri Gynther else {
24412e4456f0SMarek Vasut pr_warn("%s: invalid driver type, default to driver type B\n",
24422e4456f0SMarek Vasut mmc_hostname(mmc));
244343e943a0SPetri Gynther ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
244443e943a0SPetri Gynther }
2445d6d50a15SArindam Nath
2446d6d50a15SArindam Nath sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
2447c981cdfbSAdrian Hunter host->drv_type = ios->drv_type;
2448d6d50a15SArindam Nath }
244949c468fcSArindam Nath
24506322cdd0SPhilip Rakity host->ops->set_uhs_signaling(host, ios->timing);
2451d975f121SRussell King host->timing = ios->timing;
245249c468fcSArindam Nath
2453c981cdfbSAdrian Hunter if (sdhci_preset_needed(host, ios->timing)) {
245452983382SKevin Liu u16 preset;
245552983382SKevin Liu
245652983382SKevin Liu sdhci_enable_preset_value(host, true);
245752983382SKevin Liu preset = sdhci_get_preset_value(host);
2458fa091010SMasahiro Yamada ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK,
2459fa091010SMasahiro Yamada preset);
2460c981cdfbSAdrian Hunter host->drv_type = ios->drv_type;
246152983382SKevin Liu }
246252983382SKevin Liu
246349c468fcSArindam Nath /* Re-enable SD Clock */
24641771059cSRussell King host->ops->set_clock(host, host->clock);
2465758535c4SArindam Nath } else
2466758535c4SArindam Nath sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
24671c6a0718SPierre Ossman }
24686a6d4cebSHu Ziji EXPORT_SYMBOL_GPL(sdhci_set_ios);
24691c6a0718SPierre Ossman
sdhci_get_cd(struct mmc_host * mmc)2470ded97e0bSDong Aisheng static int sdhci_get_cd(struct mmc_host *mmc)
247166fd8ad5SAdrian Hunter {
247266fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc);
2473ded97e0bSDong Aisheng int gpio_cd = mmc_gpio_get_cd(mmc);
247494144a46SKevin Liu
247594144a46SKevin Liu if (host->flags & SDHCI_DEVICE_DEAD)
247694144a46SKevin Liu return 0;
247794144a46SKevin Liu
247888af5655SIvan T. Ivanov /* If nonremovable, assume that the card is always present. */
2479d2f025b0SJisheng Zhang if (!mmc_card_is_removable(mmc))
248094144a46SKevin Liu return 1;
248194144a46SKevin Liu
248288af5655SIvan T. Ivanov /*
248388af5655SIvan T. Ivanov * Try slot gpio detect, if defined it take precedence
248488af5655SIvan T. Ivanov * over build in controller functionality
248588af5655SIvan T. Ivanov */
2486287980e4SArnd Bergmann if (gpio_cd >= 0)
248794144a46SKevin Liu return !!gpio_cd;
248894144a46SKevin Liu
248988af5655SIvan T. Ivanov /* If polling, assume that the card is always present. */
249088af5655SIvan T. Ivanov if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
249188af5655SIvan T. Ivanov return 1;
249288af5655SIvan T. Ivanov
249394144a46SKevin Liu /* Host native card detect */
249494144a46SKevin Liu return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
249594144a46SKevin Liu }
249694144a46SKevin Liu
sdhci_get_cd_nogpio(struct mmc_host * mmc)24972caa11bcSAndy Shevchenko int sdhci_get_cd_nogpio(struct mmc_host *mmc)
24982caa11bcSAndy Shevchenko {
24992caa11bcSAndy Shevchenko struct sdhci_host *host = mmc_priv(mmc);
25002caa11bcSAndy Shevchenko unsigned long flags;
25012caa11bcSAndy Shevchenko int ret = 0;
25022caa11bcSAndy Shevchenko
25032caa11bcSAndy Shevchenko spin_lock_irqsave(&host->lock, flags);
25042caa11bcSAndy Shevchenko
25052caa11bcSAndy Shevchenko if (host->flags & SDHCI_DEVICE_DEAD)
25062caa11bcSAndy Shevchenko goto out;
25072caa11bcSAndy Shevchenko
25082caa11bcSAndy Shevchenko ret = !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
25092caa11bcSAndy Shevchenko out:
25102caa11bcSAndy Shevchenko spin_unlock_irqrestore(&host->lock, flags);
25112caa11bcSAndy Shevchenko
25122caa11bcSAndy Shevchenko return ret;
25132caa11bcSAndy Shevchenko }
25142caa11bcSAndy Shevchenko EXPORT_SYMBOL_GPL(sdhci_get_cd_nogpio);
25152caa11bcSAndy Shevchenko
sdhci_check_ro(struct sdhci_host * host)251666fd8ad5SAdrian Hunter static int sdhci_check_ro(struct sdhci_host *host)
25171c6a0718SPierre Ossman {
2518*3336979bSAdrian Hunter bool allow_invert = false;
25192dfb579cSWolfram Sang int is_readonly;
25201c6a0718SPierre Ossman
2521*3336979bSAdrian Hunter if (host->flags & SDHCI_DEVICE_DEAD) {
25222dfb579cSWolfram Sang is_readonly = 0;
2523*3336979bSAdrian Hunter } else if (host->ops->get_ro) {
25242dfb579cSWolfram Sang is_readonly = host->ops->get_ro(host);
2525*3336979bSAdrian Hunter } else if (mmc_can_gpio_ro(host->mmc)) {
25266d5cd068SThomas Petazzoni is_readonly = mmc_gpio_get_ro(host->mmc);
2527*3336979bSAdrian Hunter /* Do not invert twice */
2528*3336979bSAdrian Hunter allow_invert = !(host->mmc->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
2529*3336979bSAdrian Hunter } else {
25302dfb579cSWolfram Sang is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
25312dfb579cSWolfram Sang & SDHCI_WRITE_PROTECT);
2532*3336979bSAdrian Hunter allow_invert = true;
2533*3336979bSAdrian Hunter }
25341c6a0718SPierre Ossman
2535*3336979bSAdrian Hunter if (is_readonly >= 0 &&
2536*3336979bSAdrian Hunter allow_invert &&
2537*3336979bSAdrian Hunter (host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT))
2538*3336979bSAdrian Hunter is_readonly = !is_readonly;
2539*3336979bSAdrian Hunter
2540*3336979bSAdrian Hunter return is_readonly;
25411c6a0718SPierre Ossman }
25421c6a0718SPierre Ossman
254382b0e23aSTakashi Iwai #define SAMPLE_COUNT 5
254482b0e23aSTakashi Iwai
sdhci_get_ro(struct mmc_host * mmc)2545ded97e0bSDong Aisheng static int sdhci_get_ro(struct mmc_host *mmc)
254682b0e23aSTakashi Iwai {
2547ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc);
254882b0e23aSTakashi Iwai int i, ro_count;
254982b0e23aSTakashi Iwai
255082b0e23aSTakashi Iwai if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
255166fd8ad5SAdrian Hunter return sdhci_check_ro(host);
255282b0e23aSTakashi Iwai
255382b0e23aSTakashi Iwai ro_count = 0;
255482b0e23aSTakashi Iwai for (i = 0; i < SAMPLE_COUNT; i++) {
255566fd8ad5SAdrian Hunter if (sdhci_check_ro(host)) {
255682b0e23aSTakashi Iwai if (++ro_count > SAMPLE_COUNT / 2)
255782b0e23aSTakashi Iwai return 1;
255882b0e23aSTakashi Iwai }
255982b0e23aSTakashi Iwai msleep(30);
256082b0e23aSTakashi Iwai }
256182b0e23aSTakashi Iwai return 0;
256282b0e23aSTakashi Iwai }
256382b0e23aSTakashi Iwai
sdhci_hw_reset(struct mmc_host * mmc)256420758b66SAdrian Hunter static void sdhci_hw_reset(struct mmc_host *mmc)
256520758b66SAdrian Hunter {
256620758b66SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc);
256720758b66SAdrian Hunter
256820758b66SAdrian Hunter if (host->ops && host->ops->hw_reset)
256920758b66SAdrian Hunter host->ops->hw_reset(host);
257020758b66SAdrian Hunter }
257120758b66SAdrian Hunter
sdhci_enable_sdio_irq_nolock(struct sdhci_host * host,int enable)257266fd8ad5SAdrian Hunter static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
257366fd8ad5SAdrian Hunter {
2574be138554SRussell King if (!(host->flags & SDHCI_DEVICE_DEAD)) {
257566fd8ad5SAdrian Hunter if (enable)
2576b537f94cSRussell King host->ier |= SDHCI_INT_CARD_INT;
25777260cf5eSAnton Vorontsov else
2578b537f94cSRussell King host->ier &= ~SDHCI_INT_CARD_INT;
2579b537f94cSRussell King
2580b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
2581b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
258266fd8ad5SAdrian Hunter }
2583ef104333SRussell King }
2584f75979b7SPierre Ossman
sdhci_enable_sdio_irq(struct mmc_host * mmc,int enable)25852f05b6abSHu Ziji void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
258666fd8ad5SAdrian Hunter {
258766fd8ad5SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc);
258866fd8ad5SAdrian Hunter unsigned long flags;
258966fd8ad5SAdrian Hunter
2590923713b3SHans de Goede if (enable)
2591bac53336SJisheng Zhang pm_runtime_get_noresume(mmc_dev(mmc));
2592923713b3SHans de Goede
259366fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags);
259466fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, enable);
2595f75979b7SPierre Ossman spin_unlock_irqrestore(&host->lock, flags);
2596923713b3SHans de Goede
2597923713b3SHans de Goede if (!enable)
2598bac53336SJisheng Zhang pm_runtime_put_noidle(mmc_dev(mmc));
2599f75979b7SPierre Ossman }
26002f05b6abSHu Ziji EXPORT_SYMBOL_GPL(sdhci_enable_sdio_irq);
2601f75979b7SPierre Ossman
sdhci_ack_sdio_irq(struct mmc_host * mmc)260289f3c365SAdrian Hunter static void sdhci_ack_sdio_irq(struct mmc_host *mmc)
260389f3c365SAdrian Hunter {
260489f3c365SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc);
260589f3c365SAdrian Hunter unsigned long flags;
260689f3c365SAdrian Hunter
260789f3c365SAdrian Hunter spin_lock_irqsave(&host->lock, flags);
260889f3c365SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true);
260989f3c365SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
261089f3c365SAdrian Hunter }
261189f3c365SAdrian Hunter
sdhci_start_signal_voltage_switch(struct mmc_host * mmc,struct mmc_ios * ios)2612c376ea9eSHu Ziji int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
261321f5998fSFabio Estevam struct mmc_ios *ios)
2614f2119df6SArindam Nath {
2615ded97e0bSDong Aisheng struct sdhci_host *host = mmc_priv(mmc);
261620b92a30SKevin Liu u16 ctrl;
26176231f3deSPhilip Rakity int ret;
2618f2119df6SArindam Nath
261920b92a30SKevin Liu /*
262020b92a30SKevin Liu * Signal Voltage Switching is only applicable for Host Controllers
262120b92a30SKevin Liu * v3.00 and above.
262220b92a30SKevin Liu */
262320b92a30SKevin Liu if (host->version < SDHCI_SPEC_300)
262420b92a30SKevin Liu return 0;
262520b92a30SKevin Liu
262620b92a30SKevin Liu ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
262720b92a30SKevin Liu
262821f5998fSFabio Estevam switch (ios->signal_voltage) {
262920b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_330:
26308cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_330))
26318cb851a4SAdrian Hunter return -EINVAL;
2632f2119df6SArindam Nath /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
2633f2119df6SArindam Nath ctrl &= ~SDHCI_CTRL_VDD_180;
2634f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
2635f2119df6SArindam Nath
26363a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) {
2637761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios);
26389cbe0fc8SMarek Vasut if (ret < 0) {
26396606110dSJoe Perches pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
26406606110dSJoe Perches mmc_hostname(mmc));
26416231f3deSPhilip Rakity return -EIO;
26426231f3deSPhilip Rakity }
26436231f3deSPhilip Rakity }
2644f2119df6SArindam Nath /* Wait for 5ms */
2645f2119df6SArindam Nath usleep_range(5000, 5500);
2646f2119df6SArindam Nath
2647f2119df6SArindam Nath /* 3.3V regulator output should be stable within 5 ms */
2648f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
2649f2119df6SArindam Nath if (!(ctrl & SDHCI_CTRL_VDD_180))
2650f2119df6SArindam Nath return 0;
26516231f3deSPhilip Rakity
2652b0b19ce6SFabio Estevam pr_warn("%s: 3.3V regulator output did not become stable\n",
26534e743f1fSMarkus Mayer mmc_hostname(mmc));
26546231f3deSPhilip Rakity
265520b92a30SKevin Liu return -EAGAIN;
265620b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_180:
26578cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_180))
26588cb851a4SAdrian Hunter return -EINVAL;
26593a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) {
2660761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios);
26619cbe0fc8SMarek Vasut if (ret < 0) {
26626606110dSJoe Perches pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
26636606110dSJoe Perches mmc_hostname(mmc));
2664f2119df6SArindam Nath return -EIO;
2665f2119df6SArindam Nath }
266620b92a30SKevin Liu }
26676231f3deSPhilip Rakity
2668f2119df6SArindam Nath /*
2669f2119df6SArindam Nath * Enable 1.8V Signal Enable in the Host Control2
2670f2119df6SArindam Nath * register
2671f2119df6SArindam Nath */
2672f2119df6SArindam Nath ctrl |= SDHCI_CTRL_VDD_180;
2673f2119df6SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
2674f2119df6SArindam Nath
26759d967a61SVincent Yang /* Some controller need to do more when switching */
26769d967a61SVincent Yang if (host->ops->voltage_switch)
26779d967a61SVincent Yang host->ops->voltage_switch(host);
26789d967a61SVincent Yang
267920b92a30SKevin Liu /* 1.8V regulator output should be stable within 5 ms */
2680f2119df6SArindam Nath ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
268120b92a30SKevin Liu if (ctrl & SDHCI_CTRL_VDD_180)
2682f2119df6SArindam Nath return 0;
2683f2119df6SArindam Nath
2684b0b19ce6SFabio Estevam pr_warn("%s: 1.8V regulator output did not become stable\n",
26854e743f1fSMarkus Mayer mmc_hostname(mmc));
26866231f3deSPhilip Rakity
2687f2119df6SArindam Nath return -EAGAIN;
268820b92a30SKevin Liu case MMC_SIGNAL_VOLTAGE_120:
26898cb851a4SAdrian Hunter if (!(host->flags & SDHCI_SIGNALING_120))
26908cb851a4SAdrian Hunter return -EINVAL;
26913a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) {
2692761daa36SDong Aisheng ret = mmc_regulator_set_vqmmc(mmc, ios);
26939cbe0fc8SMarek Vasut if (ret < 0) {
26946606110dSJoe Perches pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
26956606110dSJoe Perches mmc_hostname(mmc));
269620b92a30SKevin Liu return -EIO;
26976231f3deSPhilip Rakity }
269820b92a30SKevin Liu }
26996231f3deSPhilip Rakity return 0;
270020b92a30SKevin Liu default:
2701f2119df6SArindam Nath /* No signal voltage switch required */
2702f2119df6SArindam Nath return 0;
2703f2119df6SArindam Nath }
270420b92a30SKevin Liu }
2705c376ea9eSHu Ziji EXPORT_SYMBOL_GPL(sdhci_start_signal_voltage_switch);
2706f2119df6SArindam Nath
sdhci_card_busy(struct mmc_host * mmc)270720b92a30SKevin Liu static int sdhci_card_busy(struct mmc_host *mmc)
270820b92a30SKevin Liu {
270920b92a30SKevin Liu struct sdhci_host *host = mmc_priv(mmc);
271020b92a30SKevin Liu u32 present_state;
271120b92a30SKevin Liu
2712e613cc47SAdrian Hunter /* Check whether DAT[0] is 0 */
271320b92a30SKevin Liu present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
271420b92a30SKevin Liu
2715e613cc47SAdrian Hunter return !(present_state & SDHCI_DATA_0_LVL_MASK);
271620b92a30SKevin Liu }
271720b92a30SKevin Liu
sdhci_prepare_hs400_tuning(struct mmc_host * mmc,struct mmc_ios * ios)2718b5540ce1SAdrian Hunter static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
2719b5540ce1SAdrian Hunter {
2720b5540ce1SAdrian Hunter struct sdhci_host *host = mmc_priv(mmc);
2721b5540ce1SAdrian Hunter unsigned long flags;
2722b5540ce1SAdrian Hunter
2723b5540ce1SAdrian Hunter spin_lock_irqsave(&host->lock, flags);
2724b5540ce1SAdrian Hunter host->flags |= SDHCI_HS400_TUNING;
2725b5540ce1SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
2726b5540ce1SAdrian Hunter
2727b5540ce1SAdrian Hunter return 0;
2728b5540ce1SAdrian Hunter }
2729b5540ce1SAdrian Hunter
sdhci_start_tuning(struct sdhci_host * host)27306663c419Sernest.zhang void sdhci_start_tuning(struct sdhci_host *host)
2731da4bc4f2SAdrian Hunter {
2732da4bc4f2SAdrian Hunter u16 ctrl;
2733da4bc4f2SAdrian Hunter
2734da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
2735da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_EXEC_TUNING;
2736da4bc4f2SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND)
2737da4bc4f2SAdrian Hunter ctrl |= SDHCI_CTRL_TUNED_CLK;
2738da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
2739da4bc4f2SAdrian Hunter
2740da4bc4f2SAdrian Hunter /*
2741da4bc4f2SAdrian Hunter * As per the Host Controller spec v3.00, tuning command
2742da4bc4f2SAdrian Hunter * generates Buffer Read Ready interrupt, so enable that.
2743da4bc4f2SAdrian Hunter *
2744da4bc4f2SAdrian Hunter * Note: The spec clearly says that when tuning sequence
2745da4bc4f2SAdrian Hunter * is being performed, the controller does not generate
2746da4bc4f2SAdrian Hunter * interrupts other than Buffer Read Ready interrupt. But
2747da4bc4f2SAdrian Hunter * to make sure we don't hit a controller bug, we _only_
2748da4bc4f2SAdrian Hunter * enable Buffer Read Ready interrupt here.
2749da4bc4f2SAdrian Hunter */
2750da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
2751da4bc4f2SAdrian Hunter sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
2752da4bc4f2SAdrian Hunter }
27536663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_start_tuning);
2754da4bc4f2SAdrian Hunter
sdhci_end_tuning(struct sdhci_host * host)27556663c419Sernest.zhang void sdhci_end_tuning(struct sdhci_host *host)
2756da4bc4f2SAdrian Hunter {
2757da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
2758da4bc4f2SAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
2759da4bc4f2SAdrian Hunter }
27606663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_end_tuning);
2761da4bc4f2SAdrian Hunter
sdhci_reset_tuning(struct sdhci_host * host)27626663c419Sernest.zhang void sdhci_reset_tuning(struct sdhci_host *host)
2763da4bc4f2SAdrian Hunter {
2764da4bc4f2SAdrian Hunter u16 ctrl;
2765da4bc4f2SAdrian Hunter
2766da4bc4f2SAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
2767da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_TUNED_CLK;
2768da4bc4f2SAdrian Hunter ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
2769da4bc4f2SAdrian Hunter sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
2770da4bc4f2SAdrian Hunter }
27716663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_reset_tuning);
2772da4bc4f2SAdrian Hunter
sdhci_abort_tuning(struct sdhci_host * host,u32 opcode)27737353788cSBen Chuang void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
2774da4bc4f2SAdrian Hunter {
2775da4bc4f2SAdrian Hunter sdhci_reset_tuning(host);
2776da4bc4f2SAdrian Hunter
27771e63d297SAdrian Hunter sdhci_reset_for(host, TUNING_ABORT);
2778da4bc4f2SAdrian Hunter
2779da4bc4f2SAdrian Hunter sdhci_end_tuning(host);
2780da4bc4f2SAdrian Hunter
278121adc2e4SWolfram Sang mmc_send_abort_tuning(host->mmc, opcode);
2782da4bc4f2SAdrian Hunter }
27837353788cSBen Chuang EXPORT_SYMBOL_GPL(sdhci_abort_tuning);
2784da4bc4f2SAdrian Hunter
2785da4bc4f2SAdrian Hunter /*
2786da4bc4f2SAdrian Hunter * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI
2787da4bc4f2SAdrian Hunter * tuning command does not have a data payload (or rather the hardware does it
2788da4bc4f2SAdrian Hunter * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command
2789da4bc4f2SAdrian Hunter * interrupt setup is different to other commands and there is no timeout
2790da4bc4f2SAdrian Hunter * interrupt so special handling is needed.
2791da4bc4f2SAdrian Hunter */
sdhci_send_tuning(struct sdhci_host * host,u32 opcode)27926663c419Sernest.zhang void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
2793da4bc4f2SAdrian Hunter {
2794da4bc4f2SAdrian Hunter struct mmc_host *mmc = host->mmc;
2795c7836d15SMasahiro Yamada struct mmc_command cmd = {};
2796c7836d15SMasahiro Yamada struct mmc_request mrq = {};
27972a85ef25SAdrian Hunter unsigned long flags;
2798c846a00fSSrinivas Kandagatla u32 b = host->sdma_boundary;
27992a85ef25SAdrian Hunter
28002a85ef25SAdrian Hunter spin_lock_irqsave(&host->lock, flags);
2801da4bc4f2SAdrian Hunter
2802da4bc4f2SAdrian Hunter cmd.opcode = opcode;
2803da4bc4f2SAdrian Hunter cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
2804da4bc4f2SAdrian Hunter cmd.mrq = &mrq;
2805da4bc4f2SAdrian Hunter
2806da4bc4f2SAdrian Hunter mrq.cmd = &cmd;
2807da4bc4f2SAdrian Hunter /*
2808da4bc4f2SAdrian Hunter * In response to CMD19, the card sends 64 bytes of tuning
2809da4bc4f2SAdrian Hunter * block to the Host Controller. So we set the block size
2810da4bc4f2SAdrian Hunter * to 64 here.
2811da4bc4f2SAdrian Hunter */
281285336109SAdrian Hunter if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200 &&
281385336109SAdrian Hunter mmc->ios.bus_width == MMC_BUS_WIDTH_8)
2814c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 128), SDHCI_BLOCK_SIZE);
281585336109SAdrian Hunter else
2816c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 64), SDHCI_BLOCK_SIZE);
2817da4bc4f2SAdrian Hunter
2818da4bc4f2SAdrian Hunter /*
2819da4bc4f2SAdrian Hunter * The tuning block is sent by the card to the host controller.
2820da4bc4f2SAdrian Hunter * So we set the TRNS_READ bit in the Transfer Mode register.
2821da4bc4f2SAdrian Hunter * This also takes care of setting DMA Enable and Multi Block
2822da4bc4f2SAdrian Hunter * Select in the same register to 0.
2823da4bc4f2SAdrian Hunter */
2824da4bc4f2SAdrian Hunter sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
2825da4bc4f2SAdrian Hunter
2826845c939eSAdrian Hunter if (!sdhci_send_command_retry(host, &cmd, flags)) {
2827845c939eSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
2828845c939eSAdrian Hunter host->tuning_done = 0;
2829845c939eSAdrian Hunter return;
2830845c939eSAdrian Hunter }
2831da4bc4f2SAdrian Hunter
2832da4bc4f2SAdrian Hunter host->cmd = NULL;
2833da4bc4f2SAdrian Hunter
2834da4bc4f2SAdrian Hunter sdhci_del_timer(host, &mrq);
2835da4bc4f2SAdrian Hunter
2836da4bc4f2SAdrian Hunter host->tuning_done = 0;
2837da4bc4f2SAdrian Hunter
2838da4bc4f2SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
2839da4bc4f2SAdrian Hunter
2840da4bc4f2SAdrian Hunter /* Wait for Buffer Read Ready interrupt */
2841da4bc4f2SAdrian Hunter wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1),
2842da4bc4f2SAdrian Hunter msecs_to_jiffies(50));
2843da4bc4f2SAdrian Hunter
2844da4bc4f2SAdrian Hunter }
28456663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_send_tuning);
2846da4bc4f2SAdrian Hunter
__sdhci_execute_tuning(struct sdhci_host * host,u32 opcode)28477d8bb1f4SYinbo Zhu static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
28486b11e70bSAdrian Hunter {
28496b11e70bSAdrian Hunter int i;
28506b11e70bSAdrian Hunter
28516b11e70bSAdrian Hunter /*
28526b11e70bSAdrian Hunter * Issue opcode repeatedly till Execute Tuning is set to 0 or the number
28531d8cd065SSowjanya Komatineni * of loops reaches tuning loop count.
28546b11e70bSAdrian Hunter */
28551d8cd065SSowjanya Komatineni for (i = 0; i < host->tuning_loop_count; i++) {
28566b11e70bSAdrian Hunter u16 ctrl;
28576b11e70bSAdrian Hunter
28582a85ef25SAdrian Hunter sdhci_send_tuning(host, opcode);
28596b11e70bSAdrian Hunter
28606b11e70bSAdrian Hunter if (!host->tuning_done) {
2861811ba676SFaiz Abbas pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n",
28626b11e70bSAdrian Hunter mmc_hostname(host->mmc));
28632a85ef25SAdrian Hunter sdhci_abort_tuning(host, opcode);
28647d8bb1f4SYinbo Zhu return -ETIMEDOUT;
28656b11e70bSAdrian Hunter }
28666b11e70bSAdrian Hunter
28672b06e159SBOUGH CHEN /* Spec does not require a delay between tuning cycles */
28682b06e159SBOUGH CHEN if (host->tuning_delay > 0)
28692b06e159SBOUGH CHEN mdelay(host->tuning_delay);
28702b06e159SBOUGH CHEN
28716b11e70bSAdrian Hunter ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
28726b11e70bSAdrian Hunter if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
28736b11e70bSAdrian Hunter if (ctrl & SDHCI_CTRL_TUNED_CLK)
28747d8bb1f4SYinbo Zhu return 0; /* Success! */
28756b11e70bSAdrian Hunter break;
28766b11e70bSAdrian Hunter }
28776b11e70bSAdrian Hunter
28786b11e70bSAdrian Hunter }
28796b11e70bSAdrian Hunter
28806b11e70bSAdrian Hunter pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
28816b11e70bSAdrian Hunter mmc_hostname(host->mmc));
28826b11e70bSAdrian Hunter sdhci_reset_tuning(host);
28837d8bb1f4SYinbo Zhu return -EAGAIN;
28846b11e70bSAdrian Hunter }
28856b11e70bSAdrian Hunter
sdhci_execute_tuning(struct mmc_host * mmc,u32 opcode)288685a882c2SMasahiro Yamada int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
2887b513ea25SArindam Nath {
28884b6f37d3SRussell King struct sdhci_host *host = mmc_priv(mmc);
2889b513ea25SArindam Nath int err = 0;
289038e40bf5SAdrian Hunter unsigned int tuning_count = 0;
2891b5540ce1SAdrian Hunter bool hs400_tuning;
2892b513ea25SArindam Nath
2893b5540ce1SAdrian Hunter hs400_tuning = host->flags & SDHCI_HS400_TUNING;
2894b5540ce1SAdrian Hunter
289538e40bf5SAdrian Hunter if (host->tuning_mode == SDHCI_TUNING_MODE_1)
289638e40bf5SAdrian Hunter tuning_count = host->tuning_count;
289738e40bf5SAdrian Hunter
2898b513ea25SArindam Nath /*
28999faac7b9SWeijun Yang * The Host Controller needs tuning in case of SDR104 and DDR50
29009faac7b9SWeijun Yang * mode, and for SDR50 mode when Use Tuning for SDR50 is set in
29019faac7b9SWeijun Yang * the Capabilities register.
2902069c9f14SGirish K S * If the Host Controller supports the HS200 mode then the
2903069c9f14SGirish K S * tuning function has to be executed.
2904b513ea25SArindam Nath */
29054b6f37d3SRussell King switch (host->timing) {
2906b5540ce1SAdrian Hunter /* HS400 tuning is done in HS200 mode */
2907e9fb05d5SAdrian Hunter case MMC_TIMING_MMC_HS400:
2908b5540ce1SAdrian Hunter err = -EINVAL;
29092a85ef25SAdrian Hunter goto out;
2910b5540ce1SAdrian Hunter
29114b6f37d3SRussell King case MMC_TIMING_MMC_HS200:
2912b5540ce1SAdrian Hunter /*
2913b5540ce1SAdrian Hunter * Periodic re-tuning for HS400 is not expected to be needed, so
2914b5540ce1SAdrian Hunter * disable it here.
2915b5540ce1SAdrian Hunter */
2916b5540ce1SAdrian Hunter if (hs400_tuning)
2917b5540ce1SAdrian Hunter tuning_count = 0;
2918b5540ce1SAdrian Hunter break;
2919b5540ce1SAdrian Hunter
29204b6f37d3SRussell King case MMC_TIMING_UHS_SDR104:
29219faac7b9SWeijun Yang case MMC_TIMING_UHS_DDR50:
29224b6f37d3SRussell King break;
2923069c9f14SGirish K S
29244b6f37d3SRussell King case MMC_TIMING_UHS_SDR50:
29254228b213SAdrian Hunter if (host->flags & SDHCI_SDR50_NEEDS_TUNING)
29264b6f37d3SRussell King break;
2927df561f66SGustavo A. R. Silva fallthrough;
29284b6f37d3SRussell King
29294b6f37d3SRussell King default:
29302a85ef25SAdrian Hunter goto out;
2931b513ea25SArindam Nath }
2932b513ea25SArindam Nath
293345251812SDong Aisheng if (host->ops->platform_execute_tuning) {
29348a8fa879SRitesh Harjani err = host->ops->platform_execute_tuning(host, opcode);
29352a85ef25SAdrian Hunter goto out;
293645251812SDong Aisheng }
293745251812SDong Aisheng
2938d2f025b0SJisheng Zhang mmc->retune_period = tuning_count;
29396b11e70bSAdrian Hunter
294083b600b8SAdrian Hunter if (host->tuning_delay < 0)
294183b600b8SAdrian Hunter host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK;
294283b600b8SAdrian Hunter
2943da4bc4f2SAdrian Hunter sdhci_start_tuning(host);
2944b513ea25SArindam Nath
29457d8bb1f4SYinbo Zhu host->tuning_err = __sdhci_execute_tuning(host, opcode);
2946cf2b5eeaSArindam Nath
2947da4bc4f2SAdrian Hunter sdhci_end_tuning(host);
29482a85ef25SAdrian Hunter out:
29498a8fa879SRitesh Harjani host->flags &= ~SDHCI_HS400_TUNING;
29506b11e70bSAdrian Hunter
2951b513ea25SArindam Nath return err;
2952b513ea25SArindam Nath }
295385a882c2SMasahiro Yamada EXPORT_SYMBOL_GPL(sdhci_execute_tuning);
2954b513ea25SArindam Nath
sdhci_enable_preset_value(struct sdhci_host * host,bool enable)295552983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
29564d55c5a1SArindam Nath {
29574d55c5a1SArindam Nath /* Host Controller v3.00 defines preset value registers */
29584d55c5a1SArindam Nath if (host->version < SDHCI_SPEC_300)
29594d55c5a1SArindam Nath return;
29604d55c5a1SArindam Nath
29614d55c5a1SArindam Nath /*
29624d55c5a1SArindam Nath * We only enable or disable Preset Value if they are not already
29634d55c5a1SArindam Nath * enabled or disabled respectively. Otherwise, we bail out.
29644d55c5a1SArindam Nath */
2965da91a8f9SRussell King if (host->preset_enabled != enable) {
2966da91a8f9SRussell King u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
2967da91a8f9SRussell King
2968da91a8f9SRussell King if (enable)
29694d55c5a1SArindam Nath ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
2970da91a8f9SRussell King else
29714d55c5a1SArindam Nath ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
2972da91a8f9SRussell King
29734d55c5a1SArindam Nath sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
2974da91a8f9SRussell King
2975da91a8f9SRussell King if (enable)
2976da91a8f9SRussell King host->flags |= SDHCI_PV_ENABLED;
2977da91a8f9SRussell King else
297866fd8ad5SAdrian Hunter host->flags &= ~SDHCI_PV_ENABLED;
2979da91a8f9SRussell King
2980da91a8f9SRussell King host->preset_enabled = enable;
29814d55c5a1SArindam Nath }
298266fd8ad5SAdrian Hunter }
298366fd8ad5SAdrian Hunter
sdhci_post_req(struct mmc_host * mmc,struct mmc_request * mrq,int err)2984348487cbSHaibo Chen static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
2985348487cbSHaibo Chen int err)
2986348487cbSHaibo Chen {
2987348487cbSHaibo Chen struct mmc_data *data = mrq->data;
2988348487cbSHaibo Chen
2989f48f039cSRussell King if (data->host_cookie != COOKIE_UNMAPPED)
2990d2f025b0SJisheng Zhang dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len,
2991feeef096SHeiner Kallweit mmc_get_dma_dir(data));
2992771a3dc2SRussell King
2993d31911b9SHaibo Chen data->host_cookie = COOKIE_UNMAPPED;
2994348487cbSHaibo Chen }
2995348487cbSHaibo Chen
sdhci_pre_req(struct mmc_host * mmc,struct mmc_request * mrq)2996d3c6aac3SLinus Walleij static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
2997348487cbSHaibo Chen {
2998348487cbSHaibo Chen struct sdhci_host *host = mmc_priv(mmc);
2999348487cbSHaibo Chen
3000d31911b9SHaibo Chen mrq->data->host_cookie = COOKIE_UNMAPPED;
3001348487cbSHaibo Chen
3002bd9b9027SLinus Walleij /*
3003bd9b9027SLinus Walleij * No pre-mapping in the pre hook if we're using the bounce buffer,
3004bd9b9027SLinus Walleij * for that we would need two bounce buffers since one buffer is
3005bd9b9027SLinus Walleij * in flight when this is getting called.
3006bd9b9027SLinus Walleij */
3007bd9b9027SLinus Walleij if (host->flags & SDHCI_REQ_USE_DMA && !host->bounce_buffer)
300894538e51SRussell King sdhci_pre_dma_transfer(host, mrq->data, COOKIE_PRE_MAPPED);
3009348487cbSHaibo Chen }
3010348487cbSHaibo Chen
sdhci_error_out_mrqs(struct sdhci_host * host,int err)30115d0d11c5SAdrian Hunter static void sdhci_error_out_mrqs(struct sdhci_host *host, int err)
30125d0d11c5SAdrian Hunter {
30135d0d11c5SAdrian Hunter if (host->data_cmd) {
30145d0d11c5SAdrian Hunter host->data_cmd->error = err;
30155d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq);
30165d0d11c5SAdrian Hunter }
30175d0d11c5SAdrian Hunter
30185d0d11c5SAdrian Hunter if (host->cmd) {
30195d0d11c5SAdrian Hunter host->cmd->error = err;
30205d0d11c5SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq);
30215d0d11c5SAdrian Hunter }
30225d0d11c5SAdrian Hunter }
30235d0d11c5SAdrian Hunter
sdhci_card_event(struct mmc_host * mmc)302471e69211SGuennadi Liakhovetski static void sdhci_card_event(struct mmc_host *mmc)
30251c6a0718SPierre Ossman {
302671e69211SGuennadi Liakhovetski struct sdhci_host *host = mmc_priv(mmc);
30271c6a0718SPierre Ossman unsigned long flags;
30282836766aSKrzysztof Kozlowski int present;
30291c6a0718SPierre Ossman
3030722e1280SChristian Daudt /* First check if client has provided their own card event */
3031722e1280SChristian Daudt if (host->ops->card_event)
3032722e1280SChristian Daudt host->ops->card_event(host);
3033722e1280SChristian Daudt
3034d3940f27SAdrian Hunter present = mmc->ops->get_cd(mmc);
30352836766aSKrzysztof Kozlowski
30361c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags);
30371c6a0718SPierre Ossman
30385d0d11c5SAdrian Hunter /* Check sdhci_has_requests() first in case we are runtime suspended */
30395d0d11c5SAdrian Hunter if (sdhci_has_requests(host) && !present) {
3040a3c76eb9SGirish K S pr_err("%s: Card removed during transfer!\n",
3041d2f025b0SJisheng Zhang mmc_hostname(mmc));
3042a3c76eb9SGirish K S pr_err("%s: Resetting controller.\n",
3043d2f025b0SJisheng Zhang mmc_hostname(mmc));
30441c6a0718SPierre Ossman
30451e63d297SAdrian Hunter sdhci_reset_for(host, CARD_REMOVED);
30461c6a0718SPierre Ossman
30475d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM);
30481c6a0718SPierre Ossman }
30491c6a0718SPierre Ossman
30501c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags);
305171e69211SGuennadi Liakhovetski }
305271e69211SGuennadi Liakhovetski
305371e69211SGuennadi Liakhovetski static const struct mmc_host_ops sdhci_ops = {
305471e69211SGuennadi Liakhovetski .request = sdhci_request,
3055348487cbSHaibo Chen .post_req = sdhci_post_req,
3056348487cbSHaibo Chen .pre_req = sdhci_pre_req,
305771e69211SGuennadi Liakhovetski .set_ios = sdhci_set_ios,
305894144a46SKevin Liu .get_cd = sdhci_get_cd,
305971e69211SGuennadi Liakhovetski .get_ro = sdhci_get_ro,
306032f18e59SWolfram Sang .card_hw_reset = sdhci_hw_reset,
306171e69211SGuennadi Liakhovetski .enable_sdio_irq = sdhci_enable_sdio_irq,
306289f3c365SAdrian Hunter .ack_sdio_irq = sdhci_ack_sdio_irq,
306371e69211SGuennadi Liakhovetski .start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
3064b5540ce1SAdrian Hunter .prepare_hs400_tuning = sdhci_prepare_hs400_tuning,
306571e69211SGuennadi Liakhovetski .execute_tuning = sdhci_execute_tuning,
306671e69211SGuennadi Liakhovetski .card_event = sdhci_card_event,
306720b92a30SKevin Liu .card_busy = sdhci_card_busy,
306871e69211SGuennadi Liakhovetski };
306971e69211SGuennadi Liakhovetski
307071e69211SGuennadi Liakhovetski /*****************************************************************************\
307171e69211SGuennadi Liakhovetski * *
3072c07a48c2SAdrian Hunter * Request done *
307371e69211SGuennadi Liakhovetski * *
307471e69211SGuennadi Liakhovetski \*****************************************************************************/
307571e69211SGuennadi Liakhovetski
sdhci_request_done(struct sdhci_host * host)30764e9f8fe5SAdrian Hunter static bool sdhci_request_done(struct sdhci_host *host)
30771c6a0718SPierre Ossman {
30781c6a0718SPierre Ossman unsigned long flags;
30791c6a0718SPierre Ossman struct mmc_request *mrq;
30804e9f8fe5SAdrian Hunter int i;
30811c6a0718SPierre Ossman
308266fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags);
308366fd8ad5SAdrian Hunter
30844e9f8fe5SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) {
30854e9f8fe5SAdrian Hunter mrq = host->mrqs_done[i];
30866ebebeabSAdrian Hunter if (mrq)
30874e9f8fe5SAdrian Hunter break;
30884e9f8fe5SAdrian Hunter }
30891c6a0718SPierre Ossman
30904e9f8fe5SAdrian Hunter if (!mrq) {
30914e9f8fe5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
30924e9f8fe5SAdrian Hunter return true;
30934e9f8fe5SAdrian Hunter }
30941c6a0718SPierre Ossman
30951c6a0718SPierre Ossman /*
309621e35e89SPradeep P V K * The controller needs a reset of internal state machines
309721e35e89SPradeep P V K * upon error conditions.
309821e35e89SPradeep P V K */
309921e35e89SPradeep P V K if (sdhci_needs_reset(host, mrq)) {
310021e35e89SPradeep P V K /*
310121e35e89SPradeep P V K * Do not finish until command and data lines are available for
310221e35e89SPradeep P V K * reset. Note there can only be one other mrq, so it cannot
310321e35e89SPradeep P V K * also be in mrqs_done, otherwise host->cmd and host->data_cmd
310421e35e89SPradeep P V K * would both be null.
310521e35e89SPradeep P V K */
310621e35e89SPradeep P V K if (host->cmd || host->data_cmd) {
310721e35e89SPradeep P V K spin_unlock_irqrestore(&host->lock, flags);
310821e35e89SPradeep P V K return true;
310921e35e89SPradeep P V K }
311021e35e89SPradeep P V K
311121e35e89SPradeep P V K /* Some controllers need this kick or reset won't work here */
311221e35e89SPradeep P V K if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
311321e35e89SPradeep P V K /* This is to force an update */
311421e35e89SPradeep P V K host->ops->set_clock(host, host->clock);
311521e35e89SPradeep P V K
31161e63d297SAdrian Hunter sdhci_reset_for(host, REQUEST_ERROR);
311721e35e89SPradeep P V K
311821e35e89SPradeep P V K host->pending_reset = false;
311921e35e89SPradeep P V K }
312021e35e89SPradeep P V K
312121e35e89SPradeep P V K /*
3122054cedffSRussell King * Always unmap the data buffers if they were mapped by
3123054cedffSRussell King * sdhci_prepare_data() whenever we finish with a request.
3124054cedffSRussell King * This avoids leaking DMA mappings on error.
3125054cedffSRussell King */
3126054cedffSRussell King if (host->flags & SDHCI_REQ_USE_DMA) {
3127054cedffSRussell King struct mmc_data *data = mrq->data;
3128054cedffSRussell King
312918e762e3SChunyan Zhang if (host->use_external_dma && data &&
313018e762e3SChunyan Zhang (mrq->cmd->error || data->error)) {
313118e762e3SChunyan Zhang struct dma_chan *chan = sdhci_external_dma_channel(host, data);
313218e762e3SChunyan Zhang
313318e762e3SChunyan Zhang host->mrqs_done[i] = NULL;
313418e762e3SChunyan Zhang spin_unlock_irqrestore(&host->lock, flags);
313518e762e3SChunyan Zhang dmaengine_terminate_sync(chan);
313618e762e3SChunyan Zhang spin_lock_irqsave(&host->lock, flags);
313718e762e3SChunyan Zhang sdhci_set_mrq_done(host, mrq);
313818e762e3SChunyan Zhang }
313918e762e3SChunyan Zhang
3140054cedffSRussell King if (data && data->host_cookie == COOKIE_MAPPED) {
3141bd9b9027SLinus Walleij if (host->bounce_buffer) {
3142bd9b9027SLinus Walleij /*
3143bd9b9027SLinus Walleij * On reads, copy the bounced data into the
3144bd9b9027SLinus Walleij * sglist
3145bd9b9027SLinus Walleij */
3146bd9b9027SLinus Walleij if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) {
3147bd9b9027SLinus Walleij unsigned int length = data->bytes_xfered;
3148bd9b9027SLinus Walleij
3149bd9b9027SLinus Walleij if (length > host->bounce_buffer_size) {
3150bd9b9027SLinus Walleij pr_err("%s: bounce buffer is %u bytes but DMA claims to have transferred %u bytes\n",
3151bd9b9027SLinus Walleij mmc_hostname(host->mmc),
3152bd9b9027SLinus Walleij host->bounce_buffer_size,
3153bd9b9027SLinus Walleij data->bytes_xfered);
3154bd9b9027SLinus Walleij /* Cap it down and continue */
3155bd9b9027SLinus Walleij length = host->bounce_buffer_size;
3156bd9b9027SLinus Walleij }
3157bd9b9027SLinus Walleij dma_sync_single_for_cpu(
3158bac53336SJisheng Zhang mmc_dev(host->mmc),
3159bd9b9027SLinus Walleij host->bounce_addr,
3160bd9b9027SLinus Walleij host->bounce_buffer_size,
3161bd9b9027SLinus Walleij DMA_FROM_DEVICE);
3162bd9b9027SLinus Walleij sg_copy_from_buffer(data->sg,
3163bd9b9027SLinus Walleij data->sg_len,
3164bd9b9027SLinus Walleij host->bounce_buffer,
3165bd9b9027SLinus Walleij length);
3166bd9b9027SLinus Walleij } else {
3167bd9b9027SLinus Walleij /* No copying, just switch ownership */
3168bd9b9027SLinus Walleij dma_sync_single_for_cpu(
3169bac53336SJisheng Zhang mmc_dev(host->mmc),
3170bd9b9027SLinus Walleij host->bounce_addr,
3171bd9b9027SLinus Walleij host->bounce_buffer_size,
3172feeef096SHeiner Kallweit mmc_get_dma_dir(data));
3173bd9b9027SLinus Walleij }
3174bd9b9027SLinus Walleij } else {
3175bd9b9027SLinus Walleij /* Unmap the raw data */
3176bd9b9027SLinus Walleij dma_unmap_sg(mmc_dev(host->mmc), data->sg,
3177bd9b9027SLinus Walleij data->sg_len,
3178bd9b9027SLinus Walleij mmc_get_dma_dir(data));
3179bd9b9027SLinus Walleij }
3180054cedffSRussell King data->host_cookie = COOKIE_UNMAPPED;
3181054cedffSRussell King }
3182054cedffSRussell King }
3183054cedffSRussell King
31846ebebeabSAdrian Hunter host->mrqs_done[i] = NULL;
31856ebebeabSAdrian Hunter
31861c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags);
31871c6a0718SPierre Ossman
31881774b002SBaolin Wang if (host->ops->request_done)
31891774b002SBaolin Wang host->ops->request_done(host, mrq);
31901774b002SBaolin Wang else
31911c6a0718SPierre Ossman mmc_request_done(host->mmc, mrq);
31924e9f8fe5SAdrian Hunter
31934e9f8fe5SAdrian Hunter return false;
31944e9f8fe5SAdrian Hunter }
31954e9f8fe5SAdrian Hunter
sdhci_complete_work(struct work_struct * work)3196c07a48c2SAdrian Hunter static void sdhci_complete_work(struct work_struct *work)
31974e9f8fe5SAdrian Hunter {
3198c07a48c2SAdrian Hunter struct sdhci_host *host = container_of(work, struct sdhci_host,
3199c07a48c2SAdrian Hunter complete_work);
32004e9f8fe5SAdrian Hunter
32014e9f8fe5SAdrian Hunter while (!sdhci_request_done(host))
32024e9f8fe5SAdrian Hunter ;
32031c6a0718SPierre Ossman }
32041c6a0718SPierre Ossman
sdhci_timeout_timer(struct timer_list * t)32052ee4f620SKees Cook static void sdhci_timeout_timer(struct timer_list *t)
32061c6a0718SPierre Ossman {
32071c6a0718SPierre Ossman struct sdhci_host *host;
32081c6a0718SPierre Ossman unsigned long flags;
32091c6a0718SPierre Ossman
32102ee4f620SKees Cook host = from_timer(host, t, timer);
32111c6a0718SPierre Ossman
32121c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags);
32131c6a0718SPierre Ossman
3214d7422fb4SAdrian Hunter if (host->cmd && !sdhci_data_line_cmd(host->cmd)) {
3215d7422fb4SAdrian Hunter pr_err("%s: Timeout waiting for hardware cmd interrupt.\n",
3216d7422fb4SAdrian Hunter mmc_hostname(host->mmc));
3217efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, REQ_TIMEOUT);
3218d7422fb4SAdrian Hunter sdhci_dumpregs(host);
3219d7422fb4SAdrian Hunter
3220d7422fb4SAdrian Hunter host->cmd->error = -ETIMEDOUT;
3221d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq);
3222d7422fb4SAdrian Hunter }
3223d7422fb4SAdrian Hunter
3224d7422fb4SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
3225d7422fb4SAdrian Hunter }
3226d7422fb4SAdrian Hunter
sdhci_timeout_data_timer(struct timer_list * t)32272ee4f620SKees Cook static void sdhci_timeout_data_timer(struct timer_list *t)
3228d7422fb4SAdrian Hunter {
3229d7422fb4SAdrian Hunter struct sdhci_host *host;
3230d7422fb4SAdrian Hunter unsigned long flags;
3231d7422fb4SAdrian Hunter
32322ee4f620SKees Cook host = from_timer(host, t, data_timer);
3233d7422fb4SAdrian Hunter
3234d7422fb4SAdrian Hunter spin_lock_irqsave(&host->lock, flags);
3235d7422fb4SAdrian Hunter
3236d7422fb4SAdrian Hunter if (host->data || host->data_cmd ||
3237d7422fb4SAdrian Hunter (host->cmd && sdhci_data_line_cmd(host->cmd))) {
32382e4456f0SMarek Vasut pr_err("%s: Timeout waiting for hardware interrupt.\n",
32392e4456f0SMarek Vasut mmc_hostname(host->mmc));
3240efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, REQ_TIMEOUT);
32411c6a0718SPierre Ossman sdhci_dumpregs(host);
32421c6a0718SPierre Ossman
32431c6a0718SPierre Ossman if (host->data) {
324417b0429dSPierre Ossman host->data->error = -ETIMEDOUT;
3245845c939eSAdrian Hunter __sdhci_finish_data(host, true);
3246c07a48c2SAdrian Hunter queue_work(host->complete_wq, &host->complete_work);
3247d7422fb4SAdrian Hunter } else if (host->data_cmd) {
3248d7422fb4SAdrian Hunter host->data_cmd->error = -ETIMEDOUT;
3249d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->data_cmd->mrq);
32501c6a0718SPierre Ossman } else {
325117b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT;
3252d7422fb4SAdrian Hunter sdhci_finish_mrq(host, host->cmd->mrq);
32531c6a0718SPierre Ossman }
32541c6a0718SPierre Ossman }
32551c6a0718SPierre Ossman
32561c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags);
32571c6a0718SPierre Ossman }
32581c6a0718SPierre Ossman
32591c6a0718SPierre Ossman /*****************************************************************************\
32601c6a0718SPierre Ossman * *
32611c6a0718SPierre Ossman * Interrupt handling *
32621c6a0718SPierre Ossman * *
32631c6a0718SPierre Ossman \*****************************************************************************/
32641c6a0718SPierre Ossman
sdhci_cmd_irq(struct sdhci_host * host,u32 intmask,u32 * intmask_p)32654bf78099SAdrian Hunter static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p)
32661c6a0718SPierre Ossman {
3267af849c86SAdrian Hunter /* Handle auto-CMD12 error */
3268af849c86SAdrian Hunter if (intmask & SDHCI_INT_AUTO_CMD_ERR && host->data_cmd) {
3269af849c86SAdrian Hunter struct mmc_request *mrq = host->data_cmd->mrq;
3270af849c86SAdrian Hunter u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS);
3271af849c86SAdrian Hunter int data_err_bit = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ?
3272af849c86SAdrian Hunter SDHCI_INT_DATA_TIMEOUT :
3273af849c86SAdrian Hunter SDHCI_INT_DATA_CRC;
3274af849c86SAdrian Hunter
3275af849c86SAdrian Hunter /* Treat auto-CMD12 error the same as data error */
3276af849c86SAdrian Hunter if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) {
3277af849c86SAdrian Hunter *intmask_p |= data_err_bit;
3278af849c86SAdrian Hunter return;
3279af849c86SAdrian Hunter }
3280af849c86SAdrian Hunter }
3281af849c86SAdrian Hunter
32821c6a0718SPierre Ossman if (!host->cmd) {
3283ed1563deSAdrian Hunter /*
3284ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data
3285ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more
3286ed1563deSAdrian Hunter * interrupts, so ignore them in that case.
3287ed1563deSAdrian Hunter */
3288ed1563deSAdrian Hunter if (host->pending_reset)
3289ed1563deSAdrian Hunter return;
32902e4456f0SMarek Vasut pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n",
3291b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask);
3292efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ);
32931c6a0718SPierre Ossman sdhci_dumpregs(host);
32941c6a0718SPierre Ossman return;
32951c6a0718SPierre Ossman }
32961c6a0718SPierre Ossman
3297ec014cbaSRussell King if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC |
3298ec014cbaSRussell King SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) {
3299efe8f5c9SShaik Sajida Bhanu if (intmask & SDHCI_INT_TIMEOUT) {
330017b0429dSPierre Ossman host->cmd->error = -ETIMEDOUT;
3301efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_TIMEOUT);
3302efe8f5c9SShaik Sajida Bhanu } else {
330317b0429dSPierre Ossman host->cmd->error = -EILSEQ;
3304efe8f5c9SShaik Sajida Bhanu if (!mmc_op_tuning(host->cmd->opcode))
3305efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_CRC);
3306efe8f5c9SShaik Sajida Bhanu }
33074bf78099SAdrian Hunter /* Treat data command CRC error the same as data CRC error */
330871fcbda0SRussell King if (host->cmd->data &&
330971fcbda0SRussell King (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) ==
331071fcbda0SRussell King SDHCI_INT_CRC) {
331171fcbda0SRussell King host->cmd = NULL;
33124bf78099SAdrian Hunter *intmask_p |= SDHCI_INT_DATA_CRC;
331371fcbda0SRussell King return;
331471fcbda0SRussell King }
331571fcbda0SRussell King
331619d2f695SAdrian Hunter __sdhci_finish_mrq(host, host->cmd->mrq);
3317e809517fSPierre Ossman return;
3318e809517fSPierre Ossman }
3319e809517fSPierre Ossman
3320af849c86SAdrian Hunter /* Handle auto-CMD23 error */
3321af849c86SAdrian Hunter if (intmask & SDHCI_INT_AUTO_CMD_ERR) {
3322af849c86SAdrian Hunter struct mmc_request *mrq = host->cmd->mrq;
3323af849c86SAdrian Hunter u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS);
3324af849c86SAdrian Hunter int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ?
3325af849c86SAdrian Hunter -ETIMEDOUT :
3326af849c86SAdrian Hunter -EILSEQ;
3327af849c86SAdrian Hunter
3328efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, AUTO_CMD);
3329efe8f5c9SShaik Sajida Bhanu
333038929d4fSChanWoo Lee if (sdhci_auto_cmd23(host, mrq)) {
3331af849c86SAdrian Hunter mrq->sbc->error = err;
333219d2f695SAdrian Hunter __sdhci_finish_mrq(host, mrq);
3333af849c86SAdrian Hunter return;
3334af849c86SAdrian Hunter }
3335af849c86SAdrian Hunter }
3336af849c86SAdrian Hunter
3337e809517fSPierre Ossman if (intmask & SDHCI_INT_RESPONSE)
333843b58b36SPierre Ossman sdhci_finish_command(host);
33391c6a0718SPierre Ossman }
33401c6a0718SPierre Ossman
sdhci_adma_show_error(struct sdhci_host * host)334108621b18SAdrian Hunter static void sdhci_adma_show_error(struct sdhci_host *host)
33426882a8c0SBen Dooks {
33431c3d5f6dSAdrian Hunter void *desc = host->adma_table;
3344d1c536e3SRussell King dma_addr_t dma = host->adma_addr;
33456882a8c0SBen Dooks
33466882a8c0SBen Dooks sdhci_dumpregs(host);
33476882a8c0SBen Dooks
33486882a8c0SBen Dooks while (true) {
3349e57a5f61SAdrian Hunter struct sdhci_adma2_64_desc *dma_desc = desc;
33506882a8c0SBen Dooks
3351e57a5f61SAdrian Hunter if (host->flags & SDHCI_USE_64_BIT_DMA)
3352d1c536e3SRussell King SDHCI_DUMP("%08llx: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n",
3353d1c536e3SRussell King (unsigned long long)dma,
3354d1c536e3SRussell King le32_to_cpu(dma_desc->addr_hi),
3355e57a5f61SAdrian Hunter le32_to_cpu(dma_desc->addr_lo),
3356e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->len),
3357e57a5f61SAdrian Hunter le16_to_cpu(dma_desc->cmd));
3358e57a5f61SAdrian Hunter else
3359d1c536e3SRussell King SDHCI_DUMP("%08llx: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
3360d1c536e3SRussell King (unsigned long long)dma,
3361d1c536e3SRussell King le32_to_cpu(dma_desc->addr_lo),
33620545230fSAdrian Hunter le16_to_cpu(dma_desc->len),
33630545230fSAdrian Hunter le16_to_cpu(dma_desc->cmd));
33646882a8c0SBen Dooks
336576fe379aSAdrian Hunter desc += host->desc_sz;
3366d1c536e3SRussell King dma += host->desc_sz;
33676882a8c0SBen Dooks
33680545230fSAdrian Hunter if (dma_desc->cmd & cpu_to_le16(ADMA2_END))
33696882a8c0SBen Dooks break;
33706882a8c0SBen Dooks }
33716882a8c0SBen Dooks }
33726882a8c0SBen Dooks
sdhci_data_irq(struct sdhci_host * host,u32 intmask)33731c6a0718SPierre Ossman static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
33741c6a0718SPierre Ossman {
3375f4ff24f8SHaibo Chen /*
3376f4ff24f8SHaibo Chen * CMD19 generates _only_ Buffer Read Ready interrupt if
3377f4ff24f8SHaibo Chen * use sdhci_send_tuning.
3378f4ff24f8SHaibo Chen * Need to exclude this case: PIO mode and use mmc_send_tuning,
3379f4ff24f8SHaibo Chen * If not, sdhci_transfer_pio will never be called, make the
3380f4ff24f8SHaibo Chen * SDHCI_INT_DATA_AVAIL always there, stuck in irq storm.
3381f4ff24f8SHaibo Chen */
3382f4ff24f8SHaibo Chen if (intmask & SDHCI_INT_DATA_AVAIL && !host->data) {
3383b98e7e8dSChanWoo Lee if (mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) {
3384b513ea25SArindam Nath host->tuning_done = 1;
3385b513ea25SArindam Nath wake_up(&host->buf_ready_int);
3386b513ea25SArindam Nath return;
3387b513ea25SArindam Nath }
3388b513ea25SArindam Nath }
3389b513ea25SArindam Nath
33901c6a0718SPierre Ossman if (!host->data) {
33917c89a3d9SAdrian Hunter struct mmc_command *data_cmd = host->data_cmd;
33927c89a3d9SAdrian Hunter
33931c6a0718SPierre Ossman /*
3394e809517fSPierre Ossman * The "data complete" interrupt is also used to
3395e809517fSPierre Ossman * indicate that a busy state has ended. See comment
3396e809517fSPierre Ossman * above in sdhci_cmd_irq().
33971c6a0718SPierre Ossman */
33987c89a3d9SAdrian Hunter if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) {
3399c5abd5e8SMatthieu CASTET if (intmask & SDHCI_INT_DATA_TIMEOUT) {
340069b962a6SAdrian Hunter host->data_cmd = NULL;
34017c89a3d9SAdrian Hunter data_cmd->error = -ETIMEDOUT;
3402efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_TIMEOUT);
340319d2f695SAdrian Hunter __sdhci_finish_mrq(host, data_cmd->mrq);
3404c5abd5e8SMatthieu CASTET return;
3405c5abd5e8SMatthieu CASTET }
3406e809517fSPierre Ossman if (intmask & SDHCI_INT_DATA_END) {
340769b962a6SAdrian Hunter host->data_cmd = NULL;
3408e99783a4SChanho Min /*
3409e99783a4SChanho Min * Some cards handle busy-end interrupt
3410e99783a4SChanho Min * before the command completed, so make
3411e99783a4SChanho Min * sure we do things in the proper order.
3412e99783a4SChanho Min */
3413ea968023SAdrian Hunter if (host->cmd == data_cmd)
3414ea968023SAdrian Hunter return;
3415ea968023SAdrian Hunter
341619d2f695SAdrian Hunter __sdhci_finish_mrq(host, data_cmd->mrq);
34171c6a0718SPierre Ossman return;
3418e809517fSPierre Ossman }
3419e809517fSPierre Ossman }
34201c6a0718SPierre Ossman
3421ed1563deSAdrian Hunter /*
3422ed1563deSAdrian Hunter * SDHCI recovers from errors by resetting the cmd and data
3423ed1563deSAdrian Hunter * circuits. Until that is done, there very well might be more
3424ed1563deSAdrian Hunter * interrupts, so ignore them in that case.
3425ed1563deSAdrian Hunter */
3426ed1563deSAdrian Hunter if (host->pending_reset)
3427ed1563deSAdrian Hunter return;
3428ed1563deSAdrian Hunter
34292e4456f0SMarek Vasut pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
3430b67ac3f3SPierre Ossman mmc_hostname(host->mmc), (unsigned)intmask);
3431efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ);
34321c6a0718SPierre Ossman sdhci_dumpregs(host);
34331c6a0718SPierre Ossman
34341c6a0718SPierre Ossman return;
34351c6a0718SPierre Ossman }
34361c6a0718SPierre Ossman
3437efe8f5c9SShaik Sajida Bhanu if (intmask & SDHCI_INT_DATA_TIMEOUT) {
343817b0429dSPierre Ossman host->data->error = -ETIMEDOUT;
3439efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_TIMEOUT);
3440efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_DATA_END_BIT) {
344122113efdSAries Lee host->data->error = -EILSEQ;
3442efe8f5c9SShaik Sajida Bhanu if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
3443efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_CRC);
3444d9ae0aa8SAdrian Hunter } else if ((intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_TUNING_ERROR)) &&
344522113efdSAries Lee SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))
3446efe8f5c9SShaik Sajida Bhanu != MMC_BUS_TEST_R) {
344717b0429dSPierre Ossman host->data->error = -EILSEQ;
3448efe8f5c9SShaik Sajida Bhanu if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
3449efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_CRC);
3450d9ae0aa8SAdrian Hunter if (intmask & SDHCI_INT_TUNING_ERROR) {
3451d9ae0aa8SAdrian Hunter u16 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
3452d9ae0aa8SAdrian Hunter
3453d9ae0aa8SAdrian Hunter ctrl2 &= ~SDHCI_CTRL_TUNED_CLK;
3454d9ae0aa8SAdrian Hunter sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
3455d9ae0aa8SAdrian Hunter }
3456efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_ADMA_ERROR) {
3457d1c536e3SRussell King pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc),
3458d1c536e3SRussell King intmask);
345908621b18SAdrian Hunter sdhci_adma_show_error(host);
3460efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, ADMA);
34612134a922SPierre Ossman host->data->error = -EIO;
3462a4071fbbSHaijun Zhang if (host->ops->adma_workaround)
3463a4071fbbSHaijun Zhang host->ops->adma_workaround(host, intmask);
34646882a8c0SBen Dooks }
34651c6a0718SPierre Ossman
346617b0429dSPierre Ossman if (host->data->error)
34671c6a0718SPierre Ossman sdhci_finish_data(host);
34681c6a0718SPierre Ossman else {
34691c6a0718SPierre Ossman if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
34701c6a0718SPierre Ossman sdhci_transfer_pio(host);
34711c6a0718SPierre Ossman
34726ba736a1SPierre Ossman /*
34736ba736a1SPierre Ossman * We currently don't do anything fancy with DMA
34746ba736a1SPierre Ossman * boundaries, but as we can't disable the feature
34756ba736a1SPierre Ossman * we need to at least restart the transfer.
3476f6a03cbfSMikko Vinni *
3477f6a03cbfSMikko Vinni * According to the spec sdhci_readl(host, SDHCI_DMA_ADDRESS)
3478f6a03cbfSMikko Vinni * should return a valid address to continue from, but as
3479f6a03cbfSMikko Vinni * some controllers are faulty, don't trust them.
34806ba736a1SPierre Ossman */
3481f6a03cbfSMikko Vinni if (intmask & SDHCI_INT_DMA_END) {
3482917a0c52SChunyan Zhang dma_addr_t dmastart, dmanow;
3483bd9b9027SLinus Walleij
3484bd9b9027SLinus Walleij dmastart = sdhci_sdma_address(host);
3485f6a03cbfSMikko Vinni dmanow = dmastart + host->data->bytes_xfered;
3486f6a03cbfSMikko Vinni /*
3487f6a03cbfSMikko Vinni * Force update to the next DMA block boundary.
3488f6a03cbfSMikko Vinni */
3489f6a03cbfSMikko Vinni dmanow = (dmanow &
3490917a0c52SChunyan Zhang ~((dma_addr_t)SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
3491f6a03cbfSMikko Vinni SDHCI_DEFAULT_BOUNDARY_SIZE;
3492f6a03cbfSMikko Vinni host->data->bytes_xfered = dmanow - dmastart;
3493917a0c52SChunyan Zhang DBG("DMA base %pad, transferred 0x%06x bytes, next %pad\n",
3494917a0c52SChunyan Zhang &dmastart, host->data->bytes_xfered, &dmanow);
3495917a0c52SChunyan Zhang sdhci_set_sdma_addr(host, dmanow);
3496f6a03cbfSMikko Vinni }
34976ba736a1SPierre Ossman
3498e538fbe8SPierre Ossman if (intmask & SDHCI_INT_DATA_END) {
34997c89a3d9SAdrian Hunter if (host->cmd == host->data_cmd) {
3500e538fbe8SPierre Ossman /*
3501e538fbe8SPierre Ossman * Data managed to finish before the
3502e538fbe8SPierre Ossman * command completed. Make sure we do
3503e538fbe8SPierre Ossman * things in the proper order.
3504e538fbe8SPierre Ossman */
3505e538fbe8SPierre Ossman host->data_early = 1;
3506e538fbe8SPierre Ossman } else {
35071c6a0718SPierre Ossman sdhci_finish_data(host);
35081c6a0718SPierre Ossman }
35091c6a0718SPierre Ossman }
3510e538fbe8SPierre Ossman }
3511e538fbe8SPierre Ossman }
35121c6a0718SPierre Ossman
sdhci_defer_done(struct sdhci_host * host,struct mmc_request * mrq)351319d2f695SAdrian Hunter static inline bool sdhci_defer_done(struct sdhci_host *host,
351419d2f695SAdrian Hunter struct mmc_request *mrq)
351519d2f695SAdrian Hunter {
351619d2f695SAdrian Hunter struct mmc_data *data = mrq->data;
351719d2f695SAdrian Hunter
35184730831cSBaolin Wang return host->pending_reset || host->always_defer_done ||
351919d2f695SAdrian Hunter ((host->flags & SDHCI_REQ_USE_DMA) && data &&
352019d2f695SAdrian Hunter data->host_cookie == COOKIE_MAPPED);
352119d2f695SAdrian Hunter }
352219d2f695SAdrian Hunter
sdhci_irq(int irq,void * dev_id)35231c6a0718SPierre Ossman static irqreturn_t sdhci_irq(int irq, void *dev_id)
35241c6a0718SPierre Ossman {
352519d2f695SAdrian Hunter struct mmc_request *mrqs_done[SDHCI_MAX_MRQS] = {0};
3526781e989cSRussell King irqreturn_t result = IRQ_NONE;
35271c6a0718SPierre Ossman struct sdhci_host *host = dev_id;
352841005003SRussell King u32 intmask, mask, unexpected = 0;
3529781e989cSRussell King int max_loops = 16;
353019d2f695SAdrian Hunter int i;
35311c6a0718SPierre Ossman
35321c6a0718SPierre Ossman spin_lock(&host->lock);
35331c6a0718SPierre Ossman
3534af5d2b7bSUlf Hansson if (host->runtime_suspended) {
353566fd8ad5SAdrian Hunter spin_unlock(&host->lock);
3536655bca76SAdrian Hunter return IRQ_NONE;
353766fd8ad5SAdrian Hunter }
353866fd8ad5SAdrian Hunter
35394e4141a5SAnton Vorontsov intmask = sdhci_readl(host, SDHCI_INT_STATUS);
35401c6a0718SPierre Ossman if (!intmask || intmask == 0xffffffff) {
35411c6a0718SPierre Ossman result = IRQ_NONE;
35421c6a0718SPierre Ossman goto out;
35431c6a0718SPierre Ossman }
35441c6a0718SPierre Ossman
354541005003SRussell King do {
3546f12e39dbSAdrian Hunter DBG("IRQ status 0x%08x\n", intmask);
3547f12e39dbSAdrian Hunter
3548f12e39dbSAdrian Hunter if (host->ops->irq) {
3549f12e39dbSAdrian Hunter intmask = host->ops->irq(host, intmask);
3550f12e39dbSAdrian Hunter if (!intmask)
3551f12e39dbSAdrian Hunter goto cont;
3552f12e39dbSAdrian Hunter }
3553f12e39dbSAdrian Hunter
355441005003SRussell King /* Clear selected interrupts. */
355541005003SRussell King mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
355641005003SRussell King SDHCI_INT_BUS_POWER);
355741005003SRussell King sdhci_writel(host, mask, SDHCI_INT_STATUS);
355841005003SRussell King
35591c6a0718SPierre Ossman if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
3560d25928d1SShawn Guo u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
3561d25928d1SShawn Guo SDHCI_CARD_PRESENT;
3562d25928d1SShawn Guo
3563d25928d1SShawn Guo /*
356441005003SRussell King * There is a observation on i.mx esdhc. INSERT
356541005003SRussell King * bit will be immediately set again when it gets
356641005003SRussell King * cleared, if a card is inserted. We have to mask
356741005003SRussell King * the irq to prevent interrupt storm which will
356841005003SRussell King * freeze the system. And the REMOVE gets the
356941005003SRussell King * same situation.
3570d25928d1SShawn Guo *
357141005003SRussell King * More testing are needed here to ensure it works
357241005003SRussell King * for other platforms though.
3573d25928d1SShawn Guo */
3574b537f94cSRussell King host->ier &= ~(SDHCI_INT_CARD_INSERT |
3575d25928d1SShawn Guo SDHCI_INT_CARD_REMOVE);
3576b537f94cSRussell King host->ier |= present ? SDHCI_INT_CARD_REMOVE :
3577b537f94cSRussell King SDHCI_INT_CARD_INSERT;
3578b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
3579b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
3580d25928d1SShawn Guo
35814e4141a5SAnton Vorontsov sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
35824e4141a5SAnton Vorontsov SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
35833560db8eSRussell King
35843560db8eSRussell King host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT |
35853560db8eSRussell King SDHCI_INT_CARD_REMOVE);
35863560db8eSRussell King result = IRQ_WAKE_THREAD;
35871c6a0718SPierre Ossman }
35881c6a0718SPierre Ossman
358941005003SRussell King if (intmask & SDHCI_INT_CMD_MASK)
35904bf78099SAdrian Hunter sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask);
35911c6a0718SPierre Ossman
359241005003SRussell King if (intmask & SDHCI_INT_DATA_MASK)
35931c6a0718SPierre Ossman sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
35941c6a0718SPierre Ossman
359541005003SRussell King if (intmask & SDHCI_INT_BUS_POWER)
3596a3c76eb9SGirish K S pr_err("%s: Card is consuming too much power!\n",
35971c6a0718SPierre Ossman mmc_hostname(host->mmc));
35981c6a0718SPierre Ossman
3599f37b20ebSDong Aisheng if (intmask & SDHCI_INT_RETUNE)
3600f37b20ebSDong Aisheng mmc_retune_needed(host->mmc);
3601f37b20ebSDong Aisheng
3602161e6d44SGabriel Krisman Bertazi if ((intmask & SDHCI_INT_CARD_INT) &&
3603161e6d44SGabriel Krisman Bertazi (host->ier & SDHCI_INT_CARD_INT)) {
3604781e989cSRussell King sdhci_enable_sdio_irq_nolock(host, false);
360589f3c365SAdrian Hunter sdio_signal_irq(host->mmc);
3606781e989cSRussell King }
3607f75979b7SPierre Ossman
360841005003SRussell King intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
360941005003SRussell King SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
361041005003SRussell King SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
3611f37b20ebSDong Aisheng SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT);
3612f75979b7SPierre Ossman
36131c6a0718SPierre Ossman if (intmask) {
36146379b237SAlexander Stein unexpected |= intmask;
36154e4141a5SAnton Vorontsov sdhci_writel(host, intmask, SDHCI_INT_STATUS);
36161c6a0718SPierre Ossman }
3617f12e39dbSAdrian Hunter cont:
3618781e989cSRussell King if (result == IRQ_NONE)
36191c6a0718SPierre Ossman result = IRQ_HANDLED;
36201c6a0718SPierre Ossman
36216379b237SAlexander Stein intmask = sdhci_readl(host, SDHCI_INT_STATUS);
362241005003SRussell King } while (intmask && --max_loops);
362319d2f695SAdrian Hunter
362419d2f695SAdrian Hunter /* Determine if mrqs can be completed immediately */
362519d2f695SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) {
362619d2f695SAdrian Hunter struct mmc_request *mrq = host->mrqs_done[i];
362719d2f695SAdrian Hunter
362819d2f695SAdrian Hunter if (!mrq)
362919d2f695SAdrian Hunter continue;
363019d2f695SAdrian Hunter
363119d2f695SAdrian Hunter if (sdhci_defer_done(host, mrq)) {
3632c07a48c2SAdrian Hunter result = IRQ_WAKE_THREAD;
363319d2f695SAdrian Hunter } else {
363419d2f695SAdrian Hunter mrqs_done[i] = mrq;
363519d2f695SAdrian Hunter host->mrqs_done[i] = NULL;
363619d2f695SAdrian Hunter }
363719d2f695SAdrian Hunter }
36381c6a0718SPierre Ossman out:
3639845c939eSAdrian Hunter if (host->deferred_cmd)
3640845c939eSAdrian Hunter result = IRQ_WAKE_THREAD;
3641845c939eSAdrian Hunter
36421c6a0718SPierre Ossman spin_unlock(&host->lock);
36431c6a0718SPierre Ossman
364419d2f695SAdrian Hunter /* Process mrqs ready for immediate completion */
364519d2f695SAdrian Hunter for (i = 0; i < SDHCI_MAX_MRQS; i++) {
36461774b002SBaolin Wang if (!mrqs_done[i])
36471774b002SBaolin Wang continue;
36481774b002SBaolin Wang
36491774b002SBaolin Wang if (host->ops->request_done)
36501774b002SBaolin Wang host->ops->request_done(host, mrqs_done[i]);
36511774b002SBaolin Wang else
365219d2f695SAdrian Hunter mmc_request_done(host->mmc, mrqs_done[i]);
365319d2f695SAdrian Hunter }
365419d2f695SAdrian Hunter
36556379b237SAlexander Stein if (unexpected) {
36566379b237SAlexander Stein pr_err("%s: Unexpected interrupt 0x%08x.\n",
36576379b237SAlexander Stein mmc_hostname(host->mmc), unexpected);
3658efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ);
36596379b237SAlexander Stein sdhci_dumpregs(host);
36606379b237SAlexander Stein }
3661f75979b7SPierre Ossman
36621c6a0718SPierre Ossman return result;
36631c6a0718SPierre Ossman }
36641c6a0718SPierre Ossman
sdhci_thread_irq(int irq,void * dev_id)3665781e989cSRussell King static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
3666781e989cSRussell King {
3667781e989cSRussell King struct sdhci_host *host = dev_id;
3668845c939eSAdrian Hunter struct mmc_command *cmd;
3669781e989cSRussell King unsigned long flags;
3670781e989cSRussell King u32 isr;
3671781e989cSRussell King
3672c07a48c2SAdrian Hunter while (!sdhci_request_done(host))
3673c07a48c2SAdrian Hunter ;
3674c07a48c2SAdrian Hunter
3675781e989cSRussell King spin_lock_irqsave(&host->lock, flags);
3676845c939eSAdrian Hunter
3677781e989cSRussell King isr = host->thread_isr;
3678781e989cSRussell King host->thread_isr = 0;
3679845c939eSAdrian Hunter
3680845c939eSAdrian Hunter cmd = host->deferred_cmd;
3681845c939eSAdrian Hunter if (cmd && !sdhci_send_command_retry(host, cmd, flags))
3682845c939eSAdrian Hunter sdhci_finish_mrq(host, cmd->mrq);
3683845c939eSAdrian Hunter
3684781e989cSRussell King spin_unlock_irqrestore(&host->lock, flags);
3685781e989cSRussell King
36863560db8eSRussell King if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
3687d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc;
3688d3940f27SAdrian Hunter
3689d3940f27SAdrian Hunter mmc->ops->card_event(mmc);
3690d3940f27SAdrian Hunter mmc_detect_change(mmc, msecs_to_jiffies(200));
36913560db8eSRussell King }
36923560db8eSRussell King
3693c07a48c2SAdrian Hunter return IRQ_HANDLED;
3694781e989cSRussell King }
3695781e989cSRussell King
36961c6a0718SPierre Ossman /*****************************************************************************\
36971c6a0718SPierre Ossman * *
36981c6a0718SPierre Ossman * Suspend/resume *
36991c6a0718SPierre Ossman * *
37001c6a0718SPierre Ossman \*****************************************************************************/
37011c6a0718SPierre Ossman
37021c6a0718SPierre Ossman #ifdef CONFIG_PM
37039c316b38SAdrian Hunter
sdhci_cd_irq_can_wakeup(struct sdhci_host * host)37049c316b38SAdrian Hunter static bool sdhci_cd_irq_can_wakeup(struct sdhci_host *host)
37059c316b38SAdrian Hunter {
37069c316b38SAdrian Hunter return mmc_card_is_removable(host->mmc) &&
37079c316b38SAdrian Hunter !(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
37089c316b38SAdrian Hunter !mmc_can_gpio_cd(host->mmc);
37099c316b38SAdrian Hunter }
37109c316b38SAdrian Hunter
371184d62605SLudovic Desroches /*
371284d62605SLudovic Desroches * To enable wakeup events, the corresponding events have to be enabled in
371384d62605SLudovic Desroches * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal
371484d62605SLudovic Desroches * Table' in the SD Host Controller Standard Specification.
371584d62605SLudovic Desroches * It is useless to restore SDHCI_INT_ENABLE state in
371684d62605SLudovic Desroches * sdhci_disable_irq_wakeups() since it will be set by
371784d62605SLudovic Desroches * sdhci_enable_card_detection() or sdhci_init().
371884d62605SLudovic Desroches */
sdhci_enable_irq_wakeups(struct sdhci_host * host)371958e79b60SAdrian Hunter static bool sdhci_enable_irq_wakeups(struct sdhci_host *host)
3720ad080d79SKevin Liu {
372181b14543SAdrian Hunter u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE |
372281b14543SAdrian Hunter SDHCI_WAKE_ON_INT;
372381b14543SAdrian Hunter u32 irq_val = 0;
372481b14543SAdrian Hunter u8 wake_val = 0;
3725ad080d79SKevin Liu u8 val;
372681b14543SAdrian Hunter
37279c316b38SAdrian Hunter if (sdhci_cd_irq_can_wakeup(host)) {
372881b14543SAdrian Hunter wake_val |= SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE;
372981b14543SAdrian Hunter irq_val |= SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE;
373081b14543SAdrian Hunter }
373181b14543SAdrian Hunter
3732d5d568faSAdrian Hunter if (mmc_card_wake_sdio_irq(host->mmc)) {
373381b14543SAdrian Hunter wake_val |= SDHCI_WAKE_ON_INT;
373481b14543SAdrian Hunter irq_val |= SDHCI_INT_CARD_INT;
3735d5d568faSAdrian Hunter }
3736d5d568faSAdrian Hunter
3737d5d568faSAdrian Hunter if (!irq_val)
3738d5d568faSAdrian Hunter return false;
3739ad080d79SKevin Liu
3740ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
374181b14543SAdrian Hunter val &= ~mask;
374281b14543SAdrian Hunter val |= wake_val;
3743ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
374481b14543SAdrian Hunter
374584d62605SLudovic Desroches sdhci_writel(host, irq_val, SDHCI_INT_ENABLE);
374658e79b60SAdrian Hunter
374758e79b60SAdrian Hunter host->irq_wake_enabled = !enable_irq_wake(host->irq);
374858e79b60SAdrian Hunter
374958e79b60SAdrian Hunter return host->irq_wake_enabled;
3750ad080d79SKevin Liu }
3751ad080d79SKevin Liu
sdhci_disable_irq_wakeups(struct sdhci_host * host)37520b10f478SFabio Estevam static void sdhci_disable_irq_wakeups(struct sdhci_host *host)
3753ad080d79SKevin Liu {
3754ad080d79SKevin Liu u8 val;
3755ad080d79SKevin Liu u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE
3756ad080d79SKevin Liu | SDHCI_WAKE_ON_INT;
3757ad080d79SKevin Liu
3758ad080d79SKevin Liu val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
3759ad080d79SKevin Liu val &= ~mask;
3760ad080d79SKevin Liu sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
376158e79b60SAdrian Hunter
376258e79b60SAdrian Hunter disable_irq_wake(host->irq);
376358e79b60SAdrian Hunter
376458e79b60SAdrian Hunter host->irq_wake_enabled = false;
3765ad080d79SKevin Liu }
37661c6a0718SPierre Ossman
sdhci_suspend_host(struct sdhci_host * host)376729495aa0SManuel Lauss int sdhci_suspend_host(struct sdhci_host *host)
37681c6a0718SPierre Ossman {
37697260cf5eSAnton Vorontsov sdhci_disable_card_detection(host);
37707260cf5eSAnton Vorontsov
377166c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc);
3772cf2b5eeaSArindam Nath
377358e79b60SAdrian Hunter if (!device_may_wakeup(mmc_dev(host->mmc)) ||
377458e79b60SAdrian Hunter !sdhci_enable_irq_wakeups(host)) {
3775b537f94cSRussell King host->ier = 0;
3776b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE);
3777b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
3778b8c86fc5SPierre Ossman free_irq(host->irq, host);
3779ad080d79SKevin Liu }
378058e79b60SAdrian Hunter
37814ee14ec6SUlf Hansson return 0;
3782b8c86fc5SPierre Ossman }
3783b8c86fc5SPierre Ossman
3784b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_suspend_host);
3785b8c86fc5SPierre Ossman
sdhci_resume_host(struct sdhci_host * host)3786b8c86fc5SPierre Ossman int sdhci_resume_host(struct sdhci_host *host)
3787b8c86fc5SPierre Ossman {
3788d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc;
37894ee14ec6SUlf Hansson int ret = 0;
3790b8c86fc5SPierre Ossman
3791a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
3792b8c86fc5SPierre Ossman if (host->ops->enable_dma)
3793b8c86fc5SPierre Ossman host->ops->enable_dma(host);
3794b8c86fc5SPierre Ossman }
3795b8c86fc5SPierre Ossman
3796d2f025b0SJisheng Zhang if ((mmc->pm_flags & MMC_PM_KEEP_POWER) &&
37976308d290SAdrian Hunter (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) {
37986308d290SAdrian Hunter /* Card keeps power but host controller does not */
37996308d290SAdrian Hunter sdhci_init(host, 0);
38006308d290SAdrian Hunter host->pwr = 0;
38016308d290SAdrian Hunter host->clock = 0;
3802c981cdfbSAdrian Hunter host->reinit_uhs = true;
3803d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios);
38046308d290SAdrian Hunter } else {
3805d2f025b0SJisheng Zhang sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER));
38066308d290SAdrian Hunter }
3807b8c86fc5SPierre Ossman
380858e79b60SAdrian Hunter if (host->irq_wake_enabled) {
380958e79b60SAdrian Hunter sdhci_disable_irq_wakeups(host);
381058e79b60SAdrian Hunter } else {
381114a7b416SHaibo Chen ret = request_threaded_irq(host->irq, sdhci_irq,
381214a7b416SHaibo Chen sdhci_thread_irq, IRQF_SHARED,
3813d2f025b0SJisheng Zhang mmc_hostname(mmc), host);
381414a7b416SHaibo Chen if (ret)
381514a7b416SHaibo Chen return ret;
381614a7b416SHaibo Chen }
381714a7b416SHaibo Chen
38187260cf5eSAnton Vorontsov sdhci_enable_card_detection(host);
38197260cf5eSAnton Vorontsov
38202f4cbb3dSNicolas Pitre return ret;
38211c6a0718SPierre Ossman }
38221c6a0718SPierre Ossman
3823b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_resume_host);
382466fd8ad5SAdrian Hunter
sdhci_runtime_suspend_host(struct sdhci_host * host)382566fd8ad5SAdrian Hunter int sdhci_runtime_suspend_host(struct sdhci_host *host)
382666fd8ad5SAdrian Hunter {
382766fd8ad5SAdrian Hunter unsigned long flags;
382866fd8ad5SAdrian Hunter
382966c39dfcSAdrian Hunter mmc_retune_timer_stop(host->mmc);
383066fd8ad5SAdrian Hunter
383166fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags);
3832b537f94cSRussell King host->ier &= SDHCI_INT_CARD_INT;
3833b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
3834b537f94cSRussell King sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
383566fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
383666fd8ad5SAdrian Hunter
3837781e989cSRussell King synchronize_hardirq(host->irq);
383866fd8ad5SAdrian Hunter
383966fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags);
384066fd8ad5SAdrian Hunter host->runtime_suspended = true;
384166fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
384266fd8ad5SAdrian Hunter
38438a125badSMarkus Pargmann return 0;
384466fd8ad5SAdrian Hunter }
384566fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host);
384666fd8ad5SAdrian Hunter
sdhci_runtime_resume_host(struct sdhci_host * host,int soft_reset)3847c6303c5dSBaolin Wang int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset)
384866fd8ad5SAdrian Hunter {
3849d3940f27SAdrian Hunter struct mmc_host *mmc = host->mmc;
385066fd8ad5SAdrian Hunter unsigned long flags;
38518a125badSMarkus Pargmann int host_flags = host->flags;
385266fd8ad5SAdrian Hunter
385366fd8ad5SAdrian Hunter if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
385466fd8ad5SAdrian Hunter if (host->ops->enable_dma)
385566fd8ad5SAdrian Hunter host->ops->enable_dma(host);
385666fd8ad5SAdrian Hunter }
385766fd8ad5SAdrian Hunter
3858c6303c5dSBaolin Wang sdhci_init(host, soft_reset);
385966fd8ad5SAdrian Hunter
386070bc85adSZhoujie Wu if (mmc->ios.power_mode != MMC_POWER_UNDEFINED &&
386170bc85adSZhoujie Wu mmc->ios.power_mode != MMC_POWER_OFF) {
386266fd8ad5SAdrian Hunter /* Force clock and power re-program */
386366fd8ad5SAdrian Hunter host->pwr = 0;
386466fd8ad5SAdrian Hunter host->clock = 0;
3865c981cdfbSAdrian Hunter host->reinit_uhs = true;
3866d3940f27SAdrian Hunter mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios);
3867d3940f27SAdrian Hunter mmc->ops->set_ios(mmc, &mmc->ios);
386866fd8ad5SAdrian Hunter
386952983382SKevin Liu if ((host_flags & SDHCI_PV_ENABLED) &&
387052983382SKevin Liu !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
387152983382SKevin Liu spin_lock_irqsave(&host->lock, flags);
387252983382SKevin Liu sdhci_enable_preset_value(host, true);
387352983382SKevin Liu spin_unlock_irqrestore(&host->lock, flags);
387452983382SKevin Liu }
387566fd8ad5SAdrian Hunter
3876086b0ddbSAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HS400_ES) &&
3877086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe)
3878086b0ddbSAdrian Hunter mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios);
387984ec048bSAdrian Hunter }
3880086b0ddbSAdrian Hunter
388166fd8ad5SAdrian Hunter spin_lock_irqsave(&host->lock, flags);
388266fd8ad5SAdrian Hunter
388366fd8ad5SAdrian Hunter host->runtime_suspended = false;
388466fd8ad5SAdrian Hunter
388566fd8ad5SAdrian Hunter /* Enable SDIO IRQ */
38860e62614bSUlf Hansson if (sdio_irq_claimed(mmc))
388766fd8ad5SAdrian Hunter sdhci_enable_sdio_irq_nolock(host, true);
388866fd8ad5SAdrian Hunter
388966fd8ad5SAdrian Hunter /* Enable Card Detection */
389066fd8ad5SAdrian Hunter sdhci_enable_card_detection(host);
389166fd8ad5SAdrian Hunter
389266fd8ad5SAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
389366fd8ad5SAdrian Hunter
38948a125badSMarkus Pargmann return 0;
389566fd8ad5SAdrian Hunter }
389666fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host);
389766fd8ad5SAdrian Hunter
3898162d6f98SRafael J. Wysocki #endif /* CONFIG_PM */
389966fd8ad5SAdrian Hunter
39001c6a0718SPierre Ossman /*****************************************************************************\
39011c6a0718SPierre Ossman * *
3902f12e39dbSAdrian Hunter * Command Queue Engine (CQE) helpers *
3903f12e39dbSAdrian Hunter * *
3904f12e39dbSAdrian Hunter \*****************************************************************************/
3905f12e39dbSAdrian Hunter
sdhci_cqe_enable(struct mmc_host * mmc)3906f12e39dbSAdrian Hunter void sdhci_cqe_enable(struct mmc_host *mmc)
3907f12e39dbSAdrian Hunter {
3908f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc);
3909f12e39dbSAdrian Hunter unsigned long flags;
3910f12e39dbSAdrian Hunter u8 ctrl;
3911f12e39dbSAdrian Hunter
3912f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags);
3913f12e39dbSAdrian Hunter
3914f12e39dbSAdrian Hunter ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
3915f12e39dbSAdrian Hunter ctrl &= ~SDHCI_CTRL_DMA_MASK;
39164c4faff6SSowjanya Komatineni /*
39174c4faff6SSowjanya Komatineni * Host from V4.10 supports ADMA3 DMA type.
39184c4faff6SSowjanya Komatineni * ADMA3 performs integrated descriptor which is more suitable
39194c4faff6SSowjanya Komatineni * for cmd queuing to fetch both command and transfer descriptors.
39204c4faff6SSowjanya Komatineni */
39214c4faff6SSowjanya Komatineni if (host->v4_mode && (host->caps1 & SDHCI_CAN_DO_ADMA3))
39224c4faff6SSowjanya Komatineni ctrl |= SDHCI_CTRL_ADMA3;
39234c4faff6SSowjanya Komatineni else if (host->flags & SDHCI_USE_64_BIT_DMA)
3924f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA64;
3925f12e39dbSAdrian Hunter else
3926f12e39dbSAdrian Hunter ctrl |= SDHCI_CTRL_ADMA32;
3927f12e39dbSAdrian Hunter sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
3928f12e39dbSAdrian Hunter
3929c846a00fSSrinivas Kandagatla sdhci_writew(host, SDHCI_MAKE_BLKSZ(host->sdma_boundary, 512),
3930f12e39dbSAdrian Hunter SDHCI_BLOCK_SIZE);
3931f12e39dbSAdrian Hunter
3932f12e39dbSAdrian Hunter /* Set maximum timeout */
3933401059dfSBOUGH CHEN sdhci_set_timeout(host, NULL);
3934f12e39dbSAdrian Hunter
3935f12e39dbSAdrian Hunter host->ier = host->cqe_ier;
3936f12e39dbSAdrian Hunter
3937f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
3938f12e39dbSAdrian Hunter sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
3939f12e39dbSAdrian Hunter
3940f12e39dbSAdrian Hunter host->cqe_on = true;
3941f12e39dbSAdrian Hunter
3942f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE on, IRQ mask %#x, IRQ status %#x\n",
3943f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier,
3944f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS));
3945f12e39dbSAdrian Hunter
3946f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
3947f12e39dbSAdrian Hunter }
3948f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_enable);
3949f12e39dbSAdrian Hunter
sdhci_cqe_disable(struct mmc_host * mmc,bool recovery)3950f12e39dbSAdrian Hunter void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery)
3951f12e39dbSAdrian Hunter {
3952f12e39dbSAdrian Hunter struct sdhci_host *host = mmc_priv(mmc);
3953f12e39dbSAdrian Hunter unsigned long flags;
3954f12e39dbSAdrian Hunter
3955f12e39dbSAdrian Hunter spin_lock_irqsave(&host->lock, flags);
3956f12e39dbSAdrian Hunter
3957f12e39dbSAdrian Hunter sdhci_set_default_irqs(host);
3958f12e39dbSAdrian Hunter
3959f12e39dbSAdrian Hunter host->cqe_on = false;
3960f12e39dbSAdrian Hunter
39611e63d297SAdrian Hunter if (recovery)
39621e63d297SAdrian Hunter sdhci_reset_for(host, CQE_RECOVERY);
3963f12e39dbSAdrian Hunter
3964f12e39dbSAdrian Hunter pr_debug("%s: sdhci: CQE off, IRQ mask %#x, IRQ status %#x\n",
3965f12e39dbSAdrian Hunter mmc_hostname(mmc), host->ier,
3966f12e39dbSAdrian Hunter sdhci_readl(host, SDHCI_INT_STATUS));
3967f12e39dbSAdrian Hunter
3968f12e39dbSAdrian Hunter spin_unlock_irqrestore(&host->lock, flags);
3969f12e39dbSAdrian Hunter }
3970f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_disable);
3971f12e39dbSAdrian Hunter
sdhci_cqe_irq(struct sdhci_host * host,u32 intmask,int * cmd_error,int * data_error)3972f12e39dbSAdrian Hunter bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error,
3973f12e39dbSAdrian Hunter int *data_error)
3974f12e39dbSAdrian Hunter {
3975f12e39dbSAdrian Hunter u32 mask;
3976f12e39dbSAdrian Hunter
3977f12e39dbSAdrian Hunter if (!host->cqe_on)
3978f12e39dbSAdrian Hunter return false;
3979f12e39dbSAdrian Hunter
3980efe8f5c9SShaik Sajida Bhanu if (intmask & (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC)) {
3981f12e39dbSAdrian Hunter *cmd_error = -EILSEQ;
3982faded9b5SWenchao Chen if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
3983efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_CRC);
3984efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_TIMEOUT) {
3985f12e39dbSAdrian Hunter *cmd_error = -ETIMEDOUT;
3986efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, CMD_TIMEOUT);
3987efe8f5c9SShaik Sajida Bhanu } else
3988f12e39dbSAdrian Hunter *cmd_error = 0;
3989f12e39dbSAdrian Hunter
3990d9ae0aa8SAdrian Hunter if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_TUNING_ERROR)) {
3991f12e39dbSAdrian Hunter *data_error = -EILSEQ;
3992faded9b5SWenchao Chen if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
3993efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_CRC);
3994efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_DATA_TIMEOUT) {
3995f12e39dbSAdrian Hunter *data_error = -ETIMEDOUT;
3996efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, DAT_TIMEOUT);
3997efe8f5c9SShaik Sajida Bhanu } else if (intmask & SDHCI_INT_ADMA_ERROR) {
3998f12e39dbSAdrian Hunter *data_error = -EIO;
3999efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, ADMA);
4000efe8f5c9SShaik Sajida Bhanu } else
4001f12e39dbSAdrian Hunter *data_error = 0;
4002f12e39dbSAdrian Hunter
4003f12e39dbSAdrian Hunter /* Clear selected interrupts. */
4004f12e39dbSAdrian Hunter mask = intmask & host->cqe_ier;
4005f12e39dbSAdrian Hunter sdhci_writel(host, mask, SDHCI_INT_STATUS);
4006f12e39dbSAdrian Hunter
4007f12e39dbSAdrian Hunter if (intmask & SDHCI_INT_BUS_POWER)
4008f12e39dbSAdrian Hunter pr_err("%s: Card is consuming too much power!\n",
4009f12e39dbSAdrian Hunter mmc_hostname(host->mmc));
4010f12e39dbSAdrian Hunter
4011f12e39dbSAdrian Hunter intmask &= ~(host->cqe_ier | SDHCI_INT_ERROR);
4012f12e39dbSAdrian Hunter if (intmask) {
4013f12e39dbSAdrian Hunter sdhci_writel(host, intmask, SDHCI_INT_STATUS);
4014f12e39dbSAdrian Hunter pr_err("%s: CQE: Unexpected interrupt 0x%08x.\n",
4015f12e39dbSAdrian Hunter mmc_hostname(host->mmc), intmask);
4016efe8f5c9SShaik Sajida Bhanu sdhci_err_stats_inc(host, UNEXPECTED_IRQ);
4017f12e39dbSAdrian Hunter sdhci_dumpregs(host);
4018f12e39dbSAdrian Hunter }
4019f12e39dbSAdrian Hunter
4020f12e39dbSAdrian Hunter return true;
4021f12e39dbSAdrian Hunter }
4022f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_irq);
4023f12e39dbSAdrian Hunter
4024f12e39dbSAdrian Hunter /*****************************************************************************\
4025f12e39dbSAdrian Hunter * *
4026b8c86fc5SPierre Ossman * Device allocation/registration *
40271c6a0718SPierre Ossman * *
40281c6a0718SPierre Ossman \*****************************************************************************/
40291c6a0718SPierre Ossman
sdhci_alloc_host(struct device * dev,size_t priv_size)4030b8c86fc5SPierre Ossman struct sdhci_host *sdhci_alloc_host(struct device *dev,
4031b8c86fc5SPierre Ossman size_t priv_size)
40321c6a0718SPierre Ossman {
40331c6a0718SPierre Ossman struct mmc_host *mmc;
40341c6a0718SPierre Ossman struct sdhci_host *host;
40351c6a0718SPierre Ossman
4036b8c86fc5SPierre Ossman WARN_ON(dev == NULL);
40371c6a0718SPierre Ossman
4038b8c86fc5SPierre Ossman mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev);
40391c6a0718SPierre Ossman if (!mmc)
4040b8c86fc5SPierre Ossman return ERR_PTR(-ENOMEM);
40411c6a0718SPierre Ossman
40421c6a0718SPierre Ossman host = mmc_priv(mmc);
40431c6a0718SPierre Ossman host->mmc = mmc;
4044bf60e592SAdrian Hunter host->mmc_host_ops = sdhci_ops;
4045bf60e592SAdrian Hunter mmc->ops = &host->mmc_host_ops;
40461c6a0718SPierre Ossman
40478cb851a4SAdrian Hunter host->flags = SDHCI_SIGNALING_330;
40488cb851a4SAdrian Hunter
4049f12e39dbSAdrian Hunter host->cqe_ier = SDHCI_CQE_INT_MASK;
4050f12e39dbSAdrian Hunter host->cqe_err_ier = SDHCI_CQE_INT_ERR_MASK;
4051f12e39dbSAdrian Hunter
405283b600b8SAdrian Hunter host->tuning_delay = -1;
40531d8cd065SSowjanya Komatineni host->tuning_loop_count = MAX_TUNING_LOOP;
405483b600b8SAdrian Hunter
4055c846a00fSSrinivas Kandagatla host->sdma_boundary = SDHCI_DEFAULT_BOUNDARY_ARG;
4056c846a00fSSrinivas Kandagatla
4057e93be38aSJisheng Zhang /*
4058e93be38aSJisheng Zhang * The DMA table descriptor count is calculated as the maximum
4059e93be38aSJisheng Zhang * number of segments times 2, to allow for an alignment
4060e93be38aSJisheng Zhang * descriptor for each segment, plus 1 for a nop end descriptor.
4061e93be38aSJisheng Zhang */
4062e93be38aSJisheng Zhang host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1;
40633d7c194bSAdrian Hunter host->max_adma = 65536;
4064e93be38aSJisheng Zhang
4065e30314f2SSarthak Garg host->max_timeout_count = 0xE;
4066e30314f2SSarthak Garg
4067b8c86fc5SPierre Ossman return host;
40681c6a0718SPierre Ossman }
40691c6a0718SPierre Ossman
4070b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_alloc_host);
4071b8c86fc5SPierre Ossman
sdhci_set_dma_mask(struct sdhci_host * host)40727b91369bSAlexandre Courbot static int sdhci_set_dma_mask(struct sdhci_host *host)
40737b91369bSAlexandre Courbot {
40747b91369bSAlexandre Courbot struct mmc_host *mmc = host->mmc;
40757b91369bSAlexandre Courbot struct device *dev = mmc_dev(mmc);
40767b91369bSAlexandre Courbot int ret = -EINVAL;
40777b91369bSAlexandre Courbot
40787b91369bSAlexandre Courbot if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA)
40797b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA;
40807b91369bSAlexandre Courbot
40817b91369bSAlexandre Courbot /* Try 64-bit mask if hardware is capable of it */
40827b91369bSAlexandre Courbot if (host->flags & SDHCI_USE_64_BIT_DMA) {
40837b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
40847b91369bSAlexandre Courbot if (ret) {
40857b91369bSAlexandre Courbot pr_warn("%s: Failed to set 64-bit DMA mask.\n",
40867b91369bSAlexandre Courbot mmc_hostname(mmc));
40877b91369bSAlexandre Courbot host->flags &= ~SDHCI_USE_64_BIT_DMA;
40887b91369bSAlexandre Courbot }
40897b91369bSAlexandre Courbot }
40907b91369bSAlexandre Courbot
40917b91369bSAlexandre Courbot /* 32-bit mask as default & fallback */
40927b91369bSAlexandre Courbot if (ret) {
40937b91369bSAlexandre Courbot ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
40947b91369bSAlexandre Courbot if (ret)
40957b91369bSAlexandre Courbot pr_warn("%s: Failed to set 32-bit DMA mask.\n",
40967b91369bSAlexandre Courbot mmc_hostname(mmc));
40977b91369bSAlexandre Courbot }
40987b91369bSAlexandre Courbot
40997b91369bSAlexandre Courbot return ret;
41007b91369bSAlexandre Courbot }
41017b91369bSAlexandre Courbot
__sdhci_read_caps(struct sdhci_host * host,const u16 * ver,const u32 * caps,const u32 * caps1)41028784edc8SMasahiro Yamada void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver,
41038784edc8SMasahiro Yamada const u32 *caps, const u32 *caps1)
41046132a3bfSAdrian Hunter {
41056132a3bfSAdrian Hunter u16 v;
410692e0c44bSZach Brown u64 dt_caps_mask = 0;
410792e0c44bSZach Brown u64 dt_caps = 0;
41086132a3bfSAdrian Hunter
41096132a3bfSAdrian Hunter if (host->read_caps)
41106132a3bfSAdrian Hunter return;
41116132a3bfSAdrian Hunter
41126132a3bfSAdrian Hunter host->read_caps = true;
41136132a3bfSAdrian Hunter
41146132a3bfSAdrian Hunter if (debug_quirks)
41156132a3bfSAdrian Hunter host->quirks = debug_quirks;
41166132a3bfSAdrian Hunter
41176132a3bfSAdrian Hunter if (debug_quirks2)
41186132a3bfSAdrian Hunter host->quirks2 = debug_quirks2;
41196132a3bfSAdrian Hunter
4120aa990722SAdrian Hunter sdhci_reset_for_all(host);
41216132a3bfSAdrian Hunter
4122b3f80b43SChunyan Zhang if (host->v4_mode)
4123b3f80b43SChunyan Zhang sdhci_do_enable_v4_mode(host);
4124b3f80b43SChunyan Zhang
4125cb80a7e9SJeremy Linton device_property_read_u64(mmc_dev(host->mmc),
4126cb80a7e9SJeremy Linton "sdhci-caps-mask", &dt_caps_mask);
4127cb80a7e9SJeremy Linton device_property_read_u64(mmc_dev(host->mmc),
4128cb80a7e9SJeremy Linton "sdhci-caps", &dt_caps);
412992e0c44bSZach Brown
41306132a3bfSAdrian Hunter v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION);
41316132a3bfSAdrian Hunter host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
41326132a3bfSAdrian Hunter
413392e0c44bSZach Brown if (caps) {
413492e0c44bSZach Brown host->caps = *caps;
413592e0c44bSZach Brown } else {
413692e0c44bSZach Brown host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
413792e0c44bSZach Brown host->caps &= ~lower_32_bits(dt_caps_mask);
413892e0c44bSZach Brown host->caps |= lower_32_bits(dt_caps);
413992e0c44bSZach Brown }
41406132a3bfSAdrian Hunter
41416132a3bfSAdrian Hunter if (host->version < SDHCI_SPEC_300)
41426132a3bfSAdrian Hunter return;
41436132a3bfSAdrian Hunter
414492e0c44bSZach Brown if (caps1) {
414592e0c44bSZach Brown host->caps1 = *caps1;
414692e0c44bSZach Brown } else {
414792e0c44bSZach Brown host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
414892e0c44bSZach Brown host->caps1 &= ~upper_32_bits(dt_caps_mask);
414992e0c44bSZach Brown host->caps1 |= upper_32_bits(dt_caps);
415092e0c44bSZach Brown }
41516132a3bfSAdrian Hunter }
41526132a3bfSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_read_caps);
41536132a3bfSAdrian Hunter
sdhci_allocate_bounce_buffer(struct sdhci_host * host)4154a68dd9a0SChunyan Zhang static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)
4155bd9b9027SLinus Walleij {
4156bd9b9027SLinus Walleij struct mmc_host *mmc = host->mmc;
4157bd9b9027SLinus Walleij unsigned int max_blocks;
4158bd9b9027SLinus Walleij unsigned int bounce_size;
4159bd9b9027SLinus Walleij int ret;
4160bd9b9027SLinus Walleij
4161bd9b9027SLinus Walleij /*
4162bd9b9027SLinus Walleij * Cap the bounce buffer at 64KB. Using a bigger bounce buffer
4163bd9b9027SLinus Walleij * has diminishing returns, this is probably because SD/MMC
4164bd9b9027SLinus Walleij * cards are usually optimized to handle this size of requests.
4165bd9b9027SLinus Walleij */
4166bd9b9027SLinus Walleij bounce_size = SZ_64K;
4167bd9b9027SLinus Walleij /*
4168bd9b9027SLinus Walleij * Adjust downwards to maximum request size if this is less
4169bd9b9027SLinus Walleij * than our segment size, else hammer down the maximum
4170bd9b9027SLinus Walleij * request size to the maximum buffer size.
4171bd9b9027SLinus Walleij */
4172bd9b9027SLinus Walleij if (mmc->max_req_size < bounce_size)
4173bd9b9027SLinus Walleij bounce_size = mmc->max_req_size;
4174bd9b9027SLinus Walleij max_blocks = bounce_size / 512;
4175bd9b9027SLinus Walleij
4176bd9b9027SLinus Walleij /*
4177bd9b9027SLinus Walleij * When we just support one segment, we can get significant
4178bd9b9027SLinus Walleij * speedups by the help of a bounce buffer to group scattered
4179bd9b9027SLinus Walleij * reads/writes together.
4180bd9b9027SLinus Walleij */
4181bac53336SJisheng Zhang host->bounce_buffer = devm_kmalloc(mmc_dev(mmc),
4182bd9b9027SLinus Walleij bounce_size,
4183bd9b9027SLinus Walleij GFP_KERNEL);
4184bd9b9027SLinus Walleij if (!host->bounce_buffer) {
4185bd9b9027SLinus Walleij pr_err("%s: failed to allocate %u bytes for bounce buffer, falling back to single segments\n",
4186bd9b9027SLinus Walleij mmc_hostname(mmc),
4187bd9b9027SLinus Walleij bounce_size);
4188bd9b9027SLinus Walleij /*
4189bd9b9027SLinus Walleij * Exiting with zero here makes sure we proceed with
4190bd9b9027SLinus Walleij * mmc->max_segs == 1.
4191bd9b9027SLinus Walleij */
4192a68dd9a0SChunyan Zhang return;
4193bd9b9027SLinus Walleij }
4194bd9b9027SLinus Walleij
4195bac53336SJisheng Zhang host->bounce_addr = dma_map_single(mmc_dev(mmc),
4196bd9b9027SLinus Walleij host->bounce_buffer,
4197bd9b9027SLinus Walleij bounce_size,
4198bd9b9027SLinus Walleij DMA_BIDIRECTIONAL);
4199bac53336SJisheng Zhang ret = dma_mapping_error(mmc_dev(mmc), host->bounce_addr);
420049036ba8STakashi Iwai if (ret) {
420149036ba8STakashi Iwai devm_kfree(mmc_dev(mmc), host->bounce_buffer);
420249036ba8STakashi Iwai host->bounce_buffer = NULL;
4203bd9b9027SLinus Walleij /* Again fall back to max_segs == 1 */
4204a68dd9a0SChunyan Zhang return;
420549036ba8STakashi Iwai }
420649036ba8STakashi Iwai
4207bd9b9027SLinus Walleij host->bounce_buffer_size = bounce_size;
4208bd9b9027SLinus Walleij
4209bd9b9027SLinus Walleij /* Lie about this since we're bouncing */
4210bd9b9027SLinus Walleij mmc->max_segs = max_blocks;
4211bd9b9027SLinus Walleij mmc->max_seg_size = bounce_size;
4212bd9b9027SLinus Walleij mmc->max_req_size = bounce_size;
4213bd9b9027SLinus Walleij
4214bd9b9027SLinus Walleij pr_info("%s bounce up to %u segments into one, max segment size %u bytes\n",
4215bd9b9027SLinus Walleij mmc_hostname(mmc), max_blocks, bounce_size);
4216bd9b9027SLinus Walleij }
4217bd9b9027SLinus Walleij
sdhci_can_64bit_dma(struct sdhci_host * host)4218685e444bSChunyan Zhang static inline bool sdhci_can_64bit_dma(struct sdhci_host *host)
4219685e444bSChunyan Zhang {
4220685e444bSChunyan Zhang /*
4221685e444bSChunyan Zhang * According to SD Host Controller spec v4.10, bit[27] added from
4222685e444bSChunyan Zhang * version 4.10 in Capabilities Register is used as 64-bit System
4223685e444bSChunyan Zhang * Address support for V4 mode.
4224685e444bSChunyan Zhang */
4225685e444bSChunyan Zhang if (host->version >= SDHCI_SPEC_410 && host->v4_mode)
4226685e444bSChunyan Zhang return host->caps & SDHCI_CAN_64BIT_V4;
4227685e444bSChunyan Zhang
4228685e444bSChunyan Zhang return host->caps & SDHCI_CAN_64BIT;
4229685e444bSChunyan Zhang }
4230685e444bSChunyan Zhang
sdhci_setup_host(struct sdhci_host * host)423152f5336dSAdrian Hunter int sdhci_setup_host(struct sdhci_host *host)
4232b8c86fc5SPierre Ossman {
4233b8c86fc5SPierre Ossman struct mmc_host *mmc;
4234f2119df6SArindam Nath u32 max_current_caps;
4235f2119df6SArindam Nath unsigned int ocr_avail;
4236f5fa92e5SAdrian Hunter unsigned int override_timeout_clk;
423759241757SDong Aisheng u32 max_clk;
4238907be2a6SDan Carpenter int ret = 0;
42390fcb031eSVijay Viswanath bool enable_vqmmc = false;
4240b8c86fc5SPierre Ossman
4241b8c86fc5SPierre Ossman WARN_ON(host == NULL);
4242b8c86fc5SPierre Ossman if (host == NULL)
4243b8c86fc5SPierre Ossman return -EINVAL;
4244b8c86fc5SPierre Ossman
4245b8c86fc5SPierre Ossman mmc = host->mmc;
4246b8c86fc5SPierre Ossman
4247efba142bSJon Hunter /*
4248efba142bSJon Hunter * If there are external regulators, get them. Note this must be done
4249efba142bSJon Hunter * early before resetting the host and reading the capabilities so that
4250efba142bSJon Hunter * the host can take the appropriate action if regulators are not
4251efba142bSJon Hunter * available.
4252efba142bSJon Hunter */
42530fcb031eSVijay Viswanath if (!mmc->supply.vqmmc) {
4254efba142bSJon Hunter ret = mmc_regulator_get_supply(mmc);
42552a63303dSWolfram Sang if (ret)
4256efba142bSJon Hunter return ret;
42570fcb031eSVijay Viswanath enable_vqmmc = true;
42580fcb031eSVijay Viswanath }
4259efba142bSJon Hunter
426006ebc601SShawn Lin DBG("Version: 0x%08x | Present: 0x%08x\n",
426106ebc601SShawn Lin sdhci_readw(host, SDHCI_HOST_VERSION),
426206ebc601SShawn Lin sdhci_readl(host, SDHCI_PRESENT_STATE));
426306ebc601SShawn Lin DBG("Caps: 0x%08x | Caps_1: 0x%08x\n",
426406ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES),
426506ebc601SShawn Lin sdhci_readl(host, SDHCI_CAPABILITIES_1));
426606ebc601SShawn Lin
42676132a3bfSAdrian Hunter sdhci_read_caps(host);
4268b8c86fc5SPierre Ossman
4269f5fa92e5SAdrian Hunter override_timeout_clk = host->timeout_clk;
4270f5fa92e5SAdrian Hunter
427118da1990SChunyan Zhang if (host->version > SDHCI_SPEC_420) {
42722e4456f0SMarek Vasut pr_err("%s: Unknown controller version (%d). You may experience problems.\n",
42732e4456f0SMarek Vasut mmc_hostname(mmc), host->version);
42741c6a0718SPierre Ossman }
42751c6a0718SPierre Ossman
4276b8c86fc5SPierre Ossman if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
4277a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA;
427828da3589SAdrian Hunter else if (!(host->caps & SDHCI_CAN_DO_SDMA))
4279a13abc7bSRichard Röjfors DBG("Controller doesn't have SDMA capability\n");
42801c6a0718SPierre Ossman else
4281a13abc7bSRichard Röjfors host->flags |= SDHCI_USE_SDMA;
42821c6a0718SPierre Ossman
4283b8c86fc5SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) &&
4284a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA)) {
4285cee687ceSRolf Eike Beer DBG("Disabling DMA as it is marked broken\n");
4286a13abc7bSRichard Röjfors host->flags &= ~SDHCI_USE_SDMA;
42877c168e3dSFeng Tang }
42887c168e3dSFeng Tang
4289f2119df6SArindam Nath if ((host->version >= SDHCI_SPEC_200) &&
429028da3589SAdrian Hunter (host->caps & SDHCI_CAN_DO_ADMA2))
42912134a922SPierre Ossman host->flags |= SDHCI_USE_ADMA;
42922134a922SPierre Ossman
42932134a922SPierre Ossman if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) &&
42942134a922SPierre Ossman (host->flags & SDHCI_USE_ADMA)) {
42952134a922SPierre Ossman DBG("Disabling ADMA as it is marked broken\n");
42962134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA;
42972134a922SPierre Ossman }
42982134a922SPierre Ossman
4299685e444bSChunyan Zhang if (sdhci_can_64bit_dma(host))
4300e57a5f61SAdrian Hunter host->flags |= SDHCI_USE_64_BIT_DMA;
4301e57a5f61SAdrian Hunter
430218e762e3SChunyan Zhang if (host->use_external_dma) {
430318e762e3SChunyan Zhang ret = sdhci_external_dma_init(host);
430418e762e3SChunyan Zhang if (ret == -EPROBE_DEFER)
430518e762e3SChunyan Zhang goto unreg;
430618e762e3SChunyan Zhang /*
430718e762e3SChunyan Zhang * Fall back to use the DMA/PIO integrated in standard SDHCI
430818e762e3SChunyan Zhang * instead of external DMA devices.
430918e762e3SChunyan Zhang */
431018e762e3SChunyan Zhang else if (ret)
431118e762e3SChunyan Zhang sdhci_switch_external_dma(host, false);
431218e762e3SChunyan Zhang /* Disable internal DMA sources */
431318e762e3SChunyan Zhang else
431418e762e3SChunyan Zhang host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA);
431518e762e3SChunyan Zhang }
431618e762e3SChunyan Zhang
4317a13abc7bSRichard Röjfors if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
43184ee7dde4SAdrian Hunter if (host->ops->set_dma_mask)
43194ee7dde4SAdrian Hunter ret = host->ops->set_dma_mask(host);
43204ee7dde4SAdrian Hunter else
43217b91369bSAlexandre Courbot ret = sdhci_set_dma_mask(host);
43227b91369bSAlexandre Courbot
43237b91369bSAlexandre Courbot if (!ret && host->ops->enable_dma)
43247b91369bSAlexandre Courbot ret = host->ops->enable_dma(host);
43257b91369bSAlexandre Courbot
43267b91369bSAlexandre Courbot if (ret) {
43276606110dSJoe Perches pr_warn("%s: No suitable DMA available - falling back to PIO\n",
4328b8c86fc5SPierre Ossman mmc_hostname(mmc));
43297b91369bSAlexandre Courbot host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA);
43307b91369bSAlexandre Courbot
43317b91369bSAlexandre Courbot ret = 0;
43321c6a0718SPierre Ossman }
4333b8c86fc5SPierre Ossman }
43341c6a0718SPierre Ossman
4335917a0c52SChunyan Zhang /* SDMA does not support 64-bit DMA if v4 mode not set */
4336917a0c52SChunyan Zhang if ((host->flags & SDHCI_USE_64_BIT_DMA) && !host->v4_mode)
4337e57a5f61SAdrian Hunter host->flags &= ~SDHCI_USE_SDMA;
4338e57a5f61SAdrian Hunter
43392134a922SPierre Ossman if (host->flags & SDHCI_USE_ADMA) {
4340e66e61cbSRussell King dma_addr_t dma;
4341e66e61cbSRussell King void *buf;
4342e66e61cbSRussell King
4343a663f64bSVeerabhadrarao Badiganti if (!(host->flags & SDHCI_USE_64_BIT_DMA))
4344a663f64bSVeerabhadrarao Badiganti host->alloc_desc_sz = SDHCI_ADMA2_32_DESC_SZ;
4345a663f64bSVeerabhadrarao Badiganti else if (!host->alloc_desc_sz)
4346a663f64bSVeerabhadrarao Badiganti host->alloc_desc_sz = SDHCI_ADMA2_64_DESC_SZ(host);
4347a663f64bSVeerabhadrarao Badiganti
4348a663f64bSVeerabhadrarao Badiganti host->desc_sz = host->alloc_desc_sz;
4349a663f64bSVeerabhadrarao Badiganti host->adma_table_sz = host->adma_table_cnt * host->desc_sz;
4350e66e61cbSRussell King
435104a5ae6fSAdrian Hunter host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN;
4352685e444bSChunyan Zhang /*
4353685e444bSChunyan Zhang * Use zalloc to zero the reserved high 32-bits of 128-bit
4354685e444bSChunyan Zhang * descriptors so that they never need to be written.
4355685e444bSChunyan Zhang */
4356750afb08SLuis Chamberlain buf = dma_alloc_coherent(mmc_dev(mmc),
4357750afb08SLuis Chamberlain host->align_buffer_sz + host->adma_table_sz,
4358750afb08SLuis Chamberlain &dma, GFP_KERNEL);
4359e66e61cbSRussell King if (!buf) {
43606606110dSJoe Perches pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n",
43612134a922SPierre Ossman mmc_hostname(mmc));
43622134a922SPierre Ossman host->flags &= ~SDHCI_USE_ADMA;
4363e66e61cbSRussell King } else if ((dma + host->align_buffer_sz) &
4364e66e61cbSRussell King (SDHCI_ADMA2_DESC_ALIGN - 1)) {
43656606110dSJoe Perches pr_warn("%s: unable to allocate aligned ADMA descriptor\n",
4366d1e49f77SRussell King mmc_hostname(mmc));
4367d1e49f77SRussell King host->flags &= ~SDHCI_USE_ADMA;
4368e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz +
4369e66e61cbSRussell King host->adma_table_sz, buf, dma);
4370e66e61cbSRussell King } else {
4371e66e61cbSRussell King host->align_buffer = buf;
4372e66e61cbSRussell King host->align_addr = dma;
4373edd63fccSRussell King
4374e66e61cbSRussell King host->adma_table = buf + host->align_buffer_sz;
4375e66e61cbSRussell King host->adma_addr = dma + host->align_buffer_sz;
4376e66e61cbSRussell King }
43772134a922SPierre Ossman }
43782134a922SPierre Ossman
43797659150cSPierre Ossman /*
43807659150cSPierre Ossman * If we use DMA, then it's up to the caller to set the DMA
43817659150cSPierre Ossman * mask, but PIO does not need the hw shim so we set a new
43827659150cSPierre Ossman * mask here in that case.
43837659150cSPierre Ossman */
4384a13abc7bSRichard Röjfors if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) {
43857659150cSPierre Ossman host->dma_mask = DMA_BIT_MASK(64);
43864e743f1fSMarkus Mayer mmc_dev(mmc)->dma_mask = &host->dma_mask;
43877659150cSPierre Ossman }
43881c6a0718SPierre Ossman
4389c4687d5fSZhangfei Gao if (host->version >= SDHCI_SPEC_300)
4390a8e809ecSMasahiro Yamada host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps);
4391c4687d5fSZhangfei Gao else
4392a8e809ecSMasahiro Yamada host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps);
4393c4687d5fSZhangfei Gao
43944240ff0aSBen Dooks host->max_clk *= 1000000;
4395f27f47efSAnton Vorontsov if (host->max_clk == 0 || host->quirks &
4396f27f47efSAnton Vorontsov SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) {
43974240ff0aSBen Dooks if (!host->ops->get_max_clock) {
43982e4456f0SMarek Vasut pr_err("%s: Hardware doesn't specify base clock frequency.\n",
43992e4456f0SMarek Vasut mmc_hostname(mmc));
4400eb5c20deSAdrian Hunter ret = -ENODEV;
4401eb5c20deSAdrian Hunter goto undma;
44021c6a0718SPierre Ossman }
44034240ff0aSBen Dooks host->max_clk = host->ops->get_max_clock(host);
44044240ff0aSBen Dooks }
44051c6a0718SPierre Ossman
44061c6a0718SPierre Ossman /*
4407c3ed3877SArindam Nath * In case of Host Controller v3.00, find out whether clock
4408c3ed3877SArindam Nath * multiplier is supported.
4409c3ed3877SArindam Nath */
4410a8e809ecSMasahiro Yamada host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1);
4411c3ed3877SArindam Nath
4412c3ed3877SArindam Nath /*
4413c3ed3877SArindam Nath * In case the value in Clock Multiplier is 0, then programmable
4414c3ed3877SArindam Nath * clock mode is not supported, otherwise the actual clock
4415c3ed3877SArindam Nath * multiplier is one more than the value of Clock Multiplier
4416c3ed3877SArindam Nath * in the Capabilities Register.
4417c3ed3877SArindam Nath */
4418c3ed3877SArindam Nath if (host->clk_mul)
4419c3ed3877SArindam Nath host->clk_mul += 1;
4420c3ed3877SArindam Nath
4421c3ed3877SArindam Nath /*
44221c6a0718SPierre Ossman * Set host parameters.
44231c6a0718SPierre Ossman */
442459241757SDong Aisheng max_clk = host->max_clk;
442559241757SDong Aisheng
4426ce5f036bSMarek Szyprowski if (host->ops->get_min_clock)
4427a9e58f25SAnton Vorontsov mmc->f_min = host->ops->get_min_clock(host);
4428c3ed3877SArindam Nath else if (host->version >= SDHCI_SPEC_300) {
44292a187d03SMichał Mirosław if (host->clk_mul)
443059241757SDong Aisheng max_clk = host->max_clk * host->clk_mul;
44312a187d03SMichał Mirosław /*
44322a187d03SMichał Mirosław * Divided Clock Mode minimum clock rate is always less than
44332a187d03SMichał Mirosław * Programmable Clock Mode minimum clock rate.
44342a187d03SMichał Mirosław */
44350397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
4436c3ed3877SArindam Nath } else
44370397526dSZhangfei Gao mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
443815ec4461SPhilip Rakity
4439d310ae49SAdrian Hunter if (!mmc->f_max || mmc->f_max > max_clk)
444059241757SDong Aisheng mmc->f_max = max_clk;
444159241757SDong Aisheng
444228aab053SAisheng Dong if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
4443a8e809ecSMasahiro Yamada host->timeout_clk = FIELD_GET(SDHCI_TIMEOUT_CLK_MASK, host->caps);
44448cc35289SShawn Lin
44458cc35289SShawn Lin if (host->caps & SDHCI_TIMEOUT_CLK_UNIT)
44468cc35289SShawn Lin host->timeout_clk *= 1000;
44478cc35289SShawn Lin
4448272308caSAndy Shevchenko if (host->timeout_clk == 0) {
44498cc35289SShawn Lin if (!host->ops->get_timeout_clock) {
445028aab053SAisheng Dong pr_err("%s: Hardware doesn't specify timeout clock frequency.\n",
445128aab053SAisheng Dong mmc_hostname(mmc));
4452eb5c20deSAdrian Hunter ret = -ENODEV;
4453eb5c20deSAdrian Hunter goto undma;
4454272308caSAndy Shevchenko }
445528aab053SAisheng Dong
44568cc35289SShawn Lin host->timeout_clk =
44578cc35289SShawn Lin DIV_ROUND_UP(host->ops->get_timeout_clock(host),
44588cc35289SShawn Lin 1000);
44598cc35289SShawn Lin }
4460272308caSAndy Shevchenko
446199513624SAdrian Hunter if (override_timeout_clk)
446299513624SAdrian Hunter host->timeout_clk = override_timeout_clk;
446399513624SAdrian Hunter
4464a6ff5aebSAisheng Dong mmc->max_busy_timeout = host->ops->get_max_timeout_count ?
4465a6ff5aebSAisheng Dong host->ops->get_max_timeout_count(host) : 1 << 27;
4466a6ff5aebSAisheng Dong mmc->max_busy_timeout /= host->timeout_clk;
446728aab053SAisheng Dong }
446858d1246dSAdrian Hunter
4469a999fd93SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT &&
4470a999fd93SAdrian Hunter !host->ops->get_max_timeout_count)
4471a999fd93SAdrian Hunter mmc->max_busy_timeout = 0;
4472a999fd93SAdrian Hunter
44731be64c79SUlf Hansson mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_CMD23;
4474781e989cSRussell King mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
4475e89d456fSAndrei Warkentin
4476e89d456fSAndrei Warkentin if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
4477e89d456fSAndrei Warkentin host->flags |= SDHCI_AUTO_CMD12;
44785fe23c7fSAnton Vorontsov
44797ed71a9dSChunyan Zhang /*
44807ed71a9dSChunyan Zhang * For v3 mode, Auto-CMD23 stuff only works in ADMA or PIO.
44817ed71a9dSChunyan Zhang * For v4 mode, SDMA may use Auto-CMD23 as well.
44827ed71a9dSChunyan Zhang */
44834f3d3e9bSAndrei Warkentin if ((host->version >= SDHCI_SPEC_300) &&
44848edf6371SAndrei Warkentin ((host->flags & SDHCI_USE_ADMA) ||
44857ed71a9dSChunyan Zhang !(host->flags & SDHCI_USE_SDMA) || host->v4_mode) &&
44863bfa6f03SScott Branden !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN)) {
44878edf6371SAndrei Warkentin host->flags |= SDHCI_AUTO_CMD23;
4488f421865dSAdrian Hunter DBG("Auto-CMD23 available\n");
44898edf6371SAndrei Warkentin } else {
4490f421865dSAdrian Hunter DBG("Auto-CMD23 unavailable\n");
44918edf6371SAndrei Warkentin }
44928edf6371SAndrei Warkentin
449315ec4461SPhilip Rakity /*
449415ec4461SPhilip Rakity * A controller may support 8-bit width, but the board itself
449515ec4461SPhilip Rakity * might not have the pins brought out. Boards that support
449615ec4461SPhilip Rakity * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in
449715ec4461SPhilip Rakity * their platform code before calling sdhci_add_host(), and we
449815ec4461SPhilip Rakity * won't assume 8-bit width for hosts without that CAP.
449915ec4461SPhilip Rakity */
45005fe23c7fSAnton Vorontsov if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
450115ec4461SPhilip Rakity mmc->caps |= MMC_CAP_4_BIT_DATA;
45021c6a0718SPierre Ossman
450363ef5d8cSJerry Huang if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
450463ef5d8cSJerry Huang mmc->caps &= ~MMC_CAP_CMD23;
450563ef5d8cSJerry Huang
450628da3589SAdrian Hunter if (host->caps & SDHCI_CAN_DO_HISPD)
4507a29e7e18SZhangfei Gao mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
45081c6a0718SPierre Ossman
4509176d1ed4SJaehoon Chung if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
4510860951c5SJaehoon Chung mmc_card_is_removable(mmc) &&
4511d2f025b0SJisheng Zhang mmc_gpio_get_cd(mmc) < 0)
451268d1fb7eSAnton Vorontsov mmc->caps |= MMC_CAP_NEEDS_POLL;
451368d1fb7eSAnton Vorontsov
45143a48edc4STim Kryger if (!IS_ERR(mmc->supply.vqmmc)) {
45150fcb031eSVijay Viswanath if (enable_vqmmc) {
45163a48edc4STim Kryger ret = regulator_enable(mmc->supply.vqmmc);
45170fcb031eSVijay Viswanath host->sdhci_core_to_disable_vqmmc = !ret;
45180fcb031eSVijay Viswanath }
45191b5190c2SStefan Agner
45201b5190c2SStefan Agner /* If vqmmc provides no 1.8V signalling, then there's no UHS */
45213a48edc4STim Kryger if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
4522cec2e216SKevin Liu 1950000))
452328da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
45248363c374SKevin Liu SDHCI_SUPPORT_SDR50 |
45256231f3deSPhilip Rakity SDHCI_SUPPORT_DDR50);
45261b5190c2SStefan Agner
45271b5190c2SStefan Agner /* In eMMC case vqmmc might be a fixed 1.8V regulator */
45281b5190c2SStefan Agner if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000,
45291b5190c2SStefan Agner 3600000))
45301b5190c2SStefan Agner host->flags &= ~SDHCI_SIGNALING_330;
45311b5190c2SStefan Agner
4532a3361abaSChris Ball if (ret) {
4533a3361abaSChris Ball pr_warn("%s: Failed to enable vqmmc regulator: %d\n",
4534a3361abaSChris Ball mmc_hostname(mmc), ret);
45354bb74313SAdrian Hunter mmc->supply.vqmmc = ERR_PTR(-EINVAL);
4536a3361abaSChris Ball }
45373debc24fSVeerabhadrarao Badiganti
45388363c374SKevin Liu }
45396231f3deSPhilip Rakity
454028da3589SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) {
454128da3589SAdrian Hunter host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
45426a66180aSDaniel Drake SDHCI_SUPPORT_DDR50);
4543c16bc9a7SKishon Vijay Abraham I /*
4544c16bc9a7SKishon Vijay Abraham I * The SDHCI controller in a SoC might support HS200/HS400
4545c16bc9a7SKishon Vijay Abraham I * (indicated using mmc-hs200-1_8v/mmc-hs400-1_8v dt property),
4546c16bc9a7SKishon Vijay Abraham I * but if the board is modeled such that the IO lines are not
4547c16bc9a7SKishon Vijay Abraham I * connected to 1.8v then HS200/HS400 cannot be supported.
4548c16bc9a7SKishon Vijay Abraham I * Disable HS200/HS400 if the board does not have 1.8v connected
4549c16bc9a7SKishon Vijay Abraham I * to the IO lines. (Applicable for other modes in 1.8v)
4550c16bc9a7SKishon Vijay Abraham I */
4551c16bc9a7SKishon Vijay Abraham I mmc->caps2 &= ~(MMC_CAP2_HSX00_1_8V | MMC_CAP2_HS400_ES);
4552c16bc9a7SKishon Vijay Abraham I mmc->caps &= ~(MMC_CAP_1_8V_DDR | MMC_CAP_UHS);
455328da3589SAdrian Hunter }
45546a66180aSDaniel Drake
45554188bba0SAl Cooper /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
455628da3589SAdrian Hunter if (host->caps1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
45574188bba0SAl Cooper SDHCI_SUPPORT_DDR50))
4558f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25;
4559f2119df6SArindam Nath
4560f2119df6SArindam Nath /* SDR104 supports also implies SDR50 support */
456128da3589SAdrian Hunter if (host->caps1 & SDHCI_SUPPORT_SDR104) {
4562f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50;
4563156e14b1SGiuseppe CAVALLARO /* SD3.0: SDR104 is supported so (for eMMC) the caps2
4564156e14b1SGiuseppe CAVALLARO * field can be promoted to support HS200.
4565156e14b1SGiuseppe CAVALLARO */
4566549c0b18SAdrian Hunter if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200))
4567156e14b1SGiuseppe CAVALLARO mmc->caps2 |= MMC_CAP2_HS200;
456828da3589SAdrian Hunter } else if (host->caps1 & SDHCI_SUPPORT_SDR50) {
4569f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_SDR50;
457028da3589SAdrian Hunter }
4571f2119df6SArindam Nath
4572e9fb05d5SAdrian Hunter if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 &&
457328da3589SAdrian Hunter (host->caps1 & SDHCI_SUPPORT_HS400))
4574e9fb05d5SAdrian Hunter mmc->caps2 |= MMC_CAP2_HS400;
4575e9fb05d5SAdrian Hunter
4576549c0b18SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) &&
4577549c0b18SAdrian Hunter (IS_ERR(mmc->supply.vqmmc) ||
4578549c0b18SAdrian Hunter !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000,
4579549c0b18SAdrian Hunter 1300000)))
4580549c0b18SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V;
4581549c0b18SAdrian Hunter
458228da3589SAdrian Hunter if ((host->caps1 & SDHCI_SUPPORT_DDR50) &&
45839107ebbfSMicky Ching !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50))
4584f2119df6SArindam Nath mmc->caps |= MMC_CAP_UHS_DDR50;
4585f2119df6SArindam Nath
4586069c9f14SGirish K S /* Does the host need tuning for SDR50? */
458728da3589SAdrian Hunter if (host->caps1 & SDHCI_USE_SDR50_TUNING)
4588b513ea25SArindam Nath host->flags |= SDHCI_SDR50_NEEDS_TUNING;
4589b513ea25SArindam Nath
4590d6d50a15SArindam Nath /* Driver Type(s) (A, C, D) supported by the host */
459128da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_A)
4592d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
459328da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_C)
4594d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_C;
459528da3589SAdrian Hunter if (host->caps1 & SDHCI_DRIVER_TYPE_D)
4596d6d50a15SArindam Nath mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
4597d6d50a15SArindam Nath
4598cf2b5eeaSArindam Nath /* Initial value for re-tuning timer count */
4599a8e809ecSMasahiro Yamada host->tuning_count = FIELD_GET(SDHCI_RETUNING_TIMER_COUNT_MASK,
4600a8e809ecSMasahiro Yamada host->caps1);
4601cf2b5eeaSArindam Nath
4602cf2b5eeaSArindam Nath /*
4603cf2b5eeaSArindam Nath * In case Re-tuning Timer is not disabled, the actual value of
4604cf2b5eeaSArindam Nath * re-tuning timer will be 2 ^ (n - 1).
4605cf2b5eeaSArindam Nath */
4606cf2b5eeaSArindam Nath if (host->tuning_count)
4607cf2b5eeaSArindam Nath host->tuning_count = 1 << (host->tuning_count - 1);
4608cf2b5eeaSArindam Nath
4609cf2b5eeaSArindam Nath /* Re-tuning mode supported by the Host Controller */
4610a8e809ecSMasahiro Yamada host->tuning_mode = FIELD_GET(SDHCI_RETUNING_MODE_MASK, host->caps1);
4611cf2b5eeaSArindam Nath
46128f230f45STakashi Iwai ocr_avail = 0;
4613bad37e1aSPhilip Rakity
4614f2119df6SArindam Nath /*
4615f2119df6SArindam Nath * According to SD Host Controller spec v3.00, if the Host System
4616f2119df6SArindam Nath * can afford more than 150mA, Host Driver should set XPC to 1. Also
4617f2119df6SArindam Nath * the value is meaningful only if Voltage Support in the Capabilities
4618f2119df6SArindam Nath * register is set. The actual current value is 4 times the register
4619f2119df6SArindam Nath * value.
4620f2119df6SArindam Nath */
4621f2119df6SArindam Nath max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
46223a48edc4STim Kryger if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) {
4623ae906037SChuanxiao.Dong int curr = regulator_get_current_limit(mmc->supply.vmmc);
4624bad37e1aSPhilip Rakity if (curr > 0) {
4625bad37e1aSPhilip Rakity
4626bad37e1aSPhilip Rakity /* convert to SDHCI_MAX_CURRENT format */
4627bad37e1aSPhilip Rakity curr = curr/1000; /* convert to mA */
4628bad37e1aSPhilip Rakity curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER;
4629bad37e1aSPhilip Rakity
4630bad37e1aSPhilip Rakity curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT);
4631bad37e1aSPhilip Rakity max_current_caps =
4632804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, curr) |
4633804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, curr) |
4634804a65b3SMasahiro Yamada FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, curr);
4635bad37e1aSPhilip Rakity }
4636bad37e1aSPhilip Rakity }
4637f2119df6SArindam Nath
463828da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_330) {
46398f230f45STakashi Iwai ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
4640f2119df6SArindam Nath
4641804a65b3SMasahiro Yamada mmc->max_current_330 = FIELD_GET(SDHCI_MAX_CURRENT_330_MASK,
4642804a65b3SMasahiro Yamada max_current_caps) *
4643f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER;
4644f2119df6SArindam Nath }
464528da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_300) {
46468f230f45STakashi Iwai ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
4647f2119df6SArindam Nath
4648804a65b3SMasahiro Yamada mmc->max_current_300 = FIELD_GET(SDHCI_MAX_CURRENT_300_MASK,
4649804a65b3SMasahiro Yamada max_current_caps) *
4650f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER;
4651f2119df6SArindam Nath }
465228da3589SAdrian Hunter if (host->caps & SDHCI_CAN_VDD_180) {
46538f230f45STakashi Iwai ocr_avail |= MMC_VDD_165_195;
46548f230f45STakashi Iwai
4655804a65b3SMasahiro Yamada mmc->max_current_180 = FIELD_GET(SDHCI_MAX_CURRENT_180_MASK,
4656804a65b3SMasahiro Yamada max_current_caps) *
4657f2119df6SArindam Nath SDHCI_MAX_CURRENT_MULTIPLIER;
4658f2119df6SArindam Nath }
4659f2119df6SArindam Nath
46605fd26c7eSUlf Hansson /* If OCR set by host, use it instead. */
46615fd26c7eSUlf Hansson if (host->ocr_mask)
46625fd26c7eSUlf Hansson ocr_avail = host->ocr_mask;
46635fd26c7eSUlf Hansson
46645fd26c7eSUlf Hansson /* If OCR set by external regulators, give it highest prio. */
46653a48edc4STim Kryger if (mmc->ocr_avail)
466652221610STim Kryger ocr_avail = mmc->ocr_avail;
46673a48edc4STim Kryger
46688f230f45STakashi Iwai mmc->ocr_avail = ocr_avail;
46698f230f45STakashi Iwai mmc->ocr_avail_sdio = ocr_avail;
46708f230f45STakashi Iwai if (host->ocr_avail_sdio)
46718f230f45STakashi Iwai mmc->ocr_avail_sdio &= host->ocr_avail_sdio;
46728f230f45STakashi Iwai mmc->ocr_avail_sd = ocr_avail;
46738f230f45STakashi Iwai if (host->ocr_avail_sd)
46748f230f45STakashi Iwai mmc->ocr_avail_sd &= host->ocr_avail_sd;
46758f230f45STakashi Iwai else /* normal SD controllers don't support 1.8V */
46768f230f45STakashi Iwai mmc->ocr_avail_sd &= ~MMC_VDD_165_195;
46778f230f45STakashi Iwai mmc->ocr_avail_mmc = ocr_avail;
46788f230f45STakashi Iwai if (host->ocr_avail_mmc)
46798f230f45STakashi Iwai mmc->ocr_avail_mmc &= host->ocr_avail_mmc;
46801c6a0718SPierre Ossman
46811c6a0718SPierre Ossman if (mmc->ocr_avail == 0) {
46822e4456f0SMarek Vasut pr_err("%s: Hardware doesn't report any support voltages.\n",
46832e4456f0SMarek Vasut mmc_hostname(mmc));
4684eb5c20deSAdrian Hunter ret = -ENODEV;
4685eb5c20deSAdrian Hunter goto unreg;
46861c6a0718SPierre Ossman }
46871c6a0718SPierre Ossman
46888cb851a4SAdrian Hunter if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
46898cb851a4SAdrian Hunter MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 |
46908cb851a4SAdrian Hunter MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) ||
46918cb851a4SAdrian Hunter (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V)))
46928cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_180;
46938cb851a4SAdrian Hunter
46948cb851a4SAdrian Hunter if (mmc->caps2 & MMC_CAP2_HSX00_1_2V)
46958cb851a4SAdrian Hunter host->flags |= SDHCI_SIGNALING_120;
46968cb851a4SAdrian Hunter
46971c6a0718SPierre Ossman spin_lock_init(&host->lock);
46981c6a0718SPierre Ossman
46991c6a0718SPierre Ossman /*
4700ac00531dSAdrian Hunter * Maximum number of sectors in one transfer. Limited by SDMA boundary
4701ac00531dSAdrian Hunter * size (512KiB). Note some tuning modes impose a 4MiB limit, but this
4702ac00531dSAdrian Hunter * is less anyway.
47031c6a0718SPierre Ossman */
47041c6a0718SPierre Ossman mmc->max_req_size = 524288;
47051c6a0718SPierre Ossman
47061c6a0718SPierre Ossman /*
4707250dcd11SUlf Hansson * Maximum number of segments. Depends on if the hardware
4708250dcd11SUlf Hansson * can do scatter/gather or not.
4709250dcd11SUlf Hansson */
4710250dcd11SUlf Hansson if (host->flags & SDHCI_USE_ADMA) {
4711250dcd11SUlf Hansson mmc->max_segs = SDHCI_MAX_SEGS;
4712250dcd11SUlf Hansson } else if (host->flags & SDHCI_USE_SDMA) {
4713250dcd11SUlf Hansson mmc->max_segs = 1;
471466e8d3b8SChristoph Hellwig mmc->max_req_size = min_t(size_t, mmc->max_req_size,
471566e8d3b8SChristoph Hellwig dma_max_mapping_size(mmc_dev(mmc)));
4716250dcd11SUlf Hansson } else { /* PIO */
4717250dcd11SUlf Hansson mmc->max_segs = SDHCI_MAX_SEGS;
4718250dcd11SUlf Hansson }
4719250dcd11SUlf Hansson
4720250dcd11SUlf Hansson /*
47211c6a0718SPierre Ossman * Maximum segment size. Could be one segment with the maximum number
47222134a922SPierre Ossman * of bytes. When doing hardware scatter/gather, each entry cannot
47232134a922SPierre Ossman * be larger than 64 KiB though.
47241c6a0718SPierre Ossman */
472530652aa3SOlof Johansson if (host->flags & SDHCI_USE_ADMA) {
47263d7c194bSAdrian Hunter if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) {
47273d7c194bSAdrian Hunter host->max_adma = 65532; /* 32-bit alignment */
472830652aa3SOlof Johansson mmc->max_seg_size = 65535;
47293d7c194bSAdrian Hunter } else {
473030652aa3SOlof Johansson mmc->max_seg_size = 65536;
47313d7c194bSAdrian Hunter }
473230652aa3SOlof Johansson } else {
47331c6a0718SPierre Ossman mmc->max_seg_size = mmc->max_req_size;
473430652aa3SOlof Johansson }
47351c6a0718SPierre Ossman
47361c6a0718SPierre Ossman /*
47371c6a0718SPierre Ossman * Maximum block size. This varies from controller to controller and
47381c6a0718SPierre Ossman * is specified in the capabilities register.
47391c6a0718SPierre Ossman */
47400633f654SAnton Vorontsov if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) {
47410633f654SAnton Vorontsov mmc->max_blk_size = 2;
47420633f654SAnton Vorontsov } else {
474328da3589SAdrian Hunter mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >>
47440633f654SAnton Vorontsov SDHCI_MAX_BLOCK_SHIFT;
47451c6a0718SPierre Ossman if (mmc->max_blk_size >= 3) {
47466606110dSJoe Perches pr_warn("%s: Invalid maximum block size, assuming 512 bytes\n",
47476606110dSJoe Perches mmc_hostname(mmc));
47480633f654SAnton Vorontsov mmc->max_blk_size = 0;
47490633f654SAnton Vorontsov }
47500633f654SAnton Vorontsov }
47510633f654SAnton Vorontsov
47521c6a0718SPierre Ossman mmc->max_blk_size = 512 << mmc->max_blk_size;
47531c6a0718SPierre Ossman
47541c6a0718SPierre Ossman /*
47551c6a0718SPierre Ossman * Maximum block count.
47561c6a0718SPierre Ossman */
47571388eefdSBen Dooks mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
47581c6a0718SPierre Ossman
4759a68dd9a0SChunyan Zhang if (mmc->max_segs == 1)
4760bd9b9027SLinus Walleij /* This may alter mmc->*_blk_* parameters */
4761a68dd9a0SChunyan Zhang sdhci_allocate_bounce_buffer(host);
4762bd9b9027SLinus Walleij
476352f5336dSAdrian Hunter return 0;
476452f5336dSAdrian Hunter
476552f5336dSAdrian Hunter unreg:
47660fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc)
476752f5336dSAdrian Hunter regulator_disable(mmc->supply.vqmmc);
476852f5336dSAdrian Hunter undma:
476952f5336dSAdrian Hunter if (host->align_buffer)
477052f5336dSAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz +
477152f5336dSAdrian Hunter host->adma_table_sz, host->align_buffer,
477252f5336dSAdrian Hunter host->align_addr);
477352f5336dSAdrian Hunter host->adma_table = NULL;
477452f5336dSAdrian Hunter host->align_buffer = NULL;
477552f5336dSAdrian Hunter
477652f5336dSAdrian Hunter return ret;
477752f5336dSAdrian Hunter }
477852f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_setup_host);
477952f5336dSAdrian Hunter
sdhci_cleanup_host(struct sdhci_host * host)47804180ffa8SAdrian Hunter void sdhci_cleanup_host(struct sdhci_host *host)
47814180ffa8SAdrian Hunter {
47824180ffa8SAdrian Hunter struct mmc_host *mmc = host->mmc;
47834180ffa8SAdrian Hunter
47840fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc)
47854180ffa8SAdrian Hunter regulator_disable(mmc->supply.vqmmc);
47864180ffa8SAdrian Hunter
47874180ffa8SAdrian Hunter if (host->align_buffer)
47884180ffa8SAdrian Hunter dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz +
47894180ffa8SAdrian Hunter host->adma_table_sz, host->align_buffer,
47904180ffa8SAdrian Hunter host->align_addr);
479118e762e3SChunyan Zhang
479218e762e3SChunyan Zhang if (host->use_external_dma)
479318e762e3SChunyan Zhang sdhci_external_dma_release(host);
479418e762e3SChunyan Zhang
47954180ffa8SAdrian Hunter host->adma_table = NULL;
47964180ffa8SAdrian Hunter host->align_buffer = NULL;
47974180ffa8SAdrian Hunter }
47984180ffa8SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cleanup_host);
47994180ffa8SAdrian Hunter
__sdhci_add_host(struct sdhci_host * host)480052f5336dSAdrian Hunter int __sdhci_add_host(struct sdhci_host *host)
480152f5336dSAdrian Hunter {
4802c07a48c2SAdrian Hunter unsigned int flags = WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI;
480352f5336dSAdrian Hunter struct mmc_host *mmc = host->mmc;
480452f5336dSAdrian Hunter int ret;
480552f5336dSAdrian Hunter
48062b17b8d7SAdrian Hunter if ((mmc->caps2 & MMC_CAP2_CQE) &&
48072b17b8d7SAdrian Hunter (host->quirks & SDHCI_QUIRK_BROKEN_CQE)) {
48082b17b8d7SAdrian Hunter mmc->caps2 &= ~MMC_CAP2_CQE;
48092b17b8d7SAdrian Hunter mmc->cqe_ops = NULL;
48102b17b8d7SAdrian Hunter }
48112b17b8d7SAdrian Hunter
4812c07a48c2SAdrian Hunter host->complete_wq = alloc_workqueue("sdhci", flags, 0);
4813c07a48c2SAdrian Hunter if (!host->complete_wq)
4814c07a48c2SAdrian Hunter return -ENOMEM;
4815c07a48c2SAdrian Hunter
4816c07a48c2SAdrian Hunter INIT_WORK(&host->complete_work, sdhci_complete_work);
48171c6a0718SPierre Ossman
48182ee4f620SKees Cook timer_setup(&host->timer, sdhci_timeout_timer, 0);
48192ee4f620SKees Cook timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0);
48201c6a0718SPierre Ossman
4821b513ea25SArindam Nath init_waitqueue_head(&host->buf_ready_int);
4822b513ea25SArindam Nath
48232af502caSShawn Guo sdhci_init(host, 0);
48242af502caSShawn Guo
4825781e989cSRussell King ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
4826781e989cSRussell King IRQF_SHARED, mmc_hostname(mmc), host);
48270fc81ee3SMark Brown if (ret) {
48280fc81ee3SMark Brown pr_err("%s: Failed to request IRQ %d: %d\n",
48290fc81ee3SMark Brown mmc_hostname(mmc), host->irq, ret);
4830c07a48c2SAdrian Hunter goto unwq;
48310fc81ee3SMark Brown }
48321c6a0718SPierre Ossman
4833061d17a6SAdrian Hunter ret = sdhci_led_register(host);
48340fc81ee3SMark Brown if (ret) {
48350fc81ee3SMark Brown pr_err("%s: Failed to register LED device: %d\n",
48360fc81ee3SMark Brown mmc_hostname(mmc), ret);
4837eb5c20deSAdrian Hunter goto unirq;
48380fc81ee3SMark Brown }
48392f730fecSPierre Ossman
4840eb5c20deSAdrian Hunter ret = mmc_add_host(mmc);
4841eb5c20deSAdrian Hunter if (ret)
4842eb5c20deSAdrian Hunter goto unled;
48431c6a0718SPierre Ossman
4844a3c76eb9SGirish K S pr_info("%s: SDHCI controller on %s [%s] using %s\n",
4845d1b26863SKay Sievers mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
484618e762e3SChunyan Zhang host->use_external_dma ? "External DMA" :
4847e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_ADMA) ?
4848e57a5f61SAdrian Hunter (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" :
4849a13abc7bSRichard Röjfors (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
48501c6a0718SPierre Ossman
48517260cf5eSAnton Vorontsov sdhci_enable_card_detection(host);
48527260cf5eSAnton Vorontsov
48531c6a0718SPierre Ossman return 0;
48541c6a0718SPierre Ossman
4855eb5c20deSAdrian Hunter unled:
4856061d17a6SAdrian Hunter sdhci_led_unregister(host);
4857eb5c20deSAdrian Hunter unirq:
4858aa990722SAdrian Hunter sdhci_reset_for_all(host);
4859b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE);
4860b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
48612f730fecSPierre Ossman free_irq(host->irq, host);
4862c07a48c2SAdrian Hunter unwq:
4863c07a48c2SAdrian Hunter destroy_workqueue(host->complete_wq);
486452f5336dSAdrian Hunter
48651c6a0718SPierre Ossman return ret;
48661c6a0718SPierre Ossman }
486752f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_add_host);
48681c6a0718SPierre Ossman
sdhci_add_host(struct sdhci_host * host)486952f5336dSAdrian Hunter int sdhci_add_host(struct sdhci_host *host)
487052f5336dSAdrian Hunter {
487152f5336dSAdrian Hunter int ret;
487252f5336dSAdrian Hunter
487352f5336dSAdrian Hunter ret = sdhci_setup_host(host);
487452f5336dSAdrian Hunter if (ret)
487552f5336dSAdrian Hunter return ret;
487652f5336dSAdrian Hunter
48774180ffa8SAdrian Hunter ret = __sdhci_add_host(host);
48784180ffa8SAdrian Hunter if (ret)
48794180ffa8SAdrian Hunter goto cleanup;
48804180ffa8SAdrian Hunter
48814180ffa8SAdrian Hunter return 0;
48824180ffa8SAdrian Hunter
48834180ffa8SAdrian Hunter cleanup:
48844180ffa8SAdrian Hunter sdhci_cleanup_host(host);
48854180ffa8SAdrian Hunter
48864180ffa8SAdrian Hunter return ret;
488752f5336dSAdrian Hunter }
4888b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_add_host);
4889b8c86fc5SPierre Ossman
sdhci_remove_host(struct sdhci_host * host,int dead)48901e72859eSPierre Ossman void sdhci_remove_host(struct sdhci_host *host, int dead)
48911c6a0718SPierre Ossman {
48923a48edc4STim Kryger struct mmc_host *mmc = host->mmc;
48931e72859eSPierre Ossman unsigned long flags;
48941e72859eSPierre Ossman
48951e72859eSPierre Ossman if (dead) {
48961e72859eSPierre Ossman spin_lock_irqsave(&host->lock, flags);
48971e72859eSPierre Ossman
48981e72859eSPierre Ossman host->flags |= SDHCI_DEVICE_DEAD;
48991e72859eSPierre Ossman
49005d0d11c5SAdrian Hunter if (sdhci_has_requests(host)) {
4901a3c76eb9SGirish K S pr_err("%s: Controller removed during "
49024e743f1fSMarkus Mayer " transfer!\n", mmc_hostname(mmc));
49035d0d11c5SAdrian Hunter sdhci_error_out_mrqs(host, -ENOMEDIUM);
49041e72859eSPierre Ossman }
49051e72859eSPierre Ossman
49061e72859eSPierre Ossman spin_unlock_irqrestore(&host->lock, flags);
49071e72859eSPierre Ossman }
49081e72859eSPierre Ossman
49097260cf5eSAnton Vorontsov sdhci_disable_card_detection(host);
49107260cf5eSAnton Vorontsov
49114e743f1fSMarkus Mayer mmc_remove_host(mmc);
49121c6a0718SPierre Ossman
4913061d17a6SAdrian Hunter sdhci_led_unregister(host);
49142f730fecSPierre Ossman
49151e72859eSPierre Ossman if (!dead)
4916aa990722SAdrian Hunter sdhci_reset_for_all(host);
49171c6a0718SPierre Ossman
4918b537f94cSRussell King sdhci_writel(host, 0, SDHCI_INT_ENABLE);
4919b537f94cSRussell King sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
49201c6a0718SPierre Ossman free_irq(host->irq, host);
49211c6a0718SPierre Ossman
49221c6a0718SPierre Ossman del_timer_sync(&host->timer);
4923d7422fb4SAdrian Hunter del_timer_sync(&host->data_timer);
49241c6a0718SPierre Ossman
4925c07a48c2SAdrian Hunter destroy_workqueue(host->complete_wq);
49262134a922SPierre Ossman
49270fcb031eSVijay Viswanath if (host->sdhci_core_to_disable_vqmmc)
49283a48edc4STim Kryger regulator_disable(mmc->supply.vqmmc);
49296231f3deSPhilip Rakity
4930edd63fccSRussell King if (host->align_buffer)
4931e66e61cbSRussell King dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz +
4932e66e61cbSRussell King host->adma_table_sz, host->align_buffer,
4933e66e61cbSRussell King host->align_addr);
49342134a922SPierre Ossman
493518e762e3SChunyan Zhang if (host->use_external_dma)
493618e762e3SChunyan Zhang sdhci_external_dma_release(host);
493718e762e3SChunyan Zhang
49384efaa6fbSAdrian Hunter host->adma_table = NULL;
49392134a922SPierre Ossman host->align_buffer = NULL;
49401c6a0718SPierre Ossman }
49411c6a0718SPierre Ossman
4942b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_remove_host);
4943b8c86fc5SPierre Ossman
sdhci_free_host(struct sdhci_host * host)4944b8c86fc5SPierre Ossman void sdhci_free_host(struct sdhci_host *host)
49451c6a0718SPierre Ossman {
4946b8c86fc5SPierre Ossman mmc_free_host(host->mmc);
49471c6a0718SPierre Ossman }
49481c6a0718SPierre Ossman
4949b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_free_host);
49501c6a0718SPierre Ossman
49511c6a0718SPierre Ossman /*****************************************************************************\
49521c6a0718SPierre Ossman * *
49531c6a0718SPierre Ossman * Driver init/exit *
49541c6a0718SPierre Ossman * *
49551c6a0718SPierre Ossman \*****************************************************************************/
49561c6a0718SPierre Ossman
sdhci_drv_init(void)49571c6a0718SPierre Ossman static int __init sdhci_drv_init(void)
49581c6a0718SPierre Ossman {
4959a3c76eb9SGirish K S pr_info(DRIVER_NAME
49601c6a0718SPierre Ossman ": Secure Digital Host Controller Interface driver\n");
4961a3c76eb9SGirish K S pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
49621c6a0718SPierre Ossman
4963b8c86fc5SPierre Ossman return 0;
49641c6a0718SPierre Ossman }
49651c6a0718SPierre Ossman
sdhci_drv_exit(void)49661c6a0718SPierre Ossman static void __exit sdhci_drv_exit(void)
49671c6a0718SPierre Ossman {
49681c6a0718SPierre Ossman }
49691c6a0718SPierre Ossman
49701c6a0718SPierre Ossman module_init(sdhci_drv_init);
49711c6a0718SPierre Ossman module_exit(sdhci_drv_exit);
49721c6a0718SPierre Ossman
49731c6a0718SPierre Ossman module_param(debug_quirks, uint, 0444);
497466fd8ad5SAdrian Hunter module_param(debug_quirks2, uint, 0444);
49751c6a0718SPierre Ossman
497632710e8fSPierre Ossman MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
4977b8c86fc5SPierre Ossman MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver");
49781c6a0718SPierre Ossman MODULE_LICENSE("GPL");
49791c6a0718SPierre Ossman
49801c6a0718SPierre Ossman MODULE_PARM_DESC(debug_quirks, "Force certain quirks.");
498166fd8ad5SAdrian Hunter MODULE_PARM_DESC(debug_quirks2, "Force certain other quirks.");
4982