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