From 8645233e6375a93e4054ad1568b79bed8271d50c Mon Sep 17 00:00:00 2001 From: Joakim Bech Date: Mon, 23 May 2011 16:23:56 +0200 Subject: cryp: CPU mode register read/write optimizations - Minimize the number of read/write to the cryp hardware. - Write direct to hardware instead of going through functions that aren't inlined to get rid of function prologues/epilogues. - Remove NULL checks where performance is needed and the check itself is unnecessary since it is catched earlier in the callstack. - Remove unused defines/includes that are not used any longer due to above optimizations. ST-Ericsson ID: 341921 ST-Ericsson Linux next: Not tested, ER 320876 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I9efff1714f851672f8cb04e0c946a753a4b3f4b8 Signed-off-by: Joakim Bech Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23719 Reviewed-by: Berne HEBARK Reviewed-by: QATEST Reviewed-by: Jonas ABERG --- drivers/crypto/ux500/cryp/cryp.c | 119 +++++++++++++--------------------- drivers/crypto/ux500/cryp/cryp.h | 11 +--- drivers/crypto/ux500/cryp/cryp_core.c | 58 ++++++----------- drivers/crypto/ux500/cryp/cryp_p.h | 4 +- 4 files changed, 69 insertions(+), 123 deletions(-) (limited to 'drivers/crypto') diff --git a/drivers/crypto/ux500/cryp/cryp.c b/drivers/crypto/ux500/cryp/cryp.c index ed9eeccf1d3..f627c57d9bd 100644 --- a/drivers/crypto/ux500/cryp/cryp.c +++ b/drivers/crypto/ux500/cryp/cryp.c @@ -8,12 +8,8 @@ * License terms: GNU General Public License (GPL) version 2 */ -#include -#include #include -#include #include -#include #include #include "cryp_p.h" @@ -94,23 +90,25 @@ void cryp_flush_inoutfifo(struct cryp_device_data *device_data) /** * cryp_set_configuration - This routine set the cr CRYP IP * @device_data: Pointer to the device data struct for base address. - * @p_cryp_config: Pointer to the configuration parameter + * @cryp_config: Pointer to the configuration parameter + * @control_register: The control register to be written later on. */ int cryp_set_configuration(struct cryp_device_data *device_data, - struct cryp_config *p_cryp_config) + struct cryp_config *cryp_config, + u32 *control_register) { - if (NULL == device_data || NULL == p_cryp_config) + u32 cr_for_kse; + + if (NULL == device_data || NULL == cryp_config) return -EINVAL; - CRYP_PUT_BITS(&device_data->base->cr, - p_cryp_config->keysize, - CRYP_CR_KEYSIZE_POS, - CRYP_CR_KEYSIZE_MASK); + *control_register |= (cryp_config->keysize << CRYP_CR_KEYSIZE_POS); /* Prepare key for decryption in AES_ECB and AES_CBC mode. */ - if ((CRYP_ALGORITHM_DECRYPT == p_cryp_config->algodir) && - ((CRYP_ALGO_AES_ECB == p_cryp_config->algomode) || - (CRYP_ALGO_AES_CBC == p_cryp_config->algomode))) { + if ((CRYP_ALGORITHM_DECRYPT == cryp_config->algodir) && + ((CRYP_ALGO_AES_ECB == cryp_config->algomode) || + (CRYP_ALGO_AES_CBC == cryp_config->algomode))) { + cr_for_kse = *control_register; /* * This seems a bit odd, but it is indeed needed to set this to * encrypt even though it is a decryption that we are doing. It @@ -118,49 +116,27 @@ int cryp_set_configuration(struct cryp_device_data *device_data, * After the keyprepartion for decrypting is done you should set * algodir back to decryption, which is done outside this if * statement. - */ - CRYP_PUT_BITS(&device_data->base->cr, - CRYP_ALGORITHM_ENCRYPT, - CRYP_CR_ALGODIR_POS, - CRYP_CR_ALGODIR_MASK); - - /* + * * According to design specification we should set mode ECB * during key preparation even though we might be running CBC * when enter this function. - */ - CRYP_PUT_BITS(&device_data->base->cr, - CRYP_ALGO_AES_ECB, - CRYP_CR_ALGOMODE_POS, - CRYP_CR_ALGOMODE_MASK); - - CRYP_PUT_BITS(&device_data->base->cr, - CRYP_CRYPEN_ENABLE, - CRYP_CR_CRYPEN_POS, - CRYP_CR_CRYPEN_MASK); - - /* + * * Writing to KSE_ENABLED will drop CRYPEN when key preparation * is done. Therefore we need to set CRYPEN again outside this * if statement when running decryption. */ - CRYP_PUT_BITS(&device_data->base->cr, - KSE_ENABLED, - CRYP_CR_KSE_POS, - CRYP_CR_KSE_MASK); + cr_for_kse |= ((CRYP_ALGORITHM_ENCRYPT << CRYP_CR_ALGODIR_POS) | + (CRYP_ALGO_AES_ECB << CRYP_CR_ALGOMODE_POS) | + (CRYP_CRYPEN_ENABLE << CRYP_CR_CRYPEN_POS) | + (KSE_ENABLED << CRYP_CR_KSE_POS)); + writel(cr_for_kse, &device_data->base->cr); cryp_wait_until_done(device_data); } - CRYP_PUT_BITS(&device_data->base->cr, - p_cryp_config->algomode, - CRYP_CR_ALGOMODE_POS, - CRYP_CR_ALGOMODE_MASK); - - CRYP_PUT_BITS(&device_data->base->cr, - p_cryp_config->algodir, - CRYP_CR_ALGODIR_POS, - CRYP_CR_ALGODIR_MASK); + *control_register |= + ((cryp_config->algomode << CRYP_CR_ALGOMODE_POS) | + (cryp_config->algodir << CRYP_CR_ALGODIR_POS)); return 0; } @@ -300,7 +276,10 @@ int cryp_configure_init_vector(struct cryp_device_data *device_data, void cryp_save_device_context(struct cryp_device_data *device_data, struct cryp_device_context *ctx) { + enum cryp_algo_mode algomode; struct cryp_register *src_reg = device_data->base; + struct cryp_config *config = + (struct cryp_config *)device_data->current_ctx; /* * Always start by disable the hardware and wait for it to finish the @@ -315,28 +294,29 @@ void cryp_save_device_context(struct cryp_device_data *device_data, ctx->cr = readl(&src_reg->cr) & CRYP_CR_CONTEXT_SAVE_MASK; - CRYP_PUT_BITS(&src_reg->cr, 1, CRYP_CR_KEYRDEN_POS, - CRYP_CR_KEYRDEN_MASK); + switch (config->keysize) { + case CRYP_KEY_SIZE_256: + ctx->key_4_l = readl(&src_reg->key_4_l); + ctx->key_4_r = readl(&src_reg->key_4_r); - ctx->key_1_l = readl(&src_reg->key_1_l); - ctx->key_1_r = readl(&src_reg->key_1_r); - ctx->key_2_l = readl(&src_reg->key_2_l); - ctx->key_2_r = readl(&src_reg->key_2_r); - ctx->key_3_l = readl(&src_reg->key_3_l); - ctx->key_3_r = readl(&src_reg->key_3_r); - ctx->key_4_l = readl(&src_reg->key_4_l); - ctx->key_4_r = readl(&src_reg->key_4_r); + case CRYP_KEY_SIZE_192: + ctx->key_3_l = readl(&src_reg->key_3_l); + ctx->key_3_r = readl(&src_reg->key_3_r); - CRYP_PUT_BITS(&src_reg->cr, 0, CRYP_CR_KEYRDEN_POS, - CRYP_CR_KEYRDEN_MASK); + case CRYP_KEY_SIZE_128: + ctx->key_2_l = readl(&src_reg->key_2_l); + ctx->key_2_r = readl(&src_reg->key_2_r); + + default: + ctx->key_1_l = readl(&src_reg->key_1_l); + ctx->key_1_r = readl(&src_reg->key_1_r); + } /* Save IV for CBC mode for both AES and DES. */ - if (CRYP_TEST_BITS(&src_reg->cr, CRYP_CR_ALGOMODE_POS) == - CRYP_ALGO_TDES_CBC || - CRYP_TEST_BITS(&src_reg->cr, CRYP_CR_ALGOMODE_POS) == - CRYP_ALGO_DES_CBC || - CRYP_TEST_BITS(&src_reg->cr, CRYP_CR_ALGOMODE_POS) == - CRYP_ALGO_AES_CBC) { + algomode = ((ctx->cr & CRYP_CR_ALGOMODE_MASK) >> CRYP_CR_ALGOMODE_POS); + if (algomode == CRYP_ALGO_TDES_CBC || + algomode == CRYP_ALGO_DES_CBC || + algomode == CRYP_ALGO_AES_CBC) { ctx->init_vect_0_l = readl(&src_reg->init_vect_0_l); ctx->init_vect_0_r = readl(&src_reg->init_vect_0_r); ctx->init_vect_1_l = readl(&src_reg->init_vect_1_l); @@ -357,7 +337,6 @@ void cryp_restore_device_context(struct cryp_device_data *device_data, struct cryp_config *config = (struct cryp_config *)device_data->current_ctx; - /* * Fall through for all items in switch statement. DES is captured in * the default. @@ -389,9 +368,6 @@ void cryp_restore_device_context(struct cryp_device_data *device_data, writel(ctx->init_vect_1_l, ®->init_vect_1_l); writel(ctx->init_vect_1_r, ®->init_vect_1_r); } - - writel(ctx->cr, ®->cr); - cryp_activity(device_data, CRYP_CRYPEN_ENABLE); } /** @@ -402,8 +378,6 @@ void cryp_restore_device_context(struct cryp_device_data *device_data, */ int cryp_write_indata(struct cryp_device_data *device_data, u32 write_data) { - if (NULL == device_data) - return -EINVAL; writel(write_data, &device_data->base->din); return 0; @@ -417,11 +391,6 @@ int cryp_write_indata(struct cryp_device_data *device_data, u32 write_data) */ int cryp_read_outdata(struct cryp_device_data *device_data, u32 *read_data) { - if (NULL == device_data) - return -EINVAL; - if (NULL == read_data) - return -EINVAL; - *read_data = readl(&device_data->base->dout); return 0; diff --git a/drivers/crypto/ux500/cryp/cryp.h b/drivers/crypto/ux500/cryp/cryp.h index ee7aee3dcb1..bfa2beb694f 100644 --- a/drivers/crypto/ux500/cryp/cryp.h +++ b/drivers/crypto/ux500/cryp/cryp.h @@ -53,12 +53,6 @@ enum cryp_key_prep { #define CRYP_KEY_SIZE_192 (1) #define CRYP_KEY_SIZE_256 (2) -/* Data type Swap */ -#define CRYP_DATA_TYPE_32BIT_SWAP (0) -#define CRYP_DATA_TYPE_16BIT_SWAP (1) -#define CRYP_DATA_TYPE_8BIT_SWAP (2) -#define CRYP_DATA_TYPE_BIT_SWAP (3) - /* AES modes */ enum cryp_algo_mode { CRYP_ALGO_TDES_ECB, @@ -88,7 +82,6 @@ enum cryp_mode { * struct cryp_config - * @keyrden: Cryp state enable/disable * @keysize: Key size for AES - * @datatype: Data type Swap * @algomode: AES modes * @algodir: Cryp Encryption or Decryption * @@ -97,7 +90,6 @@ enum cryp_mode { struct cryp_config { enum cryp_state keyrden; int keysize; - int datatype; enum cryp_algo_mode algomode; enum cryp_algorithm_dir algodir; }; @@ -267,7 +259,8 @@ void cryp_activity(struct cryp_device_data *device_data, void cryp_flush_inoutfifo(struct cryp_device_data *device_data); int cryp_set_configuration(struct cryp_device_data *device_data, - struct cryp_config *p_cryp_config); + struct cryp_config *cryp_config, + u32 *control_register); void cryp_configure_for_dma(struct cryp_device_data *device_data, enum cryp_dma_req_type dma_req); diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c index f67577c386e..051874bff03 100644 --- a/drivers/crypto/ux500/cryp/cryp_core.c +++ b/drivers/crypto/ux500/cryp/cryp_core.c @@ -358,13 +358,9 @@ static int cfg_keys(struct cryp_ctx *ctx) static int cryp_setup_context(struct cryp_ctx *ctx, struct cryp_device_data *device_data) { + u32 control_register = CRYP_CR_DEFAULT; cryp_flush_inoutfifo(device_data); - CRYP_PUT_BITS(&device_data->base->cr, - ctx->config.datatype, - CRYP_CR_DATATYPE_POS, - CRYP_CR_DATATYPE_MASK); - switch (cryp_mode) { case CRYP_MODE_INTERRUPT: writel(CRYP_IMSC_DEFAULT, &device_data->base->imsc); @@ -378,9 +374,10 @@ static int cryp_setup_context(struct cryp_ctx *ctx, break; } - if (ctx->updated) + if (ctx->updated) { cryp_restore_device_context(device_data, &ctx->dev_ctx); - else { + control_register = ctx->dev_ctx.cr; + } else { if (cfg_keys(ctx) != 0) { dev_err(ctx->device->dev, "[%s]: cfg_keys failed!", __func__); @@ -395,10 +392,12 @@ static int cryp_setup_context(struct cryp_ctx *ctx, return -EPERM; } - cryp_set_configuration(device_data, &ctx->config); + cryp_set_configuration(device_data, &ctx->config, + &control_register); } - cryp_activity(device_data, CRYP_CRYPEN_ENABLE); + writel(control_register | (CRYP_CRYPEN_ENABLE << CRYP_CR_CRYPEN_POS), + &device_data->base->cr); return 0; } @@ -612,37 +611,28 @@ static int cryp_dma_read(struct cryp_ctx *ctx, struct scatterlist *sg, int len) return len; } -static int cryp_polling_mode(struct cryp_ctx *ctx, - struct cryp_device_data *device_data) +static void cryp_polling_mode(struct cryp_ctx *ctx, + struct cryp_device_data *device_data) { int i; - int ret = 0; int remaining_length = ctx->datalen; - const u8 *indata = ctx->indata; - u8 *outdata = ctx->outdata; + u32 *indata = (u32 *)ctx->indata; + u32 *outdata = (u32 *)ctx->outdata; - cryp_activity(device_data, CRYP_CRYPEN_ENABLE); while (remaining_length > 0) { for (i = 0; i < ctx->blocksize / BYTES_PER_WORD; i++) { - ret = cryp_write_indata(device_data, - *((u32 *)indata)); - if (ret) - goto out; - indata += BYTES_PER_WORD; + writel(*indata, &device_data->base->din); + ++indata; remaining_length -= BYTES_PER_WORD; } cryp_wait_until_done(device_data); + for (i = 0; i < ctx->blocksize / BYTES_PER_WORD; i++) { - ret = cryp_read_outdata(device_data, - (u32 *)outdata); - if (ret) - goto out; - outdata += BYTES_PER_WORD; + *outdata = readl(&device_data->base->dout); + ++outdata; } cryp_wait_until_done(device_data); } -out: - return ret; } static int cryp_disable_power(struct device *dev, @@ -727,7 +717,7 @@ out: static int hw_crypt_noxts(struct cryp_ctx *ctx, struct cryp_device_data *device_data) { - int ret; + int ret = 0; const u8 *indata = ctx->indata; u8 *outdata = ctx->outdata; @@ -737,8 +727,6 @@ static int hw_crypt_noxts(struct cryp_ctx *ctx, pr_debug(DEV_DBG_NAME " [%s]", __func__); ctx->outlen = ctx->datalen; - ctx->config.keyrden = CRYP_STATE_ENABLE; - ctx->config.datatype = CRYP_DATA_TYPE_8BIT_SWAP; if (unlikely(!IS_ALIGNED((u32)indata, 4))) { pr_debug(DEV_DBG_NAME " [%s]: Data isn't aligned! Addr: " @@ -771,9 +759,7 @@ static int hw_crypt_noxts(struct cryp_ctx *ctx, * the polling mode. Overhead of doing DMA setup eats up the * benefits using it. */ - ret = cryp_polling_mode(ctx, device_data); - if (ret) - goto out; + cryp_polling_mode(ctx, device_data); } else { dev_err(ctx->device->dev, "[%s]: Invalid operation mode!", __func__); @@ -781,10 +767,8 @@ static int hw_crypt_noxts(struct cryp_ctx *ctx, goto out; } - ret = 0; cryp_save_device_context(device_data, &ctx->dev_ctx); - if (ctx->updated == 0) - ctx->updated = 1; + ctx->updated = 1; out: ctx->indata = indata; @@ -820,8 +804,6 @@ static int ablk_dma_crypt(struct ablkcipher_request *areq) pr_debug(DEV_DBG_NAME " [%s]", __func__); - ctx->config.keyrden = CRYP_STATE_ENABLE; - ctx->config.datatype = CRYP_DATA_TYPE_8BIT_SWAP; ctx->datalen = areq->nbytes; ctx->outlen = areq->nbytes; diff --git a/drivers/crypto/ux500/cryp/cryp_p.h b/drivers/crypto/ux500/cryp/cryp_p.h index adc95457499..5171ee10f71 100644 --- a/drivers/crypto/ux500/cryp/cryp_p.h +++ b/drivers/crypto/ux500/cryp/cryp_p.h @@ -50,7 +50,9 @@ * CRYP register default values */ #define MAX_DEVICE_SUPPORT 2 -#define CRYP_CR_DEFAULT 0x0002 + +/* Priv set, keyrden set and datatype 8bits swapped set as default. */ +#define CRYP_CR_DEFAULT 0x0482 #define CRYP_DMACR_DEFAULT 0x0 #define CRYP_IMSC_DEFAULT 0x0 #define CRYP_DIN_DEFAULT 0x0 -- cgit v1.2.3