589 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			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 */
 | 
