diff options
Diffstat (limited to 'wl1271/platforms/hw/linux/SdioAdapter.c')
-rw-r--r-- | wl1271/platforms/hw/linux/SdioAdapter.c | 567 |
1 files changed, 0 insertions, 567 deletions
diff --git a/wl1271/platforms/hw/linux/SdioAdapter.c b/wl1271/platforms/hw/linux/SdioAdapter.c deleted file mode 100644 index 9b00e79..0000000 --- a/wl1271/platforms/hw/linux/SdioAdapter.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * SdioAdapter.c - * - * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. - * Copyright(c) 2008 - 2009 Google, Inc. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Texas Instruments nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** \file SdioAdapter.c - * \brief The SDIO driver adapter. Platform dependent. - * - * An adaptation layer between the lower SDIO driver (in BSP) and the upper Sdio - * Used for issuing all SDIO transaction types towards the lower SDIO-driver. - * Makes the decision whether to use Sync or Async transaction, and reflects it - * by the return value and calling its callback in case of Async. - * - * \see SdioAdapter.h, SdioDrv.c & h - */ - -#ifdef CONFIG_MMC_EMBEDDED_SDIO -#include <linux/kernel.h> -#include <linux/mutex.h> -#include <linux/mmc/core.h> -#include <linux/mmc/card.h> -#include <linux/mmc/sdio_func.h> -#include <linux/mmc/sdio_ids.h> -#include "TxnDefs.h" - -#define TI_SDIO_DEBUG - -#define TIWLAN_MMC_MAX_DMA 8192 - -int wifi_set_carddetect( int on ); - -static struct sdio_func *tiwlan_func = NULL; -static struct completion sdio_wait; - -ETxnStatus sdioAdapt_TransactBytes (unsigned int uFuncId, - unsigned int uHwAddr, - void * pHostAddr, - unsigned int uLength, - unsigned int bDirection, - unsigned int bMore); - -static int sdio_wifi_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - int rc; - - printk("%s: %d\n", __FUNCTION__, func->class); - - if (func->class != SDIO_CLASS_WLAN) - return -EINVAL; - - sdio_claim_host(func); - - rc = sdio_enable_func(func); - if (rc) - goto err1; - rc = sdio_set_block_size(func, 512); - - if (rc) { - printk("%s: Unable to set blocksize\n", __FUNCTION__); - goto err2; - } - - tiwlan_func = func; - complete(&sdio_wait); - return 0; -err2: - sdio_disable_func(func); -err1: - sdio_release_host(func); - complete(&sdio_wait); - return rc; -} - -static void sdio_wifi_remove(struct sdio_func *func) -{ -} - -static const struct sdio_device_id sdio_wifi_ids[] = { - { SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN) }, - { }, -}; - -MODULE_DEVICE_TABLE(sdio, sdio_wifi_ids); - -static struct sdio_driver sdio_wifi_driver = { - .probe = sdio_wifi_probe, - .remove = sdio_wifi_remove, - .name = "sdio_wifi", - .id_table = sdio_wifi_ids, -}; - -ETxnStatus sdioAdapt_TransactBytes (unsigned int uFuncId, - unsigned int uHwAddr, - void * pHostAddr, - unsigned int uLength, - unsigned int bDirection, - unsigned int bMore); - -int sdioAdapt_ConnectBus (void * fCbFunc, - void * hCbArg, - unsigned int uBlkSizeShift, - unsigned int uSdioThreadPriority, - unsigned char **pTxDmaSrcAddr) -{ - int rc; - - init_completion(&sdio_wait); - wifi_set_carddetect( 1 ); - rc = sdio_register_driver(&sdio_wifi_driver); - if (rc < 0) { - printk(KERN_ERR "%s: Fail to register sdio_wifi_driver\n", __func__); - return rc; - } - if (!wait_for_completion_timeout(&sdio_wait, msecs_to_jiffies(10000))) { - printk(KERN_ERR "%s: Timed out waiting for device detect\n", __func__); - sdio_unregister_driver(&sdio_wifi_driver); - return -ENODEV; - } - /* Provide the DMA buffer address to the upper layer so it will use it as the transactions host buffer. */ - if (pTxDmaSrcAddr) { /* Dm: check what to do with it */ - *pTxDmaSrcAddr = kmalloc(TIWLAN_MMC_MAX_DMA, GFP_KERNEL | GFP_DMA); - } - return 0; -} - -int sdioAdapt_DisconnectBus (void) -{ - if (tiwlan_func) { - sdio_disable_func( tiwlan_func ); - sdio_release_host( tiwlan_func ); - } - wifi_set_carddetect( 0 ); - sdio_unregister_driver(&sdio_wifi_driver); - return 0; -} - -ETxnStatus sdioAdapt_TransactBytes (unsigned int uFuncId, - unsigned int uHwAddr, - void * pHostAddr, - unsigned int uLength, - unsigned int bDirection, - unsigned int bMore) -{ - unsigned char *pData = pHostAddr; - unsigned int i; - int rc = 0, final_rc = 0; - - for (i = 0; i < uLength; i++) { - if( bDirection ) { - if (uFuncId == 0) - *pData = (unsigned char)sdio_f0_readb(tiwlan_func, uHwAddr, &rc); - else - *pData = (unsigned char)sdio_readb(tiwlan_func, uHwAddr, &rc); - } - else { - if (uFuncId == 0) - sdio_f0_writeb(tiwlan_func, *pData, uHwAddr, &rc); - else - sdio_writeb(tiwlan_func, *pData, uHwAddr, &rc); - } - if( rc ) { - final_rc = rc; - } -#ifdef TI_SDIO_DEBUG - printk(KERN_INFO "%c52: [0x%x](%u) %c 0x%x\n", (bDirection ? 'R' : 'W'), uHwAddr, uLength, (bDirection ? '=' : '<'), (unsigned)*pData); -#endif - uHwAddr++; - pData++; - } - /* If failed return ERROR, if succeeded return COMPLETE */ - if (final_rc) { - return TXN_STATUS_ERROR; - } - return TXN_STATUS_COMPLETE; -} - -ETxnStatus sdioAdapt_Transact (unsigned int uFuncId, - unsigned int uHwAddr, - void * pHostAddr, - unsigned int uLength, - unsigned int bDirection, - unsigned int bBlkMode, - unsigned int bFixedAddr, - unsigned int bMore) -{ - int rc; - - if (uFuncId == 0) - return sdioAdapt_TransactBytes (uFuncId, uHwAddr, pHostAddr, - uLength, bDirection, bMore); - if (bDirection) { - if (bFixedAddr) - rc = sdio_memcpy_fromio(tiwlan_func, pHostAddr, uHwAddr, uLength); - else - rc = sdio_readsb(tiwlan_func, pHostAddr, uHwAddr, uLength); - - } - else { - if (bFixedAddr) - rc = sdio_memcpy_toio(tiwlan_func, uHwAddr, pHostAddr, uLength); - else - rc = sdio_writesb(tiwlan_func, uHwAddr, pHostAddr, uLength); - } -#ifdef TI_SDIO_DEBUG - if (uLength == 1) - printk(KERN_INFO "%c53: [0x%x](%u) %c 0x%x\n", (bDirection ? 'R' : 'W'), uHwAddr, uLength, (bDirection ? '=' : '<'), (unsigned)(*(char *)pHostAddr)); - else if (uLength == 2) - printk(KERN_INFO "%c53: [0x%x](%u) %c 0x%x\n", (bDirection ? 'R' : 'W'), uHwAddr, uLength, (bDirection ? '=' : '<'), (unsigned)(*(short *)pHostAddr)); - else if (uLength == 4) - printk(KERN_INFO "%c53: [0x%x](%u) %c 0x%x\n", (bDirection ? 'R' : 'W'), uHwAddr, uLength, (bDirection ? '=' : '<'), (unsigned)(*(long *)pHostAddr)); - else - printk(KERN_INFO "%c53: [0x%x](%u) F[%d] B[%d] I[%d] = %d\n", (bDirection ? 'R' : 'W'), uHwAddr, uLength, uFuncId, bBlkMode, bFixedAddr, rc); -#endif - /* If failed return ERROR, if succeeded return COMPLETE */ - if (rc) { - return TXN_STATUS_ERROR; - } - return TXN_STATUS_COMPLETE; -} - -#else - -#include "SdioDrvDbg.h" -#include "TxnDefs.h" -#include "SdioAdapter.h" -#include "SdioDrv.h" -#include "bmtrace_api.h" -#include <linux/slab.h> - -#ifdef SDIO_1_BIT /* see also in SdioDrv.c */ -#define SDIO_BITS_CODE 0x80 /* 1 bits */ -#else -#define SDIO_BITS_CODE 0x82 /* 4 bits */ -#endif - -static unsigned char *pDmaBufAddr = 0; - -/************************************************************************ - * Defines - ************************************************************************/ -/* Sync/Async Threshold */ -#ifdef FULL_ASYNC_MODE -#define SYNC_ASYNC_LENGTH_THRESH 0 /* Use Async for all transactions */ -#else -#define SYNC_ASYNC_LENGTH_THRESH 360 /* Use Async for transactions longer than this threshold (in bytes) */ -#endif - -#define MAX_RETRIES 10 - -#define MAX_BUS_TXN_SIZE 8192 /* Max bus transaction size in bytes (for the DMA buffer allocation) */ - -/* For block mode configuration */ -#define FN0_FBR2_REG_108 0x210 -#define FN0_FBR2_REG_108_BIT_MASK 0xFFF - -int sdioAdapt_ConnectBus (void * fCbFunc, - void * hCbArg, - unsigned int uBlkSizeShift, - unsigned int uSdioThreadPriority, - unsigned char **pRxDmaBufAddr, - unsigned int *pRxDmaBufLen, - unsigned char **pTxDmaBufAddr, - unsigned int *pTxDmaBufLen) -{ - unsigned char uByte; - unsigned long uLong; - unsigned long uCount = 0; - unsigned int uBlkSize = 1 << uBlkSizeShift; - int iStatus; - - if (uBlkSize < SYNC_ASYNC_LENGTH_THRESH) - { - PERR1("%s(): Block-Size should be bigger than SYNC_ASYNC_LENGTH_THRESH!!\n", __FUNCTION__ ); - } - - /* Enabling clocks if thet are not enabled */ - sdioDrv_clk_enable(); - - /* Allocate a DMA-able buffer and provide it to the upper layer to be used for all read and write transactions */ - if (pDmaBufAddr == 0) /* allocate only once (in case this function is called multiple times) */ - { - pDmaBufAddr = kmalloc(MAX_BUS_TXN_SIZE, GFP_KERNEL | GFP_DMA); - if (pDmaBufAddr == 0) - { - iStatus = -1; - goto fail; - } - } - *pRxDmaBufAddr = *pTxDmaBufAddr = pDmaBufAddr; - *pRxDmaBufLen = *pTxDmaBufLen = MAX_BUS_TXN_SIZE; - - /* Init SDIO driver and HW */ - iStatus = sdioDrv_ConnectBus (fCbFunc, hCbArg, uBlkSizeShift, uSdioThreadPriority); - if (iStatus) { goto fail; } - - /* Send commands sequence: 0, 5, 3, 7 */ - iStatus = sdioDrv_ExecuteCmd (SD_IO_GO_IDLE_STATE, 0, MMC_RSP_NONE, &uByte, sizeof(uByte)); - if (iStatus) - { - printk("%s %d command number: %d failed\n", __FUNCTION__, __LINE__, SD_IO_GO_IDLE_STATE); - goto fail; - } - - iStatus = sdioDrv_ExecuteCmd (SDIO_CMD5, VDD_VOLTAGE_WINDOW, MMC_RSP_R4, &uByte, sizeof(uByte)); - if (iStatus) { - printk("%s %d command number: %d failed\n", __FUNCTION__, __LINE__, SDIO_CMD5); - goto fail; - } - - iStatus = sdioDrv_ExecuteCmd (SD_IO_SEND_RELATIVE_ADDR, 0, MMC_RSP_R6, &uLong, sizeof(uLong)); - if (iStatus) { - printk("%s %d command number: %d failed\n", __FUNCTION__, __LINE__, SD_IO_SEND_RELATIVE_ADDR); - goto fail; - } - - iStatus = sdioDrv_ExecuteCmd (SD_IO_SELECT_CARD, uLong, MMC_RSP_R6, &uByte, sizeof(uByte)); - if (iStatus) { - printk("%s %d command number: %d failed\n", __FUNCTION__, __LINE__, SD_IO_SELECT_CARD); - goto fail; - } - - /* NOTE: - * ===== - * Each of the following loops is a workaround for a HW bug that will be solved in PG1.1 !! - * Each write of CMD-52 to function-0 should use it as follows: - * 1) Write the desired byte using CMD-52 - * 2) Read back the byte using CMD-52 - * 3) Write two dummy bytes to address 0xC8 using CMD-53 - * 4) If the byte read in step 2 is different than the written byte repeat the sequence - */ - - /* set device side bus width to 4 bit (for 1 bit write 0x80 instead of 0x82) */ - do - { - uByte = SDIO_BITS_CODE; - iStatus = sdioDrv_WriteSyncBytes (TXN_FUNC_ID_CTRL, CCCR_BUS_INTERFACE_CONTOROL, &uByte, 1, 1); - if (iStatus) { goto fail; } - - iStatus = sdioDrv_ReadSyncBytes (TXN_FUNC_ID_CTRL, CCCR_BUS_INTERFACE_CONTOROL, &uByte, 1, 1); - if (iStatus) { goto fail; } - - iStatus = sdioDrv_WriteSync (TXN_FUNC_ID_CTRL, 0xC8, &uLong, 2, 1, 1); - if (iStatus) { goto fail; } - - uCount++; - - } while ((uByte != SDIO_BITS_CODE) && (uCount < MAX_RETRIES)); - - uCount = 0; - - /* allow function 2 */ - do - { - uByte = 4; - iStatus = sdioDrv_WriteSyncBytes (TXN_FUNC_ID_CTRL, CCCR_IO_ENABLE, &uByte, 1, 1); - if (iStatus) { goto fail; } - - iStatus = sdioDrv_ReadSyncBytes (TXN_FUNC_ID_CTRL, CCCR_IO_ENABLE, &uByte, 1, 1); - if (iStatus) { goto fail; } - - iStatus = sdioDrv_WriteSync (TXN_FUNC_ID_CTRL, 0xC8, &uLong, 2, 1, 1); - if (iStatus) { goto fail; } - - uCount++; - - } while ((uByte != 4) && (uCount < MAX_RETRIES)); - - -#ifdef SDIO_IN_BAND_INTERRUPT - - uCount = 0; - - do - { - uByte = 3; - iStatus = sdioDrv_WriteSyncBytes (TXN_FUNC_ID_CTRL, CCCR_INT_ENABLE, &uByte, 1, 1); - if (iStatus) { goto fail; } - - iStatus = sdioDrv_ReadSyncBytes (TXN_FUNC_ID_CTRL, CCCR_INT_ENABLE, &uByte, 1, 1); - if (iStatus) { goto fail; } - - iStatus = sdioDrv_WriteSync (TXN_FUNC_ID_CTRL, 0xC8, &uLong, 2, 1, 1); - if (iStatus) { goto fail; } - - uCount++; - - } while ((uByte != 3) && (uCount < MAX_RETRIES)); - - -#endif - - uCount = 0; - - /* set block size for SDIO block mode */ - do - { - uLong = uBlkSize; - iStatus = sdioDrv_WriteSync (TXN_FUNC_ID_CTRL, FN0_FBR2_REG_108, &uLong, 2, 1, 1); - if (iStatus) { goto fail; } - - iStatus = sdioDrv_ReadSync (TXN_FUNC_ID_CTRL, FN0_FBR2_REG_108, &uLong, 2, 1, 1); - if (iStatus) { goto fail; } - - iStatus = sdioDrv_WriteSync (TXN_FUNC_ID_CTRL, 0xC8, &uLong, 2, 1, 1); - if (iStatus) { goto fail; } - - uCount++; - - } while (((uLong & FN0_FBR2_REG_108_BIT_MASK) != uBlkSize) && (uCount < MAX_RETRIES)); - - if (uCount >= MAX_RETRIES) - { - /* Failed to write CMD52_WRITE to function 0 */ - iStatus = (int)uCount; - } - -fail: - /* Disable the clocks for now */ - sdioDrv_clk_disable(); - - return iStatus; -} - - -int sdioAdapt_DisconnectBus (void) -{ - if (pDmaBufAddr) - { - kfree (pDmaBufAddr); - pDmaBufAddr = 0; - } - - return sdioDrv_DisconnectBus (); -} - -ETxnStatus sdioAdapt_Transact (unsigned int uFuncId, - unsigned int uHwAddr, - void * pHostAddr, - unsigned int uLength, - unsigned int bDirection, - unsigned int bBlkMode, - unsigned int bFixedAddr, - unsigned int bMore) -{ - int iStatus; - - /* If transction length is below threshold, use Sync methods */ - if (uLength < SYNC_ASYNC_LENGTH_THRESH) - { - /* Call read or write Sync method */ - if (bDirection) - { - CL_TRACE_START_L2(); - iStatus = sdioDrv_ReadSync (uFuncId, uHwAddr, pHostAddr, uLength, bFixedAddr, bMore); - CL_TRACE_END_L2("tiwlan_drv.ko", "INHERIT", "SDIO", ".ReadSync"); - } - else - { - CL_TRACE_START_L2(); - iStatus = sdioDrv_WriteSync (uFuncId, uHwAddr, pHostAddr, uLength, bFixedAddr, bMore); - CL_TRACE_END_L2("tiwlan_drv.ko", "INHERIT", "SDIO", ".WriteSync"); - } - - /* If failed return ERROR, if succeeded return COMPLETE */ - if (iStatus) - { - return TXN_STATUS_ERROR; - } - return TXN_STATUS_COMPLETE; - } - - /* If transction length is above threshold, use Async methods */ - else - { - /* Call read or write Async method */ - if (bDirection) - { - CL_TRACE_START_L2(); - iStatus = sdioDrv_ReadAsync (uFuncId, uHwAddr, pHostAddr, uLength, bBlkMode, bFixedAddr, bMore); - CL_TRACE_END_L2("tiwlan_drv.ko", "INHERIT", "SDIO", ".ReadAsync"); - } - else - { - CL_TRACE_START_L2(); - iStatus = sdioDrv_WriteAsync (uFuncId, uHwAddr, pHostAddr, uLength, bBlkMode, bFixedAddr, bMore); - CL_TRACE_END_L2("tiwlan_drv.ko", "INHERIT", "SDIO", ".WriteAsync"); - } - - /* If failed return ERROR, if succeeded return PENDING */ - if (iStatus) - { - return TXN_STATUS_ERROR; - } - return TXN_STATUS_PENDING; - } -} - -ETxnStatus sdioAdapt_TransactBytes (unsigned int uFuncId, - unsigned int uHwAddr, - void * pHostAddr, - unsigned int uLength, - unsigned int bDirection, - unsigned int bMore) -{ - static unsigned int lastMore = 0; - int iStatus; - - if ((bMore == 1) || (lastMore == bMore)) - { - sdioDrv_cancel_inact_timer(); - sdioDrv_clk_enable(); - } - - /* Call read or write bytes Sync method */ - if (bDirection) - { - iStatus = sdioDrv_ReadSyncBytes (uFuncId, uHwAddr, pHostAddr, uLength, bMore); - } - else - { - iStatus = sdioDrv_WriteSyncBytes (uFuncId, uHwAddr, pHostAddr, uLength, bMore); - } - - if (bMore == 0) - { - sdioDrv_start_inact_timer(); - } - lastMore = bMore; - - /* If failed return ERROR, if succeeded return COMPLETE */ - if (iStatus) - { - return TXN_STATUS_ERROR; - } - return TXN_STATUS_COMPLETE; -} -#endif |