diff options
Diffstat (limited to 'drivers/mmc/core/sdio_io.c')
-rw-r--r-- | drivers/mmc/core/sdio_io.c | 167 |
1 files changed, 128 insertions, 39 deletions
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c index 625b92ce9ce..f61fc2d4cd0 100644 --- a/drivers/mmc/core/sdio_io.c +++ b/drivers/mmc/core/sdio_io.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/mmc/core/sdio_io.c | 2 | * linux/drivers/mmc/core/sdio_io.c |
3 | * | 3 | * |
4 | * Copyright 2007 Pierre Ossman | 4 | * Copyright 2007-2008 Pierre Ossman |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -76,11 +76,7 @@ int sdio_enable_func(struct sdio_func *func) | |||
76 | if (ret) | 76 | if (ret) |
77 | goto err; | 77 | goto err; |
78 | 78 | ||
79 | /* | 79 | timeout = jiffies + msecs_to_jiffies(func->enable_timeout); |
80 | * FIXME: This should timeout based on information in the CIS, | ||
81 | * but we don't have card to parse that yet. | ||
82 | */ | ||
83 | timeout = jiffies + HZ; | ||
84 | 80 | ||
85 | while (1) { | 81 | while (1) { |
86 | ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IORx, 0, ®); | 82 | ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IORx, 0, ®); |
@@ -167,10 +163,8 @@ int sdio_set_block_size(struct sdio_func *func, unsigned blksz) | |||
167 | return -EINVAL; | 163 | return -EINVAL; |
168 | 164 | ||
169 | if (blksz == 0) { | 165 | if (blksz == 0) { |
170 | blksz = min(min( | 166 | blksz = min(func->max_blksize, func->card->host->max_blk_size); |
171 | func->max_blksize, | 167 | blksz = min(blksz, 512u); |
172 | func->card->host->max_blk_size), | ||
173 | 512u); | ||
174 | } | 168 | } |
175 | 169 | ||
176 | ret = mmc_io_rw_direct(func->card, 1, 0, | 170 | ret = mmc_io_rw_direct(func->card, 1, 0, |
@@ -186,9 +180,116 @@ int sdio_set_block_size(struct sdio_func *func, unsigned blksz) | |||
186 | func->cur_blksize = blksz; | 180 | func->cur_blksize = blksz; |
187 | return 0; | 181 | return 0; |
188 | } | 182 | } |
189 | |||
190 | EXPORT_SYMBOL_GPL(sdio_set_block_size); | 183 | EXPORT_SYMBOL_GPL(sdio_set_block_size); |
191 | 184 | ||
185 | /* | ||
186 | * Calculate the maximum byte mode transfer size | ||
187 | */ | ||
188 | static inline unsigned int sdio_max_byte_size(struct sdio_func *func) | ||
189 | { | ||
190 | unsigned mval = min(func->card->host->max_seg_size, | ||
191 | func->card->host->max_blk_size); | ||
192 | mval = min(mval, func->max_blksize); | ||
193 | return min(mval, 512u); /* maximum size for byte mode */ | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * sdio_align_size - pads a transfer size to a more optimal value | ||
198 | * @func: SDIO function | ||
199 | * @sz: original transfer size | ||
200 | * | ||
201 | * Pads the original data size with a number of extra bytes in | ||
202 | * order to avoid controller bugs and/or performance hits | ||
203 | * (e.g. some controllers revert to PIO for certain sizes). | ||
204 | * | ||
205 | * If possible, it will also adjust the size so that it can be | ||
206 | * handled in just a single request. | ||
207 | * | ||
208 | * Returns the improved size, which might be unmodified. | ||
209 | */ | ||
210 | unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz) | ||
211 | { | ||
212 | unsigned int orig_sz; | ||
213 | unsigned int blk_sz, byte_sz; | ||
214 | unsigned chunk_sz; | ||
215 | |||
216 | orig_sz = sz; | ||
217 | |||
218 | /* | ||
219 | * Do a first check with the controller, in case it | ||
220 | * wants to increase the size up to a point where it | ||
221 | * might need more than one block. | ||
222 | */ | ||
223 | sz = mmc_align_data_size(func->card, sz); | ||
224 | |||
225 | /* | ||
226 | * If we can still do this with just a byte transfer, then | ||
227 | * we're done. | ||
228 | */ | ||
229 | if (sz <= sdio_max_byte_size(func)) | ||
230 | return sz; | ||
231 | |||
232 | if (func->card->cccr.multi_block) { | ||
233 | /* | ||
234 | * Check if the transfer is already block aligned | ||
235 | */ | ||
236 | if ((sz % func->cur_blksize) == 0) | ||
237 | return sz; | ||
238 | |||
239 | /* | ||
240 | * Realign it so that it can be done with one request, | ||
241 | * and recheck if the controller still likes it. | ||
242 | */ | ||
243 | blk_sz = ((sz + func->cur_blksize - 1) / | ||
244 | func->cur_blksize) * func->cur_blksize; | ||
245 | blk_sz = mmc_align_data_size(func->card, blk_sz); | ||
246 | |||
247 | /* | ||
248 | * This value is only good if it is still just | ||
249 | * one request. | ||
250 | */ | ||
251 | if ((blk_sz % func->cur_blksize) == 0) | ||
252 | return blk_sz; | ||
253 | |||
254 | /* | ||
255 | * We failed to do one request, but at least try to | ||
256 | * pad the remainder properly. | ||
257 | */ | ||
258 | byte_sz = mmc_align_data_size(func->card, | ||
259 | sz % func->cur_blksize); | ||
260 | if (byte_sz <= sdio_max_byte_size(func)) { | ||
261 | blk_sz = sz / func->cur_blksize; | ||
262 | return blk_sz * func->cur_blksize + byte_sz; | ||
263 | } | ||
264 | } else { | ||
265 | /* | ||
266 | * We need multiple requests, so first check that the | ||
267 | * controller can handle the chunk size; | ||
268 | */ | ||
269 | chunk_sz = mmc_align_data_size(func->card, | ||
270 | sdio_max_byte_size(func)); | ||
271 | if (chunk_sz == sdio_max_byte_size(func)) { | ||
272 | /* | ||
273 | * Fix up the size of the remainder (if any) | ||
274 | */ | ||
275 | byte_sz = orig_sz % chunk_sz; | ||
276 | if (byte_sz) { | ||
277 | byte_sz = mmc_align_data_size(func->card, | ||
278 | byte_sz); | ||
279 | } | ||
280 | |||
281 | return (orig_sz / chunk_sz) * chunk_sz + byte_sz; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * The controller is simply incapable of transferring the size | ||
287 | * we want in decent manner, so just return the original size. | ||
288 | */ | ||
289 | return orig_sz; | ||
290 | } | ||
291 | EXPORT_SYMBOL_GPL(sdio_align_size); | ||
292 | |||
192 | /* Split an arbitrarily sized data transfer into several | 293 | /* Split an arbitrarily sized data transfer into several |
193 | * IO_RW_EXTENDED commands. */ | 294 | * IO_RW_EXTENDED commands. */ |
194 | static int sdio_io_rw_ext_helper(struct sdio_func *func, int write, | 295 | static int sdio_io_rw_ext_helper(struct sdio_func *func, int write, |
@@ -199,14 +300,13 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write, | |||
199 | int ret; | 300 | int ret; |
200 | 301 | ||
201 | /* Do the bulk of the transfer using block mode (if supported). */ | 302 | /* Do the bulk of the transfer using block mode (if supported). */ |
202 | if (func->card->cccr.multi_block) { | 303 | if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) { |
203 | /* Blocks per command is limited by host count, host transfer | 304 | /* Blocks per command is limited by host count, host transfer |
204 | * size (we only use a single sg entry) and the maximum for | 305 | * size (we only use a single sg entry) and the maximum for |
205 | * IO_RW_EXTENDED of 511 blocks. */ | 306 | * IO_RW_EXTENDED of 511 blocks. */ |
206 | max_blocks = min(min( | 307 | max_blocks = min(func->card->host->max_blk_count, |
207 | func->card->host->max_blk_count, | 308 | func->card->host->max_seg_size / func->cur_blksize); |
208 | func->card->host->max_seg_size / func->cur_blksize), | 309 | max_blocks = min(max_blocks, 511u); |
209 | 511u); | ||
210 | 310 | ||
211 | while (remainder > func->cur_blksize) { | 311 | while (remainder > func->cur_blksize) { |
212 | unsigned blocks; | 312 | unsigned blocks; |
@@ -231,11 +331,7 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write, | |||
231 | 331 | ||
232 | /* Write the remainder using byte mode. */ | 332 | /* Write the remainder using byte mode. */ |
233 | while (remainder > 0) { | 333 | while (remainder > 0) { |
234 | size = remainder; | 334 | size = min(remainder, sdio_max_byte_size(func)); |
235 | if (size > func->cur_blksize) | ||
236 | size = func->cur_blksize; | ||
237 | if (size > 512) | ||
238 | size = 512; /* maximum size for byte mode */ | ||
239 | 335 | ||
240 | ret = mmc_io_rw_extended(func->card, write, func->num, addr, | 336 | ret = mmc_io_rw_extended(func->card, write, func->num, addr, |
241 | incr_addr, buf, 1, size); | 337 | incr_addr, buf, 1, size); |
@@ -260,11 +356,10 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write, | |||
260 | * function. If there is a problem reading the address, 0xff | 356 | * function. If there is a problem reading the address, 0xff |
261 | * is returned and @err_ret will contain the error code. | 357 | * is returned and @err_ret will contain the error code. |
262 | */ | 358 | */ |
263 | unsigned char sdio_readb(struct sdio_func *func, unsigned int addr, | 359 | u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret) |
264 | int *err_ret) | ||
265 | { | 360 | { |
266 | int ret; | 361 | int ret; |
267 | unsigned char val; | 362 | u8 val; |
268 | 363 | ||
269 | BUG_ON(!func); | 364 | BUG_ON(!func); |
270 | 365 | ||
@@ -293,8 +388,7 @@ EXPORT_SYMBOL_GPL(sdio_readb); | |||
293 | * function. @err_ret will contain the status of the actual | 388 | * function. @err_ret will contain the status of the actual |
294 | * transfer. | 389 | * transfer. |
295 | */ | 390 | */ |
296 | void sdio_writeb(struct sdio_func *func, unsigned char b, unsigned int addr, | 391 | void sdio_writeb(struct sdio_func *func, u8 b, unsigned int addr, int *err_ret) |
297 | int *err_ret) | ||
298 | { | 392 | { |
299 | int ret; | 393 | int ret; |
300 | 394 | ||
@@ -355,7 +449,6 @@ int sdio_readsb(struct sdio_func *func, void *dst, unsigned int addr, | |||
355 | { | 449 | { |
356 | return sdio_io_rw_ext_helper(func, 0, addr, 0, dst, count); | 450 | return sdio_io_rw_ext_helper(func, 0, addr, 0, dst, count); |
357 | } | 451 | } |
358 | |||
359 | EXPORT_SYMBOL_GPL(sdio_readsb); | 452 | EXPORT_SYMBOL_GPL(sdio_readsb); |
360 | 453 | ||
361 | /** | 454 | /** |
@@ -385,8 +478,7 @@ EXPORT_SYMBOL_GPL(sdio_writesb); | |||
385 | * function. If there is a problem reading the address, 0xffff | 478 | * function. If there is a problem reading the address, 0xffff |
386 | * is returned and @err_ret will contain the error code. | 479 | * is returned and @err_ret will contain the error code. |
387 | */ | 480 | */ |
388 | unsigned short sdio_readw(struct sdio_func *func, unsigned int addr, | 481 | u16 sdio_readw(struct sdio_func *func, unsigned int addr, int *err_ret) |
389 | int *err_ret) | ||
390 | { | 482 | { |
391 | int ret; | 483 | int ret; |
392 | 484 | ||
@@ -400,7 +492,7 @@ unsigned short sdio_readw(struct sdio_func *func, unsigned int addr, | |||
400 | return 0xFFFF; | 492 | return 0xFFFF; |
401 | } | 493 | } |
402 | 494 | ||
403 | return le16_to_cpu(*(u16*)func->tmpbuf); | 495 | return le16_to_cpup((__le16 *)func->tmpbuf); |
404 | } | 496 | } |
405 | EXPORT_SYMBOL_GPL(sdio_readw); | 497 | EXPORT_SYMBOL_GPL(sdio_readw); |
406 | 498 | ||
@@ -415,12 +507,11 @@ EXPORT_SYMBOL_GPL(sdio_readw); | |||
415 | * function. @err_ret will contain the status of the actual | 507 | * function. @err_ret will contain the status of the actual |
416 | * transfer. | 508 | * transfer. |
417 | */ | 509 | */ |
418 | void sdio_writew(struct sdio_func *func, unsigned short b, unsigned int addr, | 510 | void sdio_writew(struct sdio_func *func, u16 b, unsigned int addr, int *err_ret) |
419 | int *err_ret) | ||
420 | { | 511 | { |
421 | int ret; | 512 | int ret; |
422 | 513 | ||
423 | *(u16*)func->tmpbuf = cpu_to_le16(b); | 514 | *(__le16 *)func->tmpbuf = cpu_to_le16(b); |
424 | 515 | ||
425 | ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 2); | 516 | ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 2); |
426 | if (err_ret) | 517 | if (err_ret) |
@@ -439,8 +530,7 @@ EXPORT_SYMBOL_GPL(sdio_writew); | |||
439 | * 0xffffffff is returned and @err_ret will contain the error | 530 | * 0xffffffff is returned and @err_ret will contain the error |
440 | * code. | 531 | * code. |
441 | */ | 532 | */ |
442 | unsigned long sdio_readl(struct sdio_func *func, unsigned int addr, | 533 | u32 sdio_readl(struct sdio_func *func, unsigned int addr, int *err_ret) |
443 | int *err_ret) | ||
444 | { | 534 | { |
445 | int ret; | 535 | int ret; |
446 | 536 | ||
@@ -454,7 +544,7 @@ unsigned long sdio_readl(struct sdio_func *func, unsigned int addr, | |||
454 | return 0xFFFFFFFF; | 544 | return 0xFFFFFFFF; |
455 | } | 545 | } |
456 | 546 | ||
457 | return le32_to_cpu(*(u32*)func->tmpbuf); | 547 | return le32_to_cpup((__le32 *)func->tmpbuf); |
458 | } | 548 | } |
459 | EXPORT_SYMBOL_GPL(sdio_readl); | 549 | EXPORT_SYMBOL_GPL(sdio_readl); |
460 | 550 | ||
@@ -469,12 +559,11 @@ EXPORT_SYMBOL_GPL(sdio_readl); | |||
469 | * function. @err_ret will contain the status of the actual | 559 | * function. @err_ret will contain the status of the actual |
470 | * transfer. | 560 | * transfer. |
471 | */ | 561 | */ |
472 | void sdio_writel(struct sdio_func *func, unsigned long b, unsigned int addr, | 562 | void sdio_writel(struct sdio_func *func, u32 b, unsigned int addr, int *err_ret) |
473 | int *err_ret) | ||
474 | { | 563 | { |
475 | int ret; | 564 | int ret; |
476 | 565 | ||
477 | *(u32*)func->tmpbuf = cpu_to_le32(b); | 566 | *(__le32 *)func->tmpbuf = cpu_to_le32(b); |
478 | 567 | ||
479 | ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 4); | 568 | ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 4); |
480 | if (err_ret) | 569 | if (err_ret) |