diff options
Diffstat (limited to 'target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif')
3 files changed, 0 insertions, 1694 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; -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif2.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif2.c deleted file mode 100644 index 386d96e668..0000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif2.c +++ /dev/null @@ -1,768 +0,0 @@ -/* - * hif2.c - HIF layer re-implementation for the Linux SDIO stack - * - * Copyright (C) 2008, 2009 by OpenMoko, Inc. - * Written by Werner Almesberger <werner@openmoko.org> - * All Rights Reserved - * - * 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; - * - * Based on: - * - * @abstract: HIF layer reference implementation for Atheros SDIO stack - * @notice: Copyright (c) 2004-2006 Atheros Communications Inc. - */ - - -#include <linux/kernel.h> -#include <linux/kthread.h> -#include <linux/list.h> -#include <linux/wait.h> -#include <linux/spinlock.h> -#include <linux/mutex.h> -#include <linux/sched.h> -#include <linux/mmc/sdio_func.h> -#include <linux/mmc/sdio.h> -#include <linux/mmc/sdio_ids.h> - -#include "athdefs.h" -#include "a_types.h" -#include "hif.h" - - -/* @@@ Hack - this wants cleaning up */ - -#ifdef CONFIG_MACH_NEO1973_GTA02 - -#include <mach/gta02-pm-wlan.h> - -#else /* CONFIG_MACH_NEO1973_GTA02 */ - -#define gta02_wlan_query_rfkill_lock() 1 -#define gta02_wlan_set_rfkill_cb(cb, hif) ((void) cb) -#define gta02_wlan_query_rfkill_unlock() -#define gta02_wlan_clear_rfkill_cb() - -#endif /* !CONFIG_MACH_NEO1973_GTA02 */ - - -/* - * KNOWN BUGS: - * - * - HIF_DEVICE_IRQ_ASYNC_SYNC doesn't work yet (gets MMC errors) - * - latency can reach hundreds of ms, probably because of scheduling delays - * - packets go through about three queues before finally hitting the network - */ - -/* - * Differences from Atheros' HIFs: - * - * - synchronous and asynchronous requests may get reordered with respect to - * each other, e.g., if HIFReadWrite returns for an asynchronous request and - * then HIFReadWrite is called for a synchronous request, the synchronous - * request may be executed before the asynchronous request. - * - * - request queue locking seems unnecessarily complex in the Atheros HIFs. - * - * - Atheros mask interrupts by calling sdio_claim_irq/sdio_release_irq, which - * can cause quite a bit of overhead. This HIF has its own light-weight - * interrupt masking. - * - * - Atheros call deviceInsertedHandler from a thread spawned off the probe or - * device insertion function. The original explanation for the Atheros SDIO - * stack said that this is done because a delay is needed to let the chip - * complete initialization. There is indeed a one second delay in the thread. - * - * The Atheros Linux SDIO HIF removes the delay and only retains the thread. - * Experimentally removing the thread didn't show any conflicts, so let's get - * rid of it for good. - * - * - The Atheros SDIO stack with Samuel's driver sets SDIO_CCCR_POWER in - * SDIO_POWER_EMPC. Atheros' Linux SDIO code apparently doesn't. We don't - * either, and this seems to work fine. - * @@@ Need to check this with Atheros. - */ - - -#define MBOXES 4 - -#define HIF_MBOX_BLOCK_SIZE 128 -#define HIF_MBOX_BASE_ADDR 0x800 -#define HIF_MBOX_WIDTH 0x800 -#define HIF_MBOX_START_ADDR(mbox) \ - (HIF_MBOX_BASE_ADDR+(mbox)*HIF_MBOX_WIDTH) - - -struct hif_device { - void *htc_handle; - struct sdio_func *func; - - /* - * @@@ our sweet little bit of bogosity - the mechanism that lets us - * use the SDIO stack from softirqs. This really wants to use skbs. - */ - struct list_head queue; - spinlock_t queue_lock; - struct task_struct *io_task; - wait_queue_head_t wait; - - /* - * activate_lock protects "active" and the activation/deactivation - * process itself. - * - * Relation to other locks: The SDIO function can be claimed while - * activate_lock is being held, but trying to acquire activate_lock - * while having ownership of the SDIO function could cause a deadlock. - */ - int active; - struct mutex activate_lock; -}; - -struct hif_request { - struct list_head list; - struct sdio_func *func; - int (*read)(struct sdio_func *func, - void *dst, unsigned int addr, int count); - int (*write)(struct sdio_func *func, - unsigned int addr, void *src, int count); - void *buf; - unsigned long addr; - int len; - A_STATUS (*completion)(void *context, A_STATUS status); - void *context; -}; - - -static HTC_CALLBACKS htcCallbacks; - -/* - * shutdown_lock prevents recursion through HIFShutDownDevice - */ -static DEFINE_MUTEX(shutdown_lock); - - -/* ----- Request processing ------------------------------------------------ */ - - -static A_STATUS process_request(struct hif_request *req) -{ - int ret; - A_STATUS status; - - dev_dbg(&req->func->dev, "process_request(req %p)\n", req); - sdio_claim_host(req->func); - if (req->read) { - ret = req->read(req->func, req->buf, req->addr, req->len); - } else { - ret = req->write(req->func, req->addr, req->buf, req->len); - } - sdio_release_host(req->func); - status = ret ? A_ERROR : A_OK; - if (req->completion) - req->completion(req->context, status); - kfree(req); - return status; -} - - -static void enqueue_request(struct hif_device *hif, struct hif_request *req) -{ - unsigned long flags; - - dev_dbg(&req->func->dev, "enqueue_request(req %p)\n", req); - spin_lock_irqsave(&hif->queue_lock, flags); - list_add_tail(&req->list, &hif->queue); - spin_unlock_irqrestore(&hif->queue_lock, flags); - wake_up(&hif->wait); -} - - -static struct hif_request *dequeue_request(struct hif_device *hif) -{ - struct hif_request *req; - unsigned long flags; - - spin_lock_irqsave(&hif->queue_lock, flags); - if (list_empty(&hif->queue)) - req = NULL; - else { - req = list_first_entry(&hif->queue, - struct hif_request, list); - list_del(&req->list); - } - spin_unlock_irqrestore(&hif->queue_lock, flags); - return req; -} - - -static void wait_queue_empty(struct hif_device *hif) -{ - unsigned long flags; - int empty; - - while (1) { - spin_lock_irqsave(&hif->queue_lock, flags); - empty = list_empty(&hif->queue); - spin_unlock_irqrestore(&hif->queue_lock, flags); - if (empty) - break; - else - yield(); - } -} - - -static int io(void *data) -{ - struct hif_device *hif = data; - struct sched_param param = { .sched_priority = 2 }; - /* one priority level slower than ksdioirqd (which is at 1) */ - DEFINE_WAIT(wait); - struct hif_request *req; - - sched_setscheduler(current, SCHED_FIFO, ¶m); - - while (1) { - while (1) { - /* - * Since we never use signals here, one might think - * that this ought to be TASK_UNINTERRUPTIBLE. However, - * such a task would increase the load average and, - * worse, it would trigger the softlockup check. - */ - prepare_to_wait(&hif->wait, &wait, TASK_INTERRUPTIBLE); - if (kthread_should_stop()) { - finish_wait(&hif->wait, &wait); - return 0; - } - req = dequeue_request(hif); - if (req) - break; - schedule(); - } - finish_wait(&hif->wait, &wait); - - (void) process_request(req); - } - return 0; -} - - -A_STATUS HIFReadWrite(HIF_DEVICE *hif, A_UINT32 address, A_UCHAR *buffer, - A_UINT32 length, A_UINT32 request, void *context) -{ - struct device *dev = HIFGetOSDevice(hif); - struct hif_request *req; - - dev_dbg(dev, "HIFReadWrite(device %p, address 0x%x, buffer %p, " - "length %d, request 0x%x, context %p)\n", - hif, address, buffer, length, request, context); - - BUG_ON(!(request & (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS))); - BUG_ON(!(request & (HIF_BYTE_BASIS | HIF_BLOCK_BASIS))); - BUG_ON(!(request & (HIF_READ | HIF_WRITE))); - BUG_ON(!(request & HIF_EXTENDED_IO)); - - if (address >= HIF_MBOX_START_ADDR(0) && - address < HIF_MBOX_START_ADDR(MBOXES+1)) { - BUG_ON(length > HIF_MBOX_WIDTH); - /* Adjust the address so that the last byte falls on the EOM - address. */ - address += HIF_MBOX_WIDTH-length; - } - - req = kzalloc(sizeof(*req), GFP_ATOMIC); - if (!req) { - if (request & HIF_ASYNCHRONOUS) - htcCallbacks.rwCompletionHandler(context, A_ERROR); - return A_ERROR; - } - - req->func = hif->func; - req->addr = address; - req->buf = buffer; - req->len = length; - - if (request & HIF_READ) { - if (request & HIF_FIXED_ADDRESS) - req->read = sdio_readsb; - else - req->read = sdio_memcpy_fromio; - } else { - if (request & HIF_FIXED_ADDRESS) - req->write = sdio_writesb; - else - req->write = sdio_memcpy_toio; - } - - if (!(request & HIF_ASYNCHRONOUS)) - return process_request(req); - - req->completion = htcCallbacks.rwCompletionHandler; - req->context = context; - enqueue_request(hif, req); - - return A_OK; -} - - -/* ----- Interrupt handling ------------------------------------------------ */ - -/* - * Volatile ought to be good enough to make gcc do the right thing on S3C24xx. - * No need to use atomic or put barriers, keeping the code more readable. - * - * Warning: this story changes if going SMP/SMT. - */ - -static volatile int masked = 1; -static volatile int pending; -static volatile int in_interrupt; - - -static void ar6000_do_irq(struct sdio_func *func) -{ - HIF_DEVICE *hif = sdio_get_drvdata(func); - struct device *dev = HIFGetOSDevice(hif); - A_STATUS status; - - dev_dbg(dev, "ar6000_do_irq -> %p\n", htcCallbacks.dsrHandler); - - status = htcCallbacks.dsrHandler(hif->htc_handle); - BUG_ON(status != A_OK); -} - - -static void sdio_ar6000_irq(struct sdio_func *func) -{ - HIF_DEVICE *hif = sdio_get_drvdata(func); - struct device *dev = HIFGetOSDevice(hif); - - dev_dbg(dev, "sdio_ar6000_irq\n"); - - in_interrupt = 1; - if (masked) { - in_interrupt = 0; - pending++; - return; - } - /* - * @@@ This is ugly. If we don't drop the lock, we'll deadlock when - * the handler tries to do SDIO. So there are four choices: - * - * 1) Break the call chain by calling the callback from a workqueue. - * Ugh. - * 2) Make process_request aware that we already have the lock. - * 3) Drop the lock. Which is ugly but should be safe as long as we're - * making sure the device doesn't go away. - * 4) Change the AR6k driver such that it only issues asynchronous - * quests when called from an interrupt. - * - * Solution 2) is probably the best for now. Will try it later. - */ - sdio_release_host(func); - ar6000_do_irq(func); - sdio_claim_host(func); - in_interrupt = 0; -} - - -void HIFAckInterrupt(HIF_DEVICE *hif) -{ - struct device *dev = HIFGetOSDevice(hif); - - dev_dbg(dev, "HIFAckInterrupt\n"); - /* do nothing */ -} - - -void HIFUnMaskInterrupt(HIF_DEVICE *hif) -{ - struct device *dev = HIFGetOSDevice(hif); - - dev_dbg(dev, "HIFUnMaskInterrupt\n"); - do { - masked = 1; - if (pending) { - pending = 0; - ar6000_do_irq(hif->func); - /* We may take an interrupt before unmasking and thus - get it pending. In this case, we just loop back. */ - } - masked = 0; - } - while (pending); -} - - -void HIFMaskInterrupt(HIF_DEVICE *hif) -{ - struct device *dev = HIFGetOSDevice(hif); - - dev_dbg(dev, "HIFMaskInterrupt\n"); - /* - * Since sdio_ar6000_irq can also be called from a process context, we - * may conceivably end up racing with it. Thus, we need to wait until - * we can be sure that no concurrent interrupt processing is going on - * before we return. - * - * Note: this may be a bit on the paranoid side - the callers may - * actually be nice enough to disable scheduling. Check later. - */ - masked = 1; - while (in_interrupt) - yield(); -} - - -/* ----- HIF API glue functions -------------------------------------------- */ - - -struct device *HIFGetOSDevice(HIF_DEVICE *hif) -{ - return &hif->func->dev; -} - - -void HIFSetHandle(void *hif_handle, void *handle) -{ - HIF_DEVICE *hif = (HIF_DEVICE *) hif_handle; - - hif->htc_handle = handle; -} - - -/* ----- Device configuration (HIF side) ----------------------------------- */ - - -A_STATUS HIFConfigureDevice(HIF_DEVICE *hif, - HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen) -{ - struct device *dev = HIFGetOSDevice(hif); - HIF_DEVICE_IRQ_PROCESSING_MODE *ipm_cfg = config; - A_UINT32 *mbs_cfg = config; - int i; - - dev_dbg(dev, "HIFConfigureDevice\n"); - - switch (opcode) { - case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: - for (i = 0; i != MBOXES; i++) - mbs_cfg[i] = HIF_MBOX_BLOCK_SIZE; - break; - case HIF_DEVICE_GET_MBOX_ADDR: - for (i = 0; i != MBOXES; i++) - mbs_cfg[i] = HIF_MBOX_START_ADDR(i); - break; - case HIF_DEVICE_GET_IRQ_PROC_MODE: - *ipm_cfg = HIF_DEVICE_IRQ_SYNC_ONLY; -// *ipm_cfg = HIF_DEVICE_IRQ_ASYNC_SYNC; - break; - default: - return A_ERROR; - } - return A_OK; -} - - -/* ----- Device probe and removal (Linux side) ----------------------------- */ - - -static int ar6000_do_activate(struct hif_device *hif) -{ - struct sdio_func *func = hif->func; - struct device *dev = &func->dev; - int ret; - - dev_dbg(dev, "ar6000_do_activate\n"); - - sdio_claim_host(func); - sdio_enable_func(func); - - INIT_LIST_HEAD(&hif->queue); - init_waitqueue_head(&hif->wait); - spin_lock_init(&hif->queue_lock); - - ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE); - if (ret < 0) { - dev_err(dev, "sdio_set_block_size returns %d\n", ret); - goto out_enabled; - } - ret = sdio_claim_irq(func, sdio_ar6000_irq); - if (ret) { - dev_err(dev, "sdio_claim_irq returns %d\n", ret); - goto out_enabled; - } - /* Set SDIO_BUS_CD_DISABLE in SDIO_CCCR_IF ? */ -#if 0 - sdio_f0_writeb(func, SDIO_CCCR_CAP_E4MI, SDIO_CCCR_CAPS, &ret); - if (ret) { - dev_err(dev, "sdio_f0_writeb(SDIO_CCCR_CAPS) returns %d\n", - ret); - goto out_got_irq; - } -#else - if (0) /* avoid warning */ - goto out_got_irq; -#endif - - sdio_release_host(func); - - hif->io_task = kthread_run(io, hif, "ar6000_io"); - ret = IS_ERR(hif->io_task); - if (ret) { - dev_err(dev, "kthread_run(ar6000_io): %d\n", ret); - goto out_func_ready; - } - - ret = htcCallbacks.deviceInsertedHandler(hif); - if (ret == A_OK) - return 0; - - dev_err(dev, "deviceInsertedHandler: %d\n", ret); - - ret = kthread_stop(hif->io_task); - if (ret) - dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret); - -out_func_ready: - sdio_claim_host(func); - -out_got_irq: - sdio_release_irq(func); - -out_enabled: - sdio_disable_func(func); - sdio_release_host(func); - - return ret; -} - - -static void ar6000_do_deactivate(struct hif_device *hif) -{ - struct sdio_func *func = hif->func; - struct device *dev = &func->dev; - int ret; - - dev_dbg(dev, "ar6000_do_deactivate\n"); - if (!hif->active) - return; - - if (mutex_trylock(&shutdown_lock)) { - /* - * Funny, Atheros' HIF does this call, but this just puts us in - * a recursion through HTCShutDown/HIFShutDown if unloading the - * module. - * - * However, we need it for suspend/resume. See the comment at - * HIFShutDown, below. - */ - ret = htcCallbacks.deviceRemovedHandler(hif->htc_handle, A_OK); - if (ret != A_OK) - dev_err(dev, "deviceRemovedHandler: %d\n", ret); - mutex_unlock(&shutdown_lock); - } - wait_queue_empty(hif); - ret = kthread_stop(hif->io_task); - if (ret) - dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret); - sdio_claim_host(func); - sdio_release_irq(func); - sdio_disable_func(func); - sdio_release_host(func); -} - - -static int ar6000_activate(struct hif_device *hif) -{ - int ret = 0; - - dev_dbg(&hif->func->dev, "ar6000_activate\n"); - mutex_lock(&hif->activate_lock); - if (!hif->active) { - ret = ar6000_do_activate(hif); - if (ret) { - printk(KERN_ERR "%s: Failed to activate %d\n", - __func__, ret); - goto out; - } - hif->active = 1; - } -out: - mutex_unlock(&hif->activate_lock); - return ret; -} - - -static void ar6000_deactivate(struct hif_device *hif) -{ - dev_dbg(&hif->func->dev, "ar6000_deactivate\n"); - mutex_lock(&hif->activate_lock); - if (hif->active) { - ar6000_do_deactivate(hif); - hif->active = 0; - } - mutex_unlock(&hif->activate_lock); -} - - -static int ar6000_rfkill_cb(void *data, int on) -{ - struct hif_device *hif = data; - struct sdio_func *func = hif->func; - struct device *dev = &func->dev; - - dev_dbg(dev, "ar6000_rfkill_cb: on %d\n", on); - if (on) - return ar6000_activate(hif); - ar6000_deactivate(hif); - return 0; -} - - -static int sdio_ar6000_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - struct device *dev = &func->dev; - struct hif_device *hif; - int ret = 0; - - dev_dbg(dev, "sdio_ar6000_probe\n"); - BUG_ON(!htcCallbacks.deviceInsertedHandler); - - hif = kzalloc(sizeof(*hif), GFP_KERNEL); - if (!hif) - return -ENOMEM; - - sdio_set_drvdata(func, hif); - hif->func = func; - mutex_init(&hif->activate_lock); - hif->active = 0; - - if (gta02_wlan_query_rfkill_lock()) - ret = ar6000_activate(hif); - if (!ret) { - gta02_wlan_set_rfkill_cb(ar6000_rfkill_cb, hif); - return 0; - } - gta02_wlan_query_rfkill_unlock(); - sdio_set_drvdata(func, NULL); - kfree(hif); - return ret; -} - - -static void sdio_ar6000_remove(struct sdio_func *func) -{ - struct device *dev = &func->dev; - HIF_DEVICE *hif = sdio_get_drvdata(func); - - dev_dbg(dev, "sdio_ar6000_remove\n"); - gta02_wlan_clear_rfkill_cb(); - ar6000_deactivate(hif); - sdio_set_drvdata(func, NULL); - kfree(hif); -} - - -/* ----- Device registration/unregistration (called by HIF) ---------------- */ - - -#define ATHEROS_SDIO_DEVICE(id, offset) \ - SDIO_DEVICE(SDIO_VENDOR_ID_ATHEROS, SDIO_DEVICE_ID_ATHEROS_##id | (offset)) - -static const struct sdio_device_id sdio_ar6000_ids[] = { - { ATHEROS_SDIO_DEVICE(AR6002, 0) }, - { ATHEROS_SDIO_DEVICE(AR6002, 0x1) }, - { ATHEROS_SDIO_DEVICE(AR6001, 0x8) }, - { ATHEROS_SDIO_DEVICE(AR6001, 0x9) }, - { ATHEROS_SDIO_DEVICE(AR6001, 0xa) }, - { ATHEROS_SDIO_DEVICE(AR6001, 0xb) }, - { /* end: all zeroes */ }, -}; - -MODULE_DEVICE_TABLE(sdio, sdio_ar6000_ids); - - -static struct sdio_driver sdio_ar6000_driver = { - .probe = sdio_ar6000_probe, - .remove = sdio_ar6000_remove, - .name = "sdio_ar6000", - .id_table = sdio_ar6000_ids, -}; - - -int HIFInit(HTC_CALLBACKS *callbacks) -{ - int ret; - - BUG_ON(!callbacks); - - printk(KERN_DEBUG "HIFInit\n"); - htcCallbacks = *callbacks; - - ret = sdio_register_driver(&sdio_ar6000_driver); - if (ret) { - printk(KERN_ERR - "sdio_register_driver(sdio_ar6000_driver): %d\n", ret); - return A_ERROR; - } - - return 0; -} - - -/* - * We have four possible call chains here: - * - * System shutdown/reboot: - * - * kernel_restart_prepare ...> device_shutdown ... > s3cmci_shutdown -> - * mmc_remove_host ..> sdio_bus_remove -> sdio_ar6000_remove -> - * ar6000_deactivate -> ar6000_do_deactivate -> - * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice - * - * This is roughly the same sequence as suspend, described below. - * - * Module removal: - * - * sys_delete_module -> ar6000_cleanup_module -> HTCShutDown -> - * HIFShutDownDevice -> sdio_unregister_driver ...> sdio_bus_remove -> - * sdio_ar6000_remove -> ar6000_deactivate -> ar6000_do_deactivate - * - * In this case, HIFShutDownDevice must call sdio_unregister_driver to - * notify the driver about its removal. ar6000_do_deactivate must not call - * deviceRemovedHandler, because that would loop back into HIFShutDownDevice. - * - * Suspend: - * - * device_suspend ...> s3cmci_suspend ...> sdio_bus_remove -> - * sdio_ar6000_remove -> ar6000_deactivate -> ar6000_do_deactivate -> - * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice - * - * We must call deviceRemovedHandler to inform the ar6k stack that the device - * has been removed. Since HTCTargetRemovedHandler calls back into - * HIFShutDownDevice, we must also prevent the call to - * sdio_unregister_driver, or we'd end up recursing into the SDIO stack, - * eventually deadlocking somewhere. - * - * rfkill: - * - * rfkill_state_store -> rfkill_toggle_radio -> gta02_wlan_toggle_radio -> - * ar6000_rfkill_cb -> ar6000_deactivate -> ar6000_do_deactivate -> - * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice - * - * This is similar to suspend - only the entry point changes. - */ - -void HIFShutDownDevice(HIF_DEVICE *hif) -{ - /* Beware, HTCShutDown calls us with hif == NULL ! */ - if (mutex_trylock(&shutdown_lock)) { - sdio_unregister_driver(&sdio_ar6000_driver); - mutex_unlock(&shutdown_lock); - } -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif_internal.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif_internal.h deleted file mode 100644 index d8fc101323..0000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif_internal.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * @file: hif_internal.h - * - * @abstract: internal header file for hif layer - * - * @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 <linux/sdio/ctsystem.h> -#include <linux/sdio/sdio_busdriver.h> -#include <linux/sdio/_sdio_defs.h> -#include <linux/sdio/sdio_lib.h> -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "a_osapi.h" -#include "hif.h" - -#define MANUFACTURER_ID_AR6001_BASE 0x100 -#define MANUFACTURER_ID_AR6002_BASE 0x200 -#define FUNCTION_CLASS 0x0 -#define MANUFACTURER_CODE 0x271 - -#define BUS_REQUEST_MAX_NUM 64 - -#define SDIO_CLOCK_FREQUENCY_DEFAULT 25000000 -#define SDWLAN_ENABLE_DISABLE_TIMEOUT 20 -#define FLAGS_CARD_ENAB 0x02 -#define FLAGS_CARD_IRQ_UNMSK 0x04 - -#define HIF_MBOX_BLOCK_SIZE 128 -#define HIF_MBOX_BASE_ADDR 0x800 -#define HIF_MBOX_WIDTH 0x800 -#define HIF_MBOX0_BLOCK_SIZE 1 -#define HIF_MBOX1_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE -#define HIF_MBOX2_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE -#define HIF_MBOX3_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE - -#define HIF_MBOX_START_ADDR(mbox) \ - HIF_MBOX_BASE_ADDR + mbox * HIF_MBOX_WIDTH - -#define HIF_MBOX_END_ADDR(mbox) \ - HIF_MBOX_START_ADDR(mbox) + HIF_MBOX_WIDTH - 1 - -struct hif_device { - SDDEVICE *handle; - void *htc_handle; - OSKERNEL_HELPER insert_helper; - BOOL helper_started; -}; - -typedef struct target_function_context { - SDFUNCTION function; /* function description of the bus driver */ - OS_SEMAPHORE instanceSem; /* instance lock. Unused */ - SDLIST instanceList; /* list of instances. Unused */ -} TARGET_FUNCTION_CONTEXT; - -typedef struct bus_request { - struct bus_request *next; - SDREQUEST *request; - void *context; -} BUS_REQUEST; - -BOOL -hifDeviceInserted(SDFUNCTION *function, SDDEVICE *device); - -void -hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *device); - -SDREQUEST * -hifAllocateDeviceRequest(SDDEVICE *device); - -void -hifFreeDeviceRequest(SDREQUEST *request); - -void -hifRWCompletionHandler(SDREQUEST *request); - -void -hifIRQHandler(void *context); - -HIF_DEVICE * -addHifDevice(SDDEVICE *handle); - -HIF_DEVICE * -getHifDevice(SDDEVICE *handle); - -void -delHifDevice(SDDEVICE *handle); |