xref: /openbmc/linux/drivers/mmc/core/sdio_io.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
246f555f2SPierre Ossman /*
346f555f2SPierre Ossman  *  linux/drivers/mmc/core/sdio_io.c
446f555f2SPierre Ossman  *
5ad3868b2SPierre Ossman  *  Copyright 2007-2008 Pierre Ossman
646f555f2SPierre Ossman  */
746f555f2SPierre Ossman 
83ef77af1SPaul Gortmaker #include <linux/export.h>
9eae343c2SUlf Hansson #include <linux/kernel.h>
1046f555f2SPierre Ossman #include <linux/mmc/host.h>
1146f555f2SPierre Ossman #include <linux/mmc/card.h>
12fa64efa1SPierre Ossman #include <linux/mmc/sdio.h>
1346f555f2SPierre Ossman #include <linux/mmc/sdio_func.h>
1446f555f2SPierre Ossman 
1546f555f2SPierre Ossman #include "sdio_ops.h"
1655244c56SUlf Hansson #include "core.h"
174facdde1SUlf Hansson #include "card.h"
18b4c9f938SDouglas Anderson #include "host.h"
1946f555f2SPierre Ossman 
2046f555f2SPierre Ossman /**
2146f555f2SPierre Ossman  *	sdio_claim_host - exclusively claim a bus for a certain SDIO function
2246f555f2SPierre Ossman  *	@func: SDIO function that will be accessed
2346f555f2SPierre Ossman  *
2446f555f2SPierre Ossman  *	Claim a bus for a set of operations. The SDIO function given
2546f555f2SPierre Ossman  *	is used to figure out which bus is relevant.
2646f555f2SPierre Ossman  */
sdio_claim_host(struct sdio_func * func)2746f555f2SPierre Ossman void sdio_claim_host(struct sdio_func *func)
2846f555f2SPierre Ossman {
29923dff87SShawn Lin 	if (WARN_ON(!func))
30923dff87SShawn Lin 		return;
3146f555f2SPierre Ossman 
3246f555f2SPierre Ossman 	mmc_claim_host(func->card->host);
3346f555f2SPierre Ossman }
3446f555f2SPierre Ossman EXPORT_SYMBOL_GPL(sdio_claim_host);
3546f555f2SPierre Ossman 
3646f555f2SPierre Ossman /**
3746f555f2SPierre Ossman  *	sdio_release_host - release a bus for a certain SDIO function
3846f555f2SPierre Ossman  *	@func: SDIO function that was accessed
3946f555f2SPierre Ossman  *
4046f555f2SPierre Ossman  *	Release a bus, allowing others to claim the bus for their
4146f555f2SPierre Ossman  *	operations.
4246f555f2SPierre Ossman  */
sdio_release_host(struct sdio_func * func)4346f555f2SPierre Ossman void sdio_release_host(struct sdio_func *func)
4446f555f2SPierre Ossman {
45923dff87SShawn Lin 	if (WARN_ON(!func))
46923dff87SShawn Lin 		return;
4746f555f2SPierre Ossman 
4846f555f2SPierre Ossman 	mmc_release_host(func->card->host);
4946f555f2SPierre Ossman }
5046f555f2SPierre Ossman EXPORT_SYMBOL_GPL(sdio_release_host);
5146f555f2SPierre Ossman 
5246f555f2SPierre Ossman /**
53fa64efa1SPierre Ossman  *	sdio_enable_func - enables a SDIO function for usage
54fa64efa1SPierre Ossman  *	@func: SDIO function to enable
55fa64efa1SPierre Ossman  *
56fa64efa1SPierre Ossman  *	Powers up and activates a SDIO function so that register
57fa64efa1SPierre Ossman  *	access is possible.
58fa64efa1SPierre Ossman  */
sdio_enable_func(struct sdio_func * func)59fa64efa1SPierre Ossman int sdio_enable_func(struct sdio_func *func)
60fa64efa1SPierre Ossman {
61fa64efa1SPierre Ossman 	int ret;
62fa64efa1SPierre Ossman 	unsigned char reg;
63fa64efa1SPierre Ossman 	unsigned long timeout;
64fa64efa1SPierre Ossman 
65923dff87SShawn Lin 	if (!func)
66923dff87SShawn Lin 		return -EINVAL;
67fa64efa1SPierre Ossman 
68fa64efa1SPierre Ossman 	pr_debug("SDIO: Enabling device %s...\n", sdio_func_id(func));
69fa64efa1SPierre Ossman 
70fa64efa1SPierre Ossman 	ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IOEx, 0, &reg);
71fa64efa1SPierre Ossman 	if (ret)
72fa64efa1SPierre Ossman 		goto err;
73fa64efa1SPierre Ossman 
74fa64efa1SPierre Ossman 	reg |= 1 << func->num;
75fa64efa1SPierre Ossman 
76fa64efa1SPierre Ossman 	ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IOEx, reg, NULL);
77fa64efa1SPierre Ossman 	if (ret)
78fa64efa1SPierre Ossman 		goto err;
79fa64efa1SPierre Ossman 
8062a7573eSBenzi Zbit 	timeout = jiffies + msecs_to_jiffies(func->enable_timeout);
81fa64efa1SPierre Ossman 
82fa64efa1SPierre Ossman 	while (1) {
83fa64efa1SPierre Ossman 		ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IORx, 0, &reg);
84fa64efa1SPierre Ossman 		if (ret)
85fa64efa1SPierre Ossman 			goto err;
86fa64efa1SPierre Ossman 		if (reg & (1 << func->num))
87fa64efa1SPierre Ossman 			break;
88fa64efa1SPierre Ossman 		ret = -ETIME;
89fa64efa1SPierre Ossman 		if (time_after(jiffies, timeout))
90fa64efa1SPierre Ossman 			goto err;
91fa64efa1SPierre Ossman 	}
92fa64efa1SPierre Ossman 
93fa64efa1SPierre Ossman 	pr_debug("SDIO: Enabled device %s\n", sdio_func_id(func));
94fa64efa1SPierre Ossman 
95fa64efa1SPierre Ossman 	return 0;
96fa64efa1SPierre Ossman 
97fa64efa1SPierre Ossman err:
98fa64efa1SPierre Ossman 	pr_debug("SDIO: Failed to enable device %s\n", sdio_func_id(func));
99fa64efa1SPierre Ossman 	return ret;
100fa64efa1SPierre Ossman }
101fa64efa1SPierre Ossman EXPORT_SYMBOL_GPL(sdio_enable_func);
102fa64efa1SPierre Ossman 
103fa64efa1SPierre Ossman /**
104fa64efa1SPierre Ossman  *	sdio_disable_func - disable a SDIO function
105fa64efa1SPierre Ossman  *	@func: SDIO function to disable
106fa64efa1SPierre Ossman  *
107fa64efa1SPierre Ossman  *	Powers down and deactivates a SDIO function. Register access
108fa64efa1SPierre Ossman  *	to this function will fail until the function is reenabled.
109fa64efa1SPierre Ossman  */
sdio_disable_func(struct sdio_func * func)110fa64efa1SPierre Ossman int sdio_disable_func(struct sdio_func *func)
111fa64efa1SPierre Ossman {
112fa64efa1SPierre Ossman 	int ret;
113fa64efa1SPierre Ossman 	unsigned char reg;
114fa64efa1SPierre Ossman 
115923dff87SShawn Lin 	if (!func)
116923dff87SShawn Lin 		return -EINVAL;
117fa64efa1SPierre Ossman 
118fa64efa1SPierre Ossman 	pr_debug("SDIO: Disabling device %s...\n", sdio_func_id(func));
119fa64efa1SPierre Ossman 
120fa64efa1SPierre Ossman 	ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IOEx, 0, &reg);
121fa64efa1SPierre Ossman 	if (ret)
122fa64efa1SPierre Ossman 		goto err;
123fa64efa1SPierre Ossman 
124fa64efa1SPierre Ossman 	reg &= ~(1 << func->num);
125fa64efa1SPierre Ossman 
126fa64efa1SPierre Ossman 	ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IOEx, reg, NULL);
127fa64efa1SPierre Ossman 	if (ret)
128fa64efa1SPierre Ossman 		goto err;
129fa64efa1SPierre Ossman 
130fa64efa1SPierre Ossman 	pr_debug("SDIO: Disabled device %s\n", sdio_func_id(func));
131fa64efa1SPierre Ossman 
132fa64efa1SPierre Ossman 	return 0;
133fa64efa1SPierre Ossman 
134fa64efa1SPierre Ossman err:
135fa64efa1SPierre Ossman 	pr_debug("SDIO: Failed to disable device %s\n", sdio_func_id(func));
13642a166d7SYue Hu 	return ret;
137fa64efa1SPierre Ossman }
138fa64efa1SPierre Ossman EXPORT_SYMBOL_GPL(sdio_disable_func);
139fa64efa1SPierre Ossman 
140fa64efa1SPierre Ossman /**
1419a08f82bSDavid Vrabel  *	sdio_set_block_size - set the block size of an SDIO function
1429a08f82bSDavid Vrabel  *	@func: SDIO function to change
1439a08f82bSDavid Vrabel  *	@blksz: new block size or 0 to use the default.
1449a08f82bSDavid Vrabel  *
1459a08f82bSDavid Vrabel  *	The default block size is the largest supported by both the function
1469a08f82bSDavid Vrabel  *	and the host, with a maximum of 512 to ensure that arbitrarily sized
1479a08f82bSDavid Vrabel  *	data transfer use the optimal (least) number of commands.
1489a08f82bSDavid Vrabel  *
1499a08f82bSDavid Vrabel  *	A driver may call this to override the default block size set by the
1509a08f82bSDavid Vrabel  *	core. This can be used to set a block size greater than the maximum
1519a08f82bSDavid Vrabel  *	that reported by the card; it is the driver's responsibility to ensure
1529a08f82bSDavid Vrabel  *	it uses a value that the card supports.
1539a08f82bSDavid Vrabel  *
1549a08f82bSDavid Vrabel  *	Returns 0 on success, -EINVAL if the host does not support the
1559a08f82bSDavid Vrabel  *	requested block size, or -EIO (etc.) if one of the resultant FBR block
1569a08f82bSDavid Vrabel  *	size register writes failed.
1579a08f82bSDavid Vrabel  *
1589a08f82bSDavid Vrabel  */
sdio_set_block_size(struct sdio_func * func,unsigned blksz)1599a08f82bSDavid Vrabel int sdio_set_block_size(struct sdio_func *func, unsigned blksz)
1609a08f82bSDavid Vrabel {
1619a08f82bSDavid Vrabel 	int ret;
1629a08f82bSDavid Vrabel 
1639a08f82bSDavid Vrabel 	if (blksz > func->card->host->max_blk_size)
1649a08f82bSDavid Vrabel 		return -EINVAL;
1659a08f82bSDavid Vrabel 
1669a08f82bSDavid Vrabel 	if (blksz == 0) {
1676d373331STomas Winkler 		blksz = min(func->max_blksize, func->card->host->max_blk_size);
1686d373331STomas Winkler 		blksz = min(blksz, 512u);
1699a08f82bSDavid Vrabel 	}
1709a08f82bSDavid Vrabel 
1719a08f82bSDavid Vrabel 	ret = mmc_io_rw_direct(func->card, 1, 0,
1729a08f82bSDavid Vrabel 		SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE,
1739a08f82bSDavid Vrabel 		blksz & 0xff, NULL);
1749a08f82bSDavid Vrabel 	if (ret)
1759a08f82bSDavid Vrabel 		return ret;
1769a08f82bSDavid Vrabel 	ret = mmc_io_rw_direct(func->card, 1, 0,
1779a08f82bSDavid Vrabel 		SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1,
1789a08f82bSDavid Vrabel 		(blksz >> 8) & 0xff, NULL);
1799a08f82bSDavid Vrabel 	if (ret)
1809a08f82bSDavid Vrabel 		return ret;
1819a08f82bSDavid Vrabel 	func->cur_blksize = blksz;
1829a08f82bSDavid Vrabel 	return 0;
1839a08f82bSDavid Vrabel }
1849a08f82bSDavid Vrabel EXPORT_SYMBOL_GPL(sdio_set_block_size);
1859a08f82bSDavid Vrabel 
186eea0f581SPierre Ossman /*
187eea0f581SPierre Ossman  * Calculate the maximum byte mode transfer size
188eea0f581SPierre Ossman  */
sdio_max_byte_size(struct sdio_func * func)189eea0f581SPierre Ossman static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
190eea0f581SPierre Ossman {
191968a64eaSKyoungil Kim 	unsigned mval =	func->card->host->max_blk_size;
1923fb7fb4aSBing Zhao 
1933fb7fb4aSBing Zhao 	if (mmc_blksz_for_byte_mode(func->card))
1943fb7fb4aSBing Zhao 		mval = min(mval, func->cur_blksize);
1953fb7fb4aSBing Zhao 	else
196ea901300STomas Winkler 		mval = min(mval, func->max_blksize);
1973fb7fb4aSBing Zhao 
198052d81daSStefan Nilsson XK 	if (mmc_card_broken_byte_mode_512(func->card))
199052d81daSStefan Nilsson XK 		return min(mval, 511u);
200052d81daSStefan Nilsson XK 
201ea901300STomas Winkler 	return min(mval, 512u); /* maximum size for byte mode */
202eea0f581SPierre Ossman }
203eea0f581SPierre Ossman 
204eae343c2SUlf Hansson /*
205eae343c2SUlf Hansson  * This is legacy code, which needs to be re-worked some day. Basically we need
206eae343c2SUlf Hansson  * to take into account the properties of the host, as to enable the SDIO func
207eae343c2SUlf Hansson  * driver layer to allocate optimal buffers.
208eae343c2SUlf Hansson  */
_sdio_align_size(unsigned int sz)209eae343c2SUlf Hansson static inline unsigned int _sdio_align_size(unsigned int sz)
210eae343c2SUlf Hansson {
211eae343c2SUlf Hansson 	/*
212eae343c2SUlf Hansson 	 * FIXME: We don't have a system for the controller to tell
213eae343c2SUlf Hansson 	 * the core about its problems yet, so for now we just 32-bit
214eae343c2SUlf Hansson 	 * align the size.
215eae343c2SUlf Hansson 	 */
216eae343c2SUlf Hansson 	return ALIGN(sz, 4);
217eae343c2SUlf Hansson }
218eae343c2SUlf Hansson 
219ad3868b2SPierre Ossman /**
220ad3868b2SPierre Ossman  *	sdio_align_size - pads a transfer size to a more optimal value
221ad3868b2SPierre Ossman  *	@func: SDIO function
222ad3868b2SPierre Ossman  *	@sz: original transfer size
223ad3868b2SPierre Ossman  *
224ad3868b2SPierre Ossman  *	Pads the original data size with a number of extra bytes in
225ad3868b2SPierre Ossman  *	order to avoid controller bugs and/or performance hits
226ad3868b2SPierre Ossman  *	(e.g. some controllers revert to PIO for certain sizes).
227ad3868b2SPierre Ossman  *
228ad3868b2SPierre Ossman  *	If possible, it will also adjust the size so that it can be
229ad3868b2SPierre Ossman  *	handled in just a single request.
230ad3868b2SPierre Ossman  *
231ad3868b2SPierre Ossman  *	Returns the improved size, which might be unmodified.
232ad3868b2SPierre Ossman  */
sdio_align_size(struct sdio_func * func,unsigned int sz)233ad3868b2SPierre Ossman unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
234ad3868b2SPierre Ossman {
235ad3868b2SPierre Ossman 	unsigned int orig_sz;
236ad3868b2SPierre Ossman 	unsigned int blk_sz, byte_sz;
237ad3868b2SPierre Ossman 	unsigned chunk_sz;
238ad3868b2SPierre Ossman 
239ad3868b2SPierre Ossman 	orig_sz = sz;
240ad3868b2SPierre Ossman 
241ad3868b2SPierre Ossman 	/*
242ad3868b2SPierre Ossman 	 * Do a first check with the controller, in case it
243ad3868b2SPierre Ossman 	 * wants to increase the size up to a point where it
244ad3868b2SPierre Ossman 	 * might need more than one block.
245ad3868b2SPierre Ossman 	 */
246eae343c2SUlf Hansson 	sz = _sdio_align_size(sz);
247ad3868b2SPierre Ossman 
248ad3868b2SPierre Ossman 	/*
249ad3868b2SPierre Ossman 	 * If we can still do this with just a byte transfer, then
250ad3868b2SPierre Ossman 	 * we're done.
251ad3868b2SPierre Ossman 	 */
252eea0f581SPierre Ossman 	if (sz <= sdio_max_byte_size(func))
253ad3868b2SPierre Ossman 		return sz;
254ad3868b2SPierre Ossman 
255ad3868b2SPierre Ossman 	if (func->card->cccr.multi_block) {
256ad3868b2SPierre Ossman 		/*
257ad3868b2SPierre Ossman 		 * Check if the transfer is already block aligned
258ad3868b2SPierre Ossman 		 */
259ad3868b2SPierre Ossman 		if ((sz % func->cur_blksize) == 0)
260ad3868b2SPierre Ossman 			return sz;
261ad3868b2SPierre Ossman 
262ad3868b2SPierre Ossman 		/*
263ad3868b2SPierre Ossman 		 * Realign it so that it can be done with one request,
264ad3868b2SPierre Ossman 		 * and recheck if the controller still likes it.
265ad3868b2SPierre Ossman 		 */
266ad3868b2SPierre Ossman 		blk_sz = ((sz + func->cur_blksize - 1) /
267ad3868b2SPierre Ossman 			func->cur_blksize) * func->cur_blksize;
268eae343c2SUlf Hansson 		blk_sz = _sdio_align_size(blk_sz);
269ad3868b2SPierre Ossman 
270ad3868b2SPierre Ossman 		/*
271ad3868b2SPierre Ossman 		 * This value is only good if it is still just
272ad3868b2SPierre Ossman 		 * one request.
273ad3868b2SPierre Ossman 		 */
274ad3868b2SPierre Ossman 		if ((blk_sz % func->cur_blksize) == 0)
275ad3868b2SPierre Ossman 			return blk_sz;
276ad3868b2SPierre Ossman 
277ad3868b2SPierre Ossman 		/*
278ad3868b2SPierre Ossman 		 * We failed to do one request, but at least try to
279ad3868b2SPierre Ossman 		 * pad the remainder properly.
280ad3868b2SPierre Ossman 		 */
281eae343c2SUlf Hansson 		byte_sz = _sdio_align_size(sz % func->cur_blksize);
282eea0f581SPierre Ossman 		if (byte_sz <= sdio_max_byte_size(func)) {
283ad3868b2SPierre Ossman 			blk_sz = sz / func->cur_blksize;
284ad3868b2SPierre Ossman 			return blk_sz * func->cur_blksize + byte_sz;
285ad3868b2SPierre Ossman 		}
286ad3868b2SPierre Ossman 	} else {
287ad3868b2SPierre Ossman 		/*
288ad3868b2SPierre Ossman 		 * We need multiple requests, so first check that the
289ad3868b2SPierre Ossman 		 * controller can handle the chunk size;
290ad3868b2SPierre Ossman 		 */
291eae343c2SUlf Hansson 		chunk_sz = _sdio_align_size(sdio_max_byte_size(func));
292eea0f581SPierre Ossman 		if (chunk_sz == sdio_max_byte_size(func)) {
293ad3868b2SPierre Ossman 			/*
294ad3868b2SPierre Ossman 			 * Fix up the size of the remainder (if any)
295ad3868b2SPierre Ossman 			 */
296ad3868b2SPierre Ossman 			byte_sz = orig_sz % chunk_sz;
297ad3868b2SPierre Ossman 			if (byte_sz) {
298eae343c2SUlf Hansson 				byte_sz = _sdio_align_size(byte_sz);
299ad3868b2SPierre Ossman 			}
300ad3868b2SPierre Ossman 
301ad3868b2SPierre Ossman 			return (orig_sz / chunk_sz) * chunk_sz + byte_sz;
302ad3868b2SPierre Ossman 		}
303ad3868b2SPierre Ossman 	}
304ad3868b2SPierre Ossman 
305ad3868b2SPierre Ossman 	/*
306ad3868b2SPierre Ossman 	 * The controller is simply incapable of transferring the size
307ad3868b2SPierre Ossman 	 * we want in decent manner, so just return the original size.
308ad3868b2SPierre Ossman 	 */
309ad3868b2SPierre Ossman 	return orig_sz;
310ad3868b2SPierre Ossman }
311ad3868b2SPierre Ossman EXPORT_SYMBOL_GPL(sdio_align_size);
312ad3868b2SPierre Ossman 
313eb659468SDavid Vrabel /* Split an arbitrarily sized data transfer into several
314eb659468SDavid Vrabel  * IO_RW_EXTENDED commands. */
sdio_io_rw_ext_helper(struct sdio_func * func,int write,unsigned addr,int incr_addr,u8 * buf,unsigned size)315eb659468SDavid Vrabel static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
316eb659468SDavid Vrabel 	unsigned addr, int incr_addr, u8 *buf, unsigned size)
317eb659468SDavid Vrabel {
318eb659468SDavid Vrabel 	unsigned remainder = size;
319eb659468SDavid Vrabel 	unsigned max_blocks;
320eb659468SDavid Vrabel 	int ret;
321eb659468SDavid Vrabel 
322923dff87SShawn Lin 	if (!func || (func->num > 7))
323923dff87SShawn Lin 		return -EINVAL;
324923dff87SShawn Lin 
325eb659468SDavid Vrabel 	/* Do the bulk of the transfer using block mode (if supported). */
326eea0f581SPierre Ossman 	if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) {
327eb659468SDavid Vrabel 		/* Blocks per command is limited by host count, host transfer
328968a64eaSKyoungil Kim 		 * size and the maximum for IO_RW_EXTENDED of 511 blocks. */
329968a64eaSKyoungil Kim 		max_blocks = min(func->card->host->max_blk_count, 511u);
330eb659468SDavid Vrabel 
331052d81daSStefan Nilsson XK 		while (remainder >= func->cur_blksize) {
332eb659468SDavid Vrabel 			unsigned blocks;
333eb659468SDavid Vrabel 
334eb659468SDavid Vrabel 			blocks = remainder / func->cur_blksize;
335eb659468SDavid Vrabel 			if (blocks > max_blocks)
336eb659468SDavid Vrabel 				blocks = max_blocks;
337eb659468SDavid Vrabel 			size = blocks * func->cur_blksize;
338eb659468SDavid Vrabel 
339eb659468SDavid Vrabel 			ret = mmc_io_rw_extended(func->card, write,
340eb659468SDavid Vrabel 				func->num, addr, incr_addr, buf,
341eb659468SDavid Vrabel 				blocks, func->cur_blksize);
342eb659468SDavid Vrabel 			if (ret)
343eb659468SDavid Vrabel 				return ret;
344eb659468SDavid Vrabel 
345eb659468SDavid Vrabel 			remainder -= size;
346eb659468SDavid Vrabel 			buf += size;
347eb659468SDavid Vrabel 			if (incr_addr)
348eb659468SDavid Vrabel 				addr += size;
349eb659468SDavid Vrabel 		}
350eb659468SDavid Vrabel 	}
351eb659468SDavid Vrabel 
352eb659468SDavid Vrabel 	/* Write the remainder using byte mode. */
353eb659468SDavid Vrabel 	while (remainder > 0) {
354eea0f581SPierre Ossman 		size = min(remainder, sdio_max_byte_size(func));
355eb659468SDavid Vrabel 
356052d81daSStefan Nilsson XK 		/* Indicate byte mode by setting "blocks" = 0 */
357eb659468SDavid Vrabel 		ret = mmc_io_rw_extended(func->card, write, func->num, addr,
358052d81daSStefan Nilsson XK 			 incr_addr, buf, 0, size);
359eb659468SDavid Vrabel 		if (ret)
360eb659468SDavid Vrabel 			return ret;
361eb659468SDavid Vrabel 
362eb659468SDavid Vrabel 		remainder -= size;
363eb659468SDavid Vrabel 		buf += size;
364eb659468SDavid Vrabel 		if (incr_addr)
365eb659468SDavid Vrabel 			addr += size;
366eb659468SDavid Vrabel 	}
367eb659468SDavid Vrabel 	return 0;
368eb659468SDavid Vrabel }
369eb659468SDavid Vrabel 
3709a08f82bSDavid Vrabel /**
37146f555f2SPierre Ossman  *	sdio_readb - read a single byte from a SDIO function
37246f555f2SPierre Ossman  *	@func: SDIO function to access
37346f555f2SPierre Ossman  *	@addr: address to read
37446f555f2SPierre Ossman  *	@err_ret: optional status value from transfer
37546f555f2SPierre Ossman  *
37646f555f2SPierre Ossman  *	Reads a single byte from the address space of a given SDIO
37746f555f2SPierre Ossman  *	function. If there is a problem reading the address, 0xff
37846f555f2SPierre Ossman  *	is returned and @err_ret will contain the error code.
37946f555f2SPierre Ossman  */
sdio_readb(struct sdio_func * func,unsigned int addr,int * err_ret)3806d373331STomas Winkler u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret)
38146f555f2SPierre Ossman {
38246f555f2SPierre Ossman 	int ret;
3836d373331STomas Winkler 	u8 val;
38446f555f2SPierre Ossman 
385923dff87SShawn Lin 	if (!func) {
3869b980d95Stcharding 		if (err_ret)
387923dff87SShawn Lin 			*err_ret = -EINVAL;
388923dff87SShawn Lin 		return 0xFF;
389923dff87SShawn Lin 	}
39046f555f2SPierre Ossman 
39146f555f2SPierre Ossman 	ret = mmc_io_rw_direct(func->card, 0, func->num, addr, 0, &val);
39246f555f2SPierre Ossman 	if (err_ret)
39346f555f2SPierre Ossman 		*err_ret = ret;
3948e11b284Stcharding 	if (ret)
39546f555f2SPierre Ossman 		return 0xFF;
39646f555f2SPierre Ossman 
39746f555f2SPierre Ossman 	return val;
39846f555f2SPierre Ossman }
39946f555f2SPierre Ossman EXPORT_SYMBOL_GPL(sdio_readb);
40046f555f2SPierre Ossman 
40146f555f2SPierre Ossman /**
40246f555f2SPierre Ossman  *	sdio_writeb - write a single byte to a SDIO function
40346f555f2SPierre Ossman  *	@func: SDIO function to access
40446f555f2SPierre Ossman  *	@b: byte to write
40546f555f2SPierre Ossman  *	@addr: address to write to
40646f555f2SPierre Ossman  *	@err_ret: optional status value from transfer
40746f555f2SPierre Ossman  *
40846f555f2SPierre Ossman  *	Writes a single byte to the address space of a given SDIO
40946f555f2SPierre Ossman  *	function. @err_ret will contain the status of the actual
41046f555f2SPierre Ossman  *	transfer.
41146f555f2SPierre Ossman  */
sdio_writeb(struct sdio_func * func,u8 b,unsigned int addr,int * err_ret)4126d373331STomas Winkler void sdio_writeb(struct sdio_func *func, u8 b, unsigned int addr, int *err_ret)
41346f555f2SPierre Ossman {
41446f555f2SPierre Ossman 	int ret;
41546f555f2SPierre Ossman 
416923dff87SShawn Lin 	if (!func) {
4179b980d95Stcharding 		if (err_ret)
418923dff87SShawn Lin 			*err_ret = -EINVAL;
419923dff87SShawn Lin 		return;
420923dff87SShawn Lin 	}
42146f555f2SPierre Ossman 
42246f555f2SPierre Ossman 	ret = mmc_io_rw_direct(func->card, 1, func->num, addr, b, NULL);
42346f555f2SPierre Ossman 	if (err_ret)
42446f555f2SPierre Ossman 		*err_ret = ret;
42546f555f2SPierre Ossman }
42646f555f2SPierre Ossman EXPORT_SYMBOL_GPL(sdio_writeb);
42746f555f2SPierre Ossman 
428112c9db9SPierre Ossman /**
4296c1f716eSGrazvydas Ignotas  *	sdio_writeb_readb - write and read a byte from SDIO function
4306c1f716eSGrazvydas Ignotas  *	@func: SDIO function to access
4316c1f716eSGrazvydas Ignotas  *	@write_byte: byte to write
4326c1f716eSGrazvydas Ignotas  *	@addr: address to write to
4336c1f716eSGrazvydas Ignotas  *	@err_ret: optional status value from transfer
4346c1f716eSGrazvydas Ignotas  *
4356c1f716eSGrazvydas Ignotas  *	Performs a RAW (Read after Write) operation as defined by SDIO spec -
4366c1f716eSGrazvydas Ignotas  *	single byte is written to address space of a given SDIO function and
4376c1f716eSGrazvydas Ignotas  *	response is read back from the same address, both using single request.
4386c1f716eSGrazvydas Ignotas  *	If there is a problem with the operation, 0xff is returned and
4396c1f716eSGrazvydas Ignotas  *	@err_ret will contain the error code.
4406c1f716eSGrazvydas Ignotas  */
sdio_writeb_readb(struct sdio_func * func,u8 write_byte,unsigned int addr,int * err_ret)4416c1f716eSGrazvydas Ignotas u8 sdio_writeb_readb(struct sdio_func *func, u8 write_byte,
4426c1f716eSGrazvydas Ignotas 	unsigned int addr, int *err_ret)
4436c1f716eSGrazvydas Ignotas {
4446c1f716eSGrazvydas Ignotas 	int ret;
4456c1f716eSGrazvydas Ignotas 	u8 val;
4466c1f716eSGrazvydas Ignotas 
4476c1f716eSGrazvydas Ignotas 	ret = mmc_io_rw_direct(func->card, 1, func->num, addr,
4486c1f716eSGrazvydas Ignotas 			write_byte, &val);
4496c1f716eSGrazvydas Ignotas 	if (err_ret)
4506c1f716eSGrazvydas Ignotas 		*err_ret = ret;
4516c1f716eSGrazvydas Ignotas 	if (ret)
4528e11b284Stcharding 		return 0xff;
4536c1f716eSGrazvydas Ignotas 
4546c1f716eSGrazvydas Ignotas 	return val;
4556c1f716eSGrazvydas Ignotas }
4566c1f716eSGrazvydas Ignotas EXPORT_SYMBOL_GPL(sdio_writeb_readb);
4576c1f716eSGrazvydas Ignotas 
4586c1f716eSGrazvydas Ignotas /**
459112c9db9SPierre Ossman  *	sdio_memcpy_fromio - read a chunk of memory from a SDIO function
460112c9db9SPierre Ossman  *	@func: SDIO function to access
461112c9db9SPierre Ossman  *	@dst: buffer to store the data
462112c9db9SPierre Ossman  *	@addr: address to begin reading from
463112c9db9SPierre Ossman  *	@count: number of bytes to read
464112c9db9SPierre Ossman  *
465eb659468SDavid Vrabel  *	Reads from the address space of a given SDIO function. Return
466eb659468SDavid Vrabel  *	value indicates if the transfer succeeded or not.
467112c9db9SPierre Ossman  */
sdio_memcpy_fromio(struct sdio_func * func,void * dst,unsigned int addr,int count)468112c9db9SPierre Ossman int sdio_memcpy_fromio(struct sdio_func *func, void *dst,
469112c9db9SPierre Ossman 	unsigned int addr, int count)
470112c9db9SPierre Ossman {
471eb659468SDavid Vrabel 	return sdio_io_rw_ext_helper(func, 0, addr, 1, dst, count);
472112c9db9SPierre Ossman }
473112c9db9SPierre Ossman EXPORT_SYMBOL_GPL(sdio_memcpy_fromio);
474112c9db9SPierre Ossman 
475112c9db9SPierre Ossman /**
476112c9db9SPierre Ossman  *	sdio_memcpy_toio - write a chunk of memory to a SDIO function
477112c9db9SPierre Ossman  *	@func: SDIO function to access
478112c9db9SPierre Ossman  *	@addr: address to start writing to
479112c9db9SPierre Ossman  *	@src: buffer that contains the data to write
480112c9db9SPierre Ossman  *	@count: number of bytes to write
481112c9db9SPierre Ossman  *
482eb659468SDavid Vrabel  *	Writes to the address space of a given SDIO function. Return
483eb659468SDavid Vrabel  *	value indicates if the transfer succeeded or not.
484112c9db9SPierre Ossman  */
sdio_memcpy_toio(struct sdio_func * func,unsigned int addr,void * src,int count)485112c9db9SPierre Ossman int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr,
486112c9db9SPierre Ossman 	void *src, int count)
487112c9db9SPierre Ossman {
488eb659468SDavid Vrabel 	return sdio_io_rw_ext_helper(func, 1, addr, 1, src, count);
489112c9db9SPierre Ossman }
490112c9db9SPierre Ossman EXPORT_SYMBOL_GPL(sdio_memcpy_toio);
491112c9db9SPierre Ossman 
492112c9db9SPierre Ossman /**
493112c9db9SPierre Ossman  *	sdio_readsb - read from a FIFO on a SDIO function
494112c9db9SPierre Ossman  *	@func: SDIO function to access
495112c9db9SPierre Ossman  *	@dst: buffer to store the data
496112c9db9SPierre Ossman  *	@addr: address of (single byte) FIFO
497112c9db9SPierre Ossman  *	@count: number of bytes to read
498112c9db9SPierre Ossman  *
499eb659468SDavid Vrabel  *	Reads from the specified FIFO of a given SDIO function. Return
500eb659468SDavid Vrabel  *	value indicates if the transfer succeeded or not.
501112c9db9SPierre Ossman  */
sdio_readsb(struct sdio_func * func,void * dst,unsigned int addr,int count)502112c9db9SPierre Ossman int sdio_readsb(struct sdio_func *func, void *dst, unsigned int addr,
503112c9db9SPierre Ossman 	int count)
504112c9db9SPierre Ossman {
505eb659468SDavid Vrabel 	return sdio_io_rw_ext_helper(func, 0, addr, 0, dst, count);
506112c9db9SPierre Ossman }
507112c9db9SPierre Ossman EXPORT_SYMBOL_GPL(sdio_readsb);
508112c9db9SPierre Ossman 
509112c9db9SPierre Ossman /**
510112c9db9SPierre Ossman  *	sdio_writesb - write to a FIFO of a SDIO function
511112c9db9SPierre Ossman  *	@func: SDIO function to access
512112c9db9SPierre Ossman  *	@addr: address of (single byte) FIFO
513112c9db9SPierre Ossman  *	@src: buffer that contains the data to write
514112c9db9SPierre Ossman  *	@count: number of bytes to write
515112c9db9SPierre Ossman  *
516eb659468SDavid Vrabel  *	Writes to the specified FIFO of a given SDIO function. Return
517eb659468SDavid Vrabel  *	value indicates if the transfer succeeded or not.
518112c9db9SPierre Ossman  */
sdio_writesb(struct sdio_func * func,unsigned int addr,void * src,int count)519112c9db9SPierre Ossman int sdio_writesb(struct sdio_func *func, unsigned int addr, void *src,
520112c9db9SPierre Ossman 	int count)
521112c9db9SPierre Ossman {
522eb659468SDavid Vrabel 	return sdio_io_rw_ext_helper(func, 1, addr, 0, src, count);
523112c9db9SPierre Ossman }
524112c9db9SPierre Ossman EXPORT_SYMBOL_GPL(sdio_writesb);
525112c9db9SPierre Ossman 
526112c9db9SPierre Ossman /**
527112c9db9SPierre Ossman  *	sdio_readw - read a 16 bit integer from a SDIO function
528112c9db9SPierre Ossman  *	@func: SDIO function to access
529112c9db9SPierre Ossman  *	@addr: address to read
530112c9db9SPierre Ossman  *	@err_ret: optional status value from transfer
531112c9db9SPierre Ossman  *
532112c9db9SPierre Ossman  *	Reads a 16 bit integer from the address space of a given SDIO
533112c9db9SPierre Ossman  *	function. If there is a problem reading the address, 0xffff
534112c9db9SPierre Ossman  *	is returned and @err_ret will contain the error code.
535112c9db9SPierre Ossman  */
sdio_readw(struct sdio_func * func,unsigned int addr,int * err_ret)5366d373331STomas Winkler u16 sdio_readw(struct sdio_func *func, unsigned int addr, int *err_ret)
537112c9db9SPierre Ossman {
538112c9db9SPierre Ossman 	int ret;
539112c9db9SPierre Ossman 
540112c9db9SPierre Ossman 	ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 2);
541112c9db9SPierre Ossman 	if (err_ret)
542112c9db9SPierre Ossman 		*err_ret = ret;
5438e11b284Stcharding 	if (ret)
544112c9db9SPierre Ossman 		return 0xFFFF;
545112c9db9SPierre Ossman 
5466d373331STomas Winkler 	return le16_to_cpup((__le16 *)func->tmpbuf);
547112c9db9SPierre Ossman }
548112c9db9SPierre Ossman EXPORT_SYMBOL_GPL(sdio_readw);
549112c9db9SPierre Ossman 
550112c9db9SPierre Ossman /**
551112c9db9SPierre Ossman  *	sdio_writew - write a 16 bit integer to a SDIO function
552112c9db9SPierre Ossman  *	@func: SDIO function to access
553112c9db9SPierre Ossman  *	@b: integer to write
554112c9db9SPierre Ossman  *	@addr: address to write to
555112c9db9SPierre Ossman  *	@err_ret: optional status value from transfer
556112c9db9SPierre Ossman  *
557112c9db9SPierre Ossman  *	Writes a 16 bit integer to the address space of a given SDIO
558112c9db9SPierre Ossman  *	function. @err_ret will contain the status of the actual
559112c9db9SPierre Ossman  *	transfer.
560112c9db9SPierre Ossman  */
sdio_writew(struct sdio_func * func,u16 b,unsigned int addr,int * err_ret)5616d373331STomas Winkler void sdio_writew(struct sdio_func *func, u16 b, unsigned int addr, int *err_ret)
562112c9db9SPierre Ossman {
563112c9db9SPierre Ossman 	int ret;
564112c9db9SPierre Ossman 
5656d373331STomas Winkler 	*(__le16 *)func->tmpbuf = cpu_to_le16(b);
566112c9db9SPierre Ossman 
567112c9db9SPierre Ossman 	ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 2);
568112c9db9SPierre Ossman 	if (err_ret)
569112c9db9SPierre Ossman 		*err_ret = ret;
570112c9db9SPierre Ossman }
571112c9db9SPierre Ossman EXPORT_SYMBOL_GPL(sdio_writew);
572112c9db9SPierre Ossman 
573112c9db9SPierre Ossman /**
574112c9db9SPierre Ossman  *	sdio_readl - read a 32 bit integer from a SDIO function
575112c9db9SPierre Ossman  *	@func: SDIO function to access
576112c9db9SPierre Ossman  *	@addr: address to read
577112c9db9SPierre Ossman  *	@err_ret: optional status value from transfer
578112c9db9SPierre Ossman  *
579112c9db9SPierre Ossman  *	Reads a 32 bit integer from the address space of a given SDIO
580112c9db9SPierre Ossman  *	function. If there is a problem reading the address,
581112c9db9SPierre Ossman  *	0xffffffff is returned and @err_ret will contain the error
582112c9db9SPierre Ossman  *	code.
583112c9db9SPierre Ossman  */
sdio_readl(struct sdio_func * func,unsigned int addr,int * err_ret)5846d373331STomas Winkler u32 sdio_readl(struct sdio_func *func, unsigned int addr, int *err_ret)
585112c9db9SPierre Ossman {
586112c9db9SPierre Ossman 	int ret;
587112c9db9SPierre Ossman 
588112c9db9SPierre Ossman 	ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 4);
589112c9db9SPierre Ossman 	if (err_ret)
590112c9db9SPierre Ossman 		*err_ret = ret;
5918e11b284Stcharding 	if (ret)
592112c9db9SPierre Ossman 		return 0xFFFFFFFF;
593112c9db9SPierre Ossman 
5946d373331STomas Winkler 	return le32_to_cpup((__le32 *)func->tmpbuf);
595112c9db9SPierre Ossman }
596112c9db9SPierre Ossman EXPORT_SYMBOL_GPL(sdio_readl);
597112c9db9SPierre Ossman 
598112c9db9SPierre Ossman /**
599112c9db9SPierre Ossman  *	sdio_writel - write a 32 bit integer to a SDIO function
600112c9db9SPierre Ossman  *	@func: SDIO function to access
601112c9db9SPierre Ossman  *	@b: integer to write
602112c9db9SPierre Ossman  *	@addr: address to write to
603112c9db9SPierre Ossman  *	@err_ret: optional status value from transfer
604112c9db9SPierre Ossman  *
605112c9db9SPierre Ossman  *	Writes a 32 bit integer to the address space of a given SDIO
606112c9db9SPierre Ossman  *	function. @err_ret will contain the status of the actual
607112c9db9SPierre Ossman  *	transfer.
608112c9db9SPierre Ossman  */
sdio_writel(struct sdio_func * func,u32 b,unsigned int addr,int * err_ret)6096d373331STomas Winkler void sdio_writel(struct sdio_func *func, u32 b, unsigned int addr, int *err_ret)
610112c9db9SPierre Ossman {
611112c9db9SPierre Ossman 	int ret;
612112c9db9SPierre Ossman 
6136d373331STomas Winkler 	*(__le32 *)func->tmpbuf = cpu_to_le32(b);
614112c9db9SPierre Ossman 
615112c9db9SPierre Ossman 	ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 4);
616112c9db9SPierre Ossman 	if (err_ret)
617112c9db9SPierre Ossman 		*err_ret = ret;
618112c9db9SPierre Ossman }
619112c9db9SPierre Ossman EXPORT_SYMBOL_GPL(sdio_writel);
620112c9db9SPierre Ossman 
6217806cdb4SDavid Vrabel /**
6227806cdb4SDavid Vrabel  *	sdio_f0_readb - read a single byte from SDIO function 0
6237806cdb4SDavid Vrabel  *	@func: an SDIO function of the card
6247806cdb4SDavid Vrabel  *	@addr: address to read
6257806cdb4SDavid Vrabel  *	@err_ret: optional status value from transfer
6267806cdb4SDavid Vrabel  *
6277806cdb4SDavid Vrabel  *	Reads a single byte from the address space of SDIO function 0.
6287806cdb4SDavid Vrabel  *	If there is a problem reading the address, 0xff is returned
6297806cdb4SDavid Vrabel  *	and @err_ret will contain the error code.
6307806cdb4SDavid Vrabel  */
sdio_f0_readb(struct sdio_func * func,unsigned int addr,int * err_ret)6317806cdb4SDavid Vrabel unsigned char sdio_f0_readb(struct sdio_func *func, unsigned int addr,
6327806cdb4SDavid Vrabel 	int *err_ret)
6337806cdb4SDavid Vrabel {
6347806cdb4SDavid Vrabel 	int ret;
6357806cdb4SDavid Vrabel 	unsigned char val;
6367806cdb4SDavid Vrabel 
637923dff87SShawn Lin 	if (!func) {
6389b980d95Stcharding 		if (err_ret)
639923dff87SShawn Lin 			*err_ret = -EINVAL;
640923dff87SShawn Lin 		return 0xFF;
641923dff87SShawn Lin 	}
6427806cdb4SDavid Vrabel 
6437806cdb4SDavid Vrabel 	ret = mmc_io_rw_direct(func->card, 0, 0, addr, 0, &val);
6447806cdb4SDavid Vrabel 	if (err_ret)
6457806cdb4SDavid Vrabel 		*err_ret = ret;
6468e11b284Stcharding 	if (ret)
6477806cdb4SDavid Vrabel 		return 0xFF;
6487806cdb4SDavid Vrabel 
6497806cdb4SDavid Vrabel 	return val;
6507806cdb4SDavid Vrabel }
6517806cdb4SDavid Vrabel EXPORT_SYMBOL_GPL(sdio_f0_readb);
6527806cdb4SDavid Vrabel 
6537806cdb4SDavid Vrabel /**
6547806cdb4SDavid Vrabel  *	sdio_f0_writeb - write a single byte to SDIO function 0
6557806cdb4SDavid Vrabel  *	@func: an SDIO function of the card
6567806cdb4SDavid Vrabel  *	@b: byte to write
6577806cdb4SDavid Vrabel  *	@addr: address to write to
6587806cdb4SDavid Vrabel  *	@err_ret: optional status value from transfer
6597806cdb4SDavid Vrabel  *
6607806cdb4SDavid Vrabel  *	Writes a single byte to the address space of SDIO function 0.
6617806cdb4SDavid Vrabel  *	@err_ret will contain the status of the actual transfer.
6627806cdb4SDavid Vrabel  *
6637806cdb4SDavid Vrabel  *	Only writes to the vendor specific CCCR registers (0xF0 -
6647806cdb4SDavid Vrabel  *	0xFF) are permiited; @err_ret will be set to -EINVAL for *
6657806cdb4SDavid Vrabel  *	writes outside this range.
6667806cdb4SDavid Vrabel  */
sdio_f0_writeb(struct sdio_func * func,unsigned char b,unsigned int addr,int * err_ret)6677806cdb4SDavid Vrabel void sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr,
6687806cdb4SDavid Vrabel 	int *err_ret)
6697806cdb4SDavid Vrabel {
6707806cdb4SDavid Vrabel 	int ret;
6717806cdb4SDavid Vrabel 
672923dff87SShawn Lin 	if (!func) {
6739b980d95Stcharding 		if (err_ret)
674923dff87SShawn Lin 			*err_ret = -EINVAL;
675923dff87SShawn Lin 		return;
676923dff87SShawn Lin 	}
6777806cdb4SDavid Vrabel 
6787c979ec7SOhad Ben-Cohen 	if ((addr < 0xF0 || addr > 0xFF) && (!mmc_card_lenient_fn0(func->card))) {
6797806cdb4SDavid Vrabel 		if (err_ret)
6807806cdb4SDavid Vrabel 			*err_ret = -EINVAL;
6817806cdb4SDavid Vrabel 		return;
6827806cdb4SDavid Vrabel 	}
6837806cdb4SDavid Vrabel 
6847806cdb4SDavid Vrabel 	ret = mmc_io_rw_direct(func->card, 1, 0, addr, b, NULL);
6857806cdb4SDavid Vrabel 	if (err_ret)
6867806cdb4SDavid Vrabel 		*err_ret = ret;
6877806cdb4SDavid Vrabel }
6887806cdb4SDavid Vrabel EXPORT_SYMBOL_GPL(sdio_f0_writeb);
689da68c4ebSNicolas Pitre 
690da68c4ebSNicolas Pitre /**
691da68c4ebSNicolas Pitre  *	sdio_get_host_pm_caps - get host power management capabilities
692da68c4ebSNicolas Pitre  *	@func: SDIO function attached to host
693da68c4ebSNicolas Pitre  *
694da68c4ebSNicolas Pitre  *	Returns a capability bitmask corresponding to power management
695da68c4ebSNicolas Pitre  *	features supported by the host controller that the card function
696da68c4ebSNicolas Pitre  *	might rely upon during a system suspend.  The host doesn't need
697da68c4ebSNicolas Pitre  *	to be claimed, nor the function active, for this information to be
698da68c4ebSNicolas Pitre  *	obtained.
699da68c4ebSNicolas Pitre  */
sdio_get_host_pm_caps(struct sdio_func * func)700da68c4ebSNicolas Pitre mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func)
701da68c4ebSNicolas Pitre {
702923dff87SShawn Lin 	if (!func)
703923dff87SShawn Lin 		return 0;
704da68c4ebSNicolas Pitre 
705da68c4ebSNicolas Pitre 	return func->card->host->pm_caps;
706da68c4ebSNicolas Pitre }
707da68c4ebSNicolas Pitre EXPORT_SYMBOL_GPL(sdio_get_host_pm_caps);
708da68c4ebSNicolas Pitre 
709da68c4ebSNicolas Pitre /**
710da68c4ebSNicolas Pitre  *	sdio_set_host_pm_flags - set wanted host power management capabilities
711da68c4ebSNicolas Pitre  *	@func: SDIO function attached to host
712a79c3f40SLee Jones  *	@flags: Power Management flags to set
713da68c4ebSNicolas Pitre  *
714da68c4ebSNicolas Pitre  *	Set a capability bitmask corresponding to wanted host controller
715da68c4ebSNicolas Pitre  *	power management features for the upcoming suspend state.
716da68c4ebSNicolas Pitre  *	This must be called, if needed, each time the suspend method of
717da68c4ebSNicolas Pitre  *	the function driver is called, and must contain only bits that
718da68c4ebSNicolas Pitre  *	were returned by sdio_get_host_pm_caps().
719da68c4ebSNicolas Pitre  *	The host doesn't need to be claimed, nor the function active,
720da68c4ebSNicolas Pitre  *	for this information to be set.
721da68c4ebSNicolas Pitre  */
sdio_set_host_pm_flags(struct sdio_func * func,mmc_pm_flag_t flags)722da68c4ebSNicolas Pitre int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags)
723da68c4ebSNicolas Pitre {
724da68c4ebSNicolas Pitre 	struct mmc_host *host;
725da68c4ebSNicolas Pitre 
726923dff87SShawn Lin 	if (!func)
727923dff87SShawn Lin 		return -EINVAL;
728da68c4ebSNicolas Pitre 
729da68c4ebSNicolas Pitre 	host = func->card->host;
730da68c4ebSNicolas Pitre 
731da68c4ebSNicolas Pitre 	if (flags & ~host->pm_caps)
732da68c4ebSNicolas Pitre 		return -EINVAL;
733da68c4ebSNicolas Pitre 
734da68c4ebSNicolas Pitre 	/* function suspend methods are serialized, hence no lock needed */
735da68c4ebSNicolas Pitre 	host->pm_flags |= flags;
736da68c4ebSNicolas Pitre 	return 0;
737da68c4ebSNicolas Pitre }
738da68c4ebSNicolas Pitre EXPORT_SYMBOL_GPL(sdio_set_host_pm_flags);
7390a55f4abSDouglas Anderson 
7400a55f4abSDouglas Anderson /**
7410a55f4abSDouglas Anderson  *	sdio_retune_crc_disable - temporarily disable retuning on CRC errors
7420a55f4abSDouglas Anderson  *	@func: SDIO function attached to host
7430a55f4abSDouglas Anderson  *
7440a55f4abSDouglas Anderson  *	If the SDIO card is known to be in a state where it might produce
7450a55f4abSDouglas Anderson  *	CRC errors on the bus in response to commands (like if we know it is
7460a55f4abSDouglas Anderson  *	transitioning between power states), an SDIO function driver can
7470a55f4abSDouglas Anderson  *	call this function to temporarily disable the SD/MMC core behavior of
7480a55f4abSDouglas Anderson  *	triggering an automatic retuning.
7490a55f4abSDouglas Anderson  *
7500a55f4abSDouglas Anderson  *	This function should be called while the host is claimed and the host
7510a55f4abSDouglas Anderson  *	should remain claimed until sdio_retune_crc_enable() is called.
7520a55f4abSDouglas Anderson  *	Specifically, the expected sequence of calls is:
7530a55f4abSDouglas Anderson  *	- sdio_claim_host()
7540a55f4abSDouglas Anderson  *	- sdio_retune_crc_disable()
7550a55f4abSDouglas Anderson  *	- some number of calls like sdio_writeb() and sdio_readb()
7560a55f4abSDouglas Anderson  *	- sdio_retune_crc_enable()
7570a55f4abSDouglas Anderson  *	- sdio_release_host()
7580a55f4abSDouglas Anderson  */
sdio_retune_crc_disable(struct sdio_func * func)7590a55f4abSDouglas Anderson void sdio_retune_crc_disable(struct sdio_func *func)
7600a55f4abSDouglas Anderson {
7610a55f4abSDouglas Anderson 	func->card->host->retune_crc_disable = true;
7620a55f4abSDouglas Anderson }
7630a55f4abSDouglas Anderson EXPORT_SYMBOL_GPL(sdio_retune_crc_disable);
7640a55f4abSDouglas Anderson 
7650a55f4abSDouglas Anderson /**
7660a55f4abSDouglas Anderson  *	sdio_retune_crc_enable - re-enable retuning on CRC errors
7670a55f4abSDouglas Anderson  *	@func: SDIO function attached to host
7680a55f4abSDouglas Anderson  *
769*930ba0cbSGeert Uytterhoeven  *	This is the complement to sdio_retune_crc_disable().
7700a55f4abSDouglas Anderson  */
sdio_retune_crc_enable(struct sdio_func * func)7710a55f4abSDouglas Anderson void sdio_retune_crc_enable(struct sdio_func *func)
7720a55f4abSDouglas Anderson {
7730a55f4abSDouglas Anderson 	func->card->host->retune_crc_disable = false;
7740a55f4abSDouglas Anderson }
7750a55f4abSDouglas Anderson EXPORT_SYMBOL_GPL(sdio_retune_crc_enable);
776b4c9f938SDouglas Anderson 
777b4c9f938SDouglas Anderson /**
778b4c9f938SDouglas Anderson  *	sdio_retune_hold_now - start deferring retuning requests till release
779b4c9f938SDouglas Anderson  *	@func: SDIO function attached to host
780b4c9f938SDouglas Anderson  *
781b4c9f938SDouglas Anderson  *	This function can be called if it's currently a bad time to do
782b4c9f938SDouglas Anderson  *	a retune of the SDIO card.  Retune requests made during this time
783b4c9f938SDouglas Anderson  *	will be held and we'll actually do the retune sometime after the
784b4c9f938SDouglas Anderson  *	release.
785b4c9f938SDouglas Anderson  *
786b4c9f938SDouglas Anderson  *	This function could be useful if an SDIO card is in a power state
787b4c9f938SDouglas Anderson  *	where it can respond to a small subset of commands that doesn't
788b4c9f938SDouglas Anderson  *	include the retuning command.  Care should be taken when using
789b4c9f938SDouglas Anderson  *	this function since (presumably) the retuning request we might be
790b4c9f938SDouglas Anderson  *	deferring was made for a good reason.
791b4c9f938SDouglas Anderson  *
792b4c9f938SDouglas Anderson  *	This function should be called while the host is claimed.
793b4c9f938SDouglas Anderson  */
sdio_retune_hold_now(struct sdio_func * func)794b4c9f938SDouglas Anderson void sdio_retune_hold_now(struct sdio_func *func)
795b4c9f938SDouglas Anderson {
796b4c9f938SDouglas Anderson 	mmc_retune_hold_now(func->card->host);
797b4c9f938SDouglas Anderson }
798b4c9f938SDouglas Anderson EXPORT_SYMBOL_GPL(sdio_retune_hold_now);
799b4c9f938SDouglas Anderson 
800b4c9f938SDouglas Anderson /**
801b4c9f938SDouglas Anderson  *	sdio_retune_release - signal that it's OK to retune now
802b4c9f938SDouglas Anderson  *	@func: SDIO function attached to host
803b4c9f938SDouglas Anderson  *
804b4c9f938SDouglas Anderson  *	This is the complement to sdio_retune_hold_now().  Calling this
805b4c9f938SDouglas Anderson  *	function won't make a retune happen right away but will allow
806b4c9f938SDouglas Anderson  *	them to be scheduled normally.
807b4c9f938SDouglas Anderson  *
808b4c9f938SDouglas Anderson  *	This function should be called while the host is claimed.
809b4c9f938SDouglas Anderson  */
sdio_retune_release(struct sdio_func * func)810b4c9f938SDouglas Anderson void sdio_retune_release(struct sdio_func *func)
811b4c9f938SDouglas Anderson {
812b4c9f938SDouglas Anderson 	mmc_retune_release(func->card->host);
813b4c9f938SDouglas Anderson }
814b4c9f938SDouglas Anderson EXPORT_SYMBOL_GPL(sdio_retune_release);
815