[Feature]Upload Modem source code
Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/driver/devdrv/soe/src/drv_soe.c b/mcu/driver/devdrv/soe/src/drv_soe.c
new file mode 100644
index 0000000..910fcd6
--- /dev/null
+++ b/mcu/driver/devdrv/soe/src/drv_soe.c
@@ -0,0 +1,937 @@
+/*****************************************************************************
+* Copyright Statement:
+* --------------------
+* This software is protected by Copyright and the information contained
+* herein is confidential. The software may not be copied and the information
+* contained herein may not be used or disclosed except with the written
+* permission of MediaTek Inc. (C) 2013
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * drv_soe.c
+ *
+ * Description:
+ * ------------
+ * SOE Driver
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ * HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ *****************************************************************************/
+
+
+/*******************************************************************************
+ * Include header files
+ *******************************************************************************/
+#include "kal_general_types.h"
+#include "sleepdrv_interface.h"
+#include "drvpdn.h"
+#include "ex_public.h"
+
+#include "drv_soe_reg.h"
+#include "drv_soe_key.h"
+#include "drv_soe_bm.h"
+#include "drv_soe_engine.h"
+
+#ifdef SOE_CHB_MODE
+ #define SOE_GPD_CHK SOE_CHK_32
+#else
+ #define SOE_GPD_CHK SOE_CHK_28
+#endif
+#define SOE_BD_CHK SOE_CHK_16
+
+#if 0 //defined(ATEST_ENABLE)
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#else
+#define DRV_MSG(level, fmt...)
+#endif
+
+#if defined(ATEST_ENABLE)
+kal_uint32 drv_soe_dbg_frc[5];
+kal_uint32 drv_soe_frc_start[5], drv_soe_frc_end[5];
+extern kal_uint32 drv_sm_getCurFRC(void);
+
+#define DRV_DBG_FRC_INIT(t) drv_soe_dbg_frc[t]=0
+#define DRV_DBG_FRC_START(t) do{ drv_soe_frc_start[t] = drv_sm_getCurFRC(); \
+ }while(0)
+
+#define DRV_DBG_FRC_END(t) do{ drv_soe_frc_end[t] = drv_sm_getCurFRC(); \
+ drv_soe_dbg_frc[t] += (drv_soe_frc_end[t] - drv_soe_frc_start[t]); \
+ }while(0)
+#else
+#define DRV_DBG_FRC_INIT(t)
+#define DRV_DBG_FRC_START(t)
+#define DRV_DBG_FRC_END(t)
+#endif
+
+//#define DRV_DISABLE_IRQ
+
+/*******************************************************************************
+ * global variable definitions
+ *******************************************************************************/
+static kal_bool drv_inited = KAL_FALSE;
+static kal_enhmutexid drv_soe_locker;
+static kal_eventgrpid drv_soe_egid;
+#ifdef ATEST_ENABLE
+static void (*drv_soe_lisr_handler_cb)(kal_uint32 vector) = NULL;
+#endif
+
+kal_bool drv_soe_irq_en = KAL_TRUE;
+
+/*******************************************************************************
+ * SOE register dump
+ *******************************************************************************/
+EX_BBREG_DUMP soe_reg_dump;
+const kal_uint32 soe_reg_dump_regions[] = {
+ SOE_BASE, 0xC0, 4,
+ SOE_BASE+0x200, 0xB0, 4,
+ SOE_BASE+0x8000, 0x10, 4,
+};
+
+static void drv_soe_register_bbreg_dump(void)
+{
+ soe_reg_dump.regions = (kal_uint32*)soe_reg_dump_regions;
+ soe_reg_dump.num = sizeof(soe_reg_dump_regions) / (sizeof(kal_uint32) * 3);
+ soe_reg_dump.bbreg_dump_callback = NULL;
+ EX_REGISTER_BBREG_DUMP(&soe_reg_dump);
+}
+
+/*******************************************************************************
+ * Function definitions
+ *******************************************************************************/
+static kal_uint8 drv_soe_calc_chksum(kal_uint8 *data, kal_uint16 len)
+{
+ kal_uint8 *uDataPtr, ckSum;
+ kal_uint16 i;
+
+ *(data + 1) = 0x0;
+ uDataPtr = data;
+ ckSum = 0;
+ for (i = 0; i < len; i++)
+ ckSum += *(uDataPtr + i);
+ return 0xFF - ckSum;
+}
+
+static void drv_soe_set_reg(kal_uint32 reg, kal_uint32 mask, kal_uint32 val, kal_uint32 offset)
+{
+ kal_uint32 tmp;
+ tmp = SOE_REG(reg);
+ tmp &= (~mask);
+ tmp |= (val << offset);
+ SOE_REG(SOE_CR) = tmp;
+}
+
+void drv_soe_lisr(kal_uint32 irq_id)
+{
+ kal_uint32 intr_status;
+
+#ifdef ATEST_ENABLE
+ if(drv_soe_lisr_handler_cb != NULL) {
+ drv_soe_lisr_handler_cb(irq_id);
+ return;
+ }
+#endif
+ intr_status = SOE_REG(SOE_L2ISAR);
+ SOE_REG(SOE_L2ISAR) = intr_status;
+#if defined(MT6297)
+ intr_status |= (SOE_REG(SOE_ASYM_STATUS_REG7) << 8);
+#endif
+ Data_Sync_Barrier();
+ IRQClearInt(SOE_IRQ);
+ Data_Sync_Barrier();
+
+ kal_set_eg_events(drv_soe_egid, intr_status, KAL_OR);
+}
+
+#ifdef ATEST_ENABLE
+void drv_soe_reg_interrupt(void (*handler)(kal_uint32 vector))
+{
+ drv_soe_lisr_handler_cb = handler;
+}
+#endif
+
+void drv_soe_init(void)
+{
+ if(drv_inited) {
+ return;
+ }
+
+ drv_soe_locker = kal_create_enh_mutex("SOEMtx");
+ if(!drv_soe_locker) ASSERT(0);
+
+ drv_soe_egid = kal_create_event_group("SOEEvt");
+ if(!drv_soe_egid) ASSERT(0);
+
+ //move to interface/service/config/kal_config/xxx_isr_config.h
+ //IRQ_Register_LISR(SOE_IRQ, drv_soe_lisr, "SOE handler");
+ //IRQSensitivity(SOE_IRQ, KAL_TRUE);
+ IRQClearInt(SOE_IRQ);
+ IRQUnmask(SOE_IRQ);
+
+ drv_inited = KAL_TRUE;
+ DRV_DBG_FRC_INIT(0);
+ DRV_DBG_FRC_INIT(1);
+ drv_soe_register_bbreg_dump();
+}
+
+static kal_uint32 drv_soe_gen_key_attr(drv_soe_key_attr_t *key_attr, sec_key_t *key_table)
+{
+#ifdef SOE_CHB_MODE
+ kal_uint32 kindex2;
+#endif
+ kal_uint32 i, kindex = 0;
+ kal_bool extKey = KAL_TRUE;
+
+ //Get valid key index
+ for(i=0; i < SOE_DRV_KEY_ENTRY_MAX; i++) {
+ if(!SECK_GET_VALID(key_table[i])) {
+ kindex = i;
+#ifdef SOE_CHB_MODE
+ kindex2 = (i + 1);
+#endif
+ break;
+ }
+ }
+ if(i == (SOE_KEY_ENTRY_MAX + 1)) {
+ return 1;
+ }
+
+ if (key_attr->mode == SECK_CHB) {
+ key_attr->en = SECK_DEC;
+ }
+
+ if((kal_uint32)key_attr->key >= (kal_uint32)key_table &&
+ (kal_uint32)key_attr->key < ((kal_uint32)key_table + sizeof(sec_key_t))) {
+ extKey = KAL_FALSE;
+ }
+ else {
+ memset(&key_table[kindex], 0, sizeof(sec_key_t));
+ }
+ SECK_SET_VALID(key_table[kindex]);
+ key_attr->idx = (kindex + 1);
+
+ if (key_attr->en == SECK_ENC) {
+ SECK_SET_ENC(key_table[kindex]);
+ }
+ else {
+ SECK_SET_DEC(key_table[kindex]);
+ }
+
+ if (key_attr->mode == SECK_CHB) {
+ SECK_SET_MODE(key_table[kindex], SECK_AES);
+ }
+ else {
+ SECK_SET_MODE(key_table[kindex], key_attr->mode);
+ }
+ SECK_SET_OPT(key_table[kindex], key_attr->opt);
+ SECK_SET_ALG(key_table[kindex], key_attr->alg);
+
+ if (key_attr->mode == SECK_DES && key_attr->opt == SECK_OPT_3DES) {
+ SECK_SET_3DES(key_table[kindex], key_attr->desmode);
+ }
+#if defined(SOE_MD97_HW)
+ if (key_attr->mode == SECK_RC5) {
+ rc5_para_t rc5_para;
+ rc5_para.pack.keylen = key_attr->var_key.rc5_len;
+ rc5_para.pack.block = key_attr->ops_para.rc5_attr.word_size / SECK_RC5_WORD_SIZE_BIT_INC;
+ rc5_para.pack.round = key_attr->ops_para.rc5_attr.rounds / SECK_RC5_ROUND_INC ;
+ SECK_SET_RC5_ATTR(key_table[kindex], rc5_para.p);
+ }
+
+ if (key_attr->mode == SECK_IDEA && key_attr->opt == SECK_OPT_3IDEA) {
+ SECK_SET_3IDEA(key_table[kindex], key_attr->ideamode);
+ }
+
+ if (key_attr->mode == SECK_CAST5 || key_attr->mode == SECK_CAST6 || key_attr->mode == SECK_BLOWFISH) {
+ SECK_SET_VAR_KEYLEN(key_table[kindex], key_attr->keylen);
+ }
+ if ((key_attr->mode == SECK_HASH || key_attr->mode == SECK_HMAC) && (key_attr->alg == SECK_ALG_TIGER))
+ {
+ tiger_para_t tiger_para;
+ tiger_para.pack.bits = key_attr->ops_para.tiger_attr.bits;
+ tiger_para.pack.rounds = key_attr->ops_para.tiger_attr.rounds;
+ SECK_SET_TIGER_ATTR(key_table[kindex], tiger_para.p);
+ }
+#endif
+ /*MSG(MSG_INFO, "%s mod = %d\r\n", __FUNCTION__, attr->mode);*/
+
+ if (key_attr->key && extKey) {
+ SECK_SET_KEY(key_table[kindex], key_attr->key, key_attr->keylen);
+ }
+ SOE_CACHE_STORE(&key_table[kindex], sizeof(sec_key_t));
+#ifdef SOE_CHB_MODE
+ if (key_attr->mode == SECK_CHB) {
+ if(extKey) {
+ memset(&key_table[kindex2], 0, sizeof(sec_key_t));
+ }
+ SECK_SET_VALID(key_table[kindex2]);
+ key_attr->idx2 = (kindex2 + 1);
+
+ if (key_attr->en == SECK_ENC) {
+ SECK_SET_ENC(key_table[kindex2]);
+ }
+ else {
+ SECK_SET_DEC(key_table[kindex2]);
+ }
+
+ SECK_SET_MODE(key_table[kindex2], SECK_HMAC);
+ SECK_SET_OPT(key_table[kindex2], key_attr->opt2);
+ SECK_SET_ALG(key_table[kindex2], key_attr->alg2);
+
+ if (key_attr->key2 && extKey) {
+ SECK_SET_KEY(key_table[kindex2], key_attr->key2, key_attr->keylen2);
+ }
+ SOE_CACHE_STORE(&key_table[kindex2], sizeof(sec_key_t));
+ }
+#endif
+ return 0;
+}
+
+static kal_uint32 drv_soe_list_init(drv_soe_list_attr_t *attr)
+{
+ kal_uint16 i, type;
+ gpd_t *gpd_now = NULL, *gpd_new;
+ bd_t *bd_now = NULL, *bd_new;
+ drv_soe_gpd_attr_t *gpd_attr;
+ drv_soe_key_attr_t *key_attr;
+ kal_uint32 len;
+ kal_uint8 *buf;
+
+ for (i = 0; i < attr->gpdnum; i++) {
+ /* reset variable */
+ gpd_attr = &attr->gpd[i];
+ key_attr = &attr->key[i];
+ bd_now = NULL;
+ gpd_new = gpd_attr->gpd;
+ if (gpd_now != NULL) {
+ SOE_SET_NEXT(gpd_now, virt_to_phys(gpd_new));
+ SOE_SET_CHKSUM(gpd_now, SOE_GPD_CHK);
+ }
+ memset(gpd_new, 0, GPD_SIZE);
+ SOE_SET_FLAGS_HWO(gpd_new);
+ if (gpd_attr->bd == NULL) {
+ SOE_CLR_FLAGS_BDP(gpd_new);
+ } else {
+ SOE_SET_FLAGS_BDP(gpd_new);
+ }
+ SOE_CLR_FORMAT_VR(gpd_new);
+
+ if(!SOE_IS_DYNA_DRAM((kal_uint32)gpd_attr->outbuf, gpd_attr->outlen)) {
+ return DRV_SOE_ERR_INVALID_PTR;
+ }
+ if(query_is_cached_ram((kal_uint32)gpd_attr->outbuf, gpd_attr->outlen)) {
+ SOE_CACHE_STORE(gpd_attr->outbuf, gpd_attr->outlen);
+ SOE_CACHE_INVALIDATE(gpd_attr->outbuf, gpd_attr->outlen);
+ gpd_attr->outbuf = (kal_uint8*)virt_to_phys(gpd_attr->outbuf);
+ }
+ SOE_SET_BUF_LEN(gpd_new, gpd_attr->buflen);
+ SOE_SET_OUTPTR(gpd_new, gpd_attr->outbuf);
+
+ if(gpd_attr->icblen) {
+ if(!SOE_IS_DYNA_DRAM((kal_uint32)gpd_attr->icb, gpd_attr->icblen)) {
+ return DRV_SOE_ERR_INVALID_PTR;
+ }
+ if(query_is_cached_ram((kal_uint32)gpd_attr->icb, gpd_attr->icblen)) {
+ SOE_CACHE_STORE(gpd_attr->icb, gpd_attr->icblen);
+ gpd_attr->icb = (kal_uint8*)virt_to_phys(gpd_attr->icb);
+ }
+ SOE_SET_ICBPTR(gpd_new, gpd_attr->icb);
+ if(key_attr->alg == SECK_ALG_CBC) {
+#if defined(SOE_MD97_HW) && !defined(MT6297)
+ SOE_SET_FORMAT_UI(gpd_new);
+#else
+ /* Apollo is not ready for using UI with new algorithms */
+ do {
+ if(key_attr->mode == SECK_DES || key_attr->mode == SECK_AES)
+ SOE_SET_FORMAT_UI(gpd_new);
+ }while(0);
+#endif
+ }
+ }
+ else {
+ SOE_SET_ICBPTR(gpd_new, gpd_attr->outbuf); //dummy ptr
+ }
+
+ if(gpd_attr->icvlen) {
+ if(!SOE_IS_DYNA_DRAM((kal_uint32)gpd_attr->icv, gpd_attr->icvlen)) {
+ return DRV_SOE_ERR_INVALID_PTR;
+ }
+ if(query_is_cached_ram((kal_uint32)gpd_attr->icv, gpd_attr->icvlen)) {
+ SOE_CACHE_STORE(gpd_attr->icv, gpd_attr->icvlen);
+ SOE_CACHE_INVALIDATE(gpd_attr->icv, gpd_attr->icvlen);
+ gpd_attr->icv = (kal_uint8*)virt_to_phys(gpd_attr->icv);
+ }
+ SOE_SET_ICVPTR(gpd_new, gpd_attr->icv);
+ }
+ else {
+ SOE_SET_ICVPTR(gpd_new, gpd_attr->outbuf); //dummy ptr
+ }
+ SOE_SET_KEY_IDX(gpd_new, gpd_attr->keyidx);
+#ifdef SOE_CHB_MODE
+ SOE_SET_KEY_IDX2(gpd_new, gpd_attr->keyidx2);
+ SOE_SET_CIPHER_OFFSET(gpd_new, gpd_attr->cipher_offset);
+ if (key_attr->mode == SECK_CHB) {
+ SOE_SET_FORMAT_CHB(gpd_new);
+ }
+ else {
+ SOE_CLR_FORMAT_CHB(gpd_new);
+ }
+#endif
+
+ if (gpd_attr->bd == NULL) {
+ /* No BD, set data ptr */
+ if(!SOE_IS_DYNA_DRAM((kal_uint32)gpd_attr->inbuf, gpd_attr->inlen)) {
+ return DRV_SOE_ERR_INVALID_PTR;
+ }
+ if(query_is_cached_ram((kal_uint32)gpd_attr->inbuf, gpd_attr->inlen)) {
+ SOE_CACHE_STORE(gpd_attr->inbuf, gpd_attr->inlen);
+ gpd_attr->inbuf = (kal_uint8*)virt_to_phys(gpd_attr->inbuf);
+ }
+ SOE_SET_DATA(gpd_new, gpd_attr->inbuf);
+ } else {
+ /* Generate BDs */
+ for (type = 0; type < 2; type++) {
+ if(key_attr->alg == SECK_ALG_XCBC) {
+ // XCBC
+ buf = type ? gpd_attr->inbuf : gpd_attr->icb;
+ len = type ? gpd_attr->inlen : gpd_attr->icblen;
+ }
+ else {
+ // CCM/GCM
+ buf = type ? gpd_attr->inbuf : gpd_attr->abuf;
+ len = type ? gpd_attr->inlen : gpd_attr->alen;
+ }
+
+ if(!SOE_IS_DYNA_DRAM((kal_uint32)buf, len)) {
+ return DRV_SOE_ERR_INVALID_PTR;
+ }
+ if(query_is_cached_ram((kal_uint32)buf, len)) {
+ SOE_CACHE_STORE(buf, len);
+ buf = (kal_uint8*)virt_to_phys(buf);
+ }
+ bd_new = &gpd_attr->bd[type];
+
+ /* set data ptr */
+ memset(bd_new, 0, BD_SIZE);
+ BD_SET_DATA(bd_new, buf);
+ BD_SET_BUF_LEN(bd_new, len);
+ /* set list */
+ if (bd_now == NULL) {
+ SOE_SET_BD(gpd_new, virt_to_phys(bd_new));
+ } else {
+ if(!len)
+ BD_SET_FLAGS_EOL(bd_now);
+ BD_SET_NEXT(bd_now, virt_to_phys(bd_new));
+ BD_SET_CHKSUM(bd_now, SOE_BD_CHK);
+ SOE_CACHE_STORE(bd_now, BD_SIZE);
+ }
+ if (type == 1) { /* last BD */
+ BD_SET_FLAGS_EOL(bd_new);
+ }
+ bd_now = bd_new;
+ }
+ BD_SET_CHKSUM(bd_now, SOE_BD_CHK);
+ SOE_CACHE_STORE(bd_now, BD_SIZE);
+ }
+ SOE_SET_CHKSUM(gpd_new, SOE_GPD_CHK);
+ SOE_CACHE_STORE(gpd_new, GPD_SIZE);
+ gpd_now = gpd_new;
+ }
+ /* link last GPD */
+ gpd_new = (gpd_t *)&gpd_now[1];
+ SOE_SET_NEXT(gpd_now, virt_to_phys(gpd_new));
+ SOE_SET_FLAGS_INT(gpd_now);
+ SOE_SET_CHKSUM(gpd_now, SOE_GPD_CHK);
+ SOE_CACHE_STORE(gpd_now, GPD_SIZE);
+ memset(gpd_new, 0, GPD_SIZE);
+ SOE_CACHE_STORE(gpd_new, GPD_SIZE);
+ return 0;
+}
+
+static kal_uint32 drv_soe_gen_gpd_attr(drv_soe_gpd_attr_t *attr, drv_soe_key_attr_t *key)
+{
+ kal_uint32 err = 0;
+
+ // check keylen and datalen
+ switch(key->mode) {
+ case SECK_NULL:
+ err = 0;
+ break;
+ case SECK_HMAC:
+ switch(key->alg) {
+ case SECK_ALG_MD5:
+ case SECK_ALG_SHA1:
+ case SECK_ALG_SHA256:
+#if defined(SOE_MD97_HW)
+ case SECK_ALG_TIGER:
+#endif
+ if(key->keylen != 64) err = DRV_SOE_ERR_KEYLEN;
+ break;
+ case SECK_ALG_SHA384:
+ case SECK_ALG_SHA512:
+ if(key->keylen != 128) err = DRV_SOE_ERR_KEYLEN;
+ break;
+ default:
+ err = DRV_SOE_ERR_ALG;
+ break;
+ }
+ //following check as HASH
+ case SECK_HASH:
+ if(attr->inlen > 65535) err = DRV_SOE_ERR_INLEN;
+#if defined(SOE_MD97_HW)
+ if(key->alg > SECK_ALG_TIGER) err = DRV_SOE_ERR_ALG;
+#else
+ if(key->alg > SECK_ALG_SHA512) err = DRV_SOE_ERR_ALG;
+#endif
+ switch(key->alg) {
+ case SECK_ALG_MD5:
+ if(attr->outlen != 16) err = DRV_SOE_ERR_OUTLEN;
+ break;
+ case SECK_ALG_SHA1:
+ if(attr->outlen != 20) err = DRV_SOE_ERR_OUTLEN;
+ break;
+ case SECK_ALG_SHA256:
+ if(attr->outlen != 32) err = DRV_SOE_ERR_OUTLEN;
+ break;
+ case SECK_ALG_SHA384:
+ if(attr->outlen != 48) err = DRV_SOE_ERR_OUTLEN;
+ break;
+ case SECK_ALG_SHA512:
+ if(attr->outlen != 64) err = DRV_SOE_ERR_OUTLEN;
+ break;
+#if defined(SOE_MD97_HW)
+ case SECK_ALG_TIGER:
+ if(attr->outlen != 16 && attr->outlen != 24 && attr->outlen != 32) err = DRV_SOE_ERR_OUTLEN;
+ break;
+#endif
+ default:
+ err = DRV_SOE_ERR_ALG;
+ break;
+ }
+ break;
+ case SECK_DES:
+ if(key->opt > SECK_OPT_3DES) err = DRV_SOE_ERR_OPT;
+ if(key->alg > SECK_ALG_CBC) err = DRV_SOE_ERR_ALG;
+ if(!(attr->inlen == 8 || (attr->inlen >= 16 && attr->inlen <= 65528))) err = DRV_SOE_ERR_INLEN;
+ if(attr->inlen != attr->outlen) err = DRV_SOE_ERR_OUTLEN;
+ if(key->opt == SECK_OPT_DES && key->keylen != 8) err = DRV_SOE_ERR_KEYLEN;
+ if(key->opt == SECK_OPT_3DES && key->keylen != 24) err = DRV_SOE_ERR_KEYLEN;
+ if(key->alg == SECK_ALG_CBC && attr->icblen != 8) err = DRV_SOE_ERR_ICBLEN;
+ break;
+ case SECK_AES:
+ if(key->alg != SECK_ALG_XCBC && key->alg != SECK_ALG_CMAC) {
+ if(key->opt > SECK_AES_256) err = DRV_SOE_ERR_OPT;
+ if(attr->inlen != attr->outlen) err = DRV_SOE_ERR_OUTLEN;
+ }
+ else {
+ if(key->opt > SECK_AES_128) err = DRV_SOE_ERR_OPT;
+ if(attr->inlen > 65535) err = DRV_SOE_ERR_INLEN;
+ if(key->en == SECK_DEC && attr->icvlen != 16) err = DRV_SOE_ERR_ICVLEN;
+ }
+ switch(key->alg) {
+ case SECK_ALG_CBC:
+ if(attr->icblen != 16) err = DRV_SOE_ERR_ICBLEN;
+ //following check as ECB
+ case SECK_ALG_ECB:
+ if(!(attr->inlen == 16 || (attr->inlen >= 32 && attr->inlen <= 65520))) err = DRV_SOE_ERR_INLEN;
+ break;
+ case SECK_ALG_CTR:
+ if(attr->inlen == 0 || attr->inlen > 65535) {
+ err = DRV_SOE_ERR_INLEN;
+ }
+ if(attr->icblen != 16) err = DRV_SOE_ERR_ICBLEN;
+ break;
+ case SECK_ALG_CCM:
+ case SECK_ALG_GCM:
+ //check in next stage
+ default:
+ break;
+ }
+ break;
+#if defined(SOE_MD97_HW)
+ case SECK_RC5:
+ if(key->opt != 0) err = DRV_SOE_ERR_OPT;
+ if(key->alg > SECK_ALG_CBC) err = DRV_SOE_ERR_ALG;
+ if(!(attr->inlen == 8 || (attr->inlen >= 16 && attr->inlen <= 65528))) err = DRV_SOE_ERR_INLEN;
+ if(attr->inlen != attr->outlen) err = DRV_SOE_ERR_OUTLEN;
+ if(key->alg == SECK_ALG_CBC && (attr->icblen != 4 && attr->icblen != 8 && attr->icblen != 16)) err = DRV_SOE_ERR_ICBLEN;
+ if(key->keylen == 0 /*|| key->keylen > 255 */) err = DRV_SOE_ERR_KEYLEN;
+ break;
+ case SECK_IDEA:
+ if(key->opt > SECK_OPT_3IDEA) err = DRV_SOE_ERR_OPT;
+ if(key->alg > SECK_ALG_CBC) err = DRV_SOE_ERR_ALG;
+ if(!(attr->inlen == 8 || (attr->inlen >= 16 && attr->inlen <= 65528))) err = DRV_SOE_ERR_INLEN;
+ if(attr->inlen != attr->outlen) err = DRV_SOE_ERR_OUTLEN;
+ if(key->opt == SECK_OPT_IDEA && key->keylen != 16) err = DRV_SOE_ERR_KEYLEN;
+ if(key->opt == SECK_OPT_3IDEA && key->keylen != 48) err = DRV_SOE_ERR_KEYLEN;
+ if(key->alg == SECK_ALG_CBC && attr->icblen != 8) err = DRV_SOE_ERR_ICBLEN;
+ break;
+ case SECK_CAST5:
+ if(key->opt != 0) err = DRV_SOE_ERR_OPT;
+ if(key->alg > SECK_ALG_CBC) err = DRV_SOE_ERR_ALG;
+ if(!(attr->inlen == 8 || (attr->inlen >= 16 && attr->inlen <= 65528))) err = DRV_SOE_ERR_INLEN;
+ if(attr->inlen != attr->outlen) err = DRV_SOE_ERR_OUTLEN;
+ if(key->alg == SECK_ALG_CBC && attr->icblen != 8) err = DRV_SOE_ERR_ICBLEN;
+ if(key->keylen < 5 || key->keylen > 16) err = DRV_SOE_ERR_KEYLEN;
+ break;
+ case SECK_CAST6:
+ if(key->opt != 0) err = DRV_SOE_ERR_OPT;
+ if(key->alg > SECK_ALG_CBC) err = DRV_SOE_ERR_ALG;
+ if(!(attr->inlen == 16 || (attr->inlen >= 32 && attr->inlen <= 65520))) err = DRV_SOE_ERR_INLEN;
+ if(attr->inlen != attr->outlen) err = DRV_SOE_ERR_OUTLEN;
+ if(key->alg == SECK_ALG_CBC && attr->icblen != 16) err = DRV_SOE_ERR_ICBLEN;
+ if(key->keylen < 16 || key->keylen > 32 || (key->keylen & 3) != 0) err = DRV_SOE_ERR_KEYLEN;
+ break;
+ case SECK_BLOWFISH:
+ if(key->opt != 0) err = DRV_SOE_ERR_OPT;
+ if(key->alg > SECK_ALG_CBC) err = DRV_SOE_ERR_ALG;
+ if(!(attr->inlen == 8 || (attr->inlen >= 16 && attr->inlen <= 65528))) err = DRV_SOE_ERR_INLEN;
+ if(attr->inlen != attr->outlen) err = DRV_SOE_ERR_OUTLEN;
+ if(key->alg == SECK_ALG_CBC && attr->icblen != 8) err = DRV_SOE_ERR_ICBLEN;
+ if(key->keylen < 4 || key->keylen > 56) err = DRV_SOE_ERR_KEYLEN;
+ break;
+ case SECK_CHB:
+ if (key->opt != SECK_AES_128) err = DRV_SOE_ERR_OPT;
+ if (key->alg != SECK_ALG_CBC) err = DRV_SOE_ERR_ALG;
+ if (key->alg2 > SECK_ALG_SHA256) err = 3;
+ break;
+ case SECK_RSADH:
+ if (key->opt != 0) err = DRV_SOE_ERR_OPT;
+ if (key->alg > SECK_ALG_MODEXP) err = DRV_SOE_ERR_ALG;
+ break;
+ case SECK_ECC:
+ if (key->opt != 0) err = DRV_SOE_ERR_OPT;
+ if (key->alg > SECK_ALG_PADD) err = DRV_SOE_ERR_ALG;
+ break;
+#endif
+ default:
+ err = DRV_SOE_ERR_MODE;
+ }
+
+ //check CHB mode
+ if (key->mode != SECK_CHB) {
+ if ((key->mode == SECK_AES) && (key->alg == SECK_ALG_CCM || key->alg == SECK_ALG_GCM)) {
+ attr->buflen = attr->inlen;
+ if((attr->inlen + attr->alen) > 65535) {
+ err = DRV_SOE_ERR_CHBLEN;
+ }
+ }
+ else {
+ attr->alen = 0;
+ }
+ }
+ else {
+ attr->alen = 0;
+ }
+ if(err) {
+ DRV_MSG(MSG_INFO, "%s err: %x\r\n", __FUNCTION__, err);
+ return err;
+ }
+
+ //assign keyidx
+ attr->keyidx = key->idx;
+ if (key->mode == SECK_CHB) {
+ attr->keyidx2 = key->idx2;
+ }
+ DRV_MSG(MSG_INFO, "%s keyidx:%d keyidx2:%d\r\n", __FUNCTION__, attr->keyidx, attr->keyidx2);
+
+ return 0;
+}
+
+kal_uint32 drv_soe_gen_attr(drv_soe_ctrl_struct_t *ctrl)
+{
+ drv_soe_list_attr_t *attr = &ctrl->list_attr;
+ kal_uint32 i, idx, ret;
+
+ DRV_DBG_FRC_START(0);
+
+ // check ptr
+ if(ctrl->gpd == NULL || ctrl->key == NULL) {
+ return DRV_SOE_ERR_INVALID_PTR;
+ }
+ if(!SOE_IS_DYNA_DRAM((kal_uint32)ctrl->gpd, sizeof(gpd_t))) {
+ return DRV_SOE_ERR_INVALID_PTR;
+ }
+ if(!SOE_IS_DYNA_DRAM((kal_uint32)ctrl->key, sizeof(sec_key_t))) {
+ return DRV_SOE_ERR_INVALID_PTR;
+ }
+
+ // set key table
+ for(i = 0, idx = 0; i < attr->gpdnum; i++) {
+ if(idx == (SOE_DRV_GPD_MAX + 1)) {
+ return DRV_SOE_ERR_GPD_OVERFLOW;
+ }
+
+ ret = drv_soe_gen_key_attr(&attr->key[i], ctrl->key);
+ if(ret) {
+ DRV_MSG(MSG_INFO, "%s gen_key err: %x\r\n", __FUNCTION__, ret);
+ return ret;
+ }
+
+ if(attr->gpd[i].alen > 0) {
+ ret = attr->key[i].idx - 1;
+ SECK_SET_ADATA(ctrl->key[ret], attr->gpd[i].alen);
+ SOE_CACHE_STORE(&ctrl->key[ret], sizeof(sec_key_t));
+ }
+
+ memset(&ctrl->gpd[idx], 0, sizeof(gpd_t));
+ attr->gpd[i].gpd = &ctrl->gpd[idx++];
+ ret = drv_soe_gen_gpd_attr(&attr->gpd[i], &attr->key[i]);
+ if(ret) {
+ DRV_MSG(MSG_INFO, "%s gen_gpd err: %x\r\n", __FUNCTION__, ret);
+ return ret;
+ }
+ if(attr->gpd[i].alen || (attr->key[i].mode == SECK_AES && attr->key[i].alg == SECK_ALG_XCBC && attr->gpd[i].icblen) ) {
+ memset(&ctrl->gpd[idx], 0, sizeof(gpd_t));
+ attr->gpd[i].bd = (bd_t*)&ctrl->gpd[attr->gpdnum + idx];
+ }
+ }
+ ret = drv_soe_list_init(attr);
+
+#ifdef ATEST_ENABLE
+ if(!ret)
+ ctrl->r_gpd_cnt += attr->gpdnum;
+#endif
+ DRV_DBG_FRC_END(0);
+ return ret;
+}
+
+kal_uint32 drv_soe_update_attr(drv_soe_ctrl_struct_t *ctrl)
+{
+ drv_soe_list_attr_t *attr = &ctrl->list_attr;
+ kal_uint32 ret;
+
+ DRV_DBG_FRC_START(0);
+
+ // check ctrl
+ if(!SOE_GET_NEXT(ctrl->gpd)) {
+ return DRV_SOE_ERR_INVALID_GPD;
+ }
+
+ // update GPD
+ ret = drv_soe_list_init(attr);
+
+#ifdef ATEST_ENABLE
+ if(!ret)
+ ctrl->r_gpd_cnt += attr->gpdnum;
+#endif
+ DRV_DBG_FRC_END(0);
+ return ret;
+}
+
+kal_uint32 drv_soe_trigger(gpd_t *pGpd, sec_key_t *pKey)
+{
+ kal_uint32 err = 0;
+ kal_uint32 event_group = 0;
+ kal_uint32 soe_timeout_ticks;
+ gpd_t *last_gpd = pGpd;
+
+ //check GPD/KEY
+ if(last_gpd == NULL || pKey == NULL) return DRV_SOE_ERR_INVALID_PTR;
+ if((kal_uint32)last_gpd & 0x3) return DRV_SOE_ERR_INVALID_PTR;
+ if((kal_uint32)pKey & 0x3) return DRV_SOE_ERR_INVALID_PTR;
+ if(!SOE_IS_DYNA_DRAM((kal_uint32)pGpd, sizeof(gpd_t))) return DRV_SOE_ERR_INVALID_PTR;
+
+ pKey = (sec_key_t*)((kal_uint32)pKey - sizeof(sec_key_t));
+ if(!SOE_IS_DYNA_DRAM((kal_uint32)pKey, sizeof(sec_key_t))) return DRV_SOE_ERR_INVALID_PTR;
+ while(SOE_IS_FLAGS_HWO(last_gpd)) {
+ if(!SECK_GET_VALID(pKey[last_gpd->keyidx])) return DRV_SOE_ERR_INVALID_KEY;
+ if(last_gpd->pnext == NULL) return DRV_SOE_ERR_INVALID_PNEXT;
+ if(last_gpd->icbptr == NULL) return DRV_SOE_ERR_INVALID_ICB;
+ if(last_gpd->icvptr == NULL) return DRV_SOE_ERR_INVALID_ICV;
+ last_gpd = last_gpd->pnext;
+ }
+ if(last_gpd == pGpd) return DRV_SOE_ERR_INVALID_GPD;
+
+ DRV_DBG_FRC_START(0);
+
+ //check drv init
+ if(!drv_inited) {
+ drv_soe_init();
+ }
+
+ //mutex lock
+ kal_take_enh_mutex(drv_soe_locker);
+ SleepDrv_LockSleep(SLEEP_CTL_SOE, SMP);
+ PDN_CLR(PDN_SOE);
+
+ //check SOE status
+ Data_Mem_Barrier();
+ if(SOE_REG(SOE_QCSR) & SOQ_STAT) {
+ err = DRV_SOE_ERR_STAT_BUSY;
+ goto EngineError;
+ }
+
+ //unmask irq
+#ifndef DRV_DISABLE_IRQ
+ if(drv_soe_irq_en) {
+ SOE_REG(SOE_L2ISAR) = 0xFFFFFFFF;
+ SOE_REG(SOE_L2IMCR) = 0xFFFFFFFF;
+ IRQClearInt(SOE_IRQ);
+ IRQUnmask(SOE_IRQ);
+ }
+#endif
+
+ //config SOE
+#if defined(MT6297)
+ SOE_REG(SOE_ASYM_STATUS_REG7) = 0xFFFFFFFF;
+#endif
+ SOE_REG(SOE_CR) = (SOE_CS_EN | SOE_CSALL_EN);
+ drv_soe_set_reg(SOE_CR, SOE_DMA_MODE, SOE_DMA_MODE, SOE_DMA_MODE_BITS);
+ if(query_is_cached_ram((kal_uint32)pKey, sizeof(sec_key_t))) {
+ SOE_REG(SOE_KTSAR) = virt_to_phys(pKey);
+ }
+ else {
+ SOE_REG(SOE_KTSAR) = (kal_uint32)pKey;
+ }
+ if(query_is_cached_ram((kal_uint32)pGpd, sizeof(gpd_t))) {
+ SOE_REG(SOE_QSAR) = virt_to_phys(pGpd);
+ }
+ else {
+ SOE_REG(SOE_QSAR) = (kal_uint32)pGpd;
+ }
+
+ //start queue
+ Data_Mem_Barrier();
+ DRV_DBG_FRC_START(1);
+ SOE_REG(SOE_QCSR) = SOQ_START;
+ Data_Sync_Barrier();
+
+ //wait done
+#ifndef DRV_DISABLE_IRQ
+ if(drv_soe_irq_en) {
+ kal_retrieve_eg_events(drv_soe_egid, (SO_ERROR_MASK | SO_DONE), KAL_OR_CONSUME, &event_group, KAL_SUSPEND);
+ }
+ else
+#endif
+ {
+ soe_timeout_ticks = drv_get_current_time();
+ while(SOE_REG(SOE_QCSR) & SOQ_STAT) {
+ if(drv_get_duration_ms(soe_timeout_ticks) > 8000) {
+ DRV_DBG_FRC_END(1);
+ err = DRV_SOE_ERR_STAT_BUSY;
+ goto EngineError;
+ }
+ }
+ event_group = SOE_REG(SOE_L2ISAR);
+ #if defined(MT6297)
+ event_group |= (SOE_REG(SOE_ASYM_STATUS_REG7) << 8);
+ #endif
+ }
+ DRV_DBG_FRC_END(1);
+ if(event_group & SO_GPD_CSERR) err = DRV_SOE_ERR_GPD_CSERR;
+ if(event_group & SO_BD_CSERR) err = DRV_SOE_ERR_BD_CSERR;
+ if(event_group & SO_LENERR) err = DRV_SOE_ERR_LENERR;
+ if(event_group & SO_KTERR) err = DRV_SOE_ERR_KTERR;
+ if(SOE_IS_FORMAT_VR(pGpd)) err = DRV_SOE_ERR_VRERR;
+ if(event_group & SO_ASYM_ERROR_MASK) err = DRV_SOE_ERR_ASYMERR;
+ if(err) goto EngineError;
+
+ SOE_REG(SOE_L2IMSR) = 0xFFFFFFFF;
+ Data_Sync_Barrier();
+EngineError:
+ PDN_SET(PDN_SOE);
+ SleepDrv_UnlockSleep(SLEEP_CTL_SOE, SMP);
+ kal_give_enh_mutex(drv_soe_locker);
+ DRV_DBG_FRC_END(0);
+ return err;
+}
+
+void drv_soe_cache_ctrl(kal_bool clean, kal_bool invalidate, kal_uint32 addr, kal_uint32 ln)
+{
+ if(clean)
+ SOE_CACHE_STORE(addr, ln);
+ if(invalidate)
+ SOE_CACHE_INVALIDATE(addr, ln);
+}
+
+void* drv_soe_memcpy(kal_uint8 *dst, kal_uint8 *src, kal_uint32 ln)
+{
+ return memcpy((kal_uint8*)virt_to_phys(dst), \
+ (kal_uint8*)virt_to_phys(src), \
+ ln);
+}
+
+//Call from devdrv_common.c Drv_Init_Phase2()
+void SOE_Drv_Init(void)
+{
+ drv_soe_init();
+ PDN_SET(PDN_SOE);
+}