Commit e66862e6 authored by Corentin Labbe's avatar Corentin Labbe Committed by Herbert Xu
Browse files

crypto: sun8i-ce - handle different error registers



Error registers are different across SoCs.
This patch handle those difference.

Signed-off-by: default avatarCorentin Labbe <clabbe@baylibre.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 0605fa0f
Loading
Loading
Loading
Loading
+54 −8
Original line number Diff line number Diff line
@@ -40,7 +40,8 @@ static const struct ce_variant ce_h3_variant = {
	.ce_clks = {
		{ "bus", 0, 200000000 },
		{ "mod", 50000000, 0 },
		}
		},
	.esr = ESR_H3,
};

static const struct ce_variant ce_h5_variant = {
@@ -51,7 +52,8 @@ static const struct ce_variant ce_h5_variant = {
	.ce_clks = {
		{ "bus", 0, 200000000 },
		{ "mod", 300000000, 0 },
		}
		},
	.esr = ESR_H5,
};

static const struct ce_variant ce_h6_variant = {
@@ -64,7 +66,8 @@ static const struct ce_variant ce_h6_variant = {
		{ "bus", 0, 200000000 },
		{ "mod", 300000000, 0 },
		{ "ram", 0, 400000000 },
		}
		},
	.esr = ESR_H6,
};

static const struct ce_variant ce_a64_variant = {
@@ -75,7 +78,8 @@ static const struct ce_variant ce_a64_variant = {
	.ce_clks = {
		{ "bus", 0, 200000000 },
		{ "mod", 300000000, 0 },
		}
		},
	.esr = ESR_A64,
};

static const struct ce_variant ce_r40_variant = {
@@ -86,7 +90,8 @@ static const struct ce_variant ce_r40_variant = {
	.ce_clks = {
		{ "bus", 0, 200000000 },
		{ "mod", 300000000, 0 },
		}
		},
	.esr = ESR_R40,
};

/*
@@ -102,6 +107,7 @@ int sun8i_ce_run_task(struct sun8i_ce_dev *ce, int flow, const char *name)
{
	u32 v;
	int err = 0;
	struct ce_task *cet = ce->chanlist[flow].tl;

#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG
	ce->chanlist[flow].stat_req++;
@@ -131,19 +137,56 @@ int sun8i_ce_run_task(struct sun8i_ce_dev *ce, int flow, const char *name)
			msecs_to_jiffies(ce->chanlist[flow].timeout));

	if (ce->chanlist[flow].status == 0) {
		dev_err(ce->dev, "DMA timeout for %s\n", name);
		dev_err(ce->dev, "DMA timeout for %s (tm=%d) on flow %d\n", name,
			ce->chanlist[flow].timeout, flow);
		err = -EFAULT;
	}
	/* No need to lock for this read, the channel is locked so
	 * nothing could modify the error value for this channel
	 */
	v = readl(ce->base + CE_ESR);
	switch (ce->variant->esr) {
	case ESR_H3:
		/* Sadly, the error bit is not per flow */
		if (v) {
			dev_err(ce->dev, "CE ERROR: %x for flow %x\n", v, flow);
			err = -EFAULT;
			print_hex_dump(KERN_INFO, "TASK: ", DUMP_PREFIX_NONE, 16, 4,
				       cet, sizeof(struct ce_task), false);
		}
		if (v & CE_ERR_ALGO_NOTSUP)
			dev_err(ce->dev, "CE ERROR: algorithm not supported\n");
		if (v & CE_ERR_DATALEN)
			dev_err(ce->dev, "CE ERROR: data length error\n");
		if (v & CE_ERR_KEYSRAM)
			dev_err(ce->dev, "CE ERROR: keysram access error for AES\n");
		break;
	case ESR_A64:
	case ESR_H5:
	case ESR_R40:
		v >>= (flow * 4);
		v &= 0xF;
		if (v) {
			dev_err(ce->dev, "CE ERROR: %x for flow %x\n", v, flow);
			err = -EFAULT;
			print_hex_dump(KERN_INFO, "TASK: ", DUMP_PREFIX_NONE, 16, 4,
				       cet, sizeof(struct ce_task), false);
		}
		if (v & CE_ERR_ALGO_NOTSUP)
			dev_err(ce->dev, "CE ERROR: algorithm not supported\n");
		if (v & CE_ERR_DATALEN)
			dev_err(ce->dev, "CE ERROR: data length error\n");
		if (v & CE_ERR_KEYSRAM)
			dev_err(ce->dev, "CE ERROR: keysram access error for AES\n");
		break;
	case ESR_H6:
		v >>= (flow * 8);
		v &= 0xFF;
		if (v) {
			dev_err(ce->dev, "CE ERROR: %x for flow %x\n", v, flow);
			err = -EFAULT;
			print_hex_dump(KERN_INFO, "TASK: ", DUMP_PREFIX_NONE, 16, 4,
				       cet, sizeof(struct ce_task), false);
		}
		if (v & CE_ERR_ALGO_NOTSUP)
			dev_err(ce->dev, "CE ERROR: algorithm not supported\n");
@@ -153,6 +196,9 @@ int sun8i_ce_run_task(struct sun8i_ce_dev *ce, int flow, const char *name)
			dev_err(ce->dev, "CE ERROR: keysram access error for AES\n");
		if (v & CE_ERR_ADDR_INVALID)
			dev_err(ce->dev, "CE ERROR: address invalid\n");
		if (v & CE_ERR_KEYLADDER)
			dev_err(ce->dev, "CE ERROR: key ladder configuration error\n");
		break;
	}

	return err;
+8 −0
Original line number Diff line number Diff line
@@ -65,6 +65,12 @@
#define CE_ERR_ADDR_INVALID	BIT(5)
#define CE_ERR_KEYLADDER	BIT(6)

#define ESR_H3	0
#define ESR_A64	1
#define ESR_R40	2
#define ESR_H5	3
#define ESR_H6	4

#define CE_DIE_ID_SHIFT	16
#define CE_DIE_ID_MASK	0x07

@@ -94,12 +100,14 @@ struct ce_clock {
 * @has_t_dlen_in_bytes:	Does the request size for cipher is in
 *				bytes or words
 * @ce_clks:	list of clocks needed by this variant
 * @esr:	The type of error register
 */
struct ce_variant {
	char alg_cipher[CE_ID_CIPHER_MAX];
	u32 op_mode[CE_ID_OP_MAX];
	bool has_t_dlen_in_bytes;
	struct ce_clock ce_clks[CE_MAX_CLOCKS];
	int esr;
};

struct sginfo {