408 lines
9.4 KiB
C
408 lines
9.4 KiB
C
/*
|
|
* The interface function of controlling the CE 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 <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <hal_mem.h>
|
|
#include <hal_osal.h>
|
|
#include <sunxi_hal_ce.h>
|
|
#include <hal_log.h>
|
|
|
|
#include "ce_common.h"
|
|
#include "ce_reg.h"
|
|
#include "platform_ce.h"
|
|
|
|
#ifdef CONFIG_ARCH_SUN20IW2P1
|
|
#include <hal_reset.h>
|
|
static int sunxi_ce_clk_init(bool enable)
|
|
{
|
|
hal_clk_status_t ret;
|
|
hal_reset_type_t reset_type = HAL_SUNXI_RESET;
|
|
u32 reset_id;
|
|
hal_clk_type_t clk_type = HAL_SUNXI_CCU;
|
|
hal_clk_id_t clk_id;
|
|
hal_clk_t clk;
|
|
struct reset_control *reset;
|
|
|
|
clk_id = SUNXI_CLK_CE;
|
|
reset_id = SUNXI_RST_CE;
|
|
if (enable)
|
|
{
|
|
reset = hal_reset_control_get(reset_type, reset_id);
|
|
hal_reset_control_deassert(reset);
|
|
hal_reset_control_put(reset);
|
|
|
|
hal_clock_enable(hal_clock_get(clk_type, SUNXI_CLK_MBUS_CE));
|
|
clk = hal_clock_get(clk_type, clk_id);
|
|
ret = hal_clock_enable(clk);
|
|
if (ret != HAL_CLK_STATUS_OK)
|
|
CE_ERR("CE clock enable failed.\n");
|
|
}
|
|
else
|
|
{
|
|
clk = hal_clock_get(clk_type, clk_id);
|
|
ret = hal_clock_disable(clk);
|
|
if (ret != HAL_CLK_STATUS_OK)
|
|
CE_ERR("CE clock disable failed.\n");
|
|
hal_clock_disable(hal_clock_get(clk_type, SUNXI_CLK_MBUS_CE));
|
|
hal_clock_put(clk);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
void hal_ce_clock_init(void)
|
|
{
|
|
#ifdef CONFIG_ARCH_SUN20IW2P1
|
|
sunxi_ce_clk_init(1);
|
|
#else
|
|
uint32_t reg_val;
|
|
|
|
reg_val = readl(CCMU_CE_CLK_REG);
|
|
|
|
/*set div n*/
|
|
reg_val &= ~(CE_CLK_DIV_RATION_N_MASK << CE_CLK_DIV_RATION_N_BIT);
|
|
reg_val |= CE_CLK_DIV_RATION_N << CE_CLK_DIV_RATION_N_BIT;
|
|
|
|
/*set div m*/
|
|
reg_val &= ~(CE_CLK_DIV_RATION_M_MASK << CE_CLK_DIV_RATION_M_BIT);
|
|
reg_val |= CE_CLK_DIV_RATION_M << CE_CLK_DIV_RATION_M_BIT;
|
|
|
|
writel(reg_val, CCMU_CE_CLK_REG);
|
|
|
|
/*set CE src clock*/
|
|
reg_val &= ~(CE_CLK_SRC_MASK << CE_CLK_SRC_SEL_BIT);
|
|
|
|
/* PLL_PERI0(2X) */
|
|
reg_val |= CE_CLK_SRC << CE_CLK_SRC_SEL_BIT;
|
|
|
|
/*set src clock on*/
|
|
reg_val |= CE_SCLK_ON << CE_SCLK_ONOFF_BIT;
|
|
|
|
writel(reg_val, CCMU_CE_CLK_REG);
|
|
|
|
/*open CE gating*/
|
|
reg_val = readl(CCMU_CE_BGR_REG);
|
|
reg_val |= CE_GATING_PASS << CE_GATING_BIT;
|
|
writel(reg_val, CCMU_CE_BGR_REG);
|
|
|
|
/*de-assert*/
|
|
reg_val = readl(CCMU_CE_BGR_REG);
|
|
reg_val |= CE_DEASSERT << CE_RST_BIT;
|
|
writel(reg_val, CCMU_CE_BGR_REG);
|
|
|
|
/*set mbus clock gating*/
|
|
reg_val = readl(MBUS_MAT_CLK_GATING_REG);
|
|
reg_val |= 1 << 2;
|
|
writel(reg_val, MBUS_MAT_CLK_GATING_REG);
|
|
#endif
|
|
}
|
|
|
|
|
|
uint32_t ce_readl(uint32_t offset)
|
|
{
|
|
#ifdef CONFIG_ARCH_SUN20IW2P1
|
|
return readl(CE_NS_BASE_REG + offset);
|
|
#else
|
|
return readl(CE_S_BASE_REG + offset);
|
|
#endif
|
|
}
|
|
|
|
static void ce_writel(uint32_t offset, uint32_t val)
|
|
{
|
|
#ifdef CONFIG_ARCH_SUN20IW2P1
|
|
writel(val, CE_NS_BASE_REG + offset);
|
|
#else
|
|
writel(val, CE_S_BASE_REG + offset);
|
|
#endif
|
|
}
|
|
|
|
uint32_t hal_ce_reg_rd(uint32_t offset)
|
|
{
|
|
return ce_readl(offset);
|
|
}
|
|
|
|
void hal_ce_reg_wr(uint32_t offset, uint32_t val)
|
|
{
|
|
ce_writel(offset, val);
|
|
}
|
|
|
|
void hal_ce_keyselect_set(int select, ce_task_desc_t *task)
|
|
{
|
|
task->sym_ctl |= select << CE_SYM_CTL_KEY_SELECT_SHIFT;
|
|
}
|
|
|
|
void hal_ce_keysize_set(int size, ce_task_desc_t *task)
|
|
{
|
|
volatile int type = CE_AES_KEY_SIZE_128;
|
|
|
|
switch (size) {
|
|
case AES_KEYSIZE_16:
|
|
type = CE_AES_KEY_SIZE_128;
|
|
break;
|
|
case AES_KEYSIZE_24:
|
|
type = CE_AES_KEY_SIZE_192;
|
|
break;
|
|
case AES_KEYSIZE_32:
|
|
type = CE_AES_KEY_SIZE_256;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
task->sym_ctl |= (type << CE_SYM_CTL_KEY_SIZE_SHIFT);
|
|
}
|
|
#ifdef CE_SUPPORT_CE_V3_1
|
|
void hal_ce_rsa_width_set(int size, ce_task_desc_t *task)
|
|
{
|
|
int width_type = 0;
|
|
|
|
switch (size) {
|
|
case 512:
|
|
width_type = CE_RSA_PUB_MODULUS_WIDTH_512;
|
|
break;
|
|
case 1024:
|
|
width_type = CE_RSA_PUB_MODULUS_WIDTH_1024;
|
|
break;
|
|
case 2048:
|
|
width_type = CE_RSA_PUB_MODULUS_WIDTH_2048;
|
|
break;
|
|
case 3072:
|
|
width_type = CE_RSA_PUB_MODULUS_WIDTH_3072;
|
|
break;
|
|
case 4096:
|
|
width_type = CE_RSA_PUB_MODULUS_WIDTH_4096;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
task->asym_ctl |= width_type << CE_ASYM_CTL_RSA_PM_WIDTH_SHIFT;
|
|
}
|
|
#endif
|
|
|
|
/* key: phsical address. */
|
|
void hal_ce_key_set(char *key, int size, ce_task_desc_t *task)
|
|
{
|
|
int i = 0;
|
|
int key_sel = CE_KEY_SELECT_INPUT;
|
|
struct {
|
|
int type;
|
|
char desc[AES_MIN_KEY_SIZE];
|
|
} keys[] = {
|
|
{CE_KEY_SELECT_SSK, CE_KS_SSK},
|
|
{CE_KEY_SELECT_HUK, CE_KS_HUK},
|
|
{CE_KEY_SELECT_RSSK, CE_KS_RSSK},
|
|
{CE_KEY_SELECT_INTERNAL_0, CE_KS_INTERNAL_0},
|
|
{CE_KEY_SELECT_INTERNAL_1, CE_KS_INTERNAL_1},
|
|
{CE_KEY_SELECT_INTERNAL_2, CE_KS_INTERNAL_2},
|
|
{CE_KEY_SELECT_INTERNAL_3, CE_KS_INTERNAL_3},
|
|
{CE_KEY_SELECT_INTERNAL_4, CE_KS_INTERNAL_4},
|
|
{CE_KEY_SELECT_INTERNAL_5, CE_KS_INTERNAL_5},
|
|
{CE_KEY_SELECT_INTERNAL_6, CE_KS_INTERNAL_6},
|
|
{CE_KEY_SELECT_INTERNAL_7, CE_KS_INTERNAL_7},
|
|
{CE_KEY_SELECT_INPUT, ""} };
|
|
|
|
while (keys[i].type != CE_KEY_SELECT_INPUT) {
|
|
if (strncasecmp(key, keys[i].desc, AES_MIN_KEY_SIZE) == 0) {
|
|
key_sel = keys[i].type;
|
|
memset(key, 0, size);
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
CE_DBG("The key size: %d\n", size);
|
|
|
|
hal_ce_keyselect_set(key_sel, task);
|
|
hal_ce_keysize_set(size, task);
|
|
task->key_addr = (uint32_t)__va_to_pa((uint32_t)key);
|
|
}
|
|
|
|
void hal_ce_pending_clear(int flow)
|
|
{
|
|
int val = CE_CHAN_PENDING << flow;
|
|
|
|
ce_writel(CE_REG_ISR, val);
|
|
}
|
|
|
|
int hal_ce_pending_get(void)
|
|
{
|
|
return ce_readl(CE_REG_ISR);
|
|
}
|
|
|
|
void hal_ce_irq_enable(int flow)
|
|
{
|
|
int val = ce_readl(CE_REG_ICR);
|
|
|
|
val |= CE_CHAN_INT_ENABLE << flow;
|
|
ce_writel(CE_REG_ICR, val);
|
|
}
|
|
|
|
void hal_ce_irq_disable(int flow)
|
|
{
|
|
int val = ce_readl(CE_REG_ICR);
|
|
|
|
val &= ~(CE_CHAN_INT_ENABLE << flow);
|
|
ce_writel(CE_REG_ICR, val);
|
|
}
|
|
|
|
void hal_ce_md_get(char *dst, char *src, int size)
|
|
{
|
|
memcpy(dst, src, size);
|
|
}
|
|
|
|
|
|
void hal_ce_iv_set(char *iv, int size, ce_task_desc_t *task)
|
|
{
|
|
task->iv_addr = (uint32_t)__va_to_pa((uint32_t)iv);
|
|
}
|
|
|
|
void hal_ce_iv_mode_set(int mode, ce_task_desc_t *task)
|
|
{
|
|
task->comm_ctl |= mode << CE_COMM_CTL_IV_MODE_SHIFT;
|
|
}
|
|
|
|
void hal_ce_cntsize_set(int size, ce_task_desc_t *task)
|
|
{
|
|
task->sym_ctl |= size << CE_SYM_CTL_CTR_SIZE_SHIFT;
|
|
}
|
|
|
|
void hal_ce_cnt_set(char *cnt, int size, ce_task_desc_t *task)
|
|
{
|
|
task->ctr_addr = (uint32_t)__va_to_pa((uint32_t)cnt);
|
|
hal_ce_cntsize_set(CE_CTR_SIZE_128, task);
|
|
}
|
|
|
|
void hal_ce_cts_last(ce_task_desc_t *task)
|
|
{
|
|
task->sym_ctl |= CE_SYM_CTL_AES_CTS_LAST;
|
|
}
|
|
|
|
#ifndef CE_SUPPORT_CE_V3_1
|
|
|
|
void hal_ce_xts_first(ce_task_desc_t *task)
|
|
{
|
|
task->sym_ctl |= CE_SYM_CTL_AES_XTS_FIRST;
|
|
}
|
|
|
|
void hal_ce_xts_last(ce_task_desc_t *task)
|
|
{
|
|
task->sym_ctl |= CE_SYM_CTL_AES_XTS_LAST;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
void hal_ce_method_set(int dir, int type, ce_task_desc_t *task)
|
|
{
|
|
if (dir != 0)
|
|
task->comm_ctl |= 1 << CE_COMM_CTL_OP_DIR_SHIFT;
|
|
task->comm_ctl |= type << CE_COMM_CTL_METHOD_SHIFT;
|
|
}
|
|
|
|
void hal_ce_aes_mode_set(int mode, ce_task_desc_t *task)
|
|
{
|
|
task->sym_ctl |= mode << CE_SYM_CTL_OP_MODE_SHIFT;
|
|
}
|
|
|
|
void hal_ce_task_enable(ce_task_desc_t *task)
|
|
{
|
|
task->comm_ctl |= CE_COMM_CTL_TASK_INT_MASK;
|
|
}
|
|
|
|
void hal_ce_cfb_bitwidth_set(int bitwidth, ce_task_desc_t *task)
|
|
{
|
|
int val = 0;
|
|
|
|
switch (bitwidth) {
|
|
case 1:
|
|
val = CE_CFB_WIDTH_1;
|
|
break;
|
|
case 8:
|
|
val = CE_CFB_WIDTH_8;
|
|
break;
|
|
case 64:
|
|
val = CE_CFB_WIDTH_64;
|
|
break;
|
|
case 128:
|
|
val = CE_CFB_WIDTH_128;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
task->sym_ctl |= val << CE_SYM_CTL_CFB_WIDTH_SHIFT;
|
|
}
|
|
|
|
void hal_ce_set_task(uint32_t task_addr)
|
|
{
|
|
ce_writel(CE_REG_TSK, __va_to_pa((uint32_t)task_addr));
|
|
|
|
}
|
|
|
|
void hal_ce_ctrl_start(void)
|
|
{
|
|
uint32_t val = ce_readl(CE_REG_TLR);
|
|
val = val | (0x1 << 0);
|
|
ce_writel(CE_REG_TLR, val);
|
|
}
|
|
|
|
int hal_ce_flow_err(int flow)
|
|
{
|
|
return ce_readl(CE_REG_ERR) & CE_REG_ESR_CHAN_MASK(flow);
|
|
}
|
|
|
|
|
|
void hal_ce_data_len_set(int len, ce_task_desc_t *task)
|
|
{
|
|
#ifdef CE_SUPPORT_CE_V3_1
|
|
task->data_len = (len >> 2);
|
|
#else
|
|
task->data_len = len;
|
|
#endif
|
|
}
|
|
|
|
void hal_ce_wait_finish(uint32_t flow)
|
|
{
|
|
uint32_t int_en;
|
|
int_en = ce_readl(CE_REG_ICR) & 0xf;
|
|
int_en = int_en & (0x01 << flow);
|
|
if (int_en != 0) {
|
|
while ((ce_readl(CE_REG_ISR) & (0x01 << flow)) == 0) {
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t hal_ce_get_erro(void)
|
|
{
|
|
return (ce_readl(CE_REG_ERR));
|
|
}
|
|
|
|
void hal_ce_reg_printf(void)
|
|
{
|
|
hal_log_err("The ce control register:\n");
|
|
hal_log_err("[TSK] = 0x%08x\n", ce_readl(CE_REG_TSK));
|
|
#ifdef CE_SUPPORT_CE_V3_1
|
|
hal_log_err("[CTL] = 0x%08x\n", ce_readl(CE_REG_CTL));
|
|
#endif
|
|
hal_log_err("[ICR] = 0x%08x\n", ce_readl(CE_REG_ICR));
|
|
hal_log_err("[ISR] = 0x%08x\n", ce_readl(CE_REG_ISR));
|
|
hal_log_err("[TLR] = 0x%08x\n", ce_readl(CE_REG_TLR));
|
|
hal_log_err("[TSR] = 0x%08x\n", ce_readl(CE_REG_TSR));
|
|
hal_log_err("[ERR] = 0x%08x\n", ce_readl(CE_REG_ERR));
|
|
hal_log_err("[CSA] = 0x%08x\n", ce_readl(CE_REG_CSA));
|
|
hal_log_err("[CDA] = 0x%08x\n", ce_readl(CE_REG_CDA));
|
|
hal_log_err("[VER] = 0x%08x\n", ce_readl(CE_REG_VER));
|
|
}
|