xref: /linux/drivers/crypto/talitos.c (revision 4bbfb839259a9c96a0be872e16f7471b7136aee5)
19c4a7965SKim Phillips /*
29c4a7965SKim Phillips  * talitos - Freescale Integrated Security Engine (SEC) device driver
39c4a7965SKim Phillips  *
45228f0f7SKim Phillips  * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
59c4a7965SKim Phillips  *
69c4a7965SKim Phillips  * Scatterlist Crypto API glue code copied from files with the following:
79c4a7965SKim Phillips  * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
89c4a7965SKim Phillips  *
99c4a7965SKim Phillips  * Crypto algorithm registration code copied from hifn driver:
109c4a7965SKim Phillips  * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
119c4a7965SKim Phillips  * All rights reserved.
129c4a7965SKim Phillips  *
139c4a7965SKim Phillips  * This program is free software; you can redistribute it and/or modify
149c4a7965SKim Phillips  * it under the terms of the GNU General Public License as published by
159c4a7965SKim Phillips  * the Free Software Foundation; either version 2 of the License, or
169c4a7965SKim Phillips  * (at your option) any later version.
179c4a7965SKim Phillips  *
189c4a7965SKim Phillips  * This program is distributed in the hope that it will be useful,
199c4a7965SKim Phillips  * but WITHOUT ANY WARRANTY; without even the implied warranty of
209c4a7965SKim Phillips  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
219c4a7965SKim Phillips  * GNU General Public License for more details.
229c4a7965SKim Phillips  *
239c4a7965SKim Phillips  * You should have received a copy of the GNU General Public License
249c4a7965SKim Phillips  * along with this program; if not, write to the Free Software
259c4a7965SKim Phillips  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
269c4a7965SKim Phillips  */
279c4a7965SKim Phillips 
289c4a7965SKim Phillips #include <linux/kernel.h>
299c4a7965SKim Phillips #include <linux/module.h>
309c4a7965SKim Phillips #include <linux/mod_devicetable.h>
319c4a7965SKim Phillips #include <linux/device.h>
329c4a7965SKim Phillips #include <linux/interrupt.h>
339c4a7965SKim Phillips #include <linux/crypto.h>
349c4a7965SKim Phillips #include <linux/hw_random.h>
355af50730SRob Herring #include <linux/of_address.h>
365af50730SRob Herring #include <linux/of_irq.h>
379c4a7965SKim Phillips #include <linux/of_platform.h>
389c4a7965SKim Phillips #include <linux/dma-mapping.h>
399c4a7965SKim Phillips #include <linux/io.h>
409c4a7965SKim Phillips #include <linux/spinlock.h>
419c4a7965SKim Phillips #include <linux/rtnetlink.h>
425a0e3ad6STejun Heo #include <linux/slab.h>
439c4a7965SKim Phillips 
449c4a7965SKim Phillips #include <crypto/algapi.h>
459c4a7965SKim Phillips #include <crypto/aes.h>
463952f17eSLee Nipper #include <crypto/des.h>
479c4a7965SKim Phillips #include <crypto/sha.h>
48497f2e6bSLee Nipper #include <crypto/md5.h>
49e98014abSHerbert Xu #include <crypto/internal/aead.h>
509c4a7965SKim Phillips #include <crypto/authenc.h>
514de9d0b5SLee Nipper #include <crypto/skcipher.h>
52acbf7c62SLee Nipper #include <crypto/hash.h>
53acbf7c62SLee Nipper #include <crypto/internal/hash.h>
544de9d0b5SLee Nipper #include <crypto/scatterwalk.h>
559c4a7965SKim Phillips 
569c4a7965SKim Phillips #include "talitos.h"
579c4a7965SKim Phillips 
58922f9dc8SLEROY Christophe static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
59da9de146SLEROY Christophe 			   unsigned int len, bool is_sec1)
6081eb024cSKim Phillips {
61edc6bd69SLEROY Christophe 	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
62da9de146SLEROY Christophe 	if (is_sec1) {
63da9de146SLEROY Christophe 		ptr->len1 = cpu_to_be16(len);
64da9de146SLEROY Christophe 	} else {
65da9de146SLEROY Christophe 		ptr->len = cpu_to_be16(len);
66edc6bd69SLEROY Christophe 		ptr->eptr = upper_32_bits(dma_addr);
6781eb024cSKim Phillips 	}
68da9de146SLEROY Christophe }
6981eb024cSKim Phillips 
70340ff60aSHoria Geant? static void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
71340ff60aSHoria Geant? 			     struct talitos_ptr *src_ptr, bool is_sec1)
72340ff60aSHoria Geant? {
73340ff60aSHoria Geant? 	dst_ptr->ptr = src_ptr->ptr;
74922f9dc8SLEROY Christophe 	if (is_sec1) {
75da9de146SLEROY Christophe 		dst_ptr->len1 = src_ptr->len1;
76922f9dc8SLEROY Christophe 	} else {
77da9de146SLEROY Christophe 		dst_ptr->len = src_ptr->len;
78da9de146SLEROY Christophe 		dst_ptr->eptr = src_ptr->eptr;
79538caf83SLEROY Christophe 	}
80922f9dc8SLEROY Christophe }
81538caf83SLEROY Christophe 
82922f9dc8SLEROY Christophe static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
83922f9dc8SLEROY Christophe 					   bool is_sec1)
84538caf83SLEROY Christophe {
85922f9dc8SLEROY Christophe 	if (is_sec1)
86922f9dc8SLEROY Christophe 		return be16_to_cpu(ptr->len1);
87922f9dc8SLEROY Christophe 	else
88538caf83SLEROY Christophe 		return be16_to_cpu(ptr->len);
89538caf83SLEROY Christophe }
90538caf83SLEROY Christophe 
91b096b544SLEROY Christophe static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
92b096b544SLEROY Christophe 				   bool is_sec1)
93185eb79fSLEROY Christophe {
94922f9dc8SLEROY Christophe 	if (!is_sec1)
95b096b544SLEROY Christophe 		ptr->j_extent = val;
96b096b544SLEROY Christophe }
97b096b544SLEROY Christophe 
98b096b544SLEROY Christophe static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
99b096b544SLEROY Christophe {
100b096b544SLEROY Christophe 	if (!is_sec1)
101b096b544SLEROY Christophe 		ptr->j_extent |= val;
102185eb79fSLEROY Christophe }
103185eb79fSLEROY Christophe 
1049c4a7965SKim Phillips /*
1059c4a7965SKim Phillips  * map virtual single (contiguous) pointer to h/w descriptor pointer
1069c4a7965SKim Phillips  */
1076a4967c3SLEROY Christophe static void __map_single_talitos_ptr(struct device *dev,
1086a4967c3SLEROY Christophe 				     struct talitos_ptr *ptr,
1096a4967c3SLEROY Christophe 				     unsigned int len, void *data,
1106a4967c3SLEROY Christophe 				     enum dma_data_direction dir,
1116a4967c3SLEROY Christophe 				     unsigned long attrs)
1126a4967c3SLEROY Christophe {
1136a4967c3SLEROY Christophe 	dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs);
1146a4967c3SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1156a4967c3SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1166a4967c3SLEROY Christophe 
1176a4967c3SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr, len, is_sec1);
1186a4967c3SLEROY Christophe }
1196a4967c3SLEROY Christophe 
1209c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev,
121edc6bd69SLEROY Christophe 				   struct talitos_ptr *ptr,
12242e8b0d7SHoria Geant? 				   unsigned int len, void *data,
1239c4a7965SKim Phillips 				   enum dma_data_direction dir)
1249c4a7965SKim Phillips {
1256a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir, 0);
1266a4967c3SLEROY Christophe }
12781eb024cSKim Phillips 
1286a4967c3SLEROY Christophe static void map_single_talitos_ptr_nosync(struct device *dev,
1296a4967c3SLEROY Christophe 					  struct talitos_ptr *ptr,
1306a4967c3SLEROY Christophe 					  unsigned int len, void *data,
1316a4967c3SLEROY Christophe 					  enum dma_data_direction dir)
1326a4967c3SLEROY Christophe {
1336a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir,
1346a4967c3SLEROY Christophe 				 DMA_ATTR_SKIP_CPU_SYNC);
1359c4a7965SKim Phillips }
1369c4a7965SKim Phillips 
1379c4a7965SKim Phillips /*
1389c4a7965SKim Phillips  * unmap bus single (contiguous) h/w descriptor pointer
1399c4a7965SKim Phillips  */
1409c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev,
141edc6bd69SLEROY Christophe 				     struct talitos_ptr *ptr,
1429c4a7965SKim Phillips 				     enum dma_data_direction dir)
1439c4a7965SKim Phillips {
144922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
145922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
146922f9dc8SLEROY Christophe 
147edc6bd69SLEROY Christophe 	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
148922f9dc8SLEROY Christophe 			 from_talitos_ptr_len(ptr, is_sec1), dir);
1499c4a7965SKim Phillips }
1509c4a7965SKim Phillips 
1519c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch)
1529c4a7965SKim Phillips {
1539c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1549c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
155dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1569c4a7965SKim Phillips 
157dd3c0987SLEROY Christophe 	if (is_sec1) {
158dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
159dd3c0987SLEROY Christophe 			  TALITOS1_CCCR_LO_RESET);
1609c4a7965SKim Phillips 
161dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
162dd3c0987SLEROY Christophe 			TALITOS1_CCCR_LO_RESET) && --timeout)
1639c4a7965SKim Phillips 			cpu_relax();
164dd3c0987SLEROY Christophe 	} else {
165dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
166dd3c0987SLEROY Christophe 			  TALITOS2_CCCR_RESET);
167dd3c0987SLEROY Christophe 
168dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
169dd3c0987SLEROY Christophe 			TALITOS2_CCCR_RESET) && --timeout)
170dd3c0987SLEROY Christophe 			cpu_relax();
171dd3c0987SLEROY Christophe 	}
1729c4a7965SKim Phillips 
1739c4a7965SKim Phillips 	if (timeout == 0) {
1749c4a7965SKim Phillips 		dev_err(dev, "failed to reset channel %d\n", ch);
1759c4a7965SKim Phillips 		return -EIO;
1769c4a7965SKim Phillips 	}
1779c4a7965SKim Phillips 
17881eb024cSKim Phillips 	/* set 36-bit addressing, done writeback enable and done IRQ enable */
179ad42d5fcSKim Phillips 	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
18081eb024cSKim Phillips 		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
18137b5e889SLEROY Christophe 	/* enable chaining descriptors */
18237b5e889SLEROY Christophe 	if (is_sec1)
18337b5e889SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
18437b5e889SLEROY Christophe 			  TALITOS_CCCR_LO_NE);
1859c4a7965SKim Phillips 
186fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
187fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
188ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
189fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
190fe5720e2SKim Phillips 
1919c4a7965SKim Phillips 	return 0;
1929c4a7965SKim Phillips }
1939c4a7965SKim Phillips 
1949c4a7965SKim Phillips static int reset_device(struct device *dev)
1959c4a7965SKim Phillips {
1969c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1979c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
198dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
199dd3c0987SLEROY Christophe 	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
2009c4a7965SKim Phillips 
201c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
2029c4a7965SKim Phillips 
203dd3c0987SLEROY Christophe 	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
2049c4a7965SKim Phillips 	       && --timeout)
2059c4a7965SKim Phillips 		cpu_relax();
2069c4a7965SKim Phillips 
2072cdba3cfSKim Phillips 	if (priv->irq[1]) {
208c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
209c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
210c3e337f8SKim Phillips 	}
211c3e337f8SKim Phillips 
2129c4a7965SKim Phillips 	if (timeout == 0) {
2139c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
2149c4a7965SKim Phillips 		return -EIO;
2159c4a7965SKim Phillips 	}
2169c4a7965SKim Phillips 
2179c4a7965SKim Phillips 	return 0;
2189c4a7965SKim Phillips }
2199c4a7965SKim Phillips 
2209c4a7965SKim Phillips /*
2219c4a7965SKim Phillips  * Reset and initialize the device
2229c4a7965SKim Phillips  */
2239c4a7965SKim Phillips static int init_device(struct device *dev)
2249c4a7965SKim Phillips {
2259c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2269c4a7965SKim Phillips 	int ch, err;
227dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2289c4a7965SKim Phillips 
2299c4a7965SKim Phillips 	/*
2309c4a7965SKim Phillips 	 * Master reset
2319c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
2329c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
2339c4a7965SKim Phillips 	 * set bit twice to completely reset
2349c4a7965SKim Phillips 	 */
2359c4a7965SKim Phillips 	err = reset_device(dev);
2369c4a7965SKim Phillips 	if (err)
2379c4a7965SKim Phillips 		return err;
2389c4a7965SKim Phillips 
2399c4a7965SKim Phillips 	err = reset_device(dev);
2409c4a7965SKim Phillips 	if (err)
2419c4a7965SKim Phillips 		return err;
2429c4a7965SKim Phillips 
2439c4a7965SKim Phillips 	/* reset channels */
2449c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
2459c4a7965SKim Phillips 		err = reset_channel(dev, ch);
2469c4a7965SKim Phillips 		if (err)
2479c4a7965SKim Phillips 			return err;
2489c4a7965SKim Phillips 	}
2499c4a7965SKim Phillips 
2509c4a7965SKim Phillips 	/* enable channel done and error interrupts */
251dd3c0987SLEROY Christophe 	if (is_sec1) {
252dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
253dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
254dd3c0987SLEROY Christophe 		/* disable parity error check in DEU (erroneous? test vect.) */
255dd3c0987SLEROY Christophe 		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
256dd3c0987SLEROY Christophe 	} else {
257dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
258dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
259dd3c0987SLEROY Christophe 	}
2609c4a7965SKim Phillips 
261fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
262fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2635fa7fa14SLEROY Christophe 		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
264fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
265fe5720e2SKim Phillips 
2669c4a7965SKim Phillips 	return 0;
2679c4a7965SKim Phillips }
2689c4a7965SKim Phillips 
2699c4a7965SKim Phillips /**
2709c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
2719c4a7965SKim Phillips  * @dev:	the SEC device to be used
2725228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
2739c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
2749c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
2759c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
2769c4a7965SKim Phillips  *
2779c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
2789c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
2799c4a7965SKim Phillips  * for device processing status.
2809c4a7965SKim Phillips  */
281865d5061SHoria Geanta int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2829c4a7965SKim Phillips 		   void (*callback)(struct device *dev,
2839c4a7965SKim Phillips 				    struct talitos_desc *desc,
2849c4a7965SKim Phillips 				    void *context, int error),
2859c4a7965SKim Phillips 		   void *context)
2869c4a7965SKim Phillips {
2879c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2889c4a7965SKim Phillips 	struct talitos_request *request;
2895228f0f7SKim Phillips 	unsigned long flags;
2909c4a7965SKim Phillips 	int head;
2917d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2929c4a7965SKim Phillips 
2934b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2949c4a7965SKim Phillips 
2954b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
296ec6644d6SKim Phillips 		/* h/w fifo is full */
2974b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2989c4a7965SKim Phillips 		return -EAGAIN;
2999c4a7965SKim Phillips 	}
3009c4a7965SKim Phillips 
3014b992628SKim Phillips 	head = priv->chan[ch].head;
3024b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
303ec6644d6SKim Phillips 
3049c4a7965SKim Phillips 	/* map descriptor and save caller data */
3057d607c6aSLEROY Christophe 	if (is_sec1) {
3067d607c6aSLEROY Christophe 		desc->hdr1 = desc->hdr;
3077d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, &desc->hdr1,
3087d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
3099c4a7965SKim Phillips 						   DMA_BIDIRECTIONAL);
3107d607c6aSLEROY Christophe 	} else {
3117d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, desc,
3127d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
3137d607c6aSLEROY Christophe 						   DMA_BIDIRECTIONAL);
3147d607c6aSLEROY Christophe 	}
3159c4a7965SKim Phillips 	request->callback = callback;
3169c4a7965SKim Phillips 	request->context = context;
3179c4a7965SKim Phillips 
3189c4a7965SKim Phillips 	/* increment fifo head */
3194b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
3209c4a7965SKim Phillips 
3219c4a7965SKim Phillips 	smp_wmb();
3229c4a7965SKim Phillips 	request->desc = desc;
3239c4a7965SKim Phillips 
3249c4a7965SKim Phillips 	/* GO! */
3259c4a7965SKim Phillips 	wmb();
326ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
327ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
328ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
329a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
3309c4a7965SKim Phillips 
3314b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3329c4a7965SKim Phillips 
3339c4a7965SKim Phillips 	return -EINPROGRESS;
3349c4a7965SKim Phillips }
335865d5061SHoria Geanta EXPORT_SYMBOL(talitos_submit);
3369c4a7965SKim Phillips 
3379c4a7965SKim Phillips /*
3389c4a7965SKim Phillips  * process what was done, notify callback of error if not
3399c4a7965SKim Phillips  */
3409c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3419c4a7965SKim Phillips {
3429c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3439c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
3449c4a7965SKim Phillips 	unsigned long flags;
3459c4a7965SKim Phillips 	int tail, status;
3467d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3479c4a7965SKim Phillips 
3484b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3499c4a7965SKim Phillips 
3504b992628SKim Phillips 	tail = priv->chan[ch].tail;
3514b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
3527d607c6aSLEROY Christophe 		__be32 hdr;
3537d607c6aSLEROY Christophe 
3544b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
3559c4a7965SKim Phillips 
3569c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
3579c4a7965SKim Phillips 		rmb();
35837b5e889SLEROY Christophe 		if (!is_sec1)
35937b5e889SLEROY Christophe 			hdr = request->desc->hdr;
36037b5e889SLEROY Christophe 		else if (request->desc->next_desc)
36137b5e889SLEROY Christophe 			hdr = (request->desc + 1)->hdr1;
36237b5e889SLEROY Christophe 		else
36337b5e889SLEROY Christophe 			hdr = request->desc->hdr1;
3647d607c6aSLEROY Christophe 
3657d607c6aSLEROY Christophe 		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3669c4a7965SKim Phillips 			status = 0;
367ca38a814SLee Nipper 		else
3689c4a7965SKim Phillips 			if (!error)
3699c4a7965SKim Phillips 				break;
3709c4a7965SKim Phillips 			else
3719c4a7965SKim Phillips 				status = error;
3729c4a7965SKim Phillips 
3739c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
3747d607c6aSLEROY Christophe 				 TALITOS_DESC_SIZE,
375e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
3769c4a7965SKim Phillips 
3779c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
3789c4a7965SKim Phillips 		saved_req.desc = request->desc;
3799c4a7965SKim Phillips 		saved_req.callback = request->callback;
3809c4a7965SKim Phillips 		saved_req.context = request->context;
3819c4a7965SKim Phillips 
3829c4a7965SKim Phillips 		/* release request entry in fifo */
3839c4a7965SKim Phillips 		smp_wmb();
3849c4a7965SKim Phillips 		request->desc = NULL;
3859c4a7965SKim Phillips 
3869c4a7965SKim Phillips 		/* increment fifo tail */
3874b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3889c4a7965SKim Phillips 
3894b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
390ec6644d6SKim Phillips 
3914b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
392ec6644d6SKim Phillips 
3939c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
3949c4a7965SKim Phillips 				   status);
3959c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
3969c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
3979c4a7965SKim Phillips 			return;
3984b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3994b992628SKim Phillips 		tail = priv->chan[ch].tail;
4009c4a7965SKim Phillips 	}
4019c4a7965SKim Phillips 
4024b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
4039c4a7965SKim Phillips }
4049c4a7965SKim Phillips 
4059c4a7965SKim Phillips /*
4069c4a7965SKim Phillips  * process completed requests for channels that have done status
4079c4a7965SKim Phillips  */
408dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask)				\
409dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data)			\
410dd3c0987SLEROY Christophe {									\
411dd3c0987SLEROY Christophe 	struct device *dev = (struct device *)data;			\
412dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		\
413dd3c0987SLEROY Christophe 	unsigned long flags;						\
414dd3c0987SLEROY Christophe 									\
415dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x10000000)					\
416dd3c0987SLEROY Christophe 		flush_channel(dev, 0, 0, 0);			\
417dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x40000000)					\
418dd3c0987SLEROY Christophe 		flush_channel(dev, 1, 0, 0);			\
419dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00010000)					\
420dd3c0987SLEROY Christophe 		flush_channel(dev, 2, 0, 0);			\
421dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00040000)					\
422dd3c0987SLEROY Christophe 		flush_channel(dev, 3, 0, 0);			\
423dd3c0987SLEROY Christophe 									\
424dd3c0987SLEROY Christophe 	/* At this point, all completed channels have been processed */	\
425dd3c0987SLEROY Christophe 	/* Unmask done interrupts for channels completed later on. */	\
426dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			\
427dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
428dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
429dd3c0987SLEROY Christophe 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
430dd3c0987SLEROY Christophe }
431dd3c0987SLEROY Christophe 
432dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
4339c02e285SLEROY Christophe DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
434dd3c0987SLEROY Christophe 
435dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask)				\
436dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data)			\
437c3e337f8SKim Phillips {									\
438c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
439c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
440511d63cbSHoria Geanta 	unsigned long flags;						\
441c3e337f8SKim Phillips 									\
442c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
443c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
444c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
445c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
446c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
447c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
448c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
449c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
450c3e337f8SKim Phillips 									\
451c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
452c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
453511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
454c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
455dd3c0987SLEROY Christophe 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
456511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4579c4a7965SKim Phillips }
458dd3c0987SLEROY Christophe 
459dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
4609c02e285SLEROY Christophe DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
461dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
462dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4639c4a7965SKim Phillips 
4649c4a7965SKim Phillips /*
4659c4a7965SKim Phillips  * locate current (offending) descriptor
4669c4a7965SKim Phillips  */
4673e721aebSKim Phillips static u32 current_desc_hdr(struct device *dev, int ch)
4689c4a7965SKim Phillips {
4699c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
470b62ffd8cSHoria Geanta 	int tail, iter;
4719c4a7965SKim Phillips 	dma_addr_t cur_desc;
4729c4a7965SKim Phillips 
473b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
474b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4759c4a7965SKim Phillips 
476b62ffd8cSHoria Geanta 	if (!cur_desc) {
477b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
478b62ffd8cSHoria Geanta 		return 0;
479b62ffd8cSHoria Geanta 	}
480b62ffd8cSHoria Geanta 
481b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
482b62ffd8cSHoria Geanta 
483b62ffd8cSHoria Geanta 	iter = tail;
48437b5e889SLEROY Christophe 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc &&
48537b5e889SLEROY Christophe 	       priv->chan[ch].fifo[iter].desc->next_desc != cur_desc) {
486b62ffd8cSHoria Geanta 		iter = (iter + 1) & (priv->fifo_len - 1);
487b62ffd8cSHoria Geanta 		if (iter == tail) {
4889c4a7965SKim Phillips 			dev_err(dev, "couldn't locate current descriptor\n");
4893e721aebSKim Phillips 			return 0;
4909c4a7965SKim Phillips 		}
4919c4a7965SKim Phillips 	}
4929c4a7965SKim Phillips 
49337b5e889SLEROY Christophe 	if (priv->chan[ch].fifo[iter].desc->next_desc == cur_desc)
49437b5e889SLEROY Christophe 		return (priv->chan[ch].fifo[iter].desc + 1)->hdr;
49537b5e889SLEROY Christophe 
496b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
4979c4a7965SKim Phillips }
4989c4a7965SKim Phillips 
4999c4a7965SKim Phillips /*
5009c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
5019c4a7965SKim Phillips  */
5023e721aebSKim Phillips static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
5039c4a7965SKim Phillips {
5049c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5059c4a7965SKim Phillips 	int i;
5069c4a7965SKim Phillips 
5073e721aebSKim Phillips 	if (!desc_hdr)
508ad42d5fcSKim Phillips 		desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
5093e721aebSKim Phillips 
5103e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
5119c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
5129c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
5135fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR),
5145fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
5159c4a7965SKim Phillips 		break;
5169c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
5179c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
5185fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR),
5195fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
5209c4a7965SKim Phillips 		break;
5219c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
5229c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
5239c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5245fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5255fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5269c4a7965SKim Phillips 		break;
5279c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
5289c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
5295fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR),
5305fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5319c4a7965SKim Phillips 		break;
5329c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
5339c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5345fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5355fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5369c4a7965SKim Phillips 		break;
5379c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
5389c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5395fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR),
5405fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5419c4a7965SKim Phillips 		break;
5429c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
5439c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5445fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5455fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5469c4a7965SKim Phillips 		break;
5479c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
5489c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5495fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5505fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5519c4a7965SKim Phillips 		break;
5529c4a7965SKim Phillips 	}
5539c4a7965SKim Phillips 
5543e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5559c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
5569c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
5579c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5585fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5595fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5609c4a7965SKim Phillips 		break;
5619c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
5629c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5635fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5645fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5659c4a7965SKim Phillips 		break;
5669c4a7965SKim Phillips 	}
5679c4a7965SKim Phillips 
5689c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
5699c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
570ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
571ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5729c4a7965SKim Phillips }
5739c4a7965SKim Phillips 
5749c4a7965SKim Phillips /*
5759c4a7965SKim Phillips  * recover from error interrupts
5769c4a7965SKim Phillips  */
5775e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5789c4a7965SKim Phillips {
5799c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5809c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
581dd3c0987SLEROY Christophe 	int ch, error, reset_dev = 0;
58242e8b0d7SHoria Geant? 	u32 v_lo;
583dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
584dd3c0987SLEROY Christophe 	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5859c4a7965SKim Phillips 
5869c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
5879c4a7965SKim Phillips 		/* skip channels without errors */
588dd3c0987SLEROY Christophe 		if (is_sec1) {
589dd3c0987SLEROY Christophe 			/* bits 29, 31, 17, 19 */
590dd3c0987SLEROY Christophe 			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
591dd3c0987SLEROY Christophe 				continue;
592dd3c0987SLEROY Christophe 		} else {
5939c4a7965SKim Phillips 			if (!(isr & (1 << (ch * 2 + 1))))
5949c4a7965SKim Phillips 				continue;
595dd3c0987SLEROY Christophe 		}
5969c4a7965SKim Phillips 
5979c4a7965SKim Phillips 		error = -EINVAL;
5989c4a7965SKim Phillips 
599ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
6009c4a7965SKim Phillips 
6019c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
6029c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
6039c4a7965SKim Phillips 			error = -EAGAIN;
6049c4a7965SKim Phillips 			reset_ch = 1;
6059c4a7965SKim Phillips 		}
6069c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
6079c4a7965SKim Phillips 			/* h/w dropped descriptor */
6089c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
6099c4a7965SKim Phillips 			error = -EAGAIN;
6109c4a7965SKim Phillips 		}
6119c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
6129c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
6139c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
6144d9b3a5bSColin Ian King 			dev_err(dev, is_sec1 ? "pointer not complete error\n"
615dd3c0987SLEROY Christophe 					     : "s/g data length zero error\n");
6169c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
617dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "parity error\n"
618dd3c0987SLEROY Christophe 					     : "fetch pointer zero error\n");
6199c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
6209c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
6219c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
622dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "static assignment error\n"
623dd3c0987SLEROY Christophe 					     : "invalid exec unit error\n");
6249c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
6253e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
626dd3c0987SLEROY Christophe 		if (!is_sec1) {
6279c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GB)
6289c4a7965SKim Phillips 				dev_err(dev, "gather boundary error\n");
6299c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GRL)
6309c4a7965SKim Phillips 				dev_err(dev, "gather return/length error\n");
6319c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SB)
6329c4a7965SKim Phillips 				dev_err(dev, "scatter boundary error\n");
6339c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SRL)
6349c4a7965SKim Phillips 				dev_err(dev, "scatter return/length error\n");
635dd3c0987SLEROY Christophe 		}
6369c4a7965SKim Phillips 
6379c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
6389c4a7965SKim Phillips 
6399c4a7965SKim Phillips 		if (reset_ch) {
6409c4a7965SKim Phillips 			reset_channel(dev, ch);
6419c4a7965SKim Phillips 		} else {
642ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
643dd3c0987SLEROY Christophe 				  TALITOS2_CCCR_CONT);
644ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
645ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
646dd3c0987SLEROY Christophe 			       TALITOS2_CCCR_CONT) && --timeout)
6479c4a7965SKim Phillips 				cpu_relax();
6489c4a7965SKim Phillips 			if (timeout == 0) {
6499c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
6509c4a7965SKim Phillips 					ch);
6519c4a7965SKim Phillips 				reset_dev = 1;
6529c4a7965SKim Phillips 			}
6539c4a7965SKim Phillips 		}
6549c4a7965SKim Phillips 	}
655dd3c0987SLEROY Christophe 	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
656dd3c0987SLEROY Christophe 	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
657dd3c0987SLEROY Christophe 		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
658dd3c0987SLEROY Christophe 			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
659dd3c0987SLEROY Christophe 				isr, isr_lo);
660dd3c0987SLEROY Christophe 		else
661dd3c0987SLEROY Christophe 			dev_err(dev, "done overflow, internal time out, or "
662dd3c0987SLEROY Christophe 				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6639c4a7965SKim Phillips 
6649c4a7965SKim Phillips 		/* purge request queues */
6659c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
6669c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
6679c4a7965SKim Phillips 
6689c4a7965SKim Phillips 		/* reset and reinitialize the device */
6699c4a7965SKim Phillips 		init_device(dev);
6709c4a7965SKim Phillips 	}
6719c4a7965SKim Phillips }
6729c4a7965SKim Phillips 
673dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
674dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
675dd3c0987SLEROY Christophe {									       \
676dd3c0987SLEROY Christophe 	struct device *dev = data;					       \
677dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
678dd3c0987SLEROY Christophe 	u32 isr, isr_lo;						       \
679dd3c0987SLEROY Christophe 	unsigned long flags;						       \
680dd3c0987SLEROY Christophe 									       \
681dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
682dd3c0987SLEROY Christophe 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
683dd3c0987SLEROY Christophe 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
684dd3c0987SLEROY Christophe 	/* Acknowledge interrupt */					       \
685dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
686dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
687dd3c0987SLEROY Christophe 									       \
688dd3c0987SLEROY Christophe 	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
689dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
690dd3c0987SLEROY Christophe 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
691dd3c0987SLEROY Christophe 	}								       \
692dd3c0987SLEROY Christophe 	else {								       \
693dd3c0987SLEROY Christophe 		if (likely(isr & ch_done_mask)) {			       \
694dd3c0987SLEROY Christophe 			/* mask further done interrupts. */		       \
695dd3c0987SLEROY Christophe 			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
696dd3c0987SLEROY Christophe 			/* done_task will unmask done interrupts at exit */    \
697dd3c0987SLEROY Christophe 			tasklet_schedule(&priv->done_task[tlet]);	       \
698dd3c0987SLEROY Christophe 		}							       \
699dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
700dd3c0987SLEROY Christophe 	}								       \
701dd3c0987SLEROY Christophe 									       \
702dd3c0987SLEROY Christophe 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
703dd3c0987SLEROY Christophe 								IRQ_NONE;      \
704dd3c0987SLEROY Christophe }
705dd3c0987SLEROY Christophe 
706dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
707dd3c0987SLEROY Christophe 
708dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
709dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
710c3e337f8SKim Phillips {									       \
711c3e337f8SKim Phillips 	struct device *dev = data;					       \
712c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
713c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
714511d63cbSHoria Geanta 	unsigned long flags;						       \
715c3e337f8SKim Phillips 									       \
716511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
717c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
718c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
719c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
720c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
721c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
722c3e337f8SKim Phillips 									       \
723511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
724511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
725511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
726511d63cbSHoria Geanta 	}								       \
727511d63cbSHoria Geanta 	else {								       \
728c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
729c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
730c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
731c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
732c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
733c3e337f8SKim Phillips 		}							       \
734511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
735511d63cbSHoria Geanta 	}								       \
736c3e337f8SKim Phillips 									       \
737c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
738c3e337f8SKim Phillips 								IRQ_NONE;      \
7391c2e8811SLee Nipper }
740dd3c0987SLEROY Christophe 
741dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
742dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
743dd3c0987SLEROY Christophe 		       0)
744dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
745dd3c0987SLEROY Christophe 		       1)
7469c4a7965SKim Phillips 
7479c4a7965SKim Phillips /*
7489c4a7965SKim Phillips  * hwrng
7499c4a7965SKim Phillips  */
7509c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
7519c4a7965SKim Phillips {
7529c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7539c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7549c4a7965SKim Phillips 	u32 ofl;
7559c4a7965SKim Phillips 	int i;
7569c4a7965SKim Phillips 
7579c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
7585fa7fa14SLEROY Christophe 		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7599c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
7609c4a7965SKim Phillips 		if (ofl || !wait)
7619c4a7965SKim Phillips 			break;
7629c4a7965SKim Phillips 		udelay(10);
7639c4a7965SKim Phillips 	}
7649c4a7965SKim Phillips 
7659c4a7965SKim Phillips 	return !!ofl;
7669c4a7965SKim Phillips }
7679c4a7965SKim Phillips 
7689c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7699c4a7965SKim Phillips {
7709c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7719c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7729c4a7965SKim Phillips 
7739c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
7745fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7755fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7769c4a7965SKim Phillips 
7779c4a7965SKim Phillips 	return sizeof(u32);
7789c4a7965SKim Phillips }
7799c4a7965SKim Phillips 
7809c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
7819c4a7965SKim Phillips {
7829c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7839c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7849c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
7859c4a7965SKim Phillips 
7865fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7875fa7fa14SLEROY Christophe 	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7885fa7fa14SLEROY Christophe 		 & TALITOS_RNGUSR_LO_RD)
7899c4a7965SKim Phillips 	       && --timeout)
7909c4a7965SKim Phillips 		cpu_relax();
7919c4a7965SKim Phillips 	if (timeout == 0) {
7929c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
7939c4a7965SKim Phillips 		return -ENODEV;
7949c4a7965SKim Phillips 	}
7959c4a7965SKim Phillips 
7969c4a7965SKim Phillips 	/* start generating */
7975fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
7989c4a7965SKim Phillips 
7999c4a7965SKim Phillips 	return 0;
8009c4a7965SKim Phillips }
8019c4a7965SKim Phillips 
8029c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
8039c4a7965SKim Phillips {
8049c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
80535a3bb3dSAaron Sierra 	int err;
8069c4a7965SKim Phillips 
8079c4a7965SKim Phillips 	priv->rng.name		= dev_driver_string(dev),
8089c4a7965SKim Phillips 	priv->rng.init		= talitos_rng_init,
8099c4a7965SKim Phillips 	priv->rng.data_present	= talitos_rng_data_present,
8109c4a7965SKim Phillips 	priv->rng.data_read	= talitos_rng_data_read,
8119c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
8129c4a7965SKim Phillips 
81335a3bb3dSAaron Sierra 	err = hwrng_register(&priv->rng);
81435a3bb3dSAaron Sierra 	if (!err)
81535a3bb3dSAaron Sierra 		priv->rng_registered = true;
81635a3bb3dSAaron Sierra 
81735a3bb3dSAaron Sierra 	return err;
8189c4a7965SKim Phillips }
8199c4a7965SKim Phillips 
8209c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
8219c4a7965SKim Phillips {
8229c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
8239c4a7965SKim Phillips 
82435a3bb3dSAaron Sierra 	if (!priv->rng_registered)
82535a3bb3dSAaron Sierra 		return;
82635a3bb3dSAaron Sierra 
8279c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
82835a3bb3dSAaron Sierra 	priv->rng_registered = false;
8299c4a7965SKim Phillips }
8309c4a7965SKim Phillips 
8319c4a7965SKim Phillips /*
8329c4a7965SKim Phillips  * crypto alg
8339c4a7965SKim Phillips  */
8349c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
8357405c8d7SLEROY Christophe /*
8367405c8d7SLEROY Christophe  * Defines a priority for doing AEAD with descriptors type
8377405c8d7SLEROY Christophe  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
8387405c8d7SLEROY Christophe  */
8397405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
840b8fbdc2bSChristophe Leroy #ifdef CONFIG_CRYPTO_DEV_TALITOS_SEC2
84103d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
842b8fbdc2bSChristophe Leroy #else
843b8fbdc2bSChristophe Leroy #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE)
844b8fbdc2bSChristophe Leroy #endif
8453952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
84670bcaca7SLee Nipper 
8479c4a7965SKim Phillips struct talitos_ctx {
8489c4a7965SKim Phillips 	struct device *dev;
8495228f0f7SKim Phillips 	int ch;
8509c4a7965SKim Phillips 	__be32 desc_hdr_template;
8519c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
85270bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8532e13ce08SLEROY Christophe 	dma_addr_t dma_key;
8549c4a7965SKim Phillips 	unsigned int keylen;
8559c4a7965SKim Phillips 	unsigned int enckeylen;
8569c4a7965SKim Phillips 	unsigned int authkeylen;
8579c4a7965SKim Phillips };
8589c4a7965SKim Phillips 
859497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
860497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
861497f2e6bSLee Nipper 
862497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
86360f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
864497f2e6bSLee Nipper 	unsigned int hw_context_size;
8653c0dd190SLEROY Christophe 	u8 buf[2][HASH_MAX_BLOCK_SIZE];
8663c0dd190SLEROY Christophe 	int buf_idx;
86760f208d7SKim Phillips 	unsigned int swinit;
868497f2e6bSLee Nipper 	unsigned int first;
869497f2e6bSLee Nipper 	unsigned int last;
870497f2e6bSLee Nipper 	unsigned int to_hash_later;
87142e8b0d7SHoria Geant? 	unsigned int nbuf;
872497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
873497f2e6bSLee Nipper 	struct scatterlist *psrc;
874497f2e6bSLee Nipper };
875497f2e6bSLee Nipper 
8763639ca84SHoria Geant? struct talitos_export_state {
8773639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8783639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8793639ca84SHoria Geant? 	unsigned int swinit;
8803639ca84SHoria Geant? 	unsigned int first;
8813639ca84SHoria Geant? 	unsigned int last;
8823639ca84SHoria Geant? 	unsigned int to_hash_later;
8833639ca84SHoria Geant? 	unsigned int nbuf;
8843639ca84SHoria Geant? };
8853639ca84SHoria Geant? 
88656af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8879c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8889c4a7965SKim Phillips {
8899c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
8902e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
891c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8929c4a7965SKim Phillips 
893c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8949c4a7965SKim Phillips 		goto badkey;
8959c4a7965SKim Phillips 
896c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8979c4a7965SKim Phillips 		goto badkey;
8989c4a7965SKim Phillips 
8992e13ce08SLEROY Christophe 	if (ctx->keylen)
9002e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
9012e13ce08SLEROY Christophe 
902c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
903c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
9049c4a7965SKim Phillips 
905c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
906c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
907c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
9082e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
9092e13ce08SLEROY Christophe 				      DMA_TO_DEVICE);
9109c4a7965SKim Phillips 
9118f0691fcSTudor-Dan Ambarus 	memzero_explicit(&keys, sizeof(keys));
9129c4a7965SKim Phillips 	return 0;
9139c4a7965SKim Phillips 
9149c4a7965SKim Phillips badkey:
9159c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
9168f0691fcSTudor-Dan Ambarus 	memzero_explicit(&keys, sizeof(keys));
9179c4a7965SKim Phillips 	return -EINVAL;
9189c4a7965SKim Phillips }
9199c4a7965SKim Phillips 
920ef7c5c85SHerbert Xu static int aead_des3_setkey(struct crypto_aead *authenc,
921ef7c5c85SHerbert Xu 			    const u8 *key, unsigned int keylen)
922ef7c5c85SHerbert Xu {
923ef7c5c85SHerbert Xu 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
924ef7c5c85SHerbert Xu 	struct device *dev = ctx->dev;
925ef7c5c85SHerbert Xu 	struct crypto_authenc_keys keys;
926ef7c5c85SHerbert Xu 	u32 flags;
927ef7c5c85SHerbert Xu 	int err;
928ef7c5c85SHerbert Xu 
929ef7c5c85SHerbert Xu 	err = crypto_authenc_extractkeys(&keys, key, keylen);
930ef7c5c85SHerbert Xu 	if (unlikely(err))
931ef7c5c85SHerbert Xu 		goto badkey;
932ef7c5c85SHerbert Xu 
933ef7c5c85SHerbert Xu 	err = -EINVAL;
934ef7c5c85SHerbert Xu 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
935ef7c5c85SHerbert Xu 		goto badkey;
936ef7c5c85SHerbert Xu 
937ef7c5c85SHerbert Xu 	if (keys.enckeylen != DES3_EDE_KEY_SIZE)
938ef7c5c85SHerbert Xu 		goto badkey;
939ef7c5c85SHerbert Xu 
940ef7c5c85SHerbert Xu 	flags = crypto_aead_get_flags(authenc);
941ef7c5c85SHerbert Xu 	err = __des3_verify_key(&flags, keys.enckey);
942ef7c5c85SHerbert Xu 	if (unlikely(err)) {
943ef7c5c85SHerbert Xu 		crypto_aead_set_flags(authenc, flags);
944ef7c5c85SHerbert Xu 		goto out;
945ef7c5c85SHerbert Xu 	}
946ef7c5c85SHerbert Xu 
947ef7c5c85SHerbert Xu 	if (ctx->keylen)
948ef7c5c85SHerbert Xu 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
949ef7c5c85SHerbert Xu 
950ef7c5c85SHerbert Xu 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
951ef7c5c85SHerbert Xu 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
952ef7c5c85SHerbert Xu 
953ef7c5c85SHerbert Xu 	ctx->keylen = keys.authkeylen + keys.enckeylen;
954ef7c5c85SHerbert Xu 	ctx->enckeylen = keys.enckeylen;
955ef7c5c85SHerbert Xu 	ctx->authkeylen = keys.authkeylen;
956ef7c5c85SHerbert Xu 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
957ef7c5c85SHerbert Xu 				      DMA_TO_DEVICE);
958ef7c5c85SHerbert Xu 
959ef7c5c85SHerbert Xu out:
960ef7c5c85SHerbert Xu 	memzero_explicit(&keys, sizeof(keys));
961ef7c5c85SHerbert Xu 	return err;
962ef7c5c85SHerbert Xu 
963ef7c5c85SHerbert Xu badkey:
964ef7c5c85SHerbert Xu 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
965ef7c5c85SHerbert Xu 	goto out;
966ef7c5c85SHerbert Xu }
967ef7c5c85SHerbert Xu 
9689c4a7965SKim Phillips /*
96956af8cd4SLee Nipper  * talitos_edesc - s/w-extended descriptor
9709c4a7965SKim Phillips  * @src_nents: number of segments in input scatterlist
9719c4a7965SKim Phillips  * @dst_nents: number of segments in output scatterlist
972aeb4c132SHerbert Xu  * @icv_ool: whether ICV is out-of-line
97379fd31d3SHoria Geanta  * @iv_dma: dma address of iv for checking continuity and link table
9749c4a7965SKim Phillips  * @dma_len: length of dma mapped link_tbl space
9756f65f6acSLEROY Christophe  * @dma_link_tbl: bus physical address of link_tbl/buf
9769c4a7965SKim Phillips  * @desc: h/w descriptor
9776f65f6acSLEROY Christophe  * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
9786f65f6acSLEROY Christophe  * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
9799c4a7965SKim Phillips  *
9809c4a7965SKim Phillips  * if decrypting (with authcheck), or either one of src_nents or dst_nents
9819c4a7965SKim Phillips  * is greater than 1, an integrity check value is concatenated to the end
9829c4a7965SKim Phillips  * of link_tbl data
9839c4a7965SKim Phillips  */
98456af8cd4SLee Nipper struct talitos_edesc {
9859c4a7965SKim Phillips 	int src_nents;
9869c4a7965SKim Phillips 	int dst_nents;
987aeb4c132SHerbert Xu 	bool icv_ool;
98879fd31d3SHoria Geanta 	dma_addr_t iv_dma;
9899c4a7965SKim Phillips 	int dma_len;
9909c4a7965SKim Phillips 	dma_addr_t dma_link_tbl;
9919c4a7965SKim Phillips 	struct talitos_desc desc;
9926f65f6acSLEROY Christophe 	union {
9939c4a7965SKim Phillips 		struct talitos_ptr link_tbl[0];
9946f65f6acSLEROY Christophe 		u8 buf[0];
9956f65f6acSLEROY Christophe 	};
9969c4a7965SKim Phillips };
9979c4a7965SKim Phillips 
9984de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9994de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
10004de9d0b5SLee Nipper 			     struct scatterlist *src,
10016a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
10026a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
1003246a87cdSLEROY Christophe {
1004246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1005246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10066a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
10076a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
1008246a87cdSLEROY Christophe 
10096a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
10106a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
1011246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
10126a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
10136a1e8d14SLEROY Christophe 				     offset);
1014246a87cdSLEROY Christophe 	}
10156a1e8d14SLEROY Christophe 	if (src != dst) {
10166a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
10176a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
10186a1e8d14SLEROY Christophe 
10196a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
10206a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
10216a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
10226a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
1023246a87cdSLEROY Christophe 	}
1024246a87cdSLEROY Christophe }
1025246a87cdSLEROY Christophe 
10269c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
102756af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
10287ede4c36SChristophe Leroy 			    struct aead_request *areq, bool encrypt)
10299c4a7965SKim Phillips {
1030549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1031549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
1032549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
10337ede4c36SChristophe Leroy 	unsigned int authsize = crypto_aead_authsize(aead);
10347ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
10359a655608SLEROY Christophe 	bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
10369a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
1037549bd8bcSLEROY Christophe 
10389a655608SLEROY Christophe 	if (is_ipsec_esp)
1039549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
1040549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
10419a655608SLEROY Christophe 	unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
10429c4a7965SKim Phillips 
10437ede4c36SChristophe Leroy 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, cryptlen,
10446a1e8d14SLEROY Christophe 			 areq->assoclen);
10459c4a7965SKim Phillips 
10469c4a7965SKim Phillips 	if (edesc->dma_len)
10479c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
10489c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
1049549bd8bcSLEROY Christophe 
10509a655608SLEROY Christophe 	if (!is_ipsec_esp) {
1051549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
1052549bd8bcSLEROY Christophe 
1053549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
10547ede4c36SChristophe Leroy 				   areq->assoclen + cryptlen - ivsize);
1055549bd8bcSLEROY Christophe 	}
10569c4a7965SKim Phillips }
10579c4a7965SKim Phillips 
10589c4a7965SKim Phillips /*
10599c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
10609c4a7965SKim Phillips  */
10619c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
10629c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
10639c4a7965SKim Phillips 				   int err)
10649c4a7965SKim Phillips {
1065549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1066549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10679c4a7965SKim Phillips 	struct aead_request *areq = context;
10689c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1069aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
10702e13ce08SLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(authenc);
107119bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10729c4a7965SKim Phillips 	struct scatterlist *sg;
10739c4a7965SKim Phillips 	void *icvdata;
10749c4a7965SKim Phillips 
107519bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
107619bbbc63SKim Phillips 
10777ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, areq, true);
10789c4a7965SKim Phillips 
10799c4a7965SKim Phillips 	/* copy the generated ICV to dst */
1080aeb4c132SHerbert Xu 	if (edesc->icv_ool) {
1081549bd8bcSLEROY Christophe 		if (is_sec1)
1082549bd8bcSLEROY Christophe 			icvdata = edesc->buf + areq->assoclen + areq->cryptlen;
1083549bd8bcSLEROY Christophe 		else
10849c4a7965SKim Phillips 			icvdata = &edesc->link_tbl[edesc->src_nents +
1085aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
10869c4a7965SKim Phillips 		sg = sg_last(areq->dst, edesc->dst_nents);
1087aeb4c132SHerbert Xu 		memcpy((char *)sg_virt(sg) + sg->length - authsize,
1088aeb4c132SHerbert Xu 		       icvdata, authsize);
10899c4a7965SKim Phillips 	}
10909c4a7965SKim Phillips 
10912e13ce08SLEROY Christophe 	dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
10922e13ce08SLEROY Christophe 
10939c4a7965SKim Phillips 	kfree(edesc);
10949c4a7965SKim Phillips 
10959c4a7965SKim Phillips 	aead_request_complete(areq, err);
10969c4a7965SKim Phillips }
10979c4a7965SKim Phillips 
1098fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1099e938e465SKim Phillips 					  struct talitos_desc *desc,
1100e938e465SKim Phillips 					  void *context, int err)
11019c4a7965SKim Phillips {
11029c4a7965SKim Phillips 	struct aead_request *req = context;
11039c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1104aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
110519bbbc63SKim Phillips 	struct talitos_edesc *edesc;
11069c4a7965SKim Phillips 	struct scatterlist *sg;
1107aeb4c132SHerbert Xu 	char *oicv, *icv;
1108549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1109549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
11109c4a7965SKim Phillips 
111119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
111219bbbc63SKim Phillips 
11137ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, req, false);
11149c4a7965SKim Phillips 
11159c4a7965SKim Phillips 	if (!err) {
11169c4a7965SKim Phillips 		/* auth check */
11179c4a7965SKim Phillips 		sg = sg_last(req->dst, edesc->dst_nents ? : 1);
1118aeb4c132SHerbert Xu 		icv = (char *)sg_virt(sg) + sg->length - authsize;
1119aeb4c132SHerbert Xu 
1120aeb4c132SHerbert Xu 		if (edesc->dma_len) {
1121549bd8bcSLEROY Christophe 			if (is_sec1)
1122549bd8bcSLEROY Christophe 				oicv = (char *)&edesc->dma_link_tbl +
1123549bd8bcSLEROY Christophe 					       req->assoclen + req->cryptlen;
1124549bd8bcSLEROY Christophe 			else
1125549bd8bcSLEROY Christophe 				oicv = (char *)
1126549bd8bcSLEROY Christophe 				       &edesc->link_tbl[edesc->src_nents +
1127aeb4c132SHerbert Xu 							edesc->dst_nents + 2];
1128aeb4c132SHerbert Xu 			if (edesc->icv_ool)
1129aeb4c132SHerbert Xu 				icv = oicv + authsize;
1130aeb4c132SHerbert Xu 		} else
1131aeb4c132SHerbert Xu 			oicv = (char *)&edesc->link_tbl[0];
1132aeb4c132SHerbert Xu 
113379960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
11349c4a7965SKim Phillips 	}
11359c4a7965SKim Phillips 
11369c4a7965SKim Phillips 	kfree(edesc);
11379c4a7965SKim Phillips 
11389c4a7965SKim Phillips 	aead_request_complete(req, err);
11399c4a7965SKim Phillips }
11409c4a7965SKim Phillips 
1141fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1142e938e465SKim Phillips 					  struct talitos_desc *desc,
1143e938e465SKim Phillips 					  void *context, int err)
1144fe5720e2SKim Phillips {
1145fe5720e2SKim Phillips 	struct aead_request *req = context;
114619bbbc63SKim Phillips 	struct talitos_edesc *edesc;
114719bbbc63SKim Phillips 
114819bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1149fe5720e2SKim Phillips 
11507ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, req, false);
1151fe5720e2SKim Phillips 
1152fe5720e2SKim Phillips 	/* check ICV auth status */
1153e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1154e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1155fe5720e2SKim Phillips 		err = -EBADMSG;
1156fe5720e2SKim Phillips 
1157fe5720e2SKim Phillips 	kfree(edesc);
1158fe5720e2SKim Phillips 
1159fe5720e2SKim Phillips 	aead_request_complete(req, err);
1160fe5720e2SKim Phillips }
1161fe5720e2SKim Phillips 
11629c4a7965SKim Phillips /*
11639c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
11649c4a7965SKim Phillips  * stop at cryptlen bytes
11659c4a7965SKim Phillips  */
1166aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1167aeb4c132SHerbert Xu 				 unsigned int offset, int cryptlen,
1168aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
11699c4a7965SKim Phillips {
117070bcaca7SLee Nipper 	int n_sg = sg_count;
1171aeb4c132SHerbert Xu 	int count = 0;
117270bcaca7SLee Nipper 
1173aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1174aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1175aeb4c132SHerbert Xu 
1176aeb4c132SHerbert Xu 		if (offset >= len) {
1177aeb4c132SHerbert Xu 			offset -= len;
1178aeb4c132SHerbert Xu 			goto next;
1179aeb4c132SHerbert Xu 		}
1180aeb4c132SHerbert Xu 
1181aeb4c132SHerbert Xu 		len -= offset;
1182aeb4c132SHerbert Xu 
1183aeb4c132SHerbert Xu 		if (len > cryptlen)
1184aeb4c132SHerbert Xu 			len = cryptlen;
1185aeb4c132SHerbert Xu 
1186aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1187da9de146SLEROY Christophe 			       sg_dma_address(sg) + offset, len, 0);
1188b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1189aeb4c132SHerbert Xu 		count++;
1190aeb4c132SHerbert Xu 		cryptlen -= len;
1191aeb4c132SHerbert Xu 		offset = 0;
1192aeb4c132SHerbert Xu 
1193aeb4c132SHerbert Xu next:
11945be4d4c9SCristian Stoica 		sg = sg_next(sg);
11959c4a7965SKim Phillips 	}
11969c4a7965SKim Phillips 
11979c4a7965SKim Phillips 	/* tag end of link table */
1198aeb4c132SHerbert Xu 	if (count > 0)
1199b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1200b096b544SLEROY Christophe 				       DESC_PTR_LNKTBL_RETURN, 0);
120170bcaca7SLee Nipper 
1202aeb4c132SHerbert Xu 	return count;
1203aeb4c132SHerbert Xu }
1204aeb4c132SHerbert Xu 
12052b122730SLEROY Christophe static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
1206246a87cdSLEROY Christophe 			      unsigned int len, struct talitos_edesc *edesc,
12072b122730SLEROY Christophe 			      struct talitos_ptr *ptr, int sg_count,
12082b122730SLEROY Christophe 			      unsigned int offset, int tbl_off, int elen)
1209246a87cdSLEROY Christophe {
1210246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1211246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1212246a87cdSLEROY Christophe 
121387a81dceSLEROY Christophe 	if (!src) {
121487a81dceSLEROY Christophe 		to_talitos_ptr(ptr, 0, 0, is_sec1);
121587a81dceSLEROY Christophe 		return 1;
121687a81dceSLEROY Christophe 	}
12172b122730SLEROY Christophe 	to_talitos_ptr_ext_set(ptr, elen, is_sec1);
1218246a87cdSLEROY Christophe 	if (sg_count == 1) {
1219da9de146SLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1);
1220246a87cdSLEROY Christophe 		return sg_count;
1221246a87cdSLEROY Christophe 	}
1222246a87cdSLEROY Christophe 	if (is_sec1) {
1223da9de146SLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1);
12246a1e8d14SLEROY Christophe 		return sg_count;
1225246a87cdSLEROY Christophe 	}
12262b122730SLEROY Christophe 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len + elen,
12276a1e8d14SLEROY Christophe 					 &edesc->link_tbl[tbl_off]);
1228246a87cdSLEROY Christophe 	if (sg_count == 1) {
12296a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
12306a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
12316a1e8d14SLEROY Christophe 		return sg_count;
12326a1e8d14SLEROY Christophe 	}
1233246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
1234da9de146SLEROY Christophe 			    tbl_off * sizeof(struct talitos_ptr), len, is_sec1);
12356a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
12366a1e8d14SLEROY Christophe 
12376a1e8d14SLEROY Christophe 	return sg_count;
1238246a87cdSLEROY Christophe }
1239246a87cdSLEROY Christophe 
12402b122730SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src,
12412b122730SLEROY Christophe 			  unsigned int len, struct talitos_edesc *edesc,
12422b122730SLEROY Christophe 			  struct talitos_ptr *ptr, int sg_count,
12432b122730SLEROY Christophe 			  unsigned int offset, int tbl_off)
12442b122730SLEROY Christophe {
12452b122730SLEROY Christophe 	return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset,
12462b122730SLEROY Christophe 				  tbl_off, 0);
12472b122730SLEROY Christophe }
12482b122730SLEROY Christophe 
12499c4a7965SKim Phillips /*
12509c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
12519c4a7965SKim Phillips  */
125256af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
12537ede4c36SChristophe Leroy 		     bool encrypt,
1254aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
12559c4a7965SKim Phillips 				      struct talitos_desc *desc,
12569c4a7965SKim Phillips 				      void *context, int error))
12579c4a7965SKim Phillips {
12589c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1259aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
12609c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
12619c4a7965SKim Phillips 	struct device *dev = ctx->dev;
12629c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
12637ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
1264e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1265aeb4c132SHerbert Xu 	int tbl_off = 0;
1266fa86a267SKim Phillips 	int sg_count, ret;
12672b122730SLEROY Christophe 	int elen = 0;
1268549bd8bcSLEROY Christophe 	bool sync_needed = false;
1269549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1270549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
12719a655608SLEROY Christophe 	bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
12729a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
12739a655608SLEROY Christophe 	struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
12749c4a7965SKim Phillips 
12759c4a7965SKim Phillips 	/* hmac key */
12762e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1);
127779fd31d3SHoria Geanta 
1278549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1279549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1280549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1281549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1282549bd8bcSLEROY Christophe 	else
1283549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1284549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1285549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1286549bd8bcSLEROY Christophe 
12879c4a7965SKim Phillips 	/* hmac data */
1288549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1289549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
129079fd31d3SHoria Geanta 
1291549bd8bcSLEROY Christophe 	if (ret > 1) {
1292340ff60aSHoria Geant? 		tbl_off += ret;
1293549bd8bcSLEROY Christophe 		sync_needed = true;
129479fd31d3SHoria Geanta 	}
129579fd31d3SHoria Geanta 
12969c4a7965SKim Phillips 	/* cipher iv */
12979a655608SLEROY Christophe 	to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1);
12989c4a7965SKim Phillips 
12999c4a7965SKim Phillips 	/* cipher key */
13002e13ce08SLEROY Christophe 	to_talitos_ptr(ckey_ptr, ctx->dma_key  + ctx->authkeylen,
13012e13ce08SLEROY Christophe 		       ctx->enckeylen, is_sec1);
13029c4a7965SKim Phillips 
13039c4a7965SKim Phillips 	/*
13049c4a7965SKim Phillips 	 * cipher in
13059c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
13069c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
13079c4a7965SKim Phillips 	 * typically 12 for ipsec
13089c4a7965SKim Phillips 	 */
13092b122730SLEROY Christophe 	if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV))
13102b122730SLEROY Christophe 		elen = authsize;
1311549bd8bcSLEROY Christophe 
13122b122730SLEROY Christophe 	ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4],
13132b122730SLEROY Christophe 				 sg_count, areq->assoclen, tbl_off, elen);
1314549bd8bcSLEROY Christophe 
1315ec8c7d14SLEROY Christophe 	if (ret > 1) {
1316ec8c7d14SLEROY Christophe 		tbl_off += ret;
1317549bd8bcSLEROY Christophe 		sync_needed = true;
1318340ff60aSHoria Geant? 	}
13199c4a7965SKim Phillips 
13209c4a7965SKim Phillips 	/* cipher out */
1321549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1322549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1323549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1324549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1325549bd8bcSLEROY Christophe 	}
13269c4a7965SKim Phillips 
1327e04a61beSLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
1328e04a61beSLEROY Christophe 			     sg_count, areq->assoclen, tbl_off);
13299c4a7965SKim Phillips 
13309a655608SLEROY Christophe 	if (is_ipsec_esp)
1331549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1332aeb4c132SHerbert Xu 
1333e04a61beSLEROY Christophe 	/* ICV data */
1334e04a61beSLEROY Christophe 	if (ret > 1) {
1335e04a61beSLEROY Christophe 		tbl_off += ret;
1336549bd8bcSLEROY Christophe 		edesc->icv_ool = true;
1337549bd8bcSLEROY Christophe 		sync_needed = true;
1338549bd8bcSLEROY Christophe 
13399a655608SLEROY Christophe 		if (is_ipsec_esp) {
134079fd31d3SHoria Geanta 			struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1341549bd8bcSLEROY Christophe 			int offset = (edesc->src_nents + edesc->dst_nents + 2) *
1342549bd8bcSLEROY Christophe 				     sizeof(struct talitos_ptr) + authsize;
1343fe5720e2SKim Phillips 
1344f3c85bc1SLee Nipper 			/* Add an entry to the link table for ICV data */
1345e04a61beSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
1346549bd8bcSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN,
1347549bd8bcSLEROY Christophe 					       is_sec1);
13489c4a7965SKim Phillips 
13499c4a7965SKim Phillips 			/* icv data follows link tables */
1350549bd8bcSLEROY Christophe 			to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl + offset,
1351da9de146SLEROY Christophe 				       authsize, is_sec1);
1352e04a61beSLEROY Christophe 		} else {
1353e04a61beSLEROY Christophe 			dma_addr_t addr = edesc->dma_link_tbl;
1354e04a61beSLEROY Christophe 
1355e04a61beSLEROY Christophe 			if (is_sec1)
1356e04a61beSLEROY Christophe 				addr += areq->assoclen + cryptlen;
1357e04a61beSLEROY Christophe 			else
1358e04a61beSLEROY Christophe 				addr += sizeof(struct talitos_ptr) * tbl_off;
1359e04a61beSLEROY Christophe 
1360da9de146SLEROY Christophe 			to_talitos_ptr(&desc->ptr[6], addr, authsize, is_sec1);
1361549bd8bcSLEROY Christophe 		}
13629a655608SLEROY Christophe 	} else if (!is_ipsec_esp) {
1363e04a61beSLEROY Christophe 		ret = talitos_sg_map(dev, areq->dst, authsize, edesc,
1364e04a61beSLEROY Christophe 				     &desc->ptr[6], sg_count, areq->assoclen +
1365e04a61beSLEROY Christophe 							      cryptlen,
1366e04a61beSLEROY Christophe 				     tbl_off);
1367e04a61beSLEROY Christophe 		if (ret > 1) {
1368e04a61beSLEROY Christophe 			tbl_off += ret;
1369e04a61beSLEROY Christophe 			edesc->icv_ool = true;
1370e04a61beSLEROY Christophe 			sync_needed = true;
1371340ff60aSHoria Geant? 		} else {
1372549bd8bcSLEROY Christophe 			edesc->icv_ool = false;
1373549bd8bcSLEROY Christophe 		}
1374e04a61beSLEROY Christophe 	} else {
1375e04a61beSLEROY Christophe 		edesc->icv_ool = false;
1376340ff60aSHoria Geant? 	}
13779c4a7965SKim Phillips 
13789c4a7965SKim Phillips 	/* iv out */
13799a655608SLEROY Christophe 	if (is_ipsec_esp)
1380a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
13819c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
13829c4a7965SKim Phillips 
1383549bd8bcSLEROY Christophe 	if (sync_needed)
1384549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1385549bd8bcSLEROY Christophe 					   edesc->dma_len,
1386549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1387549bd8bcSLEROY Christophe 
13885228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1389fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
13907ede4c36SChristophe Leroy 		ipsec_esp_unmap(dev, edesc, areq, encrypt);
1391fa86a267SKim Phillips 		kfree(edesc);
1392fa86a267SKim Phillips 	}
1393fa86a267SKim Phillips 	return ret;
13949c4a7965SKim Phillips }
13959c4a7965SKim Phillips 
13969c4a7965SKim Phillips /*
139756af8cd4SLee Nipper  * allocate and map the extended descriptor
13989c4a7965SKim Phillips  */
13994de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
14004de9d0b5SLee Nipper 						 struct scatterlist *src,
14014de9d0b5SLee Nipper 						 struct scatterlist *dst,
140279fd31d3SHoria Geanta 						 u8 *iv,
140379fd31d3SHoria Geanta 						 unsigned int assoclen,
14044de9d0b5SLee Nipper 						 unsigned int cryptlen,
14054de9d0b5SLee Nipper 						 unsigned int authsize,
140679fd31d3SHoria Geanta 						 unsigned int ivsize,
14074de9d0b5SLee Nipper 						 int icv_stashing,
140862293a37SHoria Geanta 						 u32 cryptoflags,
140962293a37SHoria Geanta 						 bool encrypt)
14109c4a7965SKim Phillips {
141156af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14126a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
141379fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
14144de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1415586725f8SKim Phillips 		      GFP_ATOMIC;
14166f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
14176f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
14186f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
14199c4a7965SKim Phillips 
14206f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
14214de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
14229c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
14239c4a7965SKim Phillips 	}
14249c4a7965SKim Phillips 
142562293a37SHoria Geanta 	if (!dst || dst == src) {
14266a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
14276a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
14288e409fe1SLABBE Corentin 		if (src_nents < 0) {
14298e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
1430c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
14318e409fe1SLABBE Corentin 		}
14329c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
143362293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
14346a1e8d14SLEROY Christophe 		dst_len = 0;
143562293a37SHoria Geanta 	} else { /* dst && dst != src*/
14366a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
14376a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
14388e409fe1SLABBE Corentin 		if (src_nents < 0) {
14398e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
1440c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
14418e409fe1SLABBE Corentin 		}
144262293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
14436a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
14446a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
14458e409fe1SLABBE Corentin 		if (dst_nents < 0) {
14468e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
1447c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
14488e409fe1SLABBE Corentin 		}
1449695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
14509c4a7965SKim Phillips 	}
14519c4a7965SKim Phillips 
14529c4a7965SKim Phillips 	/*
14539c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1454aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1455aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
14569c4a7965SKim Phillips 	 */
145756af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1458aeb4c132SHerbert Xu 	if (src_nents || dst_nents) {
14596f65f6acSLEROY Christophe 		if (is_sec1)
14606a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
14616a1e8d14SLEROY Christophe 				  (dst_nents ? dst_len : 0);
14626f65f6acSLEROY Christophe 		else
1463aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1464aeb4c132SHerbert Xu 				  sizeof(struct talitos_ptr) + authsize * 2;
14659c4a7965SKim Phillips 		alloc_len += dma_len;
14669c4a7965SKim Phillips 	} else {
14679c4a7965SKim Phillips 		dma_len = 0;
14684de9d0b5SLee Nipper 		alloc_len += icv_stashing ? authsize : 0;
14699c4a7965SKim Phillips 	}
14709c4a7965SKim Phillips 
147137b5e889SLEROY Christophe 	/* if its a ahash, add space for a second desc next to the first one */
147237b5e889SLEROY Christophe 	if (is_sec1 && !dst)
147337b5e889SLEROY Christophe 		alloc_len += sizeof(struct talitos_desc);
14741bea445bSChristophe Leroy 	alloc_len += ivsize;
147537b5e889SLEROY Christophe 
1476586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
1477c56c2e17SChristophe Leroy 	if (!edesc)
1478c56c2e17SChristophe Leroy 		return ERR_PTR(-ENOMEM);
14791bea445bSChristophe Leroy 	if (ivsize) {
14801bea445bSChristophe Leroy 		iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
1481c56c2e17SChristophe Leroy 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
14821bea445bSChristophe Leroy 	}
1483e4a647c4SLEROY Christophe 	memset(&edesc->desc, 0, sizeof(edesc->desc));
14849c4a7965SKim Phillips 
14859c4a7965SKim Phillips 	edesc->src_nents = src_nents;
14869c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
148779fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
14889c4a7965SKim Phillips 	edesc->dma_len = dma_len;
148937b5e889SLEROY Christophe 	if (dma_len) {
149037b5e889SLEROY Christophe 		void *addr = &edesc->link_tbl[0];
149137b5e889SLEROY Christophe 
149237b5e889SLEROY Christophe 		if (is_sec1 && !dst)
149337b5e889SLEROY Christophe 			addr += sizeof(struct talitos_desc);
149437b5e889SLEROY Christophe 		edesc->dma_link_tbl = dma_map_single(dev, addr,
1495497f2e6bSLee Nipper 						     edesc->dma_len,
1496497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
149737b5e889SLEROY Christophe 	}
14989c4a7965SKim Phillips 	return edesc;
14999c4a7965SKim Phillips }
15009c4a7965SKim Phillips 
150179fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
150262293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
15034de9d0b5SLee Nipper {
15044de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1505aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
15064de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
150779fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
15087ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
15094de9d0b5SLee Nipper 
1510aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
15117ede4c36SChristophe Leroy 				   iv, areq->assoclen, cryptlen,
1512aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
151362293a37SHoria Geanta 				   areq->base.flags, encrypt);
15144de9d0b5SLee Nipper }
15154de9d0b5SLee Nipper 
151656af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
15179c4a7965SKim Phillips {
15189c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
15199c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
152056af8cd4SLee Nipper 	struct talitos_edesc *edesc;
15219c4a7965SKim Phillips 
15229c4a7965SKim Phillips 	/* allocate extended descriptor */
152362293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
15249c4a7965SKim Phillips 	if (IS_ERR(edesc))
15259c4a7965SKim Phillips 		return PTR_ERR(edesc);
15269c4a7965SKim Phillips 
15279c4a7965SKim Phillips 	/* set encrypt */
152870bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
15299c4a7965SKim Phillips 
15307ede4c36SChristophe Leroy 	return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done);
15319c4a7965SKim Phillips }
15329c4a7965SKim Phillips 
153356af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
15349c4a7965SKim Phillips {
15359c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1536aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
15379c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1538fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
153956af8cd4SLee Nipper 	struct talitos_edesc *edesc;
15409c4a7965SKim Phillips 	struct scatterlist *sg;
15419c4a7965SKim Phillips 	void *icvdata;
15429c4a7965SKim Phillips 
15439c4a7965SKim Phillips 	/* allocate extended descriptor */
154462293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
15459c4a7965SKim Phillips 	if (IS_ERR(edesc))
15469c4a7965SKim Phillips 		return PTR_ERR(edesc);
15479c4a7965SKim Phillips 
1548*4bbfb839SChristophe Leroy 	if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) &&
1549*4bbfb839SChristophe Leroy 	    (priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1550e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1551e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1552fe5720e2SKim Phillips 
1553fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1554e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1555e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1556fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1557fe5720e2SKim Phillips 
1558fe5720e2SKim Phillips 		/* reset integrity check result bits */
1559fe5720e2SKim Phillips 
15607ede4c36SChristophe Leroy 		return ipsec_esp(edesc, req, false,
15617ede4c36SChristophe Leroy 				 ipsec_esp_decrypt_hwauth_done);
1562e938e465SKim Phillips 	}
1563fe5720e2SKim Phillips 
1564fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1565fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1566fe5720e2SKim Phillips 
15679c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
15689c4a7965SKim Phillips 	if (edesc->dma_len)
1569aeb4c132SHerbert Xu 		icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1570aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
15719c4a7965SKim Phillips 	else
15729c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[0];
15739c4a7965SKim Phillips 
15749c4a7965SKim Phillips 	sg = sg_last(req->src, edesc->src_nents ? : 1);
15759c4a7965SKim Phillips 
1576aeb4c132SHerbert Xu 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
15779c4a7965SKim Phillips 
15787ede4c36SChristophe Leroy 	return ipsec_esp(edesc, req, false, ipsec_esp_decrypt_swauth_done);
15799c4a7965SKim Phillips }
15809c4a7965SKim Phillips 
15814de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
15824de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
15834de9d0b5SLee Nipper {
15844de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15852e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
1586f384cdc4SLEROY Christophe 
15872e13ce08SLEROY Christophe 	if (ctx->keylen)
15882e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
15892e13ce08SLEROY Christophe 
15904de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
15914de9d0b5SLee Nipper 	ctx->keylen = keylen;
15924de9d0b5SLee Nipper 
15932e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE);
15942e13ce08SLEROY Christophe 
15954de9d0b5SLee Nipper 	return 0;
15964de9d0b5SLee Nipper }
15974de9d0b5SLee Nipper 
1598ef7c5c85SHerbert Xu static int ablkcipher_des_setkey(struct crypto_ablkcipher *cipher,
1599ef7c5c85SHerbert Xu 				 const u8 *key, unsigned int keylen)
1600ef7c5c85SHerbert Xu {
1601ef7c5c85SHerbert Xu 	u32 tmp[DES_EXPKEY_WORDS];
1602ef7c5c85SHerbert Xu 
1603ef7c5c85SHerbert Xu 	if (unlikely(crypto_ablkcipher_get_flags(cipher) &
1604ef7c5c85SHerbert Xu 		     CRYPTO_TFM_REQ_FORBID_WEAK_KEYS) &&
1605ef7c5c85SHerbert Xu 	    !des_ekey(tmp, key)) {
1606ef7c5c85SHerbert Xu 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY);
1607ef7c5c85SHerbert Xu 		return -EINVAL;
1608ef7c5c85SHerbert Xu 	}
1609ef7c5c85SHerbert Xu 
1610ef7c5c85SHerbert Xu 	return ablkcipher_setkey(cipher, key, keylen);
1611ef7c5c85SHerbert Xu }
1612ef7c5c85SHerbert Xu 
1613ef7c5c85SHerbert Xu static int ablkcipher_des3_setkey(struct crypto_ablkcipher *cipher,
1614ef7c5c85SHerbert Xu 				  const u8 *key, unsigned int keylen)
1615ef7c5c85SHerbert Xu {
1616ef7c5c85SHerbert Xu 	u32 flags;
1617ef7c5c85SHerbert Xu 	int err;
1618ef7c5c85SHerbert Xu 
1619ef7c5c85SHerbert Xu 	flags = crypto_ablkcipher_get_flags(cipher);
1620ef7c5c85SHerbert Xu 	err = __des3_verify_key(&flags, key);
1621ef7c5c85SHerbert Xu 	if (unlikely(err)) {
1622ef7c5c85SHerbert Xu 		crypto_ablkcipher_set_flags(cipher, flags);
1623ef7c5c85SHerbert Xu 		return err;
1624ef7c5c85SHerbert Xu 	}
1625ef7c5c85SHerbert Xu 
1626ef7c5c85SHerbert Xu 	return ablkcipher_setkey(cipher, key, keylen);
1627ef7c5c85SHerbert Xu }
1628ef7c5c85SHerbert Xu 
16291ba34e71SChristophe Leroy static int ablkcipher_aes_setkey(struct crypto_ablkcipher *cipher,
16301ba34e71SChristophe Leroy 				  const u8 *key, unsigned int keylen)
16311ba34e71SChristophe Leroy {
16321ba34e71SChristophe Leroy 	if (keylen == AES_KEYSIZE_128 || keylen == AES_KEYSIZE_192 ||
16331ba34e71SChristophe Leroy 	    keylen == AES_KEYSIZE_256)
16341ba34e71SChristophe Leroy 		return ablkcipher_setkey(cipher, key, keylen);
16351ba34e71SChristophe Leroy 
16361ba34e71SChristophe Leroy 	crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
16371ba34e71SChristophe Leroy 
16381ba34e71SChristophe Leroy 	return -EINVAL;
16391ba34e71SChristophe Leroy }
16401ba34e71SChristophe Leroy 
16414de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
16424de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
16434de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
16444de9d0b5SLee Nipper {
16454de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1646032d197eSLEROY Christophe 
16476a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0);
16484de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
16494de9d0b5SLee Nipper 
16504de9d0b5SLee Nipper 	if (edesc->dma_len)
16514de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
16524de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
16534de9d0b5SLee Nipper }
16544de9d0b5SLee Nipper 
16554de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
16564de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
16574de9d0b5SLee Nipper 			    int err)
16584de9d0b5SLee Nipper {
16594de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
16603e03e792SChristophe Leroy 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16613e03e792SChristophe Leroy 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16623e03e792SChristophe Leroy 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
166319bbbc63SKim Phillips 	struct talitos_edesc *edesc;
166419bbbc63SKim Phillips 
166519bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
16664de9d0b5SLee Nipper 
16674de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
16683e03e792SChristophe Leroy 	memcpy(areq->info, ctx->iv, ivsize);
16694de9d0b5SLee Nipper 
16704de9d0b5SLee Nipper 	kfree(edesc);
16714de9d0b5SLee Nipper 
16724de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
16734de9d0b5SLee Nipper }
16744de9d0b5SLee Nipper 
16754de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
16764de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
16774de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
16784de9d0b5SLee Nipper 					     struct talitos_desc *desc,
16794de9d0b5SLee Nipper 					     void *context, int error))
16804de9d0b5SLee Nipper {
16814de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16824de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16834de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
16844de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
16854de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
168679fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
16874de9d0b5SLee Nipper 	int sg_count, ret;
16886a1e8d14SLEROY Christophe 	bool sync_needed = false;
1689922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1690922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
16914de9d0b5SLee Nipper 
16924de9d0b5SLee Nipper 	/* first DWORD empty */
16934de9d0b5SLee Nipper 
16944de9d0b5SLee Nipper 	/* cipher iv */
1695da9de146SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1);
16964de9d0b5SLee Nipper 
16974de9d0b5SLee Nipper 	/* cipher key */
16982e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1);
16994de9d0b5SLee Nipper 
17006a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
17016a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
17026a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
17036a1e8d14SLEROY Christophe 				  cryptlen);
17046a1e8d14SLEROY Christophe 	else
17056a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
17066a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
17076a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
17084de9d0b5SLee Nipper 	/*
17094de9d0b5SLee Nipper 	 * cipher in
17104de9d0b5SLee Nipper 	 */
17116a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
17126a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
17136a1e8d14SLEROY Christophe 	if (sg_count > 1)
17146a1e8d14SLEROY Christophe 		sync_needed = true;
17154de9d0b5SLee Nipper 
17164de9d0b5SLee Nipper 	/* cipher out */
17176a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
17186a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
17196a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
17206a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
17216a1e8d14SLEROY Christophe 	}
17226a1e8d14SLEROY Christophe 
17236a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
17246a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
17256a1e8d14SLEROY Christophe 	if (ret > 1)
17266a1e8d14SLEROY Christophe 		sync_needed = true;
17274de9d0b5SLee Nipper 
17284de9d0b5SLee Nipper 	/* iv out */
1729a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
17304de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
17314de9d0b5SLee Nipper 
17324de9d0b5SLee Nipper 	/* last DWORD empty */
17334de9d0b5SLee Nipper 
17346a1e8d14SLEROY Christophe 	if (sync_needed)
17356a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
17366a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
17376a1e8d14SLEROY Christophe 
17385228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
17394de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
17404de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
17414de9d0b5SLee Nipper 		kfree(edesc);
17424de9d0b5SLee Nipper 	}
17434de9d0b5SLee Nipper 	return ret;
17444de9d0b5SLee Nipper }
17454de9d0b5SLee Nipper 
1746e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
174762293a37SHoria Geanta 						    areq, bool encrypt)
17484de9d0b5SLee Nipper {
17494de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
17504de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
175179fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
17524de9d0b5SLee Nipper 
1753aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
175479fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
175562293a37SHoria Geanta 				   areq->base.flags, encrypt);
17564de9d0b5SLee Nipper }
17574de9d0b5SLee Nipper 
17584de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
17594de9d0b5SLee Nipper {
17604de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
17614de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
17624de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
1763ee483d32SChristophe Leroy 	unsigned int blocksize =
1764ee483d32SChristophe Leroy 			crypto_tfm_alg_blocksize(crypto_ablkcipher_tfm(cipher));
1765ee483d32SChristophe Leroy 
1766ee483d32SChristophe Leroy 	if (!areq->nbytes)
1767ee483d32SChristophe Leroy 		return 0;
1768ee483d32SChristophe Leroy 
1769ee483d32SChristophe Leroy 	if (areq->nbytes % blocksize)
1770ee483d32SChristophe Leroy 		return -EINVAL;
17714de9d0b5SLee Nipper 
17724de9d0b5SLee Nipper 	/* allocate extended descriptor */
177362293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
17744de9d0b5SLee Nipper 	if (IS_ERR(edesc))
17754de9d0b5SLee Nipper 		return PTR_ERR(edesc);
17764de9d0b5SLee Nipper 
17774de9d0b5SLee Nipper 	/* set encrypt */
17784de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
17794de9d0b5SLee Nipper 
1780febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
17814de9d0b5SLee Nipper }
17824de9d0b5SLee Nipper 
17834de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
17844de9d0b5SLee Nipper {
17854de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
17864de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
17874de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
1788ee483d32SChristophe Leroy 	unsigned int blocksize =
1789ee483d32SChristophe Leroy 			crypto_tfm_alg_blocksize(crypto_ablkcipher_tfm(cipher));
1790ee483d32SChristophe Leroy 
1791ee483d32SChristophe Leroy 	if (!areq->nbytes)
1792ee483d32SChristophe Leroy 		return 0;
1793ee483d32SChristophe Leroy 
1794ee483d32SChristophe Leroy 	if (areq->nbytes % blocksize)
1795ee483d32SChristophe Leroy 		return -EINVAL;
17964de9d0b5SLee Nipper 
17974de9d0b5SLee Nipper 	/* allocate extended descriptor */
179862293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
17994de9d0b5SLee Nipper 	if (IS_ERR(edesc))
18004de9d0b5SLee Nipper 		return PTR_ERR(edesc);
18014de9d0b5SLee Nipper 
18024de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
18034de9d0b5SLee Nipper 
1804febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
18054de9d0b5SLee Nipper }
18064de9d0b5SLee Nipper 
1807497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1808497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1809497f2e6bSLee Nipper 				       struct ahash_request *areq)
1810497f2e6bSLee Nipper {
1811497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1812ad4cd51fSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1813ad4cd51fSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1814ad4cd51fSLEROY Christophe 	struct talitos_desc *desc = &edesc->desc;
1815ad4cd51fSLEROY Christophe 	struct talitos_desc *desc2 = desc + 1;
1816ad4cd51fSLEROY Christophe 
1817ad4cd51fSLEROY Christophe 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1818ad4cd51fSLEROY Christophe 	if (desc->next_desc &&
1819ad4cd51fSLEROY Christophe 	    desc->ptr[5].ptr != desc2->ptr[5].ptr)
1820ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
1821497f2e6bSLee Nipper 
18226a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1823032d197eSLEROY Christophe 
1824ad4cd51fSLEROY Christophe 	/* When using hashctx-in, must unmap it. */
1825ad4cd51fSLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
1826ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1827ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1828ad4cd51fSLEROY Christophe 	else if (desc->next_desc)
1829ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[1],
1830ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1831ad4cd51fSLEROY Christophe 
1832ad4cd51fSLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
1833ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc->ptr[3],
1834ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1835ad4cd51fSLEROY Christophe 
1836497f2e6bSLee Nipper 	if (edesc->dma_len)
1837497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1838497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1839497f2e6bSLee Nipper 
184037b5e889SLEROY Christophe 	if (edesc->desc.next_desc)
184137b5e889SLEROY Christophe 		dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc),
184237b5e889SLEROY Christophe 				 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
1843497f2e6bSLee Nipper }
1844497f2e6bSLee Nipper 
1845497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1846497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1847497f2e6bSLee Nipper 		       int err)
1848497f2e6bSLee Nipper {
1849497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1850497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1851497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1852497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1853497f2e6bSLee Nipper 
1854497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1855497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
18563c0dd190SLEROY Christophe 		req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
18575e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1858497f2e6bSLee Nipper 	}
1859497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1860497f2e6bSLee Nipper 
1861497f2e6bSLee Nipper 	kfree(edesc);
1862497f2e6bSLee Nipper 
1863497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1864497f2e6bSLee Nipper }
1865497f2e6bSLee Nipper 
18662d02905eSLEROY Christophe /*
18672d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
18682d02905eSLEROY Christophe  * ourself and submit a padded block
18692d02905eSLEROY Christophe  */
18705b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
18712d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
18722d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
18732d02905eSLEROY Christophe {
18742d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
18752d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18762d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18772d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18782d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18792d02905eSLEROY Christophe 	};
18802d02905eSLEROY Christophe 
18812d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
18822d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
18832d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
18842d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
18852d02905eSLEROY Christophe }
18862d02905eSLEROY Christophe 
1887497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1888497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
188937b5e889SLEROY Christophe 				unsigned int offset,
1890497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1891497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1892497f2e6bSLee Nipper 						  void *context, int error))
1893497f2e6bSLee Nipper {
1894497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1895497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1896497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1897497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1898497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1899032d197eSLEROY Christophe 	int ret;
19006a1e8d14SLEROY Christophe 	bool sync_needed = false;
1901922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1902922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
19036a1e8d14SLEROY Christophe 	int sg_count;
1904497f2e6bSLee Nipper 
1905497f2e6bSLee Nipper 	/* first DWORD empty */
1906497f2e6bSLee Nipper 
190760f208d7SKim Phillips 	/* hash context in */
190860f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
19096a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
1910ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
19116a4967c3SLEROY Christophe 					      req_ctx->hw_context,
1912ad4cd51fSLEROY Christophe 					      DMA_TO_DEVICE);
191360f208d7SKim Phillips 		req_ctx->swinit = 0;
1914afd62fa2SLEROY Christophe 	}
1915497f2e6bSLee Nipper 	/* Indicate next op is not the first. */
1916497f2e6bSLee Nipper 	req_ctx->first = 0;
1917497f2e6bSLee Nipper 
1918497f2e6bSLee Nipper 	/* HMAC key */
1919497f2e6bSLee Nipper 	if (ctx->keylen)
19202e13ce08SLEROY Christophe 		to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
19212e13ce08SLEROY Christophe 			       is_sec1);
1922497f2e6bSLee Nipper 
192337b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
192437b5e889SLEROY Christophe 		length -= req_ctx->nbuf;
192537b5e889SLEROY Christophe 
19266a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
19276a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
192837b5e889SLEROY Christophe 		sg_pcopy_to_buffer(req_ctx->psrc, sg_count,
192937b5e889SLEROY Christophe 				   edesc->buf + sizeof(struct talitos_desc),
193037b5e889SLEROY Christophe 				   length, req_ctx->nbuf);
193137b5e889SLEROY Christophe 	else if (length)
19326a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
19336a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1934497f2e6bSLee Nipper 	/*
1935497f2e6bSLee Nipper 	 * data in
1936497f2e6bSLee Nipper 	 */
193737b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf) {
1938ad4cd51fSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
1939ad4cd51fSLEROY Christophe 				       req_ctx->buf[req_ctx->buf_idx],
1940ad4cd51fSLEROY Christophe 				       DMA_TO_DEVICE);
194137b5e889SLEROY Christophe 	} else {
19426a1e8d14SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
194337b5e889SLEROY Christophe 					  &desc->ptr[3], sg_count, offset, 0);
19446a1e8d14SLEROY Christophe 		if (sg_count > 1)
19456a1e8d14SLEROY Christophe 			sync_needed = true;
194637b5e889SLEROY Christophe 	}
1947497f2e6bSLee Nipper 
1948497f2e6bSLee Nipper 	/* fifth DWORD empty */
1949497f2e6bSLee Nipper 
1950497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1951497f2e6bSLee Nipper 	if (req_ctx->last)
1952497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1953497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1954a2b35aa8SLEROY Christophe 				       areq->result, DMA_FROM_DEVICE);
1955497f2e6bSLee Nipper 	else
19566a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1957ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
19586a4967c3SLEROY Christophe 					      req_ctx->hw_context,
19596a4967c3SLEROY Christophe 					      DMA_FROM_DEVICE);
1960497f2e6bSLee Nipper 
1961497f2e6bSLee Nipper 	/* last DWORD empty */
1962497f2e6bSLee Nipper 
19632d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
19642d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
19652d02905eSLEROY Christophe 
196637b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf && length) {
196737b5e889SLEROY Christophe 		struct talitos_desc *desc2 = desc + 1;
196837b5e889SLEROY Christophe 		dma_addr_t next_desc;
196937b5e889SLEROY Christophe 
197037b5e889SLEROY Christophe 		memset(desc2, 0, sizeof(*desc2));
197137b5e889SLEROY Christophe 		desc2->hdr = desc->hdr;
197237b5e889SLEROY Christophe 		desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
197337b5e889SLEROY Christophe 		desc2->hdr1 = desc2->hdr;
197437b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
197537b5e889SLEROY Christophe 		desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
197637b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
197737b5e889SLEROY Christophe 
1978ad4cd51fSLEROY Christophe 		if (desc->ptr[1].ptr)
1979ad4cd51fSLEROY Christophe 			copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
1980ad4cd51fSLEROY Christophe 					 is_sec1);
1981ad4cd51fSLEROY Christophe 		else
19826a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc2->ptr[1],
1983ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1984ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1985ad4cd51fSLEROY Christophe 						      DMA_TO_DEVICE);
198637b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
198737b5e889SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
198837b5e889SLEROY Christophe 					  &desc2->ptr[3], sg_count, offset, 0);
198937b5e889SLEROY Christophe 		if (sg_count > 1)
199037b5e889SLEROY Christophe 			sync_needed = true;
199137b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
199237b5e889SLEROY Christophe 		if (req_ctx->last)
19936a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1994ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1995ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1996ad4cd51fSLEROY Christophe 						      DMA_FROM_DEVICE);
199737b5e889SLEROY Christophe 
199837b5e889SLEROY Christophe 		next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE,
199937b5e889SLEROY Christophe 					   DMA_BIDIRECTIONAL);
200037b5e889SLEROY Christophe 		desc->next_desc = cpu_to_be32(next_desc);
200137b5e889SLEROY Christophe 	}
200237b5e889SLEROY Christophe 
20036a1e8d14SLEROY Christophe 	if (sync_needed)
20046a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
20056a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
20066a1e8d14SLEROY Christophe 
20075228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
2008497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
2009497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
2010497f2e6bSLee Nipper 		kfree(edesc);
2011497f2e6bSLee Nipper 	}
2012497f2e6bSLee Nipper 	return ret;
2013497f2e6bSLee Nipper }
2014497f2e6bSLee Nipper 
2015497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
2016497f2e6bSLee Nipper 					       unsigned int nbytes)
2017497f2e6bSLee Nipper {
2018497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2019497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
2020497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
202137b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
202237b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
202337b5e889SLEROY Christophe 
202437b5e889SLEROY Christophe 	if (is_sec1)
202537b5e889SLEROY Christophe 		nbytes -= req_ctx->nbuf;
2026497f2e6bSLee Nipper 
2027aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
202862293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
2029497f2e6bSLee Nipper }
2030497f2e6bSLee Nipper 
2031497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
2032497f2e6bSLee Nipper {
2033497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
20346a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
20356a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
2036497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
203749f9783bSLEROY Christophe 	unsigned int size;
20386a4967c3SLEROY Christophe 	dma_addr_t dma;
2039497f2e6bSLee Nipper 
2040497f2e6bSLee Nipper 	/* Initialize the context */
20413c0dd190SLEROY Christophe 	req_ctx->buf_idx = 0;
20425e833bc4SLee Nipper 	req_ctx->nbuf = 0;
204360f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
204460f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
204549f9783bSLEROY Christophe 	size =	(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
2046497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
2047497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
204849f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
2049497f2e6bSLee Nipper 
20506a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
20516a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
20526a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
20536a4967c3SLEROY Christophe 
2054497f2e6bSLee Nipper 	return 0;
2055497f2e6bSLee Nipper }
2056497f2e6bSLee Nipper 
205760f208d7SKim Phillips /*
205860f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
205960f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
206060f208d7SKim Phillips  */
206160f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
206260f208d7SKim Phillips {
206360f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
206460f208d7SKim Phillips 
2065a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
2066a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
2067a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
2068a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
2069a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
2070a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
2071a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
2072a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
207360f208d7SKim Phillips 
207460f208d7SKim Phillips 	/* init 64-bit count */
207560f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
207660f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
207760f208d7SKim Phillips 
20786a4967c3SLEROY Christophe 	ahash_init(areq);
20796a4967c3SLEROY Christophe 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
20806a4967c3SLEROY Christophe 
208160f208d7SKim Phillips 	return 0;
208260f208d7SKim Phillips }
208360f208d7SKim Phillips 
2084497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
2085497f2e6bSLee Nipper {
2086497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2087497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
2088497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2089497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
2090497f2e6bSLee Nipper 	unsigned int blocksize =
2091497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
2092497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
2093497f2e6bSLee Nipper 	unsigned int to_hash_later;
20945e833bc4SLee Nipper 	unsigned int nsg;
20958e409fe1SLABBE Corentin 	int nents;
209637b5e889SLEROY Christophe 	struct device *dev = ctx->dev;
209737b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
209837b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
209937b5e889SLEROY Christophe 	int offset = 0;
21003c0dd190SLEROY Christophe 	u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
2101497f2e6bSLee Nipper 
21025e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
21035e833bc4SLee Nipper 		/* Buffer up to one whole block */
21048e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
21058e409fe1SLABBE Corentin 		if (nents < 0) {
21068e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
21078e409fe1SLABBE Corentin 			return nents;
21088e409fe1SLABBE Corentin 		}
21098e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
21103c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, nbytes);
21115e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
2112497f2e6bSLee Nipper 		return 0;
2113497f2e6bSLee Nipper 	}
2114497f2e6bSLee Nipper 
21155e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
21165e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
21175e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
21185e833bc4SLee Nipper 
21195e833bc4SLee Nipper 	if (req_ctx->last)
21205e833bc4SLee Nipper 		to_hash_later = 0;
21215e833bc4SLee Nipper 	else if (to_hash_later)
21225e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
21235e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
21245e833bc4SLee Nipper 	else {
21255e833bc4SLee Nipper 		/* Keep one block buffered */
21265e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
21275e833bc4SLee Nipper 		to_hash_later = blocksize;
2128497f2e6bSLee Nipper 	}
21295e833bc4SLee Nipper 
21305e833bc4SLee Nipper 	/* Chain in any previously buffered data */
213137b5e889SLEROY Christophe 	if (!is_sec1 && req_ctx->nbuf) {
21325e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
21335e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
21343c0dd190SLEROY Christophe 		sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
21355e833bc4SLee Nipper 		if (nsg > 1)
2136c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
21375e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
213837b5e889SLEROY Christophe 	} else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
213937b5e889SLEROY Christophe 		if (nbytes_to_hash > blocksize)
214037b5e889SLEROY Christophe 			offset = blocksize - req_ctx->nbuf;
214137b5e889SLEROY Christophe 		else
214237b5e889SLEROY Christophe 			offset = nbytes_to_hash - req_ctx->nbuf;
214337b5e889SLEROY Christophe 		nents = sg_nents_for_len(areq->src, offset);
214437b5e889SLEROY Christophe 		if (nents < 0) {
214537b5e889SLEROY Christophe 			dev_err(ctx->dev, "Invalid number of src SG.\n");
214637b5e889SLEROY Christophe 			return nents;
214737b5e889SLEROY Christophe 		}
214837b5e889SLEROY Christophe 		sg_copy_to_buffer(areq->src, nents,
21493c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, offset);
215037b5e889SLEROY Christophe 		req_ctx->nbuf += offset;
215137b5e889SLEROY Christophe 		req_ctx->psrc = areq->src;
21525e833bc4SLee Nipper 	} else
21535e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
21545e833bc4SLee Nipper 
2155497f2e6bSLee Nipper 	if (to_hash_later) {
21568e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
21578e409fe1SLABBE Corentin 		if (nents < 0) {
21588e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
21598e409fe1SLABBE Corentin 			return nents;
21608e409fe1SLABBE Corentin 		}
2161d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
21623c0dd190SLEROY Christophe 				   req_ctx->buf[(req_ctx->buf_idx + 1) & 1],
2163497f2e6bSLee Nipper 				      to_hash_later,
2164497f2e6bSLee Nipper 				      nbytes - to_hash_later);
2165497f2e6bSLee Nipper 	}
2166497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
2167497f2e6bSLee Nipper 
21685e833bc4SLee Nipper 	/* Allocate extended descriptor */
2169497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
2170497f2e6bSLee Nipper 	if (IS_ERR(edesc))
2171497f2e6bSLee Nipper 		return PTR_ERR(edesc);
2172497f2e6bSLee Nipper 
2173497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
2174497f2e6bSLee Nipper 
2175497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
2176497f2e6bSLee Nipper 	if (req_ctx->last)
2177497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
2178497f2e6bSLee Nipper 	else
2179497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
2180497f2e6bSLee Nipper 
218160f208d7SKim Phillips 	/* request SEC to INIT hash. */
218260f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
2183497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
2184497f2e6bSLee Nipper 
2185497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
2186497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
2187497f2e6bSLee Nipper 	 */
2188497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
2189497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
2190497f2e6bSLee Nipper 
219137b5e889SLEROY Christophe 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, offset,
2192497f2e6bSLee Nipper 				    ahash_done);
2193497f2e6bSLee Nipper }
2194497f2e6bSLee Nipper 
2195497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
2196497f2e6bSLee Nipper {
2197497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2198497f2e6bSLee Nipper 
2199497f2e6bSLee Nipper 	req_ctx->last = 0;
2200497f2e6bSLee Nipper 
2201497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2202497f2e6bSLee Nipper }
2203497f2e6bSLee Nipper 
2204497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
2205497f2e6bSLee Nipper {
2206497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2207497f2e6bSLee Nipper 
2208497f2e6bSLee Nipper 	req_ctx->last = 1;
2209497f2e6bSLee Nipper 
2210497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
2211497f2e6bSLee Nipper }
2212497f2e6bSLee Nipper 
2213497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
2214497f2e6bSLee Nipper {
2215497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2216497f2e6bSLee Nipper 
2217497f2e6bSLee Nipper 	req_ctx->last = 1;
2218497f2e6bSLee Nipper 
2219497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2220497f2e6bSLee Nipper }
2221497f2e6bSLee Nipper 
2222497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
2223497f2e6bSLee Nipper {
2224497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
222560f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2226497f2e6bSLee Nipper 
222760f208d7SKim Phillips 	ahash->init(areq);
2228497f2e6bSLee Nipper 	req_ctx->last = 1;
2229497f2e6bSLee Nipper 
2230497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2231497f2e6bSLee Nipper }
2232497f2e6bSLee Nipper 
22333639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
22343639ca84SHoria Geant? {
22353639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
22363639ca84SHoria Geant? 	struct talitos_export_state *export = out;
22376a4967c3SLEROY Christophe 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
22386a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
22396a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
22406a4967c3SLEROY Christophe 	dma_addr_t dma;
22416a4967c3SLEROY Christophe 
22426a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
22436a4967c3SLEROY Christophe 			     DMA_FROM_DEVICE);
22446a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE);
22453639ca84SHoria Geant? 
22463639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
22473639ca84SHoria Geant? 	       req_ctx->hw_context_size);
22483c0dd190SLEROY Christophe 	memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf);
22493639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
22503639ca84SHoria Geant? 	export->first = req_ctx->first;
22513639ca84SHoria Geant? 	export->last = req_ctx->last;
22523639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
22533639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
22543639ca84SHoria Geant? 
22553639ca84SHoria Geant? 	return 0;
22563639ca84SHoria Geant? }
22573639ca84SHoria Geant? 
22583639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
22593639ca84SHoria Geant? {
22603639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
22613639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
22626a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
22636a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
22643639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
226549f9783bSLEROY Christophe 	unsigned int size;
22666a4967c3SLEROY Christophe 	dma_addr_t dma;
22673639ca84SHoria Geant? 
22683639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
226949f9783bSLEROY Christophe 	size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
22703639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
22713639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
227249f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
227349f9783bSLEROY Christophe 	memcpy(req_ctx->hw_context, export->hw_context, size);
22743c0dd190SLEROY Christophe 	memcpy(req_ctx->buf[0], export->buf, export->nbuf);
22753639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
22763639ca84SHoria Geant? 	req_ctx->first = export->first;
22773639ca84SHoria Geant? 	req_ctx->last = export->last;
22783639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
22793639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
22803639ca84SHoria Geant? 
22816a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
22826a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
22836a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
22846a4967c3SLEROY Christophe 
22853639ca84SHoria Geant? 	return 0;
22863639ca84SHoria Geant? }
22873639ca84SHoria Geant? 
228879b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
228979b3a418SLee Nipper 		   u8 *hash)
229079b3a418SLee Nipper {
229179b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
229279b3a418SLee Nipper 
229379b3a418SLee Nipper 	struct scatterlist sg[1];
229479b3a418SLee Nipper 	struct ahash_request *req;
2295f1c90ac3SGilad Ben-Yossef 	struct crypto_wait wait;
229679b3a418SLee Nipper 	int ret;
229779b3a418SLee Nipper 
2298f1c90ac3SGilad Ben-Yossef 	crypto_init_wait(&wait);
229979b3a418SLee Nipper 
230079b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
230179b3a418SLee Nipper 	if (!req)
230279b3a418SLee Nipper 		return -ENOMEM;
230379b3a418SLee Nipper 
230479b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
230579b3a418SLee Nipper 	ctx->keylen = 0;
230679b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
2307f1c90ac3SGilad Ben-Yossef 				   crypto_req_done, &wait);
230879b3a418SLee Nipper 
230979b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
231079b3a418SLee Nipper 
231179b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
2312f1c90ac3SGilad Ben-Yossef 	ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
2313f1c90ac3SGilad Ben-Yossef 
231479b3a418SLee Nipper 	ahash_request_free(req);
231579b3a418SLee Nipper 
231679b3a418SLee Nipper 	return ret;
231779b3a418SLee Nipper }
231879b3a418SLee Nipper 
231979b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
232079b3a418SLee Nipper 			unsigned int keylen)
232179b3a418SLee Nipper {
232279b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
23232e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
232479b3a418SLee Nipper 	unsigned int blocksize =
232579b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
232679b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
232779b3a418SLee Nipper 	unsigned int keysize = keylen;
232879b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
232979b3a418SLee Nipper 	int ret;
233079b3a418SLee Nipper 
233179b3a418SLee Nipper 	if (keylen <= blocksize)
233279b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
233379b3a418SLee Nipper 	else {
233479b3a418SLee Nipper 		/* Must get the hash of the long key */
233579b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
233679b3a418SLee Nipper 
233779b3a418SLee Nipper 		if (ret) {
233879b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
233979b3a418SLee Nipper 			return -EINVAL;
234079b3a418SLee Nipper 		}
234179b3a418SLee Nipper 
234279b3a418SLee Nipper 		keysize = digestsize;
234379b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
234479b3a418SLee Nipper 	}
234579b3a418SLee Nipper 
23462e13ce08SLEROY Christophe 	if (ctx->keylen)
23472e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
23482e13ce08SLEROY Christophe 
234979b3a418SLee Nipper 	ctx->keylen = keysize;
23502e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE);
235179b3a418SLee Nipper 
235279b3a418SLee Nipper 	return 0;
235379b3a418SLee Nipper }
235479b3a418SLee Nipper 
235579b3a418SLee Nipper 
23569c4a7965SKim Phillips struct talitos_alg_template {
2357d5e4aaefSLee Nipper 	u32 type;
2358b0057763SLEROY Christophe 	u32 priority;
2359d5e4aaefSLee Nipper 	union {
2360d5e4aaefSLee Nipper 		struct crypto_alg crypto;
2361acbf7c62SLee Nipper 		struct ahash_alg hash;
2362aeb4c132SHerbert Xu 		struct aead_alg aead;
2363d5e4aaefSLee Nipper 	} alg;
23649c4a7965SKim Phillips 	__be32 desc_hdr_template;
23659c4a7965SKim Phillips };
23669c4a7965SKim Phillips 
23679c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2368991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2369d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2370aeb4c132SHerbert Xu 		.alg.aead = {
2371aeb4c132SHerbert Xu 			.base = {
237256af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2373aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2374aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
237556af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2376aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2377aeb4c132SHerbert Xu 			},
23783952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
23793952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
23809c4a7965SKim Phillips 		},
23819c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23829c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
23839c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
23849c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
23859c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
23869c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
23879c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
238870bcaca7SLee Nipper 	},
2389d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23907405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23917405c8d7SLEROY Christophe 		.alg.aead = {
23927405c8d7SLEROY Christophe 			.base = {
23937405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
23947405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
2395a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
23967405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
23977405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23987405c8d7SLEROY Christophe 			},
23997405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
24007405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
24017405c8d7SLEROY Christophe 		},
24027405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24037405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
24047405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
24057405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24067405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24077405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24087405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
24097405c8d7SLEROY Christophe 	},
24107405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2411aeb4c132SHerbert Xu 		.alg.aead = {
2412aeb4c132SHerbert Xu 			.base = {
2413aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2414aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2415aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2416aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
241756af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2418aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2419aeb4c132SHerbert Xu 			},
24203952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
24213952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
2422ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
242370bcaca7SLee Nipper 		},
242470bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
242570bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
242670bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
242770bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
242870bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
242970bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
243070bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
243170bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
24323952f17eSLee Nipper 	},
2433d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24347405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24357405c8d7SLEROY Christophe 		.alg.aead = {
24367405c8d7SLEROY Christophe 			.base = {
24377405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),"
24387405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
24397405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
2440a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
24417405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24427405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24437405c8d7SLEROY Christophe 			},
24447405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
24457405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
2446ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
24477405c8d7SLEROY Christophe 		},
24487405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24497405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24507405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
24517405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
24527405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24537405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24547405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24557405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
24567405c8d7SLEROY Christophe 	},
24577405c8d7SLEROY Christophe 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2458aeb4c132SHerbert Xu 		.alg.aead = {
2459aeb4c132SHerbert Xu 			.base = {
2460357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2461aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2462aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2463357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2464aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2465aeb4c132SHerbert Xu 			},
2466357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2467357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2468357fb605SHoria Geanta 		},
2469357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2470357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2471357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2472357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2473357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2474357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2475357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2476357fb605SHoria Geanta 	},
2477357fb605SHoria Geanta 	{       .type = CRYPTO_ALG_TYPE_AEAD,
24787405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24797405c8d7SLEROY Christophe 		.alg.aead = {
24807405c8d7SLEROY Christophe 			.base = {
24817405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
24827405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
2483a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
24847405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
24857405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24867405c8d7SLEROY Christophe 			},
24877405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
24887405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
24897405c8d7SLEROY Christophe 		},
24907405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24917405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
24927405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
24937405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24947405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24957405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24967405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
24977405c8d7SLEROY Christophe 	},
24987405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2499aeb4c132SHerbert Xu 		.alg.aead = {
2500aeb4c132SHerbert Xu 			.base = {
2501aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2502aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2503aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2504aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2505357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2506aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2507aeb4c132SHerbert Xu 			},
2508357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2509357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2510ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2511357fb605SHoria Geanta 		},
2512357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2513357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2514357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2515357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2516357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2517357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2518357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2519357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2520357fb605SHoria Geanta 	},
2521357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25227405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25237405c8d7SLEROY Christophe 		.alg.aead = {
25247405c8d7SLEROY Christophe 			.base = {
25257405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),"
25267405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
25277405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
2528a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
25297405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
25307405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25317405c8d7SLEROY Christophe 			},
25327405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
25337405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
2534ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
25357405c8d7SLEROY Christophe 		},
25367405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25377405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
25387405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
25397405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
25407405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25417405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25427405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25437405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
25447405c8d7SLEROY Christophe 	},
25457405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2546aeb4c132SHerbert Xu 		.alg.aead = {
2547aeb4c132SHerbert Xu 			.base = {
254856af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2549aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2550aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
255156af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2552aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2553aeb4c132SHerbert Xu 			},
25543952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
25553952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
25563952f17eSLee Nipper 		},
25573952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25583952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
25593952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
25603952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25613952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25623952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25633952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25643952f17eSLee Nipper 	},
2565d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25667405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25677405c8d7SLEROY Christophe 		.alg.aead = {
25687405c8d7SLEROY Christophe 			.base = {
25697405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
25707405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
2571a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
25727405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
25737405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25747405c8d7SLEROY Christophe 			},
25757405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
25767405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
25777405c8d7SLEROY Christophe 		},
25787405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25797405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
25807405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
25817405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25827405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25837405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25847405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25857405c8d7SLEROY Christophe 	},
25867405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2587aeb4c132SHerbert Xu 		.alg.aead = {
2588aeb4c132SHerbert Xu 			.base = {
2589aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2590aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2591aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2592aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
259356af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2594aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2595aeb4c132SHerbert Xu 			},
25963952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
25973952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
2598ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
25993952f17eSLee Nipper 		},
26003952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26013952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
26023952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
26033952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
26043952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26053952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
26063952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
26073952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
26083952f17eSLee Nipper 	},
2609d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
26107405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26117405c8d7SLEROY Christophe 		.alg.aead = {
26127405c8d7SLEROY Christophe 			.base = {
26137405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),"
26147405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
26157405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
2616a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
26177405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26187405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
26197405c8d7SLEROY Christophe 			},
26207405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
26217405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
2622ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
26237405c8d7SLEROY Christophe 		},
26247405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
26257405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
26267405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
26277405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
26287405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
26297405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
26307405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
26317405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
26327405c8d7SLEROY Christophe 	},
26337405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2634aeb4c132SHerbert Xu 		.alg.aead = {
2635aeb4c132SHerbert Xu 			.base = {
2636357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2637aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2638aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2639357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2640aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2641aeb4c132SHerbert Xu 			},
2642357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2643357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2644357fb605SHoria Geanta 		},
2645357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2646357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2647357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2648357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2649357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2650357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2651357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2652357fb605SHoria Geanta 	},
2653357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2654aeb4c132SHerbert Xu 		.alg.aead = {
2655aeb4c132SHerbert Xu 			.base = {
2656aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2657aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2658aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2659aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2660357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2661aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2662aeb4c132SHerbert Xu 			},
2663357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2664357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2665ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2666357fb605SHoria Geanta 		},
2667357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2668357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2669357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2670357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2671357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2672357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2673357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2674357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2675357fb605SHoria Geanta 	},
2676357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2677aeb4c132SHerbert Xu 		.alg.aead = {
2678aeb4c132SHerbert Xu 			.base = {
2679357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2680aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2681aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2682357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2683aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2684aeb4c132SHerbert Xu 			},
2685357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2686357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2687357fb605SHoria Geanta 		},
2688357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2689357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2690357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2691357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2692357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2693357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2694357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2695357fb605SHoria Geanta 	},
2696357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2697aeb4c132SHerbert Xu 		.alg.aead = {
2698aeb4c132SHerbert Xu 			.base = {
2699aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2700aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2701aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2702aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2703357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2704aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2705aeb4c132SHerbert Xu 			},
2706357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2707357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2708ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2709357fb605SHoria Geanta 		},
2710357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2711357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2712357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2713357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2714357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2715357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2716357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2717357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2718357fb605SHoria Geanta 	},
2719357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2720aeb4c132SHerbert Xu 		.alg.aead = {
2721aeb4c132SHerbert Xu 			.base = {
272256af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2723aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2724aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
272556af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2726aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2727aeb4c132SHerbert Xu 			},
27283952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
27293952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
27303952f17eSLee Nipper 		},
27313952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
27323952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
27333952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
27343952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
27353952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
27363952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
27373952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27383952f17eSLee Nipper 	},
2739d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
27407405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
27417405c8d7SLEROY Christophe 		.alg.aead = {
27427405c8d7SLEROY Christophe 			.base = {
27437405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(aes))",
27447405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
2745a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
27467405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
27477405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
27487405c8d7SLEROY Christophe 			},
27497405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
27507405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
27517405c8d7SLEROY Christophe 		},
27527405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
27537405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
27547405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
27557405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
27567405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
27577405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
27587405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27597405c8d7SLEROY Christophe 	},
27607405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2761aeb4c132SHerbert Xu 		.alg.aead = {
2762aeb4c132SHerbert Xu 			.base = {
276356af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2764aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2765aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
276656af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2767aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2768aeb4c132SHerbert Xu 			},
27693952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
27703952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
2771ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
27723952f17eSLee Nipper 		},
27733952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
27743952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
27753952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
27763952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
27773952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
27783952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
27793952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
27803952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27814de9d0b5SLee Nipper 	},
27827405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
27837405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
27847405c8d7SLEROY Christophe 		.alg.aead = {
27857405c8d7SLEROY Christophe 			.base = {
27867405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
27877405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
2788a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
27897405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
27907405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
27917405c8d7SLEROY Christophe 			},
27927405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
27937405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
2794ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
27957405c8d7SLEROY Christophe 		},
27967405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
27977405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
27987405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
27997405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
28007405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
28017405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
28027405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
28037405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
28047405c8d7SLEROY Christophe 	},
28054de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2806d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2807d5e4aaefSLee Nipper 		.alg.crypto = {
28085e75ae1bSLEROY Christophe 			.cra_name = "ecb(aes)",
28095e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-aes-talitos",
28105e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
28115e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28125e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
28135e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
28145e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
28155e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
28161ba34e71SChristophe Leroy 				.setkey = ablkcipher_aes_setkey,
28175e75ae1bSLEROY Christophe 			}
28185e75ae1bSLEROY Christophe 		},
28195e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28205e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
28215e75ae1bSLEROY Christophe 	},
28225e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
28235e75ae1bSLEROY Christophe 		.alg.crypto = {
28244de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
28254de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
28264de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
28274de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28284de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
28294de9d0b5SLee Nipper 			.cra_ablkcipher = {
28304de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
28314de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
28324de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
28331ba34e71SChristophe Leroy 				.setkey = ablkcipher_aes_setkey,
28344de9d0b5SLee Nipper 			}
28354de9d0b5SLee Nipper 		},
28364de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28374de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
28384de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
28394de9d0b5SLee Nipper 	},
2840d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2841d5e4aaefSLee Nipper 		.alg.crypto = {
28425e75ae1bSLEROY Christophe 			.cra_name = "ctr(aes)",
28435e75ae1bSLEROY Christophe 			.cra_driver_name = "ctr-aes-talitos",
2844b9a05b60SChristophe Leroy 			.cra_blocksize = 1,
28455e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28465e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
28475e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
28485e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
28495e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
28505e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
28511ba34e71SChristophe Leroy 				.setkey = ablkcipher_aes_setkey,
28525e75ae1bSLEROY Christophe 			}
28535e75ae1bSLEROY Christophe 		},
285470d355ccSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
28555e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
28565e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
28575e75ae1bSLEROY Christophe 	},
28585e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
28595e75ae1bSLEROY Christophe 		.alg.crypto = {
28605e75ae1bSLEROY Christophe 			.cra_name = "ecb(des)",
28615e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-des-talitos",
28625e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
28635e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28645e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
28655e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
28665e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
28675e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
2868ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des_setkey,
28695e75ae1bSLEROY Christophe 			}
28705e75ae1bSLEROY Christophe 		},
28715e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28725e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
28735e75ae1bSLEROY Christophe 	},
28745e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
28755e75ae1bSLEROY Christophe 		.alg.crypto = {
28765e75ae1bSLEROY Christophe 			.cra_name = "cbc(des)",
28775e75ae1bSLEROY Christophe 			.cra_driver_name = "cbc-des-talitos",
28785e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
28795e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28805e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
28815e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
28825e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
28835e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
28845e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
2885ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des_setkey,
28865e75ae1bSLEROY Christophe 			}
28875e75ae1bSLEROY Christophe 		},
28885e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28895e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
28905e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
28915e75ae1bSLEROY Christophe 	},
28925e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
28935e75ae1bSLEROY Christophe 		.alg.crypto = {
28945e75ae1bSLEROY Christophe 			.cra_name = "ecb(des3_ede)",
28955e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-3des-talitos",
28965e75ae1bSLEROY Christophe 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
28975e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28985e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
28995e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
29005e75ae1bSLEROY Christophe 				.min_keysize = DES3_EDE_KEY_SIZE,
29015e75ae1bSLEROY Christophe 				.max_keysize = DES3_EDE_KEY_SIZE,
2902ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des3_setkey,
29035e75ae1bSLEROY Christophe 			}
29045e75ae1bSLEROY Christophe 		},
29055e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
29065e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
29075e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
29085e75ae1bSLEROY Christophe 	},
29095e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
29105e75ae1bSLEROY Christophe 		.alg.crypto = {
29114de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
29124de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
29134de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
29144de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
29154de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
29164de9d0b5SLee Nipper 			.cra_ablkcipher = {
29174de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
29184de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
29194de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
2920ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des3_setkey,
29214de9d0b5SLee Nipper 			}
29224de9d0b5SLee Nipper 		},
29234de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
29244de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
29254de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
29264de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2927497f2e6bSLee Nipper 	},
2928497f2e6bSLee Nipper 	/* AHASH algorithms. */
2929497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2930497f2e6bSLee Nipper 		.alg.hash = {
2931497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
29323639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2933497f2e6bSLee Nipper 			.halg.base = {
2934497f2e6bSLee Nipper 				.cra_name = "md5",
2935497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2936b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
29376a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
29389c4a7965SKim Phillips 			}
2939497f2e6bSLee Nipper 		},
2940497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2941497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2942497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2943497f2e6bSLee Nipper 	},
2944497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2945497f2e6bSLee Nipper 		.alg.hash = {
2946497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
29473639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2948497f2e6bSLee Nipper 			.halg.base = {
2949497f2e6bSLee Nipper 				.cra_name = "sha1",
2950497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2951497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
29526a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2953497f2e6bSLee Nipper 			}
2954497f2e6bSLee Nipper 		},
2955497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2956497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2957497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2958497f2e6bSLee Nipper 	},
2959497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2960497f2e6bSLee Nipper 		.alg.hash = {
296160f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
29623639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
296360f208d7SKim Phillips 			.halg.base = {
296460f208d7SKim Phillips 				.cra_name = "sha224",
296560f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
296660f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
29676a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
296860f208d7SKim Phillips 			}
296960f208d7SKim Phillips 		},
297060f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
297160f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
297260f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
297360f208d7SKim Phillips 	},
297460f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
297560f208d7SKim Phillips 		.alg.hash = {
2976497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
29773639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2978497f2e6bSLee Nipper 			.halg.base = {
2979497f2e6bSLee Nipper 				.cra_name = "sha256",
2980497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2981497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
29826a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2983497f2e6bSLee Nipper 			}
2984497f2e6bSLee Nipper 		},
2985497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2986497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2987497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2988497f2e6bSLee Nipper 	},
2989497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2990497f2e6bSLee Nipper 		.alg.hash = {
2991497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
29923639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2993497f2e6bSLee Nipper 			.halg.base = {
2994497f2e6bSLee Nipper 				.cra_name = "sha384",
2995497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2996497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
29976a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2998497f2e6bSLee Nipper 			}
2999497f2e6bSLee Nipper 		},
3000497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
3001497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
3002497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
3003497f2e6bSLee Nipper 	},
3004497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
3005497f2e6bSLee Nipper 		.alg.hash = {
3006497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
30073639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
3008497f2e6bSLee Nipper 			.halg.base = {
3009497f2e6bSLee Nipper 				.cra_name = "sha512",
3010497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
3011497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
30126a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
3013497f2e6bSLee Nipper 			}
3014497f2e6bSLee Nipper 		},
3015497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
3016497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
3017497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
3018497f2e6bSLee Nipper 	},
301979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
302079b3a418SLee Nipper 		.alg.hash = {
302179b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
30223639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
302379b3a418SLee Nipper 			.halg.base = {
302479b3a418SLee Nipper 				.cra_name = "hmac(md5)",
302579b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
3026b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
30276a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
302879b3a418SLee Nipper 			}
302979b3a418SLee Nipper 		},
303079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
303179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
303279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
303379b3a418SLee Nipper 	},
303479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
303579b3a418SLee Nipper 		.alg.hash = {
303679b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
30373639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
303879b3a418SLee Nipper 			.halg.base = {
303979b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
304079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
304179b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
30426a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
304379b3a418SLee Nipper 			}
304479b3a418SLee Nipper 		},
304579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
304679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
304779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
304879b3a418SLee Nipper 	},
304979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
305079b3a418SLee Nipper 		.alg.hash = {
305179b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
30523639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
305379b3a418SLee Nipper 			.halg.base = {
305479b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
305579b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
305679b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
30576a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
305879b3a418SLee Nipper 			}
305979b3a418SLee Nipper 		},
306079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
306179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
306279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
306379b3a418SLee Nipper 	},
306479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
306579b3a418SLee Nipper 		.alg.hash = {
306679b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
30673639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
306879b3a418SLee Nipper 			.halg.base = {
306979b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
307079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
307179b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
30726a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
307379b3a418SLee Nipper 			}
307479b3a418SLee Nipper 		},
307579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
307679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
307779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
307879b3a418SLee Nipper 	},
307979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
308079b3a418SLee Nipper 		.alg.hash = {
308179b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
30823639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
308379b3a418SLee Nipper 			.halg.base = {
308479b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
308579b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
308679b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
30876a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
308879b3a418SLee Nipper 			}
308979b3a418SLee Nipper 		},
309079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
309179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
309279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
309379b3a418SLee Nipper 	},
309479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
309579b3a418SLee Nipper 		.alg.hash = {
309679b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
30973639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
309879b3a418SLee Nipper 			.halg.base = {
309979b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
310079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
310179b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
31026a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
310379b3a418SLee Nipper 			}
310479b3a418SLee Nipper 		},
310579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
310679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
310779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
310879b3a418SLee Nipper 	}
31099c4a7965SKim Phillips };
31109c4a7965SKim Phillips 
31119c4a7965SKim Phillips struct talitos_crypto_alg {
31129c4a7965SKim Phillips 	struct list_head entry;
31139c4a7965SKim Phillips 	struct device *dev;
3114acbf7c62SLee Nipper 	struct talitos_alg_template algt;
31159c4a7965SKim Phillips };
31169c4a7965SKim Phillips 
311789d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
311889d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
31199c4a7965SKim Phillips {
31205228f0f7SKim Phillips 	struct talitos_private *priv;
31219c4a7965SKim Phillips 
31229c4a7965SKim Phillips 	/* update context with ptr to dev */
31239c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
312419bbbc63SKim Phillips 
31255228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
31265228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
31275228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
31285228f0f7SKim Phillips 		  (priv->num_channels - 1);
31295228f0f7SKim Phillips 
31309c4a7965SKim Phillips 	/* copy descriptor header template value */
3131acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
31329c4a7965SKim Phillips 
3133602dba5aSKim Phillips 	/* select done notification */
3134602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
3135602dba5aSKim Phillips 
3136497f2e6bSLee Nipper 	return 0;
3137497f2e6bSLee Nipper }
3138497f2e6bSLee Nipper 
313989d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm)
314089d124cbSJonas Eymann {
314189d124cbSJonas Eymann 	struct crypto_alg *alg = tfm->__crt_alg;
314289d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
314389d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
314489d124cbSJonas Eymann 
314589d124cbSJonas Eymann 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
314689d124cbSJonas Eymann 		talitos_alg = container_of(__crypto_ahash_alg(alg),
314789d124cbSJonas Eymann 					   struct talitos_crypto_alg,
314889d124cbSJonas Eymann 					   algt.alg.hash);
314989d124cbSJonas Eymann 	else
315089d124cbSJonas Eymann 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
315189d124cbSJonas Eymann 					   algt.alg.crypto);
315289d124cbSJonas Eymann 
315389d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
315489d124cbSJonas Eymann }
315589d124cbSJonas Eymann 
3156aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
3157497f2e6bSLee Nipper {
315889d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
315989d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
316089d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
316189d124cbSJonas Eymann 
316289d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
316389d124cbSJonas Eymann 				   algt.alg.aead);
316489d124cbSJonas Eymann 
316589d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
31669c4a7965SKim Phillips }
31679c4a7965SKim Phillips 
3168497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
3169497f2e6bSLee Nipper {
3170497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
3171497f2e6bSLee Nipper 
3172497f2e6bSLee Nipper 	talitos_cra_init(tfm);
3173497f2e6bSLee Nipper 
3174497f2e6bSLee Nipper 	ctx->keylen = 0;
3175497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
3176497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
3177497f2e6bSLee Nipper 
3178497f2e6bSLee Nipper 	return 0;
3179497f2e6bSLee Nipper }
3180497f2e6bSLee Nipper 
31812e13ce08SLEROY Christophe static void talitos_cra_exit(struct crypto_tfm *tfm)
31822e13ce08SLEROY Christophe {
31832e13ce08SLEROY Christophe 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
31842e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
31852e13ce08SLEROY Christophe 
31862e13ce08SLEROY Christophe 	if (ctx->keylen)
31872e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
31882e13ce08SLEROY Christophe }
31892e13ce08SLEROY Christophe 
31909c4a7965SKim Phillips /*
31919c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
31929c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
31939c4a7965SKim Phillips  * capabilities description provided in the device tree node.
31949c4a7965SKim Phillips  */
31959c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
31969c4a7965SKim Phillips {
31979c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31989c4a7965SKim Phillips 	int ret;
31999c4a7965SKim Phillips 
32009c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
32019c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
32029c4a7965SKim Phillips 
32039c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
32049c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
32059c4a7965SKim Phillips 		              & priv->exec_units);
32069c4a7965SKim Phillips 
32079c4a7965SKim Phillips 	return ret;
32089c4a7965SKim Phillips }
32099c4a7965SKim Phillips 
32102dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
32119c4a7965SKim Phillips {
32129c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
32139c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
32149c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
32159c4a7965SKim Phillips 	int i;
32169c4a7965SKim Phillips 
32179c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
3218acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
3219acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
3220acbf7c62SLee Nipper 			break;
3221aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
3222aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
3223acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
3224acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
3225acbf7c62SLee Nipper 			break;
3226acbf7c62SLee Nipper 		}
32279c4a7965SKim Phillips 		list_del(&t_alg->entry);
32289c4a7965SKim Phillips 	}
32299c4a7965SKim Phillips 
32309c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
32319c4a7965SKim Phillips 		talitos_unregister_rng(dev);
32329c4a7965SKim Phillips 
3233c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
32342cdba3cfSKim Phillips 		if (priv->irq[i]) {
3235c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
3236c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
32379c4a7965SKim Phillips 		}
32389c4a7965SKim Phillips 
3239c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
32402cdba3cfSKim Phillips 	if (priv->irq[1])
3241c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
32429c4a7965SKim Phillips 
32439c4a7965SKim Phillips 	return 0;
32449c4a7965SKim Phillips }
32459c4a7965SKim Phillips 
32469c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
32479c4a7965SKim Phillips 						    struct talitos_alg_template
32489c4a7965SKim Phillips 						           *template)
32499c4a7965SKim Phillips {
325060f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
32519c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
32529c4a7965SKim Phillips 	struct crypto_alg *alg;
32539c4a7965SKim Phillips 
325424b92ff2SLEROY Christophe 	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
325524b92ff2SLEROY Christophe 			     GFP_KERNEL);
32569c4a7965SKim Phillips 	if (!t_alg)
32579c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
32589c4a7965SKim Phillips 
3259acbf7c62SLee Nipper 	t_alg->algt = *template;
3260acbf7c62SLee Nipper 
3261acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
3262acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
3263497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
3264497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
32652e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3266d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
3267ef7c5c85SHerbert Xu 		alg->cra_ablkcipher.setkey = alg->cra_ablkcipher.setkey ?:
3268ef7c5c85SHerbert Xu 					     ablkcipher_setkey;
3269b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
3270b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
3271497f2e6bSLee Nipper 		break;
3272acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
3273aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
32742e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3275aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
3276ef7c5c85SHerbert Xu 		t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?:
3277ef7c5c85SHerbert Xu 					      aead_setkey;
3278aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
3279aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
32806cda075aSLEROY Christophe 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
32816cda075aSLEROY Christophe 		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
328224b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
32836cda075aSLEROY Christophe 			return ERR_PTR(-ENOTSUPP);
32846cda075aSLEROY Christophe 		}
3285acbf7c62SLee Nipper 		break;
3286acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
3287acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
3288497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
3289ad4cd51fSLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3290b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
3291b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
3292b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
3293b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
3294b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
329556136631SLEROY Christophe 		if (!strncmp(alg->cra_name, "hmac", 4))
3296b286e003SKim Phillips 			t_alg->algt.alg.hash.setkey = ahash_setkey;
32973639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
32983639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
3299b286e003SKim Phillips 
330079b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
33010b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
330224b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
330379b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
33040b2730d8SKim Phillips 		}
330560f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
330679b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
330779b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
330860f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
330960f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
331060f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
331160f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
331260f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
331360f208d7SKim Phillips 		}
3314497f2e6bSLee Nipper 		break;
33151d11911aSKim Phillips 	default:
33161d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
331724b92ff2SLEROY Christophe 		devm_kfree(dev, t_alg);
33181d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
3319acbf7c62SLee Nipper 	}
33209c4a7965SKim Phillips 
33219c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
3322b0057763SLEROY Christophe 	if (t_alg->algt.priority)
3323b0057763SLEROY Christophe 		alg->cra_priority = t_alg->algt.priority;
3324b0057763SLEROY Christophe 	else
33259c4a7965SKim Phillips 		alg->cra_priority = TALITOS_CRA_PRIORITY;
33269c4a7965SKim Phillips 	alg->cra_alignmask = 0;
33279c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
3328d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
33299c4a7965SKim Phillips 
33309c4a7965SKim Phillips 	t_alg->dev = dev;
33319c4a7965SKim Phillips 
33329c4a7965SKim Phillips 	return t_alg;
33339c4a7965SKim Phillips }
33349c4a7965SKim Phillips 
3335c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
3336c3e337f8SKim Phillips {
3337c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
3338c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
3339c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3340c3e337f8SKim Phillips 	int err;
3341dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3342c3e337f8SKim Phillips 
3343c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
33442cdba3cfSKim Phillips 	if (!priv->irq[0]) {
3345c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
3346c3e337f8SKim Phillips 		return -EINVAL;
3347c3e337f8SKim Phillips 	}
3348dd3c0987SLEROY Christophe 	if (is_sec1) {
3349dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
3350dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
3351dd3c0987SLEROY Christophe 		goto primary_out;
3352dd3c0987SLEROY Christophe 	}
3353c3e337f8SKim Phillips 
3354c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
3355c3e337f8SKim Phillips 
3356c3e337f8SKim Phillips 	/* get the primary irq line */
33572cdba3cfSKim Phillips 	if (!priv->irq[1]) {
3358dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
3359c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
3360c3e337f8SKim Phillips 		goto primary_out;
3361c3e337f8SKim Phillips 	}
3362c3e337f8SKim Phillips 
3363dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
3364c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3365c3e337f8SKim Phillips 	if (err)
3366c3e337f8SKim Phillips 		goto primary_out;
3367c3e337f8SKim Phillips 
3368c3e337f8SKim Phillips 	/* get the secondary irq line */
3369dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
3370c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3371c3e337f8SKim Phillips 	if (err) {
3372c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
3373c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
33742cdba3cfSKim Phillips 		priv->irq[1] = 0;
3375c3e337f8SKim Phillips 	}
3376c3e337f8SKim Phillips 
3377c3e337f8SKim Phillips 	return err;
3378c3e337f8SKim Phillips 
3379c3e337f8SKim Phillips primary_out:
3380c3e337f8SKim Phillips 	if (err) {
3381c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
3382c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
33832cdba3cfSKim Phillips 		priv->irq[0] = 0;
3384c3e337f8SKim Phillips 	}
3385c3e337f8SKim Phillips 
3386c3e337f8SKim Phillips 	return err;
3387c3e337f8SKim Phillips }
3388c3e337f8SKim Phillips 
33891c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
33909c4a7965SKim Phillips {
33919c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
339261c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
33939c4a7965SKim Phillips 	struct talitos_private *priv;
33949c4a7965SKim Phillips 	int i, err;
33955fa7fa14SLEROY Christophe 	int stride;
3396fd5ea7f0SLEROY Christophe 	struct resource *res;
33979c4a7965SKim Phillips 
339824b92ff2SLEROY Christophe 	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
33999c4a7965SKim Phillips 	if (!priv)
34009c4a7965SKim Phillips 		return -ENOMEM;
34019c4a7965SKim Phillips 
3402f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
3403f3de9cb1SKevin Hao 
34049c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
34059c4a7965SKim Phillips 
34069c4a7965SKim Phillips 	priv->ofdev = ofdev;
34079c4a7965SKim Phillips 
3408511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
3409511d63cbSHoria Geanta 
3410fd5ea7f0SLEROY Christophe 	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
3411fd5ea7f0SLEROY Christophe 	if (!res)
3412fd5ea7f0SLEROY Christophe 		return -ENXIO;
3413fd5ea7f0SLEROY Christophe 	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
34149c4a7965SKim Phillips 	if (!priv->reg) {
34159c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
34169c4a7965SKim Phillips 		err = -ENOMEM;
34179c4a7965SKim Phillips 		goto err_out;
34189c4a7965SKim Phillips 	}
34199c4a7965SKim Phillips 
34209c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
3421fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
3422fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
3423fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
3424fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,descriptor-types-mask",
3425fa14c6cfSLEROY Christophe 			     &priv->desc_types);
34269c4a7965SKim Phillips 
34279c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
34289c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
34299c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
34309c4a7965SKim Phillips 		err = -EINVAL;
34319c4a7965SKim Phillips 		goto err_out;
34329c4a7965SKim Phillips 	}
34339c4a7965SKim Phillips 
3434f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3435f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3436f3c85bc1SLee Nipper 
3437fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
343860f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
343979b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
344079b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3441fe5720e2SKim Phillips 
344221590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
344321590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
344421590888SLEROY Christophe 
34455fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
34465fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
34475fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
34485fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
34495fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
34505fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
34515fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
34525fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
34535fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
34545fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
34555fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
34565fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
34575fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
34585fa7fa14SLEROY Christophe 	} else {
34595fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
34605fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
34615fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
34625fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
34635fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
34645fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
34655fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
34665fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
34675fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
34685fa7fa14SLEROY Christophe 	}
34695fa7fa14SLEROY Christophe 
3470dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3471dd3c0987SLEROY Christophe 	if (err)
3472dd3c0987SLEROY Christophe 		goto err_out;
3473dd3c0987SLEROY Christophe 
3474dd3c0987SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0")) {
34759c02e285SLEROY Christophe 		if (priv->num_channels == 1)
34769c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
34779c02e285SLEROY Christophe 				     (unsigned long)dev);
34789c02e285SLEROY Christophe 		else
3479dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3480dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3481dd3c0987SLEROY Christophe 	} else {
34829c02e285SLEROY Christophe 		if (priv->irq[1]) {
3483dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3484dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3485dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3486dd3c0987SLEROY Christophe 				     (unsigned long)dev);
34879c02e285SLEROY Christophe 		} else if (priv->num_channels == 1) {
34889c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
34899c02e285SLEROY Christophe 				     (unsigned long)dev);
34909c02e285SLEROY Christophe 		} else {
34919c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
34929c02e285SLEROY Christophe 				     (unsigned long)dev);
3493dd3c0987SLEROY Christophe 		}
3494dd3c0987SLEROY Christophe 	}
3495dd3c0987SLEROY Christophe 
3496a86854d0SKees Cook 	priv->chan = devm_kcalloc(dev,
3497a86854d0SKees Cook 				  priv->num_channels,
3498a86854d0SKees Cook 				  sizeof(struct talitos_channel),
3499a86854d0SKees Cook 				  GFP_KERNEL);
35004b992628SKim Phillips 	if (!priv->chan) {
35014b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
35029c4a7965SKim Phillips 		err = -ENOMEM;
35039c4a7965SKim Phillips 		goto err_out;
35049c4a7965SKim Phillips 	}
35059c4a7965SKim Phillips 
3506f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3507f641ddddSMartin Hicks 
3508c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
35095fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
35102cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3511c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3512ad42d5fcSKim Phillips 
35134b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
35144b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
35159c4a7965SKim Phillips 
3516a86854d0SKees Cook 		priv->chan[i].fifo = devm_kcalloc(dev,
3517a86854d0SKees Cook 						priv->fifo_len,
3518a86854d0SKees Cook 						sizeof(struct talitos_request),
3519a86854d0SKees Cook 						GFP_KERNEL);
35204b992628SKim Phillips 		if (!priv->chan[i].fifo) {
35219c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
35229c4a7965SKim Phillips 			err = -ENOMEM;
35239c4a7965SKim Phillips 			goto err_out;
35249c4a7965SKim Phillips 		}
35259c4a7965SKim Phillips 
35264b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
35274b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3528f641ddddSMartin Hicks 	}
35299c4a7965SKim Phillips 
353081eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
353181eb024cSKim Phillips 
35329c4a7965SKim Phillips 	/* reset and initialize the h/w */
35339c4a7965SKim Phillips 	err = init_device(dev);
35349c4a7965SKim Phillips 	if (err) {
35359c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
35369c4a7965SKim Phillips 		goto err_out;
35379c4a7965SKim Phillips 	}
35389c4a7965SKim Phillips 
35399c4a7965SKim Phillips 	/* register the RNG, if available */
35409c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
35419c4a7965SKim Phillips 		err = talitos_register_rng(dev);
35429c4a7965SKim Phillips 		if (err) {
35439c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
35449c4a7965SKim Phillips 			goto err_out;
35459c4a7965SKim Phillips 		} else
35469c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
35479c4a7965SKim Phillips 	}
35489c4a7965SKim Phillips 
35499c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
35509c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
35519c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
35529c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3553aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
35549c4a7965SKim Phillips 
35559c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
35569c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
35579c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
35580b2730d8SKim Phillips 				if (err == -ENOTSUPP)
355979b3a418SLee Nipper 					continue;
35609c4a7965SKim Phillips 				goto err_out;
35619c4a7965SKim Phillips 			}
35629c4a7965SKim Phillips 
3563acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3564acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
3565acbf7c62SLee Nipper 				err = crypto_register_alg(
3566acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
3567aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.crypto;
3568acbf7c62SLee Nipper 				break;
3569aeb4c132SHerbert Xu 
3570aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3571aeb4c132SHerbert Xu 				err = crypto_register_aead(
3572aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3573aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3574aeb4c132SHerbert Xu 				break;
3575aeb4c132SHerbert Xu 
3576acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3577acbf7c62SLee Nipper 				err = crypto_register_ahash(
3578acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3579aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3580acbf7c62SLee Nipper 				break;
3581acbf7c62SLee Nipper 			}
35829c4a7965SKim Phillips 			if (err) {
35839c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3584aeb4c132SHerbert Xu 					alg->cra_driver_name);
358524b92ff2SLEROY Christophe 				devm_kfree(dev, t_alg);
3586991155baSHoria Geanta 			} else
35879c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
35889c4a7965SKim Phillips 		}
35899c4a7965SKim Phillips 	}
35905b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
35915b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
35925b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
35939c4a7965SKim Phillips 
35949c4a7965SKim Phillips 	return 0;
35959c4a7965SKim Phillips 
35969c4a7965SKim Phillips err_out:
35979c4a7965SKim Phillips 	talitos_remove(ofdev);
35989c4a7965SKim Phillips 
35999c4a7965SKim Phillips 	return err;
36009c4a7965SKim Phillips }
36019c4a7965SKim Phillips 
36026c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
36030635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
36040635b7dbSLEROY Christophe 	{
36050635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
36060635b7dbSLEROY Christophe 	},
36070635b7dbSLEROY Christophe #endif
36080635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
36099c4a7965SKim Phillips 	{
36109c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
36119c4a7965SKim Phillips 	},
36120635b7dbSLEROY Christophe #endif
36139c4a7965SKim Phillips 	{},
36149c4a7965SKim Phillips };
36159c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
36169c4a7965SKim Phillips 
36171c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
36184018294bSGrant Likely 	.driver = {
36199c4a7965SKim Phillips 		.name = "talitos",
36204018294bSGrant Likely 		.of_match_table = talitos_match,
36214018294bSGrant Likely 	},
36229c4a7965SKim Phillips 	.probe = talitos_probe,
3623596f1034SAl Viro 	.remove = talitos_remove,
36249c4a7965SKim Phillips };
36259c4a7965SKim Phillips 
3626741e8c2dSAxel Lin module_platform_driver(talitos_driver);
36279c4a7965SKim Phillips 
36289c4a7965SKim Phillips MODULE_LICENSE("GPL");
36299c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
36309c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3631