summaryrefslogtreecommitdiff
path: root/drivers/crypto/ux500/cryp/cryp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/crypto/ux500/cryp/cryp.c')
-rw-r--r--drivers/crypto/ux500/cryp/cryp.c392
1 files changed, 132 insertions, 260 deletions
diff --git a/drivers/crypto/ux500/cryp/cryp.c b/drivers/crypto/ux500/cryp/cryp.c
index 94928f7efce..ed9eeccf1d3 100644
--- a/drivers/crypto/ux500/cryp/cryp.c
+++ b/drivers/crypto/ux500/cryp/cryp.c
@@ -53,40 +53,6 @@ int cryp_check(struct cryp_device_data *device_data)
}
/**
- * cryp_reset - This routine loads the cryp register with the default values
- * @device_data: Pointer to the device data struct for base address.
- */
-void cryp_reset(struct cryp_device_data *device_data)
-{
- writel(CRYP_DMACR_DEFAULT, &device_data->base->dmacr);
- writel(CRYP_IMSC_DEFAULT, &device_data->base->imsc);
-
- writel(CRYP_KEY_DEFAULT, &device_data->base->key_1_l);
- writel(CRYP_KEY_DEFAULT, &device_data->base->key_1_r);
- writel(CRYP_KEY_DEFAULT, &device_data->base->key_2_l);
- writel(CRYP_KEY_DEFAULT, &device_data->base->key_2_r);
- writel(CRYP_KEY_DEFAULT, &device_data->base->key_3_l);
- writel(CRYP_KEY_DEFAULT, &device_data->base->key_3_r);
- writel(CRYP_INIT_VECT_DEFAULT, &device_data->base->init_vect_0_l);
- writel(CRYP_INIT_VECT_DEFAULT, &device_data->base->init_vect_0_r);
- writel(CRYP_KEY_DEFAULT, &device_data->base->key_4_l);
- writel(CRYP_KEY_DEFAULT, &device_data->base->key_4_r);
- writel(CRYP_INIT_VECT_DEFAULT, &device_data->base->init_vect_1_l);
- writel(CRYP_INIT_VECT_DEFAULT, &device_data->base->init_vect_1_r);
-
- /* Last step since the protection mode bits need to be modified. */
- writel(CRYP_CR_DEFAULT | CRYP_CR_FFLUSH, &device_data->base->cr);
-
- /*
- * CRYP_INFIFO_READY_MASK is the expected value on the status register
- * when starting a new calculation, which means Input FIFO is not full
- * and input FIFO is empty.
- */
- while (readl(&device_data->base->status) != CRYP_INFIFO_READY_MASK)
- cpu_relax();
-}
-
-/**
* cryp_activity - This routine enables/disable the cryptography function.
* @device_data: Pointer to the device data struct for base address.
* @cryp_activity: Enable/Disable functionality
@@ -96,49 +62,8 @@ void cryp_activity(struct cryp_device_data *device_data,
{
CRYP_PUT_BITS(&device_data->base->cr,
cryp_crypen,
- CRYP_CRYPEN_POS,
- CRYP_CRYPEN_MASK);
-}
-
-/**
- * cryp_start - starts the computation
- * @device_data: Pointer to the device data struct for base address.
- * @cryp_start: Enable/Disable functionality
- */
-void cryp_start(struct cryp_device_data *device_data)
-{
- CRYP_PUT_BITS(&device_data->base->cr,
- CRYP_START_ENABLE,
- CRYP_START_POS,
- CRYP_START_MASK);
-}
-
-/**
- * cryp_init_signal - This routine submit the initialization values.
- * @device_data: Pointer to the device data struct for base address.
- * @cryp_init_bit: Enable/Disable init signal
- */
-void cryp_init_signal(struct cryp_device_data *device_data,
- enum cryp_init cryp_init_bit)
-{
- CRYP_PUT_BITS(&device_data->base->cr,
- cryp_init_bit,
- CRYP_INIT_POS,
- CRYP_INIT_MASK);
-}
-
-/**
- * cryp_key_preparation - This routine prepares key for decryption.
- * @device_data: Pointer to the device data struct for base address.
- * @cryp_prepkey: Enable/Disable
- */
-void cryp_key_preparation(struct cryp_device_data *device_data,
- enum cryp_key_prep cryp_prepkey)
-{
- CRYP_PUT_BITS(&device_data->base->cr,
- cryp_prepkey,
- CRYP_KSE_POS,
- CRYP_KSE_MASK);
+ CRYP_CR_CRYPEN_POS,
+ CRYP_CR_CRYPEN_MASK);
}
/**
@@ -147,43 +72,23 @@ void cryp_key_preparation(struct cryp_device_data *device_data,
*/
void cryp_flush_inoutfifo(struct cryp_device_data *device_data)
{
- CRYP_SET_BITS(&device_data->base->cr, CRYP_FIFO_FLUSH_MASK);
-}
-
-/**
- * cryp_set_dir -
- * @device_data: Pointer to the device data struct for base address.
- * @dir: Crypto direction, encrypt/decrypt
- */
-void cryp_set_dir(struct cryp_device_data *device_data, int dir)
-{
- CRYP_PUT_BITS(&device_data->base->cr,
- dir,
- CRYP_ENC_DEC_POS,
- CRYP_ENC_DEC_MASK);
-
- CRYP_PUT_BITS(&device_data->base->cr,
- CRYP_DATA_TYPE_8BIT_SWAP,
- CRYP_DATA_TYPE_POS,
- CRYP_DATA_TYPE_MASK);
-}
+ /*
+ * We always need to disble the hardware before trying to flush the
+ * FIFO. This is something that isn't written in the design
+ * specification, but we have been informed by the hardware designers
+ * that this must be done.
+ */
+ cryp_activity(device_data, CRYP_CRYPEN_DISABLE);
+ cryp_wait_until_done(device_data);
-/**
- * cryp_cen_flush -
- * @device_data: Pointer to the device data struct for base address.
- */
-void cryp_cen_flush(struct cryp_device_data *device_data)
-{
- CRYP_PUT_BITS(&device_data->base->cr,
- CRYP_STATE_DISABLE,
- CRYP_KEY_ACCESS_POS,
- CRYP_KEY_ACCESS_MASK);
- CRYP_SET_BITS(&device_data->base->cr,
- CRYP_FIFO_FLUSH_MASK);
- CRYP_PUT_BITS(&device_data->base->cr,
- CRYP_CRYPEN_ENABLE,
- CRYP_CRYPEN_POS,
- CRYP_CRYPEN_MASK);
+ CRYP_SET_BITS(&device_data->base->cr, CRYP_CR_FFLUSH_MASK);
+ /*
+ * CRYP_SR_INFIFO_READY_MASK is the expected value on the status
+ * register when starting a new calculation, which means Input FIFO is
+ * not full and input FIFO is empty.
+ */
+ while (readl(&device_data->base->sr) != CRYP_SR_INFIFO_READY_MASK)
+ cpu_relax();
}
/**
@@ -194,96 +99,68 @@ void cryp_cen_flush(struct cryp_device_data *device_data)
int cryp_set_configuration(struct cryp_device_data *device_data,
struct cryp_config *p_cryp_config)
{
- if (NULL == device_data)
- return -EINVAL;
- if (NULL == p_cryp_config)
+ if (NULL == device_data || NULL == p_cryp_config)
return -EINVAL;
- /* Since more than one bit is written macro put_bits is used*/
CRYP_PUT_BITS(&device_data->base->cr,
- p_cryp_config->key_access,
- CRYP_KEY_ACCESS_POS,
- CRYP_KEY_ACCESS_MASK);
- CRYP_PUT_BITS(&device_data->base->cr,
- p_cryp_config->key_size,
- CRYP_KEY_SIZE_POS,
- CRYP_KEY_SIZE_MASK);
- CRYP_PUT_BITS(&device_data->base->cr,
- p_cryp_config->data_type,
- CRYP_DATA_TYPE_POS,
- CRYP_DATA_TYPE_MASK);
-
- /* Prepare key for decryption */
- if ((CRYP_ALGORITHM_DECRYPT == p_cryp_config->encrypt_or_decrypt) &&
- ((CRYP_ALGO_AES_ECB == p_cryp_config->algo_mode) ||
- (CRYP_ALGO_AES_CBC == p_cryp_config->algo_mode))) {
+ p_cryp_config->keysize,
+ CRYP_CR_KEYSIZE_POS,
+ CRYP_CR_KEYSIZE_MASK);
+
+ /* 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))) {
+ /*
+ * 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
+ * also mentioned in the design spec that you need to do this.
+ * 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_ALGOMODE_POS,
- CRYP_ALGOMODE_MASK);
+ CRYP_CR_ALGOMODE_POS,
+ CRYP_CR_ALGOMODE_MASK);
+
CRYP_PUT_BITS(&device_data->base->cr,
CRYP_CRYPEN_ENABLE,
- CRYP_CRYPEN_POS,
- CRYP_CRYPEN_MASK);
+ 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_KSE_POS,
- CRYP_KSE_MASK);
+ CRYP_CR_KSE_POS,
+ CRYP_CR_KSE_MASK);
cryp_wait_until_done(device_data);
-
- CRYP_PUT_BITS(&device_data->base->cr,
- CRYP_CRYPEN_DISABLE,
- CRYP_CRYPEN_POS,
- CRYP_CRYPEN_MASK);
}
CRYP_PUT_BITS(&device_data->base->cr,
- CRYP_CRYPEN_ENABLE,
- CRYP_CRYPEN_POS,
- CRYP_CRYPEN_MASK);
- CRYP_PUT_BITS(&device_data->base->cr,
- p_cryp_config->algo_mode,
- CRYP_ALGOMODE_POS,
- CRYP_ALGOMODE_MASK);
- CRYP_PUT_BITS(&device_data->base->cr,
- p_cryp_config->encrypt_or_decrypt,
- CRYP_ENC_DEC_POS,
- CRYP_ENC_DEC_MASK);
-
- return 0;
-}
-
-/**
- * cryp_get_configuration - gets the parameter of the control register of IP
- * @device_data: Pointer to the device data struct for base address.
- * @p_cryp_config: Gets the configuration parameter from cryp ip.
- */
-int cryp_get_configuration(struct cryp_device_data *device_data,
- struct cryp_config *p_cryp_config)
-{
- if (NULL == p_cryp_config)
- return -EINVAL;
+ p_cryp_config->algomode,
+ CRYP_CR_ALGOMODE_POS,
+ CRYP_CR_ALGOMODE_MASK);
- p_cryp_config->key_access =
- ((readl(&device_data->base->cr) & CRYP_KEY_ACCESS_MASK) ?
- CRYP_STATE_ENABLE :
- CRYP_STATE_DISABLE);
- p_cryp_config->key_size =
- ((readl(&device_data->base->cr) & CRYP_KEY_SIZE_MASK) >>
- CRYP_KEY_SIZE_POS);
-
- p_cryp_config->encrypt_or_decrypt =
- ((readl(&device_data->base->cr) & CRYP_ENC_DEC_MASK) ?
- CRYP_ALGORITHM_DECRYPT :
- CRYP_ALGORITHM_ENCRYPT);
-
- p_cryp_config->data_type =
- ((readl(&device_data->base->cr) & CRYP_DATA_TYPE_MASK) >>
- CRYP_DATA_TYPE_POS);
- p_cryp_config->algo_mode =
- ((readl(&device_data->base->cr) & CRYP_ALGOMODE_MASK) >>
- CRYP_ALGOMODE_POS);
+ CRYP_PUT_BITS(&device_data->base->cr,
+ p_cryp_config->algodir,
+ CRYP_CR_ALGODIR_POS,
+ CRYP_CR_ALGODIR_MASK);
return 0;
}
@@ -302,11 +179,11 @@ int cryp_configure_protection(struct cryp_device_data *device_data,
CRYP_WRITE_BIT(&device_data->base->cr,
(u32) p_protect_config->secure_access,
- CRYP_SECURE_MASK);
+ CRYP_CR_SECURE_MASK);
CRYP_PUT_BITS(&device_data->base->cr,
p_protect_config->privilege_access,
- CRYP_PRLG_POS,
- CRYP_PRLG_MASK);
+ CRYP_CR_PRLG_POS,
+ CRYP_CR_PRLG_MASK);
return 0;
}
@@ -317,20 +194,9 @@ int cryp_configure_protection(struct cryp_device_data *device_data,
*/
int cryp_is_logic_busy(struct cryp_device_data *device_data)
{
- return CRYP_TEST_BITS(&device_data->base->status,
- CRYP_BUSY_STATUS_MASK);
-}
-
-/**
- * cryp_get_status - This routine returns the complete status of the cryp logic
- * @device_data: Pointer to the device data struct for base address.
- */
-/*
-int cryp_get_status(struct cryp_device_data *device_data)
-{
- return (int) readl(device_data->base->status);
+ return CRYP_TEST_BITS(&device_data->base->sr,
+ CRYP_SR_BUSY_MASK);
}
-*/
/**
* cryp_configure_for_dma - configures the CRYP IP for DMA operation
@@ -426,17 +292,6 @@ int cryp_configure_init_vector(struct cryp_device_data *device_data,
}
/**
- * cryp_prep_ctx_mgmt - Prepares for handling the context of the block
- * @device_data: Pointer to the device data struct for base address.
- */
-static void cryp_prep_ctx_mgmt(struct cryp_device_data *device_data)
-{
- cryp_configure_for_dma(device_data, CRYP_DMA_DISABLE_BOTH);
- cryp_activity(device_data, CRYP_CRYPEN_DISABLE);
- cryp_wait_until_done(device_data);
-}
-
-/**
* cryp_save_device_context - Store hardware registers and
* other device context parameter
* @device_data: Pointer to the device data struct for base address.
@@ -447,15 +302,21 @@ void cryp_save_device_context(struct cryp_device_data *device_data,
{
struct cryp_register *src_reg = device_data->base;
- cryp_prep_ctx_mgmt(device_data);
+ /*
+ * Always start by disable the hardware and wait for it to finish the
+ * ongoing calculations before trying to reprogram it.
+ */
+ cryp_activity(device_data, CRYP_CRYPEN_DISABLE);
+ cryp_wait_until_done(device_data);
+ cryp_configure_for_dma(device_data, CRYP_DMA_DISABLE_BOTH);
- ctx->din = readl(&src_reg->din);
+ if (CRYP_TEST_BITS(&src_reg->sr, CRYP_SR_IFEM_MASK) == 0)
+ ctx->din = readl(&src_reg->din);
- ctx->dout = readl(&src_reg->dout);
+ ctx->cr = readl(&src_reg->cr) & CRYP_CR_CONTEXT_SAVE_MASK;
- ctx->cr = readl(&src_reg->cr);
- ctx->dmacr = readl(&src_reg->dmacr);
- ctx->imsc = readl(&src_reg->imsc);
+ CRYP_PUT_BITS(&src_reg->cr, 1, CRYP_CR_KEYRDEN_POS,
+ CRYP_CR_KEYRDEN_MASK);
ctx->key_1_l = readl(&src_reg->key_1_l);
ctx->key_1_r = readl(&src_reg->key_1_r);
@@ -466,10 +327,21 @@ void cryp_save_device_context(struct cryp_device_data *device_data,
ctx->key_4_l = readl(&src_reg->key_4_l);
ctx->key_4_r = readl(&src_reg->key_4_r);
- 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);
- ctx->init_vect_1_r = readl(&src_reg->init_vect_1_r);
+ CRYP_PUT_BITS(&src_reg->cr, 0, CRYP_CR_KEYRDEN_POS,
+ CRYP_CR_KEYRDEN_MASK);
+
+ /* 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) {
+ 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);
+ ctx->init_vect_1_r = readl(&src_reg->init_vect_1_r);
+ }
}
/**
@@ -482,26 +354,44 @@ void cryp_restore_device_context(struct cryp_device_data *device_data,
struct cryp_device_context *ctx)
{
struct cryp_register *reg = device_data->base;
+ struct cryp_config *config =
+ (struct cryp_config *)device_data->current_ctx;
+
- cryp_prep_ctx_mgmt(device_data);
+ /*
+ * Fall through for all items in switch statement. DES is captured in
+ * the default.
+ */
+ switch (config->keysize) {
+ case CRYP_KEY_SIZE_256:
+ writel(ctx->key_4_l, &reg->key_4_l);
+ writel(ctx->key_4_r, &reg->key_4_r);
+
+ case CRYP_KEY_SIZE_192:
+ writel(ctx->key_3_l, &reg->key_3_l);
+ writel(ctx->key_3_r, &reg->key_3_r);
+
+ case CRYP_KEY_SIZE_128:
+ writel(ctx->key_2_l, &reg->key_2_l);
+ writel(ctx->key_2_r, &reg->key_2_r);
+
+ default:
+ writel(ctx->key_1_l, &reg->key_1_l);
+ writel(ctx->key_1_r, &reg->key_1_r);
+ }
+
+ /* Restore IV for CBC mode for AES and DES. */
+ if (config->algomode == CRYP_ALGO_TDES_CBC ||
+ config->algomode == CRYP_ALGO_DES_CBC ||
+ config->algomode == CRYP_ALGO_AES_CBC) {
+ writel(ctx->init_vect_0_l, &reg->init_vect_0_l);
+ writel(ctx->init_vect_0_r, &reg->init_vect_0_r);
+ writel(ctx->init_vect_1_l, &reg->init_vect_1_l);
+ writel(ctx->init_vect_1_r, &reg->init_vect_1_r);
+ }
- writel(ctx->din, &reg->din);
- writel(ctx->dout, &reg->dout);
writel(ctx->cr, &reg->cr);
- writel(ctx->dmacr, &reg->dmacr);
- writel(ctx->imsc, &reg->imsc);
- writel(ctx->key_1_l, &reg->key_1_l);
- writel(ctx->key_1_r, &reg->key_1_r);
- writel(ctx->key_2_l, &reg->key_2_l);
- writel(ctx->key_2_r, &reg->key_2_r);
- writel(ctx->key_3_l, &reg->key_3_l);
- writel(ctx->key_3_r, &reg->key_3_r);
- writel(ctx->key_4_l, &reg->key_4_l);
- writel(ctx->key_4_r, &reg->key_4_r);
- writel(ctx->init_vect_0_l, &reg->init_vect_0_l);
- writel(ctx->init_vect_0_r, &reg->init_vect_0_r);
- writel(ctx->init_vect_1_l, &reg->init_vect_1_l);
- writel(ctx->init_vect_1_r, &reg->init_vect_1_r);
+ cryp_activity(device_data, CRYP_CRYPEN_ENABLE);
}
/**
@@ -520,24 +410,6 @@ int cryp_write_indata(struct cryp_device_data *device_data, u32 write_data)
}
/**
- * cryp_read_indata - This routine reads the 32 bit data from the data input
- * register into the specified location.
- * @device_data: Pointer to the device data struct for base address.
- * @p_read_data: Read the data from the input FIFO.
- */
-int cryp_read_indata(struct cryp_device_data *device_data, u32 *p_read_data)
-{
- if (NULL == device_data)
- return -EINVAL;
- if (NULL == p_read_data)
- return -EINVAL;
-
- *p_read_data = readl(&device_data->base->din);
-
- return 0;
-}
-
-/**
* cryp_read_outdata - This routine reads the data from the data output
* register of the CRYP logic
* @device_data: Pointer to the device data struct for base address.