diff options
Diffstat (limited to 'target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif.c')
-rw-r--r-- | target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif.c | 824 |
1 files changed, 0 insertions, 824 deletions
diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif.c deleted file mode 100644 index d04486c35b..0000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif.c +++ /dev/null @@ -1,824 +0,0 @@ -/* - * @file: hif.c - * - * @abstract: HIF layer reference implementation for Atheros SDIO stack - * - * @notice: Copyright (c) 2004-2006 Atheros Communications Inc. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "hif_internal.h" - -/* ------ Static Variables ------ */ - -/* ------ Global Variable Declarations ------- */ -SD_PNP_INFO Ids[] = { - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0xB, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0xA, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0x9, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0x8, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6002_BASE | 0x0, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6002_BASE | 0x1, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - } //list is null termintaed -}; - -TARGET_FUNCTION_CONTEXT FunctionContext = { - .function.Version = CT_SDIO_STACK_VERSION_CODE, - .function.pName = "sdio_wlan", - .function.MaxDevices = 1, - .function.NumDevices = 0, - .function.pIds = Ids, - .function.pProbe = hifDeviceInserted, - .function.pRemove = hifDeviceRemoved, - .function.pSuspend = NULL, - .function.pResume = NULL, - .function.pWake = NULL, - .function.pContext = &FunctionContext, -}; - -HIF_DEVICE hifDevice[HIF_MAX_DEVICES]; -HTC_CALLBACKS htcCallbacks; -BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM]; -static BUS_REQUEST *s_busRequestFreeQueue = NULL; -OS_CRITICALSECTION lock; -extern A_UINT32 onebitmode; -extern A_UINT32 busspeedlow; - -#ifdef DEBUG -extern A_UINT32 debughif; -#define ATH_DEBUG_ERROR 1 -#define ATH_DEBUG_WARN 2 -#define ATH_DEBUG_TRACE 3 -#define _AR_DEBUG_PRINTX_ARG(arg...) arg -#define AR_DEBUG_PRINTF(lvl, args)\ - {if (lvl <= debughif)\ - A_PRINTF(KERN_ALERT _AR_DEBUG_PRINTX_ARG args);\ - } -#else -#define AR_DEBUG_PRINTF(lvl, args) -#endif - -static BUS_REQUEST *hifAllocateBusRequest(void); -static void hifFreeBusRequest(BUS_REQUEST *busrequest); -static THREAD_RETURN insert_helper_func(POSKERNEL_HELPER pHelper); -static void ResetAllCards(void); - -/* ------ Functions ------ */ -int HIFInit(HTC_CALLBACKS *callbacks) -{ - SDIO_STATUS status; - DBG_ASSERT(callbacks != NULL); - - /* Store the callback and event handlers */ - htcCallbacks.deviceInsertedHandler = callbacks->deviceInsertedHandler; - htcCallbacks.deviceRemovedHandler = callbacks->deviceRemovedHandler; - htcCallbacks.deviceSuspendHandler = callbacks->deviceSuspendHandler; - htcCallbacks.deviceResumeHandler = callbacks->deviceResumeHandler; - htcCallbacks.deviceWakeupHandler = callbacks->deviceWakeupHandler; - htcCallbacks.rwCompletionHandler = callbacks->rwCompletionHandler; - htcCallbacks.dsrHandler = callbacks->dsrHandler; - - CriticalSectionInit(&lock); - - /* Register with bus driver core */ - status = SDIO_RegisterFunction(&FunctionContext.function); - DBG_ASSERT(SDIO_SUCCESS(status)); - - return(0); -} - -A_STATUS -HIFReadWrite(HIF_DEVICE *device, - A_UINT32 address, - A_UCHAR *buffer, - A_UINT32 length, - A_UINT32 request, - void *context) -{ - A_UINT8 rw; - A_UINT8 mode; - A_UINT8 funcNo; - A_UINT8 opcode; - A_UINT16 count; - SDREQUEST *sdrequest; - SDIO_STATUS sdiostatus; - BUS_REQUEST *busrequest; - A_STATUS status = A_OK; - - DBG_ASSERT(device != NULL); - DBG_ASSERT(device->handle != NULL); - - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); - - do { - busrequest = hifAllocateBusRequest(); - if (busrequest == NULL) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF Unable to allocate bus request\n")); - status = A_NO_RESOURCE; - break; - } - - sdrequest = busrequest->request; - busrequest->context = context; - - sdrequest->pDataBuffer = buffer; - if (request & HIF_SYNCHRONOUS) { - sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS; - sdrequest->pCompleteContext = NULL; - sdrequest->pCompletion = NULL; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Synchronous\n")); - } else if (request & HIF_ASYNCHRONOUS) { - sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS | - SDREQ_FLAGS_TRANS_ASYNC; - sdrequest->pCompleteContext = busrequest; - sdrequest->pCompletion = hifRWCompletionHandler; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Asynchronous\n")); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Invalid execution mode: 0x%08x\n", request)); - status = A_EINVAL; - break; - } - - if (request & HIF_EXTENDED_IO) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Command type: CMD53\n")); - sdrequest->Command = CMD53; - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Invalid command type: 0x%08x\n", request)); - status = A_EINVAL; - break; - } - - if (request & HIF_BLOCK_BASIS) { - mode = CMD53_BLOCK_BASIS; - sdrequest->BlockLen = HIF_MBOX_BLOCK_SIZE; - sdrequest->BlockCount = length / HIF_MBOX_BLOCK_SIZE; - count = sdrequest->BlockCount; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Block mode (BlockLen: %d, BlockCount: %d)\n", - sdrequest->BlockLen, sdrequest->BlockCount)); - } else if (request & HIF_BYTE_BASIS) { - mode = CMD53_BYTE_BASIS; - sdrequest->BlockLen = length; - sdrequest->BlockCount = 1; - count = sdrequest->BlockLen; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Byte mode (BlockLen: %d, BlockCount: %d)\n", - sdrequest->BlockLen, sdrequest->BlockCount)); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Invalid data mode: 0x%08x\n", request)); - status = A_EINVAL; - break; - } - -#if 0 - /* useful for checking register accesses */ - if (length & 0x3) { - A_PRINTF(KERN_ALERT"HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n", - request & HIF_WRITE ? "write":"read", address, length); - } -#endif - - if ((address >= HIF_MBOX_START_ADDR(0)) && - (address <= HIF_MBOX_END_ADDR(3))) - { - - DBG_ASSERT(length <= HIF_MBOX_WIDTH); - - /* - * Mailbox write. Adjust the address so that the last byte - * falls on the EOM address. - */ - address += (HIF_MBOX_WIDTH - length); - } - - - - if (request & HIF_WRITE) { - rw = CMD53_WRITE; - sdrequest->Flags |= SDREQ_FLAGS_DATA_WRITE; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Write\n")); - } else if (request & HIF_READ) { - rw = CMD53_READ; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Read\n")); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Invalid direction: 0x%08x\n", request)); - status = A_EINVAL; - break; - } - - if (request & HIF_FIXED_ADDRESS) { - opcode = CMD53_FIXED_ADDRESS; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Fixed\n")); - } else if (request & HIF_INCREMENTAL_ADDRESS) { - opcode = CMD53_INCR_ADDRESS; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Incremental\n")); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Invalid address mode: 0x%08x\n", request)); - status = A_EINVAL; - break; - } - - funcNo = SDDEVICE_GET_SDIO_FUNCNO(device->handle); - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Function number: %d\n", funcNo)); - SDIO_SET_CMD53_ARG(sdrequest->Argument, rw, funcNo, - mode, opcode, address, count); - - /* Send the command out */ - sdiostatus = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest); - - if (!SDIO_SUCCESS(sdiostatus)) { - status = A_ERROR; - } - - } while (FALSE); - - if (A_FAILED(status) || (request & HIF_SYNCHRONOUS)) { - if (busrequest != NULL) { - hifFreeBusRequest(busrequest); - } - } - - if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) { - /* call back async handler on failure */ - htcCallbacks.rwCompletionHandler(context, status); - } - - return status; -} - -A_STATUS -HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, - void *config, A_UINT32 configLen) -{ - A_UINT32 count; - - switch(opcode) { - case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: - ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; - ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; - ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; - ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; - break; - - case HIF_DEVICE_GET_MBOX_ADDR: - for (count = 0; count < 4; count ++) { - ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count); - } - break; - case HIF_DEVICE_GET_IRQ_PROC_MODE: - /* the SDIO stack allows the interrupts to be processed either way, ASYNC or SYNC */ - *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_ASYNC_SYNC; - break; - default: - AR_DEBUG_PRINTF(ATH_DEBUG_WARN, - ("Unsupported configuration opcode: %d\n", opcode)); - return A_ERROR; - } - - return A_OK; -} - -void -HIFShutDownDevice(HIF_DEVICE *device) -{ - A_UINT8 data; - A_UINT32 count; - SDIO_STATUS status; - SDCONFIG_BUS_MODE_DATA busSettings; - SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData; - - if (device != NULL) { - DBG_ASSERT(device->handle != NULL); - - /* Remove the allocated current if any */ - status = SDLIB_IssueConfig(device->handle, - SDCONFIG_FUNC_FREE_SLOT_CURRENT, NULL, 0); - DBG_ASSERT(SDIO_SUCCESS(status)); - - /* Disable the card */ - fData.EnableFlags = SDCONFIG_DISABLE_FUNC; - fData.TimeOut = 1; - status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ENABLE_DISABLE, - &fData, sizeof(fData)); - DBG_ASSERT(SDIO_SUCCESS(status)); - - /* Perform a soft I/O reset */ - data = SDIO_IO_RESET; - status = SDLIB_IssueCMD52(device->handle, 0, SDIO_IO_ABORT_REG, - &data, 1, 1); - DBG_ASSERT(SDIO_SUCCESS(status)); - - /* - * WAR - Codetelligence driver does not seem to shutdown correctly in 1 - * bit mode. By default it configures the HC in the 4 bit. Its later in - * our driver that we switch to 1 bit mode. If we try to shutdown, the - * driver hangs so we revert to 4 bit mode, to be transparent to the - * underlying bus driver. - */ - if (onebitmode) { - ZERO_OBJECT(busSettings); - busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(device->handle); - SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags, - SDCONFIG_BUS_WIDTH_4_BIT); - - /* Issue config request to change the bus width to 4 bit */ - status = SDLIB_IssueConfig(device->handle, SDCONFIG_BUS_MODE_CTRL, - &busSettings, - sizeof(SDCONFIG_BUS_MODE_DATA)); - DBG_ASSERT(SDIO_SUCCESS(status)); - } - - /* Free the bus requests */ - for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { - SDDeviceFreeRequest(device->handle, busRequest[count].request); - } - /* Clean up the queue */ - s_busRequestFreeQueue = NULL; - } else { - /* since we are unloading the driver anyways, reset all cards in case the SDIO card - * is externally powered and we are unloading the SDIO stack. This avoids the problem when - * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already - * enumerated */ - ResetAllCards(); - /* Unregister with bus driver core */ - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Unregistering with the bus driver\n")); - status = SDIO_UnregisterFunction(&FunctionContext.function); - DBG_ASSERT(SDIO_SUCCESS(status)); - } -} - -void -hifRWCompletionHandler(SDREQUEST *request) -{ - A_STATUS status; - void *context; - BUS_REQUEST *busrequest; - - if (SDIO_SUCCESS(request->Status)) { - status = A_OK; - } else { - status = A_ERROR; - } - - DBG_ASSERT(status == A_OK); - busrequest = (BUS_REQUEST *) request->pCompleteContext; - context = (void *) busrequest->context; - /* free the request before calling the callback, in case the - * callback submits another request, this guarantees that - * there is at least 1 free request available everytime the callback - * is invoked */ - hifFreeBusRequest(busrequest); - htcCallbacks.rwCompletionHandler(context, status); -} - -void -hifIRQHandler(void *context) -{ - A_STATUS status; - HIF_DEVICE *device; - - device = (HIF_DEVICE *)context; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); - status = htcCallbacks.dsrHandler(device->htc_handle); - DBG_ASSERT(status == A_OK); -} - -BOOL -hifDeviceInserted(SDFUNCTION *function, SDDEVICE *handle) -{ - BOOL enabled; - A_UINT8 data; - A_UINT32 count; - HIF_DEVICE *device; - SDIO_STATUS status; - A_UINT16 maxBlocks; - A_UINT16 maxBlockSize; - SDCONFIG_BUS_MODE_DATA busSettings; - SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData; - TARGET_FUNCTION_CONTEXT *functionContext; - SDCONFIG_FUNC_SLOT_CURRENT_DATA slotCurrent; - SD_BUSCLOCK_RATE currentBusClock; - - DBG_ASSERT(function != NULL); - DBG_ASSERT(handle != NULL); - - device = addHifDevice(handle); - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); - functionContext = (TARGET_FUNCTION_CONTEXT *)function->pContext; - - /* - * Issue commands to get the manufacturer ID and stuff and compare it - * against the rev Id derived from the ID registered during the - * initialization process. Report the device only in the case there - * is a match. In the case od SDIO, the bus driver has already queried - * these details so we just need to use their data structures to get the - * relevant values. Infact, the driver has already matched it against - * the Ids that we registered with it so we dont need to the step here. - */ - - /* Configure the SDIO Bus Width */ - if (onebitmode) { - data = SDIO_BUS_WIDTH_1_BIT; - status = SDLIB_IssueCMD52(handle, 0, SDIO_BUS_IF_REG, &data, 1, 1); - if (!SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Unable to set the bus width to 1 bit\n")); - return FALSE; - } - } - - /* Get current bus flags */ - ZERO_OBJECT(busSettings); - - busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(handle); - if (onebitmode) { - SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags, - SDCONFIG_BUS_WIDTH_1_BIT); - } - - /* get the current operating clock, the bus driver sets us up based - * on what our CIS reports and what the host controller can handle - * we can use this to determine whether we want to drop our clock rate - * down */ - currentBusClock = SDDEVICE_GET_OPER_CLOCK(handle); - busSettings.ClockRate = currentBusClock; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("HIF currently running at: %d \n",currentBusClock)); - - /* see if HIF wants to run at a lower clock speed, we may already be - * at that lower clock speed */ - if (currentBusClock > (SDIO_CLOCK_FREQUENCY_DEFAULT >> busspeedlow)) { - busSettings.ClockRate = SDIO_CLOCK_FREQUENCY_DEFAULT >> busspeedlow; - AR_DEBUG_PRINTF(ATH_DEBUG_WARN, - ("HIF overriding clock to %d \n",busSettings.ClockRate)); - } - - /* Issue config request to override clock rate */ - status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_CHANGE_BUS_MODE, &busSettings, - sizeof(SDCONFIG_BUS_MODE_DATA)); - if (!SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Unable to configure the host clock\n")); - return FALSE; - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Configured clock: %d, Maximum clock: %d\n", - busSettings.ActualClockRate, - SDDEVICE_GET_MAX_CLOCK(handle))); - } - - /* - * Check if the target supports block mode. This result of this check - * can be used to implement the HIFReadWrite API. - */ - if (SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle)) { - /* Limit block size to operational block limit or card function - capability */ - maxBlockSize = min(SDDEVICE_GET_OPER_BLOCK_LEN(handle), - SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle)); - - /* check if the card support multi-block transfers */ - if (!(SDDEVICE_GET_SDIOCARD_CAPS(handle) & SDIO_CAPS_MULTI_BLOCK)) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Byte basis only\n")); - - /* Limit block size to max byte basis */ - maxBlockSize = min(maxBlockSize, - (A_UINT16)SDIO_MAX_LENGTH_BYTE_BASIS); - maxBlocks = 1; - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Multi-block capable\n")); - maxBlocks = SDDEVICE_GET_OPER_BLOCKS(handle); - status = SDLIB_SetFunctionBlockSize(handle, HIF_MBOX_BLOCK_SIZE); - if (!SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Failed to set block size. Err:%d\n", status)); - return FALSE; - } - } - - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Bytes Per Block: %d bytes, Block Count:%d \n", - maxBlockSize, maxBlocks)); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Function does not support Block Mode!\n")); - return FALSE; - } - - /* Allocate the slot current */ - status = SDLIB_GetDefaultOpCurrent(handle, &slotCurrent.SlotCurrent); - if (SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Allocating Slot current: %d mA\n", - slotCurrent.SlotCurrent)); - status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ALLOC_SLOT_CURRENT, - &slotCurrent, sizeof(slotCurrent)); - if (!SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Failed to allocate slot current %d\n", status)); - return FALSE; - } - } - - /* Enable the dragon function */ - count = 0; - enabled = FALSE; - fData.TimeOut = 1; - fData.EnableFlags = SDCONFIG_ENABLE_FUNC; - while ((count++ < SDWLAN_ENABLE_DISABLE_TIMEOUT) && !enabled) - { - /* Enable dragon */ - status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ENABLE_DISABLE, - &fData, sizeof(fData)); - if (!SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Attempting to enable the card again\n")); - continue; - } - - /* Mark the status as enabled */ - enabled = TRUE; - } - - /* Check if we were succesful in enabling the target */ - if (!enabled) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Failed to communicate with the target\n")); - return FALSE; - } - - /* Allocate the bus requests to be used later */ - A_MEMZERO(busRequest, sizeof(busRequest)); - for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { - if ((busRequest[count].request = SDDeviceAllocRequest(handle)) == NULL){ - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Unable to allocate memory\n")); - /* TODO: Free the memory that has already been allocated */ - return FALSE; - } - hifFreeBusRequest(&busRequest[count]); - - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("0x%08x = busRequest[%d].request = 0x%08x\n", - (unsigned int) &busRequest[count], count, - (unsigned int) busRequest[count].request)); - } - - /* Schedule a worker to handle device inserted, this is a temporary workaround - * to fix a deadlock if the device fails to intialize in the insertion handler - * The failure causes the instance to shutdown the HIF layer and unregister the - * function driver within the busdriver probe context which can deadlock - * - * NOTE: we cannot use the default work queue because that would block - * SD bus request processing for all synchronous I/O. We must use a kernel - * thread that is creating using the helper library. - * */ - - if (SDIO_SUCCESS(SDLIB_OSCreateHelper(&device->insert_helper, - insert_helper_func, - device))) { - device->helper_started = TRUE; - } - - return TRUE; -} - -static THREAD_RETURN insert_helper_func(POSKERNEL_HELPER pHelper) -{ - - /* - * Adding a wait of around a second before we issue the very first - * command to dragon. During the process of loading/unloading the - * driver repeatedly it was observed that we get a data timeout - * while accessing function 1 registers in the chip. The theory at - * this point is that some initialization delay in dragon is - * causing the SDIO state in dragon core to be not ready even after - * the ready bit indicates that function 1 is ready. Accomodating - * for this behavior by adding some delay in the driver before it - * issues the first command after switching on dragon. Need to - * investigate this a bit more - TODO - */ - - A_MDELAY(1000); - /* Inform HTC */ - if ((htcCallbacks.deviceInsertedHandler(SD_GET_OS_HELPER_CONTEXT(pHelper))) != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device rejected\n")); - } - - return 0; -} - -void -HIFAckInterrupt(HIF_DEVICE *device) -{ - SDIO_STATUS status; - DBG_ASSERT(device != NULL); - DBG_ASSERT(device->handle != NULL); - - /* Acknowledge our function IRQ */ - status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ACK_IRQ, - NULL, 0); - DBG_ASSERT(SDIO_SUCCESS(status)); -} - -void -HIFUnMaskInterrupt(HIF_DEVICE *device) -{ - SDIO_STATUS status; - - DBG_ASSERT(device != NULL); - DBG_ASSERT(device->handle != NULL); - - /* Register the IRQ Handler */ - SDDEVICE_SET_IRQ_HANDLER(device->handle, hifIRQHandler, device); - - /* Unmask our function IRQ */ - status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_UNMASK_IRQ, - NULL, 0); - DBG_ASSERT(SDIO_SUCCESS(status)); -} - -void HIFMaskInterrupt(HIF_DEVICE *device) -{ - SDIO_STATUS status; - DBG_ASSERT(device != NULL); - DBG_ASSERT(device->handle != NULL); - - /* Mask our function IRQ */ - status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_MASK_IRQ, - NULL, 0); - DBG_ASSERT(SDIO_SUCCESS(status)); - - /* Unregister the IRQ Handler */ - SDDEVICE_SET_IRQ_HANDLER(device->handle, NULL, NULL); -} - -static BUS_REQUEST *hifAllocateBusRequest(void) -{ - BUS_REQUEST *busrequest; - - /* Acquire lock */ - CriticalSectionAcquire(&lock); - - /* Remove first in list */ - if((busrequest = s_busRequestFreeQueue) != NULL) - { - s_busRequestFreeQueue = busrequest->next; - } - - /* Release lock */ - CriticalSectionRelease(&lock); - - return busrequest; -} - -static void -hifFreeBusRequest(BUS_REQUEST *busrequest) -{ - DBG_ASSERT(busrequest != NULL); - - /* Acquire lock */ - CriticalSectionAcquire(&lock); - - /* Insert first in list */ - busrequest->next = s_busRequestFreeQueue; - s_busRequestFreeQueue = busrequest; - - /* Release lock */ - CriticalSectionRelease(&lock); -} - -void -hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *handle) -{ - A_STATUS status; - HIF_DEVICE *device; - DBG_ASSERT(function != NULL); - DBG_ASSERT(handle != NULL); - - device = getHifDevice(handle); - status = htcCallbacks.deviceRemovedHandler(device->htc_handle, A_OK); - - /* cleanup the helper thread */ - if (device->helper_started) { - SDLIB_OSDeleteHelper(&device->insert_helper); - device->helper_started = FALSE; - } - - delHifDevice(handle); - DBG_ASSERT(status == A_OK); -} - -HIF_DEVICE * -addHifDevice(SDDEVICE *handle) -{ - DBG_ASSERT(handle != NULL); - hifDevice[0].handle = handle; - return &hifDevice[0]; -} - -HIF_DEVICE * -getHifDevice(SDDEVICE *handle) -{ - DBG_ASSERT(handle != NULL); - return &hifDevice[0]; -} - -void -delHifDevice(SDDEVICE *handle) -{ - DBG_ASSERT(handle != NULL); - hifDevice[0].handle = NULL; -} - -struct device* -HIFGetOSDevice(HIF_DEVICE *device) -{ - return &device->handle->Device->dev; -} - -static void ResetAllCards(void) -{ - UINT8 data; - SDIO_STATUS status; - int i; - - data = SDIO_IO_RESET; - - /* set the I/O CARD reset bit: - * NOTE: we are exploiting a "feature" of the SDIO core that resets the core when you - * set the RES bit in the SDIO_IO_ABORT register. This bit however "normally" resets the - * I/O functions leaving the SDIO core in the same state (as per SDIO spec). - * In this design, this reset can be used to reset the SDIO core itself */ - for (i = 0; i < HIF_MAX_DEVICES; i++) { - if (hifDevice[i].handle != NULL) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Issuing I/O Card reset for instance: %d \n",i)); - /* set the I/O Card reset bit */ - status = SDLIB_IssueCMD52(hifDevice[i].handle, - 0, /* function 0 space */ - SDIO_IO_ABORT_REG, - &data, - 1, /* 1 byte */ - TRUE); /* write */ - } - } - -} - -void HIFSetHandle(void *hif_handle, void *handle) -{ - HIF_DEVICE *device = (HIF_DEVICE *) hif_handle; - - device->htc_handle = handle; - - return; -} |