SmartAudio/lichee/linux-4.9/drivers/crypto/sunxi-ss/v2/sunxi_ss_reg.c

353 lines
6.9 KiB
C

/*
* The interface function of controlling the SS register.
*
* Copyright (C) 2013 Allwinner.
*
* Mintow <duanmintao@allwinnertech.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/types.h>
#include <linux/delay.h>
#include <asm/io.h>
#include "../sunxi_ss.h"
#include "sunxi_ss_reg.h"
static int gs_ss_osc_prev_state;
inline u32 ss_readl(u32 offset)
{
return readl(ss_membase() + offset);
}
inline void ss_writel(u32 offset, u32 val)
{
writel(val, ss_membase() + offset);
}
u32 ss_reg_rd(u32 offset)
{
return ss_readl(offset);
}
void ss_reg_wr(u32 offset, u32 val)
{
ss_writel(offset, val);
}
void ss_keyselect_set(int select)
{
int val = ss_readl(SS_REG_CTL);
val &= ~SS_REG_CTL_KEY_SELECT_MASK;
val |= select << SS_REG_CTL_KEY_SELECT_SHIFT;
ss_writel(SS_REG_CTL, val);
}
void ss_keysize_set(int size)
{
int val = ss_readl(SS_REG_CTL);
int type = SS_AES_KEY_SIZE_128;
switch (size) {
case AES_KEYSIZE_192:
type = SS_AES_KEY_SIZE_192;
break;
case AES_KEYSIZE_256:
type = SS_AES_KEY_SIZE_256;
break;
default:
/* type = SS_AES_KEY_SIZE_128; */
break;
}
val &= ~(SS_REG_CTL_KEY_SIZE_MASK);
val |= (type << SS_REG_CTL_KEY_SIZE_SHIFT);
ss_writel(SS_REG_CTL, val);
}
void ss_flow_enable(int flow)
{
int val = ss_readl(SS_REG_CTL);
val &= ~(SS_STREM1_SELECT|SS_STREM0_SELECT);
if (flow == 0)
val |= SS_STREM0_SELECT;
else
val |= SS_STREM1_SELECT;
ss_writel(SS_REG_CTL, val);
}
void ss_flow_mode_set(int mode)
{
int val = ss_readl(SS_REG_CTL);
val &= ~(SS_REG_CTL_FLOW_MODE_MASK);
val |= mode;
ss_writel(SS_REG_CTL, val);
}
void ss_pending_clear(int flow)
{
int val = ss_readl(SS_REG_ISR);
val &= ~(SS_REG_ICR_FLOW0_PENDING_MASK|SS_REG_ICR_FLOW1_PENDING_MASK);
val |= SS_FLOW_PENDING << flow;
ss_writel(SS_REG_ISR, val);
}
int ss_pending_get(void)
{
return ss_readl(SS_REG_ISR);
}
void ss_irq_enable(int flow)
{
int val = ss_readl(SS_REG_ICR);
val |= SS_FLOW_END_INT_ENABLE << flow;
ss_writel(SS_REG_ICR, val);
}
void ss_irq_disable(int flow)
{
int val = ss_readl(SS_REG_ICR);
val &= ~(SS_FLOW_END_INT_ENABLE << flow);
ss_writel(SS_REG_ICR, val);
}
/* key: phsical address. */
void ss_key_set(char *key, int size)
{
ss_keyselect_set(SS_KEY_SELECT_INPUT);
ss_keysize_set(size);
ss_writel(SS_REG_KEY_L, virt_to_phys(key));
}
/* iv: phsical address. */
void ss_iv_set(char *iv, int size)
{
ss_writel(SS_REG_IV_L, virt_to_phys(iv));
}
void ss_cntsize_set(int size)
{
int val = ss_readl(SS_REG_CTL);
val &= ~SS_REG_CTL_CTR_SIZE_MASK;
val |= size << SS_REG_CTL_CTR_SIZE_SHIFT;
ss_writel(SS_REG_CTL, val);
}
void ss_cnt_set(char *cnt, int size)
{
ss_cntsize_set(SS_CTR_SIZE_128);
ss_writel(SS_REG_IV_L, virt_to_phys(cnt));
}
void ss_cnt_get(int flow, char *cnt, int size)
{
int i;
int *val = (int *)cnt;
int base = SS_REG_CNT_BASE;
if (flow == 1)
base = SS_REG_FLOW1_CNT_BASE;
for (i = 0; i < size/4; i++, val++)
*val = ss_readl(base + i*4);
}
void ss_md_get(char *dst, char *src, int size)
{
memcpy(dst, src, size);
}
void ss_iv_mode_set(int mode)
{
int val = ss_readl(SS_REG_CTL);
val &= ~SS_REG_CTL_IV_MODE_MASK;
val |= mode << SS_REG_CTL_IV_MODE_SHIFT;
ss_writel(SS_REG_CTL, val);
}
void ss_cts_last(void)
{
int val = ss_readl(SS_REG_CTL);
val |= SS_REG_CTL_AES_CTS_LAST;
ss_writel(SS_REG_CTL, val);
}
void ss_method_set(int dir, int type)
{
int val = ss_readl(SS_REG_CTL);
val &= ~(SS_REG_CTL_OP_DIR_MASK|SS_REG_CTL_METHOD_MASK);
val |= dir << SS_REG_CTL_OP_DIR_SHIFT;
val |= type << SS_REG_CTL_METHOD_SHIFT;
ss_writel(SS_REG_CTL, val);
}
void ss_aes_mode_set(int mode)
{
int val = ss_readl(SS_REG_CTL);
val &= ~SS_REG_CTL_OP_MODE_MASK;
val |= mode << SS_REG_CTL_OP_MODE_SHIFT;
ss_writel(SS_REG_CTL, val);
}
void ss_rng_mode_set(int mode)
{
int val = ss_readl(SS_REG_CTL);
val &= ~SS_REG_CTL_PRNG_MODE_MASK;
val |= mode << SS_REG_CTL_PRNG_MODE_SHIFT;
ss_writel(SS_REG_CTL, val);
}
void ss_trng_osc_enable(void)
{
int val = readl(SS_TRNG_OSC_ADDR);
gs_ss_osc_prev_state = 1;
if (val & 1)
return;
val |= 1;
writel(val, SS_TRNG_OSC_ADDR);
}
void ss_trng_osc_disable(void)
{
int val = 0;
if (gs_ss_osc_prev_state == 1)
return;
val = readl(SS_TRNG_OSC_ADDR);
val &= ~1;
writel(val, SS_TRNG_OSC_ADDR);
}
void ss_sha_final(void)
{
/* unsupported. */
}
void ss_check_sha_end(void)
{
/* unsupported. */
}
void ss_rsa_width_set(int size)
{
int val = ss_readl(SS_REG_CTL);
int width_type = SS_RSA_PUB_MODULUS_WIDTH_512;
switch (size*8) {
case 512:
width_type = SS_RSA_PUB_MODULUS_WIDTH_512;
break;
case 1024:
width_type = SS_RSA_PUB_MODULUS_WIDTH_1024;
break;
case 2048:
width_type = SS_RSA_PUB_MODULUS_WIDTH_2048;
break;
case 3072:
width_type = SS_RSA_PUB_MODULUS_WIDTH_3072;
break;
default:
break;
}
val &= ~SS_REG_CTL_RSA_PM_WIDTH_MASK;
val |= width_type<<SS_REG_CTL_RSA_PM_WIDTH_SHIFT;
ss_writel(SS_REG_CTL, val);
}
void ss_ctrl_start(void)
{
int val = ss_readl(SS_REG_CTL);
val |= 1<<27;
val |= SS_CTL_START;
ss_writel(SS_REG_CTL, val);
}
void ss_ctrl_stop(void)
{
int val = ss_readl(SS_REG_CTL);
val &= ~SS_CTL_START;
ss_writel(SS_REG_CTL, val);
}
void ss_wait_idle(void)
{
while ((ss_readl(SS_REG_CTL) & SS_REG_CTL_IDLE_MASK) == SS_CTL_BUSY) {
/* SS_DBG("Need wait for the hardware.\n"); */
msleep(20);
}
}
void ss_data_src_set(int addr)
{
ss_writel(SS_REG_DATA_SRC_H, 0);
ss_writel(SS_REG_DATA_SRC_L, addr);
}
void ss_data_dst_set(int addr)
{
ss_writel(SS_REG_DATA_DST_H, 0);
ss_writel(SS_REG_DATA_DST_L, addr);
}
void ss_data_len_set(int len)
{
ss_writel(SS_REG_DATA_LEN, len);
}
int ss_reg_print(char *buf, int len)
{
return snprintf(buf, len,
"The SS control register:\n"
"[CTL] 0x%02x = 0x%08x\n"
"[ICR] 0x%02x = 0x%08x, [ISR] 0x%02x = 0x%08x\n"
"[KEY_L] 0x%02x = 0x%08x, [KEY_H] 0x%02x = 0x%08x\n"
"[IV_L] 0x%02x = 0x%08x, [IV_H] 0x%02x = 0x%08x\n"
"[DATA_SRC_L] 0x%02x = 0x%08x, [DATA_SRC_H] 0x%02x = 0x%08x\n"
"[DATA_DST_L] 0x%02x = 0x%08x, [DATA_DST_H] 0x%02x = 0x%08x\n"
"[DATA_LEN] 0x%02x = 0x%08x\n"
"[CNT0-3] 0x%02x = 0x%08x, 0x%08x, 0x%08x, 0x%08x\n"
"[CNT4-7] 0x%02x = 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
SS_REG_CTL, ss_readl(SS_REG_CTL),
SS_REG_ICR, ss_readl(SS_REG_ICR),
SS_REG_ISR, ss_readl(SS_REG_ISR),
SS_REG_KEY_L, ss_readl(SS_REG_KEY_L),
SS_REG_KEY_H, ss_readl(SS_REG_KEY_H),
SS_REG_IV_L, ss_readl(SS_REG_IV_L),
SS_REG_IV_H, ss_readl(SS_REG_IV_H),
SS_REG_DATA_SRC_L, ss_readl(SS_REG_DATA_SRC_L),
SS_REG_DATA_SRC_H, ss_readl(SS_REG_DATA_SRC_H),
SS_REG_DATA_DST_L, ss_readl(SS_REG_DATA_DST_L),
SS_REG_DATA_DST_H, ss_readl(SS_REG_DATA_DST_H),
SS_REG_DATA_LEN, ss_readl(SS_REG_DATA_LEN),
SS_REG_CNT(0),
ss_readl(SS_REG_CNT(0)), ss_readl(SS_REG_CNT(1)),
ss_readl(SS_REG_CNT(2)), ss_readl(SS_REG_CNT(3)),
SS_REG_FLOW1_CNT(0),
ss_readl(SS_REG_FLOW1_CNT(0)), ss_readl(SS_REG_FLOW1_CNT(1)),
ss_readl(SS_REG_FLOW1_CNT(2)), ss_readl(SS_REG_FLOW1_CNT(3))
);
}