Commit 848572f8 authored by Tudor Ambarus's avatar Tudor Ambarus Committed by Herbert Xu
Browse files

crypto: atmel-tdes - Map driver data flags to Mode Register



Simplifies the configuration of the TDES IP.

Signed-off-by: default avatarTudor Ambarus <tudor.ambarus@microchip.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 7d0979e2
Loading
Loading
Loading
Loading
+71 −73
Original line number Diff line number Diff line
@@ -40,20 +40,23 @@
#define ATMEL_TDES_PRIORITY	300

/* TDES flags  */
#define TDES_FLAGS_MODE_MASK		0x00ff
#define TDES_FLAGS_ENCRYPT	BIT(0)
#define TDES_FLAGS_CBC		BIT(1)
#define TDES_FLAGS_CFB		BIT(2)
#define TDES_FLAGS_CFB8		BIT(3)
#define TDES_FLAGS_CFB16	BIT(4)
#define TDES_FLAGS_CFB32	BIT(5)
#define TDES_FLAGS_CFB64	BIT(6)
#define TDES_FLAGS_OFB		BIT(7)

#define TDES_FLAGS_INIT		BIT(16)
#define TDES_FLAGS_FAST		BIT(17)
#define TDES_FLAGS_BUSY		BIT(18)
#define TDES_FLAGS_DMA		BIT(19)
/* Reserve bits [17:16], [13:12], [2:0] for AES Mode Register */
#define TDES_FLAGS_ENCRYPT	TDES_MR_CYPHER_ENC
#define TDES_FLAGS_OPMODE_MASK	(TDES_MR_OPMOD_MASK | TDES_MR_CFBS_MASK)
#define TDES_FLAGS_ECB		TDES_MR_OPMOD_ECB
#define TDES_FLAGS_CBC		TDES_MR_OPMOD_CBC
#define TDES_FLAGS_OFB		TDES_MR_OPMOD_OFB
#define TDES_FLAGS_CFB64	(TDES_MR_OPMOD_CFB | TDES_MR_CFBS_64b)
#define TDES_FLAGS_CFB32	(TDES_MR_OPMOD_CFB | TDES_MR_CFBS_32b)
#define TDES_FLAGS_CFB16	(TDES_MR_OPMOD_CFB | TDES_MR_CFBS_16b)
#define TDES_FLAGS_CFB8		(TDES_MR_OPMOD_CFB | TDES_MR_CFBS_8b)

#define TDES_FLAGS_MODE_MASK	(TDES_FLAGS_OPMODE_MASK | TDES_FLAGS_ENCRYPT)

#define TDES_FLAGS_INIT		BIT(3)
#define TDES_FLAGS_FAST		BIT(4)
#define TDES_FLAGS_BUSY		BIT(5)
#define TDES_FLAGS_DMA		BIT(6)

#define ATMEL_TDES_QUEUE_LENGTH	50

@@ -287,35 +290,15 @@ static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd)
		valmr |= TDES_MR_TDESMOD_DES;
	}

	if (dd->flags & TDES_FLAGS_CBC) {
		valmr |= TDES_MR_OPMOD_CBC;
	} else if (dd->flags & TDES_FLAGS_CFB) {
		valmr |= TDES_MR_OPMOD_CFB;

		if (dd->flags & TDES_FLAGS_CFB8)
			valmr |= TDES_MR_CFBS_8b;
		else if (dd->flags & TDES_FLAGS_CFB16)
			valmr |= TDES_MR_CFBS_16b;
		else if (dd->flags & TDES_FLAGS_CFB32)
			valmr |= TDES_MR_CFBS_32b;
		else if (dd->flags & TDES_FLAGS_CFB64)
			valmr |= TDES_MR_CFBS_64b;
	} else if (dd->flags & TDES_FLAGS_OFB) {
		valmr |= TDES_MR_OPMOD_OFB;
	}

	if ((dd->flags & TDES_FLAGS_ENCRYPT) || (dd->flags & TDES_FLAGS_OFB))
		valmr |= TDES_MR_CYPHER_ENC;
	valmr |= dd->flags & TDES_FLAGS_MODE_MASK;

	atmel_tdes_write(dd, TDES_MR, valmr);

	atmel_tdes_write_n(dd, TDES_KEY1W1R, dd->ctx->key,
						dd->ctx->keylen >> 2);

	if (((dd->flags & TDES_FLAGS_CBC) || (dd->flags & TDES_FLAGS_CFB) ||
		(dd->flags & TDES_FLAGS_OFB)) && dd->req->iv) {
	if (dd->req->iv && (valmr & TDES_MR_OPMOD_MASK) != TDES_MR_OPMOD_ECB)
		atmel_tdes_write_n(dd, TDES_IV1R, (void *)dd->req->iv, 2);
	}

	return 0;
}
@@ -406,6 +389,7 @@ static int atmel_tdes_crypt_pdc(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
{
	struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
	struct atmel_tdes_dev *dd = ctx->dd;
	struct atmel_tdes_reqctx *rctx = skcipher_request_ctx(dd->req);
	int len32;

	dd->dma_size = length;
@@ -415,12 +399,19 @@ static int atmel_tdes_crypt_pdc(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
					   DMA_TO_DEVICE);
	}

	if ((dd->flags & TDES_FLAGS_CFB) && (dd->flags & TDES_FLAGS_CFB8))
	switch (rctx->mode & TDES_FLAGS_OPMODE_MASK) {
	case TDES_FLAGS_CFB8:
		len32 = DIV_ROUND_UP(length, sizeof(u8));
	else if ((dd->flags & TDES_FLAGS_CFB) && (dd->flags & TDES_FLAGS_CFB16))
		break;

	case TDES_FLAGS_CFB16:
		len32 = DIV_ROUND_UP(length, sizeof(u16));
	else
		break;

	default:
		len32 = DIV_ROUND_UP(length, sizeof(u32));
		break;
	}

	atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS);
	atmel_tdes_write(dd, TDES_TPR, dma_addr_in);
@@ -442,8 +433,10 @@ static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
{
	struct atmel_tdes_ctx *ctx = crypto_tfm_ctx(tfm);
	struct atmel_tdes_dev *dd = ctx->dd;
	struct atmel_tdes_reqctx *rctx = skcipher_request_ctx(dd->req);
	struct scatterlist sg[2];
	struct dma_async_tx_descriptor	*in_desc, *out_desc;
	enum dma_slave_buswidth addr_width;

	dd->dma_size = length;

@@ -452,23 +445,23 @@ static int atmel_tdes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
					   DMA_TO_DEVICE);
	}

	if (dd->flags & TDES_FLAGS_CFB8) {
		dd->dma_lch_in.dma_conf.dst_addr_width =
			DMA_SLAVE_BUSWIDTH_1_BYTE;
		dd->dma_lch_out.dma_conf.src_addr_width =
			DMA_SLAVE_BUSWIDTH_1_BYTE;
	} else if (dd->flags & TDES_FLAGS_CFB16) {
		dd->dma_lch_in.dma_conf.dst_addr_width =
			DMA_SLAVE_BUSWIDTH_2_BYTES;
		dd->dma_lch_out.dma_conf.src_addr_width =
			DMA_SLAVE_BUSWIDTH_2_BYTES;
	} else {
		dd->dma_lch_in.dma_conf.dst_addr_width =
			DMA_SLAVE_BUSWIDTH_4_BYTES;
		dd->dma_lch_out.dma_conf.src_addr_width =
			DMA_SLAVE_BUSWIDTH_4_BYTES;
	switch (rctx->mode & TDES_FLAGS_OPMODE_MASK) {
	case TDES_FLAGS_CFB8:
		addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
		break;

	case TDES_FLAGS_CFB16:
		addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
		break;

	default:
		addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		break;
	}

	dd->dma_lch_in.dma_conf.dst_addr_width = addr_width;
	dd->dma_lch_out.dma_conf.src_addr_width = addr_width;

	dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
	dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf);

@@ -703,30 +696,38 @@ static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode)
	struct atmel_tdes_ctx *ctx = crypto_skcipher_ctx(skcipher);
	struct atmel_tdes_reqctx *rctx = skcipher_request_ctx(req);

	if (mode & TDES_FLAGS_CFB8) {
	switch (mode & TDES_FLAGS_OPMODE_MASK) {
	case TDES_FLAGS_CFB8:
		if (!IS_ALIGNED(req->cryptlen, CFB8_BLOCK_SIZE)) {
			pr_err("request size is not exact amount of CFB8 blocks\n");
			return -EINVAL;
		}
		ctx->block_size = CFB8_BLOCK_SIZE;
	} else if (mode & TDES_FLAGS_CFB16) {
		break;

	case TDES_FLAGS_CFB16:
		if (!IS_ALIGNED(req->cryptlen, CFB16_BLOCK_SIZE)) {
			pr_err("request size is not exact amount of CFB16 blocks\n");
			return -EINVAL;
		}
		ctx->block_size = CFB16_BLOCK_SIZE;
	} else if (mode & TDES_FLAGS_CFB32) {
		break;

	case TDES_FLAGS_CFB32:
		if (!IS_ALIGNED(req->cryptlen, CFB32_BLOCK_SIZE)) {
			pr_err("request size is not exact amount of CFB32 blocks\n");
			return -EINVAL;
		}
		ctx->block_size = CFB32_BLOCK_SIZE;
	} else {
		break;

	default:
		if (!IS_ALIGNED(req->cryptlen, DES_BLOCK_SIZE)) {
			pr_err("request size is not exact amount of DES blocks\n");
			return -EINVAL;
		}
		ctx->block_size = DES_BLOCK_SIZE;
		break;
	}

	rctx->mode = mode;
@@ -833,17 +834,17 @@ static int atmel_tdes_setkey(struct crypto_skcipher *tfm, const u8 *key,

static int atmel_tdes_ecb_encrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT);
	return atmel_tdes_crypt(req, TDES_FLAGS_ECB | TDES_FLAGS_ENCRYPT);
}

static int atmel_tdes_ecb_decrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, 0);
	return atmel_tdes_crypt(req, TDES_FLAGS_ECB);
}

static int atmel_tdes_cbc_encrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CBC);
	return atmel_tdes_crypt(req, TDES_FLAGS_CBC | TDES_FLAGS_ENCRYPT);
}

static int atmel_tdes_cbc_decrypt(struct skcipher_request *req)
@@ -852,50 +853,47 @@ static int atmel_tdes_cbc_decrypt(struct skcipher_request *req)
}
static int atmel_tdes_cfb_encrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB);
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB64 | TDES_FLAGS_ENCRYPT);
}

static int atmel_tdes_cfb_decrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB);
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB64);
}

static int atmel_tdes_cfb8_encrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
						TDES_FLAGS_CFB8);
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB8 | TDES_FLAGS_ENCRYPT);
}

static int atmel_tdes_cfb8_decrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB8);
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB8);
}

static int atmel_tdes_cfb16_encrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
						TDES_FLAGS_CFB16);
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB16 | TDES_FLAGS_ENCRYPT);
}

static int atmel_tdes_cfb16_decrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB16);
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB16);
}

static int atmel_tdes_cfb32_encrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_CFB |
						TDES_FLAGS_CFB32);
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB32 | TDES_FLAGS_ENCRYPT);
}

static int atmel_tdes_cfb32_decrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB | TDES_FLAGS_CFB32);
	return atmel_tdes_crypt(req, TDES_FLAGS_CFB32);
}

static int atmel_tdes_ofb_encrypt(struct skcipher_request *req)
{
	return atmel_tdes_crypt(req, TDES_FLAGS_ENCRYPT | TDES_FLAGS_OFB);
	return atmel_tdes_crypt(req, TDES_FLAGS_OFB | TDES_FLAGS_ENCRYPT);
}

static int atmel_tdes_ofb_decrypt(struct skcipher_request *req)