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, ®);
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, ®);
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, ®);
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