U32 static_Hash_HwPerform64bDigest(U32* pData, U32 nProcessedBytes, U32 control) { /* * Restore the DIGCNT register first */ OUTREG32(&g_pSha1Md5Reg_t->DIGCNT, nProcessedBytes); /* * Then set the register control to start the operation */ OUTREG32(&g_pSha1Md5Reg_t->CTRL, control); if (scxPublicCryptoWaitForReadyBit((VU32 *) &g_pSha1Md5Reg_t->IRQSTAT, DIGEST_IRQSTAT_INPUT_READY_BIT) != PUBLIC_CRYPTO_OPERATION_SUCCESS) { return PUBLIC_CRYPTO_ERR_TIMEOUT; } /* * The pData buffer is a buffer of at least 64 bytes. * For an update operation, we are always processing a 64-bytes buffer. * Only the final operation might process a smaller buffer. * Let's make it simple, and always write all registers. */ OUTREG32(&g_pSha1Md5Reg_t->DIN_0, pData[0]); OUTREG32(&g_pSha1Md5Reg_t->DIN_1, pData[1]); OUTREG32(&g_pSha1Md5Reg_t->DIN_2, pData[2]); OUTREG32(&g_pSha1Md5Reg_t->DIN_3, pData[3]); OUTREG32(&g_pSha1Md5Reg_t->DIN_4, pData[4]); OUTREG32(&g_pSha1Md5Reg_t->DIN_5, pData[5]); OUTREG32(&g_pSha1Md5Reg_t->DIN_6, pData[6]); OUTREG32(&g_pSha1Md5Reg_t->DIN_7, pData[7]); OUTREG32(&g_pSha1Md5Reg_t->DIN_8, pData[8]); OUTREG32(&g_pSha1Md5Reg_t->DIN_9, pData[9]); OUTREG32(&g_pSha1Md5Reg_t->DIN_10, pData[10]); OUTREG32(&g_pSha1Md5Reg_t->DIN_11, pData[11]); OUTREG32(&g_pSha1Md5Reg_t->DIN_12, pData[12]); OUTREG32(&g_pSha1Md5Reg_t->DIN_13, pData[13]); OUTREG32(&g_pSha1Md5Reg_t->DIN_14, pData[14]); OUTREG32(&g_pSha1Md5Reg_t->DIN_15, pData[15]); /* * Wait until the hash operation is finished. */ if (scxPublicCryptoWaitForReadyBit((VU32 *) &g_pSha1Md5Reg_t->IRQSTAT, DIGEST_IRQSTAT_OUTPUT_READY_BIT) != PUBLIC_CRYPTO_OPERATION_SUCCESS) { return PUBLIC_CRYPTO_ERR_TIMEOUT; } return PUBLIC_CRYPTO_OPERATION_SUCCESS; }
U32 PDrvCryptoUpdateDES(PUBLIC_CRYPTO_DES_DES3_CONTEXT * pDesDes3Ctx, U8 * pSrc, U8 * pDest, U32 nbBlocks, U32 dmaUse) { U32 nbr_of_blocks; U8 * pProcessSrc; U8 * pProcessDest; U32 vTemp; pProcessSrc = pSrc; pProcessDest = pDest; if ((dmaUse == PUBLIC_CRYPTO_DMA_USE_POLLING) || (dmaUse == PUBLIC_CRYPTO_DMA_USE_IRQ)) { return PDrvCryptoUpdateDESWithDMA(pDesDes3Ctx, pSrc, pDest, nbBlocks, dmaUse); } for (nbr_of_blocks = 0; nbr_of_blocks < nbBlocks ; nbr_of_blocks++) { /* (2) : We wait for the input ready */ if (scxPublicCryptoWaitForReadyBit((VU32 *) &g_pDESReg_t->DES_CTRL, DES_CTRL_INPUT_READY_BIT) != PUBLIC_CRYPTO_OPERATION_SUCCESS) { return PUBLIC_CRYPTO_ERR_TIMEOUT; } /* (3) : We copy the 8 bytes of data src->reg */ vTemp = (U32) BYTES_TO_LONG(pProcessSrc); OUTREG32(&g_pDESReg_t->DES_DATA_L, vTemp); pProcessSrc += 4; vTemp = (U32) BYTES_TO_LONG(pProcessSrc); OUTREG32(&g_pDESReg_t->DES_DATA_H, vTemp); pProcessSrc += 4; /* (4) : We wait for the output ready */ if (scxPublicCryptoWaitForReadyBit((VU32 *) &g_pDESReg_t->DES_CTRL, DES_CTRL_OUTPUT_READY_BIT) != PUBLIC_CRYPTO_OPERATION_SUCCESS) { return PUBLIC_CRYPTO_ERR_TIMEOUT; } /* (5) : We copy the 8 bytes of data reg->dest */ vTemp = INREG32(&g_pDESReg_t->DES_DATA_L); LONG_TO_BYTE(pProcessDest, vTemp); pProcessDest += 4; vTemp = INREG32(&g_pDESReg_t->DES_DATA_H); LONG_TO_BYTE(pProcessDest, vTemp); pProcessDest += 4; } return PUBLIC_CRYPTO_OPERATION_SUCCESS; }
U32 static_Hash_HwPerformDmaDigest(U32* pData, U32 nProcessedBytes, U32 control, U32 dmaUse) { U32 bufIn_phys = virt_to_phys(pData); U32 dma_ch0 = OMAP3430_SMC_DMA_CH_0; /* Hard Coded Tx Data */ SCX_DMA_CHANNEL_PARAM ch0_parameters; U32 returnCode = PUBLIC_CRYPTO_OPERATION_SUCCESS; int sizeToProcess; sizeToProcess = (control & 0xFFFFFFE0)>>5; /* Makes sure that if the dma channels that will need to be used are currently active, one can reprogram it (them) */ scxPublicDMADisableChannel(dma_ch0); if (dmaUse == PUBLIC_CRYPTO_DMA_USE_IRQ) { /* Reset DMA int (DMA CTRL) - The DMA int (INT CTRL) is reset by the OS */ scxPublicDMADisableL3IRQ(); scxPublicDMAClearL3IRQ(); } /* DMA1: Mem -> HASH */ ch0_parameters.data_type = DMA_CSDP_Srce_Endian_little | DMA_CSDP_Srce_Endian_Lock_off | DMA_CSDP_Dest_Endian_little | DMA_CSDP_Dest_Endian_Lock_off | DMA_CSDP_Write_Mode_none_posted | DMA_CSDP_Dest_Burst_64B | DMA_CSDP_Dest_packed_off | DMA_CSDP_WR_Add_Trslt | DMA_CSDP_Src_Burst_64B | DMA_CSDP_Src_packed_off | DMA_CSDP_RD_Add_Trslt | DMA_CSDP_Data_32b; ch0_parameters.elem_count = DMA_CEN_Elts_per_Frame_SHA; ch0_parameters.frame_count = sizeToProcess / HASH_BLOCK_BYTES_LENGTH; ch0_parameters.src_amode = 1; /* post increment */ ch0_parameters.src_start = bufIn_phys; ch0_parameters.src_ei = DMA_CSEI_Default; ch0_parameters.src_fi = DMA_CSFI_Default; ch0_parameters.dst_amode = 0; /* const */ ch0_parameters.dst_start = DIGEST1_REGS_HW_ADDR + 0x30; ch0_parameters.dst_ei = DMA_CDEI_Default; ch0_parameters.dst_fi = DMA_CDFI_Default; /* source frame index */ ch0_parameters.trigger = DMA_CCR_Mask_Channel(DMA_CCR_Channel_Mem2SHA); ch0_parameters.sync_mode = 0x2; /* FS =1, BS=0 => An entire frame is transferred once a DMA request is made */ ch0_parameters.src_or_dst_synch = 0; /* Transfert is triggered by the Dest */ dprintk(KERN_INFO "PDrvCryptoUpdateHASHWithDMA: scxPublicDMASetParams(ch0)\n"); scxPublicDMASetParams(dma_ch0, &ch0_parameters); if (nProcessedBytes == 0) { // Reset the digest hw => Because DIGCNT should be reset : it's the only way to do so OUTREG32(&g_pSha1Md5Reg_t->MASK, DIGEST_MASK_SOFTRESET_BIT); if (scxPublicCryptoWaitForReadyBit((VU32 *) &g_pSha1Md5Reg_t->SYSSTATUS, DIGEST_SYSTATUS_RESET_DONE) != PUBLIC_CRYPTO_OPERATION_SUCCESS) { return PUBLIC_CRYPTO_ERR_TIMEOUT; } } dprintk(KERN_INFO "PDrvCryptoUpdateHASHWithDMA: Start DMA channel %d\n", (unsigned int)dma_ch0); /* * Set the register control to start the operation */ OUTREG32(&g_pSha1Md5Reg_t->CTRL, control); /* * Set the DIGCNT register */ OUTREG32(&g_pSha1Md5Reg_t->DIGCNT, nProcessedBytes); if (dmaUse == PUBLIC_CRYPTO_DMA_USE_IRQ) { scxPublicDMAEnableL3IRQ(); } dprintk(KERN_INFO "PDrvCryptoUpdateHASHWithDMA: Start DMA channel %d\n", (unsigned int)dma_ch0); v7_dma_flush_range((int) pData, (int) pData + sizeToProcess); /* Start operation */ /* Triggers operation - Interrupt, Free Running + GO (DMA on) */ OUTREG32(&g_pSha1Md5Reg_t->MASK, INREG32(&g_pSha1Md5Reg_t->MASK)|DIGEST_MASK_DMA_EN_BIT|DIGEST_MASK_IT_EN_BIT); scxPublicDMAStart(dma_ch0, OMAP_DMA_DROP_IRQ|OMAP_DMA_BLOCK_IRQ); if (dmaUse == PUBLIC_CRYPTO_DMA_USE_IRQ) { /* Suspends the process until the DMA IRQ occurs */ dprintk(KERN_INFO "PDrvCryptoUpdateHASHWithDMA: Waiting for IRQ\n"); returnCode = scxPublicDMAWait(); } else { dprintk(KERN_INFO "PDrvCryptoUpdateHASHWithDMA: Polling DMA\n"); returnCode = scxPublicDMAPoll(dma_ch0); } if (returnCode != PUBLIC_CRYPTO_OPERATION_SUCCESS) { dprintk(KERN_ERR "PDrvCryptoUpdateHASHWithDMA: Timeout\n"); /* Do not exit function but clear properly the operation */ } if (dmaUse == PUBLIC_CRYPTO_DMA_USE_IRQ) { /* Acknoledge DMA interrupt */ scxPublicDMADisableL3IRQ(); } scxPublicDMAClearChannel(dma_ch0); /* The dma transfert is finished, now wait until the hash operation is finished. */ if (scxPublicCryptoWaitForReadyBit((VU32 *) &g_pSha1Md5Reg_t->IRQSTAT, DIGEST_IRQSTAT_OUTPUT_READY_BIT) != PUBLIC_CRYPTO_OPERATION_SUCCESS) { return PUBLIC_CRYPTO_ERR_TIMEOUT; } /* Stop clocks */ OUTREG32(&g_pSha1Md5Reg_t->MASK, INREG32(&g_pSha1Md5Reg_t->MASK)&(~DIGEST_MASK_DMA_EN_BIT)&(~DIGEST_MASK_IT_EN_BIT)); /* Clear the interrupt */ OUTREG32(&g_pSha1Md5Reg_t->CTRL, INREG32(&g_pSha1Md5Reg_t->CTRL)&0x0000001F);/* clear length field */ return PUBLIC_CRYPTO_OPERATION_SUCCESS; }