1
2
3
4
5
6
7
8
9
10
11
12#include <linux/export.h>
13#include <linux/mmc/host.h>
14#include <linux/mmc/card.h>
15#include <linux/mmc/sdio.h>
16#include <linux/mmc/sdio_func.h>
17
18#include "sdio_ops.h"
19#include "core.h"
20#include "card.h"
21
22
23
24
25
26
27
28
29void sdio_claim_host(struct sdio_func *func)
30{
31 if (WARN_ON(!func))
32 return;
33
34 mmc_claim_host(func->card->host);
35}
36EXPORT_SYMBOL_GPL(sdio_claim_host);
37
38
39
40
41
42
43
44
45void sdio_release_host(struct sdio_func *func)
46{
47 if (WARN_ON(!func))
48 return;
49
50 mmc_release_host(func->card->host);
51}
52EXPORT_SYMBOL_GPL(sdio_release_host);
53
54
55
56
57
58
59
60
61int sdio_enable_func(struct sdio_func *func)
62{
63 int ret;
64 unsigned char reg;
65 unsigned long timeout;
66
67 if (!func)
68 return -EINVAL;
69
70 pr_debug("SDIO: Enabling device %s...\n", sdio_func_id(func));
71
72 ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IOEx, 0, ®);
73 if (ret)
74 goto err;
75
76 reg |= 1 << func->num;
77
78 ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IOEx, reg, NULL);
79 if (ret)
80 goto err;
81
82 timeout = jiffies + msecs_to_jiffies(func->enable_timeout);
83
84 while (1) {
85 ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IORx, 0, ®);
86 if (ret)
87 goto err;
88 if (reg & (1 << func->num))
89 break;
90 ret = -ETIME;
91 if (time_after(jiffies, timeout))
92 goto err;
93 }
94
95 pr_debug("SDIO: Enabled device %s\n", sdio_func_id(func));
96
97 return 0;
98
99err:
100 pr_debug("SDIO: Failed to enable device %s\n", sdio_func_id(func));
101 return ret;
102}
103EXPORT_SYMBOL_GPL(sdio_enable_func);
104
105
106
107
108
109
110
111
112int sdio_disable_func(struct sdio_func *func)
113{
114 int ret;
115 unsigned char reg;
116
117 if (!func)
118 return -EINVAL;
119
120 pr_debug("SDIO: Disabling device %s...\n", sdio_func_id(func));
121
122 ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IOEx, 0, ®);
123 if (ret)
124 goto err;
125
126 reg &= ~(1 << func->num);
127
128 ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IOEx, reg, NULL);
129 if (ret)
130 goto err;
131
132 pr_debug("SDIO: Disabled device %s\n", sdio_func_id(func));
133
134 return 0;
135
136err:
137 pr_debug("SDIO: Failed to disable device %s\n", sdio_func_id(func));
138 return -EIO;
139}
140EXPORT_SYMBOL_GPL(sdio_disable_func);
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161int sdio_set_block_size(struct sdio_func *func, unsigned blksz)
162{
163 int ret;
164
165 if (blksz > func->card->host->max_blk_size)
166 return -EINVAL;
167
168 if (blksz == 0) {
169 blksz = min(func->max_blksize, func->card->host->max_blk_size);
170 blksz = min(blksz, 512u);
171 }
172
173 ret = mmc_io_rw_direct(func->card, 1, 0,
174 SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE,
175 blksz & 0xff, NULL);
176 if (ret)
177 return ret;
178 ret = mmc_io_rw_direct(func->card, 1, 0,
179 SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1,
180 (blksz >> 8) & 0xff, NULL);
181 if (ret)
182 return ret;
183 func->cur_blksize = blksz;
184 return 0;
185}
186EXPORT_SYMBOL_GPL(sdio_set_block_size);
187
188
189
190
191static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
192{
193 unsigned mval = func->card->host->max_blk_size;
194
195 if (mmc_blksz_for_byte_mode(func->card))
196 mval = min(mval, func->cur_blksize);
197 else
198 mval = min(mval, func->max_blksize);
199
200 if (mmc_card_broken_byte_mode_512(func->card))
201 return min(mval, 511u);
202
203 return min(mval, 512u);
204}
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
221{
222 unsigned int orig_sz;
223 unsigned int blk_sz, byte_sz;
224 unsigned chunk_sz;
225
226 orig_sz = sz;
227
228
229
230
231
232
233 sz = mmc_align_data_size(func->card, sz);
234
235
236
237
238
239 if (sz <= sdio_max_byte_size(func))
240 return sz;
241
242 if (func->card->cccr.multi_block) {
243
244
245
246 if ((sz % func->cur_blksize) == 0)
247 return sz;
248
249
250
251
252
253 blk_sz = ((sz + func->cur_blksize - 1) /
254 func->cur_blksize) * func->cur_blksize;
255 blk_sz = mmc_align_data_size(func->card, blk_sz);
256
257
258
259
260
261 if ((blk_sz % func->cur_blksize) == 0)
262 return blk_sz;
263
264
265
266
267
268 byte_sz = mmc_align_data_size(func->card,
269 sz % func->cur_blksize);
270 if (byte_sz <= sdio_max_byte_size(func)) {
271 blk_sz = sz / func->cur_blksize;
272 return blk_sz * func->cur_blksize + byte_sz;
273 }
274 } else {
275
276
277
278
279 chunk_sz = mmc_align_data_size(func->card,
280 sdio_max_byte_size(func));
281 if (chunk_sz == sdio_max_byte_size(func)) {
282
283
284
285 byte_sz = orig_sz % chunk_sz;
286 if (byte_sz) {
287 byte_sz = mmc_align_data_size(func->card,
288 byte_sz);
289 }
290
291 return (orig_sz / chunk_sz) * chunk_sz + byte_sz;
292 }
293 }
294
295
296
297
298
299 return orig_sz;
300}
301EXPORT_SYMBOL_GPL(sdio_align_size);
302
303
304
305static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
306 unsigned addr, int incr_addr, u8 *buf, unsigned size)
307{
308 unsigned remainder = size;
309 unsigned max_blocks;
310 int ret;
311
312 if (!func || (func->num > 7))
313 return -EINVAL;
314
315
316 if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) {
317
318
319 max_blocks = min(func->card->host->max_blk_count, 511u);
320
321 while (remainder >= func->cur_blksize) {
322 unsigned blocks;
323
324 blocks = remainder / func->cur_blksize;
325 if (blocks > max_blocks)
326 blocks = max_blocks;
327 size = blocks * func->cur_blksize;
328
329 ret = mmc_io_rw_extended(func->card, write,
330 func->num, addr, incr_addr, buf,
331 blocks, func->cur_blksize);
332 if (ret)
333 return ret;
334
335 remainder -= size;
336 buf += size;
337 if (incr_addr)
338 addr += size;
339 }
340 }
341
342
343 while (remainder > 0) {
344 size = min(remainder, sdio_max_byte_size(func));
345
346
347 ret = mmc_io_rw_extended(func->card, write, func->num, addr,
348 incr_addr, buf, 0, size);
349 if (ret)
350 return ret;
351
352 remainder -= size;
353 buf += size;
354 if (incr_addr)
355 addr += size;
356 }
357 return 0;
358}
359
360
361
362
363
364
365
366
367
368
369
370u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret)
371{
372 int ret;
373 u8 val;
374
375 if (!func) {
376 if (err_ret)
377 *err_ret = -EINVAL;
378 return 0xFF;
379 }
380
381 ret = mmc_io_rw_direct(func->card, 0, func->num, addr, 0, &val);
382 if (err_ret)
383 *err_ret = ret;
384 if (ret)
385 return 0xFF;
386
387 return val;
388}
389EXPORT_SYMBOL_GPL(sdio_readb);
390
391
392
393
394
395
396
397
398
399
400
401
402void sdio_writeb(struct sdio_func *func, u8 b, unsigned int addr, int *err_ret)
403{
404 int ret;
405
406 if (!func) {
407 if (err_ret)
408 *err_ret = -EINVAL;
409 return;
410 }
411
412 ret = mmc_io_rw_direct(func->card, 1, func->num, addr, b, NULL);
413 if (err_ret)
414 *err_ret = ret;
415}
416EXPORT_SYMBOL_GPL(sdio_writeb);
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431u8 sdio_writeb_readb(struct sdio_func *func, u8 write_byte,
432 unsigned int addr, int *err_ret)
433{
434 int ret;
435 u8 val;
436
437 ret = mmc_io_rw_direct(func->card, 1, func->num, addr,
438 write_byte, &val);
439 if (err_ret)
440 *err_ret = ret;
441 if (ret)
442 return 0xff;
443
444 return val;
445}
446EXPORT_SYMBOL_GPL(sdio_writeb_readb);
447
448
449
450
451
452
453
454
455
456
457
458int sdio_memcpy_fromio(struct sdio_func *func, void *dst,
459 unsigned int addr, int count)
460{
461 return sdio_io_rw_ext_helper(func, 0, addr, 1, dst, count);
462}
463EXPORT_SYMBOL_GPL(sdio_memcpy_fromio);
464
465
466
467
468
469
470
471
472
473
474
475int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr,
476 void *src, int count)
477{
478 return sdio_io_rw_ext_helper(func, 1, addr, 1, src, count);
479}
480EXPORT_SYMBOL_GPL(sdio_memcpy_toio);
481
482
483
484
485
486
487
488
489
490
491
492int sdio_readsb(struct sdio_func *func, void *dst, unsigned int addr,
493 int count)
494{
495 return sdio_io_rw_ext_helper(func, 0, addr, 0, dst, count);
496}
497EXPORT_SYMBOL_GPL(sdio_readsb);
498
499
500
501
502
503
504
505
506
507
508
509int sdio_writesb(struct sdio_func *func, unsigned int addr, void *src,
510 int count)
511{
512 return sdio_io_rw_ext_helper(func, 1, addr, 0, src, count);
513}
514EXPORT_SYMBOL_GPL(sdio_writesb);
515
516
517
518
519
520
521
522
523
524
525
526u16 sdio_readw(struct sdio_func *func, unsigned int addr, int *err_ret)
527{
528 int ret;
529
530 ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 2);
531 if (err_ret)
532 *err_ret = ret;
533 if (ret)
534 return 0xFFFF;
535
536 return le16_to_cpup((__le16 *)func->tmpbuf);
537}
538EXPORT_SYMBOL_GPL(sdio_readw);
539
540
541
542
543
544
545
546
547
548
549
550
551void sdio_writew(struct sdio_func *func, u16 b, unsigned int addr, int *err_ret)
552{
553 int ret;
554
555 *(__le16 *)func->tmpbuf = cpu_to_le16(b);
556
557 ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 2);
558 if (err_ret)
559 *err_ret = ret;
560}
561EXPORT_SYMBOL_GPL(sdio_writew);
562
563
564
565
566
567
568
569
570
571
572
573
574u32 sdio_readl(struct sdio_func *func, unsigned int addr, int *err_ret)
575{
576 int ret;
577
578 ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 4);
579 if (err_ret)
580 *err_ret = ret;
581 if (ret)
582 return 0xFFFFFFFF;
583
584 return le32_to_cpup((__le32 *)func->tmpbuf);
585}
586EXPORT_SYMBOL_GPL(sdio_readl);
587
588
589
590
591
592
593
594
595
596
597
598
599void sdio_writel(struct sdio_func *func, u32 b, unsigned int addr, int *err_ret)
600{
601 int ret;
602
603 *(__le32 *)func->tmpbuf = cpu_to_le32(b);
604
605 ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 4);
606 if (err_ret)
607 *err_ret = ret;
608}
609EXPORT_SYMBOL_GPL(sdio_writel);
610
611
612
613
614
615
616
617
618
619
620
621unsigned char sdio_f0_readb(struct sdio_func *func, unsigned int addr,
622 int *err_ret)
623{
624 int ret;
625 unsigned char val;
626
627 if (!func) {
628 if (err_ret)
629 *err_ret = -EINVAL;
630 return 0xFF;
631 }
632
633 ret = mmc_io_rw_direct(func->card, 0, 0, addr, 0, &val);
634 if (err_ret)
635 *err_ret = ret;
636 if (ret)
637 return 0xFF;
638
639 return val;
640}
641EXPORT_SYMBOL_GPL(sdio_f0_readb);
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657void sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr,
658 int *err_ret)
659{
660 int ret;
661
662 if (!func) {
663 if (err_ret)
664 *err_ret = -EINVAL;
665 return;
666 }
667
668 if ((addr < 0xF0 || addr > 0xFF) && (!mmc_card_lenient_fn0(func->card))) {
669 if (err_ret)
670 *err_ret = -EINVAL;
671 return;
672 }
673
674 ret = mmc_io_rw_direct(func->card, 1, 0, addr, b, NULL);
675 if (err_ret)
676 *err_ret = ret;
677}
678EXPORT_SYMBOL_GPL(sdio_f0_writeb);
679
680
681
682
683
684
685
686
687
688
689
690mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func)
691{
692 if (!func)
693 return 0;
694
695 return func->card->host->pm_caps;
696}
697EXPORT_SYMBOL_GPL(sdio_get_host_pm_caps);
698
699
700
701
702
703
704
705
706
707
708
709
710
711int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags)
712{
713 struct mmc_host *host;
714
715 if (!func)
716 return -EINVAL;
717
718 host = func->card->host;
719
720 if (flags & ~host->pm_caps)
721 return -EINVAL;
722
723
724 host->pm_flags |= flags;
725 return 0;
726}
727EXPORT_SYMBOL_GPL(sdio_set_host_pm_flags);
728