1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <linux/mmc/card.h>
26#include <linux/mmc/mmc.h>
27#include <linux/mmc/host.h>
28#include <linux/mmc/sdio_func.h>
29#include <linux/mmc/sdio_ids.h>
30#include <linux/mmc/sdio.h>
31#include <linux/mmc/sd.h>
32#include <linux/kthread.h>
33
34
35
36#define HIF_USE_DMA_BOUNCE_BUFFER 1
37#include "hif_internal.h"
38#define ATH_MODULE_NAME hif
39#include "a_debug.h"
40#include "AR6002/hw2.0/hw/mbox_host_reg.h"
41
42#if HIF_USE_DMA_BOUNCE_BUFFER
43
44
45
46
47#define BUFFER_NEEDS_BOUNCE(buffer) (((unsigned long)(buffer) & 0x3) || !virt_addr_valid((buffer)))
48#else
49#define BUFFER_NEEDS_BOUNCE(buffer) (FALSE)
50#endif
51
52
53#if defined(CONFIG_PM)
54#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)
55#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv)
56static int hifDeviceSuspend(struct device *dev);
57static int hifDeviceResume(struct device *dev);
58#endif
59static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id);
60static void hifDeviceRemoved(struct sdio_func *func);
61static HIF_DEVICE *addHifDevice(struct sdio_func *func);
62static HIF_DEVICE *getHifDevice(struct sdio_func *func);
63static void delHifDevice(HIF_DEVICE * device);
64static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte);
65static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte);
66
67int reset_sdio_on_unload = 0;
68module_param(reset_sdio_on_unload, int, 0644);
69
70extern A_UINT32 nohifscattersupport;
71
72
73
74static const struct sdio_device_id ar6k_id_table[] = {
75 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x0)) },
76 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x1)) },
77 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0)) },
78 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1)) },
79 { },
80};
81MODULE_DEVICE_TABLE(sdio, ar6k_id_table);
82
83static struct sdio_driver ar6k_driver = {
84 .name = "ar6k_wlan",
85 .id_table = ar6k_id_table,
86 .probe = hifDeviceInserted,
87 .remove = hifDeviceRemoved,
88};
89
90#if defined(CONFIG_PM)
91
92
93
94
95static struct dev_pm_ops ar6k_device_pm_ops = {
96 .suspend = hifDeviceSuspend,
97 .resume = hifDeviceResume,
98};
99#endif
100
101
102static int registered = 0;
103
104OSDRV_CALLBACKS osdrvCallbacks;
105extern A_UINT32 onebitmode;
106extern A_UINT32 busspeedlow;
107extern A_UINT32 debughif;
108
109static void ResetAllCards(void);
110static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func);
111static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func);
112
113#ifdef DEBUG
114
115ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif,
116 "hif",
117 "(Linux MMC) Host Interconnect Framework",
118 ATH_DEBUG_MASK_DEFAULTS,
119 0,
120 NULL);
121
122#endif
123
124
125
126A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks)
127{
128 int status;
129 AR_DEBUG_ASSERT(callbacks != NULL);
130
131 A_REGISTER_MODULE_DEBUG_INFO(hif);
132
133
134 osdrvCallbacks = *callbacks;
135
136
137 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFInit registering\n"));
138 registered = 1;
139#if defined(CONFIG_PM)
140 if (callbacks->deviceSuspendHandler && callbacks->deviceResumeHandler) {
141 ar6k_driver.drv.pm = &ar6k_device_pm_ops;
142 }
143#endif
144 status = sdio_register_driver(&ar6k_driver);
145 AR_DEBUG_ASSERT(status==0);
146
147 if (status != 0) {
148 return A_ERROR;
149 }
150
151 return A_OK;
152
153}
154
155static A_STATUS
156__HIFReadWrite(HIF_DEVICE *device,
157 A_UINT32 address,
158 A_UCHAR *buffer,
159 A_UINT32 length,
160 A_UINT32 request,
161 void *context)
162{
163 A_UINT8 opcode;
164 A_STATUS status = A_OK;
165 int ret;
166 A_UINT8 *tbuffer;
167 A_BOOL bounced = FALSE;
168
169 AR_DEBUG_ASSERT(device != NULL);
170 AR_DEBUG_ASSERT(device->func != NULL);
171
172 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: 0x%p, buffer:0x%p (addr:0x%X)\n",
173 device, buffer, address));
174
175 do {
176 if (request & HIF_EXTENDED_IO) {
177
178 } else {
179 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
180 ("AR6000: Invalid command type: 0x%08x\n", request));
181 status = A_EINVAL;
182 break;
183 }
184
185 if (request & HIF_BLOCK_BASIS) {
186
187 length = (length / HIF_MBOX_BLOCK_SIZE) * HIF_MBOX_BLOCK_SIZE;
188 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
189 ("AR6000: Block mode (BlockLen: %d)\n",
190 length));
191 } else if (request & HIF_BYTE_BASIS) {
192 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
193 ("AR6000: Byte mode (BlockLen: %d)\n",
194 length));
195 } else {
196 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
197 ("AR6000: Invalid data mode: 0x%08x\n", request));
198 status = A_EINVAL;
199 break;
200 }
201
202#if 0
203
204 if (length & 0x3) {
205 A_PRINTF(KERN_ALERT"AR6000: HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n",
206 request & HIF_WRITE ? "write":"read", address, length);
207 }
208#endif
209
210 if (request & HIF_WRITE) {
211 if ((address >= HIF_MBOX_START_ADDR(0)) &&
212 (address <= HIF_MBOX_END_ADDR(3)))
213 {
214
215 AR_DEBUG_ASSERT(length <= HIF_MBOX_WIDTH);
216
217
218
219
220
221 address += (HIF_MBOX_WIDTH - length);
222 }
223 }
224
225 if (request & HIF_FIXED_ADDRESS) {
226 opcode = CMD53_FIXED_ADDRESS;
227 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Fixed 0x%X\n", address));
228 } else if (request & HIF_INCREMENTAL_ADDRESS) {
229 opcode = CMD53_INCR_ADDRESS;
230 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Incremental 0x%X\n", address));
231 } else {
232 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
233 ("AR6000: Invalid address mode: 0x%08x\n", request));
234 status = A_EINVAL;
235 break;
236 }
237
238 if (request & HIF_WRITE) {
239#if HIF_USE_DMA_BOUNCE_BUFFER
240 if (BUFFER_NEEDS_BOUNCE(buffer)) {
241 AR_DEBUG_ASSERT(device->dma_buffer != NULL);
242 tbuffer = device->dma_buffer;
243
244 AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
245 memcpy(tbuffer, buffer, length);
246 bounced = TRUE;
247 } else {
248 tbuffer = buffer;
249 }
250#else
251 tbuffer = buffer;
252#endif
253 if (opcode == CMD53_FIXED_ADDRESS) {
254 ret = sdio_writesb(device->func, address, tbuffer, length);
255 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writesb ret=%d address: 0x%X, len: %d, 0x%X\n",
256 ret, address, length, *(int *)tbuffer));
257 } else {
258 ret = sdio_memcpy_toio(device->func, address, tbuffer, length);
259 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writeio ret=%d address: 0x%X, len: %d, 0x%X\n",
260 ret, address, length, *(int *)tbuffer));
261 }
262 } else if (request & HIF_READ) {
263#if HIF_USE_DMA_BOUNCE_BUFFER
264 if (BUFFER_NEEDS_BOUNCE(buffer)) {
265 AR_DEBUG_ASSERT(device->dma_buffer != NULL);
266 AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
267 tbuffer = device->dma_buffer;
268 bounced = TRUE;
269 } else {
270 tbuffer = buffer;
271 }
272#else
273 tbuffer = buffer;
274#endif
275 if (opcode == CMD53_FIXED_ADDRESS) {
276 ret = sdio_readsb(device->func, tbuffer, address, length);
277 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readsb ret=%d address: 0x%X, len: %d, 0x%X\n",
278 ret, address, length, *(int *)tbuffer));
279 } else {
280 ret = sdio_memcpy_fromio(device->func, tbuffer, address, length);
281 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readio ret=%d address: 0x%X, len: %d, 0x%X\n",
282 ret, address, length, *(int *)tbuffer));
283 }
284#if HIF_USE_DMA_BOUNCE_BUFFER
285 if (bounced) {
286
287 memcpy(buffer, tbuffer, length);
288 }
289#endif
290 } else {
291 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
292 ("AR6000: Invalid direction: 0x%08x\n", request));
293 status = A_EINVAL;
294 break;
295 }
296
297 if (ret) {
298 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
299 ("AR6000: SDIO bus operation failed! MMC stack returned : %d \n", ret));
300 status = A_ERROR;
301 }
302 } while (FALSE);
303
304 return status;
305}
306
307void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest)
308{
309 unsigned long flags;
310 BUS_REQUEST *async;
311 BUS_REQUEST *active;
312
313 spin_lock_irqsave(&device->asynclock, flags);
314 active = device->asyncreq;
315 if (active == NULL) {
316 device->asyncreq = busrequest;
317 device->asyncreq->inusenext = NULL;
318 } else {
319 for (async = device->asyncreq;
320 async != NULL;
321 async = async->inusenext) {
322 active = async;
323 }
324 active->inusenext = busrequest;
325 busrequest->inusenext = NULL;
326 }
327 spin_unlock_irqrestore(&device->asynclock, flags);
328}
329
330
331
332A_STATUS
333HIFReadWrite(HIF_DEVICE *device,
334 A_UINT32 address,
335 A_UCHAR *buffer,
336 A_UINT32 length,
337 A_UINT32 request,
338 void *context)
339{
340 A_STATUS status = A_OK;
341 BUS_REQUEST *busrequest;
342
343
344 AR_DEBUG_ASSERT(device != NULL);
345 AR_DEBUG_ASSERT(device->func != NULL);
346
347 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: %p addr:0x%X\n", device,address));
348
349 do {
350 if ((request & HIF_ASYNCHRONOUS) || (request & HIF_SYNCHRONOUS)){
351
352 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Execution mode: %s\n",
353 (request & HIF_ASYNCHRONOUS)?"Async":"Synch"));
354 busrequest = hifAllocateBusRequest(device);
355 if (busrequest == NULL) {
356 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
357 ("AR6000: no async bus requests available (%s, addr:0x%X, len:%d) \n",
358 request & HIF_READ ? "READ":"WRITE", address, length));
359 return A_ERROR;
360 }
361 busrequest->address = address;
362 busrequest->buffer = buffer;
363 busrequest->length = length;
364 busrequest->request = request;
365 busrequest->context = context;
366
367 AddToAsyncList(device, busrequest);
368
369 if (request & HIF_SYNCHRONOUS) {
370 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%lX\n", (unsigned long)busrequest));
371
372
373 up(&device->sem_async);
374 if (down_interruptible(&busrequest->sem_req) != 0) {
375
376 return A_ERROR;
377 } else {
378 A_STATUS status = busrequest->status;
379 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freeing 0x%lX: 0x%X\n",
380 (unsigned long)busrequest, busrequest->status));
381 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X\n", (unsigned int)request));
382 hifFreeBusRequest(device, busrequest);
383 return status;
384 }
385 } else {
386 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x%lX\n", (unsigned long)busrequest));
387 up(&device->sem_async);
388 return A_PENDING;
389 }
390 } else {
391 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
392 ("AR6000: Invalid execution mode: 0x%08x\n", (unsigned int)request));
393 status = A_EINVAL;
394 break;
395 }
396 } while(0);
397
398 return status;
399}
400
401static int async_task(void *param)
402 {
403 HIF_DEVICE *device;
404 BUS_REQUEST *request;
405 A_STATUS status;
406 unsigned long flags;
407
408 device = (HIF_DEVICE *)param;
409 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task\n"));
410 set_current_state(TASK_INTERRUPTIBLE);
411 while(!device->async_shutdown) {
412
413 if (down_interruptible(&device->sem_async) != 0) {
414
415 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task interrupted\n"));
416 break;
417 }
418 if (device->async_shutdown) {
419 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task stopping\n"));
420 break;
421 }
422
423 sdio_claim_host(device->func);
424 spin_lock_irqsave(&device->asynclock, flags);
425
426 while (device->asyncreq != NULL) {
427 request = device->asyncreq;
428 if (request->inusenext != NULL) {
429 device->asyncreq = request->inusenext;
430 } else {
431 device->asyncreq = NULL;
432 }
433 spin_unlock_irqrestore(&device->asynclock, flags);
434 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task processing req: 0x%lX\n", (unsigned long)request));
435
436 if (request->pScatterReq != NULL) {
437 A_ASSERT(device->scatter_enabled);
438
439
440
441 status = DoHifReadWriteScatter(device,request);
442 } else {
443
444 status = __HIFReadWrite(device, request->address, request->buffer,
445 request->length, request->request & ~HIF_SYNCHRONOUS, NULL);
446 if (request->request & HIF_ASYNCHRONOUS) {
447 void *context = request->context;
448 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task freeing req: 0x%lX\n", (unsigned long)request));
449 hifFreeBusRequest(device, request);
450 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task completion routine req: 0x%lX\n", (unsigned long)request));
451 device->htcCallbacks.rwCompletionHandler(context, status);
452 } else {
453 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task upping req: 0x%lX\n", (unsigned long)request));
454 request->status = status;
455 up(&request->sem_req);
456 }
457 }
458 spin_lock_irqsave(&device->asynclock, flags);
459 }
460 spin_unlock_irqrestore(&device->asynclock, flags);
461 sdio_release_host(device->func);
462 }
463
464 complete_and_exit(&device->async_completion, 0);
465 return 0;
466}
467
468static A_INT32 IssueSDCommand(HIF_DEVICE *device, A_UINT32 opcode, A_UINT32 arg, A_UINT32 flags, A_UINT32 *resp)
469{
470 struct mmc_command cmd;
471 A_INT32 err;
472 struct mmc_host *host;
473 struct sdio_func *func;
474
475 func = device->func;
476 host = func->card->host;
477
478 memset(&cmd, 0, sizeof(struct mmc_command));
479 cmd.opcode = opcode;
480 cmd.arg = arg;
481 cmd.flags = flags;
482 err = mmc_wait_for_cmd(host, &cmd, 3);
483
484 if ((!err) && (resp)) {
485 *resp = cmd.resp[0];
486 }
487
488 return err;
489}
490
491A_STATUS ReinitSDIO(HIF_DEVICE *device)
492{
493 A_INT32 err;
494 struct mmc_host *host;
495 struct mmc_card *card;
496 struct sdio_func *func;
497 A_UINT8 cmd52_resp;
498 A_UINT32 clock;
499
500 func = device->func;
501 card = func->card;
502 host = card->host;
503
504 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +ReinitSDIO \n"));
505 sdio_claim_host(func);
506
507 do {
508 if (!device->is_suspend) {
509 A_UINT32 resp;
510 A_UINT16 rca;
511 A_UINT32 i;
512 int bit = fls(host->ocr_avail) - 1;
513
514 host->ios.vdd = bit;
515 host->ios.chip_select = MMC_CS_DONTCARE;
516 host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
517 host->ios.power_mode = MMC_POWER_UP;
518 host->ios.bus_width = MMC_BUS_WIDTH_1;
519 host->ios.timing = MMC_TIMING_LEGACY;
520 host->ops->set_ios(host, &host->ios);
521
522
523
524
525 msleep(2);
526
527 host->ios.clock = host->f_min;
528 host->ios.power_mode = MMC_POWER_ON;
529 host->ops->set_ios(host, &host->ios);
530
531
532
533
534
535 msleep(2);
536
537
538 host->ios.chip_select = MMC_CS_HIGH;
539 host->ops->set_ios(host, &host->ios);
540 msleep(1);
541 err = IssueSDCommand(device, MMC_GO_IDLE_STATE, 0, (MMC_RSP_NONE | MMC_CMD_BC), NULL);
542 host->ios.chip_select = MMC_CS_DONTCARE;
543 host->ops->set_ios(host, &host->ios);
544 msleep(1);
545 host->use_spi_crc = 0;
546
547 if (err) {
548 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD0 failed : %d \n",err));
549 break;
550 }
551
552 if (!host->ocr) {
553
554 err = IssueSDCommand(device, SD_IO_SEND_OP_COND, 0, (MMC_RSP_R4 | MMC_CMD_BCR), &resp);
555 if (err) {
556 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err));
557 break;
558 }
559 host->ocr = resp;
560 }
561
562
563 for (i=0;i<100;i++) {
564 err = IssueSDCommand(device, SD_IO_SEND_OP_COND, host->ocr, (MMC_RSP_R4 | MMC_CMD_BCR), &resp);
565 if (err) {
566 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err));
567 break;
568 }
569 if (resp & MMC_CARD_BUSY) {
570 break;
571 }
572 msleep(10);
573 }
574
575 if ((i == 100) || (err)) {
576 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: card in not ready : %d %d \n",i,err));
577 break;
578 }
579
580
581 err = IssueSDCommand(device, SD_SEND_RELATIVE_ADDR, 0, MMC_RSP_R6 | MMC_CMD_BCR, &resp);
582 if (err) {
583 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD3 failed : %d \n",err));
584 break;
585 }
586 rca = resp >> 16;
587 host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
588 host->ops->set_ios(host, &host->ios);
589
590
591 err = IssueSDCommand(device, MMC_SELECT_CARD, (rca << 16), MMC_RSP_R1 | MMC_CMD_AC, NULL);
592 if (err) {
593 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD7 failed : %d \n",err));
594 break;
595 }
596 }
597
598
599 if (card->host->caps & MMC_CAP_SD_HIGHSPEED) {
600 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("ReinitSDIO: Set high speed mode\n"));
601 err = Func0_CMD52ReadByte(card, SDIO_CCCR_SPEED, &cmd52_resp);
602 if (err) {
603 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 read to CCCR speed register failed : %d \n",err));
604 card->state &= ~MMC_STATE_HIGHSPEED;
605
606 } else {
607 err = Func0_CMD52WriteByte(card, SDIO_CCCR_SPEED, (cmd52_resp | SDIO_SPEED_EHS));
608 if (err) {
609 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 write to CCCR speed register failed : %d \n",err));
610 break;
611 }
612 mmc_card_set_highspeed(card);
613 host->ios.timing = MMC_TIMING_SD_HS;
614 host->ops->set_ios(host, &host->ios);
615 }
616 }
617
618
619 if (mmc_card_highspeed(card)) {
620 clock = 50000000;
621 } else {
622 clock = card->cis.max_dtr;
623 }
624
625 if (clock > host->f_max) {
626 clock = host->f_max;
627 }
628 host->ios.clock = clock;
629 host->ops->set_ios(host, &host->ios);
630
631
632 if (card->host->caps & MMC_CAP_4_BIT_DATA) {
633
634 err = Func0_CMD52WriteByte(card, SDIO_CCCR_IF, SDIO_BUS_CD_DISABLE | SDIO_BUS_WIDTH_4BIT);
635 if (err) {
636 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 to set bus mode failed : %d \n",err));
637 break;
638 }
639 host->ios.bus_width = MMC_BUS_WIDTH_4;
640 host->ops->set_ios(host, &host->ios);
641 }
642 } while (0);
643
644 sdio_release_host(func);
645 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -ReinitSDIO \n"));
646
647 return (err) ? A_ERROR : A_OK;
648}
649
650A_STATUS
651PowerStateChangeNotify(HIF_DEVICE *device, HIF_DEVICE_POWER_CHANGE_TYPE config)
652{
653 A_STATUS status = A_OK;
654#if defined(CONFIG_PM)
655 struct sdio_func *func = device->func;
656 int old_reset_val;
657 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +PowerStateChangeNotify %d\n", config));
658 switch (config) {
659 case HIF_DEVICE_POWER_DOWN:
660 case HIF_DEVICE_POWER_CUT:
661 old_reset_val = reset_sdio_on_unload;
662 reset_sdio_on_unload = 1;
663 status = hifDisableFunc(device, func);
664 reset_sdio_on_unload = old_reset_val;
665 if (!device->is_suspend) {
666 struct mmc_host *host = func->card->host;
667 host->ios.clock = 0;
668 host->ios.vdd = 0;
669 host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
670 host->ios.chip_select = MMC_CS_DONTCARE;
671 host->ios.power_mode = MMC_POWER_OFF;
672 host->ios.bus_width = MMC_BUS_WIDTH_1;
673 host->ios.timing = MMC_TIMING_LEGACY;
674 host->ops->set_ios(host, &host->ios);
675 }
676 break;
677 case HIF_DEVICE_POWER_UP:
678 if (device->powerConfig == HIF_DEVICE_POWER_CUT) {
679 status = ReinitSDIO(device);
680 }
681 if (status == A_OK) {
682 status = hifEnableFunc(device, func);
683 }
684 break;
685 }
686 device->powerConfig = config;
687
688 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -PowerStateChangeNotify\n"));
689#endif
690 return status;
691}
692
693A_STATUS
694HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
695 void *config, A_UINT32 configLen)
696{
697 A_UINT32 count;
698 A_STATUS status = A_OK;
699
700 switch(opcode) {
701 case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
702 ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
703 ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
704 ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
705 ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
706 break;
707
708 case HIF_DEVICE_GET_MBOX_ADDR:
709 for (count = 0; count < 4; count ++) {
710 ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count);
711 }
712
713 if (configLen >= sizeof(HIF_DEVICE_MBOX_INFO)) {
714 SetExtendedMboxWindowInfo((A_UINT16)device->func->device,
715 (HIF_DEVICE_MBOX_INFO *)config);
716 }
717
718 break;
719 case HIF_DEVICE_GET_IRQ_PROC_MODE:
720 *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY;
721 break;
722 case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT:
723 if (!device->scatter_enabled) {
724 return A_ENOTSUP;
725 }
726 status = SetupHIFScatterSupport(device, (HIF_DEVICE_SCATTER_SUPPORT_INFO *)config);
727 if (A_FAILED(status)) {
728 device->scatter_enabled = FALSE;
729 }
730 break;
731 case HIF_DEVICE_GET_OS_DEVICE:
732
733 ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->dev;
734 break;
735 case HIF_DEVICE_POWER_STATE_CHANGE:
736 status = PowerStateChangeNotify(device, *(HIF_DEVICE_POWER_CHANGE_TYPE *)config);
737 break;
738 default:
739 AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
740 ("AR6000: Unsupported configuration opcode: %d\n", opcode));
741 status = A_ERROR;
742 }
743
744 return status;
745}
746
747void
748HIFShutDownDevice(HIF_DEVICE *device)
749{
750 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n"));
751 if (device != NULL) {
752 AR_DEBUG_ASSERT(device->func != NULL);
753 } else {
754
755
756
757
758 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFShutDownDevice, resetting\n"));
759 ResetAllCards();
760
761
762 if (registered) {
763 registered = 0;
764 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
765 ("AR6000: Unregistering with the bus driver\n"));
766 sdio_unregister_driver(&ar6k_driver);
767 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
768 ("AR6000: Unregistered\n"));
769 }
770 }
771 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -HIFShutDownDevice\n"));
772}
773
774static void
775hifIRQHandler(struct sdio_func *func)
776{
777 A_STATUS status;
778 HIF_DEVICE *device;
779 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifIRQHandler\n"));
780
781 device = getHifDevice(func);
782 atomic_set(&device->irqHandling, 1);
783
784 sdio_release_host(device->func);
785 status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context);
786 sdio_claim_host(device->func);
787 atomic_set(&device->irqHandling, 0);
788 AR_DEBUG_ASSERT(status == A_OK || status == A_ECANCELED);
789 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifIRQHandler\n"));
790}
791
792
793static int startup_task(void *param)
794{
795 HIF_DEVICE *device;
796
797 device = (HIF_DEVICE *)param;
798 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n"));
799
800 if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != A_OK) {
801 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
802 }
803 return 0;
804}
805
806#if defined(CONFIG_PM)
807static int enable_task(void *param)
808{
809 HIF_DEVICE *device;
810 device = (HIF_DEVICE *)param;
811 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call from resume_task\n"));
812
813
814 if (device &&
815 device->claimedContext &&
816 osdrvCallbacks.devicePowerChangeHandler &&
817 osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != A_OK)
818 {
819 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
820 }
821
822 return 0;
823}
824#endif
825
826static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id)
827{
828 int ret;
829 HIF_DEVICE * device;
830 int count;
831
832 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
833 ("AR6000: hifDeviceInserted, Function: 0x%X, Vendor ID: 0x%X, Device ID: 0x%X, block size: 0x%X/0x%X\n",
834 func->num, func->vendor, func->device, func->max_blksize, func->cur_blksize));
835
836 addHifDevice(func);
837 device = getHifDevice(func);
838
839 device->id = id;
840 device->is_disabled = TRUE;
841
842 spin_lock_init(&device->lock);
843
844 spin_lock_init(&device->asynclock);
845
846 DL_LIST_INIT(&device->ScatterReqHead);
847
848 if (!nohifscattersupport) {
849
850
851 device->scatter_enabled = TRUE;
852 }
853
854
855 A_MEMZERO(device->busRequest, sizeof(device->busRequest));
856 for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
857 sema_init(&device->busRequest[count].sem_req, 0);
858 hifFreeBusRequest(device, &device->busRequest[count]);
859 }
860 sema_init(&device->sem_async, 0);
861
862 ret = hifEnableFunc(device, func);
863
864 return ret;
865}
866
867
868void
869HIFAckInterrupt(HIF_DEVICE *device)
870{
871 AR_DEBUG_ASSERT(device != NULL);
872
873
874}
875
876void
877HIFUnMaskInterrupt(HIF_DEVICE *device)
878{
879 int ret;
880
881 AR_DEBUG_ASSERT(device != NULL);
882 AR_DEBUG_ASSERT(device->func != NULL);
883
884 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFUnMaskInterrupt\n"));
885
886
887 sdio_claim_host(device->func);
888 ret = sdio_claim_irq(device->func, hifIRQHandler);
889 sdio_release_host(device->func);
890 AR_DEBUG_ASSERT(ret == 0);
891}
892
893void HIFMaskInterrupt(HIF_DEVICE *device)
894{
895 int ret;
896 AR_DEBUG_ASSERT(device != NULL);
897 AR_DEBUG_ASSERT(device->func != NULL);
898
899 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFMaskInterrupt\n"));
900
901
902 sdio_claim_host(device->func);
903 while (atomic_read(&device->irqHandling)) {
904 sdio_release_host(device->func);
905 schedule_timeout(HZ/10);
906 sdio_claim_host(device->func);
907 }
908 ret = sdio_release_irq(device->func);
909 sdio_release_host(device->func);
910 AR_DEBUG_ASSERT(ret == 0);
911}
912
913BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device)
914{
915 BUS_REQUEST *busrequest;
916 unsigned long flag;
917
918
919 spin_lock_irqsave(&device->lock, flag);
920
921
922 if((busrequest = device->s_busRequestFreeQueue) != NULL)
923 {
924 device->s_busRequestFreeQueue = busrequest->next;
925 }
926
927 spin_unlock_irqrestore(&device->lock, flag);
928 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifAllocateBusRequest: 0x%p\n", busrequest));
929 return busrequest;
930}
931
932void
933hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest)
934{
935 unsigned long flag;
936
937 AR_DEBUG_ASSERT(busrequest != NULL);
938 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifFreeBusRequest: 0x%p\n", busrequest));
939
940 spin_lock_irqsave(&device->lock, flag);
941
942
943
944 busrequest->next = device->s_busRequestFreeQueue;
945 busrequest->inusenext = NULL;
946 device->s_busRequestFreeQueue = busrequest;
947
948
949 spin_unlock_irqrestore(&device->lock, flag);
950}
951
952static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func)
953{
954 int ret;
955 A_STATUS status = A_OK;
956
957 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDisableFunc\n"));
958 device = getHifDevice(func);
959 if (!IS_ERR(device->async_task)) {
960 init_completion(&device->async_completion);
961 device->async_shutdown = 1;
962 up(&device->sem_async);
963 wait_for_completion(&device->async_completion);
964 device->async_task = NULL;
965 }
966
967 sdio_claim_host(device->func);
968 ret = sdio_disable_func(device->func);
969 if (ret) {
970 status = A_ERROR;
971 }
972
973 if (reset_sdio_on_unload) {
974
975
976
977 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: reseting SDIO card back to uninitialized state \n"));
978
979
980
981
982 ret = Func0_CMD52WriteByte(device->func->card, SDIO_CCCR_ABORT, (1 << 3));
983 if (ret) {
984 status = A_ERROR;
985 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: reset failed : %d \n",ret));
986 }
987 }
988
989 sdio_release_host(device->func);
990
991 if (status == A_OK) {
992 device->is_disabled = TRUE;
993 }
994 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDisableFunc\n"));
995
996 return status;
997}
998
999static int hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func)
1000{
1001 struct task_struct* pTask;
1002 const char *taskName = NULL;
1003 int (*taskFunc)(void *) = NULL;
1004 int ret = A_OK;
1005
1006 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifEnableFunc\n"));
1007 device = getHifDevice(func);
1008
1009 if (device->is_disabled) {
1010
1011 sdio_claim_host(func);
1012
1013 if ((device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK) >= MANUFACTURER_ID_AR6003_BASE) {
1014
1015 ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG, SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
1016 if (ret) {
1017 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to enable 4-bit ASYNC IRQ mode %d \n",ret));
1018 sdio_release_host(func);
1019 return A_ERROR;
1020 }
1021 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: 4-bit ASYNC IRQ mode enabled\n"));
1022 }
1023
1024 func->enable_timeout = 100;
1025 ret = sdio_enable_func(func);
1026 if (ret) {
1027 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n",
1028 __FUNCTION__, ret));
1029 sdio_release_host(func);
1030 return A_ERROR;
1031 }
1032 ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
1033 sdio_release_host(func);
1034 if (ret) {
1035 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x AR6K: 0x%X\n",
1036 __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret));
1037 return A_ERROR;
1038 }
1039 device->is_disabled = FALSE;
1040
1041 if (!device->async_task) {
1042 device->async_shutdown = 0;
1043 device->async_task = kthread_create(async_task,
1044 (void *)device,
1045 "AR6K Async");
1046 if (IS_ERR(device->async_task)) {
1047 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__));
1048 return A_ERROR;
1049 }
1050 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n"));
1051 wake_up_process(device->async_task );
1052 }
1053 }
1054
1055 if (!device->claimedContext) {
1056 taskFunc = startup_task;
1057 taskName = "AR6K startup";
1058 ret = A_OK;
1059#if defined(CONFIG_PM)
1060 } else {
1061 taskFunc = enable_task;
1062 taskName = "AR6K enable";
1063 ret = A_PENDING;
1064#endif
1065 }
1066
1067 pTask = kthread_create(taskFunc, (void *)device, taskName);
1068 if (IS_ERR(pTask)) {
1069 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create enabel task\n", __FUNCTION__));
1070 return A_ERROR;
1071 }
1072 wake_up_process(pTask);
1073 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifEnableFunc\n"));
1074
1075
1076 return ret;
1077}
1078
1079#if defined(CONFIG_PM)
1080static int hifDeviceSuspend(struct device *dev)
1081{
1082 struct sdio_func *func=dev_to_sdio_func(dev);
1083 A_STATUS status = A_OK;
1084 HIF_DEVICE *device;
1085
1086 device = getHifDevice(func);
1087 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceSuspend\n"));
1088 if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) {
1089 device->is_suspend = TRUE;
1090 status = osdrvCallbacks.deviceSuspendHandler(device->claimedContext);
1091 if (status != A_OK) {
1092 device->is_suspend = FALSE;
1093 }
1094 }
1095 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceSuspend\n"));
1096
1097 switch (status) {
1098 case A_OK:
1099 return 0;
1100 case A_EBUSY:
1101 return -EBUSY;
1102 default:
1103 return -1;
1104 }
1105}
1106
1107static int hifDeviceResume(struct device *dev)
1108{
1109 struct sdio_func *func=dev_to_sdio_func(dev);
1110 A_STATUS status = A_OK;
1111 HIF_DEVICE *device;
1112
1113 device = getHifDevice(func);
1114 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceResume\n"));
1115 if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) {
1116 status = osdrvCallbacks.deviceResumeHandler(device->claimedContext);
1117 if (status == A_OK) {
1118 device->is_suspend = FALSE;
1119 }
1120 }
1121 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceResume\n"));
1122
1123 return A_SUCCESS(status) ? 0 : status;
1124}
1125#endif
1126
1127static void hifDeviceRemoved(struct sdio_func *func)
1128{
1129 A_STATUS status = A_OK;
1130 HIF_DEVICE *device;
1131 AR_DEBUG_ASSERT(func != NULL);
1132
1133 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n"));
1134 device = getHifDevice(func);
1135 if (device->claimedContext != NULL) {
1136 status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, device);
1137 }
1138
1139 if (device->is_disabled) {
1140 device->is_disabled = FALSE;
1141 } else {
1142 status = hifDisableFunc(device, func);
1143 }
1144 CleanupHIFScatterResources(device);
1145
1146 delHifDevice(device);
1147 AR_DEBUG_ASSERT(status == A_OK);
1148 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceRemoved\n"));
1149}
1150
1151
1152
1153
1154A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device)
1155{
1156 A_INT32 cnt = 10;
1157 A_UINT8 host_int_status;
1158 A_STATUS status = A_OK;
1159
1160 do {
1161 while (atomic_read(&device->irqHandling)) {
1162
1163 schedule_timeout(HZ/10);
1164 }
1165
1166 host_int_status = 0;
1167 status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS,
1168 (A_UINT8 *)&host_int_status, sizeof(host_int_status),
1169 HIF_RD_SYNC_BYTE_INC, NULL);
1170 host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)) : 0;
1171 if (host_int_status) {
1172 schedule();
1173 }
1174 } while (host_int_status && --cnt > 0);
1175
1176 if (host_int_status && cnt == 0) {
1177 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
1178 ("AR6000: %s(), Unable clear up pending IRQ before the system suspended\n", __FUNCTION__));
1179 }
1180
1181 return A_OK;
1182}
1183
1184
1185static HIF_DEVICE *
1186addHifDevice(struct sdio_func *func)
1187{
1188 HIF_DEVICE *hifdevice;
1189 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice\n"));
1190 AR_DEBUG_ASSERT(func != NULL);
1191 hifdevice = kzalloc(sizeof(HIF_DEVICE), GFP_KERNEL);
1192 AR_DEBUG_ASSERT(hifdevice != NULL);
1193#if HIF_USE_DMA_BOUNCE_BUFFER
1194 hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL);
1195 AR_DEBUG_ASSERT(hifdevice->dma_buffer != NULL);
1196#endif
1197 hifdevice->func = func;
1198 hifdevice->powerConfig = HIF_DEVICE_POWER_UP;
1199 sdio_set_drvdata(func, hifdevice);
1200 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice; 0x%p\n", hifdevice));
1201 return hifdevice;
1202}
1203
1204static HIF_DEVICE *
1205getHifDevice(struct sdio_func *func)
1206{
1207 AR_DEBUG_ASSERT(func != NULL);
1208 return (HIF_DEVICE *)sdio_get_drvdata(func);
1209}
1210
1211static void
1212delHifDevice(HIF_DEVICE * device)
1213{
1214 AR_DEBUG_ASSERT(device!= NULL);
1215 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: delHifDevice; 0x%p\n", device));
1216 if (device->dma_buffer != NULL) {
1217 kfree(device->dma_buffer);
1218 }
1219 kfree(device);
1220}
1221
1222static void ResetAllCards(void)
1223{
1224}
1225
1226void HIFClaimDevice(HIF_DEVICE *device, void *context)
1227{
1228 device->claimedContext = context;
1229}
1230
1231void HIFReleaseDevice(HIF_DEVICE *device)
1232{
1233 device->claimedContext = NULL;
1234}
1235
1236A_STATUS HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks)
1237{
1238 if (device->htcCallbacks.context != NULL) {
1239
1240 return A_ERROR;
1241 }
1242 device->htcCallbacks = *callbacks;
1243 return A_OK;
1244}
1245
1246void HIFDetachHTC(HIF_DEVICE *device)
1247{
1248 A_MEMZERO(&device->htcCallbacks,sizeof(device->htcCallbacks));
1249}
1250
1251#define SDIO_SET_CMD52_ARG(arg,rw,func,raw,address,writedata) \
1252 (arg) = (((rw) & 1) << 31) | \
1253 (((func) & 0x7) << 28) | \
1254 (((raw) & 1) << 27) | \
1255 (1 << 26) | \
1256 (((address) & 0x1FFFF) << 9) | \
1257 (1 << 8) | \
1258 ((writedata) & 0xFF)
1259
1260#define SDIO_SET_CMD52_READ_ARG(arg,func,address) \
1261 SDIO_SET_CMD52_ARG(arg,0,(func),0,address,0x00)
1262#define SDIO_SET_CMD52_WRITE_ARG(arg,func,address,value) \
1263 SDIO_SET_CMD52_ARG(arg,1,(func),0,address,value)
1264
1265static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte)
1266{
1267 struct mmc_command ioCmd;
1268 unsigned long arg;
1269
1270 memset(&ioCmd,0,sizeof(ioCmd));
1271 SDIO_SET_CMD52_WRITE_ARG(arg,0,address,byte);
1272 ioCmd.opcode = SD_IO_RW_DIRECT;
1273 ioCmd.arg = arg;
1274 ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
1275
1276 return mmc_wait_for_cmd(card->host, &ioCmd, 0);
1277}
1278
1279static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte)
1280{
1281 struct mmc_command ioCmd;
1282 unsigned long arg;
1283 A_INT32 err;
1284
1285 memset(&ioCmd,0,sizeof(ioCmd));
1286 SDIO_SET_CMD52_READ_ARG(arg,0,address);
1287 ioCmd.opcode = SD_IO_RW_DIRECT;
1288 ioCmd.arg = arg;
1289 ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
1290
1291 err = mmc_wait_for_cmd(card->host, &ioCmd, 0);
1292
1293 if ((!err) && (byte)) {
1294 *byte = ioCmd.resp[0] & 0xFF;
1295 }
1296
1297 return err;
1298}
1299