xref: /linux/drivers/crypto/talitos.c (revision ad4cd51fb8375109edb377712b5f9c0c31ece33e)
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);
16337b5e889SLEROY Christophe 	/* enable chaining descriptors */
16437b5e889SLEROY Christophe 	if (is_sec1)
16537b5e889SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
16637b5e889SLEROY Christophe 			  TALITOS_CCCR_LO_NE);
1679c4a7965SKim Phillips 
168fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
169fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
170ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
171fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
172fe5720e2SKim Phillips 
1739c4a7965SKim Phillips 	return 0;
1749c4a7965SKim Phillips }
1759c4a7965SKim Phillips 
1769c4a7965SKim Phillips static int reset_device(struct device *dev)
1779c4a7965SKim Phillips {
1789c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1799c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
180dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
181dd3c0987SLEROY Christophe 	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
1829c4a7965SKim Phillips 
183c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
1849c4a7965SKim Phillips 
185dd3c0987SLEROY Christophe 	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
1869c4a7965SKim Phillips 	       && --timeout)
1879c4a7965SKim Phillips 		cpu_relax();
1889c4a7965SKim Phillips 
1892cdba3cfSKim Phillips 	if (priv->irq[1]) {
190c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
191c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
192c3e337f8SKim Phillips 	}
193c3e337f8SKim Phillips 
1949c4a7965SKim Phillips 	if (timeout == 0) {
1959c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
1969c4a7965SKim Phillips 		return -EIO;
1979c4a7965SKim Phillips 	}
1989c4a7965SKim Phillips 
1999c4a7965SKim Phillips 	return 0;
2009c4a7965SKim Phillips }
2019c4a7965SKim Phillips 
2029c4a7965SKim Phillips /*
2039c4a7965SKim Phillips  * Reset and initialize the device
2049c4a7965SKim Phillips  */
2059c4a7965SKim Phillips static int init_device(struct device *dev)
2069c4a7965SKim Phillips {
2079c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2089c4a7965SKim Phillips 	int ch, err;
209dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2109c4a7965SKim Phillips 
2119c4a7965SKim Phillips 	/*
2129c4a7965SKim Phillips 	 * Master reset
2139c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
2149c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
2159c4a7965SKim Phillips 	 * set bit twice to completely reset
2169c4a7965SKim Phillips 	 */
2179c4a7965SKim Phillips 	err = reset_device(dev);
2189c4a7965SKim Phillips 	if (err)
2199c4a7965SKim Phillips 		return err;
2209c4a7965SKim Phillips 
2219c4a7965SKim Phillips 	err = reset_device(dev);
2229c4a7965SKim Phillips 	if (err)
2239c4a7965SKim Phillips 		return err;
2249c4a7965SKim Phillips 
2259c4a7965SKim Phillips 	/* reset channels */
2269c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
2279c4a7965SKim Phillips 		err = reset_channel(dev, ch);
2289c4a7965SKim Phillips 		if (err)
2299c4a7965SKim Phillips 			return err;
2309c4a7965SKim Phillips 	}
2319c4a7965SKim Phillips 
2329c4a7965SKim Phillips 	/* enable channel done and error interrupts */
233dd3c0987SLEROY Christophe 	if (is_sec1) {
234dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
235dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
236dd3c0987SLEROY Christophe 		/* disable parity error check in DEU (erroneous? test vect.) */
237dd3c0987SLEROY Christophe 		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
238dd3c0987SLEROY Christophe 	} else {
239dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
240dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
241dd3c0987SLEROY Christophe 	}
2429c4a7965SKim Phillips 
243fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
244fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2455fa7fa14SLEROY Christophe 		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
246fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
247fe5720e2SKim Phillips 
2489c4a7965SKim Phillips 	return 0;
2499c4a7965SKim Phillips }
2509c4a7965SKim Phillips 
2519c4a7965SKim Phillips /**
2529c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
2539c4a7965SKim Phillips  * @dev:	the SEC device to be used
2545228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
2559c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
2569c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
2579c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
2589c4a7965SKim Phillips  *
2599c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
2609c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
2619c4a7965SKim Phillips  * for device processing status.
2629c4a7965SKim Phillips  */
263865d5061SHoria Geanta int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2649c4a7965SKim Phillips 		   void (*callback)(struct device *dev,
2659c4a7965SKim Phillips 				    struct talitos_desc *desc,
2669c4a7965SKim Phillips 				    void *context, int error),
2679c4a7965SKim Phillips 		   void *context)
2689c4a7965SKim Phillips {
2699c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2709c4a7965SKim Phillips 	struct talitos_request *request;
2715228f0f7SKim Phillips 	unsigned long flags;
2729c4a7965SKim Phillips 	int head;
2737d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2749c4a7965SKim Phillips 
2754b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2769c4a7965SKim Phillips 
2774b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
278ec6644d6SKim Phillips 		/* h/w fifo is full */
2794b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2809c4a7965SKim Phillips 		return -EAGAIN;
2819c4a7965SKim Phillips 	}
2829c4a7965SKim Phillips 
2834b992628SKim Phillips 	head = priv->chan[ch].head;
2844b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
285ec6644d6SKim Phillips 
2869c4a7965SKim Phillips 	/* map descriptor and save caller data */
2877d607c6aSLEROY Christophe 	if (is_sec1) {
2887d607c6aSLEROY Christophe 		desc->hdr1 = desc->hdr;
2897d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, &desc->hdr1,
2907d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2919c4a7965SKim Phillips 						   DMA_BIDIRECTIONAL);
2927d607c6aSLEROY Christophe 	} else {
2937d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, desc,
2947d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2957d607c6aSLEROY Christophe 						   DMA_BIDIRECTIONAL);
2967d607c6aSLEROY Christophe 	}
2979c4a7965SKim Phillips 	request->callback = callback;
2989c4a7965SKim Phillips 	request->context = context;
2999c4a7965SKim Phillips 
3009c4a7965SKim Phillips 	/* increment fifo head */
3014b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
3029c4a7965SKim Phillips 
3039c4a7965SKim Phillips 	smp_wmb();
3049c4a7965SKim Phillips 	request->desc = desc;
3059c4a7965SKim Phillips 
3069c4a7965SKim Phillips 	/* GO! */
3079c4a7965SKim Phillips 	wmb();
308ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
309ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
310ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
311a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
3129c4a7965SKim Phillips 
3134b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3149c4a7965SKim Phillips 
3159c4a7965SKim Phillips 	return -EINPROGRESS;
3169c4a7965SKim Phillips }
317865d5061SHoria Geanta EXPORT_SYMBOL(talitos_submit);
3189c4a7965SKim Phillips 
3199c4a7965SKim Phillips /*
3209c4a7965SKim Phillips  * process what was done, notify callback of error if not
3219c4a7965SKim Phillips  */
3229c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3239c4a7965SKim Phillips {
3249c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3259c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
3269c4a7965SKim Phillips 	unsigned long flags;
3279c4a7965SKim Phillips 	int tail, status;
3287d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3299c4a7965SKim Phillips 
3304b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3319c4a7965SKim Phillips 
3324b992628SKim Phillips 	tail = priv->chan[ch].tail;
3334b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
3347d607c6aSLEROY Christophe 		__be32 hdr;
3357d607c6aSLEROY Christophe 
3364b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
3379c4a7965SKim Phillips 
3389c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
3399c4a7965SKim Phillips 		rmb();
34037b5e889SLEROY Christophe 		if (!is_sec1)
34137b5e889SLEROY Christophe 			hdr = request->desc->hdr;
34237b5e889SLEROY Christophe 		else if (request->desc->next_desc)
34337b5e889SLEROY Christophe 			hdr = (request->desc + 1)->hdr1;
34437b5e889SLEROY Christophe 		else
34537b5e889SLEROY Christophe 			hdr = request->desc->hdr1;
3467d607c6aSLEROY Christophe 
3477d607c6aSLEROY Christophe 		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3489c4a7965SKim Phillips 			status = 0;
349ca38a814SLee Nipper 		else
3509c4a7965SKim Phillips 			if (!error)
3519c4a7965SKim Phillips 				break;
3529c4a7965SKim Phillips 			else
3539c4a7965SKim Phillips 				status = error;
3549c4a7965SKim Phillips 
3559c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
3567d607c6aSLEROY Christophe 				 TALITOS_DESC_SIZE,
357e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
3589c4a7965SKim Phillips 
3599c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
3609c4a7965SKim Phillips 		saved_req.desc = request->desc;
3619c4a7965SKim Phillips 		saved_req.callback = request->callback;
3629c4a7965SKim Phillips 		saved_req.context = request->context;
3639c4a7965SKim Phillips 
3649c4a7965SKim Phillips 		/* release request entry in fifo */
3659c4a7965SKim Phillips 		smp_wmb();
3669c4a7965SKim Phillips 		request->desc = NULL;
3679c4a7965SKim Phillips 
3689c4a7965SKim Phillips 		/* increment fifo tail */
3694b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3709c4a7965SKim Phillips 
3714b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
372ec6644d6SKim Phillips 
3734b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
374ec6644d6SKim Phillips 
3759c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
3769c4a7965SKim Phillips 				   status);
3779c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
3789c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
3799c4a7965SKim Phillips 			return;
3804b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3814b992628SKim Phillips 		tail = priv->chan[ch].tail;
3829c4a7965SKim Phillips 	}
3839c4a7965SKim Phillips 
3844b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
3859c4a7965SKim Phillips }
3869c4a7965SKim Phillips 
3879c4a7965SKim Phillips /*
3889c4a7965SKim Phillips  * process completed requests for channels that have done status
3899c4a7965SKim Phillips  */
390dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask)				\
391dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data)			\
392dd3c0987SLEROY Christophe {									\
393dd3c0987SLEROY Christophe 	struct device *dev = (struct device *)data;			\
394dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		\
395dd3c0987SLEROY Christophe 	unsigned long flags;						\
396dd3c0987SLEROY Christophe 									\
397dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x10000000)					\
398dd3c0987SLEROY Christophe 		flush_channel(dev, 0, 0, 0);			\
399dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x40000000)					\
400dd3c0987SLEROY Christophe 		flush_channel(dev, 1, 0, 0);			\
401dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00010000)					\
402dd3c0987SLEROY Christophe 		flush_channel(dev, 2, 0, 0);			\
403dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00040000)					\
404dd3c0987SLEROY Christophe 		flush_channel(dev, 3, 0, 0);			\
405dd3c0987SLEROY Christophe 									\
406dd3c0987SLEROY Christophe 	/* At this point, all completed channels have been processed */	\
407dd3c0987SLEROY Christophe 	/* Unmask done interrupts for channels completed later on. */	\
408dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			\
409dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
410dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
411dd3c0987SLEROY Christophe 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
412dd3c0987SLEROY Christophe }
413dd3c0987SLEROY Christophe 
414dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
4159c02e285SLEROY Christophe DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
416dd3c0987SLEROY Christophe 
417dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask)				\
418dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data)			\
419c3e337f8SKim Phillips {									\
420c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
421c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
422511d63cbSHoria Geanta 	unsigned long flags;						\
423c3e337f8SKim Phillips 									\
424c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
425c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
426c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
427c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
428c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
429c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
430c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
431c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
432c3e337f8SKim Phillips 									\
433c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
434c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
435511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
436c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
437dd3c0987SLEROY Christophe 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
438511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4399c4a7965SKim Phillips }
440dd3c0987SLEROY Christophe 
441dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
4429c02e285SLEROY Christophe DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
443dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
444dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4459c4a7965SKim Phillips 
4469c4a7965SKim Phillips /*
4479c4a7965SKim Phillips  * locate current (offending) descriptor
4489c4a7965SKim Phillips  */
4493e721aebSKim Phillips static u32 current_desc_hdr(struct device *dev, int ch)
4509c4a7965SKim Phillips {
4519c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
452b62ffd8cSHoria Geanta 	int tail, iter;
4539c4a7965SKim Phillips 	dma_addr_t cur_desc;
4549c4a7965SKim Phillips 
455b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
456b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4579c4a7965SKim Phillips 
458b62ffd8cSHoria Geanta 	if (!cur_desc) {
459b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
460b62ffd8cSHoria Geanta 		return 0;
461b62ffd8cSHoria Geanta 	}
462b62ffd8cSHoria Geanta 
463b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
464b62ffd8cSHoria Geanta 
465b62ffd8cSHoria Geanta 	iter = tail;
46637b5e889SLEROY Christophe 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc &&
46737b5e889SLEROY Christophe 	       priv->chan[ch].fifo[iter].desc->next_desc != cur_desc) {
468b62ffd8cSHoria Geanta 		iter = (iter + 1) & (priv->fifo_len - 1);
469b62ffd8cSHoria Geanta 		if (iter == tail) {
4709c4a7965SKim Phillips 			dev_err(dev, "couldn't locate current descriptor\n");
4713e721aebSKim Phillips 			return 0;
4729c4a7965SKim Phillips 		}
4739c4a7965SKim Phillips 	}
4749c4a7965SKim Phillips 
47537b5e889SLEROY Christophe 	if (priv->chan[ch].fifo[iter].desc->next_desc == cur_desc)
47637b5e889SLEROY Christophe 		return (priv->chan[ch].fifo[iter].desc + 1)->hdr;
47737b5e889SLEROY Christophe 
478b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
4799c4a7965SKim Phillips }
4809c4a7965SKim Phillips 
4819c4a7965SKim Phillips /*
4829c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
4839c4a7965SKim Phillips  */
4843e721aebSKim Phillips static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
4859c4a7965SKim Phillips {
4869c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
4879c4a7965SKim Phillips 	int i;
4889c4a7965SKim Phillips 
4893e721aebSKim Phillips 	if (!desc_hdr)
490ad42d5fcSKim Phillips 		desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
4913e721aebSKim Phillips 
4923e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
4939c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
4949c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
4955fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR),
4965fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
4979c4a7965SKim Phillips 		break;
4989c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
4999c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
5005fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR),
5015fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
5029c4a7965SKim Phillips 		break;
5039c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
5049c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
5059c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5065fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5075fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5089c4a7965SKim Phillips 		break;
5099c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
5109c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
5115fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR),
5125fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5139c4a7965SKim Phillips 		break;
5149c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
5159c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5165fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5175fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5189c4a7965SKim Phillips 		break;
5199c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
5209c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5215fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR),
5225fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5239c4a7965SKim Phillips 		break;
5249c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
5259c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5265fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5275fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5289c4a7965SKim Phillips 		break;
5299c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
5309c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5315fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5325fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5339c4a7965SKim Phillips 		break;
5349c4a7965SKim Phillips 	}
5359c4a7965SKim Phillips 
5363e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5379c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
5389c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
5399c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5405fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5415fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5429c4a7965SKim Phillips 		break;
5439c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
5449c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5455fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5465fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5479c4a7965SKim Phillips 		break;
5489c4a7965SKim Phillips 	}
5499c4a7965SKim Phillips 
5509c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
5519c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
552ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
553ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5549c4a7965SKim Phillips }
5559c4a7965SKim Phillips 
5569c4a7965SKim Phillips /*
5579c4a7965SKim Phillips  * recover from error interrupts
5589c4a7965SKim Phillips  */
5595e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5609c4a7965SKim Phillips {
5619c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5629c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
563dd3c0987SLEROY Christophe 	int ch, error, reset_dev = 0;
56442e8b0d7SHoria Geant? 	u32 v_lo;
565dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
566dd3c0987SLEROY Christophe 	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5679c4a7965SKim Phillips 
5689c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
5699c4a7965SKim Phillips 		/* skip channels without errors */
570dd3c0987SLEROY Christophe 		if (is_sec1) {
571dd3c0987SLEROY Christophe 			/* bits 29, 31, 17, 19 */
572dd3c0987SLEROY Christophe 			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
573dd3c0987SLEROY Christophe 				continue;
574dd3c0987SLEROY Christophe 		} else {
5759c4a7965SKim Phillips 			if (!(isr & (1 << (ch * 2 + 1))))
5769c4a7965SKim Phillips 				continue;
577dd3c0987SLEROY Christophe 		}
5789c4a7965SKim Phillips 
5799c4a7965SKim Phillips 		error = -EINVAL;
5809c4a7965SKim Phillips 
581ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
5829c4a7965SKim Phillips 
5839c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
5849c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
5859c4a7965SKim Phillips 			error = -EAGAIN;
5869c4a7965SKim Phillips 			reset_ch = 1;
5879c4a7965SKim Phillips 		}
5889c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
5899c4a7965SKim Phillips 			/* h/w dropped descriptor */
5909c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
5919c4a7965SKim Phillips 			error = -EAGAIN;
5929c4a7965SKim Phillips 		}
5939c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
5949c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
5959c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
5964d9b3a5bSColin Ian King 			dev_err(dev, is_sec1 ? "pointer not complete error\n"
597dd3c0987SLEROY Christophe 					     : "s/g data length zero error\n");
5989c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
599dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "parity error\n"
600dd3c0987SLEROY Christophe 					     : "fetch pointer zero error\n");
6019c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
6029c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
6039c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
604dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "static assignment error\n"
605dd3c0987SLEROY Christophe 					     : "invalid exec unit error\n");
6069c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
6073e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
608dd3c0987SLEROY Christophe 		if (!is_sec1) {
6099c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GB)
6109c4a7965SKim Phillips 				dev_err(dev, "gather boundary error\n");
6119c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GRL)
6129c4a7965SKim Phillips 				dev_err(dev, "gather return/length error\n");
6139c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SB)
6149c4a7965SKim Phillips 				dev_err(dev, "scatter boundary error\n");
6159c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SRL)
6169c4a7965SKim Phillips 				dev_err(dev, "scatter return/length error\n");
617dd3c0987SLEROY Christophe 		}
6189c4a7965SKim Phillips 
6199c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
6209c4a7965SKim Phillips 
6219c4a7965SKim Phillips 		if (reset_ch) {
6229c4a7965SKim Phillips 			reset_channel(dev, ch);
6239c4a7965SKim Phillips 		} else {
624ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
625dd3c0987SLEROY Christophe 				  TALITOS2_CCCR_CONT);
626ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
627ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
628dd3c0987SLEROY Christophe 			       TALITOS2_CCCR_CONT) && --timeout)
6299c4a7965SKim Phillips 				cpu_relax();
6309c4a7965SKim Phillips 			if (timeout == 0) {
6319c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
6329c4a7965SKim Phillips 					ch);
6339c4a7965SKim Phillips 				reset_dev = 1;
6349c4a7965SKim Phillips 			}
6359c4a7965SKim Phillips 		}
6369c4a7965SKim Phillips 	}
637dd3c0987SLEROY Christophe 	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
638dd3c0987SLEROY Christophe 	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
639dd3c0987SLEROY Christophe 		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
640dd3c0987SLEROY Christophe 			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
641dd3c0987SLEROY Christophe 				isr, isr_lo);
642dd3c0987SLEROY Christophe 		else
643dd3c0987SLEROY Christophe 			dev_err(dev, "done overflow, internal time out, or "
644dd3c0987SLEROY Christophe 				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6459c4a7965SKim Phillips 
6469c4a7965SKim Phillips 		/* purge request queues */
6479c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
6489c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
6499c4a7965SKim Phillips 
6509c4a7965SKim Phillips 		/* reset and reinitialize the device */
6519c4a7965SKim Phillips 		init_device(dev);
6529c4a7965SKim Phillips 	}
6539c4a7965SKim Phillips }
6549c4a7965SKim Phillips 
655dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
656dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
657dd3c0987SLEROY Christophe {									       \
658dd3c0987SLEROY Christophe 	struct device *dev = data;					       \
659dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
660dd3c0987SLEROY Christophe 	u32 isr, isr_lo;						       \
661dd3c0987SLEROY Christophe 	unsigned long flags;						       \
662dd3c0987SLEROY Christophe 									       \
663dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
664dd3c0987SLEROY Christophe 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
665dd3c0987SLEROY Christophe 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
666dd3c0987SLEROY Christophe 	/* Acknowledge interrupt */					       \
667dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
668dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
669dd3c0987SLEROY Christophe 									       \
670dd3c0987SLEROY Christophe 	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
671dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
672dd3c0987SLEROY Christophe 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
673dd3c0987SLEROY Christophe 	}								       \
674dd3c0987SLEROY Christophe 	else {								       \
675dd3c0987SLEROY Christophe 		if (likely(isr & ch_done_mask)) {			       \
676dd3c0987SLEROY Christophe 			/* mask further done interrupts. */		       \
677dd3c0987SLEROY Christophe 			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
678dd3c0987SLEROY Christophe 			/* done_task will unmask done interrupts at exit */    \
679dd3c0987SLEROY Christophe 			tasklet_schedule(&priv->done_task[tlet]);	       \
680dd3c0987SLEROY Christophe 		}							       \
681dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
682dd3c0987SLEROY Christophe 	}								       \
683dd3c0987SLEROY Christophe 									       \
684dd3c0987SLEROY Christophe 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
685dd3c0987SLEROY Christophe 								IRQ_NONE;      \
686dd3c0987SLEROY Christophe }
687dd3c0987SLEROY Christophe 
688dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
689dd3c0987SLEROY Christophe 
690dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
691dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
692c3e337f8SKim Phillips {									       \
693c3e337f8SKim Phillips 	struct device *dev = data;					       \
694c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
695c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
696511d63cbSHoria Geanta 	unsigned long flags;						       \
697c3e337f8SKim Phillips 									       \
698511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
699c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
700c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
701c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
702c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
703c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
704c3e337f8SKim Phillips 									       \
705511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
706511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
707511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
708511d63cbSHoria Geanta 	}								       \
709511d63cbSHoria Geanta 	else {								       \
710c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
711c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
712c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
713c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
714c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
715c3e337f8SKim Phillips 		}							       \
716511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
717511d63cbSHoria Geanta 	}								       \
718c3e337f8SKim Phillips 									       \
719c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
720c3e337f8SKim Phillips 								IRQ_NONE;      \
7211c2e8811SLee Nipper }
722dd3c0987SLEROY Christophe 
723dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
724dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
725dd3c0987SLEROY Christophe 		       0)
726dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
727dd3c0987SLEROY Christophe 		       1)
7289c4a7965SKim Phillips 
7299c4a7965SKim Phillips /*
7309c4a7965SKim Phillips  * hwrng
7319c4a7965SKim Phillips  */
7329c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
7339c4a7965SKim Phillips {
7349c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7359c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7369c4a7965SKim Phillips 	u32 ofl;
7379c4a7965SKim Phillips 	int i;
7389c4a7965SKim Phillips 
7399c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
7405fa7fa14SLEROY Christophe 		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7419c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
7429c4a7965SKim Phillips 		if (ofl || !wait)
7439c4a7965SKim Phillips 			break;
7449c4a7965SKim Phillips 		udelay(10);
7459c4a7965SKim Phillips 	}
7469c4a7965SKim Phillips 
7479c4a7965SKim Phillips 	return !!ofl;
7489c4a7965SKim Phillips }
7499c4a7965SKim Phillips 
7509c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7519c4a7965SKim Phillips {
7529c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7539c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7549c4a7965SKim Phillips 
7559c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
7565fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7575fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7589c4a7965SKim Phillips 
7599c4a7965SKim Phillips 	return sizeof(u32);
7609c4a7965SKim Phillips }
7619c4a7965SKim Phillips 
7629c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
7639c4a7965SKim Phillips {
7649c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7659c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7669c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
7679c4a7965SKim Phillips 
7685fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7695fa7fa14SLEROY Christophe 	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7705fa7fa14SLEROY Christophe 		 & TALITOS_RNGUSR_LO_RD)
7719c4a7965SKim Phillips 	       && --timeout)
7729c4a7965SKim Phillips 		cpu_relax();
7739c4a7965SKim Phillips 	if (timeout == 0) {
7749c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
7759c4a7965SKim Phillips 		return -ENODEV;
7769c4a7965SKim Phillips 	}
7779c4a7965SKim Phillips 
7789c4a7965SKim Phillips 	/* start generating */
7795fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
7809c4a7965SKim Phillips 
7819c4a7965SKim Phillips 	return 0;
7829c4a7965SKim Phillips }
7839c4a7965SKim Phillips 
7849c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
7859c4a7965SKim Phillips {
7869c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
78735a3bb3dSAaron Sierra 	int err;
7889c4a7965SKim Phillips 
7899c4a7965SKim Phillips 	priv->rng.name		= dev_driver_string(dev),
7909c4a7965SKim Phillips 	priv->rng.init		= talitos_rng_init,
7919c4a7965SKim Phillips 	priv->rng.data_present	= talitos_rng_data_present,
7929c4a7965SKim Phillips 	priv->rng.data_read	= talitos_rng_data_read,
7939c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
7949c4a7965SKim Phillips 
79535a3bb3dSAaron Sierra 	err = hwrng_register(&priv->rng);
79635a3bb3dSAaron Sierra 	if (!err)
79735a3bb3dSAaron Sierra 		priv->rng_registered = true;
79835a3bb3dSAaron Sierra 
79935a3bb3dSAaron Sierra 	return err;
8009c4a7965SKim Phillips }
8019c4a7965SKim Phillips 
8029c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
8039c4a7965SKim Phillips {
8049c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
8059c4a7965SKim Phillips 
80635a3bb3dSAaron Sierra 	if (!priv->rng_registered)
80735a3bb3dSAaron Sierra 		return;
80835a3bb3dSAaron Sierra 
8099c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
81035a3bb3dSAaron Sierra 	priv->rng_registered = false;
8119c4a7965SKim Phillips }
8129c4a7965SKim Phillips 
8139c4a7965SKim Phillips /*
8149c4a7965SKim Phillips  * crypto alg
8159c4a7965SKim Phillips  */
8169c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
8177405c8d7SLEROY Christophe /*
8187405c8d7SLEROY Christophe  * Defines a priority for doing AEAD with descriptors type
8197405c8d7SLEROY Christophe  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
8207405c8d7SLEROY Christophe  */
8217405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
82203d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
8233952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
82470bcaca7SLee Nipper 
8259c4a7965SKim Phillips struct talitos_ctx {
8269c4a7965SKim Phillips 	struct device *dev;
8275228f0f7SKim Phillips 	int ch;
8289c4a7965SKim Phillips 	__be32 desc_hdr_template;
8299c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
83070bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8312e13ce08SLEROY Christophe 	dma_addr_t dma_key;
8329c4a7965SKim Phillips 	unsigned int keylen;
8339c4a7965SKim Phillips 	unsigned int enckeylen;
8349c4a7965SKim Phillips 	unsigned int authkeylen;
8359c4a7965SKim Phillips };
8369c4a7965SKim Phillips 
837497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
838497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
839497f2e6bSLee Nipper 
840497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
84160f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
842497f2e6bSLee Nipper 	unsigned int hw_context_size;
8433c0dd190SLEROY Christophe 	u8 buf[2][HASH_MAX_BLOCK_SIZE];
8443c0dd190SLEROY Christophe 	int buf_idx;
84560f208d7SKim Phillips 	unsigned int swinit;
846497f2e6bSLee Nipper 	unsigned int first;
847497f2e6bSLee Nipper 	unsigned int last;
848497f2e6bSLee Nipper 	unsigned int to_hash_later;
84942e8b0d7SHoria Geant? 	unsigned int nbuf;
850497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
851497f2e6bSLee Nipper 	struct scatterlist *psrc;
852497f2e6bSLee Nipper };
853497f2e6bSLee Nipper 
8543639ca84SHoria Geant? struct talitos_export_state {
8553639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8563639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8573639ca84SHoria Geant? 	unsigned int swinit;
8583639ca84SHoria Geant? 	unsigned int first;
8593639ca84SHoria Geant? 	unsigned int last;
8603639ca84SHoria Geant? 	unsigned int to_hash_later;
8613639ca84SHoria Geant? 	unsigned int nbuf;
8623639ca84SHoria Geant? };
8633639ca84SHoria Geant? 
86456af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8659c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8669c4a7965SKim Phillips {
8679c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
8682e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
869c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8709c4a7965SKim Phillips 
871c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8729c4a7965SKim Phillips 		goto badkey;
8739c4a7965SKim Phillips 
874c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8759c4a7965SKim Phillips 		goto badkey;
8769c4a7965SKim Phillips 
8772e13ce08SLEROY Christophe 	if (ctx->keylen)
8782e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
8792e13ce08SLEROY Christophe 
880c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
881c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
8829c4a7965SKim Phillips 
883c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
884c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
885c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
8862e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
8872e13ce08SLEROY Christophe 				      DMA_TO_DEVICE);
8889c4a7965SKim Phillips 
8899c4a7965SKim Phillips 	return 0;
8909c4a7965SKim Phillips 
8919c4a7965SKim Phillips badkey:
8929c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
8939c4a7965SKim Phillips 	return -EINVAL;
8949c4a7965SKim Phillips }
8959c4a7965SKim Phillips 
8969c4a7965SKim Phillips /*
89756af8cd4SLee Nipper  * talitos_edesc - s/w-extended descriptor
8989c4a7965SKim Phillips  * @src_nents: number of segments in input scatterlist
8999c4a7965SKim Phillips  * @dst_nents: number of segments in output scatterlist
900aeb4c132SHerbert Xu  * @icv_ool: whether ICV is out-of-line
90179fd31d3SHoria Geanta  * @iv_dma: dma address of iv for checking continuity and link table
9029c4a7965SKim Phillips  * @dma_len: length of dma mapped link_tbl space
9036f65f6acSLEROY Christophe  * @dma_link_tbl: bus physical address of link_tbl/buf
9049c4a7965SKim Phillips  * @desc: h/w descriptor
9056f65f6acSLEROY Christophe  * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
9066f65f6acSLEROY Christophe  * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
9079c4a7965SKim Phillips  *
9089c4a7965SKim Phillips  * if decrypting (with authcheck), or either one of src_nents or dst_nents
9099c4a7965SKim Phillips  * is greater than 1, an integrity check value is concatenated to the end
9109c4a7965SKim Phillips  * of link_tbl data
9119c4a7965SKim Phillips  */
91256af8cd4SLee Nipper struct talitos_edesc {
9139c4a7965SKim Phillips 	int src_nents;
9149c4a7965SKim Phillips 	int dst_nents;
915aeb4c132SHerbert Xu 	bool icv_ool;
91679fd31d3SHoria Geanta 	dma_addr_t iv_dma;
9179c4a7965SKim Phillips 	int dma_len;
9189c4a7965SKim Phillips 	dma_addr_t dma_link_tbl;
9199c4a7965SKim Phillips 	struct talitos_desc desc;
9206f65f6acSLEROY Christophe 	union {
9219c4a7965SKim Phillips 		struct talitos_ptr link_tbl[0];
9226f65f6acSLEROY Christophe 		u8 buf[0];
9236f65f6acSLEROY Christophe 	};
9249c4a7965SKim Phillips };
9259c4a7965SKim Phillips 
9264de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9274de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9284de9d0b5SLee Nipper 			     struct scatterlist *src,
9296a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
9306a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
931246a87cdSLEROY Christophe {
932246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
933246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9346a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
9356a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
936246a87cdSLEROY Christophe 
9376a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
9386a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
939246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
9406a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
9416a1e8d14SLEROY Christophe 				     offset);
942246a87cdSLEROY Christophe 	}
9436a1e8d14SLEROY Christophe 	if (src != dst) {
9446a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
9456a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
9466a1e8d14SLEROY Christophe 
9476a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
9486a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
9496a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
9506a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
951246a87cdSLEROY Christophe 	}
952246a87cdSLEROY Christophe }
953246a87cdSLEROY Christophe 
9549c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
95556af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
9569c4a7965SKim Phillips 			    struct aead_request *areq)
9579c4a7965SKim Phillips {
958549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
959549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
960549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
9619a655608SLEROY Christophe 	bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
9629a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
963549bd8bcSLEROY Christophe 
9649a655608SLEROY Christophe 	if (is_ipsec_esp)
965549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
966549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
9679a655608SLEROY Christophe 	unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
9689c4a7965SKim Phillips 
9696a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen,
9706a1e8d14SLEROY Christophe 			 areq->assoclen);
9719c4a7965SKim Phillips 
9729c4a7965SKim Phillips 	if (edesc->dma_len)
9739c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
9749c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
975549bd8bcSLEROY Christophe 
9769a655608SLEROY Christophe 	if (!is_ipsec_esp) {
977549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
978549bd8bcSLEROY Christophe 
979549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
980549bd8bcSLEROY Christophe 				   areq->assoclen + areq->cryptlen - ivsize);
981549bd8bcSLEROY Christophe 	}
9829c4a7965SKim Phillips }
9839c4a7965SKim Phillips 
9849c4a7965SKim Phillips /*
9859c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
9869c4a7965SKim Phillips  */
9879c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
9889c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
9899c4a7965SKim Phillips 				   int err)
9909c4a7965SKim Phillips {
991549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
992549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9939c4a7965SKim Phillips 	struct aead_request *areq = context;
9949c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
995aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
9962e13ce08SLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(authenc);
99719bbbc63SKim Phillips 	struct talitos_edesc *edesc;
9989c4a7965SKim Phillips 	struct scatterlist *sg;
9999c4a7965SKim Phillips 	void *icvdata;
10009c4a7965SKim Phillips 
100119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
100219bbbc63SKim Phillips 
10039c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, areq);
10049c4a7965SKim Phillips 
10059c4a7965SKim Phillips 	/* copy the generated ICV to dst */
1006aeb4c132SHerbert Xu 	if (edesc->icv_ool) {
1007549bd8bcSLEROY Christophe 		if (is_sec1)
1008549bd8bcSLEROY Christophe 			icvdata = edesc->buf + areq->assoclen + areq->cryptlen;
1009549bd8bcSLEROY Christophe 		else
10109c4a7965SKim Phillips 			icvdata = &edesc->link_tbl[edesc->src_nents +
1011aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
10129c4a7965SKim Phillips 		sg = sg_last(areq->dst, edesc->dst_nents);
1013aeb4c132SHerbert Xu 		memcpy((char *)sg_virt(sg) + sg->length - authsize,
1014aeb4c132SHerbert Xu 		       icvdata, authsize);
10159c4a7965SKim Phillips 	}
10169c4a7965SKim Phillips 
10172e13ce08SLEROY Christophe 	dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
10182e13ce08SLEROY Christophe 
10199c4a7965SKim Phillips 	kfree(edesc);
10209c4a7965SKim Phillips 
10219c4a7965SKim Phillips 	aead_request_complete(areq, err);
10229c4a7965SKim Phillips }
10239c4a7965SKim Phillips 
1024fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1025e938e465SKim Phillips 					  struct talitos_desc *desc,
1026e938e465SKim Phillips 					  void *context, int err)
10279c4a7965SKim Phillips {
10289c4a7965SKim Phillips 	struct aead_request *req = context;
10299c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1030aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
103119bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10329c4a7965SKim Phillips 	struct scatterlist *sg;
1033aeb4c132SHerbert Xu 	char *oicv, *icv;
1034549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1035549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10369c4a7965SKim Phillips 
103719bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
103819bbbc63SKim Phillips 
10399c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
10409c4a7965SKim Phillips 
10419c4a7965SKim Phillips 	if (!err) {
10429c4a7965SKim Phillips 		/* auth check */
10439c4a7965SKim Phillips 		sg = sg_last(req->dst, edesc->dst_nents ? : 1);
1044aeb4c132SHerbert Xu 		icv = (char *)sg_virt(sg) + sg->length - authsize;
1045aeb4c132SHerbert Xu 
1046aeb4c132SHerbert Xu 		if (edesc->dma_len) {
1047549bd8bcSLEROY Christophe 			if (is_sec1)
1048549bd8bcSLEROY Christophe 				oicv = (char *)&edesc->dma_link_tbl +
1049549bd8bcSLEROY Christophe 					       req->assoclen + req->cryptlen;
1050549bd8bcSLEROY Christophe 			else
1051549bd8bcSLEROY Christophe 				oicv = (char *)
1052549bd8bcSLEROY Christophe 				       &edesc->link_tbl[edesc->src_nents +
1053aeb4c132SHerbert Xu 							edesc->dst_nents + 2];
1054aeb4c132SHerbert Xu 			if (edesc->icv_ool)
1055aeb4c132SHerbert Xu 				icv = oicv + authsize;
1056aeb4c132SHerbert Xu 		} else
1057aeb4c132SHerbert Xu 			oicv = (char *)&edesc->link_tbl[0];
1058aeb4c132SHerbert Xu 
105979960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10609c4a7965SKim Phillips 	}
10619c4a7965SKim Phillips 
10629c4a7965SKim Phillips 	kfree(edesc);
10639c4a7965SKim Phillips 
10649c4a7965SKim Phillips 	aead_request_complete(req, err);
10659c4a7965SKim Phillips }
10669c4a7965SKim Phillips 
1067fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1068e938e465SKim Phillips 					  struct talitos_desc *desc,
1069e938e465SKim Phillips 					  void *context, int err)
1070fe5720e2SKim Phillips {
1071fe5720e2SKim Phillips 	struct aead_request *req = context;
107219bbbc63SKim Phillips 	struct talitos_edesc *edesc;
107319bbbc63SKim Phillips 
107419bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1075fe5720e2SKim Phillips 
1076fe5720e2SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
1077fe5720e2SKim Phillips 
1078fe5720e2SKim Phillips 	/* check ICV auth status */
1079e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1080e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1081fe5720e2SKim Phillips 		err = -EBADMSG;
1082fe5720e2SKim Phillips 
1083fe5720e2SKim Phillips 	kfree(edesc);
1084fe5720e2SKim Phillips 
1085fe5720e2SKim Phillips 	aead_request_complete(req, err);
1086fe5720e2SKim Phillips }
1087fe5720e2SKim Phillips 
10889c4a7965SKim Phillips /*
10899c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
10909c4a7965SKim Phillips  * stop at cryptlen bytes
10919c4a7965SKim Phillips  */
1092aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1093aeb4c132SHerbert Xu 				 unsigned int offset, int cryptlen,
1094aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
10959c4a7965SKim Phillips {
109670bcaca7SLee Nipper 	int n_sg = sg_count;
1097aeb4c132SHerbert Xu 	int count = 0;
109870bcaca7SLee Nipper 
1099aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1100aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1101aeb4c132SHerbert Xu 
1102aeb4c132SHerbert Xu 		if (offset >= len) {
1103aeb4c132SHerbert Xu 			offset -= len;
1104aeb4c132SHerbert Xu 			goto next;
1105aeb4c132SHerbert Xu 		}
1106aeb4c132SHerbert Xu 
1107aeb4c132SHerbert Xu 		len -= offset;
1108aeb4c132SHerbert Xu 
1109aeb4c132SHerbert Xu 		if (len > cryptlen)
1110aeb4c132SHerbert Xu 			len = cryptlen;
1111aeb4c132SHerbert Xu 
1112aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1113da9de146SLEROY Christophe 			       sg_dma_address(sg) + offset, len, 0);
1114b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1115aeb4c132SHerbert Xu 		count++;
1116aeb4c132SHerbert Xu 		cryptlen -= len;
1117aeb4c132SHerbert Xu 		offset = 0;
1118aeb4c132SHerbert Xu 
1119aeb4c132SHerbert Xu next:
11205be4d4c9SCristian Stoica 		sg = sg_next(sg);
11219c4a7965SKim Phillips 	}
11229c4a7965SKim Phillips 
11239c4a7965SKim Phillips 	/* tag end of link table */
1124aeb4c132SHerbert Xu 	if (count > 0)
1125b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1126b096b544SLEROY Christophe 				       DESC_PTR_LNKTBL_RETURN, 0);
112770bcaca7SLee Nipper 
1128aeb4c132SHerbert Xu 	return count;
1129aeb4c132SHerbert Xu }
1130aeb4c132SHerbert Xu 
11315b2cf268SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src,
1132246a87cdSLEROY Christophe 		   unsigned int len, struct talitos_edesc *edesc,
11336a1e8d14SLEROY Christophe 		   struct talitos_ptr *ptr,
11346a1e8d14SLEROY Christophe 		   int sg_count, unsigned int offset, int tbl_off)
1135246a87cdSLEROY Christophe {
1136246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1137246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1138246a87cdSLEROY Christophe 
113987a81dceSLEROY Christophe 	if (!src) {
114087a81dceSLEROY Christophe 		to_talitos_ptr(ptr, 0, 0, is_sec1);
114187a81dceSLEROY Christophe 		return 1;
114287a81dceSLEROY Christophe 	}
1143246a87cdSLEROY Christophe 	if (sg_count == 1) {
1144da9de146SLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1);
1145246a87cdSLEROY Christophe 		return sg_count;
1146246a87cdSLEROY Christophe 	}
1147246a87cdSLEROY Christophe 	if (is_sec1) {
1148da9de146SLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1);
11496a1e8d14SLEROY Christophe 		return sg_count;
1150246a87cdSLEROY Christophe 	}
11516a1e8d14SLEROY Christophe 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len,
11526a1e8d14SLEROY Christophe 					 &edesc->link_tbl[tbl_off]);
1153246a87cdSLEROY Christophe 	if (sg_count == 1) {
11546a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
11556a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
11566a1e8d14SLEROY Christophe 		return sg_count;
11576a1e8d14SLEROY Christophe 	}
1158246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
1159da9de146SLEROY Christophe 			    tbl_off * sizeof(struct talitos_ptr), len, is_sec1);
11606a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
11616a1e8d14SLEROY Christophe 
11626a1e8d14SLEROY Christophe 	return sg_count;
1163246a87cdSLEROY Christophe }
1164246a87cdSLEROY Christophe 
11659c4a7965SKim Phillips /*
11669c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
11679c4a7965SKim Phillips  */
116856af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
1169aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
11709c4a7965SKim Phillips 				      struct talitos_desc *desc,
11719c4a7965SKim Phillips 				      void *context, int error))
11729c4a7965SKim Phillips {
11739c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1174aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
11759c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
11769c4a7965SKim Phillips 	struct device *dev = ctx->dev;
11779c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
11789c4a7965SKim Phillips 	unsigned int cryptlen = areq->cryptlen;
1179e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1180aeb4c132SHerbert Xu 	int tbl_off = 0;
1181fa86a267SKim Phillips 	int sg_count, ret;
1182fe5720e2SKim Phillips 	int sg_link_tbl_len;
1183549bd8bcSLEROY Christophe 	bool sync_needed = false;
1184549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1185549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
11869a655608SLEROY Christophe 	bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
11879a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
11889a655608SLEROY Christophe 	struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
11899c4a7965SKim Phillips 
11909c4a7965SKim Phillips 	/* hmac key */
11912e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1);
119279fd31d3SHoria Geanta 
1193549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1194549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1195549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1196549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1197549bd8bcSLEROY Christophe 	else
1198549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1199549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1200549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1201549bd8bcSLEROY Christophe 
12029c4a7965SKim Phillips 	/* hmac data */
1203549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1204549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
120579fd31d3SHoria Geanta 
1206549bd8bcSLEROY Christophe 	if (ret > 1) {
1207340ff60aSHoria Geant? 		tbl_off += ret;
1208549bd8bcSLEROY Christophe 		sync_needed = true;
120979fd31d3SHoria Geanta 	}
121079fd31d3SHoria Geanta 
12119c4a7965SKim Phillips 	/* cipher iv */
12129a655608SLEROY Christophe 	to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1);
12139c4a7965SKim Phillips 
12149c4a7965SKim Phillips 	/* cipher key */
12152e13ce08SLEROY Christophe 	to_talitos_ptr(ckey_ptr, ctx->dma_key  + ctx->authkeylen,
12162e13ce08SLEROY Christophe 		       ctx->enckeylen, is_sec1);
12179c4a7965SKim Phillips 
12189c4a7965SKim Phillips 	/*
12199c4a7965SKim Phillips 	 * cipher in
12209c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
12219c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
12229c4a7965SKim Phillips 	 * typically 12 for ipsec
12239c4a7965SKim Phillips 	 */
1224fe5720e2SKim Phillips 	sg_link_tbl_len = cryptlen;
1225549bd8bcSLEROY Christophe 
12269a655608SLEROY Christophe 	if (is_ipsec_esp) {
1227549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[4], authsize, is_sec1);
1228549bd8bcSLEROY Christophe 
12299a655608SLEROY Christophe 		if (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)
1230aeb4c132SHerbert Xu 			sg_link_tbl_len += authsize;
1231549bd8bcSLEROY Christophe 	}
1232e938e465SKim Phillips 
1233fbb22137SLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, sg_link_tbl_len, edesc,
1234fbb22137SLEROY Christophe 			     &desc->ptr[4], sg_count, areq->assoclen, tbl_off);
1235549bd8bcSLEROY Christophe 
1236ec8c7d14SLEROY Christophe 	if (ret > 1) {
1237ec8c7d14SLEROY Christophe 		tbl_off += ret;
1238549bd8bcSLEROY Christophe 		sync_needed = true;
1239340ff60aSHoria Geant? 	}
12409c4a7965SKim Phillips 
12419c4a7965SKim Phillips 	/* cipher out */
1242549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1243549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1244549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1245549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1246549bd8bcSLEROY Christophe 	}
12479c4a7965SKim Phillips 
1248e04a61beSLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
1249e04a61beSLEROY Christophe 			     sg_count, areq->assoclen, tbl_off);
12509c4a7965SKim Phillips 
12519a655608SLEROY Christophe 	if (is_ipsec_esp)
1252549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1253aeb4c132SHerbert Xu 
1254e04a61beSLEROY Christophe 	/* ICV data */
1255e04a61beSLEROY Christophe 	if (ret > 1) {
1256e04a61beSLEROY Christophe 		tbl_off += ret;
1257549bd8bcSLEROY Christophe 		edesc->icv_ool = true;
1258549bd8bcSLEROY Christophe 		sync_needed = true;
1259549bd8bcSLEROY Christophe 
12609a655608SLEROY Christophe 		if (is_ipsec_esp) {
126179fd31d3SHoria Geanta 			struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1262549bd8bcSLEROY Christophe 			int offset = (edesc->src_nents + edesc->dst_nents + 2) *
1263549bd8bcSLEROY Christophe 				     sizeof(struct talitos_ptr) + authsize;
1264fe5720e2SKim Phillips 
1265f3c85bc1SLee Nipper 			/* Add an entry to the link table for ICV data */
1266e04a61beSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
1267549bd8bcSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN,
1268549bd8bcSLEROY Christophe 					       is_sec1);
12699c4a7965SKim Phillips 
12709c4a7965SKim Phillips 			/* icv data follows link tables */
1271549bd8bcSLEROY Christophe 			to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl + offset,
1272da9de146SLEROY Christophe 				       authsize, is_sec1);
1273e04a61beSLEROY Christophe 		} else {
1274e04a61beSLEROY Christophe 			dma_addr_t addr = edesc->dma_link_tbl;
1275e04a61beSLEROY Christophe 
1276e04a61beSLEROY Christophe 			if (is_sec1)
1277e04a61beSLEROY Christophe 				addr += areq->assoclen + cryptlen;
1278e04a61beSLEROY Christophe 			else
1279e04a61beSLEROY Christophe 				addr += sizeof(struct talitos_ptr) * tbl_off;
1280e04a61beSLEROY Christophe 
1281da9de146SLEROY Christophe 			to_talitos_ptr(&desc->ptr[6], addr, authsize, is_sec1);
1282549bd8bcSLEROY Christophe 		}
12839a655608SLEROY Christophe 	} else if (!is_ipsec_esp) {
1284e04a61beSLEROY Christophe 		ret = talitos_sg_map(dev, areq->dst, authsize, edesc,
1285e04a61beSLEROY Christophe 				     &desc->ptr[6], sg_count, areq->assoclen +
1286e04a61beSLEROY Christophe 							      cryptlen,
1287e04a61beSLEROY Christophe 				     tbl_off);
1288e04a61beSLEROY Christophe 		if (ret > 1) {
1289e04a61beSLEROY Christophe 			tbl_off += ret;
1290e04a61beSLEROY Christophe 			edesc->icv_ool = true;
1291e04a61beSLEROY Christophe 			sync_needed = true;
1292340ff60aSHoria Geant? 		} else {
1293549bd8bcSLEROY Christophe 			edesc->icv_ool = false;
1294549bd8bcSLEROY Christophe 		}
1295e04a61beSLEROY Christophe 	} else {
1296e04a61beSLEROY Christophe 		edesc->icv_ool = false;
1297340ff60aSHoria Geant? 	}
12989c4a7965SKim Phillips 
12999c4a7965SKim Phillips 	/* iv out */
13009a655608SLEROY Christophe 	if (is_ipsec_esp)
1301a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
13029c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
13039c4a7965SKim Phillips 
1304549bd8bcSLEROY Christophe 	if (sync_needed)
1305549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1306549bd8bcSLEROY Christophe 					   edesc->dma_len,
1307549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1308549bd8bcSLEROY Christophe 
13095228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1310fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
1311fa86a267SKim Phillips 		ipsec_esp_unmap(dev, edesc, areq);
1312fa86a267SKim Phillips 		kfree(edesc);
1313fa86a267SKim Phillips 	}
1314fa86a267SKim Phillips 	return ret;
13159c4a7965SKim Phillips }
13169c4a7965SKim Phillips 
13179c4a7965SKim Phillips /*
131856af8cd4SLee Nipper  * allocate and map the extended descriptor
13199c4a7965SKim Phillips  */
13204de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13214de9d0b5SLee Nipper 						 struct scatterlist *src,
13224de9d0b5SLee Nipper 						 struct scatterlist *dst,
132379fd31d3SHoria Geanta 						 u8 *iv,
132479fd31d3SHoria Geanta 						 unsigned int assoclen,
13254de9d0b5SLee Nipper 						 unsigned int cryptlen,
13264de9d0b5SLee Nipper 						 unsigned int authsize,
132779fd31d3SHoria Geanta 						 unsigned int ivsize,
13284de9d0b5SLee Nipper 						 int icv_stashing,
132962293a37SHoria Geanta 						 u32 cryptoflags,
133062293a37SHoria Geanta 						 bool encrypt)
13319c4a7965SKim Phillips {
133256af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13336a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
133479fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
13354de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1336586725f8SKim Phillips 		      GFP_ATOMIC;
13376f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
13386f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
13396f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
13408e409fe1SLABBE Corentin 	void *err;
13419c4a7965SKim Phillips 
13426f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
13434de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
13449c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
13459c4a7965SKim Phillips 	}
13469c4a7965SKim Phillips 
1347935e99a3SHoria Geanta 	if (ivsize)
134879fd31d3SHoria Geanta 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
134979fd31d3SHoria Geanta 
135062293a37SHoria Geanta 	if (!dst || dst == src) {
13516a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
13526a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13538e409fe1SLABBE Corentin 		if (src_nents < 0) {
13548e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13558e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13568e409fe1SLABBE Corentin 			goto error_sg;
13578e409fe1SLABBE Corentin 		}
13589c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
135962293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
13606a1e8d14SLEROY Christophe 		dst_len = 0;
136162293a37SHoria Geanta 	} else { /* dst && dst != src*/
13626a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
13636a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13648e409fe1SLABBE Corentin 		if (src_nents < 0) {
13658e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13668e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13678e409fe1SLABBE Corentin 			goto error_sg;
13688e409fe1SLABBE Corentin 		}
136962293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
13706a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
13716a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
13728e409fe1SLABBE Corentin 		if (dst_nents < 0) {
13738e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
13748e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13758e409fe1SLABBE Corentin 			goto error_sg;
13768e409fe1SLABBE Corentin 		}
1377695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
13789c4a7965SKim Phillips 	}
13799c4a7965SKim Phillips 
13809c4a7965SKim Phillips 	/*
13819c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1382aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1383aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
13849c4a7965SKim Phillips 	 */
138556af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1386aeb4c132SHerbert Xu 	if (src_nents || dst_nents) {
13876f65f6acSLEROY Christophe 		if (is_sec1)
13886a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
13896a1e8d14SLEROY Christophe 				  (dst_nents ? dst_len : 0);
13906f65f6acSLEROY Christophe 		else
1391aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1392aeb4c132SHerbert Xu 				  sizeof(struct talitos_ptr) + authsize * 2;
13939c4a7965SKim Phillips 		alloc_len += dma_len;
13949c4a7965SKim Phillips 	} else {
13959c4a7965SKim Phillips 		dma_len = 0;
13964de9d0b5SLee Nipper 		alloc_len += icv_stashing ? authsize : 0;
13979c4a7965SKim Phillips 	}
13989c4a7965SKim Phillips 
139937b5e889SLEROY Christophe 	/* if its a ahash, add space for a second desc next to the first one */
140037b5e889SLEROY Christophe 	if (is_sec1 && !dst)
140137b5e889SLEROY Christophe 		alloc_len += sizeof(struct talitos_desc);
140237b5e889SLEROY Christophe 
1403586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
14049c4a7965SKim Phillips 	if (!edesc) {
14054de9d0b5SLee Nipper 		dev_err(dev, "could not allocate edescriptor\n");
14068e409fe1SLABBE Corentin 		err = ERR_PTR(-ENOMEM);
14078e409fe1SLABBE Corentin 		goto error_sg;
14089c4a7965SKim Phillips 	}
1409e4a647c4SLEROY Christophe 	memset(&edesc->desc, 0, sizeof(edesc->desc));
14109c4a7965SKim Phillips 
14119c4a7965SKim Phillips 	edesc->src_nents = src_nents;
14129c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
141379fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
14149c4a7965SKim Phillips 	edesc->dma_len = dma_len;
141537b5e889SLEROY Christophe 	if (dma_len) {
141637b5e889SLEROY Christophe 		void *addr = &edesc->link_tbl[0];
141737b5e889SLEROY Christophe 
141837b5e889SLEROY Christophe 		if (is_sec1 && !dst)
141937b5e889SLEROY Christophe 			addr += sizeof(struct talitos_desc);
142037b5e889SLEROY Christophe 		edesc->dma_link_tbl = dma_map_single(dev, addr,
1421497f2e6bSLee Nipper 						     edesc->dma_len,
1422497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
142337b5e889SLEROY Christophe 	}
14249c4a7965SKim Phillips 	return edesc;
14258e409fe1SLABBE Corentin error_sg:
14268e409fe1SLABBE Corentin 	if (iv_dma)
14278e409fe1SLABBE Corentin 		dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
14288e409fe1SLABBE Corentin 	return err;
14299c4a7965SKim Phillips }
14309c4a7965SKim Phillips 
143179fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
143262293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
14334de9d0b5SLee Nipper {
14344de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1435aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14364de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
143779fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
14384de9d0b5SLee Nipper 
1439aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
144079fd31d3SHoria Geanta 				   iv, areq->assoclen, areq->cryptlen,
1441aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
144262293a37SHoria Geanta 				   areq->base.flags, encrypt);
14434de9d0b5SLee Nipper }
14444de9d0b5SLee Nipper 
144556af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
14469c4a7965SKim Phillips {
14479c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14489c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
144956af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14509c4a7965SKim Phillips 
14519c4a7965SKim Phillips 	/* allocate extended descriptor */
145262293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
14539c4a7965SKim Phillips 	if (IS_ERR(edesc))
14549c4a7965SKim Phillips 		return PTR_ERR(edesc);
14559c4a7965SKim Phillips 
14569c4a7965SKim Phillips 	/* set encrypt */
145770bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14589c4a7965SKim Phillips 
1459aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
14609c4a7965SKim Phillips }
14619c4a7965SKim Phillips 
146256af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
14639c4a7965SKim Phillips {
14649c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1465aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14669c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1467fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
146856af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14699c4a7965SKim Phillips 	struct scatterlist *sg;
14709c4a7965SKim Phillips 	void *icvdata;
14719c4a7965SKim Phillips 
14729c4a7965SKim Phillips 	req->cryptlen -= authsize;
14739c4a7965SKim Phillips 
14749c4a7965SKim Phillips 	/* allocate extended descriptor */
147562293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14769c4a7965SKim Phillips 	if (IS_ERR(edesc))
14779c4a7965SKim Phillips 		return PTR_ERR(edesc);
14789c4a7965SKim Phillips 
1479fe5720e2SKim Phillips 	if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1480e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1481e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1482fe5720e2SKim Phillips 
1483fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1484e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1485e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1486fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1487fe5720e2SKim Phillips 
1488fe5720e2SKim Phillips 		/* reset integrity check result bits */
1489fe5720e2SKim Phillips 
1490aeb4c132SHerbert Xu 		return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
1491e938e465SKim Phillips 	}
1492fe5720e2SKim Phillips 
1493fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1494fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1495fe5720e2SKim Phillips 
14969c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
14979c4a7965SKim Phillips 	if (edesc->dma_len)
1498aeb4c132SHerbert Xu 		icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1499aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
15009c4a7965SKim Phillips 	else
15019c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[0];
15029c4a7965SKim Phillips 
15039c4a7965SKim Phillips 	sg = sg_last(req->src, edesc->src_nents ? : 1);
15049c4a7965SKim Phillips 
1505aeb4c132SHerbert Xu 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
15069c4a7965SKim Phillips 
1507aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
15089c4a7965SKim Phillips }
15099c4a7965SKim Phillips 
15104de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
15114de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
15124de9d0b5SLee Nipper {
15134de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15142e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
1515f384cdc4SLEROY Christophe 	u32 tmp[DES_EXPKEY_WORDS];
15164de9d0b5SLee Nipper 
151703d2c511SMartin Hicks 	if (keylen > TALITOS_MAX_KEY_SIZE) {
151803d2c511SMartin Hicks 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
151903d2c511SMartin Hicks 		return -EINVAL;
152003d2c511SMartin Hicks 	}
152103d2c511SMartin Hicks 
1522f384cdc4SLEROY Christophe 	if (unlikely(crypto_ablkcipher_get_flags(cipher) &
1523f384cdc4SLEROY Christophe 		     CRYPTO_TFM_REQ_WEAK_KEY) &&
1524f384cdc4SLEROY Christophe 	    !des_ekey(tmp, key)) {
1525f384cdc4SLEROY Christophe 		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_WEAK_KEY);
1526f384cdc4SLEROY Christophe 		return -EINVAL;
1527f384cdc4SLEROY Christophe 	}
1528f384cdc4SLEROY Christophe 
15292e13ce08SLEROY Christophe 	if (ctx->keylen)
15302e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
15312e13ce08SLEROY Christophe 
15324de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
15334de9d0b5SLee Nipper 	ctx->keylen = keylen;
15344de9d0b5SLee Nipper 
15352e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE);
15362e13ce08SLEROY Christophe 
15374de9d0b5SLee Nipper 	return 0;
15384de9d0b5SLee Nipper }
15394de9d0b5SLee Nipper 
15404de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
15414de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
15424de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
15434de9d0b5SLee Nipper {
15444de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1545032d197eSLEROY Christophe 
15466a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0);
15474de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
15484de9d0b5SLee Nipper 
15494de9d0b5SLee Nipper 	if (edesc->dma_len)
15504de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
15514de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
15524de9d0b5SLee Nipper }
15534de9d0b5SLee Nipper 
15544de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
15554de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
15564de9d0b5SLee Nipper 			    int err)
15574de9d0b5SLee Nipper {
15584de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
155919bbbc63SKim Phillips 	struct talitos_edesc *edesc;
156019bbbc63SKim Phillips 
156119bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
15624de9d0b5SLee Nipper 
15634de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
15644de9d0b5SLee Nipper 
15654de9d0b5SLee Nipper 	kfree(edesc);
15664de9d0b5SLee Nipper 
15674de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
15684de9d0b5SLee Nipper }
15694de9d0b5SLee Nipper 
15704de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
15714de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
15724de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
15734de9d0b5SLee Nipper 					     struct talitos_desc *desc,
15744de9d0b5SLee Nipper 					     void *context, int error))
15754de9d0b5SLee Nipper {
15764de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15774de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15784de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
15794de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
15804de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
158179fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
15824de9d0b5SLee Nipper 	int sg_count, ret;
15836a1e8d14SLEROY Christophe 	bool sync_needed = false;
1584922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1585922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
15864de9d0b5SLee Nipper 
15874de9d0b5SLee Nipper 	/* first DWORD empty */
15884de9d0b5SLee Nipper 
15894de9d0b5SLee Nipper 	/* cipher iv */
1590da9de146SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1);
15914de9d0b5SLee Nipper 
15924de9d0b5SLee Nipper 	/* cipher key */
15932e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1);
15944de9d0b5SLee Nipper 
15956a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
15966a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
15976a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
15986a1e8d14SLEROY Christophe 				  cryptlen);
15996a1e8d14SLEROY Christophe 	else
16006a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
16016a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
16026a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
16034de9d0b5SLee Nipper 	/*
16044de9d0b5SLee Nipper 	 * cipher in
16054de9d0b5SLee Nipper 	 */
16066a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
16076a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
16086a1e8d14SLEROY Christophe 	if (sg_count > 1)
16096a1e8d14SLEROY Christophe 		sync_needed = true;
16104de9d0b5SLee Nipper 
16114de9d0b5SLee Nipper 	/* cipher out */
16126a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
16136a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
16146a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
16156a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
16166a1e8d14SLEROY Christophe 	}
16176a1e8d14SLEROY Christophe 
16186a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
16196a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
16206a1e8d14SLEROY Christophe 	if (ret > 1)
16216a1e8d14SLEROY Christophe 		sync_needed = true;
16224de9d0b5SLee Nipper 
16234de9d0b5SLee Nipper 	/* iv out */
1624a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
16254de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
16264de9d0b5SLee Nipper 
16274de9d0b5SLee Nipper 	/* last DWORD empty */
16284de9d0b5SLee Nipper 
16296a1e8d14SLEROY Christophe 	if (sync_needed)
16306a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
16316a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
16326a1e8d14SLEROY Christophe 
16335228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
16344de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
16354de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
16364de9d0b5SLee Nipper 		kfree(edesc);
16374de9d0b5SLee Nipper 	}
16384de9d0b5SLee Nipper 	return ret;
16394de9d0b5SLee Nipper }
16404de9d0b5SLee Nipper 
1641e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
164262293a37SHoria Geanta 						    areq, bool encrypt)
16434de9d0b5SLee Nipper {
16444de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16454de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
164679fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
16474de9d0b5SLee Nipper 
1648aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
164979fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
165062293a37SHoria Geanta 				   areq->base.flags, encrypt);
16514de9d0b5SLee Nipper }
16524de9d0b5SLee Nipper 
16534de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
16544de9d0b5SLee Nipper {
16554de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16564de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16574de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16584de9d0b5SLee Nipper 
16594de9d0b5SLee Nipper 	/* allocate extended descriptor */
166062293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
16614de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16624de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16634de9d0b5SLee Nipper 
16644de9d0b5SLee Nipper 	/* set encrypt */
16654de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16664de9d0b5SLee Nipper 
1667febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16684de9d0b5SLee Nipper }
16694de9d0b5SLee Nipper 
16704de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
16714de9d0b5SLee Nipper {
16724de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16734de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16744de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16754de9d0b5SLee Nipper 
16764de9d0b5SLee Nipper 	/* allocate extended descriptor */
167762293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
16784de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16794de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16804de9d0b5SLee Nipper 
16814de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
16824de9d0b5SLee Nipper 
1683febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16844de9d0b5SLee Nipper }
16854de9d0b5SLee Nipper 
1686497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1687497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1688497f2e6bSLee Nipper 				       struct ahash_request *areq)
1689497f2e6bSLee Nipper {
1690497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1691*ad4cd51fSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1692*ad4cd51fSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1693*ad4cd51fSLEROY Christophe 	struct talitos_desc *desc = &edesc->desc;
1694*ad4cd51fSLEROY Christophe 	struct talitos_desc *desc2 = desc + 1;
1695*ad4cd51fSLEROY Christophe 
1696*ad4cd51fSLEROY Christophe 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1697*ad4cd51fSLEROY Christophe 	if (desc->next_desc &&
1698*ad4cd51fSLEROY Christophe 	    desc->ptr[5].ptr != desc2->ptr[5].ptr)
1699*ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
1700497f2e6bSLee Nipper 
17016a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1702032d197eSLEROY Christophe 
1703*ad4cd51fSLEROY Christophe 	/* When using hashctx-in, must unmap it. */
1704*ad4cd51fSLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
1705*ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1706*ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1707*ad4cd51fSLEROY Christophe 	else if (desc->next_desc)
1708*ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[1],
1709*ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1710*ad4cd51fSLEROY Christophe 
1711*ad4cd51fSLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
1712*ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc->ptr[3],
1713*ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1714*ad4cd51fSLEROY Christophe 
1715497f2e6bSLee Nipper 	if (edesc->dma_len)
1716497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1717497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1718497f2e6bSLee Nipper 
171937b5e889SLEROY Christophe 	if (edesc->desc.next_desc)
172037b5e889SLEROY Christophe 		dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc),
172137b5e889SLEROY Christophe 				 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
1722497f2e6bSLee Nipper }
1723497f2e6bSLee Nipper 
1724497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1725497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1726497f2e6bSLee Nipper 		       int err)
1727497f2e6bSLee Nipper {
1728497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1729497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1730497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1731497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1732497f2e6bSLee Nipper 
1733497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1734497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
17353c0dd190SLEROY Christophe 		req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
17365e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1737497f2e6bSLee Nipper 	}
1738497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1739497f2e6bSLee Nipper 
1740497f2e6bSLee Nipper 	kfree(edesc);
1741497f2e6bSLee Nipper 
1742497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1743497f2e6bSLee Nipper }
1744497f2e6bSLee Nipper 
17452d02905eSLEROY Christophe /*
17462d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
17472d02905eSLEROY Christophe  * ourself and submit a padded block
17482d02905eSLEROY Christophe  */
17495b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
17502d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
17512d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
17522d02905eSLEROY Christophe {
17532d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
17542d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17552d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17562d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17572d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17582d02905eSLEROY Christophe 	};
17592d02905eSLEROY Christophe 
17602d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
17612d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
17622d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
17632d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
17642d02905eSLEROY Christophe }
17652d02905eSLEROY Christophe 
1766497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1767497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
176837b5e889SLEROY Christophe 				unsigned int offset,
1769497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1770497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1771497f2e6bSLee Nipper 						  void *context, int error))
1772497f2e6bSLee Nipper {
1773497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1774497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1775497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1776497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1777497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1778032d197eSLEROY Christophe 	int ret;
17796a1e8d14SLEROY Christophe 	bool sync_needed = false;
1780922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1781922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
17826a1e8d14SLEROY Christophe 	int sg_count;
1783497f2e6bSLee Nipper 
1784497f2e6bSLee Nipper 	/* first DWORD empty */
1785497f2e6bSLee Nipper 
178660f208d7SKim Phillips 	/* hash context in */
178760f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
1788*ad4cd51fSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[1],
1789*ad4cd51fSLEROY Christophe 				       req_ctx->hw_context_size,
1790*ad4cd51fSLEROY Christophe 				       (char *)req_ctx->hw_context,
1791*ad4cd51fSLEROY Christophe 				       DMA_TO_DEVICE);
179260f208d7SKim Phillips 		req_ctx->swinit = 0;
1793afd62fa2SLEROY Christophe 	}
1794497f2e6bSLee Nipper 	/* Indicate next op is not the first. */
1795497f2e6bSLee Nipper 	req_ctx->first = 0;
1796497f2e6bSLee Nipper 
1797497f2e6bSLee Nipper 	/* HMAC key */
1798497f2e6bSLee Nipper 	if (ctx->keylen)
17992e13ce08SLEROY Christophe 		to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
18002e13ce08SLEROY Christophe 			       is_sec1);
1801497f2e6bSLee Nipper 
180237b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
180337b5e889SLEROY Christophe 		length -= req_ctx->nbuf;
180437b5e889SLEROY Christophe 
18056a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
18066a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
180737b5e889SLEROY Christophe 		sg_pcopy_to_buffer(req_ctx->psrc, sg_count,
180837b5e889SLEROY Christophe 				   edesc->buf + sizeof(struct talitos_desc),
180937b5e889SLEROY Christophe 				   length, req_ctx->nbuf);
181037b5e889SLEROY Christophe 	else if (length)
18116a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
18126a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1813497f2e6bSLee Nipper 	/*
1814497f2e6bSLee Nipper 	 * data in
1815497f2e6bSLee Nipper 	 */
181637b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf) {
1817*ad4cd51fSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
1818*ad4cd51fSLEROY Christophe 				       req_ctx->buf[req_ctx->buf_idx],
1819*ad4cd51fSLEROY Christophe 				       DMA_TO_DEVICE);
182037b5e889SLEROY Christophe 	} else {
18216a1e8d14SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
182237b5e889SLEROY Christophe 					  &desc->ptr[3], sg_count, offset, 0);
18236a1e8d14SLEROY Christophe 		if (sg_count > 1)
18246a1e8d14SLEROY Christophe 			sync_needed = true;
182537b5e889SLEROY Christophe 	}
1826497f2e6bSLee Nipper 
1827497f2e6bSLee Nipper 	/* fifth DWORD empty */
1828497f2e6bSLee Nipper 
1829497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1830497f2e6bSLee Nipper 	if (req_ctx->last)
1831497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1832497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1833a2b35aa8SLEROY Christophe 				       areq->result, DMA_FROM_DEVICE);
1834497f2e6bSLee Nipper 	else
1835*ad4cd51fSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[5],
1836*ad4cd51fSLEROY Christophe 				       req_ctx->hw_context_size,
1837*ad4cd51fSLEROY Christophe 				       req_ctx->hw_context, DMA_FROM_DEVICE);
1838497f2e6bSLee Nipper 
1839497f2e6bSLee Nipper 	/* last DWORD empty */
1840497f2e6bSLee Nipper 
18412d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
18422d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
18432d02905eSLEROY Christophe 
184437b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf && length) {
184537b5e889SLEROY Christophe 		struct talitos_desc *desc2 = desc + 1;
184637b5e889SLEROY Christophe 		dma_addr_t next_desc;
184737b5e889SLEROY Christophe 
184837b5e889SLEROY Christophe 		memset(desc2, 0, sizeof(*desc2));
184937b5e889SLEROY Christophe 		desc2->hdr = desc->hdr;
185037b5e889SLEROY Christophe 		desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
185137b5e889SLEROY Christophe 		desc2->hdr1 = desc2->hdr;
185237b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
185337b5e889SLEROY Christophe 		desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
185437b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
185537b5e889SLEROY Christophe 
1856*ad4cd51fSLEROY Christophe 		if (desc->ptr[1].ptr)
1857*ad4cd51fSLEROY Christophe 			copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
1858*ad4cd51fSLEROY Christophe 					 is_sec1);
1859*ad4cd51fSLEROY Christophe 		else
1860*ad4cd51fSLEROY Christophe 			map_single_talitos_ptr(dev, &desc2->ptr[1],
1861*ad4cd51fSLEROY Christophe 					       req_ctx->hw_context_size,
1862*ad4cd51fSLEROY Christophe 					       req_ctx->hw_context,
1863*ad4cd51fSLEROY Christophe 					       DMA_TO_DEVICE);
186437b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
186537b5e889SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
186637b5e889SLEROY Christophe 					  &desc2->ptr[3], sg_count, offset, 0);
186737b5e889SLEROY Christophe 		if (sg_count > 1)
186837b5e889SLEROY Christophe 			sync_needed = true;
186937b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
187037b5e889SLEROY Christophe 		if (req_ctx->last)
1871*ad4cd51fSLEROY Christophe 			map_single_talitos_ptr(dev, &desc->ptr[5],
1872*ad4cd51fSLEROY Christophe 					       req_ctx->hw_context_size,
1873*ad4cd51fSLEROY Christophe 					       req_ctx->hw_context,
1874*ad4cd51fSLEROY Christophe 					       DMA_FROM_DEVICE);
187537b5e889SLEROY Christophe 
187637b5e889SLEROY Christophe 		next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE,
187737b5e889SLEROY Christophe 					   DMA_BIDIRECTIONAL);
187837b5e889SLEROY Christophe 		desc->next_desc = cpu_to_be32(next_desc);
187937b5e889SLEROY Christophe 	}
188037b5e889SLEROY Christophe 
18816a1e8d14SLEROY Christophe 	if (sync_needed)
18826a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
18836a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
18846a1e8d14SLEROY Christophe 
18855228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1886497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1887497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1888497f2e6bSLee Nipper 		kfree(edesc);
1889497f2e6bSLee Nipper 	}
1890497f2e6bSLee Nipper 	return ret;
1891497f2e6bSLee Nipper }
1892497f2e6bSLee Nipper 
1893497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1894497f2e6bSLee Nipper 					       unsigned int nbytes)
1895497f2e6bSLee Nipper {
1896497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1897497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1898497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
189937b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
190037b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
190137b5e889SLEROY Christophe 
190237b5e889SLEROY Christophe 	if (is_sec1)
190337b5e889SLEROY Christophe 		nbytes -= req_ctx->nbuf;
1904497f2e6bSLee Nipper 
1905aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
190662293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1907497f2e6bSLee Nipper }
1908497f2e6bSLee Nipper 
1909497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1910497f2e6bSLee Nipper {
1911497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1912497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
191349f9783bSLEROY Christophe 	unsigned int size;
1914497f2e6bSLee Nipper 
1915497f2e6bSLee Nipper 	/* Initialize the context */
19163c0dd190SLEROY Christophe 	req_ctx->buf_idx = 0;
19175e833bc4SLee Nipper 	req_ctx->nbuf = 0;
191860f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
191960f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
192049f9783bSLEROY Christophe 	size =	(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1921497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1922497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
192349f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
1924497f2e6bSLee Nipper 
1925497f2e6bSLee Nipper 	return 0;
1926497f2e6bSLee Nipper }
1927497f2e6bSLee Nipper 
192860f208d7SKim Phillips /*
192960f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
193060f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
193160f208d7SKim Phillips  */
193260f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
193360f208d7SKim Phillips {
193460f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
193560f208d7SKim Phillips 
193660f208d7SKim Phillips 	ahash_init(areq);
193760f208d7SKim Phillips 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
193860f208d7SKim Phillips 
1939a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1940a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1941a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1942a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1943a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1944a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1945a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1946a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
194760f208d7SKim Phillips 
194860f208d7SKim Phillips 	/* init 64-bit count */
194960f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
195060f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
195160f208d7SKim Phillips 
195260f208d7SKim Phillips 	return 0;
195360f208d7SKim Phillips }
195460f208d7SKim Phillips 
1955497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1956497f2e6bSLee Nipper {
1957497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1958497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1959497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1960497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1961497f2e6bSLee Nipper 	unsigned int blocksize =
1962497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1963497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1964497f2e6bSLee Nipper 	unsigned int to_hash_later;
19655e833bc4SLee Nipper 	unsigned int nsg;
19668e409fe1SLABBE Corentin 	int nents;
196737b5e889SLEROY Christophe 	struct device *dev = ctx->dev;
196837b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
196937b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
197037b5e889SLEROY Christophe 	int offset = 0;
19713c0dd190SLEROY Christophe 	u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
1972497f2e6bSLee Nipper 
19735e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
19745e833bc4SLee Nipper 		/* Buffer up to one whole block */
19758e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
19768e409fe1SLABBE Corentin 		if (nents < 0) {
19778e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
19788e409fe1SLABBE Corentin 			return nents;
19798e409fe1SLABBE Corentin 		}
19808e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
19813c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, nbytes);
19825e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
1983497f2e6bSLee Nipper 		return 0;
1984497f2e6bSLee Nipper 	}
1985497f2e6bSLee Nipper 
19865e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
19875e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
19885e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
19895e833bc4SLee Nipper 
19905e833bc4SLee Nipper 	if (req_ctx->last)
19915e833bc4SLee Nipper 		to_hash_later = 0;
19925e833bc4SLee Nipper 	else if (to_hash_later)
19935e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
19945e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
19955e833bc4SLee Nipper 	else {
19965e833bc4SLee Nipper 		/* Keep one block buffered */
19975e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
19985e833bc4SLee Nipper 		to_hash_later = blocksize;
1999497f2e6bSLee Nipper 	}
20005e833bc4SLee Nipper 
20015e833bc4SLee Nipper 	/* Chain in any previously buffered data */
200237b5e889SLEROY Christophe 	if (!is_sec1 && req_ctx->nbuf) {
20035e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
20045e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
20053c0dd190SLEROY Christophe 		sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
20065e833bc4SLee Nipper 		if (nsg > 1)
2007c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
20085e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
200937b5e889SLEROY Christophe 	} else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
201037b5e889SLEROY Christophe 		if (nbytes_to_hash > blocksize)
201137b5e889SLEROY Christophe 			offset = blocksize - req_ctx->nbuf;
201237b5e889SLEROY Christophe 		else
201337b5e889SLEROY Christophe 			offset = nbytes_to_hash - req_ctx->nbuf;
201437b5e889SLEROY Christophe 		nents = sg_nents_for_len(areq->src, offset);
201537b5e889SLEROY Christophe 		if (nents < 0) {
201637b5e889SLEROY Christophe 			dev_err(ctx->dev, "Invalid number of src SG.\n");
201737b5e889SLEROY Christophe 			return nents;
201837b5e889SLEROY Christophe 		}
201937b5e889SLEROY Christophe 		sg_copy_to_buffer(areq->src, nents,
20203c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, offset);
202137b5e889SLEROY Christophe 		req_ctx->nbuf += offset;
202237b5e889SLEROY Christophe 		req_ctx->psrc = areq->src;
20235e833bc4SLee Nipper 	} else
20245e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
20255e833bc4SLee Nipper 
2026497f2e6bSLee Nipper 	if (to_hash_later) {
20278e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
20288e409fe1SLABBE Corentin 		if (nents < 0) {
20298e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
20308e409fe1SLABBE Corentin 			return nents;
20318e409fe1SLABBE Corentin 		}
2032d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
20333c0dd190SLEROY Christophe 				   req_ctx->buf[(req_ctx->buf_idx + 1) & 1],
2034497f2e6bSLee Nipper 				      to_hash_later,
2035497f2e6bSLee Nipper 				      nbytes - to_hash_later);
2036497f2e6bSLee Nipper 	}
2037497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
2038497f2e6bSLee Nipper 
20395e833bc4SLee Nipper 	/* Allocate extended descriptor */
2040497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
2041497f2e6bSLee Nipper 	if (IS_ERR(edesc))
2042497f2e6bSLee Nipper 		return PTR_ERR(edesc);
2043497f2e6bSLee Nipper 
2044497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
2045497f2e6bSLee Nipper 
2046497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
2047497f2e6bSLee Nipper 	if (req_ctx->last)
2048497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
2049497f2e6bSLee Nipper 	else
2050497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
2051497f2e6bSLee Nipper 
205260f208d7SKim Phillips 	/* request SEC to INIT hash. */
205360f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
2054497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
2055497f2e6bSLee Nipper 
2056497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
2057497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
2058497f2e6bSLee Nipper 	 */
2059497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
2060497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
2061497f2e6bSLee Nipper 
206237b5e889SLEROY Christophe 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, offset,
2063497f2e6bSLee Nipper 				    ahash_done);
2064497f2e6bSLee Nipper }
2065497f2e6bSLee Nipper 
2066497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
2067497f2e6bSLee Nipper {
2068497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2069497f2e6bSLee Nipper 
2070497f2e6bSLee Nipper 	req_ctx->last = 0;
2071497f2e6bSLee Nipper 
2072497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2073497f2e6bSLee Nipper }
2074497f2e6bSLee Nipper 
2075497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
2076497f2e6bSLee Nipper {
2077497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2078497f2e6bSLee Nipper 
2079497f2e6bSLee Nipper 	req_ctx->last = 1;
2080497f2e6bSLee Nipper 
2081497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
2082497f2e6bSLee Nipper }
2083497f2e6bSLee Nipper 
2084497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
2085497f2e6bSLee Nipper {
2086497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2087497f2e6bSLee Nipper 
2088497f2e6bSLee Nipper 	req_ctx->last = 1;
2089497f2e6bSLee Nipper 
2090497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2091497f2e6bSLee Nipper }
2092497f2e6bSLee Nipper 
2093497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
2094497f2e6bSLee Nipper {
2095497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
209660f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2097497f2e6bSLee Nipper 
209860f208d7SKim Phillips 	ahash->init(areq);
2099497f2e6bSLee Nipper 	req_ctx->last = 1;
2100497f2e6bSLee Nipper 
2101497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2102497f2e6bSLee Nipper }
2103497f2e6bSLee Nipper 
21043639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
21053639ca84SHoria Geant? {
21063639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21073639ca84SHoria Geant? 	struct talitos_export_state *export = out;
21083639ca84SHoria Geant? 
21093639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
21103639ca84SHoria Geant? 	       req_ctx->hw_context_size);
21113c0dd190SLEROY Christophe 	memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf);
21123639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
21133639ca84SHoria Geant? 	export->first = req_ctx->first;
21143639ca84SHoria Geant? 	export->last = req_ctx->last;
21153639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
21163639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
21173639ca84SHoria Geant? 
21183639ca84SHoria Geant? 	return 0;
21193639ca84SHoria Geant? }
21203639ca84SHoria Geant? 
21213639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
21223639ca84SHoria Geant? {
21233639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21243639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
21253639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
212649f9783bSLEROY Christophe 	unsigned int size;
21273639ca84SHoria Geant? 
21283639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
212949f9783bSLEROY Christophe 	size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
21303639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
21313639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
213249f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
213349f9783bSLEROY Christophe 	memcpy(req_ctx->hw_context, export->hw_context, size);
21343c0dd190SLEROY Christophe 	memcpy(req_ctx->buf[0], export->buf, export->nbuf);
21353639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
21363639ca84SHoria Geant? 	req_ctx->first = export->first;
21373639ca84SHoria Geant? 	req_ctx->last = export->last;
21383639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
21393639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
21403639ca84SHoria Geant? 
21413639ca84SHoria Geant? 	return 0;
21423639ca84SHoria Geant? }
21433639ca84SHoria Geant? 
214479b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
214579b3a418SLee Nipper 		   u8 *hash)
214679b3a418SLee Nipper {
214779b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
214879b3a418SLee Nipper 
214979b3a418SLee Nipper 	struct scatterlist sg[1];
215079b3a418SLee Nipper 	struct ahash_request *req;
2151f1c90ac3SGilad Ben-Yossef 	struct crypto_wait wait;
215279b3a418SLee Nipper 	int ret;
215379b3a418SLee Nipper 
2154f1c90ac3SGilad Ben-Yossef 	crypto_init_wait(&wait);
215579b3a418SLee Nipper 
215679b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
215779b3a418SLee Nipper 	if (!req)
215879b3a418SLee Nipper 		return -ENOMEM;
215979b3a418SLee Nipper 
216079b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
216179b3a418SLee Nipper 	ctx->keylen = 0;
216279b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
2163f1c90ac3SGilad Ben-Yossef 				   crypto_req_done, &wait);
216479b3a418SLee Nipper 
216579b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
216679b3a418SLee Nipper 
216779b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
2168f1c90ac3SGilad Ben-Yossef 	ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
2169f1c90ac3SGilad Ben-Yossef 
217079b3a418SLee Nipper 	ahash_request_free(req);
217179b3a418SLee Nipper 
217279b3a418SLee Nipper 	return ret;
217379b3a418SLee Nipper }
217479b3a418SLee Nipper 
217579b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
217679b3a418SLee Nipper 			unsigned int keylen)
217779b3a418SLee Nipper {
217879b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
21792e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
218079b3a418SLee Nipper 	unsigned int blocksize =
218179b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
218279b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
218379b3a418SLee Nipper 	unsigned int keysize = keylen;
218479b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
218579b3a418SLee Nipper 	int ret;
218679b3a418SLee Nipper 
218779b3a418SLee Nipper 	if (keylen <= blocksize)
218879b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
218979b3a418SLee Nipper 	else {
219079b3a418SLee Nipper 		/* Must get the hash of the long key */
219179b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
219279b3a418SLee Nipper 
219379b3a418SLee Nipper 		if (ret) {
219479b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
219579b3a418SLee Nipper 			return -EINVAL;
219679b3a418SLee Nipper 		}
219779b3a418SLee Nipper 
219879b3a418SLee Nipper 		keysize = digestsize;
219979b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
220079b3a418SLee Nipper 	}
220179b3a418SLee Nipper 
22022e13ce08SLEROY Christophe 	if (ctx->keylen)
22032e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
22042e13ce08SLEROY Christophe 
220579b3a418SLee Nipper 	ctx->keylen = keysize;
22062e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE);
220779b3a418SLee Nipper 
220879b3a418SLee Nipper 	return 0;
220979b3a418SLee Nipper }
221079b3a418SLee Nipper 
221179b3a418SLee Nipper 
22129c4a7965SKim Phillips struct talitos_alg_template {
2213d5e4aaefSLee Nipper 	u32 type;
2214b0057763SLEROY Christophe 	u32 priority;
2215d5e4aaefSLee Nipper 	union {
2216d5e4aaefSLee Nipper 		struct crypto_alg crypto;
2217acbf7c62SLee Nipper 		struct ahash_alg hash;
2218aeb4c132SHerbert Xu 		struct aead_alg aead;
2219d5e4aaefSLee Nipper 	} alg;
22209c4a7965SKim Phillips 	__be32 desc_hdr_template;
22219c4a7965SKim Phillips };
22229c4a7965SKim Phillips 
22239c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2224991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2225d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2226aeb4c132SHerbert Xu 		.alg.aead = {
2227aeb4c132SHerbert Xu 			.base = {
222856af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2229aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2230aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
223156af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2232aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2233aeb4c132SHerbert Xu 			},
22343952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
22353952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
22369c4a7965SKim Phillips 		},
22379c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
22389c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
22399c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
22409c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
22419c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
22429c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
22439c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
224470bcaca7SLee Nipper 	},
2245d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
22467405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22477405c8d7SLEROY Christophe 		.alg.aead = {
22487405c8d7SLEROY Christophe 			.base = {
22497405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
22507405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
22517405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
22527405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
22537405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22547405c8d7SLEROY Christophe 			},
22557405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
22567405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
22577405c8d7SLEROY Christophe 		},
22587405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
22597405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
22607405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
22617405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
22627405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
22637405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
22647405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
22657405c8d7SLEROY Christophe 	},
22667405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2267aeb4c132SHerbert Xu 		.alg.aead = {
2268aeb4c132SHerbert Xu 			.base = {
2269aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2270aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2271aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2272aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
227356af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2274aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2275aeb4c132SHerbert Xu 			},
22763952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
22773952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
227870bcaca7SLee Nipper 		},
227970bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
228070bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
228170bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
228270bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
228370bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
228470bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
228570bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
228670bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
22873952f17eSLee Nipper 	},
2288d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
22897405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22907405c8d7SLEROY Christophe 		.alg.aead = {
22917405c8d7SLEROY Christophe 			.base = {
22927405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),"
22937405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
22947405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
22957405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
22967405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
22977405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22987405c8d7SLEROY Christophe 			},
22997405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
23007405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
23017405c8d7SLEROY Christophe 		},
23027405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23037405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
23047405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
23057405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
23067405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23077405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23087405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23097405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23107405c8d7SLEROY Christophe 	},
23117405c8d7SLEROY Christophe 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2312aeb4c132SHerbert Xu 		.alg.aead = {
2313aeb4c132SHerbert Xu 			.base = {
2314357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2315aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2316aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2317357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2318aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2319aeb4c132SHerbert Xu 			},
2320357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2321357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2322357fb605SHoria Geanta 		},
2323357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2324357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2325357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2326357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2327357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2328357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2329357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2330357fb605SHoria Geanta 	},
2331357fb605SHoria Geanta 	{       .type = CRYPTO_ALG_TYPE_AEAD,
23327405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23337405c8d7SLEROY Christophe 		.alg.aead = {
23347405c8d7SLEROY Christophe 			.base = {
23357405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
23367405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
23377405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
23387405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
23397405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23407405c8d7SLEROY Christophe 			},
23417405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
23427405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
23437405c8d7SLEROY Christophe 		},
23447405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23457405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23467405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23477405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23487405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23497405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23507405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
23517405c8d7SLEROY Christophe 	},
23527405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2353aeb4c132SHerbert Xu 		.alg.aead = {
2354aeb4c132SHerbert Xu 			.base = {
2355aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2356aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2357aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2358aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2359357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2360aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2361aeb4c132SHerbert Xu 			},
2362357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2363357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2364357fb605SHoria Geanta 		},
2365357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2366357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2367357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2368357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2369357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2370357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2371357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2372357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2373357fb605SHoria Geanta 	},
2374357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23757405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23767405c8d7SLEROY Christophe 		.alg.aead = {
23777405c8d7SLEROY Christophe 			.base = {
23787405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),"
23797405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
23807405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
23817405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
23827405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
23837405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23847405c8d7SLEROY Christophe 			},
23857405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
23867405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
23877405c8d7SLEROY Christophe 		},
23887405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23897405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
23907405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
23917405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
23927405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23937405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23947405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23957405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
23967405c8d7SLEROY Christophe 	},
23977405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2398aeb4c132SHerbert Xu 		.alg.aead = {
2399aeb4c132SHerbert Xu 			.base = {
240056af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2401aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2402aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
240356af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2404aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2405aeb4c132SHerbert Xu 			},
24063952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
24073952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
24083952f17eSLee Nipper 		},
24093952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24103952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
24113952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
24123952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
24133952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
24143952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
24153952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24163952f17eSLee Nipper 	},
2417d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24187405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24197405c8d7SLEROY Christophe 		.alg.aead = {
24207405c8d7SLEROY Christophe 			.base = {
24217405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
24227405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
24237405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
24247405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
24257405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24267405c8d7SLEROY Christophe 			},
24277405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
24287405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
24297405c8d7SLEROY Christophe 		},
24307405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24317405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
24327405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
24337405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24347405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24357405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24367405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24377405c8d7SLEROY Christophe 	},
24387405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2439aeb4c132SHerbert Xu 		.alg.aead = {
2440aeb4c132SHerbert Xu 			.base = {
2441aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2442aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2443aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2444aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
244556af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2446aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2447aeb4c132SHerbert Xu 			},
24483952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
24493952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
24503952f17eSLee Nipper 		},
24513952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24523952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
24533952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
24543952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
24553952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
24563952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
24573952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
24583952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24593952f17eSLee Nipper 	},
2460d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24617405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24627405c8d7SLEROY Christophe 		.alg.aead = {
24637405c8d7SLEROY Christophe 			.base = {
24647405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),"
24657405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
24667405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
24677405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
24687405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24697405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24707405c8d7SLEROY Christophe 			},
24717405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
24727405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
24737405c8d7SLEROY Christophe 		},
24747405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24757405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24767405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
24777405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
24787405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24797405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24807405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24817405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24827405c8d7SLEROY Christophe 	},
24837405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2484aeb4c132SHerbert Xu 		.alg.aead = {
2485aeb4c132SHerbert Xu 			.base = {
2486357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2487aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2488aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2489357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2490aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2491aeb4c132SHerbert Xu 			},
2492357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2493357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2494357fb605SHoria Geanta 		},
2495357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2496357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2497357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2498357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2499357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2500357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2501357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2502357fb605SHoria Geanta 	},
2503357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2504aeb4c132SHerbert Xu 		.alg.aead = {
2505aeb4c132SHerbert Xu 			.base = {
2506aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2507aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2508aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2509aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2510357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2511aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2512aeb4c132SHerbert Xu 			},
2513357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2514357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2515357fb605SHoria Geanta 		},
2516357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2517357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2518357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2519357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2520357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2521357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2522357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2523357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2524357fb605SHoria Geanta 	},
2525357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2526aeb4c132SHerbert Xu 		.alg.aead = {
2527aeb4c132SHerbert Xu 			.base = {
2528357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2529aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2530aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2531357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2532aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2533aeb4c132SHerbert Xu 			},
2534357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2535357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2536357fb605SHoria Geanta 		},
2537357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2538357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2539357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2540357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2541357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2542357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2543357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2544357fb605SHoria Geanta 	},
2545357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2546aeb4c132SHerbert Xu 		.alg.aead = {
2547aeb4c132SHerbert Xu 			.base = {
2548aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2549aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2550aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2551aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2552357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2553aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2554aeb4c132SHerbert Xu 			},
2555357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2556357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2557357fb605SHoria Geanta 		},
2558357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2559357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2560357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2561357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2562357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2563357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2564357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2565357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2566357fb605SHoria Geanta 	},
2567357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2568aeb4c132SHerbert Xu 		.alg.aead = {
2569aeb4c132SHerbert Xu 			.base = {
257056af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2571aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2572aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
257356af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2574aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2575aeb4c132SHerbert Xu 			},
25763952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
25773952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
25783952f17eSLee Nipper 		},
25793952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25803952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
25813952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
25823952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25833952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25843952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25853952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
25863952f17eSLee Nipper 	},
2587d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25887405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25897405c8d7SLEROY Christophe 		.alg.aead = {
25907405c8d7SLEROY Christophe 			.base = {
25917405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(aes))",
25927405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
25937405c8d7SLEROY Christophe 						   "cbc-aes-talitos",
25947405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
25957405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25967405c8d7SLEROY Christophe 			},
25977405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
25987405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
25997405c8d7SLEROY Christophe 		},
26007405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
26017405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
26027405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
26037405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
26047405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
26057405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
26067405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26077405c8d7SLEROY Christophe 	},
26087405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2609aeb4c132SHerbert Xu 		.alg.aead = {
2610aeb4c132SHerbert Xu 			.base = {
261156af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2612aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2613aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
261456af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2615aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2616aeb4c132SHerbert Xu 			},
26173952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
26183952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
26193952f17eSLee Nipper 		},
26203952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26213952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
26223952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
26233952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
26243952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26253952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
26263952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
26273952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26284de9d0b5SLee Nipper 	},
26297405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
26307405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26317405c8d7SLEROY Christophe 		.alg.aead = {
26327405c8d7SLEROY Christophe 			.base = {
26337405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
26347405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
26357405c8d7SLEROY Christophe 						   "cbc-3des-talitos",
26367405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26377405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
26387405c8d7SLEROY Christophe 			},
26397405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
26407405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
26417405c8d7SLEROY Christophe 		},
26427405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
26437405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
26447405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
26457405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
26467405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
26477405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
26487405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
26497405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26507405c8d7SLEROY Christophe 	},
26514de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2652d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2653d5e4aaefSLee Nipper 		.alg.crypto = {
26545e75ae1bSLEROY Christophe 			.cra_name = "ecb(aes)",
26555e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-aes-talitos",
26565e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
26575e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26585e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26595e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26605e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
26615e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
26625e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
26635e75ae1bSLEROY Christophe 			}
26645e75ae1bSLEROY Christophe 		},
26655e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26665e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
26675e75ae1bSLEROY Christophe 	},
26685e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
26695e75ae1bSLEROY Christophe 		.alg.crypto = {
26704de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
26714de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
26724de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
26734de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26744de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
26754de9d0b5SLee Nipper 			.cra_ablkcipher = {
26764de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
26774de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
26784de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
26794de9d0b5SLee Nipper 			}
26804de9d0b5SLee Nipper 		},
26814de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
26824de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
26834de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
26844de9d0b5SLee Nipper 	},
2685d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2686d5e4aaefSLee Nipper 		.alg.crypto = {
26875e75ae1bSLEROY Christophe 			.cra_name = "ctr(aes)",
26885e75ae1bSLEROY Christophe 			.cra_driver_name = "ctr-aes-talitos",
26895e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
26905e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
26915e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
26925e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
26935e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
26945e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
26955e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
26965e75ae1bSLEROY Christophe 			}
26975e75ae1bSLEROY Christophe 		},
269870d355ccSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
26995e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
27005e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
27015e75ae1bSLEROY Christophe 	},
27025e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27035e75ae1bSLEROY Christophe 		.alg.crypto = {
27045e75ae1bSLEROY Christophe 			.cra_name = "ecb(des)",
27055e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-des-talitos",
27065e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
27075e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27085e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27095e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27105e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
27115e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
27125e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
27135e75ae1bSLEROY Christophe 			}
27145e75ae1bSLEROY Christophe 		},
27155e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27165e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
27175e75ae1bSLEROY Christophe 	},
27185e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27195e75ae1bSLEROY Christophe 		.alg.crypto = {
27205e75ae1bSLEROY Christophe 			.cra_name = "cbc(des)",
27215e75ae1bSLEROY Christophe 			.cra_driver_name = "cbc-des-talitos",
27225e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
27235e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27245e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27255e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27265e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
27275e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
27285e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
27295e75ae1bSLEROY Christophe 			}
27305e75ae1bSLEROY Christophe 		},
27315e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27325e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
27335e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
27345e75ae1bSLEROY Christophe 	},
27355e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27365e75ae1bSLEROY Christophe 		.alg.crypto = {
27375e75ae1bSLEROY Christophe 			.cra_name = "ecb(des3_ede)",
27385e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-3des-talitos",
27395e75ae1bSLEROY Christophe 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
27405e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27415e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27425e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27435e75ae1bSLEROY Christophe 				.min_keysize = DES3_EDE_KEY_SIZE,
27445e75ae1bSLEROY Christophe 				.max_keysize = DES3_EDE_KEY_SIZE,
27455e75ae1bSLEROY Christophe 				.ivsize = DES3_EDE_BLOCK_SIZE,
27465e75ae1bSLEROY Christophe 			}
27475e75ae1bSLEROY Christophe 		},
27485e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27495e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
27505e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
27515e75ae1bSLEROY Christophe 	},
27525e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27535e75ae1bSLEROY Christophe 		.alg.crypto = {
27544de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
27554de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
27564de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
27574de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27584de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
27594de9d0b5SLee Nipper 			.cra_ablkcipher = {
27604de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
27614de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
27624de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
27634de9d0b5SLee Nipper 			}
27644de9d0b5SLee Nipper 		},
27654de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27664de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
27674de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
27684de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2769497f2e6bSLee Nipper 	},
2770497f2e6bSLee Nipper 	/* AHASH algorithms. */
2771497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2772497f2e6bSLee Nipper 		.alg.hash = {
2773497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
27743639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2775497f2e6bSLee Nipper 			.halg.base = {
2776497f2e6bSLee Nipper 				.cra_name = "md5",
2777497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2778b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2779497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2780497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
27819c4a7965SKim Phillips 			}
2782497f2e6bSLee Nipper 		},
2783497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2784497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2785497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2786497f2e6bSLee Nipper 	},
2787497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2788497f2e6bSLee Nipper 		.alg.hash = {
2789497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
27903639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2791497f2e6bSLee Nipper 			.halg.base = {
2792497f2e6bSLee Nipper 				.cra_name = "sha1",
2793497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2794497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2795497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2796497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2797497f2e6bSLee Nipper 			}
2798497f2e6bSLee Nipper 		},
2799497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2800497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2801497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2802497f2e6bSLee Nipper 	},
2803497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2804497f2e6bSLee Nipper 		.alg.hash = {
280560f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
28063639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
280760f208d7SKim Phillips 			.halg.base = {
280860f208d7SKim Phillips 				.cra_name = "sha224",
280960f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
281060f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
281160f208d7SKim Phillips 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
281260f208d7SKim Phillips 					     CRYPTO_ALG_ASYNC,
281360f208d7SKim Phillips 			}
281460f208d7SKim Phillips 		},
281560f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
281660f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
281760f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
281860f208d7SKim Phillips 	},
281960f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
282060f208d7SKim Phillips 		.alg.hash = {
2821497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
28223639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2823497f2e6bSLee Nipper 			.halg.base = {
2824497f2e6bSLee Nipper 				.cra_name = "sha256",
2825497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2826497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2827497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2828497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2829497f2e6bSLee Nipper 			}
2830497f2e6bSLee Nipper 		},
2831497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2832497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2833497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2834497f2e6bSLee Nipper 	},
2835497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2836497f2e6bSLee Nipper 		.alg.hash = {
2837497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
28383639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2839497f2e6bSLee Nipper 			.halg.base = {
2840497f2e6bSLee Nipper 				.cra_name = "sha384",
2841497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2842497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
2843497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2844497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2845497f2e6bSLee Nipper 			}
2846497f2e6bSLee Nipper 		},
2847497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2848497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2849497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2850497f2e6bSLee Nipper 	},
2851497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2852497f2e6bSLee Nipper 		.alg.hash = {
2853497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
28543639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2855497f2e6bSLee Nipper 			.halg.base = {
2856497f2e6bSLee Nipper 				.cra_name = "sha512",
2857497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2858497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
2859497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2860497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2861497f2e6bSLee Nipper 			}
2862497f2e6bSLee Nipper 		},
2863497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2864497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2865497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2866497f2e6bSLee Nipper 	},
286779b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
286879b3a418SLee Nipper 		.alg.hash = {
286979b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
28703639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
287179b3a418SLee Nipper 			.halg.base = {
287279b3a418SLee Nipper 				.cra_name = "hmac(md5)",
287379b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2874b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
287579b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
287679b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
287779b3a418SLee Nipper 			}
287879b3a418SLee Nipper 		},
287979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
288079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
288179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
288279b3a418SLee Nipper 	},
288379b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
288479b3a418SLee Nipper 		.alg.hash = {
288579b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
28863639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
288779b3a418SLee Nipper 			.halg.base = {
288879b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
288979b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
289079b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
289179b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
289279b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
289379b3a418SLee Nipper 			}
289479b3a418SLee Nipper 		},
289579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
289679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
289779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
289879b3a418SLee Nipper 	},
289979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
290079b3a418SLee Nipper 		.alg.hash = {
290179b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
29023639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
290379b3a418SLee Nipper 			.halg.base = {
290479b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
290579b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
290679b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
290779b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
290879b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
290979b3a418SLee Nipper 			}
291079b3a418SLee Nipper 		},
291179b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
291279b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
291379b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
291479b3a418SLee Nipper 	},
291579b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
291679b3a418SLee Nipper 		.alg.hash = {
291779b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
29183639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
291979b3a418SLee Nipper 			.halg.base = {
292079b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
292179b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
292279b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
292379b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
292479b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
292579b3a418SLee Nipper 			}
292679b3a418SLee Nipper 		},
292779b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
292879b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
292979b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
293079b3a418SLee Nipper 	},
293179b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
293279b3a418SLee Nipper 		.alg.hash = {
293379b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
29343639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
293579b3a418SLee Nipper 			.halg.base = {
293679b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
293779b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
293879b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
293979b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
294079b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
294179b3a418SLee Nipper 			}
294279b3a418SLee Nipper 		},
294379b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
294479b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
294579b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
294679b3a418SLee Nipper 	},
294779b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
294879b3a418SLee Nipper 		.alg.hash = {
294979b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
29503639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
295179b3a418SLee Nipper 			.halg.base = {
295279b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
295379b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
295479b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
295579b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
295679b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
295779b3a418SLee Nipper 			}
295879b3a418SLee Nipper 		},
295979b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
296079b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
296179b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
296279b3a418SLee Nipper 	}
29639c4a7965SKim Phillips };
29649c4a7965SKim Phillips 
29659c4a7965SKim Phillips struct talitos_crypto_alg {
29669c4a7965SKim Phillips 	struct list_head entry;
29679c4a7965SKim Phillips 	struct device *dev;
2968acbf7c62SLee Nipper 	struct talitos_alg_template algt;
29699c4a7965SKim Phillips };
29709c4a7965SKim Phillips 
297189d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
297289d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
29739c4a7965SKim Phillips {
29745228f0f7SKim Phillips 	struct talitos_private *priv;
29759c4a7965SKim Phillips 
29769c4a7965SKim Phillips 	/* update context with ptr to dev */
29779c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
297819bbbc63SKim Phillips 
29795228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
29805228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
29815228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
29825228f0f7SKim Phillips 		  (priv->num_channels - 1);
29835228f0f7SKim Phillips 
29849c4a7965SKim Phillips 	/* copy descriptor header template value */
2985acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
29869c4a7965SKim Phillips 
2987602dba5aSKim Phillips 	/* select done notification */
2988602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
2989602dba5aSKim Phillips 
2990497f2e6bSLee Nipper 	return 0;
2991497f2e6bSLee Nipper }
2992497f2e6bSLee Nipper 
299389d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm)
299489d124cbSJonas Eymann {
299589d124cbSJonas Eymann 	struct crypto_alg *alg = tfm->__crt_alg;
299689d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
299789d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
299889d124cbSJonas Eymann 
299989d124cbSJonas Eymann 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
300089d124cbSJonas Eymann 		talitos_alg = container_of(__crypto_ahash_alg(alg),
300189d124cbSJonas Eymann 					   struct talitos_crypto_alg,
300289d124cbSJonas Eymann 					   algt.alg.hash);
300389d124cbSJonas Eymann 	else
300489d124cbSJonas Eymann 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
300589d124cbSJonas Eymann 					   algt.alg.crypto);
300689d124cbSJonas Eymann 
300789d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
300889d124cbSJonas Eymann }
300989d124cbSJonas Eymann 
3010aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
3011497f2e6bSLee Nipper {
301289d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
301389d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
301489d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
301589d124cbSJonas Eymann 
301689d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
301789d124cbSJonas Eymann 				   algt.alg.aead);
301889d124cbSJonas Eymann 
301989d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
30209c4a7965SKim Phillips }
30219c4a7965SKim Phillips 
3022497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
3023497f2e6bSLee Nipper {
3024497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
3025497f2e6bSLee Nipper 
3026497f2e6bSLee Nipper 	talitos_cra_init(tfm);
3027497f2e6bSLee Nipper 
3028497f2e6bSLee Nipper 	ctx->keylen = 0;
3029497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
3030497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
3031497f2e6bSLee Nipper 
3032497f2e6bSLee Nipper 	return 0;
3033497f2e6bSLee Nipper }
3034497f2e6bSLee Nipper 
30352e13ce08SLEROY Christophe static void talitos_cra_exit(struct crypto_tfm *tfm)
30362e13ce08SLEROY Christophe {
30372e13ce08SLEROY Christophe 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
30382e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
30392e13ce08SLEROY Christophe 
30402e13ce08SLEROY Christophe 	if (ctx->keylen)
30412e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
30422e13ce08SLEROY Christophe }
30432e13ce08SLEROY Christophe 
30449c4a7965SKim Phillips /*
30459c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
30469c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
30479c4a7965SKim Phillips  * capabilities description provided in the device tree node.
30489c4a7965SKim Phillips  */
30499c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
30509c4a7965SKim Phillips {
30519c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
30529c4a7965SKim Phillips 	int ret;
30539c4a7965SKim Phillips 
30549c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
30559c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
30569c4a7965SKim Phillips 
30579c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
30589c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
30599c4a7965SKim Phillips 		              & priv->exec_units);
30609c4a7965SKim Phillips 
30619c4a7965SKim Phillips 	return ret;
30629c4a7965SKim Phillips }
30639c4a7965SKim Phillips 
30642dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
30659c4a7965SKim Phillips {
30669c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
30679c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
30689c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
30699c4a7965SKim Phillips 	int i;
30709c4a7965SKim Phillips 
30719c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
3072acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
3073acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
3074acbf7c62SLee Nipper 			break;
3075aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
3076aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
3077acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
3078acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
3079acbf7c62SLee Nipper 			break;
3080acbf7c62SLee Nipper 		}
30819c4a7965SKim Phillips 		list_del(&t_alg->entry);
30829c4a7965SKim Phillips 	}
30839c4a7965SKim Phillips 
30849c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
30859c4a7965SKim Phillips 		talitos_unregister_rng(dev);
30869c4a7965SKim Phillips 
3087c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
30882cdba3cfSKim Phillips 		if (priv->irq[i]) {
3089c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
3090c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
30919c4a7965SKim Phillips 		}
30929c4a7965SKim Phillips 
3093c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
30942cdba3cfSKim Phillips 	if (priv->irq[1])
3095c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
30969c4a7965SKim Phillips 
30979c4a7965SKim Phillips 	return 0;
30989c4a7965SKim Phillips }
30999c4a7965SKim Phillips 
31009c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
31019c4a7965SKim Phillips 						    struct talitos_alg_template
31029c4a7965SKim Phillips 						           *template)
31039c4a7965SKim Phillips {
310460f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31059c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
31069c4a7965SKim Phillips 	struct crypto_alg *alg;
31079c4a7965SKim Phillips 
310824b92ff2SLEROY Christophe 	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
310924b92ff2SLEROY Christophe 			     GFP_KERNEL);
31109c4a7965SKim Phillips 	if (!t_alg)
31119c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
31129c4a7965SKim Phillips 
3113acbf7c62SLee Nipper 	t_alg->algt = *template;
3114acbf7c62SLee Nipper 
3115acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
3116acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
3117497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
3118497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
31192e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3120d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
3121b286e003SKim Phillips 		alg->cra_ablkcipher.setkey = ablkcipher_setkey;
3122b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
3123b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
3124b286e003SKim Phillips 		alg->cra_ablkcipher.geniv = "eseqiv";
3125497f2e6bSLee Nipper 		break;
3126acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
3127aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
31282e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3129aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
3130aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.setkey = aead_setkey;
3131aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
3132aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
31336cda075aSLEROY Christophe 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
31346cda075aSLEROY Christophe 		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
313524b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
31366cda075aSLEROY Christophe 			return ERR_PTR(-ENOTSUPP);
31376cda075aSLEROY Christophe 		}
3138acbf7c62SLee Nipper 		break;
3139acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
3140acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
3141497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
3142*ad4cd51fSLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3143d4cd3283SKim Phillips 		alg->cra_type = &crypto_ahash_type;
3144b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
3145b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
3146b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
3147b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
3148b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
314956136631SLEROY Christophe 		if (!strncmp(alg->cra_name, "hmac", 4))
3150b286e003SKim Phillips 			t_alg->algt.alg.hash.setkey = ahash_setkey;
31513639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
31523639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
3153b286e003SKim Phillips 
315479b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
31550b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
315624b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
315779b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
31580b2730d8SKim Phillips 		}
315960f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
316079b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
316179b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
316260f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
316360f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
316460f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
316560f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
316660f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
316760f208d7SKim Phillips 		}
3168497f2e6bSLee Nipper 		break;
31691d11911aSKim Phillips 	default:
31701d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
317124b92ff2SLEROY Christophe 		devm_kfree(dev, t_alg);
31721d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
3173acbf7c62SLee Nipper 	}
31749c4a7965SKim Phillips 
31759c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
3176b0057763SLEROY Christophe 	if (t_alg->algt.priority)
3177b0057763SLEROY Christophe 		alg->cra_priority = t_alg->algt.priority;
3178b0057763SLEROY Christophe 	else
31799c4a7965SKim Phillips 		alg->cra_priority = TALITOS_CRA_PRIORITY;
31809c4a7965SKim Phillips 	alg->cra_alignmask = 0;
31819c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
3182d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
31839c4a7965SKim Phillips 
31849c4a7965SKim Phillips 	t_alg->dev = dev;
31859c4a7965SKim Phillips 
31869c4a7965SKim Phillips 	return t_alg;
31879c4a7965SKim Phillips }
31889c4a7965SKim Phillips 
3189c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
3190c3e337f8SKim Phillips {
3191c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
3192c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
3193c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3194c3e337f8SKim Phillips 	int err;
3195dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3196c3e337f8SKim Phillips 
3197c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
31982cdba3cfSKim Phillips 	if (!priv->irq[0]) {
3199c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
3200c3e337f8SKim Phillips 		return -EINVAL;
3201c3e337f8SKim Phillips 	}
3202dd3c0987SLEROY Christophe 	if (is_sec1) {
3203dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
3204dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
3205dd3c0987SLEROY Christophe 		goto primary_out;
3206dd3c0987SLEROY Christophe 	}
3207c3e337f8SKim Phillips 
3208c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
3209c3e337f8SKim Phillips 
3210c3e337f8SKim Phillips 	/* get the primary irq line */
32112cdba3cfSKim Phillips 	if (!priv->irq[1]) {
3212dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
3213c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
3214c3e337f8SKim Phillips 		goto primary_out;
3215c3e337f8SKim Phillips 	}
3216c3e337f8SKim Phillips 
3217dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
3218c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3219c3e337f8SKim Phillips 	if (err)
3220c3e337f8SKim Phillips 		goto primary_out;
3221c3e337f8SKim Phillips 
3222c3e337f8SKim Phillips 	/* get the secondary irq line */
3223dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
3224c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3225c3e337f8SKim Phillips 	if (err) {
3226c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
3227c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
32282cdba3cfSKim Phillips 		priv->irq[1] = 0;
3229c3e337f8SKim Phillips 	}
3230c3e337f8SKim Phillips 
3231c3e337f8SKim Phillips 	return err;
3232c3e337f8SKim Phillips 
3233c3e337f8SKim Phillips primary_out:
3234c3e337f8SKim Phillips 	if (err) {
3235c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
3236c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
32372cdba3cfSKim Phillips 		priv->irq[0] = 0;
3238c3e337f8SKim Phillips 	}
3239c3e337f8SKim Phillips 
3240c3e337f8SKim Phillips 	return err;
3241c3e337f8SKim Phillips }
3242c3e337f8SKim Phillips 
32431c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
32449c4a7965SKim Phillips {
32459c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
324661c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
32479c4a7965SKim Phillips 	struct talitos_private *priv;
32489c4a7965SKim Phillips 	int i, err;
32495fa7fa14SLEROY Christophe 	int stride;
3250fd5ea7f0SLEROY Christophe 	struct resource *res;
32519c4a7965SKim Phillips 
325224b92ff2SLEROY Christophe 	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
32539c4a7965SKim Phillips 	if (!priv)
32549c4a7965SKim Phillips 		return -ENOMEM;
32559c4a7965SKim Phillips 
3256f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
3257f3de9cb1SKevin Hao 
32589c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
32599c4a7965SKim Phillips 
32609c4a7965SKim Phillips 	priv->ofdev = ofdev;
32619c4a7965SKim Phillips 
3262511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
3263511d63cbSHoria Geanta 
3264fd5ea7f0SLEROY Christophe 	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
3265fd5ea7f0SLEROY Christophe 	if (!res)
3266fd5ea7f0SLEROY Christophe 		return -ENXIO;
3267fd5ea7f0SLEROY Christophe 	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
32689c4a7965SKim Phillips 	if (!priv->reg) {
32699c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
32709c4a7965SKim Phillips 		err = -ENOMEM;
32719c4a7965SKim Phillips 		goto err_out;
32729c4a7965SKim Phillips 	}
32739c4a7965SKim Phillips 
32749c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
3275fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
3276fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
3277fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
3278fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,descriptor-types-mask",
3279fa14c6cfSLEROY Christophe 			     &priv->desc_types);
32809c4a7965SKim Phillips 
32819c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
32829c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
32839c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
32849c4a7965SKim Phillips 		err = -EINVAL;
32859c4a7965SKim Phillips 		goto err_out;
32869c4a7965SKim Phillips 	}
32879c4a7965SKim Phillips 
3288f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3289f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3290f3c85bc1SLee Nipper 
3291fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
329260f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
329379b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
329479b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3295fe5720e2SKim Phillips 
329621590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
329721590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
329821590888SLEROY Christophe 
32995fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
33005fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
33015fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
33025fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
33035fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
33045fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
33055fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
33065fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
33075fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
33085fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
33095fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
33105fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
33115fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
33125fa7fa14SLEROY Christophe 	} else {
33135fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
33145fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
33155fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
33165fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
33175fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
33185fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
33195fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
33205fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
33215fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
33225fa7fa14SLEROY Christophe 	}
33235fa7fa14SLEROY Christophe 
3324dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3325dd3c0987SLEROY Christophe 	if (err)
3326dd3c0987SLEROY Christophe 		goto err_out;
3327dd3c0987SLEROY Christophe 
3328dd3c0987SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0")) {
33299c02e285SLEROY Christophe 		if (priv->num_channels == 1)
33309c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
33319c02e285SLEROY Christophe 				     (unsigned long)dev);
33329c02e285SLEROY Christophe 		else
3333dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3334dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3335dd3c0987SLEROY Christophe 	} else {
33369c02e285SLEROY Christophe 		if (priv->irq[1]) {
3337dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3338dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3339dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3340dd3c0987SLEROY Christophe 				     (unsigned long)dev);
33419c02e285SLEROY Christophe 		} else if (priv->num_channels == 1) {
33429c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
33439c02e285SLEROY Christophe 				     (unsigned long)dev);
33449c02e285SLEROY Christophe 		} else {
33459c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
33469c02e285SLEROY Christophe 				     (unsigned long)dev);
3347dd3c0987SLEROY Christophe 		}
3348dd3c0987SLEROY Christophe 	}
3349dd3c0987SLEROY Christophe 
335024b92ff2SLEROY Christophe 	priv->chan = devm_kzalloc(dev, sizeof(struct talitos_channel) *
33514b992628SKim Phillips 				       priv->num_channels, GFP_KERNEL);
33524b992628SKim Phillips 	if (!priv->chan) {
33534b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
33549c4a7965SKim Phillips 		err = -ENOMEM;
33559c4a7965SKim Phillips 		goto err_out;
33569c4a7965SKim Phillips 	}
33579c4a7965SKim Phillips 
3358f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3359f641ddddSMartin Hicks 
3360c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
33615fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
33622cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3363c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3364ad42d5fcSKim Phillips 
33654b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
33664b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
33679c4a7965SKim Phillips 
336824b92ff2SLEROY Christophe 		priv->chan[i].fifo = devm_kzalloc(dev,
336924b92ff2SLEROY Christophe 						sizeof(struct talitos_request) *
33709c4a7965SKim Phillips 						priv->fifo_len, GFP_KERNEL);
33714b992628SKim Phillips 		if (!priv->chan[i].fifo) {
33729c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
33739c4a7965SKim Phillips 			err = -ENOMEM;
33749c4a7965SKim Phillips 			goto err_out;
33759c4a7965SKim Phillips 		}
33769c4a7965SKim Phillips 
33774b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
33784b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3379f641ddddSMartin Hicks 	}
33809c4a7965SKim Phillips 
338181eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
338281eb024cSKim Phillips 
33839c4a7965SKim Phillips 	/* reset and initialize the h/w */
33849c4a7965SKim Phillips 	err = init_device(dev);
33859c4a7965SKim Phillips 	if (err) {
33869c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
33879c4a7965SKim Phillips 		goto err_out;
33889c4a7965SKim Phillips 	}
33899c4a7965SKim Phillips 
33909c4a7965SKim Phillips 	/* register the RNG, if available */
33919c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
33929c4a7965SKim Phillips 		err = talitos_register_rng(dev);
33939c4a7965SKim Phillips 		if (err) {
33949c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
33959c4a7965SKim Phillips 			goto err_out;
33969c4a7965SKim Phillips 		} else
33979c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
33989c4a7965SKim Phillips 	}
33999c4a7965SKim Phillips 
34009c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
34019c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
34029c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
34039c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3404aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
34059c4a7965SKim Phillips 
34069c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
34079c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
34089c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
34090b2730d8SKim Phillips 				if (err == -ENOTSUPP)
341079b3a418SLee Nipper 					continue;
34119c4a7965SKim Phillips 				goto err_out;
34129c4a7965SKim Phillips 			}
34139c4a7965SKim Phillips 
3414acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3415acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
3416acbf7c62SLee Nipper 				err = crypto_register_alg(
3417acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
3418aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.crypto;
3419acbf7c62SLee Nipper 				break;
3420aeb4c132SHerbert Xu 
3421aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3422aeb4c132SHerbert Xu 				err = crypto_register_aead(
3423aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3424aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3425aeb4c132SHerbert Xu 				break;
3426aeb4c132SHerbert Xu 
3427acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3428acbf7c62SLee Nipper 				err = crypto_register_ahash(
3429acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3430aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3431acbf7c62SLee Nipper 				break;
3432acbf7c62SLee Nipper 			}
34339c4a7965SKim Phillips 			if (err) {
34349c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3435aeb4c132SHerbert Xu 					alg->cra_driver_name);
343624b92ff2SLEROY Christophe 				devm_kfree(dev, t_alg);
3437991155baSHoria Geanta 			} else
34389c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
34399c4a7965SKim Phillips 		}
34409c4a7965SKim Phillips 	}
34415b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
34425b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
34435b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
34449c4a7965SKim Phillips 
34459c4a7965SKim Phillips 	return 0;
34469c4a7965SKim Phillips 
34479c4a7965SKim Phillips err_out:
34489c4a7965SKim Phillips 	talitos_remove(ofdev);
34499c4a7965SKim Phillips 
34509c4a7965SKim Phillips 	return err;
34519c4a7965SKim Phillips }
34529c4a7965SKim Phillips 
34536c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
34540635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
34550635b7dbSLEROY Christophe 	{
34560635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
34570635b7dbSLEROY Christophe 	},
34580635b7dbSLEROY Christophe #endif
34590635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
34609c4a7965SKim Phillips 	{
34619c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
34629c4a7965SKim Phillips 	},
34630635b7dbSLEROY Christophe #endif
34649c4a7965SKim Phillips 	{},
34659c4a7965SKim Phillips };
34669c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
34679c4a7965SKim Phillips 
34681c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
34694018294bSGrant Likely 	.driver = {
34709c4a7965SKim Phillips 		.name = "talitos",
34714018294bSGrant Likely 		.of_match_table = talitos_match,
34724018294bSGrant Likely 	},
34739c4a7965SKim Phillips 	.probe = talitos_probe,
3474596f1034SAl Viro 	.remove = talitos_remove,
34759c4a7965SKim Phillips };
34769c4a7965SKim Phillips 
3477741e8c2dSAxel Lin module_platform_driver(talitos_driver);
34789c4a7965SKim Phillips 
34799c4a7965SKim Phillips MODULE_LICENSE("GPL");
34809c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
34819c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3482