| OLD | NEW |
| 1 //------------------------------------------------------------------------------ | 1 //------------------------------------------------------------------------------ |
| 2 // <copyright file="hif.c" company="Atheros"> | 2 // <copyright file="hif.c" company="Atheros"> |
| 3 // Copyright (c) 2004-2008 Atheros Corporation. All rights reserved. | 3 // Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. |
| 4 // | 4 // |
| 5 // This program is free software; you can redistribute it and/or modify | |
| 6 // it under the terms of the GNU General Public License version 2 as | |
| 7 // published by the Free Software Foundation; | |
| 8 // | 5 // |
| 9 // Software distributed under the License is distributed on an "AS | 6 // Permission to use, copy, modify, and/or distribute this software for any |
| 10 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | 7 // purpose with or without fee is hereby granted, provided that the above |
| 11 // implied. See the License for the specific language governing | 8 // copyright notice and this permission notice appear in all copies. |
| 12 // rights and limitations under the License. | 9 // |
| 10 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 11 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 12 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 13 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 14 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 15 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 16 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 13 // | 17 // |
| 14 // | 18 // |
| 15 //------------------------------------------------------------------------------ | 19 //------------------------------------------------------------------------------ |
| 16 //============================================================================== | 20 //============================================================================== |
| 17 // HIF layer reference implementation for Linux Native MMC stack | 21 // HIF layer reference implementation for Linux Native MMC stack |
| 18 // | 22 // |
| 19 // Author(s): ="Atheros" | 23 // Author(s): ="Atheros" |
| 20 //============================================================================== | 24 //============================================================================== |
| 21 #include <linux/mmc/card.h> | 25 #include <linux/mmc/card.h> |
| 22 #include <linux/mmc/mmc.h> | 26 #include <linux/mmc/mmc.h> |
| 23 #include <linux/mmc/host.h> | 27 #include <linux/mmc/host.h> |
| 24 #include <linux/mmc/sdio_func.h> | 28 #include <linux/mmc/sdio_func.h> |
| 25 #include <linux/mmc/sdio_ids.h> | 29 #include <linux/mmc/sdio_ids.h> |
| 26 #include <linux/mmc/sdio.h> | 30 #include <linux/mmc/sdio.h> |
| 31 #include <linux/mmc/sd.h> |
| 27 #include <linux/kthread.h> | 32 #include <linux/kthread.h> |
| 28 | 33 |
| 29 /* by default setup a bounce buffer for the data packets, if the underlying host
controller driver | 34 /* by default setup a bounce buffer for the data packets, if the underlying host
controller driver |
| 30 does not use DMA you may be able to skip this step and save the memory alloca
tion and transfer time */ | 35 does not use DMA you may be able to skip this step and save the memory alloca
tion and transfer time */ |
| 31 #define HIF_USE_DMA_BOUNCE_BUFFER 1 | 36 #define HIF_USE_DMA_BOUNCE_BUFFER 1 |
| 32 #include "hif_internal.h" | 37 #include "hif_internal.h" |
| 33 #define ATH_MODULE_NAME hif | 38 #define ATH_MODULE_NAME hif |
| 34 #include "a_debug.h" | 39 #include "a_debug.h" |
| 35 #include "AR6002/hw2.0/hw/mbox_host_reg.h" | 40 #include "AR6002/hw2.0/hw/mbox_host_reg.h" |
| 36 | 41 |
| 37 #if HIF_USE_DMA_BOUNCE_BUFFER | 42 #if HIF_USE_DMA_BOUNCE_BUFFER |
| 38 /* macro to check if DMA buffer is WORD-aligned and DMA-able. Most host control
lers assume the | 43 /* macro to check if DMA buffer is WORD-aligned and DMA-able. Most host control
lers assume the |
| 39 * buffer is DMA'able and will bug-check otherwise (i.e. buffers on the stack).
| 44 * buffer is DMA'able and will bug-check otherwise (i.e. buffers on the stack).
|
| 40 * virt_addr_valid check fails on stack memory. | 45 * virt_addr_valid check fails on stack memory. |
| 41 */ | 46 */ |
| 42 #define BUFFER_NEEDS_BOUNCE(buffer) (((A_UINT32)(buffer) & 0x3) || !virt_addr_v
alid((buffer))) | 47 #define BUFFER_NEEDS_BOUNCE(buffer) (((unsigned long)(buffer) & 0x3) || !virt_a
ddr_valid((buffer))) |
| 43 #else | 48 #else |
| 44 #define BUFFER_NEEDS_BOUNCE(buffer) (FALSE) | 49 #define BUFFER_NEEDS_BOUNCE(buffer) (FALSE) |
| 45 #endif | 50 #endif |
| 46 | 51 |
| 47 /* ATHENV */ | 52 /* ATHENV */ |
| 48 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) | 53 #if defined(CONFIG_PM) |
| 49 #define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) | 54 #define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) |
| 50 #define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) | 55 #define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) |
| 51 static int hifDeviceSuspend(struct device *dev); | 56 static int hifDeviceSuspend(struct device *dev); |
| 52 static int hifDeviceResume(struct device *dev); | 57 static int hifDeviceResume(struct device *dev); |
| 53 #endif /* CONFIG_PM */ | 58 #endif /* CONFIG_PM */ |
| 54 static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id
*id); | 59 static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id
*id); |
| 55 static void hifDeviceRemoved(struct sdio_func *func); | 60 static void hifDeviceRemoved(struct sdio_func *func); |
| 56 static HIF_DEVICE *addHifDevice(struct sdio_func *func); | 61 static HIF_DEVICE *addHifDevice(struct sdio_func *func); |
| 57 static HIF_DEVICE *getHifDevice(struct sdio_func *func); | 62 static HIF_DEVICE *getHifDevice(struct sdio_func *func); |
| 58 static void delHifDevice(HIF_DEVICE * device); | 63 static void delHifDevice(HIF_DEVICE * device); |
| 59 static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, uns
igned char byte); | 64 static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, uns
igned char byte); |
| 65 static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsi
gned char *byte); |
| 60 | 66 |
| 61 int reset_sdio_on_unload = 0; | 67 int reset_sdio_on_unload = 0; |
| 62 module_param(reset_sdio_on_unload, int, 0644); | 68 module_param(reset_sdio_on_unload, int, 0644); |
| 63 | 69 |
| 64 extern A_UINT32 nohifscattersupport; | 70 extern A_UINT32 nohifscattersupport; |
| 65 | 71 |
| 66 | 72 |
| 67 /* ------ Static Variables ------ */ | 73 /* ------ Static Variables ------ */ |
| 68 static const struct sdio_device_id ar6k_id_table[] = { | 74 static const struct sdio_device_id ar6k_id_table[] = { |
| 69 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x0)) }, | 75 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x0)) }, |
| 70 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x1)) }, | 76 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x1)) }, |
| 71 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0)) }, | 77 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0)) }, |
| 72 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1)) }, | 78 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1)) }, |
| 73 { /* null */ }, | 79 { /* null */ }, |
| 74 }; | 80 }; |
| 75 MODULE_DEVICE_TABLE(sdio, ar6k_id_table); | 81 MODULE_DEVICE_TABLE(sdio, ar6k_id_table); |
| 76 | 82 |
| 77 static struct sdio_driver ar6k_driver = { | 83 static struct sdio_driver ar6k_driver = { |
| 78 .name = "ar6k_wlan", | 84 .name = "ar6k_wlan", |
| 79 .id_table = ar6k_id_table, | 85 .id_table = ar6k_id_table, |
| 80 .probe = hifDeviceInserted, | 86 .probe = hifDeviceInserted, |
| 81 .remove = hifDeviceRemoved, | 87 .remove = hifDeviceRemoved, |
| 82 }; | 88 }; |
| 83 | 89 |
| 84 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) | 90 #if defined(CONFIG_PM) |
| 85 /* New suspend/resume based on linux-2.6.32 | 91 /* New suspend/resume based on linux-2.6.32 |
| 86 * Need to patch linux-2.6.32 with mmc2.6.32_suspend.patch | 92 * Need to patch linux-2.6.32 with mmc2.6.32_suspend.patch |
| 87 * Need to patch with msmsdcc2.6.29_suspend.patch for msm_sdcc host | 93 * Need to patch with msmsdcc2.6.29_suspend.patch for msm_sdcc host |
| 88 */ | 94 */ |
| 89 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) | |
| 90 static struct dev_pm_ops ar6k_device_pm_ops = { | 95 static struct dev_pm_ops ar6k_device_pm_ops = { |
| 91 #else | |
| 92 static struct pm_ops ar6k_device_pm_ops = { | |
| 93 #endif | |
| 94 .suspend = hifDeviceSuspend, | 96 .suspend = hifDeviceSuspend, |
| 95 .resume = hifDeviceResume, | 97 .resume = hifDeviceResume, |
| 96 }; | 98 }; |
| 97 #endif /* CONFIG_PM */ | 99 #endif /* CONFIG_PM */ |
| 98 | 100 |
| 99 /* make sure we only unregister when registered. */ | 101 /* make sure we only unregister when registered. */ |
| 100 static int registered = 0; | 102 static int registered = 0; |
| 101 | 103 |
| 102 OSDRV_CALLBACKS osdrvCallbacks; | 104 OSDRV_CALLBACKS osdrvCallbacks; |
| 103 extern A_UINT32 onebitmode; | 105 extern A_UINT32 onebitmode; |
| 104 extern A_UINT32 busspeedlow; | 106 extern A_UINT32 busspeedlow; |
| 105 extern A_UINT32 debughif; | 107 extern A_UINT32 debughif; |
| 106 | 108 |
| 107 static void ResetAllCards(void); | 109 static void ResetAllCards(void); |
| 110 static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func); |
| 111 static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func); |
| 108 | 112 |
| 109 #ifdef DEBUG | 113 #ifdef DEBUG |
| 110 | 114 |
| 111 ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, | 115 ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, |
| 112 "hif", | 116 "hif", |
| 113 "(Linux MMC) Host Interconnect Framework", | 117 "(Linux MMC) Host Interconnect Framework", |
| 114 ATH_DEBUG_MASK_DEFAULTS, | 118 ATH_DEBUG_MASK_DEFAULTS, |
| 115 0, | 119 0, |
| 116 NULL); | 120 NULL); |
| 117 | 121 |
| 118 #endif | 122 #endif |
| 119 | 123 |
| 120 | 124 |
| 121 /* ------ Functions ------ */ | 125 /* ------ Functions ------ */ |
| 122 A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks) | 126 A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks) |
| 123 { | 127 { |
| 124 int status; | 128 int status; |
| 125 AR_DEBUG_ASSERT(callbacks != NULL); | 129 AR_DEBUG_ASSERT(callbacks != NULL); |
| 126 | 130 |
| 127 A_REGISTER_MODULE_DEBUG_INFO(hif); | 131 A_REGISTER_MODULE_DEBUG_INFO(hif); |
| 128 | 132 |
| 129 /* store the callback handlers */ | 133 /* store the callback handlers */ |
| 130 osdrvCallbacks = *callbacks; | 134 osdrvCallbacks = *callbacks; |
| 131 | 135 |
| 132 /* Register with bus driver core */ | 136 /* Register with bus driver core */ |
| 133 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFInit registering\n")); | 137 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFInit registering\n")); |
| 134 registered = 1; | 138 registered = 1; |
| 135 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) | 139 #if defined(CONFIG_PM) |
| 136 if (callbacks->deviceSuspendHandler && callbacks->deviceResumeHandler) { | 140 if (callbacks->deviceSuspendHandler && callbacks->deviceResumeHandler) { |
| 137 ar6k_driver.drv.pm = &ar6k_device_pm_ops; | 141 ar6k_driver.drv.pm = &ar6k_device_pm_ops; |
| 138 } | 142 } |
| 139 #endif /* CONFIG_PM */ | 143 #endif /* CONFIG_PM */ |
| 140 status = sdio_register_driver(&ar6k_driver); | 144 status = sdio_register_driver(&ar6k_driver); |
| 141 AR_DEBUG_ASSERT(status==0); | 145 AR_DEBUG_ASSERT(status==0); |
| 142 | 146 |
| 143 if (status != 0) { | 147 if (status != 0) { |
| 144 return A_ERROR; | 148 return A_ERROR; |
| 145 } | 149 } |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 } | 360 } |
| 357 busrequest->address = address; | 361 busrequest->address = address; |
| 358 busrequest->buffer = buffer; | 362 busrequest->buffer = buffer; |
| 359 busrequest->length = length; | 363 busrequest->length = length; |
| 360 busrequest->request = request; | 364 busrequest->request = request; |
| 361 busrequest->context = context; | 365 busrequest->context = context; |
| 362 | 366 |
| 363 AddToAsyncList(device, busrequest); | 367 AddToAsyncList(device, busrequest); |
| 364 | 368 |
| 365 if (request & HIF_SYNCHRONOUS) { | 369 if (request & HIF_SYNCHRONOUS) { |
| 366 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%X
\n", (unsigned int)busrequest)); | 370 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%l
X\n", (unsigned long)busrequest)); |
| 367 | 371 |
| 368 /* wait for completion */ | 372 /* wait for completion */ |
| 369 up(&device->sem_async); | 373 up(&device->sem_async); |
| 370 if (down_interruptible(&busrequest->sem_req) != 0) { | 374 if (down_interruptible(&busrequest->sem_req) != 0) { |
| 371 /* interrupted, exit */ | 375 /* interrupted, exit */ |
| 372 return A_ERROR; | 376 return A_ERROR; |
| 373 } else { | 377 } else { |
| 374 A_STATUS status = busrequest->status; | 378 A_STATUS status = busrequest->status; |
| 375 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freei
ng 0x%X: 0x%X\n", | 379 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freei
ng 0x%lX: 0x%X\n", |
| 376 » » » » » » (unsigned int)busrequest,
busrequest->status)); | 380 » » » » » » (unsigned long)busrequest,
busrequest->status)); |
| 377 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X
\n", (unsigned int)request)); | 381 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X
\n", (unsigned int)request)); |
| 378 hifFreeBusRequest(device, busrequest); | 382 hifFreeBusRequest(device, busrequest); |
| 379 return status; | 383 return status; |
| 380 } | 384 } |
| 381 } else { | 385 } else { |
| 382 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x%
X\n", (unsigned int)busrequest)); | 386 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x%
lX\n", (unsigned long)busrequest)); |
| 383 up(&device->sem_async); | 387 up(&device->sem_async); |
| 384 return A_PENDING; | 388 return A_PENDING; |
| 385 } | 389 } |
| 386 } else { | 390 } else { |
| 387 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, | 391 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, |
| 388 ("AR6000: Invalid execution mode: 0x%08x\n", (unsign
ed int)request)); | 392 ("AR6000: Invalid execution mode: 0x%08x\n", (unsign
ed int)request)); |
| 389 status = A_EINVAL; | 393 status = A_EINVAL; |
| 390 break; | 394 break; |
| 391 } | 395 } |
| 392 } while(0); | 396 } while(0); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 420 spin_lock_irqsave(&device->asynclock, flags); | 424 spin_lock_irqsave(&device->asynclock, flags); |
| 421 /* pull the request to work on */ | 425 /* pull the request to work on */ |
| 422 while (device->asyncreq != NULL) { | 426 while (device->asyncreq != NULL) { |
| 423 request = device->asyncreq; | 427 request = device->asyncreq; |
| 424 if (request->inusenext != NULL) { | 428 if (request->inusenext != NULL) { |
| 425 device->asyncreq = request->inusenext; | 429 device->asyncreq = request->inusenext; |
| 426 } else { | 430 } else { |
| 427 device->asyncreq = NULL; | 431 device->asyncreq = NULL; |
| 428 } | 432 } |
| 429 spin_unlock_irqrestore(&device->asynclock, flags); | 433 spin_unlock_irqrestore(&device->asynclock, flags); |
| 430 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task processing req
: 0x%X\n", (unsigned int)request)); | 434 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task processing req
: 0x%lX\n", (unsigned long)request)); |
| 431 | 435 |
| 432 if (request->pScatterReq != NULL) { | 436 if (request->pScatterReq != NULL) { |
| 433 A_ASSERT(device->scatter_enabled); | 437 A_ASSERT(device->scatter_enabled); |
| 434 /* this is a queued scatter request, pass the request to sca
tter routine which | 438 /* this is a queued scatter request, pass the request to sca
tter routine which |
| 435 * executes it synchronously, note, no need to free the requ
est since scatter requests | 439 * executes it synchronously, note, no need to free the requ
est since scatter requests |
| 436 * are maintained on a separate list */ | 440 * are maintained on a separate list */ |
| 437 status = DoHifReadWriteScatter(device,request); | 441 status = DoHifReadWriteScatter(device,request); |
| 438 } else { | 442 } else { |
| 439 /* call HIFReadWrite in sync mode to do the work */ | 443 /* call HIFReadWrite in sync mode to do the work */ |
| 440 status = __HIFReadWrite(device, request->address, request->buffe
r, | 444 status = __HIFReadWrite(device, request->address, request->buffe
r, |
| 441 request->length, request->request & ~HIF_S
YNCHRONOUS, NULL); | 445 request->length, request->request & ~HIF_S
YNCHRONOUS, NULL); |
| 442 if (request->request & HIF_ASYNCHRONOUS) { | 446 if (request->request & HIF_ASYNCHRONOUS) { |
| 443 void *context = request->context; | 447 void *context = request->context; |
| 444 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task freein
g req: 0x%X\n", (unsigned int)request)); | 448 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task freein
g req: 0x%lX\n", (unsigned long)request)); |
| 445 hifFreeBusRequest(device, request); | 449 hifFreeBusRequest(device, request); |
| 446 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task comple
tion routine req: 0x%X\n", (unsigned int)request)); | 450 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task comple
tion routine req: 0x%lX\n", (unsigned long)request)); |
| 447 device->htcCallbacks.rwCompletionHandler(context, status); | 451 device->htcCallbacks.rwCompletionHandler(context, status); |
| 448 } else { | 452 } else { |
| 449 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task upping
req: 0x%X\n", (unsigned int)request)); | 453 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task upping
req: 0x%lX\n", (unsigned long)request)); |
| 450 request->status = status; | 454 request->status = status; |
| 451 up(&request->sem_req); | 455 up(&request->sem_req); |
| 452 } | 456 } |
| 453 } | 457 } |
| 454 spin_lock_irqsave(&device->asynclock, flags); | 458 spin_lock_irqsave(&device->asynclock, flags); |
| 455 } | 459 } |
| 456 spin_unlock_irqrestore(&device->asynclock, flags); | 460 spin_unlock_irqrestore(&device->asynclock, flags); |
| 457 sdio_release_host(device->func); | 461 sdio_release_host(device->func); |
| 458 } | 462 } |
| 459 | 463 |
| 460 complete_and_exit(&device->async_completion, 0); | 464 complete_and_exit(&device->async_completion, 0); |
| 461 return 0; | 465 return 0; |
| 462 } | 466 } |
| 467 |
| 468 static 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 |
| 491 A_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 /* emulate the mmc_power_up(...) */ |
| 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 * This delay should be sufficient to allow the power supply |
| 523 * to reach the minimum voltage. |
| 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 * This delay must be at least 74 clock sizes, or 1 ms, or the |
| 533 * time required to reach a stable voltage. |
| 534 */ |
| 535 msleep(2); |
| 536 |
| 537 /* Issue CMD0. Goto idle state */ |
| 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 | M
MC_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 /* Issue CMD5, arg = 0 */ |
| 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 /* Issue CMD5, arg = ocr. Wait till card is ready */ |
| 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 /* Issue CMD3, get RCA */ |
| 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 /* Issue CMD7, select card */ |
| 591 err = IssueSDCommand(device, MMC_SELECT_CARD, (rca << 16), MMC_RSP_R
1 | 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 /* Enable high speed */ |
| 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 /* no need to break */ |
| 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 /* Set clock */ |
| 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 /* CMD52: Set bus width & disable card detect resistor */ |
| 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 mo
de 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 |
| 650 A_STATUS |
| 651 PowerStateChangeNotify(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", co
nfig)); |
| 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 } |
| 463 | 692 |
| 464 A_STATUS | 693 A_STATUS |
| 465 HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, | 694 HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, |
| 466 void *config, A_UINT32 configLen) | 695 void *config, A_UINT32 configLen) |
| 467 { | 696 { |
| 468 A_UINT32 count; | 697 A_UINT32 count; |
| 469 A_STATUS status; | 698 A_STATUS status = A_OK; |
| 470 | 699 |
| 471 switch(opcode) { | 700 switch(opcode) { |
| 472 case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: | 701 case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: |
| 473 ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; | 702 ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; |
| 474 ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; | 703 ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; |
| 475 ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; | 704 ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; |
| 476 ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; | 705 ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; |
| 477 break; | 706 break; |
| 478 | 707 |
| 479 case HIF_DEVICE_GET_MBOX_ADDR: | 708 case HIF_DEVICE_GET_MBOX_ADDR: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 491 *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ON
LY; | 720 *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ON
LY; |
| 492 break; | 721 break; |
| 493 case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT: | 722 case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT: |
| 494 if (!device->scatter_enabled) { | 723 if (!device->scatter_enabled) { |
| 495 return A_ENOTSUP; | 724 return A_ENOTSUP; |
| 496 } | 725 } |
| 497 status = SetupHIFScatterSupport(device, (HIF_DEVICE_SCATTER_SUPPORT_
INFO *)config); | 726 status = SetupHIFScatterSupport(device, (HIF_DEVICE_SCATTER_SUPPORT_
INFO *)config); |
| 498 if (A_FAILED(status)) { | 727 if (A_FAILED(status)) { |
| 499 device->scatter_enabled = FALSE; | 728 device->scatter_enabled = FALSE; |
| 500 } | 729 } |
| 501 return status; | 730 break; |
| 502 case HIF_DEVICE_GET_OS_DEVICE: | 731 case HIF_DEVICE_GET_OS_DEVICE: |
| 503 /* pass back a pointer to the SDIO function's "dev" struct */ | 732 /* pass back a pointer to the SDIO function's "dev" struct */ |
| 504 ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->de
v; | 733 ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->de
v; |
| 505 break; | 734 break; |
| 735 case HIF_DEVICE_POWER_STATE_CHANGE: |
| 736 status = PowerStateChangeNotify(device, *(HIF_DEVICE_POWER_CHANGE_TY
PE *)config); |
| 737 break; |
| 506 default: | 738 default: |
| 507 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, | 739 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, |
| 508 ("AR6000: Unsupported configuration opcode: %d\n", o
pcode)); | 740 ("AR6000: Unsupported configuration opcode: %d\n", o
pcode)); |
| 509 return A_ERROR; | 741 status = A_ERROR; |
| 510 } | 742 } |
| 511 | 743 |
| 512 return A_OK; | 744 return status; |
| 513 } | 745 } |
| 514 | 746 |
| 515 void | 747 void |
| 516 HIFShutDownDevice(HIF_DEVICE *device) | 748 HIFShutDownDevice(HIF_DEVICE *device) |
| 517 { | 749 { |
| 518 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n")); | 750 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n")); |
| 519 if (device != NULL) { | 751 if (device != NULL) { |
| 520 AR_DEBUG_ASSERT(device->func != NULL); | 752 AR_DEBUG_ASSERT(device->func != NULL); |
| 521 } else { | 753 } else { |
| 522 /* since we are unloading the driver anyways, reset all cards in cas
e the SDIO card | 754 /* since we are unloading the driver anyways, reset all cards in cas
e the SDIO card |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 | 796 |
| 565 device = (HIF_DEVICE *)param; | 797 device = (HIF_DEVICE *)param; |
| 566 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n")); | 798 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n")); |
| 567 /* start up inform DRV layer */ | 799 /* start up inform DRV layer */ |
| 568 if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) !=
A_OK) { | 800 if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) !=
A_OK) { |
| 569 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); | 801 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); |
| 570 } | 802 } |
| 571 return 0; | 803 return 0; |
| 572 } | 804 } |
| 573 | 805 |
| 574 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) | 806 #if defined(CONFIG_PM) |
| 575 /* handle HTC startup via thread*/ | 807 static int enable_task(void *param) |
| 576 static int resume_task(void *param) | |
| 577 { | 808 { |
| 578 HIF_DEVICE *device; | 809 HIF_DEVICE *device; |
| 579 device = (HIF_DEVICE *)param; | 810 device = (HIF_DEVICE *)param; |
| 580 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from resume_task\n")); | 811 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call from resume_task\n")); |
| 812 |
| 581 /* start up inform DRV layer */ | 813 /* start up inform DRV layer */ |
| 582 if (device && device->claimedContext && osdrvCallbacks.deviceResumeHandler &
& | 814 if (device && |
| 583 osdrvCallbacks.deviceResumeHandler(device->claimedContext) != A_OK) { | 815 device->claimedContext && |
| 816 osdrvCallbacks.devicePowerChangeHandler && |
| 817 osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVI
CE_POWER_UP) != A_OK) |
| 818 { |
| 584 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); | 819 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); |
| 585 } | 820 } |
| 821 |
| 586 return 0; | 822 return 0; |
| 587 } | 823 } |
| 588 #endif /* CONFIG_PM */ | 824 #endif |
| 589 | 825 |
| 590 static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id
*id) | 826 static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id
*id) |
| 591 { | 827 { |
| 592 int ret; | 828 int ret; |
| 593 HIF_DEVICE * device; | 829 HIF_DEVICE * device; |
| 594 int count; | 830 int count; |
| 595 struct task_struct* startup_task_struct; | |
| 596 | 831 |
| 597 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, | 832 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, |
| 598 ("AR6000: hifDeviceInserted, Function: 0x%X, Vendor ID: 0x%X
, Device ID: 0x%X, block size: 0x%X/0x%X\n", | 833 ("AR6000: hifDeviceInserted, Function: 0x%X, Vendor ID: 0x%X
, Device ID: 0x%X, block size: 0x%X/0x%X\n", |
| 599 func->num, func->vendor, func->device, func->max_blksize, f
unc->cur_blksize)); | 834 func->num, func->vendor, func->device, func->max_blksize, f
unc->cur_blksize)); |
| 600 | 835 |
| 601 addHifDevice(func); | 836 addHifDevice(func); |
| 602 device = getHifDevice(func); | 837 device = getHifDevice(func); |
| 603 | 838 |
| 839 device->id = id; |
| 840 device->is_disabled = TRUE; |
| 841 |
| 604 spin_lock_init(&device->lock); | 842 spin_lock_init(&device->lock); |
| 605 | 843 |
| 606 spin_lock_init(&device->asynclock); | 844 spin_lock_init(&device->asynclock); |
| 607 | 845 |
| 608 DL_LIST_INIT(&device->ScatterReqHead); | 846 DL_LIST_INIT(&device->ScatterReqHead); |
| 609 | 847 |
| 610 if (!nohifscattersupport) { | 848 if (!nohifscattersupport) { |
| 611 /* try to allow scatter operation on all instances, | 849 /* try to allow scatter operation on all instances, |
| 612 * unless globally overridden */ | 850 * unless globally overridden */ |
| 613 device->scatter_enabled = TRUE; | 851 device->scatter_enabled = TRUE; |
| 614 } | 852 } |
| 615 | |
| 616 /* enable the SDIO function */ | |
| 617 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: claim\n")); | |
| 618 sdio_claim_host(func); | |
| 619 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: enable\n")); | |
| 620 | 853 |
| 621 if ((id->device & MANUFACTURER_ID_AR6K_BASE_MASK) >= MANUFACTURER_ID_AR6003_
BASE) { | |
| 622 /* enable 4-bit ASYNC interrupt on AR6003 or later devices */ | |
| 623 ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG, SDIO_IRQ_
MODE_ASYNC_4BIT_IRQ); | |
| 624 if (ret) { | |
| 625 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to enable 4-bit ASYN
C IRQ mode %d \n",ret)); | |
| 626 sdio_release_host(func); | |
| 627 return ret; | |
| 628 } | |
| 629 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: 4-bit ASYNC IRQ mode enabled\
n")); | |
| 630 } | |
| 631 | |
| 632 | |
| 633 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) | |
| 634 /* give us some time to enable, in ms */ | |
| 635 func->enable_timeout = 100; | |
| 636 #endif | |
| 637 ret = sdio_enable_func(func); | |
| 638 if (ret) { | |
| 639 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K:
0x%X\n", | |
| 640 __FUNCTION__, ret)); | |
| 641 sdio_release_host(func); | |
| 642 return ret; | |
| 643 } | |
| 644 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: set block size 0x%X\n", HIF_MBOX_
BLOCK_SIZE)); | |
| 645 ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE); | |
| 646 sdio_release_host(func); | |
| 647 if (ret) { | |
| 648 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block siz
e 0x%x AR6K: 0x%X\n", | |
| 649 __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret
)); | |
| 650 return ret; | |
| 651 } | |
| 652 /* Initialize the bus requests to be used later */ | 854 /* Initialize the bus requests to be used later */ |
| 653 A_MEMZERO(device->busRequest, sizeof(device->busRequest)); | 855 A_MEMZERO(device->busRequest, sizeof(device->busRequest)); |
| 654 for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { | 856 for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { |
| 655 sema_init(&device->busRequest[count].sem_req, 0); | 857 sema_init(&device->busRequest[count].sem_req, 0); |
| 656 hifFreeBusRequest(device, &device->busRequest[count]); | 858 hifFreeBusRequest(device, &device->busRequest[count]); |
| 657 } | 859 } |
| 860 sema_init(&device->sem_async, 0); |
| 861 |
| 862 ret = hifEnableFunc(device, func); |
| 658 | 863 |
| 659 /* create async I/O thread */ | |
| 660 device->async_shutdown = 0; | |
| 661 device->async_task = kthread_create(async_task, | |
| 662 (void *)device, | |
| 663 "AR6K Async"); | |
| 664 if (IS_ERR(device->async_task)) { | |
| 665 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n"
, __FUNCTION__)); | |
| 666 return A_ERROR; | |
| 667 } | |
| 668 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n")); | |
| 669 sema_init(&device->sem_async, 0); | |
| 670 wake_up_process(device->async_task ); | |
| 671 | |
| 672 /* create startup thread */ | |
| 673 startup_task_struct = kthread_create(startup_task, | |
| 674 (void *)device, | |
| 675 "AR6K startup"); | |
| 676 if (IS_ERR(startup_task_struct)) { | |
| 677 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create startup task\
n", __FUNCTION__)); | |
| 678 return A_ERROR; | |
| 679 } | |
| 680 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start startup task\n")); | |
| 681 wake_up_process(startup_task_struct); | |
| 682 | |
| 683 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: return %d\n", ret)); | |
| 684 return ret; | 864 return ret; |
| 685 } | 865 } |
| 686 | 866 |
| 687 | 867 |
| 688 void | 868 void |
| 689 HIFAckInterrupt(HIF_DEVICE *device) | 869 HIFAckInterrupt(HIF_DEVICE *device) |
| 690 { | 870 { |
| 691 AR_DEBUG_ASSERT(device != NULL); | 871 AR_DEBUG_ASSERT(device != NULL); |
| 692 | 872 |
| 693 /* Acknowledge our function IRQ */ | 873 /* Acknowledge our function IRQ */ |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 unsigned long flag; | 916 unsigned long flag; |
| 737 | 917 |
| 738 /* Acquire lock */ | 918 /* Acquire lock */ |
| 739 spin_lock_irqsave(&device->lock, flag); | 919 spin_lock_irqsave(&device->lock, flag); |
| 740 | 920 |
| 741 /* Remove first in list */ | 921 /* Remove first in list */ |
| 742 if((busrequest = device->s_busRequestFreeQueue) != NULL) | 922 if((busrequest = device->s_busRequestFreeQueue) != NULL) |
| 743 { | 923 { |
| 744 device->s_busRequestFreeQueue = busrequest->next; | 924 device->s_busRequestFreeQueue = busrequest->next; |
| 745 } | 925 } |
| 746 | |
| 747 /* Release lock */ | 926 /* Release lock */ |
| 748 spin_unlock_irqrestore(&device->lock, flag); | 927 spin_unlock_irqrestore(&device->lock, flag); |
| 749 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifAllocateBusRequest: 0x%p\n", b
usrequest)); | 928 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifAllocateBusRequest: 0x%p\n", b
usrequest)); |
| 750 return busrequest; | 929 return busrequest; |
| 751 } | 930 } |
| 752 | 931 |
| 753 void | 932 void |
| 754 hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest) | 933 hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest) |
| 755 { | 934 { |
| 756 unsigned long flag; | 935 unsigned long flag; |
| 757 | 936 |
| 758 AR_DEBUG_ASSERT(busrequest != NULL); | 937 AR_DEBUG_ASSERT(busrequest != NULL); |
| 759 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifFreeBusRequest: 0x%p\n", busre
quest)); | 938 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifFreeBusRequest: 0x%p\n", busre
quest)); |
| 760 /* Acquire lock */ | 939 /* Acquire lock */ |
| 761 spin_lock_irqsave(&device->lock, flag); | 940 spin_lock_irqsave(&device->lock, flag); |
| 762 | 941 |
| 763 | 942 |
| 764 /* Insert first in list */ | 943 /* Insert first in list */ |
| 765 busrequest->next = device->s_busRequestFreeQueue; | 944 busrequest->next = device->s_busRequestFreeQueue; |
| 766 busrequest->inusenext = NULL; | 945 busrequest->inusenext = NULL; |
| 767 device->s_busRequestFreeQueue = busrequest; | 946 device->s_busRequestFreeQueue = busrequest; |
| 768 | 947 |
| 769 /* Release lock */ | 948 /* Release lock */ |
| 770 spin_unlock_irqrestore(&device->lock, flag); | 949 spin_unlock_irqrestore(&device->lock, flag); |
| 771 } | 950 } |
| 772 | 951 |
| 773 static int hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func) | 952 static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func) |
| 774 { | 953 { |
| 775 int ret = 0; | 954 int ret; |
| 955 A_STATUS status = A_OK; |
| 776 | 956 |
| 777 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n")); | 957 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDisableFunc\n")); |
| 778 device = getHifDevice(func); | 958 device = getHifDevice(func); |
| 779 if (!IS_ERR(device->async_task)) { | 959 if (!IS_ERR(device->async_task)) { |
| 780 init_completion(&device->async_completion); | 960 init_completion(&device->async_completion); |
| 781 device->async_shutdown = 1; | 961 device->async_shutdown = 1; |
| 782 up(&device->sem_async); | 962 up(&device->sem_async); |
| 783 wait_for_completion(&device->async_completion); | 963 wait_for_completion(&device->async_completion); |
| 784 device->async_task = NULL; | 964 device->async_task = NULL; |
| 785 } | 965 } |
| 786 /* Disable the card */ | 966 /* Disable the card */ |
| 787 sdio_claim_host(device->func); | 967 sdio_claim_host(device->func); |
| 788 ret = sdio_disable_func(device->func); | 968 ret = sdio_disable_func(device->func); |
| 969 if (ret) { |
| 970 status = A_ERROR; |
| 971 } |
| 789 | 972 |
| 790 if (reset_sdio_on_unload) { | 973 if (reset_sdio_on_unload) { |
| 791 /* reset the SDIO interface. This is useful in automated testing where
the card | 974 /* reset the SDIO interface. This is useful in automated testing where
the card |
| 792 * does not need to be removed at the end of the test. It is expected t
hat the user will | 975 * does not need to be removed at the end of the test. It is expected t
hat the user will |
| 793 * also unload/reload the host controller driver to force the bus driver
to re-enumerate the slot */ | 976 * also unload/reload the host controller driver to force the bus driver
to re-enumerate the slot */ |
| 794 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: reseting SDIO card back to uni
nitialized state \n")); | 977 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: reseting SDIO card back to uni
nitialized state \n")); |
| 795 | 978 |
| 796 /* NOTE : sdio_f0_writeb() cannot be used here, that API only allows acc
ess | 979 /* NOTE : sdio_f0_writeb() cannot be used here, that API only allows acc
ess |
| 797 * to undefined registers in the range of: 0xF0-0xFF */ | 980 * to undefined registers in the range of: 0xF0-0xFF */ |
| 798 | 981 |
| 799 ret = Func0_CMD52WriteByte(device->func->card, SDIO_CCCR_ABORT, (1 << 3)
); | 982 ret = Func0_CMD52WriteByte(device->func->card, SDIO_CCCR_ABORT, (1 << 3)
); |
| 800 if (ret) { | 983 if (ret) { |
| 801 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: reset failed : %d \n",ret)
); | 984 status = A_ERROR; |
| 985 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: reset failed : %d \n",ret))
; |
| 802 } | 986 } |
| 803 } | 987 } |
| 804 | 988 |
| 805 sdio_release_host(device->func); | 989 sdio_release_host(device->func); |
| 806 return ret; | 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; |
| 807 } | 997 } |
| 808 | 998 |
| 809 static void hifDeviceRemoved(struct sdio_func *func) | 999 static int hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func) |
| 810 { | |
| 811 A_STATUS status = A_OK; | |
| 812 HIF_DEVICE *device; | |
| 813 AR_DEBUG_ASSERT(func != NULL); | |
| 814 | |
| 815 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n")); | |
| 816 device = getHifDevice(func); | |
| 817 if (device->claimedContext != NULL) { | |
| 818 status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, dev
ice); | |
| 819 } | |
| 820 | |
| 821 if (device->is_suspend) { | |
| 822 device->is_suspend = FALSE; | |
| 823 } else { | |
| 824 if (hifDisableFunc(device, func)!=0) { | |
| 825 status = A_ERROR; | |
| 826 } | |
| 827 } | |
| 828 CleanupHIFScatterResources(device); | |
| 829 | |
| 830 delHifDevice(device); | |
| 831 AR_DEBUG_ASSERT(status == A_OK); | |
| 832 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceRemoved\n")); | |
| 833 } | |
| 834 | |
| 835 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) | |
| 836 static int hifDeviceSuspend(struct device *dev) | |
| 837 { | |
| 838 » struct sdio_func *func = dev_to_sdio_func(dev); | |
| 839 A_STATUS status = A_OK; | |
| 840 HIF_DEVICE *device; | |
| 841 device = getHifDevice(func); | |
| 842 if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler)
{ | |
| 843 status = osdrvCallbacks.deviceSuspendHandler(device->claimedContext); | |
| 844 } | |
| 845 if (status == A_OK) { | |
| 846 int oldresetvalue = reset_sdio_on_unload; | |
| 847 reset_sdio_on_unload = 1; | |
| 848 hifDisableFunc(device, func); | |
| 849 reset_sdio_on_unload = oldresetvalue; | |
| 850 device->is_suspend = TRUE; | |
| 851 } else if (status == A_EBUSY) { | |
| 852 A_INT32 cnt = 10; | |
| 853 A_UINT8 host_int_status; | |
| 854 » do { » » | |
| 855 » » while (atomic_read(&device->irqHandling)) { | |
| 856 » » » /* wait until irq handler finished all the jobs */ | |
| 857 » » » schedule_timeout(HZ/10); | |
| 858 » » } | |
| 859 » » /* check if there is any pending irq due to force done */ | |
| 860 » » host_int_status = 0; | |
| 861 » » status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS, | |
| 862 » » » » (A_UINT8 *)&host_int_status, sizeof(host_int
_status), | |
| 863 » » » » HIF_RD_SYNC_BYTE_INC, NULL); | |
| 864 » » host_int_status = A_SUCCESS(status) ? (host_int_status & (1
<< 0)) : 0; | |
| 865 » » if (host_int_status) { | |
| 866 » » » schedule(); /* schedule for next dsrHandler */ | |
| 867 » » } | |
| 868 » } while (host_int_status && --cnt > 0); | |
| 869 | |
| 870 if (host_int_status && cnt == 0) { | |
| 871 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, | |
| 872 ("AR6000: %s(), Unable clear up pending IRQ before t
he system suspended\n", | |
| 873 » » » » » __FUNCTION__)); | |
| 874 } | |
| 875 #if 1 | |
| 876 status = A_OK; /* assume that sdio host controller will take care the po
wer of wifi chip */ | |
| 877 #else | |
| 878 return -EBUSY; /* Return -EBUSY if customer use all android patch of mmc
stack provided by us */ | |
| 879 #endif | |
| 880 } | |
| 881 return A_SUCCESS(status) ? 0 : status; | |
| 882 } | |
| 883 | |
| 884 static int hifDeviceResume(struct device *dev) | |
| 885 { | 1000 { |
| 886 struct task_struct* pTask; | 1001 struct task_struct* pTask; |
| 887 const char *taskName; | 1002 const char *taskName = NULL; |
| 888 int (*taskFunc)(void *); | 1003 int (*taskFunc)(void *) = NULL; |
| 889 » struct sdio_func *func = dev_to_sdio_func(dev); | 1004 int ret = A_OK; |
| 890 A_STATUS ret = A_OK; | 1005 |
| 891 HIF_DEVICE *device; | 1006 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifEnableFunc\n")); |
| 892 device = getHifDevice(func); | 1007 device = getHifDevice(func); |
| 893 | 1008 |
| 894 if (device->is_suspend) { | 1009 if (device->is_disabled) { |
| 895 /* enable the SDIO function */ | 1010 /* enable the SDIO function */ |
| 896 sdio_claim_host(func); | 1011 sdio_claim_host(func); |
| 897 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) | 1012 |
| 1013 if ((device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK) >= MANUFACTURE
R_ID_AR6003_BASE) { |
| 1014 /* enable 4-bit ASYNC interrupt on AR6003 or later devices */ |
| 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 enab
led\n")); |
| 1022 } |
| 898 /* give us some time to enable, in ms */ | 1023 /* give us some time to enable, in ms */ |
| 899 func->enable_timeout = 100; | 1024 func->enable_timeout = 100; |
| 900 #endif | |
| 901 ret = sdio_enable_func(func); | 1025 ret = sdio_enable_func(func); |
| 902 if (ret) { | 1026 if (ret) { |
| 903 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR
6K: 0x%X\n", | 1027 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR
6K: 0x%X\n", |
| 904 __FUNCTION__, ret)); | 1028 __FUNCTION__, ret)); |
| 905 sdio_release_host(func); | 1029 sdio_release_host(func); |
| 906 return ret; | 1030 return A_ERROR; |
| 907 } | 1031 } |
| 908 ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE); | 1032 ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE); |
| 909 sdio_release_host(func); | 1033 sdio_release_host(func); |
| 910 if (ret) { | 1034 if (ret) { |
| 911 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block
size 0x%x AR6K: 0x%X\n", | 1035 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block
size 0x%x AR6K: 0x%X\n", |
| 912 __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret
)); | 1036 __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret
)); |
| 913 return ret; | 1037 return A_ERROR; |
| 914 } | 1038 } |
| 915 device->is_suspend = FALSE; | 1039 device->is_disabled = FALSE; |
| 916 /* create async I/O thread */ | 1040 /* create async I/O thread */ |
| 917 if (!device->async_task) { | 1041 if (!device->async_task) { |
| 918 device->async_shutdown = 0; | 1042 device->async_shutdown = 0; |
| 919 device->async_task = kthread_create(async_task, | 1043 device->async_task = kthread_create(async_task, |
| 920 (void *)device, | 1044 (void *)device, |
| 921 "AR6K Async"); | 1045 "AR6K Async"); |
| 922 if (IS_ERR(device->async_task)) { | 1046 if (IS_ERR(device->async_task)) { |
| 923 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async
task\n", __FUNCTION__)); | 1047 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async
task\n", __FUNCTION__)); |
| 924 return A_ERROR; | 1048 return A_ERROR; |
| 925 } | 1049 } |
| 926 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n")); | 1050 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n")); |
| 927 wake_up_process(device->async_task ); | 1051 wake_up_process(device->async_task ); |
| 928 } | 1052 } |
| 929 } | 1053 } |
| 930 | 1054 |
| 931 if (!device->claimedContext) { | 1055 if (!device->claimedContext) { |
| 932 printk("WARNING!!! No claimedContext during resume wlan\n"); | |
| 933 taskFunc = startup_task; | 1056 taskFunc = startup_task; |
| 934 taskName = "AR6K startup"; | 1057 taskName = "AR6K startup"; |
| 1058 ret = A_OK; |
| 1059 #if defined(CONFIG_PM) |
| 935 } else { | 1060 } else { |
| 936 taskFunc = resume_task; | 1061 taskFunc = enable_task; |
| 937 taskName = "AR6K resume"; | 1062 taskName = "AR6K enable"; |
| 1063 ret = A_PENDING; |
| 1064 #endif /* CONFIG_PM */ |
| 938 } | 1065 } |
| 939 /* create resume thread */ | 1066 /* create resume thread */ |
| 940 pTask = kthread_create(taskFunc, (void *)device, taskName); | 1067 pTask = kthread_create(taskFunc, (void *)device, taskName); |
| 941 if (IS_ERR(pTask)) { | 1068 if (IS_ERR(pTask)) { |
| 942 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create resume task\n
", __FUNCTION__)); | 1069 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create enabel task\n
", __FUNCTION__)); |
| 943 return A_ERROR; | 1070 return A_ERROR; |
| 944 } | 1071 } |
| 945 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start resume task\n")); | |
| 946 wake_up_process(pTask); | 1072 wake_up_process(pTask); |
| 947 return A_SUCCESS(ret) ? 0 : ret; | 1073 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifEnableFunc\n")); |
| 1074 |
| 1075 /* task will call the enable func, indicate pending */ |
| 1076 return ret; |
| 1077 } |
| 1078 |
| 1079 #if defined(CONFIG_PM) |
| 1080 static 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; /* set true first for PowerStateChangeNotify(
..) */ |
| 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; /* Hack for kernel in order to support deep sleep and wow
*/ |
| 1102 default: |
| 1103 return -1; |
| 1104 } |
| 1105 } |
| 1106 |
| 1107 static 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; |
| 948 } | 1124 } |
| 949 #endif /* CONFIG_PM */ | 1125 #endif /* CONFIG_PM */ |
| 950 | 1126 |
| 1127 static 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, dev
ice); |
| 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 * This should be moved to AR6K HTC layer. |
| 1153 */ |
| 1154 A_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 /* wait until irq handler finished all the jobs */ |
| 1163 schedule_timeout(HZ/10); |
| 1164 } |
| 1165 /* check if there is any pending irq due to force done */ |
| 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(); /* schedule for next dsrHandler */ |
| 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 t
he system suspended\n", __FUNCTION__)); |
| 1179 } |
| 1180 |
| 1181 return A_OK; |
| 1182 } |
| 1183 |
| 1184 |
| 951 static HIF_DEVICE * | 1185 static HIF_DEVICE * |
| 952 addHifDevice(struct sdio_func *func) | 1186 addHifDevice(struct sdio_func *func) |
| 953 { | 1187 { |
| 954 HIF_DEVICE *hifdevice; | 1188 HIF_DEVICE *hifdevice; |
| 955 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice\n")); | 1189 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice\n")); |
| 956 AR_DEBUG_ASSERT(func != NULL); | 1190 AR_DEBUG_ASSERT(func != NULL); |
| 957 hifdevice = (HIF_DEVICE *)kzalloc(sizeof(HIF_DEVICE), GFP_KERNEL); | 1191 hifdevice = (HIF_DEVICE *)kzalloc(sizeof(HIF_DEVICE), GFP_KERNEL); |
| 958 AR_DEBUG_ASSERT(hifdevice != NULL); | 1192 AR_DEBUG_ASSERT(hifdevice != NULL); |
| 959 #if HIF_USE_DMA_BOUNCE_BUFFER | 1193 #if HIF_USE_DMA_BOUNCE_BUFFER |
| 960 hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL); | 1194 hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL); |
| 961 AR_DEBUG_ASSERT(hifdevice->dma_buffer != NULL); | 1195 AR_DEBUG_ASSERT(hifdevice->dma_buffer != NULL); |
| 962 #endif | 1196 #endif |
| 963 hifdevice->func = func; | 1197 hifdevice->func = func; |
| 1198 hifdevice->powerConfig = HIF_DEVICE_POWER_UP; |
| 964 sdio_set_drvdata(func, hifdevice); | 1199 sdio_set_drvdata(func, hifdevice); |
| 965 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice; 0x%p\n", hifdevice)
); | 1200 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice; 0x%p\n", hifdevice)
); |
| 966 return hifdevice; | 1201 return hifdevice; |
| 967 } | 1202 } |
| 968 | 1203 |
| 969 static HIF_DEVICE * | 1204 static HIF_DEVICE * |
| 970 getHifDevice(struct sdio_func *func) | 1205 getHifDevice(struct sdio_func *func) |
| 971 { | 1206 { |
| 972 AR_DEBUG_ASSERT(func != NULL); | 1207 AR_DEBUG_ASSERT(func != NULL); |
| 973 return (HIF_DEVICE *)sdio_get_drvdata(func); | 1208 return (HIF_DEVICE *)sdio_get_drvdata(func); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1034 | 1269 |
| 1035 memset(&ioCmd,0,sizeof(ioCmd)); | 1270 memset(&ioCmd,0,sizeof(ioCmd)); |
| 1036 SDIO_SET_CMD52_WRITE_ARG(arg,0,address,byte); | 1271 SDIO_SET_CMD52_WRITE_ARG(arg,0,address,byte); |
| 1037 ioCmd.opcode = SD_IO_RW_DIRECT; | 1272 ioCmd.opcode = SD_IO_RW_DIRECT; |
| 1038 ioCmd.arg = arg; | 1273 ioCmd.arg = arg; |
| 1039 ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC; | 1274 ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC; |
| 1040 | 1275 |
| 1041 return mmc_wait_for_cmd(card->host, &ioCmd, 0); | 1276 return mmc_wait_for_cmd(card->host, &ioCmd, 0); |
| 1042 } | 1277 } |
| 1043 | 1278 |
| 1279 static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsi
gned 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; |
| 1044 | 1290 |
| 1291 err = mmc_wait_for_cmd(card->host, &ioCmd, 0); |
| 1045 | 1292 |
| 1293 if ((!err) && (byte)) { |
| 1294 *byte = ioCmd.resp[0] & 0xFF; |
| 1295 } |
| 1046 | 1296 |
| 1297 return err; |
| 1298 } |
| OLD | NEW |