xref: /linux/drivers/crypto/talitos.c (revision 6ae7a8b193d353fe3a2a371b61ec4c8ecfcbb0a1)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29c4a7965SKim Phillips /*
39c4a7965SKim Phillips  * talitos - Freescale Integrated Security Engine (SEC) device driver
49c4a7965SKim Phillips  *
55228f0f7SKim Phillips  * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
69c4a7965SKim Phillips  *
79c4a7965SKim Phillips  * Scatterlist Crypto API glue code copied from files with the following:
89c4a7965SKim Phillips  * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
99c4a7965SKim Phillips  *
109c4a7965SKim Phillips  * Crypto algorithm registration code copied from hifn driver:
119c4a7965SKim Phillips  * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
129c4a7965SKim Phillips  * All rights reserved.
139c4a7965SKim Phillips  */
149c4a7965SKim Phillips 
159c4a7965SKim Phillips #include <linux/kernel.h>
169c4a7965SKim Phillips #include <linux/module.h>
179c4a7965SKim Phillips #include <linux/mod_devicetable.h>
189c4a7965SKim Phillips #include <linux/device.h>
199c4a7965SKim Phillips #include <linux/interrupt.h>
209c4a7965SKim Phillips #include <linux/crypto.h>
219c4a7965SKim Phillips #include <linux/hw_random.h>
225af50730SRob Herring #include <linux/of_address.h>
235af50730SRob Herring #include <linux/of_irq.h>
249c4a7965SKim Phillips #include <linux/of_platform.h>
259c4a7965SKim Phillips #include <linux/dma-mapping.h>
269c4a7965SKim Phillips #include <linux/io.h>
279c4a7965SKim Phillips #include <linux/spinlock.h>
289c4a7965SKim Phillips #include <linux/rtnetlink.h>
295a0e3ad6STejun Heo #include <linux/slab.h>
309c4a7965SKim Phillips 
319c4a7965SKim Phillips #include <crypto/algapi.h>
329c4a7965SKim Phillips #include <crypto/aes.h>
339d574ae8SArd Biesheuvel #include <crypto/internal/des.h>
34a24d22b2SEric Biggers #include <crypto/sha1.h>
35a24d22b2SEric Biggers #include <crypto/sha2.h>
36497f2e6bSLee Nipper #include <crypto/md5.h>
37e98014abSHerbert Xu #include <crypto/internal/aead.h>
389c4a7965SKim Phillips #include <crypto/authenc.h>
39373960d7SArd Biesheuvel #include <crypto/internal/skcipher.h>
40acbf7c62SLee Nipper #include <crypto/hash.h>
41acbf7c62SLee Nipper #include <crypto/internal/hash.h>
424de9d0b5SLee Nipper #include <crypto/scatterwalk.h>
439c4a7965SKim Phillips 
449c4a7965SKim Phillips #include "talitos.h"
459c4a7965SKim Phillips 
46922f9dc8SLEROY Christophe static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
47da9de146SLEROY Christophe 			   unsigned int len, bool is_sec1)
4881eb024cSKim Phillips {
49edc6bd69SLEROY Christophe 	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
50da9de146SLEROY Christophe 	if (is_sec1) {
51da9de146SLEROY Christophe 		ptr->len1 = cpu_to_be16(len);
52da9de146SLEROY Christophe 	} else {
53da9de146SLEROY Christophe 		ptr->len = cpu_to_be16(len);
54edc6bd69SLEROY Christophe 		ptr->eptr = upper_32_bits(dma_addr);
5581eb024cSKim Phillips 	}
56da9de146SLEROY Christophe }
5781eb024cSKim Phillips 
58340ff60aSHoria Geant? static void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
59340ff60aSHoria Geant? 			     struct talitos_ptr *src_ptr, bool is_sec1)
60340ff60aSHoria Geant? {
61340ff60aSHoria Geant? 	dst_ptr->ptr = src_ptr->ptr;
62922f9dc8SLEROY Christophe 	if (is_sec1) {
63da9de146SLEROY Christophe 		dst_ptr->len1 = src_ptr->len1;
64922f9dc8SLEROY Christophe 	} else {
65da9de146SLEROY Christophe 		dst_ptr->len = src_ptr->len;
66da9de146SLEROY Christophe 		dst_ptr->eptr = src_ptr->eptr;
67538caf83SLEROY Christophe 	}
68922f9dc8SLEROY Christophe }
69538caf83SLEROY Christophe 
70922f9dc8SLEROY Christophe static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
71922f9dc8SLEROY Christophe 					   bool is_sec1)
72538caf83SLEROY Christophe {
73922f9dc8SLEROY Christophe 	if (is_sec1)
74922f9dc8SLEROY Christophe 		return be16_to_cpu(ptr->len1);
75922f9dc8SLEROY Christophe 	else
76538caf83SLEROY Christophe 		return be16_to_cpu(ptr->len);
77538caf83SLEROY Christophe }
78538caf83SLEROY Christophe 
79b096b544SLEROY Christophe static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
80b096b544SLEROY Christophe 				   bool is_sec1)
81185eb79fSLEROY Christophe {
82922f9dc8SLEROY Christophe 	if (!is_sec1)
83b096b544SLEROY Christophe 		ptr->j_extent = val;
84b096b544SLEROY Christophe }
85b096b544SLEROY Christophe 
86b096b544SLEROY Christophe static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
87b096b544SLEROY Christophe {
88b096b544SLEROY Christophe 	if (!is_sec1)
89b096b544SLEROY Christophe 		ptr->j_extent |= val;
90185eb79fSLEROY Christophe }
91185eb79fSLEROY Christophe 
929c4a7965SKim Phillips /*
939c4a7965SKim Phillips  * map virtual single (contiguous) pointer to h/w descriptor pointer
949c4a7965SKim Phillips  */
956a4967c3SLEROY Christophe static void __map_single_talitos_ptr(struct device *dev,
966a4967c3SLEROY Christophe 				     struct talitos_ptr *ptr,
976a4967c3SLEROY Christophe 				     unsigned int len, void *data,
986a4967c3SLEROY Christophe 				     enum dma_data_direction dir,
996a4967c3SLEROY Christophe 				     unsigned long attrs)
1006a4967c3SLEROY Christophe {
1016a4967c3SLEROY Christophe 	dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs);
1026a4967c3SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1036a4967c3SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1046a4967c3SLEROY Christophe 
1056a4967c3SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr, len, is_sec1);
1066a4967c3SLEROY Christophe }
1076a4967c3SLEROY Christophe 
1089c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev,
109edc6bd69SLEROY Christophe 				   struct talitos_ptr *ptr,
11042e8b0d7SHoria Geant? 				   unsigned int len, void *data,
1119c4a7965SKim Phillips 				   enum dma_data_direction dir)
1129c4a7965SKim Phillips {
1136a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir, 0);
1146a4967c3SLEROY Christophe }
11581eb024cSKim Phillips 
1166a4967c3SLEROY Christophe static void map_single_talitos_ptr_nosync(struct device *dev,
1176a4967c3SLEROY Christophe 					  struct talitos_ptr *ptr,
1186a4967c3SLEROY Christophe 					  unsigned int len, void *data,
1196a4967c3SLEROY Christophe 					  enum dma_data_direction dir)
1206a4967c3SLEROY Christophe {
1216a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir,
1226a4967c3SLEROY Christophe 				 DMA_ATTR_SKIP_CPU_SYNC);
1239c4a7965SKim Phillips }
1249c4a7965SKim Phillips 
1259c4a7965SKim Phillips /*
1269c4a7965SKim Phillips  * unmap bus single (contiguous) h/w descriptor pointer
1279c4a7965SKim Phillips  */
1289c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev,
129edc6bd69SLEROY Christophe 				     struct talitos_ptr *ptr,
1309c4a7965SKim Phillips 				     enum dma_data_direction dir)
1319c4a7965SKim Phillips {
132922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
133922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
134922f9dc8SLEROY Christophe 
135edc6bd69SLEROY Christophe 	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
136922f9dc8SLEROY Christophe 			 from_talitos_ptr_len(ptr, is_sec1), dir);
1379c4a7965SKim Phillips }
1389c4a7965SKim Phillips 
1399c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch)
1409c4a7965SKim Phillips {
1419c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1429c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
143dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1449c4a7965SKim Phillips 
145dd3c0987SLEROY Christophe 	if (is_sec1) {
146dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
147dd3c0987SLEROY Christophe 			  TALITOS1_CCCR_LO_RESET);
1489c4a7965SKim Phillips 
149dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
150dd3c0987SLEROY Christophe 			TALITOS1_CCCR_LO_RESET) && --timeout)
1519c4a7965SKim Phillips 			cpu_relax();
152dd3c0987SLEROY Christophe 	} else {
153dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
154dd3c0987SLEROY Christophe 			  TALITOS2_CCCR_RESET);
155dd3c0987SLEROY Christophe 
156dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
157dd3c0987SLEROY Christophe 			TALITOS2_CCCR_RESET) && --timeout)
158dd3c0987SLEROY Christophe 			cpu_relax();
159dd3c0987SLEROY Christophe 	}
1609c4a7965SKim Phillips 
1619c4a7965SKim Phillips 	if (timeout == 0) {
1629c4a7965SKim Phillips 		dev_err(dev, "failed to reset channel %d\n", ch);
1639c4a7965SKim Phillips 		return -EIO;
1649c4a7965SKim Phillips 	}
1659c4a7965SKim Phillips 
16681eb024cSKim Phillips 	/* set 36-bit addressing, done writeback enable and done IRQ enable */
167ad42d5fcSKim Phillips 	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
16881eb024cSKim Phillips 		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
16937b5e889SLEROY Christophe 	/* enable chaining descriptors */
17037b5e889SLEROY Christophe 	if (is_sec1)
17137b5e889SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
17237b5e889SLEROY Christophe 			  TALITOS_CCCR_LO_NE);
1739c4a7965SKim Phillips 
174fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
175fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
176ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
177fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
178fe5720e2SKim Phillips 
1799c4a7965SKim Phillips 	return 0;
1809c4a7965SKim Phillips }
1819c4a7965SKim Phillips 
1829c4a7965SKim Phillips static int reset_device(struct device *dev)
1839c4a7965SKim Phillips {
1849c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1859c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
186dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
187dd3c0987SLEROY Christophe 	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
1889c4a7965SKim Phillips 
189c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
1909c4a7965SKim Phillips 
191dd3c0987SLEROY Christophe 	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
1929c4a7965SKim Phillips 	       && --timeout)
1939c4a7965SKim Phillips 		cpu_relax();
1949c4a7965SKim Phillips 
1952cdba3cfSKim Phillips 	if (priv->irq[1]) {
196c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
197c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
198c3e337f8SKim Phillips 	}
199c3e337f8SKim Phillips 
2009c4a7965SKim Phillips 	if (timeout == 0) {
2019c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
2029c4a7965SKim Phillips 		return -EIO;
2039c4a7965SKim Phillips 	}
2049c4a7965SKim Phillips 
2059c4a7965SKim Phillips 	return 0;
2069c4a7965SKim Phillips }
2079c4a7965SKim Phillips 
2089c4a7965SKim Phillips /*
2099c4a7965SKim Phillips  * Reset and initialize the device
2109c4a7965SKim Phillips  */
2119c4a7965SKim Phillips static int init_device(struct device *dev)
2129c4a7965SKim Phillips {
2139c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2149c4a7965SKim Phillips 	int ch, err;
215dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2169c4a7965SKim Phillips 
2179c4a7965SKim Phillips 	/*
2189c4a7965SKim Phillips 	 * Master reset
2199c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
2209c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
2219c4a7965SKim Phillips 	 * set bit twice to completely reset
2229c4a7965SKim Phillips 	 */
2239c4a7965SKim Phillips 	err = reset_device(dev);
2249c4a7965SKim Phillips 	if (err)
2259c4a7965SKim Phillips 		return err;
2269c4a7965SKim Phillips 
2279c4a7965SKim Phillips 	err = reset_device(dev);
2289c4a7965SKim Phillips 	if (err)
2299c4a7965SKim Phillips 		return err;
2309c4a7965SKim Phillips 
2319c4a7965SKim Phillips 	/* reset channels */
2329c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
2339c4a7965SKim Phillips 		err = reset_channel(dev, ch);
2349c4a7965SKim Phillips 		if (err)
2359c4a7965SKim Phillips 			return err;
2369c4a7965SKim Phillips 	}
2379c4a7965SKim Phillips 
2389c4a7965SKim Phillips 	/* enable channel done and error interrupts */
239dd3c0987SLEROY Christophe 	if (is_sec1) {
240dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
241dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
242dd3c0987SLEROY Christophe 		/* disable parity error check in DEU (erroneous? test vect.) */
243dd3c0987SLEROY Christophe 		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
244dd3c0987SLEROY Christophe 	} else {
245dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
246dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
247dd3c0987SLEROY Christophe 	}
2489c4a7965SKim Phillips 
249fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
250fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2515fa7fa14SLEROY Christophe 		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
252fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
253fe5720e2SKim Phillips 
2549c4a7965SKim Phillips 	return 0;
2559c4a7965SKim Phillips }
2569c4a7965SKim Phillips 
2579c4a7965SKim Phillips /**
2589c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
2599c4a7965SKim Phillips  * @dev:	the SEC device to be used
2605228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
2619c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
2629c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
2639c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
2649c4a7965SKim Phillips  *
2659c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
2669c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
2679c4a7965SKim Phillips  * for device processing status.
2689c4a7965SKim Phillips  */
269fbb8d46eSChristophe Leroy static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2709c4a7965SKim Phillips 			  void (*callback)(struct device *dev,
2719c4a7965SKim Phillips 					   struct talitos_desc *desc,
2729c4a7965SKim Phillips 					   void *context, int error),
2739c4a7965SKim Phillips 			  void *context)
2749c4a7965SKim Phillips {
2759c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2769c4a7965SKim Phillips 	struct talitos_request *request;
2775228f0f7SKim Phillips 	unsigned long flags;
2789c4a7965SKim Phillips 	int head;
2797d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2809c4a7965SKim Phillips 
2814b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2829c4a7965SKim Phillips 
2834b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
284ec6644d6SKim Phillips 		/* h/w fifo is full */
2854b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2869c4a7965SKim Phillips 		return -EAGAIN;
2879c4a7965SKim Phillips 	}
2889c4a7965SKim Phillips 
2894b992628SKim Phillips 	head = priv->chan[ch].head;
2904b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
291ec6644d6SKim Phillips 
2929c4a7965SKim Phillips 	/* map descriptor and save caller data */
2937d607c6aSLEROY Christophe 	if (is_sec1) {
2947d607c6aSLEROY Christophe 		desc->hdr1 = desc->hdr;
2957d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, &desc->hdr1,
2967d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2979c4a7965SKim Phillips 						   DMA_BIDIRECTIONAL);
2987d607c6aSLEROY Christophe 	} else {
2997d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, desc,
3007d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
3017d607c6aSLEROY Christophe 						   DMA_BIDIRECTIONAL);
3027d607c6aSLEROY Christophe 	}
3039c4a7965SKim Phillips 	request->callback = callback;
3049c4a7965SKim Phillips 	request->context = context;
3059c4a7965SKim Phillips 
3069c4a7965SKim Phillips 	/* increment fifo head */
3074b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
3089c4a7965SKim Phillips 
3099c4a7965SKim Phillips 	smp_wmb();
3109c4a7965SKim Phillips 	request->desc = desc;
3119c4a7965SKim Phillips 
3129c4a7965SKim Phillips 	/* GO! */
3139c4a7965SKim Phillips 	wmb();
314ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
315ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
316ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
317a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
3189c4a7965SKim Phillips 
3194b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3209c4a7965SKim Phillips 
3219c4a7965SKim Phillips 	return -EINPROGRESS;
3229c4a7965SKim Phillips }
3239c4a7965SKim Phillips 
32458cdbc6dSChristophe Leroy static __be32 get_request_hdr(struct talitos_request *request, bool is_sec1)
32558cdbc6dSChristophe Leroy {
32658cdbc6dSChristophe Leroy 	struct talitos_edesc *edesc;
32758cdbc6dSChristophe Leroy 
32858cdbc6dSChristophe Leroy 	if (!is_sec1)
32958cdbc6dSChristophe Leroy 		return request->desc->hdr;
33058cdbc6dSChristophe Leroy 
33158cdbc6dSChristophe Leroy 	if (!request->desc->next_desc)
33258cdbc6dSChristophe Leroy 		return request->desc->hdr1;
33358cdbc6dSChristophe Leroy 
33458cdbc6dSChristophe Leroy 	edesc = container_of(request->desc, struct talitos_edesc, desc);
33558cdbc6dSChristophe Leroy 
33658cdbc6dSChristophe Leroy 	return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1;
33758cdbc6dSChristophe Leroy }
3389c4a7965SKim Phillips 
3399c4a7965SKim Phillips /*
3409c4a7965SKim Phillips  * process what was done, notify callback of error if not
3419c4a7965SKim Phillips  */
3429c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3439c4a7965SKim Phillips {
3449c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3459c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
3469c4a7965SKim Phillips 	unsigned long flags;
3479c4a7965SKim Phillips 	int tail, status;
3487d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3499c4a7965SKim Phillips 
3504b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3519c4a7965SKim Phillips 
3524b992628SKim Phillips 	tail = priv->chan[ch].tail;
3534b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
3547d607c6aSLEROY Christophe 		__be32 hdr;
3557d607c6aSLEROY Christophe 
3564b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
3579c4a7965SKim Phillips 
3589c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
3599c4a7965SKim Phillips 		rmb();
36058cdbc6dSChristophe Leroy 		hdr = get_request_hdr(request, is_sec1);
3617d607c6aSLEROY Christophe 
3627d607c6aSLEROY Christophe 		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3639c4a7965SKim Phillips 			status = 0;
364ca38a814SLee Nipper 		else
3659c4a7965SKim Phillips 			if (!error)
3669c4a7965SKim Phillips 				break;
3679c4a7965SKim Phillips 			else
3689c4a7965SKim Phillips 				status = error;
3699c4a7965SKim Phillips 
3709c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
3717d607c6aSLEROY Christophe 				 TALITOS_DESC_SIZE,
372e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
3739c4a7965SKim Phillips 
3749c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
3759c4a7965SKim Phillips 		saved_req.desc = request->desc;
3769c4a7965SKim Phillips 		saved_req.callback = request->callback;
3779c4a7965SKim Phillips 		saved_req.context = request->context;
3789c4a7965SKim Phillips 
3799c4a7965SKim Phillips 		/* release request entry in fifo */
3809c4a7965SKim Phillips 		smp_wmb();
3819c4a7965SKim Phillips 		request->desc = NULL;
3829c4a7965SKim Phillips 
3839c4a7965SKim Phillips 		/* increment fifo tail */
3844b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3859c4a7965SKim Phillips 
3864b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
387ec6644d6SKim Phillips 
3884b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
389ec6644d6SKim Phillips 
3909c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
3919c4a7965SKim Phillips 				   status);
3929c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
3939c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
3949c4a7965SKim Phillips 			return;
3954b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3964b992628SKim Phillips 		tail = priv->chan[ch].tail;
3979c4a7965SKim Phillips 	}
3989c4a7965SKim Phillips 
3994b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
4009c4a7965SKim Phillips }
4019c4a7965SKim Phillips 
4029c4a7965SKim Phillips /*
4039c4a7965SKim Phillips  * process completed requests for channels that have done status
4049c4a7965SKim Phillips  */
405dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask)				\
406dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data)			\
407dd3c0987SLEROY Christophe {									\
408dd3c0987SLEROY Christophe 	struct device *dev = (struct device *)data;			\
409dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		\
410dd3c0987SLEROY Christophe 	unsigned long flags;						\
411dd3c0987SLEROY Christophe 									\
412dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x10000000)					\
413dd3c0987SLEROY Christophe 		flush_channel(dev, 0, 0, 0);			\
414dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x40000000)					\
415dd3c0987SLEROY Christophe 		flush_channel(dev, 1, 0, 0);			\
416dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00010000)					\
417dd3c0987SLEROY Christophe 		flush_channel(dev, 2, 0, 0);			\
418dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00040000)					\
419dd3c0987SLEROY Christophe 		flush_channel(dev, 3, 0, 0);			\
420dd3c0987SLEROY Christophe 									\
421dd3c0987SLEROY Christophe 	/* At this point, all completed channels have been processed */	\
422dd3c0987SLEROY Christophe 	/* Unmask done interrupts for channels completed later on. */	\
423dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			\
424dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
425dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
426dd3c0987SLEROY Christophe 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
427dd3c0987SLEROY Christophe }
428dd3c0987SLEROY Christophe 
429dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
4309c02e285SLEROY Christophe DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
431dd3c0987SLEROY Christophe 
432dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask)				\
433dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data)			\
434c3e337f8SKim Phillips {									\
435c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
436c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
437511d63cbSHoria Geanta 	unsigned long flags;						\
438c3e337f8SKim Phillips 									\
439c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
440c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
441c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
442c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
443c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
444c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
445c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
446c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
447c3e337f8SKim Phillips 									\
448c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
449c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
450511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
451c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
452dd3c0987SLEROY Christophe 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
453511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4549c4a7965SKim Phillips }
455dd3c0987SLEROY Christophe 
456dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
4579c02e285SLEROY Christophe DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
458dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
459dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4609c4a7965SKim Phillips 
4619c4a7965SKim Phillips /*
4629c4a7965SKim Phillips  * locate current (offending) descriptor
4639c4a7965SKim Phillips  */
46402376161SChristophe Leroy static __be32 current_desc_hdr(struct device *dev, int ch)
4659c4a7965SKim Phillips {
4669c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
467b62ffd8cSHoria Geanta 	int tail, iter;
4689c4a7965SKim Phillips 	dma_addr_t cur_desc;
4699c4a7965SKim Phillips 
470b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
471b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4729c4a7965SKim Phillips 
473b62ffd8cSHoria Geanta 	if (!cur_desc) {
474b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
475b62ffd8cSHoria Geanta 		return 0;
476b62ffd8cSHoria Geanta 	}
477b62ffd8cSHoria Geanta 
478b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
479b62ffd8cSHoria Geanta 
480b62ffd8cSHoria Geanta 	iter = tail;
48137b5e889SLEROY Christophe 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc &&
482195404dbSChristophe Leroy 	       priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) {
483b62ffd8cSHoria Geanta 		iter = (iter + 1) & (priv->fifo_len - 1);
484b62ffd8cSHoria Geanta 		if (iter == tail) {
4859c4a7965SKim Phillips 			dev_err(dev, "couldn't locate current descriptor\n");
4863e721aebSKim Phillips 			return 0;
4879c4a7965SKim Phillips 		}
4889c4a7965SKim Phillips 	}
4899c4a7965SKim Phillips 
490195404dbSChristophe Leroy 	if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) {
49158cdbc6dSChristophe Leroy 		struct talitos_edesc *edesc;
49258cdbc6dSChristophe Leroy 
49358cdbc6dSChristophe Leroy 		edesc = container_of(priv->chan[ch].fifo[iter].desc,
49458cdbc6dSChristophe Leroy 				     struct talitos_edesc, desc);
49558cdbc6dSChristophe Leroy 		return ((struct talitos_desc *)
49658cdbc6dSChristophe Leroy 			(edesc->buf + edesc->dma_len))->hdr;
49758cdbc6dSChristophe Leroy 	}
49837b5e889SLEROY Christophe 
499b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
5009c4a7965SKim Phillips }
5019c4a7965SKim Phillips 
5029c4a7965SKim Phillips /*
5039c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
5049c4a7965SKim Phillips  */
50502376161SChristophe Leroy static void report_eu_error(struct device *dev, int ch, __be32 desc_hdr)
5069c4a7965SKim Phillips {
5079c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5089c4a7965SKim Phillips 	int i;
5099c4a7965SKim Phillips 
5103e721aebSKim Phillips 	if (!desc_hdr)
51102376161SChristophe Leroy 		desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF));
5123e721aebSKim Phillips 
5133e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
5149c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
5159c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
5165fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR),
5175fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
5189c4a7965SKim Phillips 		break;
5199c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
5209c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
5215fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR),
5225fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
5239c4a7965SKim Phillips 		break;
5249c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
5259c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
5269c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5275fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5285fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5299c4a7965SKim Phillips 		break;
5309c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
5319c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
5325fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR),
5335fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5349c4a7965SKim Phillips 		break;
5359c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
5369c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5375fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5385fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5399c4a7965SKim Phillips 		break;
5409c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
5419c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5425fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR),
5435fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5449c4a7965SKim Phillips 		break;
5459c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
5469c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5475fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5485fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5499c4a7965SKim Phillips 		break;
5509c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
5519c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5525fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5535fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5549c4a7965SKim Phillips 		break;
5559c4a7965SKim Phillips 	}
5569c4a7965SKim Phillips 
5573e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5589c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
5599c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
5609c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5615fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5625fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5639c4a7965SKim Phillips 		break;
5649c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
5659c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5665fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5675fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5689c4a7965SKim Phillips 		break;
5699c4a7965SKim Phillips 	}
5709c4a7965SKim Phillips 
5719c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
5729c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
573ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
574ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5759c4a7965SKim Phillips }
5769c4a7965SKim Phillips 
5779c4a7965SKim Phillips /*
5789c4a7965SKim Phillips  * recover from error interrupts
5799c4a7965SKim Phillips  */
5805e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5819c4a7965SKim Phillips {
5829c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5839c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
584dd3c0987SLEROY Christophe 	int ch, error, reset_dev = 0;
58542e8b0d7SHoria Geant? 	u32 v_lo;
586dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
587dd3c0987SLEROY Christophe 	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5889c4a7965SKim Phillips 
5899c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
5909c4a7965SKim Phillips 		/* skip channels without errors */
591dd3c0987SLEROY Christophe 		if (is_sec1) {
592dd3c0987SLEROY Christophe 			/* bits 29, 31, 17, 19 */
593dd3c0987SLEROY Christophe 			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
594dd3c0987SLEROY Christophe 				continue;
595dd3c0987SLEROY Christophe 		} else {
5969c4a7965SKim Phillips 			if (!(isr & (1 << (ch * 2 + 1))))
5979c4a7965SKim Phillips 				continue;
598dd3c0987SLEROY Christophe 		}
5999c4a7965SKim Phillips 
6009c4a7965SKim Phillips 		error = -EINVAL;
6019c4a7965SKim Phillips 
602ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
6039c4a7965SKim Phillips 
6049c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
6059c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
6069c4a7965SKim Phillips 			error = -EAGAIN;
6079c4a7965SKim Phillips 			reset_ch = 1;
6089c4a7965SKim Phillips 		}
6099c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
6109c4a7965SKim Phillips 			/* h/w dropped descriptor */
6119c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
6129c4a7965SKim Phillips 			error = -EAGAIN;
6139c4a7965SKim Phillips 		}
6149c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
6159c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
6169c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
6174d9b3a5bSColin Ian King 			dev_err(dev, is_sec1 ? "pointer not complete error\n"
618dd3c0987SLEROY Christophe 					     : "s/g data length zero error\n");
6199c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
620dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "parity error\n"
621dd3c0987SLEROY Christophe 					     : "fetch pointer zero error\n");
6229c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
6239c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
6249c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
625dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "static assignment error\n"
626dd3c0987SLEROY Christophe 					     : "invalid exec unit error\n");
6279c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
6283e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
629dd3c0987SLEROY Christophe 		if (!is_sec1) {
6309c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GB)
6319c4a7965SKim Phillips 				dev_err(dev, "gather boundary error\n");
6329c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GRL)
6339c4a7965SKim Phillips 				dev_err(dev, "gather return/length error\n");
6349c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SB)
6359c4a7965SKim Phillips 				dev_err(dev, "scatter boundary error\n");
6369c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SRL)
6379c4a7965SKim Phillips 				dev_err(dev, "scatter return/length error\n");
638dd3c0987SLEROY Christophe 		}
6399c4a7965SKim Phillips 
6409c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
6419c4a7965SKim Phillips 
6429c4a7965SKim Phillips 		if (reset_ch) {
6439c4a7965SKim Phillips 			reset_channel(dev, ch);
6449c4a7965SKim Phillips 		} else {
645ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
646dd3c0987SLEROY Christophe 				  TALITOS2_CCCR_CONT);
647ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
648ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
649dd3c0987SLEROY Christophe 			       TALITOS2_CCCR_CONT) && --timeout)
6509c4a7965SKim Phillips 				cpu_relax();
6519c4a7965SKim Phillips 			if (timeout == 0) {
6529c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
6539c4a7965SKim Phillips 					ch);
6549c4a7965SKim Phillips 				reset_dev = 1;
6559c4a7965SKim Phillips 			}
6569c4a7965SKim Phillips 		}
6579c4a7965SKim Phillips 	}
658dd3c0987SLEROY Christophe 	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
659dd3c0987SLEROY Christophe 	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
660dd3c0987SLEROY Christophe 		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
661dd3c0987SLEROY Christophe 			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
662dd3c0987SLEROY Christophe 				isr, isr_lo);
663dd3c0987SLEROY Christophe 		else
664dd3c0987SLEROY Christophe 			dev_err(dev, "done overflow, internal time out, or "
665dd3c0987SLEROY Christophe 				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6669c4a7965SKim Phillips 
6679c4a7965SKim Phillips 		/* purge request queues */
6689c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
6699c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
6709c4a7965SKim Phillips 
6719c4a7965SKim Phillips 		/* reset and reinitialize the device */
6729c4a7965SKim Phillips 		init_device(dev);
6739c4a7965SKim Phillips 	}
6749c4a7965SKim Phillips }
6759c4a7965SKim Phillips 
676dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
677dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
678dd3c0987SLEROY Christophe {									       \
679dd3c0987SLEROY Christophe 	struct device *dev = data;					       \
680dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
681dd3c0987SLEROY Christophe 	u32 isr, isr_lo;						       \
682dd3c0987SLEROY Christophe 	unsigned long flags;						       \
683dd3c0987SLEROY Christophe 									       \
684dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
685dd3c0987SLEROY Christophe 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
686dd3c0987SLEROY Christophe 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
687dd3c0987SLEROY Christophe 	/* Acknowledge interrupt */					       \
688dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
689dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
690dd3c0987SLEROY Christophe 									       \
691dd3c0987SLEROY Christophe 	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
692dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
693dd3c0987SLEROY Christophe 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
694dd3c0987SLEROY Christophe 	}								       \
695dd3c0987SLEROY Christophe 	else {								       \
696dd3c0987SLEROY Christophe 		if (likely(isr & ch_done_mask)) {			       \
697dd3c0987SLEROY Christophe 			/* mask further done interrupts. */		       \
698dd3c0987SLEROY Christophe 			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
699dd3c0987SLEROY Christophe 			/* done_task will unmask done interrupts at exit */    \
700dd3c0987SLEROY Christophe 			tasklet_schedule(&priv->done_task[tlet]);	       \
701dd3c0987SLEROY Christophe 		}							       \
702dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
703dd3c0987SLEROY Christophe 	}								       \
704dd3c0987SLEROY Christophe 									       \
705dd3c0987SLEROY Christophe 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
706dd3c0987SLEROY Christophe 								IRQ_NONE;      \
707dd3c0987SLEROY Christophe }
708dd3c0987SLEROY Christophe 
709dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
710dd3c0987SLEROY Christophe 
711dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
712dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
713c3e337f8SKim Phillips {									       \
714c3e337f8SKim Phillips 	struct device *dev = data;					       \
715c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
716c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
717511d63cbSHoria Geanta 	unsigned long flags;						       \
718c3e337f8SKim Phillips 									       \
719511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
720c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
721c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
722c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
723c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
724c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
725c3e337f8SKim Phillips 									       \
726511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
727511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
728511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
729511d63cbSHoria Geanta 	}								       \
730511d63cbSHoria Geanta 	else {								       \
731c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
732c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
733c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
734c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
735c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
736c3e337f8SKim Phillips 		}							       \
737511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
738511d63cbSHoria Geanta 	}								       \
739c3e337f8SKim Phillips 									       \
740c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
741c3e337f8SKim Phillips 								IRQ_NONE;      \
7421c2e8811SLee Nipper }
743dd3c0987SLEROY Christophe 
744dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
745dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
746dd3c0987SLEROY Christophe 		       0)
747dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
748dd3c0987SLEROY Christophe 		       1)
7499c4a7965SKim Phillips 
7509c4a7965SKim Phillips /*
7519c4a7965SKim Phillips  * hwrng
7529c4a7965SKim Phillips  */
7539c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
7549c4a7965SKim Phillips {
7559c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7569c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7579c4a7965SKim Phillips 	u32 ofl;
7589c4a7965SKim Phillips 	int i;
7599c4a7965SKim Phillips 
7609c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
7615fa7fa14SLEROY Christophe 		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7629c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
7639c4a7965SKim Phillips 		if (ofl || !wait)
7649c4a7965SKim Phillips 			break;
7659c4a7965SKim Phillips 		udelay(10);
7669c4a7965SKim Phillips 	}
7679c4a7965SKim Phillips 
7689c4a7965SKim Phillips 	return !!ofl;
7699c4a7965SKim Phillips }
7709c4a7965SKim Phillips 
7719c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7729c4a7965SKim Phillips {
7739c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7749c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7759c4a7965SKim Phillips 
7769c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
7775fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7785fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7799c4a7965SKim Phillips 
7809c4a7965SKim Phillips 	return sizeof(u32);
7819c4a7965SKim Phillips }
7829c4a7965SKim Phillips 
7839c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
7849c4a7965SKim Phillips {
7859c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7869c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7879c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
7889c4a7965SKim Phillips 
7895fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7905fa7fa14SLEROY Christophe 	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7915fa7fa14SLEROY Christophe 		 & TALITOS_RNGUSR_LO_RD)
7929c4a7965SKim Phillips 	       && --timeout)
7939c4a7965SKim Phillips 		cpu_relax();
7949c4a7965SKim Phillips 	if (timeout == 0) {
7959c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
7969c4a7965SKim Phillips 		return -ENODEV;
7979c4a7965SKim Phillips 	}
7989c4a7965SKim Phillips 
7999c4a7965SKim Phillips 	/* start generating */
8005fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
8019c4a7965SKim Phillips 
8029c4a7965SKim Phillips 	return 0;
8039c4a7965SKim Phillips }
8049c4a7965SKim Phillips 
8059c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
8069c4a7965SKim Phillips {
8079c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
80835a3bb3dSAaron Sierra 	int err;
8099c4a7965SKim Phillips 
81077450fd7SJulia Lawall 	priv->rng.name		= dev_driver_string(dev);
81177450fd7SJulia Lawall 	priv->rng.init		= talitos_rng_init;
81277450fd7SJulia Lawall 	priv->rng.data_present	= talitos_rng_data_present;
81377450fd7SJulia Lawall 	priv->rng.data_read	= talitos_rng_data_read;
8149c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
8159c4a7965SKim Phillips 
81635a3bb3dSAaron Sierra 	err = hwrng_register(&priv->rng);
81735a3bb3dSAaron Sierra 	if (!err)
81835a3bb3dSAaron Sierra 		priv->rng_registered = true;
81935a3bb3dSAaron Sierra 
82035a3bb3dSAaron Sierra 	return err;
8219c4a7965SKim Phillips }
8229c4a7965SKim Phillips 
8239c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
8249c4a7965SKim Phillips {
8259c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
8269c4a7965SKim Phillips 
82735a3bb3dSAaron Sierra 	if (!priv->rng_registered)
82835a3bb3dSAaron Sierra 		return;
82935a3bb3dSAaron Sierra 
8309c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
83135a3bb3dSAaron Sierra 	priv->rng_registered = false;
8329c4a7965SKim Phillips }
8339c4a7965SKim Phillips 
8349c4a7965SKim Phillips /*
8359c4a7965SKim Phillips  * crypto alg
8369c4a7965SKim Phillips  */
8379c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
8387405c8d7SLEROY Christophe /*
8397405c8d7SLEROY Christophe  * Defines a priority for doing AEAD with descriptors type
8407405c8d7SLEROY Christophe  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
8417405c8d7SLEROY Christophe  */
8427405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
843192125edSChristophe Leroy #ifdef CONFIG_CRYPTO_DEV_TALITOS2
84403d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
845b8fbdc2bSChristophe Leroy #else
846b8fbdc2bSChristophe Leroy #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE)
847b8fbdc2bSChristophe Leroy #endif
8483952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
84970bcaca7SLee Nipper 
8509c4a7965SKim Phillips struct talitos_ctx {
8519c4a7965SKim Phillips 	struct device *dev;
8525228f0f7SKim Phillips 	int ch;
8539c4a7965SKim Phillips 	__be32 desc_hdr_template;
8549c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
85570bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8562e13ce08SLEROY Christophe 	dma_addr_t dma_key;
8579c4a7965SKim Phillips 	unsigned int keylen;
8589c4a7965SKim Phillips 	unsigned int enckeylen;
8599c4a7965SKim Phillips 	unsigned int authkeylen;
8609c4a7965SKim Phillips };
8619c4a7965SKim Phillips 
862497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
863497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
864497f2e6bSLee Nipper 
865497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
86660f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
867497f2e6bSLee Nipper 	unsigned int hw_context_size;
8683c0dd190SLEROY Christophe 	u8 buf[2][HASH_MAX_BLOCK_SIZE];
8693c0dd190SLEROY Christophe 	int buf_idx;
87060f208d7SKim Phillips 	unsigned int swinit;
871497f2e6bSLee Nipper 	unsigned int first;
872497f2e6bSLee Nipper 	unsigned int last;
873497f2e6bSLee Nipper 	unsigned int to_hash_later;
87442e8b0d7SHoria Geant? 	unsigned int nbuf;
875497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
876497f2e6bSLee Nipper 	struct scatterlist *psrc;
877497f2e6bSLee Nipper };
878497f2e6bSLee Nipper 
8793639ca84SHoria Geant? struct talitos_export_state {
8803639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8813639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8823639ca84SHoria Geant? 	unsigned int swinit;
8833639ca84SHoria Geant? 	unsigned int first;
8843639ca84SHoria Geant? 	unsigned int last;
8853639ca84SHoria Geant? 	unsigned int to_hash_later;
8863639ca84SHoria Geant? 	unsigned int nbuf;
8873639ca84SHoria Geant? };
8883639ca84SHoria Geant? 
88956af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8909c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8919c4a7965SKim Phillips {
8929c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
8932e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
894c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8959c4a7965SKim Phillips 
896c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8979c4a7965SKim Phillips 		goto badkey;
8989c4a7965SKim Phillips 
899c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
9009c4a7965SKim Phillips 		goto badkey;
9019c4a7965SKim Phillips 
9022e13ce08SLEROY Christophe 	if (ctx->keylen)
9032e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
9042e13ce08SLEROY Christophe 
905c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
906c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
9079c4a7965SKim Phillips 
908c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
909c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
910c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
9112e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
9122e13ce08SLEROY Christophe 				      DMA_TO_DEVICE);
9139c4a7965SKim Phillips 
9148f0691fcSTudor-Dan Ambarus 	memzero_explicit(&keys, sizeof(keys));
9159c4a7965SKim Phillips 	return 0;
9169c4a7965SKim Phillips 
9179c4a7965SKim Phillips badkey:
9188f0691fcSTudor-Dan Ambarus 	memzero_explicit(&keys, sizeof(keys));
9199c4a7965SKim Phillips 	return -EINVAL;
9209c4a7965SKim Phillips }
9219c4a7965SKim Phillips 
922ef7c5c85SHerbert Xu static int aead_des3_setkey(struct crypto_aead *authenc,
923ef7c5c85SHerbert Xu 			    const u8 *key, unsigned int keylen)
924ef7c5c85SHerbert Xu {
925ef7c5c85SHerbert Xu 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
926ef7c5c85SHerbert Xu 	struct device *dev = ctx->dev;
927ef7c5c85SHerbert Xu 	struct crypto_authenc_keys keys;
928ef7c5c85SHerbert Xu 	int err;
929ef7c5c85SHerbert Xu 
930ef7c5c85SHerbert Xu 	err = crypto_authenc_extractkeys(&keys, key, keylen);
931ef7c5c85SHerbert Xu 	if (unlikely(err))
932674f368aSEric Biggers 		goto out;
933ef7c5c85SHerbert Xu 
934ef7c5c85SHerbert Xu 	err = -EINVAL;
935ef7c5c85SHerbert Xu 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
936674f368aSEric Biggers 		goto out;
937ef7c5c85SHerbert Xu 
9389d574ae8SArd Biesheuvel 	err = verify_aead_des3_key(authenc, keys.enckey, keys.enckeylen);
9399d574ae8SArd Biesheuvel 	if (err)
940ef7c5c85SHerbert Xu 		goto out;
941ef7c5c85SHerbert Xu 
942ef7c5c85SHerbert Xu 	if (ctx->keylen)
943ef7c5c85SHerbert Xu 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
944ef7c5c85SHerbert Xu 
945ef7c5c85SHerbert Xu 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
946ef7c5c85SHerbert Xu 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
947ef7c5c85SHerbert Xu 
948ef7c5c85SHerbert Xu 	ctx->keylen = keys.authkeylen + keys.enckeylen;
949ef7c5c85SHerbert Xu 	ctx->enckeylen = keys.enckeylen;
950ef7c5c85SHerbert Xu 	ctx->authkeylen = keys.authkeylen;
951ef7c5c85SHerbert Xu 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
952ef7c5c85SHerbert Xu 				      DMA_TO_DEVICE);
953ef7c5c85SHerbert Xu 
954ef7c5c85SHerbert Xu out:
955ef7c5c85SHerbert Xu 	memzero_explicit(&keys, sizeof(keys));
956ef7c5c85SHerbert Xu 	return err;
957ef7c5c85SHerbert Xu }
958ef7c5c85SHerbert Xu 
9594de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9604de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9614de9d0b5SLee Nipper 			     struct scatterlist *src,
9626a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
9636a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
964246a87cdSLEROY Christophe {
965246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
966246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9676a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
9686a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
969246a87cdSLEROY Christophe 
9706a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
9716a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
972246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
9736a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
9746a1e8d14SLEROY Christophe 				     offset);
975246a87cdSLEROY Christophe 	}
9766a1e8d14SLEROY Christophe 	if (src != dst) {
9776a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
9786a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
9796a1e8d14SLEROY Christophe 
9806a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
9816a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
9826a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
9836a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
984246a87cdSLEROY Christophe 	}
985246a87cdSLEROY Christophe }
986246a87cdSLEROY Christophe 
9879c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
98856af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
9897ede4c36SChristophe Leroy 			    struct aead_request *areq, bool encrypt)
9909c4a7965SKim Phillips {
991549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
992549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
993549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
9947ede4c36SChristophe Leroy 	unsigned int authsize = crypto_aead_authsize(aead);
9957ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
9969a655608SLEROY Christophe 	bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
9979a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
998549bd8bcSLEROY Christophe 
9999a655608SLEROY Christophe 	if (is_ipsec_esp)
1000549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
1001549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
10029a655608SLEROY Christophe 	unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
10039c4a7965SKim Phillips 
1004e345177dSChristophe Leroy 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst,
1005e345177dSChristophe Leroy 			 cryptlen + authsize, areq->assoclen);
10069c4a7965SKim Phillips 
10079c4a7965SKim Phillips 	if (edesc->dma_len)
10089c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
10099c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
1010549bd8bcSLEROY Christophe 
10119a655608SLEROY Christophe 	if (!is_ipsec_esp) {
1012549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
1013549bd8bcSLEROY Christophe 
1014549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
10157ede4c36SChristophe Leroy 				   areq->assoclen + cryptlen - ivsize);
1016549bd8bcSLEROY Christophe 	}
10179c4a7965SKim Phillips }
10189c4a7965SKim Phillips 
10199c4a7965SKim Phillips /*
10209c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
10219c4a7965SKim Phillips  */
10229c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
10239c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
10249c4a7965SKim Phillips 				   int err)
10259c4a7965SKim Phillips {
10269c4a7965SKim Phillips 	struct aead_request *areq = context;
10279c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
10282e13ce08SLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(authenc);
102919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10309c4a7965SKim Phillips 
103119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
103219bbbc63SKim Phillips 
10337ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, areq, true);
10349c4a7965SKim Phillips 
10352e13ce08SLEROY Christophe 	dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
10362e13ce08SLEROY Christophe 
10379c4a7965SKim Phillips 	kfree(edesc);
10389c4a7965SKim Phillips 
10399c4a7965SKim Phillips 	aead_request_complete(areq, err);
10409c4a7965SKim Phillips }
10419c4a7965SKim Phillips 
1042fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1043e938e465SKim Phillips 					  struct talitos_desc *desc,
1044e938e465SKim Phillips 					  void *context, int err)
10459c4a7965SKim Phillips {
10469c4a7965SKim Phillips 	struct aead_request *req = context;
10479c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1048aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
104919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
1050aeb4c132SHerbert Xu 	char *oicv, *icv;
10519c4a7965SKim Phillips 
105219bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
105319bbbc63SKim Phillips 
10547ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, req, false);
10559c4a7965SKim Phillips 
10569c4a7965SKim Phillips 	if (!err) {
10579c4a7965SKim Phillips 		/* auth check */
1058e345177dSChristophe Leroy 		oicv = edesc->buf + edesc->dma_len;
1059e345177dSChristophe Leroy 		icv = oicv - authsize;
1060aeb4c132SHerbert Xu 
106179960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10629c4a7965SKim Phillips 	}
10639c4a7965SKim Phillips 
10649c4a7965SKim Phillips 	kfree(edesc);
10659c4a7965SKim Phillips 
10669c4a7965SKim Phillips 	aead_request_complete(req, err);
10679c4a7965SKim Phillips }
10689c4a7965SKim Phillips 
1069fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1070e938e465SKim Phillips 					  struct talitos_desc *desc,
1071e938e465SKim Phillips 					  void *context, int err)
1072fe5720e2SKim Phillips {
1073fe5720e2SKim Phillips 	struct aead_request *req = context;
107419bbbc63SKim Phillips 	struct talitos_edesc *edesc;
107519bbbc63SKim Phillips 
107619bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1077fe5720e2SKim Phillips 
10787ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, req, false);
1079fe5720e2SKim Phillips 
1080fe5720e2SKim Phillips 	/* check ICV auth status */
1081e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1082e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1083fe5720e2SKim Phillips 		err = -EBADMSG;
1084fe5720e2SKim Phillips 
1085fe5720e2SKim Phillips 	kfree(edesc);
1086fe5720e2SKim Phillips 
1087fe5720e2SKim Phillips 	aead_request_complete(req, err);
1088fe5720e2SKim Phillips }
1089fe5720e2SKim Phillips 
10909c4a7965SKim Phillips /*
10919c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
10929c4a7965SKim Phillips  * stop at cryptlen bytes
10939c4a7965SKim Phillips  */
1094aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1095e345177dSChristophe Leroy 				 unsigned int offset, int datalen, int elen,
1096416b8467SChristophe Leroy 				 struct talitos_ptr *link_tbl_ptr, int align)
10979c4a7965SKim Phillips {
1098e345177dSChristophe Leroy 	int n_sg = elen ? sg_count + 1 : sg_count;
1099aeb4c132SHerbert Xu 	int count = 0;
1100e345177dSChristophe Leroy 	int cryptlen = datalen + elen;
1101416b8467SChristophe Leroy 	int padding = ALIGN(cryptlen, align) - cryptlen;
110270bcaca7SLee Nipper 
1103aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1104aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1105aeb4c132SHerbert Xu 
1106aeb4c132SHerbert Xu 		if (offset >= len) {
1107aeb4c132SHerbert Xu 			offset -= len;
1108aeb4c132SHerbert Xu 			goto next;
1109aeb4c132SHerbert Xu 		}
1110aeb4c132SHerbert Xu 
1111aeb4c132SHerbert Xu 		len -= offset;
1112aeb4c132SHerbert Xu 
1113aeb4c132SHerbert Xu 		if (len > cryptlen)
1114aeb4c132SHerbert Xu 			len = cryptlen;
1115aeb4c132SHerbert Xu 
1116e345177dSChristophe Leroy 		if (datalen > 0 && len > datalen) {
1117e345177dSChristophe Leroy 			to_talitos_ptr(link_tbl_ptr + count,
1118e345177dSChristophe Leroy 				       sg_dma_address(sg) + offset, datalen, 0);
1119e345177dSChristophe Leroy 			to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1120e345177dSChristophe Leroy 			count++;
1121e345177dSChristophe Leroy 			len -= datalen;
1122e345177dSChristophe Leroy 			offset += datalen;
1123e345177dSChristophe Leroy 		}
1124aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1125416b8467SChristophe Leroy 			       sg_dma_address(sg) + offset, sg_next(sg) ? len : len + padding, 0);
1126b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1127aeb4c132SHerbert Xu 		count++;
1128aeb4c132SHerbert Xu 		cryptlen -= len;
1129e345177dSChristophe Leroy 		datalen -= len;
1130aeb4c132SHerbert Xu 		offset = 0;
1131aeb4c132SHerbert Xu 
1132aeb4c132SHerbert Xu next:
11335be4d4c9SCristian Stoica 		sg = sg_next(sg);
11349c4a7965SKim Phillips 	}
11359c4a7965SKim Phillips 
11369c4a7965SKim Phillips 	/* tag end of link table */
1137aeb4c132SHerbert Xu 	if (count > 0)
1138b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1139e345177dSChristophe Leroy 				       DESC_PTR_LNKTBL_RET, 0);
114070bcaca7SLee Nipper 
1141aeb4c132SHerbert Xu 	return count;
1142aeb4c132SHerbert Xu }
1143aeb4c132SHerbert Xu 
11442b122730SLEROY Christophe static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
1145246a87cdSLEROY Christophe 			      unsigned int len, struct talitos_edesc *edesc,
11462b122730SLEROY Christophe 			      struct talitos_ptr *ptr, int sg_count,
1147e345177dSChristophe Leroy 			      unsigned int offset, int tbl_off, int elen,
1148416b8467SChristophe Leroy 			      bool force, int align)
1149246a87cdSLEROY Christophe {
1150246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1151246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1152416b8467SChristophe Leroy 	int aligned_len = ALIGN(len, align);
1153246a87cdSLEROY Christophe 
115487a81dceSLEROY Christophe 	if (!src) {
115587a81dceSLEROY Christophe 		to_talitos_ptr(ptr, 0, 0, is_sec1);
115687a81dceSLEROY Christophe 		return 1;
115787a81dceSLEROY Christophe 	}
11582b122730SLEROY Christophe 	to_talitos_ptr_ext_set(ptr, elen, is_sec1);
1159e345177dSChristophe Leroy 	if (sg_count == 1 && !force) {
1160416b8467SChristophe Leroy 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, aligned_len, is_sec1);
1161246a87cdSLEROY Christophe 		return sg_count;
1162246a87cdSLEROY Christophe 	}
1163246a87cdSLEROY Christophe 	if (is_sec1) {
1164416b8467SChristophe Leroy 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, aligned_len, is_sec1);
11656a1e8d14SLEROY Christophe 		return sg_count;
1166246a87cdSLEROY Christophe 	}
1167e345177dSChristophe Leroy 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen,
1168416b8467SChristophe Leroy 					 &edesc->link_tbl[tbl_off], align);
1169e345177dSChristophe Leroy 	if (sg_count == 1 && !force) {
11706a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
11716a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
11726a1e8d14SLEROY Christophe 		return sg_count;
11736a1e8d14SLEROY Christophe 	}
1174246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
1175416b8467SChristophe Leroy 			    tbl_off * sizeof(struct talitos_ptr), aligned_len, is_sec1);
11766a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
11776a1e8d14SLEROY Christophe 
11786a1e8d14SLEROY Christophe 	return sg_count;
1179246a87cdSLEROY Christophe }
1180246a87cdSLEROY Christophe 
11812b122730SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src,
11822b122730SLEROY Christophe 			  unsigned int len, struct talitos_edesc *edesc,
11832b122730SLEROY Christophe 			  struct talitos_ptr *ptr, int sg_count,
11842b122730SLEROY Christophe 			  unsigned int offset, int tbl_off)
11852b122730SLEROY Christophe {
11862b122730SLEROY Christophe 	return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset,
1187416b8467SChristophe Leroy 				  tbl_off, 0, false, 1);
11882b122730SLEROY Christophe }
11892b122730SLEROY Christophe 
11909c4a7965SKim Phillips /*
11919c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
11929c4a7965SKim Phillips  */
119356af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
11947ede4c36SChristophe Leroy 		     bool encrypt,
1195aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
11969c4a7965SKim Phillips 				      struct talitos_desc *desc,
11979c4a7965SKim Phillips 				      void *context, int error))
11989c4a7965SKim Phillips {
11999c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1200aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
12019c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
12029c4a7965SKim Phillips 	struct device *dev = ctx->dev;
12039c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
12047ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
1205e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1206aeb4c132SHerbert Xu 	int tbl_off = 0;
1207fa86a267SKim Phillips 	int sg_count, ret;
12082b122730SLEROY Christophe 	int elen = 0;
1209549bd8bcSLEROY Christophe 	bool sync_needed = false;
1210549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1211549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
12129a655608SLEROY Christophe 	bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
12139a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
12149a655608SLEROY Christophe 	struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
1215e345177dSChristophe Leroy 	dma_addr_t dma_icv = edesc->dma_link_tbl + edesc->dma_len - authsize;
12169c4a7965SKim Phillips 
12179c4a7965SKim Phillips 	/* hmac key */
12182e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1);
121979fd31d3SHoria Geanta 
1220549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1221549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1222549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1223549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1224549bd8bcSLEROY Christophe 	else
1225549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1226549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1227549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1228549bd8bcSLEROY Christophe 
12299c4a7965SKim Phillips 	/* hmac data */
1230549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1231549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
123279fd31d3SHoria Geanta 
1233549bd8bcSLEROY Christophe 	if (ret > 1) {
1234340ff60aSHoria Geant? 		tbl_off += ret;
1235549bd8bcSLEROY Christophe 		sync_needed = true;
123679fd31d3SHoria Geanta 	}
123779fd31d3SHoria Geanta 
12389c4a7965SKim Phillips 	/* cipher iv */
12399a655608SLEROY Christophe 	to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1);
12409c4a7965SKim Phillips 
12419c4a7965SKim Phillips 	/* cipher key */
12422e13ce08SLEROY Christophe 	to_talitos_ptr(ckey_ptr, ctx->dma_key  + ctx->authkeylen,
12432e13ce08SLEROY Christophe 		       ctx->enckeylen, is_sec1);
12449c4a7965SKim Phillips 
12459c4a7965SKim Phillips 	/*
12469c4a7965SKim Phillips 	 * cipher in
12479c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
12489c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
12499c4a7965SKim Phillips 	 * typically 12 for ipsec
12509c4a7965SKim Phillips 	 */
12512b122730SLEROY Christophe 	if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV))
12522b122730SLEROY Christophe 		elen = authsize;
1253549bd8bcSLEROY Christophe 
12542b122730SLEROY Christophe 	ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4],
1255e345177dSChristophe Leroy 				 sg_count, areq->assoclen, tbl_off, elen,
1256416b8467SChristophe Leroy 				 false, 1);
1257549bd8bcSLEROY Christophe 
1258ec8c7d14SLEROY Christophe 	if (ret > 1) {
1259ec8c7d14SLEROY Christophe 		tbl_off += ret;
1260549bd8bcSLEROY Christophe 		sync_needed = true;
1261340ff60aSHoria Geant? 	}
12629c4a7965SKim Phillips 
12639c4a7965SKim Phillips 	/* cipher out */
1264549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1265549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1266549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1267549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1268549bd8bcSLEROY Christophe 	}
12699c4a7965SKim Phillips 
1270e345177dSChristophe Leroy 	if (is_ipsec_esp && encrypt)
1271e345177dSChristophe Leroy 		elen = authsize;
1272e345177dSChristophe Leroy 	else
1273e345177dSChristophe Leroy 		elen = 0;
1274e345177dSChristophe Leroy 	ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
1275e345177dSChristophe Leroy 				 sg_count, areq->assoclen, tbl_off, elen,
1276416b8467SChristophe Leroy 				 is_ipsec_esp && !encrypt, 1);
1277e04a61beSLEROY Christophe 	tbl_off += ret;
1278549bd8bcSLEROY Christophe 
1279e345177dSChristophe Leroy 	if (!encrypt && is_ipsec_esp) {
128079fd31d3SHoria Geanta 		struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1281fe5720e2SKim Phillips 
1282f3c85bc1SLee Nipper 		/* Add an entry to the link table for ICV data */
1283e04a61beSLEROY Christophe 		to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
1284e345177dSChristophe Leroy 		to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RET, is_sec1);
12859c4a7965SKim Phillips 
12869c4a7965SKim Phillips 		/* icv data follows link tables */
1287e345177dSChristophe Leroy 		to_talitos_ptr(tbl_ptr, dma_icv, authsize, is_sec1);
1288e345177dSChristophe Leroy 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1289e04a61beSLEROY Christophe 		sync_needed = true;
1290e345177dSChristophe Leroy 	} else if (!encrypt) {
1291e345177dSChristophe Leroy 		to_talitos_ptr(&desc->ptr[6], dma_icv, authsize, is_sec1);
1292e345177dSChristophe Leroy 		sync_needed = true;
1293e345177dSChristophe Leroy 	} else if (!is_ipsec_esp) {
1294e345177dSChristophe Leroy 		talitos_sg_map(dev, areq->dst, authsize, edesc, &desc->ptr[6],
1295e345177dSChristophe Leroy 			       sg_count, areq->assoclen + cryptlen, tbl_off);
1296340ff60aSHoria Geant? 	}
12979c4a7965SKim Phillips 
12989c4a7965SKim Phillips 	/* iv out */
12999a655608SLEROY Christophe 	if (is_ipsec_esp)
1300a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
13019c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
13029c4a7965SKim Phillips 
1303549bd8bcSLEROY Christophe 	if (sync_needed)
1304549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1305549bd8bcSLEROY Christophe 					   edesc->dma_len,
1306549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1307549bd8bcSLEROY Christophe 
13085228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1309fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
13107ede4c36SChristophe Leroy 		ipsec_esp_unmap(dev, edesc, areq, encrypt);
1311fa86a267SKim Phillips 		kfree(edesc);
1312fa86a267SKim Phillips 	}
1313fa86a267SKim Phillips 	return ret;
13149c4a7965SKim Phillips }
13159c4a7965SKim Phillips 
13169c4a7965SKim Phillips /*
131756af8cd4SLee Nipper  * allocate and map the extended descriptor
13189c4a7965SKim Phillips  */
13194de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13204de9d0b5SLee Nipper 						 struct scatterlist *src,
13214de9d0b5SLee Nipper 						 struct scatterlist *dst,
132279fd31d3SHoria Geanta 						 u8 *iv,
132379fd31d3SHoria Geanta 						 unsigned int assoclen,
13244de9d0b5SLee Nipper 						 unsigned int cryptlen,
13254de9d0b5SLee Nipper 						 unsigned int authsize,
132679fd31d3SHoria Geanta 						 unsigned int ivsize,
13274de9d0b5SLee Nipper 						 int icv_stashing,
132862293a37SHoria Geanta 						 u32 cryptoflags,
132962293a37SHoria Geanta 						 bool encrypt)
13309c4a7965SKim Phillips {
133156af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13326a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
133379fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
13344de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1335586725f8SKim Phillips 		      GFP_ATOMIC;
13366f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
13376f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
13386f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
13399c4a7965SKim Phillips 
13406f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
13414de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
13429c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
13439c4a7965SKim Phillips 	}
13449c4a7965SKim Phillips 
134562293a37SHoria Geanta 	if (!dst || dst == src) {
13466a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
13476a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13488e409fe1SLABBE Corentin 		if (src_nents < 0) {
13498e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
1350c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
13518e409fe1SLABBE Corentin 		}
13529c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
135362293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
13546a1e8d14SLEROY Christophe 		dst_len = 0;
135562293a37SHoria Geanta 	} else { /* dst && dst != src*/
13566a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
13576a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13588e409fe1SLABBE Corentin 		if (src_nents < 0) {
13598e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
1360c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
13618e409fe1SLABBE Corentin 		}
136262293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
13636a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
13646a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
13658e409fe1SLABBE Corentin 		if (dst_nents < 0) {
13668e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
1367c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
13688e409fe1SLABBE Corentin 		}
1369695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
13709c4a7965SKim Phillips 	}
13719c4a7965SKim Phillips 
13729c4a7965SKim Phillips 	/*
13739c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1374aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1375aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
13769c4a7965SKim Phillips 	 */
137756af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1378e345177dSChristophe Leroy 	if (src_nents || dst_nents || !encrypt) {
13796f65f6acSLEROY Christophe 		if (is_sec1)
13806a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
1381e345177dSChristophe Leroy 				  (dst_nents ? dst_len : 0) + authsize;
13826f65f6acSLEROY Christophe 		else
1383aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1384e345177dSChristophe Leroy 				  sizeof(struct talitos_ptr) + authsize;
13859c4a7965SKim Phillips 		alloc_len += dma_len;
13869c4a7965SKim Phillips 	} else {
13879c4a7965SKim Phillips 		dma_len = 0;
13889c4a7965SKim Phillips 	}
1389e345177dSChristophe Leroy 	alloc_len += icv_stashing ? authsize : 0;
13909c4a7965SKim Phillips 
139137b5e889SLEROY Christophe 	/* if its a ahash, add space for a second desc next to the first one */
139237b5e889SLEROY Christophe 	if (is_sec1 && !dst)
139337b5e889SLEROY Christophe 		alloc_len += sizeof(struct talitos_desc);
13941bea445bSChristophe Leroy 	alloc_len += ivsize;
139537b5e889SLEROY Christophe 
1396586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
1397c56c2e17SChristophe Leroy 	if (!edesc)
1398c56c2e17SChristophe Leroy 		return ERR_PTR(-ENOMEM);
13991bea445bSChristophe Leroy 	if (ivsize) {
14001bea445bSChristophe Leroy 		iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
1401c56c2e17SChristophe Leroy 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
14021bea445bSChristophe Leroy 	}
1403e4a647c4SLEROY Christophe 	memset(&edesc->desc, 0, sizeof(edesc->desc));
14049c4a7965SKim Phillips 
14059c4a7965SKim Phillips 	edesc->src_nents = src_nents;
14069c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
140779fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
14089c4a7965SKim Phillips 	edesc->dma_len = dma_len;
140958cdbc6dSChristophe Leroy 	if (dma_len)
141058cdbc6dSChristophe Leroy 		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1411497f2e6bSLee Nipper 						     edesc->dma_len,
1412497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
141358cdbc6dSChristophe Leroy 
14149c4a7965SKim Phillips 	return edesc;
14159c4a7965SKim Phillips }
14169c4a7965SKim Phillips 
141779fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
141862293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
14194de9d0b5SLee Nipper {
14204de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1421aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14224de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
142379fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
14247ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
14254de9d0b5SLee Nipper 
1426aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
14277ede4c36SChristophe Leroy 				   iv, areq->assoclen, cryptlen,
1428aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
142962293a37SHoria Geanta 				   areq->base.flags, encrypt);
14304de9d0b5SLee Nipper }
14314de9d0b5SLee Nipper 
143256af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
14339c4a7965SKim Phillips {
14349c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14359c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
143656af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14379c4a7965SKim Phillips 
14389c4a7965SKim Phillips 	/* allocate extended descriptor */
143962293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
14409c4a7965SKim Phillips 	if (IS_ERR(edesc))
14419c4a7965SKim Phillips 		return PTR_ERR(edesc);
14429c4a7965SKim Phillips 
14439c4a7965SKim Phillips 	/* set encrypt */
144470bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14459c4a7965SKim Phillips 
14467ede4c36SChristophe Leroy 	return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done);
14479c4a7965SKim Phillips }
14489c4a7965SKim Phillips 
144956af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
14509c4a7965SKim Phillips {
14519c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1452aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14539c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1454fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
145556af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14569c4a7965SKim Phillips 	void *icvdata;
14579c4a7965SKim Phillips 
14589c4a7965SKim Phillips 	/* allocate extended descriptor */
145962293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14609c4a7965SKim Phillips 	if (IS_ERR(edesc))
14619c4a7965SKim Phillips 		return PTR_ERR(edesc);
14629c4a7965SKim Phillips 
14634bbfb839SChristophe Leroy 	if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) &&
14644bbfb839SChristophe Leroy 	    (priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1465e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1466e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1467fe5720e2SKim Phillips 
1468fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1469e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1470e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1471fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1472fe5720e2SKim Phillips 
1473fe5720e2SKim Phillips 		/* reset integrity check result bits */
1474fe5720e2SKim Phillips 
14757ede4c36SChristophe Leroy 		return ipsec_esp(edesc, req, false,
14767ede4c36SChristophe Leroy 				 ipsec_esp_decrypt_hwauth_done);
1477e938e465SKim Phillips 	}
1478fe5720e2SKim Phillips 
1479fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1480fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1481fe5720e2SKim Phillips 
14829c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
1483e345177dSChristophe Leroy 	icvdata = edesc->buf + edesc->dma_len;
14849c4a7965SKim Phillips 
1485eae55a58SChristophe Leroy 	sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize,
1486eae55a58SChristophe Leroy 			   req->assoclen + req->cryptlen - authsize);
14879c4a7965SKim Phillips 
14887ede4c36SChristophe Leroy 	return ipsec_esp(edesc, req, false, ipsec_esp_decrypt_swauth_done);
14899c4a7965SKim Phillips }
14909c4a7965SKim Phillips 
1491373960d7SArd Biesheuvel static int skcipher_setkey(struct crypto_skcipher *cipher,
14924de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
14934de9d0b5SLee Nipper {
1494373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
14952e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
1496f384cdc4SLEROY Christophe 
14972e13ce08SLEROY Christophe 	if (ctx->keylen)
14982e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
14992e13ce08SLEROY Christophe 
15004de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
15014de9d0b5SLee Nipper 	ctx->keylen = keylen;
15024de9d0b5SLee Nipper 
15032e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE);
15042e13ce08SLEROY Christophe 
15054de9d0b5SLee Nipper 	return 0;
15064de9d0b5SLee Nipper }
15074de9d0b5SLee Nipper 
1508373960d7SArd Biesheuvel static int skcipher_des_setkey(struct crypto_skcipher *cipher,
1509ef7c5c85SHerbert Xu 				 const u8 *key, unsigned int keylen)
1510ef7c5c85SHerbert Xu {
1511373960d7SArd Biesheuvel 	return verify_skcipher_des_key(cipher, key) ?:
1512373960d7SArd Biesheuvel 	       skcipher_setkey(cipher, key, keylen);
1513ef7c5c85SHerbert Xu }
1514ef7c5c85SHerbert Xu 
1515373960d7SArd Biesheuvel static int skcipher_des3_setkey(struct crypto_skcipher *cipher,
1516ef7c5c85SHerbert Xu 				  const u8 *key, unsigned int keylen)
1517ef7c5c85SHerbert Xu {
1518373960d7SArd Biesheuvel 	return verify_skcipher_des3_key(cipher, key) ?:
1519373960d7SArd Biesheuvel 	       skcipher_setkey(cipher, key, keylen);
1520ef7c5c85SHerbert Xu }
1521ef7c5c85SHerbert Xu 
1522373960d7SArd Biesheuvel static int skcipher_aes_setkey(struct crypto_skcipher *cipher,
15231ba34e71SChristophe Leroy 				  const u8 *key, unsigned int keylen)
15241ba34e71SChristophe Leroy {
15251ba34e71SChristophe Leroy 	if (keylen == AES_KEYSIZE_128 || keylen == AES_KEYSIZE_192 ||
15261ba34e71SChristophe Leroy 	    keylen == AES_KEYSIZE_256)
1527373960d7SArd Biesheuvel 		return skcipher_setkey(cipher, key, keylen);
15281ba34e71SChristophe Leroy 
15291ba34e71SChristophe Leroy 	return -EINVAL;
15301ba34e71SChristophe Leroy }
15311ba34e71SChristophe Leroy 
15324de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
15334de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
1534373960d7SArd Biesheuvel 				  struct skcipher_request *areq)
15354de9d0b5SLee Nipper {
15364de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1537032d197eSLEROY Christophe 
1538373960d7SArd Biesheuvel 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, 0);
15394de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
15404de9d0b5SLee Nipper 
15414de9d0b5SLee Nipper 	if (edesc->dma_len)
15424de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
15434de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
15444de9d0b5SLee Nipper }
15454de9d0b5SLee Nipper 
1546373960d7SArd Biesheuvel static void skcipher_done(struct device *dev,
15474de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
15484de9d0b5SLee Nipper 			    int err)
15494de9d0b5SLee Nipper {
1550373960d7SArd Biesheuvel 	struct skcipher_request *areq = context;
1551373960d7SArd Biesheuvel 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
1552373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
1553373960d7SArd Biesheuvel 	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
155419bbbc63SKim Phillips 	struct talitos_edesc *edesc;
155519bbbc63SKim Phillips 
155619bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
15574de9d0b5SLee Nipper 
15584de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
1559373960d7SArd Biesheuvel 	memcpy(areq->iv, ctx->iv, ivsize);
15604de9d0b5SLee Nipper 
15614de9d0b5SLee Nipper 	kfree(edesc);
15624de9d0b5SLee Nipper 
15634de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
15644de9d0b5SLee Nipper }
15654de9d0b5SLee Nipper 
15664de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
1567373960d7SArd Biesheuvel 			   struct skcipher_request *areq,
15684de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
15694de9d0b5SLee Nipper 					     struct talitos_desc *desc,
15704de9d0b5SLee Nipper 					     void *context, int error))
15714de9d0b5SLee Nipper {
1572373960d7SArd Biesheuvel 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
1573373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
15744de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
15754de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1576373960d7SArd Biesheuvel 	unsigned int cryptlen = areq->cryptlen;
1577373960d7SArd Biesheuvel 	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
15784de9d0b5SLee Nipper 	int sg_count, ret;
15796a1e8d14SLEROY Christophe 	bool sync_needed = false;
1580922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1581922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1582416b8467SChristophe Leroy 	bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU &&
1583416b8467SChristophe Leroy 		      (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR;
15844de9d0b5SLee Nipper 
15854de9d0b5SLee Nipper 	/* first DWORD empty */
15864de9d0b5SLee Nipper 
15874de9d0b5SLee Nipper 	/* cipher iv */
1588da9de146SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1);
15894de9d0b5SLee Nipper 
15904de9d0b5SLee Nipper 	/* cipher key */
15912e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1);
15924de9d0b5SLee Nipper 
15936a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
15946a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
15956a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
15966a1e8d14SLEROY Christophe 				  cryptlen);
15976a1e8d14SLEROY Christophe 	else
15986a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
15996a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
16006a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
16014de9d0b5SLee Nipper 	/*
16024de9d0b5SLee Nipper 	 * cipher in
16034de9d0b5SLee Nipper 	 */
1604416b8467SChristophe Leroy 	sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3],
1605416b8467SChristophe Leroy 				      sg_count, 0, 0, 0, false, is_ctr ? 16 : 1);
16066a1e8d14SLEROY Christophe 	if (sg_count > 1)
16076a1e8d14SLEROY Christophe 		sync_needed = true;
16084de9d0b5SLee Nipper 
16094de9d0b5SLee Nipper 	/* cipher out */
16106a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
16116a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
16126a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
16136a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
16146a1e8d14SLEROY Christophe 	}
16156a1e8d14SLEROY Christophe 
16166a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
16176a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
16186a1e8d14SLEROY Christophe 	if (ret > 1)
16196a1e8d14SLEROY Christophe 		sync_needed = true;
16204de9d0b5SLee Nipper 
16214de9d0b5SLee Nipper 	/* iv out */
1622a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
16234de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
16244de9d0b5SLee Nipper 
16254de9d0b5SLee Nipper 	/* last DWORD empty */
16264de9d0b5SLee Nipper 
16276a1e8d14SLEROY Christophe 	if (sync_needed)
16286a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
16296a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
16306a1e8d14SLEROY Christophe 
16315228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
16324de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
16334de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
16344de9d0b5SLee Nipper 		kfree(edesc);
16354de9d0b5SLee Nipper 	}
16364de9d0b5SLee Nipper 	return ret;
16374de9d0b5SLee Nipper }
16384de9d0b5SLee Nipper 
1639373960d7SArd Biesheuvel static struct talitos_edesc *skcipher_edesc_alloc(struct skcipher_request *
164062293a37SHoria Geanta 						    areq, bool encrypt)
16414de9d0b5SLee Nipper {
1642373960d7SArd Biesheuvel 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
1643373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
1644373960d7SArd Biesheuvel 	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
16454de9d0b5SLee Nipper 
1646aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
1647373960d7SArd Biesheuvel 				   areq->iv, 0, areq->cryptlen, 0, ivsize, 0,
164862293a37SHoria Geanta 				   areq->base.flags, encrypt);
16494de9d0b5SLee Nipper }
16504de9d0b5SLee Nipper 
1651373960d7SArd Biesheuvel static int skcipher_encrypt(struct skcipher_request *areq)
16524de9d0b5SLee Nipper {
1653373960d7SArd Biesheuvel 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
1654373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
16554de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
1656ee483d32SChristophe Leroy 	unsigned int blocksize =
1657373960d7SArd Biesheuvel 			crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher));
1658ee483d32SChristophe Leroy 
1659373960d7SArd Biesheuvel 	if (!areq->cryptlen)
1660ee483d32SChristophe Leroy 		return 0;
1661ee483d32SChristophe Leroy 
1662373960d7SArd Biesheuvel 	if (areq->cryptlen % blocksize)
1663ee483d32SChristophe Leroy 		return -EINVAL;
16644de9d0b5SLee Nipper 
16654de9d0b5SLee Nipper 	/* allocate extended descriptor */
1666373960d7SArd Biesheuvel 	edesc = skcipher_edesc_alloc(areq, true);
16674de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16684de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16694de9d0b5SLee Nipper 
16704de9d0b5SLee Nipper 	/* set encrypt */
16714de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16724de9d0b5SLee Nipper 
1673373960d7SArd Biesheuvel 	return common_nonsnoop(edesc, areq, skcipher_done);
16744de9d0b5SLee Nipper }
16754de9d0b5SLee Nipper 
1676373960d7SArd Biesheuvel static int skcipher_decrypt(struct skcipher_request *areq)
16774de9d0b5SLee Nipper {
1678373960d7SArd Biesheuvel 	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
1679373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
16804de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
1681ee483d32SChristophe Leroy 	unsigned int blocksize =
1682373960d7SArd Biesheuvel 			crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher));
1683ee483d32SChristophe Leroy 
1684373960d7SArd Biesheuvel 	if (!areq->cryptlen)
1685ee483d32SChristophe Leroy 		return 0;
1686ee483d32SChristophe Leroy 
1687373960d7SArd Biesheuvel 	if (areq->cryptlen % blocksize)
1688ee483d32SChristophe Leroy 		return -EINVAL;
16894de9d0b5SLee Nipper 
16904de9d0b5SLee Nipper 	/* allocate extended descriptor */
1691373960d7SArd Biesheuvel 	edesc = skcipher_edesc_alloc(areq, false);
16924de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16934de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16944de9d0b5SLee Nipper 
16954de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
16964de9d0b5SLee Nipper 
1697373960d7SArd Biesheuvel 	return common_nonsnoop(edesc, areq, skcipher_done);
16984de9d0b5SLee Nipper }
16994de9d0b5SLee Nipper 
1700497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1701497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1702497f2e6bSLee Nipper 				       struct ahash_request *areq)
1703497f2e6bSLee Nipper {
1704497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
17057a6eda5bSChristophe Leroy 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1706ad4cd51fSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1707ad4cd51fSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1708ad4cd51fSLEROY Christophe 	struct talitos_desc *desc = &edesc->desc;
170958cdbc6dSChristophe Leroy 	struct talitos_desc *desc2 = (struct talitos_desc *)
171058cdbc6dSChristophe Leroy 				     (edesc->buf + edesc->dma_len);
1711ad4cd51fSLEROY Christophe 
1712*6ae7a8b1Sjianchunfu 	unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE);
1713ad4cd51fSLEROY Christophe 	if (desc->next_desc &&
1714ad4cd51fSLEROY Christophe 	    desc->ptr[5].ptr != desc2->ptr[5].ptr)
1715ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
17167a6eda5bSChristophe Leroy 	if (req_ctx->last)
17177a6eda5bSChristophe Leroy 		memcpy(areq->result, req_ctx->hw_context,
17187a6eda5bSChristophe Leroy 		       crypto_ahash_digestsize(tfm));
1719497f2e6bSLee Nipper 
172058cdbc6dSChristophe Leroy 	if (req_ctx->psrc)
17216a1e8d14SLEROY Christophe 		talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1722032d197eSLEROY Christophe 
1723ad4cd51fSLEROY Christophe 	/* When using hashctx-in, must unmap it. */
1724*6ae7a8b1Sjianchunfu 	if (from_talitos_ptr_len(&desc->ptr[1], is_sec1))
1725*6ae7a8b1Sjianchunfu 		unmap_single_talitos_ptr(dev, &desc->ptr[1],
1726ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1727ad4cd51fSLEROY Christophe 	else if (desc->next_desc)
1728ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[1],
1729ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1730ad4cd51fSLEROY Christophe 
1731ad4cd51fSLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
1732ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc->ptr[3],
1733ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1734ad4cd51fSLEROY Christophe 
1735497f2e6bSLee Nipper 	if (edesc->dma_len)
1736497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1737497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1738497f2e6bSLee Nipper 
1739*6ae7a8b1Sjianchunfu 	if (desc->next_desc)
1740*6ae7a8b1Sjianchunfu 		dma_unmap_single(dev, be32_to_cpu(desc->next_desc),
174137b5e889SLEROY Christophe 				 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
1742497f2e6bSLee Nipper }
1743497f2e6bSLee Nipper 
1744497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1745497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1746497f2e6bSLee Nipper 		       int err)
1747497f2e6bSLee Nipper {
1748497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1749497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1750497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1751497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1752497f2e6bSLee Nipper 
1753497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1754497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
17553c0dd190SLEROY Christophe 		req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
17565e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1757497f2e6bSLee Nipper 	}
1758497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1759497f2e6bSLee Nipper 
1760497f2e6bSLee Nipper 	kfree(edesc);
1761497f2e6bSLee Nipper 
1762497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1763497f2e6bSLee Nipper }
1764497f2e6bSLee Nipper 
17652d02905eSLEROY Christophe /*
17662d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
17672d02905eSLEROY Christophe  * ourself and submit a padded block
17682d02905eSLEROY Christophe  */
17695b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
17702d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
17712d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
17722d02905eSLEROY Christophe {
17732d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
17742d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17752d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17762d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17772d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17782d02905eSLEROY Christophe 	};
17792d02905eSLEROY Christophe 
17802d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
17812d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
17822d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
17832d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
17842d02905eSLEROY Christophe }
17852d02905eSLEROY Christophe 
1786497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1787497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
1788497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1789497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1790497f2e6bSLee Nipper 						  void *context, int error))
1791497f2e6bSLee Nipper {
1792497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1793497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1794497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1795497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1796497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1797032d197eSLEROY Christophe 	int ret;
17986a1e8d14SLEROY Christophe 	bool sync_needed = false;
1799922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1800922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
18016a1e8d14SLEROY Christophe 	int sg_count;
1802497f2e6bSLee Nipper 
1803497f2e6bSLee Nipper 	/* first DWORD empty */
1804497f2e6bSLee Nipper 
180560f208d7SKim Phillips 	/* hash context in */
180660f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
18076a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
1808ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
18096a4967c3SLEROY Christophe 					      req_ctx->hw_context,
1810ad4cd51fSLEROY Christophe 					      DMA_TO_DEVICE);
181160f208d7SKim Phillips 		req_ctx->swinit = 0;
1812afd62fa2SLEROY Christophe 	}
1813497f2e6bSLee Nipper 	/* Indicate next op is not the first. */
1814497f2e6bSLee Nipper 	req_ctx->first = 0;
1815497f2e6bSLee Nipper 
1816497f2e6bSLee Nipper 	/* HMAC key */
1817497f2e6bSLee Nipper 	if (ctx->keylen)
18182e13ce08SLEROY Christophe 		to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
18192e13ce08SLEROY Christophe 			       is_sec1);
1820497f2e6bSLee Nipper 
182137b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
182237b5e889SLEROY Christophe 		length -= req_ctx->nbuf;
182337b5e889SLEROY Christophe 
18246a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
18256a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
182658cdbc6dSChristophe Leroy 		sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
182737b5e889SLEROY Christophe 	else if (length)
18286a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
18296a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1830497f2e6bSLee Nipper 	/*
1831497f2e6bSLee Nipper 	 * data in
1832497f2e6bSLee Nipper 	 */
183337b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf) {
1834ad4cd51fSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
1835ad4cd51fSLEROY Christophe 				       req_ctx->buf[req_ctx->buf_idx],
1836ad4cd51fSLEROY Christophe 				       DMA_TO_DEVICE);
183737b5e889SLEROY Christophe 	} else {
18386a1e8d14SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
183958cdbc6dSChristophe Leroy 					  &desc->ptr[3], sg_count, 0, 0);
18406a1e8d14SLEROY Christophe 		if (sg_count > 1)
18416a1e8d14SLEROY Christophe 			sync_needed = true;
184237b5e889SLEROY Christophe 	}
1843497f2e6bSLee Nipper 
1844497f2e6bSLee Nipper 	/* fifth DWORD empty */
1845497f2e6bSLee Nipper 
1846497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1847497f2e6bSLee Nipper 	if (req_ctx->last)
1848497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1849497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
18507a6eda5bSChristophe Leroy 				       req_ctx->hw_context, DMA_FROM_DEVICE);
1851497f2e6bSLee Nipper 	else
18526a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1853ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
18546a4967c3SLEROY Christophe 					      req_ctx->hw_context,
18556a4967c3SLEROY Christophe 					      DMA_FROM_DEVICE);
1856497f2e6bSLee Nipper 
1857497f2e6bSLee Nipper 	/* last DWORD empty */
1858497f2e6bSLee Nipper 
18592d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
18602d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
18612d02905eSLEROY Christophe 
186237b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf && length) {
186358cdbc6dSChristophe Leroy 		struct talitos_desc *desc2 = (struct talitos_desc *)
186458cdbc6dSChristophe Leroy 					     (edesc->buf + edesc->dma_len);
186537b5e889SLEROY Christophe 		dma_addr_t next_desc;
186637b5e889SLEROY Christophe 
186737b5e889SLEROY Christophe 		memset(desc2, 0, sizeof(*desc2));
186837b5e889SLEROY Christophe 		desc2->hdr = desc->hdr;
186937b5e889SLEROY Christophe 		desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
187037b5e889SLEROY Christophe 		desc2->hdr1 = desc2->hdr;
187137b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
187237b5e889SLEROY Christophe 		desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
187337b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
187437b5e889SLEROY Christophe 
1875ad4cd51fSLEROY Christophe 		if (desc->ptr[1].ptr)
1876ad4cd51fSLEROY Christophe 			copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
1877ad4cd51fSLEROY Christophe 					 is_sec1);
1878ad4cd51fSLEROY Christophe 		else
18796a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc2->ptr[1],
1880ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1881ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1882ad4cd51fSLEROY Christophe 						      DMA_TO_DEVICE);
188337b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
188437b5e889SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
188558cdbc6dSChristophe Leroy 					  &desc2->ptr[3], sg_count, 0, 0);
188637b5e889SLEROY Christophe 		if (sg_count > 1)
188737b5e889SLEROY Christophe 			sync_needed = true;
188837b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
188937b5e889SLEROY Christophe 		if (req_ctx->last)
18906a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1891ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1892ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1893ad4cd51fSLEROY Christophe 						      DMA_FROM_DEVICE);
189437b5e889SLEROY Christophe 
189537b5e889SLEROY Christophe 		next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE,
189637b5e889SLEROY Christophe 					   DMA_BIDIRECTIONAL);
189737b5e889SLEROY Christophe 		desc->next_desc = cpu_to_be32(next_desc);
189837b5e889SLEROY Christophe 	}
189937b5e889SLEROY Christophe 
19006a1e8d14SLEROY Christophe 	if (sync_needed)
19016a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
19026a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
19036a1e8d14SLEROY Christophe 
19045228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1905497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1906497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1907497f2e6bSLee Nipper 		kfree(edesc);
1908497f2e6bSLee Nipper 	}
1909497f2e6bSLee Nipper 	return ret;
1910497f2e6bSLee Nipper }
1911497f2e6bSLee Nipper 
1912497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1913497f2e6bSLee Nipper 					       unsigned int nbytes)
1914497f2e6bSLee Nipper {
1915497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1916497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1917497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
191837b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
191937b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
192037b5e889SLEROY Christophe 
192137b5e889SLEROY Christophe 	if (is_sec1)
192237b5e889SLEROY Christophe 		nbytes -= req_ctx->nbuf;
1923497f2e6bSLee Nipper 
1924aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
192562293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1926497f2e6bSLee Nipper }
1927497f2e6bSLee Nipper 
1928497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1929497f2e6bSLee Nipper {
1930497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
19316a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
19326a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
1933497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
193449f9783bSLEROY Christophe 	unsigned int size;
19356a4967c3SLEROY Christophe 	dma_addr_t dma;
1936497f2e6bSLee Nipper 
1937497f2e6bSLee Nipper 	/* Initialize the context */
19383c0dd190SLEROY Christophe 	req_ctx->buf_idx = 0;
19395e833bc4SLee Nipper 	req_ctx->nbuf = 0;
194060f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
194160f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
194249f9783bSLEROY Christophe 	size =	(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1943497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1944497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
194549f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
1946497f2e6bSLee Nipper 
19476a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
19486a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
19496a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
19506a4967c3SLEROY Christophe 
1951497f2e6bSLee Nipper 	return 0;
1952497f2e6bSLee Nipper }
1953497f2e6bSLee Nipper 
195460f208d7SKim Phillips /*
195560f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
195660f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
195760f208d7SKim Phillips  */
195860f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
195960f208d7SKim Phillips {
196060f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
196160f208d7SKim Phillips 
1962a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1963a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1964a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1965a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1966a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1967a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1968a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1969a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
197060f208d7SKim Phillips 
197160f208d7SKim Phillips 	/* init 64-bit count */
197260f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
197360f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
197460f208d7SKim Phillips 
19756a4967c3SLEROY Christophe 	ahash_init(areq);
19766a4967c3SLEROY Christophe 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
19776a4967c3SLEROY Christophe 
197860f208d7SKim Phillips 	return 0;
197960f208d7SKim Phillips }
198060f208d7SKim Phillips 
1981497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1982497f2e6bSLee Nipper {
1983497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1984497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1985497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1986497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1987497f2e6bSLee Nipper 	unsigned int blocksize =
1988497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1989497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1990497f2e6bSLee Nipper 	unsigned int to_hash_later;
19915e833bc4SLee Nipper 	unsigned int nsg;
19928e409fe1SLABBE Corentin 	int nents;
199337b5e889SLEROY Christophe 	struct device *dev = ctx->dev;
199437b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
199537b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
19963c0dd190SLEROY Christophe 	u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
1997497f2e6bSLee Nipper 
19985e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
19995e833bc4SLee Nipper 		/* Buffer up to one whole block */
20008e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
20018e409fe1SLABBE Corentin 		if (nents < 0) {
20028e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
20038e409fe1SLABBE Corentin 			return nents;
20048e409fe1SLABBE Corentin 		}
20058e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
20063c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, nbytes);
20075e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
2008497f2e6bSLee Nipper 		return 0;
2009497f2e6bSLee Nipper 	}
2010497f2e6bSLee Nipper 
20115e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
20125e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
20135e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
20145e833bc4SLee Nipper 
20155e833bc4SLee Nipper 	if (req_ctx->last)
20165e833bc4SLee Nipper 		to_hash_later = 0;
20175e833bc4SLee Nipper 	else if (to_hash_later)
20185e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
20195e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
20205e833bc4SLee Nipper 	else {
20215e833bc4SLee Nipper 		/* Keep one block buffered */
20225e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
20235e833bc4SLee Nipper 		to_hash_later = blocksize;
2024497f2e6bSLee Nipper 	}
20255e833bc4SLee Nipper 
20265e833bc4SLee Nipper 	/* Chain in any previously buffered data */
202737b5e889SLEROY Christophe 	if (!is_sec1 && req_ctx->nbuf) {
20285e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
20295e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
20303c0dd190SLEROY Christophe 		sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
20315e833bc4SLee Nipper 		if (nsg > 1)
2032c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
20335e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
203437b5e889SLEROY Christophe 	} else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
203558cdbc6dSChristophe Leroy 		int offset;
203658cdbc6dSChristophe Leroy 
203737b5e889SLEROY Christophe 		if (nbytes_to_hash > blocksize)
203837b5e889SLEROY Christophe 			offset = blocksize - req_ctx->nbuf;
203937b5e889SLEROY Christophe 		else
204037b5e889SLEROY Christophe 			offset = nbytes_to_hash - req_ctx->nbuf;
204137b5e889SLEROY Christophe 		nents = sg_nents_for_len(areq->src, offset);
204237b5e889SLEROY Christophe 		if (nents < 0) {
204337b5e889SLEROY Christophe 			dev_err(ctx->dev, "Invalid number of src SG.\n");
204437b5e889SLEROY Christophe 			return nents;
204537b5e889SLEROY Christophe 		}
204637b5e889SLEROY Christophe 		sg_copy_to_buffer(areq->src, nents,
20473c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, offset);
204837b5e889SLEROY Christophe 		req_ctx->nbuf += offset;
204958cdbc6dSChristophe Leroy 		req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, areq->src,
205058cdbc6dSChristophe Leroy 						 offset);
20515e833bc4SLee Nipper 	} else
20525e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
20535e833bc4SLee Nipper 
2054497f2e6bSLee Nipper 	if (to_hash_later) {
20558e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
20568e409fe1SLABBE Corentin 		if (nents < 0) {
20578e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
20588e409fe1SLABBE Corentin 			return nents;
20598e409fe1SLABBE Corentin 		}
2060d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
20613c0dd190SLEROY Christophe 				   req_ctx->buf[(req_ctx->buf_idx + 1) & 1],
2062497f2e6bSLee Nipper 				      to_hash_later,
2063497f2e6bSLee Nipper 				      nbytes - to_hash_later);
2064497f2e6bSLee Nipper 	}
2065497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
2066497f2e6bSLee Nipper 
20675e833bc4SLee Nipper 	/* Allocate extended descriptor */
2068497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
2069497f2e6bSLee Nipper 	if (IS_ERR(edesc))
2070497f2e6bSLee Nipper 		return PTR_ERR(edesc);
2071497f2e6bSLee Nipper 
2072497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
2073497f2e6bSLee Nipper 
2074497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
2075497f2e6bSLee Nipper 	if (req_ctx->last)
2076497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
2077497f2e6bSLee Nipper 	else
2078497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
2079497f2e6bSLee Nipper 
208060f208d7SKim Phillips 	/* request SEC to INIT hash. */
208160f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
2082497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
2083497f2e6bSLee Nipper 
2084497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
2085497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
2086497f2e6bSLee Nipper 	 */
2087497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
2088497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
2089497f2e6bSLee Nipper 
209058cdbc6dSChristophe Leroy 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, ahash_done);
2091497f2e6bSLee Nipper }
2092497f2e6bSLee Nipper 
2093497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
2094497f2e6bSLee Nipper {
2095497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2096497f2e6bSLee Nipper 
2097497f2e6bSLee Nipper 	req_ctx->last = 0;
2098497f2e6bSLee Nipper 
2099497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2100497f2e6bSLee Nipper }
2101497f2e6bSLee Nipper 
2102497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
2103497f2e6bSLee Nipper {
2104497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2105497f2e6bSLee Nipper 
2106497f2e6bSLee Nipper 	req_ctx->last = 1;
2107497f2e6bSLee Nipper 
2108497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
2109497f2e6bSLee Nipper }
2110497f2e6bSLee Nipper 
2111497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
2112497f2e6bSLee Nipper {
2113497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2114497f2e6bSLee Nipper 
2115497f2e6bSLee Nipper 	req_ctx->last = 1;
2116497f2e6bSLee Nipper 
2117497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2118497f2e6bSLee Nipper }
2119497f2e6bSLee Nipper 
2120497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
2121497f2e6bSLee Nipper {
2122497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
212360f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2124497f2e6bSLee Nipper 
212560f208d7SKim Phillips 	ahash->init(areq);
2126497f2e6bSLee Nipper 	req_ctx->last = 1;
2127497f2e6bSLee Nipper 
2128497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2129497f2e6bSLee Nipper }
2130497f2e6bSLee Nipper 
21313639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
21323639ca84SHoria Geant? {
21333639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21343639ca84SHoria Geant? 	struct talitos_export_state *export = out;
21356a4967c3SLEROY Christophe 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
21366a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
21376a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
21386a4967c3SLEROY Christophe 	dma_addr_t dma;
21396a4967c3SLEROY Christophe 
21406a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
21416a4967c3SLEROY Christophe 			     DMA_FROM_DEVICE);
21426a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE);
21433639ca84SHoria Geant? 
21443639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
21453639ca84SHoria Geant? 	       req_ctx->hw_context_size);
21463c0dd190SLEROY Christophe 	memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf);
21473639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
21483639ca84SHoria Geant? 	export->first = req_ctx->first;
21493639ca84SHoria Geant? 	export->last = req_ctx->last;
21503639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
21513639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
21523639ca84SHoria Geant? 
21533639ca84SHoria Geant? 	return 0;
21543639ca84SHoria Geant? }
21553639ca84SHoria Geant? 
21563639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
21573639ca84SHoria Geant? {
21583639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21593639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
21606a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
21616a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
21623639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
216349f9783bSLEROY Christophe 	unsigned int size;
21646a4967c3SLEROY Christophe 	dma_addr_t dma;
21653639ca84SHoria Geant? 
21663639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
216749f9783bSLEROY Christophe 	size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
21683639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
21693639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
217049f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
217149f9783bSLEROY Christophe 	memcpy(req_ctx->hw_context, export->hw_context, size);
21723c0dd190SLEROY Christophe 	memcpy(req_ctx->buf[0], export->buf, export->nbuf);
21733639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
21743639ca84SHoria Geant? 	req_ctx->first = export->first;
21753639ca84SHoria Geant? 	req_ctx->last = export->last;
21763639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
21773639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
21783639ca84SHoria Geant? 
21796a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
21806a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
21816a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
21826a4967c3SLEROY Christophe 
21833639ca84SHoria Geant? 	return 0;
21843639ca84SHoria Geant? }
21853639ca84SHoria Geant? 
218679b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
218779b3a418SLee Nipper 		   u8 *hash)
218879b3a418SLee Nipper {
218979b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
219079b3a418SLee Nipper 
219179b3a418SLee Nipper 	struct scatterlist sg[1];
219279b3a418SLee Nipper 	struct ahash_request *req;
2193f1c90ac3SGilad Ben-Yossef 	struct crypto_wait wait;
219479b3a418SLee Nipper 	int ret;
219579b3a418SLee Nipper 
2196f1c90ac3SGilad Ben-Yossef 	crypto_init_wait(&wait);
219779b3a418SLee Nipper 
219879b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
219979b3a418SLee Nipper 	if (!req)
220079b3a418SLee Nipper 		return -ENOMEM;
220179b3a418SLee Nipper 
220279b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
220379b3a418SLee Nipper 	ctx->keylen = 0;
220479b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
2205f1c90ac3SGilad Ben-Yossef 				   crypto_req_done, &wait);
220679b3a418SLee Nipper 
220779b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
220879b3a418SLee Nipper 
220979b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
2210f1c90ac3SGilad Ben-Yossef 	ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
2211f1c90ac3SGilad Ben-Yossef 
221279b3a418SLee Nipper 	ahash_request_free(req);
221379b3a418SLee Nipper 
221479b3a418SLee Nipper 	return ret;
221579b3a418SLee Nipper }
221679b3a418SLee Nipper 
221779b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
221879b3a418SLee Nipper 			unsigned int keylen)
221979b3a418SLee Nipper {
222079b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
22212e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
222279b3a418SLee Nipper 	unsigned int blocksize =
222379b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
222479b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
222579b3a418SLee Nipper 	unsigned int keysize = keylen;
222679b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
222779b3a418SLee Nipper 	int ret;
222879b3a418SLee Nipper 
222979b3a418SLee Nipper 	if (keylen <= blocksize)
223079b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
223179b3a418SLee Nipper 	else {
223279b3a418SLee Nipper 		/* Must get the hash of the long key */
223379b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
223479b3a418SLee Nipper 
2235674f368aSEric Biggers 		if (ret)
223679b3a418SLee Nipper 			return -EINVAL;
223779b3a418SLee Nipper 
223879b3a418SLee Nipper 		keysize = digestsize;
223979b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
224079b3a418SLee Nipper 	}
224179b3a418SLee Nipper 
22422e13ce08SLEROY Christophe 	if (ctx->keylen)
22432e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
22442e13ce08SLEROY Christophe 
224579b3a418SLee Nipper 	ctx->keylen = keysize;
22462e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE);
224779b3a418SLee Nipper 
224879b3a418SLee Nipper 	return 0;
224979b3a418SLee Nipper }
225079b3a418SLee Nipper 
225179b3a418SLee Nipper 
22529c4a7965SKim Phillips struct talitos_alg_template {
2253d5e4aaefSLee Nipper 	u32 type;
2254b0057763SLEROY Christophe 	u32 priority;
2255d5e4aaefSLee Nipper 	union {
2256373960d7SArd Biesheuvel 		struct skcipher_alg skcipher;
2257acbf7c62SLee Nipper 		struct ahash_alg hash;
2258aeb4c132SHerbert Xu 		struct aead_alg aead;
2259d5e4aaefSLee Nipper 	} alg;
22609c4a7965SKim Phillips 	__be32 desc_hdr_template;
22619c4a7965SKim Phillips };
22629c4a7965SKim Phillips 
22639c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2264991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2265d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2266aeb4c132SHerbert Xu 		.alg.aead = {
2267aeb4c132SHerbert Xu 			.base = {
226856af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2269aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2270aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
227156af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2272b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2273b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2274aeb4c132SHerbert Xu 			},
22753952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
22763952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
22779c4a7965SKim Phillips 		},
22789c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
22799c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
22809c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
22819c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
22829c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
22839c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
22849c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
228570bcaca7SLee Nipper 	},
2286d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
22877405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22887405c8d7SLEROY Christophe 		.alg.aead = {
22897405c8d7SLEROY Christophe 			.base = {
22907405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
22917405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
2292a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
22937405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
2294b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2295b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
22967405c8d7SLEROY Christophe 			},
22977405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
22987405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
22997405c8d7SLEROY Christophe 		},
23007405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23017405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23027405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23037405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23047405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23057405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23067405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23077405c8d7SLEROY Christophe 	},
23087405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2309aeb4c132SHerbert Xu 		.alg.aead = {
2310aeb4c132SHerbert Xu 			.base = {
2311aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2312aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2313aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2314aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
231556af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2316b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2317b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2318aeb4c132SHerbert Xu 			},
23193952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
23203952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
2321ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
232270bcaca7SLee Nipper 		},
232370bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
232470bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
232570bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
232670bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
232770bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
232870bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
232970bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
233070bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23313952f17eSLee Nipper 	},
2332d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23337405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23347405c8d7SLEROY Christophe 		.alg.aead = {
23357405c8d7SLEROY Christophe 			.base = {
23367405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),"
23377405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
23387405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
2339a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
23407405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2341b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2342b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
23437405c8d7SLEROY Christophe 			},
23447405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
23457405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
2346ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
23477405c8d7SLEROY Christophe 		},
23487405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23497405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
23507405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
23517405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
23527405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23537405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23547405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23557405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23567405c8d7SLEROY Christophe 	},
23577405c8d7SLEROY Christophe 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2358aeb4c132SHerbert Xu 		.alg.aead = {
2359aeb4c132SHerbert Xu 			.base = {
2360357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2361aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2362aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2363357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2364b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2365b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2366aeb4c132SHerbert Xu 			},
2367357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2368357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2369357fb605SHoria Geanta 		},
2370357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2371357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2372357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2373357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2374357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2375357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2376357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2377357fb605SHoria Geanta 	},
2378357fb605SHoria Geanta 	{       .type = CRYPTO_ALG_TYPE_AEAD,
23797405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23807405c8d7SLEROY Christophe 		.alg.aead = {
23817405c8d7SLEROY Christophe 			.base = {
23827405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
23837405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
2384a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
23857405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
2386b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2387b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
23887405c8d7SLEROY Christophe 			},
23897405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
23907405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
23917405c8d7SLEROY Christophe 		},
23927405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23937405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23947405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23957405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23967405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23977405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23987405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
23997405c8d7SLEROY Christophe 	},
24007405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2401aeb4c132SHerbert Xu 		.alg.aead = {
2402aeb4c132SHerbert Xu 			.base = {
2403aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2404aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2405aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2406aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2407357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2408b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2409b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2410aeb4c132SHerbert Xu 			},
2411357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2412357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2413ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2414357fb605SHoria Geanta 		},
2415357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2416357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2417357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2418357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2419357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2420357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2421357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2422357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2423357fb605SHoria Geanta 	},
2424357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24257405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24267405c8d7SLEROY Christophe 		.alg.aead = {
24277405c8d7SLEROY Christophe 			.base = {
24287405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),"
24297405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
24307405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
2431a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
24327405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2433b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2434b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
24357405c8d7SLEROY Christophe 			},
24367405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
24377405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
2438ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
24397405c8d7SLEROY Christophe 		},
24407405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24417405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24427405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
24437405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
24447405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24457405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24467405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24477405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
24487405c8d7SLEROY Christophe 	},
24497405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2450aeb4c132SHerbert Xu 		.alg.aead = {
2451aeb4c132SHerbert Xu 			.base = {
245256af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2453aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2454aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
245556af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2456b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2457b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2458aeb4c132SHerbert Xu 			},
24593952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
24603952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
24613952f17eSLee Nipper 		},
24623952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24633952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
24643952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
24653952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
24663952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
24673952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
24683952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24693952f17eSLee Nipper 	},
2470d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24717405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24727405c8d7SLEROY Christophe 		.alg.aead = {
24737405c8d7SLEROY Christophe 			.base = {
24747405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
24757405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
2476a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
24777405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
2478b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2479b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
24807405c8d7SLEROY Christophe 			},
24817405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
24827405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
24837405c8d7SLEROY Christophe 		},
24847405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24857405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
24867405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
24877405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24887405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24897405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24907405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24917405c8d7SLEROY Christophe 	},
24927405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2493aeb4c132SHerbert Xu 		.alg.aead = {
2494aeb4c132SHerbert Xu 			.base = {
2495aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2496aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2497aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2498aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
249956af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2500b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2501b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2502aeb4c132SHerbert Xu 			},
25033952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
25043952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
2505ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
25063952f17eSLee Nipper 		},
25073952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25083952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
25093952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
25103952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
25113952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25123952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25133952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25143952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25153952f17eSLee Nipper 	},
2516d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25177405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25187405c8d7SLEROY Christophe 		.alg.aead = {
25197405c8d7SLEROY Christophe 			.base = {
25207405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),"
25217405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
25227405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
2523a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
25247405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2525b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2526b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
25277405c8d7SLEROY Christophe 			},
25287405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
25297405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
2530ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
25317405c8d7SLEROY Christophe 		},
25327405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25337405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
25347405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
25357405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
25367405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25377405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25387405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25397405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25407405c8d7SLEROY Christophe 	},
25417405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2542aeb4c132SHerbert Xu 		.alg.aead = {
2543aeb4c132SHerbert Xu 			.base = {
2544357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2545aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2546aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2547357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2548b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2549b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2550aeb4c132SHerbert Xu 			},
2551357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2552357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2553357fb605SHoria Geanta 		},
2554357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2555357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2556357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2557357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2558357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2559357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2560357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2561357fb605SHoria Geanta 	},
2562357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2563aeb4c132SHerbert Xu 		.alg.aead = {
2564aeb4c132SHerbert Xu 			.base = {
2565aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2566aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2567aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2568aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2569357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2570b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2571b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2572aeb4c132SHerbert Xu 			},
2573357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2574357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2575ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2576357fb605SHoria Geanta 		},
2577357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2578357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2579357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2580357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2581357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2582357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2583357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2584357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2585357fb605SHoria Geanta 	},
2586357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2587aeb4c132SHerbert Xu 		.alg.aead = {
2588aeb4c132SHerbert Xu 			.base = {
2589357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2590aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2591aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2592357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2593b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2594b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2595aeb4c132SHerbert Xu 			},
2596357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2597357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2598357fb605SHoria Geanta 		},
2599357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2600357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2601357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2602357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2603357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2604357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2605357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2606357fb605SHoria Geanta 	},
2607357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2608aeb4c132SHerbert Xu 		.alg.aead = {
2609aeb4c132SHerbert Xu 			.base = {
2610aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2611aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2612aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2613aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2614357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2615b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2616b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2617aeb4c132SHerbert Xu 			},
2618357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2619357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2620ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2621357fb605SHoria Geanta 		},
2622357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2623357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2624357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2625357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2626357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2627357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2628357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2629357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2630357fb605SHoria Geanta 	},
2631357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2632aeb4c132SHerbert Xu 		.alg.aead = {
2633aeb4c132SHerbert Xu 			.base = {
263456af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2635aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2636aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
263756af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2638b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2639b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2640aeb4c132SHerbert Xu 			},
26413952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
26423952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
26433952f17eSLee Nipper 		},
26443952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26453952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
26463952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
26473952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26483952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
26493952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
26503952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26513952f17eSLee Nipper 	},
2652d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
26537405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26547405c8d7SLEROY Christophe 		.alg.aead = {
26557405c8d7SLEROY Christophe 			.base = {
26567405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(aes))",
26577405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
2658a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
26597405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
2660b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2661b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
26627405c8d7SLEROY Christophe 			},
26637405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
26647405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
26657405c8d7SLEROY Christophe 		},
26667405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
26677405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
26687405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
26697405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
26707405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
26717405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
26727405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26737405c8d7SLEROY Christophe 	},
26747405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2675aeb4c132SHerbert Xu 		.alg.aead = {
2676aeb4c132SHerbert Xu 			.base = {
267756af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2678aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2679aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
268056af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2681b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2682b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2683aeb4c132SHerbert Xu 			},
26843952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
26853952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
2686ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
26873952f17eSLee Nipper 		},
26883952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26893952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
26903952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
26913952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
26923952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26933952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
26943952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
26953952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26964de9d0b5SLee Nipper 	},
26977405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
26987405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26997405c8d7SLEROY Christophe 		.alg.aead = {
27007405c8d7SLEROY Christophe 			.base = {
27017405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
27027405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
2703a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
27047405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2705b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2706b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
27077405c8d7SLEROY Christophe 			},
27087405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
27097405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
2710ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
27117405c8d7SLEROY Christophe 		},
27127405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
27137405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
27147405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
27157405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
27167405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
27177405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
27187405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
27197405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27207405c8d7SLEROY Christophe 	},
2721373960d7SArd Biesheuvel 	/* SKCIPHER algorithms. */
2722373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2723373960d7SArd Biesheuvel 		.alg.skcipher = {
2724373960d7SArd Biesheuvel 			.base.cra_name = "ecb(aes)",
2725373960d7SArd Biesheuvel 			.base.cra_driver_name = "ecb-aes-talitos",
2726373960d7SArd Biesheuvel 			.base.cra_blocksize = AES_BLOCK_SIZE,
2727b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2728b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
27295e75ae1bSLEROY Christophe 			.min_keysize = AES_MIN_KEY_SIZE,
27305e75ae1bSLEROY Christophe 			.max_keysize = AES_MAX_KEY_SIZE,
2731373960d7SArd Biesheuvel 			.setkey = skcipher_aes_setkey,
27325e75ae1bSLEROY Christophe 		},
27335e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27345e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
27355e75ae1bSLEROY Christophe 	},
2736373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2737373960d7SArd Biesheuvel 		.alg.skcipher = {
2738373960d7SArd Biesheuvel 			.base.cra_name = "cbc(aes)",
2739373960d7SArd Biesheuvel 			.base.cra_driver_name = "cbc-aes-talitos",
2740373960d7SArd Biesheuvel 			.base.cra_blocksize = AES_BLOCK_SIZE,
2741b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2742b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
27434de9d0b5SLee Nipper 			.min_keysize = AES_MIN_KEY_SIZE,
27444de9d0b5SLee Nipper 			.max_keysize = AES_MAX_KEY_SIZE,
27454de9d0b5SLee Nipper 			.ivsize = AES_BLOCK_SIZE,
2746373960d7SArd Biesheuvel 			.setkey = skcipher_aes_setkey,
27474de9d0b5SLee Nipper 		},
27484de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27494de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
27504de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
27514de9d0b5SLee Nipper 	},
2752373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2753373960d7SArd Biesheuvel 		.alg.skcipher = {
2754373960d7SArd Biesheuvel 			.base.cra_name = "ctr(aes)",
2755373960d7SArd Biesheuvel 			.base.cra_driver_name = "ctr-aes-talitos",
2756373960d7SArd Biesheuvel 			.base.cra_blocksize = 1,
2757b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2758b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
27595e75ae1bSLEROY Christophe 			.min_keysize = AES_MIN_KEY_SIZE,
27605e75ae1bSLEROY Christophe 			.max_keysize = AES_MAX_KEY_SIZE,
27615e75ae1bSLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
2762373960d7SArd Biesheuvel 			.setkey = skcipher_aes_setkey,
27635e75ae1bSLEROY Christophe 		},
276470d355ccSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
27655e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
27665e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
27675e75ae1bSLEROY Christophe 	},
2768373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2769373960d7SArd Biesheuvel 		.alg.skcipher = {
277043a942d2SChristophe Leroy 			.base.cra_name = "ctr(aes)",
277143a942d2SChristophe Leroy 			.base.cra_driver_name = "ctr-aes-talitos",
277243a942d2SChristophe Leroy 			.base.cra_blocksize = 1,
277343a942d2SChristophe Leroy 			.base.cra_flags = CRYPTO_ALG_ASYNC |
277443a942d2SChristophe Leroy 					  CRYPTO_ALG_ALLOCATES_MEMORY,
277543a942d2SChristophe Leroy 			.min_keysize = AES_MIN_KEY_SIZE,
277643a942d2SChristophe Leroy 			.max_keysize = AES_MAX_KEY_SIZE,
277743a942d2SChristophe Leroy 			.ivsize = AES_BLOCK_SIZE,
277843a942d2SChristophe Leroy 			.setkey = skcipher_aes_setkey,
277943a942d2SChristophe Leroy 		},
278043a942d2SChristophe Leroy 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
278143a942d2SChristophe Leroy 				     DESC_HDR_SEL0_AESU |
278243a942d2SChristophe Leroy 				     DESC_HDR_MODE0_AESU_CTR,
278343a942d2SChristophe Leroy 	},
278443a942d2SChristophe Leroy 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
278543a942d2SChristophe Leroy 		.alg.skcipher = {
2786373960d7SArd Biesheuvel 			.base.cra_name = "ecb(des)",
2787373960d7SArd Biesheuvel 			.base.cra_driver_name = "ecb-des-talitos",
2788373960d7SArd Biesheuvel 			.base.cra_blocksize = DES_BLOCK_SIZE,
2789b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2790b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
27915e75ae1bSLEROY Christophe 			.min_keysize = DES_KEY_SIZE,
27925e75ae1bSLEROY Christophe 			.max_keysize = DES_KEY_SIZE,
2793373960d7SArd Biesheuvel 			.setkey = skcipher_des_setkey,
27945e75ae1bSLEROY Christophe 		},
27955e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27965e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
27975e75ae1bSLEROY Christophe 	},
2798373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2799373960d7SArd Biesheuvel 		.alg.skcipher = {
2800373960d7SArd Biesheuvel 			.base.cra_name = "cbc(des)",
2801373960d7SArd Biesheuvel 			.base.cra_driver_name = "cbc-des-talitos",
2802373960d7SArd Biesheuvel 			.base.cra_blocksize = DES_BLOCK_SIZE,
2803b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2804b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
28055e75ae1bSLEROY Christophe 			.min_keysize = DES_KEY_SIZE,
28065e75ae1bSLEROY Christophe 			.max_keysize = DES_KEY_SIZE,
28075e75ae1bSLEROY Christophe 			.ivsize = DES_BLOCK_SIZE,
2808373960d7SArd Biesheuvel 			.setkey = skcipher_des_setkey,
28095e75ae1bSLEROY Christophe 		},
28105e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28115e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
28125e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
28135e75ae1bSLEROY Christophe 	},
2814373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2815373960d7SArd Biesheuvel 		.alg.skcipher = {
2816373960d7SArd Biesheuvel 			.base.cra_name = "ecb(des3_ede)",
2817373960d7SArd Biesheuvel 			.base.cra_driver_name = "ecb-3des-talitos",
2818373960d7SArd Biesheuvel 			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2819b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2820b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
28215e75ae1bSLEROY Christophe 			.min_keysize = DES3_EDE_KEY_SIZE,
28225e75ae1bSLEROY Christophe 			.max_keysize = DES3_EDE_KEY_SIZE,
2823373960d7SArd Biesheuvel 			.setkey = skcipher_des3_setkey,
28245e75ae1bSLEROY Christophe 		},
28255e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28265e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
28275e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
28285e75ae1bSLEROY Christophe 	},
2829373960d7SArd Biesheuvel 	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
2830373960d7SArd Biesheuvel 		.alg.skcipher = {
2831373960d7SArd Biesheuvel 			.base.cra_name = "cbc(des3_ede)",
2832373960d7SArd Biesheuvel 			.base.cra_driver_name = "cbc-3des-talitos",
2833373960d7SArd Biesheuvel 			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2834b8aa7dc5SMikulas Patocka 			.base.cra_flags = CRYPTO_ALG_ASYNC |
2835b8aa7dc5SMikulas Patocka 					  CRYPTO_ALG_ALLOCATES_MEMORY,
28364de9d0b5SLee Nipper 			.min_keysize = DES3_EDE_KEY_SIZE,
28374de9d0b5SLee Nipper 			.max_keysize = DES3_EDE_KEY_SIZE,
28384de9d0b5SLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
2839373960d7SArd Biesheuvel 			.setkey = skcipher_des3_setkey,
28404de9d0b5SLee Nipper 		},
28414de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28424de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
28434de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
28444de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2845497f2e6bSLee Nipper 	},
2846497f2e6bSLee Nipper 	/* AHASH algorithms. */
2847497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2848497f2e6bSLee Nipper 		.alg.hash = {
2849497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
28503639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2851497f2e6bSLee Nipper 			.halg.base = {
2852497f2e6bSLee Nipper 				.cra_name = "md5",
2853497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2854b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2855b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2856b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
28579c4a7965SKim Phillips 			}
2858497f2e6bSLee Nipper 		},
2859497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2860497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2861497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2862497f2e6bSLee Nipper 	},
2863497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2864497f2e6bSLee Nipper 		.alg.hash = {
2865497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
28663639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2867497f2e6bSLee Nipper 			.halg.base = {
2868497f2e6bSLee Nipper 				.cra_name = "sha1",
2869497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2870497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2871b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2872b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2873497f2e6bSLee Nipper 			}
2874497f2e6bSLee Nipper 		},
2875497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2876497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2877497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2878497f2e6bSLee Nipper 	},
2879497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2880497f2e6bSLee Nipper 		.alg.hash = {
288160f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
28823639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
288360f208d7SKim Phillips 			.halg.base = {
288460f208d7SKim Phillips 				.cra_name = "sha224",
288560f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
288660f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
2887b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2888b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
288960f208d7SKim Phillips 			}
289060f208d7SKim Phillips 		},
289160f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
289260f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
289360f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
289460f208d7SKim Phillips 	},
289560f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
289660f208d7SKim Phillips 		.alg.hash = {
2897497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
28983639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2899497f2e6bSLee Nipper 			.halg.base = {
2900497f2e6bSLee Nipper 				.cra_name = "sha256",
2901497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2902497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2903b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2904b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2905497f2e6bSLee Nipper 			}
2906497f2e6bSLee Nipper 		},
2907497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2908497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2909497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2910497f2e6bSLee Nipper 	},
2911497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2912497f2e6bSLee Nipper 		.alg.hash = {
2913497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
29143639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2915497f2e6bSLee Nipper 			.halg.base = {
2916497f2e6bSLee Nipper 				.cra_name = "sha384",
2917497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2918497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
2919b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2920b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2921497f2e6bSLee Nipper 			}
2922497f2e6bSLee Nipper 		},
2923497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2924497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2925497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2926497f2e6bSLee Nipper 	},
2927497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2928497f2e6bSLee Nipper 		.alg.hash = {
2929497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
29303639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2931497f2e6bSLee Nipper 			.halg.base = {
2932497f2e6bSLee Nipper 				.cra_name = "sha512",
2933497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2934497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
2935b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2936b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
2937497f2e6bSLee Nipper 			}
2938497f2e6bSLee Nipper 		},
2939497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2940497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2941497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2942497f2e6bSLee Nipper 	},
294379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
294479b3a418SLee Nipper 		.alg.hash = {
294579b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
29463639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
294779b3a418SLee Nipper 			.halg.base = {
294879b3a418SLee Nipper 				.cra_name = "hmac(md5)",
294979b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2950b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2951b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2952b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
295379b3a418SLee Nipper 			}
295479b3a418SLee Nipper 		},
295579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
295679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
295779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
295879b3a418SLee Nipper 	},
295979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
296079b3a418SLee Nipper 		.alg.hash = {
296179b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
29623639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
296379b3a418SLee Nipper 			.halg.base = {
296479b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
296579b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
296679b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2967b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2968b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
296979b3a418SLee Nipper 			}
297079b3a418SLee Nipper 		},
297179b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
297279b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
297379b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
297479b3a418SLee Nipper 	},
297579b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
297679b3a418SLee Nipper 		.alg.hash = {
297779b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
29783639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
297979b3a418SLee Nipper 			.halg.base = {
298079b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
298179b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
298279b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
2983b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
2984b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
298579b3a418SLee Nipper 			}
298679b3a418SLee Nipper 		},
298779b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
298879b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
298979b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
299079b3a418SLee Nipper 	},
299179b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
299279b3a418SLee Nipper 		.alg.hash = {
299379b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
29943639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
299579b3a418SLee Nipper 			.halg.base = {
299679b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
299779b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
299879b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2999b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
3000b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
300179b3a418SLee Nipper 			}
300279b3a418SLee Nipper 		},
300379b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
300479b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
300579b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
300679b3a418SLee Nipper 	},
300779b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
300879b3a418SLee Nipper 		.alg.hash = {
300979b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
30103639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
301179b3a418SLee Nipper 			.halg.base = {
301279b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
301379b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
301479b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
3015b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
3016b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
301779b3a418SLee Nipper 			}
301879b3a418SLee Nipper 		},
301979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
302079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
302179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
302279b3a418SLee Nipper 	},
302379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
302479b3a418SLee Nipper 		.alg.hash = {
302579b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
30263639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
302779b3a418SLee Nipper 			.halg.base = {
302879b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
302979b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
303079b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
3031b8aa7dc5SMikulas Patocka 				.cra_flags = CRYPTO_ALG_ASYNC |
3032b8aa7dc5SMikulas Patocka 					     CRYPTO_ALG_ALLOCATES_MEMORY,
303379b3a418SLee Nipper 			}
303479b3a418SLee Nipper 		},
303579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
303679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
303779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
303879b3a418SLee Nipper 	}
30399c4a7965SKim Phillips };
30409c4a7965SKim Phillips 
30419c4a7965SKim Phillips struct talitos_crypto_alg {
30429c4a7965SKim Phillips 	struct list_head entry;
30439c4a7965SKim Phillips 	struct device *dev;
3044acbf7c62SLee Nipper 	struct talitos_alg_template algt;
30459c4a7965SKim Phillips };
30469c4a7965SKim Phillips 
304789d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
304889d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
30499c4a7965SKim Phillips {
30505228f0f7SKim Phillips 	struct talitos_private *priv;
30519c4a7965SKim Phillips 
30529c4a7965SKim Phillips 	/* update context with ptr to dev */
30539c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
305419bbbc63SKim Phillips 
30555228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
30565228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
30575228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
30585228f0f7SKim Phillips 		  (priv->num_channels - 1);
30595228f0f7SKim Phillips 
30609c4a7965SKim Phillips 	/* copy descriptor header template value */
3061acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
30629c4a7965SKim Phillips 
3063602dba5aSKim Phillips 	/* select done notification */
3064602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
3065602dba5aSKim Phillips 
3066497f2e6bSLee Nipper 	return 0;
3067497f2e6bSLee Nipper }
3068497f2e6bSLee Nipper 
3069aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
3070497f2e6bSLee Nipper {
307189d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
307289d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
307389d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
307489d124cbSJonas Eymann 
307589d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
307689d124cbSJonas Eymann 				   algt.alg.aead);
307789d124cbSJonas Eymann 
307889d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
30799c4a7965SKim Phillips }
30809c4a7965SKim Phillips 
3081373960d7SArd Biesheuvel static int talitos_cra_init_skcipher(struct crypto_skcipher *tfm)
3082373960d7SArd Biesheuvel {
3083373960d7SArd Biesheuvel 	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
3084373960d7SArd Biesheuvel 	struct talitos_crypto_alg *talitos_alg;
3085373960d7SArd Biesheuvel 	struct talitos_ctx *ctx = crypto_skcipher_ctx(tfm);
3086373960d7SArd Biesheuvel 
3087373960d7SArd Biesheuvel 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
3088373960d7SArd Biesheuvel 				   algt.alg.skcipher);
3089373960d7SArd Biesheuvel 
3090373960d7SArd Biesheuvel 	return talitos_init_common(ctx, talitos_alg);
3091373960d7SArd Biesheuvel }
3092373960d7SArd Biesheuvel 
3093497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
3094497f2e6bSLee Nipper {
3095373960d7SArd Biesheuvel 	struct crypto_alg *alg = tfm->__crt_alg;
3096373960d7SArd Biesheuvel 	struct talitos_crypto_alg *talitos_alg;
3097497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
3098497f2e6bSLee Nipper 
3099373960d7SArd Biesheuvel 	talitos_alg = container_of(__crypto_ahash_alg(alg),
3100373960d7SArd Biesheuvel 				   struct talitos_crypto_alg,
3101373960d7SArd Biesheuvel 				   algt.alg.hash);
3102497f2e6bSLee Nipper 
3103497f2e6bSLee Nipper 	ctx->keylen = 0;
3104497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
3105497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
3106497f2e6bSLee Nipper 
3107373960d7SArd Biesheuvel 	return talitos_init_common(ctx, talitos_alg);
3108497f2e6bSLee Nipper }
3109497f2e6bSLee Nipper 
31102e13ce08SLEROY Christophe static void talitos_cra_exit(struct crypto_tfm *tfm)
31112e13ce08SLEROY Christophe {
31122e13ce08SLEROY Christophe 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
31132e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
31142e13ce08SLEROY Christophe 
31152e13ce08SLEROY Christophe 	if (ctx->keylen)
31162e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
31172e13ce08SLEROY Christophe }
31182e13ce08SLEROY Christophe 
31199c4a7965SKim Phillips /*
31209c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
31219c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
31229c4a7965SKim Phillips  * capabilities description provided in the device tree node.
31239c4a7965SKim Phillips  */
31249c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
31259c4a7965SKim Phillips {
31269c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31279c4a7965SKim Phillips 	int ret;
31289c4a7965SKim Phillips 
31299c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
31309c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
31319c4a7965SKim Phillips 
31329c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
31339c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
31349c4a7965SKim Phillips 		              & priv->exec_units);
31359c4a7965SKim Phillips 
31369c4a7965SKim Phillips 	return ret;
31379c4a7965SKim Phillips }
31389c4a7965SKim Phillips 
31392dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
31409c4a7965SKim Phillips {
31419c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
31429c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31439c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
31449c4a7965SKim Phillips 	int i;
31459c4a7965SKim Phillips 
31469c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
3147acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
3148373960d7SArd Biesheuvel 		case CRYPTO_ALG_TYPE_SKCIPHER:
3149373960d7SArd Biesheuvel 			crypto_unregister_skcipher(&t_alg->algt.alg.skcipher);
3150acbf7c62SLee Nipper 			break;
3151aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
3152aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
31535fc194eaSGustavo A. R. Silva 			break;
3154acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
3155acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
3156acbf7c62SLee Nipper 			break;
3157acbf7c62SLee Nipper 		}
31589c4a7965SKim Phillips 		list_del(&t_alg->entry);
31599c4a7965SKim Phillips 	}
31609c4a7965SKim Phillips 
31619c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
31629c4a7965SKim Phillips 		talitos_unregister_rng(dev);
31639c4a7965SKim Phillips 
3164c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
31652cdba3cfSKim Phillips 		if (priv->irq[i]) {
3166c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
3167c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
31689c4a7965SKim Phillips 		}
31699c4a7965SKim Phillips 
3170c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
31712cdba3cfSKim Phillips 	if (priv->irq[1])
3172c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
31739c4a7965SKim Phillips 
31749c4a7965SKim Phillips 	return 0;
31759c4a7965SKim Phillips }
31769c4a7965SKim Phillips 
31779c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
31789c4a7965SKim Phillips 						    struct talitos_alg_template
31799c4a7965SKim Phillips 						           *template)
31809c4a7965SKim Phillips {
318160f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31829c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
31839c4a7965SKim Phillips 	struct crypto_alg *alg;
31849c4a7965SKim Phillips 
318524b92ff2SLEROY Christophe 	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
318624b92ff2SLEROY Christophe 			     GFP_KERNEL);
31879c4a7965SKim Phillips 	if (!t_alg)
31889c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
31899c4a7965SKim Phillips 
3190acbf7c62SLee Nipper 	t_alg->algt = *template;
3191acbf7c62SLee Nipper 
3192acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
3193373960d7SArd Biesheuvel 	case CRYPTO_ALG_TYPE_SKCIPHER:
3194373960d7SArd Biesheuvel 		alg = &t_alg->algt.alg.skcipher.base;
31952e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3196373960d7SArd Biesheuvel 		t_alg->algt.alg.skcipher.init = talitos_cra_init_skcipher;
3197373960d7SArd Biesheuvel 		t_alg->algt.alg.skcipher.setkey =
3198373960d7SArd Biesheuvel 			t_alg->algt.alg.skcipher.setkey ?: skcipher_setkey;
3199373960d7SArd Biesheuvel 		t_alg->algt.alg.skcipher.encrypt = skcipher_encrypt;
3200373960d7SArd Biesheuvel 		t_alg->algt.alg.skcipher.decrypt = skcipher_decrypt;
320143a942d2SChristophe Leroy 		if (!strcmp(alg->cra_name, "ctr(aes)") && !has_ftr_sec1(priv) &&
320243a942d2SChristophe Leroy 		    DESC_TYPE(t_alg->algt.desc_hdr_template) !=
320343a942d2SChristophe Leroy 		    DESC_TYPE(DESC_HDR_TYPE_AESU_CTR_NONSNOOP)) {
320443a942d2SChristophe Leroy 			devm_kfree(dev, t_alg);
320543a942d2SChristophe Leroy 			return ERR_PTR(-ENOTSUPP);
320643a942d2SChristophe Leroy 		}
3207497f2e6bSLee Nipper 		break;
3208acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
3209aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
32102e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3211aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
3212ef7c5c85SHerbert Xu 		t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?:
3213ef7c5c85SHerbert Xu 					      aead_setkey;
3214aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
3215aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
32166cda075aSLEROY Christophe 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
32176cda075aSLEROY Christophe 		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
321824b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
32196cda075aSLEROY Christophe 			return ERR_PTR(-ENOTSUPP);
32206cda075aSLEROY Christophe 		}
3221acbf7c62SLee Nipper 		break;
3222acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
3223acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
3224497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
3225ad4cd51fSLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3226b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
3227b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
3228b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
3229b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
3230b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
323156136631SLEROY Christophe 		if (!strncmp(alg->cra_name, "hmac", 4))
3232b286e003SKim Phillips 			t_alg->algt.alg.hash.setkey = ahash_setkey;
32333639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
32343639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
3235b286e003SKim Phillips 
323679b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
32370b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
323824b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
323979b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
32400b2730d8SKim Phillips 		}
324160f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
324279b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
324379b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
324460f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
324560f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
324660f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
324760f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
324860f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
324960f208d7SKim Phillips 		}
3250497f2e6bSLee Nipper 		break;
32511d11911aSKim Phillips 	default:
32521d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
325324b92ff2SLEROY Christophe 		devm_kfree(dev, t_alg);
32541d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
3255acbf7c62SLee Nipper 	}
32569c4a7965SKim Phillips 
32579c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
3258b0057763SLEROY Christophe 	if (t_alg->algt.priority)
3259b0057763SLEROY Christophe 		alg->cra_priority = t_alg->algt.priority;
3260b0057763SLEROY Christophe 	else
32619c4a7965SKim Phillips 		alg->cra_priority = TALITOS_CRA_PRIORITY;
3262c9cca703SChristophe Leroy 	if (has_ftr_sec1(priv))
3263c9cca703SChristophe Leroy 		alg->cra_alignmask = 3;
3264c9cca703SChristophe Leroy 	else
32659c4a7965SKim Phillips 		alg->cra_alignmask = 0;
32669c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
3267d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
32689c4a7965SKim Phillips 
32699c4a7965SKim Phillips 	t_alg->dev = dev;
32709c4a7965SKim Phillips 
32719c4a7965SKim Phillips 	return t_alg;
32729c4a7965SKim Phillips }
32739c4a7965SKim Phillips 
3274c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
3275c3e337f8SKim Phillips {
3276c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
3277c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
3278c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3279c3e337f8SKim Phillips 	int err;
3280dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3281c3e337f8SKim Phillips 
3282c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
32832cdba3cfSKim Phillips 	if (!priv->irq[0]) {
3284c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
3285c3e337f8SKim Phillips 		return -EINVAL;
3286c3e337f8SKim Phillips 	}
3287dd3c0987SLEROY Christophe 	if (is_sec1) {
3288dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
3289dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
3290dd3c0987SLEROY Christophe 		goto primary_out;
3291dd3c0987SLEROY Christophe 	}
3292c3e337f8SKim Phillips 
3293c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
3294c3e337f8SKim Phillips 
3295c3e337f8SKim Phillips 	/* get the primary irq line */
32962cdba3cfSKim Phillips 	if (!priv->irq[1]) {
3297dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
3298c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
3299c3e337f8SKim Phillips 		goto primary_out;
3300c3e337f8SKim Phillips 	}
3301c3e337f8SKim Phillips 
3302dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
3303c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3304c3e337f8SKim Phillips 	if (err)
3305c3e337f8SKim Phillips 		goto primary_out;
3306c3e337f8SKim Phillips 
3307c3e337f8SKim Phillips 	/* get the secondary irq line */
3308dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
3309c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3310c3e337f8SKim Phillips 	if (err) {
3311c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
3312c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
33132cdba3cfSKim Phillips 		priv->irq[1] = 0;
3314c3e337f8SKim Phillips 	}
3315c3e337f8SKim Phillips 
3316c3e337f8SKim Phillips 	return err;
3317c3e337f8SKim Phillips 
3318c3e337f8SKim Phillips primary_out:
3319c3e337f8SKim Phillips 	if (err) {
3320c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
3321c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
33222cdba3cfSKim Phillips 		priv->irq[0] = 0;
3323c3e337f8SKim Phillips 	}
3324c3e337f8SKim Phillips 
3325c3e337f8SKim Phillips 	return err;
3326c3e337f8SKim Phillips }
3327c3e337f8SKim Phillips 
33281c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
33299c4a7965SKim Phillips {
33309c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
333161c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
33329c4a7965SKim Phillips 	struct talitos_private *priv;
33339c4a7965SKim Phillips 	int i, err;
33345fa7fa14SLEROY Christophe 	int stride;
3335fd5ea7f0SLEROY Christophe 	struct resource *res;
33369c4a7965SKim Phillips 
333724b92ff2SLEROY Christophe 	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
33389c4a7965SKim Phillips 	if (!priv)
33399c4a7965SKim Phillips 		return -ENOMEM;
33409c4a7965SKim Phillips 
3341f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
3342f3de9cb1SKevin Hao 
33439c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
33449c4a7965SKim Phillips 
33459c4a7965SKim Phillips 	priv->ofdev = ofdev;
33469c4a7965SKim Phillips 
3347511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
3348511d63cbSHoria Geanta 
3349fd5ea7f0SLEROY Christophe 	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
3350fd5ea7f0SLEROY Christophe 	if (!res)
3351fd5ea7f0SLEROY Christophe 		return -ENXIO;
3352fd5ea7f0SLEROY Christophe 	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
33539c4a7965SKim Phillips 	if (!priv->reg) {
33549c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
33559c4a7965SKim Phillips 		err = -ENOMEM;
33569c4a7965SKim Phillips 		goto err_out;
33579c4a7965SKim Phillips 	}
33589c4a7965SKim Phillips 
33599c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
3360fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
3361fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
3362fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
3363fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,descriptor-types-mask",
3364fa14c6cfSLEROY Christophe 			     &priv->desc_types);
33659c4a7965SKim Phillips 
33669c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
33679c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
33689c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
33699c4a7965SKim Phillips 		err = -EINVAL;
33709c4a7965SKim Phillips 		goto err_out;
33719c4a7965SKim Phillips 	}
33729c4a7965SKim Phillips 
3373f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3374f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3375f3c85bc1SLee Nipper 
3376fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
337760f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
337879b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
337979b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3380fe5720e2SKim Phillips 
338121590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
338221590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
338321590888SLEROY Christophe 
33845fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
33855fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
33865fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
33875fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
33885fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
33895fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
33905fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
33915fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
33925fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
33935fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
33945fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
33955fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
33965fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
33975fa7fa14SLEROY Christophe 	} else {
33985fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
33995fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
34005fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
34015fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
34025fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
34035fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
34045fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
34055fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
34065fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
34075fa7fa14SLEROY Christophe 	}
34085fa7fa14SLEROY Christophe 
3409dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3410dd3c0987SLEROY Christophe 	if (err)
3411dd3c0987SLEROY Christophe 		goto err_out;
3412dd3c0987SLEROY Christophe 
3413c8c74647SChristophe Leroy 	if (has_ftr_sec1(priv)) {
34149c02e285SLEROY Christophe 		if (priv->num_channels == 1)
34159c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
34169c02e285SLEROY Christophe 				     (unsigned long)dev);
34179c02e285SLEROY Christophe 		else
3418dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3419dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3420dd3c0987SLEROY Christophe 	} else {
34219c02e285SLEROY Christophe 		if (priv->irq[1]) {
3422dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3423dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3424dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3425dd3c0987SLEROY Christophe 				     (unsigned long)dev);
34269c02e285SLEROY Christophe 		} else if (priv->num_channels == 1) {
34279c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
34289c02e285SLEROY Christophe 				     (unsigned long)dev);
34299c02e285SLEROY Christophe 		} else {
34309c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
34319c02e285SLEROY Christophe 				     (unsigned long)dev);
3432dd3c0987SLEROY Christophe 		}
3433dd3c0987SLEROY Christophe 	}
3434dd3c0987SLEROY Christophe 
3435a86854d0SKees Cook 	priv->chan = devm_kcalloc(dev,
3436a86854d0SKees Cook 				  priv->num_channels,
3437a86854d0SKees Cook 				  sizeof(struct talitos_channel),
3438a86854d0SKees Cook 				  GFP_KERNEL);
34394b992628SKim Phillips 	if (!priv->chan) {
34404b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
34419c4a7965SKim Phillips 		err = -ENOMEM;
34429c4a7965SKim Phillips 		goto err_out;
34439c4a7965SKim Phillips 	}
34449c4a7965SKim Phillips 
3445f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3446f641ddddSMartin Hicks 
3447c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
34485fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
34492cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3450c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3451ad42d5fcSKim Phillips 
34524b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
34534b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
34549c4a7965SKim Phillips 
3455a86854d0SKees Cook 		priv->chan[i].fifo = devm_kcalloc(dev,
3456a86854d0SKees Cook 						priv->fifo_len,
3457a86854d0SKees Cook 						sizeof(struct talitos_request),
3458a86854d0SKees Cook 						GFP_KERNEL);
34594b992628SKim Phillips 		if (!priv->chan[i].fifo) {
34609c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
34619c4a7965SKim Phillips 			err = -ENOMEM;
34629c4a7965SKim Phillips 			goto err_out;
34639c4a7965SKim Phillips 		}
34649c4a7965SKim Phillips 
34654b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
34664b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3467f641ddddSMartin Hicks 	}
34689c4a7965SKim Phillips 
346981eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
347081eb024cSKim Phillips 
34719c4a7965SKim Phillips 	/* reset and initialize the h/w */
34729c4a7965SKim Phillips 	err = init_device(dev);
34739c4a7965SKim Phillips 	if (err) {
34749c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
34759c4a7965SKim Phillips 		goto err_out;
34769c4a7965SKim Phillips 	}
34779c4a7965SKim Phillips 
34789c4a7965SKim Phillips 	/* register the RNG, if available */
34799c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
34809c4a7965SKim Phillips 		err = talitos_register_rng(dev);
34819c4a7965SKim Phillips 		if (err) {
34829c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
34839c4a7965SKim Phillips 			goto err_out;
34849c4a7965SKim Phillips 		} else
34859c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
34869c4a7965SKim Phillips 	}
34879c4a7965SKim Phillips 
34889c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
34899c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
34909c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
34919c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3492aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
34939c4a7965SKim Phillips 
34949c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
34959c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
34969c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
34970b2730d8SKim Phillips 				if (err == -ENOTSUPP)
349879b3a418SLee Nipper 					continue;
34999c4a7965SKim Phillips 				goto err_out;
35009c4a7965SKim Phillips 			}
35019c4a7965SKim Phillips 
3502acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3503373960d7SArd Biesheuvel 			case CRYPTO_ALG_TYPE_SKCIPHER:
3504373960d7SArd Biesheuvel 				err = crypto_register_skcipher(
3505373960d7SArd Biesheuvel 						&t_alg->algt.alg.skcipher);
3506373960d7SArd Biesheuvel 				alg = &t_alg->algt.alg.skcipher.base;
3507acbf7c62SLee Nipper 				break;
3508aeb4c132SHerbert Xu 
3509aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3510aeb4c132SHerbert Xu 				err = crypto_register_aead(
3511aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3512aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3513aeb4c132SHerbert Xu 				break;
3514aeb4c132SHerbert Xu 
3515acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3516acbf7c62SLee Nipper 				err = crypto_register_ahash(
3517acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3518aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3519acbf7c62SLee Nipper 				break;
3520acbf7c62SLee Nipper 			}
35219c4a7965SKim Phillips 			if (err) {
35229c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3523aeb4c132SHerbert Xu 					alg->cra_driver_name);
352424b92ff2SLEROY Christophe 				devm_kfree(dev, t_alg);
3525991155baSHoria Geanta 			} else
35269c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
35279c4a7965SKim Phillips 		}
35289c4a7965SKim Phillips 	}
35295b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
35305b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
35315b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
35329c4a7965SKim Phillips 
35339c4a7965SKim Phillips 	return 0;
35349c4a7965SKim Phillips 
35359c4a7965SKim Phillips err_out:
35369c4a7965SKim Phillips 	talitos_remove(ofdev);
35379c4a7965SKim Phillips 
35389c4a7965SKim Phillips 	return err;
35399c4a7965SKim Phillips }
35409c4a7965SKim Phillips 
35416c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
35420635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
35430635b7dbSLEROY Christophe 	{
35440635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
35450635b7dbSLEROY Christophe 	},
35460635b7dbSLEROY Christophe #endif
35470635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
35489c4a7965SKim Phillips 	{
35499c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
35509c4a7965SKim Phillips 	},
35510635b7dbSLEROY Christophe #endif
35529c4a7965SKim Phillips 	{},
35539c4a7965SKim Phillips };
35549c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
35559c4a7965SKim Phillips 
35561c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
35574018294bSGrant Likely 	.driver = {
35589c4a7965SKim Phillips 		.name = "talitos",
35594018294bSGrant Likely 		.of_match_table = talitos_match,
35604018294bSGrant Likely 	},
35619c4a7965SKim Phillips 	.probe = talitos_probe,
3562596f1034SAl Viro 	.remove = talitos_remove,
35639c4a7965SKim Phillips };
35649c4a7965SKim Phillips 
3565741e8c2dSAxel Lin module_platform_driver(talitos_driver);
35669c4a7965SKim Phillips 
35679c4a7965SKim Phillips MODULE_LICENSE("GPL");
35689c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
35699c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3570