xref: /linux/drivers/crypto/talitos.c (revision 9a655608a468535cd15eafff5ef93e2656e6e2fc)
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  */
1079c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev,
108edc6bd69SLEROY Christophe 				   struct talitos_ptr *ptr,
10942e8b0d7SHoria Geant? 				   unsigned int len, void *data,
1109c4a7965SKim Phillips 				   enum dma_data_direction dir)
1119c4a7965SKim Phillips {
11281eb024cSKim Phillips 	dma_addr_t dma_addr = dma_map_single(dev, data, len, dir);
113922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
114922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
11581eb024cSKim Phillips 
116da9de146SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr, len, is_sec1);
1179c4a7965SKim Phillips }
1189c4a7965SKim Phillips 
1199c4a7965SKim Phillips /*
1209c4a7965SKim Phillips  * unmap bus single (contiguous) h/w descriptor pointer
1219c4a7965SKim Phillips  */
1229c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev,
123edc6bd69SLEROY Christophe 				     struct talitos_ptr *ptr,
1249c4a7965SKim Phillips 				     enum dma_data_direction dir)
1259c4a7965SKim Phillips {
126922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
127922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
128922f9dc8SLEROY Christophe 
129edc6bd69SLEROY Christophe 	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
130922f9dc8SLEROY Christophe 			 from_talitos_ptr_len(ptr, is_sec1), dir);
1319c4a7965SKim Phillips }
1329c4a7965SKim Phillips 
1339c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch)
1349c4a7965SKim Phillips {
1359c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1369c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
137dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1389c4a7965SKim Phillips 
139dd3c0987SLEROY Christophe 	if (is_sec1) {
140dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
141dd3c0987SLEROY Christophe 			  TALITOS1_CCCR_LO_RESET);
1429c4a7965SKim Phillips 
143dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
144dd3c0987SLEROY Christophe 			TALITOS1_CCCR_LO_RESET) && --timeout)
1459c4a7965SKim Phillips 			cpu_relax();
146dd3c0987SLEROY Christophe 	} else {
147dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
148dd3c0987SLEROY Christophe 			  TALITOS2_CCCR_RESET);
149dd3c0987SLEROY Christophe 
150dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
151dd3c0987SLEROY Christophe 			TALITOS2_CCCR_RESET) && --timeout)
152dd3c0987SLEROY Christophe 			cpu_relax();
153dd3c0987SLEROY Christophe 	}
1549c4a7965SKim Phillips 
1559c4a7965SKim Phillips 	if (timeout == 0) {
1569c4a7965SKim Phillips 		dev_err(dev, "failed to reset channel %d\n", ch);
1579c4a7965SKim Phillips 		return -EIO;
1589c4a7965SKim Phillips 	}
1599c4a7965SKim Phillips 
16081eb024cSKim Phillips 	/* set 36-bit addressing, done writeback enable and done IRQ enable */
161ad42d5fcSKim Phillips 	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
16281eb024cSKim Phillips 		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
1639c4a7965SKim Phillips 
164fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
165fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
166ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
167fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
168fe5720e2SKim Phillips 
1699c4a7965SKim Phillips 	return 0;
1709c4a7965SKim Phillips }
1719c4a7965SKim Phillips 
1729c4a7965SKim Phillips static int reset_device(struct device *dev)
1739c4a7965SKim Phillips {
1749c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1759c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
176dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
177dd3c0987SLEROY Christophe 	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
1789c4a7965SKim Phillips 
179c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
1809c4a7965SKim Phillips 
181dd3c0987SLEROY Christophe 	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
1829c4a7965SKim Phillips 	       && --timeout)
1839c4a7965SKim Phillips 		cpu_relax();
1849c4a7965SKim Phillips 
1852cdba3cfSKim Phillips 	if (priv->irq[1]) {
186c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
187c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
188c3e337f8SKim Phillips 	}
189c3e337f8SKim Phillips 
1909c4a7965SKim Phillips 	if (timeout == 0) {
1919c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
1929c4a7965SKim Phillips 		return -EIO;
1939c4a7965SKim Phillips 	}
1949c4a7965SKim Phillips 
1959c4a7965SKim Phillips 	return 0;
1969c4a7965SKim Phillips }
1979c4a7965SKim Phillips 
1989c4a7965SKim Phillips /*
1999c4a7965SKim Phillips  * Reset and initialize the device
2009c4a7965SKim Phillips  */
2019c4a7965SKim Phillips static int init_device(struct device *dev)
2029c4a7965SKim Phillips {
2039c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2049c4a7965SKim Phillips 	int ch, err;
205dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2069c4a7965SKim Phillips 
2079c4a7965SKim Phillips 	/*
2089c4a7965SKim Phillips 	 * Master reset
2099c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
2109c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
2119c4a7965SKim Phillips 	 * set bit twice to completely reset
2129c4a7965SKim Phillips 	 */
2139c4a7965SKim Phillips 	err = reset_device(dev);
2149c4a7965SKim Phillips 	if (err)
2159c4a7965SKim Phillips 		return err;
2169c4a7965SKim Phillips 
2179c4a7965SKim Phillips 	err = reset_device(dev);
2189c4a7965SKim Phillips 	if (err)
2199c4a7965SKim Phillips 		return err;
2209c4a7965SKim Phillips 
2219c4a7965SKim Phillips 	/* reset channels */
2229c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
2239c4a7965SKim Phillips 		err = reset_channel(dev, ch);
2249c4a7965SKim Phillips 		if (err)
2259c4a7965SKim Phillips 			return err;
2269c4a7965SKim Phillips 	}
2279c4a7965SKim Phillips 
2289c4a7965SKim Phillips 	/* enable channel done and error interrupts */
229dd3c0987SLEROY Christophe 	if (is_sec1) {
230dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
231dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
232dd3c0987SLEROY Christophe 		/* disable parity error check in DEU (erroneous? test vect.) */
233dd3c0987SLEROY Christophe 		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
234dd3c0987SLEROY Christophe 	} else {
235dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
236dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
237dd3c0987SLEROY Christophe 	}
2389c4a7965SKim Phillips 
239fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
240fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2415fa7fa14SLEROY Christophe 		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
242fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
243fe5720e2SKim Phillips 
2449c4a7965SKim Phillips 	return 0;
2459c4a7965SKim Phillips }
2469c4a7965SKim Phillips 
2479c4a7965SKim Phillips /**
2489c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
2499c4a7965SKim Phillips  * @dev:	the SEC device to be used
2505228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
2519c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
2529c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
2539c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
2549c4a7965SKim Phillips  *
2559c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
2569c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
2579c4a7965SKim Phillips  * for device processing status.
2589c4a7965SKim Phillips  */
259865d5061SHoria Geanta int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2609c4a7965SKim Phillips 		   void (*callback)(struct device *dev,
2619c4a7965SKim Phillips 				    struct talitos_desc *desc,
2629c4a7965SKim Phillips 				    void *context, int error),
2639c4a7965SKim Phillips 		   void *context)
2649c4a7965SKim Phillips {
2659c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2669c4a7965SKim Phillips 	struct talitos_request *request;
2675228f0f7SKim Phillips 	unsigned long flags;
2689c4a7965SKim Phillips 	int head;
2697d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2709c4a7965SKim Phillips 
2714b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2729c4a7965SKim Phillips 
2734b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
274ec6644d6SKim Phillips 		/* h/w fifo is full */
2754b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2769c4a7965SKim Phillips 		return -EAGAIN;
2779c4a7965SKim Phillips 	}
2789c4a7965SKim Phillips 
2794b992628SKim Phillips 	head = priv->chan[ch].head;
2804b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
281ec6644d6SKim Phillips 
2829c4a7965SKim Phillips 	/* map descriptor and save caller data */
2837d607c6aSLEROY Christophe 	if (is_sec1) {
2847d607c6aSLEROY Christophe 		desc->hdr1 = desc->hdr;
2857d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, &desc->hdr1,
2867d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2879c4a7965SKim Phillips 						   DMA_BIDIRECTIONAL);
2887d607c6aSLEROY Christophe 	} else {
2897d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, desc,
2907d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2917d607c6aSLEROY Christophe 						   DMA_BIDIRECTIONAL);
2927d607c6aSLEROY Christophe 	}
2939c4a7965SKim Phillips 	request->callback = callback;
2949c4a7965SKim Phillips 	request->context = context;
2959c4a7965SKim Phillips 
2969c4a7965SKim Phillips 	/* increment fifo head */
2974b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
2989c4a7965SKim Phillips 
2999c4a7965SKim Phillips 	smp_wmb();
3009c4a7965SKim Phillips 	request->desc = desc;
3019c4a7965SKim Phillips 
3029c4a7965SKim Phillips 	/* GO! */
3039c4a7965SKim Phillips 	wmb();
304ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
305ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
306ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
307a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
3089c4a7965SKim Phillips 
3094b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3109c4a7965SKim Phillips 
3119c4a7965SKim Phillips 	return -EINPROGRESS;
3129c4a7965SKim Phillips }
313865d5061SHoria Geanta EXPORT_SYMBOL(talitos_submit);
3149c4a7965SKim Phillips 
3159c4a7965SKim Phillips /*
3169c4a7965SKim Phillips  * process what was done, notify callback of error if not
3179c4a7965SKim Phillips  */
3189c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3199c4a7965SKim Phillips {
3209c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3219c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
3229c4a7965SKim Phillips 	unsigned long flags;
3239c4a7965SKim Phillips 	int tail, status;
3247d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3259c4a7965SKim Phillips 
3264b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3279c4a7965SKim Phillips 
3284b992628SKim Phillips 	tail = priv->chan[ch].tail;
3294b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
3307d607c6aSLEROY Christophe 		__be32 hdr;
3317d607c6aSLEROY Christophe 
3324b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
3339c4a7965SKim Phillips 
3349c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
3359c4a7965SKim Phillips 		rmb();
3367d607c6aSLEROY Christophe 		hdr = is_sec1 ? request->desc->hdr1 : request->desc->hdr;
3377d607c6aSLEROY Christophe 
3387d607c6aSLEROY Christophe 		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3399c4a7965SKim Phillips 			status = 0;
340ca38a814SLee Nipper 		else
3419c4a7965SKim Phillips 			if (!error)
3429c4a7965SKim Phillips 				break;
3439c4a7965SKim Phillips 			else
3449c4a7965SKim Phillips 				status = error;
3459c4a7965SKim Phillips 
3469c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
3477d607c6aSLEROY Christophe 				 TALITOS_DESC_SIZE,
348e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
3499c4a7965SKim Phillips 
3509c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
3519c4a7965SKim Phillips 		saved_req.desc = request->desc;
3529c4a7965SKim Phillips 		saved_req.callback = request->callback;
3539c4a7965SKim Phillips 		saved_req.context = request->context;
3549c4a7965SKim Phillips 
3559c4a7965SKim Phillips 		/* release request entry in fifo */
3569c4a7965SKim Phillips 		smp_wmb();
3579c4a7965SKim Phillips 		request->desc = NULL;
3589c4a7965SKim Phillips 
3599c4a7965SKim Phillips 		/* increment fifo tail */
3604b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3619c4a7965SKim Phillips 
3624b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
363ec6644d6SKim Phillips 
3644b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
365ec6644d6SKim Phillips 
3669c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
3679c4a7965SKim Phillips 				   status);
3689c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
3699c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
3709c4a7965SKim Phillips 			return;
3714b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3724b992628SKim Phillips 		tail = priv->chan[ch].tail;
3739c4a7965SKim Phillips 	}
3749c4a7965SKim Phillips 
3754b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
3769c4a7965SKim Phillips }
3779c4a7965SKim Phillips 
3789c4a7965SKim Phillips /*
3799c4a7965SKim Phillips  * process completed requests for channels that have done status
3809c4a7965SKim Phillips  */
381dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask)				\
382dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data)			\
383dd3c0987SLEROY Christophe {									\
384dd3c0987SLEROY Christophe 	struct device *dev = (struct device *)data;			\
385dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		\
386dd3c0987SLEROY Christophe 	unsigned long flags;						\
387dd3c0987SLEROY Christophe 									\
388dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x10000000)					\
389dd3c0987SLEROY Christophe 		flush_channel(dev, 0, 0, 0);			\
390dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x40000000)					\
391dd3c0987SLEROY Christophe 		flush_channel(dev, 1, 0, 0);			\
392dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00010000)					\
393dd3c0987SLEROY Christophe 		flush_channel(dev, 2, 0, 0);			\
394dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00040000)					\
395dd3c0987SLEROY Christophe 		flush_channel(dev, 3, 0, 0);			\
396dd3c0987SLEROY Christophe 									\
397dd3c0987SLEROY Christophe 	/* At this point, all completed channels have been processed */	\
398dd3c0987SLEROY Christophe 	/* Unmask done interrupts for channels completed later on. */	\
399dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			\
400dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
401dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
402dd3c0987SLEROY Christophe 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
403dd3c0987SLEROY Christophe }
404dd3c0987SLEROY Christophe 
405dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
4069c02e285SLEROY Christophe DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
407dd3c0987SLEROY Christophe 
408dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask)				\
409dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data)			\
410c3e337f8SKim Phillips {									\
411c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
412c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
413511d63cbSHoria Geanta 	unsigned long flags;						\
414c3e337f8SKim Phillips 									\
415c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
416c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
417c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
418c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
419c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
420c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
421c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
422c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
423c3e337f8SKim Phillips 									\
424c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
425c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
426511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
427c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
428dd3c0987SLEROY Christophe 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
429511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4309c4a7965SKim Phillips }
431dd3c0987SLEROY Christophe 
432dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
4339c02e285SLEROY Christophe DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
434dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
435dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4369c4a7965SKim Phillips 
4379c4a7965SKim Phillips /*
4389c4a7965SKim Phillips  * locate current (offending) descriptor
4399c4a7965SKim Phillips  */
4403e721aebSKim Phillips static u32 current_desc_hdr(struct device *dev, int ch)
4419c4a7965SKim Phillips {
4429c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
443b62ffd8cSHoria Geanta 	int tail, iter;
4449c4a7965SKim Phillips 	dma_addr_t cur_desc;
4459c4a7965SKim Phillips 
446b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
447b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4489c4a7965SKim Phillips 
449b62ffd8cSHoria Geanta 	if (!cur_desc) {
450b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
451b62ffd8cSHoria Geanta 		return 0;
452b62ffd8cSHoria Geanta 	}
453b62ffd8cSHoria Geanta 
454b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
455b62ffd8cSHoria Geanta 
456b62ffd8cSHoria Geanta 	iter = tail;
457b62ffd8cSHoria Geanta 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc) {
458b62ffd8cSHoria Geanta 		iter = (iter + 1) & (priv->fifo_len - 1);
459b62ffd8cSHoria Geanta 		if (iter == tail) {
4609c4a7965SKim Phillips 			dev_err(dev, "couldn't locate current descriptor\n");
4613e721aebSKim Phillips 			return 0;
4629c4a7965SKim Phillips 		}
4639c4a7965SKim Phillips 	}
4649c4a7965SKim Phillips 
465b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
4669c4a7965SKim Phillips }
4679c4a7965SKim Phillips 
4689c4a7965SKim Phillips /*
4699c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
4709c4a7965SKim Phillips  */
4713e721aebSKim Phillips static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
4729c4a7965SKim Phillips {
4739c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
4749c4a7965SKim Phillips 	int i;
4759c4a7965SKim Phillips 
4763e721aebSKim Phillips 	if (!desc_hdr)
477ad42d5fcSKim Phillips 		desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
4783e721aebSKim Phillips 
4793e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
4809c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
4819c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
4825fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR),
4835fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
4849c4a7965SKim Phillips 		break;
4859c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
4869c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
4875fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR),
4885fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
4899c4a7965SKim Phillips 		break;
4909c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
4919c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
4929c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
4935fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
4945fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
4959c4a7965SKim Phillips 		break;
4969c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
4979c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
4985fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR),
4995fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5009c4a7965SKim Phillips 		break;
5019c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
5029c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5035fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5045fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5059c4a7965SKim Phillips 		break;
5069c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
5079c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5085fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR),
5095fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5109c4a7965SKim Phillips 		break;
5119c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
5129c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5135fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5145fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5159c4a7965SKim Phillips 		break;
5169c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
5179c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5185fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5195fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5209c4a7965SKim Phillips 		break;
5219c4a7965SKim Phillips 	}
5229c4a7965SKim Phillips 
5233e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5249c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
5259c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
5269c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5275fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5285fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5299c4a7965SKim Phillips 		break;
5309c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
5319c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5325fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5335fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5349c4a7965SKim Phillips 		break;
5359c4a7965SKim Phillips 	}
5369c4a7965SKim Phillips 
5379c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
5389c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
539ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
540ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5419c4a7965SKim Phillips }
5429c4a7965SKim Phillips 
5439c4a7965SKim Phillips /*
5449c4a7965SKim Phillips  * recover from error interrupts
5459c4a7965SKim Phillips  */
5465e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5479c4a7965SKim Phillips {
5489c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5499c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
550dd3c0987SLEROY Christophe 	int ch, error, reset_dev = 0;
55142e8b0d7SHoria Geant? 	u32 v_lo;
552dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
553dd3c0987SLEROY Christophe 	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5549c4a7965SKim Phillips 
5559c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
5569c4a7965SKim Phillips 		/* skip channels without errors */
557dd3c0987SLEROY Christophe 		if (is_sec1) {
558dd3c0987SLEROY Christophe 			/* bits 29, 31, 17, 19 */
559dd3c0987SLEROY Christophe 			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
560dd3c0987SLEROY Christophe 				continue;
561dd3c0987SLEROY Christophe 		} else {
5629c4a7965SKim Phillips 			if (!(isr & (1 << (ch * 2 + 1))))
5639c4a7965SKim Phillips 				continue;
564dd3c0987SLEROY Christophe 		}
5659c4a7965SKim Phillips 
5669c4a7965SKim Phillips 		error = -EINVAL;
5679c4a7965SKim Phillips 
568ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
5699c4a7965SKim Phillips 
5709c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
5719c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
5729c4a7965SKim Phillips 			error = -EAGAIN;
5739c4a7965SKim Phillips 			reset_ch = 1;
5749c4a7965SKim Phillips 		}
5759c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
5769c4a7965SKim Phillips 			/* h/w dropped descriptor */
5779c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
5789c4a7965SKim Phillips 			error = -EAGAIN;
5799c4a7965SKim Phillips 		}
5809c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
5819c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
5829c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
5834d9b3a5bSColin Ian King 			dev_err(dev, is_sec1 ? "pointer not complete error\n"
584dd3c0987SLEROY Christophe 					     : "s/g data length zero error\n");
5859c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
586dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "parity error\n"
587dd3c0987SLEROY Christophe 					     : "fetch pointer zero error\n");
5889c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
5899c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
5909c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
591dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "static assignment error\n"
592dd3c0987SLEROY Christophe 					     : "invalid exec unit error\n");
5939c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
5943e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
595dd3c0987SLEROY Christophe 		if (!is_sec1) {
5969c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GB)
5979c4a7965SKim Phillips 				dev_err(dev, "gather boundary error\n");
5989c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GRL)
5999c4a7965SKim Phillips 				dev_err(dev, "gather return/length error\n");
6009c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SB)
6019c4a7965SKim Phillips 				dev_err(dev, "scatter boundary error\n");
6029c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SRL)
6039c4a7965SKim Phillips 				dev_err(dev, "scatter return/length error\n");
604dd3c0987SLEROY Christophe 		}
6059c4a7965SKim Phillips 
6069c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
6079c4a7965SKim Phillips 
6089c4a7965SKim Phillips 		if (reset_ch) {
6099c4a7965SKim Phillips 			reset_channel(dev, ch);
6109c4a7965SKim Phillips 		} else {
611ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
612dd3c0987SLEROY Christophe 				  TALITOS2_CCCR_CONT);
613ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
614ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
615dd3c0987SLEROY Christophe 			       TALITOS2_CCCR_CONT) && --timeout)
6169c4a7965SKim Phillips 				cpu_relax();
6179c4a7965SKim Phillips 			if (timeout == 0) {
6189c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
6199c4a7965SKim Phillips 					ch);
6209c4a7965SKim Phillips 				reset_dev = 1;
6219c4a7965SKim Phillips 			}
6229c4a7965SKim Phillips 		}
6239c4a7965SKim Phillips 	}
624dd3c0987SLEROY Christophe 	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
625dd3c0987SLEROY Christophe 	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
626dd3c0987SLEROY Christophe 		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
627dd3c0987SLEROY Christophe 			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
628dd3c0987SLEROY Christophe 				isr, isr_lo);
629dd3c0987SLEROY Christophe 		else
630dd3c0987SLEROY Christophe 			dev_err(dev, "done overflow, internal time out, or "
631dd3c0987SLEROY Christophe 				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6329c4a7965SKim Phillips 
6339c4a7965SKim Phillips 		/* purge request queues */
6349c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
6359c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
6369c4a7965SKim Phillips 
6379c4a7965SKim Phillips 		/* reset and reinitialize the device */
6389c4a7965SKim Phillips 		init_device(dev);
6399c4a7965SKim Phillips 	}
6409c4a7965SKim Phillips }
6419c4a7965SKim Phillips 
642dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
643dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
644dd3c0987SLEROY Christophe {									       \
645dd3c0987SLEROY Christophe 	struct device *dev = data;					       \
646dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
647dd3c0987SLEROY Christophe 	u32 isr, isr_lo;						       \
648dd3c0987SLEROY Christophe 	unsigned long flags;						       \
649dd3c0987SLEROY Christophe 									       \
650dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
651dd3c0987SLEROY Christophe 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
652dd3c0987SLEROY Christophe 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
653dd3c0987SLEROY Christophe 	/* Acknowledge interrupt */					       \
654dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
655dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
656dd3c0987SLEROY Christophe 									       \
657dd3c0987SLEROY Christophe 	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
658dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
659dd3c0987SLEROY Christophe 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
660dd3c0987SLEROY Christophe 	}								       \
661dd3c0987SLEROY Christophe 	else {								       \
662dd3c0987SLEROY Christophe 		if (likely(isr & ch_done_mask)) {			       \
663dd3c0987SLEROY Christophe 			/* mask further done interrupts. */		       \
664dd3c0987SLEROY Christophe 			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
665dd3c0987SLEROY Christophe 			/* done_task will unmask done interrupts at exit */    \
666dd3c0987SLEROY Christophe 			tasklet_schedule(&priv->done_task[tlet]);	       \
667dd3c0987SLEROY Christophe 		}							       \
668dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
669dd3c0987SLEROY Christophe 	}								       \
670dd3c0987SLEROY Christophe 									       \
671dd3c0987SLEROY Christophe 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
672dd3c0987SLEROY Christophe 								IRQ_NONE;      \
673dd3c0987SLEROY Christophe }
674dd3c0987SLEROY Christophe 
675dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
676dd3c0987SLEROY Christophe 
677dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
678dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
679c3e337f8SKim Phillips {									       \
680c3e337f8SKim Phillips 	struct device *dev = data;					       \
681c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
682c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
683511d63cbSHoria Geanta 	unsigned long flags;						       \
684c3e337f8SKim Phillips 									       \
685511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
686c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
687c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
688c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
689c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
690c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
691c3e337f8SKim Phillips 									       \
692511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
693511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
694511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
695511d63cbSHoria Geanta 	}								       \
696511d63cbSHoria Geanta 	else {								       \
697c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
698c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
699c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
700c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
701c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
702c3e337f8SKim Phillips 		}							       \
703511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
704511d63cbSHoria Geanta 	}								       \
705c3e337f8SKim Phillips 									       \
706c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
707c3e337f8SKim Phillips 								IRQ_NONE;      \
7081c2e8811SLee Nipper }
709dd3c0987SLEROY Christophe 
710dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
711dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
712dd3c0987SLEROY Christophe 		       0)
713dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
714dd3c0987SLEROY Christophe 		       1)
7159c4a7965SKim Phillips 
7169c4a7965SKim Phillips /*
7179c4a7965SKim Phillips  * hwrng
7189c4a7965SKim Phillips  */
7199c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
7209c4a7965SKim Phillips {
7219c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7229c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7239c4a7965SKim Phillips 	u32 ofl;
7249c4a7965SKim Phillips 	int i;
7259c4a7965SKim Phillips 
7269c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
7275fa7fa14SLEROY Christophe 		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7289c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
7299c4a7965SKim Phillips 		if (ofl || !wait)
7309c4a7965SKim Phillips 			break;
7319c4a7965SKim Phillips 		udelay(10);
7329c4a7965SKim Phillips 	}
7339c4a7965SKim Phillips 
7349c4a7965SKim Phillips 	return !!ofl;
7359c4a7965SKim Phillips }
7369c4a7965SKim Phillips 
7379c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7389c4a7965SKim Phillips {
7399c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7409c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7419c4a7965SKim Phillips 
7429c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
7435fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7445fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7459c4a7965SKim Phillips 
7469c4a7965SKim Phillips 	return sizeof(u32);
7479c4a7965SKim Phillips }
7489c4a7965SKim Phillips 
7499c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
7509c4a7965SKim Phillips {
7519c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7529c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7539c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
7549c4a7965SKim Phillips 
7555fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7565fa7fa14SLEROY Christophe 	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7575fa7fa14SLEROY Christophe 		 & TALITOS_RNGUSR_LO_RD)
7589c4a7965SKim Phillips 	       && --timeout)
7599c4a7965SKim Phillips 		cpu_relax();
7609c4a7965SKim Phillips 	if (timeout == 0) {
7619c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
7629c4a7965SKim Phillips 		return -ENODEV;
7639c4a7965SKim Phillips 	}
7649c4a7965SKim Phillips 
7659c4a7965SKim Phillips 	/* start generating */
7665fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
7679c4a7965SKim Phillips 
7689c4a7965SKim Phillips 	return 0;
7699c4a7965SKim Phillips }
7709c4a7965SKim Phillips 
7719c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
7729c4a7965SKim Phillips {
7739c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
77435a3bb3dSAaron Sierra 	int err;
7759c4a7965SKim Phillips 
7769c4a7965SKim Phillips 	priv->rng.name		= dev_driver_string(dev),
7779c4a7965SKim Phillips 	priv->rng.init		= talitos_rng_init,
7789c4a7965SKim Phillips 	priv->rng.data_present	= talitos_rng_data_present,
7799c4a7965SKim Phillips 	priv->rng.data_read	= talitos_rng_data_read,
7809c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
7819c4a7965SKim Phillips 
78235a3bb3dSAaron Sierra 	err = hwrng_register(&priv->rng);
78335a3bb3dSAaron Sierra 	if (!err)
78435a3bb3dSAaron Sierra 		priv->rng_registered = true;
78535a3bb3dSAaron Sierra 
78635a3bb3dSAaron Sierra 	return err;
7879c4a7965SKim Phillips }
7889c4a7965SKim Phillips 
7899c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
7909c4a7965SKim Phillips {
7919c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7929c4a7965SKim Phillips 
79335a3bb3dSAaron Sierra 	if (!priv->rng_registered)
79435a3bb3dSAaron Sierra 		return;
79535a3bb3dSAaron Sierra 
7969c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
79735a3bb3dSAaron Sierra 	priv->rng_registered = false;
7989c4a7965SKim Phillips }
7999c4a7965SKim Phillips 
8009c4a7965SKim Phillips /*
8019c4a7965SKim Phillips  * crypto alg
8029c4a7965SKim Phillips  */
8039c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
8047405c8d7SLEROY Christophe /*
8057405c8d7SLEROY Christophe  * Defines a priority for doing AEAD with descriptors type
8067405c8d7SLEROY Christophe  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
8077405c8d7SLEROY Christophe  */
8087405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
80903d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
8103952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
81170bcaca7SLee Nipper 
8129c4a7965SKim Phillips struct talitos_ctx {
8139c4a7965SKim Phillips 	struct device *dev;
8145228f0f7SKim Phillips 	int ch;
8159c4a7965SKim Phillips 	__be32 desc_hdr_template;
8169c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
81770bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8189c4a7965SKim Phillips 	unsigned int keylen;
8199c4a7965SKim Phillips 	unsigned int enckeylen;
8209c4a7965SKim Phillips 	unsigned int authkeylen;
8219c4a7965SKim Phillips };
8229c4a7965SKim Phillips 
823497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
824497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
825497f2e6bSLee Nipper 
826497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
82760f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
828497f2e6bSLee Nipper 	unsigned int hw_context_size;
829497f2e6bSLee Nipper 	u8 buf[HASH_MAX_BLOCK_SIZE];
830497f2e6bSLee Nipper 	u8 bufnext[HASH_MAX_BLOCK_SIZE];
83160f208d7SKim Phillips 	unsigned int swinit;
832497f2e6bSLee Nipper 	unsigned int first;
833497f2e6bSLee Nipper 	unsigned int last;
834497f2e6bSLee Nipper 	unsigned int to_hash_later;
83542e8b0d7SHoria Geant? 	unsigned int nbuf;
836497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
837497f2e6bSLee Nipper 	struct scatterlist *psrc;
838497f2e6bSLee Nipper };
839497f2e6bSLee Nipper 
8403639ca84SHoria Geant? struct talitos_export_state {
8413639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8423639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8433639ca84SHoria Geant? 	unsigned int swinit;
8443639ca84SHoria Geant? 	unsigned int first;
8453639ca84SHoria Geant? 	unsigned int last;
8463639ca84SHoria Geant? 	unsigned int to_hash_later;
8473639ca84SHoria Geant? 	unsigned int nbuf;
8483639ca84SHoria Geant? };
8493639ca84SHoria Geant? 
85056af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8519c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8529c4a7965SKim Phillips {
8539c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
854c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8559c4a7965SKim Phillips 
856c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8579c4a7965SKim Phillips 		goto badkey;
8589c4a7965SKim Phillips 
859c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8609c4a7965SKim Phillips 		goto badkey;
8619c4a7965SKim Phillips 
862c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
863c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
8649c4a7965SKim Phillips 
865c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
866c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
867c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
8689c4a7965SKim Phillips 
8699c4a7965SKim Phillips 	return 0;
8709c4a7965SKim Phillips 
8719c4a7965SKim Phillips badkey:
8729c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
8739c4a7965SKim Phillips 	return -EINVAL;
8749c4a7965SKim Phillips }
8759c4a7965SKim Phillips 
8769c4a7965SKim Phillips /*
87756af8cd4SLee Nipper  * talitos_edesc - s/w-extended descriptor
8789c4a7965SKim Phillips  * @src_nents: number of segments in input scatterlist
8799c4a7965SKim Phillips  * @dst_nents: number of segments in output scatterlist
880aeb4c132SHerbert Xu  * @icv_ool: whether ICV is out-of-line
88179fd31d3SHoria Geanta  * @iv_dma: dma address of iv for checking continuity and link table
8829c4a7965SKim Phillips  * @dma_len: length of dma mapped link_tbl space
8836f65f6acSLEROY Christophe  * @dma_link_tbl: bus physical address of link_tbl/buf
8849c4a7965SKim Phillips  * @desc: h/w descriptor
8856f65f6acSLEROY Christophe  * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
8866f65f6acSLEROY Christophe  * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
8879c4a7965SKim Phillips  *
8889c4a7965SKim Phillips  * if decrypting (with authcheck), or either one of src_nents or dst_nents
8899c4a7965SKim Phillips  * is greater than 1, an integrity check value is concatenated to the end
8909c4a7965SKim Phillips  * of link_tbl data
8919c4a7965SKim Phillips  */
89256af8cd4SLee Nipper struct talitos_edesc {
8939c4a7965SKim Phillips 	int src_nents;
8949c4a7965SKim Phillips 	int dst_nents;
895aeb4c132SHerbert Xu 	bool icv_ool;
89679fd31d3SHoria Geanta 	dma_addr_t iv_dma;
8979c4a7965SKim Phillips 	int dma_len;
8989c4a7965SKim Phillips 	dma_addr_t dma_link_tbl;
8999c4a7965SKim Phillips 	struct talitos_desc desc;
9006f65f6acSLEROY Christophe 	union {
9019c4a7965SKim Phillips 		struct talitos_ptr link_tbl[0];
9026f65f6acSLEROY Christophe 		u8 buf[0];
9036f65f6acSLEROY Christophe 	};
9049c4a7965SKim Phillips };
9059c4a7965SKim Phillips 
9064de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9074de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9084de9d0b5SLee Nipper 			     struct scatterlist *src,
9096a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
9106a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
911246a87cdSLEROY Christophe {
912246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
913246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9146a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
9156a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
916246a87cdSLEROY Christophe 
9176a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
9186a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
919246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
9206a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
9216a1e8d14SLEROY Christophe 				     offset);
922246a87cdSLEROY Christophe 	}
9236a1e8d14SLEROY Christophe 	if (src != dst) {
9246a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
9256a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
9266a1e8d14SLEROY Christophe 
9276a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
9286a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
9296a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
9306a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
931246a87cdSLEROY Christophe 	}
932246a87cdSLEROY Christophe }
933246a87cdSLEROY Christophe 
9349c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
93556af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
9369c4a7965SKim Phillips 			    struct aead_request *areq)
9379c4a7965SKim Phillips {
938549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
939549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
940549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
941*9a655608SLEROY Christophe 	bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
942*9a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
943*9a655608SLEROY Christophe 	struct talitos_ptr *ckey_ptr = &edesc->desc.ptr[is_ipsec_esp ? 3 : 2];
944549bd8bcSLEROY Christophe 
945*9a655608SLEROY Christophe 	if (is_ipsec_esp)
946549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
947549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
948*9a655608SLEROY Christophe 	unmap_single_talitos_ptr(dev, ckey_ptr, DMA_TO_DEVICE);
949*9a655608SLEROY Christophe 	unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
9509c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[0], DMA_TO_DEVICE);
9519c4a7965SKim Phillips 
9526a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen,
9536a1e8d14SLEROY Christophe 			 areq->assoclen);
9549c4a7965SKim Phillips 
9559c4a7965SKim Phillips 	if (edesc->dma_len)
9569c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
9579c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
958549bd8bcSLEROY Christophe 
959*9a655608SLEROY Christophe 	if (!is_ipsec_esp) {
960549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
961549bd8bcSLEROY Christophe 
962549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
963549bd8bcSLEROY Christophe 				   areq->assoclen + areq->cryptlen - ivsize);
964549bd8bcSLEROY Christophe 	}
9659c4a7965SKim Phillips }
9669c4a7965SKim Phillips 
9679c4a7965SKim Phillips /*
9689c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
9699c4a7965SKim Phillips  */
9709c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
9719c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
9729c4a7965SKim Phillips 				   int err)
9739c4a7965SKim Phillips {
974549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
975549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9769c4a7965SKim Phillips 	struct aead_request *areq = context;
9779c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
978aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
97919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
9809c4a7965SKim Phillips 	struct scatterlist *sg;
9819c4a7965SKim Phillips 	void *icvdata;
9829c4a7965SKim Phillips 
98319bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
98419bbbc63SKim Phillips 
9859c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, areq);
9869c4a7965SKim Phillips 
9879c4a7965SKim Phillips 	/* copy the generated ICV to dst */
988aeb4c132SHerbert Xu 	if (edesc->icv_ool) {
989549bd8bcSLEROY Christophe 		if (is_sec1)
990549bd8bcSLEROY Christophe 			icvdata = edesc->buf + areq->assoclen + areq->cryptlen;
991549bd8bcSLEROY Christophe 		else
9929c4a7965SKim Phillips 			icvdata = &edesc->link_tbl[edesc->src_nents +
993aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
9949c4a7965SKim Phillips 		sg = sg_last(areq->dst, edesc->dst_nents);
995aeb4c132SHerbert Xu 		memcpy((char *)sg_virt(sg) + sg->length - authsize,
996aeb4c132SHerbert Xu 		       icvdata, authsize);
9979c4a7965SKim Phillips 	}
9989c4a7965SKim Phillips 
9999c4a7965SKim Phillips 	kfree(edesc);
10009c4a7965SKim Phillips 
10019c4a7965SKim Phillips 	aead_request_complete(areq, err);
10029c4a7965SKim Phillips }
10039c4a7965SKim Phillips 
1004fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1005e938e465SKim Phillips 					  struct talitos_desc *desc,
1006e938e465SKim Phillips 					  void *context, int err)
10079c4a7965SKim Phillips {
10089c4a7965SKim Phillips 	struct aead_request *req = context;
10099c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1010aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
101119bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10129c4a7965SKim Phillips 	struct scatterlist *sg;
1013aeb4c132SHerbert Xu 	char *oicv, *icv;
1014549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1015549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10169c4a7965SKim Phillips 
101719bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
101819bbbc63SKim Phillips 
10199c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
10209c4a7965SKim Phillips 
10219c4a7965SKim Phillips 	if (!err) {
10229c4a7965SKim Phillips 		/* auth check */
10239c4a7965SKim Phillips 		sg = sg_last(req->dst, edesc->dst_nents ? : 1);
1024aeb4c132SHerbert Xu 		icv = (char *)sg_virt(sg) + sg->length - authsize;
1025aeb4c132SHerbert Xu 
1026aeb4c132SHerbert Xu 		if (edesc->dma_len) {
1027549bd8bcSLEROY Christophe 			if (is_sec1)
1028549bd8bcSLEROY Christophe 				oicv = (char *)&edesc->dma_link_tbl +
1029549bd8bcSLEROY Christophe 					       req->assoclen + req->cryptlen;
1030549bd8bcSLEROY Christophe 			else
1031549bd8bcSLEROY Christophe 				oicv = (char *)
1032549bd8bcSLEROY Christophe 				       &edesc->link_tbl[edesc->src_nents +
1033aeb4c132SHerbert Xu 							edesc->dst_nents + 2];
1034aeb4c132SHerbert Xu 			if (edesc->icv_ool)
1035aeb4c132SHerbert Xu 				icv = oicv + authsize;
1036aeb4c132SHerbert Xu 		} else
1037aeb4c132SHerbert Xu 			oicv = (char *)&edesc->link_tbl[0];
1038aeb4c132SHerbert Xu 
103979960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10409c4a7965SKim Phillips 	}
10419c4a7965SKim Phillips 
10429c4a7965SKim Phillips 	kfree(edesc);
10439c4a7965SKim Phillips 
10449c4a7965SKim Phillips 	aead_request_complete(req, err);
10459c4a7965SKim Phillips }
10469c4a7965SKim Phillips 
1047fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1048e938e465SKim Phillips 					  struct talitos_desc *desc,
1049e938e465SKim Phillips 					  void *context, int err)
1050fe5720e2SKim Phillips {
1051fe5720e2SKim Phillips 	struct aead_request *req = context;
105219bbbc63SKim Phillips 	struct talitos_edesc *edesc;
105319bbbc63SKim Phillips 
105419bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1055fe5720e2SKim Phillips 
1056fe5720e2SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
1057fe5720e2SKim Phillips 
1058fe5720e2SKim Phillips 	/* check ICV auth status */
1059e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1060e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1061fe5720e2SKim Phillips 		err = -EBADMSG;
1062fe5720e2SKim Phillips 
1063fe5720e2SKim Phillips 	kfree(edesc);
1064fe5720e2SKim Phillips 
1065fe5720e2SKim Phillips 	aead_request_complete(req, err);
1066fe5720e2SKim Phillips }
1067fe5720e2SKim Phillips 
10689c4a7965SKim Phillips /*
10699c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
10709c4a7965SKim Phillips  * stop at cryptlen bytes
10719c4a7965SKim Phillips  */
1072aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1073aeb4c132SHerbert Xu 				 unsigned int offset, int cryptlen,
1074aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
10759c4a7965SKim Phillips {
107670bcaca7SLee Nipper 	int n_sg = sg_count;
1077aeb4c132SHerbert Xu 	int count = 0;
107870bcaca7SLee Nipper 
1079aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1080aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1081aeb4c132SHerbert Xu 
1082aeb4c132SHerbert Xu 		if (offset >= len) {
1083aeb4c132SHerbert Xu 			offset -= len;
1084aeb4c132SHerbert Xu 			goto next;
1085aeb4c132SHerbert Xu 		}
1086aeb4c132SHerbert Xu 
1087aeb4c132SHerbert Xu 		len -= offset;
1088aeb4c132SHerbert Xu 
1089aeb4c132SHerbert Xu 		if (len > cryptlen)
1090aeb4c132SHerbert Xu 			len = cryptlen;
1091aeb4c132SHerbert Xu 
1092aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1093da9de146SLEROY Christophe 			       sg_dma_address(sg) + offset, len, 0);
1094b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1095aeb4c132SHerbert Xu 		count++;
1096aeb4c132SHerbert Xu 		cryptlen -= len;
1097aeb4c132SHerbert Xu 		offset = 0;
1098aeb4c132SHerbert Xu 
1099aeb4c132SHerbert Xu next:
11005be4d4c9SCristian Stoica 		sg = sg_next(sg);
11019c4a7965SKim Phillips 	}
11029c4a7965SKim Phillips 
11039c4a7965SKim Phillips 	/* tag end of link table */
1104aeb4c132SHerbert Xu 	if (count > 0)
1105b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1106b096b544SLEROY Christophe 				       DESC_PTR_LNKTBL_RETURN, 0);
110770bcaca7SLee Nipper 
1108aeb4c132SHerbert Xu 	return count;
1109aeb4c132SHerbert Xu }
1110aeb4c132SHerbert Xu 
11115b2cf268SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src,
1112246a87cdSLEROY Christophe 		   unsigned int len, struct talitos_edesc *edesc,
11136a1e8d14SLEROY Christophe 		   struct talitos_ptr *ptr,
11146a1e8d14SLEROY Christophe 		   int sg_count, unsigned int offset, int tbl_off)
1115246a87cdSLEROY Christophe {
1116246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1117246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1118246a87cdSLEROY Christophe 
1119246a87cdSLEROY Christophe 	if (sg_count == 1) {
1120da9de146SLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1);
1121246a87cdSLEROY Christophe 		return sg_count;
1122246a87cdSLEROY Christophe 	}
1123246a87cdSLEROY Christophe 	if (is_sec1) {
1124da9de146SLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1);
11256a1e8d14SLEROY Christophe 		return sg_count;
1126246a87cdSLEROY Christophe 	}
11276a1e8d14SLEROY Christophe 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len,
11286a1e8d14SLEROY Christophe 					 &edesc->link_tbl[tbl_off]);
1129246a87cdSLEROY Christophe 	if (sg_count == 1) {
11306a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
11316a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
11326a1e8d14SLEROY Christophe 		return sg_count;
11336a1e8d14SLEROY Christophe 	}
1134246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
1135da9de146SLEROY Christophe 			    tbl_off * sizeof(struct talitos_ptr), len, is_sec1);
11366a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
11376a1e8d14SLEROY Christophe 
11386a1e8d14SLEROY Christophe 	return sg_count;
1139246a87cdSLEROY Christophe }
1140246a87cdSLEROY Christophe 
11419c4a7965SKim Phillips /*
11429c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
11439c4a7965SKim Phillips  */
114456af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
1145aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
11469c4a7965SKim Phillips 				      struct talitos_desc *desc,
11479c4a7965SKim Phillips 				      void *context, int error))
11489c4a7965SKim Phillips {
11499c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1150aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
11519c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
11529c4a7965SKim Phillips 	struct device *dev = ctx->dev;
11539c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
11549c4a7965SKim Phillips 	unsigned int cryptlen = areq->cryptlen;
1155e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1156aeb4c132SHerbert Xu 	int tbl_off = 0;
1157fa86a267SKim Phillips 	int sg_count, ret;
1158fe5720e2SKim Phillips 	int sg_link_tbl_len;
1159549bd8bcSLEROY Christophe 	bool sync_needed = false;
1160549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1161549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1162*9a655608SLEROY Christophe 	bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
1163*9a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
1164*9a655608SLEROY Christophe 	struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
11659c4a7965SKim Phillips 
11669c4a7965SKim Phillips 	/* hmac key */
11679c4a7965SKim Phillips 	map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
1168a2b35aa8SLEROY Christophe 			       DMA_TO_DEVICE);
116979fd31d3SHoria Geanta 
1170549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1171549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1172549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1173549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1174549bd8bcSLEROY Christophe 	else
1175549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1176549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1177549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1178549bd8bcSLEROY Christophe 
11799c4a7965SKim Phillips 	/* hmac data */
1180549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1181549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
118279fd31d3SHoria Geanta 
1183549bd8bcSLEROY Christophe 	if (ret > 1) {
1184340ff60aSHoria Geant? 		tbl_off += ret;
1185549bd8bcSLEROY Christophe 		sync_needed = true;
118679fd31d3SHoria Geanta 	}
118779fd31d3SHoria Geanta 
11889c4a7965SKim Phillips 	/* cipher iv */
1189*9a655608SLEROY Christophe 	to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1);
11909c4a7965SKim Phillips 
11919c4a7965SKim Phillips 	/* cipher key */
1192*9a655608SLEROY Christophe 	map_single_talitos_ptr(dev, ckey_ptr, ctx->enckeylen,
1193549bd8bcSLEROY Christophe 			       (char *)&ctx->key + ctx->authkeylen,
1194549bd8bcSLEROY Christophe 			       DMA_TO_DEVICE);
11959c4a7965SKim Phillips 
11969c4a7965SKim Phillips 	/*
11979c4a7965SKim Phillips 	 * cipher in
11989c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
11999c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
12009c4a7965SKim Phillips 	 * typically 12 for ipsec
12019c4a7965SKim Phillips 	 */
1202fe5720e2SKim Phillips 	sg_link_tbl_len = cryptlen;
1203549bd8bcSLEROY Christophe 
1204*9a655608SLEROY Christophe 	if (is_ipsec_esp) {
1205549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[4], authsize, is_sec1);
1206549bd8bcSLEROY Christophe 
1207*9a655608SLEROY Christophe 		if (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)
1208aeb4c132SHerbert Xu 			sg_link_tbl_len += authsize;
1209549bd8bcSLEROY Christophe 	}
1210e938e465SKim Phillips 
1211fbb22137SLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, sg_link_tbl_len, edesc,
1212fbb22137SLEROY Christophe 			     &desc->ptr[4], sg_count, areq->assoclen, tbl_off);
1213549bd8bcSLEROY Christophe 
1214ec8c7d14SLEROY Christophe 	if (ret > 1) {
1215ec8c7d14SLEROY Christophe 		tbl_off += ret;
1216549bd8bcSLEROY Christophe 		sync_needed = true;
1217340ff60aSHoria Geant? 	}
12189c4a7965SKim Phillips 
12199c4a7965SKim Phillips 	/* cipher out */
1220549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1221549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1222549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1223549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1224549bd8bcSLEROY Christophe 	}
12259c4a7965SKim Phillips 
1226e04a61beSLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
1227e04a61beSLEROY Christophe 			     sg_count, areq->assoclen, tbl_off);
12289c4a7965SKim Phillips 
1229*9a655608SLEROY Christophe 	if (is_ipsec_esp)
1230549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1231aeb4c132SHerbert Xu 
1232e04a61beSLEROY Christophe 	/* ICV data */
1233e04a61beSLEROY Christophe 	if (ret > 1) {
1234e04a61beSLEROY Christophe 		tbl_off += ret;
1235549bd8bcSLEROY Christophe 		edesc->icv_ool = true;
1236549bd8bcSLEROY Christophe 		sync_needed = true;
1237549bd8bcSLEROY Christophe 
1238*9a655608SLEROY Christophe 		if (is_ipsec_esp) {
123979fd31d3SHoria Geanta 			struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1240549bd8bcSLEROY Christophe 			int offset = (edesc->src_nents + edesc->dst_nents + 2) *
1241549bd8bcSLEROY Christophe 				     sizeof(struct talitos_ptr) + authsize;
1242fe5720e2SKim Phillips 
1243f3c85bc1SLee Nipper 			/* Add an entry to the link table for ICV data */
1244e04a61beSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
1245549bd8bcSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN,
1246549bd8bcSLEROY Christophe 					       is_sec1);
12479c4a7965SKim Phillips 
12489c4a7965SKim Phillips 			/* icv data follows link tables */
1249549bd8bcSLEROY Christophe 			to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl + offset,
1250da9de146SLEROY Christophe 				       authsize, is_sec1);
1251e04a61beSLEROY Christophe 		} else {
1252e04a61beSLEROY Christophe 			dma_addr_t addr = edesc->dma_link_tbl;
1253e04a61beSLEROY Christophe 
1254e04a61beSLEROY Christophe 			if (is_sec1)
1255e04a61beSLEROY Christophe 				addr += areq->assoclen + cryptlen;
1256e04a61beSLEROY Christophe 			else
1257e04a61beSLEROY Christophe 				addr += sizeof(struct talitos_ptr) * tbl_off;
1258e04a61beSLEROY Christophe 
1259da9de146SLEROY Christophe 			to_talitos_ptr(&desc->ptr[6], addr, authsize, is_sec1);
1260549bd8bcSLEROY Christophe 		}
1261*9a655608SLEROY Christophe 	} else if (!is_ipsec_esp) {
1262e04a61beSLEROY Christophe 		ret = talitos_sg_map(dev, areq->dst, authsize, edesc,
1263e04a61beSLEROY Christophe 				     &desc->ptr[6], sg_count, areq->assoclen +
1264e04a61beSLEROY Christophe 							      cryptlen,
1265e04a61beSLEROY Christophe 				     tbl_off);
1266e04a61beSLEROY Christophe 		if (ret > 1) {
1267e04a61beSLEROY Christophe 			tbl_off += ret;
1268e04a61beSLEROY Christophe 			edesc->icv_ool = true;
1269e04a61beSLEROY Christophe 			sync_needed = true;
1270340ff60aSHoria Geant? 		} else {
1271549bd8bcSLEROY Christophe 			edesc->icv_ool = false;
1272549bd8bcSLEROY Christophe 		}
1273e04a61beSLEROY Christophe 	} else {
1274e04a61beSLEROY Christophe 		edesc->icv_ool = false;
1275340ff60aSHoria Geant? 	}
12769c4a7965SKim Phillips 
12779c4a7965SKim Phillips 	/* iv out */
1278*9a655608SLEROY Christophe 	if (is_ipsec_esp)
1279a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
12809c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
12819c4a7965SKim Phillips 
1282549bd8bcSLEROY Christophe 	if (sync_needed)
1283549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1284549bd8bcSLEROY Christophe 					   edesc->dma_len,
1285549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1286549bd8bcSLEROY Christophe 
12875228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1288fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
1289fa86a267SKim Phillips 		ipsec_esp_unmap(dev, edesc, areq);
1290fa86a267SKim Phillips 		kfree(edesc);
1291fa86a267SKim Phillips 	}
1292fa86a267SKim Phillips 	return ret;
12939c4a7965SKim Phillips }
12949c4a7965SKim Phillips 
12959c4a7965SKim Phillips /*
129656af8cd4SLee Nipper  * allocate and map the extended descriptor
12979c4a7965SKim Phillips  */
12984de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
12994de9d0b5SLee Nipper 						 struct scatterlist *src,
13004de9d0b5SLee Nipper 						 struct scatterlist *dst,
130179fd31d3SHoria Geanta 						 u8 *iv,
130279fd31d3SHoria Geanta 						 unsigned int assoclen,
13034de9d0b5SLee Nipper 						 unsigned int cryptlen,
13044de9d0b5SLee Nipper 						 unsigned int authsize,
130579fd31d3SHoria Geanta 						 unsigned int ivsize,
13064de9d0b5SLee Nipper 						 int icv_stashing,
130762293a37SHoria Geanta 						 u32 cryptoflags,
130862293a37SHoria Geanta 						 bool encrypt)
13099c4a7965SKim Phillips {
131056af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13116a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
131279fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
13134de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1314586725f8SKim Phillips 		      GFP_ATOMIC;
13156f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
13166f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
13176f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
13188e409fe1SLABBE Corentin 	void *err;
13199c4a7965SKim Phillips 
13206f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
13214de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
13229c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
13239c4a7965SKim Phillips 	}
13249c4a7965SKim Phillips 
1325935e99a3SHoria Geanta 	if (ivsize)
132679fd31d3SHoria Geanta 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
132779fd31d3SHoria Geanta 
132862293a37SHoria Geanta 	if (!dst || dst == src) {
13296a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
13306a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13318e409fe1SLABBE Corentin 		if (src_nents < 0) {
13328e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13338e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13348e409fe1SLABBE Corentin 			goto error_sg;
13358e409fe1SLABBE Corentin 		}
13369c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
133762293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
13386a1e8d14SLEROY Christophe 		dst_len = 0;
133962293a37SHoria Geanta 	} else { /* dst && dst != src*/
13406a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
13416a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13428e409fe1SLABBE Corentin 		if (src_nents < 0) {
13438e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13448e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13458e409fe1SLABBE Corentin 			goto error_sg;
13468e409fe1SLABBE Corentin 		}
134762293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
13486a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
13496a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
13508e409fe1SLABBE Corentin 		if (dst_nents < 0) {
13518e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
13528e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13538e409fe1SLABBE Corentin 			goto error_sg;
13548e409fe1SLABBE Corentin 		}
1355695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
13569c4a7965SKim Phillips 	}
13579c4a7965SKim Phillips 
13589c4a7965SKim Phillips 	/*
13599c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1360aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1361aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
13629c4a7965SKim Phillips 	 */
136356af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1364aeb4c132SHerbert Xu 	if (src_nents || dst_nents) {
13656f65f6acSLEROY Christophe 		if (is_sec1)
13666a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
13676a1e8d14SLEROY Christophe 				  (dst_nents ? dst_len : 0);
13686f65f6acSLEROY Christophe 		else
1369aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1370aeb4c132SHerbert Xu 				  sizeof(struct talitos_ptr) + authsize * 2;
13719c4a7965SKim Phillips 		alloc_len += dma_len;
13729c4a7965SKim Phillips 	} else {
13739c4a7965SKim Phillips 		dma_len = 0;
13744de9d0b5SLee Nipper 		alloc_len += icv_stashing ? authsize : 0;
13759c4a7965SKim Phillips 	}
13769c4a7965SKim Phillips 
1377586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
13789c4a7965SKim Phillips 	if (!edesc) {
13794de9d0b5SLee Nipper 		dev_err(dev, "could not allocate edescriptor\n");
13808e409fe1SLABBE Corentin 		err = ERR_PTR(-ENOMEM);
13818e409fe1SLABBE Corentin 		goto error_sg;
13829c4a7965SKim Phillips 	}
1383e4a647c4SLEROY Christophe 	memset(&edesc->desc, 0, sizeof(edesc->desc));
13849c4a7965SKim Phillips 
13859c4a7965SKim Phillips 	edesc->src_nents = src_nents;
13869c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
138779fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
13889c4a7965SKim Phillips 	edesc->dma_len = dma_len;
1389497f2e6bSLee Nipper 	if (dma_len)
13904de9d0b5SLee Nipper 		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1391497f2e6bSLee Nipper 						     edesc->dma_len,
1392497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
13939c4a7965SKim Phillips 
13949c4a7965SKim Phillips 	return edesc;
13958e409fe1SLABBE Corentin error_sg:
13968e409fe1SLABBE Corentin 	if (iv_dma)
13978e409fe1SLABBE Corentin 		dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
13988e409fe1SLABBE Corentin 	return err;
13999c4a7965SKim Phillips }
14009c4a7965SKim Phillips 
140179fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
140262293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
14034de9d0b5SLee Nipper {
14044de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1405aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14064de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
140779fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
14084de9d0b5SLee Nipper 
1409aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
141079fd31d3SHoria Geanta 				   iv, areq->assoclen, areq->cryptlen,
1411aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
141262293a37SHoria Geanta 				   areq->base.flags, encrypt);
14134de9d0b5SLee Nipper }
14144de9d0b5SLee Nipper 
141556af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
14169c4a7965SKim Phillips {
14179c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14189c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
141956af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14209c4a7965SKim Phillips 
14219c4a7965SKim Phillips 	/* allocate extended descriptor */
142262293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
14239c4a7965SKim Phillips 	if (IS_ERR(edesc))
14249c4a7965SKim Phillips 		return PTR_ERR(edesc);
14259c4a7965SKim Phillips 
14269c4a7965SKim Phillips 	/* set encrypt */
142770bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14289c4a7965SKim Phillips 
1429aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
14309c4a7965SKim Phillips }
14319c4a7965SKim Phillips 
143256af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
14339c4a7965SKim Phillips {
14349c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1435aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14369c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1437fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
143856af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14399c4a7965SKim Phillips 	struct scatterlist *sg;
14409c4a7965SKim Phillips 	void *icvdata;
14419c4a7965SKim Phillips 
14429c4a7965SKim Phillips 	req->cryptlen -= authsize;
14439c4a7965SKim Phillips 
14449c4a7965SKim Phillips 	/* allocate extended descriptor */
144562293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14469c4a7965SKim Phillips 	if (IS_ERR(edesc))
14479c4a7965SKim Phillips 		return PTR_ERR(edesc);
14489c4a7965SKim Phillips 
1449fe5720e2SKim Phillips 	if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1450e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1451e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1452fe5720e2SKim Phillips 
1453fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1454e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1455e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1456fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1457fe5720e2SKim Phillips 
1458fe5720e2SKim Phillips 		/* reset integrity check result bits */
1459fe5720e2SKim Phillips 
1460aeb4c132SHerbert Xu 		return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
1461e938e465SKim Phillips 	}
1462fe5720e2SKim Phillips 
1463fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1464fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1465fe5720e2SKim Phillips 
14669c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
14679c4a7965SKim Phillips 	if (edesc->dma_len)
1468aeb4c132SHerbert Xu 		icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1469aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
14709c4a7965SKim Phillips 	else
14719c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[0];
14729c4a7965SKim Phillips 
14739c4a7965SKim Phillips 	sg = sg_last(req->src, edesc->src_nents ? : 1);
14749c4a7965SKim Phillips 
1475aeb4c132SHerbert Xu 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
14769c4a7965SKim Phillips 
1477aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
14789c4a7965SKim Phillips }
14799c4a7965SKim Phillips 
14804de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
14814de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
14824de9d0b5SLee Nipper {
14834de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
1484f384cdc4SLEROY Christophe 	u32 tmp[DES_EXPKEY_WORDS];
14854de9d0b5SLee Nipper 
148603d2c511SMartin Hicks 	if (keylen > TALITOS_MAX_KEY_SIZE) {
148703d2c511SMartin Hicks 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
148803d2c511SMartin Hicks 		return -EINVAL;
148903d2c511SMartin Hicks 	}
149003d2c511SMartin Hicks 
1491f384cdc4SLEROY Christophe 	if (unlikely(crypto_ablkcipher_get_flags(cipher) &
1492f384cdc4SLEROY Christophe 		     CRYPTO_TFM_REQ_WEAK_KEY) &&
1493f384cdc4SLEROY Christophe 	    !des_ekey(tmp, key)) {
1494f384cdc4SLEROY Christophe 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY);
1495f384cdc4SLEROY Christophe 		return -EINVAL;
1496f384cdc4SLEROY Christophe 	}
1497f384cdc4SLEROY Christophe 
14984de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
14994de9d0b5SLee Nipper 	ctx->keylen = keylen;
15004de9d0b5SLee Nipper 
15014de9d0b5SLee Nipper 	return 0;
15024de9d0b5SLee Nipper }
15034de9d0b5SLee Nipper 
15044de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
15054de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
15064de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
15074de9d0b5SLee Nipper {
15084de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1509032d197eSLEROY Christophe 
15106a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0);
15114de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
15124de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
15134de9d0b5SLee Nipper 
15144de9d0b5SLee Nipper 	if (edesc->dma_len)
15154de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
15164de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
15174de9d0b5SLee Nipper }
15184de9d0b5SLee Nipper 
15194de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
15204de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
15214de9d0b5SLee Nipper 			    int err)
15224de9d0b5SLee Nipper {
15234de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
152419bbbc63SKim Phillips 	struct talitos_edesc *edesc;
152519bbbc63SKim Phillips 
152619bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
15274de9d0b5SLee Nipper 
15284de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
15294de9d0b5SLee Nipper 
15304de9d0b5SLee Nipper 	kfree(edesc);
15314de9d0b5SLee Nipper 
15324de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
15334de9d0b5SLee Nipper }
15344de9d0b5SLee Nipper 
15354de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
15364de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
15374de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
15384de9d0b5SLee Nipper 					     struct talitos_desc *desc,
15394de9d0b5SLee Nipper 					     void *context, int error))
15404de9d0b5SLee Nipper {
15414de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15424de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15434de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
15444de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
15454de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
154679fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
15474de9d0b5SLee Nipper 	int sg_count, ret;
15486a1e8d14SLEROY Christophe 	bool sync_needed = false;
1549922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1550922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
15514de9d0b5SLee Nipper 
15524de9d0b5SLee Nipper 	/* first DWORD empty */
15534de9d0b5SLee Nipper 
15544de9d0b5SLee Nipper 	/* cipher iv */
1555da9de146SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1);
15564de9d0b5SLee Nipper 
15574de9d0b5SLee Nipper 	/* cipher key */
15584de9d0b5SLee Nipper 	map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1559a2b35aa8SLEROY Christophe 			       (char *)&ctx->key, DMA_TO_DEVICE);
15604de9d0b5SLee Nipper 
15616a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
15626a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
15636a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
15646a1e8d14SLEROY Christophe 				  cryptlen);
15656a1e8d14SLEROY Christophe 	else
15666a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
15676a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
15686a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
15694de9d0b5SLee Nipper 	/*
15704de9d0b5SLee Nipper 	 * cipher in
15714de9d0b5SLee Nipper 	 */
15726a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
15736a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
15746a1e8d14SLEROY Christophe 	if (sg_count > 1)
15756a1e8d14SLEROY Christophe 		sync_needed = true;
15764de9d0b5SLee Nipper 
15774de9d0b5SLee Nipper 	/* cipher out */
15786a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
15796a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
15806a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
15816a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
15826a1e8d14SLEROY Christophe 	}
15836a1e8d14SLEROY Christophe 
15846a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
15856a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
15866a1e8d14SLEROY Christophe 	if (ret > 1)
15876a1e8d14SLEROY Christophe 		sync_needed = true;
15884de9d0b5SLee Nipper 
15894de9d0b5SLee Nipper 	/* iv out */
1590a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
15914de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
15924de9d0b5SLee Nipper 
15934de9d0b5SLee Nipper 	/* last DWORD empty */
15944de9d0b5SLee Nipper 
15956a1e8d14SLEROY Christophe 	if (sync_needed)
15966a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
15976a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
15986a1e8d14SLEROY Christophe 
15995228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
16004de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
16014de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
16024de9d0b5SLee Nipper 		kfree(edesc);
16034de9d0b5SLee Nipper 	}
16044de9d0b5SLee Nipper 	return ret;
16054de9d0b5SLee Nipper }
16064de9d0b5SLee Nipper 
1607e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
160862293a37SHoria Geanta 						    areq, bool encrypt)
16094de9d0b5SLee Nipper {
16104de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16114de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
161279fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
16134de9d0b5SLee Nipper 
1614aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
161579fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
161662293a37SHoria Geanta 				   areq->base.flags, encrypt);
16174de9d0b5SLee Nipper }
16184de9d0b5SLee Nipper 
16194de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
16204de9d0b5SLee Nipper {
16214de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16224de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16234de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16244de9d0b5SLee Nipper 
16254de9d0b5SLee Nipper 	/* allocate extended descriptor */
162662293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
16274de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16284de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16294de9d0b5SLee Nipper 
16304de9d0b5SLee Nipper 	/* set encrypt */
16314de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16324de9d0b5SLee Nipper 
1633febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16344de9d0b5SLee Nipper }
16354de9d0b5SLee Nipper 
16364de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
16374de9d0b5SLee Nipper {
16384de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16394de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16404de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16414de9d0b5SLee Nipper 
16424de9d0b5SLee Nipper 	/* allocate extended descriptor */
164362293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
16444de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16454de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16464de9d0b5SLee Nipper 
16474de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
16484de9d0b5SLee Nipper 
1649febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16504de9d0b5SLee Nipper }
16514de9d0b5SLee Nipper 
1652497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1653497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1654497f2e6bSLee Nipper 				       struct ahash_request *areq)
1655497f2e6bSLee Nipper {
1656497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1657922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1658922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1659497f2e6bSLee Nipper 
1660497f2e6bSLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1661497f2e6bSLee Nipper 
16626a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1663032d197eSLEROY Christophe 
1664497f2e6bSLee Nipper 	/* When using hashctx-in, must unmap it. */
1665922f9dc8SLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
1666497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1667497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1668497f2e6bSLee Nipper 
1669922f9dc8SLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[2], is_sec1))
1670497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2],
1671497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1672497f2e6bSLee Nipper 
1673497f2e6bSLee Nipper 	if (edesc->dma_len)
1674497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1675497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1676497f2e6bSLee Nipper 
1677497f2e6bSLee Nipper }
1678497f2e6bSLee Nipper 
1679497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1680497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1681497f2e6bSLee Nipper 		       int err)
1682497f2e6bSLee Nipper {
1683497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1684497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1685497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1686497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1687497f2e6bSLee Nipper 
1688497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1689497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
1690497f2e6bSLee Nipper 		memcpy(req_ctx->buf, req_ctx->bufnext, req_ctx->to_hash_later);
16915e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1692497f2e6bSLee Nipper 	}
1693497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1694497f2e6bSLee Nipper 
1695497f2e6bSLee Nipper 	kfree(edesc);
1696497f2e6bSLee Nipper 
1697497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1698497f2e6bSLee Nipper }
1699497f2e6bSLee Nipper 
17002d02905eSLEROY Christophe /*
17012d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
17022d02905eSLEROY Christophe  * ourself and submit a padded block
17032d02905eSLEROY Christophe  */
17045b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
17052d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
17062d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
17072d02905eSLEROY Christophe {
17082d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
17092d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17102d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17112d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17122d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17132d02905eSLEROY Christophe 	};
17142d02905eSLEROY Christophe 
17152d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
17162d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
17172d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
17182d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
17192d02905eSLEROY Christophe }
17202d02905eSLEROY Christophe 
1721497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1722497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
1723497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1724497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1725497f2e6bSLee Nipper 						  void *context, int error))
1726497f2e6bSLee Nipper {
1727497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1728497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1729497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1730497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1731497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1732032d197eSLEROY Christophe 	int ret;
17336a1e8d14SLEROY Christophe 	bool sync_needed = false;
1734922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1735922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
17366a1e8d14SLEROY Christophe 	int sg_count;
1737497f2e6bSLee Nipper 
1738497f2e6bSLee Nipper 	/* first DWORD empty */
1739497f2e6bSLee Nipper 
174060f208d7SKim Phillips 	/* hash context in */
174160f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
1742497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[1],
1743497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1744a2b35aa8SLEROY Christophe 				       (char *)req_ctx->hw_context,
1745497f2e6bSLee Nipper 				       DMA_TO_DEVICE);
174660f208d7SKim Phillips 		req_ctx->swinit = 0;
1747afd62fa2SLEROY Christophe 	}
1748497f2e6bSLee Nipper 	/* Indicate next op is not the first. */
1749497f2e6bSLee Nipper 	req_ctx->first = 0;
1750497f2e6bSLee Nipper 
1751497f2e6bSLee Nipper 	/* HMAC key */
1752497f2e6bSLee Nipper 	if (ctx->keylen)
1753497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1754a2b35aa8SLEROY Christophe 				       (char *)&ctx->key, DMA_TO_DEVICE);
1755497f2e6bSLee Nipper 
17566a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
17576a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
1758886a27c0SLEROY Christophe 		sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
17596a1e8d14SLEROY Christophe 	else
17606a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
17616a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1762497f2e6bSLee Nipper 	/*
1763497f2e6bSLee Nipper 	 * data in
1764497f2e6bSLee Nipper 	 */
17656a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
17666a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
17676a1e8d14SLEROY Christophe 	if (sg_count > 1)
17686a1e8d14SLEROY Christophe 		sync_needed = true;
1769497f2e6bSLee Nipper 
1770497f2e6bSLee Nipper 	/* fifth DWORD empty */
1771497f2e6bSLee Nipper 
1772497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1773497f2e6bSLee Nipper 	if (req_ctx->last)
1774497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1775497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1776a2b35aa8SLEROY Christophe 				       areq->result, DMA_FROM_DEVICE);
1777497f2e6bSLee Nipper 	else
1778497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1779497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1780a2b35aa8SLEROY Christophe 				       req_ctx->hw_context, DMA_FROM_DEVICE);
1781497f2e6bSLee Nipper 
1782497f2e6bSLee Nipper 	/* last DWORD empty */
1783497f2e6bSLee Nipper 
17842d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
17852d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
17862d02905eSLEROY Christophe 
17876a1e8d14SLEROY Christophe 	if (sync_needed)
17886a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
17896a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
17906a1e8d14SLEROY Christophe 
17915228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1792497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1793497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1794497f2e6bSLee Nipper 		kfree(edesc);
1795497f2e6bSLee Nipper 	}
1796497f2e6bSLee Nipper 	return ret;
1797497f2e6bSLee Nipper }
1798497f2e6bSLee Nipper 
1799497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1800497f2e6bSLee Nipper 					       unsigned int nbytes)
1801497f2e6bSLee Nipper {
1802497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1803497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1804497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1805497f2e6bSLee Nipper 
1806aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
180762293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1808497f2e6bSLee Nipper }
1809497f2e6bSLee Nipper 
1810497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1811497f2e6bSLee Nipper {
1812497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1813497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1814497f2e6bSLee Nipper 
1815497f2e6bSLee Nipper 	/* Initialize the context */
18165e833bc4SLee Nipper 	req_ctx->nbuf = 0;
181760f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
181860f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
1819497f2e6bSLee Nipper 	req_ctx->hw_context_size =
1820497f2e6bSLee Nipper 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1821497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1822497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
1823497f2e6bSLee Nipper 
1824497f2e6bSLee Nipper 	return 0;
1825497f2e6bSLee Nipper }
1826497f2e6bSLee Nipper 
182760f208d7SKim Phillips /*
182860f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
182960f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
183060f208d7SKim Phillips  */
183160f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
183260f208d7SKim Phillips {
183360f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
183460f208d7SKim Phillips 
183560f208d7SKim Phillips 	ahash_init(areq);
183660f208d7SKim Phillips 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
183760f208d7SKim Phillips 
1838a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1839a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1840a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1841a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1842a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1843a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1844a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1845a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
184660f208d7SKim Phillips 
184760f208d7SKim Phillips 	/* init 64-bit count */
184860f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
184960f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
185060f208d7SKim Phillips 
185160f208d7SKim Phillips 	return 0;
185260f208d7SKim Phillips }
185360f208d7SKim Phillips 
1854497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1855497f2e6bSLee Nipper {
1856497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1857497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1858497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1859497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1860497f2e6bSLee Nipper 	unsigned int blocksize =
1861497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1862497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1863497f2e6bSLee Nipper 	unsigned int to_hash_later;
18645e833bc4SLee Nipper 	unsigned int nsg;
18658e409fe1SLABBE Corentin 	int nents;
1866497f2e6bSLee Nipper 
18675e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
18685e833bc4SLee Nipper 		/* Buffer up to one whole block */
18698e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
18708e409fe1SLABBE Corentin 		if (nents < 0) {
18718e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
18728e409fe1SLABBE Corentin 			return nents;
18738e409fe1SLABBE Corentin 		}
18748e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
18755e833bc4SLee Nipper 				  req_ctx->buf + req_ctx->nbuf, nbytes);
18765e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
1877497f2e6bSLee Nipper 		return 0;
1878497f2e6bSLee Nipper 	}
1879497f2e6bSLee Nipper 
18805e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
18815e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
18825e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
18835e833bc4SLee Nipper 
18845e833bc4SLee Nipper 	if (req_ctx->last)
18855e833bc4SLee Nipper 		to_hash_later = 0;
18865e833bc4SLee Nipper 	else if (to_hash_later)
18875e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
18885e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
18895e833bc4SLee Nipper 	else {
18905e833bc4SLee Nipper 		/* Keep one block buffered */
18915e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
18925e833bc4SLee Nipper 		to_hash_later = blocksize;
1893497f2e6bSLee Nipper 	}
18945e833bc4SLee Nipper 
18955e833bc4SLee Nipper 	/* Chain in any previously buffered data */
18965e833bc4SLee Nipper 	if (req_ctx->nbuf) {
18975e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
18985e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
18995e833bc4SLee Nipper 		sg_set_buf(req_ctx->bufsl, req_ctx->buf, req_ctx->nbuf);
19005e833bc4SLee Nipper 		if (nsg > 1)
1901c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
19025e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
19035e833bc4SLee Nipper 	} else
19045e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
19055e833bc4SLee Nipper 
1906497f2e6bSLee Nipper 	if (to_hash_later) {
19078e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
19088e409fe1SLABBE Corentin 		if (nents < 0) {
19098e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
19108e409fe1SLABBE Corentin 			return nents;
19118e409fe1SLABBE Corentin 		}
1912d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
1913497f2e6bSLee Nipper 				      req_ctx->bufnext,
1914497f2e6bSLee Nipper 				      to_hash_later,
1915497f2e6bSLee Nipper 				      nbytes - to_hash_later);
1916497f2e6bSLee Nipper 	}
1917497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
1918497f2e6bSLee Nipper 
19195e833bc4SLee Nipper 	/* Allocate extended descriptor */
1920497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
1921497f2e6bSLee Nipper 	if (IS_ERR(edesc))
1922497f2e6bSLee Nipper 		return PTR_ERR(edesc);
1923497f2e6bSLee Nipper 
1924497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
1925497f2e6bSLee Nipper 
1926497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
1927497f2e6bSLee Nipper 	if (req_ctx->last)
1928497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
1929497f2e6bSLee Nipper 	else
1930497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
1931497f2e6bSLee Nipper 
193260f208d7SKim Phillips 	/* request SEC to INIT hash. */
193360f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
1934497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
1935497f2e6bSLee Nipper 
1936497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
1937497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
1938497f2e6bSLee Nipper 	 */
1939497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
1940497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
1941497f2e6bSLee Nipper 
1942497f2e6bSLee Nipper 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash,
1943497f2e6bSLee Nipper 				    ahash_done);
1944497f2e6bSLee Nipper }
1945497f2e6bSLee Nipper 
1946497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
1947497f2e6bSLee Nipper {
1948497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1949497f2e6bSLee Nipper 
1950497f2e6bSLee Nipper 	req_ctx->last = 0;
1951497f2e6bSLee Nipper 
1952497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1953497f2e6bSLee Nipper }
1954497f2e6bSLee Nipper 
1955497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
1956497f2e6bSLee Nipper {
1957497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1958497f2e6bSLee Nipper 
1959497f2e6bSLee Nipper 	req_ctx->last = 1;
1960497f2e6bSLee Nipper 
1961497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
1962497f2e6bSLee Nipper }
1963497f2e6bSLee Nipper 
1964497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
1965497f2e6bSLee Nipper {
1966497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1967497f2e6bSLee Nipper 
1968497f2e6bSLee Nipper 	req_ctx->last = 1;
1969497f2e6bSLee Nipper 
1970497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1971497f2e6bSLee Nipper }
1972497f2e6bSLee Nipper 
1973497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
1974497f2e6bSLee Nipper {
1975497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
197660f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
1977497f2e6bSLee Nipper 
197860f208d7SKim Phillips 	ahash->init(areq);
1979497f2e6bSLee Nipper 	req_ctx->last = 1;
1980497f2e6bSLee Nipper 
1981497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1982497f2e6bSLee Nipper }
1983497f2e6bSLee Nipper 
19843639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
19853639ca84SHoria Geant? {
19863639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
19873639ca84SHoria Geant? 	struct talitos_export_state *export = out;
19883639ca84SHoria Geant? 
19893639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
19903639ca84SHoria Geant? 	       req_ctx->hw_context_size);
19913639ca84SHoria Geant? 	memcpy(export->buf, req_ctx->buf, req_ctx->nbuf);
19923639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
19933639ca84SHoria Geant? 	export->first = req_ctx->first;
19943639ca84SHoria Geant? 	export->last = req_ctx->last;
19953639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
19963639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
19973639ca84SHoria Geant? 
19983639ca84SHoria Geant? 	return 0;
19993639ca84SHoria Geant? }
20003639ca84SHoria Geant? 
20013639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
20023639ca84SHoria Geant? {
20033639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
20043639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
20053639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
20063639ca84SHoria Geant? 
20073639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
20083639ca84SHoria Geant? 	req_ctx->hw_context_size =
20093639ca84SHoria Geant? 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
20103639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
20113639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
20123639ca84SHoria Geant? 	memcpy(req_ctx->hw_context, export->hw_context,
20133639ca84SHoria Geant? 	       req_ctx->hw_context_size);
20143639ca84SHoria Geant? 	memcpy(req_ctx->buf, export->buf, export->nbuf);
20153639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
20163639ca84SHoria Geant? 	req_ctx->first = export->first;
20173639ca84SHoria Geant? 	req_ctx->last = export->last;
20183639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
20193639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
20203639ca84SHoria Geant? 
20213639ca84SHoria Geant? 	return 0;
20223639ca84SHoria Geant? }
20233639ca84SHoria Geant? 
202479b3a418SLee Nipper struct keyhash_result {
202579b3a418SLee Nipper 	struct completion completion;
202679b3a418SLee Nipper 	int err;
202779b3a418SLee Nipper };
202879b3a418SLee Nipper 
202979b3a418SLee Nipper static void keyhash_complete(struct crypto_async_request *req, int err)
203079b3a418SLee Nipper {
203179b3a418SLee Nipper 	struct keyhash_result *res = req->data;
203279b3a418SLee Nipper 
203379b3a418SLee Nipper 	if (err == -EINPROGRESS)
203479b3a418SLee Nipper 		return;
203579b3a418SLee Nipper 
203679b3a418SLee Nipper 	res->err = err;
203779b3a418SLee Nipper 	complete(&res->completion);
203879b3a418SLee Nipper }
203979b3a418SLee Nipper 
204079b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
204179b3a418SLee Nipper 		   u8 *hash)
204279b3a418SLee Nipper {
204379b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
204479b3a418SLee Nipper 
204579b3a418SLee Nipper 	struct scatterlist sg[1];
204679b3a418SLee Nipper 	struct ahash_request *req;
204779b3a418SLee Nipper 	struct keyhash_result hresult;
204879b3a418SLee Nipper 	int ret;
204979b3a418SLee Nipper 
205079b3a418SLee Nipper 	init_completion(&hresult.completion);
205179b3a418SLee Nipper 
205279b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
205379b3a418SLee Nipper 	if (!req)
205479b3a418SLee Nipper 		return -ENOMEM;
205579b3a418SLee Nipper 
205679b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
205779b3a418SLee Nipper 	ctx->keylen = 0;
205879b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
205979b3a418SLee Nipper 				   keyhash_complete, &hresult);
206079b3a418SLee Nipper 
206179b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
206279b3a418SLee Nipper 
206379b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
206479b3a418SLee Nipper 	ret = crypto_ahash_digest(req);
206579b3a418SLee Nipper 	switch (ret) {
206679b3a418SLee Nipper 	case 0:
206779b3a418SLee Nipper 		break;
206879b3a418SLee Nipper 	case -EINPROGRESS:
206979b3a418SLee Nipper 	case -EBUSY:
207079b3a418SLee Nipper 		ret = wait_for_completion_interruptible(
207179b3a418SLee Nipper 			&hresult.completion);
207279b3a418SLee Nipper 		if (!ret)
207379b3a418SLee Nipper 			ret = hresult.err;
207479b3a418SLee Nipper 		break;
207579b3a418SLee Nipper 	default:
207679b3a418SLee Nipper 		break;
207779b3a418SLee Nipper 	}
207879b3a418SLee Nipper 	ahash_request_free(req);
207979b3a418SLee Nipper 
208079b3a418SLee Nipper 	return ret;
208179b3a418SLee Nipper }
208279b3a418SLee Nipper 
208379b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
208479b3a418SLee Nipper 			unsigned int keylen)
208579b3a418SLee Nipper {
208679b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
208779b3a418SLee Nipper 	unsigned int blocksize =
208879b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
208979b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
209079b3a418SLee Nipper 	unsigned int keysize = keylen;
209179b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
209279b3a418SLee Nipper 	int ret;
209379b3a418SLee Nipper 
209479b3a418SLee Nipper 	if (keylen <= blocksize)
209579b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
209679b3a418SLee Nipper 	else {
209779b3a418SLee Nipper 		/* Must get the hash of the long key */
209879b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
209979b3a418SLee Nipper 
210079b3a418SLee Nipper 		if (ret) {
210179b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
210279b3a418SLee Nipper 			return -EINVAL;
210379b3a418SLee Nipper 		}
210479b3a418SLee Nipper 
210579b3a418SLee Nipper 		keysize = digestsize;
210679b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
210779b3a418SLee Nipper 	}
210879b3a418SLee Nipper 
210979b3a418SLee Nipper 	ctx->keylen = keysize;
211079b3a418SLee Nipper 
211179b3a418SLee Nipper 	return 0;
211279b3a418SLee Nipper }
211379b3a418SLee Nipper 
211479b3a418SLee Nipper 
21159c4a7965SKim Phillips struct talitos_alg_template {
2116d5e4aaefSLee Nipper 	u32 type;
2117b0057763SLEROY Christophe 	u32 priority;
2118d5e4aaefSLee Nipper 	union {
2119d5e4aaefSLee Nipper 		struct crypto_alg crypto;
2120acbf7c62SLee Nipper 		struct ahash_alg hash;
2121aeb4c132SHerbert Xu 		struct aead_alg aead;
2122d5e4aaefSLee Nipper 	} alg;
21239c4a7965SKim Phillips 	__be32 desc_hdr_template;
21249c4a7965SKim Phillips };
21259c4a7965SKim Phillips 
21269c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2127991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2128d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2129aeb4c132SHerbert Xu 		.alg.aead = {
2130aeb4c132SHerbert Xu 			.base = {
213156af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2132aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2133aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
213456af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2135aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2136aeb4c132SHerbert Xu 			},
21373952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
21383952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
21399c4a7965SKim Phillips 		},
21409c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
21419c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
21429c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
21439c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
21449c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
21459c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
21469c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
214770bcaca7SLee Nipper 	},
2148d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
21497405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
21507405c8d7SLEROY Christophe 		.alg.aead = {
21517405c8d7SLEROY Christophe 			.base = {
21527405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
21537405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
21547405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
21557405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
21567405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
21577405c8d7SLEROY Christophe 			},
21587405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
21597405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
21607405c8d7SLEROY Christophe 		},
21617405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
21627405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
21637405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
21647405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
21657405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
21667405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
21677405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
21687405c8d7SLEROY Christophe 	},
21697405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2170aeb4c132SHerbert Xu 		.alg.aead = {
2171aeb4c132SHerbert Xu 			.base = {
2172aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2173aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2174aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2175aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
217656af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2177aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2178aeb4c132SHerbert Xu 			},
21793952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
21803952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
218170bcaca7SLee Nipper 		},
218270bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
218370bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
218470bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
218570bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
218670bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
218770bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
218870bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
218970bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
21903952f17eSLee Nipper 	},
2191d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
21927405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
21937405c8d7SLEROY Christophe 		.alg.aead = {
21947405c8d7SLEROY Christophe 			.base = {
21957405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),"
21967405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
21977405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
21987405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
21997405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
22007405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22017405c8d7SLEROY Christophe 			},
22027405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
22037405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
22047405c8d7SLEROY Christophe 		},
22057405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
22067405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
22077405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
22087405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
22097405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
22107405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
22117405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
22127405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
22137405c8d7SLEROY Christophe 	},
22147405c8d7SLEROY Christophe 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2215aeb4c132SHerbert Xu 		.alg.aead = {
2216aeb4c132SHerbert Xu 			.base = {
2217357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2218aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2219aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2220357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2221aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2222aeb4c132SHerbert Xu 			},
2223357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2224357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2225357fb605SHoria Geanta 		},
2226357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2227357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2228357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2229357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2230357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2231357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2232357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2233357fb605SHoria Geanta 	},
2234357fb605SHoria Geanta 	{       .type = CRYPTO_ALG_TYPE_AEAD,
22357405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22367405c8d7SLEROY Christophe 		.alg.aead = {
22377405c8d7SLEROY Christophe 			.base = {
22387405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
22397405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
22407405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
22417405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
22427405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22437405c8d7SLEROY Christophe 			},
22447405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
22457405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
22467405c8d7SLEROY Christophe 		},
22477405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
22487405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
22497405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
22507405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
22517405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
22527405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
22537405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
22547405c8d7SLEROY Christophe 	},
22557405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2256aeb4c132SHerbert Xu 		.alg.aead = {
2257aeb4c132SHerbert Xu 			.base = {
2258aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2259aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2260aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2261aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2262357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2263aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2264aeb4c132SHerbert Xu 			},
2265357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2266357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2267357fb605SHoria Geanta 		},
2268357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2269357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2270357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2271357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2272357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2273357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2274357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2275357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2276357fb605SHoria Geanta 	},
2277357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
22787405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22797405c8d7SLEROY Christophe 		.alg.aead = {
22807405c8d7SLEROY Christophe 			.base = {
22817405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),"
22827405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
22837405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
22847405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
22857405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
22867405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22877405c8d7SLEROY Christophe 			},
22887405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
22897405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
22907405c8d7SLEROY Christophe 		},
22917405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
22927405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
22937405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
22947405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
22957405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
22967405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
22977405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
22987405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
22997405c8d7SLEROY Christophe 	},
23007405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2301aeb4c132SHerbert Xu 		.alg.aead = {
2302aeb4c132SHerbert Xu 			.base = {
230356af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2304aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2305aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
230656af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2307aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2308aeb4c132SHerbert Xu 			},
23093952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
23103952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
23113952f17eSLee Nipper 		},
23123952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23133952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
23143952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
23153952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
23163952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
23173952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
23183952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
23193952f17eSLee Nipper 	},
2320d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23217405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23227405c8d7SLEROY Christophe 		.alg.aead = {
23237405c8d7SLEROY Christophe 			.base = {
23247405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
23257405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
23267405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
23277405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
23287405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23297405c8d7SLEROY Christophe 			},
23307405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
23317405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
23327405c8d7SLEROY Christophe 		},
23337405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23347405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23357405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23367405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23377405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23387405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23397405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
23407405c8d7SLEROY Christophe 	},
23417405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2342aeb4c132SHerbert Xu 		.alg.aead = {
2343aeb4c132SHerbert Xu 			.base = {
2344aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2345aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2346aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2347aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
234856af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2349aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2350aeb4c132SHerbert Xu 			},
23513952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
23523952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
23533952f17eSLee Nipper 		},
23543952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23553952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
23563952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
23573952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
23583952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
23593952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
23603952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
23613952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
23623952f17eSLee Nipper 	},
2363d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23647405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23657405c8d7SLEROY Christophe 		.alg.aead = {
23667405c8d7SLEROY Christophe 			.base = {
23677405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),"
23687405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
23697405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
23707405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
23717405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
23727405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23737405c8d7SLEROY Christophe 			},
23747405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
23757405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
23767405c8d7SLEROY Christophe 		},
23777405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23787405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
23797405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
23807405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
23817405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23827405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23837405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23847405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
23857405c8d7SLEROY Christophe 	},
23867405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2387aeb4c132SHerbert Xu 		.alg.aead = {
2388aeb4c132SHerbert Xu 			.base = {
2389357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2390aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2391aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2392357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2393aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2394aeb4c132SHerbert Xu 			},
2395357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2396357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2397357fb605SHoria Geanta 		},
2398357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2399357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2400357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2401357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2402357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2403357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2404357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2405357fb605SHoria Geanta 	},
2406357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2407aeb4c132SHerbert Xu 		.alg.aead = {
2408aeb4c132SHerbert Xu 			.base = {
2409aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2410aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2411aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2412aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2413357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2414aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2415aeb4c132SHerbert Xu 			},
2416357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2417357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2418357fb605SHoria Geanta 		},
2419357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2420357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2421357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2422357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2423357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2424357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2425357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2426357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2427357fb605SHoria Geanta 	},
2428357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2429aeb4c132SHerbert Xu 		.alg.aead = {
2430aeb4c132SHerbert Xu 			.base = {
2431357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2432aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2433aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2434357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2435aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2436aeb4c132SHerbert Xu 			},
2437357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2438357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2439357fb605SHoria Geanta 		},
2440357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2441357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2442357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2443357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2444357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2445357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2446357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2447357fb605SHoria Geanta 	},
2448357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2449aeb4c132SHerbert Xu 		.alg.aead = {
2450aeb4c132SHerbert Xu 			.base = {
2451aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2452aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2453aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2454aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2455357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2456aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2457aeb4c132SHerbert Xu 			},
2458357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2459357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2460357fb605SHoria Geanta 		},
2461357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2462357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2463357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2464357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2465357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2466357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2467357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2468357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2469357fb605SHoria Geanta 	},
2470357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2471aeb4c132SHerbert Xu 		.alg.aead = {
2472aeb4c132SHerbert Xu 			.base = {
247356af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2474aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2475aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
247656af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2477aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2478aeb4c132SHerbert Xu 			},
24793952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
24803952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
24813952f17eSLee Nipper 		},
24823952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24833952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
24843952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
24853952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
24863952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
24873952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
24883952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
24893952f17eSLee Nipper 	},
2490d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24917405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24927405c8d7SLEROY Christophe 		.alg.aead = {
24937405c8d7SLEROY Christophe 			.base = {
24947405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(aes))",
24957405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
24967405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
24977405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
24987405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24997405c8d7SLEROY Christophe 			},
25007405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
25017405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
25027405c8d7SLEROY Christophe 		},
25037405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25047405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
25057405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
25067405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25077405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25087405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25097405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25107405c8d7SLEROY Christophe 	},
25117405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2512aeb4c132SHerbert Xu 		.alg.aead = {
2513aeb4c132SHerbert Xu 			.base = {
251456af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2515aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2516aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
251756af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2518aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2519aeb4c132SHerbert Xu 			},
25203952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
25213952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
25223952f17eSLee Nipper 		},
25233952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25243952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
25253952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
25263952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
25273952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25283952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25293952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25303952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25314de9d0b5SLee Nipper 	},
25327405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25337405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25347405c8d7SLEROY Christophe 		.alg.aead = {
25357405c8d7SLEROY Christophe 			.base = {
25367405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
25377405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
25387405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
25397405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
25407405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25417405c8d7SLEROY Christophe 			},
25427405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
25437405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
25447405c8d7SLEROY Christophe 		},
25457405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25467405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
25477405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
25487405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
25497405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25507405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25517405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25527405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25537405c8d7SLEROY Christophe 	},
25544de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2555d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2556d5e4aaefSLee Nipper 		.alg.crypto = {
25575e75ae1bSLEROY Christophe 			.cra_name = "ecb(aes)",
25585e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-aes-talitos",
25595e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
25605e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
25615e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
25625e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
25635e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
25645e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
25655e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
25665e75ae1bSLEROY Christophe 			}
25675e75ae1bSLEROY Christophe 		},
25685e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
25695e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
25705e75ae1bSLEROY Christophe 	},
25715e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
25725e75ae1bSLEROY Christophe 		.alg.crypto = {
25734de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
25744de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
25754de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
25764de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
25774de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
25784de9d0b5SLee Nipper 			.cra_ablkcipher = {
25794de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
25804de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
25814de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
25824de9d0b5SLee Nipper 			}
25834de9d0b5SLee Nipper 		},
25844de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
25854de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
25864de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
25874de9d0b5SLee Nipper 	},
2588d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2589d5e4aaefSLee Nipper 		.alg.crypto = {
25905e75ae1bSLEROY Christophe 			.cra_name = "ctr(aes)",
25915e75ae1bSLEROY Christophe 			.cra_driver_name = "ctr-aes-talitos",
25925e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
25935e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
25945e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
25955e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
25965e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
25975e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
25985e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
25995e75ae1bSLEROY Christophe 			}
26005e75ae1bSLEROY Christophe 		},
260170d355ccSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
26025e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
26035e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
26045e75ae1bSLEROY Christophe 	},
26055e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26065e75ae1bSLEROY Christophe 		.alg.crypto = {
26075e75ae1bSLEROY Christophe 			.cra_name = "ecb(des)",
26085e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-des-talitos",
26095e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
26105e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26115e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26125e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26135e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
26145e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
26155e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
26165e75ae1bSLEROY Christophe 			}
26175e75ae1bSLEROY Christophe 		},
26185e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26195e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
26205e75ae1bSLEROY Christophe 	},
26215e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26225e75ae1bSLEROY Christophe 		.alg.crypto = {
26235e75ae1bSLEROY Christophe 			.cra_name = "cbc(des)",
26245e75ae1bSLEROY Christophe 			.cra_driver_name = "cbc-des-talitos",
26255e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
26265e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26275e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26285e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26295e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
26305e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
26315e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
26325e75ae1bSLEROY Christophe 			}
26335e75ae1bSLEROY Christophe 		},
26345e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26355e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
26365e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
26375e75ae1bSLEROY Christophe 	},
26385e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26395e75ae1bSLEROY Christophe 		.alg.crypto = {
26405e75ae1bSLEROY Christophe 			.cra_name = "ecb(des3_ede)",
26415e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-3des-talitos",
26425e75ae1bSLEROY Christophe 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26435e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26445e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26455e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26465e75ae1bSLEROY Christophe 				.min_keysize = DES3_EDE_KEY_SIZE,
26475e75ae1bSLEROY Christophe 				.max_keysize = DES3_EDE_KEY_SIZE,
26485e75ae1bSLEROY Christophe 				.ivsize = DES3_EDE_BLOCK_SIZE,
26495e75ae1bSLEROY Christophe 			}
26505e75ae1bSLEROY Christophe 		},
26515e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26525e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
26535e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
26545e75ae1bSLEROY Christophe 	},
26555e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26565e75ae1bSLEROY Christophe 		.alg.crypto = {
26574de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
26584de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
26594de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26604de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26614de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
26624de9d0b5SLee Nipper 			.cra_ablkcipher = {
26634de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
26644de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
26654de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
26664de9d0b5SLee Nipper 			}
26674de9d0b5SLee Nipper 		},
26684de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26694de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
26704de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
26714de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2672497f2e6bSLee Nipper 	},
2673497f2e6bSLee Nipper 	/* AHASH algorithms. */
2674497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2675497f2e6bSLee Nipper 		.alg.hash = {
2676497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
26773639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2678497f2e6bSLee Nipper 			.halg.base = {
2679497f2e6bSLee Nipper 				.cra_name = "md5",
2680497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2681b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2682497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2683497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
26849c4a7965SKim Phillips 			}
2685497f2e6bSLee Nipper 		},
2686497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2687497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2688497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2689497f2e6bSLee Nipper 	},
2690497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2691497f2e6bSLee Nipper 		.alg.hash = {
2692497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
26933639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2694497f2e6bSLee Nipper 			.halg.base = {
2695497f2e6bSLee Nipper 				.cra_name = "sha1",
2696497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2697497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2698497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2699497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2700497f2e6bSLee Nipper 			}
2701497f2e6bSLee Nipper 		},
2702497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2703497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2704497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2705497f2e6bSLee Nipper 	},
2706497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2707497f2e6bSLee Nipper 		.alg.hash = {
270860f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
27093639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
271060f208d7SKim Phillips 			.halg.base = {
271160f208d7SKim Phillips 				.cra_name = "sha224",
271260f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
271360f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
271460f208d7SKim Phillips 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
271560f208d7SKim Phillips 					     CRYPTO_ALG_ASYNC,
271660f208d7SKim Phillips 			}
271760f208d7SKim Phillips 		},
271860f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
271960f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
272060f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
272160f208d7SKim Phillips 	},
272260f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
272360f208d7SKim Phillips 		.alg.hash = {
2724497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
27253639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2726497f2e6bSLee Nipper 			.halg.base = {
2727497f2e6bSLee Nipper 				.cra_name = "sha256",
2728497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2729497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2730497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2731497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2732497f2e6bSLee Nipper 			}
2733497f2e6bSLee Nipper 		},
2734497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2735497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2736497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2737497f2e6bSLee Nipper 	},
2738497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2739497f2e6bSLee Nipper 		.alg.hash = {
2740497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
27413639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2742497f2e6bSLee Nipper 			.halg.base = {
2743497f2e6bSLee Nipper 				.cra_name = "sha384",
2744497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2745497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
2746497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2747497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2748497f2e6bSLee Nipper 			}
2749497f2e6bSLee Nipper 		},
2750497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2751497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2752497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2753497f2e6bSLee Nipper 	},
2754497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2755497f2e6bSLee Nipper 		.alg.hash = {
2756497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
27573639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2758497f2e6bSLee Nipper 			.halg.base = {
2759497f2e6bSLee Nipper 				.cra_name = "sha512",
2760497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2761497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
2762497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2763497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2764497f2e6bSLee Nipper 			}
2765497f2e6bSLee Nipper 		},
2766497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2767497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2768497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2769497f2e6bSLee Nipper 	},
277079b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
277179b3a418SLee Nipper 		.alg.hash = {
277279b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
27733639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
277479b3a418SLee Nipper 			.halg.base = {
277579b3a418SLee Nipper 				.cra_name = "hmac(md5)",
277679b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2777b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
277879b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
277979b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
278079b3a418SLee Nipper 			}
278179b3a418SLee Nipper 		},
278279b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
278379b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
278479b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
278579b3a418SLee Nipper 	},
278679b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
278779b3a418SLee Nipper 		.alg.hash = {
278879b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
27893639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
279079b3a418SLee Nipper 			.halg.base = {
279179b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
279279b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
279379b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
279479b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
279579b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
279679b3a418SLee Nipper 			}
279779b3a418SLee Nipper 		},
279879b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
279979b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
280079b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
280179b3a418SLee Nipper 	},
280279b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
280379b3a418SLee Nipper 		.alg.hash = {
280479b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
28053639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
280679b3a418SLee Nipper 			.halg.base = {
280779b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
280879b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
280979b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
281079b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
281179b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
281279b3a418SLee Nipper 			}
281379b3a418SLee Nipper 		},
281479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
281579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
281679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
281779b3a418SLee Nipper 	},
281879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
281979b3a418SLee Nipper 		.alg.hash = {
282079b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
28213639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
282279b3a418SLee Nipper 			.halg.base = {
282379b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
282479b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
282579b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
282679b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
282779b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
282879b3a418SLee Nipper 			}
282979b3a418SLee Nipper 		},
283079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
283179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
283279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
283379b3a418SLee Nipper 	},
283479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
283579b3a418SLee Nipper 		.alg.hash = {
283679b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
28373639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
283879b3a418SLee Nipper 			.halg.base = {
283979b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
284079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
284179b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
284279b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
284379b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
284479b3a418SLee Nipper 			}
284579b3a418SLee Nipper 		},
284679b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
284779b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
284879b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
284979b3a418SLee Nipper 	},
285079b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
285179b3a418SLee Nipper 		.alg.hash = {
285279b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
28533639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
285479b3a418SLee Nipper 			.halg.base = {
285579b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
285679b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
285779b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
285879b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
285979b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
286079b3a418SLee Nipper 			}
286179b3a418SLee Nipper 		},
286279b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
286379b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
286479b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
286579b3a418SLee Nipper 	}
28669c4a7965SKim Phillips };
28679c4a7965SKim Phillips 
28689c4a7965SKim Phillips struct talitos_crypto_alg {
28699c4a7965SKim Phillips 	struct list_head entry;
28709c4a7965SKim Phillips 	struct device *dev;
2871acbf7c62SLee Nipper 	struct talitos_alg_template algt;
28729c4a7965SKim Phillips };
28739c4a7965SKim Phillips 
287489d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
287589d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
28769c4a7965SKim Phillips {
28775228f0f7SKim Phillips 	struct talitos_private *priv;
28789c4a7965SKim Phillips 
28799c4a7965SKim Phillips 	/* update context with ptr to dev */
28809c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
288119bbbc63SKim Phillips 
28825228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
28835228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
28845228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
28855228f0f7SKim Phillips 		  (priv->num_channels - 1);
28865228f0f7SKim Phillips 
28879c4a7965SKim Phillips 	/* copy descriptor header template value */
2888acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
28899c4a7965SKim Phillips 
2890602dba5aSKim Phillips 	/* select done notification */
2891602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
2892602dba5aSKim Phillips 
2893497f2e6bSLee Nipper 	return 0;
2894497f2e6bSLee Nipper }
2895497f2e6bSLee Nipper 
289689d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm)
289789d124cbSJonas Eymann {
289889d124cbSJonas Eymann 	struct crypto_alg *alg = tfm->__crt_alg;
289989d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
290089d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
290189d124cbSJonas Eymann 
290289d124cbSJonas Eymann 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
290389d124cbSJonas Eymann 		talitos_alg = container_of(__crypto_ahash_alg(alg),
290489d124cbSJonas Eymann 					   struct talitos_crypto_alg,
290589d124cbSJonas Eymann 					   algt.alg.hash);
290689d124cbSJonas Eymann 	else
290789d124cbSJonas Eymann 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
290889d124cbSJonas Eymann 					   algt.alg.crypto);
290989d124cbSJonas Eymann 
291089d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
291189d124cbSJonas Eymann }
291289d124cbSJonas Eymann 
2913aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
2914497f2e6bSLee Nipper {
291589d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
291689d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
291789d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
291889d124cbSJonas Eymann 
291989d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
292089d124cbSJonas Eymann 				   algt.alg.aead);
292189d124cbSJonas Eymann 
292289d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
29239c4a7965SKim Phillips }
29249c4a7965SKim Phillips 
2925497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
2926497f2e6bSLee Nipper {
2927497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
2928497f2e6bSLee Nipper 
2929497f2e6bSLee Nipper 	talitos_cra_init(tfm);
2930497f2e6bSLee Nipper 
2931497f2e6bSLee Nipper 	ctx->keylen = 0;
2932497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
2933497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
2934497f2e6bSLee Nipper 
2935497f2e6bSLee Nipper 	return 0;
2936497f2e6bSLee Nipper }
2937497f2e6bSLee Nipper 
29389c4a7965SKim Phillips /*
29399c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
29409c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
29419c4a7965SKim Phillips  * capabilities description provided in the device tree node.
29429c4a7965SKim Phillips  */
29439c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
29449c4a7965SKim Phillips {
29459c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
29469c4a7965SKim Phillips 	int ret;
29479c4a7965SKim Phillips 
29489c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
29499c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
29509c4a7965SKim Phillips 
29519c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
29529c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
29539c4a7965SKim Phillips 		              & priv->exec_units);
29549c4a7965SKim Phillips 
29559c4a7965SKim Phillips 	return ret;
29569c4a7965SKim Phillips }
29579c4a7965SKim Phillips 
29582dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
29599c4a7965SKim Phillips {
29609c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
29619c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
29629c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
29639c4a7965SKim Phillips 	int i;
29649c4a7965SKim Phillips 
29659c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
2966acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
2967acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
2968acbf7c62SLee Nipper 			break;
2969aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
2970aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
2971acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
2972acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
2973acbf7c62SLee Nipper 			break;
2974acbf7c62SLee Nipper 		}
29759c4a7965SKim Phillips 		list_del(&t_alg->entry);
29769c4a7965SKim Phillips 	}
29779c4a7965SKim Phillips 
29789c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
29799c4a7965SKim Phillips 		talitos_unregister_rng(dev);
29809c4a7965SKim Phillips 
2981c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
29822cdba3cfSKim Phillips 		if (priv->irq[i]) {
2983c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
2984c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
29859c4a7965SKim Phillips 		}
29869c4a7965SKim Phillips 
2987c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
29882cdba3cfSKim Phillips 	if (priv->irq[1])
2989c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
29909c4a7965SKim Phillips 
29919c4a7965SKim Phillips 	return 0;
29929c4a7965SKim Phillips }
29939c4a7965SKim Phillips 
29949c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
29959c4a7965SKim Phillips 						    struct talitos_alg_template
29969c4a7965SKim Phillips 						           *template)
29979c4a7965SKim Phillips {
299860f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
29999c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
30009c4a7965SKim Phillips 	struct crypto_alg *alg;
30019c4a7965SKim Phillips 
300224b92ff2SLEROY Christophe 	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
300324b92ff2SLEROY Christophe 			     GFP_KERNEL);
30049c4a7965SKim Phillips 	if (!t_alg)
30059c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
30069c4a7965SKim Phillips 
3007acbf7c62SLee Nipper 	t_alg->algt = *template;
3008acbf7c62SLee Nipper 
3009acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
3010acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
3011497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
3012497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
3013d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
3014b286e003SKim Phillips 		alg->cra_ablkcipher.setkey = ablkcipher_setkey;
3015b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
3016b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
3017b286e003SKim Phillips 		alg->cra_ablkcipher.geniv = "eseqiv";
3018497f2e6bSLee Nipper 		break;
3019acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
3020aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
3021aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
3022aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.setkey = aead_setkey;
3023aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
3024aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
30256cda075aSLEROY Christophe 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
30266cda075aSLEROY Christophe 		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
302724b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
30286cda075aSLEROY Christophe 			return ERR_PTR(-ENOTSUPP);
30296cda075aSLEROY Christophe 		}
3030acbf7c62SLee Nipper 		break;
3031acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
3032acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
3033497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
3034d4cd3283SKim Phillips 		alg->cra_type = &crypto_ahash_type;
3035b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
3036b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
3037b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
3038b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
3039b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
304056136631SLEROY Christophe 		if (!strncmp(alg->cra_name, "hmac", 4))
3041b286e003SKim Phillips 			t_alg->algt.alg.hash.setkey = ahash_setkey;
30423639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
30433639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
3044b286e003SKim Phillips 
304579b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
30460b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
304724b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
304879b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
30490b2730d8SKim Phillips 		}
305060f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
305179b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
305279b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
305360f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
305460f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
305560f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
305660f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
305760f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
305860f208d7SKim Phillips 		}
3059497f2e6bSLee Nipper 		break;
30601d11911aSKim Phillips 	default:
30611d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
306224b92ff2SLEROY Christophe 		devm_kfree(dev, t_alg);
30631d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
3064acbf7c62SLee Nipper 	}
30659c4a7965SKim Phillips 
30669c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
3067b0057763SLEROY Christophe 	if (t_alg->algt.priority)
3068b0057763SLEROY Christophe 		alg->cra_priority = t_alg->algt.priority;
3069b0057763SLEROY Christophe 	else
30709c4a7965SKim Phillips 		alg->cra_priority = TALITOS_CRA_PRIORITY;
30719c4a7965SKim Phillips 	alg->cra_alignmask = 0;
30729c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
3073d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
30749c4a7965SKim Phillips 
30759c4a7965SKim Phillips 	t_alg->dev = dev;
30769c4a7965SKim Phillips 
30779c4a7965SKim Phillips 	return t_alg;
30789c4a7965SKim Phillips }
30799c4a7965SKim Phillips 
3080c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
3081c3e337f8SKim Phillips {
3082c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
3083c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
3084c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3085c3e337f8SKim Phillips 	int err;
3086dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3087c3e337f8SKim Phillips 
3088c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
30892cdba3cfSKim Phillips 	if (!priv->irq[0]) {
3090c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
3091c3e337f8SKim Phillips 		return -EINVAL;
3092c3e337f8SKim Phillips 	}
3093dd3c0987SLEROY Christophe 	if (is_sec1) {
3094dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
3095dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
3096dd3c0987SLEROY Christophe 		goto primary_out;
3097dd3c0987SLEROY Christophe 	}
3098c3e337f8SKim Phillips 
3099c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
3100c3e337f8SKim Phillips 
3101c3e337f8SKim Phillips 	/* get the primary irq line */
31022cdba3cfSKim Phillips 	if (!priv->irq[1]) {
3103dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
3104c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
3105c3e337f8SKim Phillips 		goto primary_out;
3106c3e337f8SKim Phillips 	}
3107c3e337f8SKim Phillips 
3108dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
3109c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3110c3e337f8SKim Phillips 	if (err)
3111c3e337f8SKim Phillips 		goto primary_out;
3112c3e337f8SKim Phillips 
3113c3e337f8SKim Phillips 	/* get the secondary irq line */
3114dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
3115c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3116c3e337f8SKim Phillips 	if (err) {
3117c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
3118c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
31192cdba3cfSKim Phillips 		priv->irq[1] = 0;
3120c3e337f8SKim Phillips 	}
3121c3e337f8SKim Phillips 
3122c3e337f8SKim Phillips 	return err;
3123c3e337f8SKim Phillips 
3124c3e337f8SKim Phillips primary_out:
3125c3e337f8SKim Phillips 	if (err) {
3126c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
3127c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
31282cdba3cfSKim Phillips 		priv->irq[0] = 0;
3129c3e337f8SKim Phillips 	}
3130c3e337f8SKim Phillips 
3131c3e337f8SKim Phillips 	return err;
3132c3e337f8SKim Phillips }
3133c3e337f8SKim Phillips 
31341c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
31359c4a7965SKim Phillips {
31369c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
313761c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
31389c4a7965SKim Phillips 	struct talitos_private *priv;
31399c4a7965SKim Phillips 	int i, err;
31405fa7fa14SLEROY Christophe 	int stride;
3141fd5ea7f0SLEROY Christophe 	struct resource *res;
31429c4a7965SKim Phillips 
314324b92ff2SLEROY Christophe 	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
31449c4a7965SKim Phillips 	if (!priv)
31459c4a7965SKim Phillips 		return -ENOMEM;
31469c4a7965SKim Phillips 
3147f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
3148f3de9cb1SKevin Hao 
31499c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
31509c4a7965SKim Phillips 
31519c4a7965SKim Phillips 	priv->ofdev = ofdev;
31529c4a7965SKim Phillips 
3153511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
3154511d63cbSHoria Geanta 
3155fd5ea7f0SLEROY Christophe 	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
3156fd5ea7f0SLEROY Christophe 	if (!res)
3157fd5ea7f0SLEROY Christophe 		return -ENXIO;
3158fd5ea7f0SLEROY Christophe 	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
31599c4a7965SKim Phillips 	if (!priv->reg) {
31609c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
31619c4a7965SKim Phillips 		err = -ENOMEM;
31629c4a7965SKim Phillips 		goto err_out;
31639c4a7965SKim Phillips 	}
31649c4a7965SKim Phillips 
31659c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
3166fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
3167fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
3168fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
3169fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,descriptor-types-mask",
3170fa14c6cfSLEROY Christophe 			     &priv->desc_types);
31719c4a7965SKim Phillips 
31729c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
31739c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
31749c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
31759c4a7965SKim Phillips 		err = -EINVAL;
31769c4a7965SKim Phillips 		goto err_out;
31779c4a7965SKim Phillips 	}
31789c4a7965SKim Phillips 
3179f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3180f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3181f3c85bc1SLee Nipper 
3182fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
318360f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
318479b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
318579b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3186fe5720e2SKim Phillips 
318721590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
318821590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
318921590888SLEROY Christophe 
31905fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
31915fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
31925fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
31935fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
31945fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
31955fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
31965fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
31975fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
31985fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
31995fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
32005fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
32015fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
32025fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
32035fa7fa14SLEROY Christophe 	} else {
32045fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
32055fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
32065fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
32075fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
32085fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
32095fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
32105fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
32115fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
32125fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
32135fa7fa14SLEROY Christophe 	}
32145fa7fa14SLEROY Christophe 
3215dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3216dd3c0987SLEROY Christophe 	if (err)
3217dd3c0987SLEROY Christophe 		goto err_out;
3218dd3c0987SLEROY Christophe 
3219dd3c0987SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0")) {
32209c02e285SLEROY Christophe 		if (priv->num_channels == 1)
32219c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
32229c02e285SLEROY Christophe 				     (unsigned long)dev);
32239c02e285SLEROY Christophe 		else
3224dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3225dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3226dd3c0987SLEROY Christophe 	} else {
32279c02e285SLEROY Christophe 		if (priv->irq[1]) {
3228dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3229dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3230dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3231dd3c0987SLEROY Christophe 				     (unsigned long)dev);
32329c02e285SLEROY Christophe 		} else if (priv->num_channels == 1) {
32339c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
32349c02e285SLEROY Christophe 				     (unsigned long)dev);
32359c02e285SLEROY Christophe 		} else {
32369c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
32379c02e285SLEROY Christophe 				     (unsigned long)dev);
3238dd3c0987SLEROY Christophe 		}
3239dd3c0987SLEROY Christophe 	}
3240dd3c0987SLEROY Christophe 
324124b92ff2SLEROY Christophe 	priv->chan = devm_kzalloc(dev, sizeof(struct talitos_channel) *
32424b992628SKim Phillips 				       priv->num_channels, GFP_KERNEL);
32434b992628SKim Phillips 	if (!priv->chan) {
32444b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
32459c4a7965SKim Phillips 		err = -ENOMEM;
32469c4a7965SKim Phillips 		goto err_out;
32479c4a7965SKim Phillips 	}
32489c4a7965SKim Phillips 
3249f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3250f641ddddSMartin Hicks 
3251c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
32525fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
32532cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3254c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3255ad42d5fcSKim Phillips 
32564b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
32574b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
32589c4a7965SKim Phillips 
325924b92ff2SLEROY Christophe 		priv->chan[i].fifo = devm_kzalloc(dev,
326024b92ff2SLEROY Christophe 						sizeof(struct talitos_request) *
32619c4a7965SKim Phillips 						priv->fifo_len, GFP_KERNEL);
32624b992628SKim Phillips 		if (!priv->chan[i].fifo) {
32639c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
32649c4a7965SKim Phillips 			err = -ENOMEM;
32659c4a7965SKim Phillips 			goto err_out;
32669c4a7965SKim Phillips 		}
32679c4a7965SKim Phillips 
32684b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
32694b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3270f641ddddSMartin Hicks 	}
32719c4a7965SKim Phillips 
327281eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
327381eb024cSKim Phillips 
32749c4a7965SKim Phillips 	/* reset and initialize the h/w */
32759c4a7965SKim Phillips 	err = init_device(dev);
32769c4a7965SKim Phillips 	if (err) {
32779c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
32789c4a7965SKim Phillips 		goto err_out;
32799c4a7965SKim Phillips 	}
32809c4a7965SKim Phillips 
32819c4a7965SKim Phillips 	/* register the RNG, if available */
32829c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
32839c4a7965SKim Phillips 		err = talitos_register_rng(dev);
32849c4a7965SKim Phillips 		if (err) {
32859c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
32869c4a7965SKim Phillips 			goto err_out;
32879c4a7965SKim Phillips 		} else
32889c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
32899c4a7965SKim Phillips 	}
32909c4a7965SKim Phillips 
32919c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
32929c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
32939c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
32949c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3295aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
32969c4a7965SKim Phillips 
32979c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
32989c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
32999c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
33000b2730d8SKim Phillips 				if (err == -ENOTSUPP)
330179b3a418SLee Nipper 					continue;
33029c4a7965SKim Phillips 				goto err_out;
33039c4a7965SKim Phillips 			}
33049c4a7965SKim Phillips 
3305acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3306acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
3307acbf7c62SLee Nipper 				err = crypto_register_alg(
3308acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
3309aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.crypto;
3310acbf7c62SLee Nipper 				break;
3311aeb4c132SHerbert Xu 
3312aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3313aeb4c132SHerbert Xu 				err = crypto_register_aead(
3314aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3315aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3316aeb4c132SHerbert Xu 				break;
3317aeb4c132SHerbert Xu 
3318acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3319acbf7c62SLee Nipper 				err = crypto_register_ahash(
3320acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3321aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3322acbf7c62SLee Nipper 				break;
3323acbf7c62SLee Nipper 			}
33249c4a7965SKim Phillips 			if (err) {
33259c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3326aeb4c132SHerbert Xu 					alg->cra_driver_name);
332724b92ff2SLEROY Christophe 				devm_kfree(dev, t_alg);
3328991155baSHoria Geanta 			} else
33299c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
33309c4a7965SKim Phillips 		}
33319c4a7965SKim Phillips 	}
33325b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
33335b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
33345b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
33359c4a7965SKim Phillips 
33369c4a7965SKim Phillips 	return 0;
33379c4a7965SKim Phillips 
33389c4a7965SKim Phillips err_out:
33399c4a7965SKim Phillips 	talitos_remove(ofdev);
33409c4a7965SKim Phillips 
33419c4a7965SKim Phillips 	return err;
33429c4a7965SKim Phillips }
33439c4a7965SKim Phillips 
33446c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
33450635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
33460635b7dbSLEROY Christophe 	{
33470635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
33480635b7dbSLEROY Christophe 	},
33490635b7dbSLEROY Christophe #endif
33500635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
33519c4a7965SKim Phillips 	{
33529c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
33539c4a7965SKim Phillips 	},
33540635b7dbSLEROY Christophe #endif
33559c4a7965SKim Phillips 	{},
33569c4a7965SKim Phillips };
33579c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
33589c4a7965SKim Phillips 
33591c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
33604018294bSGrant Likely 	.driver = {
33619c4a7965SKim Phillips 		.name = "talitos",
33624018294bSGrant Likely 		.of_match_table = talitos_match,
33634018294bSGrant Likely 	},
33649c4a7965SKim Phillips 	.probe = talitos_probe,
3365596f1034SAl Viro 	.remove = talitos_remove,
33669c4a7965SKim Phillips };
33679c4a7965SKim Phillips 
3368741e8c2dSAxel Lin module_platform_driver(talitos_driver);
33699c4a7965SKim Phillips 
33709c4a7965SKim Phillips MODULE_LICENSE("GPL");
33719c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
33729c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3373