summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoakim Bech <joakim.xx.bech@stericsson.com>2011-05-23 16:23:56 +0200
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:04:35 +0200
commit8645233e6375a93e4054ad1568b79bed8271d50c (patch)
tree555dd7c2474ba6d0134d79d0d4b49abbbc132dae
parenteebb14cb2df3fb6071b217e1b1f571ad2b9a79ad (diff)
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 <joakim.xx.bech@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23719 Reviewed-by: Berne HEBARK <berne.hebark@stericsson.com> Reviewed-by: QATEST Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
-rw-r--r--drivers/crypto/ux500/cryp/cryp.c119
-rw-r--r--drivers/crypto/ux500/cryp/cryp.h11
-rw-r--r--drivers/crypto/ux500/cryp/cryp_core.c58
-rw-r--r--drivers/crypto/ux500/cryp/cryp_p.h4
4 files changed, 69 insertions, 123 deletions
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 <linux/delay.h>
-#include <linux/device.h>
#include <linux/errno.h>
-#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/spinlock.h>
#include <linux/types.h>
#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, &reg->init_vect_1_l);
writel(ctx->init_vect_1_r, &reg->init_vect_1_r);
}
-
- writel(ctx->cr, &reg->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