diff options
author | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2013-02-04 15:23:10 +0000 |
---|---|---|
committer | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2013-02-04 15:23:10 +0000 |
commit | c279470c06c135961bd60905e755ab4b06c10229 (patch) | |
tree | 2228db80941708e1ce07a929ea9fc9096806d27a /target/linux/coldfire/patches/024-Add-SEC-1.1-support-for-MCF547x-and-MCF548x.patch | |
parent | df7b7e61854c0e0da9e75b4a678f0e3b196f79ea (diff) |
coldfire: R.I.P.
The target still uses 2.6.38. The support of that
kernel version has been removed ~9 months ago.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35489 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/coldfire/patches/024-Add-SEC-1.1-support-for-MCF547x-and-MCF548x.patch')
-rw-r--r-- | target/linux/coldfire/patches/024-Add-SEC-1.1-support-for-MCF547x-and-MCF548x.patch | 2093 |
1 files changed, 0 insertions, 2093 deletions
diff --git a/target/linux/coldfire/patches/024-Add-SEC-1.1-support-for-MCF547x-and-MCF548x.patch b/target/linux/coldfire/patches/024-Add-SEC-1.1-support-for-MCF547x-and-MCF548x.patch deleted file mode 100644 index 53cebe184..000000000 --- a/target/linux/coldfire/patches/024-Add-SEC-1.1-support-for-MCF547x-and-MCF548x.patch +++ /dev/null @@ -1,2093 +0,0 @@ -From c925421b8c35357427499f3d298777535c2c6cfd Mon Sep 17 00:00:00 2001 -From: Alison Wang <b18965@freescale.com> -Date: Thu, 4 Aug 2011 09:59:45 +0800 -Subject: [PATCH 24/52] Add SEC 1.1 support for MCF547x and MCF548x - -Add SEC 1.1 support for MCF547x and MCF548x. The SEC driver is -in drivers/crypto. - -Signed-off-by: Alison Wang <b18965@freescale.com> ---- - arch/m68k/coldfire/m547x/mcf548x-devices.c | 2 +- - arch/m68k/include/asm/cf_io.h | 4 + - crypto/testmgr.c | 18 +- - drivers/crypto/Kconfig | 13 + - drivers/crypto/Makefile | 1 + - drivers/crypto/cf_talitos.c | 1727 ++++++++++++++++++++++++++++ - drivers/crypto/cf_talitos.h | 229 ++++ - 7 files changed, 1989 insertions(+), 5 deletions(-) - create mode 100644 drivers/crypto/cf_talitos.c - create mode 100644 drivers/crypto/cf_talitos.h - ---- a/arch/m68k/coldfire/m547x/mcf548x-devices.c -+++ b/arch/m68k/coldfire/m547x/mcf548x-devices.c -@@ -54,7 +54,7 @@ static struct resource coldfire_sec_reso - }; - - static struct platform_device coldfire_sec_device = { -- .name = "fsl-sec1", -+ .name = "talitos", - .id = -1, - .num_resources = ARRAY_SIZE(coldfire_sec_resources), - .resource = coldfire_sec_resources, ---- a/arch/m68k/include/asm/cf_io.h -+++ b/arch/m68k/include/asm/cf_io.h -@@ -192,4 +192,8 @@ static inline void memcpy_toio(volatile - #define writel(b, addr) (void)((*(volatile unsigned int *) (addr)) = (b)) - #endif /* readb */ - -+/* access ports */ -+#define setbits32(_addr, _v) out_be32((_addr), in_be32(_addr) | (_v)) -+#define clrbits32(_addr, _v) out_be32((_addr), in_be32(_addr) & ~(_v)) -+ - #endif /* _IO_H */ ---- a/crypto/testmgr.c -+++ b/crypto/testmgr.c -@@ -212,7 +212,11 @@ static int test_hash(struct crypto_ahash - tcrypt_complete, &tresult); - - j = 0; -+#if defined(CONFIG_CRYPTO_DEV_CF_TALITOS) -+ for (i = 1; i < tcount; i++) { -+#else - for (i = 0; i < tcount; i++) { -+#endif - if (template[i].np) - continue; - -@@ -276,7 +280,9 @@ static int test_hash(struct crypto_ahash - hexdump(result, crypto_ahash_digestsize(tfm)); - ret = -EINVAL; - goto out; -- } -+ } else -+ printk(KERN_INFO "alg: hash: Test %d succeed for %s\n", -+ j, algo); - } - - j = 0; -@@ -344,7 +350,9 @@ static int test_hash(struct crypto_ahash - hexdump(result, crypto_ahash_digestsize(tfm)); - ret = -EINVAL; - goto out; -- } -+ } else -+ printk(KERN_INFO "alg: hash: Chunking test %d " -+ "succeed for %s\n", j, algo); - } - } - -@@ -788,7 +796,6 @@ static int test_skcipher(struct crypto_a - else - e = "decryption"; - -- printk(KERN_INFO "%s testing %s %s\n", __func__, algo, e); - init_completion(&result.completion); - - req = ablkcipher_request_alloc(tfm, GFP_KERNEL); -@@ -963,7 +970,10 @@ static int test_skcipher(struct crypto_a - "%u for %s\n", j, e, k, algo); - hexdump(q, template[i].tap[k]); - goto out; -- } -+ } else -+ printk(KERN_INFO "alg: skcipher: Chunk " -+ "test %d pass on %s for %s\n", -+ j, e, algo); - - q += template[i].tap[k]; - for (n = 0; offset_in_page(q + n) && q[n]; n++) ---- a/drivers/crypto/Kconfig -+++ b/drivers/crypto/Kconfig -@@ -282,6 +282,19 @@ config CRYPTO_DEV_TALITOS - To compile this driver as a module, choose M here: the module - will be called talitos. - -+config CRYPTO_DEV_CF_TALITOS -+ tristate "Talitos Freescale Coldfire Security Engine (SEC)" -+ select CRYPTO_ALGAPI -+ select CRYPTO_AUTHENC -+ select HW_RANDOM -+ depends on (M547X || M548X) -+ help -+ Say 'Y' here to use the Freescale Coldfire Security Engine (SEC) -+ to offload cryptographic algorithm computation. -+ -+ The Freescale SEC is present on Coldfire MCF547x and MCF548x -+ processors. -+ - config CRYPTO_DEV_IXP4XX - tristate "Driver for IXP4xx crypto hardware acceleration" - depends on ARCH_IXP4XX ---- a/drivers/crypto/Makefile -+++ b/drivers/crypto/Makefile -@@ -6,6 +6,7 @@ n2_crypto-y := n2_core.o n2_asm.o - obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o - obj-$(CONFIG_CRYPTO_DEV_MV_CESA) += mv_cesa.o - obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o -+obj-$(CONFIG_CRYPTO_DEV_CF_TALITOS) += cf_talitos.o - obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o - obj-$(CONFIG_CRYPTO_DEV_MCFCAU) += mcfcau.o - obj-$(CONFIG_CRYPTO_DEV_MCFCAU_DES) += mcfcau-des.o ---- /dev/null -+++ b/drivers/crypto/cf_talitos.c -@@ -0,0 +1,1727 @@ -+/* -+ * cf_talitos - Freescale Coldfire Integrated Security Engine -+ * (SEC) device driver -+ * -+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * Author: Alison Wang <b18965@freescale.com> -+ * based on talitos.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/mod_devicetable.h> -+#include <linux/device.h> -+#include <linux/interrupt.h> -+#include <linux/crypto.h> -+#include <linux/hw_random.h> -+#include <linux/platform_device.h> -+#include <linux/dma-mapping.h> -+#include <linux/io.h> -+#include <linux/spinlock.h> -+#include <linux/rtnetlink.h> -+#include <linux/slab.h> -+ -+#include <crypto/algapi.h> -+#include <crypto/aes.h> -+#include <crypto/des.h> -+#include <crypto/sha.h> -+#include <crypto/md5.h> -+#include <crypto/aead.h> -+#include <crypto/authenc.h> -+#include <crypto/skcipher.h> -+#include <crypto/hash.h> -+#include <crypto/internal/hash.h> -+#include <crypto/scatterwalk.h> -+ -+#include <asm/m5485sim.h> -+#include "cf_talitos.h" -+ -+#define TALITOS_TIMEOUT 100000 -+#define TALITOS_MAX_DATA_LEN 65535 -+ -+#define DESC_TYPE(desc_hdr) (((desc_hdr) >> 4) & 0xf) -+#define PRIMARY_EU(desc_hdr) (((desc_hdr) >> 28) & 0xf) -+#define SECONDARY_EU(desc_hdr) (((desc_hdr) >> 16) & 0xf) -+ -+#define CF_TALITOS_DEBUG 0 -+#if CF_TALITOS_DEBUG -+#define dprintk(args...) printk(args) -+#else -+#define dprintk(...) -+#endif -+ -+/* descriptor pointer entry */ -+struct talitos_ptr { -+ u32 len; /* length */ -+ u32 ptr; /* address */ -+}; -+ -+static const struct talitos_ptr zero_entry = { -+ .len = 0, -+ .ptr = 0 -+}; -+ -+/* descriptor */ -+struct talitos_desc { -+ u32 hdr; /* header */ -+ struct talitos_ptr ptr[7]; /* ptr/len pair array */ -+ u32 next_hdr; -+}; -+ -+/** -+ * talitos_request - descriptor submission request -+ * @desc: descriptor pointer (kernel virtual) -+ * @dma_desc: descriptor's physical bus address -+ * @callback: whom to call when descriptor processing is done -+ * @context: caller context (optional) -+ */ -+struct talitos_request { -+ struct talitos_desc *desc; -+ dma_addr_t dma_desc; -+ void (*callback) (struct device *dev, struct talitos_desc *desc, -+ void *context, int error); -+ void *context; -+}; -+ -+/* per-channel fifo management */ -+struct talitos_channel { -+ /* request fifo */ -+ struct talitos_request *fifo; -+ -+ /* number of requests pending in channel h/w fifo */ -+ atomic_t submit_count ____cacheline_aligned; -+ -+ /* request submission (head) lock */ -+ spinlock_t head_lock ____cacheline_aligned; -+ /* index to next free descriptor request */ -+ int head; -+ -+ /* request release (tail) lock */ -+ spinlock_t tail_lock ____cacheline_aligned; -+ /* index to next in-progress/done descriptor request */ -+ int tail; -+}; -+ -+struct talitos_private { -+ struct device *dev; -+ struct platform_device *pdev; -+ void __iomem *reg; -+ int irq; -+ -+ /* SEC version geometry (from device tree node) */ -+ unsigned int num_channels; -+ unsigned int chfifo_len; -+ unsigned int exec_units; -+ unsigned int desc_types; -+ -+ /* SEC Compatibility info */ -+ unsigned long features; -+ -+ /* -+ * length of the request fifo -+ * fifo_len is chfifo_len rounded up to next power of 2 -+ * so we can use bitwise ops to wrap -+ */ -+ unsigned int fifo_len; -+ -+ struct talitos_channel *chan; -+ -+ /* next channel to be assigned next incoming descriptor */ -+ atomic_t last_chan ____cacheline_aligned; -+ -+ /* request callback tasklet */ -+ struct tasklet_struct done_task; -+ -+ /* list of registered algorithms */ -+ struct list_head alg_list; -+ -+ /* hwrng device */ -+ struct hwrng rng; -+}; -+ -+/* .features flag */ -+#define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001 -+#define TALITOS_FTR_HW_AUTH_CHECK 0x00000002 -+#define TALITOS_FTR_SHA224_HWINIT 0x00000004 -+ -+/* -+ * map virtual single (contiguous) pointer to h/w descriptor pointer -+ */ -+static void map_single_talitos_ptr(struct device *dev, -+ struct talitos_ptr *talitos_ptr, -+ unsigned short len, void *data, -+ unsigned char extent, -+ enum dma_data_direction dir) -+{ -+ dma_addr_t dma_addr = dma_map_single(dev, data, len, dir); -+ -+ talitos_ptr->len = len; -+ talitos_ptr->ptr = dma_addr; -+} -+ -+/* -+ * unmap bus single (contiguous) h/w descriptor pointer -+ */ -+static void unmap_single_talitos_ptr(struct device *dev, -+ struct talitos_ptr *talitos_ptr, -+ enum dma_data_direction dir) -+{ -+ dma_unmap_single(dev, talitos_ptr->ptr, talitos_ptr->len, dir); -+} -+ -+static int reset_channel(struct device *dev, int ch) -+{ -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ unsigned int timeout = TALITOS_TIMEOUT; -+ -+ setbits32(priv->reg + TALITOS_CCCR(ch), TALITOS_CCCR_RESET); -+ -+ while ((in_be32(priv->reg + TALITOS_CCCR(ch)) & -+ TALITOS_CCCR_RESET) && --timeout) -+ cpu_relax(); -+ -+ if (timeout == 0) { -+ dev_err(dev, "failed to reset channel %d\n", ch); -+ return -EIO; -+ } -+ -+ /* set 36-bit addressing, done writeback enable and done IRQ enable */ -+ setbits32(priv->reg + TALITOS_CCCR(ch), TALITOS_CCCR_NE | -+ TALITOS_CCCR_NT | TALITOS_CCCR_CDWE | -+ TALITOS_CCCR_CDIE); -+ -+ return 0; -+} -+ -+static int reset_device(struct device *dev) -+{ -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ unsigned int timeout = TALITOS_TIMEOUT; -+ -+ setbits32(priv->reg + TALITOS_MCR, TALITOS_MCR_SWR); -+ -+ while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS_MCR_SWR) -+ && --timeout) -+ cpu_relax(); -+ -+ if (timeout == 0) { -+ dev_err(dev, "failed to reset device\n"); -+ return -EIO; -+ } -+ -+ setbits32(priv->reg + TALITOS_DEURCR, TALITOS_DEURCR_RESET); -+ setbits32(priv->reg + TALITOS_AFEURCR, TALITOS_AFEURCR_RESET); -+ setbits32(priv->reg + TALITOS_AESURCR, TALITOS_AESURCR_RESET); -+ setbits32(priv->reg + TALITOS_MDEURCR, TALITOS_MDEURCR_RESET); -+ setbits32(priv->reg + TALITOS_RNGRCR, TALITOS_RNGRCR_SR); -+ return 0; -+} -+ -+/* -+ * Reset and initialize the device -+ */ -+static int init_device(struct device *dev) -+{ -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ int ch, err; -+ -+ /* -+ * Master reset -+ * errata documentation: warning: certain SEC interrupts -+ * are not fully cleared by writing the MCR:SWR bit, -+ * set bit twice to completely reset -+ */ -+ err = reset_device(dev); -+ if (err) -+ return err; -+ -+ err = reset_device(dev); -+ if (err) -+ return err; -+ -+ /* reset channels */ -+ for (ch = 0; ch < priv->num_channels; ch++) { -+ err = reset_channel(dev, ch); -+ if (err) -+ return err; -+ } -+ -+ /* enable channel done and error interrupts */ -+ out_be32(priv->reg + TALITOS_IMR, 0); -+ out_be32(priv->reg + TALITOS_IMR_LO, 0); -+ -+ out_be32(priv->reg + TALITOS_ICR, -+ TALITOS_ICR_CHERR | TALITOS_ICR_CHDONE); -+ out_be32(priv->reg + TALITOS_ICR_LO, -+ TALITOS_ICR_LO_CHERR | TALITOS_ICR_LO_CHDONE); -+ -+ return 0; -+} -+ -+/** -+ * talitos_submit - submits a descriptor to the device for processing -+ * @dev: the SEC device to be used -+ * @desc: the descriptor to be processed by the device -+ * @callback: whom to call when processing is complete -+ * @context: a handle for use by caller (optional) -+ * -+ * desc must contain valid dma-mapped (bus physical) address pointers. -+ * callback must check err and feedback in descriptor header -+ * for device processing status. -+ */ -+static int talitos_submit(struct device *dev, struct talitos_desc *desc, -+ void (*callback)(struct device *dev, -+ struct talitos_desc *desc, -+ void *context, int error), -+ void *context) -+{ -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ struct talitos_request *request; -+ unsigned long flags, ch; -+ int head; -+ -+ /* ignore key parity check in triple DES */ -+ if (((desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_DEU) && -+ (desc->hdr & DESC_HDR_MODE0_DEU_3DES)) -+ setbits32(priv->reg + TALITOS_DEUIMR, TALITOS_DEUIMR_KPE_MASK); -+ -+ /* select done notification */ -+ desc->hdr |= DESC_HDR_DONE; -+ -+ /* emulate SEC's round-robin channel fifo polling scheme */ -+ ch = atomic_inc_return(&priv->last_chan) & (priv->num_channels - 1); -+ -+ spin_lock_irqsave(&priv->chan[ch].head_lock, flags); -+ -+ head = priv->chan[ch].head; -+ request = &priv->chan[ch].fifo[head]; -+ -+ /* map descriptor and save caller data */ -+ request->dma_desc = dma_map_single(dev, desc, sizeof(*desc), -+ DMA_BIDIRECTIONAL); -+ request->callback = callback; -+ request->context = context; -+ -+ /* increment fifo head */ -+ priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1); -+ -+ smp_wmb(); -+ request->desc = desc; -+ -+ /* GO! */ -+ wmb(); -+ out_be32(priv->reg + TALITOS_FF(ch), request->dma_desc); -+ -+ spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags); -+ -+ return -EINPROGRESS; -+} -+ -+/* -+ * process what was done, notify callback of error if not -+ */ -+static void flush_channel(struct device *dev, int ch, int error, int reset_ch) -+{ -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ struct talitos_request *request, saved_req; -+ unsigned long flags; -+ int tail, status; -+ -+ spin_lock_irqsave(&priv->chan[ch].tail_lock, flags); -+ -+ tail = priv->chan[ch].tail; -+ while (priv->chan[ch].fifo[tail].desc) { -+ request = &priv->chan[ch].fifo[tail]; -+ -+ /* descriptors with their done bits set don't get the error */ -+ rmb(); -+ if ((request->desc->hdr & DESC_HDR_DONE) == DESC_HDR_DONE) -+ status = 0; -+ else -+ if (!error) -+ break; -+ else -+ status = error; -+ -+ dma_unmap_single(dev, request->dma_desc, -+ sizeof(struct talitos_desc), -+ DMA_BIDIRECTIONAL); -+ -+ /* copy entries so we can call callback outside lock */ -+ saved_req.desc = request->desc; -+ saved_req.callback = request->callback; -+ saved_req.context = request->context; -+ -+ /* release request entry in fifo */ -+ smp_wmb(); -+ request->desc = NULL; -+ -+ /* increment fifo tail */ -+ priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1); -+ -+ spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags); -+ -+ atomic_dec(&priv->chan[ch].submit_count); -+ -+ saved_req.callback(dev, saved_req.desc, saved_req.context, -+ status); -+ /* channel may resume processing in single desc error case */ -+ if (error && !reset_ch && status == error) -+ return; -+ spin_lock_irqsave(&priv->chan[ch].tail_lock, flags); -+ tail = priv->chan[ch].tail; -+ } -+ -+ spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags); -+} -+ -+/* -+ * process completed requests for channels that have done status -+ */ -+static void talitos_done(unsigned long data) -+{ -+ struct device *dev = (struct device *)data; -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ int ch; -+ -+ for (ch = 0; ch < priv->num_channels; ch++) -+ flush_channel(dev, ch, 0, 0); -+ -+ /* At this point, all completed channels have been processed. -+ * Unmask done interrupts for channels completed later on. -+ */ -+ out_be32(priv->reg + TALITOS_IMR, 0); -+ out_be32(priv->reg + TALITOS_IMR_LO, 0); -+ -+ out_be32(priv->reg + TALITOS_ICR, -+ TALITOS_ICR_CHERR | TALITOS_ICR_CHDONE); -+ out_be32(priv->reg + TALITOS_ICR_LO, -+ TALITOS_ICR_LO_CHERR | TALITOS_ICR_LO_CHDONE); -+} -+ -+/* -+ * locate current (offending) descriptor -+ */ -+static struct talitos_desc *current_desc(struct device *dev, int ch) -+{ -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ int tail = priv->chan[ch].tail; -+ dma_addr_t cur_desc; -+ -+ cur_desc = in_be32(priv->reg + TALITOS_CDPR(ch)); -+ -+ while (priv->chan[ch].fifo[tail].dma_desc != cur_desc) { -+ tail = (tail + 1) & (priv->fifo_len - 1); -+ if (tail == priv->chan[ch].tail) { -+ dev_err(dev, "couldn't locate current descriptor\n"); -+ return NULL; -+ } -+ } -+ -+ return priv->chan[ch].fifo[tail].desc; -+} -+ -+/* -+ * user diagnostics; report root cause of error based on execution unit status -+ */ -+static void report_eu_error(struct device *dev, int ch, -+ struct talitos_desc *desc) -+{ -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ int i; -+ -+ switch (desc->hdr & DESC_HDR_SEL0_MASK) { -+ case DESC_HDR_SEL0_AFEU: -+ dev_err(dev, "AFEUISR 0x%08x\n", -+ in_be32(priv->reg + TALITOS_AFEUISR)); -+ break; -+ case DESC_HDR_SEL0_DEU: -+ dev_err(dev, "DEUISR 0x%08x\n", -+ in_be32(priv->reg + TALITOS_DEUISR)); -+ break; -+ case DESC_HDR_SEL0_MDEU: -+ dev_err(dev, "MDEUISR 0x%08x\n", -+ in_be32(priv->reg + TALITOS_MDEUISR)); -+ break; -+ case DESC_HDR_SEL0_RNG: -+ dev_err(dev, "RNGISR 0x%08x\n", -+ in_be32(priv->reg + TALITOS_RNGISR)); -+ break; -+ case DESC_HDR_SEL0_AESU: -+ dev_err(dev, "AESUISR 0x%08x\n", -+ in_be32(priv->reg + TALITOS_AESUISR)); -+ break; -+ } -+ -+ switch (desc->hdr & DESC_HDR_SEL1_MASK) { -+ case DESC_HDR_SEL1_MDEU: -+ dev_err(dev, "MDEUISR 0x%08x\n", -+ in_be32(priv->reg + TALITOS_MDEUISR)); -+ break; -+ } -+ -+ for (i = 0; i < 8; i++) -+ dev_err(dev, "DESCBUF 0x%08x\n", -+ in_be32(priv->reg + TALITOS_DESCBUF(ch) + 8 * i)); -+} -+ -+/* -+ * recover from error interrupts -+ */ -+static void talitos_error(unsigned long data, u32 isr, u32 isr_lo) -+{ -+ struct device *dev = (struct device *)data; -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ int ch, error, reset_ch = 0; -+ u32 v, v_lo; -+ -+ for (ch = 0; ch < priv->num_channels; ch++) { -+ /* skip channels without errors */ -+ if (!((isr >> 29) & (1 << (ch * 2)))) -+ continue; -+ -+ error = -EINVAL; -+ -+ v = in_be32(priv->reg + TALITOS_CCPSR(ch)); -+ v_lo = in_be32(priv->reg + TALITOS_CCPSR_LO(ch)); -+ -+ if (v_lo & TALITOS_CCPSR_LO_TEA) -+ dev_err(dev, "master data transfer error\n"); -+ if (v_lo & TALITOS_CCPSR_LO_PERR) -+ dev_err(dev, "fetch pointer not complete error\n"); -+ if (v_lo & TALITOS_CCPSR_LO_DERR) -+ dev_err(dev, "illegal descriptor header error\n"); -+ if (v_lo & TALITOS_CCPSR_LO_SERR) -+ dev_err(dev, "static assignment error\n"); -+ if (v_lo & TALITOS_CCPSR_LO_EUERR) -+ report_eu_error(dev, ch, current_desc(dev, ch)); -+ -+ flush_channel(dev, ch, error, reset_ch); -+ -+ if (reset_ch) -+ reset_channel(dev, ch); -+ } -+ -+ /* purge request queues */ -+ for (ch = 0; ch < priv->num_channels; ch++) -+ flush_channel(dev, ch, -EIO, 1); -+ -+ /* reset and reinitialize the device */ -+ init_device(dev); -+} -+ -+static irqreturn_t talitos_interrupt(int irq, void *data) -+{ -+ struct device *dev = data; -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ u32 isr, isr_lo; -+ -+ isr = in_be32(priv->reg + TALITOS_ISR); -+ isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); -+ /* Acknowledge interrupt */ -+ out_be32(priv->reg + TALITOS_ICR, isr); -+ out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); -+ -+ if (unlikely(isr & ~TALITOS_ISR_CHDONE)) { -+ talitos_error((unsigned long)data, isr, isr_lo); -+ } else if (likely(isr & TALITOS_ISR_CHDONE)) { -+ /* mask further done interrupts. */ -+ setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_DONE); -+ /* done_task will unmask done interrupts at exit */ -+ tasklet_schedule(&priv->done_task); -+ } -+ -+ return (isr || isr_lo) ? IRQ_HANDLED : IRQ_NONE; -+} -+ -+ -+/* -+ * crypto alg -+ */ -+#define TALITOS_CRA_PRIORITY 3000 -+#define TALITOS_MAX_KEY_SIZE 64 -+#define TALITOS_MAX_IV_LENGTH 16 -+#define TALITOS_MAX_OUTPUTDATA_SIZE 64 -+#define TALITOS_MAX_INPUTDATA_SIZE 64 -+ -+#define ARC4_MIN_KEY_SIZE 4 -+#define ARC4_MAX_KEY_SIZE 16 -+#define ARC4_BLOCK_SIZE 64 -+#define MD5_BLOCK_SIZE 64 -+ -+struct talitos_ctx { -+ struct device *dev; -+ __be32 desc_hdr_template; -+ u8 key[TALITOS_MAX_KEY_SIZE]; -+ u8 iv[TALITOS_MAX_IV_LENGTH]; -+ unsigned int keylen; -+ unsigned int enckeylen; -+ unsigned int authkeylen; -+ unsigned int authsize; -+}; -+ -+#define HASH_MAX_BLOCK_SIZE SHA512_BLOCK_SIZE -+#define TALITOS_MDEU_MAX_CONTEXT_SIZE \ -+ TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 -+ -+struct talitos_ahash_req_ctx { -+ u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)]; -+ unsigned int hw_context_size; -+ u8 buf[HASH_MAX_BLOCK_SIZE]; -+ u8 bufnext[HASH_MAX_BLOCK_SIZE]; -+ unsigned int swinit; -+ unsigned int first; -+ unsigned int last; -+ unsigned int to_hash_later; -+ u64 nbuf; -+ struct scatterlist bufsl[2]; -+ struct scatterlist *psrc; -+}; -+ -+/* -+ * talitos_edesc - s/w-extended descriptor -+ * @src_nents: number of segments in input scatterlist -+ * @dst_nents: number of segments in output scatterlist -+ * @desc: h/w descriptor -+ * -+ * if decrypting (with authcheck), or either one of src_nents or dst_nents -+ * is greater than 1, an integrity check value is concatenated to the end -+ * of link_tbl data -+ */ -+struct talitos_edesc { -+ int src_nents; -+ int dst_nents; -+ int src_is_chained; -+ int dst_is_chained; -+ struct talitos_desc desc; -+ u8 src_buf[TALITOS_MAX_INPUTDATA_SIZE]; -+ u8 dst_buf[TALITOS_MAX_OUTPUTDATA_SIZE]; -+}; -+ -+static int talitos_map_sg(struct device *dev, struct scatterlist *sg, -+ unsigned int nents, enum dma_data_direction dir, -+ int chained) -+{ -+ if (unlikely(chained)) -+ while (sg) { -+ dma_map_sg(dev, sg, 1, dir); -+ sg = scatterwalk_sg_next(sg); -+ } -+ else -+ dma_map_sg(dev, sg, nents, dir); -+ return nents; -+} -+ -+static void talitos_unmap_sg_chain(struct device *dev, struct scatterlist *sg, -+ enum dma_data_direction dir) -+{ -+ while (sg) { -+ dma_unmap_sg(dev, sg, 1, dir); -+ sg = scatterwalk_sg_next(sg); -+ } -+} -+ -+static void talitos_sg_unmap(struct device *dev, -+ struct talitos_edesc *edesc, -+ struct scatterlist *src, -+ struct scatterlist *dst) -+{ -+ unsigned int src_nents = edesc->src_nents ? : 1; -+ unsigned int dst_nents = edesc->dst_nents ? : 1; -+ -+ if (src != dst) { -+ if (edesc->src_is_chained) -+ talitos_unmap_sg_chain(dev, src, DMA_TO_DEVICE); -+ else -+ dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); -+ -+ if (dst) { -+ if (edesc->dst_is_chained) -+ talitos_unmap_sg_chain(dev, dst, -+ DMA_FROM_DEVICE); -+ else -+ dma_unmap_sg(dev, dst, dst_nents, -+ DMA_FROM_DEVICE); -+ } -+ } else -+ if (edesc->src_is_chained) -+ talitos_unmap_sg_chain(dev, src, DMA_BIDIRECTIONAL); -+ else -+ dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); -+} -+ -+/* -+ * derive number of elements in scatterlist -+ */ -+static int sg_count(struct scatterlist *sg_list, int nbytes, int *chained) -+{ -+ struct scatterlist *sg = sg_list; -+ int sg_nents = 0; -+ -+ *chained = 0; -+ while (nbytes > 0) { -+ sg_nents++; -+ nbytes -= sg->length; -+ if (!sg_is_last(sg) && (sg + 1)->length == 0) -+ *chained = 1; -+ sg = scatterwalk_sg_next(sg); -+ } -+ -+ return sg_nents; -+} -+ -+/** -+ * sg_copy_end_to_buffer - Copy end data from SG list to a linear buffer -+ * @sgl: The SG list -+ * @nents: Number of SG entries -+ * @buf: Where to copy to -+ * @buflen: The number of bytes to copy -+ * @skip: The number of bytes to skip before copying. -+ * Note: skip + buflen should equal SG total size. -+ * -+ * Returns the number of copied bytes. -+ * -+ **/ -+static size_t sg_copy_end_to_buffer(struct scatterlist *sgl, unsigned int nents, -+ void *buf, size_t buflen, unsigned int skip) -+{ -+ unsigned int offset = 0; -+ unsigned int boffset = 0; -+ struct sg_mapping_iter miter; -+ unsigned long flags; -+ unsigned int sg_flags = SG_MITER_ATOMIC; -+ size_t total_buffer = buflen + skip; -+ -+ sg_flags |= SG_MITER_FROM_SG; -+ -+ sg_miter_start(&miter, sgl, nents, sg_flags); -+ -+ local_irq_save(flags); -+ -+ while (sg_miter_next(&miter) && offset < total_buffer) { -+ unsigned int len; -+ unsigned int ignore; -+ -+ if ((offset + miter.length) > skip) { -+ if (offset < skip) { -+ /* Copy part of this segment */ -+ ignore = skip - offset; -+ len = miter.length - ignore; -+ if (boffset + len > buflen) -+ len = buflen - boffset; -+ memcpy(buf + boffset, miter.addr + ignore, len); -+ } else { -+ /* Copy all of this segment (up to buflen) */ -+ len = miter.length; -+ if (boffset + len > buflen) -+ len = buflen - boffset; -+ memcpy(buf + boffset, miter.addr, len); -+ } -+ boffset += len; -+ } -+ offset += miter.length; -+ } -+ -+ sg_miter_stop(&miter); -+ -+ local_irq_restore(flags); -+ return boffset; -+} -+ -+/* -+ * allocate and map the extended descriptor -+ */ -+static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, -+ struct scatterlist *src, -+ struct scatterlist *dst, -+ int hash_result, -+ unsigned int cryptlen, -+ unsigned int authsize, -+ int icv_stashing, -+ u32 cryptoflags) -+{ -+ struct talitos_edesc *edesc; -+ int src_nents, dst_nents, alloc_len; -+ int src_chained, dst_chained = 0; -+ gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : -+ GFP_ATOMIC; -+ -+ if (cryptlen + authsize > TALITOS_MAX_DATA_LEN) { -+ dev_err(dev, "length exceeds h/w max limit\n"); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ src_nents = sg_count(src, cryptlen + authsize, &src_chained); -+ src_nents = (src_nents == 1) ? 0 : src_nents; -+ -+ if (hash_result) { -+ dst_nents = 0; -+ } else { -+ if (dst == src) { -+ dst_nents = src_nents; -+ } else { -+ dst_nents = sg_count(dst, cryptlen + authsize, -+ &dst_chained); -+ dst_nents = (dst_nents == 1) ? 0 : dst_nents; -+ } -+ } -+ -+ /* -+ * allocate space for base edesc plus the link tables, -+ * allowing for two separate entries for ICV and generated ICV (+ 2), -+ * and the ICV data itself -+ */ -+ alloc_len = sizeof(struct talitos_edesc); -+ -+ edesc = kmalloc(alloc_len, GFP_KERNEL | flags); -+ if (!edesc) { -+ dev_err(dev, "could not allocate edescriptor\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ edesc->src_nents = src_nents; -+ edesc->dst_nents = dst_nents; -+ edesc->src_is_chained = src_chained; -+ edesc->dst_is_chained = dst_chained; -+ return edesc; -+} -+ -+static int ablkcipher_setkey(struct crypto_ablkcipher *cipher, -+ const u8 *key, unsigned int keylen) -+{ -+ struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); -+ struct ablkcipher_alg *alg = crypto_ablkcipher_alg(cipher); -+ -+ if (keylen > TALITOS_MAX_KEY_SIZE) -+ goto badkey; -+ -+ if (keylen < alg->min_keysize || keylen > alg->max_keysize) -+ goto badkey; -+ -+ memcpy(&ctx->key, key, keylen); -+ ctx->keylen = keylen; -+ -+ return 0; -+ -+badkey: -+ crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ return -EINVAL; -+} -+ -+static void common_nonsnoop_unmap(struct device *dev, -+ struct talitos_edesc *edesc, -+ struct ablkcipher_request *areq) -+{ -+ unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); -+ unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE); -+ unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE); -+ -+ talitos_sg_unmap(dev, edesc, areq->src, areq->dst); -+} -+ -+static void ablkcipher_done(struct device *dev, -+ struct talitos_desc *desc, void *context, -+ int err) -+{ -+ struct ablkcipher_request *areq = context; -+ struct talitos_edesc *edesc; -+ -+ edesc = container_of(desc, struct talitos_edesc, desc); -+ -+ if (edesc->dst_nents != 0) -+ sg_copy_from_buffer(areq->dst, edesc->dst_nents, -+ edesc->dst_buf, areq->nbytes); -+ -+ common_nonsnoop_unmap(dev, edesc, areq); -+ -+ kfree(edesc); -+ -+ areq->base.complete(&areq->base, err); -+} -+ -+static int common_nonsnoop(struct talitos_edesc *edesc, -+ struct ablkcipher_request *areq, -+ u8 *giv, -+ void (*callback) (struct device *dev, -+ struct talitos_desc *desc, -+ void *context, int error)) -+{ -+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); -+ struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); -+ struct device *dev = ctx->dev; -+ struct talitos_desc *desc = &edesc->desc; -+ unsigned int cryptlen = areq->nbytes; -+ unsigned int ivsize; -+ int sg_count, ret; -+ -+ desc->next_hdr = 0; -+ -+ /* first DWORD empty */ -+ desc->ptr[0] = zero_entry; -+ -+ /* cipher iv */ -+ ivsize = crypto_ablkcipher_ivsize(cipher); -+ map_single_talitos_ptr(dev, &desc->ptr[1], ivsize, giv ?: areq->info, 0, -+ DMA_TO_DEVICE); -+ -+ /* AFEU using a key */ -+ if (((desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AFEU) && -+ ((desc->hdr & DESC_HDR_MODE0_MASK) == -+ DESC_HDR_MODE0_AFEU_USE_KEY)) -+ desc->ptr[1] = zero_entry; -+ -+ /* cipher key */ -+ map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen, -+ (char *)&ctx->key, 0, DMA_TO_DEVICE); -+ -+ /* AFEU using context */ -+ if (((desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AFEU) && -+ ((desc->hdr & DESC_HDR_MODE0_MASK) == -+ DESC_HDR_MODE0_AFEU_USE_CONTEXT)) -+ desc->ptr[2] = zero_entry; -+ -+ /* -+ * cipher in -+ */ -+ desc->ptr[3].len = cpu_to_be16(cryptlen); -+ -+ sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ? : 1, -+ (areq->src == areq->dst) ? DMA_BIDIRECTIONAL -+ : DMA_TO_DEVICE, -+ edesc->src_is_chained); -+ -+ if (sg_count == 1) -+ desc->ptr[3].ptr = sg_dma_address(areq->src); -+ else { -+ sg_copy_to_buffer(areq->src, sg_count, edesc->src_buf, -+ desc->ptr[3].len); -+ desc->ptr[3].ptr = (u32)edesc->src_buf; -+ } -+ -+ /* cipher out */ -+ desc->ptr[4].len = cpu_to_be16(cryptlen); -+ -+ if (areq->src != areq->dst) -+ sg_count = talitos_map_sg(dev, areq->dst, -+ edesc->dst_nents ? : 1, -+ DMA_FROM_DEVICE, -+ edesc->dst_is_chained); -+ -+ if (sg_count == 1) -+ desc->ptr[4].ptr = sg_dma_address(areq->dst); -+ else -+ desc->ptr[4].ptr = (u32)edesc->dst_buf; -+ -+ /* iv out */ -+ map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv, 0, -+ DMA_FROM_DEVICE); -+ -+ /* last DWORD empty */ -+ desc->ptr[6] = zero_entry; -+ -+ ret = talitos_submit(dev, desc, callback, areq); -+ if (ret != -EINPROGRESS) { -+ common_nonsnoop_unmap(dev, edesc, areq); -+ kfree(edesc); -+ } -+ return ret; -+} -+ -+static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request * -+ areq) -+{ -+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); -+ struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); -+ -+ return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 0, -+ areq->nbytes, 0, 0, areq->base.flags); -+} -+ -+static int ablkcipher_encrypt(struct ablkcipher_request *areq) -+{ -+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); -+ struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); -+ struct talitos_edesc *edesc; -+ -+ /* allocate extended descriptor */ -+ edesc = ablkcipher_edesc_alloc(areq); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ /* set encrypt except AFEU */ -+ if ((ctx->desc_hdr_template & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AFEU) -+ edesc->desc.hdr = ctx->desc_hdr_template; -+ else -+ edesc->desc.hdr = ctx->desc_hdr_template | -+ DESC_HDR_MODE0_ENCRYP; -+ -+ return common_nonsnoop(edesc, areq, NULL, ablkcipher_done); -+} -+ -+static int ablkcipher_decrypt(struct ablkcipher_request *areq) -+{ -+ struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); -+ struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); -+ struct talitos_edesc *edesc; -+ -+ /* allocate extended descriptor */ -+ edesc = ablkcipher_edesc_alloc(areq); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; -+ -+ return common_nonsnoop(edesc, areq, NULL, ablkcipher_done); -+} -+ -+static void common_nonsnoop_hash_unmap(struct device *dev, -+ struct talitos_edesc *edesc, -+ struct ahash_request *areq) -+{ -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ -+ unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); -+ -+ /* When using hashctx-in, must unmap it. */ -+ if (edesc->desc.ptr[1].len) -+ unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], -+ DMA_TO_DEVICE); -+ -+ if (edesc->desc.ptr[2].len) -+ unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], -+ DMA_TO_DEVICE); -+ -+ talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL); -+} -+ -+static void ahash_done(struct device *dev, -+ struct talitos_desc *desc, void *context, -+ int err) -+{ -+ struct ahash_request *areq = context; -+ struct talitos_edesc *edesc = -+ container_of(desc, struct talitos_edesc, desc); -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ -+ if (!req_ctx->last && req_ctx->to_hash_later) { -+ /* Position any partial block for next update/final/finup */ -+ memcpy(req_ctx->buf, req_ctx->bufnext, req_ctx->to_hash_later); -+ req_ctx->nbuf = req_ctx->to_hash_later; -+ } -+ common_nonsnoop_hash_unmap(dev, edesc, areq); -+ -+ kfree(edesc); -+ -+ areq->base.complete(&areq->base, err); -+} -+ -+static int common_nonsnoop_hash(struct talitos_edesc *edesc, -+ struct ahash_request *areq, unsigned int length, -+ void (*callback) (struct device *dev, -+ struct talitos_desc *desc, -+ void *context, int error)) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ struct device *dev = ctx->dev; -+ struct talitos_desc *desc = &edesc->desc; -+ int sg_count, ret; -+ -+ desc->next_hdr = 0; -+ -+ /* first DWORD empty */ -+ desc->ptr[0] = zero_entry; -+ -+ /* hash context in */ -+ if (!req_ctx->first || req_ctx->swinit) { -+ map_single_talitos_ptr(dev, &desc->ptr[1], -+ req_ctx->hw_context_size, -+ (char *)req_ctx->hw_context, 0, -+ DMA_TO_DEVICE); -+ req_ctx->swinit = 0; -+ } else { -+ desc->ptr[1] = zero_entry; -+ /* Indicate next op is not the first. */ -+ req_ctx->first = 0; -+ } -+ -+ /* HMAC key */ -+ if (ctx->keylen) -+ map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen, -+ (char *)&ctx->key, 0, DMA_TO_DEVICE); -+ else -+ desc->ptr[2] = zero_entry; -+ -+ /* -+ * data in -+ */ -+ desc->ptr[3].len = length; -+ sg_count = talitos_map_sg(dev, req_ctx->psrc, -+ edesc->src_nents ? : 1, -+ DMA_TO_DEVICE, -+ edesc->src_is_chained); -+ -+ if (sg_count == 1) -+ desc->ptr[3].ptr = sg_dma_address(req_ctx->psrc); -+ else { -+ sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->src_buf, -+ desc->ptr[3].len); -+ desc->ptr[3].ptr = (u32)edesc->src_buf; -+ } -+ -+ /* fifth DWORD empty */ -+ desc->ptr[4] = zero_entry; -+ -+ /* hash/HMAC out -or- hash context out */ -+ if (req_ctx->last) -+ map_single_talitos_ptr(dev, &desc->ptr[5], -+ crypto_ahash_digestsize(tfm), -+ areq->result, 0, DMA_FROM_DEVICE); -+ else -+ map_single_talitos_ptr(dev, &desc->ptr[5], -+ req_ctx->hw_context_size, -+ req_ctx->hw_context, 0, DMA_FROM_DEVICE); -+ -+ /* last DWORD empty */ -+ desc->ptr[6] = zero_entry; -+ -+ ret = talitos_submit(dev, desc, callback, areq); -+ if (ret != -EINPROGRESS) { -+ common_nonsnoop_hash_unmap(dev, edesc, areq); -+ kfree(edesc); -+ } -+ return ret; -+} -+ -+static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq, -+ unsigned int nbytes) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ -+ return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, 1, -+ nbytes, 0, 0, areq->base.flags); -+} -+ -+static int ahash_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ -+ /* Initialize the context */ -+ req_ctx->nbuf = 0; -+ req_ctx->first = 1; /* first indicates h/w must init its context */ -+ req_ctx->swinit = 0; /* assume h/w init of context */ -+ req_ctx->hw_context_size = -+ (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE) -+ ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 -+ : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512; -+ -+ return 0; -+} -+ -+/* -+ * on h/w without explicit sha224 support, we initialize h/w context -+ * manually with sha224 constants, and tell it to run sha256. -+ */ -+static int ahash_init_sha224_swinit(struct ahash_request *areq) -+{ -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ -+ ahash_init(areq); -+ req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/ -+ -+ req_ctx->hw_context[0] = SHA224_H0; -+ req_ctx->hw_context[1] = SHA224_H1; -+ req_ctx->hw_context[2] = SHA224_H2; -+ req_ctx->hw_context[3] = SHA224_H3; -+ req_ctx->hw_context[4] = SHA224_H4; -+ req_ctx->hw_context[5] = SHA224_H5; -+ req_ctx->hw_context[6] = SHA224_H6; -+ req_ctx->hw_context[7] = SHA224_H7; -+ -+ /* init 64-bit count */ -+ req_ctx->hw_context[8] = 0; -+ req_ctx->hw_context[9] = 0; -+ -+ return 0; -+} -+ -+static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct talitos_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ struct talitos_edesc *edesc; -+ unsigned int blocksize = -+ crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); -+ unsigned int nbytes_to_hash; -+ unsigned int to_hash_later; -+ unsigned int nsg; -+ int chained; -+ -+ if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) { -+ /* Buffer up to one whole block */ -+ sg_copy_to_buffer(areq->src, -+ sg_count(areq->src, nbytes, &chained), -+ req_ctx->buf + req_ctx->nbuf, nbytes); -+ req_ctx->nbuf += nbytes; -+ return 0; -+ } -+ -+ /* At least (blocksize + 1) bytes are available to hash */ -+ nbytes_to_hash = nbytes + req_ctx->nbuf; -+ to_hash_later = nbytes_to_hash & (blocksize - 1); -+ -+ if (req_ctx->last) -+ to_hash_later = 0; -+ else if (to_hash_later) -+ /* There is a partial block. Hash the full block(s) now */ -+ nbytes_to_hash -= to_hash_later; -+ else { -+ /* Keep one block buffered */ -+ nbytes_to_hash -= blocksize; -+ to_hash_later = blocksize; -+ } -+ -+ /* Chain in any previously buffered data */ -+ if (req_ctx->nbuf) { -+ nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1; -+ sg_init_table(req_ctx->bufsl, nsg); -+ sg_set_buf(req_ctx->bufsl, req_ctx->buf, req_ctx->nbuf); -+ if (nsg > 1) -+ scatterwalk_sg_chain(req_ctx->bufsl, 2, areq->src); -+ req_ctx->psrc = req_ctx->bufsl; -+ } else -+ req_ctx->psrc = areq->src; -+ -+ if (to_hash_later) { -+ int nents = sg_count(areq->src, nbytes, &chained); -+ sg_copy_end_to_buffer(areq->src, nents, -+ req_ctx->bufnext, -+ to_hash_later, -+ nbytes - to_hash_later); -+ } -+ req_ctx->to_hash_later = to_hash_later; -+ -+ /* Allocate extended descriptor */ -+ edesc = ahash_edesc_alloc(areq, nbytes_to_hash); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ edesc->desc.hdr = ctx->desc_hdr_template; -+ -+ /* On last one, request SEC to pad; otherwise continue */ -+ if (req_ctx->last) -+ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD; -+ else -+ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT; -+ -+ /* request SEC to INIT hash. */ -+ if (req_ctx->first && !req_ctx->swinit) -+ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT; -+ -+ /* When the tfm context has a keylen, it's an HMAC. -+ * A first or last (ie. not middle) descriptor must request HMAC. -+ */ -+ if (ctx->keylen && (req_ctx->first || req_ctx->last)) -+ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC; -+ -+ return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, -+ ahash_done); -+} -+ -+static int ahash_update(struct ahash_request *areq) -+{ -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ -+ req_ctx->last = 0; -+ -+ return ahash_process_req(areq, areq->nbytes); -+} -+ -+static int ahash_final(struct ahash_request *areq) -+{ -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ -+ req_ctx->last = 1; -+ -+ return ahash_process_req(areq, 0); -+} -+ -+static int ahash_finup(struct ahash_request *areq) -+{ -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ -+ req_ctx->last = 1; -+ -+ return ahash_process_req(areq, areq->nbytes); -+} -+ -+static int ahash_digest(struct ahash_request *areq) -+{ -+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq); -+ -+ ahash->init(areq); -+ req_ctx->last = 1; -+ -+ return ahash_process_req(areq, areq->nbytes); -+} -+ -+struct talitos_alg_template { -+ u32 type; -+ union { -+ struct crypto_alg crypto; -+ struct ahash_alg hash; -+ } alg; -+ __be32 desc_hdr_template; -+}; -+ -+static struct talitos_alg_template driver_algs[] = { -+ /* ABLKCIPHER algorithms. */ -+ { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, -+ .alg.crypto = { -+ .cra_name = "ecb(arc4)", -+ .cra_driver_name = "ecb-arc4-talitos", -+ .cra_blocksize = ARC4_BLOCK_SIZE, -+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | -+ CRYPTO_ALG_ASYNC, -+ .cra_type = &crypto_ablkcipher_type, -+ .cra_ablkcipher = { -+ .setkey = ablkcipher_setkey, -+ .encrypt = ablkcipher_encrypt, -+ .decrypt = ablkcipher_decrypt, -+ .geniv = "eseqiv", -+ .min_keysize = ARC4_MIN_KEY_SIZE, -+ .max_keysize = ARC4_MAX_KEY_SIZE, -+ .ivsize = ARC4_BLOCK_SIZE, -+ } -+ }, -+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_AFEU | -+ DESC_HDR_SEL0_AFEU | -+ DESC_HDR_MODE0_AFEU_USE_KEY, -+ }, -+ { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, -+ .alg.crypto = { -+ .cra_name = "cbc(aes)", -+ .cra_driver_name = "cbc-aes-talitos", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | -+ CRYPTO_ALG_ASYNC, -+ .cra_type = &crypto_ablkcipher_type, -+ .cra_ablkcipher = { -+ .setkey = ablkcipher_setkey, -+ .encrypt = ablkcipher_encrypt, -+ .decrypt = ablkcipher_decrypt, -+ .geniv = "eseqiv", -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ } -+ }, -+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | -+ DESC_HDR_SEL0_AESU | -+ DESC_HDR_MODE0_AESU_CBC, -+ }, -+ { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, -+ .alg.crypto = { -+ .cra_name = "cbc(des)", -+ .cra_driver_name = "cbc-des-talitos", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | -+ CRYPTO_ALG_ASYNC, -+ .cra_type = &crypto_ablkcipher_type, -+ .cra_ablkcipher = { -+ .setkey = ablkcipher_setkey, -+ .encrypt = ablkcipher_encrypt, -+ .decrypt = ablkcipher_decrypt, -+ .geniv = "eseqiv", -+ .min_keysize = DES_KEY_SIZE, -+ .max_keysize = DES_KEY_SIZE, -+ .ivsize = DES_BLOCK_SIZE, -+ } -+ }, -+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | -+ DESC_HDR_SEL0_DEU | -+ DESC_HDR_MODE0_DEU_CBC, -+ }, -+ { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, -+ .alg.crypto = { -+ .cra_name = "cbc(des3_ede)", -+ .cra_driver_name = "cbc-3des-talitos", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | -+ CRYPTO_ALG_ASYNC, -+ .cra_type = &crypto_ablkcipher_type, -+ .cra_ablkcipher = { -+ .setkey = ablkcipher_setkey, -+ .encrypt = ablkcipher_encrypt, -+ .decrypt = ablkcipher_decrypt, -+ .geniv = "eseqiv", -+ .min_keysize = DES3_EDE_KEY_SIZE, -+ .max_keysize = DES3_EDE_KEY_SIZE, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ } -+ }, -+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | -+ DESC_HDR_SEL0_DEU | -+ DESC_HDR_MODE0_DEU_CBC | -+ DESC_HDR_MODE0_DEU_3DES, -+ }, -+ /* AHASH algorithms. */ -+ { .type = CRYPTO_ALG_TYPE_AHASH, -+ .alg.hash = { -+ .init = ahash_init, -+ .update = ahash_update, -+ .final = ahash_final, -+ .finup = ahash_finup, -+ .digest = ahash_digest, -+ .halg.digestsize = MD5_DIGEST_SIZE, -+ .halg.base = { -+ .cra_name = "md5", -+ .cra_driver_name = "md5-talitos", -+ .cra_blocksize = MD5_BLOCK_SIZE, -+ .cra_flags = CRYPTO_ALG_TYPE_AHASH | -+ CRYPTO_ALG_ASYNC, -+ .cra_type = &crypto_ahash_type -+ } -+ }, -+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | -+ DESC_HDR_SEL0_MDEU | -+ DESC_HDR_MODE0_MDEU_MD5, -+ }, -+ { .type = CRYPTO_ALG_TYPE_AHASH, -+ .alg.hash = { -+ .init = ahash_init, -+ .update = ahash_update, -+ .final = ahash_final, -+ .finup = ahash_finup, -+ .digest = ahash_digest, -+ .halg.digestsize = SHA1_DIGEST_SIZE, -+ .halg.base = { -+ .cra_name = "sha1", -+ .cra_driver_name = "sha1-talitos", -+ .cra_blocksize = SHA1_BLOCK_SIZE, -+ .cra_flags = CRYPTO_ALG_TYPE_AHASH | -+ CRYPTO_ALG_ASYNC, -+ .cra_type = &crypto_ahash_type -+ } -+ }, -+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | -+ DESC_HDR_SEL0_MDEU | -+ DESC_HDR_MODE0_MDEU_SHA1, -+ }, -+}; -+ -+struct talitos_crypto_alg { -+ struct list_head entry; -+ struct device *dev; -+ struct talitos_alg_template algt; -+}; -+ -+static int talitos_cra_init(struct crypto_tfm *tfm) -+{ -+ struct crypto_alg *alg = tfm->__crt_alg; -+ struct talitos_crypto_alg *talitos_alg; -+ struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH) -+ talitos_alg = container_of(__crypto_ahash_alg(alg), -+ struct talitos_crypto_alg, -+ algt.alg.hash); -+ else -+ talitos_alg = container_of(alg, struct talitos_crypto_alg, -+ algt.alg.crypto); -+ -+ /* update context with ptr to dev */ -+ ctx->dev = talitos_alg->dev; -+ -+ /* copy descriptor header template value */ -+ ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template; -+ -+ return 0; -+} -+ -+static int talitos_cra_init_ahash(struct crypto_tfm *tfm) -+{ -+ struct talitos_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ talitos_cra_init(tfm); -+ -+ ctx->keylen = 0; -+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), -+ sizeof(struct talitos_ahash_req_ctx)); -+ -+ return 0; -+} -+ -+/* -+ * given the alg's descriptor header template, determine whether descriptor -+ * type and primary/secondary execution units required match the hw -+ * capabilities description provided in the device tree node. -+ */ -+static int hw_supports(struct device *dev, __be32 desc_hdr_template) -+{ -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = (DESC_TYPE(desc_hdr_template) & priv->desc_types) && -+ (PRIMARY_EU(desc_hdr_template) & priv->exec_units); -+ -+ if (SECONDARY_EU(desc_hdr_template)) -+ ret = ret && (SECONDARY_EU(desc_hdr_template) -+ & priv->exec_units); -+ -+ return ret; -+} -+ -+static int talitos_remove(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ struct talitos_crypto_alg *t_alg, *n; -+ int i; -+ -+ list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) { -+ switch (t_alg->algt.type) { -+ case CRYPTO_ALG_TYPE_ABLKCIPHER: -+ case CRYPTO_ALG_TYPE_AEAD: -+ crypto_unregister_alg(&t_alg->algt.alg.crypto); -+ break; -+ case CRYPTO_ALG_TYPE_AHASH: -+ crypto_unregister_ahash(&t_alg->algt.alg.hash); -+ break; -+ } -+ list_del(&t_alg->entry); -+ kfree(t_alg); -+ } -+ -+ for (i = 0; i < priv->num_channels; i++) -+ kfree(priv->chan[i].fifo); -+ -+ kfree(priv->chan); -+ -+ if (priv->irq != 0) -+ free_irq(priv->irq, dev); -+ -+ tasklet_kill(&priv->done_task); -+ -+ iounmap(priv->reg); -+ -+ dev_set_drvdata(dev, NULL); -+ -+ kfree(priv); -+ -+ return 0; -+} -+ -+static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, -+ struct talitos_alg_template -+ *template) -+{ -+ struct talitos_private *priv = dev_get_drvdata(dev); -+ struct talitos_crypto_alg *t_alg; -+ struct crypto_alg *alg; -+ -+ t_alg = kzalloc(sizeof(struct talitos_crypto_alg), GFP_KERNEL); -+ if (!t_alg) -+ return ERR_PTR(-ENOMEM); -+ -+ t_alg->algt = *template; -+ -+ switch (t_alg->algt.type) { -+ case CRYPTO_ALG_TYPE_ABLKCIPHER: -+ alg = &t_alg->algt.alg.crypto; -+ alg->cra_init = talitos_cra_init; -+ break; -+ case CRYPTO_ALG_TYPE_AHASH: -+ alg = &t_alg->algt.alg.hash.halg.base; -+ alg->cra_init = talitos_cra_init_ahash; -+ if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && -+ !strcmp(alg->cra_name, "sha224")) { -+ t_alg->algt.alg.hash.init = ahash_init_sha224_swinit; -+ t_alg->algt.desc_hdr_template = -+ DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | -+ DESC_HDR_SEL0_MDEU | -+ DESC_HDR_MODE0_MDEU_SHA256; -+ } -+ break; -+ default: -+ dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ alg->cra_module = THIS_MODULE; -+ alg->cra_priority = TALITOS_CRA_PRIORITY; -+ alg->cra_alignmask = 0; -+ alg->cra_ctxsize = sizeof(struct talitos_ctx); -+ -+ t_alg->dev = dev; -+ -+ return t_alg; -+} -+ -+static int __devinit talitos_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct talitos_private *priv; -+ int prop; -+ struct resource *r; -+ int i, err; -+ -+ priv = kzalloc(sizeof(struct talitos_private), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ dev_set_drvdata(dev, priv); -+ -+ priv->pdev = pdev; -+ -+ tasklet_init(&priv->done_task, talitos_done, (unsigned long)dev); -+ -+ INIT_LIST_HEAD(&priv->alg_list); -+ -+ priv->irq = 64 + ISC_SEC; -+ /* get the irq line */ -+ err = request_irq(priv->irq, talitos_interrupt, IRQF_DISABLED, -+ dev_driver_string(dev), dev); -+ if (err) { -+ dev_err(dev, "failed to request irq %d\n", priv->irq); -+ goto err_out; -+ } else -+ MCF_ICR(ISC_SEC) = ILP_SEC; -+ -+ -+ /* get a pointer to the register memory */ -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ priv->reg = ioremap(r->start, (r->end - r->start)); -+ if (!priv->reg) -+ dev_err(dev, "failed to ioremap\n"); -+ -+ /* get SEC version capabilities from device tree */ -+ prop = in_be32(priv->reg + TALITOS_ID); -+ if (prop & TALITOS_ID_SEC_1_1) { -+ priv->num_channels = TALITOS_NCHANNELS_SEC_1_1; -+ priv->chfifo_len = TALITOS_CHFIFOLEN_SEC_1_1; -+ priv->exec_units = TALITOS_HAS_EUS_SEC_1_1; -+ priv->desc_types = TALITOS_HAS_DESCTYPES_SEC_1_1; -+ } else { -+ dev_err(dev, "failed to id device\n"); -+ goto err_out; -+ } -+ -+ priv->chan = kzalloc(sizeof(struct talitos_channel) * -+ priv->num_channels, GFP_KERNEL); -+ if (!priv->chan) { -+ dev_err(dev, "failed to allocate channel management space\n"); -+ err = -ENOMEM; -+ goto err_out; -+ } -+ -+ for (i = 0; i < priv->num_channels; i++) { -+ spin_lock_init(&priv->chan[i].head_lock); -+ spin_lock_init(&priv->chan[i].tail_lock); -+ } -+ -+ priv->fifo_len = roundup_pow_of_two(priv->chfifo_len); -+ -+ for (i = 0; i < priv->num_channels; i++) { -+ priv->chan[i].fifo = kzalloc(sizeof(struct talitos_request) * -+ priv->fifo_len, GFP_KERNEL); -+ if (!priv->chan[i].fifo) { -+ dev_err(dev, "failed to allocate request fifo %d\n", i); -+ err = -ENOMEM; -+ goto err_out; -+ } -+ } -+ -+ for (i = 0; i < priv->num_channels; i++) -+ atomic_set(&priv->chan[i].submit_count, -+ -(priv->chfifo_len - 1)); -+ -+ dma_set_mask(dev, DMA_BIT_MASK(36)); -+ -+ /* reset and initialize the h/w */ -+ err = init_device(dev); -+ if (err) { -+ dev_err(dev, "failed to initialize device\n"); -+ goto err_out; -+ } -+ -+ /* register crypto algorithms the device supports */ -+ for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { -+ if (hw_supports(dev, driver_algs[i].desc_hdr_template)) { -+ struct talitos_crypto_alg *t_alg; -+ char *name = NULL; -+ -+ t_alg = talitos_alg_alloc(dev, &driver_algs[i]); -+ if (IS_ERR(t_alg)) { -+ err = PTR_ERR(t_alg); -+ goto err_out; -+ } -+ -+ switch (t_alg->algt.type) { -+ case CRYPTO_ALG_TYPE_ABLKCIPHER: -+ case CRYPTO_ALG_TYPE_AEAD: -+ err = crypto_register_alg( -+ &t_alg->algt.alg.crypto); -+ name = t_alg->algt.alg.crypto.cra_driver_name; -+ break; -+ case CRYPTO_ALG_TYPE_AHASH: -+ err = crypto_register_ahash( -+ &t_alg->algt.alg.hash); -+ name = -+ t_alg->algt.alg.hash.halg.base.cra_driver_name; -+ break; -+ } -+ if (err) { -+ dev_err(dev, "%s alg registration failed\n", -+ name); -+ kfree(t_alg); -+ } else { -+ list_add_tail(&t_alg->entry, &priv->alg_list); -+ dev_info(dev, "%s\n", name); -+ } -+ } -+ } -+ -+ return 0; -+ -+err_out: -+ talitos_remove(pdev); -+ -+ return err; -+} -+ -+static struct platform_driver talitos_driver = { -+ .driver = { -+ .name = "talitos", -+ .owner = THIS_MODULE, -+ }, -+ .probe = talitos_probe, -+ .remove = talitos_remove, -+}; -+ -+static int __init talitos_init(void) -+{ -+ return platform_driver_register(&talitos_driver); -+} -+module_init(talitos_init); -+ -+static void __exit talitos_exit(void) -+{ -+ platform_driver_unregister(&talitos_driver); -+} -+module_exit(talitos_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>"); -+MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver"); ---- /dev/null -+++ b/drivers/crypto/cf_talitos.h -@@ -0,0 +1,229 @@ -+/* -+ * Freescale Coldfire SEC (talitos) device dependent data structures -+ * -+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+/* device ID register values */ -+#define TALITOS_ID_SEC_1_1 (0x09000000) /* MCF547x and MCF548x */ -+ -+/* -+ * following num_channels, channel-fifo-depth, exec-unit-mask, and -+ * descriptor-types-mask are for forward-compatibility with openfirmware -+ * flat device trees -+ */ -+ -+/* -+ * num_channels : the number of channels available in each SEC version. -+ */ -+ -+/* n.b. this driver requires these values be a power of 2 */ -+#define TALITOS_NCHANNELS_SEC_1_1 2 -+ -+/* -+ * channel-fifo-depth : The number of descriptor -+ * pointers a channel fetch fifo can hold. -+ */ -+#define TALITOS_CHFIFOLEN_SEC_1_1 1 -+ -+/* the corresponding masks for each SEC version */ -+#define TALITOS_HAS_EUS_SEC_1_1 0x7 -+ -+/* the corresponding masks for each SEC version */ -+#define TALITOS_HAS_DESCTYPES_SEC_1_1 0xf -+ -+/* -+ * a TALITOS_xxx_HI address points to the low data bits (32-63) of the register -+ */ -+/* global register offset addresses */ -+/* EU Assaginment controller register is useless*/ -+#define TALITOS_EUACR 0x1000 -+#define TALITOS_EUACR_LO 0x1004 -+ -+#define TALITOS_IMR 0x1008 /* interrupt mask register */ -+#define TALITOS_IMR_ALL 0xf8000000 /* enable all interrupts mask */ -+#define TALITOS_IMR_ERR 0xa8000000 /* mask error interrupts */ -+#define TALITOS_IMR_DONE 0x50000000 /* mask done interrupts */ -+#define TALITOS_IMR_LO 0x100C /* interrupt mask register */ -+/* mask all channel interrupts mask */ -+#define TALITOS_IMR_LO_ALL 0x03333340 -+#define TALITOS_IMR_LO_ERR 0x02222240 /* mask error interrupts */ -+#define TALITOS_IMR_LO_DONE 0x01111100 /* mask done interrupts */ -+ -+#define TALITOS_ISR 0x1010 /* interrupt status register */ -+#define TALITOS_ISR_CHERR 0xa8000000 /* errors mask */ -+#define TALITOS_ISR_CHDONE 0x50000000 /* channel(s) done mask */ -+#define TALITOS_ISR_LO 0x1014 /* interrupt status register */ -+ -+#define TALITOS_ICR 0x1018 /* interrupt clear register */ -+#define TALITOS_ICR_CHERR 0xa8000000 /* errors enable */ -+#define TALITOS_ICR_CHDONE 0x50000000 /* channel(s) done enable */ -+#define TALITOS_ICR_LO 0x101C /* interrupt clear register */ -+#define TALITOS_ICR_LO_CHERR 0x02222240 /* errors enable */ -+#define TALITOS_ICR_LO_CHDONE 0x01111100 /* channel(s) done enable */ -+ -+#define TALITOS_ID 0x1020 -+ -+/* EU Assaginment status register is useless*/ -+#define TALITOS_EUASR 0x1028 -+#define TALITOS_EUASR_LO 0x102C -+ -+#define TALITOS_MCR 0x1030 /* master control register */ -+#define TALITOS_MCR_SWR 0x01000000 -+ -+#define TALITOS_MEAR 0x1038 -+ -+/* channel register address stride */ -+#define TALITOS_CH_STRIDE 0x1000 -+ -+/* channel register offset addresses and bits */ -+#define TALITOS_CCCR(ch) (ch * TALITOS_CH_STRIDE + 0x200c) -+#define TALITOS_CCCR_RESET 0x1 /* Channel Reset bit */ -+#define TALITOS_CCCR_CDWE 0x10 /* Channel done writeback enable bit */ -+#define TALITOS_CCCR_NE 0x8 /* Fetch Next Descriptor Enable bit */ -+#define TALITOS_CCCR_NT 0x4 /* Notification type bit */ -+#define TALITOS_CCCR_CDIE 0x2 /* Channel Done Interrupt Enable bit */ -+ -+/* Crypto-Channel Pointer Status Reg */ -+#define TALITOS_CCPSR(ch) (ch * TALITOS_CH_STRIDE + 0x2010) -+#define TALITOS_CCPSR_LO(ch) (ch * TALITOS_CH_STRIDE + 0x2014) -+#define TALITOS_CCPSR_LO_TEA 0x2000 /* Transfer error acknowledge */ -+#define TALITOS_CCPSR_LO_PERR 0x1000 /* Pointer not complete error */ -+#define TALITOS_CCPSR_LO_DERR 0x400 /* Descriptor error */ -+#define TALITOS_CCPSR_LO_SERR 0x200 /* Static assignment error */ -+#define TALITOS_CCPSR_LO_EUERR 0x100 /* EU error */ -+ -+/* channel fetch fifo register */ -+#define TALITOS_FF(ch) (ch * TALITOS_CH_STRIDE + 0x204c) -+ -+/* Crypto-Channel Pointer Status Reg */ -+#define TALITOS_CDPR(ch) (ch * TALITOS_CH_STRIDE + 0x2044) -+ -+/* Descriptor Buffer (debug) 0x2080-0x20BF*/ -+#define TALITOS_DESCBUF(ch) (ch * TALITOS_CH_STRIDE + 0x2080) -+ -+/* execution unit register offset addresses and bits */ -+#define TALITOS_DEURCR 0xa018 /* DEU reset control register */ -+#define TALITOS_DEURCR_RESET 0x01000000 /* DEU reset bit */ -+#define TALITOS_DEUSR 0xa028 /* DEU status register */ -+#define TALITOS_DEUSR_RESET 0x01000000 /* DEU Reset status bit */ -+#define TALITOS_DEUISR 0xa030 /* DEU interrupt status register */ -+#define TALITOS_DEUIMR 0xa038 /* DEU interrupt mask register */ -+#define TALITOS_DEUIMR_MASK 0xf63f0000 /* DEU interrupt control mask*/ -+#define TALITOS_DEUIMR_KPE_MASK 0x00200000 /* DEU interrupt KPE mask*/ -+ -+#define TALITOS_AESURCR 0x12018 /* AESU reset control register */ -+#define TALITOS_AESURCR_RESET 0x01000000 /* AESU reset bit */ -+#define TALITOS_AESUSR 0x12028 /* AESU status register */ -+#define TALITOS_AESUSR_RESET 0x01000000 /* AESU Reset status bit */ -+#define TALITOS_AESUISR 0x12030 /* AESU interrupt status register */ -+#define TALITOS_AESUIMR 0x12038 /* AESU interrupt mask register */ -+#define TALITOS_AESUIMR_MASK 0xf61f0000 /* AESU interrupt control mask*/ -+ -+#define TALITOS_MDEURCR 0xc018 /* MDEU reset control register */ -+#define TALITOS_MDEURCR_RESET 0x01000000 /* MDEU reset bit */ -+#define TALITOS_MDEUSR 0xc028 /* MDEU status register */ -+#define TALITOS_MDEUSR_RESET 0x01000000 /* MDEU Reset status bit */ -+#define TALITOS_MDEUISR 0xc030 /* MDEU interrupt status register */ -+#define TALITOS_MDEUIMR 0xc038 /* MDEU interrupt mask register */ -+#define TALITOS_MDEUIMR_MASK 0xc41f0000 /* MDEU interrupt control mask*/ -+ -+#define TALITOS_AFEURCR 0x8018 /* AFEU reset control register */ -+#define TALITOS_AFEURCR_RESET 0x01000000 /* AFEU reset bit */ -+#define TALITOS_AFEUSR 0x8028 /* AFEU status register */ -+#define TALITOS_AFEUSR_RESET 0x01000000 /* AFEU Reset status bit */ -+#define TALITOS_AFEUISR 0x8030 /* AFEU interrupt status register */ -+#define TALITOS_AFEUIMR 0x8038 /* AFEU interrupt mask register */ -+#define TALITOS_AFEUIMR_MASK 0xf61f0000 /* AFEU interrupt control mask*/ -+ -+#define TALITOS_RNGRCR 0xe018 /* RNG Reset control register */ -+#define TALITOS_RNGRCR_SR 0x01000000 /* RNG RNGRCR:Software Reset */ -+#define TALITOS_RNGSR 0xe028 /* RNG status register */ -+#define TALITOS_RNGSR_RD 0x01000000 /* RNG Reset done */ -+#define TALITOS_RNGISR 0xe030 /* RNG Interrupt status register */ -+#define TALITOS_RNGIMR 0xe038 /* RNG interrupt mask register */ -+#define TALITOS_RNGIMR_MASK 0xc2100000 /* RNG interrupt control mask*/ -+ -+#define TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256 0x28 -+#define TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512 0x48 -+ -+/***************************RC4*******************/ -+#define ARC4_SEC_MIN_KEY_SIZE 5 -+#define ARC4_SEC_MAX_KEY_SIZE 16 -+#define ARC4_SEC_CONTEXT_LEN 259 -+#define SEC_ALG_AFEU_KEY 0x10200050 -+#define SEC_ALG_AFEU_CONTEXT 0x10700050 -+ -+/* talitos descriptor header (hdr) bits */ -+ -+/* primary execution unit select */ -+#define DESC_HDR_SEL0_MASK 0xf0000000 -+#define DESC_HDR_SEL0_AFEU 0x10000000 -+#define DESC_HDR_SEL0_DEU 0x20000000 -+#define DESC_HDR_SEL0_MDEU 0x30000000 -+#define DESC_HDR_SEL0_RNG 0x40000000 -+#define DESC_HDR_SEL0_AESU 0x60000000 -+ -+/* primary execution unit mode (MODE0) and derivatives */ -+#define DESC_HDR_MODE0_MASK 0x0ff00000 -+#define DESC_HDR_MODE0_ENCRYP 0x00100000 -+#define DESC_HDR_MODE0_AFEU_USE_KEY 0x00200000 -+#define DESC_HDR_MODE0_AFEU_USE_CONTEXT 0x00700000 -+#define DESC_HDR_MODE0_AESU_CBC 0x00200000 -+#define DESC_HDR_MODE0_AESU_ENC 0x00100000 -+#define DESC_HDR_MODE0_DEU_CBC 0x00400000 -+#define DESC_HDR_MODE0_DEU_3DES 0x00200000 -+#define DESC_HDR_MODE0_DEU_ENC 0x00100000 -+#define DESC_HDR_MODE0_MDEU_CONT 0x08000000 -+#define DESC_HDR_MODE0_MDEU_INIT 0x01000000 /* init starting regs */ -+#define DESC_HDR_MODE0_MDEU_HMAC 0x00800000 -+#define DESC_HDR_MODE0_MDEU_PAD 0x00400000 /* PD */ -+#define DESC_HDR_MODE0_MDEU_MD5 0x00200000 -+#define DESC_HDR_MODE0_MDEU_SHA256 0x00100000 -+#define DESC_HDR_MODE0_MDEU_SHA1 0x00000000 /* SHA-160 */ -+#define DESC_HDR_MODE0_MDEU_MD5_HMAC \ -+ (DESC_HDR_MODE0_MDEU_MD5 | DESC_HDR_MODE0_MDEU_HMAC) -+#define DESC_HDR_MODE0_MDEU_SHA256_HMAC \ -+ (DESC_HDR_MODE0_MDEU_SHA256 | DESC_HDR_MODE0_MDEU_HMAC) -+#define DESC_HDR_MODE0_MDEU_SHA1_HMAC \ -+ (DESC_HDR_MODE0_MDEU_SHA1 | DESC_HDR_MODE0_MDEU_HMAC) -+ -+/* secondary execution unit select (SEL1) */ -+/* it's MDEU or nothing */ -+#define DESC_HDR_SEL1_MASK 0x000f0000 -+#define DESC_HDR_SEL1_MDEU 0x00030000 -+ -+/* secondary execution unit mode (MODE1) and derivatives */ -+#define DESC_HDR_MODE1_MDEU_INIT 0x00001000 /* init starting regs */ -+#define DESC_HDR_MODE1_MDEU_HMAC 0x00000800 -+#define DESC_HDR_MODE1_MDEU_PAD 0x00000400 /* PD */ -+#define DESC_HDR_MODE1_MDEU_MD5 0x00000200 -+#define DESC_HDR_MODE1_MDEU_SHA256 0x00000100 -+#define DESC_HDR_MODE1_MDEU_SHA1 0x00000000 /* SHA-160 */ -+#define DESC_HDR_MODE1_MDEU_MD5_HMAC \ -+ (DESC_HDR_MODE1_MDEU_MD5 | DESC_HDR_MODE1_MDEU_HMAC) -+#define DESC_HDR_MODE1_MDEU_SHA256_HMAC \ -+ (DESC_HDR_MODE1_MDEU_SHA256 | DESC_HDR_MODE1_MDEU_HMAC) -+#define DESC_HDR_MODE1_MDEU_SHA1_HMAC \ -+ (DESC_HDR_MODE1_MDEU_SHA1 | DESC_HDR_MODE1_MDEU_HMAC) -+ -+/* direction of overall data flow (DIR) */ -+#define DESC_HDR_DIR_OUTBOUND 0x00000000 -+#define DESC_HDR_DIR_INBOUND 0x00000002 -+ -+/* done notification (DN) */ -+#define DESC_HDR_DONE 0x00000001 -+ -+/* descriptor types */ -+#define DESC_HDR_TYPE_AESU_CTR_NONSNOOP (0 << 4) -+#define DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU (1 << 4) -+#define DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU (2 << 4) -+#define DESC_HDR_TYPE_NONHMAC_SNOOP_NO_AFEU (3 << 4) -+#define DESC_HDR_TYPE_COMMON_NONSNOOP_AFEU (5 << 4) -+ -+#define TALITOS_HDR_DONE_BITS 0xff000000 |