ETxnStatus sdioAdapt_TransactBytes (unsigned int uFuncId, unsigned int uHwAddr, void * pHostAddr, unsigned int uLength, unsigned int bDirection, unsigned int bMore) { int iStatus; /* Call read or write bytes Sync method */ if (bDirection) { iStatus = sdioDrv_ReadDirectBytes(uFuncId, uHwAddr, pHostAddr, uLength, bMore); } else { iStatus = sdioDrv_WriteDirectBytes(uFuncId, uHwAddr, pHostAddr, uLength, bMore); } // If failed return ERROR, if succeeded return COMPLETE if (iStatus) { return TXN_STATUS_ERROR; } return TXN_STATUS_COMPLETE; }
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; /* 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) { 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; } /* 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; } 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; } 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; } 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; } /* 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_WriteDirectBytes (TXN_FUNC_ID_CTRL, CCCR_BUS_INTERFACE_CONTOROL, &uByte, 1, 1); if (iStatus) { return iStatus; } iStatus = sdioDrv_ReadDirectBytes (TXN_FUNC_ID_CTRL, CCCR_BUS_INTERFACE_CONTOROL, &uByte, 1, 1); if (iStatus) { return iStatus; } iStatus = sdioDrv_WriteDirectBytes (TXN_FUNC_ID_CTRL, 0xC8, (unsigned char*)&uLong, 2, 1); if (iStatus) { return iStatus; } uCount++; } while ((uByte != SDIO_BITS_CODE) && (uCount < MAX_RETRIES)); uCount = 0; /* allow function 2 */ do { uByte = 4; iStatus = sdioDrv_WriteDirectBytes (TXN_FUNC_ID_CTRL, CCCR_IO_ENABLE, &uByte, 1, 1); if (iStatus) { return iStatus; } iStatus = sdioDrv_ReadDirectBytes (TXN_FUNC_ID_CTRL, CCCR_IO_ENABLE, &uByte, 1, 1); if (iStatus) { return iStatus; } iStatus = sdioDrv_WriteDirectBytes (TXN_FUNC_ID_CTRL, 0xC8, (unsigned char*)&uLong, 2, 1); if (iStatus) { return iStatus; } uCount++; } while ((uByte != 4) && (uCount < MAX_RETRIES)); #ifdef SDIO_IN_BAND_INTERRUPT uCount = 0; do { uByte = 3; iStatus = sdioDrv_WriteDirectBytes (TXN_FUNC_ID_CTRL, CCCR_INT_ENABLE, &uByte, 1, 1); if (iStatus) { return iStatus; } iStatus = sdioDrv_ReadDirectBytes (TXN_FUNC_ID_CTRL, CCCR_INT_ENABLE, &uByte, 1, 1); if (iStatus) { return iStatus; } iStatus = sdioDrv_WriteDirectBytes (TXN_FUNC_ID_CTRL, 0xC8, &uLong, 2, 1); if (iStatus) { return iStatus; } uCount++; } while ((uByte != 3) && (uCount < MAX_RETRIES)); #endif uCount = 0; /* set block size for SDIO block mode */ do { uLong = uBlkSize; iStatus = sdioDrv_WriteDirectBytes (TXN_FUNC_ID_CTRL, FN0_FBR2_REG_108, (unsigned char*)&uLong, 2, 1); if (iStatus) { return iStatus; } iStatus = sdioDrv_ReadDirectBytes (TXN_FUNC_ID_CTRL, FN0_FBR2_REG_108, (unsigned char*)&uLong, 2, 1); if (iStatus) { return iStatus; } iStatus = sdioDrv_WriteDirectBytes (TXN_FUNC_ID_CTRL, 0xC8, (unsigned char*)&uLong, 2, 1); if (iStatus) { return iStatus; } 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; } return iStatus; }