nt9856x/rtos/BSP/u-boot/drivers/crypto/nvt/na51103/na51103_crypto.c
2023-03-28 15:07:53 +08:00

589 lines
21 KiB
C
Executable File

/*
* Crypto API.
*
* Support for Novatek NVT Crypto Hardware acceleration.
*
* Copyright (c) 2021 Novatek Inc.
*
*/
#ifdef CONFIG_NVT_CRYPTO
#include <common.h>
#include <asm/io.h>
#include <asm/arch/IOAddress.h>
#include <asm/arch/nvt_crypto.h>
#include <asm/arch/efuse_protected.h>
/*************************************************************************************
* IO Read/Write Definition
*************************************************************************************/
#define IO_REG_RD(_base, _ofs) readl(_base+_ofs)
#define IO_REG_WR(_base, _ofs, _v) writel(_v, (_base+_ofs))
/*************************************************************************************
* Global Definition
*************************************************************************************/
//#define NVT_CRYPTO_DEBUG
#define NVT_CRYPTO_DMA_36BIT_SUPPORT 1
#define PLAT_CACHE_LINE_SIZE CONFIG_SYS_CACHELINE_SIZE
#define PLAT_CACHE_LINE_MASK (CONFIG_SYS_CACHELINE_SIZE-1)
#define DMA_ADDR_LO(x) ((uint32_t)((uint64_t)(x)))
#define DMA_ADDR_HI(x) ((uint32_t)(((uint64_t)(x)) >> 32))
/*************************************************************************************
* Debug Message Print Definition
*************************************************************************************/
#ifdef NVT_CRYPTO_DEBUG
#define crypto_dbg(...) printf("[CRYPTO_DBG]: " __VA_ARGS__)
#else
#define crypto_dbg(...)
#endif
#define crypto_err(...) printf("[CRYPTO_ERR]: " __VA_ARGS__)
#define crypto_inf(...) printf("[CRYPTO_INF]: " __VA_ARGS__)
/*************************************************************************************
* Register read/write Definition
*************************************************************************************/
#define crypto_read(_oft) IO_REG_RD(IOADDR_CRYPTO_REG_BASE, _oft)
#define crypto_write(_oft, _v) IO_REG_WR(IOADDR_CRYPTO_REG_BASE, _oft, _v)
/*************************************************************************************
* Register Definition
*************************************************************************************/
#define NVT_CRYPTO_CFG_REG 0x00 ///< crypto configuration
#define NVT_CRYPTO_CTRL_REG 0x04 ///< crypto control
#define NVT_CRYPTO_INT_ENB_REG 0x08 ///< interrupt enable
#define NVT_CRYPTO_INT_STS_REG 0x0C ///< interrupt status
#define NVT_CRYPTO_KEY0_REG 0x10 ///< key 0 ~ 31 bit
#define NVT_CRYPTO_KEY1_REG 0x14 ///< key 32 ~ 63 bit
#define NVT_CRYPTO_KEY2_REG 0x18 ///< key 64 ~ 95 bit
#define NVT_CRYPTO_KEY3_REG 0x1C ///< key 96 ~ 127 bit
#define NVT_CRYPTO_KEY4_REG 0x20 ///< key 128 ~ 159 bit
#define NVT_CRYPTO_KEY5_REG 0x24 ///< key 160 ~ 191 bit
#define NVT_CRYPTO_KEY6_REG 0x28 ///< key 192 ~ 223 bit
#define NVT_CRYPTO_KEY7_REG 0x2C ///< key 224 ~ 255 bit
#define NVT_CRYPTO_IN0_REG 0x30 ///< input data 0 ~ 31 bit
#define NVT_CRYPTO_IN1_REG 0x34 ///< input data 32 ~ 63 bit
#define NVT_CRYPTO_IN2_REG 0x38 ///< input data 64 ~ 95 bit
#define NVT_CRYPTO_IN3_REG 0x3C ///< input data 96 ~ 127 bit
#define NVT_CRYPTO_OUT0_REG 0x40 ///< output data 0 ~ 31 bit
#define NVT_CRYPTO_OUT1_REG 0x44 ///< output data 32 ~ 63 bit
#define NVT_CRYPTO_OUT2_REG 0x48 ///< output data 64 ~ 95 bit
#define NVT_CRYPTO_OUT3_REG 0x4C ///< output data 96 ~ 127 bit
#define NVT_CRYPTO_DMA0_ADDR_REG 0x50 ///< DMA channel 0 descriptor starting low address, DMA mode only
#define NVT_CRYPTO_DMA1_ADDR_REG 0x54 ///< DMA channel 1 descriptor starting low address, DMA mode only
#define NVT_CRYPTO_DMA2_ADDR_REG 0x58 ///< DMA channel 2 descriptor starting low address, DMA mode only
#define NVT_CRYPTO_DMA3_ADDR_REG 0x5C ///< DMA channel 0 descriptor starting low address, DMA mode only
#define NVT_CRYPTO_KEY_READ_REG 0x60 ///< crypto key readable control
#define NVT_CRYPTO_DMA0_ADDR_H_REG 0x70 ///< DMA channel 0 descriptor starting high address, DMA mode only
#define NVT_CRYPTO_DMA1_ADDR_H_REG 0x74 ///< DMA channel 1 descriptor starting high address, DMA mode only
#define NVT_CRYPTO_DMA2_ADDR_H_REG 0x78 ///< DMA channel 2 descriptor starting high address, DMA mode only
#define NVT_CRYPTO_DMA3_ADDR_H_REG 0x7C ///< DMA channel 3 descriptor starting high address, DMA mode only
/*************************************************************************************
* DMA Descriptor Definition
*************************************************************************************/
#define NVT_CRYPTO_MAX_IV_SIZE 16 ///< 16 Bytes, 128 bits
#define NVT_CRYPTO_MAX_KEY_SIZE 32 ///< 32 Bytes, 256 bits
#define NVT_CRYPTO_MAX_DMA_BLOCK_NUM 8 ///< hardware maximun up to 32
struct nvt_crypto_dma_block {
uint32_t src_addr;
uint32_t dst_addr;
uint32_t length;
uint32_t block_cfg;
} __attribute__((packed, aligned(4)));
struct nvt_crypto_dma_desc {
uint32_t key[NVT_CRYPTO_MAX_KEY_SIZE/sizeof(uint32_t)]; ///< crypto input key value
uint32_t iv[NVT_CRYPTO_MAX_IV_SIZE/sizeof(uint32_t)]; ///< crypto input IV value
uint32_t counter[NVT_CRYPTO_MAX_IV_SIZE/sizeof(uint32_t)]; ///< crypto input counter value in the CTR
uint32_t header_cfg; ///< DMA descriptor header configuration
uint32_t reserved[3]; ///< reserve bytes
uint32_t cv[NVT_CRYPTO_MAX_IV_SIZE/sizeof(uint32_t)]; ///< current IV
uint32_t s0[NVT_CRYPTO_MAX_IV_SIZE/sizeof(uint32_t)]; ///< E(K,Y0) or S0 in the GCM
uint32_t ghash[NVT_CRYPTO_MAX_IV_SIZE/sizeof(uint32_t)]; ///< GHASH output data in the GCM
struct nvt_crypto_dma_block block[NVT_CRYPTO_MAX_DMA_BLOCK_NUM]; ///< DMA process blocks
} __attribute__((packed, aligned(4)));
static struct nvt_crypto_dma_desc g_dma_desc __attribute__((aligned(PLAT_CACHE_LINE_SIZE))); ///< align address to 64 byte for cache line operation
/*************************************************************************************
* Local Definition
*************************************************************************************/
static int nvt_crypto_opened = 0;
static void nvt_crypto_platform_init(void)
{
uint32_t tmp;
/* Crypto clock select, 0:PLL2(400MHz) 1:PLL13(350MHz) */
tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0x24);
tmp &= ~(0x1<<10);
IO_REG_WR(IOADDR_CG_REG_BASE, 0x24, tmp);
/* Crypto master clock enable */
tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0x70);
tmp |= (0x1<<31);
IO_REG_WR(IOADDR_CG_REG_BASE, 0x70, tmp);
/* Crypto program clock enable */
tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0xE0);
tmp |= (0x1<<19);
IO_REG_WR(IOADDR_CG_REG_BASE, 0xE0, tmp);
/* Crypto reset disable */
tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0x94);
tmp |= (0x1<<22);
IO_REG_WR(IOADDR_CG_REG_BASE, 0x94, tmp);
}
static void nvt_crypto_platform_exit(void)
{
uint32_t tmp;
/* Crypto reset enable */
tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0x94);
tmp &= ~(0x1<<22);
IO_REG_WR(IOADDR_CG_REG_BASE, 0x94, tmp);
/* Crypto master clock disable */
tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0x70);
tmp &= ~(0x1<<31);
IO_REG_WR(IOADDR_CG_REG_BASE, 0x70, tmp);
}
static void nvt_crypto_reset(void)
{
uint32_t value = 0;
uint32_t cnt = 0;
/* disable crypto */
crypto_write(NVT_CRYPTO_CFG_REG, 0);
/* set reset, hardware will auto clear */
crypto_write(NVT_CRYPTO_CFG_REG, 0x01);
/* check reset done */
while ((value = crypto_read(NVT_CRYPTO_CFG_REG)) & 0x1) {
if(cnt++ >= 3000000) ///< 3sec
break;
udelay(1);
}
/* clear all status */
crypto_write(NVT_CRYPTO_INT_STS_REG, 0xFF1);
if (value & 0x1) {
crypto_err("crypto hardware reset failed!!\n");
}
}
int nvt_crypto_open(void)
{
if (!nvt_crypto_opened) {
/* platform pmu init for crypto engine */
nvt_crypto_platform_init();
/* crypto engine software reset */
nvt_crypto_reset();
nvt_crypto_opened = 1;
}
return 0;
}
void nvt_crypto_close(void)
{
if (nvt_crypto_opened) {
nvt_crypto_platform_exit();
nvt_crypto_opened = 0;
}
}
int nvt_crypto_pio_aes(struct nvt_crypto_pio_t *p_crypto)
{
int i;
int ret = 0;
uint32_t cnt = 0;
uint32_t reg_value;
uint32_t key[8];
uint32_t iv[4];
uint32_t src[4];
uint32_t dst[4];
if (!nvt_crypto_opened) {
crypto_err("crypto engine not opened!\n");
return -1;
}
/* check parameter */
if (!p_crypto) {
crypto_err("invalid parameter\n");
return -1;
}
/* check opmode */
if (p_crypto->opmode >= NVT_CRYPTO_OPMODE_MAX) {
crypto_err("opmode:%d invalid\n", p_crypto->opmode);
return -1;
}
/* check iv */
if ((p_crypto->opmode != NVT_CRYPTO_OPMODE_ECB) && (!p_crypto->iv || (p_crypto->iv_size < NVT_CRYPTO_AES_BLOCK_SIZE))) {
crypto_err("iv buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_crypto->iv, p_crypto->iv_size);
return -1;
}
/* check source buffer and size */
if (!p_crypto->src || !p_crypto->src_size || (p_crypto->src_size%NVT_CRYPTO_AES_BLOCK_SIZE)) {
crypto_err("source buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_crypto->src, p_crypto->src_size);
return -1;
}
/* check destination buffer and size */
if (!p_crypto->dst || !p_crypto->dst_size || (p_crypto->dst_size < p_crypto->src_size)) {
crypto_err("destination buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_crypto->dst, p_crypto->dst_size);
return -1;
}
/* check key buffer and size */
if (p_crypto->key_src == NVT_CRYPTO_KEY_SRC_EFUSE) {
/* efuse key only support AES128 and key offset must be 0,4,8,12,16 */
if ((p_crypto->key_size != NVT_CRYPTO_AES_128_KEY_SIZE) || (p_crypto->key_ofs%4)) {
crypto_err("key efuse size:%u offset:%d invalid\n", p_crypto->key_size, p_crypto->key_ofs);
return -1;
}
}
else {
if (!p_crypto->key || ((p_crypto->key_size != NVT_CRYPTO_AES_128_KEY_SIZE) && (p_crypto->key_size != NVT_CRYPTO_AES_256_KEY_SIZE))) {
crypto_err("key buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_crypto->key, p_crypto->key_size);
return -1;
}
}
/* check pio mode busy or not */
if (crypto_read(NVT_CRYPTO_CTRL_REG) & 0x1) {
crypto_err("crypto PIO mode busy!!\n");
return -1;
}
crypto_dbg("PIO => AES%d %s Key_Offset:%d OPMode:%d\n", p_crypto->key_size*8, (p_crypto->encrypt ? "Encrypt" : "Decrypt"), p_crypto->key_ofs, p_crypto->opmode);
/* set IV */
if (p_crypto->opmode == NVT_CRYPTO_OPMODE_CBC) {
memcpy(iv, p_crypto->iv, NVT_CRYPTO_AES_BLOCK_SIZE);
crypto_dbg("IV => 0x%08x 0x%08x 0x%08x 0x%08x\n", iv[0], iv[1], iv[2], iv[3]);
}
else {
memset(iv, 0, NVT_CRYPTO_AES_BLOCK_SIZE);
}
/* set config */
if (p_crypto->key_size == NVT_CRYPTO_AES_128_KEY_SIZE)
reg_value = 0x2 | (NVT_CRYPTO_MODE_AES_128<<4);
else
reg_value = 0x2 | (NVT_CRYPTO_MODE_AES_256<<4);
if (!p_crypto->encrypt) {
reg_value |= (0x1<<8);
}
crypto_write(NVT_CRYPTO_CFG_REG, reg_value);
/* set key */
if (p_crypto->key_src == NVT_CRYPTO_KEY_SRC_EFUSE) {
ret = otp_set_key_destination(p_crypto->key_ofs/4);
if (ret != 0) {
crypto_err("PIO Key => trigger key from efuse failed!\n");
ret = -1;
goto exit;
}
crypto_dbg("PIO Key => trigger key from efuse ready\n");
}
else {
memcpy(key, p_crypto->key, p_crypto->key_size);
crypto_write(NVT_CRYPTO_KEY0_REG, key[0]);
crypto_write(NVT_CRYPTO_KEY1_REG, key[1]);
crypto_write(NVT_CRYPTO_KEY2_REG, key[2]);
crypto_write(NVT_CRYPTO_KEY3_REG, key[3]);
crypto_dbg("PIO Key => 0x%08x 0x%08x 0x%08x 0x%08x\n", key[0], key[1], key[2], key[3]);
if (p_crypto->key_size == NVT_CRYPTO_AES_256_KEY_SIZE) {
crypto_write(NVT_CRYPTO_KEY4_REG, key[4]);
crypto_write(NVT_CRYPTO_KEY5_REG, key[5]);
crypto_write(NVT_CRYPTO_KEY6_REG, key[6]);
crypto_write(NVT_CRYPTO_KEY7_REG, key[7]);
crypto_dbg("PIO Key => 0x%08x 0x%08x 0x%08x 0x%08x\n", key[4], key[5], key[6], key[7]);
}
}
/* start data process */
for (i=0; i<(p_crypto->src_size/4); i+=(NVT_CRYPTO_AES_BLOCK_SIZE/4)) {
/* set input data */
memcpy(src, &p_crypto->src[i*4], NVT_CRYPTO_AES_BLOCK_SIZE);
if (p_crypto->opmode == NVT_CRYPTO_OPMODE_CBC) {
if (p_crypto->encrypt) {
src[0] ^= iv[0];
src[1] ^= iv[1];
src[2] ^= iv[2];
src[3] ^= iv[3];
}
}
crypto_write(NVT_CRYPTO_IN0_REG, src[0]);
crypto_write(NVT_CRYPTO_IN1_REG, src[1]);
crypto_write(NVT_CRYPTO_IN2_REG, src[2]);
crypto_write(NVT_CRYPTO_IN3_REG, src[3]);
crypto_dbg("PIO In => 0x%08x 0x%08x 0x%08x 0x%08x\n", src[0], src[1], src[2], src[3]);
/* clear PIO status */
crypto_write(NVT_CRYPTO_INT_STS_REG, 0x1);
/* trigger PIO mode */
crypto_write(NVT_CRYPTO_CTRL_REG, 0x1);
/* polling status */
cnt = 0;
reg_value = crypto_read(NVT_CRYPTO_INT_STS_REG);
while ((reg_value & 0x1) == 0) {
udelay(2);
reg_value = crypto_read(NVT_CRYPTO_INT_STS_REG);
cnt++;
if ((cnt%500000) == 0)
crypto_inf("wait crypto data complete...\n");
if (cnt > 2500000)
break;
}
if (reg_value & 0x1) {
/* clear status */
crypto_write(NVT_CRYPTO_INT_STS_REG, 0x1);
/* read output data */
dst[0] = crypto_read(NVT_CRYPTO_OUT0_REG);
dst[1] = crypto_read(NVT_CRYPTO_OUT1_REG);
dst[2] = crypto_read(NVT_CRYPTO_OUT2_REG);
dst[3] = crypto_read(NVT_CRYPTO_OUT3_REG);
if (p_crypto->opmode == NVT_CRYPTO_OPMODE_CBC) {
if (p_crypto->encrypt) {
iv[0] = dst[0];
iv[1] = dst[1];
iv[2] = dst[2];
iv[3] = dst[3];
}
else {
dst[0] ^= iv[0];
dst[1] ^= iv[1];
dst[2] ^= iv[2];
dst[3] ^= iv[3];
iv[0] = src[0];
iv[1] = src[1];
iv[2] = src[2];
iv[3] = src[3];
}
}
memcpy(&p_crypto->dst[i*4], dst, NVT_CRYPTO_AES_BLOCK_SIZE);
crypto_dbg("PIO Out => 0x%08x 0x%08x 0x%08x 0x%08x\n", dst[0], dst[1], dst[2], dst[3]);
}
else {
crypto_err("crypto PIO mode timeout!!\n");
ret = -1;
goto exit;
}
}
exit:
return ret;
}
int nvt_crypto_dma_aes(struct nvt_crypto_pio_t *p_crypto)
{
int ret = 0;
int cnt = 0;
uint32_t reg_value;
volatile struct nvt_crypto_dma_desc *desc = &g_dma_desc;
if (!nvt_crypto_opened) {
crypto_err("crypto engine not opened!\n");
return -1;
}
/* check parameter */
if (!p_crypto) {
crypto_err("invalid parameter\n");
return -1;
}
/* check opmode */
if (p_crypto->opmode >= NVT_CRYPTO_OPMODE_MAX) {
crypto_err("opmode:%d invalid\n", p_crypto->opmode);
return -1;
}
/* check iv */
if ((p_crypto->opmode != NVT_CRYPTO_OPMODE_ECB) && (!p_crypto->iv || (p_crypto->iv_size < NVT_CRYPTO_AES_BLOCK_SIZE))) {
crypto_err("iv buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_crypto->iv, p_crypto->iv_size);
return -1;
}
/* check source buffer and size and alignment, start address must align for cache line operation */
if (!p_crypto->src || !p_crypto->src_size || (p_crypto->src_size%NVT_CRYPTO_AES_BLOCK_SIZE) || (((uintptr_t)p_crypto->src)&PLAT_CACHE_LINE_MASK)) {
crypto_err("source buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_crypto->src, p_crypto->src_size);
return -1;
}
/* check destination buffer and size, start address must align for cache line operation */
if (!p_crypto->dst || !p_crypto->dst_size || (p_crypto->dst_size < p_crypto->src_size) || (((uintptr_t)p_crypto->dst)&PLAT_CACHE_LINE_MASK)) {
crypto_err("destination buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_crypto->dst, p_crypto->dst_size);
return -1;
}
/* check key buffer and size */
if (p_crypto->key_src == NVT_CRYPTO_KEY_SRC_EFUSE) {
/* efuse key only support AES128 and key offset must be 0,4,8,12,16 */
if ((p_crypto->key_size != NVT_CRYPTO_AES_128_KEY_SIZE) || (p_crypto->key_ofs%4)) {
crypto_err("key efuse size:%u offset:%d invalid\n", p_crypto->key_size, p_crypto->key_ofs);
return -1;
}
}
else {
if (!p_crypto->key || ((p_crypto->key_size != NVT_CRYPTO_AES_128_KEY_SIZE) && (p_crypto->key_size != NVT_CRYPTO_AES_256_KEY_SIZE))) {
crypto_err("key buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_crypto->key, p_crypto->key_size);
return -1;
}
}
/* check dma mode busy or not */
if (crypto_read(NVT_CRYPTO_CTRL_REG) & (0x1<<4)) {
crypto_err("crypto DMA mode busy!!\n");
return -1;
}
crypto_dbg("DMA => AES%d %s Key_Offset:%d OPMode:%d\n", p_crypto->key_size*8, (p_crypto->encrypt ? "Encrypt" : "Decrypt"), p_crypto->key_ofs, p_crypto->opmode);
crypto_dbg("DMA Src => addr:0x%08lx size:%u\n", (uintptr_t)p_crypto->src, p_crypto->src_size);
crypto_dbg("DMA Dst => addr:0x%08lx size:%u\n", (uintptr_t)p_crypto->dst, p_crypto->dst_size);
crypto_dbg("DMA DES => addr:0x%08lx size:%d\n", (uintptr_t)desc, (int)sizeof(struct nvt_crypto_dma_desc));
/* clear descriptor IV and Key and Counter and CV */
memset((void *)desc->iv, 0, sizeof(desc->iv));
memset((void *)desc->key, 0, sizeof(desc->key));
memset((void *)desc->counter, 0, sizeof(desc->counter));
memset((void *)desc->cv, 0, sizeof(desc->cv));
/* set IV */
if (p_crypto->opmode == NVT_CRYPTO_OPMODE_CBC) {
memcpy((void *)desc->iv, p_crypto->iv, NVT_CRYPTO_AES_BLOCK_SIZE);
crypto_dbg("DMA IV => %08x %08x %08x %08x\n", desc->iv[0], desc->iv[1], desc->iv[2], desc->iv[3]);
}
/* set key */
if (p_crypto->key_src == NVT_CRYPTO_KEY_SRC_EFUSE) {
ret = otp_set_key_destination(p_crypto->key_ofs/4);
if (ret != 0) {
crypto_err("DMA Key => trigger key from efuse failed!\n");
ret = -1;
goto exit;
}
crypto_dbg("DMA Key => trigger key from efuse ready\n");
}
else {
if (p_crypto->key_size == NVT_CRYPTO_AES_256_KEY_SIZE) {
memcpy((void *)desc->key, p_crypto->key, NVT_CRYPTO_AES_256_KEY_SIZE);
crypto_dbg("DMA Key => %08x %08x %08x %08x %08x %08x %08x %08x\n", desc->key[0], desc->key[1], desc->key[2], desc->key[3], desc->key[4], desc->key[5], desc->key[6], desc->key[7]);
}
else {
memcpy((void *)desc->key, p_crypto->key, NVT_CRYPTO_AES_128_KEY_SIZE);
crypto_dbg("DMA Key => %08x %08x %08x %08x\n", desc->iv[0], desc->iv[1], desc->iv[2], desc->iv[3]);
}
}
/* set header config */
if (p_crypto->key_size == NVT_CRYPTO_AES_256_KEY_SIZE)
desc->header_cfg = (NVT_CRYPTO_MODE_AES_256<<4) | (p_crypto->opmode<<8);
else
desc->header_cfg = (NVT_CRYPTO_MODE_AES_128<<4) | (p_crypto->opmode<<8);
if (p_crypto->encrypt == 0)
desc->header_cfg |= 0x1; ///< 0:encrypt 1:decrypt
if (p_crypto->key_src == NVT_CRYPTO_KEY_SRC_EFUSE)
desc->header_cfg |= (0x1<<12); ///< 0:from desc 1:from efuse
/* set crypto block config */
desc->block[0].src_addr = DMA_ADDR_LO(p_crypto->src);
desc->block[0].dst_addr = DMA_ADDR_LO(p_crypto->dst);
desc->block[0].length = p_crypto->src_size;
desc->block[0].block_cfg = 0x1; /// last block
#ifdef NVT_CRYPTO_DMA_36BIT_SUPPORT
desc->block[0].block_cfg |= (((DMA_ADDR_HI(p_crypto->src)&0xf)<<16) | ((DMA_ADDR_HI(p_crypto->dst)&0xf)<<24));
#endif
/* descriptor buffer memory flush */
flush_dcache_range((unsigned long)desc, ((unsigned long)desc) + roundup(sizeof(struct nvt_crypto_dma_desc), ARCH_DMA_MINALIGN));
/* source buffer memory flush */
flush_dcache_range((unsigned long)p_crypto->src, ((unsigned long)p_crypto->src) + roundup(p_crypto->src_size, ARCH_DMA_MINALIGN));
/* destination buffer memory invalidate */
invalidate_dcache_range((unsigned long)p_crypto->dst, ((unsigned long)p_crypto->dst) + roundup(p_crypto->dst_size, ARCH_DMA_MINALIGN));
/* set crypto enable */
reg_value = crypto_read(NVT_CRYPTO_CFG_REG);
crypto_write(NVT_CRYPTO_CFG_REG, (reg_value|0x2));
/* set interrupt disable */
reg_value = crypto_read(NVT_CRYPTO_INT_ENB_REG);
reg_value &= ~(0xf<<4);
crypto_write(NVT_CRYPTO_INT_ENB_REG, reg_value);
/* clear interrupt status */
crypto_write(NVT_CRYPTO_INT_STS_REG, (0xf<<4));
/* set DMA descriptor source address */
crypto_write(NVT_CRYPTO_DMA0_ADDR_REG, DMA_ADDR_LO(desc));
#ifdef NVT_CRYPTO_DMA_36BIT_SUPPORT
crypto_write(NVT_CRYPTO_DMA0_ADDR_H_REG, DMA_ADDR_HI(desc));
#endif
/* set DMA channel enable */
reg_value = crypto_read(NVT_CRYPTO_CTRL_REG);
reg_value &= ~(0xf<<4);
reg_value |= (0x1<<4);
crypto_write(NVT_CRYPTO_CTRL_REG, reg_value);
/* polling status */
reg_value = crypto_read(NVT_CRYPTO_INT_STS_REG);
while ((reg_value & (0x1<<4)) == 0) {
udelay(2);
reg_value = crypto_read(NVT_CRYPTO_INT_STS_REG);
cnt++;
if ((cnt%500000) == 0)
crypto_inf("wait crypto data complete...\n");
if (cnt > 2500000)
break;
}
if (reg_value & (0x1<<4)) {
/* clear status */
crypto_write(NVT_CRYPTO_INT_STS_REG, (0x1<<4));
crypto_dbg("DMA Out => 0x%08x 0x%08x 0x%08x 0x%08x\n",
(p_crypto->dst[0] | (p_crypto->dst[1]<<8) | (p_crypto->dst[2]<<16) | (p_crypto->dst[3]<<24)),
(p_crypto->dst[4] | (p_crypto->dst[5]<<8) | (p_crypto->dst[6]<<16) | (p_crypto->dst[7]<<24)),
(p_crypto->dst[8] | (p_crypto->dst[9]<<8) | (p_crypto->dst[10]<<16) | (p_crypto->dst[11]<<24)),
(p_crypto->dst[12] | (p_crypto->dst[13]<<8) | (p_crypto->dst[14]<<16) | (p_crypto->dst[15]<<24)));
}
else {
crypto_err("crypto DMA mode timeout!!\n");
ret = -1;
goto exit;
}
exit:
return ret;
}
#endif /* CONFIG_NVT_CRYPTO */