xref: /linux/drivers/crypto/talitos.c (revision 6a4967c3e1fc1f2fd19283e5c98076a65f7b29ff)
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  */
107*6a4967c3SLEROY Christophe static void __map_single_talitos_ptr(struct device *dev,
108*6a4967c3SLEROY Christophe 				     struct talitos_ptr *ptr,
109*6a4967c3SLEROY Christophe 				     unsigned int len, void *data,
110*6a4967c3SLEROY Christophe 				     enum dma_data_direction dir,
111*6a4967c3SLEROY Christophe 				     unsigned long attrs)
112*6a4967c3SLEROY Christophe {
113*6a4967c3SLEROY Christophe 	dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs);
114*6a4967c3SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
115*6a4967c3SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
116*6a4967c3SLEROY Christophe 
117*6a4967c3SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr, len, is_sec1);
118*6a4967c3SLEROY Christophe }
119*6a4967c3SLEROY 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 {
125*6a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir, 0);
126*6a4967c3SLEROY Christophe }
12781eb024cSKim Phillips 
128*6a4967c3SLEROY Christophe static void map_single_talitos_ptr_nosync(struct device *dev,
129*6a4967c3SLEROY Christophe 					  struct talitos_ptr *ptr,
130*6a4967c3SLEROY Christophe 					  unsigned int len, void *data,
131*6a4967c3SLEROY Christophe 					  enum dma_data_direction dir)
132*6a4967c3SLEROY Christophe {
133*6a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir,
134*6a4967c3SLEROY 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)
84003d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
8413952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
84270bcaca7SLee Nipper 
8439c4a7965SKim Phillips struct talitos_ctx {
8449c4a7965SKim Phillips 	struct device *dev;
8455228f0f7SKim Phillips 	int ch;
8469c4a7965SKim Phillips 	__be32 desc_hdr_template;
8479c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
84870bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8492e13ce08SLEROY Christophe 	dma_addr_t dma_key;
8509c4a7965SKim Phillips 	unsigned int keylen;
8519c4a7965SKim Phillips 	unsigned int enckeylen;
8529c4a7965SKim Phillips 	unsigned int authkeylen;
8539c4a7965SKim Phillips };
8549c4a7965SKim Phillips 
855497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
856497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
857497f2e6bSLee Nipper 
858497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
85960f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
860497f2e6bSLee Nipper 	unsigned int hw_context_size;
8613c0dd190SLEROY Christophe 	u8 buf[2][HASH_MAX_BLOCK_SIZE];
8623c0dd190SLEROY Christophe 	int buf_idx;
86360f208d7SKim Phillips 	unsigned int swinit;
864497f2e6bSLee Nipper 	unsigned int first;
865497f2e6bSLee Nipper 	unsigned int last;
866497f2e6bSLee Nipper 	unsigned int to_hash_later;
86742e8b0d7SHoria Geant? 	unsigned int nbuf;
868497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
869497f2e6bSLee Nipper 	struct scatterlist *psrc;
870497f2e6bSLee Nipper };
871497f2e6bSLee Nipper 
8723639ca84SHoria Geant? struct talitos_export_state {
8733639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8743639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8753639ca84SHoria Geant? 	unsigned int swinit;
8763639ca84SHoria Geant? 	unsigned int first;
8773639ca84SHoria Geant? 	unsigned int last;
8783639ca84SHoria Geant? 	unsigned int to_hash_later;
8793639ca84SHoria Geant? 	unsigned int nbuf;
8803639ca84SHoria Geant? };
8813639ca84SHoria Geant? 
88256af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8839c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8849c4a7965SKim Phillips {
8859c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
8862e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
887c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8889c4a7965SKim Phillips 
889c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8909c4a7965SKim Phillips 		goto badkey;
8919c4a7965SKim Phillips 
892c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8939c4a7965SKim Phillips 		goto badkey;
8949c4a7965SKim Phillips 
8952e13ce08SLEROY Christophe 	if (ctx->keylen)
8962e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
8972e13ce08SLEROY Christophe 
898c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
899c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
9009c4a7965SKim Phillips 
901c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
902c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
903c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
9042e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
9052e13ce08SLEROY Christophe 				      DMA_TO_DEVICE);
9069c4a7965SKim Phillips 
9079c4a7965SKim Phillips 	return 0;
9089c4a7965SKim Phillips 
9099c4a7965SKim Phillips badkey:
9109c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
9119c4a7965SKim Phillips 	return -EINVAL;
9129c4a7965SKim Phillips }
9139c4a7965SKim Phillips 
9149c4a7965SKim Phillips /*
91556af8cd4SLee Nipper  * talitos_edesc - s/w-extended descriptor
9169c4a7965SKim Phillips  * @src_nents: number of segments in input scatterlist
9179c4a7965SKim Phillips  * @dst_nents: number of segments in output scatterlist
918aeb4c132SHerbert Xu  * @icv_ool: whether ICV is out-of-line
91979fd31d3SHoria Geanta  * @iv_dma: dma address of iv for checking continuity and link table
9209c4a7965SKim Phillips  * @dma_len: length of dma mapped link_tbl space
9216f65f6acSLEROY Christophe  * @dma_link_tbl: bus physical address of link_tbl/buf
9229c4a7965SKim Phillips  * @desc: h/w descriptor
9236f65f6acSLEROY Christophe  * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
9246f65f6acSLEROY Christophe  * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
9259c4a7965SKim Phillips  *
9269c4a7965SKim Phillips  * if decrypting (with authcheck), or either one of src_nents or dst_nents
9279c4a7965SKim Phillips  * is greater than 1, an integrity check value is concatenated to the end
9289c4a7965SKim Phillips  * of link_tbl data
9299c4a7965SKim Phillips  */
93056af8cd4SLee Nipper struct talitos_edesc {
9319c4a7965SKim Phillips 	int src_nents;
9329c4a7965SKim Phillips 	int dst_nents;
933aeb4c132SHerbert Xu 	bool icv_ool;
93479fd31d3SHoria Geanta 	dma_addr_t iv_dma;
9359c4a7965SKim Phillips 	int dma_len;
9369c4a7965SKim Phillips 	dma_addr_t dma_link_tbl;
9379c4a7965SKim Phillips 	struct talitos_desc desc;
9386f65f6acSLEROY Christophe 	union {
9399c4a7965SKim Phillips 		struct talitos_ptr link_tbl[0];
9406f65f6acSLEROY Christophe 		u8 buf[0];
9416f65f6acSLEROY Christophe 	};
9429c4a7965SKim Phillips };
9439c4a7965SKim Phillips 
9444de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9454de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9464de9d0b5SLee Nipper 			     struct scatterlist *src,
9476a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
9486a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
949246a87cdSLEROY Christophe {
950246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
951246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9526a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
9536a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
954246a87cdSLEROY Christophe 
9556a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
9566a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
957246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
9586a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
9596a1e8d14SLEROY Christophe 				     offset);
960246a87cdSLEROY Christophe 	}
9616a1e8d14SLEROY Christophe 	if (src != dst) {
9626a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
9636a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
9646a1e8d14SLEROY Christophe 
9656a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
9666a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
9676a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
9686a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
969246a87cdSLEROY Christophe 	}
970246a87cdSLEROY Christophe }
971246a87cdSLEROY Christophe 
9729c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
97356af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
9749c4a7965SKim Phillips 			    struct aead_request *areq)
9759c4a7965SKim Phillips {
976549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
977549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
978549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
9799a655608SLEROY Christophe 	bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
9809a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
981549bd8bcSLEROY Christophe 
9829a655608SLEROY Christophe 	if (is_ipsec_esp)
983549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
984549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
9859a655608SLEROY Christophe 	unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
9869c4a7965SKim Phillips 
9876a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen,
9886a1e8d14SLEROY Christophe 			 areq->assoclen);
9899c4a7965SKim Phillips 
9909c4a7965SKim Phillips 	if (edesc->dma_len)
9919c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
9929c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
993549bd8bcSLEROY Christophe 
9949a655608SLEROY Christophe 	if (!is_ipsec_esp) {
995549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
996549bd8bcSLEROY Christophe 
997549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
998549bd8bcSLEROY Christophe 				   areq->assoclen + areq->cryptlen - ivsize);
999549bd8bcSLEROY Christophe 	}
10009c4a7965SKim Phillips }
10019c4a7965SKim Phillips 
10029c4a7965SKim Phillips /*
10039c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
10049c4a7965SKim Phillips  */
10059c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
10069c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
10079c4a7965SKim Phillips 				   int err)
10089c4a7965SKim Phillips {
1009549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1010549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10119c4a7965SKim Phillips 	struct aead_request *areq = context;
10129c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1013aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
10142e13ce08SLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(authenc);
101519bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10169c4a7965SKim Phillips 	struct scatterlist *sg;
10179c4a7965SKim Phillips 	void *icvdata;
10189c4a7965SKim Phillips 
101919bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
102019bbbc63SKim Phillips 
10219c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, areq);
10229c4a7965SKim Phillips 
10239c4a7965SKim Phillips 	/* copy the generated ICV to dst */
1024aeb4c132SHerbert Xu 	if (edesc->icv_ool) {
1025549bd8bcSLEROY Christophe 		if (is_sec1)
1026549bd8bcSLEROY Christophe 			icvdata = edesc->buf + areq->assoclen + areq->cryptlen;
1027549bd8bcSLEROY Christophe 		else
10289c4a7965SKim Phillips 			icvdata = &edesc->link_tbl[edesc->src_nents +
1029aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
10309c4a7965SKim Phillips 		sg = sg_last(areq->dst, edesc->dst_nents);
1031aeb4c132SHerbert Xu 		memcpy((char *)sg_virt(sg) + sg->length - authsize,
1032aeb4c132SHerbert Xu 		       icvdata, authsize);
10339c4a7965SKim Phillips 	}
10349c4a7965SKim Phillips 
10352e13ce08SLEROY Christophe 	dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
10362e13ce08SLEROY Christophe 
10379c4a7965SKim Phillips 	kfree(edesc);
10389c4a7965SKim Phillips 
10399c4a7965SKim Phillips 	aead_request_complete(areq, err);
10409c4a7965SKim Phillips }
10419c4a7965SKim Phillips 
1042fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1043e938e465SKim Phillips 					  struct talitos_desc *desc,
1044e938e465SKim Phillips 					  void *context, int err)
10459c4a7965SKim Phillips {
10469c4a7965SKim Phillips 	struct aead_request *req = context;
10479c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1048aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
104919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10509c4a7965SKim Phillips 	struct scatterlist *sg;
1051aeb4c132SHerbert Xu 	char *oicv, *icv;
1052549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1053549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10549c4a7965SKim Phillips 
105519bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
105619bbbc63SKim Phillips 
10579c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
10589c4a7965SKim Phillips 
10599c4a7965SKim Phillips 	if (!err) {
10609c4a7965SKim Phillips 		/* auth check */
10619c4a7965SKim Phillips 		sg = sg_last(req->dst, edesc->dst_nents ? : 1);
1062aeb4c132SHerbert Xu 		icv = (char *)sg_virt(sg) + sg->length - authsize;
1063aeb4c132SHerbert Xu 
1064aeb4c132SHerbert Xu 		if (edesc->dma_len) {
1065549bd8bcSLEROY Christophe 			if (is_sec1)
1066549bd8bcSLEROY Christophe 				oicv = (char *)&edesc->dma_link_tbl +
1067549bd8bcSLEROY Christophe 					       req->assoclen + req->cryptlen;
1068549bd8bcSLEROY Christophe 			else
1069549bd8bcSLEROY Christophe 				oicv = (char *)
1070549bd8bcSLEROY Christophe 				       &edesc->link_tbl[edesc->src_nents +
1071aeb4c132SHerbert Xu 							edesc->dst_nents + 2];
1072aeb4c132SHerbert Xu 			if (edesc->icv_ool)
1073aeb4c132SHerbert Xu 				icv = oicv + authsize;
1074aeb4c132SHerbert Xu 		} else
1075aeb4c132SHerbert Xu 			oicv = (char *)&edesc->link_tbl[0];
1076aeb4c132SHerbert Xu 
107779960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10789c4a7965SKim Phillips 	}
10799c4a7965SKim Phillips 
10809c4a7965SKim Phillips 	kfree(edesc);
10819c4a7965SKim Phillips 
10829c4a7965SKim Phillips 	aead_request_complete(req, err);
10839c4a7965SKim Phillips }
10849c4a7965SKim Phillips 
1085fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1086e938e465SKim Phillips 					  struct talitos_desc *desc,
1087e938e465SKim Phillips 					  void *context, int err)
1088fe5720e2SKim Phillips {
1089fe5720e2SKim Phillips 	struct aead_request *req = context;
109019bbbc63SKim Phillips 	struct talitos_edesc *edesc;
109119bbbc63SKim Phillips 
109219bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1093fe5720e2SKim Phillips 
1094fe5720e2SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
1095fe5720e2SKim Phillips 
1096fe5720e2SKim Phillips 	/* check ICV auth status */
1097e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1098e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1099fe5720e2SKim Phillips 		err = -EBADMSG;
1100fe5720e2SKim Phillips 
1101fe5720e2SKim Phillips 	kfree(edesc);
1102fe5720e2SKim Phillips 
1103fe5720e2SKim Phillips 	aead_request_complete(req, err);
1104fe5720e2SKim Phillips }
1105fe5720e2SKim Phillips 
11069c4a7965SKim Phillips /*
11079c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
11089c4a7965SKim Phillips  * stop at cryptlen bytes
11099c4a7965SKim Phillips  */
1110aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1111aeb4c132SHerbert Xu 				 unsigned int offset, int cryptlen,
1112aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
11139c4a7965SKim Phillips {
111470bcaca7SLee Nipper 	int n_sg = sg_count;
1115aeb4c132SHerbert Xu 	int count = 0;
111670bcaca7SLee Nipper 
1117aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1118aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1119aeb4c132SHerbert Xu 
1120aeb4c132SHerbert Xu 		if (offset >= len) {
1121aeb4c132SHerbert Xu 			offset -= len;
1122aeb4c132SHerbert Xu 			goto next;
1123aeb4c132SHerbert Xu 		}
1124aeb4c132SHerbert Xu 
1125aeb4c132SHerbert Xu 		len -= offset;
1126aeb4c132SHerbert Xu 
1127aeb4c132SHerbert Xu 		if (len > cryptlen)
1128aeb4c132SHerbert Xu 			len = cryptlen;
1129aeb4c132SHerbert Xu 
1130aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1131da9de146SLEROY Christophe 			       sg_dma_address(sg) + offset, len, 0);
1132b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1133aeb4c132SHerbert Xu 		count++;
1134aeb4c132SHerbert Xu 		cryptlen -= len;
1135aeb4c132SHerbert Xu 		offset = 0;
1136aeb4c132SHerbert Xu 
1137aeb4c132SHerbert Xu next:
11385be4d4c9SCristian Stoica 		sg = sg_next(sg);
11399c4a7965SKim Phillips 	}
11409c4a7965SKim Phillips 
11419c4a7965SKim Phillips 	/* tag end of link table */
1142aeb4c132SHerbert Xu 	if (count > 0)
1143b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1144b096b544SLEROY Christophe 				       DESC_PTR_LNKTBL_RETURN, 0);
114570bcaca7SLee Nipper 
1146aeb4c132SHerbert Xu 	return count;
1147aeb4c132SHerbert Xu }
1148aeb4c132SHerbert Xu 
11495b2cf268SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src,
1150246a87cdSLEROY Christophe 		   unsigned int len, struct talitos_edesc *edesc,
11516a1e8d14SLEROY Christophe 		   struct talitos_ptr *ptr,
11526a1e8d14SLEROY Christophe 		   int sg_count, unsigned int offset, int tbl_off)
1153246a87cdSLEROY Christophe {
1154246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1155246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1156246a87cdSLEROY Christophe 
115787a81dceSLEROY Christophe 	if (!src) {
115887a81dceSLEROY Christophe 		to_talitos_ptr(ptr, 0, 0, is_sec1);
115987a81dceSLEROY Christophe 		return 1;
116087a81dceSLEROY Christophe 	}
1161246a87cdSLEROY Christophe 	if (sg_count == 1) {
1162da9de146SLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1);
1163246a87cdSLEROY Christophe 		return sg_count;
1164246a87cdSLEROY Christophe 	}
1165246a87cdSLEROY Christophe 	if (is_sec1) {
1166da9de146SLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1);
11676a1e8d14SLEROY Christophe 		return sg_count;
1168246a87cdSLEROY Christophe 	}
11696a1e8d14SLEROY Christophe 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len,
11706a1e8d14SLEROY Christophe 					 &edesc->link_tbl[tbl_off]);
1171246a87cdSLEROY Christophe 	if (sg_count == 1) {
11726a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
11736a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
11746a1e8d14SLEROY Christophe 		return sg_count;
11756a1e8d14SLEROY Christophe 	}
1176246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
1177da9de146SLEROY Christophe 			    tbl_off * sizeof(struct talitos_ptr), len, is_sec1);
11786a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
11796a1e8d14SLEROY Christophe 
11806a1e8d14SLEROY Christophe 	return sg_count;
1181246a87cdSLEROY Christophe }
1182246a87cdSLEROY Christophe 
11839c4a7965SKim Phillips /*
11849c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
11859c4a7965SKim Phillips  */
118656af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
1187aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
11889c4a7965SKim Phillips 				      struct talitos_desc *desc,
11899c4a7965SKim Phillips 				      void *context, int error))
11909c4a7965SKim Phillips {
11919c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1192aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
11939c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
11949c4a7965SKim Phillips 	struct device *dev = ctx->dev;
11959c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
11969c4a7965SKim Phillips 	unsigned int cryptlen = areq->cryptlen;
1197e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1198aeb4c132SHerbert Xu 	int tbl_off = 0;
1199fa86a267SKim Phillips 	int sg_count, ret;
1200fe5720e2SKim Phillips 	int sg_link_tbl_len;
1201549bd8bcSLEROY Christophe 	bool sync_needed = false;
1202549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1203549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
12049a655608SLEROY Christophe 	bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
12059a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
12069a655608SLEROY Christophe 	struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
12079c4a7965SKim Phillips 
12089c4a7965SKim Phillips 	/* hmac key */
12092e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1);
121079fd31d3SHoria Geanta 
1211549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1212549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1213549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1214549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1215549bd8bcSLEROY Christophe 	else
1216549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1217549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1218549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1219549bd8bcSLEROY Christophe 
12209c4a7965SKim Phillips 	/* hmac data */
1221549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1222549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
122379fd31d3SHoria Geanta 
1224549bd8bcSLEROY Christophe 	if (ret > 1) {
1225340ff60aSHoria Geant? 		tbl_off += ret;
1226549bd8bcSLEROY Christophe 		sync_needed = true;
122779fd31d3SHoria Geanta 	}
122879fd31d3SHoria Geanta 
12299c4a7965SKim Phillips 	/* cipher iv */
12309a655608SLEROY Christophe 	to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1);
12319c4a7965SKim Phillips 
12329c4a7965SKim Phillips 	/* cipher key */
12332e13ce08SLEROY Christophe 	to_talitos_ptr(ckey_ptr, ctx->dma_key  + ctx->authkeylen,
12342e13ce08SLEROY Christophe 		       ctx->enckeylen, is_sec1);
12359c4a7965SKim Phillips 
12369c4a7965SKim Phillips 	/*
12379c4a7965SKim Phillips 	 * cipher in
12389c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
12399c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
12409c4a7965SKim Phillips 	 * typically 12 for ipsec
12419c4a7965SKim Phillips 	 */
1242fe5720e2SKim Phillips 	sg_link_tbl_len = cryptlen;
1243549bd8bcSLEROY Christophe 
12449a655608SLEROY Christophe 	if (is_ipsec_esp) {
1245549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[4], authsize, is_sec1);
1246549bd8bcSLEROY Christophe 
12479a655608SLEROY Christophe 		if (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)
1248aeb4c132SHerbert Xu 			sg_link_tbl_len += authsize;
1249549bd8bcSLEROY Christophe 	}
1250e938e465SKim Phillips 
1251fbb22137SLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, sg_link_tbl_len, edesc,
1252fbb22137SLEROY Christophe 			     &desc->ptr[4], sg_count, areq->assoclen, tbl_off);
1253549bd8bcSLEROY Christophe 
1254ec8c7d14SLEROY Christophe 	if (ret > 1) {
1255ec8c7d14SLEROY Christophe 		tbl_off += ret;
1256549bd8bcSLEROY Christophe 		sync_needed = true;
1257340ff60aSHoria Geant? 	}
12589c4a7965SKim Phillips 
12599c4a7965SKim Phillips 	/* cipher out */
1260549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1261549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1262549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1263549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1264549bd8bcSLEROY Christophe 	}
12659c4a7965SKim Phillips 
1266e04a61beSLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
1267e04a61beSLEROY Christophe 			     sg_count, areq->assoclen, tbl_off);
12689c4a7965SKim Phillips 
12699a655608SLEROY Christophe 	if (is_ipsec_esp)
1270549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1271aeb4c132SHerbert Xu 
1272e04a61beSLEROY Christophe 	/* ICV data */
1273e04a61beSLEROY Christophe 	if (ret > 1) {
1274e04a61beSLEROY Christophe 		tbl_off += ret;
1275549bd8bcSLEROY Christophe 		edesc->icv_ool = true;
1276549bd8bcSLEROY Christophe 		sync_needed = true;
1277549bd8bcSLEROY Christophe 
12789a655608SLEROY Christophe 		if (is_ipsec_esp) {
127979fd31d3SHoria Geanta 			struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1280549bd8bcSLEROY Christophe 			int offset = (edesc->src_nents + edesc->dst_nents + 2) *
1281549bd8bcSLEROY Christophe 				     sizeof(struct talitos_ptr) + authsize;
1282fe5720e2SKim Phillips 
1283f3c85bc1SLee Nipper 			/* Add an entry to the link table for ICV data */
1284e04a61beSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
1285549bd8bcSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN,
1286549bd8bcSLEROY Christophe 					       is_sec1);
12879c4a7965SKim Phillips 
12889c4a7965SKim Phillips 			/* icv data follows link tables */
1289549bd8bcSLEROY Christophe 			to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl + offset,
1290da9de146SLEROY Christophe 				       authsize, is_sec1);
1291e04a61beSLEROY Christophe 		} else {
1292e04a61beSLEROY Christophe 			dma_addr_t addr = edesc->dma_link_tbl;
1293e04a61beSLEROY Christophe 
1294e04a61beSLEROY Christophe 			if (is_sec1)
1295e04a61beSLEROY Christophe 				addr += areq->assoclen + cryptlen;
1296e04a61beSLEROY Christophe 			else
1297e04a61beSLEROY Christophe 				addr += sizeof(struct talitos_ptr) * tbl_off;
1298e04a61beSLEROY Christophe 
1299da9de146SLEROY Christophe 			to_talitos_ptr(&desc->ptr[6], addr, authsize, is_sec1);
1300549bd8bcSLEROY Christophe 		}
13019a655608SLEROY Christophe 	} else if (!is_ipsec_esp) {
1302e04a61beSLEROY Christophe 		ret = talitos_sg_map(dev, areq->dst, authsize, edesc,
1303e04a61beSLEROY Christophe 				     &desc->ptr[6], sg_count, areq->assoclen +
1304e04a61beSLEROY Christophe 							      cryptlen,
1305e04a61beSLEROY Christophe 				     tbl_off);
1306e04a61beSLEROY Christophe 		if (ret > 1) {
1307e04a61beSLEROY Christophe 			tbl_off += ret;
1308e04a61beSLEROY Christophe 			edesc->icv_ool = true;
1309e04a61beSLEROY Christophe 			sync_needed = true;
1310340ff60aSHoria Geant? 		} else {
1311549bd8bcSLEROY Christophe 			edesc->icv_ool = false;
1312549bd8bcSLEROY Christophe 		}
1313e04a61beSLEROY Christophe 	} else {
1314e04a61beSLEROY Christophe 		edesc->icv_ool = false;
1315340ff60aSHoria Geant? 	}
13169c4a7965SKim Phillips 
13179c4a7965SKim Phillips 	/* iv out */
13189a655608SLEROY Christophe 	if (is_ipsec_esp)
1319a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
13209c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
13219c4a7965SKim Phillips 
1322549bd8bcSLEROY Christophe 	if (sync_needed)
1323549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1324549bd8bcSLEROY Christophe 					   edesc->dma_len,
1325549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1326549bd8bcSLEROY Christophe 
13275228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1328fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
1329fa86a267SKim Phillips 		ipsec_esp_unmap(dev, edesc, areq);
1330fa86a267SKim Phillips 		kfree(edesc);
1331fa86a267SKim Phillips 	}
1332fa86a267SKim Phillips 	return ret;
13339c4a7965SKim Phillips }
13349c4a7965SKim Phillips 
13359c4a7965SKim Phillips /*
133656af8cd4SLee Nipper  * allocate and map the extended descriptor
13379c4a7965SKim Phillips  */
13384de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13394de9d0b5SLee Nipper 						 struct scatterlist *src,
13404de9d0b5SLee Nipper 						 struct scatterlist *dst,
134179fd31d3SHoria Geanta 						 u8 *iv,
134279fd31d3SHoria Geanta 						 unsigned int assoclen,
13434de9d0b5SLee Nipper 						 unsigned int cryptlen,
13444de9d0b5SLee Nipper 						 unsigned int authsize,
134579fd31d3SHoria Geanta 						 unsigned int ivsize,
13464de9d0b5SLee Nipper 						 int icv_stashing,
134762293a37SHoria Geanta 						 u32 cryptoflags,
134862293a37SHoria Geanta 						 bool encrypt)
13499c4a7965SKim Phillips {
135056af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13516a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
135279fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
13534de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1354586725f8SKim Phillips 		      GFP_ATOMIC;
13556f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
13566f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
13576f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
13588e409fe1SLABBE Corentin 	void *err;
13599c4a7965SKim Phillips 
13606f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
13614de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
13629c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
13639c4a7965SKim Phillips 	}
13649c4a7965SKim Phillips 
1365935e99a3SHoria Geanta 	if (ivsize)
136679fd31d3SHoria Geanta 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
136779fd31d3SHoria Geanta 
136862293a37SHoria Geanta 	if (!dst || dst == src) {
13696a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
13706a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13718e409fe1SLABBE Corentin 		if (src_nents < 0) {
13728e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13738e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13748e409fe1SLABBE Corentin 			goto error_sg;
13758e409fe1SLABBE Corentin 		}
13769c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
137762293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
13786a1e8d14SLEROY Christophe 		dst_len = 0;
137962293a37SHoria Geanta 	} else { /* dst && dst != src*/
13806a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
13816a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13828e409fe1SLABBE Corentin 		if (src_nents < 0) {
13838e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13848e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13858e409fe1SLABBE Corentin 			goto error_sg;
13868e409fe1SLABBE Corentin 		}
138762293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
13886a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
13896a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
13908e409fe1SLABBE Corentin 		if (dst_nents < 0) {
13918e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
13928e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13938e409fe1SLABBE Corentin 			goto error_sg;
13948e409fe1SLABBE Corentin 		}
1395695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
13969c4a7965SKim Phillips 	}
13979c4a7965SKim Phillips 
13989c4a7965SKim Phillips 	/*
13999c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1400aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1401aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
14029c4a7965SKim Phillips 	 */
140356af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1404aeb4c132SHerbert Xu 	if (src_nents || dst_nents) {
14056f65f6acSLEROY Christophe 		if (is_sec1)
14066a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
14076a1e8d14SLEROY Christophe 				  (dst_nents ? dst_len : 0);
14086f65f6acSLEROY Christophe 		else
1409aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1410aeb4c132SHerbert Xu 				  sizeof(struct talitos_ptr) + authsize * 2;
14119c4a7965SKim Phillips 		alloc_len += dma_len;
14129c4a7965SKim Phillips 	} else {
14139c4a7965SKim Phillips 		dma_len = 0;
14144de9d0b5SLee Nipper 		alloc_len += icv_stashing ? authsize : 0;
14159c4a7965SKim Phillips 	}
14169c4a7965SKim Phillips 
141737b5e889SLEROY Christophe 	/* if its a ahash, add space for a second desc next to the first one */
141837b5e889SLEROY Christophe 	if (is_sec1 && !dst)
141937b5e889SLEROY Christophe 		alloc_len += sizeof(struct talitos_desc);
142037b5e889SLEROY Christophe 
1421586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
14229c4a7965SKim Phillips 	if (!edesc) {
14234de9d0b5SLee Nipper 		dev_err(dev, "could not allocate edescriptor\n");
14248e409fe1SLABBE Corentin 		err = ERR_PTR(-ENOMEM);
14258e409fe1SLABBE Corentin 		goto error_sg;
14269c4a7965SKim Phillips 	}
1427e4a647c4SLEROY Christophe 	memset(&edesc->desc, 0, sizeof(edesc->desc));
14289c4a7965SKim Phillips 
14299c4a7965SKim Phillips 	edesc->src_nents = src_nents;
14309c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
143179fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
14329c4a7965SKim Phillips 	edesc->dma_len = dma_len;
143337b5e889SLEROY Christophe 	if (dma_len) {
143437b5e889SLEROY Christophe 		void *addr = &edesc->link_tbl[0];
143537b5e889SLEROY Christophe 
143637b5e889SLEROY Christophe 		if (is_sec1 && !dst)
143737b5e889SLEROY Christophe 			addr += sizeof(struct talitos_desc);
143837b5e889SLEROY Christophe 		edesc->dma_link_tbl = dma_map_single(dev, addr,
1439497f2e6bSLee Nipper 						     edesc->dma_len,
1440497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
144137b5e889SLEROY Christophe 	}
14429c4a7965SKim Phillips 	return edesc;
14438e409fe1SLABBE Corentin error_sg:
14448e409fe1SLABBE Corentin 	if (iv_dma)
14458e409fe1SLABBE Corentin 		dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
14468e409fe1SLABBE Corentin 	return err;
14479c4a7965SKim Phillips }
14489c4a7965SKim Phillips 
144979fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
145062293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
14514de9d0b5SLee Nipper {
14524de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1453aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14544de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
145579fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
14564de9d0b5SLee Nipper 
1457aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
145879fd31d3SHoria Geanta 				   iv, areq->assoclen, areq->cryptlen,
1459aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
146062293a37SHoria Geanta 				   areq->base.flags, encrypt);
14614de9d0b5SLee Nipper }
14624de9d0b5SLee Nipper 
146356af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
14649c4a7965SKim Phillips {
14659c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14669c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
146756af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14689c4a7965SKim Phillips 
14699c4a7965SKim Phillips 	/* allocate extended descriptor */
147062293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
14719c4a7965SKim Phillips 	if (IS_ERR(edesc))
14729c4a7965SKim Phillips 		return PTR_ERR(edesc);
14739c4a7965SKim Phillips 
14749c4a7965SKim Phillips 	/* set encrypt */
147570bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14769c4a7965SKim Phillips 
1477aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
14789c4a7965SKim Phillips }
14799c4a7965SKim Phillips 
148056af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
14819c4a7965SKim Phillips {
14829c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1483aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14849c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1485fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
148656af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14879c4a7965SKim Phillips 	struct scatterlist *sg;
14889c4a7965SKim Phillips 	void *icvdata;
14899c4a7965SKim Phillips 
14909c4a7965SKim Phillips 	req->cryptlen -= authsize;
14919c4a7965SKim Phillips 
14929c4a7965SKim Phillips 	/* allocate extended descriptor */
149362293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14949c4a7965SKim Phillips 	if (IS_ERR(edesc))
14959c4a7965SKim Phillips 		return PTR_ERR(edesc);
14969c4a7965SKim Phillips 
1497fe5720e2SKim Phillips 	if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1498e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1499e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1500fe5720e2SKim Phillips 
1501fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1502e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1503e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1504fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1505fe5720e2SKim Phillips 
1506fe5720e2SKim Phillips 		/* reset integrity check result bits */
1507fe5720e2SKim Phillips 
1508aeb4c132SHerbert Xu 		return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
1509e938e465SKim Phillips 	}
1510fe5720e2SKim Phillips 
1511fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1512fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1513fe5720e2SKim Phillips 
15149c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
15159c4a7965SKim Phillips 	if (edesc->dma_len)
1516aeb4c132SHerbert Xu 		icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1517aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
15189c4a7965SKim Phillips 	else
15199c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[0];
15209c4a7965SKim Phillips 
15219c4a7965SKim Phillips 	sg = sg_last(req->src, edesc->src_nents ? : 1);
15229c4a7965SKim Phillips 
1523aeb4c132SHerbert Xu 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
15249c4a7965SKim Phillips 
1525aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
15269c4a7965SKim Phillips }
15279c4a7965SKim Phillips 
15284de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
15294de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
15304de9d0b5SLee Nipper {
15314de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15322e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
1533f384cdc4SLEROY Christophe 	u32 tmp[DES_EXPKEY_WORDS];
15344de9d0b5SLee Nipper 
153503d2c511SMartin Hicks 	if (keylen > TALITOS_MAX_KEY_SIZE) {
153603d2c511SMartin Hicks 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
153703d2c511SMartin Hicks 		return -EINVAL;
153803d2c511SMartin Hicks 	}
153903d2c511SMartin Hicks 
1540f384cdc4SLEROY Christophe 	if (unlikely(crypto_ablkcipher_get_flags(cipher) &
1541f384cdc4SLEROY Christophe 		     CRYPTO_TFM_REQ_WEAK_KEY) &&
1542f384cdc4SLEROY Christophe 	    !des_ekey(tmp, key)) {
1543f384cdc4SLEROY Christophe 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY);
1544f384cdc4SLEROY Christophe 		return -EINVAL;
1545f384cdc4SLEROY Christophe 	}
1546f384cdc4SLEROY Christophe 
15472e13ce08SLEROY Christophe 	if (ctx->keylen)
15482e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
15492e13ce08SLEROY Christophe 
15504de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
15514de9d0b5SLee Nipper 	ctx->keylen = keylen;
15524de9d0b5SLee Nipper 
15532e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE);
15542e13ce08SLEROY Christophe 
15554de9d0b5SLee Nipper 	return 0;
15564de9d0b5SLee Nipper }
15574de9d0b5SLee Nipper 
15584de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
15594de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
15604de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
15614de9d0b5SLee Nipper {
15624de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1563032d197eSLEROY Christophe 
15646a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0);
15654de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
15664de9d0b5SLee Nipper 
15674de9d0b5SLee Nipper 	if (edesc->dma_len)
15684de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
15694de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
15704de9d0b5SLee Nipper }
15714de9d0b5SLee Nipper 
15724de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
15734de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
15744de9d0b5SLee Nipper 			    int err)
15754de9d0b5SLee Nipper {
15764de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
157719bbbc63SKim Phillips 	struct talitos_edesc *edesc;
157819bbbc63SKim Phillips 
157919bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
15804de9d0b5SLee Nipper 
15814de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
15824de9d0b5SLee Nipper 
15834de9d0b5SLee Nipper 	kfree(edesc);
15844de9d0b5SLee Nipper 
15854de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
15864de9d0b5SLee Nipper }
15874de9d0b5SLee Nipper 
15884de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
15894de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
15904de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
15914de9d0b5SLee Nipper 					     struct talitos_desc *desc,
15924de9d0b5SLee Nipper 					     void *context, int error))
15934de9d0b5SLee Nipper {
15944de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15954de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15964de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
15974de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
15984de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
159979fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
16004de9d0b5SLee Nipper 	int sg_count, ret;
16016a1e8d14SLEROY Christophe 	bool sync_needed = false;
1602922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1603922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
16044de9d0b5SLee Nipper 
16054de9d0b5SLee Nipper 	/* first DWORD empty */
16064de9d0b5SLee Nipper 
16074de9d0b5SLee Nipper 	/* cipher iv */
1608da9de146SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1);
16094de9d0b5SLee Nipper 
16104de9d0b5SLee Nipper 	/* cipher key */
16112e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1);
16124de9d0b5SLee Nipper 
16136a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
16146a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
16156a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
16166a1e8d14SLEROY Christophe 				  cryptlen);
16176a1e8d14SLEROY Christophe 	else
16186a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
16196a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
16206a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
16214de9d0b5SLee Nipper 	/*
16224de9d0b5SLee Nipper 	 * cipher in
16234de9d0b5SLee Nipper 	 */
16246a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
16256a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
16266a1e8d14SLEROY Christophe 	if (sg_count > 1)
16276a1e8d14SLEROY Christophe 		sync_needed = true;
16284de9d0b5SLee Nipper 
16294de9d0b5SLee Nipper 	/* cipher out */
16306a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
16316a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
16326a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
16336a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
16346a1e8d14SLEROY Christophe 	}
16356a1e8d14SLEROY Christophe 
16366a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
16376a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
16386a1e8d14SLEROY Christophe 	if (ret > 1)
16396a1e8d14SLEROY Christophe 		sync_needed = true;
16404de9d0b5SLee Nipper 
16414de9d0b5SLee Nipper 	/* iv out */
1642a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
16434de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
16444de9d0b5SLee Nipper 
16454de9d0b5SLee Nipper 	/* last DWORD empty */
16464de9d0b5SLee Nipper 
16476a1e8d14SLEROY Christophe 	if (sync_needed)
16486a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
16496a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
16506a1e8d14SLEROY Christophe 
16515228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
16524de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
16534de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
16544de9d0b5SLee Nipper 		kfree(edesc);
16554de9d0b5SLee Nipper 	}
16564de9d0b5SLee Nipper 	return ret;
16574de9d0b5SLee Nipper }
16584de9d0b5SLee Nipper 
1659e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
166062293a37SHoria Geanta 						    areq, bool encrypt)
16614de9d0b5SLee Nipper {
16624de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16634de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
166479fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
16654de9d0b5SLee Nipper 
1666aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
166779fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
166862293a37SHoria Geanta 				   areq->base.flags, encrypt);
16694de9d0b5SLee Nipper }
16704de9d0b5SLee Nipper 
16714de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
16724de9d0b5SLee Nipper {
16734de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16744de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16754de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16764de9d0b5SLee Nipper 
16774de9d0b5SLee Nipper 	/* allocate extended descriptor */
167862293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
16794de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16804de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16814de9d0b5SLee Nipper 
16824de9d0b5SLee Nipper 	/* set encrypt */
16834de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16844de9d0b5SLee Nipper 
1685febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16864de9d0b5SLee Nipper }
16874de9d0b5SLee Nipper 
16884de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
16894de9d0b5SLee Nipper {
16904de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16914de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16924de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16934de9d0b5SLee Nipper 
16944de9d0b5SLee Nipper 	/* allocate extended descriptor */
169562293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
16964de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16974de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16984de9d0b5SLee Nipper 
16994de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
17004de9d0b5SLee Nipper 
1701febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
17024de9d0b5SLee Nipper }
17034de9d0b5SLee Nipper 
1704497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1705497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1706497f2e6bSLee Nipper 				       struct ahash_request *areq)
1707497f2e6bSLee Nipper {
1708497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1709ad4cd51fSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1710ad4cd51fSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1711ad4cd51fSLEROY Christophe 	struct talitos_desc *desc = &edesc->desc;
1712ad4cd51fSLEROY Christophe 	struct talitos_desc *desc2 = desc + 1;
1713ad4cd51fSLEROY Christophe 
1714ad4cd51fSLEROY Christophe 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1715ad4cd51fSLEROY Christophe 	if (desc->next_desc &&
1716ad4cd51fSLEROY Christophe 	    desc->ptr[5].ptr != desc2->ptr[5].ptr)
1717ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
1718497f2e6bSLee Nipper 
17196a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1720032d197eSLEROY Christophe 
1721ad4cd51fSLEROY Christophe 	/* When using hashctx-in, must unmap it. */
1722ad4cd51fSLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
1723ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1724ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1725ad4cd51fSLEROY Christophe 	else if (desc->next_desc)
1726ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[1],
1727ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1728ad4cd51fSLEROY Christophe 
1729ad4cd51fSLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
1730ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc->ptr[3],
1731ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1732ad4cd51fSLEROY Christophe 
1733497f2e6bSLee Nipper 	if (edesc->dma_len)
1734497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1735497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1736497f2e6bSLee Nipper 
173737b5e889SLEROY Christophe 	if (edesc->desc.next_desc)
173837b5e889SLEROY Christophe 		dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc),
173937b5e889SLEROY Christophe 				 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
1740497f2e6bSLee Nipper }
1741497f2e6bSLee Nipper 
1742497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1743497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1744497f2e6bSLee Nipper 		       int err)
1745497f2e6bSLee Nipper {
1746497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1747497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1748497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1749497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1750497f2e6bSLee Nipper 
1751497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1752497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
17533c0dd190SLEROY Christophe 		req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
17545e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1755497f2e6bSLee Nipper 	}
1756497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1757497f2e6bSLee Nipper 
1758497f2e6bSLee Nipper 	kfree(edesc);
1759497f2e6bSLee Nipper 
1760497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1761497f2e6bSLee Nipper }
1762497f2e6bSLee Nipper 
17632d02905eSLEROY Christophe /*
17642d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
17652d02905eSLEROY Christophe  * ourself and submit a padded block
17662d02905eSLEROY Christophe  */
17675b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
17682d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
17692d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
17702d02905eSLEROY Christophe {
17712d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
17722d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17732d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17742d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17752d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17762d02905eSLEROY Christophe 	};
17772d02905eSLEROY Christophe 
17782d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
17792d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
17802d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
17812d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
17822d02905eSLEROY Christophe }
17832d02905eSLEROY Christophe 
1784497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1785497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
178637b5e889SLEROY Christophe 				unsigned int offset,
1787497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1788497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1789497f2e6bSLee Nipper 						  void *context, int error))
1790497f2e6bSLee Nipper {
1791497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1792497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1793497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1794497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1795497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1796032d197eSLEROY Christophe 	int ret;
17976a1e8d14SLEROY Christophe 	bool sync_needed = false;
1798922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1799922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
18006a1e8d14SLEROY Christophe 	int sg_count;
1801497f2e6bSLee Nipper 
1802497f2e6bSLee Nipper 	/* first DWORD empty */
1803497f2e6bSLee Nipper 
180460f208d7SKim Phillips 	/* hash context in */
180560f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
1806*6a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
1807ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
1808*6a4967c3SLEROY Christophe 					      req_ctx->hw_context,
1809ad4cd51fSLEROY Christophe 					      DMA_TO_DEVICE);
181060f208d7SKim Phillips 		req_ctx->swinit = 0;
1811afd62fa2SLEROY Christophe 	}
1812497f2e6bSLee Nipper 	/* Indicate next op is not the first. */
1813497f2e6bSLee Nipper 	req_ctx->first = 0;
1814497f2e6bSLee Nipper 
1815497f2e6bSLee Nipper 	/* HMAC key */
1816497f2e6bSLee Nipper 	if (ctx->keylen)
18172e13ce08SLEROY Christophe 		to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
18182e13ce08SLEROY Christophe 			       is_sec1);
1819497f2e6bSLee Nipper 
182037b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
182137b5e889SLEROY Christophe 		length -= req_ctx->nbuf;
182237b5e889SLEROY Christophe 
18236a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
18246a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
182537b5e889SLEROY Christophe 		sg_pcopy_to_buffer(req_ctx->psrc, sg_count,
182637b5e889SLEROY Christophe 				   edesc->buf + sizeof(struct talitos_desc),
182737b5e889SLEROY Christophe 				   length, req_ctx->nbuf);
182837b5e889SLEROY Christophe 	else if (length)
18296a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
18306a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1831497f2e6bSLee Nipper 	/*
1832497f2e6bSLee Nipper 	 * data in
1833497f2e6bSLee Nipper 	 */
183437b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf) {
1835ad4cd51fSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
1836ad4cd51fSLEROY Christophe 				       req_ctx->buf[req_ctx->buf_idx],
1837ad4cd51fSLEROY Christophe 				       DMA_TO_DEVICE);
183837b5e889SLEROY Christophe 	} else {
18396a1e8d14SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
184037b5e889SLEROY Christophe 					  &desc->ptr[3], sg_count, offset, 0);
18416a1e8d14SLEROY Christophe 		if (sg_count > 1)
18426a1e8d14SLEROY Christophe 			sync_needed = true;
184337b5e889SLEROY Christophe 	}
1844497f2e6bSLee Nipper 
1845497f2e6bSLee Nipper 	/* fifth DWORD empty */
1846497f2e6bSLee Nipper 
1847497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1848497f2e6bSLee Nipper 	if (req_ctx->last)
1849497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1850497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1851a2b35aa8SLEROY Christophe 				       areq->result, DMA_FROM_DEVICE);
1852497f2e6bSLee Nipper 	else
1853*6a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1854ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
1855*6a4967c3SLEROY Christophe 					      req_ctx->hw_context,
1856*6a4967c3SLEROY Christophe 					      DMA_FROM_DEVICE);
1857497f2e6bSLee Nipper 
1858497f2e6bSLee Nipper 	/* last DWORD empty */
1859497f2e6bSLee Nipper 
18602d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
18612d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
18622d02905eSLEROY Christophe 
186337b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf && length) {
186437b5e889SLEROY Christophe 		struct talitos_desc *desc2 = desc + 1;
186537b5e889SLEROY Christophe 		dma_addr_t next_desc;
186637b5e889SLEROY Christophe 
186737b5e889SLEROY Christophe 		memset(desc2, 0, sizeof(*desc2));
186837b5e889SLEROY Christophe 		desc2->hdr = desc->hdr;
186937b5e889SLEROY Christophe 		desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
187037b5e889SLEROY Christophe 		desc2->hdr1 = desc2->hdr;
187137b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
187237b5e889SLEROY Christophe 		desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
187337b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
187437b5e889SLEROY Christophe 
1875ad4cd51fSLEROY Christophe 		if (desc->ptr[1].ptr)
1876ad4cd51fSLEROY Christophe 			copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
1877ad4cd51fSLEROY Christophe 					 is_sec1);
1878ad4cd51fSLEROY Christophe 		else
1879*6a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc2->ptr[1],
1880ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1881ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1882ad4cd51fSLEROY Christophe 						      DMA_TO_DEVICE);
188337b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
188437b5e889SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
188537b5e889SLEROY Christophe 					  &desc2->ptr[3], sg_count, offset, 0);
188637b5e889SLEROY Christophe 		if (sg_count > 1)
188737b5e889SLEROY Christophe 			sync_needed = true;
188837b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
188937b5e889SLEROY Christophe 		if (req_ctx->last)
1890*6a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1891ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1892ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1893ad4cd51fSLEROY Christophe 						      DMA_FROM_DEVICE);
189437b5e889SLEROY Christophe 
189537b5e889SLEROY Christophe 		next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE,
189637b5e889SLEROY Christophe 					   DMA_BIDIRECTIONAL);
189737b5e889SLEROY Christophe 		desc->next_desc = cpu_to_be32(next_desc);
189837b5e889SLEROY Christophe 	}
189937b5e889SLEROY Christophe 
19006a1e8d14SLEROY Christophe 	if (sync_needed)
19016a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
19026a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
19036a1e8d14SLEROY Christophe 
19045228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1905497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1906497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1907497f2e6bSLee Nipper 		kfree(edesc);
1908497f2e6bSLee Nipper 	}
1909497f2e6bSLee Nipper 	return ret;
1910497f2e6bSLee Nipper }
1911497f2e6bSLee Nipper 
1912497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1913497f2e6bSLee Nipper 					       unsigned int nbytes)
1914497f2e6bSLee Nipper {
1915497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1916497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1917497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
191837b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
191937b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
192037b5e889SLEROY Christophe 
192137b5e889SLEROY Christophe 	if (is_sec1)
192237b5e889SLEROY Christophe 		nbytes -= req_ctx->nbuf;
1923497f2e6bSLee Nipper 
1924aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
192562293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1926497f2e6bSLee Nipper }
1927497f2e6bSLee Nipper 
1928497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1929497f2e6bSLee Nipper {
1930497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1931*6a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1932*6a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
1933497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
193449f9783bSLEROY Christophe 	unsigned int size;
1935*6a4967c3SLEROY Christophe 	dma_addr_t dma;
1936497f2e6bSLee Nipper 
1937497f2e6bSLee Nipper 	/* Initialize the context */
19383c0dd190SLEROY Christophe 	req_ctx->buf_idx = 0;
19395e833bc4SLee Nipper 	req_ctx->nbuf = 0;
194060f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
194160f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
194249f9783bSLEROY Christophe 	size =	(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1943497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1944497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
194549f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
1946497f2e6bSLee Nipper 
1947*6a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
1948*6a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
1949*6a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
1950*6a4967c3SLEROY Christophe 
1951497f2e6bSLee Nipper 	return 0;
1952497f2e6bSLee Nipper }
1953497f2e6bSLee Nipper 
195460f208d7SKim Phillips /*
195560f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
195660f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
195760f208d7SKim Phillips  */
195860f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
195960f208d7SKim Phillips {
196060f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
196160f208d7SKim Phillips 
1962a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1963a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1964a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1965a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1966a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1967a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1968a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1969a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
197060f208d7SKim Phillips 
197160f208d7SKim Phillips 	/* init 64-bit count */
197260f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
197360f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
197460f208d7SKim Phillips 
1975*6a4967c3SLEROY Christophe 	ahash_init(areq);
1976*6a4967c3SLEROY Christophe 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
1977*6a4967c3SLEROY Christophe 
197860f208d7SKim Phillips 	return 0;
197960f208d7SKim Phillips }
198060f208d7SKim Phillips 
1981497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1982497f2e6bSLee Nipper {
1983497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1984497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1985497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1986497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1987497f2e6bSLee Nipper 	unsigned int blocksize =
1988497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1989497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1990497f2e6bSLee Nipper 	unsigned int to_hash_later;
19915e833bc4SLee Nipper 	unsigned int nsg;
19928e409fe1SLABBE Corentin 	int nents;
199337b5e889SLEROY Christophe 	struct device *dev = ctx->dev;
199437b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
199537b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
199637b5e889SLEROY Christophe 	int offset = 0;
19973c0dd190SLEROY Christophe 	u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
1998497f2e6bSLee Nipper 
19995e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
20005e833bc4SLee Nipper 		/* Buffer up to one whole block */
20018e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
20028e409fe1SLABBE Corentin 		if (nents < 0) {
20038e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
20048e409fe1SLABBE Corentin 			return nents;
20058e409fe1SLABBE Corentin 		}
20068e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
20073c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, nbytes);
20085e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
2009497f2e6bSLee Nipper 		return 0;
2010497f2e6bSLee Nipper 	}
2011497f2e6bSLee Nipper 
20125e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
20135e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
20145e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
20155e833bc4SLee Nipper 
20165e833bc4SLee Nipper 	if (req_ctx->last)
20175e833bc4SLee Nipper 		to_hash_later = 0;
20185e833bc4SLee Nipper 	else if (to_hash_later)
20195e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
20205e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
20215e833bc4SLee Nipper 	else {
20225e833bc4SLee Nipper 		/* Keep one block buffered */
20235e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
20245e833bc4SLee Nipper 		to_hash_later = blocksize;
2025497f2e6bSLee Nipper 	}
20265e833bc4SLee Nipper 
20275e833bc4SLee Nipper 	/* Chain in any previously buffered data */
202837b5e889SLEROY Christophe 	if (!is_sec1 && req_ctx->nbuf) {
20295e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
20305e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
20313c0dd190SLEROY Christophe 		sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
20325e833bc4SLee Nipper 		if (nsg > 1)
2033c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
20345e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
203537b5e889SLEROY Christophe 	} else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
203637b5e889SLEROY Christophe 		if (nbytes_to_hash > blocksize)
203737b5e889SLEROY Christophe 			offset = blocksize - req_ctx->nbuf;
203837b5e889SLEROY Christophe 		else
203937b5e889SLEROY Christophe 			offset = nbytes_to_hash - req_ctx->nbuf;
204037b5e889SLEROY Christophe 		nents = sg_nents_for_len(areq->src, offset);
204137b5e889SLEROY Christophe 		if (nents < 0) {
204237b5e889SLEROY Christophe 			dev_err(ctx->dev, "Invalid number of src SG.\n");
204337b5e889SLEROY Christophe 			return nents;
204437b5e889SLEROY Christophe 		}
204537b5e889SLEROY Christophe 		sg_copy_to_buffer(areq->src, nents,
20463c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, offset);
204737b5e889SLEROY Christophe 		req_ctx->nbuf += offset;
204837b5e889SLEROY Christophe 		req_ctx->psrc = areq->src;
20495e833bc4SLee Nipper 	} else
20505e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
20515e833bc4SLee Nipper 
2052497f2e6bSLee Nipper 	if (to_hash_later) {
20538e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
20548e409fe1SLABBE Corentin 		if (nents < 0) {
20558e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
20568e409fe1SLABBE Corentin 			return nents;
20578e409fe1SLABBE Corentin 		}
2058d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
20593c0dd190SLEROY Christophe 				   req_ctx->buf[(req_ctx->buf_idx + 1) & 1],
2060497f2e6bSLee Nipper 				      to_hash_later,
2061497f2e6bSLee Nipper 				      nbytes - to_hash_later);
2062497f2e6bSLee Nipper 	}
2063497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
2064497f2e6bSLee Nipper 
20655e833bc4SLee Nipper 	/* Allocate extended descriptor */
2066497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
2067497f2e6bSLee Nipper 	if (IS_ERR(edesc))
2068497f2e6bSLee Nipper 		return PTR_ERR(edesc);
2069497f2e6bSLee Nipper 
2070497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
2071497f2e6bSLee Nipper 
2072497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
2073497f2e6bSLee Nipper 	if (req_ctx->last)
2074497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
2075497f2e6bSLee Nipper 	else
2076497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
2077497f2e6bSLee Nipper 
207860f208d7SKim Phillips 	/* request SEC to INIT hash. */
207960f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
2080497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
2081497f2e6bSLee Nipper 
2082497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
2083497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
2084497f2e6bSLee Nipper 	 */
2085497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
2086497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
2087497f2e6bSLee Nipper 
208837b5e889SLEROY Christophe 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, offset,
2089497f2e6bSLee Nipper 				    ahash_done);
2090497f2e6bSLee Nipper }
2091497f2e6bSLee Nipper 
2092497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
2093497f2e6bSLee Nipper {
2094497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2095497f2e6bSLee Nipper 
2096497f2e6bSLee Nipper 	req_ctx->last = 0;
2097497f2e6bSLee Nipper 
2098497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2099497f2e6bSLee Nipper }
2100497f2e6bSLee Nipper 
2101497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
2102497f2e6bSLee Nipper {
2103497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2104497f2e6bSLee Nipper 
2105497f2e6bSLee Nipper 	req_ctx->last = 1;
2106497f2e6bSLee Nipper 
2107497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
2108497f2e6bSLee Nipper }
2109497f2e6bSLee Nipper 
2110497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
2111497f2e6bSLee Nipper {
2112497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2113497f2e6bSLee Nipper 
2114497f2e6bSLee Nipper 	req_ctx->last = 1;
2115497f2e6bSLee Nipper 
2116497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2117497f2e6bSLee Nipper }
2118497f2e6bSLee Nipper 
2119497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
2120497f2e6bSLee Nipper {
2121497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
212260f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2123497f2e6bSLee Nipper 
212460f208d7SKim Phillips 	ahash->init(areq);
2125497f2e6bSLee Nipper 	req_ctx->last = 1;
2126497f2e6bSLee Nipper 
2127497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2128497f2e6bSLee Nipper }
2129497f2e6bSLee Nipper 
21303639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
21313639ca84SHoria Geant? {
21323639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21333639ca84SHoria Geant? 	struct talitos_export_state *export = out;
2134*6a4967c3SLEROY Christophe 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2135*6a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
2136*6a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
2137*6a4967c3SLEROY Christophe 	dma_addr_t dma;
2138*6a4967c3SLEROY Christophe 
2139*6a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
2140*6a4967c3SLEROY Christophe 			     DMA_FROM_DEVICE);
2141*6a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE);
21423639ca84SHoria Geant? 
21433639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
21443639ca84SHoria Geant? 	       req_ctx->hw_context_size);
21453c0dd190SLEROY Christophe 	memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf);
21463639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
21473639ca84SHoria Geant? 	export->first = req_ctx->first;
21483639ca84SHoria Geant? 	export->last = req_ctx->last;
21493639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
21503639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
21513639ca84SHoria Geant? 
21523639ca84SHoria Geant? 	return 0;
21533639ca84SHoria Geant? }
21543639ca84SHoria Geant? 
21553639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
21563639ca84SHoria Geant? {
21573639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21583639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2159*6a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
2160*6a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
21613639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
216249f9783bSLEROY Christophe 	unsigned int size;
2163*6a4967c3SLEROY Christophe 	dma_addr_t dma;
21643639ca84SHoria Geant? 
21653639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
216649f9783bSLEROY Christophe 	size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
21673639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
21683639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
216949f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
217049f9783bSLEROY Christophe 	memcpy(req_ctx->hw_context, export->hw_context, size);
21713c0dd190SLEROY Christophe 	memcpy(req_ctx->buf[0], export->buf, export->nbuf);
21723639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
21733639ca84SHoria Geant? 	req_ctx->first = export->first;
21743639ca84SHoria Geant? 	req_ctx->last = export->last;
21753639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
21763639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
21773639ca84SHoria Geant? 
2178*6a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
2179*6a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
2180*6a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
2181*6a4967c3SLEROY Christophe 
21823639ca84SHoria Geant? 	return 0;
21833639ca84SHoria Geant? }
21843639ca84SHoria Geant? 
218579b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
218679b3a418SLee Nipper 		   u8 *hash)
218779b3a418SLee Nipper {
218879b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
218979b3a418SLee Nipper 
219079b3a418SLee Nipper 	struct scatterlist sg[1];
219179b3a418SLee Nipper 	struct ahash_request *req;
2192f1c90ac3SGilad Ben-Yossef 	struct crypto_wait wait;
219379b3a418SLee Nipper 	int ret;
219479b3a418SLee Nipper 
2195f1c90ac3SGilad Ben-Yossef 	crypto_init_wait(&wait);
219679b3a418SLee Nipper 
219779b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
219879b3a418SLee Nipper 	if (!req)
219979b3a418SLee Nipper 		return -ENOMEM;
220079b3a418SLee Nipper 
220179b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
220279b3a418SLee Nipper 	ctx->keylen = 0;
220379b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
2204f1c90ac3SGilad Ben-Yossef 				   crypto_req_done, &wait);
220579b3a418SLee Nipper 
220679b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
220779b3a418SLee Nipper 
220879b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
2209f1c90ac3SGilad Ben-Yossef 	ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
2210f1c90ac3SGilad Ben-Yossef 
221179b3a418SLee Nipper 	ahash_request_free(req);
221279b3a418SLee Nipper 
221379b3a418SLee Nipper 	return ret;
221479b3a418SLee Nipper }
221579b3a418SLee Nipper 
221679b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
221779b3a418SLee Nipper 			unsigned int keylen)
221879b3a418SLee Nipper {
221979b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
22202e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
222179b3a418SLee Nipper 	unsigned int blocksize =
222279b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
222379b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
222479b3a418SLee Nipper 	unsigned int keysize = keylen;
222579b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
222679b3a418SLee Nipper 	int ret;
222779b3a418SLee Nipper 
222879b3a418SLee Nipper 	if (keylen <= blocksize)
222979b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
223079b3a418SLee Nipper 	else {
223179b3a418SLee Nipper 		/* Must get the hash of the long key */
223279b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
223379b3a418SLee Nipper 
223479b3a418SLee Nipper 		if (ret) {
223579b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
223679b3a418SLee Nipper 			return -EINVAL;
223779b3a418SLee Nipper 		}
223879b3a418SLee Nipper 
223979b3a418SLee Nipper 		keysize = digestsize;
224079b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
224179b3a418SLee Nipper 	}
224279b3a418SLee Nipper 
22432e13ce08SLEROY Christophe 	if (ctx->keylen)
22442e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
22452e13ce08SLEROY Christophe 
224679b3a418SLee Nipper 	ctx->keylen = keysize;
22472e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE);
224879b3a418SLee Nipper 
224979b3a418SLee Nipper 	return 0;
225079b3a418SLee Nipper }
225179b3a418SLee Nipper 
225279b3a418SLee Nipper 
22539c4a7965SKim Phillips struct talitos_alg_template {
2254d5e4aaefSLee Nipper 	u32 type;
2255b0057763SLEROY Christophe 	u32 priority;
2256d5e4aaefSLee Nipper 	union {
2257d5e4aaefSLee Nipper 		struct crypto_alg crypto;
2258acbf7c62SLee Nipper 		struct ahash_alg hash;
2259aeb4c132SHerbert Xu 		struct aead_alg aead;
2260d5e4aaefSLee Nipper 	} alg;
22619c4a7965SKim Phillips 	__be32 desc_hdr_template;
22629c4a7965SKim Phillips };
22639c4a7965SKim Phillips 
22649c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2265991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2266d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2267aeb4c132SHerbert Xu 		.alg.aead = {
2268aeb4c132SHerbert Xu 			.base = {
226956af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2270aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2271aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
227256af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2273aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2274aeb4c132SHerbert Xu 			},
22753952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
22763952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
22779c4a7965SKim Phillips 		},
22789c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
22799c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
22809c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
22819c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
22829c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
22839c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
22849c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
228570bcaca7SLee Nipper 	},
2286d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
22877405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22887405c8d7SLEROY Christophe 		.alg.aead = {
22897405c8d7SLEROY Christophe 			.base = {
22907405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
22917405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
22927405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
22937405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
22947405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22957405c8d7SLEROY Christophe 			},
22967405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
22977405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
22987405c8d7SLEROY Christophe 		},
22997405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23007405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23017405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23027405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23037405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23047405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23057405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23067405c8d7SLEROY Christophe 	},
23077405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2308aeb4c132SHerbert Xu 		.alg.aead = {
2309aeb4c132SHerbert Xu 			.base = {
2310aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2311aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2312aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2313aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
231456af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2315aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2316aeb4c132SHerbert Xu 			},
23173952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
23183952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
231970bcaca7SLee Nipper 		},
232070bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
232170bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
232270bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
232370bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
232470bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
232570bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
232670bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
232770bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23283952f17eSLee Nipper 	},
2329d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23307405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23317405c8d7SLEROY Christophe 		.alg.aead = {
23327405c8d7SLEROY Christophe 			.base = {
23337405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),"
23347405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
23357405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
23367405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
23377405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
23387405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23397405c8d7SLEROY Christophe 			},
23407405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
23417405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
23427405c8d7SLEROY Christophe 		},
23437405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23447405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
23457405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
23467405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
23477405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23487405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23497405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23507405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23517405c8d7SLEROY Christophe 	},
23527405c8d7SLEROY Christophe 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2353aeb4c132SHerbert Xu 		.alg.aead = {
2354aeb4c132SHerbert Xu 			.base = {
2355357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2356aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2357aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2358357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2359aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2360aeb4c132SHerbert Xu 			},
2361357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2362357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2363357fb605SHoria Geanta 		},
2364357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2365357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2366357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2367357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2368357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2369357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2370357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2371357fb605SHoria Geanta 	},
2372357fb605SHoria Geanta 	{       .type = CRYPTO_ALG_TYPE_AEAD,
23737405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23747405c8d7SLEROY Christophe 		.alg.aead = {
23757405c8d7SLEROY Christophe 			.base = {
23767405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
23777405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
23787405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
23797405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
23807405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23817405c8d7SLEROY Christophe 			},
23827405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
23837405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
23847405c8d7SLEROY Christophe 		},
23857405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23867405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23877405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23887405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23897405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23907405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23917405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
23927405c8d7SLEROY Christophe 	},
23937405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2394aeb4c132SHerbert Xu 		.alg.aead = {
2395aeb4c132SHerbert Xu 			.base = {
2396aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2397aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2398aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2399aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2400357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2401aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2402aeb4c132SHerbert Xu 			},
2403357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2404357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2405357fb605SHoria Geanta 		},
2406357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2407357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2408357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2409357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2410357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2411357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2412357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2413357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2414357fb605SHoria Geanta 	},
2415357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24167405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24177405c8d7SLEROY Christophe 		.alg.aead = {
24187405c8d7SLEROY Christophe 			.base = {
24197405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),"
24207405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
24217405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
24227405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
24237405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24247405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24257405c8d7SLEROY Christophe 			},
24267405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
24277405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
24287405c8d7SLEROY Christophe 		},
24297405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24307405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24317405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
24327405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
24337405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24347405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24357405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24367405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
24377405c8d7SLEROY Christophe 	},
24387405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2439aeb4c132SHerbert Xu 		.alg.aead = {
2440aeb4c132SHerbert Xu 			.base = {
244156af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2442aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2443aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
244456af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2445aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2446aeb4c132SHerbert Xu 			},
24473952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
24483952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
24493952f17eSLee Nipper 		},
24503952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24513952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
24523952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
24533952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
24543952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
24553952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
24563952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24573952f17eSLee Nipper 	},
2458d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24597405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24607405c8d7SLEROY Christophe 		.alg.aead = {
24617405c8d7SLEROY Christophe 			.base = {
24627405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
24637405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
24647405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
24657405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
24667405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24677405c8d7SLEROY Christophe 			},
24687405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
24697405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
24707405c8d7SLEROY Christophe 		},
24717405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24727405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
24737405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
24747405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24757405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24767405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24777405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24787405c8d7SLEROY Christophe 	},
24797405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2480aeb4c132SHerbert Xu 		.alg.aead = {
2481aeb4c132SHerbert Xu 			.base = {
2482aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2483aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2484aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2485aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
248656af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2487aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2488aeb4c132SHerbert Xu 			},
24893952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
24903952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
24913952f17eSLee Nipper 		},
24923952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24933952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
24943952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
24953952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
24963952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
24973952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
24983952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
24993952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25003952f17eSLee Nipper 	},
2501d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25027405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25037405c8d7SLEROY Christophe 		.alg.aead = {
25047405c8d7SLEROY Christophe 			.base = {
25057405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),"
25067405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
25077405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
25087405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
25097405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
25107405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25117405c8d7SLEROY Christophe 			},
25127405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
25137405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
25147405c8d7SLEROY Christophe 		},
25157405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25167405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
25177405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
25187405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
25197405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25207405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25217405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25227405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25237405c8d7SLEROY Christophe 	},
25247405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2525aeb4c132SHerbert Xu 		.alg.aead = {
2526aeb4c132SHerbert Xu 			.base = {
2527357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2528aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2529aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2530357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2531aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2532aeb4c132SHerbert Xu 			},
2533357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2534357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2535357fb605SHoria Geanta 		},
2536357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2537357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2538357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2539357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2540357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2541357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2542357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2543357fb605SHoria Geanta 	},
2544357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2545aeb4c132SHerbert Xu 		.alg.aead = {
2546aeb4c132SHerbert Xu 			.base = {
2547aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2548aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2549aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2550aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2551357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2552aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2553aeb4c132SHerbert Xu 			},
2554357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2555357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2556357fb605SHoria Geanta 		},
2557357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2558357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2559357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2560357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2561357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2562357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2563357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2564357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2565357fb605SHoria Geanta 	},
2566357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2567aeb4c132SHerbert Xu 		.alg.aead = {
2568aeb4c132SHerbert Xu 			.base = {
2569357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2570aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2571aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2572357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2573aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2574aeb4c132SHerbert Xu 			},
2575357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2576357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2577357fb605SHoria Geanta 		},
2578357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2579357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2580357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2581357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2582357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2583357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2584357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2585357fb605SHoria Geanta 	},
2586357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2587aeb4c132SHerbert Xu 		.alg.aead = {
2588aeb4c132SHerbert Xu 			.base = {
2589aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2590aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2591aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2592aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2593357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2594aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2595aeb4c132SHerbert Xu 			},
2596357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2597357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2598357fb605SHoria Geanta 		},
2599357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2600357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2601357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2602357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2603357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2604357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2605357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2606357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2607357fb605SHoria Geanta 	},
2608357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2609aeb4c132SHerbert Xu 		.alg.aead = {
2610aeb4c132SHerbert Xu 			.base = {
261156af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2612aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2613aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
261456af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2615aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2616aeb4c132SHerbert Xu 			},
26173952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
26183952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
26193952f17eSLee Nipper 		},
26203952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26213952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
26223952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
26233952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26243952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
26253952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
26263952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26273952f17eSLee Nipper 	},
2628d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
26297405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26307405c8d7SLEROY Christophe 		.alg.aead = {
26317405c8d7SLEROY Christophe 			.base = {
26327405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(aes))",
26337405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
26347405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
26357405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
26367405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
26377405c8d7SLEROY Christophe 			},
26387405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
26397405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
26407405c8d7SLEROY Christophe 		},
26417405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
26427405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
26437405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
26447405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
26457405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
26467405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
26477405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26487405c8d7SLEROY Christophe 	},
26497405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2650aeb4c132SHerbert Xu 		.alg.aead = {
2651aeb4c132SHerbert Xu 			.base = {
265256af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2653aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2654aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
265556af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2656aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2657aeb4c132SHerbert Xu 			},
26583952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
26593952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
26603952f17eSLee Nipper 		},
26613952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26623952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
26633952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
26643952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
26653952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26663952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
26673952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
26683952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26694de9d0b5SLee Nipper 	},
26707405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
26717405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26727405c8d7SLEROY Christophe 		.alg.aead = {
26737405c8d7SLEROY Christophe 			.base = {
26747405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
26757405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
26767405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
26777405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26787405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
26797405c8d7SLEROY Christophe 			},
26807405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
26817405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
26827405c8d7SLEROY Christophe 		},
26837405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
26847405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
26857405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
26867405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
26877405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
26887405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
26897405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
26907405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26917405c8d7SLEROY Christophe 	},
26924de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2693d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2694d5e4aaefSLee Nipper 		.alg.crypto = {
26955e75ae1bSLEROY Christophe 			.cra_name = "ecb(aes)",
26965e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-aes-talitos",
26975e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
26985e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26995e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27005e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27015e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
27025e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
27035e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
27045e75ae1bSLEROY Christophe 			}
27055e75ae1bSLEROY Christophe 		},
27065e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27075e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
27085e75ae1bSLEROY Christophe 	},
27095e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27105e75ae1bSLEROY Christophe 		.alg.crypto = {
27114de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
27124de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
27134de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
27144de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27154de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
27164de9d0b5SLee Nipper 			.cra_ablkcipher = {
27174de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
27184de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
27194de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
27204de9d0b5SLee Nipper 			}
27214de9d0b5SLee Nipper 		},
27224de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27234de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
27244de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
27254de9d0b5SLee Nipper 	},
2726d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2727d5e4aaefSLee Nipper 		.alg.crypto = {
27285e75ae1bSLEROY Christophe 			.cra_name = "ctr(aes)",
27295e75ae1bSLEROY Christophe 			.cra_driver_name = "ctr-aes-talitos",
27305e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
27315e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27325e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27335e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27345e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
27355e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
27365e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
27375e75ae1bSLEROY Christophe 			}
27385e75ae1bSLEROY Christophe 		},
273970d355ccSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
27405e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
27415e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
27425e75ae1bSLEROY Christophe 	},
27435e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27445e75ae1bSLEROY Christophe 		.alg.crypto = {
27455e75ae1bSLEROY Christophe 			.cra_name = "ecb(des)",
27465e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-des-talitos",
27475e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
27485e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27495e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27505e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27515e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
27525e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
27535e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
27545e75ae1bSLEROY Christophe 			}
27555e75ae1bSLEROY Christophe 		},
27565e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27575e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
27585e75ae1bSLEROY Christophe 	},
27595e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27605e75ae1bSLEROY Christophe 		.alg.crypto = {
27615e75ae1bSLEROY Christophe 			.cra_name = "cbc(des)",
27625e75ae1bSLEROY Christophe 			.cra_driver_name = "cbc-des-talitos",
27635e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
27645e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27655e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27665e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27675e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
27685e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
27695e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
27705e75ae1bSLEROY Christophe 			}
27715e75ae1bSLEROY Christophe 		},
27725e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27735e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
27745e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
27755e75ae1bSLEROY Christophe 	},
27765e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27775e75ae1bSLEROY Christophe 		.alg.crypto = {
27785e75ae1bSLEROY Christophe 			.cra_name = "ecb(des3_ede)",
27795e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-3des-talitos",
27805e75ae1bSLEROY Christophe 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
27815e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27825e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27835e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27845e75ae1bSLEROY Christophe 				.min_keysize = DES3_EDE_KEY_SIZE,
27855e75ae1bSLEROY Christophe 				.max_keysize = DES3_EDE_KEY_SIZE,
27865e75ae1bSLEROY Christophe 				.ivsize = DES3_EDE_BLOCK_SIZE,
27875e75ae1bSLEROY Christophe 			}
27885e75ae1bSLEROY Christophe 		},
27895e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27905e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
27915e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
27925e75ae1bSLEROY Christophe 	},
27935e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27945e75ae1bSLEROY Christophe 		.alg.crypto = {
27954de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
27964de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
27974de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
27984de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27994de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
28004de9d0b5SLee Nipper 			.cra_ablkcipher = {
28014de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
28024de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
28034de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
28044de9d0b5SLee Nipper 			}
28054de9d0b5SLee Nipper 		},
28064de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28074de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
28084de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
28094de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2810497f2e6bSLee Nipper 	},
2811497f2e6bSLee Nipper 	/* AHASH algorithms. */
2812497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2813497f2e6bSLee Nipper 		.alg.hash = {
2814497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
28153639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2816497f2e6bSLee Nipper 			.halg.base = {
2817497f2e6bSLee Nipper 				.cra_name = "md5",
2818497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2819b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2820497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2821497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
28229c4a7965SKim Phillips 			}
2823497f2e6bSLee Nipper 		},
2824497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2825497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2826497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2827497f2e6bSLee Nipper 	},
2828497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2829497f2e6bSLee Nipper 		.alg.hash = {
2830497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
28313639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2832497f2e6bSLee Nipper 			.halg.base = {
2833497f2e6bSLee Nipper 				.cra_name = "sha1",
2834497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2835497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2836497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2837497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2838497f2e6bSLee Nipper 			}
2839497f2e6bSLee Nipper 		},
2840497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2841497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2842497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2843497f2e6bSLee Nipper 	},
2844497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2845497f2e6bSLee Nipper 		.alg.hash = {
284660f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
28473639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
284860f208d7SKim Phillips 			.halg.base = {
284960f208d7SKim Phillips 				.cra_name = "sha224",
285060f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
285160f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
285260f208d7SKim Phillips 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
285360f208d7SKim Phillips 					     CRYPTO_ALG_ASYNC,
285460f208d7SKim Phillips 			}
285560f208d7SKim Phillips 		},
285660f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
285760f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
285860f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
285960f208d7SKim Phillips 	},
286060f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
286160f208d7SKim Phillips 		.alg.hash = {
2862497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
28633639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2864497f2e6bSLee Nipper 			.halg.base = {
2865497f2e6bSLee Nipper 				.cra_name = "sha256",
2866497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2867497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2868497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2869497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2870497f2e6bSLee Nipper 			}
2871497f2e6bSLee Nipper 		},
2872497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2873497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2874497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2875497f2e6bSLee Nipper 	},
2876497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2877497f2e6bSLee Nipper 		.alg.hash = {
2878497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
28793639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2880497f2e6bSLee Nipper 			.halg.base = {
2881497f2e6bSLee Nipper 				.cra_name = "sha384",
2882497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2883497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
2884497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2885497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2886497f2e6bSLee Nipper 			}
2887497f2e6bSLee Nipper 		},
2888497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2889497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2890497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2891497f2e6bSLee Nipper 	},
2892497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2893497f2e6bSLee Nipper 		.alg.hash = {
2894497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
28953639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2896497f2e6bSLee Nipper 			.halg.base = {
2897497f2e6bSLee Nipper 				.cra_name = "sha512",
2898497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2899497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
2900497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2901497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2902497f2e6bSLee Nipper 			}
2903497f2e6bSLee Nipper 		},
2904497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2905497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2906497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2907497f2e6bSLee Nipper 	},
290879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
290979b3a418SLee Nipper 		.alg.hash = {
291079b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
29113639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
291279b3a418SLee Nipper 			.halg.base = {
291379b3a418SLee Nipper 				.cra_name = "hmac(md5)",
291479b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2915b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
291679b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
291779b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
291879b3a418SLee Nipper 			}
291979b3a418SLee Nipper 		},
292079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
292179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
292279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
292379b3a418SLee Nipper 	},
292479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
292579b3a418SLee Nipper 		.alg.hash = {
292679b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
29273639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
292879b3a418SLee Nipper 			.halg.base = {
292979b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
293079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
293179b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
293279b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
293379b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
293479b3a418SLee Nipper 			}
293579b3a418SLee Nipper 		},
293679b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
293779b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
293879b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
293979b3a418SLee Nipper 	},
294079b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
294179b3a418SLee Nipper 		.alg.hash = {
294279b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
29433639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
294479b3a418SLee Nipper 			.halg.base = {
294579b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
294679b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
294779b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
294879b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
294979b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
295079b3a418SLee Nipper 			}
295179b3a418SLee Nipper 		},
295279b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
295379b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
295479b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
295579b3a418SLee Nipper 	},
295679b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
295779b3a418SLee Nipper 		.alg.hash = {
295879b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
29593639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
296079b3a418SLee Nipper 			.halg.base = {
296179b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
296279b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
296379b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
296479b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
296579b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
296679b3a418SLee Nipper 			}
296779b3a418SLee Nipper 		},
296879b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
296979b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
297079b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
297179b3a418SLee Nipper 	},
297279b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
297379b3a418SLee Nipper 		.alg.hash = {
297479b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
29753639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
297679b3a418SLee Nipper 			.halg.base = {
297779b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
297879b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
297979b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
298079b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
298179b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
298279b3a418SLee Nipper 			}
298379b3a418SLee Nipper 		},
298479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
298579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
298679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
298779b3a418SLee Nipper 	},
298879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
298979b3a418SLee Nipper 		.alg.hash = {
299079b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
29913639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
299279b3a418SLee Nipper 			.halg.base = {
299379b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
299479b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
299579b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
299679b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
299779b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
299879b3a418SLee Nipper 			}
299979b3a418SLee Nipper 		},
300079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
300179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
300279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
300379b3a418SLee Nipper 	}
30049c4a7965SKim Phillips };
30059c4a7965SKim Phillips 
30069c4a7965SKim Phillips struct talitos_crypto_alg {
30079c4a7965SKim Phillips 	struct list_head entry;
30089c4a7965SKim Phillips 	struct device *dev;
3009acbf7c62SLee Nipper 	struct talitos_alg_template algt;
30109c4a7965SKim Phillips };
30119c4a7965SKim Phillips 
301289d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
301389d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
30149c4a7965SKim Phillips {
30155228f0f7SKim Phillips 	struct talitos_private *priv;
30169c4a7965SKim Phillips 
30179c4a7965SKim Phillips 	/* update context with ptr to dev */
30189c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
301919bbbc63SKim Phillips 
30205228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
30215228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
30225228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
30235228f0f7SKim Phillips 		  (priv->num_channels - 1);
30245228f0f7SKim Phillips 
30259c4a7965SKim Phillips 	/* copy descriptor header template value */
3026acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
30279c4a7965SKim Phillips 
3028602dba5aSKim Phillips 	/* select done notification */
3029602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
3030602dba5aSKim Phillips 
3031497f2e6bSLee Nipper 	return 0;
3032497f2e6bSLee Nipper }
3033497f2e6bSLee Nipper 
303489d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm)
303589d124cbSJonas Eymann {
303689d124cbSJonas Eymann 	struct crypto_alg *alg = tfm->__crt_alg;
303789d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
303889d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
303989d124cbSJonas Eymann 
304089d124cbSJonas Eymann 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
304189d124cbSJonas Eymann 		talitos_alg = container_of(__crypto_ahash_alg(alg),
304289d124cbSJonas Eymann 					   struct talitos_crypto_alg,
304389d124cbSJonas Eymann 					   algt.alg.hash);
304489d124cbSJonas Eymann 	else
304589d124cbSJonas Eymann 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
304689d124cbSJonas Eymann 					   algt.alg.crypto);
304789d124cbSJonas Eymann 
304889d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
304989d124cbSJonas Eymann }
305089d124cbSJonas Eymann 
3051aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
3052497f2e6bSLee Nipper {
305389d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
305489d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
305589d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
305689d124cbSJonas Eymann 
305789d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
305889d124cbSJonas Eymann 				   algt.alg.aead);
305989d124cbSJonas Eymann 
306089d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
30619c4a7965SKim Phillips }
30629c4a7965SKim Phillips 
3063497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
3064497f2e6bSLee Nipper {
3065497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
3066497f2e6bSLee Nipper 
3067497f2e6bSLee Nipper 	talitos_cra_init(tfm);
3068497f2e6bSLee Nipper 
3069497f2e6bSLee Nipper 	ctx->keylen = 0;
3070497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
3071497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
3072497f2e6bSLee Nipper 
3073497f2e6bSLee Nipper 	return 0;
3074497f2e6bSLee Nipper }
3075497f2e6bSLee Nipper 
30762e13ce08SLEROY Christophe static void talitos_cra_exit(struct crypto_tfm *tfm)
30772e13ce08SLEROY Christophe {
30782e13ce08SLEROY Christophe 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
30792e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
30802e13ce08SLEROY Christophe 
30812e13ce08SLEROY Christophe 	if (ctx->keylen)
30822e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
30832e13ce08SLEROY Christophe }
30842e13ce08SLEROY Christophe 
30859c4a7965SKim Phillips /*
30869c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
30879c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
30889c4a7965SKim Phillips  * capabilities description provided in the device tree node.
30899c4a7965SKim Phillips  */
30909c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
30919c4a7965SKim Phillips {
30929c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
30939c4a7965SKim Phillips 	int ret;
30949c4a7965SKim Phillips 
30959c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
30969c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
30979c4a7965SKim Phillips 
30989c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
30999c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
31009c4a7965SKim Phillips 		              & priv->exec_units);
31019c4a7965SKim Phillips 
31029c4a7965SKim Phillips 	return ret;
31039c4a7965SKim Phillips }
31049c4a7965SKim Phillips 
31052dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
31069c4a7965SKim Phillips {
31079c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
31089c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31099c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
31109c4a7965SKim Phillips 	int i;
31119c4a7965SKim Phillips 
31129c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
3113acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
3114acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
3115acbf7c62SLee Nipper 			break;
3116aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
3117aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
3118acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
3119acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
3120acbf7c62SLee Nipper 			break;
3121acbf7c62SLee Nipper 		}
31229c4a7965SKim Phillips 		list_del(&t_alg->entry);
31239c4a7965SKim Phillips 	}
31249c4a7965SKim Phillips 
31259c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
31269c4a7965SKim Phillips 		talitos_unregister_rng(dev);
31279c4a7965SKim Phillips 
3128c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
31292cdba3cfSKim Phillips 		if (priv->irq[i]) {
3130c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
3131c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
31329c4a7965SKim Phillips 		}
31339c4a7965SKim Phillips 
3134c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
31352cdba3cfSKim Phillips 	if (priv->irq[1])
3136c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
31379c4a7965SKim Phillips 
31389c4a7965SKim Phillips 	return 0;
31399c4a7965SKim Phillips }
31409c4a7965SKim Phillips 
31419c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
31429c4a7965SKim Phillips 						    struct talitos_alg_template
31439c4a7965SKim Phillips 						           *template)
31449c4a7965SKim Phillips {
314560f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31469c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
31479c4a7965SKim Phillips 	struct crypto_alg *alg;
31489c4a7965SKim Phillips 
314924b92ff2SLEROY Christophe 	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
315024b92ff2SLEROY Christophe 			     GFP_KERNEL);
31519c4a7965SKim Phillips 	if (!t_alg)
31529c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
31539c4a7965SKim Phillips 
3154acbf7c62SLee Nipper 	t_alg->algt = *template;
3155acbf7c62SLee Nipper 
3156acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
3157acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
3158497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
3159497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
31602e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3161d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
3162b286e003SKim Phillips 		alg->cra_ablkcipher.setkey = ablkcipher_setkey;
3163b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
3164b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
3165b286e003SKim Phillips 		alg->cra_ablkcipher.geniv = "eseqiv";
3166497f2e6bSLee Nipper 		break;
3167acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
3168aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
31692e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3170aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
3171aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.setkey = aead_setkey;
3172aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
3173aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
31746cda075aSLEROY Christophe 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
31756cda075aSLEROY Christophe 		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
317624b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
31776cda075aSLEROY Christophe 			return ERR_PTR(-ENOTSUPP);
31786cda075aSLEROY Christophe 		}
3179acbf7c62SLee Nipper 		break;
3180acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
3181acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
3182497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
3183ad4cd51fSLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3184d4cd3283SKim Phillips 		alg->cra_type = &crypto_ahash_type;
3185b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
3186b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
3187b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
3188b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
3189b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
319056136631SLEROY Christophe 		if (!strncmp(alg->cra_name, "hmac", 4))
3191b286e003SKim Phillips 			t_alg->algt.alg.hash.setkey = ahash_setkey;
31923639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
31933639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
3194b286e003SKim Phillips 
319579b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
31960b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
319724b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
319879b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
31990b2730d8SKim Phillips 		}
320060f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
320179b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
320279b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
320360f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
320460f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
320560f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
320660f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
320760f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
320860f208d7SKim Phillips 		}
3209497f2e6bSLee Nipper 		break;
32101d11911aSKim Phillips 	default:
32111d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
321224b92ff2SLEROY Christophe 		devm_kfree(dev, t_alg);
32131d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
3214acbf7c62SLee Nipper 	}
32159c4a7965SKim Phillips 
32169c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
3217b0057763SLEROY Christophe 	if (t_alg->algt.priority)
3218b0057763SLEROY Christophe 		alg->cra_priority = t_alg->algt.priority;
3219b0057763SLEROY Christophe 	else
32209c4a7965SKim Phillips 		alg->cra_priority = TALITOS_CRA_PRIORITY;
32219c4a7965SKim Phillips 	alg->cra_alignmask = 0;
32229c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
3223d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
32249c4a7965SKim Phillips 
32259c4a7965SKim Phillips 	t_alg->dev = dev;
32269c4a7965SKim Phillips 
32279c4a7965SKim Phillips 	return t_alg;
32289c4a7965SKim Phillips }
32299c4a7965SKim Phillips 
3230c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
3231c3e337f8SKim Phillips {
3232c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
3233c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
3234c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3235c3e337f8SKim Phillips 	int err;
3236dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3237c3e337f8SKim Phillips 
3238c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
32392cdba3cfSKim Phillips 	if (!priv->irq[0]) {
3240c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
3241c3e337f8SKim Phillips 		return -EINVAL;
3242c3e337f8SKim Phillips 	}
3243dd3c0987SLEROY Christophe 	if (is_sec1) {
3244dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
3245dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
3246dd3c0987SLEROY Christophe 		goto primary_out;
3247dd3c0987SLEROY Christophe 	}
3248c3e337f8SKim Phillips 
3249c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
3250c3e337f8SKim Phillips 
3251c3e337f8SKim Phillips 	/* get the primary irq line */
32522cdba3cfSKim Phillips 	if (!priv->irq[1]) {
3253dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
3254c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
3255c3e337f8SKim Phillips 		goto primary_out;
3256c3e337f8SKim Phillips 	}
3257c3e337f8SKim Phillips 
3258dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
3259c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3260c3e337f8SKim Phillips 	if (err)
3261c3e337f8SKim Phillips 		goto primary_out;
3262c3e337f8SKim Phillips 
3263c3e337f8SKim Phillips 	/* get the secondary irq line */
3264dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
3265c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3266c3e337f8SKim Phillips 	if (err) {
3267c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
3268c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
32692cdba3cfSKim Phillips 		priv->irq[1] = 0;
3270c3e337f8SKim Phillips 	}
3271c3e337f8SKim Phillips 
3272c3e337f8SKim Phillips 	return err;
3273c3e337f8SKim Phillips 
3274c3e337f8SKim Phillips primary_out:
3275c3e337f8SKim Phillips 	if (err) {
3276c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
3277c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
32782cdba3cfSKim Phillips 		priv->irq[0] = 0;
3279c3e337f8SKim Phillips 	}
3280c3e337f8SKim Phillips 
3281c3e337f8SKim Phillips 	return err;
3282c3e337f8SKim Phillips }
3283c3e337f8SKim Phillips 
32841c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
32859c4a7965SKim Phillips {
32869c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
328761c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
32889c4a7965SKim Phillips 	struct talitos_private *priv;
32899c4a7965SKim Phillips 	int i, err;
32905fa7fa14SLEROY Christophe 	int stride;
3291fd5ea7f0SLEROY Christophe 	struct resource *res;
32929c4a7965SKim Phillips 
329324b92ff2SLEROY Christophe 	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
32949c4a7965SKim Phillips 	if (!priv)
32959c4a7965SKim Phillips 		return -ENOMEM;
32969c4a7965SKim Phillips 
3297f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
3298f3de9cb1SKevin Hao 
32999c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
33009c4a7965SKim Phillips 
33019c4a7965SKim Phillips 	priv->ofdev = ofdev;
33029c4a7965SKim Phillips 
3303511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
3304511d63cbSHoria Geanta 
3305fd5ea7f0SLEROY Christophe 	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
3306fd5ea7f0SLEROY Christophe 	if (!res)
3307fd5ea7f0SLEROY Christophe 		return -ENXIO;
3308fd5ea7f0SLEROY Christophe 	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
33099c4a7965SKim Phillips 	if (!priv->reg) {
33109c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
33119c4a7965SKim Phillips 		err = -ENOMEM;
33129c4a7965SKim Phillips 		goto err_out;
33139c4a7965SKim Phillips 	}
33149c4a7965SKim Phillips 
33159c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
3316fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
3317fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
3318fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
3319fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,descriptor-types-mask",
3320fa14c6cfSLEROY Christophe 			     &priv->desc_types);
33219c4a7965SKim Phillips 
33229c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
33239c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
33249c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
33259c4a7965SKim Phillips 		err = -EINVAL;
33269c4a7965SKim Phillips 		goto err_out;
33279c4a7965SKim Phillips 	}
33289c4a7965SKim Phillips 
3329f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3330f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3331f3c85bc1SLee Nipper 
3332fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
333360f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
333479b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
333579b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3336fe5720e2SKim Phillips 
333721590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
333821590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
333921590888SLEROY Christophe 
33405fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
33415fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
33425fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
33435fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
33445fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
33455fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
33465fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
33475fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
33485fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
33495fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
33505fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
33515fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
33525fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
33535fa7fa14SLEROY Christophe 	} else {
33545fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
33555fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
33565fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
33575fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
33585fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
33595fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
33605fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
33615fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
33625fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
33635fa7fa14SLEROY Christophe 	}
33645fa7fa14SLEROY Christophe 
3365dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3366dd3c0987SLEROY Christophe 	if (err)
3367dd3c0987SLEROY Christophe 		goto err_out;
3368dd3c0987SLEROY Christophe 
3369dd3c0987SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0")) {
33709c02e285SLEROY Christophe 		if (priv->num_channels == 1)
33719c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
33729c02e285SLEROY Christophe 				     (unsigned long)dev);
33739c02e285SLEROY Christophe 		else
3374dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3375dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3376dd3c0987SLEROY Christophe 	} else {
33779c02e285SLEROY Christophe 		if (priv->irq[1]) {
3378dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3379dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3380dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3381dd3c0987SLEROY Christophe 				     (unsigned long)dev);
33829c02e285SLEROY Christophe 		} else if (priv->num_channels == 1) {
33839c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
33849c02e285SLEROY Christophe 				     (unsigned long)dev);
33859c02e285SLEROY Christophe 		} else {
33869c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
33879c02e285SLEROY Christophe 				     (unsigned long)dev);
3388dd3c0987SLEROY Christophe 		}
3389dd3c0987SLEROY Christophe 	}
3390dd3c0987SLEROY Christophe 
339124b92ff2SLEROY Christophe 	priv->chan = devm_kzalloc(dev, sizeof(struct talitos_channel) *
33924b992628SKim Phillips 				       priv->num_channels, GFP_KERNEL);
33934b992628SKim Phillips 	if (!priv->chan) {
33944b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
33959c4a7965SKim Phillips 		err = -ENOMEM;
33969c4a7965SKim Phillips 		goto err_out;
33979c4a7965SKim Phillips 	}
33989c4a7965SKim Phillips 
3399f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3400f641ddddSMartin Hicks 
3401c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
34025fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
34032cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3404c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3405ad42d5fcSKim Phillips 
34064b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
34074b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
34089c4a7965SKim Phillips 
340924b92ff2SLEROY Christophe 		priv->chan[i].fifo = devm_kzalloc(dev,
341024b92ff2SLEROY Christophe 						sizeof(struct talitos_request) *
34119c4a7965SKim Phillips 						priv->fifo_len, GFP_KERNEL);
34124b992628SKim Phillips 		if (!priv->chan[i].fifo) {
34139c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
34149c4a7965SKim Phillips 			err = -ENOMEM;
34159c4a7965SKim Phillips 			goto err_out;
34169c4a7965SKim Phillips 		}
34179c4a7965SKim Phillips 
34184b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
34194b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3420f641ddddSMartin Hicks 	}
34219c4a7965SKim Phillips 
342281eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
342381eb024cSKim Phillips 
34249c4a7965SKim Phillips 	/* reset and initialize the h/w */
34259c4a7965SKim Phillips 	err = init_device(dev);
34269c4a7965SKim Phillips 	if (err) {
34279c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
34289c4a7965SKim Phillips 		goto err_out;
34299c4a7965SKim Phillips 	}
34309c4a7965SKim Phillips 
34319c4a7965SKim Phillips 	/* register the RNG, if available */
34329c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
34339c4a7965SKim Phillips 		err = talitos_register_rng(dev);
34349c4a7965SKim Phillips 		if (err) {
34359c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
34369c4a7965SKim Phillips 			goto err_out;
34379c4a7965SKim Phillips 		} else
34389c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
34399c4a7965SKim Phillips 	}
34409c4a7965SKim Phillips 
34419c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
34429c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
34439c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
34449c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3445aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
34469c4a7965SKim Phillips 
34479c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
34489c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
34499c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
34500b2730d8SKim Phillips 				if (err == -ENOTSUPP)
345179b3a418SLee Nipper 					continue;
34529c4a7965SKim Phillips 				goto err_out;
34539c4a7965SKim Phillips 			}
34549c4a7965SKim Phillips 
3455acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3456acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
3457acbf7c62SLee Nipper 				err = crypto_register_alg(
3458acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
3459aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.crypto;
3460acbf7c62SLee Nipper 				break;
3461aeb4c132SHerbert Xu 
3462aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3463aeb4c132SHerbert Xu 				err = crypto_register_aead(
3464aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3465aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3466aeb4c132SHerbert Xu 				break;
3467aeb4c132SHerbert Xu 
3468acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3469acbf7c62SLee Nipper 				err = crypto_register_ahash(
3470acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3471aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3472acbf7c62SLee Nipper 				break;
3473acbf7c62SLee Nipper 			}
34749c4a7965SKim Phillips 			if (err) {
34759c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3476aeb4c132SHerbert Xu 					alg->cra_driver_name);
347724b92ff2SLEROY Christophe 				devm_kfree(dev, t_alg);
3478991155baSHoria Geanta 			} else
34799c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
34809c4a7965SKim Phillips 		}
34819c4a7965SKim Phillips 	}
34825b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
34835b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
34845b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
34859c4a7965SKim Phillips 
34869c4a7965SKim Phillips 	return 0;
34879c4a7965SKim Phillips 
34889c4a7965SKim Phillips err_out:
34899c4a7965SKim Phillips 	talitos_remove(ofdev);
34909c4a7965SKim Phillips 
34919c4a7965SKim Phillips 	return err;
34929c4a7965SKim Phillips }
34939c4a7965SKim Phillips 
34946c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
34950635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
34960635b7dbSLEROY Christophe 	{
34970635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
34980635b7dbSLEROY Christophe 	},
34990635b7dbSLEROY Christophe #endif
35000635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
35019c4a7965SKim Phillips 	{
35029c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
35039c4a7965SKim Phillips 	},
35040635b7dbSLEROY Christophe #endif
35059c4a7965SKim Phillips 	{},
35069c4a7965SKim Phillips };
35079c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
35089c4a7965SKim Phillips 
35091c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
35104018294bSGrant Likely 	.driver = {
35119c4a7965SKim Phillips 		.name = "talitos",
35124018294bSGrant Likely 		.of_match_table = talitos_match,
35134018294bSGrant Likely 	},
35149c4a7965SKim Phillips 	.probe = talitos_probe,
3515596f1034SAl Viro 	.remove = talitos_remove,
35169c4a7965SKim Phillips };
35179c4a7965SKim Phillips 
3518741e8c2dSAxel Lin module_platform_driver(talitos_driver);
35199c4a7965SKim Phillips 
35209c4a7965SKim Phillips MODULE_LICENSE("GPL");
35219c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
35229c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3523