diff options
Diffstat (limited to 'drivers/crypto/ux500/cryp/cryp.c')
-rw-r--r-- | drivers/crypto/ux500/cryp/cryp.c | 392 |
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, ®->key_4_l); + writel(ctx->key_4_r, ®->key_4_r); + + case CRYP_KEY_SIZE_192: + writel(ctx->key_3_l, ®->key_3_l); + writel(ctx->key_3_r, ®->key_3_r); + + case CRYP_KEY_SIZE_128: + writel(ctx->key_2_l, ®->key_2_l); + writel(ctx->key_2_r, ®->key_2_r); + + default: + writel(ctx->key_1_l, ®->key_1_l); + writel(ctx->key_1_r, ®->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, ®->init_vect_0_l); + writel(ctx->init_vect_0_r, ®->init_vect_0_r); + writel(ctx->init_vect_1_l, ®->init_vect_1_l); + writel(ctx->init_vect_1_r, ®->init_vect_1_r); + } - writel(ctx->din, ®->din); - writel(ctx->dout, ®->dout); writel(ctx->cr, ®->cr); - writel(ctx->dmacr, ®->dmacr); - writel(ctx->imsc, ®->imsc); - writel(ctx->key_1_l, ®->key_1_l); - writel(ctx->key_1_r, ®->key_1_r); - writel(ctx->key_2_l, ®->key_2_l); - writel(ctx->key_2_r, ®->key_2_r); - writel(ctx->key_3_l, ®->key_3_l); - writel(ctx->key_3_r, ®->key_3_r); - writel(ctx->key_4_l, ®->key_4_l); - writel(ctx->key_4_r, ®->key_4_r); - writel(ctx->init_vect_0_l, ®->init_vect_0_l); - writel(ctx->init_vect_0_r, ®->init_vect_0_r); - writel(ctx->init_vect_1_l, ®->init_vect_1_l); - writel(ctx->init_vect_1_r, ®->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. |