xref: /linux/drivers/crypto/talitos.c (revision 549bd8bc598759607b5ffc2eb052a3c99a85552e)
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,
59922f9dc8SLEROY Christophe 			   bool is_sec1)
6081eb024cSKim Phillips {
61edc6bd69SLEROY Christophe 	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
62922f9dc8SLEROY Christophe 	if (!is_sec1)
63edc6bd69SLEROY Christophe 		ptr->eptr = upper_32_bits(dma_addr);
6481eb024cSKim Phillips }
6581eb024cSKim Phillips 
66340ff60aSHoria Geant? static void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
67340ff60aSHoria Geant? 			     struct talitos_ptr *src_ptr, bool is_sec1)
68340ff60aSHoria Geant? {
69340ff60aSHoria Geant? 	dst_ptr->ptr = src_ptr->ptr;
70340ff60aSHoria Geant? 	if (!is_sec1)
71340ff60aSHoria Geant? 		dst_ptr->eptr = src_ptr->eptr;
72340ff60aSHoria Geant? }
73340ff60aSHoria Geant? 
7442e8b0d7SHoria Geant? static void to_talitos_ptr_len(struct talitos_ptr *ptr, unsigned int len,
75922f9dc8SLEROY Christophe 			       bool is_sec1)
76538caf83SLEROY Christophe {
77922f9dc8SLEROY Christophe 	if (is_sec1) {
78922f9dc8SLEROY Christophe 		ptr->res = 0;
79922f9dc8SLEROY Christophe 		ptr->len1 = cpu_to_be16(len);
80922f9dc8SLEROY Christophe 	} else {
81538caf83SLEROY Christophe 		ptr->len = cpu_to_be16(len);
82538caf83SLEROY Christophe 	}
83922f9dc8SLEROY Christophe }
84538caf83SLEROY Christophe 
85922f9dc8SLEROY Christophe static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
86922f9dc8SLEROY Christophe 					   bool is_sec1)
87538caf83SLEROY Christophe {
88922f9dc8SLEROY Christophe 	if (is_sec1)
89922f9dc8SLEROY Christophe 		return be16_to_cpu(ptr->len1);
90922f9dc8SLEROY Christophe 	else
91538caf83SLEROY Christophe 		return be16_to_cpu(ptr->len);
92538caf83SLEROY Christophe }
93538caf83SLEROY Christophe 
94b096b544SLEROY Christophe static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
95b096b544SLEROY Christophe 				   bool is_sec1)
96185eb79fSLEROY Christophe {
97922f9dc8SLEROY Christophe 	if (!is_sec1)
98b096b544SLEROY Christophe 		ptr->j_extent = val;
99b096b544SLEROY Christophe }
100b096b544SLEROY Christophe 
101b096b544SLEROY Christophe static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
102b096b544SLEROY Christophe {
103b096b544SLEROY Christophe 	if (!is_sec1)
104b096b544SLEROY Christophe 		ptr->j_extent |= val;
105185eb79fSLEROY Christophe }
106185eb79fSLEROY Christophe 
1079c4a7965SKim Phillips /*
1089c4a7965SKim Phillips  * map virtual single (contiguous) pointer to h/w descriptor pointer
1099c4a7965SKim Phillips  */
1109c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev,
111edc6bd69SLEROY Christophe 				   struct talitos_ptr *ptr,
11242e8b0d7SHoria Geant? 				   unsigned int len, void *data,
1139c4a7965SKim Phillips 				   enum dma_data_direction dir)
1149c4a7965SKim Phillips {
11581eb024cSKim Phillips 	dma_addr_t dma_addr = dma_map_single(dev, data, len, dir);
116922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
117922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
11881eb024cSKim Phillips 
119922f9dc8SLEROY Christophe 	to_talitos_ptr_len(ptr, len, is_sec1);
120922f9dc8SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr, is_sec1);
121b096b544SLEROY Christophe 	to_talitos_ptr_ext_set(ptr, 0, is_sec1);
1229c4a7965SKim Phillips }
1239c4a7965SKim Phillips 
1249c4a7965SKim Phillips /*
1259c4a7965SKim Phillips  * unmap bus single (contiguous) h/w descriptor pointer
1269c4a7965SKim Phillips  */
1279c4a7965SKim Phillips static void unmap_single_talitos_ptr(struct device *dev,
128edc6bd69SLEROY Christophe 				     struct talitos_ptr *ptr,
1299c4a7965SKim Phillips 				     enum dma_data_direction dir)
1309c4a7965SKim Phillips {
131922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
132922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
133922f9dc8SLEROY Christophe 
134edc6bd69SLEROY Christophe 	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
135922f9dc8SLEROY Christophe 			 from_talitos_ptr_len(ptr, is_sec1), dir);
1369c4a7965SKim Phillips }
1379c4a7965SKim Phillips 
1389c4a7965SKim Phillips static int reset_channel(struct device *dev, int ch)
1399c4a7965SKim Phillips {
1409c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1419c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
142dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1439c4a7965SKim Phillips 
144dd3c0987SLEROY Christophe 	if (is_sec1) {
145dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
146dd3c0987SLEROY Christophe 			  TALITOS1_CCCR_LO_RESET);
1479c4a7965SKim Phillips 
148dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
149dd3c0987SLEROY Christophe 			TALITOS1_CCCR_LO_RESET) && --timeout)
1509c4a7965SKim Phillips 			cpu_relax();
151dd3c0987SLEROY Christophe 	} else {
152dd3c0987SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
153dd3c0987SLEROY Christophe 			  TALITOS2_CCCR_RESET);
154dd3c0987SLEROY Christophe 
155dd3c0987SLEROY Christophe 		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
156dd3c0987SLEROY Christophe 			TALITOS2_CCCR_RESET) && --timeout)
157dd3c0987SLEROY Christophe 			cpu_relax();
158dd3c0987SLEROY Christophe 	}
1599c4a7965SKim Phillips 
1609c4a7965SKim Phillips 	if (timeout == 0) {
1619c4a7965SKim Phillips 		dev_err(dev, "failed to reset channel %d\n", ch);
1629c4a7965SKim Phillips 		return -EIO;
1639c4a7965SKim Phillips 	}
1649c4a7965SKim Phillips 
16581eb024cSKim Phillips 	/* set 36-bit addressing, done writeback enable and done IRQ enable */
166ad42d5fcSKim Phillips 	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
16781eb024cSKim Phillips 		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
1689c4a7965SKim Phillips 
169fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
170fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
171ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
172fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
173fe5720e2SKim Phillips 
1749c4a7965SKim Phillips 	return 0;
1759c4a7965SKim Phillips }
1769c4a7965SKim Phillips 
1779c4a7965SKim Phillips static int reset_device(struct device *dev)
1789c4a7965SKim Phillips {
1799c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1809c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
181dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
182dd3c0987SLEROY Christophe 	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
1839c4a7965SKim Phillips 
184c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
1859c4a7965SKim Phillips 
186dd3c0987SLEROY Christophe 	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
1879c4a7965SKim Phillips 	       && --timeout)
1889c4a7965SKim Phillips 		cpu_relax();
1899c4a7965SKim Phillips 
1902cdba3cfSKim Phillips 	if (priv->irq[1]) {
191c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
192c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
193c3e337f8SKim Phillips 	}
194c3e337f8SKim Phillips 
1959c4a7965SKim Phillips 	if (timeout == 0) {
1969c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
1979c4a7965SKim Phillips 		return -EIO;
1989c4a7965SKim Phillips 	}
1999c4a7965SKim Phillips 
2009c4a7965SKim Phillips 	return 0;
2019c4a7965SKim Phillips }
2029c4a7965SKim Phillips 
2039c4a7965SKim Phillips /*
2049c4a7965SKim Phillips  * Reset and initialize the device
2059c4a7965SKim Phillips  */
2069c4a7965SKim Phillips static int init_device(struct device *dev)
2079c4a7965SKim Phillips {
2089c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2099c4a7965SKim Phillips 	int ch, err;
210dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2119c4a7965SKim Phillips 
2129c4a7965SKim Phillips 	/*
2139c4a7965SKim Phillips 	 * Master reset
2149c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
2159c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
2169c4a7965SKim Phillips 	 * set bit twice to completely reset
2179c4a7965SKim Phillips 	 */
2189c4a7965SKim Phillips 	err = reset_device(dev);
2199c4a7965SKim Phillips 	if (err)
2209c4a7965SKim Phillips 		return err;
2219c4a7965SKim Phillips 
2229c4a7965SKim Phillips 	err = reset_device(dev);
2239c4a7965SKim Phillips 	if (err)
2249c4a7965SKim Phillips 		return err;
2259c4a7965SKim Phillips 
2269c4a7965SKim Phillips 	/* reset channels */
2279c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
2289c4a7965SKim Phillips 		err = reset_channel(dev, ch);
2299c4a7965SKim Phillips 		if (err)
2309c4a7965SKim Phillips 			return err;
2319c4a7965SKim Phillips 	}
2329c4a7965SKim Phillips 
2339c4a7965SKim Phillips 	/* enable channel done and error interrupts */
234dd3c0987SLEROY Christophe 	if (is_sec1) {
235dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
236dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
237dd3c0987SLEROY Christophe 		/* disable parity error check in DEU (erroneous? test vect.) */
238dd3c0987SLEROY Christophe 		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
239dd3c0987SLEROY Christophe 	} else {
240dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
241dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
242dd3c0987SLEROY Christophe 	}
2439c4a7965SKim Phillips 
244fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
245fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2465fa7fa14SLEROY Christophe 		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
247fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
248fe5720e2SKim Phillips 
2499c4a7965SKim Phillips 	return 0;
2509c4a7965SKim Phillips }
2519c4a7965SKim Phillips 
2529c4a7965SKim Phillips /**
2539c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
2549c4a7965SKim Phillips  * @dev:	the SEC device to be used
2555228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
2569c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
2579c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
2589c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
2599c4a7965SKim Phillips  *
2609c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
2619c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
2629c4a7965SKim Phillips  * for device processing status.
2639c4a7965SKim Phillips  */
264865d5061SHoria Geanta int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2659c4a7965SKim Phillips 		   void (*callback)(struct device *dev,
2669c4a7965SKim Phillips 				    struct talitos_desc *desc,
2679c4a7965SKim Phillips 				    void *context, int error),
2689c4a7965SKim Phillips 		   void *context)
2699c4a7965SKim Phillips {
2709c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2719c4a7965SKim Phillips 	struct talitos_request *request;
2725228f0f7SKim Phillips 	unsigned long flags;
2739c4a7965SKim Phillips 	int head;
2747d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2759c4a7965SKim Phillips 
2764b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2779c4a7965SKim Phillips 
2784b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
279ec6644d6SKim Phillips 		/* h/w fifo is full */
2804b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2819c4a7965SKim Phillips 		return -EAGAIN;
2829c4a7965SKim Phillips 	}
2839c4a7965SKim Phillips 
2844b992628SKim Phillips 	head = priv->chan[ch].head;
2854b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
286ec6644d6SKim Phillips 
2879c4a7965SKim Phillips 	/* map descriptor and save caller data */
2887d607c6aSLEROY Christophe 	if (is_sec1) {
2897d607c6aSLEROY Christophe 		desc->hdr1 = desc->hdr;
2907d607c6aSLEROY Christophe 		desc->next_desc = 0;
2917d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, &desc->hdr1,
2927d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2939c4a7965SKim Phillips 						   DMA_BIDIRECTIONAL);
2947d607c6aSLEROY Christophe 	} else {
2957d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, desc,
2967d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2977d607c6aSLEROY Christophe 						   DMA_BIDIRECTIONAL);
2987d607c6aSLEROY Christophe 	}
2999c4a7965SKim Phillips 	request->callback = callback;
3009c4a7965SKim Phillips 	request->context = context;
3019c4a7965SKim Phillips 
3029c4a7965SKim Phillips 	/* increment fifo head */
3034b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
3049c4a7965SKim Phillips 
3059c4a7965SKim Phillips 	smp_wmb();
3069c4a7965SKim Phillips 	request->desc = desc;
3079c4a7965SKim Phillips 
3089c4a7965SKim Phillips 	/* GO! */
3099c4a7965SKim Phillips 	wmb();
310ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
311ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
312ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
313a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
3149c4a7965SKim Phillips 
3154b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3169c4a7965SKim Phillips 
3179c4a7965SKim Phillips 	return -EINPROGRESS;
3189c4a7965SKim Phillips }
319865d5061SHoria Geanta EXPORT_SYMBOL(talitos_submit);
3209c4a7965SKim Phillips 
3219c4a7965SKim Phillips /*
3229c4a7965SKim Phillips  * process what was done, notify callback of error if not
3239c4a7965SKim Phillips  */
3249c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3259c4a7965SKim Phillips {
3269c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3279c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
3289c4a7965SKim Phillips 	unsigned long flags;
3299c4a7965SKim Phillips 	int tail, status;
3307d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3319c4a7965SKim Phillips 
3324b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3339c4a7965SKim Phillips 
3344b992628SKim Phillips 	tail = priv->chan[ch].tail;
3354b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
3367d607c6aSLEROY Christophe 		__be32 hdr;
3377d607c6aSLEROY Christophe 
3384b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
3399c4a7965SKim Phillips 
3409c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
3419c4a7965SKim Phillips 		rmb();
3427d607c6aSLEROY Christophe 		hdr = is_sec1 ? request->desc->hdr1 : request->desc->hdr;
3437d607c6aSLEROY Christophe 
3447d607c6aSLEROY Christophe 		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3459c4a7965SKim Phillips 			status = 0;
346ca38a814SLee Nipper 		else
3479c4a7965SKim Phillips 			if (!error)
3489c4a7965SKim Phillips 				break;
3499c4a7965SKim Phillips 			else
3509c4a7965SKim Phillips 				status = error;
3519c4a7965SKim Phillips 
3529c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
3537d607c6aSLEROY Christophe 				 TALITOS_DESC_SIZE,
354e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
3559c4a7965SKim Phillips 
3569c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
3579c4a7965SKim Phillips 		saved_req.desc = request->desc;
3589c4a7965SKim Phillips 		saved_req.callback = request->callback;
3599c4a7965SKim Phillips 		saved_req.context = request->context;
3609c4a7965SKim Phillips 
3619c4a7965SKim Phillips 		/* release request entry in fifo */
3629c4a7965SKim Phillips 		smp_wmb();
3639c4a7965SKim Phillips 		request->desc = NULL;
3649c4a7965SKim Phillips 
3659c4a7965SKim Phillips 		/* increment fifo tail */
3664b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3679c4a7965SKim Phillips 
3684b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
369ec6644d6SKim Phillips 
3704b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
371ec6644d6SKim Phillips 
3729c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
3739c4a7965SKim Phillips 				   status);
3749c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
3759c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
3769c4a7965SKim Phillips 			return;
3774b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3784b992628SKim Phillips 		tail = priv->chan[ch].tail;
3799c4a7965SKim Phillips 	}
3809c4a7965SKim Phillips 
3814b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
3829c4a7965SKim Phillips }
3839c4a7965SKim Phillips 
3849c4a7965SKim Phillips /*
3859c4a7965SKim Phillips  * process completed requests for channels that have done status
3869c4a7965SKim Phillips  */
387dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask)				\
388dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data)			\
389dd3c0987SLEROY Christophe {									\
390dd3c0987SLEROY Christophe 	struct device *dev = (struct device *)data;			\
391dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		\
392dd3c0987SLEROY Christophe 	unsigned long flags;						\
393dd3c0987SLEROY Christophe 									\
394dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x10000000)					\
395dd3c0987SLEROY Christophe 		flush_channel(dev, 0, 0, 0);			\
396dd3c0987SLEROY Christophe 	if (priv->num_channels == 1)					\
397dd3c0987SLEROY Christophe 		goto out;						\
398dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x40000000)					\
399dd3c0987SLEROY Christophe 		flush_channel(dev, 1, 0, 0);			\
400dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00010000)					\
401dd3c0987SLEROY Christophe 		flush_channel(dev, 2, 0, 0);			\
402dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00040000)					\
403dd3c0987SLEROY Christophe 		flush_channel(dev, 3, 0, 0);			\
404dd3c0987SLEROY Christophe 									\
405dd3c0987SLEROY Christophe out:									\
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)
415dd3c0987SLEROY Christophe 
416dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask)				\
417dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data)			\
418c3e337f8SKim Phillips {									\
419c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
420c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
421511d63cbSHoria Geanta 	unsigned long flags;						\
422c3e337f8SKim Phillips 									\
423c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
424c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
425c3e337f8SKim Phillips 	if (priv->num_channels == 1)					\
426c3e337f8SKim Phillips 		goto out;						\
427c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
428c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
429c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
430c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
431c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
432c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
433c3e337f8SKim Phillips 									\
434c3e337f8SKim Phillips out:									\
435c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
436c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
437511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
438c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
439dd3c0987SLEROY Christophe 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
440511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4419c4a7965SKim Phillips }
442dd3c0987SLEROY Christophe 
443dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
444dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
445dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4469c4a7965SKim Phillips 
4479c4a7965SKim Phillips /*
4489c4a7965SKim Phillips  * locate current (offending) descriptor
4499c4a7965SKim Phillips  */
4503e721aebSKim Phillips static u32 current_desc_hdr(struct device *dev, int ch)
4519c4a7965SKim Phillips {
4529c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
453b62ffd8cSHoria Geanta 	int tail, iter;
4549c4a7965SKim Phillips 	dma_addr_t cur_desc;
4559c4a7965SKim Phillips 
456b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
457b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4589c4a7965SKim Phillips 
459b62ffd8cSHoria Geanta 	if (!cur_desc) {
460b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
461b62ffd8cSHoria Geanta 		return 0;
462b62ffd8cSHoria Geanta 	}
463b62ffd8cSHoria Geanta 
464b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
465b62ffd8cSHoria Geanta 
466b62ffd8cSHoria Geanta 	iter = tail;
467b62ffd8cSHoria Geanta 	while (priv->chan[ch].fifo[iter].dma_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 
475b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
4769c4a7965SKim Phillips }
4779c4a7965SKim Phillips 
4789c4a7965SKim Phillips /*
4799c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
4809c4a7965SKim Phillips  */
4813e721aebSKim Phillips static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
4829c4a7965SKim Phillips {
4839c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
4849c4a7965SKim Phillips 	int i;
4859c4a7965SKim Phillips 
4863e721aebSKim Phillips 	if (!desc_hdr)
487ad42d5fcSKim Phillips 		desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
4883e721aebSKim Phillips 
4893e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
4909c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
4919c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
4925fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR),
4935fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
4949c4a7965SKim Phillips 		break;
4959c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
4969c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
4975fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR),
4985fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
4999c4a7965SKim Phillips 		break;
5009c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
5019c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
5029c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5035fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5045fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5059c4a7965SKim Phillips 		break;
5069c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
5079c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
5085fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR),
5095fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5109c4a7965SKim Phillips 		break;
5119c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
5129c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5135fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5145fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5159c4a7965SKim Phillips 		break;
5169c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
5179c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5185fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR),
5195fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5209c4a7965SKim Phillips 		break;
5219c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
5229c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5235fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5245fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5259c4a7965SKim Phillips 		break;
5269c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
5279c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5285fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5295fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5309c4a7965SKim Phillips 		break;
5319c4a7965SKim Phillips 	}
5329c4a7965SKim Phillips 
5333e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5349c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
5359c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
5369c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5375fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5385fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5399c4a7965SKim Phillips 		break;
5409c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
5419c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5425fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5435fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5449c4a7965SKim Phillips 		break;
5459c4a7965SKim Phillips 	}
5469c4a7965SKim Phillips 
5479c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
5489c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
549ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
550ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5519c4a7965SKim Phillips }
5529c4a7965SKim Phillips 
5539c4a7965SKim Phillips /*
5549c4a7965SKim Phillips  * recover from error interrupts
5559c4a7965SKim Phillips  */
5565e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5579c4a7965SKim Phillips {
5589c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5599c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
560dd3c0987SLEROY Christophe 	int ch, error, reset_dev = 0;
56142e8b0d7SHoria Geant? 	u32 v_lo;
562dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
563dd3c0987SLEROY Christophe 	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5649c4a7965SKim Phillips 
5659c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
5669c4a7965SKim Phillips 		/* skip channels without errors */
567dd3c0987SLEROY Christophe 		if (is_sec1) {
568dd3c0987SLEROY Christophe 			/* bits 29, 31, 17, 19 */
569dd3c0987SLEROY Christophe 			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
570dd3c0987SLEROY Christophe 				continue;
571dd3c0987SLEROY Christophe 		} else {
5729c4a7965SKim Phillips 			if (!(isr & (1 << (ch * 2 + 1))))
5739c4a7965SKim Phillips 				continue;
574dd3c0987SLEROY Christophe 		}
5759c4a7965SKim Phillips 
5769c4a7965SKim Phillips 		error = -EINVAL;
5779c4a7965SKim Phillips 
578ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
5799c4a7965SKim Phillips 
5809c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
5819c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
5829c4a7965SKim Phillips 			error = -EAGAIN;
5839c4a7965SKim Phillips 			reset_ch = 1;
5849c4a7965SKim Phillips 		}
5859c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
5869c4a7965SKim Phillips 			/* h/w dropped descriptor */
5879c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
5889c4a7965SKim Phillips 			error = -EAGAIN;
5899c4a7965SKim Phillips 		}
5909c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
5919c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
5929c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
593dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "pointeur not complete error\n"
594dd3c0987SLEROY Christophe 					     : "s/g data length zero error\n");
5959c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
596dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "parity error\n"
597dd3c0987SLEROY Christophe 					     : "fetch pointer zero error\n");
5989c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
5999c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
6009c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
601dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "static assignment error\n"
602dd3c0987SLEROY Christophe 					     : "invalid exec unit error\n");
6039c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
6043e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
605dd3c0987SLEROY Christophe 		if (!is_sec1) {
6069c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GB)
6079c4a7965SKim Phillips 				dev_err(dev, "gather boundary error\n");
6089c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GRL)
6099c4a7965SKim Phillips 				dev_err(dev, "gather return/length error\n");
6109c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SB)
6119c4a7965SKim Phillips 				dev_err(dev, "scatter boundary error\n");
6129c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SRL)
6139c4a7965SKim Phillips 				dev_err(dev, "scatter return/length error\n");
614dd3c0987SLEROY Christophe 		}
6159c4a7965SKim Phillips 
6169c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
6179c4a7965SKim Phillips 
6189c4a7965SKim Phillips 		if (reset_ch) {
6199c4a7965SKim Phillips 			reset_channel(dev, ch);
6209c4a7965SKim Phillips 		} else {
621ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
622dd3c0987SLEROY Christophe 				  TALITOS2_CCCR_CONT);
623ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
624ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
625dd3c0987SLEROY Christophe 			       TALITOS2_CCCR_CONT) && --timeout)
6269c4a7965SKim Phillips 				cpu_relax();
6279c4a7965SKim Phillips 			if (timeout == 0) {
6289c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
6299c4a7965SKim Phillips 					ch);
6309c4a7965SKim Phillips 				reset_dev = 1;
6319c4a7965SKim Phillips 			}
6329c4a7965SKim Phillips 		}
6339c4a7965SKim Phillips 	}
634dd3c0987SLEROY Christophe 	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
635dd3c0987SLEROY Christophe 	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
636dd3c0987SLEROY Christophe 		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
637dd3c0987SLEROY Christophe 			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
638dd3c0987SLEROY Christophe 				isr, isr_lo);
639dd3c0987SLEROY Christophe 		else
640dd3c0987SLEROY Christophe 			dev_err(dev, "done overflow, internal time out, or "
641dd3c0987SLEROY Christophe 				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6429c4a7965SKim Phillips 
6439c4a7965SKim Phillips 		/* purge request queues */
6449c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
6459c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
6469c4a7965SKim Phillips 
6479c4a7965SKim Phillips 		/* reset and reinitialize the device */
6489c4a7965SKim Phillips 		init_device(dev);
6499c4a7965SKim Phillips 	}
6509c4a7965SKim Phillips }
6519c4a7965SKim Phillips 
652dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
653dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
654dd3c0987SLEROY Christophe {									       \
655dd3c0987SLEROY Christophe 	struct device *dev = data;					       \
656dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
657dd3c0987SLEROY Christophe 	u32 isr, isr_lo;						       \
658dd3c0987SLEROY Christophe 	unsigned long flags;						       \
659dd3c0987SLEROY Christophe 									       \
660dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
661dd3c0987SLEROY Christophe 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
662dd3c0987SLEROY Christophe 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
663dd3c0987SLEROY Christophe 	/* Acknowledge interrupt */					       \
664dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
665dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
666dd3c0987SLEROY Christophe 									       \
667dd3c0987SLEROY Christophe 	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
668dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
669dd3c0987SLEROY Christophe 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
670dd3c0987SLEROY Christophe 	}								       \
671dd3c0987SLEROY Christophe 	else {								       \
672dd3c0987SLEROY Christophe 		if (likely(isr & ch_done_mask)) {			       \
673dd3c0987SLEROY Christophe 			/* mask further done interrupts. */		       \
674dd3c0987SLEROY Christophe 			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
675dd3c0987SLEROY Christophe 			/* done_task will unmask done interrupts at exit */    \
676dd3c0987SLEROY Christophe 			tasklet_schedule(&priv->done_task[tlet]);	       \
677dd3c0987SLEROY Christophe 		}							       \
678dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
679dd3c0987SLEROY Christophe 	}								       \
680dd3c0987SLEROY Christophe 									       \
681dd3c0987SLEROY Christophe 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
682dd3c0987SLEROY Christophe 								IRQ_NONE;      \
683dd3c0987SLEROY Christophe }
684dd3c0987SLEROY Christophe 
685dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
686dd3c0987SLEROY Christophe 
687dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
688dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
689c3e337f8SKim Phillips {									       \
690c3e337f8SKim Phillips 	struct device *dev = data;					       \
691c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
692c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
693511d63cbSHoria Geanta 	unsigned long flags;						       \
694c3e337f8SKim Phillips 									       \
695511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
696c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
697c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
698c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
699c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
700c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
701c3e337f8SKim Phillips 									       \
702511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
703511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
704511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
705511d63cbSHoria Geanta 	}								       \
706511d63cbSHoria Geanta 	else {								       \
707c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
708c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
709c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
710c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
711c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
712c3e337f8SKim Phillips 		}							       \
713511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
714511d63cbSHoria Geanta 	}								       \
715c3e337f8SKim Phillips 									       \
716c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
717c3e337f8SKim Phillips 								IRQ_NONE;      \
7181c2e8811SLee Nipper }
719dd3c0987SLEROY Christophe 
720dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
721dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
722dd3c0987SLEROY Christophe 		       0)
723dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
724dd3c0987SLEROY Christophe 		       1)
7259c4a7965SKim Phillips 
7269c4a7965SKim Phillips /*
7279c4a7965SKim Phillips  * hwrng
7289c4a7965SKim Phillips  */
7299c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
7309c4a7965SKim Phillips {
7319c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7329c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7339c4a7965SKim Phillips 	u32 ofl;
7349c4a7965SKim Phillips 	int i;
7359c4a7965SKim Phillips 
7369c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
7375fa7fa14SLEROY Christophe 		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7389c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
7399c4a7965SKim Phillips 		if (ofl || !wait)
7409c4a7965SKim Phillips 			break;
7419c4a7965SKim Phillips 		udelay(10);
7429c4a7965SKim Phillips 	}
7439c4a7965SKim Phillips 
7449c4a7965SKim Phillips 	return !!ofl;
7459c4a7965SKim Phillips }
7469c4a7965SKim Phillips 
7479c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7489c4a7965SKim Phillips {
7499c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7509c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7519c4a7965SKim Phillips 
7529c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
7535fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7545fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7559c4a7965SKim Phillips 
7569c4a7965SKim Phillips 	return sizeof(u32);
7579c4a7965SKim Phillips }
7589c4a7965SKim Phillips 
7599c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
7609c4a7965SKim Phillips {
7619c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7629c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7639c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
7649c4a7965SKim Phillips 
7655fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7665fa7fa14SLEROY Christophe 	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7675fa7fa14SLEROY Christophe 		 & TALITOS_RNGUSR_LO_RD)
7689c4a7965SKim Phillips 	       && --timeout)
7699c4a7965SKim Phillips 		cpu_relax();
7709c4a7965SKim Phillips 	if (timeout == 0) {
7719c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
7729c4a7965SKim Phillips 		return -ENODEV;
7739c4a7965SKim Phillips 	}
7749c4a7965SKim Phillips 
7759c4a7965SKim Phillips 	/* start generating */
7765fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
7779c4a7965SKim Phillips 
7789c4a7965SKim Phillips 	return 0;
7799c4a7965SKim Phillips }
7809c4a7965SKim Phillips 
7819c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
7829c4a7965SKim Phillips {
7839c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
78435a3bb3dSAaron Sierra 	int err;
7859c4a7965SKim Phillips 
7869c4a7965SKim Phillips 	priv->rng.name		= dev_driver_string(dev),
7879c4a7965SKim Phillips 	priv->rng.init		= talitos_rng_init,
7889c4a7965SKim Phillips 	priv->rng.data_present	= talitos_rng_data_present,
7899c4a7965SKim Phillips 	priv->rng.data_read	= talitos_rng_data_read,
7909c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
7919c4a7965SKim Phillips 
79235a3bb3dSAaron Sierra 	err = hwrng_register(&priv->rng);
79335a3bb3dSAaron Sierra 	if (!err)
79435a3bb3dSAaron Sierra 		priv->rng_registered = true;
79535a3bb3dSAaron Sierra 
79635a3bb3dSAaron Sierra 	return err;
7979c4a7965SKim Phillips }
7989c4a7965SKim Phillips 
7999c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
8009c4a7965SKim Phillips {
8019c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
8029c4a7965SKim Phillips 
80335a3bb3dSAaron Sierra 	if (!priv->rng_registered)
80435a3bb3dSAaron Sierra 		return;
80535a3bb3dSAaron Sierra 
8069c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
80735a3bb3dSAaron Sierra 	priv->rng_registered = false;
8089c4a7965SKim Phillips }
8099c4a7965SKim Phillips 
8109c4a7965SKim Phillips /*
8119c4a7965SKim Phillips  * crypto alg
8129c4a7965SKim Phillips  */
8139c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
814357fb605SHoria Geanta #define TALITOS_MAX_KEY_SIZE		96
8153952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
81670bcaca7SLee Nipper 
8179c4a7965SKim Phillips struct talitos_ctx {
8189c4a7965SKim Phillips 	struct device *dev;
8195228f0f7SKim Phillips 	int ch;
8209c4a7965SKim Phillips 	__be32 desc_hdr_template;
8219c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
82270bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8239c4a7965SKim Phillips 	unsigned int keylen;
8249c4a7965SKim Phillips 	unsigned int enckeylen;
8259c4a7965SKim Phillips 	unsigned int authkeylen;
8269c4a7965SKim Phillips };
8279c4a7965SKim Phillips 
828497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
829497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
830497f2e6bSLee Nipper 
831497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
83260f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
833497f2e6bSLee Nipper 	unsigned int hw_context_size;
834497f2e6bSLee Nipper 	u8 buf[HASH_MAX_BLOCK_SIZE];
835497f2e6bSLee Nipper 	u8 bufnext[HASH_MAX_BLOCK_SIZE];
83660f208d7SKim Phillips 	unsigned int swinit;
837497f2e6bSLee Nipper 	unsigned int first;
838497f2e6bSLee Nipper 	unsigned int last;
839497f2e6bSLee Nipper 	unsigned int to_hash_later;
84042e8b0d7SHoria Geant? 	unsigned int nbuf;
841497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
842497f2e6bSLee Nipper 	struct scatterlist *psrc;
843497f2e6bSLee Nipper };
844497f2e6bSLee Nipper 
8453639ca84SHoria Geant? struct talitos_export_state {
8463639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8473639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8483639ca84SHoria Geant? 	unsigned int swinit;
8493639ca84SHoria Geant? 	unsigned int first;
8503639ca84SHoria Geant? 	unsigned int last;
8513639ca84SHoria Geant? 	unsigned int to_hash_later;
8523639ca84SHoria Geant? 	unsigned int nbuf;
8533639ca84SHoria Geant? };
8543639ca84SHoria Geant? 
85556af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8569c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8579c4a7965SKim Phillips {
8589c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
859c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8609c4a7965SKim Phillips 
861c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8629c4a7965SKim Phillips 		goto badkey;
8639c4a7965SKim Phillips 
864c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8659c4a7965SKim Phillips 		goto badkey;
8669c4a7965SKim Phillips 
867c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
868c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
8699c4a7965SKim Phillips 
870c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
871c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
872c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
8739c4a7965SKim Phillips 
8749c4a7965SKim Phillips 	return 0;
8759c4a7965SKim Phillips 
8769c4a7965SKim Phillips badkey:
8779c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
8789c4a7965SKim Phillips 	return -EINVAL;
8799c4a7965SKim Phillips }
8809c4a7965SKim Phillips 
8819c4a7965SKim Phillips /*
88256af8cd4SLee Nipper  * talitos_edesc - s/w-extended descriptor
8839c4a7965SKim Phillips  * @src_nents: number of segments in input scatterlist
8849c4a7965SKim Phillips  * @dst_nents: number of segments in output scatterlist
885aeb4c132SHerbert Xu  * @icv_ool: whether ICV is out-of-line
88679fd31d3SHoria Geanta  * @iv_dma: dma address of iv for checking continuity and link table
8879c4a7965SKim Phillips  * @dma_len: length of dma mapped link_tbl space
8886f65f6acSLEROY Christophe  * @dma_link_tbl: bus physical address of link_tbl/buf
8899c4a7965SKim Phillips  * @desc: h/w descriptor
8906f65f6acSLEROY Christophe  * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
8916f65f6acSLEROY Christophe  * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
8929c4a7965SKim Phillips  *
8939c4a7965SKim Phillips  * if decrypting (with authcheck), or either one of src_nents or dst_nents
8949c4a7965SKim Phillips  * is greater than 1, an integrity check value is concatenated to the end
8959c4a7965SKim Phillips  * of link_tbl data
8969c4a7965SKim Phillips  */
89756af8cd4SLee Nipper struct talitos_edesc {
8989c4a7965SKim Phillips 	int src_nents;
8999c4a7965SKim Phillips 	int dst_nents;
900aeb4c132SHerbert Xu 	bool icv_ool;
90179fd31d3SHoria Geanta 	dma_addr_t iv_dma;
9029c4a7965SKim Phillips 	int dma_len;
9039c4a7965SKim Phillips 	dma_addr_t dma_link_tbl;
9049c4a7965SKim Phillips 	struct talitos_desc desc;
9056f65f6acSLEROY Christophe 	union {
9069c4a7965SKim Phillips 		struct talitos_ptr link_tbl[0];
9076f65f6acSLEROY Christophe 		u8 buf[0];
9086f65f6acSLEROY Christophe 	};
9099c4a7965SKim Phillips };
9109c4a7965SKim Phillips 
9114de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9124de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9134de9d0b5SLee Nipper 			     struct scatterlist *src,
9146a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
9156a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
916246a87cdSLEROY Christophe {
917246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
918246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9196a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
9206a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
921246a87cdSLEROY Christophe 
9226a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
9236a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
924246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
9256a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
9266a1e8d14SLEROY Christophe 				     offset);
927246a87cdSLEROY Christophe 	}
9286a1e8d14SLEROY Christophe 	if (src != dst) {
9296a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
9306a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
9316a1e8d14SLEROY Christophe 
9326a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
9336a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
9346a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
9356a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
936246a87cdSLEROY Christophe 	}
937246a87cdSLEROY Christophe }
938246a87cdSLEROY Christophe 
9399c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
94056af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
9419c4a7965SKim Phillips 			    struct aead_request *areq)
9429c4a7965SKim Phillips {
943*549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
944*549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
945*549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
946*549bd8bcSLEROY Christophe 
947*549bd8bcSLEROY Christophe 	if (edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP)
948*549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
949*549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
9509c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[3], DMA_TO_DEVICE);
9519c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
9529c4a7965SKim Phillips 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[0], DMA_TO_DEVICE);
9539c4a7965SKim Phillips 
9546a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen,
9556a1e8d14SLEROY Christophe 			 areq->assoclen);
9569c4a7965SKim Phillips 
9579c4a7965SKim Phillips 	if (edesc->dma_len)
9589c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
9599c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
960*549bd8bcSLEROY Christophe 
961*549bd8bcSLEROY Christophe 	if (!(edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP)) {
962*549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
963*549bd8bcSLEROY Christophe 
964*549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
965*549bd8bcSLEROY Christophe 				   areq->assoclen + areq->cryptlen - ivsize);
966*549bd8bcSLEROY Christophe 	}
9679c4a7965SKim Phillips }
9689c4a7965SKim Phillips 
9699c4a7965SKim Phillips /*
9709c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
9719c4a7965SKim Phillips  */
9729c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
9739c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
9749c4a7965SKim Phillips 				   int err)
9759c4a7965SKim Phillips {
976*549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
977*549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9789c4a7965SKim Phillips 	struct aead_request *areq = context;
9799c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
980aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
98119bbbc63SKim Phillips 	struct talitos_edesc *edesc;
9829c4a7965SKim Phillips 	struct scatterlist *sg;
9839c4a7965SKim Phillips 	void *icvdata;
9849c4a7965SKim Phillips 
98519bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
98619bbbc63SKim Phillips 
9879c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, areq);
9889c4a7965SKim Phillips 
9899c4a7965SKim Phillips 	/* copy the generated ICV to dst */
990aeb4c132SHerbert Xu 	if (edesc->icv_ool) {
991*549bd8bcSLEROY Christophe 		if (is_sec1)
992*549bd8bcSLEROY Christophe 			icvdata = edesc->buf + areq->assoclen + areq->cryptlen;
993*549bd8bcSLEROY Christophe 		else
9949c4a7965SKim Phillips 			icvdata = &edesc->link_tbl[edesc->src_nents +
995aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
9969c4a7965SKim Phillips 		sg = sg_last(areq->dst, edesc->dst_nents);
997aeb4c132SHerbert Xu 		memcpy((char *)sg_virt(sg) + sg->length - authsize,
998aeb4c132SHerbert Xu 		       icvdata, authsize);
9999c4a7965SKim Phillips 	}
10009c4a7965SKim Phillips 
10019c4a7965SKim Phillips 	kfree(edesc);
10029c4a7965SKim Phillips 
10039c4a7965SKim Phillips 	aead_request_complete(areq, err);
10049c4a7965SKim Phillips }
10059c4a7965SKim Phillips 
1006fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1007e938e465SKim Phillips 					  struct talitos_desc *desc,
1008e938e465SKim Phillips 					  void *context, int err)
10099c4a7965SKim Phillips {
10109c4a7965SKim Phillips 	struct aead_request *req = context;
10119c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1012aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
101319bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10149c4a7965SKim Phillips 	struct scatterlist *sg;
1015aeb4c132SHerbert Xu 	char *oicv, *icv;
1016*549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1017*549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
10189c4a7965SKim Phillips 
101919bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
102019bbbc63SKim Phillips 
10219c4a7965SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
10229c4a7965SKim Phillips 
10239c4a7965SKim Phillips 	if (!err) {
10249c4a7965SKim Phillips 		/* auth check */
10259c4a7965SKim Phillips 		sg = sg_last(req->dst, edesc->dst_nents ? : 1);
1026aeb4c132SHerbert Xu 		icv = (char *)sg_virt(sg) + sg->length - authsize;
1027aeb4c132SHerbert Xu 
1028aeb4c132SHerbert Xu 		if (edesc->dma_len) {
1029*549bd8bcSLEROY Christophe 			if (is_sec1)
1030*549bd8bcSLEROY Christophe 				oicv = (char *)&edesc->dma_link_tbl +
1031*549bd8bcSLEROY Christophe 					       req->assoclen + req->cryptlen;
1032*549bd8bcSLEROY Christophe 			else
1033*549bd8bcSLEROY Christophe 				oicv = (char *)
1034*549bd8bcSLEROY Christophe 				       &edesc->link_tbl[edesc->src_nents +
1035aeb4c132SHerbert Xu 							edesc->dst_nents + 2];
1036aeb4c132SHerbert Xu 			if (edesc->icv_ool)
1037aeb4c132SHerbert Xu 				icv = oicv + authsize;
1038aeb4c132SHerbert Xu 		} else
1039aeb4c132SHerbert Xu 			oicv = (char *)&edesc->link_tbl[0];
1040aeb4c132SHerbert Xu 
104179960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10429c4a7965SKim Phillips 	}
10439c4a7965SKim Phillips 
10449c4a7965SKim Phillips 	kfree(edesc);
10459c4a7965SKim Phillips 
10469c4a7965SKim Phillips 	aead_request_complete(req, err);
10479c4a7965SKim Phillips }
10489c4a7965SKim Phillips 
1049fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1050e938e465SKim Phillips 					  struct talitos_desc *desc,
1051e938e465SKim Phillips 					  void *context, int err)
1052fe5720e2SKim Phillips {
1053fe5720e2SKim Phillips 	struct aead_request *req = context;
105419bbbc63SKim Phillips 	struct talitos_edesc *edesc;
105519bbbc63SKim Phillips 
105619bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1057fe5720e2SKim Phillips 
1058fe5720e2SKim Phillips 	ipsec_esp_unmap(dev, edesc, req);
1059fe5720e2SKim Phillips 
1060fe5720e2SKim Phillips 	/* check ICV auth status */
1061e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1062e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1063fe5720e2SKim Phillips 		err = -EBADMSG;
1064fe5720e2SKim Phillips 
1065fe5720e2SKim Phillips 	kfree(edesc);
1066fe5720e2SKim Phillips 
1067fe5720e2SKim Phillips 	aead_request_complete(req, err);
1068fe5720e2SKim Phillips }
1069fe5720e2SKim Phillips 
10709c4a7965SKim Phillips /*
10719c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
10729c4a7965SKim Phillips  * stop at cryptlen bytes
10739c4a7965SKim Phillips  */
1074aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1075aeb4c132SHerbert Xu 				 unsigned int offset, int cryptlen,
1076aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
10779c4a7965SKim Phillips {
107870bcaca7SLee Nipper 	int n_sg = sg_count;
1079aeb4c132SHerbert Xu 	int count = 0;
108070bcaca7SLee Nipper 
1081aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1082aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1083aeb4c132SHerbert Xu 
1084aeb4c132SHerbert Xu 		if (offset >= len) {
1085aeb4c132SHerbert Xu 			offset -= len;
1086aeb4c132SHerbert Xu 			goto next;
1087aeb4c132SHerbert Xu 		}
1088aeb4c132SHerbert Xu 
1089aeb4c132SHerbert Xu 		len -= offset;
1090aeb4c132SHerbert Xu 
1091aeb4c132SHerbert Xu 		if (len > cryptlen)
1092aeb4c132SHerbert Xu 			len = cryptlen;
1093aeb4c132SHerbert Xu 
1094aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1095aeb4c132SHerbert Xu 			       sg_dma_address(sg) + offset, 0);
1096b096b544SLEROY Christophe 		to_talitos_ptr_len(link_tbl_ptr + count, len, 0);
1097b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1098aeb4c132SHerbert Xu 		count++;
1099aeb4c132SHerbert Xu 		cryptlen -= len;
1100aeb4c132SHerbert Xu 		offset = 0;
1101aeb4c132SHerbert Xu 
1102aeb4c132SHerbert Xu next:
11035be4d4c9SCristian Stoica 		sg = sg_next(sg);
11049c4a7965SKim Phillips 	}
11059c4a7965SKim Phillips 
11069c4a7965SKim Phillips 	/* tag end of link table */
1107aeb4c132SHerbert Xu 	if (count > 0)
1108b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1109b096b544SLEROY Christophe 				       DESC_PTR_LNKTBL_RETURN, 0);
111070bcaca7SLee Nipper 
1111aeb4c132SHerbert Xu 	return count;
1112aeb4c132SHerbert Xu }
1113aeb4c132SHerbert Xu 
1114aeb4c132SHerbert Xu static inline int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
1115aeb4c132SHerbert Xu 				 int cryptlen,
1116aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
1117aeb4c132SHerbert Xu {
1118aeb4c132SHerbert Xu 	return sg_to_link_tbl_offset(sg, sg_count, 0, cryptlen,
1119aeb4c132SHerbert Xu 				     link_tbl_ptr);
11209c4a7965SKim Phillips }
11219c4a7965SKim Phillips 
11226a1e8d14SLEROY Christophe int talitos_sg_map(struct device *dev, struct scatterlist *src,
1123246a87cdSLEROY Christophe 		   unsigned int len, struct talitos_edesc *edesc,
11246a1e8d14SLEROY Christophe 		   struct talitos_ptr *ptr,
11256a1e8d14SLEROY Christophe 		   int sg_count, unsigned int offset, int tbl_off)
1126246a87cdSLEROY Christophe {
1127246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1128246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1129246a87cdSLEROY Christophe 
1130246a87cdSLEROY Christophe 	to_talitos_ptr_len(ptr, len, is_sec1);
1131246a87cdSLEROY Christophe 	to_talitos_ptr_ext_set(ptr, 0, is_sec1);
1132246a87cdSLEROY Christophe 
1133246a87cdSLEROY Christophe 	if (sg_count == 1) {
11346a1e8d14SLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, is_sec1);
1135246a87cdSLEROY Christophe 		return sg_count;
1136246a87cdSLEROY Christophe 	}
1137246a87cdSLEROY Christophe 	if (is_sec1) {
11386a1e8d14SLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, is_sec1);
11396a1e8d14SLEROY Christophe 		return sg_count;
1140246a87cdSLEROY Christophe 	}
11416a1e8d14SLEROY Christophe 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len,
11426a1e8d14SLEROY Christophe 					 &edesc->link_tbl[tbl_off]);
1143246a87cdSLEROY Christophe 	if (sg_count == 1) {
11446a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
11456a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
11466a1e8d14SLEROY Christophe 		return sg_count;
11476a1e8d14SLEROY Christophe 	}
1148246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
11496a1e8d14SLEROY Christophe 			    tbl_off * sizeof(struct talitos_ptr), is_sec1);
11506a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
11516a1e8d14SLEROY Christophe 
11526a1e8d14SLEROY Christophe 	return sg_count;
1153246a87cdSLEROY Christophe }
1154246a87cdSLEROY Christophe 
11559c4a7965SKim Phillips /*
11569c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
11579c4a7965SKim Phillips  */
115856af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
1159aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
11609c4a7965SKim Phillips 				      struct talitos_desc *desc,
11619c4a7965SKim Phillips 				      void *context, int error))
11629c4a7965SKim Phillips {
11639c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1164aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
11659c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
11669c4a7965SKim Phillips 	struct device *dev = ctx->dev;
11679c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
11689c4a7965SKim Phillips 	unsigned int cryptlen = areq->cryptlen;
1169e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1170aeb4c132SHerbert Xu 	int tbl_off = 0;
1171fa86a267SKim Phillips 	int sg_count, ret;
1172fe5720e2SKim Phillips 	int sg_link_tbl_len;
1173*549bd8bcSLEROY Christophe 	bool sync_needed = false;
1174*549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1175*549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
11769c4a7965SKim Phillips 
11779c4a7965SKim Phillips 	/* hmac key */
11789c4a7965SKim Phillips 	map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
1179a2b35aa8SLEROY Christophe 			       DMA_TO_DEVICE);
118079fd31d3SHoria Geanta 
1181*549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1182*549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1183*549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1184*549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1185*549bd8bcSLEROY Christophe 	else
1186*549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1187*549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1188*549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1189*549bd8bcSLEROY Christophe 
11909c4a7965SKim Phillips 	/* hmac data */
1191*549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1192*549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
119379fd31d3SHoria Geanta 
1194*549bd8bcSLEROY Christophe 	if (ret > 1) {
1195340ff60aSHoria Geant? 		tbl_off += ret;
1196*549bd8bcSLEROY Christophe 		sync_needed = true;
119779fd31d3SHoria Geanta 	}
119879fd31d3SHoria Geanta 
11999c4a7965SKim Phillips 	/* cipher iv */
1200*549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP) {
1201*549bd8bcSLEROY Christophe 		to_talitos_ptr(&desc->ptr[2], edesc->iv_dma, is_sec1);
1202*549bd8bcSLEROY Christophe 		to_talitos_ptr_len(&desc->ptr[2], ivsize, is_sec1);
1203*549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[2], 0, is_sec1);
1204*549bd8bcSLEROY Christophe 	} else {
1205*549bd8bcSLEROY Christophe 		to_talitos_ptr(&desc->ptr[3], edesc->iv_dma, is_sec1);
1206*549bd8bcSLEROY Christophe 		to_talitos_ptr_len(&desc->ptr[3], ivsize, is_sec1);
1207*549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[3], 0, is_sec1);
1208*549bd8bcSLEROY Christophe 	}
12099c4a7965SKim Phillips 
12109c4a7965SKim Phillips 	/* cipher key */
1211*549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)
12129c4a7965SKim Phillips 		map_single_talitos_ptr(dev, &desc->ptr[3], ctx->enckeylen,
1213a2b35aa8SLEROY Christophe 				       (char *)&ctx->key + ctx->authkeylen,
12149c4a7965SKim Phillips 				       DMA_TO_DEVICE);
1215*549bd8bcSLEROY Christophe 	else
1216*549bd8bcSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[2], ctx->enckeylen,
1217*549bd8bcSLEROY Christophe 				       (char *)&ctx->key + ctx->authkeylen,
1218*549bd8bcSLEROY Christophe 				       DMA_TO_DEVICE);
12199c4a7965SKim Phillips 
12209c4a7965SKim Phillips 	/*
12219c4a7965SKim Phillips 	 * cipher in
12229c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
12239c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
12249c4a7965SKim Phillips 	 * typically 12 for ipsec
12259c4a7965SKim Phillips 	 */
1226*549bd8bcSLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[4], cryptlen, is_sec1);
1227*549bd8bcSLEROY Christophe 	to_talitos_ptr_ext_set(&desc->ptr[4], 0, is_sec1);
12289c4a7965SKim Phillips 
1229fe5720e2SKim Phillips 	sg_link_tbl_len = cryptlen;
1230*549bd8bcSLEROY Christophe 
1231*549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP) {
1232*549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_set(&desc->ptr[4], authsize, is_sec1);
1233*549bd8bcSLEROY Christophe 
1234962a9c99SKim Phillips 		if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
1235aeb4c132SHerbert Xu 			sg_link_tbl_len += authsize;
1236*549bd8bcSLEROY Christophe 	}
1237e938e465SKim Phillips 
1238*549bd8bcSLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
1239*549bd8bcSLEROY Christophe 				  &desc->ptr[4], sg_count, areq->assoclen,
1240*549bd8bcSLEROY Christophe 				  tbl_off);
1241*549bd8bcSLEROY Christophe 
1242*549bd8bcSLEROY Christophe 	if (sg_count > 1) {
1243*549bd8bcSLEROY Christophe 		tbl_off += sg_count;
1244*549bd8bcSLEROY Christophe 		sync_needed = true;
1245340ff60aSHoria Geant? 	}
12469c4a7965SKim Phillips 
12479c4a7965SKim Phillips 	/* cipher out */
1248*549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1249*549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1250*549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1251*549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1252*549bd8bcSLEROY Christophe 	}
12539c4a7965SKim Phillips 
1254*549bd8bcSLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->dst, cryptlen, edesc,
1255*549bd8bcSLEROY Christophe 				  &desc->ptr[5], sg_count, areq->assoclen,
1256*549bd8bcSLEROY Christophe 				  tbl_off);
12579c4a7965SKim Phillips 
1258*549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)
1259*549bd8bcSLEROY Christophe 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1260aeb4c132SHerbert Xu 
1261*549bd8bcSLEROY Christophe 	if (sg_count > 1) {
1262*549bd8bcSLEROY Christophe 		edesc->icv_ool = true;
1263*549bd8bcSLEROY Christophe 		sync_needed = true;
1264*549bd8bcSLEROY Christophe 
1265*549bd8bcSLEROY Christophe 		if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP) {
126679fd31d3SHoria Geanta 			struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1267*549bd8bcSLEROY Christophe 			int offset = (edesc->src_nents + edesc->dst_nents + 2) *
1268*549bd8bcSLEROY Christophe 				     sizeof(struct talitos_ptr) + authsize;
1269fe5720e2SKim Phillips 
1270f3c85bc1SLee Nipper 			/* Add an entry to the link table for ICV data */
127179fd31d3SHoria Geanta 			tbl_ptr += sg_count - 1;
1272*549bd8bcSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr, 0, is_sec1);
127379fd31d3SHoria Geanta 			tbl_ptr++;
1274*549bd8bcSLEROY Christophe 			to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RETURN,
1275*549bd8bcSLEROY Christophe 					       is_sec1);
1276*549bd8bcSLEROY Christophe 			to_talitos_ptr_len(tbl_ptr, authsize, is_sec1);
12779c4a7965SKim Phillips 
12789c4a7965SKim Phillips 			/* icv data follows link tables */
1279*549bd8bcSLEROY Christophe 			to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl + offset,
1280*549bd8bcSLEROY Christophe 				       is_sec1);
1281*549bd8bcSLEROY Christophe 		}
1282340ff60aSHoria Geant? 	} else {
1283*549bd8bcSLEROY Christophe 		edesc->icv_ool = false;
1284*549bd8bcSLEROY Christophe 	}
1285*549bd8bcSLEROY Christophe 
1286*549bd8bcSLEROY Christophe 	/* ICV data */
1287*549bd8bcSLEROY Christophe 	if (!(desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)) {
1288*549bd8bcSLEROY Christophe 		to_talitos_ptr_len(&desc->ptr[6], authsize, is_sec1);
1289*549bd8bcSLEROY Christophe 		to_talitos_ptr(&desc->ptr[6], edesc->dma_link_tbl +
1290*549bd8bcSLEROY Christophe 			       areq->assoclen + cryptlen, is_sec1);
1291340ff60aSHoria Geant? 	}
12929c4a7965SKim Phillips 
12939c4a7965SKim Phillips 	/* iv out */
1294*549bd8bcSLEROY Christophe 	if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP)
1295a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
12969c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
12979c4a7965SKim Phillips 
1298*549bd8bcSLEROY Christophe 	if (sync_needed)
1299*549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1300*549bd8bcSLEROY Christophe 					   edesc->dma_len,
1301*549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1302*549bd8bcSLEROY Christophe 
13035228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1304fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
1305fa86a267SKim Phillips 		ipsec_esp_unmap(dev, edesc, areq);
1306fa86a267SKim Phillips 		kfree(edesc);
1307fa86a267SKim Phillips 	}
1308fa86a267SKim Phillips 	return ret;
13099c4a7965SKim Phillips }
13109c4a7965SKim Phillips 
13119c4a7965SKim Phillips /*
131256af8cd4SLee Nipper  * allocate and map the extended descriptor
13139c4a7965SKim Phillips  */
13144de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13154de9d0b5SLee Nipper 						 struct scatterlist *src,
13164de9d0b5SLee Nipper 						 struct scatterlist *dst,
131779fd31d3SHoria Geanta 						 u8 *iv,
131879fd31d3SHoria Geanta 						 unsigned int assoclen,
13194de9d0b5SLee Nipper 						 unsigned int cryptlen,
13204de9d0b5SLee Nipper 						 unsigned int authsize,
132179fd31d3SHoria Geanta 						 unsigned int ivsize,
13224de9d0b5SLee Nipper 						 int icv_stashing,
132362293a37SHoria Geanta 						 u32 cryptoflags,
132462293a37SHoria Geanta 						 bool encrypt)
13259c4a7965SKim Phillips {
132656af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13276a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
132879fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
13294de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1330586725f8SKim Phillips 		      GFP_ATOMIC;
13316f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
13326f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
13336f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
13348e409fe1SLABBE Corentin 	void *err;
13359c4a7965SKim Phillips 
13366f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
13374de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
13389c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
13399c4a7965SKim Phillips 	}
13409c4a7965SKim Phillips 
1341935e99a3SHoria Geanta 	if (ivsize)
134279fd31d3SHoria Geanta 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
134379fd31d3SHoria Geanta 
134462293a37SHoria Geanta 	if (!dst || dst == src) {
13456a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
13466a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13478e409fe1SLABBE Corentin 		if (src_nents < 0) {
13488e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13498e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13508e409fe1SLABBE Corentin 			goto error_sg;
13518e409fe1SLABBE Corentin 		}
13529c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
135362293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
13546a1e8d14SLEROY Christophe 		dst_len = 0;
135562293a37SHoria Geanta 	} else { /* dst && dst != src*/
13566a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
13576a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13588e409fe1SLABBE Corentin 		if (src_nents < 0) {
13598e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
13608e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13618e409fe1SLABBE Corentin 			goto error_sg;
13628e409fe1SLABBE Corentin 		}
136362293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
13646a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
13656a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
13668e409fe1SLABBE Corentin 		if (dst_nents < 0) {
13678e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
13688e409fe1SLABBE Corentin 			err = ERR_PTR(-EINVAL);
13698e409fe1SLABBE Corentin 			goto error_sg;
13708e409fe1SLABBE Corentin 		}
1371695ad589SLee Nipper 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
13729c4a7965SKim Phillips 	}
13739c4a7965SKim Phillips 
13749c4a7965SKim Phillips 	/*
13759c4a7965SKim Phillips 	 * allocate space for base edesc plus the link tables,
1376aeb4c132SHerbert Xu 	 * allowing for two separate entries for AD and generated ICV (+ 2),
1377aeb4c132SHerbert Xu 	 * and space for two sets of ICVs (stashed and generated)
13789c4a7965SKim Phillips 	 */
137956af8cd4SLee Nipper 	alloc_len = sizeof(struct talitos_edesc);
1380aeb4c132SHerbert Xu 	if (src_nents || dst_nents) {
13816f65f6acSLEROY Christophe 		if (is_sec1)
13826a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
13836a1e8d14SLEROY Christophe 				  (dst_nents ? dst_len : 0);
13846f65f6acSLEROY Christophe 		else
1385aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1386aeb4c132SHerbert Xu 				  sizeof(struct talitos_ptr) + authsize * 2;
13879c4a7965SKim Phillips 		alloc_len += dma_len;
13889c4a7965SKim Phillips 	} else {
13899c4a7965SKim Phillips 		dma_len = 0;
13904de9d0b5SLee Nipper 		alloc_len += icv_stashing ? authsize : 0;
13919c4a7965SKim Phillips 	}
13929c4a7965SKim Phillips 
1393586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
13949c4a7965SKim Phillips 	if (!edesc) {
13954de9d0b5SLee Nipper 		dev_err(dev, "could not allocate edescriptor\n");
13968e409fe1SLABBE Corentin 		err = ERR_PTR(-ENOMEM);
13978e409fe1SLABBE Corentin 		goto error_sg;
13989c4a7965SKim Phillips 	}
13999c4a7965SKim Phillips 
14009c4a7965SKim Phillips 	edesc->src_nents = src_nents;
14019c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
140279fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
14039c4a7965SKim Phillips 	edesc->dma_len = dma_len;
1404497f2e6bSLee Nipper 	if (dma_len)
14054de9d0b5SLee Nipper 		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1406497f2e6bSLee Nipper 						     edesc->dma_len,
1407497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
14089c4a7965SKim Phillips 
14099c4a7965SKim Phillips 	return edesc;
14108e409fe1SLABBE Corentin error_sg:
14118e409fe1SLABBE Corentin 	if (iv_dma)
14128e409fe1SLABBE Corentin 		dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
14138e409fe1SLABBE Corentin 	return err;
14149c4a7965SKim Phillips }
14159c4a7965SKim Phillips 
141679fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
141762293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
14184de9d0b5SLee Nipper {
14194de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1420aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14214de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
142279fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
14234de9d0b5SLee Nipper 
1424aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
142579fd31d3SHoria Geanta 				   iv, areq->assoclen, areq->cryptlen,
1426aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
142762293a37SHoria Geanta 				   areq->base.flags, encrypt);
14284de9d0b5SLee Nipper }
14294de9d0b5SLee Nipper 
143056af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
14319c4a7965SKim Phillips {
14329c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14339c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
143456af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14359c4a7965SKim Phillips 
14369c4a7965SKim Phillips 	/* allocate extended descriptor */
143762293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
14389c4a7965SKim Phillips 	if (IS_ERR(edesc))
14399c4a7965SKim Phillips 		return PTR_ERR(edesc);
14409c4a7965SKim Phillips 
14419c4a7965SKim Phillips 	/* set encrypt */
144270bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14439c4a7965SKim Phillips 
1444aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
14459c4a7965SKim Phillips }
14469c4a7965SKim Phillips 
144756af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
14489c4a7965SKim Phillips {
14499c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1450aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14519c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1452fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
145356af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14549c4a7965SKim Phillips 	struct scatterlist *sg;
14559c4a7965SKim Phillips 	void *icvdata;
14569c4a7965SKim Phillips 
14579c4a7965SKim Phillips 	req->cryptlen -= authsize;
14589c4a7965SKim Phillips 
14599c4a7965SKim Phillips 	/* allocate extended descriptor */
146062293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14619c4a7965SKim Phillips 	if (IS_ERR(edesc))
14629c4a7965SKim Phillips 		return PTR_ERR(edesc);
14639c4a7965SKim Phillips 
1464fe5720e2SKim Phillips 	if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1465e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1466e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1467fe5720e2SKim Phillips 
1468fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1469e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1470e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1471fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1472fe5720e2SKim Phillips 
1473fe5720e2SKim Phillips 		/* reset integrity check result bits */
1474fe5720e2SKim Phillips 		edesc->desc.hdr_lo = 0;
1475fe5720e2SKim Phillips 
1476aeb4c132SHerbert Xu 		return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
1477e938e465SKim Phillips 	}
1478fe5720e2SKim Phillips 
1479fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1480fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1481fe5720e2SKim Phillips 
14829c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
14839c4a7965SKim Phillips 	if (edesc->dma_len)
1484aeb4c132SHerbert Xu 		icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
1485aeb4c132SHerbert Xu 						   edesc->dst_nents + 2];
14869c4a7965SKim Phillips 	else
14879c4a7965SKim Phillips 		icvdata = &edesc->link_tbl[0];
14889c4a7965SKim Phillips 
14899c4a7965SKim Phillips 	sg = sg_last(req->src, edesc->src_nents ? : 1);
14909c4a7965SKim Phillips 
1491aeb4c132SHerbert Xu 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
14929c4a7965SKim Phillips 
1493aeb4c132SHerbert Xu 	return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
14949c4a7965SKim Phillips }
14959c4a7965SKim Phillips 
14964de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
14974de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
14984de9d0b5SLee Nipper {
14994de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15004de9d0b5SLee Nipper 
15014de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
15024de9d0b5SLee Nipper 	ctx->keylen = keylen;
15034de9d0b5SLee Nipper 
15044de9d0b5SLee Nipper 	return 0;
15054de9d0b5SLee Nipper }
15064de9d0b5SLee Nipper 
15074de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
15084de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
15094de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
15104de9d0b5SLee Nipper {
15114de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1512032d197eSLEROY Christophe 
15136a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0);
15144de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
15154de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
15164de9d0b5SLee Nipper 
15174de9d0b5SLee Nipper 	if (edesc->dma_len)
15184de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
15194de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
15204de9d0b5SLee Nipper }
15214de9d0b5SLee Nipper 
15224de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
15234de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
15244de9d0b5SLee Nipper 			    int err)
15254de9d0b5SLee Nipper {
15264de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
152719bbbc63SKim Phillips 	struct talitos_edesc *edesc;
152819bbbc63SKim Phillips 
152919bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
15304de9d0b5SLee Nipper 
15314de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
15324de9d0b5SLee Nipper 
15334de9d0b5SLee Nipper 	kfree(edesc);
15344de9d0b5SLee Nipper 
15354de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
15364de9d0b5SLee Nipper }
15374de9d0b5SLee Nipper 
15384de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
15394de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
15404de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
15414de9d0b5SLee Nipper 					     struct talitos_desc *desc,
15424de9d0b5SLee Nipper 					     void *context, int error))
15434de9d0b5SLee Nipper {
15444de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15454de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15464de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
15474de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
15484de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
154979fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
15504de9d0b5SLee Nipper 	int sg_count, ret;
15516a1e8d14SLEROY Christophe 	bool sync_needed = false;
1552922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1553922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
15544de9d0b5SLee Nipper 
15554de9d0b5SLee Nipper 	/* first DWORD empty */
15562529bc37SLEROY Christophe 	desc->ptr[0] = zero_entry;
15574de9d0b5SLee Nipper 
15584de9d0b5SLee Nipper 	/* cipher iv */
1559922f9dc8SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, is_sec1);
1560922f9dc8SLEROY Christophe 	to_talitos_ptr_len(&desc->ptr[1], ivsize, is_sec1);
1561b096b544SLEROY Christophe 	to_talitos_ptr_ext_set(&desc->ptr[1], 0, is_sec1);
15624de9d0b5SLee Nipper 
15634de9d0b5SLee Nipper 	/* cipher key */
15644de9d0b5SLee Nipper 	map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1565a2b35aa8SLEROY Christophe 			       (char *)&ctx->key, DMA_TO_DEVICE);
15664de9d0b5SLee Nipper 
15676a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
15686a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
15696a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
15706a1e8d14SLEROY Christophe 				  cryptlen);
15716a1e8d14SLEROY Christophe 	else
15726a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
15736a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
15746a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
15754de9d0b5SLee Nipper 	/*
15764de9d0b5SLee Nipper 	 * cipher in
15774de9d0b5SLee Nipper 	 */
15786a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
15796a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
15806a1e8d14SLEROY Christophe 	if (sg_count > 1)
15816a1e8d14SLEROY Christophe 		sync_needed = true;
15824de9d0b5SLee Nipper 
15834de9d0b5SLee Nipper 	/* cipher out */
15846a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
15856a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
15866a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
15876a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
15886a1e8d14SLEROY Christophe 	}
15896a1e8d14SLEROY Christophe 
15906a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
15916a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
15926a1e8d14SLEROY Christophe 	if (ret > 1)
15936a1e8d14SLEROY Christophe 		sync_needed = true;
15944de9d0b5SLee Nipper 
15954de9d0b5SLee Nipper 	/* iv out */
1596a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
15974de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
15984de9d0b5SLee Nipper 
15994de9d0b5SLee Nipper 	/* last DWORD empty */
16002529bc37SLEROY Christophe 	desc->ptr[6] = zero_entry;
16014de9d0b5SLee Nipper 
16026a1e8d14SLEROY Christophe 	if (sync_needed)
16036a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
16046a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
16056a1e8d14SLEROY Christophe 
16065228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
16074de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
16084de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
16094de9d0b5SLee Nipper 		kfree(edesc);
16104de9d0b5SLee Nipper 	}
16114de9d0b5SLee Nipper 	return ret;
16124de9d0b5SLee Nipper }
16134de9d0b5SLee Nipper 
1614e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
161562293a37SHoria Geanta 						    areq, bool encrypt)
16164de9d0b5SLee Nipper {
16174de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16184de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
161979fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
16204de9d0b5SLee Nipper 
1621aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
162279fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
162362293a37SHoria Geanta 				   areq->base.flags, encrypt);
16244de9d0b5SLee Nipper }
16254de9d0b5SLee Nipper 
16264de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
16274de9d0b5SLee Nipper {
16284de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16294de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16304de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16314de9d0b5SLee Nipper 
16324de9d0b5SLee Nipper 	/* allocate extended descriptor */
163362293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
16344de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16354de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16364de9d0b5SLee Nipper 
16374de9d0b5SLee Nipper 	/* set encrypt */
16384de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16394de9d0b5SLee Nipper 
1640febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16414de9d0b5SLee Nipper }
16424de9d0b5SLee Nipper 
16434de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
16444de9d0b5SLee Nipper {
16454de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16464de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16474de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
16484de9d0b5SLee Nipper 
16494de9d0b5SLee Nipper 	/* allocate extended descriptor */
165062293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
16514de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16524de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16534de9d0b5SLee Nipper 
16544de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
16554de9d0b5SLee Nipper 
1656febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16574de9d0b5SLee Nipper }
16584de9d0b5SLee Nipper 
1659497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1660497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1661497f2e6bSLee Nipper 				       struct ahash_request *areq)
1662497f2e6bSLee Nipper {
1663497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1664922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1665922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1666497f2e6bSLee Nipper 
1667497f2e6bSLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1668497f2e6bSLee Nipper 
16696a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1670032d197eSLEROY Christophe 
1671497f2e6bSLee Nipper 	/* When using hashctx-in, must unmap it. */
1672922f9dc8SLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
1673497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1674497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1675497f2e6bSLee Nipper 
1676922f9dc8SLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[2], is_sec1))
1677497f2e6bSLee Nipper 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2],
1678497f2e6bSLee Nipper 					 DMA_TO_DEVICE);
1679497f2e6bSLee Nipper 
1680497f2e6bSLee Nipper 	if (edesc->dma_len)
1681497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1682497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1683497f2e6bSLee Nipper 
1684497f2e6bSLee Nipper }
1685497f2e6bSLee Nipper 
1686497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1687497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1688497f2e6bSLee Nipper 		       int err)
1689497f2e6bSLee Nipper {
1690497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1691497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1692497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1693497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1694497f2e6bSLee Nipper 
1695497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1696497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
1697497f2e6bSLee Nipper 		memcpy(req_ctx->buf, req_ctx->bufnext, req_ctx->to_hash_later);
16985e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1699497f2e6bSLee Nipper 	}
1700497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1701497f2e6bSLee Nipper 
1702497f2e6bSLee Nipper 	kfree(edesc);
1703497f2e6bSLee Nipper 
1704497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1705497f2e6bSLee Nipper }
1706497f2e6bSLee Nipper 
17072d02905eSLEROY Christophe /*
17082d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
17092d02905eSLEROY Christophe  * ourself and submit a padded block
17102d02905eSLEROY Christophe  */
17112d02905eSLEROY Christophe void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
17122d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
17132d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
17142d02905eSLEROY Christophe {
17152d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
17162d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17172d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17182d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17192d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17202d02905eSLEROY Christophe 	};
17212d02905eSLEROY Christophe 
17222d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
17232d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
17242d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
17252d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
17262d02905eSLEROY Christophe }
17272d02905eSLEROY Christophe 
1728497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1729497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
1730497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1731497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1732497f2e6bSLee Nipper 						  void *context, int error))
1733497f2e6bSLee Nipper {
1734497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1735497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1736497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1737497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1738497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1739032d197eSLEROY Christophe 	int ret;
17406a1e8d14SLEROY Christophe 	bool sync_needed = false;
1741922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1742922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
17436a1e8d14SLEROY Christophe 	int sg_count;
1744497f2e6bSLee Nipper 
1745497f2e6bSLee Nipper 	/* first DWORD empty */
1746497f2e6bSLee Nipper 	desc->ptr[0] = zero_entry;
1747497f2e6bSLee Nipper 
174860f208d7SKim Phillips 	/* hash context in */
174960f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
1750497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[1],
1751497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1752a2b35aa8SLEROY Christophe 				       (char *)req_ctx->hw_context,
1753497f2e6bSLee Nipper 				       DMA_TO_DEVICE);
175460f208d7SKim Phillips 		req_ctx->swinit = 0;
1755497f2e6bSLee Nipper 	} else {
1756497f2e6bSLee Nipper 		desc->ptr[1] = zero_entry;
1757497f2e6bSLee Nipper 		/* Indicate next op is not the first. */
1758497f2e6bSLee Nipper 		req_ctx->first = 0;
1759497f2e6bSLee Nipper 	}
1760497f2e6bSLee Nipper 
1761497f2e6bSLee Nipper 	/* HMAC key */
1762497f2e6bSLee Nipper 	if (ctx->keylen)
1763497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
1764a2b35aa8SLEROY Christophe 				       (char *)&ctx->key, DMA_TO_DEVICE);
1765497f2e6bSLee Nipper 	else
1766497f2e6bSLee Nipper 		desc->ptr[2] = zero_entry;
1767497f2e6bSLee Nipper 
17686a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
17696a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
17706a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf, length);
17716a1e8d14SLEROY Christophe 	else
17726a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
17736a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1774497f2e6bSLee Nipper 	/*
1775497f2e6bSLee Nipper 	 * data in
1776497f2e6bSLee Nipper 	 */
17776a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
17786a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
17796a1e8d14SLEROY Christophe 	if (sg_count > 1)
17806a1e8d14SLEROY Christophe 		sync_needed = true;
1781497f2e6bSLee Nipper 
1782497f2e6bSLee Nipper 	/* fifth DWORD empty */
1783497f2e6bSLee Nipper 	desc->ptr[4] = zero_entry;
1784497f2e6bSLee Nipper 
1785497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1786497f2e6bSLee Nipper 	if (req_ctx->last)
1787497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1788497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1789a2b35aa8SLEROY Christophe 				       areq->result, DMA_FROM_DEVICE);
1790497f2e6bSLee Nipper 	else
1791497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1792497f2e6bSLee Nipper 				       req_ctx->hw_context_size,
1793a2b35aa8SLEROY Christophe 				       req_ctx->hw_context, DMA_FROM_DEVICE);
1794497f2e6bSLee Nipper 
1795497f2e6bSLee Nipper 	/* last DWORD empty */
1796497f2e6bSLee Nipper 	desc->ptr[6] = zero_entry;
1797497f2e6bSLee Nipper 
17982d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
17992d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
18002d02905eSLEROY Christophe 
18016a1e8d14SLEROY Christophe 	if (sync_needed)
18026a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
18036a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
18046a1e8d14SLEROY Christophe 
18055228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1806497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1807497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1808497f2e6bSLee Nipper 		kfree(edesc);
1809497f2e6bSLee Nipper 	}
1810497f2e6bSLee Nipper 	return ret;
1811497f2e6bSLee Nipper }
1812497f2e6bSLee Nipper 
1813497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1814497f2e6bSLee Nipper 					       unsigned int nbytes)
1815497f2e6bSLee Nipper {
1816497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1817497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1818497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1819497f2e6bSLee Nipper 
1820aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
182162293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1822497f2e6bSLee Nipper }
1823497f2e6bSLee Nipper 
1824497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1825497f2e6bSLee Nipper {
1826497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1827497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1828497f2e6bSLee Nipper 
1829497f2e6bSLee Nipper 	/* Initialize the context */
18305e833bc4SLee Nipper 	req_ctx->nbuf = 0;
183160f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
183260f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
1833497f2e6bSLee Nipper 	req_ctx->hw_context_size =
1834497f2e6bSLee Nipper 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1835497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1836497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
1837497f2e6bSLee Nipper 
1838497f2e6bSLee Nipper 	return 0;
1839497f2e6bSLee Nipper }
1840497f2e6bSLee Nipper 
184160f208d7SKim Phillips /*
184260f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
184360f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
184460f208d7SKim Phillips  */
184560f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
184660f208d7SKim Phillips {
184760f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
184860f208d7SKim Phillips 
184960f208d7SKim Phillips 	ahash_init(areq);
185060f208d7SKim Phillips 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
185160f208d7SKim Phillips 
1852a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1853a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1854a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1855a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1856a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1857a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1858a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1859a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
186060f208d7SKim Phillips 
186160f208d7SKim Phillips 	/* init 64-bit count */
186260f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
186360f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
186460f208d7SKim Phillips 
186560f208d7SKim Phillips 	return 0;
186660f208d7SKim Phillips }
186760f208d7SKim Phillips 
1868497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1869497f2e6bSLee Nipper {
1870497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1871497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1872497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1873497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1874497f2e6bSLee Nipper 	unsigned int blocksize =
1875497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1876497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1877497f2e6bSLee Nipper 	unsigned int to_hash_later;
18785e833bc4SLee Nipper 	unsigned int nsg;
18798e409fe1SLABBE Corentin 	int nents;
1880497f2e6bSLee Nipper 
18815e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
18825e833bc4SLee Nipper 		/* Buffer up to one whole block */
18838e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
18848e409fe1SLABBE Corentin 		if (nents < 0) {
18858e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
18868e409fe1SLABBE Corentin 			return nents;
18878e409fe1SLABBE Corentin 		}
18888e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
18895e833bc4SLee Nipper 				  req_ctx->buf + req_ctx->nbuf, nbytes);
18905e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
1891497f2e6bSLee Nipper 		return 0;
1892497f2e6bSLee Nipper 	}
1893497f2e6bSLee Nipper 
18945e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
18955e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
18965e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
18975e833bc4SLee Nipper 
18985e833bc4SLee Nipper 	if (req_ctx->last)
18995e833bc4SLee Nipper 		to_hash_later = 0;
19005e833bc4SLee Nipper 	else if (to_hash_later)
19015e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
19025e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
19035e833bc4SLee Nipper 	else {
19045e833bc4SLee Nipper 		/* Keep one block buffered */
19055e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
19065e833bc4SLee Nipper 		to_hash_later = blocksize;
1907497f2e6bSLee Nipper 	}
19085e833bc4SLee Nipper 
19095e833bc4SLee Nipper 	/* Chain in any previously buffered data */
19105e833bc4SLee Nipper 	if (req_ctx->nbuf) {
19115e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
19125e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
19135e833bc4SLee Nipper 		sg_set_buf(req_ctx->bufsl, req_ctx->buf, req_ctx->nbuf);
19145e833bc4SLee Nipper 		if (nsg > 1)
1915c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
19165e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
19175e833bc4SLee Nipper 	} else
19185e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
19195e833bc4SLee Nipper 
1920497f2e6bSLee Nipper 	if (to_hash_later) {
19218e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
19228e409fe1SLABBE Corentin 		if (nents < 0) {
19238e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
19248e409fe1SLABBE Corentin 			return nents;
19258e409fe1SLABBE Corentin 		}
1926d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
1927497f2e6bSLee Nipper 				      req_ctx->bufnext,
1928497f2e6bSLee Nipper 				      to_hash_later,
1929497f2e6bSLee Nipper 				      nbytes - to_hash_later);
1930497f2e6bSLee Nipper 	}
1931497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
1932497f2e6bSLee Nipper 
19335e833bc4SLee Nipper 	/* Allocate extended descriptor */
1934497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
1935497f2e6bSLee Nipper 	if (IS_ERR(edesc))
1936497f2e6bSLee Nipper 		return PTR_ERR(edesc);
1937497f2e6bSLee Nipper 
1938497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
1939497f2e6bSLee Nipper 
1940497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
1941497f2e6bSLee Nipper 	if (req_ctx->last)
1942497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
1943497f2e6bSLee Nipper 	else
1944497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
1945497f2e6bSLee Nipper 
194660f208d7SKim Phillips 	/* request SEC to INIT hash. */
194760f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
1948497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
1949497f2e6bSLee Nipper 
1950497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
1951497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
1952497f2e6bSLee Nipper 	 */
1953497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
1954497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
1955497f2e6bSLee Nipper 
1956497f2e6bSLee Nipper 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash,
1957497f2e6bSLee Nipper 				    ahash_done);
1958497f2e6bSLee Nipper }
1959497f2e6bSLee Nipper 
1960497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
1961497f2e6bSLee Nipper {
1962497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1963497f2e6bSLee Nipper 
1964497f2e6bSLee Nipper 	req_ctx->last = 0;
1965497f2e6bSLee Nipper 
1966497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1967497f2e6bSLee Nipper }
1968497f2e6bSLee Nipper 
1969497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
1970497f2e6bSLee Nipper {
1971497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1972497f2e6bSLee Nipper 
1973497f2e6bSLee Nipper 	req_ctx->last = 1;
1974497f2e6bSLee Nipper 
1975497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
1976497f2e6bSLee Nipper }
1977497f2e6bSLee Nipper 
1978497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
1979497f2e6bSLee Nipper {
1980497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1981497f2e6bSLee Nipper 
1982497f2e6bSLee Nipper 	req_ctx->last = 1;
1983497f2e6bSLee Nipper 
1984497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1985497f2e6bSLee Nipper }
1986497f2e6bSLee Nipper 
1987497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
1988497f2e6bSLee Nipper {
1989497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
199060f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
1991497f2e6bSLee Nipper 
199260f208d7SKim Phillips 	ahash->init(areq);
1993497f2e6bSLee Nipper 	req_ctx->last = 1;
1994497f2e6bSLee Nipper 
1995497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
1996497f2e6bSLee Nipper }
1997497f2e6bSLee Nipper 
19983639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
19993639ca84SHoria Geant? {
20003639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
20013639ca84SHoria Geant? 	struct talitos_export_state *export = out;
20023639ca84SHoria Geant? 
20033639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
20043639ca84SHoria Geant? 	       req_ctx->hw_context_size);
20053639ca84SHoria Geant? 	memcpy(export->buf, req_ctx->buf, req_ctx->nbuf);
20063639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
20073639ca84SHoria Geant? 	export->first = req_ctx->first;
20083639ca84SHoria Geant? 	export->last = req_ctx->last;
20093639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
20103639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
20113639ca84SHoria Geant? 
20123639ca84SHoria Geant? 	return 0;
20133639ca84SHoria Geant? }
20143639ca84SHoria Geant? 
20153639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
20163639ca84SHoria Geant? {
20173639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
20183639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
20193639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
20203639ca84SHoria Geant? 
20213639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
20223639ca84SHoria Geant? 	req_ctx->hw_context_size =
20233639ca84SHoria Geant? 		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
20243639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
20253639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
20263639ca84SHoria Geant? 	memcpy(req_ctx->hw_context, export->hw_context,
20273639ca84SHoria Geant? 	       req_ctx->hw_context_size);
20283639ca84SHoria Geant? 	memcpy(req_ctx->buf, export->buf, export->nbuf);
20293639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
20303639ca84SHoria Geant? 	req_ctx->first = export->first;
20313639ca84SHoria Geant? 	req_ctx->last = export->last;
20323639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
20333639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
20343639ca84SHoria Geant? 
20353639ca84SHoria Geant? 	return 0;
20363639ca84SHoria Geant? }
20373639ca84SHoria Geant? 
203879b3a418SLee Nipper struct keyhash_result {
203979b3a418SLee Nipper 	struct completion completion;
204079b3a418SLee Nipper 	int err;
204179b3a418SLee Nipper };
204279b3a418SLee Nipper 
204379b3a418SLee Nipper static void keyhash_complete(struct crypto_async_request *req, int err)
204479b3a418SLee Nipper {
204579b3a418SLee Nipper 	struct keyhash_result *res = req->data;
204679b3a418SLee Nipper 
204779b3a418SLee Nipper 	if (err == -EINPROGRESS)
204879b3a418SLee Nipper 		return;
204979b3a418SLee Nipper 
205079b3a418SLee Nipper 	res->err = err;
205179b3a418SLee Nipper 	complete(&res->completion);
205279b3a418SLee Nipper }
205379b3a418SLee Nipper 
205479b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
205579b3a418SLee Nipper 		   u8 *hash)
205679b3a418SLee Nipper {
205779b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
205879b3a418SLee Nipper 
205979b3a418SLee Nipper 	struct scatterlist sg[1];
206079b3a418SLee Nipper 	struct ahash_request *req;
206179b3a418SLee Nipper 	struct keyhash_result hresult;
206279b3a418SLee Nipper 	int ret;
206379b3a418SLee Nipper 
206479b3a418SLee Nipper 	init_completion(&hresult.completion);
206579b3a418SLee Nipper 
206679b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
206779b3a418SLee Nipper 	if (!req)
206879b3a418SLee Nipper 		return -ENOMEM;
206979b3a418SLee Nipper 
207079b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
207179b3a418SLee Nipper 	ctx->keylen = 0;
207279b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
207379b3a418SLee Nipper 				   keyhash_complete, &hresult);
207479b3a418SLee Nipper 
207579b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
207679b3a418SLee Nipper 
207779b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
207879b3a418SLee Nipper 	ret = crypto_ahash_digest(req);
207979b3a418SLee Nipper 	switch (ret) {
208079b3a418SLee Nipper 	case 0:
208179b3a418SLee Nipper 		break;
208279b3a418SLee Nipper 	case -EINPROGRESS:
208379b3a418SLee Nipper 	case -EBUSY:
208479b3a418SLee Nipper 		ret = wait_for_completion_interruptible(
208579b3a418SLee Nipper 			&hresult.completion);
208679b3a418SLee Nipper 		if (!ret)
208779b3a418SLee Nipper 			ret = hresult.err;
208879b3a418SLee Nipper 		break;
208979b3a418SLee Nipper 	default:
209079b3a418SLee Nipper 		break;
209179b3a418SLee Nipper 	}
209279b3a418SLee Nipper 	ahash_request_free(req);
209379b3a418SLee Nipper 
209479b3a418SLee Nipper 	return ret;
209579b3a418SLee Nipper }
209679b3a418SLee Nipper 
209779b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
209879b3a418SLee Nipper 			unsigned int keylen)
209979b3a418SLee Nipper {
210079b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
210179b3a418SLee Nipper 	unsigned int blocksize =
210279b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
210379b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
210479b3a418SLee Nipper 	unsigned int keysize = keylen;
210579b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
210679b3a418SLee Nipper 	int ret;
210779b3a418SLee Nipper 
210879b3a418SLee Nipper 	if (keylen <= blocksize)
210979b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
211079b3a418SLee Nipper 	else {
211179b3a418SLee Nipper 		/* Must get the hash of the long key */
211279b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
211379b3a418SLee Nipper 
211479b3a418SLee Nipper 		if (ret) {
211579b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
211679b3a418SLee Nipper 			return -EINVAL;
211779b3a418SLee Nipper 		}
211879b3a418SLee Nipper 
211979b3a418SLee Nipper 		keysize = digestsize;
212079b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
212179b3a418SLee Nipper 	}
212279b3a418SLee Nipper 
212379b3a418SLee Nipper 	ctx->keylen = keysize;
212479b3a418SLee Nipper 
212579b3a418SLee Nipper 	return 0;
212679b3a418SLee Nipper }
212779b3a418SLee Nipper 
212879b3a418SLee Nipper 
21299c4a7965SKim Phillips struct talitos_alg_template {
2130d5e4aaefSLee Nipper 	u32 type;
2131d5e4aaefSLee Nipper 	union {
2132d5e4aaefSLee Nipper 		struct crypto_alg crypto;
2133acbf7c62SLee Nipper 		struct ahash_alg hash;
2134aeb4c132SHerbert Xu 		struct aead_alg aead;
2135d5e4aaefSLee Nipper 	} alg;
21369c4a7965SKim Phillips 	__be32 desc_hdr_template;
21379c4a7965SKim Phillips };
21389c4a7965SKim Phillips 
21399c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2140991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2141d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2142aeb4c132SHerbert Xu 		.alg.aead = {
2143aeb4c132SHerbert Xu 			.base = {
214456af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2145aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2146aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
214756af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2148aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2149aeb4c132SHerbert Xu 			},
21503952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
21513952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
21529c4a7965SKim Phillips 		},
21539c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
21549c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
21559c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
21569c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
21579c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
21589c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
21599c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
216070bcaca7SLee Nipper 	},
2161d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2162aeb4c132SHerbert Xu 		.alg.aead = {
2163aeb4c132SHerbert Xu 			.base = {
2164aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2165aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2166aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2167aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
216856af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2169aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2170aeb4c132SHerbert Xu 			},
21713952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
21723952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
217370bcaca7SLee Nipper 		},
217470bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
217570bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
217670bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
217770bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
217870bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
217970bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
218070bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
218170bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
21823952f17eSLee Nipper 	},
2183d5e4aaefSLee Nipper 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2184aeb4c132SHerbert Xu 		.alg.aead = {
2185aeb4c132SHerbert Xu 			.base = {
2186357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2187aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2188aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2189357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2190aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2191aeb4c132SHerbert Xu 			},
2192357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2193357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2194357fb605SHoria Geanta 		},
2195357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2196357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2197357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2198357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2199357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2200357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2201357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2202357fb605SHoria Geanta 	},
2203357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2204aeb4c132SHerbert Xu 		.alg.aead = {
2205aeb4c132SHerbert Xu 			.base = {
2206aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2207aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2208aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2209aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2210357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2211aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2212aeb4c132SHerbert Xu 			},
2213357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2214357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2215357fb605SHoria Geanta 		},
2216357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2217357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2218357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2219357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2220357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2221357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2222357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2223357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2224357fb605SHoria Geanta 	},
2225357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2226aeb4c132SHerbert Xu 		.alg.aead = {
2227aeb4c132SHerbert Xu 			.base = {
222856af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2229aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
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 = SHA256_DIGEST_SIZE,
22363952f17eSLee Nipper 		},
22373952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
22383952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
22393952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
22403952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
22413952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
22423952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
22433952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
22443952f17eSLee Nipper 	},
2245d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2246aeb4c132SHerbert Xu 		.alg.aead = {
2247aeb4c132SHerbert Xu 			.base = {
2248aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2249aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2250aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2251aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
225256af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2253aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2254aeb4c132SHerbert Xu 			},
22553952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
22563952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
22573952f17eSLee Nipper 		},
22583952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
22593952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
22603952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
22613952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
22623952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
22633952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
22643952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
22653952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
22663952f17eSLee Nipper 	},
2267d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2268aeb4c132SHerbert Xu 		.alg.aead = {
2269aeb4c132SHerbert Xu 			.base = {
2270357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2271aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2272aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2273357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2274aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2275aeb4c132SHerbert Xu 			},
2276357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2277357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2278357fb605SHoria Geanta 		},
2279357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2280357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2281357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2282357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2283357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2284357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2285357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2286357fb605SHoria Geanta 	},
2287357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2288aeb4c132SHerbert Xu 		.alg.aead = {
2289aeb4c132SHerbert Xu 			.base = {
2290aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2291aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2292aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2293aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2294357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2295aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2296aeb4c132SHerbert Xu 			},
2297357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2298357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2299357fb605SHoria Geanta 		},
2300357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2301357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2302357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2303357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2304357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2305357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2306357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2307357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2308357fb605SHoria Geanta 	},
2309357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2310aeb4c132SHerbert Xu 		.alg.aead = {
2311aeb4c132SHerbert Xu 			.base = {
2312357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2313aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2314aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2315357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2316aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2317aeb4c132SHerbert Xu 			},
2318357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2319357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2320357fb605SHoria Geanta 		},
2321357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2322357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2323357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2324357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2325357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2326357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2327357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2328357fb605SHoria Geanta 	},
2329357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2330aeb4c132SHerbert Xu 		.alg.aead = {
2331aeb4c132SHerbert Xu 			.base = {
2332aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2333aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2334aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2335aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2336357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2337aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2338aeb4c132SHerbert Xu 			},
2339357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2340357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2341357fb605SHoria Geanta 		},
2342357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2343357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2344357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2345357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2346357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2347357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2348357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2349357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2350357fb605SHoria Geanta 	},
2351357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2352aeb4c132SHerbert Xu 		.alg.aead = {
2353aeb4c132SHerbert Xu 			.base = {
235456af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2355aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2356aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
235756af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2358aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2359aeb4c132SHerbert Xu 			},
23603952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
23613952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
23623952f17eSLee Nipper 		},
23633952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23643952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
23653952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
23663952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
23673952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
23683952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
23693952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
23703952f17eSLee Nipper 	},
2371d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2372aeb4c132SHerbert Xu 		.alg.aead = {
2373aeb4c132SHerbert Xu 			.base = {
237456af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2375aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2376aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
237756af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2378aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2379aeb4c132SHerbert Xu 			},
23803952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
23813952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
23823952f17eSLee Nipper 		},
23833952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23843952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
23853952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
23863952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
23873952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
23883952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
23893952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
23903952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
23914de9d0b5SLee Nipper 	},
23924de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2393d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2394d5e4aaefSLee Nipper 		.alg.crypto = {
23955e75ae1bSLEROY Christophe 			.cra_name = "ecb(aes)",
23965e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-aes-talitos",
23975e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
23985e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
23995e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
24005e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
24015e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
24025e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
24035e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
24045e75ae1bSLEROY Christophe 			}
24055e75ae1bSLEROY Christophe 		},
24065e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24075e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
24085e75ae1bSLEROY Christophe 	},
24095e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
24105e75ae1bSLEROY Christophe 		.alg.crypto = {
24114de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
24124de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
24134de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
24144de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
24154de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
24164de9d0b5SLee Nipper 			.cra_ablkcipher = {
24174de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
24184de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
24194de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
24204de9d0b5SLee Nipper 			}
24214de9d0b5SLee Nipper 		},
24224de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24234de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
24244de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
24254de9d0b5SLee Nipper 	},
2426d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2427d5e4aaefSLee Nipper 		.alg.crypto = {
24285e75ae1bSLEROY Christophe 			.cra_name = "ctr(aes)",
24295e75ae1bSLEROY Christophe 			.cra_driver_name = "ctr-aes-talitos",
24305e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
24315e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
24325e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
24335e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
24345e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
24355e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
24365e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
24375e75ae1bSLEROY Christophe 			}
24385e75ae1bSLEROY Christophe 		},
24395e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24405e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
24415e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
24425e75ae1bSLEROY Christophe 	},
24435e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
24445e75ae1bSLEROY Christophe 		.alg.crypto = {
24455e75ae1bSLEROY Christophe 			.cra_name = "ecb(des)",
24465e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-des-talitos",
24475e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
24485e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
24495e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
24505e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
24515e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
24525e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
24535e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
24545e75ae1bSLEROY Christophe 			}
24555e75ae1bSLEROY Christophe 		},
24565e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24575e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
24585e75ae1bSLEROY Christophe 	},
24595e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
24605e75ae1bSLEROY Christophe 		.alg.crypto = {
24615e75ae1bSLEROY Christophe 			.cra_name = "cbc(des)",
24625e75ae1bSLEROY Christophe 			.cra_driver_name = "cbc-des-talitos",
24635e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
24645e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
24655e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
24665e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
24675e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
24685e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
24695e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
24705e75ae1bSLEROY Christophe 			}
24715e75ae1bSLEROY Christophe 		},
24725e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24735e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24745e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
24755e75ae1bSLEROY Christophe 	},
24765e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
24775e75ae1bSLEROY Christophe 		.alg.crypto = {
24785e75ae1bSLEROY Christophe 			.cra_name = "ecb(des3_ede)",
24795e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-3des-talitos",
24805e75ae1bSLEROY Christophe 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24815e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
24825e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
24835e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
24845e75ae1bSLEROY Christophe 				.min_keysize = DES3_EDE_KEY_SIZE,
24855e75ae1bSLEROY Christophe 				.max_keysize = DES3_EDE_KEY_SIZE,
24865e75ae1bSLEROY Christophe 				.ivsize = DES3_EDE_BLOCK_SIZE,
24875e75ae1bSLEROY Christophe 			}
24885e75ae1bSLEROY Christophe 		},
24895e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
24905e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24915e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
24925e75ae1bSLEROY Christophe 	},
24935e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
24945e75ae1bSLEROY Christophe 		.alg.crypto = {
24954de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
24964de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
24974de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24984de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
24994de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
25004de9d0b5SLee Nipper 			.cra_ablkcipher = {
25014de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
25024de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
25034de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
25044de9d0b5SLee Nipper 			}
25054de9d0b5SLee Nipper 		},
25064de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
25074de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
25084de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
25094de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2510497f2e6bSLee Nipper 	},
2511497f2e6bSLee Nipper 	/* AHASH algorithms. */
2512497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2513497f2e6bSLee Nipper 		.alg.hash = {
2514497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
25153639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2516497f2e6bSLee Nipper 			.halg.base = {
2517497f2e6bSLee Nipper 				.cra_name = "md5",
2518497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2519b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
2520497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2521497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
25229c4a7965SKim Phillips 			}
2523497f2e6bSLee Nipper 		},
2524497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2525497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2526497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2527497f2e6bSLee Nipper 	},
2528497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2529497f2e6bSLee Nipper 		.alg.hash = {
2530497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
25313639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2532497f2e6bSLee Nipper 			.halg.base = {
2533497f2e6bSLee Nipper 				.cra_name = "sha1",
2534497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2535497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
2536497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2537497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2538497f2e6bSLee Nipper 			}
2539497f2e6bSLee Nipper 		},
2540497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2541497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2542497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2543497f2e6bSLee Nipper 	},
2544497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2545497f2e6bSLee Nipper 		.alg.hash = {
254660f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
25473639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
254860f208d7SKim Phillips 			.halg.base = {
254960f208d7SKim Phillips 				.cra_name = "sha224",
255060f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
255160f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
255260f208d7SKim Phillips 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
255360f208d7SKim Phillips 					     CRYPTO_ALG_ASYNC,
255460f208d7SKim Phillips 			}
255560f208d7SKim Phillips 		},
255660f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
255760f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
255860f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
255960f208d7SKim Phillips 	},
256060f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
256160f208d7SKim Phillips 		.alg.hash = {
2562497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
25633639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2564497f2e6bSLee Nipper 			.halg.base = {
2565497f2e6bSLee Nipper 				.cra_name = "sha256",
2566497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2567497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
2568497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2569497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2570497f2e6bSLee Nipper 			}
2571497f2e6bSLee Nipper 		},
2572497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2573497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2574497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2575497f2e6bSLee Nipper 	},
2576497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2577497f2e6bSLee Nipper 		.alg.hash = {
2578497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
25793639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2580497f2e6bSLee Nipper 			.halg.base = {
2581497f2e6bSLee Nipper 				.cra_name = "sha384",
2582497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2583497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
2584497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2585497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2586497f2e6bSLee Nipper 			}
2587497f2e6bSLee Nipper 		},
2588497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2589497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2590497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2591497f2e6bSLee Nipper 	},
2592497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2593497f2e6bSLee Nipper 		.alg.hash = {
2594497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
25953639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2596497f2e6bSLee Nipper 			.halg.base = {
2597497f2e6bSLee Nipper 				.cra_name = "sha512",
2598497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2599497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
2600497f2e6bSLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
2601497f2e6bSLee Nipper 					     CRYPTO_ALG_ASYNC,
2602497f2e6bSLee Nipper 			}
2603497f2e6bSLee Nipper 		},
2604497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2605497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2606497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2607497f2e6bSLee Nipper 	},
260879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
260979b3a418SLee Nipper 		.alg.hash = {
261079b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
26113639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
261279b3a418SLee Nipper 			.halg.base = {
261379b3a418SLee Nipper 				.cra_name = "hmac(md5)",
261479b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2615b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
261679b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
261779b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
261879b3a418SLee Nipper 			}
261979b3a418SLee Nipper 		},
262079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
262179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
262279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
262379b3a418SLee Nipper 	},
262479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
262579b3a418SLee Nipper 		.alg.hash = {
262679b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
26273639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
262879b3a418SLee Nipper 			.halg.base = {
262979b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
263079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
263179b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
263279b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
263379b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
263479b3a418SLee Nipper 			}
263579b3a418SLee Nipper 		},
263679b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
263779b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
263879b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
263979b3a418SLee Nipper 	},
264079b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
264179b3a418SLee Nipper 		.alg.hash = {
264279b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
26433639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
264479b3a418SLee Nipper 			.halg.base = {
264579b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
264679b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
264779b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
264879b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
264979b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
265079b3a418SLee Nipper 			}
265179b3a418SLee Nipper 		},
265279b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
265379b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
265479b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
265579b3a418SLee Nipper 	},
265679b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
265779b3a418SLee Nipper 		.alg.hash = {
265879b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
26593639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
266079b3a418SLee Nipper 			.halg.base = {
266179b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
266279b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
266379b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
266479b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
266579b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
266679b3a418SLee Nipper 			}
266779b3a418SLee Nipper 		},
266879b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
266979b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
267079b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
267179b3a418SLee Nipper 	},
267279b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
267379b3a418SLee Nipper 		.alg.hash = {
267479b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
26753639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
267679b3a418SLee Nipper 			.halg.base = {
267779b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
267879b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
267979b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
268079b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
268179b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
268279b3a418SLee Nipper 			}
268379b3a418SLee Nipper 		},
268479b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
268579b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
268679b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
268779b3a418SLee Nipper 	},
268879b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
268979b3a418SLee Nipper 		.alg.hash = {
269079b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
26913639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
269279b3a418SLee Nipper 			.halg.base = {
269379b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
269479b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
269579b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
269679b3a418SLee Nipper 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
269779b3a418SLee Nipper 					     CRYPTO_ALG_ASYNC,
269879b3a418SLee Nipper 			}
269979b3a418SLee Nipper 		},
270079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
270179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
270279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
270379b3a418SLee Nipper 	}
27049c4a7965SKim Phillips };
27059c4a7965SKim Phillips 
27069c4a7965SKim Phillips struct talitos_crypto_alg {
27079c4a7965SKim Phillips 	struct list_head entry;
27089c4a7965SKim Phillips 	struct device *dev;
2709acbf7c62SLee Nipper 	struct talitos_alg_template algt;
27109c4a7965SKim Phillips };
27119c4a7965SKim Phillips 
271289d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
271389d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
27149c4a7965SKim Phillips {
27155228f0f7SKim Phillips 	struct talitos_private *priv;
27169c4a7965SKim Phillips 
27179c4a7965SKim Phillips 	/* update context with ptr to dev */
27189c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
271919bbbc63SKim Phillips 
27205228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
27215228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
27225228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
27235228f0f7SKim Phillips 		  (priv->num_channels - 1);
27245228f0f7SKim Phillips 
27259c4a7965SKim Phillips 	/* copy descriptor header template value */
2726acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
27279c4a7965SKim Phillips 
2728602dba5aSKim Phillips 	/* select done notification */
2729602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
2730602dba5aSKim Phillips 
2731497f2e6bSLee Nipper 	return 0;
2732497f2e6bSLee Nipper }
2733497f2e6bSLee Nipper 
273489d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm)
273589d124cbSJonas Eymann {
273689d124cbSJonas Eymann 	struct crypto_alg *alg = tfm->__crt_alg;
273789d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
273889d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
273989d124cbSJonas Eymann 
274089d124cbSJonas Eymann 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
274189d124cbSJonas Eymann 		talitos_alg = container_of(__crypto_ahash_alg(alg),
274289d124cbSJonas Eymann 					   struct talitos_crypto_alg,
274389d124cbSJonas Eymann 					   algt.alg.hash);
274489d124cbSJonas Eymann 	else
274589d124cbSJonas Eymann 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
274689d124cbSJonas Eymann 					   algt.alg.crypto);
274789d124cbSJonas Eymann 
274889d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
274989d124cbSJonas Eymann }
275089d124cbSJonas Eymann 
2751aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
2752497f2e6bSLee Nipper {
275389d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
275489d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
275589d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
275689d124cbSJonas Eymann 
275789d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
275889d124cbSJonas Eymann 				   algt.alg.aead);
275989d124cbSJonas Eymann 
276089d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
27619c4a7965SKim Phillips }
27629c4a7965SKim Phillips 
2763497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
2764497f2e6bSLee Nipper {
2765497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
2766497f2e6bSLee Nipper 
2767497f2e6bSLee Nipper 	talitos_cra_init(tfm);
2768497f2e6bSLee Nipper 
2769497f2e6bSLee Nipper 	ctx->keylen = 0;
2770497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
2771497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
2772497f2e6bSLee Nipper 
2773497f2e6bSLee Nipper 	return 0;
2774497f2e6bSLee Nipper }
2775497f2e6bSLee Nipper 
27769c4a7965SKim Phillips /*
27779c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
27789c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
27799c4a7965SKim Phillips  * capabilities description provided in the device tree node.
27809c4a7965SKim Phillips  */
27819c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
27829c4a7965SKim Phillips {
27839c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
27849c4a7965SKim Phillips 	int ret;
27859c4a7965SKim Phillips 
27869c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
27879c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
27889c4a7965SKim Phillips 
27899c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
27909c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
27919c4a7965SKim Phillips 		              & priv->exec_units);
27929c4a7965SKim Phillips 
27939c4a7965SKim Phillips 	return ret;
27949c4a7965SKim Phillips }
27959c4a7965SKim Phillips 
27962dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
27979c4a7965SKim Phillips {
27989c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
27999c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
28009c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
28019c4a7965SKim Phillips 	int i;
28029c4a7965SKim Phillips 
28039c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
2804acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
2805acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
2806acbf7c62SLee Nipper 			break;
2807aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
2808aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
2809acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
2810acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
2811acbf7c62SLee Nipper 			break;
2812acbf7c62SLee Nipper 		}
28139c4a7965SKim Phillips 		list_del(&t_alg->entry);
28149c4a7965SKim Phillips 		kfree(t_alg);
28159c4a7965SKim Phillips 	}
28169c4a7965SKim Phillips 
28179c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
28189c4a7965SKim Phillips 		talitos_unregister_rng(dev);
28199c4a7965SKim Phillips 
282035a3bb3dSAaron Sierra 	for (i = 0; priv->chan && i < priv->num_channels; i++)
28214b992628SKim Phillips 		kfree(priv->chan[i].fifo);
28229c4a7965SKim Phillips 
28234b992628SKim Phillips 	kfree(priv->chan);
28249c4a7965SKim Phillips 
2825c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
28262cdba3cfSKim Phillips 		if (priv->irq[i]) {
2827c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
2828c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
28299c4a7965SKim Phillips 		}
28309c4a7965SKim Phillips 
2831c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
28322cdba3cfSKim Phillips 	if (priv->irq[1])
2833c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
28349c4a7965SKim Phillips 
28359c4a7965SKim Phillips 	iounmap(priv->reg);
28369c4a7965SKim Phillips 
28379c4a7965SKim Phillips 	kfree(priv);
28389c4a7965SKim Phillips 
28399c4a7965SKim Phillips 	return 0;
28409c4a7965SKim Phillips }
28419c4a7965SKim Phillips 
28429c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
28439c4a7965SKim Phillips 						    struct talitos_alg_template
28449c4a7965SKim Phillips 						           *template)
28459c4a7965SKim Phillips {
284660f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
28479c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
28489c4a7965SKim Phillips 	struct crypto_alg *alg;
28499c4a7965SKim Phillips 
28509c4a7965SKim Phillips 	t_alg = kzalloc(sizeof(struct talitos_crypto_alg), GFP_KERNEL);
28519c4a7965SKim Phillips 	if (!t_alg)
28529c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
28539c4a7965SKim Phillips 
2854acbf7c62SLee Nipper 	t_alg->algt = *template;
2855acbf7c62SLee Nipper 
2856acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
2857acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
2858497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
2859497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
2860d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
2861b286e003SKim Phillips 		alg->cra_ablkcipher.setkey = ablkcipher_setkey;
2862b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
2863b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
2864b286e003SKim Phillips 		alg->cra_ablkcipher.geniv = "eseqiv";
2865497f2e6bSLee Nipper 		break;
2866acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
2867aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
2868aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
2869aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.setkey = aead_setkey;
2870aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
2871aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
2872acbf7c62SLee Nipper 		break;
2873acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
2874acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
2875497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
2876d4cd3283SKim Phillips 		alg->cra_type = &crypto_ahash_type;
2877b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
2878b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
2879b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
2880b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
2881b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
2882b286e003SKim Phillips 		t_alg->algt.alg.hash.setkey = ahash_setkey;
28833639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
28843639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
2885b286e003SKim Phillips 
288679b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
28870b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
28880b2730d8SKim Phillips 			kfree(t_alg);
288979b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
28900b2730d8SKim Phillips 		}
289160f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
289279b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
289379b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
289460f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
289560f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
289660f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
289760f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
289860f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
289960f208d7SKim Phillips 		}
2900497f2e6bSLee Nipper 		break;
29011d11911aSKim Phillips 	default:
29021d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
29035fa7dadcSHoria Geant? 		kfree(t_alg);
29041d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
2905acbf7c62SLee Nipper 	}
29069c4a7965SKim Phillips 
29079c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
29089c4a7965SKim Phillips 	alg->cra_priority = TALITOS_CRA_PRIORITY;
29099c4a7965SKim Phillips 	alg->cra_alignmask = 0;
29109c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
2911d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
29129c4a7965SKim Phillips 
29139c4a7965SKim Phillips 	t_alg->dev = dev;
29149c4a7965SKim Phillips 
29159c4a7965SKim Phillips 	return t_alg;
29169c4a7965SKim Phillips }
29179c4a7965SKim Phillips 
2918c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
2919c3e337f8SKim Phillips {
2920c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
2921c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
2922c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2923c3e337f8SKim Phillips 	int err;
2924dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2925c3e337f8SKim Phillips 
2926c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
29272cdba3cfSKim Phillips 	if (!priv->irq[0]) {
2928c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
2929c3e337f8SKim Phillips 		return -EINVAL;
2930c3e337f8SKim Phillips 	}
2931dd3c0987SLEROY Christophe 	if (is_sec1) {
2932dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
2933dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
2934dd3c0987SLEROY Christophe 		goto primary_out;
2935dd3c0987SLEROY Christophe 	}
2936c3e337f8SKim Phillips 
2937c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
2938c3e337f8SKim Phillips 
2939c3e337f8SKim Phillips 	/* get the primary irq line */
29402cdba3cfSKim Phillips 	if (!priv->irq[1]) {
2941dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
2942c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
2943c3e337f8SKim Phillips 		goto primary_out;
2944c3e337f8SKim Phillips 	}
2945c3e337f8SKim Phillips 
2946dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
2947c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
2948c3e337f8SKim Phillips 	if (err)
2949c3e337f8SKim Phillips 		goto primary_out;
2950c3e337f8SKim Phillips 
2951c3e337f8SKim Phillips 	/* get the secondary irq line */
2952dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
2953c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
2954c3e337f8SKim Phillips 	if (err) {
2955c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
2956c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
29572cdba3cfSKim Phillips 		priv->irq[1] = 0;
2958c3e337f8SKim Phillips 	}
2959c3e337f8SKim Phillips 
2960c3e337f8SKim Phillips 	return err;
2961c3e337f8SKim Phillips 
2962c3e337f8SKim Phillips primary_out:
2963c3e337f8SKim Phillips 	if (err) {
2964c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
2965c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
29662cdba3cfSKim Phillips 		priv->irq[0] = 0;
2967c3e337f8SKim Phillips 	}
2968c3e337f8SKim Phillips 
2969c3e337f8SKim Phillips 	return err;
2970c3e337f8SKim Phillips }
2971c3e337f8SKim Phillips 
29721c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
29739c4a7965SKim Phillips {
29749c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
297561c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
29769c4a7965SKim Phillips 	struct talitos_private *priv;
29779c4a7965SKim Phillips 	const unsigned int *prop;
29789c4a7965SKim Phillips 	int i, err;
29795fa7fa14SLEROY Christophe 	int stride;
29809c4a7965SKim Phillips 
29819c4a7965SKim Phillips 	priv = kzalloc(sizeof(struct talitos_private), GFP_KERNEL);
29829c4a7965SKim Phillips 	if (!priv)
29839c4a7965SKim Phillips 		return -ENOMEM;
29849c4a7965SKim Phillips 
2985f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
2986f3de9cb1SKevin Hao 
29879c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
29889c4a7965SKim Phillips 
29899c4a7965SKim Phillips 	priv->ofdev = ofdev;
29909c4a7965SKim Phillips 
2991511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
2992511d63cbSHoria Geanta 
29939c4a7965SKim Phillips 	priv->reg = of_iomap(np, 0);
29949c4a7965SKim Phillips 	if (!priv->reg) {
29959c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
29969c4a7965SKim Phillips 		err = -ENOMEM;
29979c4a7965SKim Phillips 		goto err_out;
29989c4a7965SKim Phillips 	}
29999c4a7965SKim Phillips 
30009c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
30019c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,num-channels", NULL);
30029c4a7965SKim Phillips 	if (prop)
30039c4a7965SKim Phillips 		priv->num_channels = *prop;
30049c4a7965SKim Phillips 
30059c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,channel-fifo-len", NULL);
30069c4a7965SKim Phillips 	if (prop)
30079c4a7965SKim Phillips 		priv->chfifo_len = *prop;
30089c4a7965SKim Phillips 
30099c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,exec-units-mask", NULL);
30109c4a7965SKim Phillips 	if (prop)
30119c4a7965SKim Phillips 		priv->exec_units = *prop;
30129c4a7965SKim Phillips 
30139c4a7965SKim Phillips 	prop = of_get_property(np, "fsl,descriptor-types-mask", NULL);
30149c4a7965SKim Phillips 	if (prop)
30159c4a7965SKim Phillips 		priv->desc_types = *prop;
30169c4a7965SKim Phillips 
30179c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
30189c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
30199c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
30209c4a7965SKim Phillips 		err = -EINVAL;
30219c4a7965SKim Phillips 		goto err_out;
30229c4a7965SKim Phillips 	}
30239c4a7965SKim Phillips 
3024f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3025f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3026f3c85bc1SLee Nipper 
3027fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
302860f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
302979b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
303079b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3031fe5720e2SKim Phillips 
303221590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
303321590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
303421590888SLEROY Christophe 
30355fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
30365fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
30375fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
30385fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
30395fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
30405fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
30415fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
30425fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
30435fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
30445fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
30455fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
30465fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
30475fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
30485fa7fa14SLEROY Christophe 	} else {
30495fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
30505fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
30515fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
30525fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
30535fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
30545fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
30555fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
30565fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
30575fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
30585fa7fa14SLEROY Christophe 	}
30595fa7fa14SLEROY Christophe 
3060dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3061dd3c0987SLEROY Christophe 	if (err)
3062dd3c0987SLEROY Christophe 		goto err_out;
3063dd3c0987SLEROY Christophe 
3064dd3c0987SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0")) {
3065dd3c0987SLEROY Christophe 		tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3066dd3c0987SLEROY Christophe 			     (unsigned long)dev);
3067dd3c0987SLEROY Christophe 	} else {
3068dd3c0987SLEROY Christophe 		if (!priv->irq[1]) {
3069dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
3070dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3071dd3c0987SLEROY Christophe 		} else {
3072dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3073dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3074dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3075dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3076dd3c0987SLEROY Christophe 		}
3077dd3c0987SLEROY Christophe 	}
3078dd3c0987SLEROY Christophe 
30794b992628SKim Phillips 	priv->chan = kzalloc(sizeof(struct talitos_channel) *
30804b992628SKim Phillips 			     priv->num_channels, GFP_KERNEL);
30814b992628SKim Phillips 	if (!priv->chan) {
30824b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
30839c4a7965SKim Phillips 		err = -ENOMEM;
30849c4a7965SKim Phillips 		goto err_out;
30859c4a7965SKim Phillips 	}
30869c4a7965SKim Phillips 
3087f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3088f641ddddSMartin Hicks 
3089c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
30905fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
30912cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3092c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3093ad42d5fcSKim Phillips 
30944b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
30954b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
30969c4a7965SKim Phillips 
30974b992628SKim Phillips 		priv->chan[i].fifo = kzalloc(sizeof(struct talitos_request) *
30989c4a7965SKim Phillips 					     priv->fifo_len, GFP_KERNEL);
30994b992628SKim Phillips 		if (!priv->chan[i].fifo) {
31009c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
31019c4a7965SKim Phillips 			err = -ENOMEM;
31029c4a7965SKim Phillips 			goto err_out;
31039c4a7965SKim Phillips 		}
31049c4a7965SKim Phillips 
31054b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
31064b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3107f641ddddSMartin Hicks 	}
31089c4a7965SKim Phillips 
310981eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
311081eb024cSKim Phillips 
31119c4a7965SKim Phillips 	/* reset and initialize the h/w */
31129c4a7965SKim Phillips 	err = init_device(dev);
31139c4a7965SKim Phillips 	if (err) {
31149c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
31159c4a7965SKim Phillips 		goto err_out;
31169c4a7965SKim Phillips 	}
31179c4a7965SKim Phillips 
31189c4a7965SKim Phillips 	/* register the RNG, if available */
31199c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
31209c4a7965SKim Phillips 		err = talitos_register_rng(dev);
31219c4a7965SKim Phillips 		if (err) {
31229c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
31239c4a7965SKim Phillips 			goto err_out;
31249c4a7965SKim Phillips 		} else
31259c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
31269c4a7965SKim Phillips 	}
31279c4a7965SKim Phillips 
31289c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
31299c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
31309c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
31319c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3132aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
31339c4a7965SKim Phillips 
31349c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
31359c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
31369c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
31370b2730d8SKim Phillips 				if (err == -ENOTSUPP)
313879b3a418SLee Nipper 					continue;
31399c4a7965SKim Phillips 				goto err_out;
31409c4a7965SKim Phillips 			}
31419c4a7965SKim Phillips 
3142acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3143acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
3144acbf7c62SLee Nipper 				err = crypto_register_alg(
3145acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
3146aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.crypto;
3147acbf7c62SLee Nipper 				break;
3148aeb4c132SHerbert Xu 
3149aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3150aeb4c132SHerbert Xu 				err = crypto_register_aead(
3151aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3152aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3153aeb4c132SHerbert Xu 				break;
3154aeb4c132SHerbert Xu 
3155acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3156acbf7c62SLee Nipper 				err = crypto_register_ahash(
3157acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3158aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3159acbf7c62SLee Nipper 				break;
3160acbf7c62SLee Nipper 			}
31619c4a7965SKim Phillips 			if (err) {
31629c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3163aeb4c132SHerbert Xu 					alg->cra_driver_name);
31649c4a7965SKim Phillips 				kfree(t_alg);
3165991155baSHoria Geanta 			} else
31669c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
31679c4a7965SKim Phillips 		}
31689c4a7965SKim Phillips 	}
31695b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
31705b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
31715b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
31729c4a7965SKim Phillips 
31739c4a7965SKim Phillips 	return 0;
31749c4a7965SKim Phillips 
31759c4a7965SKim Phillips err_out:
31769c4a7965SKim Phillips 	talitos_remove(ofdev);
31779c4a7965SKim Phillips 
31789c4a7965SKim Phillips 	return err;
31799c4a7965SKim Phillips }
31809c4a7965SKim Phillips 
31816c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
31820635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
31830635b7dbSLEROY Christophe 	{
31840635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
31850635b7dbSLEROY Christophe 	},
31860635b7dbSLEROY Christophe #endif
31870635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
31889c4a7965SKim Phillips 	{
31899c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
31909c4a7965SKim Phillips 	},
31910635b7dbSLEROY Christophe #endif
31929c4a7965SKim Phillips 	{},
31939c4a7965SKim Phillips };
31949c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
31959c4a7965SKim Phillips 
31961c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
31974018294bSGrant Likely 	.driver = {
31989c4a7965SKim Phillips 		.name = "talitos",
31994018294bSGrant Likely 		.of_match_table = talitos_match,
32004018294bSGrant Likely 	},
32019c4a7965SKim Phillips 	.probe = talitos_probe,
3202596f1034SAl Viro 	.remove = talitos_remove,
32039c4a7965SKim Phillips };
32049c4a7965SKim Phillips 
3205741e8c2dSAxel Lin module_platform_driver(talitos_driver);
32069c4a7965SKim Phillips 
32079c4a7965SKim Phillips MODULE_LICENSE("GPL");
32089c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
32099c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3210