Imported Upstream version 17.05
[deb_dpdk.git] / drivers / crypto / dpaa2_sec / hw / rta / operation_cmd.h
diff --git a/drivers/crypto/dpaa2_sec/hw/rta/operation_cmd.h b/drivers/crypto/dpaa2_sec/hw/rta/operation_cmd.h
new file mode 100644 (file)
index 0000000..5e88fb4
--- /dev/null
@@ -0,0 +1,599 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ *   BSD LICENSE
+ *
+ * Copyright 2008-2016 Freescale Semiconductor Inc.
+ * Copyright (c) 2016 NXP.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *   GPL LICENSE SUMMARY
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __RTA_OPERATION_CMD_H__
+#define __RTA_OPERATION_CMD_H__
+
+extern enum rta_sec_era rta_sec_era;
+
+static inline int
+__rta_alg_aai_aes(uint16_t aai)
+{
+       uint16_t aes_mode = aai & OP_ALG_AESA_MODE_MASK;
+
+       if (aai & OP_ALG_AAI_C2K) {
+               if (rta_sec_era < RTA_SEC_ERA_5)
+                       return -1;
+               if ((aes_mode != OP_ALG_AAI_CCM) &&
+                   (aes_mode != OP_ALG_AAI_GCM))
+                       return -EINVAL;
+       }
+
+       switch (aes_mode) {
+       case OP_ALG_AAI_CBC_CMAC:
+       case OP_ALG_AAI_CTR_CMAC_LTE:
+       case OP_ALG_AAI_CTR_CMAC:
+               if (rta_sec_era < RTA_SEC_ERA_2)
+                       return -EINVAL;
+               /* no break */
+       case OP_ALG_AAI_CTR:
+       case OP_ALG_AAI_CBC:
+       case OP_ALG_AAI_ECB:
+       case OP_ALG_AAI_OFB:
+       case OP_ALG_AAI_CFB:
+       case OP_ALG_AAI_XTS:
+       case OP_ALG_AAI_CMAC:
+       case OP_ALG_AAI_XCBC_MAC:
+       case OP_ALG_AAI_CCM:
+       case OP_ALG_AAI_GCM:
+       case OP_ALG_AAI_CBC_XCBCMAC:
+       case OP_ALG_AAI_CTR_XCBCMAC:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_alg_aai_des(uint16_t aai)
+{
+       uint16_t aai_code = (uint16_t)(aai & ~OP_ALG_AAI_CHECKODD);
+
+       switch (aai_code) {
+       case OP_ALG_AAI_CBC:
+       case OP_ALG_AAI_ECB:
+       case OP_ALG_AAI_CFB:
+       case OP_ALG_AAI_OFB:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_alg_aai_md5(uint16_t aai)
+{
+       switch (aai) {
+       case OP_ALG_AAI_HMAC:
+               if (rta_sec_era < RTA_SEC_ERA_2)
+                       return -EINVAL;
+               /* no break */
+       case OP_ALG_AAI_SMAC:
+       case OP_ALG_AAI_HASH:
+       case OP_ALG_AAI_HMAC_PRECOMP:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_alg_aai_sha(uint16_t aai)
+{
+       switch (aai) {
+       case OP_ALG_AAI_HMAC:
+               if (rta_sec_era < RTA_SEC_ERA_2)
+                       return -EINVAL;
+               /* no break */
+       case OP_ALG_AAI_HASH:
+       case OP_ALG_AAI_HMAC_PRECOMP:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_alg_aai_rng(uint16_t aai)
+{
+       uint16_t rng_mode = aai & OP_ALG_RNG_MODE_MASK;
+       uint16_t rng_sh = aai & OP_ALG_AAI_RNG4_SH_MASK;
+
+       switch (rng_mode) {
+       case OP_ALG_AAI_RNG:
+       case OP_ALG_AAI_RNG_NZB:
+       case OP_ALG_AAI_RNG_OBP:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* State Handle bits are valid only for SEC Era >= 5 */
+       if ((rta_sec_era < RTA_SEC_ERA_5) && rng_sh)
+               return -EINVAL;
+
+       /* PS, AI, SK bits are also valid only for SEC Era >= 5 */
+       if ((rta_sec_era < RTA_SEC_ERA_5) && (aai &
+            (OP_ALG_AAI_RNG4_PS | OP_ALG_AAI_RNG4_AI | OP_ALG_AAI_RNG4_SK)))
+               return -EINVAL;
+
+       switch (rng_sh) {
+       case OP_ALG_AAI_RNG4_SH_0:
+       case OP_ALG_AAI_RNG4_SH_1:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_alg_aai_crc(uint16_t aai)
+{
+       uint16_t aai_code = aai & OP_ALG_CRC_POLY_MASK;
+
+       switch (aai_code) {
+       case OP_ALG_AAI_802:
+       case OP_ALG_AAI_3385:
+       case OP_ALG_AAI_CUST_POLY:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_alg_aai_kasumi(uint16_t aai)
+{
+       switch (aai) {
+       case OP_ALG_AAI_GSM:
+       case OP_ALG_AAI_EDGE:
+       case OP_ALG_AAI_F8:
+       case OP_ALG_AAI_F9:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_alg_aai_snow_f9(uint16_t aai)
+{
+       if (aai == OP_ALG_AAI_F9)
+               return 0;
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_alg_aai_snow_f8(uint16_t aai)
+{
+       if (aai == OP_ALG_AAI_F8)
+               return 0;
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_alg_aai_zuce(uint16_t aai)
+{
+       if (aai == OP_ALG_AAI_F8)
+               return 0;
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_alg_aai_zuca(uint16_t aai)
+{
+       if (aai == OP_ALG_AAI_F9)
+               return 0;
+
+       return -EINVAL;
+}
+
+struct alg_aai_map {
+       uint32_t chipher_algo;
+       int (*aai_func)(uint16_t);
+       uint32_t class;
+};
+
+static const struct alg_aai_map alg_table[] = {
+/*1*/  { OP_ALG_ALGSEL_AES,      __rta_alg_aai_aes,    OP_TYPE_CLASS1_ALG },
+       { OP_ALG_ALGSEL_DES,      __rta_alg_aai_des,    OP_TYPE_CLASS1_ALG },
+       { OP_ALG_ALGSEL_3DES,     __rta_alg_aai_des,    OP_TYPE_CLASS1_ALG },
+       { OP_ALG_ALGSEL_MD5,      __rta_alg_aai_md5,    OP_TYPE_CLASS2_ALG },
+       { OP_ALG_ALGSEL_SHA1,     __rta_alg_aai_md5,    OP_TYPE_CLASS2_ALG },
+       { OP_ALG_ALGSEL_SHA224,   __rta_alg_aai_sha,    OP_TYPE_CLASS2_ALG },
+       { OP_ALG_ALGSEL_SHA256,   __rta_alg_aai_sha,    OP_TYPE_CLASS2_ALG },
+       { OP_ALG_ALGSEL_SHA384,   __rta_alg_aai_sha,    OP_TYPE_CLASS2_ALG },
+       { OP_ALG_ALGSEL_SHA512,   __rta_alg_aai_sha,    OP_TYPE_CLASS2_ALG },
+       { OP_ALG_ALGSEL_RNG,      __rta_alg_aai_rng,    OP_TYPE_CLASS1_ALG },
+/*11*/ { OP_ALG_ALGSEL_CRC,      __rta_alg_aai_crc,    OP_TYPE_CLASS2_ALG },
+       { OP_ALG_ALGSEL_ARC4,     NULL,                 OP_TYPE_CLASS1_ALG },
+       { OP_ALG_ALGSEL_SNOW_F8,  __rta_alg_aai_snow_f8, OP_TYPE_CLASS1_ALG },
+/*14*/ { OP_ALG_ALGSEL_KASUMI,   __rta_alg_aai_kasumi, OP_TYPE_CLASS1_ALG },
+       { OP_ALG_ALGSEL_SNOW_F9,  __rta_alg_aai_snow_f9, OP_TYPE_CLASS2_ALG },
+       { OP_ALG_ALGSEL_ZUCE,     __rta_alg_aai_zuce,   OP_TYPE_CLASS1_ALG },
+/*17*/ { OP_ALG_ALGSEL_ZUCA,     __rta_alg_aai_zuca,   OP_TYPE_CLASS2_ALG }
+};
+
+/*
+ * Allowed OPERATION algorithms for each SEC Era.
+ * Values represent the number of entries from alg_table[] that are supported.
+ */
+static const unsigned int alg_table_sz[] = {14, 15, 15, 15, 17, 17, 11, 17};
+
+static inline int
+rta_operation(struct program *program, uint32_t cipher_algo,
+             uint16_t aai, uint8_t algo_state,
+             int icv_checking, int enc)
+{
+       uint32_t opcode = CMD_OPERATION;
+       unsigned int i, found = 0;
+       unsigned int start_pc = program->current_pc;
+       int ret;
+
+       for (i = 0; i < alg_table_sz[rta_sec_era]; i++) {
+               if (alg_table[i].chipher_algo == cipher_algo) {
+                       opcode |= cipher_algo | alg_table[i].class;
+                       /* nothing else to verify */
+                       if (alg_table[i].aai_func == NULL) {
+                               found = 1;
+                               break;
+                       }
+
+                       aai &= OP_ALG_AAI_MASK;
+
+                       ret = (*alg_table[i].aai_func)(aai);
+                       if (ret < 0) {
+                               pr_err("OPERATION: Bad AAI Type. SEC Program Line: %d\n",
+                                      program->current_pc);
+                               goto err;
+                       }
+                       opcode |= aai;
+                       found = 1;
+                       break;
+               }
+       }
+       if (!found) {
+               pr_err("OPERATION: Invalid Command. SEC Program Line: %d\n",
+                      program->current_pc);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       switch (algo_state) {
+       case OP_ALG_AS_UPDATE:
+       case OP_ALG_AS_INIT:
+       case OP_ALG_AS_FINALIZE:
+       case OP_ALG_AS_INITFINAL:
+               opcode |= algo_state;
+               break;
+       default:
+               pr_err("Invalid Operation Command\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       switch (icv_checking) {
+       case ICV_CHECK_DISABLE:
+               /*
+                * opcode |= OP_ALG_ICV_OFF;
+                * OP_ALG_ICV_OFF is 0
+                */
+               break;
+       case ICV_CHECK_ENABLE:
+               opcode |= OP_ALG_ICV_ON;
+               break;
+       default:
+               pr_err("Invalid Operation Command\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       switch (enc) {
+       case DIR_DEC:
+               /*
+                * opcode |= OP_ALG_DECRYPT;
+                * OP_ALG_DECRYPT is 0
+                */
+               break;
+       case DIR_ENC:
+               opcode |= OP_ALG_ENCRYPT;
+               break;
+       default:
+               pr_err("Invalid Operation Command\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       __rta_out32(program, opcode);
+       program->current_instruction++;
+       return (int)start_pc;
+
+ err:
+       program->first_error_pc = start_pc;
+       return ret;
+}
+
+/*
+ * OPERATION PKHA routines
+ */
+static inline int
+__rta_pkha_clearmem(uint32_t pkha_op)
+{
+       switch (pkha_op) {
+       case (OP_ALG_PKMODE_CLEARMEM_ALL):
+       case (OP_ALG_PKMODE_CLEARMEM_ABE):
+       case (OP_ALG_PKMODE_CLEARMEM_ABN):
+       case (OP_ALG_PKMODE_CLEARMEM_AB):
+       case (OP_ALG_PKMODE_CLEARMEM_AEN):
+       case (OP_ALG_PKMODE_CLEARMEM_AE):
+       case (OP_ALG_PKMODE_CLEARMEM_AN):
+       case (OP_ALG_PKMODE_CLEARMEM_A):
+       case (OP_ALG_PKMODE_CLEARMEM_BEN):
+       case (OP_ALG_PKMODE_CLEARMEM_BE):
+       case (OP_ALG_PKMODE_CLEARMEM_BN):
+       case (OP_ALG_PKMODE_CLEARMEM_B):
+       case (OP_ALG_PKMODE_CLEARMEM_EN):
+       case (OP_ALG_PKMODE_CLEARMEM_N):
+       case (OP_ALG_PKMODE_CLEARMEM_E):
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_pkha_mod_arithmetic(uint32_t pkha_op)
+{
+       pkha_op &= (uint32_t)~OP_ALG_PKMODE_OUT_A;
+
+       switch (pkha_op) {
+       case (OP_ALG_PKMODE_MOD_ADD):
+       case (OP_ALG_PKMODE_MOD_SUB_AB):
+       case (OP_ALG_PKMODE_MOD_SUB_BA):
+       case (OP_ALG_PKMODE_MOD_MULT):
+       case (OP_ALG_PKMODE_MOD_MULT_IM):
+       case (OP_ALG_PKMODE_MOD_MULT_IM_OM):
+       case (OP_ALG_PKMODE_MOD_EXPO):
+       case (OP_ALG_PKMODE_MOD_EXPO_TEQ):
+       case (OP_ALG_PKMODE_MOD_EXPO_IM):
+       case (OP_ALG_PKMODE_MOD_EXPO_IM_TEQ):
+       case (OP_ALG_PKMODE_MOD_REDUCT):
+       case (OP_ALG_PKMODE_MOD_INV):
+       case (OP_ALG_PKMODE_MOD_MONT_CNST):
+       case (OP_ALG_PKMODE_MOD_CRT_CNST):
+       case (OP_ALG_PKMODE_MOD_GCD):
+       case (OP_ALG_PKMODE_MOD_PRIMALITY):
+       case (OP_ALG_PKMODE_MOD_SML_EXP):
+       case (OP_ALG_PKMODE_F2M_ADD):
+       case (OP_ALG_PKMODE_F2M_MUL):
+       case (OP_ALG_PKMODE_F2M_MUL_IM):
+       case (OP_ALG_PKMODE_F2M_MUL_IM_OM):
+       case (OP_ALG_PKMODE_F2M_EXP):
+       case (OP_ALG_PKMODE_F2M_EXP_TEQ):
+       case (OP_ALG_PKMODE_F2M_AMODN):
+       case (OP_ALG_PKMODE_F2M_INV):
+       case (OP_ALG_PKMODE_F2M_R2):
+       case (OP_ALG_PKMODE_F2M_GCD):
+       case (OP_ALG_PKMODE_F2M_SML_EXP):
+       case (OP_ALG_PKMODE_ECC_F2M_ADD):
+       case (OP_ALG_PKMODE_ECC_F2M_ADD_IM_OM_PROJ):
+       case (OP_ALG_PKMODE_ECC_F2M_DBL):
+       case (OP_ALG_PKMODE_ECC_F2M_DBL_IM_OM_PROJ):
+       case (OP_ALG_PKMODE_ECC_F2M_MUL):
+       case (OP_ALG_PKMODE_ECC_F2M_MUL_TEQ):
+       case (OP_ALG_PKMODE_ECC_F2M_MUL_R2):
+       case (OP_ALG_PKMODE_ECC_F2M_MUL_R2_TEQ):
+       case (OP_ALG_PKMODE_ECC_F2M_MUL_R2_PROJ):
+       case (OP_ALG_PKMODE_ECC_F2M_MUL_R2_PROJ_TEQ):
+       case (OP_ALG_PKMODE_ECC_MOD_ADD):
+       case (OP_ALG_PKMODE_ECC_MOD_ADD_IM_OM_PROJ):
+       case (OP_ALG_PKMODE_ECC_MOD_DBL):
+       case (OP_ALG_PKMODE_ECC_MOD_DBL_IM_OM_PROJ):
+       case (OP_ALG_PKMODE_ECC_MOD_MUL):
+       case (OP_ALG_PKMODE_ECC_MOD_MUL_TEQ):
+       case (OP_ALG_PKMODE_ECC_MOD_MUL_R2):
+       case (OP_ALG_PKMODE_ECC_MOD_MUL_R2_TEQ):
+       case (OP_ALG_PKMODE_ECC_MOD_MUL_R2_PROJ):
+       case (OP_ALG_PKMODE_ECC_MOD_MUL_R2_PROJ_TEQ):
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_pkha_copymem(uint32_t pkha_op)
+{
+       switch (pkha_op) {
+       case (OP_ALG_PKMODE_COPY_NSZ_A0_B0):
+       case (OP_ALG_PKMODE_COPY_NSZ_A0_B1):
+       case (OP_ALG_PKMODE_COPY_NSZ_A0_B2):
+       case (OP_ALG_PKMODE_COPY_NSZ_A0_B3):
+       case (OP_ALG_PKMODE_COPY_NSZ_A1_B0):
+       case (OP_ALG_PKMODE_COPY_NSZ_A1_B1):
+       case (OP_ALG_PKMODE_COPY_NSZ_A1_B2):
+       case (OP_ALG_PKMODE_COPY_NSZ_A1_B3):
+       case (OP_ALG_PKMODE_COPY_NSZ_A2_B0):
+       case (OP_ALG_PKMODE_COPY_NSZ_A2_B1):
+       case (OP_ALG_PKMODE_COPY_NSZ_A2_B2):
+       case (OP_ALG_PKMODE_COPY_NSZ_A2_B3):
+       case (OP_ALG_PKMODE_COPY_NSZ_A3_B0):
+       case (OP_ALG_PKMODE_COPY_NSZ_A3_B1):
+       case (OP_ALG_PKMODE_COPY_NSZ_A3_B2):
+       case (OP_ALG_PKMODE_COPY_NSZ_A3_B3):
+       case (OP_ALG_PKMODE_COPY_NSZ_B0_A0):
+       case (OP_ALG_PKMODE_COPY_NSZ_B0_A1):
+       case (OP_ALG_PKMODE_COPY_NSZ_B0_A2):
+       case (OP_ALG_PKMODE_COPY_NSZ_B0_A3):
+       case (OP_ALG_PKMODE_COPY_NSZ_B1_A0):
+       case (OP_ALG_PKMODE_COPY_NSZ_B1_A1):
+       case (OP_ALG_PKMODE_COPY_NSZ_B1_A2):
+       case (OP_ALG_PKMODE_COPY_NSZ_B1_A3):
+       case (OP_ALG_PKMODE_COPY_NSZ_B2_A0):
+       case (OP_ALG_PKMODE_COPY_NSZ_B2_A1):
+       case (OP_ALG_PKMODE_COPY_NSZ_B2_A2):
+       case (OP_ALG_PKMODE_COPY_NSZ_B2_A3):
+       case (OP_ALG_PKMODE_COPY_NSZ_B3_A0):
+       case (OP_ALG_PKMODE_COPY_NSZ_B3_A1):
+       case (OP_ALG_PKMODE_COPY_NSZ_B3_A2):
+       case (OP_ALG_PKMODE_COPY_NSZ_B3_A3):
+       case (OP_ALG_PKMODE_COPY_NSZ_A_E):
+       case (OP_ALG_PKMODE_COPY_NSZ_A_N):
+       case (OP_ALG_PKMODE_COPY_NSZ_B_E):
+       case (OP_ALG_PKMODE_COPY_NSZ_B_N):
+       case (OP_ALG_PKMODE_COPY_NSZ_N_A):
+       case (OP_ALG_PKMODE_COPY_NSZ_N_B):
+       case (OP_ALG_PKMODE_COPY_NSZ_N_E):
+       case (OP_ALG_PKMODE_COPY_SSZ_A0_B0):
+       case (OP_ALG_PKMODE_COPY_SSZ_A0_B1):
+       case (OP_ALG_PKMODE_COPY_SSZ_A0_B2):
+       case (OP_ALG_PKMODE_COPY_SSZ_A0_B3):
+       case (OP_ALG_PKMODE_COPY_SSZ_A1_B0):
+       case (OP_ALG_PKMODE_COPY_SSZ_A1_B1):
+       case (OP_ALG_PKMODE_COPY_SSZ_A1_B2):
+       case (OP_ALG_PKMODE_COPY_SSZ_A1_B3):
+       case (OP_ALG_PKMODE_COPY_SSZ_A2_B0):
+       case (OP_ALG_PKMODE_COPY_SSZ_A2_B1):
+       case (OP_ALG_PKMODE_COPY_SSZ_A2_B2):
+       case (OP_ALG_PKMODE_COPY_SSZ_A2_B3):
+       case (OP_ALG_PKMODE_COPY_SSZ_A3_B0):
+       case (OP_ALG_PKMODE_COPY_SSZ_A3_B1):
+       case (OP_ALG_PKMODE_COPY_SSZ_A3_B2):
+       case (OP_ALG_PKMODE_COPY_SSZ_A3_B3):
+       case (OP_ALG_PKMODE_COPY_SSZ_B0_A0):
+       case (OP_ALG_PKMODE_COPY_SSZ_B0_A1):
+       case (OP_ALG_PKMODE_COPY_SSZ_B0_A2):
+       case (OP_ALG_PKMODE_COPY_SSZ_B0_A3):
+       case (OP_ALG_PKMODE_COPY_SSZ_B1_A0):
+       case (OP_ALG_PKMODE_COPY_SSZ_B1_A1):
+       case (OP_ALG_PKMODE_COPY_SSZ_B1_A2):
+       case (OP_ALG_PKMODE_COPY_SSZ_B1_A3):
+       case (OP_ALG_PKMODE_COPY_SSZ_B2_A0):
+       case (OP_ALG_PKMODE_COPY_SSZ_B2_A1):
+       case (OP_ALG_PKMODE_COPY_SSZ_B2_A2):
+       case (OP_ALG_PKMODE_COPY_SSZ_B2_A3):
+       case (OP_ALG_PKMODE_COPY_SSZ_B3_A0):
+       case (OP_ALG_PKMODE_COPY_SSZ_B3_A1):
+       case (OP_ALG_PKMODE_COPY_SSZ_B3_A2):
+       case (OP_ALG_PKMODE_COPY_SSZ_B3_A3):
+       case (OP_ALG_PKMODE_COPY_SSZ_A_E):
+       case (OP_ALG_PKMODE_COPY_SSZ_A_N):
+       case (OP_ALG_PKMODE_COPY_SSZ_B_E):
+       case (OP_ALG_PKMODE_COPY_SSZ_B_N):
+       case (OP_ALG_PKMODE_COPY_SSZ_N_A):
+       case (OP_ALG_PKMODE_COPY_SSZ_N_B):
+       case (OP_ALG_PKMODE_COPY_SSZ_N_E):
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+rta_pkha_operation(struct program *program, uint32_t op_pkha)
+{
+       uint32_t opcode = CMD_OPERATION | OP_TYPE_PK | OP_ALG_PK;
+       uint32_t pkha_func;
+       unsigned int start_pc = program->current_pc;
+       int ret = -EINVAL;
+
+       pkha_func = op_pkha & OP_ALG_PK_FUN_MASK;
+
+       switch (pkha_func) {
+       case (OP_ALG_PKMODE_CLEARMEM):
+               ret = __rta_pkha_clearmem(op_pkha);
+               if (ret < 0) {
+                       pr_err("OPERATION PKHA: Type not supported. SEC Program Line: %d\n",
+                              program->current_pc);
+                       goto err;
+               }
+               break;
+       case (OP_ALG_PKMODE_MOD_ADD):
+       case (OP_ALG_PKMODE_MOD_SUB_AB):
+       case (OP_ALG_PKMODE_MOD_SUB_BA):
+       case (OP_ALG_PKMODE_MOD_MULT):
+       case (OP_ALG_PKMODE_MOD_EXPO):
+       case (OP_ALG_PKMODE_MOD_REDUCT):
+       case (OP_ALG_PKMODE_MOD_INV):
+       case (OP_ALG_PKMODE_MOD_MONT_CNST):
+       case (OP_ALG_PKMODE_MOD_CRT_CNST):
+       case (OP_ALG_PKMODE_MOD_GCD):
+       case (OP_ALG_PKMODE_MOD_PRIMALITY):
+       case (OP_ALG_PKMODE_MOD_SML_EXP):
+       case (OP_ALG_PKMODE_ECC_MOD_ADD):
+       case (OP_ALG_PKMODE_ECC_MOD_DBL):
+       case (OP_ALG_PKMODE_ECC_MOD_MUL):
+               ret = __rta_pkha_mod_arithmetic(op_pkha);
+               if (ret < 0) {
+                       pr_err("OPERATION PKHA: Type not supported. SEC Program Line: %d\n",
+                              program->current_pc);
+                       goto err;
+               }
+               break;
+       case (OP_ALG_PKMODE_COPY_NSZ):
+       case (OP_ALG_PKMODE_COPY_SSZ):
+               ret = __rta_pkha_copymem(op_pkha);
+               if (ret < 0) {
+                       pr_err("OPERATION PKHA: Type not supported. SEC Program Line: %d\n",
+                              program->current_pc);
+                       goto err;
+               }
+               break;
+       default:
+               pr_err("Invalid Operation Command\n");
+               goto err;
+       }
+
+       opcode |= op_pkha;
+
+       __rta_out32(program, opcode);
+       program->current_instruction++;
+       return (int)start_pc;
+
+ err:
+       program->first_error_pc = start_pc;
+       program->current_instruction++;
+       return ret;
+}
+
+#endif /* __RTA_OPERATION_CMD_H__ */