You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
5.1 KiB
150 lines
5.1 KiB
From 1e932b627e79aa2c70e2c7278e4ac930303faa3f Mon Sep 17 00:00:00 2001
|
|
From: Christian Lamparter <chunkeey@gmail.com>
|
|
Date: Thu, 21 Dec 2017 15:09:18 +0100
|
|
Subject: [PATCH 2/6] crypto: crypto4xx - support Revision B parts
|
|
|
|
This patch adds support for the crypto4xx RevB cores
|
|
found in the 460EX, 460SX and later cores (like the APM821xx).
|
|
|
|
Without this patch, the crypto4xx driver will not be
|
|
able to process any offloaded requests and simply hang
|
|
indefinitely.
|
|
|
|
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
|
---
|
|
drivers/crypto/amcc/crypto4xx_core.c | 48 +++++++++++++++++++++++++++++----
|
|
drivers/crypto/amcc/crypto4xx_core.h | 1 +
|
|
drivers/crypto/amcc/crypto4xx_reg_def.h | 4 ++-
|
|
3 files changed, 47 insertions(+), 6 deletions(-)
|
|
|
|
--- a/drivers/crypto/amcc/crypto4xx_core.c
|
|
+++ b/drivers/crypto/amcc/crypto4xx_core.c
|
|
@@ -128,7 +128,14 @@ static void crypto4xx_hw_init(struct cry
|
|
writel(PPC4XX_INT_DESCR_CNT, dev->ce_base + CRYPTO4XX_INT_DESCR_CNT);
|
|
writel(PPC4XX_INT_DESCR_CNT, dev->ce_base + CRYPTO4XX_INT_DESCR_CNT);
|
|
writel(PPC4XX_INT_CFG, dev->ce_base + CRYPTO4XX_INT_CFG);
|
|
- writel(PPC4XX_PD_DONE_INT, dev->ce_base + CRYPTO4XX_INT_EN);
|
|
+ if (dev->is_revb) {
|
|
+ writel(PPC4XX_INT_TIMEOUT_CNT_REVB << 10,
|
|
+ dev->ce_base + CRYPTO4XX_INT_TIMEOUT_CNT);
|
|
+ writel(PPC4XX_PD_DONE_INT | PPC4XX_TMO_ERR_INT,
|
|
+ dev->ce_base + CRYPTO4XX_INT_EN);
|
|
+ } else {
|
|
+ writel(PPC4XX_PD_DONE_INT, dev->ce_base + CRYPTO4XX_INT_EN);
|
|
+ }
|
|
}
|
|
|
|
int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size)
|
|
@@ -1079,18 +1086,29 @@ static void crypto4xx_bh_tasklet_cb(unsi
|
|
/**
|
|
* Top Half of isr.
|
|
*/
|
|
-static irqreturn_t crypto4xx_ce_interrupt_handler(int irq, void *data)
|
|
+static inline irqreturn_t crypto4xx_interrupt_handler(int irq, void *data,
|
|
+ u32 clr_val)
|
|
{
|
|
struct device *dev = (struct device *)data;
|
|
struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
|
|
|
|
- writel(PPC4XX_INTERRUPT_CLR,
|
|
- core_dev->dev->ce_base + CRYPTO4XX_INT_CLR);
|
|
+ writel(clr_val, core_dev->dev->ce_base + CRYPTO4XX_INT_CLR);
|
|
tasklet_schedule(&core_dev->tasklet);
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
+static irqreturn_t crypto4xx_ce_interrupt_handler(int irq, void *data)
|
|
+{
|
|
+ return crypto4xx_interrupt_handler(irq, data, PPC4XX_INTERRUPT_CLR);
|
|
+}
|
|
+
|
|
+static irqreturn_t crypto4xx_ce_interrupt_handler_revb(int irq, void *data)
|
|
+{
|
|
+ return crypto4xx_interrupt_handler(irq, data, PPC4XX_INTERRUPT_CLR |
|
|
+ PPC4XX_TMO_ERR_INT);
|
|
+}
|
|
+
|
|
/**
|
|
* Supported Crypto Algorithms
|
|
*/
|
|
@@ -1272,6 +1290,8 @@ static int crypto4xx_probe(struct platfo
|
|
struct resource res;
|
|
struct device *dev = &ofdev->dev;
|
|
struct crypto4xx_core_device *core_dev;
|
|
+ u32 pvr;
|
|
+ bool is_revb = true;
|
|
|
|
rc = of_address_to_resource(ofdev->dev.of_node, 0, &res);
|
|
if (rc)
|
|
@@ -1288,6 +1308,7 @@ static int crypto4xx_probe(struct platfo
|
|
mfdcri(SDR0, PPC405EX_SDR0_SRST) | PPC405EX_CE_RESET);
|
|
mtdcri(SDR0, PPC405EX_SDR0_SRST,
|
|
mfdcri(SDR0, PPC405EX_SDR0_SRST) & ~PPC405EX_CE_RESET);
|
|
+ is_revb = false;
|
|
} else if (of_find_compatible_node(NULL, NULL,
|
|
"amcc,ppc460sx-crypto")) {
|
|
mtdcri(SDR0, PPC460SX_SDR0_SRST,
|
|
@@ -1310,7 +1331,22 @@ static int crypto4xx_probe(struct platfo
|
|
if (!core_dev->dev)
|
|
goto err_alloc_dev;
|
|
|
|
+ /*
|
|
+ * Older version of 460EX/GT have a hardware bug.
|
|
+ * Hence they do not support H/W based security intr coalescing
|
|
+ */
|
|
+ pvr = mfspr(SPRN_PVR);
|
|
+ if (is_revb && ((pvr >> 4) == 0x130218A)) {
|
|
+ u32 min = PVR_MIN(pvr);
|
|
+
|
|
+ if (min < 4) {
|
|
+ dev_info(dev, "RevA detected - disable interrupt coalescing\n");
|
|
+ is_revb = false;
|
|
+ }
|
|
+ }
|
|
+
|
|
core_dev->dev->core_dev = core_dev;
|
|
+ core_dev->dev->is_revb = is_revb;
|
|
core_dev->device = dev;
|
|
spin_lock_init(&core_dev->lock);
|
|
INIT_LIST_HEAD(&core_dev->dev->alg_list);
|
|
@@ -1340,7 +1376,9 @@ static int crypto4xx_probe(struct platfo
|
|
|
|
/* Register for Crypto isr, Crypto Engine IRQ */
|
|
core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
|
|
- rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0,
|
|
+ rc = request_irq(core_dev->irq, is_revb ?
|
|
+ crypto4xx_ce_interrupt_handler_revb :
|
|
+ crypto4xx_ce_interrupt_handler, 0,
|
|
core_dev->dev->name, dev);
|
|
if (rc)
|
|
goto err_request_irq;
|
|
--- a/drivers/crypto/amcc/crypto4xx_core.h
|
|
+++ b/drivers/crypto/amcc/crypto4xx_core.h
|
|
@@ -109,6 +109,7 @@ struct crypto4xx_device {
|
|
struct list_head alg_list; /* List of algorithm supported
|
|
by this device */
|
|
struct ratelimit_state aead_ratelimit;
|
|
+ bool is_revb;
|
|
};
|
|
|
|
struct crypto4xx_core_device {
|
|
--- a/drivers/crypto/amcc/crypto4xx_reg_def.h
|
|
+++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
|
|
@@ -121,13 +121,15 @@
|
|
#define PPC4XX_PD_SIZE 6
|
|
#define PPC4XX_CTX_DONE_INT 0x2000
|
|
#define PPC4XX_PD_DONE_INT 0x8000
|
|
+#define PPC4XX_TMO_ERR_INT 0x40000
|
|
#define PPC4XX_BYTE_ORDER 0x22222
|
|
#define PPC4XX_INTERRUPT_CLR 0x3ffff
|
|
#define PPC4XX_PRNG_CTRL_AUTO_EN 0x3
|
|
#define PPC4XX_DC_3DES_EN 1
|
|
#define PPC4XX_TRNG_EN 0x00020000
|
|
-#define PPC4XX_INT_DESCR_CNT 4
|
|
+#define PPC4XX_INT_DESCR_CNT 7
|
|
#define PPC4XX_INT_TIMEOUT_CNT 0
|
|
+#define PPC4XX_INT_TIMEOUT_CNT_REVB 0x3FF
|
|
#define PPC4XX_INT_CFG 1
|
|
/**
|
|
* all follow define are ad hoc
|
|
|