360 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			360 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /*
 | |
|  * RSA API.
 | |
|  *
 | |
|  * Support for Novatek NVT RSA Hardware acceleration.
 | |
|  *
 | |
|  * Copyright (c) 2021 Novatek Inc.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #ifdef CONFIG_NVT_RSA
 | |
| #include <common.h>
 | |
| #include <asm/io.h>
 | |
| #include <asm/arch/IOAddress.h>
 | |
| #include <asm/arch/nvt_rsa.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_RSA_DEBUG
 | |
| #define NVT_RSA_OUTPUT_REVERSE          1
 | |
| #define NVT_RSA_BUFFER_LEN              512     ///< bytes, hardware internal SRAM size
 | |
| 
 | |
| #ifdef CONFIG_NVT_FPGA_EMULATION
 | |
| #define NVT_RSA_TIMEOUT_USEC            (1000000*60)
 | |
| #else
 | |
| #define NVT_RSA_TIMEOUT_USEC            (1000000*10)
 | |
| #endif
 | |
| 
 | |
| /*************************************************************************************
 | |
|  *  Debug Message Print Definition
 | |
|  *************************************************************************************/
 | |
| #ifdef NVT_RSA_DEBUG
 | |
| #define rsa_dbg(...)                    printf("[RSA_DBG]: " __VA_ARGS__)
 | |
| #else
 | |
| #define rsa_dbg(...)
 | |
| #endif
 | |
| 
 | |
| #define rsa_err(...)                    printf("[RSA_ERR]: " __VA_ARGS__)
 | |
| #define rsa_inf(...)                    printf("[RSA_INF]: " __VA_ARGS__)
 | |
| 
 | |
| /*************************************************************************************
 | |
|  *  Register read/write Definition
 | |
|  *************************************************************************************/
 | |
| #define rsa_read(_oft)                 IO_REG_RD(IOADDR_RSA_REG_BASE, _oft)
 | |
| #define rsa_write(_oft, _v)            IO_REG_WR(IOADDR_RSA_REG_BASE, _oft, _v)
 | |
| 
 | |
| /*************************************************************************************
 | |
|  *  Register Definition
 | |
|  *************************************************************************************/
 | |
| #define NVT_RSA_CFG_REG                0x00           ///< configuration
 | |
| #define NVT_RSA_CTRL_REG               0x04           ///< control
 | |
| #define NVT_RSA_INT_ENB_REG            0x08           ///< interrupt enable
 | |
| #define NVT_RSA_INT_STS_REG            0x0C           ///< interrupt status
 | |
| #define NVT_RSA_KEY_N_REG              0x10           ///< key N register
 | |
| #define NVT_RSA_KEY_N_ADDR_REG         0x14           ///< key N config ram address
 | |
| #define NVT_RSA_KEY_ED_REG             0x18           ///< key E/D register
 | |
| #define NVT_RSA_KEY_ED_ADDR_REG        0x1C           ///< key E/D config ram address
 | |
| #define NVT_RSA_DATA_REG               0x20           ///< input data register
 | |
| #define NVT_RSA_DATA_ADDR_REG          0x24           ///< input data config ram address
 | |
| #define NVT_RSA_KEY_READ_REG           0x28           ///< rsa key readable control
 | |
| #define NVT_RSA_CRC32_DEFAULT_REG      0x30           ///< crc32 default value
 | |
| #define NVT_RSA_CRC32_POLY_REG         0x34           ///< crc32 polynomial parameter
 | |
| #define NVT_RSA_CRC32_OUTPUT_REG       0x38           ///< rsa key crc32 result
 | |
| 
 | |
| /*************************************************************************************
 | |
|  *  Local Definition
 | |
|  *************************************************************************************/
 | |
| static int nvt_rsa_opened = 0;
 | |
| 
 | |
| static void nvt_rsa_platform_init(void)
 | |
| {
 | |
| 	uint32_t tmp;
 | |
| 
 | |
| 	/* RSA clock select, 0:PLL2(400MHz) 1:PLL13(350MHz) */
 | |
| 	tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0x24);
 | |
| 	tmp &= ~(0x1<<9);
 | |
| 	IO_REG_WR(IOADDR_CG_REG_BASE, 0x24, tmp);
 | |
| 
 | |
| 	/* RSA master clock enable */
 | |
| 	tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0x70);
 | |
| 	tmp |= (0x1<<30);
 | |
| 	IO_REG_WR(IOADDR_CG_REG_BASE, 0x70, tmp);
 | |
| 
 | |
| 	/* RSA program clock enable */
 | |
| 	tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0xE0);
 | |
| 	tmp |= (0x1<<18);
 | |
| 	IO_REG_WR(IOADDR_CG_REG_BASE, 0xE0, tmp);
 | |
| 
 | |
| 	/* RSA reset disable */
 | |
| 	tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0x94);
 | |
| 	tmp |= (0x1<<21);
 | |
| 	IO_REG_WR(IOADDR_CG_REG_BASE, 0x94, tmp);
 | |
| 
 | |
| 	/* RSA SRAM shutdown disable */
 | |
| 	tmp = IO_REG_RD(IOADDR_TOP_REG_BASE, 0x1004);
 | |
| 	tmp &= ~(0x1<<29);
 | |
| 	IO_REG_WR(IOADDR_TOP_REG_BASE, 0x1004, tmp);
 | |
| }
 | |
| 
 | |
| static void nvt_rsa_platform_exit(void)
 | |
| {
 | |
| 	uint32_t tmp;
 | |
| 
 | |
| 	/* RSA SRAM shutdown enable */
 | |
| 	tmp = IO_REG_RD(IOADDR_TOP_REG_BASE, 0x1004);
 | |
| 	tmp |= (0x1<<29);
 | |
| 	IO_REG_WR(IOADDR_TOP_REG_BASE, 0x1004, tmp);
 | |
| 
 | |
| 	/* RSA reset enable */
 | |
| 	tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0x94);
 | |
| 	tmp &= ~(0x1<<21);
 | |
| 	IO_REG_WR(IOADDR_CG_REG_BASE, 0x94, tmp);
 | |
| 
 | |
| 	/* RSA master clock disable */
 | |
| 	tmp = IO_REG_RD(IOADDR_CG_REG_BASE, 0x70);
 | |
| 	tmp &= ~(0x1<<30);
 | |
| 	IO_REG_WR(IOADDR_CG_REG_BASE, 0x70, tmp);
 | |
| }
 | |
| 
 | |
| static void nvt_rsa_reset(void)
 | |
| {
 | |
| 	uint32_t value = 0;
 | |
| 	uint32_t cnt   = 0;
 | |
| 
 | |
| 	/* disable rsa */
 | |
| 	rsa_write(NVT_RSA_CTRL_REG, 0);
 | |
| 	rsa_write(NVT_RSA_CFG_REG,  0);
 | |
| 
 | |
| 	/* set reset, hardware will auto clear */
 | |
| 	rsa_write(NVT_RSA_CFG_REG, 0x01);
 | |
| 
 | |
| 	/* check reset done */
 | |
| 	while ((value = rsa_read(NVT_RSA_CFG_REG)) & 0x1) {
 | |
| 		if(cnt++ >= 3000000)    ///< 3sec
 | |
| 			break;
 | |
| 		udelay(1);
 | |
| 	}
 | |
| 
 | |
| 	/* clear status */
 | |
| 	rsa_write(NVT_RSA_INT_STS_REG, 0x1);
 | |
| 
 | |
| 	if (value & 0x1) {
 | |
| 		rsa_err("rsa hardware reset failed!!\n");
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int nvt_rsa_open(void)
 | |
| {
 | |
| 	if (!nvt_rsa_opened) {
 | |
| 		/* platform pmu init for rsa engine */
 | |
| 		nvt_rsa_platform_init();
 | |
| 
 | |
| 		/* rsa engine software reset */
 | |
| 		nvt_rsa_reset();
 | |
| 
 | |
| 		nvt_rsa_opened = 1;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void nvt_rsa_close(void)
 | |
| {
 | |
| 	if (nvt_rsa_opened) {
 | |
| 		nvt_rsa_platform_exit();
 | |
| 		nvt_rsa_opened = 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int nvt_rsa_pio_normal(struct nvt_rsa_pio_t *p_rsa)
 | |
| {
 | |
| 	int    i, j;
 | |
| 	int    buf_len;
 | |
| 	uint32_t cnt;
 | |
| 	uint32_t block_size;
 | |
| 	uint32_t reg_value;
 | |
| 
 | |
| 	if (!nvt_rsa_opened) {
 | |
| 		rsa_err("rsa engine not opened!\n");
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	/* check parameter */
 | |
| 	if (!p_rsa) {
 | |
| 		rsa_err("invalid parameter\n");
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	/* RSA internal SRAM buffer length */
 | |
| 	buf_len = NVT_RSA_BUFFER_LEN;
 | |
| 
 | |
| 	rsa_dbg("RSA       => key%d\n", 256<<p_rsa->key_w);
 | |
| 	rsa_dbg("Src       => addr:0x%08lx size:%u\n", (uintptr_t)p_rsa->src,    p_rsa->src_size);
 | |
| 	rsa_dbg("Dst       => addr:0x%08lx size:%u\n", (uintptr_t)p_rsa->dst,    p_rsa->dst_size);
 | |
| 	rsa_dbg("Key_N     => addr:0x%08lx size:%u\n", (uintptr_t)p_rsa->key_n,  p_rsa->key_n_size);
 | |
| 	rsa_dbg("Key_ED    => addr:0x%08lx size:%u\n", (uintptr_t)p_rsa->key_ed, p_rsa->key_ed_size);
 | |
| 
 | |
| 	/* check key width */
 | |
| 	switch (p_rsa->key_w) {
 | |
| 	case NVT_RSA_KEY_WIDTH_256:
 | |
| 		block_size = NVT_RSA_256_KEY_SIZE;
 | |
| 		break;
 | |
| 	case NVT_RSA_KEY_WIDTH_512:
 | |
| 		block_size = NVT_RSA_512_KEY_SIZE;
 | |
| 		break;
 | |
| 	case NVT_RSA_KEY_WIDTH_1024:
 | |
| 		block_size = NVT_RSA_1024_KEY_SIZE;
 | |
| 		break;
 | |
| 	case NVT_RSA_KEY_WIDTH_2048:
 | |
| 		block_size = NVT_RSA_2048_KEY_SIZE;
 | |
| 		break;
 | |
| 	case NVT_RSA_KEY_WIDTH_4096:
 | |
| 		block_size = NVT_RSA_4096_KEY_SIZE;
 | |
| 		break;
 | |
| 	default:
 | |
| 		rsa_err("key width=%d not support\n", 256<<p_rsa->key_w);
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	/* check source buffer and size */
 | |
| 	if (!p_rsa->src || !p_rsa->src_size || (p_rsa->src_size > block_size)) {
 | |
| 		rsa_err("source buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_rsa->src, p_rsa->src_size);
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	/* check destination buffer and size */
 | |
| 	if (!p_rsa->dst || !p_rsa->dst_size || (p_rsa->dst_size < block_size)) {
 | |
| 		rsa_err("destination buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_rsa->dst, p_rsa->dst_size);
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	/* check key_n buffer and size */
 | |
| 	if (!p_rsa->key_n || !p_rsa->key_n_size || (p_rsa->key_n_size > block_size)) {
 | |
| 		rsa_err("key_n buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_rsa->key_n, p_rsa->key_n_size);
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	/* check key_ed buffer and size */
 | |
| 	if (!p_rsa->key_ed || !p_rsa->key_ed_size || (p_rsa->key_ed_size > block_size)) {
 | |
| 		rsa_err("key_ed buffer=0x%08lx size:%u invalid\n", (uintptr_t)p_rsa->key_ed, p_rsa->key_ed_size);
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	/* check pio busy */
 | |
| 	if (rsa_read(NVT_RSA_INT_STS_REG) & 0x2) {
 | |
| 		rsa_err("rsa PIO mode busy!!\n");
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 *  RSA Input data byte order => big endian
 | |
| 	 *  [0000] 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
 | |
| 	 *
 | |
| 	 *  RSA SRAM data byte order => little endian
 | |
| 	 *  [0000] 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
 | |
| 	 */
 | |
| 
 | |
| 	/* set input data */
 | |
| 	rsa_write(NVT_RSA_DATA_ADDR_REG, 0);
 | |
| 	for (i=0; i<buf_len; i+=4) {
 | |
| 		if (i < p_rsa->src_size) {
 | |
| 			reg_value = 0;
 | |
| 			for (j=0; j<4; j++) {
 | |
| 				reg_value |= (((uint32_t)(((i+j) >= p_rsa->src_size) ? 0 : p_rsa->src[p_rsa->src_size-(i+j)-1]))<<(j*8));
 | |
| 			}
 | |
| 			rsa_write(NVT_RSA_DATA_REG, reg_value);
 | |
| 			rsa_dbg("RSA In    => 0x%08x\n", reg_value);
 | |
| 		}
 | |
| 		else {
 | |
| 			rsa_write(NVT_RSA_DATA_REG, 0);
 | |
| 			rsa_dbg("RSA In    => 0x%08x\n", 0);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* set key_n */
 | |
| 	rsa_write(NVT_RSA_KEY_N_ADDR_REG, 0);
 | |
| 	for (i=0; i<buf_len; i+=4) {
 | |
| 		if (i < p_rsa->key_n_size) {
 | |
| 			reg_value = 0;
 | |
| 			for (j=0; j<4; j++) {
 | |
| 				reg_value |= (((uint32_t)(((i+j) >= p_rsa->key_n_size) ? 0 : p_rsa->key_n[p_rsa->key_n_size-(i+j)-1]))<<(j*8));
 | |
| 			}
 | |
| 			rsa_write(NVT_RSA_KEY_N_REG, reg_value);
 | |
| 			rsa_dbg("RSA Key_N => 0x%08x\n", reg_value);
 | |
| 		}
 | |
| 		else {
 | |
| 			rsa_write(NVT_RSA_KEY_N_REG, 0);
 | |
| 			rsa_dbg("RSA Key_N => 0x%08x\n", 0);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* set key_ed */
 | |
| 	rsa_write(NVT_RSA_KEY_ED_ADDR_REG, 0);
 | |
| 	for (i=0; i<buf_len; i+=4) {
 | |
| 		if (i < p_rsa->key_ed_size) {
 | |
| 			reg_value = 0;
 | |
| 			for (j=0; j<4; j++) {
 | |
| 				reg_value |= (((uint32_t)(((i+j) >= p_rsa->key_ed_size) ? 0 : p_rsa->key_ed[p_rsa->key_ed_size-(i+j)-1]))<<(j*8));
 | |
| 			}
 | |
| 			rsa_write(NVT_RSA_KEY_ED_REG, reg_value);
 | |
| 			rsa_dbg("RSA Key_ED=> 0x%08x\n", reg_value);
 | |
| 		}
 | |
| 		else {
 | |
| 			rsa_write(NVT_RSA_KEY_ED_REG, 0);
 | |
| 			rsa_dbg("RSA Key_ED=> 0x%08x\n", 0);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* set key width and mode */
 | |
| 	rsa_write(NVT_RSA_CFG_REG, ((NVT_RSA_MODE_NORMAL<<4) | (p_rsa->key_w<<1)));
 | |
| 
 | |
| 	/* clear status */
 | |
| 	rsa_write(NVT_RSA_INT_STS_REG, 0x1);
 | |
| 
 | |
| 	/* trigger transfer */
 | |
| 	rsa_write(NVT_RSA_CTRL_REG, 0x1);
 | |
| 
 | |
| 	/* polling status */
 | |
| 	cnt = 0;
 | |
| 	reg_value = rsa_read(NVT_RSA_INT_STS_REG);
 | |
| 	while ((reg_value & 0x1) == 0) {
 | |
| 		udelay(2);
 | |
| 		reg_value = rsa_read(NVT_RSA_INT_STS_REG);
 | |
| 		cnt++;
 | |
| 		if ((cnt%500000) == 0)
 | |
| 			rsa_inf("wait rsa data complete...\n");
 | |
| 		if (cnt > NVT_RSA_TIMEOUT_USEC)
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	/* copy output data to destination buffer */
 | |
| 	if (reg_value & 0x1) {
 | |
| 		rsa_write(NVT_RSA_DATA_ADDR_REG, 0);
 | |
| 		for (i=0; i<block_size; i+=4) {
 | |
| 			reg_value = rsa_read(NVT_RSA_DATA_REG);
 | |
| 			for (j=0; j<4; j++) {
 | |
| #ifdef NVT_RSA_OUTPUT_REVERSE
 | |
| 				p_rsa->dst[block_size-(i+j)-1] = (reg_value>>(j*8))&0xff;    ///< data reverse
 | |
| #else
 | |
| 				p_rsa->dst[i+j] = (reg_value>>(j*8))&0xff;
 | |
| #endif
 | |
| 			}
 | |
| 			rsa_dbg("RSA Out   => 0x%08x\n", reg_value);
 | |
| 		}
 | |
| 	}
 | |
| 	else {
 | |
| 		rsa_err("rsa PIO mode timeout!!\n");
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| #endif /* CONFIG_NVT_RSA */
 |