1
2
3
4
5
6
7
8
9
10
11
12#include <linux/mmc/host.h>
13#include <linux/mmc/card.h>
14#include <linux/mmc/sdio.h>
15#include <linux/mmc/sdio_func.h>
16
17#include "sdio_ops.h"
18
19
20
21
22
23
24
25
26void sdio_claim_host(struct sdio_func *func)
27{
28 BUG_ON(!func);
29 BUG_ON(!func->card);
30
31 mmc_claim_host(func->card->host);
32}
33EXPORT_SYMBOL_GPL(sdio_claim_host);
34
35
36
37
38
39
40
41
42void sdio_release_host(struct sdio_func *func)
43{
44 BUG_ON(!func);
45 BUG_ON(!func->card);
46
47 mmc_release_host(func->card->host);
48}
49EXPORT_SYMBOL_GPL(sdio_release_host);
50
51
52
53
54
55
56
57
58int sdio_enable_func(struct sdio_func *func)
59{
60 int ret;
61 unsigned char reg;
62 unsigned long timeout;
63
64 BUG_ON(!func);
65 BUG_ON(!func->card);
66
67 pr_debug("SDIO: Enabling device %s...\n", sdio_func_id(func));
68
69 ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IOEx, 0, ®);
70 if (ret)
71 goto err;
72
73 reg |= 1 << func->num;
74
75 ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IOEx, reg, NULL);
76 if (ret)
77 goto err;
78
79
80
81
82
83 timeout = jiffies + HZ;
84
85 while (1) {
86 ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IORx, 0, ®);
87 if (ret)
88 goto err;
89 if (reg & (1 << func->num))
90 break;
91 ret = -ETIME;
92 if (time_after(jiffies, timeout))
93 goto err;
94 }
95
96 pr_debug("SDIO: Enabled device %s\n", sdio_func_id(func));
97
98 return 0;
99
100err:
101 pr_debug("SDIO: Failed to enable device %s\n", sdio_func_id(func));
102 return ret;
103}
104EXPORT_SYMBOL_GPL(sdio_enable_func);
105
106
107
108
109
110
111
112
113int sdio_disable_func(struct sdio_func *func)
114{
115 int ret;
116 unsigned char reg;
117
118 BUG_ON(!func);
119 BUG_ON(!func->card);
120
121 pr_debug("SDIO: Disabling device %s...\n", sdio_func_id(func));
122
123 ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IOEx, 0, ®);
124 if (ret)
125 goto err;
126
127 reg &= ~(1 << func->num);
128
129 ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IOEx, reg, NULL);
130 if (ret)
131 goto err;
132
133 pr_debug("SDIO: Disabled device %s\n", sdio_func_id(func));
134
135 return 0;
136
137err:
138 pr_debug("SDIO: Failed to disable device %s\n", sdio_func_id(func));
139 return -EIO;
140}
141EXPORT_SYMBOL_GPL(sdio_disable_func);
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162int sdio_set_block_size(struct sdio_func *func, unsigned blksz)
163{
164 int ret;
165
166 if (blksz > func->card->host->max_blk_size)
167 return -EINVAL;
168
169 if (blksz == 0) {
170 blksz = min(min(
171 func->max_blksize,
172 func->card->host->max_blk_size),
173 512u);
174 }
175
176 ret = mmc_io_rw_direct(func->card, 1, 0,
177 SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE,
178 blksz & 0xff, NULL);
179 if (ret)
180 return ret;
181 ret = mmc_io_rw_direct(func->card, 1, 0,
182 SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1,
183 (blksz >> 8) & 0xff, NULL);
184 if (ret)
185 return ret;
186 func->cur_blksize = blksz;
187 return 0;
188}
189
190EXPORT_SYMBOL_GPL(sdio_set_block_size);
191
192
193
194static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
195 unsigned addr, int incr_addr, u8 *buf, unsigned size)
196{
197 unsigned remainder = size;
198 unsigned max_blocks;
199 int ret;
200
201
202 if (func->card->cccr.multi_block) {
203
204
205
206 max_blocks = min(min(
207 func->card->host->max_blk_count,
208 func->card->host->max_seg_size / func->cur_blksize),
209 511u);
210
211 while (remainder > func->cur_blksize) {
212 unsigned blocks;
213
214 blocks = remainder / func->cur_blksize;
215 if (blocks > max_blocks)
216 blocks = max_blocks;
217 size = blocks * func->cur_blksize;
218
219 ret = mmc_io_rw_extended(func->card, write,
220 func->num, addr, incr_addr, buf,
221 blocks, func->cur_blksize);
222 if (ret)
223 return ret;
224
225 remainder -= size;
226 buf += size;
227 if (incr_addr)
228 addr += size;
229 }
230 }
231
232
233 while (remainder > 0) {
234 size = remainder;
235 if (size > func->cur_blksize)
236 size = func->cur_blksize;
237 if (size > 512)
238 size = 512;
239
240 ret = mmc_io_rw_extended(func->card, write, func->num, addr,
241 incr_addr, buf, 1, size);
242 if (ret)
243 return ret;
244
245 remainder -= size;
246 buf += size;
247 if (incr_addr)
248 addr += size;
249 }
250 return 0;
251}
252
253
254
255
256
257
258
259
260
261
262
263unsigned char sdio_readb(struct sdio_func *func, unsigned int addr,
264 int *err_ret)
265{
266 int ret;
267 unsigned char val;
268
269 BUG_ON(!func);
270
271 if (err_ret)
272 *err_ret = 0;
273
274 ret = mmc_io_rw_direct(func->card, 0, func->num, addr, 0, &val);
275 if (ret) {
276 if (err_ret)
277 *err_ret = ret;
278 return 0xFF;
279 }
280
281 return val;
282}
283EXPORT_SYMBOL_GPL(sdio_readb);
284
285
286
287
288
289
290
291
292
293
294
295
296void sdio_writeb(struct sdio_func *func, unsigned char b, unsigned int addr,
297 int *err_ret)
298{
299 int ret;
300
301 BUG_ON(!func);
302
303 ret = mmc_io_rw_direct(func->card, 1, func->num, addr, b, NULL);
304 if (err_ret)
305 *err_ret = ret;
306}
307EXPORT_SYMBOL_GPL(sdio_writeb);
308
309
310
311
312
313
314
315
316
317
318
319int sdio_memcpy_fromio(struct sdio_func *func, void *dst,
320 unsigned int addr, int count)
321{
322 return sdio_io_rw_ext_helper(func, 0, addr, 1, dst, count);
323}
324EXPORT_SYMBOL_GPL(sdio_memcpy_fromio);
325
326
327
328
329
330
331
332
333
334
335
336int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr,
337 void *src, int count)
338{
339 return sdio_io_rw_ext_helper(func, 1, addr, 1, src, count);
340}
341EXPORT_SYMBOL_GPL(sdio_memcpy_toio);
342
343
344
345
346
347
348
349
350
351
352
353int sdio_readsb(struct sdio_func *func, void *dst, unsigned int addr,
354 int count)
355{
356 return sdio_io_rw_ext_helper(func, 0, addr, 0, dst, count);
357}
358
359EXPORT_SYMBOL_GPL(sdio_readsb);
360
361
362
363
364
365
366
367
368
369
370
371int sdio_writesb(struct sdio_func *func, unsigned int addr, void *src,
372 int count)
373{
374 return sdio_io_rw_ext_helper(func, 1, addr, 0, src, count);
375}
376EXPORT_SYMBOL_GPL(sdio_writesb);
377
378
379
380
381
382
383
384
385
386
387
388unsigned short sdio_readw(struct sdio_func *func, unsigned int addr,
389 int *err_ret)
390{
391 int ret;
392
393 if (err_ret)
394 *err_ret = 0;
395
396 ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 2);
397 if (ret) {
398 if (err_ret)
399 *err_ret = ret;
400 return 0xFFFF;
401 }
402
403 return le16_to_cpu(*(u16*)func->tmpbuf);
404}
405EXPORT_SYMBOL_GPL(sdio_readw);
406
407
408
409
410
411
412
413
414
415
416
417
418void sdio_writew(struct sdio_func *func, unsigned short b, unsigned int addr,
419 int *err_ret)
420{
421 int ret;
422
423 *(u16*)func->tmpbuf = cpu_to_le16(b);
424
425 ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 2);
426 if (err_ret)
427 *err_ret = ret;
428}
429EXPORT_SYMBOL_GPL(sdio_writew);
430
431
432
433
434
435
436
437
438
439
440
441
442unsigned long sdio_readl(struct sdio_func *func, unsigned int addr,
443 int *err_ret)
444{
445 int ret;
446
447 if (err_ret)
448 *err_ret = 0;
449
450 ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 4);
451 if (ret) {
452 if (err_ret)
453 *err_ret = ret;
454 return 0xFFFFFFFF;
455 }
456
457 return le32_to_cpu(*(u32*)func->tmpbuf);
458}
459EXPORT_SYMBOL_GPL(sdio_readl);
460
461
462
463
464
465
466
467
468
469
470
471
472void sdio_writel(struct sdio_func *func, unsigned long b, unsigned int addr,
473 int *err_ret)
474{
475 int ret;
476
477 *(u32*)func->tmpbuf = cpu_to_le32(b);
478
479 ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 4);
480 if (err_ret)
481 *err_ret = ret;
482}
483EXPORT_SYMBOL_GPL(sdio_writel);
484
485
486
487
488
489
490
491
492
493
494
495unsigned char sdio_f0_readb(struct sdio_func *func, unsigned int addr,
496 int *err_ret)
497{
498 int ret;
499 unsigned char val;
500
501 BUG_ON(!func);
502
503 if (err_ret)
504 *err_ret = 0;
505
506 ret = mmc_io_rw_direct(func->card, 0, 0, addr, 0, &val);
507 if (ret) {
508 if (err_ret)
509 *err_ret = ret;
510 return 0xFF;
511 }
512
513 return val;
514}
515EXPORT_SYMBOL_GPL(sdio_f0_readb);
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531void sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr,
532 int *err_ret)
533{
534 int ret;
535
536 BUG_ON(!func);
537
538 if (addr < 0xF0 || addr > 0xFF) {
539 if (err_ret)
540 *err_ret = -EINVAL;
541 return;
542 }
543
544 ret = mmc_io_rw_direct(func->card, 1, 0, addr, b, NULL);
545 if (err_ret)
546 *err_ret = ret;
547}
548EXPORT_SYMBOL_GPL(sdio_f0_writeb);
549