18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/** 38c2ecf20Sopenharmony_ci * Copyright (C) ST-Ericsson SA 2010 48c2ecf20Sopenharmony_ci * Author: Shujuan Chen <shujuan.chen@stericsson.com> for ST-Ericsson. 58c2ecf20Sopenharmony_ci * Author: Jonas Linde <jonas.linde@stericsson.com> for ST-Ericsson. 68c2ecf20Sopenharmony_ci * Author: Niklas Hernaeus <niklas.hernaeus@stericsson.com> for ST-Ericsson. 78c2ecf20Sopenharmony_ci * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson. 88c2ecf20Sopenharmony_ci * Author: Berne Hebark <berne.herbark@stericsson.com> for ST-Ericsson. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/errno.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/types.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "cryp_p.h" 168c2ecf20Sopenharmony_ci#include "cryp.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/** 198c2ecf20Sopenharmony_ci * cryp_wait_until_done - wait until the device logic is not busy 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_civoid cryp_wait_until_done(struct cryp_device_data *device_data) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci while (cryp_is_logic_busy(device_data)) 248c2ecf20Sopenharmony_ci cpu_relax(); 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/** 288c2ecf20Sopenharmony_ci * cryp_check - This routine checks Peripheral and PCell Id 298c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_ciint cryp_check(struct cryp_device_data *device_data) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci int peripheralid2 = 0; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci if (NULL == device_data) 368c2ecf20Sopenharmony_ci return -EINVAL; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci peripheralid2 = readl_relaxed(&device_data->base->periphId2); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci if (peripheralid2 != CRYP_PERIPHERAL_ID2_DB8500) 418c2ecf20Sopenharmony_ci return -EPERM; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci /* Check Peripheral and Pcell Id Register for CRYP */ 448c2ecf20Sopenharmony_ci if ((CRYP_PERIPHERAL_ID0 == 458c2ecf20Sopenharmony_ci readl_relaxed(&device_data->base->periphId0)) 468c2ecf20Sopenharmony_ci && (CRYP_PERIPHERAL_ID1 == 478c2ecf20Sopenharmony_ci readl_relaxed(&device_data->base->periphId1)) 488c2ecf20Sopenharmony_ci && (CRYP_PERIPHERAL_ID3 == 498c2ecf20Sopenharmony_ci readl_relaxed(&device_data->base->periphId3)) 508c2ecf20Sopenharmony_ci && (CRYP_PCELL_ID0 == 518c2ecf20Sopenharmony_ci readl_relaxed(&device_data->base->pcellId0)) 528c2ecf20Sopenharmony_ci && (CRYP_PCELL_ID1 == 538c2ecf20Sopenharmony_ci readl_relaxed(&device_data->base->pcellId1)) 548c2ecf20Sopenharmony_ci && (CRYP_PCELL_ID2 == 558c2ecf20Sopenharmony_ci readl_relaxed(&device_data->base->pcellId2)) 568c2ecf20Sopenharmony_ci && (CRYP_PCELL_ID3 == 578c2ecf20Sopenharmony_ci readl_relaxed(&device_data->base->pcellId3))) { 588c2ecf20Sopenharmony_ci return 0; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci return -EPERM; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/** 658c2ecf20Sopenharmony_ci * cryp_activity - This routine enables/disable the cryptography function. 668c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 678c2ecf20Sopenharmony_ci * @cryp_crypen: Enable/Disable functionality 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_civoid cryp_activity(struct cryp_device_data *device_data, 708c2ecf20Sopenharmony_ci enum cryp_crypen cryp_crypen) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci CRYP_PUT_BITS(&device_data->base->cr, 738c2ecf20Sopenharmony_ci cryp_crypen, 748c2ecf20Sopenharmony_ci CRYP_CR_CRYPEN_POS, 758c2ecf20Sopenharmony_ci CRYP_CR_CRYPEN_MASK); 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/** 798c2ecf20Sopenharmony_ci * cryp_flush_inoutfifo - Resets both the input and the output FIFOs 808c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_civoid cryp_flush_inoutfifo(struct cryp_device_data *device_data) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci /* 858c2ecf20Sopenharmony_ci * We always need to disable the hardware before trying to flush the 868c2ecf20Sopenharmony_ci * FIFO. This is something that isn't written in the design 878c2ecf20Sopenharmony_ci * specification, but we have been informed by the hardware designers 888c2ecf20Sopenharmony_ci * that this must be done. 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_ci cryp_activity(device_data, CRYP_CRYPEN_DISABLE); 918c2ecf20Sopenharmony_ci cryp_wait_until_done(device_data); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci CRYP_SET_BITS(&device_data->base->cr, CRYP_CR_FFLUSH_MASK); 948c2ecf20Sopenharmony_ci /* 958c2ecf20Sopenharmony_ci * CRYP_SR_INFIFO_READY_MASK is the expected value on the status 968c2ecf20Sopenharmony_ci * register when starting a new calculation, which means Input FIFO is 978c2ecf20Sopenharmony_ci * not full and input FIFO is empty. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_ci while (readl_relaxed(&device_data->base->sr) != 1008c2ecf20Sopenharmony_ci CRYP_SR_INFIFO_READY_MASK) 1018c2ecf20Sopenharmony_ci cpu_relax(); 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/** 1058c2ecf20Sopenharmony_ci * cryp_set_configuration - This routine set the cr CRYP IP 1068c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 1078c2ecf20Sopenharmony_ci * @cryp_config: Pointer to the configuration parameter 1088c2ecf20Sopenharmony_ci * @control_register: The control register to be written later on. 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_ciint cryp_set_configuration(struct cryp_device_data *device_data, 1118c2ecf20Sopenharmony_ci struct cryp_config *cryp_config, 1128c2ecf20Sopenharmony_ci u32 *control_register) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci u32 cr_for_kse; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (NULL == device_data || NULL == cryp_config) 1178c2ecf20Sopenharmony_ci return -EINVAL; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci *control_register |= (cryp_config->keysize << CRYP_CR_KEYSIZE_POS); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* Prepare key for decryption in AES_ECB and AES_CBC mode. */ 1228c2ecf20Sopenharmony_ci if ((CRYP_ALGORITHM_DECRYPT == cryp_config->algodir) && 1238c2ecf20Sopenharmony_ci ((CRYP_ALGO_AES_ECB == cryp_config->algomode) || 1248c2ecf20Sopenharmony_ci (CRYP_ALGO_AES_CBC == cryp_config->algomode))) { 1258c2ecf20Sopenharmony_ci cr_for_kse = *control_register; 1268c2ecf20Sopenharmony_ci /* 1278c2ecf20Sopenharmony_ci * This seems a bit odd, but it is indeed needed to set this to 1288c2ecf20Sopenharmony_ci * encrypt even though it is a decryption that we are doing. It 1298c2ecf20Sopenharmony_ci * also mentioned in the design spec that you need to do this. 1308c2ecf20Sopenharmony_ci * After the keyprepartion for decrypting is done you should set 1318c2ecf20Sopenharmony_ci * algodir back to decryption, which is done outside this if 1328c2ecf20Sopenharmony_ci * statement. 1338c2ecf20Sopenharmony_ci * 1348c2ecf20Sopenharmony_ci * According to design specification we should set mode ECB 1358c2ecf20Sopenharmony_ci * during key preparation even though we might be running CBC 1368c2ecf20Sopenharmony_ci * when enter this function. 1378c2ecf20Sopenharmony_ci * 1388c2ecf20Sopenharmony_ci * Writing to KSE_ENABLED will drop CRYPEN when key preparation 1398c2ecf20Sopenharmony_ci * is done. Therefore we need to set CRYPEN again outside this 1408c2ecf20Sopenharmony_ci * if statement when running decryption. 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_ci cr_for_kse |= ((CRYP_ALGORITHM_ENCRYPT << CRYP_CR_ALGODIR_POS) | 1438c2ecf20Sopenharmony_ci (CRYP_ALGO_AES_ECB << CRYP_CR_ALGOMODE_POS) | 1448c2ecf20Sopenharmony_ci (CRYP_CRYPEN_ENABLE << CRYP_CR_CRYPEN_POS) | 1458c2ecf20Sopenharmony_ci (KSE_ENABLED << CRYP_CR_KSE_POS)); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci writel_relaxed(cr_for_kse, &device_data->base->cr); 1488c2ecf20Sopenharmony_ci cryp_wait_until_done(device_data); 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci *control_register |= 1528c2ecf20Sopenharmony_ci ((cryp_config->algomode << CRYP_CR_ALGOMODE_POS) | 1538c2ecf20Sopenharmony_ci (cryp_config->algodir << CRYP_CR_ALGODIR_POS)); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci return 0; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci/** 1598c2ecf20Sopenharmony_ci * cryp_configure_protection - set the protection bits in the CRYP logic. 1608c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 1618c2ecf20Sopenharmony_ci * @p_protect_config: Pointer to the protection mode and 1628c2ecf20Sopenharmony_ci * secure mode configuration 1638c2ecf20Sopenharmony_ci */ 1648c2ecf20Sopenharmony_ciint cryp_configure_protection(struct cryp_device_data *device_data, 1658c2ecf20Sopenharmony_ci struct cryp_protection_config *p_protect_config) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci if (NULL == p_protect_config) 1688c2ecf20Sopenharmony_ci return -EINVAL; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci CRYP_WRITE_BIT(&device_data->base->cr, 1718c2ecf20Sopenharmony_ci (u32) p_protect_config->secure_access, 1728c2ecf20Sopenharmony_ci CRYP_CR_SECURE_MASK); 1738c2ecf20Sopenharmony_ci CRYP_PUT_BITS(&device_data->base->cr, 1748c2ecf20Sopenharmony_ci p_protect_config->privilege_access, 1758c2ecf20Sopenharmony_ci CRYP_CR_PRLG_POS, 1768c2ecf20Sopenharmony_ci CRYP_CR_PRLG_MASK); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci return 0; 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci/** 1828c2ecf20Sopenharmony_ci * cryp_is_logic_busy - returns the busy status of the CRYP logic 1838c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ciint cryp_is_logic_busy(struct cryp_device_data *device_data) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci return CRYP_TEST_BITS(&device_data->base->sr, 1888c2ecf20Sopenharmony_ci CRYP_SR_BUSY_MASK); 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci/** 1928c2ecf20Sopenharmony_ci * cryp_configure_for_dma - configures the CRYP IP for DMA operation 1938c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 1948c2ecf20Sopenharmony_ci * @dma_req: Specifies the DMA request type value. 1958c2ecf20Sopenharmony_ci */ 1968c2ecf20Sopenharmony_civoid cryp_configure_for_dma(struct cryp_device_data *device_data, 1978c2ecf20Sopenharmony_ci enum cryp_dma_req_type dma_req) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci CRYP_SET_BITS(&device_data->base->dmacr, 2008c2ecf20Sopenharmony_ci (u32) dma_req); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci/** 2048c2ecf20Sopenharmony_ci * cryp_configure_key_values - configures the key values for CRYP operations 2058c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 2068c2ecf20Sopenharmony_ci * @key_reg_index: Key value index register 2078c2ecf20Sopenharmony_ci * @key_value: The key value struct 2088c2ecf20Sopenharmony_ci */ 2098c2ecf20Sopenharmony_ciint cryp_configure_key_values(struct cryp_device_data *device_data, 2108c2ecf20Sopenharmony_ci enum cryp_key_reg_index key_reg_index, 2118c2ecf20Sopenharmony_ci struct cryp_key_value key_value) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci while (cryp_is_logic_busy(device_data)) 2148c2ecf20Sopenharmony_ci cpu_relax(); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci switch (key_reg_index) { 2178c2ecf20Sopenharmony_ci case CRYP_KEY_REG_1: 2188c2ecf20Sopenharmony_ci writel_relaxed(key_value.key_value_left, 2198c2ecf20Sopenharmony_ci &device_data->base->key_1_l); 2208c2ecf20Sopenharmony_ci writel_relaxed(key_value.key_value_right, 2218c2ecf20Sopenharmony_ci &device_data->base->key_1_r); 2228c2ecf20Sopenharmony_ci break; 2238c2ecf20Sopenharmony_ci case CRYP_KEY_REG_2: 2248c2ecf20Sopenharmony_ci writel_relaxed(key_value.key_value_left, 2258c2ecf20Sopenharmony_ci &device_data->base->key_2_l); 2268c2ecf20Sopenharmony_ci writel_relaxed(key_value.key_value_right, 2278c2ecf20Sopenharmony_ci &device_data->base->key_2_r); 2288c2ecf20Sopenharmony_ci break; 2298c2ecf20Sopenharmony_ci case CRYP_KEY_REG_3: 2308c2ecf20Sopenharmony_ci writel_relaxed(key_value.key_value_left, 2318c2ecf20Sopenharmony_ci &device_data->base->key_3_l); 2328c2ecf20Sopenharmony_ci writel_relaxed(key_value.key_value_right, 2338c2ecf20Sopenharmony_ci &device_data->base->key_3_r); 2348c2ecf20Sopenharmony_ci break; 2358c2ecf20Sopenharmony_ci case CRYP_KEY_REG_4: 2368c2ecf20Sopenharmony_ci writel_relaxed(key_value.key_value_left, 2378c2ecf20Sopenharmony_ci &device_data->base->key_4_l); 2388c2ecf20Sopenharmony_ci writel_relaxed(key_value.key_value_right, 2398c2ecf20Sopenharmony_ci &device_data->base->key_4_r); 2408c2ecf20Sopenharmony_ci break; 2418c2ecf20Sopenharmony_ci default: 2428c2ecf20Sopenharmony_ci return -EINVAL; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci return 0; 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci/** 2498c2ecf20Sopenharmony_ci * cryp_configure_init_vector - configures the initialization vector register 2508c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 2518c2ecf20Sopenharmony_ci * @init_vector_index: Specifies the index of the init vector. 2528c2ecf20Sopenharmony_ci * @init_vector_value: Specifies the value for the init vector. 2538c2ecf20Sopenharmony_ci */ 2548c2ecf20Sopenharmony_ciint cryp_configure_init_vector(struct cryp_device_data *device_data, 2558c2ecf20Sopenharmony_ci enum cryp_init_vector_index 2568c2ecf20Sopenharmony_ci init_vector_index, 2578c2ecf20Sopenharmony_ci struct cryp_init_vector_value 2588c2ecf20Sopenharmony_ci init_vector_value) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci while (cryp_is_logic_busy(device_data)) 2618c2ecf20Sopenharmony_ci cpu_relax(); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci switch (init_vector_index) { 2648c2ecf20Sopenharmony_ci case CRYP_INIT_VECTOR_INDEX_0: 2658c2ecf20Sopenharmony_ci writel_relaxed(init_vector_value.init_value_left, 2668c2ecf20Sopenharmony_ci &device_data->base->init_vect_0_l); 2678c2ecf20Sopenharmony_ci writel_relaxed(init_vector_value.init_value_right, 2688c2ecf20Sopenharmony_ci &device_data->base->init_vect_0_r); 2698c2ecf20Sopenharmony_ci break; 2708c2ecf20Sopenharmony_ci case CRYP_INIT_VECTOR_INDEX_1: 2718c2ecf20Sopenharmony_ci writel_relaxed(init_vector_value.init_value_left, 2728c2ecf20Sopenharmony_ci &device_data->base->init_vect_1_l); 2738c2ecf20Sopenharmony_ci writel_relaxed(init_vector_value.init_value_right, 2748c2ecf20Sopenharmony_ci &device_data->base->init_vect_1_r); 2758c2ecf20Sopenharmony_ci break; 2768c2ecf20Sopenharmony_ci default: 2778c2ecf20Sopenharmony_ci return -EINVAL; 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci return 0; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci/** 2848c2ecf20Sopenharmony_ci * cryp_save_device_context - Store hardware registers and 2858c2ecf20Sopenharmony_ci * other device context parameter 2868c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 2878c2ecf20Sopenharmony_ci * @ctx: Crypto device context 2888c2ecf20Sopenharmony_ci */ 2898c2ecf20Sopenharmony_civoid cryp_save_device_context(struct cryp_device_data *device_data, 2908c2ecf20Sopenharmony_ci struct cryp_device_context *ctx, 2918c2ecf20Sopenharmony_ci int cryp_mode) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci enum cryp_algo_mode algomode; 2948c2ecf20Sopenharmony_ci struct cryp_register __iomem *src_reg = device_data->base; 2958c2ecf20Sopenharmony_ci struct cryp_config *config = 2968c2ecf20Sopenharmony_ci (struct cryp_config *)device_data->current_ctx; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* 2998c2ecf20Sopenharmony_ci * Always start by disable the hardware and wait for it to finish the 3008c2ecf20Sopenharmony_ci * ongoing calculations before trying to reprogram it. 3018c2ecf20Sopenharmony_ci */ 3028c2ecf20Sopenharmony_ci cryp_activity(device_data, CRYP_CRYPEN_DISABLE); 3038c2ecf20Sopenharmony_ci cryp_wait_until_done(device_data); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci if (cryp_mode == CRYP_MODE_DMA) 3068c2ecf20Sopenharmony_ci cryp_configure_for_dma(device_data, CRYP_DMA_DISABLE_BOTH); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (CRYP_TEST_BITS(&src_reg->sr, CRYP_SR_IFEM_MASK) == 0) 3098c2ecf20Sopenharmony_ci ctx->din = readl_relaxed(&src_reg->din); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci ctx->cr = readl_relaxed(&src_reg->cr) & CRYP_CR_CONTEXT_SAVE_MASK; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci switch (config->keysize) { 3148c2ecf20Sopenharmony_ci case CRYP_KEY_SIZE_256: 3158c2ecf20Sopenharmony_ci ctx->key_4_l = readl_relaxed(&src_reg->key_4_l); 3168c2ecf20Sopenharmony_ci ctx->key_4_r = readl_relaxed(&src_reg->key_4_r); 3178c2ecf20Sopenharmony_ci fallthrough; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci case CRYP_KEY_SIZE_192: 3208c2ecf20Sopenharmony_ci ctx->key_3_l = readl_relaxed(&src_reg->key_3_l); 3218c2ecf20Sopenharmony_ci ctx->key_3_r = readl_relaxed(&src_reg->key_3_r); 3228c2ecf20Sopenharmony_ci fallthrough; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci case CRYP_KEY_SIZE_128: 3258c2ecf20Sopenharmony_ci ctx->key_2_l = readl_relaxed(&src_reg->key_2_l); 3268c2ecf20Sopenharmony_ci ctx->key_2_r = readl_relaxed(&src_reg->key_2_r); 3278c2ecf20Sopenharmony_ci fallthrough; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci default: 3308c2ecf20Sopenharmony_ci ctx->key_1_l = readl_relaxed(&src_reg->key_1_l); 3318c2ecf20Sopenharmony_ci ctx->key_1_r = readl_relaxed(&src_reg->key_1_r); 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci /* Save IV for CBC mode for both AES and DES. */ 3358c2ecf20Sopenharmony_ci algomode = ((ctx->cr & CRYP_CR_ALGOMODE_MASK) >> CRYP_CR_ALGOMODE_POS); 3368c2ecf20Sopenharmony_ci if (algomode == CRYP_ALGO_TDES_CBC || 3378c2ecf20Sopenharmony_ci algomode == CRYP_ALGO_DES_CBC || 3388c2ecf20Sopenharmony_ci algomode == CRYP_ALGO_AES_CBC) { 3398c2ecf20Sopenharmony_ci ctx->init_vect_0_l = readl_relaxed(&src_reg->init_vect_0_l); 3408c2ecf20Sopenharmony_ci ctx->init_vect_0_r = readl_relaxed(&src_reg->init_vect_0_r); 3418c2ecf20Sopenharmony_ci ctx->init_vect_1_l = readl_relaxed(&src_reg->init_vect_1_l); 3428c2ecf20Sopenharmony_ci ctx->init_vect_1_r = readl_relaxed(&src_reg->init_vect_1_r); 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci/** 3478c2ecf20Sopenharmony_ci * cryp_restore_device_context - Restore hardware registers and 3488c2ecf20Sopenharmony_ci * other device context parameter 3498c2ecf20Sopenharmony_ci * @device_data: Pointer to the device data struct for base address. 3508c2ecf20Sopenharmony_ci * @ctx: Crypto device context 3518c2ecf20Sopenharmony_ci */ 3528c2ecf20Sopenharmony_civoid cryp_restore_device_context(struct cryp_device_data *device_data, 3538c2ecf20Sopenharmony_ci struct cryp_device_context *ctx) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci struct cryp_register __iomem *reg = device_data->base; 3568c2ecf20Sopenharmony_ci struct cryp_config *config = 3578c2ecf20Sopenharmony_ci (struct cryp_config *)device_data->current_ctx; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci /* 3608c2ecf20Sopenharmony_ci * Fall through for all items in switch statement. DES is captured in 3618c2ecf20Sopenharmony_ci * the default. 3628c2ecf20Sopenharmony_ci */ 3638c2ecf20Sopenharmony_ci switch (config->keysize) { 3648c2ecf20Sopenharmony_ci case CRYP_KEY_SIZE_256: 3658c2ecf20Sopenharmony_ci writel_relaxed(ctx->key_4_l, ®->key_4_l); 3668c2ecf20Sopenharmony_ci writel_relaxed(ctx->key_4_r, ®->key_4_r); 3678c2ecf20Sopenharmony_ci fallthrough; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci case CRYP_KEY_SIZE_192: 3708c2ecf20Sopenharmony_ci writel_relaxed(ctx->key_3_l, ®->key_3_l); 3718c2ecf20Sopenharmony_ci writel_relaxed(ctx->key_3_r, ®->key_3_r); 3728c2ecf20Sopenharmony_ci fallthrough; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci case CRYP_KEY_SIZE_128: 3758c2ecf20Sopenharmony_ci writel_relaxed(ctx->key_2_l, ®->key_2_l); 3768c2ecf20Sopenharmony_ci writel_relaxed(ctx->key_2_r, ®->key_2_r); 3778c2ecf20Sopenharmony_ci fallthrough; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci default: 3808c2ecf20Sopenharmony_ci writel_relaxed(ctx->key_1_l, ®->key_1_l); 3818c2ecf20Sopenharmony_ci writel_relaxed(ctx->key_1_r, ®->key_1_r); 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci /* Restore IV for CBC mode for AES and DES. */ 3858c2ecf20Sopenharmony_ci if (config->algomode == CRYP_ALGO_TDES_CBC || 3868c2ecf20Sopenharmony_ci config->algomode == CRYP_ALGO_DES_CBC || 3878c2ecf20Sopenharmony_ci config->algomode == CRYP_ALGO_AES_CBC) { 3888c2ecf20Sopenharmony_ci writel_relaxed(ctx->init_vect_0_l, ®->init_vect_0_l); 3898c2ecf20Sopenharmony_ci writel_relaxed(ctx->init_vect_0_r, ®->init_vect_0_r); 3908c2ecf20Sopenharmony_ci writel_relaxed(ctx->init_vect_1_l, ®->init_vect_1_l); 3918c2ecf20Sopenharmony_ci writel_relaxed(ctx->init_vect_1_r, ®->init_vect_1_r); 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci} 394