xref: /openbmc/linux/drivers/mmc/host/sdhci.c (revision d9ae0aa8)
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 {
25181c6a0718SPierre Ossman 	unsigned long flags;
25192dfb579cSWolfram Sang 	int is_readonly;
25201c6a0718SPierre Ossman 
25211c6a0718SPierre Ossman 	spin_lock_irqsave(&host->lock, flags);
25221c6a0718SPierre Ossman 
25231e72859eSPierre Ossman 	if (host->flags & SDHCI_DEVICE_DEAD)
25242dfb579cSWolfram Sang 		is_readonly = 0;
25252dfb579cSWolfram Sang 	else if (host->ops->get_ro)
25262dfb579cSWolfram Sang 		is_readonly = host->ops->get_ro(host);
25276d5cd068SThomas Petazzoni 	else if (mmc_can_gpio_ro(host->mmc))
25286d5cd068SThomas Petazzoni 		is_readonly = mmc_gpio_get_ro(host->mmc);
25291e72859eSPierre Ossman 	else
25302dfb579cSWolfram Sang 		is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
25312dfb579cSWolfram Sang 				& SDHCI_WRITE_PROTECT);
25321c6a0718SPierre Ossman 
25331c6a0718SPierre Ossman 	spin_unlock_irqrestore(&host->lock, flags);
25341c6a0718SPierre Ossman 
25352dfb579cSWolfram Sang 	/* This quirk needs to be replaced by a callback-function later */
25362dfb579cSWolfram Sang 	return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ?
25372dfb579cSWolfram Sang 		!is_readonly : is_readonly;
25381c6a0718SPierre Ossman }
25391c6a0718SPierre Ossman 
254082b0e23aSTakashi Iwai #define SAMPLE_COUNT	5
254182b0e23aSTakashi Iwai 
sdhci_get_ro(struct mmc_host * mmc)2542ded97e0bSDong Aisheng static int sdhci_get_ro(struct mmc_host *mmc)
254382b0e23aSTakashi Iwai {
2544ded97e0bSDong Aisheng 	struct sdhci_host *host = mmc_priv(mmc);
254582b0e23aSTakashi Iwai 	int i, ro_count;
254682b0e23aSTakashi Iwai 
254782b0e23aSTakashi Iwai 	if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
254866fd8ad5SAdrian Hunter 		return sdhci_check_ro(host);
254982b0e23aSTakashi Iwai 
255082b0e23aSTakashi Iwai 	ro_count = 0;
255182b0e23aSTakashi Iwai 	for (i = 0; i < SAMPLE_COUNT; i++) {
255266fd8ad5SAdrian Hunter 		if (sdhci_check_ro(host)) {
255382b0e23aSTakashi Iwai 			if (++ro_count > SAMPLE_COUNT / 2)
255482b0e23aSTakashi Iwai 				return 1;
255582b0e23aSTakashi Iwai 		}
255682b0e23aSTakashi Iwai 		msleep(30);
255782b0e23aSTakashi Iwai 	}
255882b0e23aSTakashi Iwai 	return 0;
255982b0e23aSTakashi Iwai }
256082b0e23aSTakashi Iwai 
sdhci_hw_reset(struct mmc_host * mmc)256120758b66SAdrian Hunter static void sdhci_hw_reset(struct mmc_host *mmc)
256220758b66SAdrian Hunter {
256320758b66SAdrian Hunter 	struct sdhci_host *host = mmc_priv(mmc);
256420758b66SAdrian Hunter 
256520758b66SAdrian Hunter 	if (host->ops && host->ops->hw_reset)
256620758b66SAdrian Hunter 		host->ops->hw_reset(host);
256720758b66SAdrian Hunter }
256820758b66SAdrian Hunter 
sdhci_enable_sdio_irq_nolock(struct sdhci_host * host,int enable)256966fd8ad5SAdrian Hunter static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
257066fd8ad5SAdrian Hunter {
2571be138554SRussell King 	if (!(host->flags & SDHCI_DEVICE_DEAD)) {
257266fd8ad5SAdrian Hunter 		if (enable)
2573b537f94cSRussell King 			host->ier |= SDHCI_INT_CARD_INT;
25747260cf5eSAnton Vorontsov 		else
2575b537f94cSRussell King 			host->ier &= ~SDHCI_INT_CARD_INT;
2576b537f94cSRussell King 
2577b537f94cSRussell King 		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
2578b537f94cSRussell King 		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
257966fd8ad5SAdrian Hunter 	}
2580ef104333SRussell King }
2581f75979b7SPierre Ossman 
sdhci_enable_sdio_irq(struct mmc_host * mmc,int enable)25822f05b6abSHu Ziji void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
258366fd8ad5SAdrian Hunter {
258466fd8ad5SAdrian Hunter 	struct sdhci_host *host = mmc_priv(mmc);
258566fd8ad5SAdrian Hunter 	unsigned long flags;
258666fd8ad5SAdrian Hunter 
2587923713b3SHans de Goede 	if (enable)
2588bac53336SJisheng Zhang 		pm_runtime_get_noresume(mmc_dev(mmc));
2589923713b3SHans de Goede 
259066fd8ad5SAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
259166fd8ad5SAdrian Hunter 	sdhci_enable_sdio_irq_nolock(host, enable);
2592f75979b7SPierre Ossman 	spin_unlock_irqrestore(&host->lock, flags);
2593923713b3SHans de Goede 
2594923713b3SHans de Goede 	if (!enable)
2595bac53336SJisheng Zhang 		pm_runtime_put_noidle(mmc_dev(mmc));
2596f75979b7SPierre Ossman }
25972f05b6abSHu Ziji EXPORT_SYMBOL_GPL(sdhci_enable_sdio_irq);
2598f75979b7SPierre Ossman 
sdhci_ack_sdio_irq(struct mmc_host * mmc)259989f3c365SAdrian Hunter static void sdhci_ack_sdio_irq(struct mmc_host *mmc)
260089f3c365SAdrian Hunter {
260189f3c365SAdrian Hunter 	struct sdhci_host *host = mmc_priv(mmc);
260289f3c365SAdrian Hunter 	unsigned long flags;
260389f3c365SAdrian Hunter 
260489f3c365SAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
260589f3c365SAdrian Hunter 	sdhci_enable_sdio_irq_nolock(host, true);
260689f3c365SAdrian Hunter 	spin_unlock_irqrestore(&host->lock, flags);
260789f3c365SAdrian Hunter }
260889f3c365SAdrian Hunter 
sdhci_start_signal_voltage_switch(struct mmc_host * mmc,struct mmc_ios * ios)2609c376ea9eSHu Ziji int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
261021f5998fSFabio Estevam 				      struct mmc_ios *ios)
2611f2119df6SArindam Nath {
2612ded97e0bSDong Aisheng 	struct sdhci_host *host = mmc_priv(mmc);
261320b92a30SKevin Liu 	u16 ctrl;
26146231f3deSPhilip Rakity 	int ret;
2615f2119df6SArindam Nath 
261620b92a30SKevin Liu 	/*
261720b92a30SKevin Liu 	 * Signal Voltage Switching is only applicable for Host Controllers
261820b92a30SKevin Liu 	 * v3.00 and above.
261920b92a30SKevin Liu 	 */
262020b92a30SKevin Liu 	if (host->version < SDHCI_SPEC_300)
262120b92a30SKevin Liu 		return 0;
262220b92a30SKevin Liu 
262320b92a30SKevin Liu 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
262420b92a30SKevin Liu 
262521f5998fSFabio Estevam 	switch (ios->signal_voltage) {
262620b92a30SKevin Liu 	case MMC_SIGNAL_VOLTAGE_330:
26278cb851a4SAdrian Hunter 		if (!(host->flags & SDHCI_SIGNALING_330))
26288cb851a4SAdrian Hunter 			return -EINVAL;
2629f2119df6SArindam Nath 		/* Set 1.8V Signal Enable in the Host Control2 register to 0 */
2630f2119df6SArindam Nath 		ctrl &= ~SDHCI_CTRL_VDD_180;
2631f2119df6SArindam Nath 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
2632f2119df6SArindam Nath 
26333a48edc4STim Kryger 		if (!IS_ERR(mmc->supply.vqmmc)) {
2634761daa36SDong Aisheng 			ret = mmc_regulator_set_vqmmc(mmc, ios);
26359cbe0fc8SMarek Vasut 			if (ret < 0) {
26366606110dSJoe Perches 				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
26376606110dSJoe Perches 					mmc_hostname(mmc));
26386231f3deSPhilip Rakity 				return -EIO;
26396231f3deSPhilip Rakity 			}
26406231f3deSPhilip Rakity 		}
2641f2119df6SArindam Nath 		/* Wait for 5ms */
2642f2119df6SArindam Nath 		usleep_range(5000, 5500);
2643f2119df6SArindam Nath 
2644f2119df6SArindam Nath 		/* 3.3V regulator output should be stable within 5 ms */
2645f2119df6SArindam Nath 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
2646f2119df6SArindam Nath 		if (!(ctrl & SDHCI_CTRL_VDD_180))
2647f2119df6SArindam Nath 			return 0;
26486231f3deSPhilip Rakity 
2649b0b19ce6SFabio Estevam 		pr_warn("%s: 3.3V regulator output did not become stable\n",
26504e743f1fSMarkus Mayer 			mmc_hostname(mmc));
26516231f3deSPhilip Rakity 
265220b92a30SKevin Liu 		return -EAGAIN;
265320b92a30SKevin Liu 	case MMC_SIGNAL_VOLTAGE_180:
26548cb851a4SAdrian Hunter 		if (!(host->flags & SDHCI_SIGNALING_180))
26558cb851a4SAdrian Hunter 			return -EINVAL;
26563a48edc4STim Kryger 		if (!IS_ERR(mmc->supply.vqmmc)) {
2657761daa36SDong Aisheng 			ret = mmc_regulator_set_vqmmc(mmc, ios);
26589cbe0fc8SMarek Vasut 			if (ret < 0) {
26596606110dSJoe Perches 				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
26606606110dSJoe Perches 					mmc_hostname(mmc));
2661f2119df6SArindam Nath 				return -EIO;
2662f2119df6SArindam Nath 			}
266320b92a30SKevin Liu 		}
26646231f3deSPhilip Rakity 
2665f2119df6SArindam Nath 		/*
2666f2119df6SArindam Nath 		 * Enable 1.8V Signal Enable in the Host Control2
2667f2119df6SArindam Nath 		 * register
2668f2119df6SArindam Nath 		 */
2669f2119df6SArindam Nath 		ctrl |= SDHCI_CTRL_VDD_180;
2670f2119df6SArindam Nath 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
2671f2119df6SArindam Nath 
26729d967a61SVincent Yang 		/* Some controller need to do more when switching */
26739d967a61SVincent Yang 		if (host->ops->voltage_switch)
26749d967a61SVincent Yang 			host->ops->voltage_switch(host);
26759d967a61SVincent Yang 
267620b92a30SKevin Liu 		/* 1.8V regulator output should be stable within 5 ms */
2677f2119df6SArindam Nath 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
267820b92a30SKevin Liu 		if (ctrl & SDHCI_CTRL_VDD_180)
2679f2119df6SArindam Nath 			return 0;
2680f2119df6SArindam Nath 
2681b0b19ce6SFabio Estevam 		pr_warn("%s: 1.8V regulator output did not become stable\n",
26824e743f1fSMarkus Mayer 			mmc_hostname(mmc));
26836231f3deSPhilip Rakity 
2684f2119df6SArindam Nath 		return -EAGAIN;
268520b92a30SKevin Liu 	case MMC_SIGNAL_VOLTAGE_120:
26868cb851a4SAdrian Hunter 		if (!(host->flags & SDHCI_SIGNALING_120))
26878cb851a4SAdrian Hunter 			return -EINVAL;
26883a48edc4STim Kryger 		if (!IS_ERR(mmc->supply.vqmmc)) {
2689761daa36SDong Aisheng 			ret = mmc_regulator_set_vqmmc(mmc, ios);
26909cbe0fc8SMarek Vasut 			if (ret < 0) {
26916606110dSJoe Perches 				pr_warn("%s: Switching to 1.2V signalling voltage failed\n",
26926606110dSJoe Perches 					mmc_hostname(mmc));
269320b92a30SKevin Liu 				return -EIO;
26946231f3deSPhilip Rakity 			}
269520b92a30SKevin Liu 		}
26966231f3deSPhilip Rakity 		return 0;
269720b92a30SKevin Liu 	default:
2698f2119df6SArindam Nath 		/* No signal voltage switch required */
2699f2119df6SArindam Nath 		return 0;
2700f2119df6SArindam Nath 	}
270120b92a30SKevin Liu }
2702c376ea9eSHu Ziji EXPORT_SYMBOL_GPL(sdhci_start_signal_voltage_switch);
2703f2119df6SArindam Nath 
sdhci_card_busy(struct mmc_host * mmc)270420b92a30SKevin Liu static int sdhci_card_busy(struct mmc_host *mmc)
270520b92a30SKevin Liu {
270620b92a30SKevin Liu 	struct sdhci_host *host = mmc_priv(mmc);
270720b92a30SKevin Liu 	u32 present_state;
270820b92a30SKevin Liu 
2709e613cc47SAdrian Hunter 	/* Check whether DAT[0] is 0 */
271020b92a30SKevin Liu 	present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
271120b92a30SKevin Liu 
2712e613cc47SAdrian Hunter 	return !(present_state & SDHCI_DATA_0_LVL_MASK);
271320b92a30SKevin Liu }
271420b92a30SKevin Liu 
sdhci_prepare_hs400_tuning(struct mmc_host * mmc,struct mmc_ios * ios)2715b5540ce1SAdrian Hunter static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
2716b5540ce1SAdrian Hunter {
2717b5540ce1SAdrian Hunter 	struct sdhci_host *host = mmc_priv(mmc);
2718b5540ce1SAdrian Hunter 	unsigned long flags;
2719b5540ce1SAdrian Hunter 
2720b5540ce1SAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
2721b5540ce1SAdrian Hunter 	host->flags |= SDHCI_HS400_TUNING;
2722b5540ce1SAdrian Hunter 	spin_unlock_irqrestore(&host->lock, flags);
2723b5540ce1SAdrian Hunter 
2724b5540ce1SAdrian Hunter 	return 0;
2725b5540ce1SAdrian Hunter }
2726b5540ce1SAdrian Hunter 
sdhci_start_tuning(struct sdhci_host * host)27276663c419Sernest.zhang void sdhci_start_tuning(struct sdhci_host *host)
2728da4bc4f2SAdrian Hunter {
2729da4bc4f2SAdrian Hunter 	u16 ctrl;
2730da4bc4f2SAdrian Hunter 
2731da4bc4f2SAdrian Hunter 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
2732da4bc4f2SAdrian Hunter 	ctrl |= SDHCI_CTRL_EXEC_TUNING;
2733da4bc4f2SAdrian Hunter 	if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND)
2734da4bc4f2SAdrian Hunter 		ctrl |= SDHCI_CTRL_TUNED_CLK;
2735da4bc4f2SAdrian Hunter 	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
2736da4bc4f2SAdrian Hunter 
2737da4bc4f2SAdrian Hunter 	/*
2738da4bc4f2SAdrian Hunter 	 * As per the Host Controller spec v3.00, tuning command
2739da4bc4f2SAdrian Hunter 	 * generates Buffer Read Ready interrupt, so enable that.
2740da4bc4f2SAdrian Hunter 	 *
2741da4bc4f2SAdrian Hunter 	 * Note: The spec clearly says that when tuning sequence
2742da4bc4f2SAdrian Hunter 	 * is being performed, the controller does not generate
2743da4bc4f2SAdrian Hunter 	 * interrupts other than Buffer Read Ready interrupt. But
2744da4bc4f2SAdrian Hunter 	 * to make sure we don't hit a controller bug, we _only_
2745da4bc4f2SAdrian Hunter 	 * enable Buffer Read Ready interrupt here.
2746da4bc4f2SAdrian Hunter 	 */
2747da4bc4f2SAdrian Hunter 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
2748da4bc4f2SAdrian Hunter 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
2749da4bc4f2SAdrian Hunter }
27506663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_start_tuning);
2751da4bc4f2SAdrian Hunter 
sdhci_end_tuning(struct sdhci_host * host)27526663c419Sernest.zhang void sdhci_end_tuning(struct sdhci_host *host)
2753da4bc4f2SAdrian Hunter {
2754da4bc4f2SAdrian Hunter 	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
2755da4bc4f2SAdrian Hunter 	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
2756da4bc4f2SAdrian Hunter }
27576663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_end_tuning);
2758da4bc4f2SAdrian Hunter 
sdhci_reset_tuning(struct sdhci_host * host)27596663c419Sernest.zhang void sdhci_reset_tuning(struct sdhci_host *host)
2760da4bc4f2SAdrian Hunter {
2761da4bc4f2SAdrian Hunter 	u16 ctrl;
2762da4bc4f2SAdrian Hunter 
2763da4bc4f2SAdrian Hunter 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
2764da4bc4f2SAdrian Hunter 	ctrl &= ~SDHCI_CTRL_TUNED_CLK;
2765da4bc4f2SAdrian Hunter 	ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
2766da4bc4f2SAdrian Hunter 	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
2767da4bc4f2SAdrian Hunter }
27686663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_reset_tuning);
2769da4bc4f2SAdrian Hunter 
sdhci_abort_tuning(struct sdhci_host * host,u32 opcode)27707353788cSBen Chuang void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
2771da4bc4f2SAdrian Hunter {
2772da4bc4f2SAdrian Hunter 	sdhci_reset_tuning(host);
2773da4bc4f2SAdrian Hunter 
27741e63d297SAdrian Hunter 	sdhci_reset_for(host, TUNING_ABORT);
2775da4bc4f2SAdrian Hunter 
2776da4bc4f2SAdrian Hunter 	sdhci_end_tuning(host);
2777da4bc4f2SAdrian Hunter 
277821adc2e4SWolfram Sang 	mmc_send_abort_tuning(host->mmc, opcode);
2779da4bc4f2SAdrian Hunter }
27807353788cSBen Chuang EXPORT_SYMBOL_GPL(sdhci_abort_tuning);
2781da4bc4f2SAdrian Hunter 
2782da4bc4f2SAdrian Hunter /*
2783da4bc4f2SAdrian Hunter  * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI
2784da4bc4f2SAdrian Hunter  * tuning command does not have a data payload (or rather the hardware does it
2785da4bc4f2SAdrian Hunter  * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command
2786da4bc4f2SAdrian Hunter  * interrupt setup is different to other commands and there is no timeout
2787da4bc4f2SAdrian Hunter  * interrupt so special handling is needed.
2788da4bc4f2SAdrian Hunter  */
sdhci_send_tuning(struct sdhci_host * host,u32 opcode)27896663c419Sernest.zhang void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
2790da4bc4f2SAdrian Hunter {
2791da4bc4f2SAdrian Hunter 	struct mmc_host *mmc = host->mmc;
2792c7836d15SMasahiro Yamada 	struct mmc_command cmd = {};
2793c7836d15SMasahiro Yamada 	struct mmc_request mrq = {};
27942a85ef25SAdrian Hunter 	unsigned long flags;
2795c846a00fSSrinivas Kandagatla 	u32 b = host->sdma_boundary;
27962a85ef25SAdrian Hunter 
27972a85ef25SAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
2798da4bc4f2SAdrian Hunter 
2799da4bc4f2SAdrian Hunter 	cmd.opcode = opcode;
2800da4bc4f2SAdrian Hunter 	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
2801da4bc4f2SAdrian Hunter 	cmd.mrq = &mrq;
2802da4bc4f2SAdrian Hunter 
2803da4bc4f2SAdrian Hunter 	mrq.cmd = &cmd;
2804da4bc4f2SAdrian Hunter 	/*
2805da4bc4f2SAdrian Hunter 	 * In response to CMD19, the card sends 64 bytes of tuning
2806da4bc4f2SAdrian Hunter 	 * block to the Host Controller. So we set the block size
2807da4bc4f2SAdrian Hunter 	 * to 64 here.
2808da4bc4f2SAdrian Hunter 	 */
280985336109SAdrian Hunter 	if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200 &&
281085336109SAdrian Hunter 	    mmc->ios.bus_width == MMC_BUS_WIDTH_8)
2811c846a00fSSrinivas Kandagatla 		sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 128), SDHCI_BLOCK_SIZE);
281285336109SAdrian Hunter 	else
2813c846a00fSSrinivas Kandagatla 		sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 64), SDHCI_BLOCK_SIZE);
2814da4bc4f2SAdrian Hunter 
2815da4bc4f2SAdrian Hunter 	/*
2816da4bc4f2SAdrian Hunter 	 * The tuning block is sent by the card to the host controller.
2817da4bc4f2SAdrian Hunter 	 * So we set the TRNS_READ bit in the Transfer Mode register.
2818da4bc4f2SAdrian Hunter 	 * This also takes care of setting DMA Enable and Multi Block
2819da4bc4f2SAdrian Hunter 	 * Select in the same register to 0.
2820da4bc4f2SAdrian Hunter 	 */
2821da4bc4f2SAdrian Hunter 	sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
2822da4bc4f2SAdrian Hunter 
2823845c939eSAdrian Hunter 	if (!sdhci_send_command_retry(host, &cmd, flags)) {
2824845c939eSAdrian Hunter 		spin_unlock_irqrestore(&host->lock, flags);
2825845c939eSAdrian Hunter 		host->tuning_done = 0;
2826845c939eSAdrian Hunter 		return;
2827845c939eSAdrian Hunter 	}
2828da4bc4f2SAdrian Hunter 
2829da4bc4f2SAdrian Hunter 	host->cmd = NULL;
2830da4bc4f2SAdrian Hunter 
2831da4bc4f2SAdrian Hunter 	sdhci_del_timer(host, &mrq);
2832da4bc4f2SAdrian Hunter 
2833da4bc4f2SAdrian Hunter 	host->tuning_done = 0;
2834da4bc4f2SAdrian Hunter 
2835da4bc4f2SAdrian Hunter 	spin_unlock_irqrestore(&host->lock, flags);
2836da4bc4f2SAdrian Hunter 
2837da4bc4f2SAdrian Hunter 	/* Wait for Buffer Read Ready interrupt */
2838da4bc4f2SAdrian Hunter 	wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1),
2839da4bc4f2SAdrian Hunter 			   msecs_to_jiffies(50));
2840da4bc4f2SAdrian Hunter 
2841da4bc4f2SAdrian Hunter }
28426663c419Sernest.zhang EXPORT_SYMBOL_GPL(sdhci_send_tuning);
2843da4bc4f2SAdrian Hunter 
__sdhci_execute_tuning(struct sdhci_host * host,u32 opcode)28447d8bb1f4SYinbo Zhu static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
28456b11e70bSAdrian Hunter {
28466b11e70bSAdrian Hunter 	int i;
28476b11e70bSAdrian Hunter 
28486b11e70bSAdrian Hunter 	/*
28496b11e70bSAdrian Hunter 	 * Issue opcode repeatedly till Execute Tuning is set to 0 or the number
28501d8cd065SSowjanya Komatineni 	 * of loops reaches tuning loop count.
28516b11e70bSAdrian Hunter 	 */
28521d8cd065SSowjanya Komatineni 	for (i = 0; i < host->tuning_loop_count; i++) {
28536b11e70bSAdrian Hunter 		u16 ctrl;
28546b11e70bSAdrian Hunter 
28552a85ef25SAdrian Hunter 		sdhci_send_tuning(host, opcode);
28566b11e70bSAdrian Hunter 
28576b11e70bSAdrian Hunter 		if (!host->tuning_done) {
2858811ba676SFaiz Abbas 			pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n",
28596b11e70bSAdrian Hunter 				 mmc_hostname(host->mmc));
28602a85ef25SAdrian Hunter 			sdhci_abort_tuning(host, opcode);
28617d8bb1f4SYinbo Zhu 			return -ETIMEDOUT;
28626b11e70bSAdrian Hunter 		}
28636b11e70bSAdrian Hunter 
28642b06e159SBOUGH CHEN 		/* Spec does not require a delay between tuning cycles */
28652b06e159SBOUGH CHEN 		if (host->tuning_delay > 0)
28662b06e159SBOUGH CHEN 			mdelay(host->tuning_delay);
28672b06e159SBOUGH CHEN 
28686b11e70bSAdrian Hunter 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
28696b11e70bSAdrian Hunter 		if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
28706b11e70bSAdrian Hunter 			if (ctrl & SDHCI_CTRL_TUNED_CLK)
28717d8bb1f4SYinbo Zhu 				return 0; /* Success! */
28726b11e70bSAdrian Hunter 			break;
28736b11e70bSAdrian Hunter 		}
28746b11e70bSAdrian Hunter 
28756b11e70bSAdrian Hunter 	}
28766b11e70bSAdrian Hunter 
28776b11e70bSAdrian Hunter 	pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
28786b11e70bSAdrian Hunter 		mmc_hostname(host->mmc));
28796b11e70bSAdrian Hunter 	sdhci_reset_tuning(host);
28807d8bb1f4SYinbo Zhu 	return -EAGAIN;
28816b11e70bSAdrian Hunter }
28826b11e70bSAdrian Hunter 
sdhci_execute_tuning(struct mmc_host * mmc,u32 opcode)288385a882c2SMasahiro Yamada int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
2884b513ea25SArindam Nath {
28854b6f37d3SRussell King 	struct sdhci_host *host = mmc_priv(mmc);
2886b513ea25SArindam Nath 	int err = 0;
288738e40bf5SAdrian Hunter 	unsigned int tuning_count = 0;
2888b5540ce1SAdrian Hunter 	bool hs400_tuning;
2889b513ea25SArindam Nath 
2890b5540ce1SAdrian Hunter 	hs400_tuning = host->flags & SDHCI_HS400_TUNING;
2891b5540ce1SAdrian Hunter 
289238e40bf5SAdrian Hunter 	if (host->tuning_mode == SDHCI_TUNING_MODE_1)
289338e40bf5SAdrian Hunter 		tuning_count = host->tuning_count;
289438e40bf5SAdrian Hunter 
2895b513ea25SArindam Nath 	/*
28969faac7b9SWeijun Yang 	 * The Host Controller needs tuning in case of SDR104 and DDR50
28979faac7b9SWeijun Yang 	 * mode, and for SDR50 mode when Use Tuning for SDR50 is set in
28989faac7b9SWeijun Yang 	 * the Capabilities register.
2899069c9f14SGirish K S 	 * If the Host Controller supports the HS200 mode then the
2900069c9f14SGirish K S 	 * tuning function has to be executed.
2901b513ea25SArindam Nath 	 */
29024b6f37d3SRussell King 	switch (host->timing) {
2903b5540ce1SAdrian Hunter 	/* HS400 tuning is done in HS200 mode */
2904e9fb05d5SAdrian Hunter 	case MMC_TIMING_MMC_HS400:
2905b5540ce1SAdrian Hunter 		err = -EINVAL;
29062a85ef25SAdrian Hunter 		goto out;
2907b5540ce1SAdrian Hunter 
29084b6f37d3SRussell King 	case MMC_TIMING_MMC_HS200:
2909b5540ce1SAdrian Hunter 		/*
2910b5540ce1SAdrian Hunter 		 * Periodic re-tuning for HS400 is not expected to be needed, so
2911b5540ce1SAdrian Hunter 		 * disable it here.
2912b5540ce1SAdrian Hunter 		 */
2913b5540ce1SAdrian Hunter 		if (hs400_tuning)
2914b5540ce1SAdrian Hunter 			tuning_count = 0;
2915b5540ce1SAdrian Hunter 		break;
2916b5540ce1SAdrian Hunter 
29174b6f37d3SRussell King 	case MMC_TIMING_UHS_SDR104:
29189faac7b9SWeijun Yang 	case MMC_TIMING_UHS_DDR50:
29194b6f37d3SRussell King 		break;
2920069c9f14SGirish K S 
29214b6f37d3SRussell King 	case MMC_TIMING_UHS_SDR50:
29224228b213SAdrian Hunter 		if (host->flags & SDHCI_SDR50_NEEDS_TUNING)
29234b6f37d3SRussell King 			break;
2924df561f66SGustavo A. R. Silva 		fallthrough;
29254b6f37d3SRussell King 
29264b6f37d3SRussell King 	default:
29272a85ef25SAdrian Hunter 		goto out;
2928b513ea25SArindam Nath 	}
2929b513ea25SArindam Nath 
293045251812SDong Aisheng 	if (host->ops->platform_execute_tuning) {
29318a8fa879SRitesh Harjani 		err = host->ops->platform_execute_tuning(host, opcode);
29322a85ef25SAdrian Hunter 		goto out;
293345251812SDong Aisheng 	}
293445251812SDong Aisheng 
2935d2f025b0SJisheng Zhang 	mmc->retune_period = tuning_count;
29366b11e70bSAdrian Hunter 
293783b600b8SAdrian Hunter 	if (host->tuning_delay < 0)
293883b600b8SAdrian Hunter 		host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK;
293983b600b8SAdrian Hunter 
2940da4bc4f2SAdrian Hunter 	sdhci_start_tuning(host);
2941b513ea25SArindam Nath 
29427d8bb1f4SYinbo Zhu 	host->tuning_err = __sdhci_execute_tuning(host, opcode);
2943cf2b5eeaSArindam Nath 
2944da4bc4f2SAdrian Hunter 	sdhci_end_tuning(host);
29452a85ef25SAdrian Hunter out:
29468a8fa879SRitesh Harjani 	host->flags &= ~SDHCI_HS400_TUNING;
29476b11e70bSAdrian Hunter 
2948b513ea25SArindam Nath 	return err;
2949b513ea25SArindam Nath }
295085a882c2SMasahiro Yamada EXPORT_SYMBOL_GPL(sdhci_execute_tuning);
2951b513ea25SArindam Nath 
sdhci_enable_preset_value(struct sdhci_host * host,bool enable)295252983382SKevin Liu static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
29534d55c5a1SArindam Nath {
29544d55c5a1SArindam Nath 	/* Host Controller v3.00 defines preset value registers */
29554d55c5a1SArindam Nath 	if (host->version < SDHCI_SPEC_300)
29564d55c5a1SArindam Nath 		return;
29574d55c5a1SArindam Nath 
29584d55c5a1SArindam Nath 	/*
29594d55c5a1SArindam Nath 	 * We only enable or disable Preset Value if they are not already
29604d55c5a1SArindam Nath 	 * enabled or disabled respectively. Otherwise, we bail out.
29614d55c5a1SArindam Nath 	 */
2962da91a8f9SRussell King 	if (host->preset_enabled != enable) {
2963da91a8f9SRussell King 		u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
2964da91a8f9SRussell King 
2965da91a8f9SRussell King 		if (enable)
29664d55c5a1SArindam Nath 			ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
2967da91a8f9SRussell King 		else
29684d55c5a1SArindam Nath 			ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
2969da91a8f9SRussell King 
29704d55c5a1SArindam Nath 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
2971da91a8f9SRussell King 
2972da91a8f9SRussell King 		if (enable)
2973da91a8f9SRussell King 			host->flags |= SDHCI_PV_ENABLED;
2974da91a8f9SRussell King 		else
297566fd8ad5SAdrian Hunter 			host->flags &= ~SDHCI_PV_ENABLED;
2976da91a8f9SRussell King 
2977da91a8f9SRussell King 		host->preset_enabled = enable;
29784d55c5a1SArindam Nath 	}
297966fd8ad5SAdrian Hunter }
298066fd8ad5SAdrian Hunter 
sdhci_post_req(struct mmc_host * mmc,struct mmc_request * mrq,int err)2981348487cbSHaibo Chen static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
2982348487cbSHaibo Chen 				int err)
2983348487cbSHaibo Chen {
2984348487cbSHaibo Chen 	struct mmc_data *data = mrq->data;
2985348487cbSHaibo Chen 
2986f48f039cSRussell King 	if (data->host_cookie != COOKIE_UNMAPPED)
2987d2f025b0SJisheng Zhang 		dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len,
2988feeef096SHeiner Kallweit 			     mmc_get_dma_dir(data));
2989771a3dc2SRussell King 
2990d31911b9SHaibo Chen 	data->host_cookie = COOKIE_UNMAPPED;
2991348487cbSHaibo Chen }
2992348487cbSHaibo Chen 
sdhci_pre_req(struct mmc_host * mmc,struct mmc_request * mrq)2993d3c6aac3SLinus Walleij static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
2994348487cbSHaibo Chen {
2995348487cbSHaibo Chen 	struct sdhci_host *host = mmc_priv(mmc);
2996348487cbSHaibo Chen 
2997d31911b9SHaibo Chen 	mrq->data->host_cookie = COOKIE_UNMAPPED;
2998348487cbSHaibo Chen 
2999bd9b9027SLinus Walleij 	/*
3000bd9b9027SLinus Walleij 	 * No pre-mapping in the pre hook if we're using the bounce buffer,
3001bd9b9027SLinus Walleij 	 * for that we would need two bounce buffers since one buffer is
3002bd9b9027SLinus Walleij 	 * in flight when this is getting called.
3003bd9b9027SLinus Walleij 	 */
3004bd9b9027SLinus Walleij 	if (host->flags & SDHCI_REQ_USE_DMA && !host->bounce_buffer)
300594538e51SRussell King 		sdhci_pre_dma_transfer(host, mrq->data, COOKIE_PRE_MAPPED);
3006348487cbSHaibo Chen }
3007348487cbSHaibo Chen 
sdhci_error_out_mrqs(struct sdhci_host * host,int err)30085d0d11c5SAdrian Hunter static void sdhci_error_out_mrqs(struct sdhci_host *host, int err)
30095d0d11c5SAdrian Hunter {
30105d0d11c5SAdrian Hunter 	if (host->data_cmd) {
30115d0d11c5SAdrian Hunter 		host->data_cmd->error = err;
30125d0d11c5SAdrian Hunter 		sdhci_finish_mrq(host, host->data_cmd->mrq);
30135d0d11c5SAdrian Hunter 	}
30145d0d11c5SAdrian Hunter 
30155d0d11c5SAdrian Hunter 	if (host->cmd) {
30165d0d11c5SAdrian Hunter 		host->cmd->error = err;
30175d0d11c5SAdrian Hunter 		sdhci_finish_mrq(host, host->cmd->mrq);
30185d0d11c5SAdrian Hunter 	}
30195d0d11c5SAdrian Hunter }
30205d0d11c5SAdrian Hunter 
sdhci_card_event(struct mmc_host * mmc)302171e69211SGuennadi Liakhovetski static void sdhci_card_event(struct mmc_host *mmc)
30221c6a0718SPierre Ossman {
302371e69211SGuennadi Liakhovetski 	struct sdhci_host *host = mmc_priv(mmc);
30241c6a0718SPierre Ossman 	unsigned long flags;
30252836766aSKrzysztof Kozlowski 	int present;
30261c6a0718SPierre Ossman 
3027722e1280SChristian Daudt 	/* First check if client has provided their own card event */
3028722e1280SChristian Daudt 	if (host->ops->card_event)
3029722e1280SChristian Daudt 		host->ops->card_event(host);
3030722e1280SChristian Daudt 
3031d3940f27SAdrian Hunter 	present = mmc->ops->get_cd(mmc);
30322836766aSKrzysztof Kozlowski 
30331c6a0718SPierre Ossman 	spin_lock_irqsave(&host->lock, flags);
30341c6a0718SPierre Ossman 
30355d0d11c5SAdrian Hunter 	/* Check sdhci_has_requests() first in case we are runtime suspended */
30365d0d11c5SAdrian Hunter 	if (sdhci_has_requests(host) && !present) {
3037a3c76eb9SGirish K S 		pr_err("%s: Card removed during transfer!\n",
3038d2f025b0SJisheng Zhang 			mmc_hostname(mmc));
3039a3c76eb9SGirish K S 		pr_err("%s: Resetting controller.\n",
3040d2f025b0SJisheng Zhang 			mmc_hostname(mmc));
30411c6a0718SPierre Ossman 
30421e63d297SAdrian Hunter 		sdhci_reset_for(host, CARD_REMOVED);
30431c6a0718SPierre Ossman 
30445d0d11c5SAdrian Hunter 		sdhci_error_out_mrqs(host, -ENOMEDIUM);
30451c6a0718SPierre Ossman 	}
30461c6a0718SPierre Ossman 
30471c6a0718SPierre Ossman 	spin_unlock_irqrestore(&host->lock, flags);
304871e69211SGuennadi Liakhovetski }
304971e69211SGuennadi Liakhovetski 
305071e69211SGuennadi Liakhovetski static const struct mmc_host_ops sdhci_ops = {
305171e69211SGuennadi Liakhovetski 	.request	= sdhci_request,
3052348487cbSHaibo Chen 	.post_req	= sdhci_post_req,
3053348487cbSHaibo Chen 	.pre_req	= sdhci_pre_req,
305471e69211SGuennadi Liakhovetski 	.set_ios	= sdhci_set_ios,
305594144a46SKevin Liu 	.get_cd		= sdhci_get_cd,
305671e69211SGuennadi Liakhovetski 	.get_ro		= sdhci_get_ro,
305732f18e59SWolfram Sang 	.card_hw_reset	= sdhci_hw_reset,
305871e69211SGuennadi Liakhovetski 	.enable_sdio_irq = sdhci_enable_sdio_irq,
305989f3c365SAdrian Hunter 	.ack_sdio_irq    = sdhci_ack_sdio_irq,
306071e69211SGuennadi Liakhovetski 	.start_signal_voltage_switch	= sdhci_start_signal_voltage_switch,
3061b5540ce1SAdrian Hunter 	.prepare_hs400_tuning		= sdhci_prepare_hs400_tuning,
306271e69211SGuennadi Liakhovetski 	.execute_tuning			= sdhci_execute_tuning,
306371e69211SGuennadi Liakhovetski 	.card_event			= sdhci_card_event,
306420b92a30SKevin Liu 	.card_busy	= sdhci_card_busy,
306571e69211SGuennadi Liakhovetski };
306671e69211SGuennadi Liakhovetski 
306771e69211SGuennadi Liakhovetski /*****************************************************************************\
306871e69211SGuennadi Liakhovetski  *                                                                           *
3069c07a48c2SAdrian Hunter  * Request done                                                              *
307071e69211SGuennadi Liakhovetski  *                                                                           *
307171e69211SGuennadi Liakhovetski \*****************************************************************************/
307271e69211SGuennadi Liakhovetski 
sdhci_request_done(struct sdhci_host * host)30734e9f8fe5SAdrian Hunter static bool sdhci_request_done(struct sdhci_host *host)
30741c6a0718SPierre Ossman {
30751c6a0718SPierre Ossman 	unsigned long flags;
30761c6a0718SPierre Ossman 	struct mmc_request *mrq;
30774e9f8fe5SAdrian Hunter 	int i;
30781c6a0718SPierre Ossman 
307966fd8ad5SAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
308066fd8ad5SAdrian Hunter 
30814e9f8fe5SAdrian Hunter 	for (i = 0; i < SDHCI_MAX_MRQS; i++) {
30824e9f8fe5SAdrian Hunter 		mrq = host->mrqs_done[i];
30836ebebeabSAdrian Hunter 		if (mrq)
30844e9f8fe5SAdrian Hunter 			break;
30854e9f8fe5SAdrian Hunter 	}
30861c6a0718SPierre Ossman 
30874e9f8fe5SAdrian Hunter 	if (!mrq) {
30884e9f8fe5SAdrian Hunter 		spin_unlock_irqrestore(&host->lock, flags);
30894e9f8fe5SAdrian Hunter 		return true;
30904e9f8fe5SAdrian Hunter 	}
30911c6a0718SPierre Ossman 
30921c6a0718SPierre Ossman 	/*
309321e35e89SPradeep P V K 	 * The controller needs a reset of internal state machines
309421e35e89SPradeep P V K 	 * upon error conditions.
309521e35e89SPradeep P V K 	 */
309621e35e89SPradeep P V K 	if (sdhci_needs_reset(host, mrq)) {
309721e35e89SPradeep P V K 		/*
309821e35e89SPradeep P V K 		 * Do not finish until command and data lines are available for
309921e35e89SPradeep P V K 		 * reset. Note there can only be one other mrq, so it cannot
310021e35e89SPradeep P V K 		 * also be in mrqs_done, otherwise host->cmd and host->data_cmd
310121e35e89SPradeep P V K 		 * would both be null.
310221e35e89SPradeep P V K 		 */
310321e35e89SPradeep P V K 		if (host->cmd || host->data_cmd) {
310421e35e89SPradeep P V K 			spin_unlock_irqrestore(&host->lock, flags);
310521e35e89SPradeep P V K 			return true;
310621e35e89SPradeep P V K 		}
310721e35e89SPradeep P V K 
310821e35e89SPradeep P V K 		/* Some controllers need this kick or reset won't work here */
310921e35e89SPradeep P V K 		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
311021e35e89SPradeep P V K 			/* This is to force an update */
311121e35e89SPradeep P V K 			host->ops->set_clock(host, host->clock);
311221e35e89SPradeep P V K 
31131e63d297SAdrian Hunter 		sdhci_reset_for(host, REQUEST_ERROR);
311421e35e89SPradeep P V K 
311521e35e89SPradeep P V K 		host->pending_reset = false;
311621e35e89SPradeep P V K 	}
311721e35e89SPradeep P V K 
311821e35e89SPradeep P V K 	/*
3119054cedffSRussell King 	 * Always unmap the data buffers if they were mapped by
3120054cedffSRussell King 	 * sdhci_prepare_data() whenever we finish with a request.
3121054cedffSRussell King 	 * This avoids leaking DMA mappings on error.
3122054cedffSRussell King 	 */
3123054cedffSRussell King 	if (host->flags & SDHCI_REQ_USE_DMA) {
3124054cedffSRussell King 		struct mmc_data *data = mrq->data;
3125054cedffSRussell King 
312618e762e3SChunyan Zhang 		if (host->use_external_dma && data &&
312718e762e3SChunyan Zhang 		    (mrq->cmd->error || data->error)) {
312818e762e3SChunyan Zhang 			struct dma_chan *chan = sdhci_external_dma_channel(host, data);
312918e762e3SChunyan Zhang 
313018e762e3SChunyan Zhang 			host->mrqs_done[i] = NULL;
313118e762e3SChunyan Zhang 			spin_unlock_irqrestore(&host->lock, flags);
313218e762e3SChunyan Zhang 			dmaengine_terminate_sync(chan);
313318e762e3SChunyan Zhang 			spin_lock_irqsave(&host->lock, flags);
313418e762e3SChunyan Zhang 			sdhci_set_mrq_done(host, mrq);
313518e762e3SChunyan Zhang 		}
313618e762e3SChunyan Zhang 
3137054cedffSRussell King 		if (data && data->host_cookie == COOKIE_MAPPED) {
3138bd9b9027SLinus Walleij 			if (host->bounce_buffer) {
3139bd9b9027SLinus Walleij 				/*
3140bd9b9027SLinus Walleij 				 * On reads, copy the bounced data into the
3141bd9b9027SLinus Walleij 				 * sglist
3142bd9b9027SLinus Walleij 				 */
3143bd9b9027SLinus Walleij 				if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) {
3144bd9b9027SLinus Walleij 					unsigned int length = data->bytes_xfered;
3145bd9b9027SLinus Walleij 
3146bd9b9027SLinus Walleij 					if (length > host->bounce_buffer_size) {
3147bd9b9027SLinus Walleij 						pr_err("%s: bounce buffer is %u bytes but DMA claims to have transferred %u bytes\n",
3148bd9b9027SLinus Walleij 						       mmc_hostname(host->mmc),
3149bd9b9027SLinus Walleij 						       host->bounce_buffer_size,
3150bd9b9027SLinus Walleij 						       data->bytes_xfered);
3151bd9b9027SLinus Walleij 						/* Cap it down and continue */
3152bd9b9027SLinus Walleij 						length = host->bounce_buffer_size;
3153bd9b9027SLinus Walleij 					}
3154bd9b9027SLinus Walleij 					dma_sync_single_for_cpu(
3155bac53336SJisheng Zhang 						mmc_dev(host->mmc),
3156bd9b9027SLinus Walleij 						host->bounce_addr,
3157bd9b9027SLinus Walleij 						host->bounce_buffer_size,
3158bd9b9027SLinus Walleij 						DMA_FROM_DEVICE);
3159bd9b9027SLinus Walleij 					sg_copy_from_buffer(data->sg,
3160bd9b9027SLinus Walleij 						data->sg_len,
3161bd9b9027SLinus Walleij 						host->bounce_buffer,
3162bd9b9027SLinus Walleij 						length);
3163bd9b9027SLinus Walleij 				} else {
3164bd9b9027SLinus Walleij 					/* No copying, just switch ownership */
3165bd9b9027SLinus Walleij 					dma_sync_single_for_cpu(
3166bac53336SJisheng Zhang 						mmc_dev(host->mmc),
3167bd9b9027SLinus Walleij 						host->bounce_addr,
3168bd9b9027SLinus Walleij 						host->bounce_buffer_size,
3169feeef096SHeiner Kallweit 						mmc_get_dma_dir(data));
3170bd9b9027SLinus Walleij 				}
3171bd9b9027SLinus Walleij 			} else {
3172bd9b9027SLinus Walleij 				/* Unmap the raw data */
3173bd9b9027SLinus Walleij 				dma_unmap_sg(mmc_dev(host->mmc), data->sg,
3174bd9b9027SLinus Walleij 					     data->sg_len,
3175bd9b9027SLinus Walleij 					     mmc_get_dma_dir(data));
3176bd9b9027SLinus Walleij 			}
3177054cedffSRussell King 			data->host_cookie = COOKIE_UNMAPPED;
3178054cedffSRussell King 		}
3179054cedffSRussell King 	}
3180054cedffSRussell King 
31816ebebeabSAdrian Hunter 	host->mrqs_done[i] = NULL;
31826ebebeabSAdrian Hunter 
31831c6a0718SPierre Ossman 	spin_unlock_irqrestore(&host->lock, flags);
31841c6a0718SPierre Ossman 
31851774b002SBaolin Wang 	if (host->ops->request_done)
31861774b002SBaolin Wang 		host->ops->request_done(host, mrq);
31871774b002SBaolin Wang 	else
31881c6a0718SPierre Ossman 		mmc_request_done(host->mmc, mrq);
31894e9f8fe5SAdrian Hunter 
31904e9f8fe5SAdrian Hunter 	return false;
31914e9f8fe5SAdrian Hunter }
31924e9f8fe5SAdrian Hunter 
sdhci_complete_work(struct work_struct * work)3193c07a48c2SAdrian Hunter static void sdhci_complete_work(struct work_struct *work)
31944e9f8fe5SAdrian Hunter {
3195c07a48c2SAdrian Hunter 	struct sdhci_host *host = container_of(work, struct sdhci_host,
3196c07a48c2SAdrian Hunter 					       complete_work);
31974e9f8fe5SAdrian Hunter 
31984e9f8fe5SAdrian Hunter 	while (!sdhci_request_done(host))
31994e9f8fe5SAdrian Hunter 		;
32001c6a0718SPierre Ossman }
32011c6a0718SPierre Ossman 
sdhci_timeout_timer(struct timer_list * t)32022ee4f620SKees Cook static void sdhci_timeout_timer(struct timer_list *t)
32031c6a0718SPierre Ossman {
32041c6a0718SPierre Ossman 	struct sdhci_host *host;
32051c6a0718SPierre Ossman 	unsigned long flags;
32061c6a0718SPierre Ossman 
32072ee4f620SKees Cook 	host = from_timer(host, t, timer);
32081c6a0718SPierre Ossman 
32091c6a0718SPierre Ossman 	spin_lock_irqsave(&host->lock, flags);
32101c6a0718SPierre Ossman 
3211d7422fb4SAdrian Hunter 	if (host->cmd && !sdhci_data_line_cmd(host->cmd)) {
3212d7422fb4SAdrian Hunter 		pr_err("%s: Timeout waiting for hardware cmd interrupt.\n",
3213d7422fb4SAdrian Hunter 		       mmc_hostname(host->mmc));
3214efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, REQ_TIMEOUT);
3215d7422fb4SAdrian Hunter 		sdhci_dumpregs(host);
3216d7422fb4SAdrian Hunter 
3217d7422fb4SAdrian Hunter 		host->cmd->error = -ETIMEDOUT;
3218d7422fb4SAdrian Hunter 		sdhci_finish_mrq(host, host->cmd->mrq);
3219d7422fb4SAdrian Hunter 	}
3220d7422fb4SAdrian Hunter 
3221d7422fb4SAdrian Hunter 	spin_unlock_irqrestore(&host->lock, flags);
3222d7422fb4SAdrian Hunter }
3223d7422fb4SAdrian Hunter 
sdhci_timeout_data_timer(struct timer_list * t)32242ee4f620SKees Cook static void sdhci_timeout_data_timer(struct timer_list *t)
3225d7422fb4SAdrian Hunter {
3226d7422fb4SAdrian Hunter 	struct sdhci_host *host;
3227d7422fb4SAdrian Hunter 	unsigned long flags;
3228d7422fb4SAdrian Hunter 
32292ee4f620SKees Cook 	host = from_timer(host, t, data_timer);
3230d7422fb4SAdrian Hunter 
3231d7422fb4SAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
3232d7422fb4SAdrian Hunter 
3233d7422fb4SAdrian Hunter 	if (host->data || host->data_cmd ||
3234d7422fb4SAdrian Hunter 	    (host->cmd && sdhci_data_line_cmd(host->cmd))) {
32352e4456f0SMarek Vasut 		pr_err("%s: Timeout waiting for hardware interrupt.\n",
32362e4456f0SMarek Vasut 		       mmc_hostname(host->mmc));
3237efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, REQ_TIMEOUT);
32381c6a0718SPierre Ossman 		sdhci_dumpregs(host);
32391c6a0718SPierre Ossman 
32401c6a0718SPierre Ossman 		if (host->data) {
324117b0429dSPierre Ossman 			host->data->error = -ETIMEDOUT;
3242845c939eSAdrian Hunter 			__sdhci_finish_data(host, true);
3243c07a48c2SAdrian Hunter 			queue_work(host->complete_wq, &host->complete_work);
3244d7422fb4SAdrian Hunter 		} else if (host->data_cmd) {
3245d7422fb4SAdrian Hunter 			host->data_cmd->error = -ETIMEDOUT;
3246d7422fb4SAdrian Hunter 			sdhci_finish_mrq(host, host->data_cmd->mrq);
32471c6a0718SPierre Ossman 		} else {
324817b0429dSPierre Ossman 			host->cmd->error = -ETIMEDOUT;
3249d7422fb4SAdrian Hunter 			sdhci_finish_mrq(host, host->cmd->mrq);
32501c6a0718SPierre Ossman 		}
32511c6a0718SPierre Ossman 	}
32521c6a0718SPierre Ossman 
32531c6a0718SPierre Ossman 	spin_unlock_irqrestore(&host->lock, flags);
32541c6a0718SPierre Ossman }
32551c6a0718SPierre Ossman 
32561c6a0718SPierre Ossman /*****************************************************************************\
32571c6a0718SPierre Ossman  *                                                                           *
32581c6a0718SPierre Ossman  * Interrupt handling                                                        *
32591c6a0718SPierre Ossman  *                                                                           *
32601c6a0718SPierre Ossman \*****************************************************************************/
32611c6a0718SPierre Ossman 
sdhci_cmd_irq(struct sdhci_host * host,u32 intmask,u32 * intmask_p)32624bf78099SAdrian Hunter static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p)
32631c6a0718SPierre Ossman {
3264af849c86SAdrian Hunter 	/* Handle auto-CMD12 error */
3265af849c86SAdrian Hunter 	if (intmask & SDHCI_INT_AUTO_CMD_ERR && host->data_cmd) {
3266af849c86SAdrian Hunter 		struct mmc_request *mrq = host->data_cmd->mrq;
3267af849c86SAdrian Hunter 		u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS);
3268af849c86SAdrian Hunter 		int data_err_bit = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ?
3269af849c86SAdrian Hunter 				   SDHCI_INT_DATA_TIMEOUT :
3270af849c86SAdrian Hunter 				   SDHCI_INT_DATA_CRC;
3271af849c86SAdrian Hunter 
3272af849c86SAdrian Hunter 		/* Treat auto-CMD12 error the same as data error */
3273af849c86SAdrian Hunter 		if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) {
3274af849c86SAdrian Hunter 			*intmask_p |= data_err_bit;
3275af849c86SAdrian Hunter 			return;
3276af849c86SAdrian Hunter 		}
3277af849c86SAdrian Hunter 	}
3278af849c86SAdrian Hunter 
32791c6a0718SPierre Ossman 	if (!host->cmd) {
3280ed1563deSAdrian Hunter 		/*
3281ed1563deSAdrian Hunter 		 * SDHCI recovers from errors by resetting the cmd and data
3282ed1563deSAdrian Hunter 		 * circuits.  Until that is done, there very well might be more
3283ed1563deSAdrian Hunter 		 * interrupts, so ignore them in that case.
3284ed1563deSAdrian Hunter 		 */
3285ed1563deSAdrian Hunter 		if (host->pending_reset)
3286ed1563deSAdrian Hunter 			return;
32872e4456f0SMarek Vasut 		pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n",
3288b67ac3f3SPierre Ossman 		       mmc_hostname(host->mmc), (unsigned)intmask);
3289efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, UNEXPECTED_IRQ);
32901c6a0718SPierre Ossman 		sdhci_dumpregs(host);
32911c6a0718SPierre Ossman 		return;
32921c6a0718SPierre Ossman 	}
32931c6a0718SPierre Ossman 
3294ec014cbaSRussell King 	if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC |
3295ec014cbaSRussell King 		       SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) {
3296efe8f5c9SShaik Sajida Bhanu 		if (intmask & SDHCI_INT_TIMEOUT) {
329717b0429dSPierre Ossman 			host->cmd->error = -ETIMEDOUT;
3298efe8f5c9SShaik Sajida Bhanu 			sdhci_err_stats_inc(host, CMD_TIMEOUT);
3299efe8f5c9SShaik Sajida Bhanu 		} else {
330017b0429dSPierre Ossman 			host->cmd->error = -EILSEQ;
3301efe8f5c9SShaik Sajida Bhanu 			if (!mmc_op_tuning(host->cmd->opcode))
3302efe8f5c9SShaik Sajida Bhanu 				sdhci_err_stats_inc(host, CMD_CRC);
3303efe8f5c9SShaik Sajida Bhanu 		}
33044bf78099SAdrian Hunter 		/* Treat data command CRC error the same as data CRC error */
330571fcbda0SRussell King 		if (host->cmd->data &&
330671fcbda0SRussell King 		    (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) ==
330771fcbda0SRussell King 		     SDHCI_INT_CRC) {
330871fcbda0SRussell King 			host->cmd = NULL;
33094bf78099SAdrian Hunter 			*intmask_p |= SDHCI_INT_DATA_CRC;
331071fcbda0SRussell King 			return;
331171fcbda0SRussell King 		}
331271fcbda0SRussell King 
331319d2f695SAdrian Hunter 		__sdhci_finish_mrq(host, host->cmd->mrq);
3314e809517fSPierre Ossman 		return;
3315e809517fSPierre Ossman 	}
3316e809517fSPierre Ossman 
3317af849c86SAdrian Hunter 	/* Handle auto-CMD23 error */
3318af849c86SAdrian Hunter 	if (intmask & SDHCI_INT_AUTO_CMD_ERR) {
3319af849c86SAdrian Hunter 		struct mmc_request *mrq = host->cmd->mrq;
3320af849c86SAdrian Hunter 		u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS);
3321af849c86SAdrian Hunter 		int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ?
3322af849c86SAdrian Hunter 			  -ETIMEDOUT :
3323af849c86SAdrian Hunter 			  -EILSEQ;
3324af849c86SAdrian Hunter 
3325efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, AUTO_CMD);
3326efe8f5c9SShaik Sajida Bhanu 
332738929d4fSChanWoo Lee 		if (sdhci_auto_cmd23(host, mrq)) {
3328af849c86SAdrian Hunter 			mrq->sbc->error = err;
332919d2f695SAdrian Hunter 			__sdhci_finish_mrq(host, mrq);
3330af849c86SAdrian Hunter 			return;
3331af849c86SAdrian Hunter 		}
3332af849c86SAdrian Hunter 	}
3333af849c86SAdrian Hunter 
3334e809517fSPierre Ossman 	if (intmask & SDHCI_INT_RESPONSE)
333543b58b36SPierre Ossman 		sdhci_finish_command(host);
33361c6a0718SPierre Ossman }
33371c6a0718SPierre Ossman 
sdhci_adma_show_error(struct sdhci_host * host)333808621b18SAdrian Hunter static void sdhci_adma_show_error(struct sdhci_host *host)
33396882a8c0SBen Dooks {
33401c3d5f6dSAdrian Hunter 	void *desc = host->adma_table;
3341d1c536e3SRussell King 	dma_addr_t dma = host->adma_addr;
33426882a8c0SBen Dooks 
33436882a8c0SBen Dooks 	sdhci_dumpregs(host);
33446882a8c0SBen Dooks 
33456882a8c0SBen Dooks 	while (true) {
3346e57a5f61SAdrian Hunter 		struct sdhci_adma2_64_desc *dma_desc = desc;
33476882a8c0SBen Dooks 
3348e57a5f61SAdrian Hunter 		if (host->flags & SDHCI_USE_64_BIT_DMA)
3349d1c536e3SRussell King 			SDHCI_DUMP("%08llx: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n",
3350d1c536e3SRussell King 			    (unsigned long long)dma,
3351d1c536e3SRussell King 			    le32_to_cpu(dma_desc->addr_hi),
3352e57a5f61SAdrian Hunter 			    le32_to_cpu(dma_desc->addr_lo),
3353e57a5f61SAdrian Hunter 			    le16_to_cpu(dma_desc->len),
3354e57a5f61SAdrian Hunter 			    le16_to_cpu(dma_desc->cmd));
3355e57a5f61SAdrian Hunter 		else
3356d1c536e3SRussell King 			SDHCI_DUMP("%08llx: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
3357d1c536e3SRussell King 			    (unsigned long long)dma,
3358d1c536e3SRussell King 			    le32_to_cpu(dma_desc->addr_lo),
33590545230fSAdrian Hunter 			    le16_to_cpu(dma_desc->len),
33600545230fSAdrian Hunter 			    le16_to_cpu(dma_desc->cmd));
33616882a8c0SBen Dooks 
336276fe379aSAdrian Hunter 		desc += host->desc_sz;
3363d1c536e3SRussell King 		dma += host->desc_sz;
33646882a8c0SBen Dooks 
33650545230fSAdrian Hunter 		if (dma_desc->cmd & cpu_to_le16(ADMA2_END))
33666882a8c0SBen Dooks 			break;
33676882a8c0SBen Dooks 	}
33686882a8c0SBen Dooks }
33696882a8c0SBen Dooks 
sdhci_data_irq(struct sdhci_host * host,u32 intmask)33701c6a0718SPierre Ossman static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
33711c6a0718SPierre Ossman {
3372f4ff24f8SHaibo Chen 	/*
3373f4ff24f8SHaibo Chen 	 * CMD19 generates _only_ Buffer Read Ready interrupt if
3374f4ff24f8SHaibo Chen 	 * use sdhci_send_tuning.
3375f4ff24f8SHaibo Chen 	 * Need to exclude this case: PIO mode and use mmc_send_tuning,
3376f4ff24f8SHaibo Chen 	 * If not, sdhci_transfer_pio will never be called, make the
3377f4ff24f8SHaibo Chen 	 * SDHCI_INT_DATA_AVAIL always there, stuck in irq storm.
3378f4ff24f8SHaibo Chen 	 */
3379f4ff24f8SHaibo Chen 	if (intmask & SDHCI_INT_DATA_AVAIL && !host->data) {
3380b98e7e8dSChanWoo Lee 		if (mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) {
3381b513ea25SArindam Nath 			host->tuning_done = 1;
3382b513ea25SArindam Nath 			wake_up(&host->buf_ready_int);
3383b513ea25SArindam Nath 			return;
3384b513ea25SArindam Nath 		}
3385b513ea25SArindam Nath 	}
3386b513ea25SArindam Nath 
33871c6a0718SPierre Ossman 	if (!host->data) {
33887c89a3d9SAdrian Hunter 		struct mmc_command *data_cmd = host->data_cmd;
33897c89a3d9SAdrian Hunter 
33901c6a0718SPierre Ossman 		/*
3391e809517fSPierre Ossman 		 * The "data complete" interrupt is also used to
3392e809517fSPierre Ossman 		 * indicate that a busy state has ended. See comment
3393e809517fSPierre Ossman 		 * above in sdhci_cmd_irq().
33941c6a0718SPierre Ossman 		 */
33957c89a3d9SAdrian Hunter 		if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) {
3396c5abd5e8SMatthieu CASTET 			if (intmask & SDHCI_INT_DATA_TIMEOUT) {
339769b962a6SAdrian Hunter 				host->data_cmd = NULL;
33987c89a3d9SAdrian Hunter 				data_cmd->error = -ETIMEDOUT;
3399efe8f5c9SShaik Sajida Bhanu 				sdhci_err_stats_inc(host, CMD_TIMEOUT);
340019d2f695SAdrian Hunter 				__sdhci_finish_mrq(host, data_cmd->mrq);
3401c5abd5e8SMatthieu CASTET 				return;
3402c5abd5e8SMatthieu CASTET 			}
3403e809517fSPierre Ossman 			if (intmask & SDHCI_INT_DATA_END) {
340469b962a6SAdrian Hunter 				host->data_cmd = NULL;
3405e99783a4SChanho Min 				/*
3406e99783a4SChanho Min 				 * Some cards handle busy-end interrupt
3407e99783a4SChanho Min 				 * before the command completed, so make
3408e99783a4SChanho Min 				 * sure we do things in the proper order.
3409e99783a4SChanho Min 				 */
3410ea968023SAdrian Hunter 				if (host->cmd == data_cmd)
3411ea968023SAdrian Hunter 					return;
3412ea968023SAdrian Hunter 
341319d2f695SAdrian Hunter 				__sdhci_finish_mrq(host, data_cmd->mrq);
34141c6a0718SPierre Ossman 				return;
3415e809517fSPierre Ossman 			}
3416e809517fSPierre Ossman 		}
34171c6a0718SPierre Ossman 
3418ed1563deSAdrian Hunter 		/*
3419ed1563deSAdrian Hunter 		 * SDHCI recovers from errors by resetting the cmd and data
3420ed1563deSAdrian Hunter 		 * circuits. Until that is done, there very well might be more
3421ed1563deSAdrian Hunter 		 * interrupts, so ignore them in that case.
3422ed1563deSAdrian Hunter 		 */
3423ed1563deSAdrian Hunter 		if (host->pending_reset)
3424ed1563deSAdrian Hunter 			return;
3425ed1563deSAdrian Hunter 
34262e4456f0SMarek Vasut 		pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
3427b67ac3f3SPierre Ossman 		       mmc_hostname(host->mmc), (unsigned)intmask);
3428efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, UNEXPECTED_IRQ);
34291c6a0718SPierre Ossman 		sdhci_dumpregs(host);
34301c6a0718SPierre Ossman 
34311c6a0718SPierre Ossman 		return;
34321c6a0718SPierre Ossman 	}
34331c6a0718SPierre Ossman 
3434efe8f5c9SShaik Sajida Bhanu 	if (intmask & SDHCI_INT_DATA_TIMEOUT) {
343517b0429dSPierre Ossman 		host->data->error = -ETIMEDOUT;
3436efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, DAT_TIMEOUT);
3437efe8f5c9SShaik Sajida Bhanu 	} else if (intmask & SDHCI_INT_DATA_END_BIT) {
343822113efdSAries Lee 		host->data->error = -EILSEQ;
3439efe8f5c9SShaik Sajida Bhanu 		if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
3440efe8f5c9SShaik Sajida Bhanu 			sdhci_err_stats_inc(host, DAT_CRC);
3441d9ae0aa8SAdrian Hunter 	} else if ((intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_TUNING_ERROR)) &&
344222113efdSAries Lee 		SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))
3443efe8f5c9SShaik Sajida Bhanu 			!= MMC_BUS_TEST_R) {
344417b0429dSPierre Ossman 		host->data->error = -EILSEQ;
3445efe8f5c9SShaik Sajida Bhanu 		if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
3446efe8f5c9SShaik Sajida Bhanu 			sdhci_err_stats_inc(host, DAT_CRC);
3447d9ae0aa8SAdrian Hunter 		if (intmask & SDHCI_INT_TUNING_ERROR) {
3448d9ae0aa8SAdrian Hunter 			u16 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
3449d9ae0aa8SAdrian Hunter 
3450d9ae0aa8SAdrian Hunter 			ctrl2 &= ~SDHCI_CTRL_TUNED_CLK;
3451d9ae0aa8SAdrian Hunter 			sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
3452d9ae0aa8SAdrian Hunter 		}
3453efe8f5c9SShaik Sajida Bhanu 	} else if (intmask & SDHCI_INT_ADMA_ERROR) {
3454d1c536e3SRussell King 		pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc),
3455d1c536e3SRussell King 		       intmask);
345608621b18SAdrian Hunter 		sdhci_adma_show_error(host);
3457efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, ADMA);
34582134a922SPierre Ossman 		host->data->error = -EIO;
3459a4071fbbSHaijun Zhang 		if (host->ops->adma_workaround)
3460a4071fbbSHaijun Zhang 			host->ops->adma_workaround(host, intmask);
34616882a8c0SBen Dooks 	}
34621c6a0718SPierre Ossman 
346317b0429dSPierre Ossman 	if (host->data->error)
34641c6a0718SPierre Ossman 		sdhci_finish_data(host);
34651c6a0718SPierre Ossman 	else {
34661c6a0718SPierre Ossman 		if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
34671c6a0718SPierre Ossman 			sdhci_transfer_pio(host);
34681c6a0718SPierre Ossman 
34696ba736a1SPierre Ossman 		/*
34706ba736a1SPierre Ossman 		 * We currently don't do anything fancy with DMA
34716ba736a1SPierre Ossman 		 * boundaries, but as we can't disable the feature
34726ba736a1SPierre Ossman 		 * we need to at least restart the transfer.
3473f6a03cbfSMikko Vinni 		 *
3474f6a03cbfSMikko Vinni 		 * According to the spec sdhci_readl(host, SDHCI_DMA_ADDRESS)
3475f6a03cbfSMikko Vinni 		 * should return a valid address to continue from, but as
3476f6a03cbfSMikko Vinni 		 * some controllers are faulty, don't trust them.
34776ba736a1SPierre Ossman 		 */
3478f6a03cbfSMikko Vinni 		if (intmask & SDHCI_INT_DMA_END) {
3479917a0c52SChunyan Zhang 			dma_addr_t dmastart, dmanow;
3480bd9b9027SLinus Walleij 
3481bd9b9027SLinus Walleij 			dmastart = sdhci_sdma_address(host);
3482f6a03cbfSMikko Vinni 			dmanow = dmastart + host->data->bytes_xfered;
3483f6a03cbfSMikko Vinni 			/*
3484f6a03cbfSMikko Vinni 			 * Force update to the next DMA block boundary.
3485f6a03cbfSMikko Vinni 			 */
3486f6a03cbfSMikko Vinni 			dmanow = (dmanow &
3487917a0c52SChunyan Zhang 				~((dma_addr_t)SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
3488f6a03cbfSMikko Vinni 				SDHCI_DEFAULT_BOUNDARY_SIZE;
3489f6a03cbfSMikko Vinni 			host->data->bytes_xfered = dmanow - dmastart;
3490917a0c52SChunyan Zhang 			DBG("DMA base %pad, transferred 0x%06x bytes, next %pad\n",
3491917a0c52SChunyan Zhang 			    &dmastart, host->data->bytes_xfered, &dmanow);
3492917a0c52SChunyan Zhang 			sdhci_set_sdma_addr(host, dmanow);
3493f6a03cbfSMikko Vinni 		}
34946ba736a1SPierre Ossman 
3495e538fbe8SPierre Ossman 		if (intmask & SDHCI_INT_DATA_END) {
34967c89a3d9SAdrian Hunter 			if (host->cmd == host->data_cmd) {
3497e538fbe8SPierre Ossman 				/*
3498e538fbe8SPierre Ossman 				 * Data managed to finish before the
3499e538fbe8SPierre Ossman 				 * command completed. Make sure we do
3500e538fbe8SPierre Ossman 				 * things in the proper order.
3501e538fbe8SPierre Ossman 				 */
3502e538fbe8SPierre Ossman 				host->data_early = 1;
3503e538fbe8SPierre Ossman 			} else {
35041c6a0718SPierre Ossman 				sdhci_finish_data(host);
35051c6a0718SPierre Ossman 			}
35061c6a0718SPierre Ossman 		}
3507e538fbe8SPierre Ossman 	}
3508e538fbe8SPierre Ossman }
35091c6a0718SPierre Ossman 
sdhci_defer_done(struct sdhci_host * host,struct mmc_request * mrq)351019d2f695SAdrian Hunter static inline bool sdhci_defer_done(struct sdhci_host *host,
351119d2f695SAdrian Hunter 				    struct mmc_request *mrq)
351219d2f695SAdrian Hunter {
351319d2f695SAdrian Hunter 	struct mmc_data *data = mrq->data;
351419d2f695SAdrian Hunter 
35154730831cSBaolin Wang 	return host->pending_reset || host->always_defer_done ||
351619d2f695SAdrian Hunter 	       ((host->flags & SDHCI_REQ_USE_DMA) && data &&
351719d2f695SAdrian Hunter 		data->host_cookie == COOKIE_MAPPED);
351819d2f695SAdrian Hunter }
351919d2f695SAdrian Hunter 
sdhci_irq(int irq,void * dev_id)35201c6a0718SPierre Ossman static irqreturn_t sdhci_irq(int irq, void *dev_id)
35211c6a0718SPierre Ossman {
352219d2f695SAdrian Hunter 	struct mmc_request *mrqs_done[SDHCI_MAX_MRQS] = {0};
3523781e989cSRussell King 	irqreturn_t result = IRQ_NONE;
35241c6a0718SPierre Ossman 	struct sdhci_host *host = dev_id;
352541005003SRussell King 	u32 intmask, mask, unexpected = 0;
3526781e989cSRussell King 	int max_loops = 16;
352719d2f695SAdrian Hunter 	int i;
35281c6a0718SPierre Ossman 
35291c6a0718SPierre Ossman 	spin_lock(&host->lock);
35301c6a0718SPierre Ossman 
3531af5d2b7bSUlf Hansson 	if (host->runtime_suspended) {
353266fd8ad5SAdrian Hunter 		spin_unlock(&host->lock);
3533655bca76SAdrian Hunter 		return IRQ_NONE;
353466fd8ad5SAdrian Hunter 	}
353566fd8ad5SAdrian Hunter 
35364e4141a5SAnton Vorontsov 	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
35371c6a0718SPierre Ossman 	if (!intmask || intmask == 0xffffffff) {
35381c6a0718SPierre Ossman 		result = IRQ_NONE;
35391c6a0718SPierre Ossman 		goto out;
35401c6a0718SPierre Ossman 	}
35411c6a0718SPierre Ossman 
354241005003SRussell King 	do {
3543f12e39dbSAdrian Hunter 		DBG("IRQ status 0x%08x\n", intmask);
3544f12e39dbSAdrian Hunter 
3545f12e39dbSAdrian Hunter 		if (host->ops->irq) {
3546f12e39dbSAdrian Hunter 			intmask = host->ops->irq(host, intmask);
3547f12e39dbSAdrian Hunter 			if (!intmask)
3548f12e39dbSAdrian Hunter 				goto cont;
3549f12e39dbSAdrian Hunter 		}
3550f12e39dbSAdrian Hunter 
355141005003SRussell King 		/* Clear selected interrupts. */
355241005003SRussell King 		mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
355341005003SRussell King 				  SDHCI_INT_BUS_POWER);
355441005003SRussell King 		sdhci_writel(host, mask, SDHCI_INT_STATUS);
355541005003SRussell King 
35561c6a0718SPierre Ossman 		if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
3557d25928d1SShawn Guo 			u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
3558d25928d1SShawn Guo 				      SDHCI_CARD_PRESENT;
3559d25928d1SShawn Guo 
3560d25928d1SShawn Guo 			/*
356141005003SRussell King 			 * There is a observation on i.mx esdhc.  INSERT
356241005003SRussell King 			 * bit will be immediately set again when it gets
356341005003SRussell King 			 * cleared, if a card is inserted.  We have to mask
356441005003SRussell King 			 * the irq to prevent interrupt storm which will
356541005003SRussell King 			 * freeze the system.  And the REMOVE gets the
356641005003SRussell King 			 * same situation.
3567d25928d1SShawn Guo 			 *
356841005003SRussell King 			 * More testing are needed here to ensure it works
356941005003SRussell King 			 * for other platforms though.
3570d25928d1SShawn Guo 			 */
3571b537f94cSRussell King 			host->ier &= ~(SDHCI_INT_CARD_INSERT |
3572d25928d1SShawn Guo 				       SDHCI_INT_CARD_REMOVE);
3573b537f94cSRussell King 			host->ier |= present ? SDHCI_INT_CARD_REMOVE :
3574b537f94cSRussell King 					       SDHCI_INT_CARD_INSERT;
3575b537f94cSRussell King 			sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
3576b537f94cSRussell King 			sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
3577d25928d1SShawn Guo 
35784e4141a5SAnton Vorontsov 			sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
35794e4141a5SAnton Vorontsov 				     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
35803560db8eSRussell King 
35813560db8eSRussell King 			host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT |
35823560db8eSRussell King 						       SDHCI_INT_CARD_REMOVE);
35833560db8eSRussell King 			result = IRQ_WAKE_THREAD;
35841c6a0718SPierre Ossman 		}
35851c6a0718SPierre Ossman 
358641005003SRussell King 		if (intmask & SDHCI_INT_CMD_MASK)
35874bf78099SAdrian Hunter 			sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask);
35881c6a0718SPierre Ossman 
358941005003SRussell King 		if (intmask & SDHCI_INT_DATA_MASK)
35901c6a0718SPierre Ossman 			sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
35911c6a0718SPierre Ossman 
359241005003SRussell King 		if (intmask & SDHCI_INT_BUS_POWER)
3593a3c76eb9SGirish K S 			pr_err("%s: Card is consuming too much power!\n",
35941c6a0718SPierre Ossman 				mmc_hostname(host->mmc));
35951c6a0718SPierre Ossman 
3596f37b20ebSDong Aisheng 		if (intmask & SDHCI_INT_RETUNE)
3597f37b20ebSDong Aisheng 			mmc_retune_needed(host->mmc);
3598f37b20ebSDong Aisheng 
3599161e6d44SGabriel Krisman Bertazi 		if ((intmask & SDHCI_INT_CARD_INT) &&
3600161e6d44SGabriel Krisman Bertazi 		    (host->ier & SDHCI_INT_CARD_INT)) {
3601781e989cSRussell King 			sdhci_enable_sdio_irq_nolock(host, false);
360289f3c365SAdrian Hunter 			sdio_signal_irq(host->mmc);
3603781e989cSRussell King 		}
3604f75979b7SPierre Ossman 
360541005003SRussell King 		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
360641005003SRussell King 			     SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
360741005003SRussell King 			     SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
3608f37b20ebSDong Aisheng 			     SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT);
3609f75979b7SPierre Ossman 
36101c6a0718SPierre Ossman 		if (intmask) {
36116379b237SAlexander Stein 			unexpected |= intmask;
36124e4141a5SAnton Vorontsov 			sdhci_writel(host, intmask, SDHCI_INT_STATUS);
36131c6a0718SPierre Ossman 		}
3614f12e39dbSAdrian Hunter cont:
3615781e989cSRussell King 		if (result == IRQ_NONE)
36161c6a0718SPierre Ossman 			result = IRQ_HANDLED;
36171c6a0718SPierre Ossman 
36186379b237SAlexander Stein 		intmask = sdhci_readl(host, SDHCI_INT_STATUS);
361941005003SRussell King 	} while (intmask && --max_loops);
362019d2f695SAdrian Hunter 
362119d2f695SAdrian Hunter 	/* Determine if mrqs can be completed immediately */
362219d2f695SAdrian Hunter 	for (i = 0; i < SDHCI_MAX_MRQS; i++) {
362319d2f695SAdrian Hunter 		struct mmc_request *mrq = host->mrqs_done[i];
362419d2f695SAdrian Hunter 
362519d2f695SAdrian Hunter 		if (!mrq)
362619d2f695SAdrian Hunter 			continue;
362719d2f695SAdrian Hunter 
362819d2f695SAdrian Hunter 		if (sdhci_defer_done(host, mrq)) {
3629c07a48c2SAdrian Hunter 			result = IRQ_WAKE_THREAD;
363019d2f695SAdrian Hunter 		} else {
363119d2f695SAdrian Hunter 			mrqs_done[i] = mrq;
363219d2f695SAdrian Hunter 			host->mrqs_done[i] = NULL;
363319d2f695SAdrian Hunter 		}
363419d2f695SAdrian Hunter 	}
36351c6a0718SPierre Ossman out:
3636845c939eSAdrian Hunter 	if (host->deferred_cmd)
3637845c939eSAdrian Hunter 		result = IRQ_WAKE_THREAD;
3638845c939eSAdrian Hunter 
36391c6a0718SPierre Ossman 	spin_unlock(&host->lock);
36401c6a0718SPierre Ossman 
364119d2f695SAdrian Hunter 	/* Process mrqs ready for immediate completion */
364219d2f695SAdrian Hunter 	for (i = 0; i < SDHCI_MAX_MRQS; i++) {
36431774b002SBaolin Wang 		if (!mrqs_done[i])
36441774b002SBaolin Wang 			continue;
36451774b002SBaolin Wang 
36461774b002SBaolin Wang 		if (host->ops->request_done)
36471774b002SBaolin Wang 			host->ops->request_done(host, mrqs_done[i]);
36481774b002SBaolin Wang 		else
364919d2f695SAdrian Hunter 			mmc_request_done(host->mmc, mrqs_done[i]);
365019d2f695SAdrian Hunter 	}
365119d2f695SAdrian Hunter 
36526379b237SAlexander Stein 	if (unexpected) {
36536379b237SAlexander Stein 		pr_err("%s: Unexpected interrupt 0x%08x.\n",
36546379b237SAlexander Stein 			   mmc_hostname(host->mmc), unexpected);
3655efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, UNEXPECTED_IRQ);
36566379b237SAlexander Stein 		sdhci_dumpregs(host);
36576379b237SAlexander Stein 	}
3658f75979b7SPierre Ossman 
36591c6a0718SPierre Ossman 	return result;
36601c6a0718SPierre Ossman }
36611c6a0718SPierre Ossman 
sdhci_thread_irq(int irq,void * dev_id)3662781e989cSRussell King static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
3663781e989cSRussell King {
3664781e989cSRussell King 	struct sdhci_host *host = dev_id;
3665845c939eSAdrian Hunter 	struct mmc_command *cmd;
3666781e989cSRussell King 	unsigned long flags;
3667781e989cSRussell King 	u32 isr;
3668781e989cSRussell King 
3669c07a48c2SAdrian Hunter 	while (!sdhci_request_done(host))
3670c07a48c2SAdrian Hunter 		;
3671c07a48c2SAdrian Hunter 
3672781e989cSRussell King 	spin_lock_irqsave(&host->lock, flags);
3673845c939eSAdrian Hunter 
3674781e989cSRussell King 	isr = host->thread_isr;
3675781e989cSRussell King 	host->thread_isr = 0;
3676845c939eSAdrian Hunter 
3677845c939eSAdrian Hunter 	cmd = host->deferred_cmd;
3678845c939eSAdrian Hunter 	if (cmd && !sdhci_send_command_retry(host, cmd, flags))
3679845c939eSAdrian Hunter 		sdhci_finish_mrq(host, cmd->mrq);
3680845c939eSAdrian Hunter 
3681781e989cSRussell King 	spin_unlock_irqrestore(&host->lock, flags);
3682781e989cSRussell King 
36833560db8eSRussell King 	if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
3684d3940f27SAdrian Hunter 		struct mmc_host *mmc = host->mmc;
3685d3940f27SAdrian Hunter 
3686d3940f27SAdrian Hunter 		mmc->ops->card_event(mmc);
3687d3940f27SAdrian Hunter 		mmc_detect_change(mmc, msecs_to_jiffies(200));
36883560db8eSRussell King 	}
36893560db8eSRussell King 
3690c07a48c2SAdrian Hunter 	return IRQ_HANDLED;
3691781e989cSRussell King }
3692781e989cSRussell King 
36931c6a0718SPierre Ossman /*****************************************************************************\
36941c6a0718SPierre Ossman  *                                                                           *
36951c6a0718SPierre Ossman  * Suspend/resume                                                            *
36961c6a0718SPierre Ossman  *                                                                           *
36971c6a0718SPierre Ossman \*****************************************************************************/
36981c6a0718SPierre Ossman 
36991c6a0718SPierre Ossman #ifdef CONFIG_PM
37009c316b38SAdrian Hunter 
sdhci_cd_irq_can_wakeup(struct sdhci_host * host)37019c316b38SAdrian Hunter static bool sdhci_cd_irq_can_wakeup(struct sdhci_host *host)
37029c316b38SAdrian Hunter {
37039c316b38SAdrian Hunter 	return mmc_card_is_removable(host->mmc) &&
37049c316b38SAdrian Hunter 	       !(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
37059c316b38SAdrian Hunter 	       !mmc_can_gpio_cd(host->mmc);
37069c316b38SAdrian Hunter }
37079c316b38SAdrian Hunter 
370884d62605SLudovic Desroches /*
370984d62605SLudovic Desroches  * To enable wakeup events, the corresponding events have to be enabled in
371084d62605SLudovic Desroches  * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal
371184d62605SLudovic Desroches  * Table' in the SD Host Controller Standard Specification.
371284d62605SLudovic Desroches  * It is useless to restore SDHCI_INT_ENABLE state in
371384d62605SLudovic Desroches  * sdhci_disable_irq_wakeups() since it will be set by
371484d62605SLudovic Desroches  * sdhci_enable_card_detection() or sdhci_init().
371584d62605SLudovic Desroches  */
sdhci_enable_irq_wakeups(struct sdhci_host * host)371658e79b60SAdrian Hunter static bool sdhci_enable_irq_wakeups(struct sdhci_host *host)
3717ad080d79SKevin Liu {
371881b14543SAdrian Hunter 	u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE |
371981b14543SAdrian Hunter 		  SDHCI_WAKE_ON_INT;
372081b14543SAdrian Hunter 	u32 irq_val = 0;
372181b14543SAdrian Hunter 	u8 wake_val = 0;
3722ad080d79SKevin Liu 	u8 val;
372381b14543SAdrian Hunter 
37249c316b38SAdrian Hunter 	if (sdhci_cd_irq_can_wakeup(host)) {
372581b14543SAdrian Hunter 		wake_val |= SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE;
372681b14543SAdrian Hunter 		irq_val |= SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE;
372781b14543SAdrian Hunter 	}
372881b14543SAdrian Hunter 
3729d5d568faSAdrian Hunter 	if (mmc_card_wake_sdio_irq(host->mmc)) {
373081b14543SAdrian Hunter 		wake_val |= SDHCI_WAKE_ON_INT;
373181b14543SAdrian Hunter 		irq_val |= SDHCI_INT_CARD_INT;
3732d5d568faSAdrian Hunter 	}
3733d5d568faSAdrian Hunter 
3734d5d568faSAdrian Hunter 	if (!irq_val)
3735d5d568faSAdrian Hunter 		return false;
3736ad080d79SKevin Liu 
3737ad080d79SKevin Liu 	val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
373881b14543SAdrian Hunter 	val &= ~mask;
373981b14543SAdrian Hunter 	val |= wake_val;
3740ad080d79SKevin Liu 	sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
374181b14543SAdrian Hunter 
374284d62605SLudovic Desroches 	sdhci_writel(host, irq_val, SDHCI_INT_ENABLE);
374358e79b60SAdrian Hunter 
374458e79b60SAdrian Hunter 	host->irq_wake_enabled = !enable_irq_wake(host->irq);
374558e79b60SAdrian Hunter 
374658e79b60SAdrian Hunter 	return host->irq_wake_enabled;
3747ad080d79SKevin Liu }
3748ad080d79SKevin Liu 
sdhci_disable_irq_wakeups(struct sdhci_host * host)37490b10f478SFabio Estevam static void sdhci_disable_irq_wakeups(struct sdhci_host *host)
3750ad080d79SKevin Liu {
3751ad080d79SKevin Liu 	u8 val;
3752ad080d79SKevin Liu 	u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE
3753ad080d79SKevin Liu 			| SDHCI_WAKE_ON_INT;
3754ad080d79SKevin Liu 
3755ad080d79SKevin Liu 	val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
3756ad080d79SKevin Liu 	val &= ~mask;
3757ad080d79SKevin Liu 	sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
375858e79b60SAdrian Hunter 
375958e79b60SAdrian Hunter 	disable_irq_wake(host->irq);
376058e79b60SAdrian Hunter 
376158e79b60SAdrian Hunter 	host->irq_wake_enabled = false;
3762ad080d79SKevin Liu }
37631c6a0718SPierre Ossman 
sdhci_suspend_host(struct sdhci_host * host)376429495aa0SManuel Lauss int sdhci_suspend_host(struct sdhci_host *host)
37651c6a0718SPierre Ossman {
37667260cf5eSAnton Vorontsov 	sdhci_disable_card_detection(host);
37677260cf5eSAnton Vorontsov 
376866c39dfcSAdrian Hunter 	mmc_retune_timer_stop(host->mmc);
3769cf2b5eeaSArindam Nath 
377058e79b60SAdrian Hunter 	if (!device_may_wakeup(mmc_dev(host->mmc)) ||
377158e79b60SAdrian Hunter 	    !sdhci_enable_irq_wakeups(host)) {
3772b537f94cSRussell King 		host->ier = 0;
3773b537f94cSRussell King 		sdhci_writel(host, 0, SDHCI_INT_ENABLE);
3774b537f94cSRussell King 		sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
3775b8c86fc5SPierre Ossman 		free_irq(host->irq, host);
3776ad080d79SKevin Liu 	}
377758e79b60SAdrian Hunter 
37784ee14ec6SUlf Hansson 	return 0;
3779b8c86fc5SPierre Ossman }
3780b8c86fc5SPierre Ossman 
3781b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_suspend_host);
3782b8c86fc5SPierre Ossman 
sdhci_resume_host(struct sdhci_host * host)3783b8c86fc5SPierre Ossman int sdhci_resume_host(struct sdhci_host *host)
3784b8c86fc5SPierre Ossman {
3785d3940f27SAdrian Hunter 	struct mmc_host *mmc = host->mmc;
37864ee14ec6SUlf Hansson 	int ret = 0;
3787b8c86fc5SPierre Ossman 
3788a13abc7bSRichard Röjfors 	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
3789b8c86fc5SPierre Ossman 		if (host->ops->enable_dma)
3790b8c86fc5SPierre Ossman 			host->ops->enable_dma(host);
3791b8c86fc5SPierre Ossman 	}
3792b8c86fc5SPierre Ossman 
3793d2f025b0SJisheng Zhang 	if ((mmc->pm_flags & MMC_PM_KEEP_POWER) &&
37946308d290SAdrian Hunter 	    (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) {
37956308d290SAdrian Hunter 		/* Card keeps power but host controller does not */
37966308d290SAdrian Hunter 		sdhci_init(host, 0);
37976308d290SAdrian Hunter 		host->pwr = 0;
37986308d290SAdrian Hunter 		host->clock = 0;
3799c981cdfbSAdrian Hunter 		host->reinit_uhs = true;
3800d3940f27SAdrian Hunter 		mmc->ops->set_ios(mmc, &mmc->ios);
38016308d290SAdrian Hunter 	} else {
3802d2f025b0SJisheng Zhang 		sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER));
38036308d290SAdrian Hunter 	}
3804b8c86fc5SPierre Ossman 
380558e79b60SAdrian Hunter 	if (host->irq_wake_enabled) {
380658e79b60SAdrian Hunter 		sdhci_disable_irq_wakeups(host);
380758e79b60SAdrian Hunter 	} else {
380814a7b416SHaibo Chen 		ret = request_threaded_irq(host->irq, sdhci_irq,
380914a7b416SHaibo Chen 					   sdhci_thread_irq, IRQF_SHARED,
3810d2f025b0SJisheng Zhang 					   mmc_hostname(mmc), host);
381114a7b416SHaibo Chen 		if (ret)
381214a7b416SHaibo Chen 			return ret;
381314a7b416SHaibo Chen 	}
381414a7b416SHaibo Chen 
38157260cf5eSAnton Vorontsov 	sdhci_enable_card_detection(host);
38167260cf5eSAnton Vorontsov 
38172f4cbb3dSNicolas Pitre 	return ret;
38181c6a0718SPierre Ossman }
38191c6a0718SPierre Ossman 
3820b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_resume_host);
382166fd8ad5SAdrian Hunter 
sdhci_runtime_suspend_host(struct sdhci_host * host)382266fd8ad5SAdrian Hunter int sdhci_runtime_suspend_host(struct sdhci_host *host)
382366fd8ad5SAdrian Hunter {
382466fd8ad5SAdrian Hunter 	unsigned long flags;
382566fd8ad5SAdrian Hunter 
382666c39dfcSAdrian Hunter 	mmc_retune_timer_stop(host->mmc);
382766fd8ad5SAdrian Hunter 
382866fd8ad5SAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
3829b537f94cSRussell King 	host->ier &= SDHCI_INT_CARD_INT;
3830b537f94cSRussell King 	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
3831b537f94cSRussell King 	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
383266fd8ad5SAdrian Hunter 	spin_unlock_irqrestore(&host->lock, flags);
383366fd8ad5SAdrian Hunter 
3834781e989cSRussell King 	synchronize_hardirq(host->irq);
383566fd8ad5SAdrian Hunter 
383666fd8ad5SAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
383766fd8ad5SAdrian Hunter 	host->runtime_suspended = true;
383866fd8ad5SAdrian Hunter 	spin_unlock_irqrestore(&host->lock, flags);
383966fd8ad5SAdrian Hunter 
38408a125badSMarkus Pargmann 	return 0;
384166fd8ad5SAdrian Hunter }
384266fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host);
384366fd8ad5SAdrian Hunter 
sdhci_runtime_resume_host(struct sdhci_host * host,int soft_reset)3844c6303c5dSBaolin Wang int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset)
384566fd8ad5SAdrian Hunter {
3846d3940f27SAdrian Hunter 	struct mmc_host *mmc = host->mmc;
384766fd8ad5SAdrian Hunter 	unsigned long flags;
38488a125badSMarkus Pargmann 	int host_flags = host->flags;
384966fd8ad5SAdrian Hunter 
385066fd8ad5SAdrian Hunter 	if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
385166fd8ad5SAdrian Hunter 		if (host->ops->enable_dma)
385266fd8ad5SAdrian Hunter 			host->ops->enable_dma(host);
385366fd8ad5SAdrian Hunter 	}
385466fd8ad5SAdrian Hunter 
3855c6303c5dSBaolin Wang 	sdhci_init(host, soft_reset);
385666fd8ad5SAdrian Hunter 
385770bc85adSZhoujie Wu 	if (mmc->ios.power_mode != MMC_POWER_UNDEFINED &&
385870bc85adSZhoujie Wu 	    mmc->ios.power_mode != MMC_POWER_OFF) {
385966fd8ad5SAdrian Hunter 		/* Force clock and power re-program */
386066fd8ad5SAdrian Hunter 		host->pwr = 0;
386166fd8ad5SAdrian Hunter 		host->clock = 0;
3862c981cdfbSAdrian Hunter 		host->reinit_uhs = true;
3863d3940f27SAdrian Hunter 		mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios);
3864d3940f27SAdrian Hunter 		mmc->ops->set_ios(mmc, &mmc->ios);
386566fd8ad5SAdrian Hunter 
386652983382SKevin Liu 		if ((host_flags & SDHCI_PV_ENABLED) &&
386752983382SKevin Liu 		    !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
386852983382SKevin Liu 			spin_lock_irqsave(&host->lock, flags);
386952983382SKevin Liu 			sdhci_enable_preset_value(host, true);
387052983382SKevin Liu 			spin_unlock_irqrestore(&host->lock, flags);
387152983382SKevin Liu 		}
387266fd8ad5SAdrian Hunter 
3873086b0ddbSAdrian Hunter 		if ((mmc->caps2 & MMC_CAP2_HS400_ES) &&
3874086b0ddbSAdrian Hunter 		    mmc->ops->hs400_enhanced_strobe)
3875086b0ddbSAdrian Hunter 			mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios);
387684ec048bSAdrian Hunter 	}
3877086b0ddbSAdrian Hunter 
387866fd8ad5SAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
387966fd8ad5SAdrian Hunter 
388066fd8ad5SAdrian Hunter 	host->runtime_suspended = false;
388166fd8ad5SAdrian Hunter 
388266fd8ad5SAdrian Hunter 	/* Enable SDIO IRQ */
38830e62614bSUlf Hansson 	if (sdio_irq_claimed(mmc))
388466fd8ad5SAdrian Hunter 		sdhci_enable_sdio_irq_nolock(host, true);
388566fd8ad5SAdrian Hunter 
388666fd8ad5SAdrian Hunter 	/* Enable Card Detection */
388766fd8ad5SAdrian Hunter 	sdhci_enable_card_detection(host);
388866fd8ad5SAdrian Hunter 
388966fd8ad5SAdrian Hunter 	spin_unlock_irqrestore(&host->lock, flags);
389066fd8ad5SAdrian Hunter 
38918a125badSMarkus Pargmann 	return 0;
389266fd8ad5SAdrian Hunter }
389366fd8ad5SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host);
389466fd8ad5SAdrian Hunter 
3895162d6f98SRafael J. Wysocki #endif /* CONFIG_PM */
389666fd8ad5SAdrian Hunter 
38971c6a0718SPierre Ossman /*****************************************************************************\
38981c6a0718SPierre Ossman  *                                                                           *
3899f12e39dbSAdrian Hunter  * Command Queue Engine (CQE) helpers                                        *
3900f12e39dbSAdrian Hunter  *                                                                           *
3901f12e39dbSAdrian Hunter \*****************************************************************************/
3902f12e39dbSAdrian Hunter 
sdhci_cqe_enable(struct mmc_host * mmc)3903f12e39dbSAdrian Hunter void sdhci_cqe_enable(struct mmc_host *mmc)
3904f12e39dbSAdrian Hunter {
3905f12e39dbSAdrian Hunter 	struct sdhci_host *host = mmc_priv(mmc);
3906f12e39dbSAdrian Hunter 	unsigned long flags;
3907f12e39dbSAdrian Hunter 	u8 ctrl;
3908f12e39dbSAdrian Hunter 
3909f12e39dbSAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
3910f12e39dbSAdrian Hunter 
3911f12e39dbSAdrian Hunter 	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
3912f12e39dbSAdrian Hunter 	ctrl &= ~SDHCI_CTRL_DMA_MASK;
39134c4faff6SSowjanya Komatineni 	/*
39144c4faff6SSowjanya Komatineni 	 * Host from V4.10 supports ADMA3 DMA type.
39154c4faff6SSowjanya Komatineni 	 * ADMA3 performs integrated descriptor which is more suitable
39164c4faff6SSowjanya Komatineni 	 * for cmd queuing to fetch both command and transfer descriptors.
39174c4faff6SSowjanya Komatineni 	 */
39184c4faff6SSowjanya Komatineni 	if (host->v4_mode && (host->caps1 & SDHCI_CAN_DO_ADMA3))
39194c4faff6SSowjanya Komatineni 		ctrl |= SDHCI_CTRL_ADMA3;
39204c4faff6SSowjanya Komatineni 	else if (host->flags & SDHCI_USE_64_BIT_DMA)
3921f12e39dbSAdrian Hunter 		ctrl |= SDHCI_CTRL_ADMA64;
3922f12e39dbSAdrian Hunter 	else
3923f12e39dbSAdrian Hunter 		ctrl |= SDHCI_CTRL_ADMA32;
3924f12e39dbSAdrian Hunter 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
3925f12e39dbSAdrian Hunter 
3926c846a00fSSrinivas Kandagatla 	sdhci_writew(host, SDHCI_MAKE_BLKSZ(host->sdma_boundary, 512),
3927f12e39dbSAdrian Hunter 		     SDHCI_BLOCK_SIZE);
3928f12e39dbSAdrian Hunter 
3929f12e39dbSAdrian Hunter 	/* Set maximum timeout */
3930401059dfSBOUGH CHEN 	sdhci_set_timeout(host, NULL);
3931f12e39dbSAdrian Hunter 
3932f12e39dbSAdrian Hunter 	host->ier = host->cqe_ier;
3933f12e39dbSAdrian Hunter 
3934f12e39dbSAdrian Hunter 	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
3935f12e39dbSAdrian Hunter 	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
3936f12e39dbSAdrian Hunter 
3937f12e39dbSAdrian Hunter 	host->cqe_on = true;
3938f12e39dbSAdrian Hunter 
3939f12e39dbSAdrian Hunter 	pr_debug("%s: sdhci: CQE on, IRQ mask %#x, IRQ status %#x\n",
3940f12e39dbSAdrian Hunter 		 mmc_hostname(mmc), host->ier,
3941f12e39dbSAdrian Hunter 		 sdhci_readl(host, SDHCI_INT_STATUS));
3942f12e39dbSAdrian Hunter 
3943f12e39dbSAdrian Hunter 	spin_unlock_irqrestore(&host->lock, flags);
3944f12e39dbSAdrian Hunter }
3945f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_enable);
3946f12e39dbSAdrian Hunter 
sdhci_cqe_disable(struct mmc_host * mmc,bool recovery)3947f12e39dbSAdrian Hunter void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery)
3948f12e39dbSAdrian Hunter {
3949f12e39dbSAdrian Hunter 	struct sdhci_host *host = mmc_priv(mmc);
3950f12e39dbSAdrian Hunter 	unsigned long flags;
3951f12e39dbSAdrian Hunter 
3952f12e39dbSAdrian Hunter 	spin_lock_irqsave(&host->lock, flags);
3953f12e39dbSAdrian Hunter 
3954f12e39dbSAdrian Hunter 	sdhci_set_default_irqs(host);
3955f12e39dbSAdrian Hunter 
3956f12e39dbSAdrian Hunter 	host->cqe_on = false;
3957f12e39dbSAdrian Hunter 
39581e63d297SAdrian Hunter 	if (recovery)
39591e63d297SAdrian Hunter 		sdhci_reset_for(host, CQE_RECOVERY);
3960f12e39dbSAdrian Hunter 
3961f12e39dbSAdrian Hunter 	pr_debug("%s: sdhci: CQE off, IRQ mask %#x, IRQ status %#x\n",
3962f12e39dbSAdrian Hunter 		 mmc_hostname(mmc), host->ier,
3963f12e39dbSAdrian Hunter 		 sdhci_readl(host, SDHCI_INT_STATUS));
3964f12e39dbSAdrian Hunter 
3965f12e39dbSAdrian Hunter 	spin_unlock_irqrestore(&host->lock, flags);
3966f12e39dbSAdrian Hunter }
3967f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_disable);
3968f12e39dbSAdrian Hunter 
sdhci_cqe_irq(struct sdhci_host * host,u32 intmask,int * cmd_error,int * data_error)3969f12e39dbSAdrian Hunter bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error,
3970f12e39dbSAdrian Hunter 		   int *data_error)
3971f12e39dbSAdrian Hunter {
3972f12e39dbSAdrian Hunter 	u32 mask;
3973f12e39dbSAdrian Hunter 
3974f12e39dbSAdrian Hunter 	if (!host->cqe_on)
3975f12e39dbSAdrian Hunter 		return false;
3976f12e39dbSAdrian Hunter 
3977efe8f5c9SShaik Sajida Bhanu 	if (intmask & (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC)) {
3978f12e39dbSAdrian Hunter 		*cmd_error = -EILSEQ;
3979faded9b5SWenchao Chen 		if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
3980efe8f5c9SShaik Sajida Bhanu 			sdhci_err_stats_inc(host, CMD_CRC);
3981efe8f5c9SShaik Sajida Bhanu 	} else if (intmask & SDHCI_INT_TIMEOUT) {
3982f12e39dbSAdrian Hunter 		*cmd_error = -ETIMEDOUT;
3983efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, CMD_TIMEOUT);
3984efe8f5c9SShaik Sajida Bhanu 	} else
3985f12e39dbSAdrian Hunter 		*cmd_error = 0;
3986f12e39dbSAdrian Hunter 
3987d9ae0aa8SAdrian Hunter 	if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_TUNING_ERROR)) {
3988f12e39dbSAdrian Hunter 		*data_error = -EILSEQ;
3989faded9b5SWenchao Chen 		if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
3990efe8f5c9SShaik Sajida Bhanu 			sdhci_err_stats_inc(host, DAT_CRC);
3991efe8f5c9SShaik Sajida Bhanu 	} else if (intmask & SDHCI_INT_DATA_TIMEOUT) {
3992f12e39dbSAdrian Hunter 		*data_error = -ETIMEDOUT;
3993efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, DAT_TIMEOUT);
3994efe8f5c9SShaik Sajida Bhanu 	} else if (intmask & SDHCI_INT_ADMA_ERROR) {
3995f12e39dbSAdrian Hunter 		*data_error = -EIO;
3996efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, ADMA);
3997efe8f5c9SShaik Sajida Bhanu 	} else
3998f12e39dbSAdrian Hunter 		*data_error = 0;
3999f12e39dbSAdrian Hunter 
4000f12e39dbSAdrian Hunter 	/* Clear selected interrupts. */
4001f12e39dbSAdrian Hunter 	mask = intmask & host->cqe_ier;
4002f12e39dbSAdrian Hunter 	sdhci_writel(host, mask, SDHCI_INT_STATUS);
4003f12e39dbSAdrian Hunter 
4004f12e39dbSAdrian Hunter 	if (intmask & SDHCI_INT_BUS_POWER)
4005f12e39dbSAdrian Hunter 		pr_err("%s: Card is consuming too much power!\n",
4006f12e39dbSAdrian Hunter 		       mmc_hostname(host->mmc));
4007f12e39dbSAdrian Hunter 
4008f12e39dbSAdrian Hunter 	intmask &= ~(host->cqe_ier | SDHCI_INT_ERROR);
4009f12e39dbSAdrian Hunter 	if (intmask) {
4010f12e39dbSAdrian Hunter 		sdhci_writel(host, intmask, SDHCI_INT_STATUS);
4011f12e39dbSAdrian Hunter 		pr_err("%s: CQE: Unexpected interrupt 0x%08x.\n",
4012f12e39dbSAdrian Hunter 		       mmc_hostname(host->mmc), intmask);
4013efe8f5c9SShaik Sajida Bhanu 		sdhci_err_stats_inc(host, UNEXPECTED_IRQ);
4014f12e39dbSAdrian Hunter 		sdhci_dumpregs(host);
4015f12e39dbSAdrian Hunter 	}
4016f12e39dbSAdrian Hunter 
4017f12e39dbSAdrian Hunter 	return true;
4018f12e39dbSAdrian Hunter }
4019f12e39dbSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cqe_irq);
4020f12e39dbSAdrian Hunter 
4021f12e39dbSAdrian Hunter /*****************************************************************************\
4022f12e39dbSAdrian Hunter  *                                                                           *
4023b8c86fc5SPierre Ossman  * Device allocation/registration                                            *
40241c6a0718SPierre Ossman  *                                                                           *
40251c6a0718SPierre Ossman \*****************************************************************************/
40261c6a0718SPierre Ossman 
sdhci_alloc_host(struct device * dev,size_t priv_size)4027b8c86fc5SPierre Ossman struct sdhci_host *sdhci_alloc_host(struct device *dev,
4028b8c86fc5SPierre Ossman 	size_t priv_size)
40291c6a0718SPierre Ossman {
40301c6a0718SPierre Ossman 	struct mmc_host *mmc;
40311c6a0718SPierre Ossman 	struct sdhci_host *host;
40321c6a0718SPierre Ossman 
4033b8c86fc5SPierre Ossman 	WARN_ON(dev == NULL);
40341c6a0718SPierre Ossman 
4035b8c86fc5SPierre Ossman 	mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev);
40361c6a0718SPierre Ossman 	if (!mmc)
4037b8c86fc5SPierre Ossman 		return ERR_PTR(-ENOMEM);
40381c6a0718SPierre Ossman 
40391c6a0718SPierre Ossman 	host = mmc_priv(mmc);
40401c6a0718SPierre Ossman 	host->mmc = mmc;
4041bf60e592SAdrian Hunter 	host->mmc_host_ops = sdhci_ops;
4042bf60e592SAdrian Hunter 	mmc->ops = &host->mmc_host_ops;
40431c6a0718SPierre Ossman 
40448cb851a4SAdrian Hunter 	host->flags = SDHCI_SIGNALING_330;
40458cb851a4SAdrian Hunter 
4046f12e39dbSAdrian Hunter 	host->cqe_ier     = SDHCI_CQE_INT_MASK;
4047f12e39dbSAdrian Hunter 	host->cqe_err_ier = SDHCI_CQE_INT_ERR_MASK;
4048f12e39dbSAdrian Hunter 
404983b600b8SAdrian Hunter 	host->tuning_delay = -1;
40501d8cd065SSowjanya Komatineni 	host->tuning_loop_count = MAX_TUNING_LOOP;
405183b600b8SAdrian Hunter 
4052c846a00fSSrinivas Kandagatla 	host->sdma_boundary = SDHCI_DEFAULT_BOUNDARY_ARG;
4053c846a00fSSrinivas Kandagatla 
4054e93be38aSJisheng Zhang 	/*
4055e93be38aSJisheng Zhang 	 * The DMA table descriptor count is calculated as the maximum
4056e93be38aSJisheng Zhang 	 * number of segments times 2, to allow for an alignment
4057e93be38aSJisheng Zhang 	 * descriptor for each segment, plus 1 for a nop end descriptor.
4058e93be38aSJisheng Zhang 	 */
4059e93be38aSJisheng Zhang 	host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1;
40603d7c194bSAdrian Hunter 	host->max_adma = 65536;
4061e93be38aSJisheng Zhang 
4062e30314f2SSarthak Garg 	host->max_timeout_count = 0xE;
4063e30314f2SSarthak Garg 
4064b8c86fc5SPierre Ossman 	return host;
40651c6a0718SPierre Ossman }
40661c6a0718SPierre Ossman 
4067b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_alloc_host);
4068b8c86fc5SPierre Ossman 
sdhci_set_dma_mask(struct sdhci_host * host)40697b91369bSAlexandre Courbot static int sdhci_set_dma_mask(struct sdhci_host *host)
40707b91369bSAlexandre Courbot {
40717b91369bSAlexandre Courbot 	struct mmc_host *mmc = host->mmc;
40727b91369bSAlexandre Courbot 	struct device *dev = mmc_dev(mmc);
40737b91369bSAlexandre Courbot 	int ret = -EINVAL;
40747b91369bSAlexandre Courbot 
40757b91369bSAlexandre Courbot 	if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA)
40767b91369bSAlexandre Courbot 		host->flags &= ~SDHCI_USE_64_BIT_DMA;
40777b91369bSAlexandre Courbot 
40787b91369bSAlexandre Courbot 	/* Try 64-bit mask if hardware is capable  of it */
40797b91369bSAlexandre Courbot 	if (host->flags & SDHCI_USE_64_BIT_DMA) {
40807b91369bSAlexandre Courbot 		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
40817b91369bSAlexandre Courbot 		if (ret) {
40827b91369bSAlexandre Courbot 			pr_warn("%s: Failed to set 64-bit DMA mask.\n",
40837b91369bSAlexandre Courbot 				mmc_hostname(mmc));
40847b91369bSAlexandre Courbot 			host->flags &= ~SDHCI_USE_64_BIT_DMA;
40857b91369bSAlexandre Courbot 		}
40867b91369bSAlexandre Courbot 	}
40877b91369bSAlexandre Courbot 
40887b91369bSAlexandre Courbot 	/* 32-bit mask as default & fallback */
40897b91369bSAlexandre Courbot 	if (ret) {
40907b91369bSAlexandre Courbot 		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
40917b91369bSAlexandre Courbot 		if (ret)
40927b91369bSAlexandre Courbot 			pr_warn("%s: Failed to set 32-bit DMA mask.\n",
40937b91369bSAlexandre Courbot 				mmc_hostname(mmc));
40947b91369bSAlexandre Courbot 	}
40957b91369bSAlexandre Courbot 
40967b91369bSAlexandre Courbot 	return ret;
40977b91369bSAlexandre Courbot }
40987b91369bSAlexandre Courbot 
__sdhci_read_caps(struct sdhci_host * host,const u16 * ver,const u32 * caps,const u32 * caps1)40998784edc8SMasahiro Yamada void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver,
41008784edc8SMasahiro Yamada 		       const u32 *caps, const u32 *caps1)
41016132a3bfSAdrian Hunter {
41026132a3bfSAdrian Hunter 	u16 v;
410392e0c44bSZach Brown 	u64 dt_caps_mask = 0;
410492e0c44bSZach Brown 	u64 dt_caps = 0;
41056132a3bfSAdrian Hunter 
41066132a3bfSAdrian Hunter 	if (host->read_caps)
41076132a3bfSAdrian Hunter 		return;
41086132a3bfSAdrian Hunter 
41096132a3bfSAdrian Hunter 	host->read_caps = true;
41106132a3bfSAdrian Hunter 
41116132a3bfSAdrian Hunter 	if (debug_quirks)
41126132a3bfSAdrian Hunter 		host->quirks = debug_quirks;
41136132a3bfSAdrian Hunter 
41146132a3bfSAdrian Hunter 	if (debug_quirks2)
41156132a3bfSAdrian Hunter 		host->quirks2 = debug_quirks2;
41166132a3bfSAdrian Hunter 
4117aa990722SAdrian Hunter 	sdhci_reset_for_all(host);
41186132a3bfSAdrian Hunter 
4119b3f80b43SChunyan Zhang 	if (host->v4_mode)
4120b3f80b43SChunyan Zhang 		sdhci_do_enable_v4_mode(host);
4121b3f80b43SChunyan Zhang 
4122cb80a7e9SJeremy Linton 	device_property_read_u64(mmc_dev(host->mmc),
4123cb80a7e9SJeremy Linton 				 "sdhci-caps-mask", &dt_caps_mask);
4124cb80a7e9SJeremy Linton 	device_property_read_u64(mmc_dev(host->mmc),
4125cb80a7e9SJeremy Linton 				 "sdhci-caps", &dt_caps);
412692e0c44bSZach Brown 
41276132a3bfSAdrian Hunter 	v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION);
41286132a3bfSAdrian Hunter 	host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
41296132a3bfSAdrian Hunter 
413092e0c44bSZach Brown 	if (caps) {
413192e0c44bSZach Brown 		host->caps = *caps;
413292e0c44bSZach Brown 	} else {
413392e0c44bSZach Brown 		host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
413492e0c44bSZach Brown 		host->caps &= ~lower_32_bits(dt_caps_mask);
413592e0c44bSZach Brown 		host->caps |= lower_32_bits(dt_caps);
413692e0c44bSZach Brown 	}
41376132a3bfSAdrian Hunter 
41386132a3bfSAdrian Hunter 	if (host->version < SDHCI_SPEC_300)
41396132a3bfSAdrian Hunter 		return;
41406132a3bfSAdrian Hunter 
414192e0c44bSZach Brown 	if (caps1) {
414292e0c44bSZach Brown 		host->caps1 = *caps1;
414392e0c44bSZach Brown 	} else {
414492e0c44bSZach Brown 		host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
414592e0c44bSZach Brown 		host->caps1 &= ~upper_32_bits(dt_caps_mask);
414692e0c44bSZach Brown 		host->caps1 |= upper_32_bits(dt_caps);
414792e0c44bSZach Brown 	}
41486132a3bfSAdrian Hunter }
41496132a3bfSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_read_caps);
41506132a3bfSAdrian Hunter 
sdhci_allocate_bounce_buffer(struct sdhci_host * host)4151a68dd9a0SChunyan Zhang static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)
4152bd9b9027SLinus Walleij {
4153bd9b9027SLinus Walleij 	struct mmc_host *mmc = host->mmc;
4154bd9b9027SLinus Walleij 	unsigned int max_blocks;
4155bd9b9027SLinus Walleij 	unsigned int bounce_size;
4156bd9b9027SLinus Walleij 	int ret;
4157bd9b9027SLinus Walleij 
4158bd9b9027SLinus Walleij 	/*
4159bd9b9027SLinus Walleij 	 * Cap the bounce buffer at 64KB. Using a bigger bounce buffer
4160bd9b9027SLinus Walleij 	 * has diminishing returns, this is probably because SD/MMC
4161bd9b9027SLinus Walleij 	 * cards are usually optimized to handle this size of requests.
4162bd9b9027SLinus Walleij 	 */
4163bd9b9027SLinus Walleij 	bounce_size = SZ_64K;
4164bd9b9027SLinus Walleij 	/*
4165bd9b9027SLinus Walleij 	 * Adjust downwards to maximum request size if this is less
4166bd9b9027SLinus Walleij 	 * than our segment size, else hammer down the maximum
4167bd9b9027SLinus Walleij 	 * request size to the maximum buffer size.
4168bd9b9027SLinus Walleij 	 */
4169bd9b9027SLinus Walleij 	if (mmc->max_req_size < bounce_size)
4170bd9b9027SLinus Walleij 		bounce_size = mmc->max_req_size;
4171bd9b9027SLinus Walleij 	max_blocks = bounce_size / 512;
4172bd9b9027SLinus Walleij 
4173bd9b9027SLinus Walleij 	/*
4174bd9b9027SLinus Walleij 	 * When we just support one segment, we can get significant
4175bd9b9027SLinus Walleij 	 * speedups by the help of a bounce buffer to group scattered
4176bd9b9027SLinus Walleij 	 * reads/writes together.
4177bd9b9027SLinus Walleij 	 */
4178bac53336SJisheng Zhang 	host->bounce_buffer = devm_kmalloc(mmc_dev(mmc),
4179bd9b9027SLinus Walleij 					   bounce_size,
4180bd9b9027SLinus Walleij 					   GFP_KERNEL);
4181bd9b9027SLinus Walleij 	if (!host->bounce_buffer) {
4182bd9b9027SLinus Walleij 		pr_err("%s: failed to allocate %u bytes for bounce buffer, falling back to single segments\n",
4183bd9b9027SLinus Walleij 		       mmc_hostname(mmc),
4184bd9b9027SLinus Walleij 		       bounce_size);
4185bd9b9027SLinus Walleij 		/*
4186bd9b9027SLinus Walleij 		 * Exiting with zero here makes sure we proceed with
4187bd9b9027SLinus Walleij 		 * mmc->max_segs == 1.
4188bd9b9027SLinus Walleij 		 */
4189a68dd9a0SChunyan Zhang 		return;
4190bd9b9027SLinus Walleij 	}
4191bd9b9027SLinus Walleij 
4192bac53336SJisheng Zhang 	host->bounce_addr = dma_map_single(mmc_dev(mmc),
4193bd9b9027SLinus Walleij 					   host->bounce_buffer,
4194bd9b9027SLinus Walleij 					   bounce_size,
4195bd9b9027SLinus Walleij 					   DMA_BIDIRECTIONAL);
4196bac53336SJisheng Zhang 	ret = dma_mapping_error(mmc_dev(mmc), host->bounce_addr);
419749036ba8STakashi Iwai 	if (ret) {
419849036ba8STakashi Iwai 		devm_kfree(mmc_dev(mmc), host->bounce_buffer);
419949036ba8STakashi Iwai 		host->bounce_buffer = NULL;
4200bd9b9027SLinus Walleij 		/* Again fall back to max_segs == 1 */
4201a68dd9a0SChunyan Zhang 		return;
420249036ba8STakashi Iwai 	}
420349036ba8STakashi Iwai 
4204bd9b9027SLinus Walleij 	host->bounce_buffer_size = bounce_size;
4205bd9b9027SLinus Walleij 
4206bd9b9027SLinus Walleij 	/* Lie about this since we're bouncing */
4207bd9b9027SLinus Walleij 	mmc->max_segs = max_blocks;
4208bd9b9027SLinus Walleij 	mmc->max_seg_size = bounce_size;
4209bd9b9027SLinus Walleij 	mmc->max_req_size = bounce_size;
4210bd9b9027SLinus Walleij 
4211bd9b9027SLinus Walleij 	pr_info("%s bounce up to %u segments into one, max segment size %u bytes\n",
4212bd9b9027SLinus Walleij 		mmc_hostname(mmc), max_blocks, bounce_size);
4213bd9b9027SLinus Walleij }
4214bd9b9027SLinus Walleij 
sdhci_can_64bit_dma(struct sdhci_host * host)4215685e444bSChunyan Zhang static inline bool sdhci_can_64bit_dma(struct sdhci_host *host)
4216685e444bSChunyan Zhang {
4217685e444bSChunyan Zhang 	/*
4218685e444bSChunyan Zhang 	 * According to SD Host Controller spec v4.10, bit[27] added from
4219685e444bSChunyan Zhang 	 * version 4.10 in Capabilities Register is used as 64-bit System
4220685e444bSChunyan Zhang 	 * Address support for V4 mode.
4221685e444bSChunyan Zhang 	 */
4222685e444bSChunyan Zhang 	if (host->version >= SDHCI_SPEC_410 && host->v4_mode)
4223685e444bSChunyan Zhang 		return host->caps & SDHCI_CAN_64BIT_V4;
4224685e444bSChunyan Zhang 
4225685e444bSChunyan Zhang 	return host->caps & SDHCI_CAN_64BIT;
4226685e444bSChunyan Zhang }
4227685e444bSChunyan Zhang 
sdhci_setup_host(struct sdhci_host * host)422852f5336dSAdrian Hunter int sdhci_setup_host(struct sdhci_host *host)
4229b8c86fc5SPierre Ossman {
4230b8c86fc5SPierre Ossman 	struct mmc_host *mmc;
4231f2119df6SArindam Nath 	u32 max_current_caps;
4232f2119df6SArindam Nath 	unsigned int ocr_avail;
4233f5fa92e5SAdrian Hunter 	unsigned int override_timeout_clk;
423459241757SDong Aisheng 	u32 max_clk;
4235907be2a6SDan Carpenter 	int ret = 0;
42360fcb031eSVijay Viswanath 	bool enable_vqmmc = false;
4237b8c86fc5SPierre Ossman 
4238b8c86fc5SPierre Ossman 	WARN_ON(host == NULL);
4239b8c86fc5SPierre Ossman 	if (host == NULL)
4240b8c86fc5SPierre Ossman 		return -EINVAL;
4241b8c86fc5SPierre Ossman 
4242b8c86fc5SPierre Ossman 	mmc = host->mmc;
4243b8c86fc5SPierre Ossman 
4244efba142bSJon Hunter 	/*
4245efba142bSJon Hunter 	 * If there are external regulators, get them. Note this must be done
4246efba142bSJon Hunter 	 * early before resetting the host and reading the capabilities so that
4247efba142bSJon Hunter 	 * the host can take the appropriate action if regulators are not
4248efba142bSJon Hunter 	 * available.
4249efba142bSJon Hunter 	 */
42500fcb031eSVijay Viswanath 	if (!mmc->supply.vqmmc) {
4251efba142bSJon Hunter 		ret = mmc_regulator_get_supply(mmc);
42522a63303dSWolfram Sang 		if (ret)
4253efba142bSJon Hunter 			return ret;
42540fcb031eSVijay Viswanath 		enable_vqmmc  = true;
42550fcb031eSVijay Viswanath 	}
4256efba142bSJon Hunter 
425706ebc601SShawn Lin 	DBG("Version:   0x%08x | Present:  0x%08x\n",
425806ebc601SShawn Lin 	    sdhci_readw(host, SDHCI_HOST_VERSION),
425906ebc601SShawn Lin 	    sdhci_readl(host, SDHCI_PRESENT_STATE));
426006ebc601SShawn Lin 	DBG("Caps:      0x%08x | Caps_1:   0x%08x\n",
426106ebc601SShawn Lin 	    sdhci_readl(host, SDHCI_CAPABILITIES),
426206ebc601SShawn Lin 	    sdhci_readl(host, SDHCI_CAPABILITIES_1));
426306ebc601SShawn Lin 
42646132a3bfSAdrian Hunter 	sdhci_read_caps(host);
4265b8c86fc5SPierre Ossman 
4266f5fa92e5SAdrian Hunter 	override_timeout_clk = host->timeout_clk;
4267f5fa92e5SAdrian Hunter 
426818da1990SChunyan Zhang 	if (host->version > SDHCI_SPEC_420) {
42692e4456f0SMarek Vasut 		pr_err("%s: Unknown controller version (%d). You may experience problems.\n",
42702e4456f0SMarek Vasut 		       mmc_hostname(mmc), host->version);
42711c6a0718SPierre Ossman 	}
42721c6a0718SPierre Ossman 
4273b8c86fc5SPierre Ossman 	if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
4274a13abc7bSRichard Röjfors 		host->flags |= SDHCI_USE_SDMA;
427528da3589SAdrian Hunter 	else if (!(host->caps & SDHCI_CAN_DO_SDMA))
4276a13abc7bSRichard Röjfors 		DBG("Controller doesn't have SDMA capability\n");
42771c6a0718SPierre Ossman 	else
4278a13abc7bSRichard Röjfors 		host->flags |= SDHCI_USE_SDMA;
42791c6a0718SPierre Ossman 
4280b8c86fc5SPierre Ossman 	if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) &&
4281a13abc7bSRichard Röjfors 		(host->flags & SDHCI_USE_SDMA)) {
4282cee687ceSRolf Eike Beer 		DBG("Disabling DMA as it is marked broken\n");
4283a13abc7bSRichard Röjfors 		host->flags &= ~SDHCI_USE_SDMA;
42847c168e3dSFeng Tang 	}
42857c168e3dSFeng Tang 
4286f2119df6SArindam Nath 	if ((host->version >= SDHCI_SPEC_200) &&
428728da3589SAdrian Hunter 		(host->caps & SDHCI_CAN_DO_ADMA2))
42882134a922SPierre Ossman 		host->flags |= SDHCI_USE_ADMA;
42892134a922SPierre Ossman 
42902134a922SPierre Ossman 	if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) &&
42912134a922SPierre Ossman 		(host->flags & SDHCI_USE_ADMA)) {
42922134a922SPierre Ossman 		DBG("Disabling ADMA as it is marked broken\n");
42932134a922SPierre Ossman 		host->flags &= ~SDHCI_USE_ADMA;
42942134a922SPierre Ossman 	}
42952134a922SPierre Ossman 
4296685e444bSChunyan Zhang 	if (sdhci_can_64bit_dma(host))
4297e57a5f61SAdrian Hunter 		host->flags |= SDHCI_USE_64_BIT_DMA;
4298e57a5f61SAdrian Hunter 
429918e762e3SChunyan Zhang 	if (host->use_external_dma) {
430018e762e3SChunyan Zhang 		ret = sdhci_external_dma_init(host);
430118e762e3SChunyan Zhang 		if (ret == -EPROBE_DEFER)
430218e762e3SChunyan Zhang 			goto unreg;
430318e762e3SChunyan Zhang 		/*
430418e762e3SChunyan Zhang 		 * Fall back to use the DMA/PIO integrated in standard SDHCI
430518e762e3SChunyan Zhang 		 * instead of external DMA devices.
430618e762e3SChunyan Zhang 		 */
430718e762e3SChunyan Zhang 		else if (ret)
430818e762e3SChunyan Zhang 			sdhci_switch_external_dma(host, false);
430918e762e3SChunyan Zhang 		/* Disable internal DMA sources */
431018e762e3SChunyan Zhang 		else
431118e762e3SChunyan Zhang 			host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA);
431218e762e3SChunyan Zhang 	}
431318e762e3SChunyan Zhang 
4314a13abc7bSRichard Röjfors 	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
43154ee7dde4SAdrian Hunter 		if (host->ops->set_dma_mask)
43164ee7dde4SAdrian Hunter 			ret = host->ops->set_dma_mask(host);
43174ee7dde4SAdrian Hunter 		else
43187b91369bSAlexandre Courbot 			ret = sdhci_set_dma_mask(host);
43197b91369bSAlexandre Courbot 
43207b91369bSAlexandre Courbot 		if (!ret && host->ops->enable_dma)
43217b91369bSAlexandre Courbot 			ret = host->ops->enable_dma(host);
43227b91369bSAlexandre Courbot 
43237b91369bSAlexandre Courbot 		if (ret) {
43246606110dSJoe Perches 			pr_warn("%s: No suitable DMA available - falling back to PIO\n",
4325b8c86fc5SPierre Ossman 				mmc_hostname(mmc));
43267b91369bSAlexandre Courbot 			host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA);
43277b91369bSAlexandre Courbot 
43287b91369bSAlexandre Courbot 			ret = 0;
43291c6a0718SPierre Ossman 		}
4330b8c86fc5SPierre Ossman 	}
43311c6a0718SPierre Ossman 
4332917a0c52SChunyan Zhang 	/* SDMA does not support 64-bit DMA if v4 mode not set */
4333917a0c52SChunyan Zhang 	if ((host->flags & SDHCI_USE_64_BIT_DMA) && !host->v4_mode)
4334e57a5f61SAdrian Hunter 		host->flags &= ~SDHCI_USE_SDMA;
4335e57a5f61SAdrian Hunter 
43362134a922SPierre Ossman 	if (host->flags & SDHCI_USE_ADMA) {
4337e66e61cbSRussell King 		dma_addr_t dma;
4338e66e61cbSRussell King 		void *buf;
4339e66e61cbSRussell King 
4340a663f64bSVeerabhadrarao Badiganti 		if (!(host->flags & SDHCI_USE_64_BIT_DMA))
4341a663f64bSVeerabhadrarao Badiganti 			host->alloc_desc_sz = SDHCI_ADMA2_32_DESC_SZ;
4342a663f64bSVeerabhadrarao Badiganti 		else if (!host->alloc_desc_sz)
4343a663f64bSVeerabhadrarao Badiganti 			host->alloc_desc_sz = SDHCI_ADMA2_64_DESC_SZ(host);
4344a663f64bSVeerabhadrarao Badiganti 
4345a663f64bSVeerabhadrarao Badiganti 		host->desc_sz = host->alloc_desc_sz;
4346a663f64bSVeerabhadrarao Badiganti 		host->adma_table_sz = host->adma_table_cnt * host->desc_sz;
4347e66e61cbSRussell King 
434804a5ae6fSAdrian Hunter 		host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN;
4349685e444bSChunyan Zhang 		/*
4350685e444bSChunyan Zhang 		 * Use zalloc to zero the reserved high 32-bits of 128-bit
4351685e444bSChunyan Zhang 		 * descriptors so that they never need to be written.
4352685e444bSChunyan Zhang 		 */
4353750afb08SLuis Chamberlain 		buf = dma_alloc_coherent(mmc_dev(mmc),
4354750afb08SLuis Chamberlain 					 host->align_buffer_sz + host->adma_table_sz,
4355750afb08SLuis Chamberlain 					 &dma, GFP_KERNEL);
4356e66e61cbSRussell King 		if (!buf) {
43576606110dSJoe Perches 			pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n",
43582134a922SPierre Ossman 				mmc_hostname(mmc));
43592134a922SPierre Ossman 			host->flags &= ~SDHCI_USE_ADMA;
4360e66e61cbSRussell King 		} else if ((dma + host->align_buffer_sz) &
4361e66e61cbSRussell King 			   (SDHCI_ADMA2_DESC_ALIGN - 1)) {
43626606110dSJoe Perches 			pr_warn("%s: unable to allocate aligned ADMA descriptor\n",
4363d1e49f77SRussell King 				mmc_hostname(mmc));
4364d1e49f77SRussell King 			host->flags &= ~SDHCI_USE_ADMA;
4365e66e61cbSRussell King 			dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz +
4366e66e61cbSRussell King 					  host->adma_table_sz, buf, dma);
4367e66e61cbSRussell King 		} else {
4368e66e61cbSRussell King 			host->align_buffer = buf;
4369e66e61cbSRussell King 			host->align_addr = dma;
4370edd63fccSRussell King 
4371e66e61cbSRussell King 			host->adma_table = buf + host->align_buffer_sz;
4372e66e61cbSRussell King 			host->adma_addr = dma + host->align_buffer_sz;
4373e66e61cbSRussell King 		}
43742134a922SPierre Ossman 	}
43752134a922SPierre Ossman 
43767659150cSPierre Ossman 	/*
43777659150cSPierre Ossman 	 * If we use DMA, then it's up to the caller to set the DMA
43787659150cSPierre Ossman 	 * mask, but PIO does not need the hw shim so we set a new
43797659150cSPierre Ossman 	 * mask here in that case.
43807659150cSPierre Ossman 	 */
4381a13abc7bSRichard Röjfors 	if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) {
43827659150cSPierre Ossman 		host->dma_mask = DMA_BIT_MASK(64);
43834e743f1fSMarkus Mayer 		mmc_dev(mmc)->dma_mask = &host->dma_mask;
43847659150cSPierre Ossman 	}
43851c6a0718SPierre Ossman 
4386c4687d5fSZhangfei Gao 	if (host->version >= SDHCI_SPEC_300)
4387a8e809ecSMasahiro Yamada 		host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps);
4388c4687d5fSZhangfei Gao 	else
4389a8e809ecSMasahiro Yamada 		host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps);
4390c4687d5fSZhangfei Gao 
43914240ff0aSBen Dooks 	host->max_clk *= 1000000;
4392f27f47efSAnton Vorontsov 	if (host->max_clk == 0 || host->quirks &
4393f27f47efSAnton Vorontsov 			SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) {
43944240ff0aSBen Dooks 		if (!host->ops->get_max_clock) {
43952e4456f0SMarek Vasut 			pr_err("%s: Hardware doesn't specify base clock frequency.\n",
43962e4456f0SMarek Vasut 			       mmc_hostname(mmc));
4397eb5c20deSAdrian Hunter 			ret = -ENODEV;
4398eb5c20deSAdrian Hunter 			goto undma;
43991c6a0718SPierre Ossman 		}
44004240ff0aSBen Dooks 		host->max_clk = host->ops->get_max_clock(host);
44014240ff0aSBen Dooks 	}
44021c6a0718SPierre Ossman 
44031c6a0718SPierre Ossman 	/*
4404c3ed3877SArindam Nath 	 * In case of Host Controller v3.00, find out whether clock
4405c3ed3877SArindam Nath 	 * multiplier is supported.
4406c3ed3877SArindam Nath 	 */
4407a8e809ecSMasahiro Yamada 	host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1);
4408c3ed3877SArindam Nath 
4409c3ed3877SArindam Nath 	/*
4410c3ed3877SArindam Nath 	 * In case the value in Clock Multiplier is 0, then programmable
4411c3ed3877SArindam Nath 	 * clock mode is not supported, otherwise the actual clock
4412c3ed3877SArindam Nath 	 * multiplier is one more than the value of Clock Multiplier
4413c3ed3877SArindam Nath 	 * in the Capabilities Register.
4414c3ed3877SArindam Nath 	 */
4415c3ed3877SArindam Nath 	if (host->clk_mul)
4416c3ed3877SArindam Nath 		host->clk_mul += 1;
4417c3ed3877SArindam Nath 
4418c3ed3877SArindam Nath 	/*
44191c6a0718SPierre Ossman 	 * Set host parameters.
44201c6a0718SPierre Ossman 	 */
442159241757SDong Aisheng 	max_clk = host->max_clk;
442259241757SDong Aisheng 
4423ce5f036bSMarek Szyprowski 	if (host->ops->get_min_clock)
4424a9e58f25SAnton Vorontsov 		mmc->f_min = host->ops->get_min_clock(host);
4425c3ed3877SArindam Nath 	else if (host->version >= SDHCI_SPEC_300) {
44262a187d03SMichał Mirosław 		if (host->clk_mul)
442759241757SDong Aisheng 			max_clk = host->max_clk * host->clk_mul;
44282a187d03SMichał Mirosław 		/*
44292a187d03SMichał Mirosław 		 * Divided Clock Mode minimum clock rate is always less than
44302a187d03SMichał Mirosław 		 * Programmable Clock Mode minimum clock rate.
44312a187d03SMichał Mirosław 		 */
44320397526dSZhangfei Gao 		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
4433c3ed3877SArindam Nath 	} else
44340397526dSZhangfei Gao 		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
443515ec4461SPhilip Rakity 
4436d310ae49SAdrian Hunter 	if (!mmc->f_max || mmc->f_max > max_clk)
443759241757SDong Aisheng 		mmc->f_max = max_clk;
443859241757SDong Aisheng 
443928aab053SAisheng Dong 	if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
4440a8e809ecSMasahiro Yamada 		host->timeout_clk = FIELD_GET(SDHCI_TIMEOUT_CLK_MASK, host->caps);
44418cc35289SShawn Lin 
44428cc35289SShawn Lin 		if (host->caps & SDHCI_TIMEOUT_CLK_UNIT)
44438cc35289SShawn Lin 			host->timeout_clk *= 1000;
44448cc35289SShawn Lin 
4445272308caSAndy Shevchenko 		if (host->timeout_clk == 0) {
44468cc35289SShawn Lin 			if (!host->ops->get_timeout_clock) {
444728aab053SAisheng Dong 				pr_err("%s: Hardware doesn't specify timeout clock frequency.\n",
444828aab053SAisheng Dong 					mmc_hostname(mmc));
4449eb5c20deSAdrian Hunter 				ret = -ENODEV;
4450eb5c20deSAdrian Hunter 				goto undma;
4451272308caSAndy Shevchenko 			}
445228aab053SAisheng Dong 
44538cc35289SShawn Lin 			host->timeout_clk =
44548cc35289SShawn Lin 				DIV_ROUND_UP(host->ops->get_timeout_clock(host),
44558cc35289SShawn Lin 					     1000);
44568cc35289SShawn Lin 		}
4457272308caSAndy Shevchenko 
445899513624SAdrian Hunter 		if (override_timeout_clk)
445999513624SAdrian Hunter 			host->timeout_clk = override_timeout_clk;
446099513624SAdrian Hunter 
4461a6ff5aebSAisheng Dong 		mmc->max_busy_timeout = host->ops->get_max_timeout_count ?
4462a6ff5aebSAisheng Dong 			host->ops->get_max_timeout_count(host) : 1 << 27;
4463a6ff5aebSAisheng Dong 		mmc->max_busy_timeout /= host->timeout_clk;
446428aab053SAisheng Dong 	}
446558d1246dSAdrian Hunter 
4466a999fd93SAdrian Hunter 	if (host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT &&
4467a999fd93SAdrian Hunter 	    !host->ops->get_max_timeout_count)
4468a999fd93SAdrian Hunter 		mmc->max_busy_timeout = 0;
4469a999fd93SAdrian Hunter 
44701be64c79SUlf Hansson 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_CMD23;
4471781e989cSRussell King 	mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
4472e89d456fSAndrei Warkentin 
4473e89d456fSAndrei Warkentin 	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
4474e89d456fSAndrei Warkentin 		host->flags |= SDHCI_AUTO_CMD12;
44755fe23c7fSAnton Vorontsov 
44767ed71a9dSChunyan Zhang 	/*
44777ed71a9dSChunyan Zhang 	 * For v3 mode, Auto-CMD23 stuff only works in ADMA or PIO.
44787ed71a9dSChunyan Zhang 	 * For v4 mode, SDMA may use Auto-CMD23 as well.
44797ed71a9dSChunyan Zhang 	 */
44804f3d3e9bSAndrei Warkentin 	if ((host->version >= SDHCI_SPEC_300) &&
44818edf6371SAndrei Warkentin 	    ((host->flags & SDHCI_USE_ADMA) ||
44827ed71a9dSChunyan Zhang 	     !(host->flags & SDHCI_USE_SDMA) || host->v4_mode) &&
44833bfa6f03SScott Branden 	     !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN)) {
44848edf6371SAndrei Warkentin 		host->flags |= SDHCI_AUTO_CMD23;
4485f421865dSAdrian Hunter 		DBG("Auto-CMD23 available\n");
44868edf6371SAndrei Warkentin 	} else {
4487f421865dSAdrian Hunter 		DBG("Auto-CMD23 unavailable\n");
44888edf6371SAndrei Warkentin 	}
44898edf6371SAndrei Warkentin 
449015ec4461SPhilip Rakity 	/*
449115ec4461SPhilip Rakity 	 * A controller may support 8-bit width, but the board itself
449215ec4461SPhilip Rakity 	 * might not have the pins brought out.  Boards that support
449315ec4461SPhilip Rakity 	 * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in
449415ec4461SPhilip Rakity 	 * their platform code before calling sdhci_add_host(), and we
449515ec4461SPhilip Rakity 	 * won't assume 8-bit width for hosts without that CAP.
449615ec4461SPhilip Rakity 	 */
44975fe23c7fSAnton Vorontsov 	if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
449815ec4461SPhilip Rakity 		mmc->caps |= MMC_CAP_4_BIT_DATA;
44991c6a0718SPierre Ossman 
450063ef5d8cSJerry Huang 	if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
450163ef5d8cSJerry Huang 		mmc->caps &= ~MMC_CAP_CMD23;
450263ef5d8cSJerry Huang 
450328da3589SAdrian Hunter 	if (host->caps & SDHCI_CAN_DO_HISPD)
4504a29e7e18SZhangfei Gao 		mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
45051c6a0718SPierre Ossman 
4506176d1ed4SJaehoon Chung 	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
4507860951c5SJaehoon Chung 	    mmc_card_is_removable(mmc) &&
4508d2f025b0SJisheng Zhang 	    mmc_gpio_get_cd(mmc) < 0)
450968d1fb7eSAnton Vorontsov 		mmc->caps |= MMC_CAP_NEEDS_POLL;
451068d1fb7eSAnton Vorontsov 
45113a48edc4STim Kryger 	if (!IS_ERR(mmc->supply.vqmmc)) {
45120fcb031eSVijay Viswanath 		if (enable_vqmmc) {
45133a48edc4STim Kryger 			ret = regulator_enable(mmc->supply.vqmmc);
45140fcb031eSVijay Viswanath 			host->sdhci_core_to_disable_vqmmc = !ret;
45150fcb031eSVijay Viswanath 		}
45161b5190c2SStefan Agner 
45171b5190c2SStefan Agner 		/* If vqmmc provides no 1.8V signalling, then there's no UHS */
45183a48edc4STim Kryger 		if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
4519cec2e216SKevin Liu 						    1950000))
452028da3589SAdrian Hunter 			host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
45218363c374SKevin Liu 					 SDHCI_SUPPORT_SDR50 |
45226231f3deSPhilip Rakity 					 SDHCI_SUPPORT_DDR50);
45231b5190c2SStefan Agner 
45241b5190c2SStefan Agner 		/* In eMMC case vqmmc might be a fixed 1.8V regulator */
45251b5190c2SStefan Agner 		if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000,
45261b5190c2SStefan Agner 						    3600000))
45271b5190c2SStefan Agner 			host->flags &= ~SDHCI_SIGNALING_330;
45281b5190c2SStefan Agner 
4529a3361abaSChris Ball 		if (ret) {
4530a3361abaSChris Ball 			pr_warn("%s: Failed to enable vqmmc regulator: %d\n",
4531a3361abaSChris Ball 				mmc_hostname(mmc), ret);
45324bb74313SAdrian Hunter 			mmc->supply.vqmmc = ERR_PTR(-EINVAL);
4533a3361abaSChris Ball 		}
45343debc24fSVeerabhadrarao Badiganti 
45358363c374SKevin Liu 	}
45366231f3deSPhilip Rakity 
453728da3589SAdrian Hunter 	if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) {
453828da3589SAdrian Hunter 		host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
45396a66180aSDaniel Drake 				 SDHCI_SUPPORT_DDR50);
4540c16bc9a7SKishon Vijay Abraham I 		/*
4541c16bc9a7SKishon Vijay Abraham I 		 * The SDHCI controller in a SoC might support HS200/HS400
4542c16bc9a7SKishon Vijay Abraham I 		 * (indicated using mmc-hs200-1_8v/mmc-hs400-1_8v dt property),
4543c16bc9a7SKishon Vijay Abraham I 		 * but if the board is modeled such that the IO lines are not
4544c16bc9a7SKishon Vijay Abraham I 		 * connected to 1.8v then HS200/HS400 cannot be supported.
4545c16bc9a7SKishon Vijay Abraham I 		 * Disable HS200/HS400 if the board does not have 1.8v connected
4546c16bc9a7SKishon Vijay Abraham I 		 * to the IO lines. (Applicable for other modes in 1.8v)
4547c16bc9a7SKishon Vijay Abraham I 		 */
4548c16bc9a7SKishon Vijay Abraham I 		mmc->caps2 &= ~(MMC_CAP2_HSX00_1_8V | MMC_CAP2_HS400_ES);
4549c16bc9a7SKishon Vijay Abraham I 		mmc->caps &= ~(MMC_CAP_1_8V_DDR | MMC_CAP_UHS);
455028da3589SAdrian Hunter 	}
45516a66180aSDaniel Drake 
45524188bba0SAl Cooper 	/* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
455328da3589SAdrian Hunter 	if (host->caps1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
45544188bba0SAl Cooper 			   SDHCI_SUPPORT_DDR50))
4555f2119df6SArindam Nath 		mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25;
4556f2119df6SArindam Nath 
4557f2119df6SArindam Nath 	/* SDR104 supports also implies SDR50 support */
455828da3589SAdrian Hunter 	if (host->caps1 & SDHCI_SUPPORT_SDR104) {
4559f2119df6SArindam Nath 		mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50;
4560156e14b1SGiuseppe CAVALLARO 		/* SD3.0: SDR104 is supported so (for eMMC) the caps2
4561156e14b1SGiuseppe CAVALLARO 		 * field can be promoted to support HS200.
4562156e14b1SGiuseppe CAVALLARO 		 */
4563549c0b18SAdrian Hunter 		if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200))
4564156e14b1SGiuseppe CAVALLARO 			mmc->caps2 |= MMC_CAP2_HS200;
456528da3589SAdrian Hunter 	} else if (host->caps1 & SDHCI_SUPPORT_SDR50) {
4566f2119df6SArindam Nath 		mmc->caps |= MMC_CAP_UHS_SDR50;
456728da3589SAdrian Hunter 	}
4568f2119df6SArindam Nath 
4569e9fb05d5SAdrian Hunter 	if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 &&
457028da3589SAdrian Hunter 	    (host->caps1 & SDHCI_SUPPORT_HS400))
4571e9fb05d5SAdrian Hunter 		mmc->caps2 |= MMC_CAP2_HS400;
4572e9fb05d5SAdrian Hunter 
4573549c0b18SAdrian Hunter 	if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) &&
4574549c0b18SAdrian Hunter 	    (IS_ERR(mmc->supply.vqmmc) ||
4575549c0b18SAdrian Hunter 	     !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000,
4576549c0b18SAdrian Hunter 					     1300000)))
4577549c0b18SAdrian Hunter 		mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V;
4578549c0b18SAdrian Hunter 
457928da3589SAdrian Hunter 	if ((host->caps1 & SDHCI_SUPPORT_DDR50) &&
45809107ebbfSMicky Ching 	    !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50))
4581f2119df6SArindam Nath 		mmc->caps |= MMC_CAP_UHS_DDR50;
4582f2119df6SArindam Nath 
4583069c9f14SGirish K S 	/* Does the host need tuning for SDR50? */
458428da3589SAdrian Hunter 	if (host->caps1 & SDHCI_USE_SDR50_TUNING)
4585b513ea25SArindam Nath 		host->flags |= SDHCI_SDR50_NEEDS_TUNING;
4586b513ea25SArindam Nath 
4587d6d50a15SArindam Nath 	/* Driver Type(s) (A, C, D) supported by the host */
458828da3589SAdrian Hunter 	if (host->caps1 & SDHCI_DRIVER_TYPE_A)
4589d6d50a15SArindam Nath 		mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
459028da3589SAdrian Hunter 	if (host->caps1 & SDHCI_DRIVER_TYPE_C)
4591d6d50a15SArindam Nath 		mmc->caps |= MMC_CAP_DRIVER_TYPE_C;
459228da3589SAdrian Hunter 	if (host->caps1 & SDHCI_DRIVER_TYPE_D)
4593d6d50a15SArindam Nath 		mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
4594d6d50a15SArindam Nath 
4595cf2b5eeaSArindam Nath 	/* Initial value for re-tuning timer count */
4596a8e809ecSMasahiro Yamada 	host->tuning_count = FIELD_GET(SDHCI_RETUNING_TIMER_COUNT_MASK,
4597a8e809ecSMasahiro Yamada 				       host->caps1);
4598cf2b5eeaSArindam Nath 
4599cf2b5eeaSArindam Nath 	/*
4600cf2b5eeaSArindam Nath 	 * In case Re-tuning Timer is not disabled, the actual value of
4601cf2b5eeaSArindam Nath 	 * re-tuning timer will be 2 ^ (n - 1).
4602cf2b5eeaSArindam Nath 	 */
4603cf2b5eeaSArindam Nath 	if (host->tuning_count)
4604cf2b5eeaSArindam Nath 		host->tuning_count = 1 << (host->tuning_count - 1);
4605cf2b5eeaSArindam Nath 
4606cf2b5eeaSArindam Nath 	/* Re-tuning mode supported by the Host Controller */
4607a8e809ecSMasahiro Yamada 	host->tuning_mode = FIELD_GET(SDHCI_RETUNING_MODE_MASK, host->caps1);
4608cf2b5eeaSArindam Nath 
46098f230f45STakashi Iwai 	ocr_avail = 0;
4610bad37e1aSPhilip Rakity 
4611f2119df6SArindam Nath 	/*
4612f2119df6SArindam Nath 	 * According to SD Host Controller spec v3.00, if the Host System
4613f2119df6SArindam Nath 	 * can afford more than 150mA, Host Driver should set XPC to 1. Also
4614f2119df6SArindam Nath 	 * the value is meaningful only if Voltage Support in the Capabilities
4615f2119df6SArindam Nath 	 * register is set. The actual current value is 4 times the register
4616f2119df6SArindam Nath 	 * value.
4617f2119df6SArindam Nath 	 */
4618f2119df6SArindam Nath 	max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
46193a48edc4STim Kryger 	if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) {
4620ae906037SChuanxiao.Dong 		int curr = regulator_get_current_limit(mmc->supply.vmmc);
4621bad37e1aSPhilip Rakity 		if (curr > 0) {
4622bad37e1aSPhilip Rakity 
4623bad37e1aSPhilip Rakity 			/* convert to SDHCI_MAX_CURRENT format */
4624bad37e1aSPhilip Rakity 			curr = curr/1000;  /* convert to mA */
4625bad37e1aSPhilip Rakity 			curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER;
4626bad37e1aSPhilip Rakity 
4627bad37e1aSPhilip Rakity 			curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT);
4628bad37e1aSPhilip Rakity 			max_current_caps =
4629804a65b3SMasahiro Yamada 				FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, curr) |
4630804a65b3SMasahiro Yamada 				FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, curr) |
4631804a65b3SMasahiro Yamada 				FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, curr);
4632bad37e1aSPhilip Rakity 		}
4633bad37e1aSPhilip Rakity 	}
4634f2119df6SArindam Nath 
463528da3589SAdrian Hunter 	if (host->caps & SDHCI_CAN_VDD_330) {
46368f230f45STakashi Iwai 		ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
4637f2119df6SArindam Nath 
4638804a65b3SMasahiro Yamada 		mmc->max_current_330 = FIELD_GET(SDHCI_MAX_CURRENT_330_MASK,
4639804a65b3SMasahiro Yamada 						 max_current_caps) *
4640f2119df6SArindam Nath 						SDHCI_MAX_CURRENT_MULTIPLIER;
4641f2119df6SArindam Nath 	}
464228da3589SAdrian Hunter 	if (host->caps & SDHCI_CAN_VDD_300) {
46438f230f45STakashi Iwai 		ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
4644f2119df6SArindam Nath 
4645804a65b3SMasahiro Yamada 		mmc->max_current_300 = FIELD_GET(SDHCI_MAX_CURRENT_300_MASK,
4646804a65b3SMasahiro Yamada 						 max_current_caps) *
4647f2119df6SArindam Nath 						SDHCI_MAX_CURRENT_MULTIPLIER;
4648f2119df6SArindam Nath 	}
464928da3589SAdrian Hunter 	if (host->caps & SDHCI_CAN_VDD_180) {
46508f230f45STakashi Iwai 		ocr_avail |= MMC_VDD_165_195;
46518f230f45STakashi Iwai 
4652804a65b3SMasahiro Yamada 		mmc->max_current_180 = FIELD_GET(SDHCI_MAX_CURRENT_180_MASK,
4653804a65b3SMasahiro Yamada 						 max_current_caps) *
4654f2119df6SArindam Nath 						SDHCI_MAX_CURRENT_MULTIPLIER;
4655f2119df6SArindam Nath 	}
4656f2119df6SArindam Nath 
46575fd26c7eSUlf Hansson 	/* If OCR set by host, use it instead. */
46585fd26c7eSUlf Hansson 	if (host->ocr_mask)
46595fd26c7eSUlf Hansson 		ocr_avail = host->ocr_mask;
46605fd26c7eSUlf Hansson 
46615fd26c7eSUlf Hansson 	/* If OCR set by external regulators, give it highest prio. */
46623a48edc4STim Kryger 	if (mmc->ocr_avail)
466352221610STim Kryger 		ocr_avail = mmc->ocr_avail;
46643a48edc4STim Kryger 
46658f230f45STakashi Iwai 	mmc->ocr_avail = ocr_avail;
46668f230f45STakashi Iwai 	mmc->ocr_avail_sdio = ocr_avail;
46678f230f45STakashi Iwai 	if (host->ocr_avail_sdio)
46688f230f45STakashi Iwai 		mmc->ocr_avail_sdio &= host->ocr_avail_sdio;
46698f230f45STakashi Iwai 	mmc->ocr_avail_sd = ocr_avail;
46708f230f45STakashi Iwai 	if (host->ocr_avail_sd)
46718f230f45STakashi Iwai 		mmc->ocr_avail_sd &= host->ocr_avail_sd;
46728f230f45STakashi Iwai 	else /* normal SD controllers don't support 1.8V */
46738f230f45STakashi Iwai 		mmc->ocr_avail_sd &= ~MMC_VDD_165_195;
46748f230f45STakashi Iwai 	mmc->ocr_avail_mmc = ocr_avail;
46758f230f45STakashi Iwai 	if (host->ocr_avail_mmc)
46768f230f45STakashi Iwai 		mmc->ocr_avail_mmc &= host->ocr_avail_mmc;
46771c6a0718SPierre Ossman 
46781c6a0718SPierre Ossman 	if (mmc->ocr_avail == 0) {
46792e4456f0SMarek Vasut 		pr_err("%s: Hardware doesn't report any support voltages.\n",
46802e4456f0SMarek Vasut 		       mmc_hostname(mmc));
4681eb5c20deSAdrian Hunter 		ret = -ENODEV;
4682eb5c20deSAdrian Hunter 		goto unreg;
46831c6a0718SPierre Ossman 	}
46841c6a0718SPierre Ossman 
46858cb851a4SAdrian Hunter 	if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
46868cb851a4SAdrian Hunter 			  MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 |
46878cb851a4SAdrian Hunter 			  MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) ||
46888cb851a4SAdrian Hunter 	    (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V)))
46898cb851a4SAdrian Hunter 		host->flags |= SDHCI_SIGNALING_180;
46908cb851a4SAdrian Hunter 
46918cb851a4SAdrian Hunter 	if (mmc->caps2 & MMC_CAP2_HSX00_1_2V)
46928cb851a4SAdrian Hunter 		host->flags |= SDHCI_SIGNALING_120;
46938cb851a4SAdrian Hunter 
46941c6a0718SPierre Ossman 	spin_lock_init(&host->lock);
46951c6a0718SPierre Ossman 
46961c6a0718SPierre Ossman 	/*
4697ac00531dSAdrian Hunter 	 * Maximum number of sectors in one transfer. Limited by SDMA boundary
4698ac00531dSAdrian Hunter 	 * size (512KiB). Note some tuning modes impose a 4MiB limit, but this
4699ac00531dSAdrian Hunter 	 * is less anyway.
47001c6a0718SPierre Ossman 	 */
47011c6a0718SPierre Ossman 	mmc->max_req_size = 524288;
47021c6a0718SPierre Ossman 
47031c6a0718SPierre Ossman 	/*
4704250dcd11SUlf Hansson 	 * Maximum number of segments. Depends on if the hardware
4705250dcd11SUlf Hansson 	 * can do scatter/gather or not.
4706250dcd11SUlf Hansson 	 */
4707250dcd11SUlf Hansson 	if (host->flags & SDHCI_USE_ADMA) {
4708250dcd11SUlf Hansson 		mmc->max_segs = SDHCI_MAX_SEGS;
4709250dcd11SUlf Hansson 	} else if (host->flags & SDHCI_USE_SDMA) {
4710250dcd11SUlf Hansson 		mmc->max_segs = 1;
471166e8d3b8SChristoph Hellwig 		mmc->max_req_size = min_t(size_t, mmc->max_req_size,
471266e8d3b8SChristoph Hellwig 					  dma_max_mapping_size(mmc_dev(mmc)));
4713250dcd11SUlf Hansson 	} else { /* PIO */
4714250dcd11SUlf Hansson 		mmc->max_segs = SDHCI_MAX_SEGS;
4715250dcd11SUlf Hansson 	}
4716250dcd11SUlf Hansson 
4717250dcd11SUlf Hansson 	/*
47181c6a0718SPierre Ossman 	 * Maximum segment size. Could be one segment with the maximum number
47192134a922SPierre Ossman 	 * of bytes. When doing hardware scatter/gather, each entry cannot
47202134a922SPierre Ossman 	 * be larger than 64 KiB though.
47211c6a0718SPierre Ossman 	 */
472230652aa3SOlof Johansson 	if (host->flags & SDHCI_USE_ADMA) {
47233d7c194bSAdrian Hunter 		if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) {
47243d7c194bSAdrian Hunter 			host->max_adma = 65532; /* 32-bit alignment */
472530652aa3SOlof Johansson 			mmc->max_seg_size = 65535;
47263d7c194bSAdrian Hunter 		} else {
472730652aa3SOlof Johansson 			mmc->max_seg_size = 65536;
47283d7c194bSAdrian Hunter 		}
472930652aa3SOlof Johansson 	} else {
47301c6a0718SPierre Ossman 		mmc->max_seg_size = mmc->max_req_size;
473130652aa3SOlof Johansson 	}
47321c6a0718SPierre Ossman 
47331c6a0718SPierre Ossman 	/*
47341c6a0718SPierre Ossman 	 * Maximum block size. This varies from controller to controller and
47351c6a0718SPierre Ossman 	 * is specified in the capabilities register.
47361c6a0718SPierre Ossman 	 */
47370633f654SAnton Vorontsov 	if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) {
47380633f654SAnton Vorontsov 		mmc->max_blk_size = 2;
47390633f654SAnton Vorontsov 	} else {
474028da3589SAdrian Hunter 		mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >>
47410633f654SAnton Vorontsov 				SDHCI_MAX_BLOCK_SHIFT;
47421c6a0718SPierre Ossman 		if (mmc->max_blk_size >= 3) {
47436606110dSJoe Perches 			pr_warn("%s: Invalid maximum block size, assuming 512 bytes\n",
47446606110dSJoe Perches 				mmc_hostname(mmc));
47450633f654SAnton Vorontsov 			mmc->max_blk_size = 0;
47460633f654SAnton Vorontsov 		}
47470633f654SAnton Vorontsov 	}
47480633f654SAnton Vorontsov 
47491c6a0718SPierre Ossman 	mmc->max_blk_size = 512 << mmc->max_blk_size;
47501c6a0718SPierre Ossman 
47511c6a0718SPierre Ossman 	/*
47521c6a0718SPierre Ossman 	 * Maximum block count.
47531c6a0718SPierre Ossman 	 */
47541388eefdSBen Dooks 	mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
47551c6a0718SPierre Ossman 
4756a68dd9a0SChunyan Zhang 	if (mmc->max_segs == 1)
4757bd9b9027SLinus Walleij 		/* This may alter mmc->*_blk_* parameters */
4758a68dd9a0SChunyan Zhang 		sdhci_allocate_bounce_buffer(host);
4759bd9b9027SLinus Walleij 
476052f5336dSAdrian Hunter 	return 0;
476152f5336dSAdrian Hunter 
476252f5336dSAdrian Hunter unreg:
47630fcb031eSVijay Viswanath 	if (host->sdhci_core_to_disable_vqmmc)
476452f5336dSAdrian Hunter 		regulator_disable(mmc->supply.vqmmc);
476552f5336dSAdrian Hunter undma:
476652f5336dSAdrian Hunter 	if (host->align_buffer)
476752f5336dSAdrian Hunter 		dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz +
476852f5336dSAdrian Hunter 				  host->adma_table_sz, host->align_buffer,
476952f5336dSAdrian Hunter 				  host->align_addr);
477052f5336dSAdrian Hunter 	host->adma_table = NULL;
477152f5336dSAdrian Hunter 	host->align_buffer = NULL;
477252f5336dSAdrian Hunter 
477352f5336dSAdrian Hunter 	return ret;
477452f5336dSAdrian Hunter }
477552f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_setup_host);
477652f5336dSAdrian Hunter 
sdhci_cleanup_host(struct sdhci_host * host)47774180ffa8SAdrian Hunter void sdhci_cleanup_host(struct sdhci_host *host)
47784180ffa8SAdrian Hunter {
47794180ffa8SAdrian Hunter 	struct mmc_host *mmc = host->mmc;
47804180ffa8SAdrian Hunter 
47810fcb031eSVijay Viswanath 	if (host->sdhci_core_to_disable_vqmmc)
47824180ffa8SAdrian Hunter 		regulator_disable(mmc->supply.vqmmc);
47834180ffa8SAdrian Hunter 
47844180ffa8SAdrian Hunter 	if (host->align_buffer)
47854180ffa8SAdrian Hunter 		dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz +
47864180ffa8SAdrian Hunter 				  host->adma_table_sz, host->align_buffer,
47874180ffa8SAdrian Hunter 				  host->align_addr);
478818e762e3SChunyan Zhang 
478918e762e3SChunyan Zhang 	if (host->use_external_dma)
479018e762e3SChunyan Zhang 		sdhci_external_dma_release(host);
479118e762e3SChunyan Zhang 
47924180ffa8SAdrian Hunter 	host->adma_table = NULL;
47934180ffa8SAdrian Hunter 	host->align_buffer = NULL;
47944180ffa8SAdrian Hunter }
47954180ffa8SAdrian Hunter EXPORT_SYMBOL_GPL(sdhci_cleanup_host);
47964180ffa8SAdrian Hunter 
__sdhci_add_host(struct sdhci_host * host)479752f5336dSAdrian Hunter int __sdhci_add_host(struct sdhci_host *host)
479852f5336dSAdrian Hunter {
4799c07a48c2SAdrian Hunter 	unsigned int flags = WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI;
480052f5336dSAdrian Hunter 	struct mmc_host *mmc = host->mmc;
480152f5336dSAdrian Hunter 	int ret;
480252f5336dSAdrian Hunter 
48032b17b8d7SAdrian Hunter 	if ((mmc->caps2 & MMC_CAP2_CQE) &&
48042b17b8d7SAdrian Hunter 	    (host->quirks & SDHCI_QUIRK_BROKEN_CQE)) {
48052b17b8d7SAdrian Hunter 		mmc->caps2 &= ~MMC_CAP2_CQE;
48062b17b8d7SAdrian Hunter 		mmc->cqe_ops = NULL;
48072b17b8d7SAdrian Hunter 	}
48082b17b8d7SAdrian Hunter 
4809c07a48c2SAdrian Hunter 	host->complete_wq = alloc_workqueue("sdhci", flags, 0);
4810c07a48c2SAdrian Hunter 	if (!host->complete_wq)
4811c07a48c2SAdrian Hunter 		return -ENOMEM;
4812c07a48c2SAdrian Hunter 
4813c07a48c2SAdrian Hunter 	INIT_WORK(&host->complete_work, sdhci_complete_work);
48141c6a0718SPierre Ossman 
48152ee4f620SKees Cook 	timer_setup(&host->timer, sdhci_timeout_timer, 0);
48162ee4f620SKees Cook 	timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0);
48171c6a0718SPierre Ossman 
4818b513ea25SArindam Nath 	init_waitqueue_head(&host->buf_ready_int);
4819b513ea25SArindam Nath 
48202af502caSShawn Guo 	sdhci_init(host, 0);
48212af502caSShawn Guo 
4822781e989cSRussell King 	ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
4823781e989cSRussell King 				   IRQF_SHARED,	mmc_hostname(mmc), host);
48240fc81ee3SMark Brown 	if (ret) {
48250fc81ee3SMark Brown 		pr_err("%s: Failed to request IRQ %d: %d\n",
48260fc81ee3SMark Brown 		       mmc_hostname(mmc), host->irq, ret);
4827c07a48c2SAdrian Hunter 		goto unwq;
48280fc81ee3SMark Brown 	}
48291c6a0718SPierre Ossman 
4830061d17a6SAdrian Hunter 	ret = sdhci_led_register(host);
48310fc81ee3SMark Brown 	if (ret) {
48320fc81ee3SMark Brown 		pr_err("%s: Failed to register LED device: %d\n",
48330fc81ee3SMark Brown 		       mmc_hostname(mmc), ret);
4834eb5c20deSAdrian Hunter 		goto unirq;
48350fc81ee3SMark Brown 	}
48362f730fecSPierre Ossman 
4837eb5c20deSAdrian Hunter 	ret = mmc_add_host(mmc);
4838eb5c20deSAdrian Hunter 	if (ret)
4839eb5c20deSAdrian Hunter 		goto unled;
48401c6a0718SPierre Ossman 
4841a3c76eb9SGirish K S 	pr_info("%s: SDHCI controller on %s [%s] using %s\n",
4842d1b26863SKay Sievers 		mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
484318e762e3SChunyan Zhang 		host->use_external_dma ? "External DMA" :
4844e57a5f61SAdrian Hunter 		(host->flags & SDHCI_USE_ADMA) ?
4845e57a5f61SAdrian Hunter 		(host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" :
4846a13abc7bSRichard Röjfors 		(host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
48471c6a0718SPierre Ossman 
48487260cf5eSAnton Vorontsov 	sdhci_enable_card_detection(host);
48497260cf5eSAnton Vorontsov 
48501c6a0718SPierre Ossman 	return 0;
48511c6a0718SPierre Ossman 
4852eb5c20deSAdrian Hunter unled:
4853061d17a6SAdrian Hunter 	sdhci_led_unregister(host);
4854eb5c20deSAdrian Hunter unirq:
4855aa990722SAdrian Hunter 	sdhci_reset_for_all(host);
4856b537f94cSRussell King 	sdhci_writel(host, 0, SDHCI_INT_ENABLE);
4857b537f94cSRussell King 	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
48582f730fecSPierre Ossman 	free_irq(host->irq, host);
4859c07a48c2SAdrian Hunter unwq:
4860c07a48c2SAdrian Hunter 	destroy_workqueue(host->complete_wq);
486152f5336dSAdrian Hunter 
48621c6a0718SPierre Ossman 	return ret;
48631c6a0718SPierre Ossman }
486452f5336dSAdrian Hunter EXPORT_SYMBOL_GPL(__sdhci_add_host);
48651c6a0718SPierre Ossman 
sdhci_add_host(struct sdhci_host * host)486652f5336dSAdrian Hunter int sdhci_add_host(struct sdhci_host *host)
486752f5336dSAdrian Hunter {
486852f5336dSAdrian Hunter 	int ret;
486952f5336dSAdrian Hunter 
487052f5336dSAdrian Hunter 	ret = sdhci_setup_host(host);
487152f5336dSAdrian Hunter 	if (ret)
487252f5336dSAdrian Hunter 		return ret;
487352f5336dSAdrian Hunter 
48744180ffa8SAdrian Hunter 	ret = __sdhci_add_host(host);
48754180ffa8SAdrian Hunter 	if (ret)
48764180ffa8SAdrian Hunter 		goto cleanup;
48774180ffa8SAdrian Hunter 
48784180ffa8SAdrian Hunter 	return 0;
48794180ffa8SAdrian Hunter 
48804180ffa8SAdrian Hunter cleanup:
48814180ffa8SAdrian Hunter 	sdhci_cleanup_host(host);
48824180ffa8SAdrian Hunter 
48834180ffa8SAdrian Hunter 	return ret;
488452f5336dSAdrian Hunter }
4885b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_add_host);
4886b8c86fc5SPierre Ossman 
sdhci_remove_host(struct sdhci_host * host,int dead)48871e72859eSPierre Ossman void sdhci_remove_host(struct sdhci_host *host, int dead)
48881c6a0718SPierre Ossman {
48893a48edc4STim Kryger 	struct mmc_host *mmc = host->mmc;
48901e72859eSPierre Ossman 	unsigned long flags;
48911e72859eSPierre Ossman 
48921e72859eSPierre Ossman 	if (dead) {
48931e72859eSPierre Ossman 		spin_lock_irqsave(&host->lock, flags);
48941e72859eSPierre Ossman 
48951e72859eSPierre Ossman 		host->flags |= SDHCI_DEVICE_DEAD;
48961e72859eSPierre Ossman 
48975d0d11c5SAdrian Hunter 		if (sdhci_has_requests(host)) {
4898a3c76eb9SGirish K S 			pr_err("%s: Controller removed during "
48994e743f1fSMarkus Mayer 				" transfer!\n", mmc_hostname(mmc));
49005d0d11c5SAdrian Hunter 			sdhci_error_out_mrqs(host, -ENOMEDIUM);
49011e72859eSPierre Ossman 		}
49021e72859eSPierre Ossman 
49031e72859eSPierre Ossman 		spin_unlock_irqrestore(&host->lock, flags);
49041e72859eSPierre Ossman 	}
49051e72859eSPierre Ossman 
49067260cf5eSAnton Vorontsov 	sdhci_disable_card_detection(host);
49077260cf5eSAnton Vorontsov 
49084e743f1fSMarkus Mayer 	mmc_remove_host(mmc);
49091c6a0718SPierre Ossman 
4910061d17a6SAdrian Hunter 	sdhci_led_unregister(host);
49112f730fecSPierre Ossman 
49121e72859eSPierre Ossman 	if (!dead)
4913aa990722SAdrian Hunter 		sdhci_reset_for_all(host);
49141c6a0718SPierre Ossman 
4915b537f94cSRussell King 	sdhci_writel(host, 0, SDHCI_INT_ENABLE);
4916b537f94cSRussell King 	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
49171c6a0718SPierre Ossman 	free_irq(host->irq, host);
49181c6a0718SPierre Ossman 
49191c6a0718SPierre Ossman 	del_timer_sync(&host->timer);
4920d7422fb4SAdrian Hunter 	del_timer_sync(&host->data_timer);
49211c6a0718SPierre Ossman 
4922c07a48c2SAdrian Hunter 	destroy_workqueue(host->complete_wq);
49232134a922SPierre Ossman 
49240fcb031eSVijay Viswanath 	if (host->sdhci_core_to_disable_vqmmc)
49253a48edc4STim Kryger 		regulator_disable(mmc->supply.vqmmc);
49266231f3deSPhilip Rakity 
4927edd63fccSRussell King 	if (host->align_buffer)
4928e66e61cbSRussell King 		dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz +
4929e66e61cbSRussell King 				  host->adma_table_sz, host->align_buffer,
4930e66e61cbSRussell King 				  host->align_addr);
49312134a922SPierre Ossman 
493218e762e3SChunyan Zhang 	if (host->use_external_dma)
493318e762e3SChunyan Zhang 		sdhci_external_dma_release(host);
493418e762e3SChunyan Zhang 
49354efaa6fbSAdrian Hunter 	host->adma_table = NULL;
49362134a922SPierre Ossman 	host->align_buffer = NULL;
49371c6a0718SPierre Ossman }
49381c6a0718SPierre Ossman 
4939b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_remove_host);
4940b8c86fc5SPierre Ossman 
sdhci_free_host(struct sdhci_host * host)4941b8c86fc5SPierre Ossman void sdhci_free_host(struct sdhci_host *host)
49421c6a0718SPierre Ossman {
4943b8c86fc5SPierre Ossman 	mmc_free_host(host->mmc);
49441c6a0718SPierre Ossman }
49451c6a0718SPierre Ossman 
4946b8c86fc5SPierre Ossman EXPORT_SYMBOL_GPL(sdhci_free_host);
49471c6a0718SPierre Ossman 
49481c6a0718SPierre Ossman /*****************************************************************************\
49491c6a0718SPierre Ossman  *                                                                           *
49501c6a0718SPierre Ossman  * Driver init/exit                                                          *
49511c6a0718SPierre Ossman  *                                                                           *
49521c6a0718SPierre Ossman \*****************************************************************************/
49531c6a0718SPierre Ossman 
sdhci_drv_init(void)49541c6a0718SPierre Ossman static int __init sdhci_drv_init(void)
49551c6a0718SPierre Ossman {
4956a3c76eb9SGirish K S 	pr_info(DRIVER_NAME
49571c6a0718SPierre Ossman 		": Secure Digital Host Controller Interface driver\n");
4958a3c76eb9SGirish K S 	pr_info(DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
49591c6a0718SPierre Ossman 
4960b8c86fc5SPierre Ossman 	return 0;
49611c6a0718SPierre Ossman }
49621c6a0718SPierre Ossman 
sdhci_drv_exit(void)49631c6a0718SPierre Ossman static void __exit sdhci_drv_exit(void)
49641c6a0718SPierre Ossman {
49651c6a0718SPierre Ossman }
49661c6a0718SPierre Ossman 
49671c6a0718SPierre Ossman module_init(sdhci_drv_init);
49681c6a0718SPierre Ossman module_exit(sdhci_drv_exit);
49691c6a0718SPierre Ossman 
49701c6a0718SPierre Ossman module_param(debug_quirks, uint, 0444);
497166fd8ad5SAdrian Hunter module_param(debug_quirks2, uint, 0444);
49721c6a0718SPierre Ossman 
497332710e8fSPierre Ossman MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
4974b8c86fc5SPierre Ossman MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver");
49751c6a0718SPierre Ossman MODULE_LICENSE("GPL");
49761c6a0718SPierre Ossman 
49771c6a0718SPierre Ossman MODULE_PARM_DESC(debug_quirks, "Force certain quirks.");
497866fd8ad5SAdrian Hunter MODULE_PARM_DESC(debug_quirks2, "Force certain other quirks.");
4979