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 */
|