4 * @abstract: HIF layer reference implementation for Atheros SDIO stack
6 * @notice: Copyright (c) 2004-2006 Atheros Communications Inc.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation;
13 * Software distributed under the License is distributed on an "AS
14 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15 * implied. See the License for the specific language governing
16 * rights and limitations under the License.
22 #include "hif_internal.h"
24 /* ------ Static Variables ------ */
26 /* ------ Global Variable Declarations ------- */
29 .SDIO_ManufacturerID
= MANUFACTURER_ID_AR6001_BASE
| 0xB,
30 .SDIO_ManufacturerCode
= MANUFACTURER_CODE
,
31 .SDIO_FunctionClass
= FUNCTION_CLASS
,
35 .SDIO_ManufacturerID
= MANUFACTURER_ID_AR6001_BASE
| 0xA,
36 .SDIO_ManufacturerCode
= MANUFACTURER_CODE
,
37 .SDIO_FunctionClass
= FUNCTION_CLASS
,
41 .SDIO_ManufacturerID
= MANUFACTURER_ID_AR6001_BASE
| 0x9,
42 .SDIO_ManufacturerCode
= MANUFACTURER_CODE
,
43 .SDIO_FunctionClass
= FUNCTION_CLASS
,
47 .SDIO_ManufacturerID
= MANUFACTURER_ID_AR6001_BASE
| 0x8,
48 .SDIO_ManufacturerCode
= MANUFACTURER_CODE
,
49 .SDIO_FunctionClass
= FUNCTION_CLASS
,
53 .SDIO_ManufacturerID
= MANUFACTURER_ID_AR6002_BASE
| 0x0,
54 .SDIO_ManufacturerCode
= MANUFACTURER_CODE
,
55 .SDIO_FunctionClass
= FUNCTION_CLASS
,
59 .SDIO_ManufacturerID
= MANUFACTURER_ID_AR6002_BASE
| 0x1,
60 .SDIO_ManufacturerCode
= MANUFACTURER_CODE
,
61 .SDIO_FunctionClass
= FUNCTION_CLASS
,
65 } //list is null termintaed
68 TARGET_FUNCTION_CONTEXT FunctionContext
= {
69 .function
.Version
= CT_SDIO_STACK_VERSION_CODE
,
70 .function
.pName
= "sdio_wlan",
71 .function
.MaxDevices
= 1,
72 .function
.NumDevices
= 0,
74 .function
.pProbe
= hifDeviceInserted
,
75 .function
.pRemove
= hifDeviceRemoved
,
76 .function
.pSuspend
= NULL
,
77 .function
.pResume
= NULL
,
78 .function
.pWake
= NULL
,
79 .function
.pContext
= &FunctionContext
,
82 HIF_DEVICE hifDevice
[HIF_MAX_DEVICES
];
83 HTC_CALLBACKS htcCallbacks
;
84 BUS_REQUEST busRequest
[BUS_REQUEST_MAX_NUM
];
85 static BUS_REQUEST
*s_busRequestFreeQueue
= NULL
;
86 OS_CRITICALSECTION lock
;
87 extern A_UINT32 onebitmode
;
88 extern A_UINT32 busspeedlow
;
91 extern A_UINT32 debughif
;
92 #define ATH_DEBUG_ERROR 1
93 #define ATH_DEBUG_WARN 2
94 #define ATH_DEBUG_TRACE 3
95 #define _AR_DEBUG_PRINTX_ARG(arg...) arg
96 #define AR_DEBUG_PRINTF(lvl, args)\
97 {if (lvl <= debughif)\
98 A_PRINTF(KERN_ALERT _AR_DEBUG_PRINTX_ARG args);\
101 #define AR_DEBUG_PRINTF(lvl, args)
104 static BUS_REQUEST
*hifAllocateBusRequest(void);
105 static void hifFreeBusRequest(BUS_REQUEST
*busrequest
);
106 static THREAD_RETURN
insert_helper_func(POSKERNEL_HELPER pHelper
);
107 static void ResetAllCards(void);
109 /* ------ Functions ------ */
110 int HIFInit(HTC_CALLBACKS
*callbacks
)
113 DBG_ASSERT(callbacks
!= NULL
);
115 /* Store the callback and event handlers */
116 htcCallbacks
.deviceInsertedHandler
= callbacks
->deviceInsertedHandler
;
117 htcCallbacks
.deviceRemovedHandler
= callbacks
->deviceRemovedHandler
;
118 htcCallbacks
.deviceSuspendHandler
= callbacks
->deviceSuspendHandler
;
119 htcCallbacks
.deviceResumeHandler
= callbacks
->deviceResumeHandler
;
120 htcCallbacks
.deviceWakeupHandler
= callbacks
->deviceWakeupHandler
;
121 htcCallbacks
.rwCompletionHandler
= callbacks
->rwCompletionHandler
;
122 htcCallbacks
.dsrHandler
= callbacks
->dsrHandler
;
124 CriticalSectionInit(&lock
);
126 /* Register with bus driver core */
127 status
= SDIO_RegisterFunction(&FunctionContext
.function
);
128 DBG_ASSERT(SDIO_SUCCESS(status
));
134 HIFReadWrite(HIF_DEVICE
*device
,
146 SDREQUEST
*sdrequest
;
147 SDIO_STATUS sdiostatus
;
148 BUS_REQUEST
*busrequest
;
149 A_STATUS status
= A_OK
;
151 DBG_ASSERT(device
!= NULL
);
152 DBG_ASSERT(device
->handle
!= NULL
);
154 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Device: %p\n", device
));
157 busrequest
= hifAllocateBusRequest();
158 if (busrequest
== NULL
) {
159 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
, ("HIF Unable to allocate bus request\n"));
160 status
= A_NO_RESOURCE
;
164 sdrequest
= busrequest
->request
;
165 busrequest
->context
= context
;
167 sdrequest
->pDataBuffer
= buffer
;
168 if (request
& HIF_SYNCHRONOUS
) {
169 sdrequest
->Flags
= SDREQ_FLAGS_RESP_SDIO_R5
| SDREQ_FLAGS_DATA_TRANS
;
170 sdrequest
->pCompleteContext
= NULL
;
171 sdrequest
->pCompletion
= NULL
;
172 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Execution mode: Synchronous\n"));
173 } else if (request
& HIF_ASYNCHRONOUS
) {
174 sdrequest
->Flags
= SDREQ_FLAGS_RESP_SDIO_R5
| SDREQ_FLAGS_DATA_TRANS
|
175 SDREQ_FLAGS_TRANS_ASYNC
;
176 sdrequest
->pCompleteContext
= busrequest
;
177 sdrequest
->pCompletion
= hifRWCompletionHandler
;
178 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Execution mode: Asynchronous\n"));
180 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
181 ("Invalid execution mode: 0x%08x\n", request
));
186 if (request
& HIF_EXTENDED_IO
) {
187 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Command type: CMD53\n"));
188 sdrequest
->Command
= CMD53
;
190 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
191 ("Invalid command type: 0x%08x\n", request
));
196 if (request
& HIF_BLOCK_BASIS
) {
197 mode
= CMD53_BLOCK_BASIS
;
198 sdrequest
->BlockLen
= HIF_MBOX_BLOCK_SIZE
;
199 sdrequest
->BlockCount
= length
/ HIF_MBOX_BLOCK_SIZE
;
200 count
= sdrequest
->BlockCount
;
201 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
,
202 ("Block mode (BlockLen: %d, BlockCount: %d)\n",
203 sdrequest
->BlockLen
, sdrequest
->BlockCount
));
204 } else if (request
& HIF_BYTE_BASIS
) {
205 mode
= CMD53_BYTE_BASIS
;
206 sdrequest
->BlockLen
= length
;
207 sdrequest
->BlockCount
= 1;
208 count
= sdrequest
->BlockLen
;
209 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
,
210 ("Byte mode (BlockLen: %d, BlockCount: %d)\n",
211 sdrequest
->BlockLen
, sdrequest
->BlockCount
));
213 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
214 ("Invalid data mode: 0x%08x\n", request
));
220 /* useful for checking register accesses */
222 A_PRINTF(KERN_ALERT
"HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n",
223 request
& HIF_WRITE
? "write":"read", address
, length
);
227 if ((address
>= HIF_MBOX_START_ADDR(0)) &&
228 (address
<= HIF_MBOX_END_ADDR(3)))
231 DBG_ASSERT(length
<= HIF_MBOX_WIDTH
);
234 * Mailbox write. Adjust the address so that the last byte
235 * falls on the EOM address.
237 address
+= (HIF_MBOX_WIDTH
- length
);
242 if (request
& HIF_WRITE
) {
244 sdrequest
->Flags
|= SDREQ_FLAGS_DATA_WRITE
;
245 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Direction: Write\n"));
246 } else if (request
& HIF_READ
) {
248 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Direction: Read\n"));
250 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
251 ("Invalid direction: 0x%08x\n", request
));
256 if (request
& HIF_FIXED_ADDRESS
) {
257 opcode
= CMD53_FIXED_ADDRESS
;
258 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Address mode: Fixed\n"));
259 } else if (request
& HIF_INCREMENTAL_ADDRESS
) {
260 opcode
= CMD53_INCR_ADDRESS
;
261 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Address mode: Incremental\n"));
263 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
264 ("Invalid address mode: 0x%08x\n", request
));
269 funcNo
= SDDEVICE_GET_SDIO_FUNCNO(device
->handle
);
270 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Function number: %d\n", funcNo
));
271 SDIO_SET_CMD53_ARG(sdrequest
->Argument
, rw
, funcNo
,
272 mode
, opcode
, address
, count
);
274 /* Send the command out */
275 sdiostatus
= SDDEVICE_CALL_REQUEST_FUNC(device
->handle
, sdrequest
);
277 if (!SDIO_SUCCESS(sdiostatus
)) {
283 if (A_FAILED(status
) || (request
& HIF_SYNCHRONOUS
)) {
284 if (busrequest
!= NULL
) {
285 hifFreeBusRequest(busrequest
);
289 if (A_FAILED(status
) && (request
& HIF_ASYNCHRONOUS
)) {
290 /* call back async handler on failure */
291 htcCallbacks
.rwCompletionHandler(context
, status
);
298 HIFConfigureDevice(HIF_DEVICE
*device
, HIF_DEVICE_CONFIG_OPCODE opcode
,
299 void *config
, A_UINT32 configLen
)
304 case HIF_DEVICE_GET_MBOX_BLOCK_SIZE
:
305 ((A_UINT32
*)config
)[0] = HIF_MBOX0_BLOCK_SIZE
;
306 ((A_UINT32
*)config
)[1] = HIF_MBOX1_BLOCK_SIZE
;
307 ((A_UINT32
*)config
)[2] = HIF_MBOX2_BLOCK_SIZE
;
308 ((A_UINT32
*)config
)[3] = HIF_MBOX3_BLOCK_SIZE
;
311 case HIF_DEVICE_GET_MBOX_ADDR
:
312 for (count
= 0; count
< 4; count
++) {
313 ((A_UINT32
*)config
)[count
] = HIF_MBOX_START_ADDR(count
);
316 case HIF_DEVICE_GET_IRQ_PROC_MODE
:
317 /* the SDIO stack allows the interrupts to be processed either way, ASYNC or SYNC */
318 *((HIF_DEVICE_IRQ_PROCESSING_MODE
*)config
) = HIF_DEVICE_IRQ_ASYNC_SYNC
;
321 AR_DEBUG_PRINTF(ATH_DEBUG_WARN
,
322 ("Unsupported configuration opcode: %d\n", opcode
));
330 HIFShutDownDevice(HIF_DEVICE
*device
)
335 SDCONFIG_BUS_MODE_DATA busSettings
;
336 SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData
;
338 if (device
!= NULL
) {
339 DBG_ASSERT(device
->handle
!= NULL
);
341 /* Remove the allocated current if any */
342 status
= SDLIB_IssueConfig(device
->handle
,
343 SDCONFIG_FUNC_FREE_SLOT_CURRENT
, NULL
, 0);
344 DBG_ASSERT(SDIO_SUCCESS(status
));
346 /* Disable the card */
347 fData
.EnableFlags
= SDCONFIG_DISABLE_FUNC
;
349 status
= SDLIB_IssueConfig(device
->handle
, SDCONFIG_FUNC_ENABLE_DISABLE
,
350 &fData
, sizeof(fData
));
351 DBG_ASSERT(SDIO_SUCCESS(status
));
353 /* Perform a soft I/O reset */
354 data
= SDIO_IO_RESET
;
355 status
= SDLIB_IssueCMD52(device
->handle
, 0, SDIO_IO_ABORT_REG
,
357 DBG_ASSERT(SDIO_SUCCESS(status
));
360 * WAR - Codetelligence driver does not seem to shutdown correctly in 1
361 * bit mode. By default it configures the HC in the 4 bit. Its later in
362 * our driver that we switch to 1 bit mode. If we try to shutdown, the
363 * driver hangs so we revert to 4 bit mode, to be transparent to the
364 * underlying bus driver.
367 ZERO_OBJECT(busSettings
);
368 busSettings
.BusModeFlags
= SDDEVICE_GET_BUSMODE_FLAGS(device
->handle
);
369 SDCONFIG_SET_BUS_WIDTH(busSettings
.BusModeFlags
,
370 SDCONFIG_BUS_WIDTH_4_BIT
);
372 /* Issue config request to change the bus width to 4 bit */
373 status
= SDLIB_IssueConfig(device
->handle
, SDCONFIG_BUS_MODE_CTRL
,
375 sizeof(SDCONFIG_BUS_MODE_DATA
));
376 DBG_ASSERT(SDIO_SUCCESS(status
));
379 /* Free the bus requests */
380 for (count
= 0; count
< BUS_REQUEST_MAX_NUM
; count
++) {
381 SDDeviceFreeRequest(device
->handle
, busRequest
[count
].request
);
383 /* Clean up the queue */
384 s_busRequestFreeQueue
= NULL
;
386 /* since we are unloading the driver anyways, reset all cards in case the SDIO card
387 * is externally powered and we are unloading the SDIO stack. This avoids the problem when
388 * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already
391 /* Unregister with bus driver core */
392 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
,
393 ("Unregistering with the bus driver\n"));
394 status
= SDIO_UnregisterFunction(&FunctionContext
.function
);
395 DBG_ASSERT(SDIO_SUCCESS(status
));
400 hifRWCompletionHandler(SDREQUEST
*request
)
404 BUS_REQUEST
*busrequest
;
406 if (SDIO_SUCCESS(request
->Status
)) {
412 DBG_ASSERT(status
== A_OK
);
413 busrequest
= (BUS_REQUEST
*) request
->pCompleteContext
;
414 context
= (void *) busrequest
->context
;
415 /* free the request before calling the callback, in case the
416 * callback submits another request, this guarantees that
417 * there is at least 1 free request available everytime the callback
419 hifFreeBusRequest(busrequest
);
420 htcCallbacks
.rwCompletionHandler(context
, status
);
424 hifIRQHandler(void *context
)
429 device
= (HIF_DEVICE
*)context
;
430 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Device: %p\n", device
));
431 status
= htcCallbacks
.dsrHandler(device
->htc_handle
);
432 DBG_ASSERT(status
== A_OK
);
436 hifDeviceInserted(SDFUNCTION
*function
, SDDEVICE
*handle
)
444 A_UINT16 maxBlockSize
;
445 SDCONFIG_BUS_MODE_DATA busSettings
;
446 SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData
;
447 TARGET_FUNCTION_CONTEXT
*functionContext
;
448 SDCONFIG_FUNC_SLOT_CURRENT_DATA slotCurrent
;
449 SD_BUSCLOCK_RATE currentBusClock
;
451 DBG_ASSERT(function
!= NULL
);
452 DBG_ASSERT(handle
!= NULL
);
454 device
= addHifDevice(handle
);
455 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Device: %p\n", device
));
456 functionContext
= (TARGET_FUNCTION_CONTEXT
*)function
->pContext
;
459 * Issue commands to get the manufacturer ID and stuff and compare it
460 * against the rev Id derived from the ID registered during the
461 * initialization process. Report the device only in the case there
462 * is a match. In the case od SDIO, the bus driver has already queried
463 * these details so we just need to use their data structures to get the
464 * relevant values. Infact, the driver has already matched it against
465 * the Ids that we registered with it so we dont need to the step here.
468 /* Configure the SDIO Bus Width */
470 data
= SDIO_BUS_WIDTH_1_BIT
;
471 status
= SDLIB_IssueCMD52(handle
, 0, SDIO_BUS_IF_REG
, &data
, 1, 1);
472 if (!SDIO_SUCCESS(status
)) {
473 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
474 ("Unable to set the bus width to 1 bit\n"));
479 /* Get current bus flags */
480 ZERO_OBJECT(busSettings
);
482 busSettings
.BusModeFlags
= SDDEVICE_GET_BUSMODE_FLAGS(handle
);
484 SDCONFIG_SET_BUS_WIDTH(busSettings
.BusModeFlags
,
485 SDCONFIG_BUS_WIDTH_1_BIT
);
488 /* get the current operating clock, the bus driver sets us up based
489 * on what our CIS reports and what the host controller can handle
490 * we can use this to determine whether we want to drop our clock rate
492 currentBusClock
= SDDEVICE_GET_OPER_CLOCK(handle
);
493 busSettings
.ClockRate
= currentBusClock
;
495 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
,
496 ("HIF currently running at: %d \n",currentBusClock
));
498 /* see if HIF wants to run at a lower clock speed, we may already be
499 * at that lower clock speed */
500 if (currentBusClock
> (SDIO_CLOCK_FREQUENCY_DEFAULT
>> busspeedlow
)) {
501 busSettings
.ClockRate
= SDIO_CLOCK_FREQUENCY_DEFAULT
>> busspeedlow
;
502 AR_DEBUG_PRINTF(ATH_DEBUG_WARN
,
503 ("HIF overriding clock to %d \n",busSettings
.ClockRate
));
506 /* Issue config request to override clock rate */
507 status
= SDLIB_IssueConfig(handle
, SDCONFIG_FUNC_CHANGE_BUS_MODE
, &busSettings
,
508 sizeof(SDCONFIG_BUS_MODE_DATA
));
509 if (!SDIO_SUCCESS(status
)) {
510 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
511 ("Unable to configure the host clock\n"));
514 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
,
515 ("Configured clock: %d, Maximum clock: %d\n",
516 busSettings
.ActualClockRate
,
517 SDDEVICE_GET_MAX_CLOCK(handle
)));
521 * Check if the target supports block mode. This result of this check
522 * can be used to implement the HIFReadWrite API.
524 if (SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle
)) {
525 /* Limit block size to operational block limit or card function
527 maxBlockSize
= min(SDDEVICE_GET_OPER_BLOCK_LEN(handle
),
528 SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle
));
530 /* check if the card support multi-block transfers */
531 if (!(SDDEVICE_GET_SDIOCARD_CAPS(handle
) & SDIO_CAPS_MULTI_BLOCK
)) {
532 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Byte basis only\n"));
534 /* Limit block size to max byte basis */
535 maxBlockSize
= min(maxBlockSize
,
536 (A_UINT16
)SDIO_MAX_LENGTH_BYTE_BASIS
);
539 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Multi-block capable\n"));
540 maxBlocks
= SDDEVICE_GET_OPER_BLOCKS(handle
);
541 status
= SDLIB_SetFunctionBlockSize(handle
, HIF_MBOX_BLOCK_SIZE
);
542 if (!SDIO_SUCCESS(status
)) {
543 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
544 ("Failed to set block size. Err:%d\n", status
));
549 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
,
550 ("Bytes Per Block: %d bytes, Block Count:%d \n",
551 maxBlockSize
, maxBlocks
));
553 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
554 ("Function does not support Block Mode!\n"));
558 /* Allocate the slot current */
559 status
= SDLIB_GetDefaultOpCurrent(handle
, &slotCurrent
.SlotCurrent
);
560 if (SDIO_SUCCESS(status
)) {
561 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Allocating Slot current: %d mA\n",
562 slotCurrent
.SlotCurrent
));
563 status
= SDLIB_IssueConfig(handle
, SDCONFIG_FUNC_ALLOC_SLOT_CURRENT
,
564 &slotCurrent
, sizeof(slotCurrent
));
565 if (!SDIO_SUCCESS(status
)) {
566 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
567 ("Failed to allocate slot current %d\n", status
));
572 /* Enable the dragon function */
576 fData
.EnableFlags
= SDCONFIG_ENABLE_FUNC
;
577 while ((count
++ < SDWLAN_ENABLE_DISABLE_TIMEOUT
) && !enabled
)
580 status
= SDLIB_IssueConfig(handle
, SDCONFIG_FUNC_ENABLE_DISABLE
,
581 &fData
, sizeof(fData
));
582 if (!SDIO_SUCCESS(status
)) {
583 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
,
584 ("Attempting to enable the card again\n"));
588 /* Mark the status as enabled */
592 /* Check if we were succesful in enabling the target */
594 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
,
595 ("Failed to communicate with the target\n"));
599 /* Allocate the bus requests to be used later */
600 A_MEMZERO(busRequest
, sizeof(busRequest
));
601 for (count
= 0; count
< BUS_REQUEST_MAX_NUM
; count
++) {
602 if ((busRequest
[count
].request
= SDDeviceAllocRequest(handle
)) == NULL
){
603 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR
, ("Unable to allocate memory\n"));
604 /* TODO: Free the memory that has already been allocated */
607 hifFreeBusRequest(&busRequest
[count
]);
609 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
,
610 ("0x%08x = busRequest[%d].request = 0x%08x\n",
611 (unsigned int) &busRequest
[count
], count
,
612 (unsigned int) busRequest
[count
].request
));
615 /* Schedule a worker to handle device inserted, this is a temporary workaround
616 * to fix a deadlock if the device fails to intialize in the insertion handler
617 * The failure causes the instance to shutdown the HIF layer and unregister the
618 * function driver within the busdriver probe context which can deadlock
620 * NOTE: we cannot use the default work queue because that would block
621 * SD bus request processing for all synchronous I/O. We must use a kernel
622 * thread that is creating using the helper library.
625 if (SDIO_SUCCESS(SDLIB_OSCreateHelper(&device
->insert_helper
,
628 device
->helper_started
= TRUE
;
634 static THREAD_RETURN
insert_helper_func(POSKERNEL_HELPER pHelper
)
638 * Adding a wait of around a second before we issue the very first
639 * command to dragon. During the process of loading/unloading the
640 * driver repeatedly it was observed that we get a data timeout
641 * while accessing function 1 registers in the chip. The theory at
642 * this point is that some initialization delay in dragon is
643 * causing the SDIO state in dragon core to be not ready even after
644 * the ready bit indicates that function 1 is ready. Accomodating
645 * for this behavior by adding some delay in the driver before it
646 * issues the first command after switching on dragon. Need to
647 * investigate this a bit more - TODO
652 if ((htcCallbacks
.deviceInsertedHandler(SD_GET_OS_HELPER_CONTEXT(pHelper
))) != A_OK
) {
653 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
, ("Device rejected\n"));
660 HIFAckInterrupt(HIF_DEVICE
*device
)
663 DBG_ASSERT(device
!= NULL
);
664 DBG_ASSERT(device
->handle
!= NULL
);
666 /* Acknowledge our function IRQ */
667 status
= SDLIB_IssueConfig(device
->handle
, SDCONFIG_FUNC_ACK_IRQ
,
669 DBG_ASSERT(SDIO_SUCCESS(status
));
673 HIFUnMaskInterrupt(HIF_DEVICE
*device
)
677 DBG_ASSERT(device
!= NULL
);
678 DBG_ASSERT(device
->handle
!= NULL
);
680 /* Register the IRQ Handler */
681 SDDEVICE_SET_IRQ_HANDLER(device
->handle
, hifIRQHandler
, device
);
683 /* Unmask our function IRQ */
684 status
= SDLIB_IssueConfig(device
->handle
, SDCONFIG_FUNC_UNMASK_IRQ
,
686 DBG_ASSERT(SDIO_SUCCESS(status
));
689 void HIFMaskInterrupt(HIF_DEVICE
*device
)
692 DBG_ASSERT(device
!= NULL
);
693 DBG_ASSERT(device
->handle
!= NULL
);
695 /* Mask our function IRQ */
696 status
= SDLIB_IssueConfig(device
->handle
, SDCONFIG_FUNC_MASK_IRQ
,
698 DBG_ASSERT(SDIO_SUCCESS(status
));
700 /* Unregister the IRQ Handler */
701 SDDEVICE_SET_IRQ_HANDLER(device
->handle
, NULL
, NULL
);
704 static BUS_REQUEST
*hifAllocateBusRequest(void)
706 BUS_REQUEST
*busrequest
;
709 CriticalSectionAcquire(&lock
);
711 /* Remove first in list */
712 if((busrequest
= s_busRequestFreeQueue
) != NULL
)
714 s_busRequestFreeQueue
= busrequest
->next
;
718 CriticalSectionRelease(&lock
);
724 hifFreeBusRequest(BUS_REQUEST
*busrequest
)
726 DBG_ASSERT(busrequest
!= NULL
);
729 CriticalSectionAcquire(&lock
);
731 /* Insert first in list */
732 busrequest
->next
= s_busRequestFreeQueue
;
733 s_busRequestFreeQueue
= busrequest
;
736 CriticalSectionRelease(&lock
);
740 hifDeviceRemoved(SDFUNCTION
*function
, SDDEVICE
*handle
)
744 DBG_ASSERT(function
!= NULL
);
745 DBG_ASSERT(handle
!= NULL
);
747 device
= getHifDevice(handle
);
748 status
= htcCallbacks
.deviceRemovedHandler(device
->htc_handle
, A_OK
);
750 /* cleanup the helper thread */
751 if (device
->helper_started
) {
752 SDLIB_OSDeleteHelper(&device
->insert_helper
);
753 device
->helper_started
= FALSE
;
756 delHifDevice(handle
);
757 DBG_ASSERT(status
== A_OK
);
761 addHifDevice(SDDEVICE
*handle
)
763 DBG_ASSERT(handle
!= NULL
);
764 hifDevice
[0].handle
= handle
;
765 return &hifDevice
[0];
769 getHifDevice(SDDEVICE
*handle
)
771 DBG_ASSERT(handle
!= NULL
);
772 return &hifDevice
[0];
776 delHifDevice(SDDEVICE
*handle
)
778 DBG_ASSERT(handle
!= NULL
);
779 hifDevice
[0].handle
= NULL
;
783 HIFGetOSDevice(HIF_DEVICE
*device
)
785 return &device
->handle
->Device
->dev
;
788 static void ResetAllCards(void)
794 data
= SDIO_IO_RESET
;
796 /* set the I/O CARD reset bit:
797 * NOTE: we are exploiting a "feature" of the SDIO core that resets the core when you
798 * set the RES bit in the SDIO_IO_ABORT register. This bit however "normally" resets the
799 * I/O functions leaving the SDIO core in the same state (as per SDIO spec).
800 * In this design, this reset can be used to reset the SDIO core itself */
801 for (i
= 0; i
< HIF_MAX_DEVICES
; i
++) {
802 if (hifDevice
[i
].handle
!= NULL
) {
803 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE
,
804 ("Issuing I/O Card reset for instance: %d \n",i
));
805 /* set the I/O Card reset bit */
806 status
= SDLIB_IssueCMD52(hifDevice
[i
].handle
,
807 0, /* function 0 space */
817 void HIFSetHandle(void *hif_handle
, void *handle
)
819 HIF_DEVICE
*device
= (HIF_DEVICE
*) hif_handle
;
821 device
->htc_handle
= handle
;