diff options
author | Dmitry Shmidt <dimitrysh@google.com> | 2010-02-01 12:29:11 -0800 |
---|---|---|
committer | Dmitry Shmidt <dimitrysh@google.com> | 2010-02-01 12:29:11 -0800 |
commit | fd6c1aaf237f7bcbbd70a4f68021903c4c005b00 (patch) | |
tree | 39dc5bd89af811e56f1f5a5fc1e1ab7b1c684c1d | |
parent | 358ae72d314bf9df7050908541f30b78a2871c8a (diff) | |
download | wlan-fd6c1aaf237f7bcbbd70a4f68021903c4c005b00.tar.gz |
wl1271: Fix clock disabling in case of bus failure
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
-rw-r--r-- | wl1271/platforms/hw/linux/SdioAdapter.c | 359 |
1 files changed, 182 insertions, 177 deletions
diff --git a/wl1271/platforms/hw/linux/SdioAdapter.c b/wl1271/platforms/hw/linux/SdioAdapter.c index 96f1294..6abed57 100644 --- a/wl1271/platforms/hw/linux/SdioAdapter.c +++ b/wl1271/platforms/hw/linux/SdioAdapter.c @@ -298,50 +298,56 @@ int sdioAdapt_ConnectBus (void * fCbFunc, unsigned int uBlkSize = 1 << uBlkSizeShift; int iStatus; - if (uBlkSize < SYNC_ASYNC_LENGTH_THRESH) + 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_ATOMIC | GFP_DMA); - if (pDmaBufAddr == 0) { return -1; } - } - *pRxDmaBufAddr = *pTxDmaBufAddr = pDmaBufAddr; - *pRxDmaBufLen = *pTxDmaBufLen = MAX_BUS_TXN_SIZE; - - /* Init SDIO driver and HW */ - iStatus = sdioDrv_ConnectBus (fCbFunc, hCbArg, uBlkSizeShift, uSdioThreadPriority); - if (iStatus) { return iStatus; } - + /* 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_ATOMIC | 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); - return 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); - return 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); - return 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); - return iStatus; - } + printk("%s %d command number: %d failed\n", __FUNCTION__, __LINE__, SD_IO_SELECT_CARD); + goto fail; + } /* NOTE: * ===== @@ -353,95 +359,94 @@ int sdioAdapt_ConnectBus (void * fCbFunc, * 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) { return iStatus; } + /* 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) { return iStatus; } + 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) { return iStatus; } + iStatus = sdioDrv_WriteSync (TXN_FUNC_ID_CTRL, 0xC8, &uLong, 2, 1, 1); + if (iStatus) { goto fail; } - uCount++; + uCount++; - } while ((uByte != SDIO_BITS_CODE) && (uCount < MAX_RETRIES)); + } while ((uByte != SDIO_BITS_CODE) && (uCount < MAX_RETRIES)); + uCount = 0; - uCount = 0; - - /* allow function 2 */ - do - { - uByte = 4; - iStatus = sdioDrv_WriteSyncBytes (TXN_FUNC_ID_CTRL, CCCR_IO_ENABLE, &uByte, 1, 1); - if (iStatus) { return iStatus; } + /* 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) { return iStatus; } + 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) { return iStatus; } + iStatus = sdioDrv_WriteSync (TXN_FUNC_ID_CTRL, 0xC8, &uLong, 2, 1, 1); + if (iStatus) { goto fail; } - uCount++; + uCount++; - } while ((uByte != 4) && (uCount < MAX_RETRIES)); + } while ((uByte != 4) && (uCount < MAX_RETRIES)); #ifdef SDIO_IN_BAND_INTERRUPT - uCount = 0; + uCount = 0; - do - { - uByte = 3; - iStatus = sdioDrv_WriteSyncBytes (TXN_FUNC_ID_CTRL, CCCR_INT_ENABLE, &uByte, 1, 1); - if (iStatus) { return iStatus; } + 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) { return iStatus; } - - iStatus = sdioDrv_WriteSync (TXN_FUNC_ID_CTRL, 0xC8, &uLong, 2, 1, 1); - if (iStatus) { return iStatus; } + 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++; + uCount++; - } while ((uByte != 3) && (uCount < MAX_RETRIES)); + } 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) { return iStatus; } - - iStatus = sdioDrv_ReadSync (TXN_FUNC_ID_CTRL, FN0_FBR2_REG_108, &uLong, 2, 1, 1); - if (iStatus) { return iStatus; } - - iStatus = sdioDrv_WriteSync (TXN_FUNC_ID_CTRL, 0xC8, &uLong, 2, 1, 1); - if (iStatus) { return iStatus; } + 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; } - uCount++; + iStatus = sdioDrv_WriteSync (TXN_FUNC_ID_CTRL, 0xC8, &uLong, 2, 1, 1); + if (iStatus) { goto fail; } - } while (((uLong & FN0_FBR2_REG_108_BIT_MASK) != uBlkSize) && (uCount < MAX_RETRIES)); + 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 */ - return (int)uCount; - } + if (uCount >= MAX_RETRIES) + { + /* Failed to write CMD52_WRITE to function 0 */ + iStatus = (int)uCount; + } - /* Disable the clocks for now */ - sdioDrv_clk_disable(); +fail: + /* Disable the clocks for now */ + sdioDrv_clk_disable(); return iStatus; } @@ -449,13 +454,13 @@ int sdioAdapt_ConnectBus (void * fCbFunc, int sdioAdapt_DisconnectBus (void) { - if (pDmaBufAddr) - { - kfree (pDmaBufAddr); - pDmaBufAddr = 0; - } + if (pDmaBufAddr) + { + kfree (pDmaBufAddr); + pDmaBufAddr = 0; + } - return sdioDrv_DisconnectBus (); + return sdioDrv_DisconnectBus (); } ETxnStatus sdioAdapt_Transact (unsigned int uFuncId, @@ -467,57 +472,57 @@ ETxnStatus sdioAdapt_Transact (unsigned int uFuncId, 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"); - } + int iStatus; - /* 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 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 PENDING */ - if (iStatus) - { - return TXN_STATUS_ERROR; - } - return TXN_STATUS_PENDING; - } + /* 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, @@ -527,35 +532,35 @@ ETxnStatus sdioAdapt_TransactBytes (unsigned int uFuncId, unsigned int bDirection, unsigned int bMore) { - static unsigned int lastMore = 0; - int iStatus; - - if ((bMore == 1) || (lastMore == bMore)) - { - 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_clk_disable(); - } - lastMore = bMore; - - /* If failed return ERROR, if succeeded return COMPLETE */ - if (iStatus) - { - return TXN_STATUS_ERROR; - } - return TXN_STATUS_COMPLETE; + static unsigned int lastMore = 0; + int iStatus; + + if ((bMore == 1) || (lastMore == bMore)) + { + 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_clk_disable(); + } + lastMore = bMore; + + /* If failed return ERROR, if succeeded return COMPLETE */ + if (iStatus) + { + return TXN_STATUS_ERROR; + } + return TXN_STATUS_COMPLETE; } #endif |