/* * The interface function of controlling the SS register. * * Copyright (C) 2013 Allwinner. * * Mintow * * 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 #include #include #include "../sunxi_ss.h" #include "sunxi_ss_reg.h" 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, ce_task_desc_t *task) { task->sym_ctl |= select << CE_SYM_CTL_KEY_SELECT_SHIFT; } void ss_keysize_set(int size, ce_task_desc_t *task) { int type = CE_AES_KEY_SIZE_128; switch (size) { case AES_KEYSIZE_192: type = CE_AES_KEY_SIZE_192; break; case AES_KEYSIZE_256: type = CE_AES_KEY_SIZE_256; break; default: break; } task->sym_ctl |= (type << CE_SYM_CTL_KEY_SIZE_SHIFT); } /* key: phsical address. */ void ss_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}, #ifdef SS_SUPPORT_CE_V3_2 {CE_KEY_SELECT_SCK0, CE_KS_SCK0}, {CE_KEY_SELECT_SCK1, CE_KS_SCK1}, #endif {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++; } SS_DBG("The key select: %d\n", key_sel); ss_keyselect_set(key_sel, task); ss_keysize_set(size, task); task->key_addr = virt_to_phys(key); } void ss_pending_clear(int flow) { int val = CE_CHAN_PENDING << flow; ss_writel(CE_REG_ISR, val); } int ss_pending_get(void) { return ss_readl(CE_REG_ISR); } void ss_irq_enable(int flow) { int val = ss_readl(CE_REG_ICR); val |= CE_CHAN_INT_ENABLE << flow; ss_writel(CE_REG_ICR, val); } void ss_irq_disable(int flow) { int val = ss_readl(CE_REG_ICR); val &= ~(CE_CHAN_INT_ENABLE << flow); ss_writel(CE_REG_ICR, val); } void ss_md_get(char *dst, char *src, int size) { memcpy(dst, src, size); } /* iv: phsical address. */ void ss_iv_set(char *iv, int size, ce_task_desc_t *task) { task->iv_addr = virt_to_phys(iv); } void ss_iv_mode_set(int mode, ce_task_desc_t *task) { task->comm_ctl |= mode << CE_COMM_CTL_IV_MODE_SHIFT; } void ss_cntsize_set(int size, ce_task_desc_t *task) { task->sym_ctl |= size << CE_SYM_CTL_CTR_SIZE_SHIFT; } void ss_cnt_set(char *cnt, int size, ce_task_desc_t *task) { task->ctr_addr = virt_to_phys(cnt); ss_cntsize_set(CE_CTR_SIZE_128, task); } void ss_cts_last(ce_task_desc_t *task) { task->sym_ctl |= CE_SYM_CTL_AES_CTS_LAST; } #ifndef SS_SUPPORT_CE_V3_1 void ss_xts_first(ce_task_desc_t *task) { task->sym_ctl |= CE_SYM_CTL_AES_XTS_FIRST; } void ss_xts_last(ce_task_desc_t *task) { task->sym_ctl |= CE_SYM_CTL_AES_XTS_LAST; } #endif void ss_hmac_sha1_last(ce_task_desc_t *task) { task->comm_ctl |= CE_HMAC_SHA1_LAST; } void ss_method_set(int dir, int type, ce_task_desc_t *task) { task->comm_ctl |= dir << CE_COMM_CTL_OP_DIR_SHIFT; task->comm_ctl |= type << CE_COMM_CTL_METHOD_SHIFT; } void ss_aes_mode_set(int mode, ce_task_desc_t *task) { task->sym_ctl |= mode << CE_SYM_CTL_OP_MODE_SHIFT; } void ss_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 ss_sha_final(void) { /* unsupported. */ } void ss_check_sha_end(void) { /* unsupported. */ } void ss_rsa_width_set(int size, ce_task_desc_t *task) { #ifdef SS_SUPPORT_CE_V3_1 int width_type = CE_RSA_PUB_MODULUS_WIDTH_512; switch (size*8) { 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<asym_ctl |= DIV_ROUND_UP(size, 4); #endif } void ss_rsa_op_mode_set(int mode, ce_task_desc_t *task) { /* Consider !2 as M_EXP, for compatible with the previous SOC. */ if (mode == CE_RSA_OP_M_MUL) task->asym_ctl |= CE_RSA_OP_M_MUL<asym_ctl |= CE_RSA_OP_M_EXP<asym_ctl |= width_type<asym_ctl |= DIV_ROUND_UP(size, 4); #endif } void ss_ecc_op_mode_set(int mode, ce_task_desc_t *task) { #ifdef SS_SUPPORT_CE_V3_1 task->asym_ctl |= mode<asym_ctl |= mode<comm_ctl&CE_COMM_CTL_METHOD_MASK; #endif ss_writel(CE_REG_TSK, virt_to_phys(task)); #ifdef SS_SUPPORT_CE_V3_1 ss_writel(CE_REG_TLR, 0x1); #else ss_writel(CE_REG_TLR, 0x1|(method<data_len = len; } int ss_reg_print(char *buf, int len) { return snprintf(buf, len, "The SS control register:\n" "[TSK] 0x%02x = 0x%08x\n" #ifdef SS_SUPPORT_CE_V3_1 "[CTL] 0x%02x = 0x%08x\n" #endif "[ICR] 0x%02x = 0x%08x, [ISR] 0x%02x = 0x%08x\n" "[TLR] 0x%02x = 0x%08x\n" "[TSR] 0x%02x = 0x%08x\n" "[ERR] 0x%02x = 0x%08x\n" #ifdef SS_SUPPORT_CE_V3_1 "[CSS] 0x%02x = 0x%08x, [CDS] 0x%02x = 0x%08x\n" #endif "[CSA] 0x%02x = 0x%08x, [CDA] 0x%02x = 0x%08x\n" #ifdef SS_SUPPORT_CE_V3_1 "[TPR] 0x%02x = 0x%08x\n" #else "[HCSA] 0x%02x = 0x%08x\n" "[HCDA] 0x%02x = 0x%08x\n" "[ACSA] 0x%02x = 0x%08x\n" "[ACDA] 0x%02x = 0x%08x\n" "[XCSA] 0x%02x = 0x%08x\n" "[XCDA] 0x%02x = 0x%08x\n" "[VER] 0x%02x = 0x%08x\n" #endif , CE_REG_TSK, ss_readl(CE_REG_TSK), #ifdef SS_SUPPORT_CE_V3_1 CE_REG_CTL, ss_readl(CE_REG_CTL), #endif CE_REG_ICR, ss_readl(CE_REG_ICR), CE_REG_ISR, ss_readl(CE_REG_ISR), CE_REG_TLR, ss_readl(CE_REG_TLR), CE_REG_TSR, ss_readl(CE_REG_TSR), CE_REG_ERR, ss_readl(CE_REG_ERR), #ifdef SS_SUPPORT_CE_V3_1 CE_REG_CSS, ss_readl(CE_REG_CSS), CE_REG_CDS, ss_readl(CE_REG_CDS), #endif CE_REG_CSA, ss_readl(CE_REG_CSA), CE_REG_CDA, ss_readl(CE_REG_CDA) #ifdef SS_SUPPORT_CE_V3_1 , CE_REG_TPR, ss_readl(CE_REG_TPR) #else , CE_REG_HCSA, ss_readl(CE_REG_HCSA), CE_REG_HCDA, ss_readl(CE_REG_HCDA), CE_REG_ACSA, ss_readl(CE_REG_ACSA), CE_REG_ACDA, ss_readl(CE_REG_ACDA), CE_REG_XCSA, ss_readl(CE_REG_XCSA), CE_REG_XCDA, ss_readl(CE_REG_XCDA), CE_REG_VER, ss_readl(CE_REG_VER) #endif ); }