xref: /linux/drivers/crypto/talitos.c (revision 7a6eda5b8d9dda3b7f15c764f1865f4569050fa6)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29c4a7965SKim Phillips /*
39c4a7965SKim Phillips  * talitos - Freescale Integrated Security Engine (SEC) device driver
49c4a7965SKim Phillips  *
55228f0f7SKim Phillips  * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
69c4a7965SKim Phillips  *
79c4a7965SKim Phillips  * Scatterlist Crypto API glue code copied from files with the following:
89c4a7965SKim Phillips  * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
99c4a7965SKim Phillips  *
109c4a7965SKim Phillips  * Crypto algorithm registration code copied from hifn driver:
119c4a7965SKim Phillips  * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
129c4a7965SKim Phillips  * All rights reserved.
139c4a7965SKim Phillips  */
149c4a7965SKim Phillips 
159c4a7965SKim Phillips #include <linux/kernel.h>
169c4a7965SKim Phillips #include <linux/module.h>
179c4a7965SKim Phillips #include <linux/mod_devicetable.h>
189c4a7965SKim Phillips #include <linux/device.h>
199c4a7965SKim Phillips #include <linux/interrupt.h>
209c4a7965SKim Phillips #include <linux/crypto.h>
219c4a7965SKim Phillips #include <linux/hw_random.h>
225af50730SRob Herring #include <linux/of_address.h>
235af50730SRob Herring #include <linux/of_irq.h>
249c4a7965SKim Phillips #include <linux/of_platform.h>
259c4a7965SKim Phillips #include <linux/dma-mapping.h>
269c4a7965SKim Phillips #include <linux/io.h>
279c4a7965SKim Phillips #include <linux/spinlock.h>
289c4a7965SKim Phillips #include <linux/rtnetlink.h>
295a0e3ad6STejun Heo #include <linux/slab.h>
309c4a7965SKim Phillips 
319c4a7965SKim Phillips #include <crypto/algapi.h>
329c4a7965SKim Phillips #include <crypto/aes.h>
339d574ae8SArd Biesheuvel #include <crypto/internal/des.h>
349c4a7965SKim Phillips #include <crypto/sha.h>
35497f2e6bSLee Nipper #include <crypto/md5.h>
36e98014abSHerbert Xu #include <crypto/internal/aead.h>
379c4a7965SKim Phillips #include <crypto/authenc.h>
384de9d0b5SLee Nipper #include <crypto/skcipher.h>
39acbf7c62SLee Nipper #include <crypto/hash.h>
40acbf7c62SLee Nipper #include <crypto/internal/hash.h>
414de9d0b5SLee Nipper #include <crypto/scatterwalk.h>
429c4a7965SKim Phillips 
439c4a7965SKim Phillips #include "talitos.h"
449c4a7965SKim Phillips 
45922f9dc8SLEROY Christophe static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
46da9de146SLEROY Christophe 			   unsigned int len, bool is_sec1)
4781eb024cSKim Phillips {
48edc6bd69SLEROY Christophe 	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
49da9de146SLEROY Christophe 	if (is_sec1) {
50da9de146SLEROY Christophe 		ptr->len1 = cpu_to_be16(len);
51da9de146SLEROY Christophe 	} else {
52da9de146SLEROY Christophe 		ptr->len = cpu_to_be16(len);
53edc6bd69SLEROY Christophe 		ptr->eptr = upper_32_bits(dma_addr);
5481eb024cSKim Phillips 	}
55da9de146SLEROY Christophe }
5681eb024cSKim Phillips 
57340ff60aSHoria Geant? static void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
58340ff60aSHoria Geant? 			     struct talitos_ptr *src_ptr, bool is_sec1)
59340ff60aSHoria Geant? {
60340ff60aSHoria Geant? 	dst_ptr->ptr = src_ptr->ptr;
61922f9dc8SLEROY Christophe 	if (is_sec1) {
62da9de146SLEROY Christophe 		dst_ptr->len1 = src_ptr->len1;
63922f9dc8SLEROY Christophe 	} else {
64da9de146SLEROY Christophe 		dst_ptr->len = src_ptr->len;
65da9de146SLEROY Christophe 		dst_ptr->eptr = src_ptr->eptr;
66538caf83SLEROY Christophe 	}
67922f9dc8SLEROY Christophe }
68538caf83SLEROY Christophe 
69922f9dc8SLEROY Christophe static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
70922f9dc8SLEROY Christophe 					   bool is_sec1)
71538caf83SLEROY Christophe {
72922f9dc8SLEROY Christophe 	if (is_sec1)
73922f9dc8SLEROY Christophe 		return be16_to_cpu(ptr->len1);
74922f9dc8SLEROY Christophe 	else
75538caf83SLEROY Christophe 		return be16_to_cpu(ptr->len);
76538caf83SLEROY Christophe }
77538caf83SLEROY Christophe 
78b096b544SLEROY Christophe static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
79b096b544SLEROY Christophe 				   bool is_sec1)
80185eb79fSLEROY Christophe {
81922f9dc8SLEROY Christophe 	if (!is_sec1)
82b096b544SLEROY Christophe 		ptr->j_extent = val;
83b096b544SLEROY Christophe }
84b096b544SLEROY Christophe 
85b096b544SLEROY Christophe static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
86b096b544SLEROY Christophe {
87b096b544SLEROY Christophe 	if (!is_sec1)
88b096b544SLEROY Christophe 		ptr->j_extent |= val;
89185eb79fSLEROY Christophe }
90185eb79fSLEROY Christophe 
919c4a7965SKim Phillips /*
929c4a7965SKim Phillips  * map virtual single (contiguous) pointer to h/w descriptor pointer
939c4a7965SKim Phillips  */
946a4967c3SLEROY Christophe static void __map_single_talitos_ptr(struct device *dev,
956a4967c3SLEROY Christophe 				     struct talitos_ptr *ptr,
966a4967c3SLEROY Christophe 				     unsigned int len, void *data,
976a4967c3SLEROY Christophe 				     enum dma_data_direction dir,
986a4967c3SLEROY Christophe 				     unsigned long attrs)
996a4967c3SLEROY Christophe {
1006a4967c3SLEROY Christophe 	dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs);
1016a4967c3SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1026a4967c3SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1036a4967c3SLEROY Christophe 
1046a4967c3SLEROY Christophe 	to_talitos_ptr(ptr, dma_addr, len, is_sec1);
1056a4967c3SLEROY Christophe }
1066a4967c3SLEROY Christophe 
1079c4a7965SKim Phillips static void map_single_talitos_ptr(struct device *dev,
108edc6bd69SLEROY Christophe 				   struct talitos_ptr *ptr,
10942e8b0d7SHoria Geant? 				   unsigned int len, void *data,
1109c4a7965SKim Phillips 				   enum dma_data_direction dir)
1119c4a7965SKim Phillips {
1126a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir, 0);
1136a4967c3SLEROY Christophe }
11481eb024cSKim Phillips 
1156a4967c3SLEROY Christophe static void map_single_talitos_ptr_nosync(struct device *dev,
1166a4967c3SLEROY Christophe 					  struct talitos_ptr *ptr,
1176a4967c3SLEROY Christophe 					  unsigned int len, void *data,
1186a4967c3SLEROY Christophe 					  enum dma_data_direction dir)
1196a4967c3SLEROY Christophe {
1206a4967c3SLEROY Christophe 	__map_single_talitos_ptr(dev, ptr, len, data, dir,
1216a4967c3SLEROY Christophe 				 DMA_ATTR_SKIP_CPU_SYNC);
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);
16837b5e889SLEROY Christophe 	/* enable chaining descriptors */
16937b5e889SLEROY Christophe 	if (is_sec1)
17037b5e889SLEROY Christophe 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
17137b5e889SLEROY Christophe 			  TALITOS_CCCR_LO_NE);
1729c4a7965SKim Phillips 
173fe5720e2SKim Phillips 	/* and ICCR writeback, if available */
174fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
175ad42d5fcSKim Phillips 		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
176fe5720e2SKim Phillips 		          TALITOS_CCCR_LO_IWSE);
177fe5720e2SKim Phillips 
1789c4a7965SKim Phillips 	return 0;
1799c4a7965SKim Phillips }
1809c4a7965SKim Phillips 
1819c4a7965SKim Phillips static int reset_device(struct device *dev)
1829c4a7965SKim Phillips {
1839c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
1849c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
185dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
186dd3c0987SLEROY Christophe 	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
1879c4a7965SKim Phillips 
188c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_MCR, mcr);
1899c4a7965SKim Phillips 
190dd3c0987SLEROY Christophe 	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
1919c4a7965SKim Phillips 	       && --timeout)
1929c4a7965SKim Phillips 		cpu_relax();
1939c4a7965SKim Phillips 
1942cdba3cfSKim Phillips 	if (priv->irq[1]) {
195c3e337f8SKim Phillips 		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
196c3e337f8SKim Phillips 		setbits32(priv->reg + TALITOS_MCR, mcr);
197c3e337f8SKim Phillips 	}
198c3e337f8SKim Phillips 
1999c4a7965SKim Phillips 	if (timeout == 0) {
2009c4a7965SKim Phillips 		dev_err(dev, "failed to reset device\n");
2019c4a7965SKim Phillips 		return -EIO;
2029c4a7965SKim Phillips 	}
2039c4a7965SKim Phillips 
2049c4a7965SKim Phillips 	return 0;
2059c4a7965SKim Phillips }
2069c4a7965SKim Phillips 
2079c4a7965SKim Phillips /*
2089c4a7965SKim Phillips  * Reset and initialize the device
2099c4a7965SKim Phillips  */
2109c4a7965SKim Phillips static int init_device(struct device *dev)
2119c4a7965SKim Phillips {
2129c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2139c4a7965SKim Phillips 	int ch, err;
214dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2159c4a7965SKim Phillips 
2169c4a7965SKim Phillips 	/*
2179c4a7965SKim Phillips 	 * Master reset
2189c4a7965SKim Phillips 	 * errata documentation: warning: certain SEC interrupts
2199c4a7965SKim Phillips 	 * are not fully cleared by writing the MCR:SWR bit,
2209c4a7965SKim Phillips 	 * set bit twice to completely reset
2219c4a7965SKim Phillips 	 */
2229c4a7965SKim Phillips 	err = reset_device(dev);
2239c4a7965SKim Phillips 	if (err)
2249c4a7965SKim Phillips 		return err;
2259c4a7965SKim Phillips 
2269c4a7965SKim Phillips 	err = reset_device(dev);
2279c4a7965SKim Phillips 	if (err)
2289c4a7965SKim Phillips 		return err;
2299c4a7965SKim Phillips 
2309c4a7965SKim Phillips 	/* reset channels */
2319c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
2329c4a7965SKim Phillips 		err = reset_channel(dev, ch);
2339c4a7965SKim Phillips 		if (err)
2349c4a7965SKim Phillips 			return err;
2359c4a7965SKim Phillips 	}
2369c4a7965SKim Phillips 
2379c4a7965SKim Phillips 	/* enable channel done and error interrupts */
238dd3c0987SLEROY Christophe 	if (is_sec1) {
239dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
240dd3c0987SLEROY Christophe 		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
241dd3c0987SLEROY Christophe 		/* disable parity error check in DEU (erroneous? test vect.) */
242dd3c0987SLEROY Christophe 		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
243dd3c0987SLEROY Christophe 	} else {
244dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
245dd3c0987SLEROY Christophe 		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
246dd3c0987SLEROY Christophe 	}
2479c4a7965SKim Phillips 
248fe5720e2SKim Phillips 	/* disable integrity check error interrupts (use writeback instead) */
249fe5720e2SKim Phillips 	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2505fa7fa14SLEROY Christophe 		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
251fe5720e2SKim Phillips 		          TALITOS_MDEUICR_LO_ICE);
252fe5720e2SKim Phillips 
2539c4a7965SKim Phillips 	return 0;
2549c4a7965SKim Phillips }
2559c4a7965SKim Phillips 
2569c4a7965SKim Phillips /**
2579c4a7965SKim Phillips  * talitos_submit - submits a descriptor to the device for processing
2589c4a7965SKim Phillips  * @dev:	the SEC device to be used
2595228f0f7SKim Phillips  * @ch:		the SEC device channel to be used
2609c4a7965SKim Phillips  * @desc:	the descriptor to be processed by the device
2619c4a7965SKim Phillips  * @callback:	whom to call when processing is complete
2629c4a7965SKim Phillips  * @context:	a handle for use by caller (optional)
2639c4a7965SKim Phillips  *
2649c4a7965SKim Phillips  * desc must contain valid dma-mapped (bus physical) address pointers.
2659c4a7965SKim Phillips  * callback must check err and feedback in descriptor header
2669c4a7965SKim Phillips  * for device processing status.
2679c4a7965SKim Phillips  */
268fbb8d46eSChristophe Leroy static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2699c4a7965SKim Phillips 			  void (*callback)(struct device *dev,
2709c4a7965SKim Phillips 					   struct talitos_desc *desc,
2719c4a7965SKim Phillips 					   void *context, int error),
2729c4a7965SKim Phillips 			  void *context)
2739c4a7965SKim Phillips {
2749c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
2759c4a7965SKim Phillips 	struct talitos_request *request;
2765228f0f7SKim Phillips 	unsigned long flags;
2779c4a7965SKim Phillips 	int head;
2787d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
2799c4a7965SKim Phillips 
2804b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2819c4a7965SKim Phillips 
2824b992628SKim Phillips 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
283ec6644d6SKim Phillips 		/* h/w fifo is full */
2844b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2859c4a7965SKim Phillips 		return -EAGAIN;
2869c4a7965SKim Phillips 	}
2879c4a7965SKim Phillips 
2884b992628SKim Phillips 	head = priv->chan[ch].head;
2894b992628SKim Phillips 	request = &priv->chan[ch].fifo[head];
290ec6644d6SKim Phillips 
2919c4a7965SKim Phillips 	/* map descriptor and save caller data */
2927d607c6aSLEROY Christophe 	if (is_sec1) {
2937d607c6aSLEROY Christophe 		desc->hdr1 = desc->hdr;
2947d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, &desc->hdr1,
2957d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
2969c4a7965SKim Phillips 						   DMA_BIDIRECTIONAL);
2977d607c6aSLEROY Christophe 	} else {
2987d607c6aSLEROY Christophe 		request->dma_desc = dma_map_single(dev, desc,
2997d607c6aSLEROY Christophe 						   TALITOS_DESC_SIZE,
3007d607c6aSLEROY Christophe 						   DMA_BIDIRECTIONAL);
3017d607c6aSLEROY Christophe 	}
3029c4a7965SKim Phillips 	request->callback = callback;
3039c4a7965SKim Phillips 	request->context = context;
3049c4a7965SKim Phillips 
3059c4a7965SKim Phillips 	/* increment fifo head */
3064b992628SKim Phillips 	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
3079c4a7965SKim Phillips 
3089c4a7965SKim Phillips 	smp_wmb();
3099c4a7965SKim Phillips 	request->desc = desc;
3109c4a7965SKim Phillips 
3119c4a7965SKim Phillips 	/* GO! */
3129c4a7965SKim Phillips 	wmb();
313ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF,
314ad42d5fcSKim Phillips 		 upper_32_bits(request->dma_desc));
315ad42d5fcSKim Phillips 	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
316a752447aSKim Phillips 		 lower_32_bits(request->dma_desc));
3179c4a7965SKim Phillips 
3184b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3199c4a7965SKim Phillips 
3209c4a7965SKim Phillips 	return -EINPROGRESS;
3219c4a7965SKim Phillips }
3229c4a7965SKim Phillips 
32358cdbc6dSChristophe Leroy static __be32 get_request_hdr(struct talitos_request *request, bool is_sec1)
32458cdbc6dSChristophe Leroy {
32558cdbc6dSChristophe Leroy 	struct talitos_edesc *edesc;
32658cdbc6dSChristophe Leroy 
32758cdbc6dSChristophe Leroy 	if (!is_sec1)
32858cdbc6dSChristophe Leroy 		return request->desc->hdr;
32958cdbc6dSChristophe Leroy 
33058cdbc6dSChristophe Leroy 	if (!request->desc->next_desc)
33158cdbc6dSChristophe Leroy 		return request->desc->hdr1;
33258cdbc6dSChristophe Leroy 
33358cdbc6dSChristophe Leroy 	edesc = container_of(request->desc, struct talitos_edesc, desc);
33458cdbc6dSChristophe Leroy 
33558cdbc6dSChristophe Leroy 	return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1;
33658cdbc6dSChristophe Leroy }
3379c4a7965SKim Phillips 
3389c4a7965SKim Phillips /*
3399c4a7965SKim Phillips  * process what was done, notify callback of error if not
3409c4a7965SKim Phillips  */
3419c4a7965SKim Phillips static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3429c4a7965SKim Phillips {
3439c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3449c4a7965SKim Phillips 	struct talitos_request *request, saved_req;
3459c4a7965SKim Phillips 	unsigned long flags;
3469c4a7965SKim Phillips 	int tail, status;
3477d607c6aSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3489c4a7965SKim Phillips 
3494b992628SKim Phillips 	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3509c4a7965SKim Phillips 
3514b992628SKim Phillips 	tail = priv->chan[ch].tail;
3524b992628SKim Phillips 	while (priv->chan[ch].fifo[tail].desc) {
3537d607c6aSLEROY Christophe 		__be32 hdr;
3547d607c6aSLEROY Christophe 
3554b992628SKim Phillips 		request = &priv->chan[ch].fifo[tail];
3569c4a7965SKim Phillips 
3579c4a7965SKim Phillips 		/* descriptors with their done bits set don't get the error */
3589c4a7965SKim Phillips 		rmb();
35958cdbc6dSChristophe Leroy 		hdr = get_request_hdr(request, is_sec1);
3607d607c6aSLEROY Christophe 
3617d607c6aSLEROY Christophe 		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3629c4a7965SKim Phillips 			status = 0;
363ca38a814SLee Nipper 		else
3649c4a7965SKim Phillips 			if (!error)
3659c4a7965SKim Phillips 				break;
3669c4a7965SKim Phillips 			else
3679c4a7965SKim Phillips 				status = error;
3689c4a7965SKim Phillips 
3699c4a7965SKim Phillips 		dma_unmap_single(dev, request->dma_desc,
3707d607c6aSLEROY Christophe 				 TALITOS_DESC_SIZE,
371e938e465SKim Phillips 				 DMA_BIDIRECTIONAL);
3729c4a7965SKim Phillips 
3739c4a7965SKim Phillips 		/* copy entries so we can call callback outside lock */
3749c4a7965SKim Phillips 		saved_req.desc = request->desc;
3759c4a7965SKim Phillips 		saved_req.callback = request->callback;
3769c4a7965SKim Phillips 		saved_req.context = request->context;
3779c4a7965SKim Phillips 
3789c4a7965SKim Phillips 		/* release request entry in fifo */
3799c4a7965SKim Phillips 		smp_wmb();
3809c4a7965SKim Phillips 		request->desc = NULL;
3819c4a7965SKim Phillips 
3829c4a7965SKim Phillips 		/* increment fifo tail */
3834b992628SKim Phillips 		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3849c4a7965SKim Phillips 
3854b992628SKim Phillips 		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
386ec6644d6SKim Phillips 
3874b992628SKim Phillips 		atomic_dec(&priv->chan[ch].submit_count);
388ec6644d6SKim Phillips 
3899c4a7965SKim Phillips 		saved_req.callback(dev, saved_req.desc, saved_req.context,
3909c4a7965SKim Phillips 				   status);
3919c4a7965SKim Phillips 		/* channel may resume processing in single desc error case */
3929c4a7965SKim Phillips 		if (error && !reset_ch && status == error)
3939c4a7965SKim Phillips 			return;
3944b992628SKim Phillips 		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3954b992628SKim Phillips 		tail = priv->chan[ch].tail;
3969c4a7965SKim Phillips 	}
3979c4a7965SKim Phillips 
3984b992628SKim Phillips 	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
3999c4a7965SKim Phillips }
4009c4a7965SKim Phillips 
4019c4a7965SKim Phillips /*
4029c4a7965SKim Phillips  * process completed requests for channels that have done status
4039c4a7965SKim Phillips  */
404dd3c0987SLEROY Christophe #define DEF_TALITOS1_DONE(name, ch_done_mask)				\
405dd3c0987SLEROY Christophe static void talitos1_done_##name(unsigned long data)			\
406dd3c0987SLEROY Christophe {									\
407dd3c0987SLEROY Christophe 	struct device *dev = (struct device *)data;			\
408dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		\
409dd3c0987SLEROY Christophe 	unsigned long flags;						\
410dd3c0987SLEROY Christophe 									\
411dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x10000000)					\
412dd3c0987SLEROY Christophe 		flush_channel(dev, 0, 0, 0);			\
413dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x40000000)					\
414dd3c0987SLEROY Christophe 		flush_channel(dev, 1, 0, 0);			\
415dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00010000)					\
416dd3c0987SLEROY Christophe 		flush_channel(dev, 2, 0, 0);			\
417dd3c0987SLEROY Christophe 	if (ch_done_mask & 0x00040000)					\
418dd3c0987SLEROY Christophe 		flush_channel(dev, 3, 0, 0);			\
419dd3c0987SLEROY Christophe 									\
420dd3c0987SLEROY Christophe 	/* At this point, all completed channels have been processed */	\
421dd3c0987SLEROY Christophe 	/* Unmask done interrupts for channels completed later on. */	\
422dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			\
423dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
424dd3c0987SLEROY Christophe 	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
425dd3c0987SLEROY Christophe 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
426dd3c0987SLEROY Christophe }
427dd3c0987SLEROY Christophe 
428dd3c0987SLEROY Christophe DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
4299c02e285SLEROY Christophe DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
430dd3c0987SLEROY Christophe 
431dd3c0987SLEROY Christophe #define DEF_TALITOS2_DONE(name, ch_done_mask)				\
432dd3c0987SLEROY Christophe static void talitos2_done_##name(unsigned long data)			\
433c3e337f8SKim Phillips {									\
434c3e337f8SKim Phillips 	struct device *dev = (struct device *)data;			\
435c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		\
436511d63cbSHoria Geanta 	unsigned long flags;						\
437c3e337f8SKim Phillips 									\
438c3e337f8SKim Phillips 	if (ch_done_mask & 1)						\
439c3e337f8SKim Phillips 		flush_channel(dev, 0, 0, 0);				\
440c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 2))					\
441c3e337f8SKim Phillips 		flush_channel(dev, 1, 0, 0);				\
442c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 4))					\
443c3e337f8SKim Phillips 		flush_channel(dev, 2, 0, 0);				\
444c3e337f8SKim Phillips 	if (ch_done_mask & (1 << 6))					\
445c3e337f8SKim Phillips 		flush_channel(dev, 3, 0, 0);				\
446c3e337f8SKim Phillips 									\
447c3e337f8SKim Phillips 	/* At this point, all completed channels have been processed */	\
448c3e337f8SKim Phillips 	/* Unmask done interrupts for channels completed later on. */	\
449511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			\
450c3e337f8SKim Phillips 	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
451dd3c0987SLEROY Christophe 	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
452511d63cbSHoria Geanta 	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4539c4a7965SKim Phillips }
454dd3c0987SLEROY Christophe 
455dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
4569c02e285SLEROY Christophe DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
457dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
458dd3c0987SLEROY Christophe DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4599c4a7965SKim Phillips 
4609c4a7965SKim Phillips /*
4619c4a7965SKim Phillips  * locate current (offending) descriptor
4629c4a7965SKim Phillips  */
4633e721aebSKim Phillips static u32 current_desc_hdr(struct device *dev, int ch)
4649c4a7965SKim Phillips {
4659c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
466b62ffd8cSHoria Geanta 	int tail, iter;
4679c4a7965SKim Phillips 	dma_addr_t cur_desc;
4689c4a7965SKim Phillips 
469b62ffd8cSHoria Geanta 	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
470b62ffd8cSHoria Geanta 	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4719c4a7965SKim Phillips 
472b62ffd8cSHoria Geanta 	if (!cur_desc) {
473b62ffd8cSHoria Geanta 		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
474b62ffd8cSHoria Geanta 		return 0;
475b62ffd8cSHoria Geanta 	}
476b62ffd8cSHoria Geanta 
477b62ffd8cSHoria Geanta 	tail = priv->chan[ch].tail;
478b62ffd8cSHoria Geanta 
479b62ffd8cSHoria Geanta 	iter = tail;
48037b5e889SLEROY Christophe 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc &&
48137b5e889SLEROY Christophe 	       priv->chan[ch].fifo[iter].desc->next_desc != cur_desc) {
482b62ffd8cSHoria Geanta 		iter = (iter + 1) & (priv->fifo_len - 1);
483b62ffd8cSHoria Geanta 		if (iter == tail) {
4849c4a7965SKim Phillips 			dev_err(dev, "couldn't locate current descriptor\n");
4853e721aebSKim Phillips 			return 0;
4869c4a7965SKim Phillips 		}
4879c4a7965SKim Phillips 	}
4889c4a7965SKim Phillips 
48958cdbc6dSChristophe Leroy 	if (priv->chan[ch].fifo[iter].desc->next_desc == cur_desc) {
49058cdbc6dSChristophe Leroy 		struct talitos_edesc *edesc;
49158cdbc6dSChristophe Leroy 
49258cdbc6dSChristophe Leroy 		edesc = container_of(priv->chan[ch].fifo[iter].desc,
49358cdbc6dSChristophe Leroy 				     struct talitos_edesc, desc);
49458cdbc6dSChristophe Leroy 		return ((struct talitos_desc *)
49558cdbc6dSChristophe Leroy 			(edesc->buf + edesc->dma_len))->hdr;
49658cdbc6dSChristophe Leroy 	}
49737b5e889SLEROY Christophe 
498b62ffd8cSHoria Geanta 	return priv->chan[ch].fifo[iter].desc->hdr;
4999c4a7965SKim Phillips }
5009c4a7965SKim Phillips 
5019c4a7965SKim Phillips /*
5029c4a7965SKim Phillips  * user diagnostics; report root cause of error based on execution unit status
5039c4a7965SKim Phillips  */
5043e721aebSKim Phillips static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
5059c4a7965SKim Phillips {
5069c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5079c4a7965SKim Phillips 	int i;
5089c4a7965SKim Phillips 
5093e721aebSKim Phillips 	if (!desc_hdr)
510ad42d5fcSKim Phillips 		desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
5113e721aebSKim Phillips 
5123e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
5139c4a7965SKim Phillips 	case DESC_HDR_SEL0_AFEU:
5149c4a7965SKim Phillips 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
5155fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR),
5165fa7fa14SLEROY Christophe 			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
5179c4a7965SKim Phillips 		break;
5189c4a7965SKim Phillips 	case DESC_HDR_SEL0_DEU:
5199c4a7965SKim Phillips 		dev_err(dev, "DEUISR 0x%08x_%08x\n",
5205fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR),
5215fa7fa14SLEROY Christophe 			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
5229c4a7965SKim Phillips 		break;
5239c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUA:
5249c4a7965SKim Phillips 	case DESC_HDR_SEL0_MDEUB:
5259c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5265fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5275fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5289c4a7965SKim Phillips 		break;
5299c4a7965SKim Phillips 	case DESC_HDR_SEL0_RNG:
5309c4a7965SKim Phillips 		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
5315fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR),
5325fa7fa14SLEROY Christophe 			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5339c4a7965SKim Phillips 		break;
5349c4a7965SKim Phillips 	case DESC_HDR_SEL0_PKEU:
5359c4a7965SKim Phillips 		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5365fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5375fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5389c4a7965SKim Phillips 		break;
5399c4a7965SKim Phillips 	case DESC_HDR_SEL0_AESU:
5409c4a7965SKim Phillips 		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5415fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR),
5425fa7fa14SLEROY Christophe 			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5439c4a7965SKim Phillips 		break;
5449c4a7965SKim Phillips 	case DESC_HDR_SEL0_CRCU:
5459c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5465fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5475fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5489c4a7965SKim Phillips 		break;
5499c4a7965SKim Phillips 	case DESC_HDR_SEL0_KEU:
5509c4a7965SKim Phillips 		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5515fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5525fa7fa14SLEROY Christophe 			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5539c4a7965SKim Phillips 		break;
5549c4a7965SKim Phillips 	}
5559c4a7965SKim Phillips 
5563e721aebSKim Phillips 	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5579c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUA:
5589c4a7965SKim Phillips 	case DESC_HDR_SEL1_MDEUB:
5599c4a7965SKim Phillips 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5605fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5615fa7fa14SLEROY Christophe 			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5629c4a7965SKim Phillips 		break;
5639c4a7965SKim Phillips 	case DESC_HDR_SEL1_CRCU:
5649c4a7965SKim Phillips 		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5655fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR),
5665fa7fa14SLEROY Christophe 			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5679c4a7965SKim Phillips 		break;
5689c4a7965SKim Phillips 	}
5699c4a7965SKim Phillips 
5709c4a7965SKim Phillips 	for (i = 0; i < 8; i++)
5719c4a7965SKim Phillips 		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
572ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
573ad42d5fcSKim Phillips 			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5749c4a7965SKim Phillips }
5759c4a7965SKim Phillips 
5769c4a7965SKim Phillips /*
5779c4a7965SKim Phillips  * recover from error interrupts
5789c4a7965SKim Phillips  */
5795e718a09SKim Phillips static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5809c4a7965SKim Phillips {
5819c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
5829c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
583dd3c0987SLEROY Christophe 	int ch, error, reset_dev = 0;
58442e8b0d7SHoria Geant? 	u32 v_lo;
585dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
586dd3c0987SLEROY Christophe 	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5879c4a7965SKim Phillips 
5889c4a7965SKim Phillips 	for (ch = 0; ch < priv->num_channels; ch++) {
5899c4a7965SKim Phillips 		/* skip channels without errors */
590dd3c0987SLEROY Christophe 		if (is_sec1) {
591dd3c0987SLEROY Christophe 			/* bits 29, 31, 17, 19 */
592dd3c0987SLEROY Christophe 			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
593dd3c0987SLEROY Christophe 				continue;
594dd3c0987SLEROY Christophe 		} else {
5959c4a7965SKim Phillips 			if (!(isr & (1 << (ch * 2 + 1))))
5969c4a7965SKim Phillips 				continue;
597dd3c0987SLEROY Christophe 		}
5989c4a7965SKim Phillips 
5999c4a7965SKim Phillips 		error = -EINVAL;
6009c4a7965SKim Phillips 
601ad42d5fcSKim Phillips 		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
6029c4a7965SKim Phillips 
6039c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_DOF) {
6049c4a7965SKim Phillips 			dev_err(dev, "double fetch fifo overflow error\n");
6059c4a7965SKim Phillips 			error = -EAGAIN;
6069c4a7965SKim Phillips 			reset_ch = 1;
6079c4a7965SKim Phillips 		}
6089c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SOF) {
6099c4a7965SKim Phillips 			/* h/w dropped descriptor */
6109c4a7965SKim Phillips 			dev_err(dev, "single fetch fifo overflow error\n");
6119c4a7965SKim Phillips 			error = -EAGAIN;
6129c4a7965SKim Phillips 		}
6139c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
6149c4a7965SKim Phillips 			dev_err(dev, "master data transfer error\n");
6159c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
6164d9b3a5bSColin Ian King 			dev_err(dev, is_sec1 ? "pointer not complete error\n"
617dd3c0987SLEROY Christophe 					     : "s/g data length zero error\n");
6189c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
619dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "parity error\n"
620dd3c0987SLEROY Christophe 					     : "fetch pointer zero error\n");
6219c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IDH)
6229c4a7965SKim Phillips 			dev_err(dev, "illegal descriptor header error\n");
6239c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_IEU)
624dd3c0987SLEROY Christophe 			dev_err(dev, is_sec1 ? "static assignment error\n"
625dd3c0987SLEROY Christophe 					     : "invalid exec unit error\n");
6269c4a7965SKim Phillips 		if (v_lo & TALITOS_CCPSR_LO_EU)
6273e721aebSKim Phillips 			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
628dd3c0987SLEROY Christophe 		if (!is_sec1) {
6299c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GB)
6309c4a7965SKim Phillips 				dev_err(dev, "gather boundary error\n");
6319c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_GRL)
6329c4a7965SKim Phillips 				dev_err(dev, "gather return/length error\n");
6339c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SB)
6349c4a7965SKim Phillips 				dev_err(dev, "scatter boundary error\n");
6359c4a7965SKim Phillips 			if (v_lo & TALITOS_CCPSR_LO_SRL)
6369c4a7965SKim Phillips 				dev_err(dev, "scatter return/length error\n");
637dd3c0987SLEROY Christophe 		}
6389c4a7965SKim Phillips 
6399c4a7965SKim Phillips 		flush_channel(dev, ch, error, reset_ch);
6409c4a7965SKim Phillips 
6419c4a7965SKim Phillips 		if (reset_ch) {
6429c4a7965SKim Phillips 			reset_channel(dev, ch);
6439c4a7965SKim Phillips 		} else {
644ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
645dd3c0987SLEROY Christophe 				  TALITOS2_CCCR_CONT);
646ad42d5fcSKim Phillips 			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
647ad42d5fcSKim Phillips 			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
648dd3c0987SLEROY Christophe 			       TALITOS2_CCCR_CONT) && --timeout)
6499c4a7965SKim Phillips 				cpu_relax();
6509c4a7965SKim Phillips 			if (timeout == 0) {
6519c4a7965SKim Phillips 				dev_err(dev, "failed to restart channel %d\n",
6529c4a7965SKim Phillips 					ch);
6539c4a7965SKim Phillips 				reset_dev = 1;
6549c4a7965SKim Phillips 			}
6559c4a7965SKim Phillips 		}
6569c4a7965SKim Phillips 	}
657dd3c0987SLEROY Christophe 	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
658dd3c0987SLEROY Christophe 	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
659dd3c0987SLEROY Christophe 		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
660dd3c0987SLEROY Christophe 			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
661dd3c0987SLEROY Christophe 				isr, isr_lo);
662dd3c0987SLEROY Christophe 		else
663dd3c0987SLEROY Christophe 			dev_err(dev, "done overflow, internal time out, or "
664dd3c0987SLEROY Christophe 				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6659c4a7965SKim Phillips 
6669c4a7965SKim Phillips 		/* purge request queues */
6679c4a7965SKim Phillips 		for (ch = 0; ch < priv->num_channels; ch++)
6689c4a7965SKim Phillips 			flush_channel(dev, ch, -EIO, 1);
6699c4a7965SKim Phillips 
6709c4a7965SKim Phillips 		/* reset and reinitialize the device */
6719c4a7965SKim Phillips 		init_device(dev);
6729c4a7965SKim Phillips 	}
6739c4a7965SKim Phillips }
6749c4a7965SKim Phillips 
675dd3c0987SLEROY Christophe #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
676dd3c0987SLEROY Christophe static irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
677dd3c0987SLEROY Christophe {									       \
678dd3c0987SLEROY Christophe 	struct device *dev = data;					       \
679dd3c0987SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
680dd3c0987SLEROY Christophe 	u32 isr, isr_lo;						       \
681dd3c0987SLEROY Christophe 	unsigned long flags;						       \
682dd3c0987SLEROY Christophe 									       \
683dd3c0987SLEROY Christophe 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
684dd3c0987SLEROY Christophe 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
685dd3c0987SLEROY Christophe 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
686dd3c0987SLEROY Christophe 	/* Acknowledge interrupt */					       \
687dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
688dd3c0987SLEROY Christophe 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
689dd3c0987SLEROY Christophe 									       \
690dd3c0987SLEROY Christophe 	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
691dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
692dd3c0987SLEROY Christophe 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
693dd3c0987SLEROY Christophe 	}								       \
694dd3c0987SLEROY Christophe 	else {								       \
695dd3c0987SLEROY Christophe 		if (likely(isr & ch_done_mask)) {			       \
696dd3c0987SLEROY Christophe 			/* mask further done interrupts. */		       \
697dd3c0987SLEROY Christophe 			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
698dd3c0987SLEROY Christophe 			/* done_task will unmask done interrupts at exit */    \
699dd3c0987SLEROY Christophe 			tasklet_schedule(&priv->done_task[tlet]);	       \
700dd3c0987SLEROY Christophe 		}							       \
701dd3c0987SLEROY Christophe 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
702dd3c0987SLEROY Christophe 	}								       \
703dd3c0987SLEROY Christophe 									       \
704dd3c0987SLEROY Christophe 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
705dd3c0987SLEROY Christophe 								IRQ_NONE;      \
706dd3c0987SLEROY Christophe }
707dd3c0987SLEROY Christophe 
708dd3c0987SLEROY Christophe DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
709dd3c0987SLEROY Christophe 
710dd3c0987SLEROY Christophe #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
711dd3c0987SLEROY Christophe static irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
712c3e337f8SKim Phillips {									       \
713c3e337f8SKim Phillips 	struct device *dev = data;					       \
714c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);		       \
715c3e337f8SKim Phillips 	u32 isr, isr_lo;						       \
716511d63cbSHoria Geanta 	unsigned long flags;						       \
717c3e337f8SKim Phillips 									       \
718511d63cbSHoria Geanta 	spin_lock_irqsave(&priv->reg_lock, flags);			       \
719c3e337f8SKim Phillips 	isr = in_be32(priv->reg + TALITOS_ISR);				       \
720c3e337f8SKim Phillips 	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
721c3e337f8SKim Phillips 	/* Acknowledge interrupt */					       \
722c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
723c3e337f8SKim Phillips 	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
724c3e337f8SKim Phillips 									       \
725511d63cbSHoria Geanta 	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
726511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
727511d63cbSHoria Geanta 		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
728511d63cbSHoria Geanta 	}								       \
729511d63cbSHoria Geanta 	else {								       \
730c3e337f8SKim Phillips 		if (likely(isr & ch_done_mask)) {			       \
731c3e337f8SKim Phillips 			/* mask further done interrupts. */		       \
732c3e337f8SKim Phillips 			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
733c3e337f8SKim Phillips 			/* done_task will unmask done interrupts at exit */    \
734c3e337f8SKim Phillips 			tasklet_schedule(&priv->done_task[tlet]);	       \
735c3e337f8SKim Phillips 		}							       \
736511d63cbSHoria Geanta 		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
737511d63cbSHoria Geanta 	}								       \
738c3e337f8SKim Phillips 									       \
739c3e337f8SKim Phillips 	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
740c3e337f8SKim Phillips 								IRQ_NONE;      \
7411c2e8811SLee Nipper }
742dd3c0987SLEROY Christophe 
743dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
744dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
745dd3c0987SLEROY Christophe 		       0)
746dd3c0987SLEROY Christophe DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
747dd3c0987SLEROY Christophe 		       1)
7489c4a7965SKim Phillips 
7499c4a7965SKim Phillips /*
7509c4a7965SKim Phillips  * hwrng
7519c4a7965SKim Phillips  */
7529c4a7965SKim Phillips static int talitos_rng_data_present(struct hwrng *rng, int wait)
7539c4a7965SKim Phillips {
7549c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7559c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7569c4a7965SKim Phillips 	u32 ofl;
7579c4a7965SKim Phillips 	int i;
7589c4a7965SKim Phillips 
7599c4a7965SKim Phillips 	for (i = 0; i < 20; i++) {
7605fa7fa14SLEROY Christophe 		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7619c4a7965SKim Phillips 		      TALITOS_RNGUSR_LO_OFL;
7629c4a7965SKim Phillips 		if (ofl || !wait)
7639c4a7965SKim Phillips 			break;
7649c4a7965SKim Phillips 		udelay(10);
7659c4a7965SKim Phillips 	}
7669c4a7965SKim Phillips 
7679c4a7965SKim Phillips 	return !!ofl;
7689c4a7965SKim Phillips }
7699c4a7965SKim Phillips 
7709c4a7965SKim Phillips static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7719c4a7965SKim Phillips {
7729c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7739c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7749c4a7965SKim Phillips 
7759c4a7965SKim Phillips 	/* rng fifo requires 64-bit accesses */
7765fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7775fa7fa14SLEROY Christophe 	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7789c4a7965SKim Phillips 
7799c4a7965SKim Phillips 	return sizeof(u32);
7809c4a7965SKim Phillips }
7819c4a7965SKim Phillips 
7829c4a7965SKim Phillips static int talitos_rng_init(struct hwrng *rng)
7839c4a7965SKim Phillips {
7849c4a7965SKim Phillips 	struct device *dev = (struct device *)rng->priv;
7859c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
7869c4a7965SKim Phillips 	unsigned int timeout = TALITOS_TIMEOUT;
7879c4a7965SKim Phillips 
7885fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7895fa7fa14SLEROY Christophe 	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7905fa7fa14SLEROY Christophe 		 & TALITOS_RNGUSR_LO_RD)
7919c4a7965SKim Phillips 	       && --timeout)
7929c4a7965SKim Phillips 		cpu_relax();
7939c4a7965SKim Phillips 	if (timeout == 0) {
7949c4a7965SKim Phillips 		dev_err(dev, "failed to reset rng hw\n");
7959c4a7965SKim Phillips 		return -ENODEV;
7969c4a7965SKim Phillips 	}
7979c4a7965SKim Phillips 
7989c4a7965SKim Phillips 	/* start generating */
7995fa7fa14SLEROY Christophe 	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
8009c4a7965SKim Phillips 
8019c4a7965SKim Phillips 	return 0;
8029c4a7965SKim Phillips }
8039c4a7965SKim Phillips 
8049c4a7965SKim Phillips static int talitos_register_rng(struct device *dev)
8059c4a7965SKim Phillips {
8069c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
80735a3bb3dSAaron Sierra 	int err;
8089c4a7965SKim Phillips 
8099c4a7965SKim Phillips 	priv->rng.name		= dev_driver_string(dev),
8109c4a7965SKim Phillips 	priv->rng.init		= talitos_rng_init,
8119c4a7965SKim Phillips 	priv->rng.data_present	= talitos_rng_data_present,
8129c4a7965SKim Phillips 	priv->rng.data_read	= talitos_rng_data_read,
8139c4a7965SKim Phillips 	priv->rng.priv		= (unsigned long)dev;
8149c4a7965SKim Phillips 
81535a3bb3dSAaron Sierra 	err = hwrng_register(&priv->rng);
81635a3bb3dSAaron Sierra 	if (!err)
81735a3bb3dSAaron Sierra 		priv->rng_registered = true;
81835a3bb3dSAaron Sierra 
81935a3bb3dSAaron Sierra 	return err;
8209c4a7965SKim Phillips }
8219c4a7965SKim Phillips 
8229c4a7965SKim Phillips static void talitos_unregister_rng(struct device *dev)
8239c4a7965SKim Phillips {
8249c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
8259c4a7965SKim Phillips 
82635a3bb3dSAaron Sierra 	if (!priv->rng_registered)
82735a3bb3dSAaron Sierra 		return;
82835a3bb3dSAaron Sierra 
8299c4a7965SKim Phillips 	hwrng_unregister(&priv->rng);
83035a3bb3dSAaron Sierra 	priv->rng_registered = false;
8319c4a7965SKim Phillips }
8329c4a7965SKim Phillips 
8339c4a7965SKim Phillips /*
8349c4a7965SKim Phillips  * crypto alg
8359c4a7965SKim Phillips  */
8369c4a7965SKim Phillips #define TALITOS_CRA_PRIORITY		3000
8377405c8d7SLEROY Christophe /*
8387405c8d7SLEROY Christophe  * Defines a priority for doing AEAD with descriptors type
8397405c8d7SLEROY Christophe  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
8407405c8d7SLEROY Christophe  */
8417405c8d7SLEROY Christophe #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
842192125edSChristophe Leroy #ifdef CONFIG_CRYPTO_DEV_TALITOS2
84303d2c511SMartin Hicks #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
844b8fbdc2bSChristophe Leroy #else
845b8fbdc2bSChristophe Leroy #define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE)
846b8fbdc2bSChristophe Leroy #endif
8473952f17eSLee Nipper #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
84870bcaca7SLee Nipper 
8499c4a7965SKim Phillips struct talitos_ctx {
8509c4a7965SKim Phillips 	struct device *dev;
8515228f0f7SKim Phillips 	int ch;
8529c4a7965SKim Phillips 	__be32 desc_hdr_template;
8539c4a7965SKim Phillips 	u8 key[TALITOS_MAX_KEY_SIZE];
85470bcaca7SLee Nipper 	u8 iv[TALITOS_MAX_IV_LENGTH];
8552e13ce08SLEROY Christophe 	dma_addr_t dma_key;
8569c4a7965SKim Phillips 	unsigned int keylen;
8579c4a7965SKim Phillips 	unsigned int enckeylen;
8589c4a7965SKim Phillips 	unsigned int authkeylen;
8599c4a7965SKim Phillips };
8609c4a7965SKim Phillips 
861497f2e6bSLee Nipper #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
862497f2e6bSLee Nipper #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
863497f2e6bSLee Nipper 
864497f2e6bSLee Nipper struct talitos_ahash_req_ctx {
86560f208d7SKim Phillips 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
866497f2e6bSLee Nipper 	unsigned int hw_context_size;
8673c0dd190SLEROY Christophe 	u8 buf[2][HASH_MAX_BLOCK_SIZE];
8683c0dd190SLEROY Christophe 	int buf_idx;
86960f208d7SKim Phillips 	unsigned int swinit;
870497f2e6bSLee Nipper 	unsigned int first;
871497f2e6bSLee Nipper 	unsigned int last;
872497f2e6bSLee Nipper 	unsigned int to_hash_later;
87342e8b0d7SHoria Geant? 	unsigned int nbuf;
874497f2e6bSLee Nipper 	struct scatterlist bufsl[2];
875497f2e6bSLee Nipper 	struct scatterlist *psrc;
876497f2e6bSLee Nipper };
877497f2e6bSLee Nipper 
8783639ca84SHoria Geant? struct talitos_export_state {
8793639ca84SHoria Geant? 	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8803639ca84SHoria Geant? 	u8 buf[HASH_MAX_BLOCK_SIZE];
8813639ca84SHoria Geant? 	unsigned int swinit;
8823639ca84SHoria Geant? 	unsigned int first;
8833639ca84SHoria Geant? 	unsigned int last;
8843639ca84SHoria Geant? 	unsigned int to_hash_later;
8853639ca84SHoria Geant? 	unsigned int nbuf;
8863639ca84SHoria Geant? };
8873639ca84SHoria Geant? 
88856af8cd4SLee Nipper static int aead_setkey(struct crypto_aead *authenc,
8899c4a7965SKim Phillips 		       const u8 *key, unsigned int keylen)
8909c4a7965SKim Phillips {
8919c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
8922e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
893c306a98dSMathias Krause 	struct crypto_authenc_keys keys;
8949c4a7965SKim Phillips 
895c306a98dSMathias Krause 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8969c4a7965SKim Phillips 		goto badkey;
8979c4a7965SKim Phillips 
898c306a98dSMathias Krause 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8999c4a7965SKim Phillips 		goto badkey;
9009c4a7965SKim Phillips 
9012e13ce08SLEROY Christophe 	if (ctx->keylen)
9022e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
9032e13ce08SLEROY Christophe 
904c306a98dSMathias Krause 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
905c306a98dSMathias Krause 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
9069c4a7965SKim Phillips 
907c306a98dSMathias Krause 	ctx->keylen = keys.authkeylen + keys.enckeylen;
908c306a98dSMathias Krause 	ctx->enckeylen = keys.enckeylen;
909c306a98dSMathias Krause 	ctx->authkeylen = keys.authkeylen;
9102e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
9112e13ce08SLEROY Christophe 				      DMA_TO_DEVICE);
9129c4a7965SKim Phillips 
9138f0691fcSTudor-Dan Ambarus 	memzero_explicit(&keys, sizeof(keys));
9149c4a7965SKim Phillips 	return 0;
9159c4a7965SKim Phillips 
9169c4a7965SKim Phillips badkey:
9179c4a7965SKim Phillips 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
9188f0691fcSTudor-Dan Ambarus 	memzero_explicit(&keys, sizeof(keys));
9199c4a7965SKim Phillips 	return -EINVAL;
9209c4a7965SKim Phillips }
9219c4a7965SKim Phillips 
922ef7c5c85SHerbert Xu static int aead_des3_setkey(struct crypto_aead *authenc,
923ef7c5c85SHerbert Xu 			    const u8 *key, unsigned int keylen)
924ef7c5c85SHerbert Xu {
925ef7c5c85SHerbert Xu 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
926ef7c5c85SHerbert Xu 	struct device *dev = ctx->dev;
927ef7c5c85SHerbert Xu 	struct crypto_authenc_keys keys;
928ef7c5c85SHerbert Xu 	int err;
929ef7c5c85SHerbert Xu 
930ef7c5c85SHerbert Xu 	err = crypto_authenc_extractkeys(&keys, key, keylen);
931ef7c5c85SHerbert Xu 	if (unlikely(err))
932ef7c5c85SHerbert Xu 		goto badkey;
933ef7c5c85SHerbert Xu 
934ef7c5c85SHerbert Xu 	err = -EINVAL;
935ef7c5c85SHerbert Xu 	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
936ef7c5c85SHerbert Xu 		goto badkey;
937ef7c5c85SHerbert Xu 
9389d574ae8SArd Biesheuvel 	err = verify_aead_des3_key(authenc, keys.enckey, keys.enckeylen);
9399d574ae8SArd Biesheuvel 	if (err)
940ef7c5c85SHerbert Xu 		goto out;
941ef7c5c85SHerbert Xu 
942ef7c5c85SHerbert Xu 	if (ctx->keylen)
943ef7c5c85SHerbert Xu 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
944ef7c5c85SHerbert Xu 
945ef7c5c85SHerbert Xu 	memcpy(ctx->key, keys.authkey, keys.authkeylen);
946ef7c5c85SHerbert Xu 	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
947ef7c5c85SHerbert Xu 
948ef7c5c85SHerbert Xu 	ctx->keylen = keys.authkeylen + keys.enckeylen;
949ef7c5c85SHerbert Xu 	ctx->enckeylen = keys.enckeylen;
950ef7c5c85SHerbert Xu 	ctx->authkeylen = keys.authkeylen;
951ef7c5c85SHerbert Xu 	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
952ef7c5c85SHerbert Xu 				      DMA_TO_DEVICE);
953ef7c5c85SHerbert Xu 
954ef7c5c85SHerbert Xu out:
955ef7c5c85SHerbert Xu 	memzero_explicit(&keys, sizeof(keys));
956ef7c5c85SHerbert Xu 	return err;
957ef7c5c85SHerbert Xu 
958ef7c5c85SHerbert Xu badkey:
959ef7c5c85SHerbert Xu 	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
960ef7c5c85SHerbert Xu 	goto out;
961ef7c5c85SHerbert Xu }
962ef7c5c85SHerbert Xu 
9634de9d0b5SLee Nipper static void talitos_sg_unmap(struct device *dev,
9644de9d0b5SLee Nipper 			     struct talitos_edesc *edesc,
9654de9d0b5SLee Nipper 			     struct scatterlist *src,
9666a1e8d14SLEROY Christophe 			     struct scatterlist *dst,
9676a1e8d14SLEROY Christophe 			     unsigned int len, unsigned int offset)
968246a87cdSLEROY Christophe {
969246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
970246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
9716a1e8d14SLEROY Christophe 	unsigned int src_nents = edesc->src_nents ? : 1;
9726a1e8d14SLEROY Christophe 	unsigned int dst_nents = edesc->dst_nents ? : 1;
973246a87cdSLEROY Christophe 
9746a1e8d14SLEROY Christophe 	if (is_sec1 && dst && dst_nents > 1) {
9756a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
976246a87cdSLEROY Christophe 					   len, DMA_FROM_DEVICE);
9776a1e8d14SLEROY Christophe 		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
9786a1e8d14SLEROY Christophe 				     offset);
979246a87cdSLEROY Christophe 	}
9806a1e8d14SLEROY Christophe 	if (src != dst) {
9816a1e8d14SLEROY Christophe 		if (src_nents == 1 || !is_sec1)
9826a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
9836a1e8d14SLEROY Christophe 
9846a1e8d14SLEROY Christophe 		if (dst && (dst_nents == 1 || !is_sec1))
9856a1e8d14SLEROY Christophe 			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
9866a1e8d14SLEROY Christophe 	} else if (src_nents == 1 || !is_sec1) {
9876a1e8d14SLEROY Christophe 		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
988246a87cdSLEROY Christophe 	}
989246a87cdSLEROY Christophe }
990246a87cdSLEROY Christophe 
9919c4a7965SKim Phillips static void ipsec_esp_unmap(struct device *dev,
99256af8cd4SLee Nipper 			    struct talitos_edesc *edesc,
9937ede4c36SChristophe Leroy 			    struct aead_request *areq, bool encrypt)
9949c4a7965SKim Phillips {
995549bd8bcSLEROY Christophe 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
996549bd8bcSLEROY Christophe 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
997549bd8bcSLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(aead);
9987ede4c36SChristophe Leroy 	unsigned int authsize = crypto_aead_authsize(aead);
9997ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
10009a655608SLEROY Christophe 	bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
10019a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
1002549bd8bcSLEROY Christophe 
10039a655608SLEROY Christophe 	if (is_ipsec_esp)
1004549bd8bcSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
1005549bd8bcSLEROY Christophe 					 DMA_FROM_DEVICE);
10069a655608SLEROY Christophe 	unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
10079c4a7965SKim Phillips 
1008e345177dSChristophe Leroy 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst,
1009e345177dSChristophe Leroy 			 cryptlen + authsize, areq->assoclen);
10109c4a7965SKim Phillips 
10119c4a7965SKim Phillips 	if (edesc->dma_len)
10129c4a7965SKim Phillips 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
10139c4a7965SKim Phillips 				 DMA_BIDIRECTIONAL);
1014549bd8bcSLEROY Christophe 
10159a655608SLEROY Christophe 	if (!is_ipsec_esp) {
1016549bd8bcSLEROY Christophe 		unsigned int dst_nents = edesc->dst_nents ? : 1;
1017549bd8bcSLEROY Christophe 
1018549bd8bcSLEROY Christophe 		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
10197ede4c36SChristophe Leroy 				   areq->assoclen + cryptlen - ivsize);
1020549bd8bcSLEROY Christophe 	}
10219c4a7965SKim Phillips }
10229c4a7965SKim Phillips 
10239c4a7965SKim Phillips /*
10249c4a7965SKim Phillips  * ipsec_esp descriptor callbacks
10259c4a7965SKim Phillips  */
10269c4a7965SKim Phillips static void ipsec_esp_encrypt_done(struct device *dev,
10279c4a7965SKim Phillips 				   struct talitos_desc *desc, void *context,
10289c4a7965SKim Phillips 				   int err)
10299c4a7965SKim Phillips {
10309c4a7965SKim Phillips 	struct aead_request *areq = context;
10319c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
10322e13ce08SLEROY Christophe 	unsigned int ivsize = crypto_aead_ivsize(authenc);
103319bbbc63SKim Phillips 	struct talitos_edesc *edesc;
10349c4a7965SKim Phillips 
103519bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
103619bbbc63SKim Phillips 
10377ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, areq, true);
10389c4a7965SKim Phillips 
10392e13ce08SLEROY Christophe 	dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
10402e13ce08SLEROY Christophe 
10419c4a7965SKim Phillips 	kfree(edesc);
10429c4a7965SKim Phillips 
10439c4a7965SKim Phillips 	aead_request_complete(areq, err);
10449c4a7965SKim Phillips }
10459c4a7965SKim Phillips 
1046fe5720e2SKim Phillips static void ipsec_esp_decrypt_swauth_done(struct device *dev,
1047e938e465SKim Phillips 					  struct talitos_desc *desc,
1048e938e465SKim Phillips 					  void *context, int err)
10499c4a7965SKim Phillips {
10509c4a7965SKim Phillips 	struct aead_request *req = context;
10519c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1052aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
105319bbbc63SKim Phillips 	struct talitos_edesc *edesc;
1054aeb4c132SHerbert Xu 	char *oicv, *icv;
10559c4a7965SKim Phillips 
105619bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
105719bbbc63SKim Phillips 
10587ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, req, false);
10599c4a7965SKim Phillips 
10609c4a7965SKim Phillips 	if (!err) {
10619c4a7965SKim Phillips 		/* auth check */
1062e345177dSChristophe Leroy 		oicv = edesc->buf + edesc->dma_len;
1063e345177dSChristophe Leroy 		icv = oicv - authsize;
1064aeb4c132SHerbert Xu 
106579960943SDavid Gstir 		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10669c4a7965SKim Phillips 	}
10679c4a7965SKim Phillips 
10689c4a7965SKim Phillips 	kfree(edesc);
10699c4a7965SKim Phillips 
10709c4a7965SKim Phillips 	aead_request_complete(req, err);
10719c4a7965SKim Phillips }
10729c4a7965SKim Phillips 
1073fe5720e2SKim Phillips static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
1074e938e465SKim Phillips 					  struct talitos_desc *desc,
1075e938e465SKim Phillips 					  void *context, int err)
1076fe5720e2SKim Phillips {
1077fe5720e2SKim Phillips 	struct aead_request *req = context;
107819bbbc63SKim Phillips 	struct talitos_edesc *edesc;
107919bbbc63SKim Phillips 
108019bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
1081fe5720e2SKim Phillips 
10827ede4c36SChristophe Leroy 	ipsec_esp_unmap(dev, edesc, req, false);
1083fe5720e2SKim Phillips 
1084fe5720e2SKim Phillips 	/* check ICV auth status */
1085e938e465SKim Phillips 	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
1086e938e465SKim Phillips 		     DESC_HDR_LO_ICCR1_PASS))
1087fe5720e2SKim Phillips 		err = -EBADMSG;
1088fe5720e2SKim Phillips 
1089fe5720e2SKim Phillips 	kfree(edesc);
1090fe5720e2SKim Phillips 
1091fe5720e2SKim Phillips 	aead_request_complete(req, err);
1092fe5720e2SKim Phillips }
1093fe5720e2SKim Phillips 
10949c4a7965SKim Phillips /*
10959c4a7965SKim Phillips  * convert scatterlist to SEC h/w link table format
10969c4a7965SKim Phillips  * stop at cryptlen bytes
10979c4a7965SKim Phillips  */
1098aeb4c132SHerbert Xu static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
1099e345177dSChristophe Leroy 				 unsigned int offset, int datalen, int elen,
1100aeb4c132SHerbert Xu 				 struct talitos_ptr *link_tbl_ptr)
11019c4a7965SKim Phillips {
1102e345177dSChristophe Leroy 	int n_sg = elen ? sg_count + 1 : sg_count;
1103aeb4c132SHerbert Xu 	int count = 0;
1104e345177dSChristophe Leroy 	int cryptlen = datalen + elen;
110570bcaca7SLee Nipper 
1106aeb4c132SHerbert Xu 	while (cryptlen && sg && n_sg--) {
1107aeb4c132SHerbert Xu 		unsigned int len = sg_dma_len(sg);
1108aeb4c132SHerbert Xu 
1109aeb4c132SHerbert Xu 		if (offset >= len) {
1110aeb4c132SHerbert Xu 			offset -= len;
1111aeb4c132SHerbert Xu 			goto next;
1112aeb4c132SHerbert Xu 		}
1113aeb4c132SHerbert Xu 
1114aeb4c132SHerbert Xu 		len -= offset;
1115aeb4c132SHerbert Xu 
1116aeb4c132SHerbert Xu 		if (len > cryptlen)
1117aeb4c132SHerbert Xu 			len = cryptlen;
1118aeb4c132SHerbert Xu 
1119e345177dSChristophe Leroy 		if (datalen > 0 && len > datalen) {
1120e345177dSChristophe Leroy 			to_talitos_ptr(link_tbl_ptr + count,
1121e345177dSChristophe Leroy 				       sg_dma_address(sg) + offset, datalen, 0);
1122e345177dSChristophe Leroy 			to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1123e345177dSChristophe Leroy 			count++;
1124e345177dSChristophe Leroy 			len -= datalen;
1125e345177dSChristophe Leroy 			offset += datalen;
1126e345177dSChristophe Leroy 		}
1127aeb4c132SHerbert Xu 		to_talitos_ptr(link_tbl_ptr + count,
1128da9de146SLEROY Christophe 			       sg_dma_address(sg) + offset, len, 0);
1129b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
1130aeb4c132SHerbert Xu 		count++;
1131aeb4c132SHerbert Xu 		cryptlen -= len;
1132e345177dSChristophe Leroy 		datalen -= len;
1133aeb4c132SHerbert Xu 		offset = 0;
1134aeb4c132SHerbert Xu 
1135aeb4c132SHerbert Xu next:
11365be4d4c9SCristian Stoica 		sg = sg_next(sg);
11379c4a7965SKim Phillips 	}
11389c4a7965SKim Phillips 
11399c4a7965SKim Phillips 	/* tag end of link table */
1140aeb4c132SHerbert Xu 	if (count > 0)
1141b096b544SLEROY Christophe 		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
1142e345177dSChristophe Leroy 				       DESC_PTR_LNKTBL_RET, 0);
114370bcaca7SLee Nipper 
1144aeb4c132SHerbert Xu 	return count;
1145aeb4c132SHerbert Xu }
1146aeb4c132SHerbert Xu 
11472b122730SLEROY Christophe static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
1148246a87cdSLEROY Christophe 			      unsigned int len, struct talitos_edesc *edesc,
11492b122730SLEROY Christophe 			      struct talitos_ptr *ptr, int sg_count,
1150e345177dSChristophe Leroy 			      unsigned int offset, int tbl_off, int elen,
1151e345177dSChristophe Leroy 			      bool force)
1152246a87cdSLEROY Christophe {
1153246a87cdSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1154246a87cdSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1155246a87cdSLEROY Christophe 
115687a81dceSLEROY Christophe 	if (!src) {
115787a81dceSLEROY Christophe 		to_talitos_ptr(ptr, 0, 0, is_sec1);
115887a81dceSLEROY Christophe 		return 1;
115987a81dceSLEROY Christophe 	}
11602b122730SLEROY Christophe 	to_talitos_ptr_ext_set(ptr, elen, is_sec1);
1161e345177dSChristophe Leroy 	if (sg_count == 1 && !force) {
1162da9de146SLEROY Christophe 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1);
1163246a87cdSLEROY Christophe 		return sg_count;
1164246a87cdSLEROY Christophe 	}
1165246a87cdSLEROY Christophe 	if (is_sec1) {
1166da9de146SLEROY Christophe 		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1);
11676a1e8d14SLEROY Christophe 		return sg_count;
1168246a87cdSLEROY Christophe 	}
1169e345177dSChristophe Leroy 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen,
11706a1e8d14SLEROY Christophe 					 &edesc->link_tbl[tbl_off]);
1171e345177dSChristophe Leroy 	if (sg_count == 1 && !force) {
11726a1e8d14SLEROY Christophe 		/* Only one segment now, so no link tbl needed*/
11736a1e8d14SLEROY Christophe 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
11746a1e8d14SLEROY Christophe 		return sg_count;
11756a1e8d14SLEROY Christophe 	}
1176246a87cdSLEROY Christophe 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
1177da9de146SLEROY Christophe 			    tbl_off * sizeof(struct talitos_ptr), len, is_sec1);
11786a1e8d14SLEROY Christophe 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
11796a1e8d14SLEROY Christophe 
11806a1e8d14SLEROY Christophe 	return sg_count;
1181246a87cdSLEROY Christophe }
1182246a87cdSLEROY Christophe 
11832b122730SLEROY Christophe static int talitos_sg_map(struct device *dev, struct scatterlist *src,
11842b122730SLEROY Christophe 			  unsigned int len, struct talitos_edesc *edesc,
11852b122730SLEROY Christophe 			  struct talitos_ptr *ptr, int sg_count,
11862b122730SLEROY Christophe 			  unsigned int offset, int tbl_off)
11872b122730SLEROY Christophe {
11882b122730SLEROY Christophe 	return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset,
1189e345177dSChristophe Leroy 				  tbl_off, 0, false);
11902b122730SLEROY Christophe }
11912b122730SLEROY Christophe 
11929c4a7965SKim Phillips /*
11939c4a7965SKim Phillips  * fill in and submit ipsec_esp descriptor
11949c4a7965SKim Phillips  */
119556af8cd4SLee Nipper static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
11967ede4c36SChristophe Leroy 		     bool encrypt,
1197aeb4c132SHerbert Xu 		     void (*callback)(struct device *dev,
11989c4a7965SKim Phillips 				      struct talitos_desc *desc,
11999c4a7965SKim Phillips 				      void *context, int error))
12009c4a7965SKim Phillips {
12019c4a7965SKim Phillips 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
1202aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
12039c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
12049c4a7965SKim Phillips 	struct device *dev = ctx->dev;
12059c4a7965SKim Phillips 	struct talitos_desc *desc = &edesc->desc;
12067ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
1207e41256f1SKim Phillips 	unsigned int ivsize = crypto_aead_ivsize(aead);
1208aeb4c132SHerbert Xu 	int tbl_off = 0;
1209fa86a267SKim Phillips 	int sg_count, ret;
12102b122730SLEROY Christophe 	int elen = 0;
1211549bd8bcSLEROY Christophe 	bool sync_needed = false;
1212549bd8bcSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1213549bd8bcSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
12149a655608SLEROY Christophe 	bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
12159a655608SLEROY Christophe 	struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
12169a655608SLEROY Christophe 	struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
1217e345177dSChristophe Leroy 	dma_addr_t dma_icv = edesc->dma_link_tbl + edesc->dma_len - authsize;
12189c4a7965SKim Phillips 
12199c4a7965SKim Phillips 	/* hmac key */
12202e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1);
122179fd31d3SHoria Geanta 
1222549bd8bcSLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
1223549bd8bcSLEROY Christophe 	if (is_sec1 && sg_count > 1)
1224549bd8bcSLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
1225549bd8bcSLEROY Christophe 				  areq->assoclen + cryptlen);
1226549bd8bcSLEROY Christophe 	else
1227549bd8bcSLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
1228549bd8bcSLEROY Christophe 				      (areq->src == areq->dst) ?
1229549bd8bcSLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
1230549bd8bcSLEROY Christophe 
12319c4a7965SKim Phillips 	/* hmac data */
1232549bd8bcSLEROY Christophe 	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
1233549bd8bcSLEROY Christophe 			     &desc->ptr[1], sg_count, 0, tbl_off);
123479fd31d3SHoria Geanta 
1235549bd8bcSLEROY Christophe 	if (ret > 1) {
1236340ff60aSHoria Geant? 		tbl_off += ret;
1237549bd8bcSLEROY Christophe 		sync_needed = true;
123879fd31d3SHoria Geanta 	}
123979fd31d3SHoria Geanta 
12409c4a7965SKim Phillips 	/* cipher iv */
12419a655608SLEROY Christophe 	to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1);
12429c4a7965SKim Phillips 
12439c4a7965SKim Phillips 	/* cipher key */
12442e13ce08SLEROY Christophe 	to_talitos_ptr(ckey_ptr, ctx->dma_key  + ctx->authkeylen,
12452e13ce08SLEROY Christophe 		       ctx->enckeylen, is_sec1);
12469c4a7965SKim Phillips 
12479c4a7965SKim Phillips 	/*
12489c4a7965SKim Phillips 	 * cipher in
12499c4a7965SKim Phillips 	 * map and adjust cipher len to aead request cryptlen.
12509c4a7965SKim Phillips 	 * extent is bytes of HMAC postpended to ciphertext,
12519c4a7965SKim Phillips 	 * typically 12 for ipsec
12529c4a7965SKim Phillips 	 */
12532b122730SLEROY Christophe 	if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV))
12542b122730SLEROY Christophe 		elen = authsize;
1255549bd8bcSLEROY Christophe 
12562b122730SLEROY Christophe 	ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4],
1257e345177dSChristophe Leroy 				 sg_count, areq->assoclen, tbl_off, elen,
1258e345177dSChristophe Leroy 				 false);
1259549bd8bcSLEROY Christophe 
1260ec8c7d14SLEROY Christophe 	if (ret > 1) {
1261ec8c7d14SLEROY Christophe 		tbl_off += ret;
1262549bd8bcSLEROY Christophe 		sync_needed = true;
1263340ff60aSHoria Geant? 	}
12649c4a7965SKim Phillips 
12659c4a7965SKim Phillips 	/* cipher out */
1266549bd8bcSLEROY Christophe 	if (areq->src != areq->dst) {
1267549bd8bcSLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
1268549bd8bcSLEROY Christophe 		if (!is_sec1 || sg_count == 1)
1269549bd8bcSLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
1270549bd8bcSLEROY Christophe 	}
12719c4a7965SKim Phillips 
1272e345177dSChristophe Leroy 	if (is_ipsec_esp && encrypt)
1273e345177dSChristophe Leroy 		elen = authsize;
1274e345177dSChristophe Leroy 	else
1275e345177dSChristophe Leroy 		elen = 0;
1276e345177dSChristophe Leroy 	ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
1277e345177dSChristophe Leroy 				 sg_count, areq->assoclen, tbl_off, elen,
1278e345177dSChristophe Leroy 				 is_ipsec_esp && !encrypt);
1279e04a61beSLEROY Christophe 	tbl_off += ret;
1280549bd8bcSLEROY Christophe 
1281e345177dSChristophe Leroy 	if (!encrypt && is_ipsec_esp) {
128279fd31d3SHoria Geanta 		struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
1283fe5720e2SKim Phillips 
1284f3c85bc1SLee Nipper 		/* Add an entry to the link table for ICV data */
1285e04a61beSLEROY Christophe 		to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
1286e345177dSChristophe Leroy 		to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RET, is_sec1);
12879c4a7965SKim Phillips 
12889c4a7965SKim Phillips 		/* icv data follows link tables */
1289e345177dSChristophe Leroy 		to_talitos_ptr(tbl_ptr, dma_icv, authsize, is_sec1);
1290e345177dSChristophe Leroy 		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
1291e04a61beSLEROY Christophe 		sync_needed = true;
1292e345177dSChristophe Leroy 	} else if (!encrypt) {
1293e345177dSChristophe Leroy 		to_talitos_ptr(&desc->ptr[6], dma_icv, authsize, is_sec1);
1294e345177dSChristophe Leroy 		sync_needed = true;
1295e345177dSChristophe Leroy 	} else if (!is_ipsec_esp) {
1296e345177dSChristophe Leroy 		talitos_sg_map(dev, areq->dst, authsize, edesc, &desc->ptr[6],
1297e345177dSChristophe Leroy 			       sg_count, areq->assoclen + cryptlen, tbl_off);
1298340ff60aSHoria Geant? 	}
12999c4a7965SKim Phillips 
13009c4a7965SKim Phillips 	/* iv out */
13019a655608SLEROY Christophe 	if (is_ipsec_esp)
1302a2b35aa8SLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
13039c4a7965SKim Phillips 				       DMA_FROM_DEVICE);
13049c4a7965SKim Phillips 
1305549bd8bcSLEROY Christophe 	if (sync_needed)
1306549bd8bcSLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
1307549bd8bcSLEROY Christophe 					   edesc->dma_len,
1308549bd8bcSLEROY Christophe 					   DMA_BIDIRECTIONAL);
1309549bd8bcSLEROY Christophe 
13105228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1311fa86a267SKim Phillips 	if (ret != -EINPROGRESS) {
13127ede4c36SChristophe Leroy 		ipsec_esp_unmap(dev, edesc, areq, encrypt);
1313fa86a267SKim Phillips 		kfree(edesc);
1314fa86a267SKim Phillips 	}
1315fa86a267SKim Phillips 	return ret;
13169c4a7965SKim Phillips }
13179c4a7965SKim Phillips 
13189c4a7965SKim Phillips /*
131956af8cd4SLee Nipper  * allocate and map the extended descriptor
13209c4a7965SKim Phillips  */
13214de9d0b5SLee Nipper static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13224de9d0b5SLee Nipper 						 struct scatterlist *src,
13234de9d0b5SLee Nipper 						 struct scatterlist *dst,
132479fd31d3SHoria Geanta 						 u8 *iv,
132579fd31d3SHoria Geanta 						 unsigned int assoclen,
13264de9d0b5SLee Nipper 						 unsigned int cryptlen,
13274de9d0b5SLee Nipper 						 unsigned int authsize,
132879fd31d3SHoria Geanta 						 unsigned int ivsize,
13294de9d0b5SLee Nipper 						 int icv_stashing,
133062293a37SHoria Geanta 						 u32 cryptoflags,
133162293a37SHoria Geanta 						 bool encrypt)
13329c4a7965SKim Phillips {
133356af8cd4SLee Nipper 	struct talitos_edesc *edesc;
13346a1e8d14SLEROY Christophe 	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
133579fd31d3SHoria Geanta 	dma_addr_t iv_dma = 0;
13364de9d0b5SLee Nipper 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
1337586725f8SKim Phillips 		      GFP_ATOMIC;
13386f65f6acSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
13396f65f6acSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
13406f65f6acSLEROY Christophe 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
13419c4a7965SKim Phillips 
13426f65f6acSLEROY Christophe 	if (cryptlen + authsize > max_len) {
13434de9d0b5SLee Nipper 		dev_err(dev, "length exceeds h/w max limit\n");
13449c4a7965SKim Phillips 		return ERR_PTR(-EINVAL);
13459c4a7965SKim Phillips 	}
13469c4a7965SKim Phillips 
134762293a37SHoria Geanta 	if (!dst || dst == src) {
13486a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + authsize;
13496a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13508e409fe1SLABBE Corentin 		if (src_nents < 0) {
13518e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
1352c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
13538e409fe1SLABBE Corentin 		}
13549c4a7965SKim Phillips 		src_nents = (src_nents == 1) ? 0 : src_nents;
135562293a37SHoria Geanta 		dst_nents = dst ? src_nents : 0;
13566a1e8d14SLEROY Christophe 		dst_len = 0;
135762293a37SHoria Geanta 	} else { /* dst && dst != src*/
13586a1e8d14SLEROY Christophe 		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
13596a1e8d14SLEROY Christophe 		src_nents = sg_nents_for_len(src, src_len);
13608e409fe1SLABBE Corentin 		if (src_nents < 0) {
13618e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of src SG.\n");
1362c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
13638e409fe1SLABBE Corentin 		}
136462293a37SHoria Geanta 		src_nents = (src_nents == 1) ? 0 : src_nents;
13656a1e8d14SLEROY Christophe 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
13666a1e8d14SLEROY Christophe 		dst_nents = sg_nents_for_len(dst, dst_len);
13678e409fe1SLABBE Corentin 		if (dst_nents < 0) {
13688e409fe1SLABBE Corentin 			dev_err(dev, "Invalid number of dst SG.\n");
1369c56c2e17SChristophe Leroy 			return ERR_PTR(-EINVAL);
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);
1380e345177dSChristophe Leroy 	if (src_nents || dst_nents || !encrypt) {
13816f65f6acSLEROY Christophe 		if (is_sec1)
13826a1e8d14SLEROY Christophe 			dma_len = (src_nents ? src_len : 0) +
1383e345177dSChristophe Leroy 				  (dst_nents ? dst_len : 0) + authsize;
13846f65f6acSLEROY Christophe 		else
1385aeb4c132SHerbert Xu 			dma_len = (src_nents + dst_nents + 2) *
1386e345177dSChristophe Leroy 				  sizeof(struct talitos_ptr) + authsize;
13879c4a7965SKim Phillips 		alloc_len += dma_len;
13889c4a7965SKim Phillips 	} else {
13899c4a7965SKim Phillips 		dma_len = 0;
13909c4a7965SKim Phillips 	}
1391e345177dSChristophe Leroy 	alloc_len += icv_stashing ? authsize : 0;
13929c4a7965SKim Phillips 
139337b5e889SLEROY Christophe 	/* if its a ahash, add space for a second desc next to the first one */
139437b5e889SLEROY Christophe 	if (is_sec1 && !dst)
139537b5e889SLEROY Christophe 		alloc_len += sizeof(struct talitos_desc);
13961bea445bSChristophe Leroy 	alloc_len += ivsize;
139737b5e889SLEROY Christophe 
1398586725f8SKim Phillips 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
1399c56c2e17SChristophe Leroy 	if (!edesc)
1400c56c2e17SChristophe Leroy 		return ERR_PTR(-ENOMEM);
14011bea445bSChristophe Leroy 	if (ivsize) {
14021bea445bSChristophe Leroy 		iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
1403c56c2e17SChristophe Leroy 		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
14041bea445bSChristophe Leroy 	}
1405e4a647c4SLEROY Christophe 	memset(&edesc->desc, 0, sizeof(edesc->desc));
14069c4a7965SKim Phillips 
14079c4a7965SKim Phillips 	edesc->src_nents = src_nents;
14089c4a7965SKim Phillips 	edesc->dst_nents = dst_nents;
140979fd31d3SHoria Geanta 	edesc->iv_dma = iv_dma;
14109c4a7965SKim Phillips 	edesc->dma_len = dma_len;
141158cdbc6dSChristophe Leroy 	if (dma_len)
141258cdbc6dSChristophe Leroy 		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
1413497f2e6bSLee Nipper 						     edesc->dma_len,
1414497f2e6bSLee Nipper 						     DMA_BIDIRECTIONAL);
141558cdbc6dSChristophe Leroy 
14169c4a7965SKim Phillips 	return edesc;
14179c4a7965SKim Phillips }
14189c4a7965SKim Phillips 
141979fd31d3SHoria Geanta static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
142062293a37SHoria Geanta 					      int icv_stashing, bool encrypt)
14214de9d0b5SLee Nipper {
14224de9d0b5SLee Nipper 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
1423aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14244de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
142579fd31d3SHoria Geanta 	unsigned int ivsize = crypto_aead_ivsize(authenc);
14267ede4c36SChristophe Leroy 	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
14274de9d0b5SLee Nipper 
1428aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
14297ede4c36SChristophe Leroy 				   iv, areq->assoclen, cryptlen,
1430aeb4c132SHerbert Xu 				   authsize, ivsize, icv_stashing,
143162293a37SHoria Geanta 				   areq->base.flags, encrypt);
14324de9d0b5SLee Nipper }
14334de9d0b5SLee Nipper 
143456af8cd4SLee Nipper static int aead_encrypt(struct aead_request *req)
14359c4a7965SKim Phillips {
14369c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14379c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
143856af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14399c4a7965SKim Phillips 
14409c4a7965SKim Phillips 	/* allocate extended descriptor */
144162293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 0, true);
14429c4a7965SKim Phillips 	if (IS_ERR(edesc))
14439c4a7965SKim Phillips 		return PTR_ERR(edesc);
14449c4a7965SKim Phillips 
14459c4a7965SKim Phillips 	/* set encrypt */
144670bcaca7SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14479c4a7965SKim Phillips 
14487ede4c36SChristophe Leroy 	return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done);
14499c4a7965SKim Phillips }
14509c4a7965SKim Phillips 
145156af8cd4SLee Nipper static int aead_decrypt(struct aead_request *req)
14529c4a7965SKim Phillips {
14539c4a7965SKim Phillips 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
1454aeb4c132SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(authenc);
14559c4a7965SKim Phillips 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
1456fe5720e2SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
145756af8cd4SLee Nipper 	struct talitos_edesc *edesc;
14589c4a7965SKim Phillips 	void *icvdata;
14599c4a7965SKim Phillips 
14609c4a7965SKim Phillips 	/* allocate extended descriptor */
146162293a37SHoria Geanta 	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14629c4a7965SKim Phillips 	if (IS_ERR(edesc))
14639c4a7965SKim Phillips 		return PTR_ERR(edesc);
14649c4a7965SKim Phillips 
14654bbfb839SChristophe Leroy 	if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) &&
14664bbfb839SChristophe Leroy 	    (priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
1467e938e465SKim Phillips 	    ((!edesc->src_nents && !edesc->dst_nents) ||
1468e938e465SKim Phillips 	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
1469fe5720e2SKim Phillips 
1470fe5720e2SKim Phillips 		/* decrypt and check the ICV */
1471e938e465SKim Phillips 		edesc->desc.hdr = ctx->desc_hdr_template |
1472e938e465SKim Phillips 				  DESC_HDR_DIR_INBOUND |
1473fe5720e2SKim Phillips 				  DESC_HDR_MODE1_MDEU_CICV;
1474fe5720e2SKim Phillips 
1475fe5720e2SKim Phillips 		/* reset integrity check result bits */
1476fe5720e2SKim Phillips 
14777ede4c36SChristophe Leroy 		return ipsec_esp(edesc, req, false,
14787ede4c36SChristophe Leroy 				 ipsec_esp_decrypt_hwauth_done);
1479e938e465SKim Phillips 	}
1480fe5720e2SKim Phillips 
1481fe5720e2SKim Phillips 	/* Have to check the ICV with software */
1482fe5720e2SKim Phillips 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
1483fe5720e2SKim Phillips 
14849c4a7965SKim Phillips 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
1485e345177dSChristophe Leroy 	icvdata = edesc->buf + edesc->dma_len;
14869c4a7965SKim Phillips 
1487eae55a58SChristophe Leroy 	sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize,
1488eae55a58SChristophe Leroy 			   req->assoclen + req->cryptlen - authsize);
14899c4a7965SKim Phillips 
14907ede4c36SChristophe Leroy 	return ipsec_esp(edesc, req, false, ipsec_esp_decrypt_swauth_done);
14919c4a7965SKim Phillips }
14929c4a7965SKim Phillips 
14934de9d0b5SLee Nipper static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
14944de9d0b5SLee Nipper 			     const u8 *key, unsigned int keylen)
14954de9d0b5SLee Nipper {
14964de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
14972e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
1498f384cdc4SLEROY Christophe 
14992e13ce08SLEROY Christophe 	if (ctx->keylen)
15002e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
15012e13ce08SLEROY Christophe 
15024de9d0b5SLee Nipper 	memcpy(&ctx->key, key, keylen);
15034de9d0b5SLee Nipper 	ctx->keylen = keylen;
15044de9d0b5SLee Nipper 
15052e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE);
15062e13ce08SLEROY Christophe 
15074de9d0b5SLee Nipper 	return 0;
15084de9d0b5SLee Nipper }
15094de9d0b5SLee Nipper 
1510ef7c5c85SHerbert Xu static int ablkcipher_des_setkey(struct crypto_ablkcipher *cipher,
1511ef7c5c85SHerbert Xu 				 const u8 *key, unsigned int keylen)
1512ef7c5c85SHerbert Xu {
15139d574ae8SArd Biesheuvel 	return verify_ablkcipher_des_key(cipher, key) ?:
15149d574ae8SArd Biesheuvel 	       ablkcipher_setkey(cipher, key, keylen);
1515ef7c5c85SHerbert Xu }
1516ef7c5c85SHerbert Xu 
1517ef7c5c85SHerbert Xu static int ablkcipher_des3_setkey(struct crypto_ablkcipher *cipher,
1518ef7c5c85SHerbert Xu 				  const u8 *key, unsigned int keylen)
1519ef7c5c85SHerbert Xu {
15209d574ae8SArd Biesheuvel 	return verify_ablkcipher_des3_key(cipher, key) ?:
15219d574ae8SArd Biesheuvel 	       ablkcipher_setkey(cipher, key, keylen);
1522ef7c5c85SHerbert Xu }
1523ef7c5c85SHerbert Xu 
15241ba34e71SChristophe Leroy static int ablkcipher_aes_setkey(struct crypto_ablkcipher *cipher,
15251ba34e71SChristophe Leroy 				  const u8 *key, unsigned int keylen)
15261ba34e71SChristophe Leroy {
15271ba34e71SChristophe Leroy 	if (keylen == AES_KEYSIZE_128 || keylen == AES_KEYSIZE_192 ||
15281ba34e71SChristophe Leroy 	    keylen == AES_KEYSIZE_256)
15291ba34e71SChristophe Leroy 		return ablkcipher_setkey(cipher, key, keylen);
15301ba34e71SChristophe Leroy 
15311ba34e71SChristophe Leroy 	crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
15321ba34e71SChristophe Leroy 
15331ba34e71SChristophe Leroy 	return -EINVAL;
15341ba34e71SChristophe Leroy }
15351ba34e71SChristophe Leroy 
15364de9d0b5SLee Nipper static void common_nonsnoop_unmap(struct device *dev,
15374de9d0b5SLee Nipper 				  struct talitos_edesc *edesc,
15384de9d0b5SLee Nipper 				  struct ablkcipher_request *areq)
15394de9d0b5SLee Nipper {
15404de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1541032d197eSLEROY Christophe 
15426a1e8d14SLEROY Christophe 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->nbytes, 0);
15434de9d0b5SLee Nipper 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
15444de9d0b5SLee Nipper 
15454de9d0b5SLee Nipper 	if (edesc->dma_len)
15464de9d0b5SLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
15474de9d0b5SLee Nipper 				 DMA_BIDIRECTIONAL);
15484de9d0b5SLee Nipper }
15494de9d0b5SLee Nipper 
15504de9d0b5SLee Nipper static void ablkcipher_done(struct device *dev,
15514de9d0b5SLee Nipper 			    struct talitos_desc *desc, void *context,
15524de9d0b5SLee Nipper 			    int err)
15534de9d0b5SLee Nipper {
15544de9d0b5SLee Nipper 	struct ablkcipher_request *areq = context;
15553e03e792SChristophe Leroy 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15563e03e792SChristophe Leroy 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15573e03e792SChristophe Leroy 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
155819bbbc63SKim Phillips 	struct talitos_edesc *edesc;
155919bbbc63SKim Phillips 
156019bbbc63SKim Phillips 	edesc = container_of(desc, struct talitos_edesc, desc);
15614de9d0b5SLee Nipper 
15624de9d0b5SLee Nipper 	common_nonsnoop_unmap(dev, edesc, areq);
15633e03e792SChristophe Leroy 	memcpy(areq->info, ctx->iv, ivsize);
15644de9d0b5SLee Nipper 
15654de9d0b5SLee Nipper 	kfree(edesc);
15664de9d0b5SLee Nipper 
15674de9d0b5SLee Nipper 	areq->base.complete(&areq->base, err);
15684de9d0b5SLee Nipper }
15694de9d0b5SLee Nipper 
15704de9d0b5SLee Nipper static int common_nonsnoop(struct talitos_edesc *edesc,
15714de9d0b5SLee Nipper 			   struct ablkcipher_request *areq,
15724de9d0b5SLee Nipper 			   void (*callback) (struct device *dev,
15734de9d0b5SLee Nipper 					     struct talitos_desc *desc,
15744de9d0b5SLee Nipper 					     void *context, int error))
15754de9d0b5SLee Nipper {
15764de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
15774de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
15784de9d0b5SLee Nipper 	struct device *dev = ctx->dev;
15794de9d0b5SLee Nipper 	struct talitos_desc *desc = &edesc->desc;
15804de9d0b5SLee Nipper 	unsigned int cryptlen = areq->nbytes;
158179fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
15824de9d0b5SLee Nipper 	int sg_count, ret;
15836a1e8d14SLEROY Christophe 	bool sync_needed = false;
1584922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1585922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
15864de9d0b5SLee Nipper 
15874de9d0b5SLee Nipper 	/* first DWORD empty */
15884de9d0b5SLee Nipper 
15894de9d0b5SLee Nipper 	/* cipher iv */
1590da9de146SLEROY Christophe 	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1);
15914de9d0b5SLee Nipper 
15924de9d0b5SLee Nipper 	/* cipher key */
15932e13ce08SLEROY Christophe 	to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1);
15944de9d0b5SLee Nipper 
15956a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
15966a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
15976a1e8d14SLEROY Christophe 		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
15986a1e8d14SLEROY Christophe 				  cryptlen);
15996a1e8d14SLEROY Christophe 	else
16006a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, areq->src, sg_count,
16016a1e8d14SLEROY Christophe 				      (areq->src == areq->dst) ?
16026a1e8d14SLEROY Christophe 				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
16034de9d0b5SLee Nipper 	/*
16044de9d0b5SLee Nipper 	 * cipher in
16054de9d0b5SLee Nipper 	 */
16066a1e8d14SLEROY Christophe 	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
16076a1e8d14SLEROY Christophe 				  &desc->ptr[3], sg_count, 0, 0);
16086a1e8d14SLEROY Christophe 	if (sg_count > 1)
16096a1e8d14SLEROY Christophe 		sync_needed = true;
16104de9d0b5SLee Nipper 
16114de9d0b5SLee Nipper 	/* cipher out */
16126a1e8d14SLEROY Christophe 	if (areq->src != areq->dst) {
16136a1e8d14SLEROY Christophe 		sg_count = edesc->dst_nents ? : 1;
16146a1e8d14SLEROY Christophe 		if (!is_sec1 || sg_count == 1)
16156a1e8d14SLEROY Christophe 			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
16166a1e8d14SLEROY Christophe 	}
16176a1e8d14SLEROY Christophe 
16186a1e8d14SLEROY Christophe 	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
16196a1e8d14SLEROY Christophe 			     sg_count, 0, (edesc->src_nents + 1));
16206a1e8d14SLEROY Christophe 	if (ret > 1)
16216a1e8d14SLEROY Christophe 		sync_needed = true;
16224de9d0b5SLee Nipper 
16234de9d0b5SLee Nipper 	/* iv out */
1624a2b35aa8SLEROY Christophe 	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
16254de9d0b5SLee Nipper 			       DMA_FROM_DEVICE);
16264de9d0b5SLee Nipper 
16274de9d0b5SLee Nipper 	/* last DWORD empty */
16284de9d0b5SLee Nipper 
16296a1e8d14SLEROY Christophe 	if (sync_needed)
16306a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
16316a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
16326a1e8d14SLEROY Christophe 
16335228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
16344de9d0b5SLee Nipper 	if (ret != -EINPROGRESS) {
16354de9d0b5SLee Nipper 		common_nonsnoop_unmap(dev, edesc, areq);
16364de9d0b5SLee Nipper 		kfree(edesc);
16374de9d0b5SLee Nipper 	}
16384de9d0b5SLee Nipper 	return ret;
16394de9d0b5SLee Nipper }
16404de9d0b5SLee Nipper 
1641e938e465SKim Phillips static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
164262293a37SHoria Geanta 						    areq, bool encrypt)
16434de9d0b5SLee Nipper {
16444de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16454de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
164679fd31d3SHoria Geanta 	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
16474de9d0b5SLee Nipper 
1648aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
164979fd31d3SHoria Geanta 				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
165062293a37SHoria Geanta 				   areq->base.flags, encrypt);
16514de9d0b5SLee Nipper }
16524de9d0b5SLee Nipper 
16534de9d0b5SLee Nipper static int ablkcipher_encrypt(struct ablkcipher_request *areq)
16544de9d0b5SLee Nipper {
16554de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16564de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16574de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
1658ee483d32SChristophe Leroy 	unsigned int blocksize =
1659ee483d32SChristophe Leroy 			crypto_tfm_alg_blocksize(crypto_ablkcipher_tfm(cipher));
1660ee483d32SChristophe Leroy 
1661ee483d32SChristophe Leroy 	if (!areq->nbytes)
1662ee483d32SChristophe Leroy 		return 0;
1663ee483d32SChristophe Leroy 
1664ee483d32SChristophe Leroy 	if (areq->nbytes % blocksize)
1665ee483d32SChristophe Leroy 		return -EINVAL;
16664de9d0b5SLee Nipper 
16674de9d0b5SLee Nipper 	/* allocate extended descriptor */
166862293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, true);
16694de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16704de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16714de9d0b5SLee Nipper 
16724de9d0b5SLee Nipper 	/* set encrypt */
16734de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16744de9d0b5SLee Nipper 
1675febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
16764de9d0b5SLee Nipper }
16774de9d0b5SLee Nipper 
16784de9d0b5SLee Nipper static int ablkcipher_decrypt(struct ablkcipher_request *areq)
16794de9d0b5SLee Nipper {
16804de9d0b5SLee Nipper 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
16814de9d0b5SLee Nipper 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
16824de9d0b5SLee Nipper 	struct talitos_edesc *edesc;
1683ee483d32SChristophe Leroy 	unsigned int blocksize =
1684ee483d32SChristophe Leroy 			crypto_tfm_alg_blocksize(crypto_ablkcipher_tfm(cipher));
1685ee483d32SChristophe Leroy 
1686ee483d32SChristophe Leroy 	if (!areq->nbytes)
1687ee483d32SChristophe Leroy 		return 0;
1688ee483d32SChristophe Leroy 
1689ee483d32SChristophe Leroy 	if (areq->nbytes % blocksize)
1690ee483d32SChristophe Leroy 		return -EINVAL;
16914de9d0b5SLee Nipper 
16924de9d0b5SLee Nipper 	/* allocate extended descriptor */
169362293a37SHoria Geanta 	edesc = ablkcipher_edesc_alloc(areq, false);
16944de9d0b5SLee Nipper 	if (IS_ERR(edesc))
16954de9d0b5SLee Nipper 		return PTR_ERR(edesc);
16964de9d0b5SLee Nipper 
16974de9d0b5SLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
16984de9d0b5SLee Nipper 
1699febec542SKim Phillips 	return common_nonsnoop(edesc, areq, ablkcipher_done);
17004de9d0b5SLee Nipper }
17014de9d0b5SLee Nipper 
1702497f2e6bSLee Nipper static void common_nonsnoop_hash_unmap(struct device *dev,
1703497f2e6bSLee Nipper 				       struct talitos_edesc *edesc,
1704497f2e6bSLee Nipper 				       struct ahash_request *areq)
1705497f2e6bSLee Nipper {
1706497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1707*7a6eda5bSChristophe Leroy 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1708ad4cd51fSLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1709ad4cd51fSLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
1710ad4cd51fSLEROY Christophe 	struct talitos_desc *desc = &edesc->desc;
171158cdbc6dSChristophe Leroy 	struct talitos_desc *desc2 = (struct talitos_desc *)
171258cdbc6dSChristophe Leroy 				     (edesc->buf + edesc->dma_len);
1713ad4cd51fSLEROY Christophe 
1714ad4cd51fSLEROY Christophe 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
1715ad4cd51fSLEROY Christophe 	if (desc->next_desc &&
1716ad4cd51fSLEROY Christophe 	    desc->ptr[5].ptr != desc2->ptr[5].ptr)
1717ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
1718*7a6eda5bSChristophe Leroy 	if (req_ctx->last)
1719*7a6eda5bSChristophe Leroy 		memcpy(areq->result, req_ctx->hw_context,
1720*7a6eda5bSChristophe Leroy 		       crypto_ahash_digestsize(tfm));
1721497f2e6bSLee Nipper 
172258cdbc6dSChristophe Leroy 	if (req_ctx->psrc)
17236a1e8d14SLEROY Christophe 		talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
1724032d197eSLEROY Christophe 
1725ad4cd51fSLEROY Christophe 	/* When using hashctx-in, must unmap it. */
1726ad4cd51fSLEROY Christophe 	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
1727ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
1728ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1729ad4cd51fSLEROY Christophe 	else if (desc->next_desc)
1730ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc2->ptr[1],
1731ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1732ad4cd51fSLEROY Christophe 
1733ad4cd51fSLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
1734ad4cd51fSLEROY Christophe 		unmap_single_talitos_ptr(dev, &desc->ptr[3],
1735ad4cd51fSLEROY Christophe 					 DMA_TO_DEVICE);
1736ad4cd51fSLEROY Christophe 
1737497f2e6bSLee Nipper 	if (edesc->dma_len)
1738497f2e6bSLee Nipper 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
1739497f2e6bSLee Nipper 				 DMA_BIDIRECTIONAL);
1740497f2e6bSLee Nipper 
174137b5e889SLEROY Christophe 	if (edesc->desc.next_desc)
174237b5e889SLEROY Christophe 		dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc),
174337b5e889SLEROY Christophe 				 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
1744497f2e6bSLee Nipper }
1745497f2e6bSLee Nipper 
1746497f2e6bSLee Nipper static void ahash_done(struct device *dev,
1747497f2e6bSLee Nipper 		       struct talitos_desc *desc, void *context,
1748497f2e6bSLee Nipper 		       int err)
1749497f2e6bSLee Nipper {
1750497f2e6bSLee Nipper 	struct ahash_request *areq = context;
1751497f2e6bSLee Nipper 	struct talitos_edesc *edesc =
1752497f2e6bSLee Nipper 		 container_of(desc, struct talitos_edesc, desc);
1753497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1754497f2e6bSLee Nipper 
1755497f2e6bSLee Nipper 	if (!req_ctx->last && req_ctx->to_hash_later) {
1756497f2e6bSLee Nipper 		/* Position any partial block for next update/final/finup */
17573c0dd190SLEROY Christophe 		req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
17585e833bc4SLee Nipper 		req_ctx->nbuf = req_ctx->to_hash_later;
1759497f2e6bSLee Nipper 	}
1760497f2e6bSLee Nipper 	common_nonsnoop_hash_unmap(dev, edesc, areq);
1761497f2e6bSLee Nipper 
1762497f2e6bSLee Nipper 	kfree(edesc);
1763497f2e6bSLee Nipper 
1764497f2e6bSLee Nipper 	areq->base.complete(&areq->base, err);
1765497f2e6bSLee Nipper }
1766497f2e6bSLee Nipper 
17672d02905eSLEROY Christophe /*
17682d02905eSLEROY Christophe  * SEC1 doesn't like hashing of 0 sized message, so we do the padding
17692d02905eSLEROY Christophe  * ourself and submit a padded block
17702d02905eSLEROY Christophe  */
17715b2cf268SLEROY Christophe static void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
17722d02905eSLEROY Christophe 			       struct talitos_edesc *edesc,
17732d02905eSLEROY Christophe 			       struct talitos_ptr *ptr)
17742d02905eSLEROY Christophe {
17752d02905eSLEROY Christophe 	static u8 padded_hash[64] = {
17762d02905eSLEROY Christophe 		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17772d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17782d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17792d02905eSLEROY Christophe 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17802d02905eSLEROY Christophe 	};
17812d02905eSLEROY Christophe 
17822d02905eSLEROY Christophe 	pr_err_once("Bug in SEC1, padding ourself\n");
17832d02905eSLEROY Christophe 	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
17842d02905eSLEROY Christophe 	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
17852d02905eSLEROY Christophe 			       (char *)padded_hash, DMA_TO_DEVICE);
17862d02905eSLEROY Christophe }
17872d02905eSLEROY Christophe 
1788497f2e6bSLee Nipper static int common_nonsnoop_hash(struct talitos_edesc *edesc,
1789497f2e6bSLee Nipper 				struct ahash_request *areq, unsigned int length,
1790497f2e6bSLee Nipper 				void (*callback) (struct device *dev,
1791497f2e6bSLee Nipper 						  struct talitos_desc *desc,
1792497f2e6bSLee Nipper 						  void *context, int error))
1793497f2e6bSLee Nipper {
1794497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1795497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1796497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1797497f2e6bSLee Nipper 	struct device *dev = ctx->dev;
1798497f2e6bSLee Nipper 	struct talitos_desc *desc = &edesc->desc;
1799032d197eSLEROY Christophe 	int ret;
18006a1e8d14SLEROY Christophe 	bool sync_needed = false;
1801922f9dc8SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
1802922f9dc8SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
18036a1e8d14SLEROY Christophe 	int sg_count;
1804497f2e6bSLee Nipper 
1805497f2e6bSLee Nipper 	/* first DWORD empty */
1806497f2e6bSLee Nipper 
180760f208d7SKim Phillips 	/* hash context in */
180860f208d7SKim Phillips 	if (!req_ctx->first || req_ctx->swinit) {
18096a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
1810ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
18116a4967c3SLEROY Christophe 					      req_ctx->hw_context,
1812ad4cd51fSLEROY Christophe 					      DMA_TO_DEVICE);
181360f208d7SKim Phillips 		req_ctx->swinit = 0;
1814afd62fa2SLEROY Christophe 	}
1815497f2e6bSLee Nipper 	/* Indicate next op is not the first. */
1816497f2e6bSLee Nipper 	req_ctx->first = 0;
1817497f2e6bSLee Nipper 
1818497f2e6bSLee Nipper 	/* HMAC key */
1819497f2e6bSLee Nipper 	if (ctx->keylen)
18202e13ce08SLEROY Christophe 		to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
18212e13ce08SLEROY Christophe 			       is_sec1);
1822497f2e6bSLee Nipper 
182337b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf)
182437b5e889SLEROY Christophe 		length -= req_ctx->nbuf;
182537b5e889SLEROY Christophe 
18266a1e8d14SLEROY Christophe 	sg_count = edesc->src_nents ?: 1;
18276a1e8d14SLEROY Christophe 	if (is_sec1 && sg_count > 1)
182858cdbc6dSChristophe Leroy 		sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
182937b5e889SLEROY Christophe 	else if (length)
18306a1e8d14SLEROY Christophe 		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
18316a1e8d14SLEROY Christophe 				      DMA_TO_DEVICE);
1832497f2e6bSLee Nipper 	/*
1833497f2e6bSLee Nipper 	 * data in
1834497f2e6bSLee Nipper 	 */
183537b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf) {
1836ad4cd51fSLEROY Christophe 		map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
1837ad4cd51fSLEROY Christophe 				       req_ctx->buf[req_ctx->buf_idx],
1838ad4cd51fSLEROY Christophe 				       DMA_TO_DEVICE);
183937b5e889SLEROY Christophe 	} else {
18406a1e8d14SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
184158cdbc6dSChristophe Leroy 					  &desc->ptr[3], sg_count, 0, 0);
18426a1e8d14SLEROY Christophe 		if (sg_count > 1)
18436a1e8d14SLEROY Christophe 			sync_needed = true;
184437b5e889SLEROY Christophe 	}
1845497f2e6bSLee Nipper 
1846497f2e6bSLee Nipper 	/* fifth DWORD empty */
1847497f2e6bSLee Nipper 
1848497f2e6bSLee Nipper 	/* hash/HMAC out -or- hash context out */
1849497f2e6bSLee Nipper 	if (req_ctx->last)
1850497f2e6bSLee Nipper 		map_single_talitos_ptr(dev, &desc->ptr[5],
1851497f2e6bSLee Nipper 				       crypto_ahash_digestsize(tfm),
1852*7a6eda5bSChristophe Leroy 				       req_ctx->hw_context, DMA_FROM_DEVICE);
1853497f2e6bSLee Nipper 	else
18546a4967c3SLEROY Christophe 		map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1855ad4cd51fSLEROY Christophe 					      req_ctx->hw_context_size,
18566a4967c3SLEROY Christophe 					      req_ctx->hw_context,
18576a4967c3SLEROY Christophe 					      DMA_FROM_DEVICE);
1858497f2e6bSLee Nipper 
1859497f2e6bSLee Nipper 	/* last DWORD empty */
1860497f2e6bSLee Nipper 
18612d02905eSLEROY Christophe 	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
18622d02905eSLEROY Christophe 		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
18632d02905eSLEROY Christophe 
186437b5e889SLEROY Christophe 	if (is_sec1 && req_ctx->nbuf && length) {
186558cdbc6dSChristophe Leroy 		struct talitos_desc *desc2 = (struct talitos_desc *)
186658cdbc6dSChristophe Leroy 					     (edesc->buf + edesc->dma_len);
186737b5e889SLEROY Christophe 		dma_addr_t next_desc;
186837b5e889SLEROY Christophe 
186937b5e889SLEROY Christophe 		memset(desc2, 0, sizeof(*desc2));
187037b5e889SLEROY Christophe 		desc2->hdr = desc->hdr;
187137b5e889SLEROY Christophe 		desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
187237b5e889SLEROY Christophe 		desc2->hdr1 = desc2->hdr;
187337b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
187437b5e889SLEROY Christophe 		desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
187537b5e889SLEROY Christophe 		desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
187637b5e889SLEROY Christophe 
1877ad4cd51fSLEROY Christophe 		if (desc->ptr[1].ptr)
1878ad4cd51fSLEROY Christophe 			copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
1879ad4cd51fSLEROY Christophe 					 is_sec1);
1880ad4cd51fSLEROY Christophe 		else
18816a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc2->ptr[1],
1882ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1883ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1884ad4cd51fSLEROY Christophe 						      DMA_TO_DEVICE);
188537b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
188637b5e889SLEROY Christophe 		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
188758cdbc6dSChristophe Leroy 					  &desc2->ptr[3], sg_count, 0, 0);
188837b5e889SLEROY Christophe 		if (sg_count > 1)
188937b5e889SLEROY Christophe 			sync_needed = true;
189037b5e889SLEROY Christophe 		copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
189137b5e889SLEROY Christophe 		if (req_ctx->last)
18926a4967c3SLEROY Christophe 			map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
1893ad4cd51fSLEROY Christophe 						      req_ctx->hw_context_size,
1894ad4cd51fSLEROY Christophe 						      req_ctx->hw_context,
1895ad4cd51fSLEROY Christophe 						      DMA_FROM_DEVICE);
189637b5e889SLEROY Christophe 
189737b5e889SLEROY Christophe 		next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE,
189837b5e889SLEROY Christophe 					   DMA_BIDIRECTIONAL);
189937b5e889SLEROY Christophe 		desc->next_desc = cpu_to_be32(next_desc);
190037b5e889SLEROY Christophe 	}
190137b5e889SLEROY Christophe 
19026a1e8d14SLEROY Christophe 	if (sync_needed)
19036a1e8d14SLEROY Christophe 		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
19046a1e8d14SLEROY Christophe 					   edesc->dma_len, DMA_BIDIRECTIONAL);
19056a1e8d14SLEROY Christophe 
19065228f0f7SKim Phillips 	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
1907497f2e6bSLee Nipper 	if (ret != -EINPROGRESS) {
1908497f2e6bSLee Nipper 		common_nonsnoop_hash_unmap(dev, edesc, areq);
1909497f2e6bSLee Nipper 		kfree(edesc);
1910497f2e6bSLee Nipper 	}
1911497f2e6bSLee Nipper 	return ret;
1912497f2e6bSLee Nipper }
1913497f2e6bSLee Nipper 
1914497f2e6bSLee Nipper static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
1915497f2e6bSLee Nipper 					       unsigned int nbytes)
1916497f2e6bSLee Nipper {
1917497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1918497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1919497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
192037b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
192137b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
192237b5e889SLEROY Christophe 
192337b5e889SLEROY Christophe 	if (is_sec1)
192437b5e889SLEROY Christophe 		nbytes -= req_ctx->nbuf;
1925497f2e6bSLee Nipper 
1926aeb4c132SHerbert Xu 	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
192762293a37SHoria Geanta 				   nbytes, 0, 0, 0, areq->base.flags, false);
1928497f2e6bSLee Nipper }
1929497f2e6bSLee Nipper 
1930497f2e6bSLee Nipper static int ahash_init(struct ahash_request *areq)
1931497f2e6bSLee Nipper {
1932497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
19336a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
19346a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
1935497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
193649f9783bSLEROY Christophe 	unsigned int size;
19376a4967c3SLEROY Christophe 	dma_addr_t dma;
1938497f2e6bSLee Nipper 
1939497f2e6bSLee Nipper 	/* Initialize the context */
19403c0dd190SLEROY Christophe 	req_ctx->buf_idx = 0;
19415e833bc4SLee Nipper 	req_ctx->nbuf = 0;
194260f208d7SKim Phillips 	req_ctx->first = 1; /* first indicates h/w must init its context */
194360f208d7SKim Phillips 	req_ctx->swinit = 0; /* assume h/w init of context */
194449f9783bSLEROY Christophe 	size =	(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
1945497f2e6bSLee Nipper 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
1946497f2e6bSLee Nipper 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
194749f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
1948497f2e6bSLee Nipper 
19496a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
19506a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
19516a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
19526a4967c3SLEROY Christophe 
1953497f2e6bSLee Nipper 	return 0;
1954497f2e6bSLee Nipper }
1955497f2e6bSLee Nipper 
195660f208d7SKim Phillips /*
195760f208d7SKim Phillips  * on h/w without explicit sha224 support, we initialize h/w context
195860f208d7SKim Phillips  * manually with sha224 constants, and tell it to run sha256.
195960f208d7SKim Phillips  */
196060f208d7SKim Phillips static int ahash_init_sha224_swinit(struct ahash_request *areq)
196160f208d7SKim Phillips {
196260f208d7SKim Phillips 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
196360f208d7SKim Phillips 
1964a752447aSKim Phillips 	req_ctx->hw_context[0] = SHA224_H0;
1965a752447aSKim Phillips 	req_ctx->hw_context[1] = SHA224_H1;
1966a752447aSKim Phillips 	req_ctx->hw_context[2] = SHA224_H2;
1967a752447aSKim Phillips 	req_ctx->hw_context[3] = SHA224_H3;
1968a752447aSKim Phillips 	req_ctx->hw_context[4] = SHA224_H4;
1969a752447aSKim Phillips 	req_ctx->hw_context[5] = SHA224_H5;
1970a752447aSKim Phillips 	req_ctx->hw_context[6] = SHA224_H6;
1971a752447aSKim Phillips 	req_ctx->hw_context[7] = SHA224_H7;
197260f208d7SKim Phillips 
197360f208d7SKim Phillips 	/* init 64-bit count */
197460f208d7SKim Phillips 	req_ctx->hw_context[8] = 0;
197560f208d7SKim Phillips 	req_ctx->hw_context[9] = 0;
197660f208d7SKim Phillips 
19776a4967c3SLEROY Christophe 	ahash_init(areq);
19786a4967c3SLEROY Christophe 	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
19796a4967c3SLEROY Christophe 
198060f208d7SKim Phillips 	return 0;
198160f208d7SKim Phillips }
198260f208d7SKim Phillips 
1983497f2e6bSLee Nipper static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
1984497f2e6bSLee Nipper {
1985497f2e6bSLee Nipper 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
1986497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
1987497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
1988497f2e6bSLee Nipper 	struct talitos_edesc *edesc;
1989497f2e6bSLee Nipper 	unsigned int blocksize =
1990497f2e6bSLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
1991497f2e6bSLee Nipper 	unsigned int nbytes_to_hash;
1992497f2e6bSLee Nipper 	unsigned int to_hash_later;
19935e833bc4SLee Nipper 	unsigned int nsg;
19948e409fe1SLABBE Corentin 	int nents;
199537b5e889SLEROY Christophe 	struct device *dev = ctx->dev;
199637b5e889SLEROY Christophe 	struct talitos_private *priv = dev_get_drvdata(dev);
199737b5e889SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
19983c0dd190SLEROY Christophe 	u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
1999497f2e6bSLee Nipper 
20005e833bc4SLee Nipper 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
20015e833bc4SLee Nipper 		/* Buffer up to one whole block */
20028e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
20038e409fe1SLABBE Corentin 		if (nents < 0) {
20048e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
20058e409fe1SLABBE Corentin 			return nents;
20068e409fe1SLABBE Corentin 		}
20078e409fe1SLABBE Corentin 		sg_copy_to_buffer(areq->src, nents,
20083c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, nbytes);
20095e833bc4SLee Nipper 		req_ctx->nbuf += nbytes;
2010497f2e6bSLee Nipper 		return 0;
2011497f2e6bSLee Nipper 	}
2012497f2e6bSLee Nipper 
20135e833bc4SLee Nipper 	/* At least (blocksize + 1) bytes are available to hash */
20145e833bc4SLee Nipper 	nbytes_to_hash = nbytes + req_ctx->nbuf;
20155e833bc4SLee Nipper 	to_hash_later = nbytes_to_hash & (blocksize - 1);
20165e833bc4SLee Nipper 
20175e833bc4SLee Nipper 	if (req_ctx->last)
20185e833bc4SLee Nipper 		to_hash_later = 0;
20195e833bc4SLee Nipper 	else if (to_hash_later)
20205e833bc4SLee Nipper 		/* There is a partial block. Hash the full block(s) now */
20215e833bc4SLee Nipper 		nbytes_to_hash -= to_hash_later;
20225e833bc4SLee Nipper 	else {
20235e833bc4SLee Nipper 		/* Keep one block buffered */
20245e833bc4SLee Nipper 		nbytes_to_hash -= blocksize;
20255e833bc4SLee Nipper 		to_hash_later = blocksize;
2026497f2e6bSLee Nipper 	}
20275e833bc4SLee Nipper 
20285e833bc4SLee Nipper 	/* Chain in any previously buffered data */
202937b5e889SLEROY Christophe 	if (!is_sec1 && req_ctx->nbuf) {
20305e833bc4SLee Nipper 		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
20315e833bc4SLee Nipper 		sg_init_table(req_ctx->bufsl, nsg);
20323c0dd190SLEROY Christophe 		sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
20335e833bc4SLee Nipper 		if (nsg > 1)
2034c56f6d12SDan Williams 			sg_chain(req_ctx->bufsl, 2, areq->src);
20355e833bc4SLee Nipper 		req_ctx->psrc = req_ctx->bufsl;
203637b5e889SLEROY Christophe 	} else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
203758cdbc6dSChristophe Leroy 		int offset;
203858cdbc6dSChristophe Leroy 
203937b5e889SLEROY Christophe 		if (nbytes_to_hash > blocksize)
204037b5e889SLEROY Christophe 			offset = blocksize - req_ctx->nbuf;
204137b5e889SLEROY Christophe 		else
204237b5e889SLEROY Christophe 			offset = nbytes_to_hash - req_ctx->nbuf;
204337b5e889SLEROY Christophe 		nents = sg_nents_for_len(areq->src, offset);
204437b5e889SLEROY Christophe 		if (nents < 0) {
204537b5e889SLEROY Christophe 			dev_err(ctx->dev, "Invalid number of src SG.\n");
204637b5e889SLEROY Christophe 			return nents;
204737b5e889SLEROY Christophe 		}
204837b5e889SLEROY Christophe 		sg_copy_to_buffer(areq->src, nents,
20493c0dd190SLEROY Christophe 				  ctx_buf + req_ctx->nbuf, offset);
205037b5e889SLEROY Christophe 		req_ctx->nbuf += offset;
205158cdbc6dSChristophe Leroy 		req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, areq->src,
205258cdbc6dSChristophe Leroy 						 offset);
20535e833bc4SLee Nipper 	} else
20545e833bc4SLee Nipper 		req_ctx->psrc = areq->src;
20555e833bc4SLee Nipper 
2056497f2e6bSLee Nipper 	if (to_hash_later) {
20578e409fe1SLABBE Corentin 		nents = sg_nents_for_len(areq->src, nbytes);
20588e409fe1SLABBE Corentin 		if (nents < 0) {
20598e409fe1SLABBE Corentin 			dev_err(ctx->dev, "Invalid number of src SG.\n");
20608e409fe1SLABBE Corentin 			return nents;
20618e409fe1SLABBE Corentin 		}
2062d0525723SAkinobu Mita 		sg_pcopy_to_buffer(areq->src, nents,
20633c0dd190SLEROY Christophe 				   req_ctx->buf[(req_ctx->buf_idx + 1) & 1],
2064497f2e6bSLee Nipper 				      to_hash_later,
2065497f2e6bSLee Nipper 				      nbytes - to_hash_later);
2066497f2e6bSLee Nipper 	}
2067497f2e6bSLee Nipper 	req_ctx->to_hash_later = to_hash_later;
2068497f2e6bSLee Nipper 
20695e833bc4SLee Nipper 	/* Allocate extended descriptor */
2070497f2e6bSLee Nipper 	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
2071497f2e6bSLee Nipper 	if (IS_ERR(edesc))
2072497f2e6bSLee Nipper 		return PTR_ERR(edesc);
2073497f2e6bSLee Nipper 
2074497f2e6bSLee Nipper 	edesc->desc.hdr = ctx->desc_hdr_template;
2075497f2e6bSLee Nipper 
2076497f2e6bSLee Nipper 	/* On last one, request SEC to pad; otherwise continue */
2077497f2e6bSLee Nipper 	if (req_ctx->last)
2078497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
2079497f2e6bSLee Nipper 	else
2080497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
2081497f2e6bSLee Nipper 
208260f208d7SKim Phillips 	/* request SEC to INIT hash. */
208360f208d7SKim Phillips 	if (req_ctx->first && !req_ctx->swinit)
2084497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
2085497f2e6bSLee Nipper 
2086497f2e6bSLee Nipper 	/* When the tfm context has a keylen, it's an HMAC.
2087497f2e6bSLee Nipper 	 * A first or last (ie. not middle) descriptor must request HMAC.
2088497f2e6bSLee Nipper 	 */
2089497f2e6bSLee Nipper 	if (ctx->keylen && (req_ctx->first || req_ctx->last))
2090497f2e6bSLee Nipper 		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
2091497f2e6bSLee Nipper 
209258cdbc6dSChristophe Leroy 	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, ahash_done);
2093497f2e6bSLee Nipper }
2094497f2e6bSLee Nipper 
2095497f2e6bSLee Nipper static int ahash_update(struct ahash_request *areq)
2096497f2e6bSLee Nipper {
2097497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2098497f2e6bSLee Nipper 
2099497f2e6bSLee Nipper 	req_ctx->last = 0;
2100497f2e6bSLee Nipper 
2101497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2102497f2e6bSLee Nipper }
2103497f2e6bSLee Nipper 
2104497f2e6bSLee Nipper static int ahash_final(struct ahash_request *areq)
2105497f2e6bSLee Nipper {
2106497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2107497f2e6bSLee Nipper 
2108497f2e6bSLee Nipper 	req_ctx->last = 1;
2109497f2e6bSLee Nipper 
2110497f2e6bSLee Nipper 	return ahash_process_req(areq, 0);
2111497f2e6bSLee Nipper }
2112497f2e6bSLee Nipper 
2113497f2e6bSLee Nipper static int ahash_finup(struct ahash_request *areq)
2114497f2e6bSLee Nipper {
2115497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
2116497f2e6bSLee Nipper 
2117497f2e6bSLee Nipper 	req_ctx->last = 1;
2118497f2e6bSLee Nipper 
2119497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2120497f2e6bSLee Nipper }
2121497f2e6bSLee Nipper 
2122497f2e6bSLee Nipper static int ahash_digest(struct ahash_request *areq)
2123497f2e6bSLee Nipper {
2124497f2e6bSLee Nipper 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
212560f208d7SKim Phillips 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
2126497f2e6bSLee Nipper 
212760f208d7SKim Phillips 	ahash->init(areq);
2128497f2e6bSLee Nipper 	req_ctx->last = 1;
2129497f2e6bSLee Nipper 
2130497f2e6bSLee Nipper 	return ahash_process_req(areq, areq->nbytes);
2131497f2e6bSLee Nipper }
2132497f2e6bSLee Nipper 
21333639ca84SHoria Geant? static int ahash_export(struct ahash_request *areq, void *out)
21343639ca84SHoria Geant? {
21353639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21363639ca84SHoria Geant? 	struct talitos_export_state *export = out;
21376a4967c3SLEROY Christophe 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
21386a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
21396a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
21406a4967c3SLEROY Christophe 	dma_addr_t dma;
21416a4967c3SLEROY Christophe 
21426a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
21436a4967c3SLEROY Christophe 			     DMA_FROM_DEVICE);
21446a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE);
21453639ca84SHoria Geant? 
21463639ca84SHoria Geant? 	memcpy(export->hw_context, req_ctx->hw_context,
21473639ca84SHoria Geant? 	       req_ctx->hw_context_size);
21483c0dd190SLEROY Christophe 	memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf);
21493639ca84SHoria Geant? 	export->swinit = req_ctx->swinit;
21503639ca84SHoria Geant? 	export->first = req_ctx->first;
21513639ca84SHoria Geant? 	export->last = req_ctx->last;
21523639ca84SHoria Geant? 	export->to_hash_later = req_ctx->to_hash_later;
21533639ca84SHoria Geant? 	export->nbuf = req_ctx->nbuf;
21543639ca84SHoria Geant? 
21553639ca84SHoria Geant? 	return 0;
21563639ca84SHoria Geant? }
21573639ca84SHoria Geant? 
21583639ca84SHoria Geant? static int ahash_import(struct ahash_request *areq, const void *in)
21593639ca84SHoria Geant? {
21603639ca84SHoria Geant? 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21613639ca84SHoria Geant? 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
21626a4967c3SLEROY Christophe 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
21636a4967c3SLEROY Christophe 	struct device *dev = ctx->dev;
21643639ca84SHoria Geant? 	const struct talitos_export_state *export = in;
216549f9783bSLEROY Christophe 	unsigned int size;
21666a4967c3SLEROY Christophe 	dma_addr_t dma;
21673639ca84SHoria Geant? 
21683639ca84SHoria Geant? 	memset(req_ctx, 0, sizeof(*req_ctx));
216949f9783bSLEROY Christophe 	size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
21703639ca84SHoria Geant? 			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
21713639ca84SHoria Geant? 			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
217249f9783bSLEROY Christophe 	req_ctx->hw_context_size = size;
217349f9783bSLEROY Christophe 	memcpy(req_ctx->hw_context, export->hw_context, size);
21743c0dd190SLEROY Christophe 	memcpy(req_ctx->buf[0], export->buf, export->nbuf);
21753639ca84SHoria Geant? 	req_ctx->swinit = export->swinit;
21763639ca84SHoria Geant? 	req_ctx->first = export->first;
21773639ca84SHoria Geant? 	req_ctx->last = export->last;
21783639ca84SHoria Geant? 	req_ctx->to_hash_later = export->to_hash_later;
21793639ca84SHoria Geant? 	req_ctx->nbuf = export->nbuf;
21803639ca84SHoria Geant? 
21816a4967c3SLEROY Christophe 	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
21826a4967c3SLEROY Christophe 			     DMA_TO_DEVICE);
21836a4967c3SLEROY Christophe 	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
21846a4967c3SLEROY Christophe 
21853639ca84SHoria Geant? 	return 0;
21863639ca84SHoria Geant? }
21873639ca84SHoria Geant? 
218879b3a418SLee Nipper static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
218979b3a418SLee Nipper 		   u8 *hash)
219079b3a418SLee Nipper {
219179b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
219279b3a418SLee Nipper 
219379b3a418SLee Nipper 	struct scatterlist sg[1];
219479b3a418SLee Nipper 	struct ahash_request *req;
2195f1c90ac3SGilad Ben-Yossef 	struct crypto_wait wait;
219679b3a418SLee Nipper 	int ret;
219779b3a418SLee Nipper 
2198f1c90ac3SGilad Ben-Yossef 	crypto_init_wait(&wait);
219979b3a418SLee Nipper 
220079b3a418SLee Nipper 	req = ahash_request_alloc(tfm, GFP_KERNEL);
220179b3a418SLee Nipper 	if (!req)
220279b3a418SLee Nipper 		return -ENOMEM;
220379b3a418SLee Nipper 
220479b3a418SLee Nipper 	/* Keep tfm keylen == 0 during hash of the long key */
220579b3a418SLee Nipper 	ctx->keylen = 0;
220679b3a418SLee Nipper 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
2207f1c90ac3SGilad Ben-Yossef 				   crypto_req_done, &wait);
220879b3a418SLee Nipper 
220979b3a418SLee Nipper 	sg_init_one(&sg[0], key, keylen);
221079b3a418SLee Nipper 
221179b3a418SLee Nipper 	ahash_request_set_crypt(req, sg, hash, keylen);
2212f1c90ac3SGilad Ben-Yossef 	ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
2213f1c90ac3SGilad Ben-Yossef 
221479b3a418SLee Nipper 	ahash_request_free(req);
221579b3a418SLee Nipper 
221679b3a418SLee Nipper 	return ret;
221779b3a418SLee Nipper }
221879b3a418SLee Nipper 
221979b3a418SLee Nipper static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
222079b3a418SLee Nipper 			unsigned int keylen)
222179b3a418SLee Nipper {
222279b3a418SLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
22232e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
222479b3a418SLee Nipper 	unsigned int blocksize =
222579b3a418SLee Nipper 			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
222679b3a418SLee Nipper 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
222779b3a418SLee Nipper 	unsigned int keysize = keylen;
222879b3a418SLee Nipper 	u8 hash[SHA512_DIGEST_SIZE];
222979b3a418SLee Nipper 	int ret;
223079b3a418SLee Nipper 
223179b3a418SLee Nipper 	if (keylen <= blocksize)
223279b3a418SLee Nipper 		memcpy(ctx->key, key, keysize);
223379b3a418SLee Nipper 	else {
223479b3a418SLee Nipper 		/* Must get the hash of the long key */
223579b3a418SLee Nipper 		ret = keyhash(tfm, key, keylen, hash);
223679b3a418SLee Nipper 
223779b3a418SLee Nipper 		if (ret) {
223879b3a418SLee Nipper 			crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
223979b3a418SLee Nipper 			return -EINVAL;
224079b3a418SLee Nipper 		}
224179b3a418SLee Nipper 
224279b3a418SLee Nipper 		keysize = digestsize;
224379b3a418SLee Nipper 		memcpy(ctx->key, hash, digestsize);
224479b3a418SLee Nipper 	}
224579b3a418SLee Nipper 
22462e13ce08SLEROY Christophe 	if (ctx->keylen)
22472e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
22482e13ce08SLEROY Christophe 
224979b3a418SLee Nipper 	ctx->keylen = keysize;
22502e13ce08SLEROY Christophe 	ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE);
225179b3a418SLee Nipper 
225279b3a418SLee Nipper 	return 0;
225379b3a418SLee Nipper }
225479b3a418SLee Nipper 
225579b3a418SLee Nipper 
22569c4a7965SKim Phillips struct talitos_alg_template {
2257d5e4aaefSLee Nipper 	u32 type;
2258b0057763SLEROY Christophe 	u32 priority;
2259d5e4aaefSLee Nipper 	union {
2260d5e4aaefSLee Nipper 		struct crypto_alg crypto;
2261acbf7c62SLee Nipper 		struct ahash_alg hash;
2262aeb4c132SHerbert Xu 		struct aead_alg aead;
2263d5e4aaefSLee Nipper 	} alg;
22649c4a7965SKim Phillips 	__be32 desc_hdr_template;
22659c4a7965SKim Phillips };
22669c4a7965SKim Phillips 
22679c4a7965SKim Phillips static struct talitos_alg_template driver_algs[] = {
2268991155baSHoria Geanta 	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
2269d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2270aeb4c132SHerbert Xu 		.alg.aead = {
2271aeb4c132SHerbert Xu 			.base = {
227256af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
2273aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2274aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
227556af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2276aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2277aeb4c132SHerbert Xu 			},
22783952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
22793952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
22809c4a7965SKim Phillips 		},
22819c4a7965SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
22829c4a7965SKim Phillips 			             DESC_HDR_SEL0_AESU |
22839c4a7965SKim Phillips 		                     DESC_HDR_MODE0_AESU_CBC |
22849c4a7965SKim Phillips 		                     DESC_HDR_SEL1_MDEUA |
22859c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_INIT |
22869c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_PAD |
22879c4a7965SKim Phillips 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
228870bcaca7SLee Nipper 	},
2289d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
22907405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22917405c8d7SLEROY Christophe 		.alg.aead = {
22927405c8d7SLEROY Christophe 			.base = {
22937405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),cbc(aes))",
22947405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
2295a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
22967405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
22977405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
22987405c8d7SLEROY Christophe 			},
22997405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
23007405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
23017405c8d7SLEROY Christophe 		},
23027405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23037405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23047405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23057405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23067405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23077405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23087405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23097405c8d7SLEROY Christophe 	},
23107405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2311aeb4c132SHerbert Xu 		.alg.aead = {
2312aeb4c132SHerbert Xu 			.base = {
2313aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha1),"
2314aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2315aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha1-"
2316aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
231756af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2318aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2319aeb4c132SHerbert Xu 			},
23203952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
23213952f17eSLee Nipper 			.maxauthsize = SHA1_DIGEST_SIZE,
2322ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
232370bcaca7SLee Nipper 		},
232470bcaca7SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
232570bcaca7SLee Nipper 			             DESC_HDR_SEL0_DEU |
232670bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
232770bcaca7SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
232870bcaca7SLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
232970bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
233070bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
233170bcaca7SLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23323952f17eSLee Nipper 	},
2333d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
23347405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23357405c8d7SLEROY Christophe 		.alg.aead = {
23367405c8d7SLEROY Christophe 			.base = {
23377405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha1),"
23387405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
23397405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha1-"
2340a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
23417405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
23427405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23437405c8d7SLEROY Christophe 			},
23447405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
23457405c8d7SLEROY Christophe 			.maxauthsize = SHA1_DIGEST_SIZE,
2346ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
23477405c8d7SLEROY Christophe 		},
23487405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23497405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
23507405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
23517405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
23527405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23537405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23547405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23557405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23567405c8d7SLEROY Christophe 	},
23577405c8d7SLEROY Christophe 	{       .type = CRYPTO_ALG_TYPE_AEAD,
2358aeb4c132SHerbert Xu 		.alg.aead = {
2359aeb4c132SHerbert Xu 			.base = {
2360357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
2361aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2362aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2363357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2364aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2365aeb4c132SHerbert Xu 			},
2366357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2367357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2368357fb605SHoria Geanta 		},
2369357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2370357fb605SHoria Geanta 				     DESC_HDR_SEL0_AESU |
2371357fb605SHoria Geanta 				     DESC_HDR_MODE0_AESU_CBC |
2372357fb605SHoria Geanta 				     DESC_HDR_SEL1_MDEUA |
2373357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_INIT |
2374357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_PAD |
2375357fb605SHoria Geanta 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2376357fb605SHoria Geanta 	},
2377357fb605SHoria Geanta 	{       .type = CRYPTO_ALG_TYPE_AEAD,
23787405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23797405c8d7SLEROY Christophe 		.alg.aead = {
23807405c8d7SLEROY Christophe 			.base = {
23817405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),cbc(aes))",
23827405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
2383a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
23847405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
23857405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
23867405c8d7SLEROY Christophe 			},
23877405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
23887405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
23897405c8d7SLEROY Christophe 		},
23907405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23917405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
23927405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
23937405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
23947405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
23957405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
23967405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
23977405c8d7SLEROY Christophe 	},
23987405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2399aeb4c132SHerbert Xu 		.alg.aead = {
2400aeb4c132SHerbert Xu 			.base = {
2401aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha224),"
2402aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2403aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha224-"
2404aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2405357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2406aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2407aeb4c132SHerbert Xu 			},
2408357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2409357fb605SHoria Geanta 			.maxauthsize = SHA224_DIGEST_SIZE,
2410ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2411357fb605SHoria Geanta 		},
2412357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2413357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2414357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2415357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2416357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUA |
2417357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2418357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2419357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
2420357fb605SHoria Geanta 	},
2421357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24227405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24237405c8d7SLEROY Christophe 		.alg.aead = {
24247405c8d7SLEROY Christophe 			.base = {
24257405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha224),"
24267405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
24277405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha224-"
2428a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
24297405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24307405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24317405c8d7SLEROY Christophe 			},
24327405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
24337405c8d7SLEROY Christophe 			.maxauthsize = SHA224_DIGEST_SIZE,
2434ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
24357405c8d7SLEROY Christophe 		},
24367405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24377405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
24387405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
24397405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
24407405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24417405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24427405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24437405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
24447405c8d7SLEROY Christophe 	},
24457405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2446aeb4c132SHerbert Xu 		.alg.aead = {
2447aeb4c132SHerbert Xu 			.base = {
244856af8cd4SLee Nipper 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
2449aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2450aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
245156af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2452aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2453aeb4c132SHerbert Xu 			},
24543952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
24553952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
24563952f17eSLee Nipper 		},
24573952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24583952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
24593952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
24603952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
24613952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
24623952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
24633952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24643952f17eSLee Nipper 	},
2465d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
24667405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24677405c8d7SLEROY Christophe 		.alg.aead = {
24687405c8d7SLEROY Christophe 			.base = {
24697405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),cbc(aes))",
24707405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
2471a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
24727405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
24737405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
24747405c8d7SLEROY Christophe 			},
24757405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
24767405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
24777405c8d7SLEROY Christophe 		},
24787405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24797405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
24807405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
24817405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
24827405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
24837405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
24847405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24857405c8d7SLEROY Christophe 	},
24867405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2487aeb4c132SHerbert Xu 		.alg.aead = {
2488aeb4c132SHerbert Xu 			.base = {
2489aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha256),"
2490aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2491aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha256-"
2492aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
249356af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2494aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2495aeb4c132SHerbert Xu 			},
24963952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
24973952f17eSLee Nipper 			.maxauthsize = SHA256_DIGEST_SIZE,
2498ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
24993952f17eSLee Nipper 		},
25003952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25013952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
25023952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
25033952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
25043952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
25053952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
25063952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
25073952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25083952f17eSLee Nipper 	},
2509d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
25107405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25117405c8d7SLEROY Christophe 		.alg.aead = {
25127405c8d7SLEROY Christophe 			.base = {
25137405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(sha256),"
25147405c8d7SLEROY Christophe 					    "cbc(des3_ede))",
25157405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-sha256-"
2516a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
25177405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
25187405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
25197405c8d7SLEROY Christophe 			},
25207405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
25217405c8d7SLEROY Christophe 			.maxauthsize = SHA256_DIGEST_SIZE,
2522ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
25237405c8d7SLEROY Christophe 		},
25247405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25257405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
25267405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
25277405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
25287405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
25297405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
25307405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
25317405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25327405c8d7SLEROY Christophe 	},
25337405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2534aeb4c132SHerbert Xu 		.alg.aead = {
2535aeb4c132SHerbert Xu 			.base = {
2536357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha384),cbc(aes))",
2537aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2538aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2539357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2540aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2541aeb4c132SHerbert Xu 			},
2542357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2543357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2544357fb605SHoria Geanta 		},
2545357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2546357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2547357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2548357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2549357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2550357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2551357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2552357fb605SHoria Geanta 	},
2553357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2554aeb4c132SHerbert Xu 		.alg.aead = {
2555aeb4c132SHerbert Xu 			.base = {
2556aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha384),"
2557aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2558aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha384-"
2559aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2560357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2561aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2562aeb4c132SHerbert Xu 			},
2563357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2564357fb605SHoria Geanta 			.maxauthsize = SHA384_DIGEST_SIZE,
2565ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2566357fb605SHoria Geanta 		},
2567357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2568357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2569357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2570357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2571357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2572357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2573357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2574357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
2575357fb605SHoria Geanta 	},
2576357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2577aeb4c132SHerbert Xu 		.alg.aead = {
2578aeb4c132SHerbert Xu 			.base = {
2579357fb605SHoria Geanta 				.cra_name = "authenc(hmac(sha512),cbc(aes))",
2580aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2581aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
2582357fb605SHoria Geanta 				.cra_blocksize = AES_BLOCK_SIZE,
2583aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2584aeb4c132SHerbert Xu 			},
2585357fb605SHoria Geanta 			.ivsize = AES_BLOCK_SIZE,
2586357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2587357fb605SHoria Geanta 		},
2588357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2589357fb605SHoria Geanta 			             DESC_HDR_SEL0_AESU |
2590357fb605SHoria Geanta 		                     DESC_HDR_MODE0_AESU_CBC |
2591357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2592357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2593357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2594357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2595357fb605SHoria Geanta 	},
2596357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2597aeb4c132SHerbert Xu 		.alg.aead = {
2598aeb4c132SHerbert Xu 			.base = {
2599aeb4c132SHerbert Xu 				.cra_name = "authenc(hmac(sha512),"
2600aeb4c132SHerbert Xu 					    "cbc(des3_ede))",
2601aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-sha512-"
2602aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
2603357fb605SHoria Geanta 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2604aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2605aeb4c132SHerbert Xu 			},
2606357fb605SHoria Geanta 			.ivsize = DES3_EDE_BLOCK_SIZE,
2607357fb605SHoria Geanta 			.maxauthsize = SHA512_DIGEST_SIZE,
2608ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
2609357fb605SHoria Geanta 		},
2610357fb605SHoria Geanta 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
2611357fb605SHoria Geanta 			             DESC_HDR_SEL0_DEU |
2612357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_CBC |
2613357fb605SHoria Geanta 		                     DESC_HDR_MODE0_DEU_3DES |
2614357fb605SHoria Geanta 		                     DESC_HDR_SEL1_MDEUB |
2615357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_INIT |
2616357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEU_PAD |
2617357fb605SHoria Geanta 		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
2618357fb605SHoria Geanta 	},
2619357fb605SHoria Geanta 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2620aeb4c132SHerbert Xu 		.alg.aead = {
2621aeb4c132SHerbert Xu 			.base = {
262256af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(aes))",
2623aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2624aeb4c132SHerbert Xu 						   "cbc-aes-talitos",
262556af8cd4SLee Nipper 				.cra_blocksize = AES_BLOCK_SIZE,
2626aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2627aeb4c132SHerbert Xu 			},
26283952f17eSLee Nipper 			.ivsize = AES_BLOCK_SIZE,
26293952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
26303952f17eSLee Nipper 		},
26313952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26323952f17eSLee Nipper 			             DESC_HDR_SEL0_AESU |
26333952f17eSLee Nipper 		                     DESC_HDR_MODE0_AESU_CBC |
26343952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26353952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
26363952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
26373952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26383952f17eSLee Nipper 	},
2639d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AEAD,
26407405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26417405c8d7SLEROY Christophe 		.alg.aead = {
26427405c8d7SLEROY Christophe 			.base = {
26437405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(aes))",
26447405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
2645a1a42f84SChristophe Leroy 						   "cbc-aes-talitos-hsna",
26467405c8d7SLEROY Christophe 				.cra_blocksize = AES_BLOCK_SIZE,
26477405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
26487405c8d7SLEROY Christophe 			},
26497405c8d7SLEROY Christophe 			.ivsize = AES_BLOCK_SIZE,
26507405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
26517405c8d7SLEROY Christophe 		},
26527405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
26537405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_AESU |
26547405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_AESU_CBC |
26557405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
26567405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
26577405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
26587405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26597405c8d7SLEROY Christophe 	},
26607405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
2661aeb4c132SHerbert Xu 		.alg.aead = {
2662aeb4c132SHerbert Xu 			.base = {
266356af8cd4SLee Nipper 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
2664aeb4c132SHerbert Xu 				.cra_driver_name = "authenc-hmac-md5-"
2665aeb4c132SHerbert Xu 						   "cbc-3des-talitos",
266656af8cd4SLee Nipper 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
2667aeb4c132SHerbert Xu 				.cra_flags = CRYPTO_ALG_ASYNC,
2668aeb4c132SHerbert Xu 			},
26693952f17eSLee Nipper 			.ivsize = DES3_EDE_BLOCK_SIZE,
26703952f17eSLee Nipper 			.maxauthsize = MD5_DIGEST_SIZE,
2671ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
26723952f17eSLee Nipper 		},
26733952f17eSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26743952f17eSLee Nipper 			             DESC_HDR_SEL0_DEU |
26753952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
26763952f17eSLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES |
26773952f17eSLee Nipper 		                     DESC_HDR_SEL1_MDEUA |
26783952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_INIT |
26793952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_PAD |
26803952f17eSLee Nipper 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26814de9d0b5SLee Nipper 	},
26827405c8d7SLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_AEAD,
26837405c8d7SLEROY Christophe 		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26847405c8d7SLEROY Christophe 		.alg.aead = {
26857405c8d7SLEROY Christophe 			.base = {
26867405c8d7SLEROY Christophe 				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
26877405c8d7SLEROY Christophe 				.cra_driver_name = "authenc-hmac-md5-"
2688a1a42f84SChristophe Leroy 						   "cbc-3des-talitos-hsna",
26897405c8d7SLEROY Christophe 				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26907405c8d7SLEROY Christophe 				.cra_flags = CRYPTO_ALG_ASYNC,
26917405c8d7SLEROY Christophe 			},
26927405c8d7SLEROY Christophe 			.ivsize = DES3_EDE_BLOCK_SIZE,
26937405c8d7SLEROY Christophe 			.maxauthsize = MD5_DIGEST_SIZE,
2694ef7c5c85SHerbert Xu 			.setkey = aead_des3_setkey,
26957405c8d7SLEROY Christophe 		},
26967405c8d7SLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
26977405c8d7SLEROY Christophe 				     DESC_HDR_SEL0_DEU |
26987405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC |
26997405c8d7SLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES |
27007405c8d7SLEROY Christophe 				     DESC_HDR_SEL1_MDEUA |
27017405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_INIT |
27027405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_PAD |
27037405c8d7SLEROY Christophe 				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27047405c8d7SLEROY Christophe 	},
27054de9d0b5SLee Nipper 	/* ABLKCIPHER algorithms. */
2706d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2707d5e4aaefSLee Nipper 		.alg.crypto = {
27085e75ae1bSLEROY Christophe 			.cra_name = "ecb(aes)",
27095e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-aes-talitos",
27105e75ae1bSLEROY Christophe 			.cra_blocksize = AES_BLOCK_SIZE,
27115e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27125e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27135e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27145e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
27155e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
27161ba34e71SChristophe Leroy 				.setkey = ablkcipher_aes_setkey,
27175e75ae1bSLEROY Christophe 			}
27185e75ae1bSLEROY Christophe 		},
27195e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27205e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU,
27215e75ae1bSLEROY Christophe 	},
27225e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27235e75ae1bSLEROY Christophe 		.alg.crypto = {
27244de9d0b5SLee Nipper 			.cra_name = "cbc(aes)",
27254de9d0b5SLee Nipper 			.cra_driver_name = "cbc-aes-talitos",
27264de9d0b5SLee Nipper 			.cra_blocksize = AES_BLOCK_SIZE,
27274de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27284de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
27294de9d0b5SLee Nipper 			.cra_ablkcipher = {
27304de9d0b5SLee Nipper 				.min_keysize = AES_MIN_KEY_SIZE,
27314de9d0b5SLee Nipper 				.max_keysize = AES_MAX_KEY_SIZE,
27324de9d0b5SLee Nipper 				.ivsize = AES_BLOCK_SIZE,
27331ba34e71SChristophe Leroy 				.setkey = ablkcipher_aes_setkey,
27344de9d0b5SLee Nipper 			}
27354de9d0b5SLee Nipper 		},
27364de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27374de9d0b5SLee Nipper 				     DESC_HDR_SEL0_AESU |
27384de9d0b5SLee Nipper 				     DESC_HDR_MODE0_AESU_CBC,
27394de9d0b5SLee Nipper 	},
2740d5e4aaefSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
2741d5e4aaefSLee Nipper 		.alg.crypto = {
27425e75ae1bSLEROY Christophe 			.cra_name = "ctr(aes)",
27435e75ae1bSLEROY Christophe 			.cra_driver_name = "ctr-aes-talitos",
2744b9a05b60SChristophe Leroy 			.cra_blocksize = 1,
27455e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27465e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27475e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27485e75ae1bSLEROY Christophe 				.min_keysize = AES_MIN_KEY_SIZE,
27495e75ae1bSLEROY Christophe 				.max_keysize = AES_MAX_KEY_SIZE,
27505e75ae1bSLEROY Christophe 				.ivsize = AES_BLOCK_SIZE,
27511ba34e71SChristophe Leroy 				.setkey = ablkcipher_aes_setkey,
27525e75ae1bSLEROY Christophe 			}
27535e75ae1bSLEROY Christophe 		},
275470d355ccSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
27555e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_AESU |
27565e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_AESU_CTR,
27575e75ae1bSLEROY Christophe 	},
27585e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27595e75ae1bSLEROY Christophe 		.alg.crypto = {
27605e75ae1bSLEROY Christophe 			.cra_name = "ecb(des)",
27615e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-des-talitos",
27625e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
27635e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27645e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27655e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27665e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
27675e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
2768ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des_setkey,
27695e75ae1bSLEROY Christophe 			}
27705e75ae1bSLEROY Christophe 		},
27715e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27725e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU,
27735e75ae1bSLEROY Christophe 	},
27745e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27755e75ae1bSLEROY Christophe 		.alg.crypto = {
27765e75ae1bSLEROY Christophe 			.cra_name = "cbc(des)",
27775e75ae1bSLEROY Christophe 			.cra_driver_name = "cbc-des-talitos",
27785e75ae1bSLEROY Christophe 			.cra_blocksize = DES_BLOCK_SIZE,
27795e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27805e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27815e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
27825e75ae1bSLEROY Christophe 				.min_keysize = DES_KEY_SIZE,
27835e75ae1bSLEROY Christophe 				.max_keysize = DES_KEY_SIZE,
27845e75ae1bSLEROY Christophe 				.ivsize = DES_BLOCK_SIZE,
2785ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des_setkey,
27865e75ae1bSLEROY Christophe 			}
27875e75ae1bSLEROY Christophe 		},
27885e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27895e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
27905e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_CBC,
27915e75ae1bSLEROY Christophe 	},
27925e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
27935e75ae1bSLEROY Christophe 		.alg.crypto = {
27945e75ae1bSLEROY Christophe 			.cra_name = "ecb(des3_ede)",
27955e75ae1bSLEROY Christophe 			.cra_driver_name = "ecb-3des-talitos",
27965e75ae1bSLEROY Christophe 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
27975e75ae1bSLEROY Christophe 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
27985e75ae1bSLEROY Christophe 				     CRYPTO_ALG_ASYNC,
27995e75ae1bSLEROY Christophe 			.cra_ablkcipher = {
28005e75ae1bSLEROY Christophe 				.min_keysize = DES3_EDE_KEY_SIZE,
28015e75ae1bSLEROY Christophe 				.max_keysize = DES3_EDE_KEY_SIZE,
2802ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des3_setkey,
28035e75ae1bSLEROY Christophe 			}
28045e75ae1bSLEROY Christophe 		},
28055e75ae1bSLEROY Christophe 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28065e75ae1bSLEROY Christophe 				     DESC_HDR_SEL0_DEU |
28075e75ae1bSLEROY Christophe 				     DESC_HDR_MODE0_DEU_3DES,
28085e75ae1bSLEROY Christophe 	},
28095e75ae1bSLEROY Christophe 	{	.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
28105e75ae1bSLEROY Christophe 		.alg.crypto = {
28114de9d0b5SLee Nipper 			.cra_name = "cbc(des3_ede)",
28124de9d0b5SLee Nipper 			.cra_driver_name = "cbc-3des-talitos",
28134de9d0b5SLee Nipper 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
28144de9d0b5SLee Nipper 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
28154de9d0b5SLee Nipper                                      CRYPTO_ALG_ASYNC,
28164de9d0b5SLee Nipper 			.cra_ablkcipher = {
28174de9d0b5SLee Nipper 				.min_keysize = DES3_EDE_KEY_SIZE,
28184de9d0b5SLee Nipper 				.max_keysize = DES3_EDE_KEY_SIZE,
28194de9d0b5SLee Nipper 				.ivsize = DES3_EDE_BLOCK_SIZE,
2820ef7c5c85SHerbert Xu 				.setkey = ablkcipher_des3_setkey,
28214de9d0b5SLee Nipper 			}
28224de9d0b5SLee Nipper 		},
28234de9d0b5SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28244de9d0b5SLee Nipper 			             DESC_HDR_SEL0_DEU |
28254de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_CBC |
28264de9d0b5SLee Nipper 		                     DESC_HDR_MODE0_DEU_3DES,
2827497f2e6bSLee Nipper 	},
2828497f2e6bSLee Nipper 	/* AHASH algorithms. */
2829497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2830497f2e6bSLee Nipper 		.alg.hash = {
2831497f2e6bSLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
28323639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2833497f2e6bSLee Nipper 			.halg.base = {
2834497f2e6bSLee Nipper 				.cra_name = "md5",
2835497f2e6bSLee Nipper 				.cra_driver_name = "md5-talitos",
2836b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
28376a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
28389c4a7965SKim Phillips 			}
2839497f2e6bSLee Nipper 		},
2840497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2841497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2842497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
2843497f2e6bSLee Nipper 	},
2844497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2845497f2e6bSLee Nipper 		.alg.hash = {
2846497f2e6bSLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
28473639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2848497f2e6bSLee Nipper 			.halg.base = {
2849497f2e6bSLee Nipper 				.cra_name = "sha1",
2850497f2e6bSLee Nipper 				.cra_driver_name = "sha1-talitos",
2851497f2e6bSLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
28526a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2853497f2e6bSLee Nipper 			}
2854497f2e6bSLee Nipper 		},
2855497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2856497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2857497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
2858497f2e6bSLee Nipper 	},
2859497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2860497f2e6bSLee Nipper 		.alg.hash = {
286160f208d7SKim Phillips 			.halg.digestsize = SHA224_DIGEST_SIZE,
28623639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
286360f208d7SKim Phillips 			.halg.base = {
286460f208d7SKim Phillips 				.cra_name = "sha224",
286560f208d7SKim Phillips 				.cra_driver_name = "sha224-talitos",
286660f208d7SKim Phillips 				.cra_blocksize = SHA224_BLOCK_SIZE,
28676a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
286860f208d7SKim Phillips 			}
286960f208d7SKim Phillips 		},
287060f208d7SKim Phillips 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
287160f208d7SKim Phillips 				     DESC_HDR_SEL0_MDEUA |
287260f208d7SKim Phillips 				     DESC_HDR_MODE0_MDEU_SHA224,
287360f208d7SKim Phillips 	},
287460f208d7SKim Phillips 	{	.type = CRYPTO_ALG_TYPE_AHASH,
287560f208d7SKim Phillips 		.alg.hash = {
2876497f2e6bSLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
28773639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2878497f2e6bSLee Nipper 			.halg.base = {
2879497f2e6bSLee Nipper 				.cra_name = "sha256",
2880497f2e6bSLee Nipper 				.cra_driver_name = "sha256-talitos",
2881497f2e6bSLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
28826a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2883497f2e6bSLee Nipper 			}
2884497f2e6bSLee Nipper 		},
2885497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2886497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUA |
2887497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
2888497f2e6bSLee Nipper 	},
2889497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2890497f2e6bSLee Nipper 		.alg.hash = {
2891497f2e6bSLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
28923639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2893497f2e6bSLee Nipper 			.halg.base = {
2894497f2e6bSLee Nipper 				.cra_name = "sha384",
2895497f2e6bSLee Nipper 				.cra_driver_name = "sha384-talitos",
2896497f2e6bSLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
28976a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2898497f2e6bSLee Nipper 			}
2899497f2e6bSLee Nipper 		},
2900497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2901497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2902497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
2903497f2e6bSLee Nipper 	},
2904497f2e6bSLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
2905497f2e6bSLee Nipper 		.alg.hash = {
2906497f2e6bSLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
29073639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
2908497f2e6bSLee Nipper 			.halg.base = {
2909497f2e6bSLee Nipper 				.cra_name = "sha512",
2910497f2e6bSLee Nipper 				.cra_driver_name = "sha512-talitos",
2911497f2e6bSLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
29126a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
2913497f2e6bSLee Nipper 			}
2914497f2e6bSLee Nipper 		},
2915497f2e6bSLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
2916497f2e6bSLee Nipper 				     DESC_HDR_SEL0_MDEUB |
2917497f2e6bSLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
2918497f2e6bSLee Nipper 	},
291979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
292079b3a418SLee Nipper 		.alg.hash = {
292179b3a418SLee Nipper 			.halg.digestsize = MD5_DIGEST_SIZE,
29223639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
292379b3a418SLee Nipper 			.halg.base = {
292479b3a418SLee Nipper 				.cra_name = "hmac(md5)",
292579b3a418SLee Nipper 				.cra_driver_name = "hmac-md5-talitos",
2926b3988618SMartin Hicks 				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
29276a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
292879b3a418SLee Nipper 			}
292979b3a418SLee Nipper 		},
293079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
293179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
293279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_MD5,
293379b3a418SLee Nipper 	},
293479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
293579b3a418SLee Nipper 		.alg.hash = {
293679b3a418SLee Nipper 			.halg.digestsize = SHA1_DIGEST_SIZE,
29373639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
293879b3a418SLee Nipper 			.halg.base = {
293979b3a418SLee Nipper 				.cra_name = "hmac(sha1)",
294079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha1-talitos",
294179b3a418SLee Nipper 				.cra_blocksize = SHA1_BLOCK_SIZE,
29426a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
294379b3a418SLee Nipper 			}
294479b3a418SLee Nipper 		},
294579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
294679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
294779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA1,
294879b3a418SLee Nipper 	},
294979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
295079b3a418SLee Nipper 		.alg.hash = {
295179b3a418SLee Nipper 			.halg.digestsize = SHA224_DIGEST_SIZE,
29523639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
295379b3a418SLee Nipper 			.halg.base = {
295479b3a418SLee Nipper 				.cra_name = "hmac(sha224)",
295579b3a418SLee Nipper 				.cra_driver_name = "hmac-sha224-talitos",
295679b3a418SLee Nipper 				.cra_blocksize = SHA224_BLOCK_SIZE,
29576a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
295879b3a418SLee Nipper 			}
295979b3a418SLee Nipper 		},
296079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
296179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
296279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA224,
296379b3a418SLee Nipper 	},
296479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
296579b3a418SLee Nipper 		.alg.hash = {
296679b3a418SLee Nipper 			.halg.digestsize = SHA256_DIGEST_SIZE,
29673639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
296879b3a418SLee Nipper 			.halg.base = {
296979b3a418SLee Nipper 				.cra_name = "hmac(sha256)",
297079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha256-talitos",
297179b3a418SLee Nipper 				.cra_blocksize = SHA256_BLOCK_SIZE,
29726a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
297379b3a418SLee Nipper 			}
297479b3a418SLee Nipper 		},
297579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
297679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUA |
297779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEU_SHA256,
297879b3a418SLee Nipper 	},
297979b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
298079b3a418SLee Nipper 		.alg.hash = {
298179b3a418SLee Nipper 			.halg.digestsize = SHA384_DIGEST_SIZE,
29823639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
298379b3a418SLee Nipper 			.halg.base = {
298479b3a418SLee Nipper 				.cra_name = "hmac(sha384)",
298579b3a418SLee Nipper 				.cra_driver_name = "hmac-sha384-talitos",
298679b3a418SLee Nipper 				.cra_blocksize = SHA384_BLOCK_SIZE,
29876a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
298879b3a418SLee Nipper 			}
298979b3a418SLee Nipper 		},
299079b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
299179b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
299279b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA384,
299379b3a418SLee Nipper 	},
299479b3a418SLee Nipper 	{	.type = CRYPTO_ALG_TYPE_AHASH,
299579b3a418SLee Nipper 		.alg.hash = {
299679b3a418SLee Nipper 			.halg.digestsize = SHA512_DIGEST_SIZE,
29973639ca84SHoria Geant? 			.halg.statesize = sizeof(struct talitos_export_state),
299879b3a418SLee Nipper 			.halg.base = {
299979b3a418SLee Nipper 				.cra_name = "hmac(sha512)",
300079b3a418SLee Nipper 				.cra_driver_name = "hmac-sha512-talitos",
300179b3a418SLee Nipper 				.cra_blocksize = SHA512_BLOCK_SIZE,
30026a38f622SEric Biggers 				.cra_flags = CRYPTO_ALG_ASYNC,
300379b3a418SLee Nipper 			}
300479b3a418SLee Nipper 		},
300579b3a418SLee Nipper 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
300679b3a418SLee Nipper 				     DESC_HDR_SEL0_MDEUB |
300779b3a418SLee Nipper 				     DESC_HDR_MODE0_MDEUB_SHA512,
300879b3a418SLee Nipper 	}
30099c4a7965SKim Phillips };
30109c4a7965SKim Phillips 
30119c4a7965SKim Phillips struct talitos_crypto_alg {
30129c4a7965SKim Phillips 	struct list_head entry;
30139c4a7965SKim Phillips 	struct device *dev;
3014acbf7c62SLee Nipper 	struct talitos_alg_template algt;
30159c4a7965SKim Phillips };
30169c4a7965SKim Phillips 
301789d124cbSJonas Eymann static int talitos_init_common(struct talitos_ctx *ctx,
301889d124cbSJonas Eymann 			       struct talitos_crypto_alg *talitos_alg)
30199c4a7965SKim Phillips {
30205228f0f7SKim Phillips 	struct talitos_private *priv;
30219c4a7965SKim Phillips 
30229c4a7965SKim Phillips 	/* update context with ptr to dev */
30239c4a7965SKim Phillips 	ctx->dev = talitos_alg->dev;
302419bbbc63SKim Phillips 
30255228f0f7SKim Phillips 	/* assign SEC channel to tfm in round-robin fashion */
30265228f0f7SKim Phillips 	priv = dev_get_drvdata(ctx->dev);
30275228f0f7SKim Phillips 	ctx->ch = atomic_inc_return(&priv->last_chan) &
30285228f0f7SKim Phillips 		  (priv->num_channels - 1);
30295228f0f7SKim Phillips 
30309c4a7965SKim Phillips 	/* copy descriptor header template value */
3031acbf7c62SLee Nipper 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
30329c4a7965SKim Phillips 
3033602dba5aSKim Phillips 	/* select done notification */
3034602dba5aSKim Phillips 	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
3035602dba5aSKim Phillips 
3036497f2e6bSLee Nipper 	return 0;
3037497f2e6bSLee Nipper }
3038497f2e6bSLee Nipper 
303989d124cbSJonas Eymann static int talitos_cra_init(struct crypto_tfm *tfm)
304089d124cbSJonas Eymann {
304189d124cbSJonas Eymann 	struct crypto_alg *alg = tfm->__crt_alg;
304289d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
304389d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
304489d124cbSJonas Eymann 
304589d124cbSJonas Eymann 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
304689d124cbSJonas Eymann 		talitos_alg = container_of(__crypto_ahash_alg(alg),
304789d124cbSJonas Eymann 					   struct talitos_crypto_alg,
304889d124cbSJonas Eymann 					   algt.alg.hash);
304989d124cbSJonas Eymann 	else
305089d124cbSJonas Eymann 		talitos_alg = container_of(alg, struct talitos_crypto_alg,
305189d124cbSJonas Eymann 					   algt.alg.crypto);
305289d124cbSJonas Eymann 
305389d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
305489d124cbSJonas Eymann }
305589d124cbSJonas Eymann 
3056aeb4c132SHerbert Xu static int talitos_cra_init_aead(struct crypto_aead *tfm)
3057497f2e6bSLee Nipper {
305889d124cbSJonas Eymann 	struct aead_alg *alg = crypto_aead_alg(tfm);
305989d124cbSJonas Eymann 	struct talitos_crypto_alg *talitos_alg;
306089d124cbSJonas Eymann 	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
306189d124cbSJonas Eymann 
306289d124cbSJonas Eymann 	talitos_alg = container_of(alg, struct talitos_crypto_alg,
306389d124cbSJonas Eymann 				   algt.alg.aead);
306489d124cbSJonas Eymann 
306589d124cbSJonas Eymann 	return talitos_init_common(ctx, talitos_alg);
30669c4a7965SKim Phillips }
30679c4a7965SKim Phillips 
3068497f2e6bSLee Nipper static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
3069497f2e6bSLee Nipper {
3070497f2e6bSLee Nipper 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
3071497f2e6bSLee Nipper 
3072497f2e6bSLee Nipper 	talitos_cra_init(tfm);
3073497f2e6bSLee Nipper 
3074497f2e6bSLee Nipper 	ctx->keylen = 0;
3075497f2e6bSLee Nipper 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
3076497f2e6bSLee Nipper 				 sizeof(struct talitos_ahash_req_ctx));
3077497f2e6bSLee Nipper 
3078497f2e6bSLee Nipper 	return 0;
3079497f2e6bSLee Nipper }
3080497f2e6bSLee Nipper 
30812e13ce08SLEROY Christophe static void talitos_cra_exit(struct crypto_tfm *tfm)
30822e13ce08SLEROY Christophe {
30832e13ce08SLEROY Christophe 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
30842e13ce08SLEROY Christophe 	struct device *dev = ctx->dev;
30852e13ce08SLEROY Christophe 
30862e13ce08SLEROY Christophe 	if (ctx->keylen)
30872e13ce08SLEROY Christophe 		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
30882e13ce08SLEROY Christophe }
30892e13ce08SLEROY Christophe 
30909c4a7965SKim Phillips /*
30919c4a7965SKim Phillips  * given the alg's descriptor header template, determine whether descriptor
30929c4a7965SKim Phillips  * type and primary/secondary execution units required match the hw
30939c4a7965SKim Phillips  * capabilities description provided in the device tree node.
30949c4a7965SKim Phillips  */
30959c4a7965SKim Phillips static int hw_supports(struct device *dev, __be32 desc_hdr_template)
30969c4a7965SKim Phillips {
30979c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
30989c4a7965SKim Phillips 	int ret;
30999c4a7965SKim Phillips 
31009c4a7965SKim Phillips 	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
31019c4a7965SKim Phillips 	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
31029c4a7965SKim Phillips 
31039c4a7965SKim Phillips 	if (SECONDARY_EU(desc_hdr_template))
31049c4a7965SKim Phillips 		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
31059c4a7965SKim Phillips 		              & priv->exec_units);
31069c4a7965SKim Phillips 
31079c4a7965SKim Phillips 	return ret;
31089c4a7965SKim Phillips }
31099c4a7965SKim Phillips 
31102dc11581SGrant Likely static int talitos_remove(struct platform_device *ofdev)
31119c4a7965SKim Phillips {
31129c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
31139c4a7965SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31149c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg, *n;
31159c4a7965SKim Phillips 	int i;
31169c4a7965SKim Phillips 
31179c4a7965SKim Phillips 	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
3118acbf7c62SLee Nipper 		switch (t_alg->algt.type) {
3119acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_ABLKCIPHER:
3120acbf7c62SLee Nipper 			break;
3121aeb4c132SHerbert Xu 		case CRYPTO_ALG_TYPE_AEAD:
3122aeb4c132SHerbert Xu 			crypto_unregister_aead(&t_alg->algt.alg.aead);
31235fc194eaSGustavo A. R. Silva 			break;
3124acbf7c62SLee Nipper 		case CRYPTO_ALG_TYPE_AHASH:
3125acbf7c62SLee Nipper 			crypto_unregister_ahash(&t_alg->algt.alg.hash);
3126acbf7c62SLee Nipper 			break;
3127acbf7c62SLee Nipper 		}
31289c4a7965SKim Phillips 		list_del(&t_alg->entry);
31299c4a7965SKim Phillips 	}
31309c4a7965SKim Phillips 
31319c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
31329c4a7965SKim Phillips 		talitos_unregister_rng(dev);
31339c4a7965SKim Phillips 
3134c3e337f8SKim Phillips 	for (i = 0; i < 2; i++)
31352cdba3cfSKim Phillips 		if (priv->irq[i]) {
3136c3e337f8SKim Phillips 			free_irq(priv->irq[i], dev);
3137c3e337f8SKim Phillips 			irq_dispose_mapping(priv->irq[i]);
31389c4a7965SKim Phillips 		}
31399c4a7965SKim Phillips 
3140c3e337f8SKim Phillips 	tasklet_kill(&priv->done_task[0]);
31412cdba3cfSKim Phillips 	if (priv->irq[1])
3142c3e337f8SKim Phillips 		tasklet_kill(&priv->done_task[1]);
31439c4a7965SKim Phillips 
31449c4a7965SKim Phillips 	return 0;
31459c4a7965SKim Phillips }
31469c4a7965SKim Phillips 
31479c4a7965SKim Phillips static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
31489c4a7965SKim Phillips 						    struct talitos_alg_template
31499c4a7965SKim Phillips 						           *template)
31509c4a7965SKim Phillips {
315160f208d7SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
31529c4a7965SKim Phillips 	struct talitos_crypto_alg *t_alg;
31539c4a7965SKim Phillips 	struct crypto_alg *alg;
31549c4a7965SKim Phillips 
315524b92ff2SLEROY Christophe 	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
315624b92ff2SLEROY Christophe 			     GFP_KERNEL);
31579c4a7965SKim Phillips 	if (!t_alg)
31589c4a7965SKim Phillips 		return ERR_PTR(-ENOMEM);
31599c4a7965SKim Phillips 
3160acbf7c62SLee Nipper 	t_alg->algt = *template;
3161acbf7c62SLee Nipper 
3162acbf7c62SLee Nipper 	switch (t_alg->algt.type) {
3163acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
3164497f2e6bSLee Nipper 		alg = &t_alg->algt.alg.crypto;
3165497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init;
31662e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3167d4cd3283SKim Phillips 		alg->cra_type = &crypto_ablkcipher_type;
3168ef7c5c85SHerbert Xu 		alg->cra_ablkcipher.setkey = alg->cra_ablkcipher.setkey ?:
3169ef7c5c85SHerbert Xu 					     ablkcipher_setkey;
3170b286e003SKim Phillips 		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
3171b286e003SKim Phillips 		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
3172497f2e6bSLee Nipper 		break;
3173acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AEAD:
3174aeb4c132SHerbert Xu 		alg = &t_alg->algt.alg.aead.base;
31752e13ce08SLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3176aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
3177ef7c5c85SHerbert Xu 		t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?:
3178ef7c5c85SHerbert Xu 					      aead_setkey;
3179aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.encrypt = aead_encrypt;
3180aeb4c132SHerbert Xu 		t_alg->algt.alg.aead.decrypt = aead_decrypt;
31816cda075aSLEROY Christophe 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
31826cda075aSLEROY Christophe 		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
318324b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
31846cda075aSLEROY Christophe 			return ERR_PTR(-ENOTSUPP);
31856cda075aSLEROY Christophe 		}
3186acbf7c62SLee Nipper 		break;
3187acbf7c62SLee Nipper 	case CRYPTO_ALG_TYPE_AHASH:
3188acbf7c62SLee Nipper 		alg = &t_alg->algt.alg.hash.halg.base;
3189497f2e6bSLee Nipper 		alg->cra_init = talitos_cra_init_ahash;
3190ad4cd51fSLEROY Christophe 		alg->cra_exit = talitos_cra_exit;
3191b286e003SKim Phillips 		t_alg->algt.alg.hash.init = ahash_init;
3192b286e003SKim Phillips 		t_alg->algt.alg.hash.update = ahash_update;
3193b286e003SKim Phillips 		t_alg->algt.alg.hash.final = ahash_final;
3194b286e003SKim Phillips 		t_alg->algt.alg.hash.finup = ahash_finup;
3195b286e003SKim Phillips 		t_alg->algt.alg.hash.digest = ahash_digest;
319656136631SLEROY Christophe 		if (!strncmp(alg->cra_name, "hmac", 4))
3197b286e003SKim Phillips 			t_alg->algt.alg.hash.setkey = ahash_setkey;
31983639ca84SHoria Geant? 		t_alg->algt.alg.hash.import = ahash_import;
31993639ca84SHoria Geant? 		t_alg->algt.alg.hash.export = ahash_export;
3200b286e003SKim Phillips 
320179b3a418SLee Nipper 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
32020b2730d8SKim Phillips 		    !strncmp(alg->cra_name, "hmac", 4)) {
320324b92ff2SLEROY Christophe 			devm_kfree(dev, t_alg);
320479b3a418SLee Nipper 			return ERR_PTR(-ENOTSUPP);
32050b2730d8SKim Phillips 		}
320660f208d7SKim Phillips 		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
320779b3a418SLee Nipper 		    (!strcmp(alg->cra_name, "sha224") ||
320879b3a418SLee Nipper 		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
320960f208d7SKim Phillips 			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
321060f208d7SKim Phillips 			t_alg->algt.desc_hdr_template =
321160f208d7SKim Phillips 					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
321260f208d7SKim Phillips 					DESC_HDR_SEL0_MDEUA |
321360f208d7SKim Phillips 					DESC_HDR_MODE0_MDEU_SHA256;
321460f208d7SKim Phillips 		}
3215497f2e6bSLee Nipper 		break;
32161d11911aSKim Phillips 	default:
32171d11911aSKim Phillips 		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
321824b92ff2SLEROY Christophe 		devm_kfree(dev, t_alg);
32191d11911aSKim Phillips 		return ERR_PTR(-EINVAL);
3220acbf7c62SLee Nipper 	}
32219c4a7965SKim Phillips 
32229c4a7965SKim Phillips 	alg->cra_module = THIS_MODULE;
3223b0057763SLEROY Christophe 	if (t_alg->algt.priority)
3224b0057763SLEROY Christophe 		alg->cra_priority = t_alg->algt.priority;
3225b0057763SLEROY Christophe 	else
32269c4a7965SKim Phillips 		alg->cra_priority = TALITOS_CRA_PRIORITY;
3227c9cca703SChristophe Leroy 	if (has_ftr_sec1(priv))
3228c9cca703SChristophe Leroy 		alg->cra_alignmask = 3;
3229c9cca703SChristophe Leroy 	else
32309c4a7965SKim Phillips 		alg->cra_alignmask = 0;
32319c4a7965SKim Phillips 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
3232d912bb76SNikos Mavrogiannopoulos 	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
32339c4a7965SKim Phillips 
32349c4a7965SKim Phillips 	t_alg->dev = dev;
32359c4a7965SKim Phillips 
32369c4a7965SKim Phillips 	return t_alg;
32379c4a7965SKim Phillips }
32389c4a7965SKim Phillips 
3239c3e337f8SKim Phillips static int talitos_probe_irq(struct platform_device *ofdev)
3240c3e337f8SKim Phillips {
3241c3e337f8SKim Phillips 	struct device *dev = &ofdev->dev;
3242c3e337f8SKim Phillips 	struct device_node *np = ofdev->dev.of_node;
3243c3e337f8SKim Phillips 	struct talitos_private *priv = dev_get_drvdata(dev);
3244c3e337f8SKim Phillips 	int err;
3245dd3c0987SLEROY Christophe 	bool is_sec1 = has_ftr_sec1(priv);
3246c3e337f8SKim Phillips 
3247c3e337f8SKim Phillips 	priv->irq[0] = irq_of_parse_and_map(np, 0);
32482cdba3cfSKim Phillips 	if (!priv->irq[0]) {
3249c3e337f8SKim Phillips 		dev_err(dev, "failed to map irq\n");
3250c3e337f8SKim Phillips 		return -EINVAL;
3251c3e337f8SKim Phillips 	}
3252dd3c0987SLEROY Christophe 	if (is_sec1) {
3253dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
3254dd3c0987SLEROY Christophe 				  dev_driver_string(dev), dev);
3255dd3c0987SLEROY Christophe 		goto primary_out;
3256dd3c0987SLEROY Christophe 	}
3257c3e337f8SKim Phillips 
3258c3e337f8SKim Phillips 	priv->irq[1] = irq_of_parse_and_map(np, 1);
3259c3e337f8SKim Phillips 
3260c3e337f8SKim Phillips 	/* get the primary irq line */
32612cdba3cfSKim Phillips 	if (!priv->irq[1]) {
3262dd3c0987SLEROY Christophe 		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
3263c3e337f8SKim Phillips 				  dev_driver_string(dev), dev);
3264c3e337f8SKim Phillips 		goto primary_out;
3265c3e337f8SKim Phillips 	}
3266c3e337f8SKim Phillips 
3267dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
3268c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3269c3e337f8SKim Phillips 	if (err)
3270c3e337f8SKim Phillips 		goto primary_out;
3271c3e337f8SKim Phillips 
3272c3e337f8SKim Phillips 	/* get the secondary irq line */
3273dd3c0987SLEROY Christophe 	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
3274c3e337f8SKim Phillips 			  dev_driver_string(dev), dev);
3275c3e337f8SKim Phillips 	if (err) {
3276c3e337f8SKim Phillips 		dev_err(dev, "failed to request secondary irq\n");
3277c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[1]);
32782cdba3cfSKim Phillips 		priv->irq[1] = 0;
3279c3e337f8SKim Phillips 	}
3280c3e337f8SKim Phillips 
3281c3e337f8SKim Phillips 	return err;
3282c3e337f8SKim Phillips 
3283c3e337f8SKim Phillips primary_out:
3284c3e337f8SKim Phillips 	if (err) {
3285c3e337f8SKim Phillips 		dev_err(dev, "failed to request primary irq\n");
3286c3e337f8SKim Phillips 		irq_dispose_mapping(priv->irq[0]);
32872cdba3cfSKim Phillips 		priv->irq[0] = 0;
3288c3e337f8SKim Phillips 	}
3289c3e337f8SKim Phillips 
3290c3e337f8SKim Phillips 	return err;
3291c3e337f8SKim Phillips }
3292c3e337f8SKim Phillips 
32931c48a5c9SGrant Likely static int talitos_probe(struct platform_device *ofdev)
32949c4a7965SKim Phillips {
32959c4a7965SKim Phillips 	struct device *dev = &ofdev->dev;
329661c7a080SGrant Likely 	struct device_node *np = ofdev->dev.of_node;
32979c4a7965SKim Phillips 	struct talitos_private *priv;
32989c4a7965SKim Phillips 	int i, err;
32995fa7fa14SLEROY Christophe 	int stride;
3300fd5ea7f0SLEROY Christophe 	struct resource *res;
33019c4a7965SKim Phillips 
330224b92ff2SLEROY Christophe 	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
33039c4a7965SKim Phillips 	if (!priv)
33049c4a7965SKim Phillips 		return -ENOMEM;
33059c4a7965SKim Phillips 
3306f3de9cb1SKevin Hao 	INIT_LIST_HEAD(&priv->alg_list);
3307f3de9cb1SKevin Hao 
33089c4a7965SKim Phillips 	dev_set_drvdata(dev, priv);
33099c4a7965SKim Phillips 
33109c4a7965SKim Phillips 	priv->ofdev = ofdev;
33119c4a7965SKim Phillips 
3312511d63cbSHoria Geanta 	spin_lock_init(&priv->reg_lock);
3313511d63cbSHoria Geanta 
3314fd5ea7f0SLEROY Christophe 	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
3315fd5ea7f0SLEROY Christophe 	if (!res)
3316fd5ea7f0SLEROY Christophe 		return -ENXIO;
3317fd5ea7f0SLEROY Christophe 	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
33189c4a7965SKim Phillips 	if (!priv->reg) {
33199c4a7965SKim Phillips 		dev_err(dev, "failed to of_iomap\n");
33209c4a7965SKim Phillips 		err = -ENOMEM;
33219c4a7965SKim Phillips 		goto err_out;
33229c4a7965SKim Phillips 	}
33239c4a7965SKim Phillips 
33249c4a7965SKim Phillips 	/* get SEC version capabilities from device tree */
3325fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
3326fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
3327fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
3328fa14c6cfSLEROY Christophe 	of_property_read_u32(np, "fsl,descriptor-types-mask",
3329fa14c6cfSLEROY Christophe 			     &priv->desc_types);
33309c4a7965SKim Phillips 
33319c4a7965SKim Phillips 	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
33329c4a7965SKim Phillips 	    !priv->exec_units || !priv->desc_types) {
33339c4a7965SKim Phillips 		dev_err(dev, "invalid property data in device tree node\n");
33349c4a7965SKim Phillips 		err = -EINVAL;
33359c4a7965SKim Phillips 		goto err_out;
33369c4a7965SKim Phillips 	}
33379c4a7965SKim Phillips 
3338f3c85bc1SLee Nipper 	if (of_device_is_compatible(np, "fsl,sec3.0"))
3339f3c85bc1SLee Nipper 		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
3340f3c85bc1SLee Nipper 
3341fe5720e2SKim Phillips 	if (of_device_is_compatible(np, "fsl,sec2.1"))
334260f208d7SKim Phillips 		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
334379b3a418SLee Nipper 				  TALITOS_FTR_SHA224_HWINIT |
334479b3a418SLee Nipper 				  TALITOS_FTR_HMAC_OK;
3345fe5720e2SKim Phillips 
334621590888SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.0"))
334721590888SLEROY Christophe 		priv->features |= TALITOS_FTR_SEC1;
334821590888SLEROY Christophe 
33495fa7fa14SLEROY Christophe 	if (of_device_is_compatible(np, "fsl,sec1.2")) {
33505fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS12_DEU;
33515fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS12_AESU;
33525fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
33535fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
33545fa7fa14SLEROY Christophe 	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
33555fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS10_DEU;
33565fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS10_AESU;
33575fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
33585fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
33595fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
33605fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
33615fa7fa14SLEROY Christophe 		stride = TALITOS1_CH_STRIDE;
33625fa7fa14SLEROY Christophe 	} else {
33635fa7fa14SLEROY Christophe 		priv->reg_deu = priv->reg + TALITOS2_DEU;
33645fa7fa14SLEROY Christophe 		priv->reg_aesu = priv->reg + TALITOS2_AESU;
33655fa7fa14SLEROY Christophe 		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
33665fa7fa14SLEROY Christophe 		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
33675fa7fa14SLEROY Christophe 		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
33685fa7fa14SLEROY Christophe 		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
33695fa7fa14SLEROY Christophe 		priv->reg_keu = priv->reg + TALITOS2_KEU;
33705fa7fa14SLEROY Christophe 		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
33715fa7fa14SLEROY Christophe 		stride = TALITOS2_CH_STRIDE;
33725fa7fa14SLEROY Christophe 	}
33735fa7fa14SLEROY Christophe 
3374dd3c0987SLEROY Christophe 	err = talitos_probe_irq(ofdev);
3375dd3c0987SLEROY Christophe 	if (err)
3376dd3c0987SLEROY Christophe 		goto err_out;
3377dd3c0987SLEROY Christophe 
3378c8c74647SChristophe Leroy 	if (has_ftr_sec1(priv)) {
33799c02e285SLEROY Christophe 		if (priv->num_channels == 1)
33809c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
33819c02e285SLEROY Christophe 				     (unsigned long)dev);
33829c02e285SLEROY Christophe 		else
3383dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
3384dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3385dd3c0987SLEROY Christophe 	} else {
33869c02e285SLEROY Christophe 		if (priv->irq[1]) {
3387dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
3388dd3c0987SLEROY Christophe 				     (unsigned long)dev);
3389dd3c0987SLEROY Christophe 			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
3390dd3c0987SLEROY Christophe 				     (unsigned long)dev);
33919c02e285SLEROY Christophe 		} else if (priv->num_channels == 1) {
33929c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
33939c02e285SLEROY Christophe 				     (unsigned long)dev);
33949c02e285SLEROY Christophe 		} else {
33959c02e285SLEROY Christophe 			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
33969c02e285SLEROY Christophe 				     (unsigned long)dev);
3397dd3c0987SLEROY Christophe 		}
3398dd3c0987SLEROY Christophe 	}
3399dd3c0987SLEROY Christophe 
3400a86854d0SKees Cook 	priv->chan = devm_kcalloc(dev,
3401a86854d0SKees Cook 				  priv->num_channels,
3402a86854d0SKees Cook 				  sizeof(struct talitos_channel),
3403a86854d0SKees Cook 				  GFP_KERNEL);
34044b992628SKim Phillips 	if (!priv->chan) {
34054b992628SKim Phillips 		dev_err(dev, "failed to allocate channel management space\n");
34069c4a7965SKim Phillips 		err = -ENOMEM;
34079c4a7965SKim Phillips 		goto err_out;
34089c4a7965SKim Phillips 	}
34099c4a7965SKim Phillips 
3410f641ddddSMartin Hicks 	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
3411f641ddddSMartin Hicks 
3412c3e337f8SKim Phillips 	for (i = 0; i < priv->num_channels; i++) {
34135fa7fa14SLEROY Christophe 		priv->chan[i].reg = priv->reg + stride * (i + 1);
34142cdba3cfSKim Phillips 		if (!priv->irq[1] || !(i & 1))
3415c3e337f8SKim Phillips 			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
3416ad42d5fcSKim Phillips 
34174b992628SKim Phillips 		spin_lock_init(&priv->chan[i].head_lock);
34184b992628SKim Phillips 		spin_lock_init(&priv->chan[i].tail_lock);
34199c4a7965SKim Phillips 
3420a86854d0SKees Cook 		priv->chan[i].fifo = devm_kcalloc(dev,
3421a86854d0SKees Cook 						priv->fifo_len,
3422a86854d0SKees Cook 						sizeof(struct talitos_request),
3423a86854d0SKees Cook 						GFP_KERNEL);
34244b992628SKim Phillips 		if (!priv->chan[i].fifo) {
34259c4a7965SKim Phillips 			dev_err(dev, "failed to allocate request fifo %d\n", i);
34269c4a7965SKim Phillips 			err = -ENOMEM;
34279c4a7965SKim Phillips 			goto err_out;
34289c4a7965SKim Phillips 		}
34299c4a7965SKim Phillips 
34304b992628SKim Phillips 		atomic_set(&priv->chan[i].submit_count,
34314b992628SKim Phillips 			   -(priv->chfifo_len - 1));
3432f641ddddSMartin Hicks 	}
34339c4a7965SKim Phillips 
343481eb024cSKim Phillips 	dma_set_mask(dev, DMA_BIT_MASK(36));
343581eb024cSKim Phillips 
34369c4a7965SKim Phillips 	/* reset and initialize the h/w */
34379c4a7965SKim Phillips 	err = init_device(dev);
34389c4a7965SKim Phillips 	if (err) {
34399c4a7965SKim Phillips 		dev_err(dev, "failed to initialize device\n");
34409c4a7965SKim Phillips 		goto err_out;
34419c4a7965SKim Phillips 	}
34429c4a7965SKim Phillips 
34439c4a7965SKim Phillips 	/* register the RNG, if available */
34449c4a7965SKim Phillips 	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
34459c4a7965SKim Phillips 		err = talitos_register_rng(dev);
34469c4a7965SKim Phillips 		if (err) {
34479c4a7965SKim Phillips 			dev_err(dev, "failed to register hwrng: %d\n", err);
34489c4a7965SKim Phillips 			goto err_out;
34499c4a7965SKim Phillips 		} else
34509c4a7965SKim Phillips 			dev_info(dev, "hwrng\n");
34519c4a7965SKim Phillips 	}
34529c4a7965SKim Phillips 
34539c4a7965SKim Phillips 	/* register crypto algorithms the device supports */
34549c4a7965SKim Phillips 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
34559c4a7965SKim Phillips 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
34569c4a7965SKim Phillips 			struct talitos_crypto_alg *t_alg;
3457aeb4c132SHerbert Xu 			struct crypto_alg *alg = NULL;
34589c4a7965SKim Phillips 
34599c4a7965SKim Phillips 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
34609c4a7965SKim Phillips 			if (IS_ERR(t_alg)) {
34619c4a7965SKim Phillips 				err = PTR_ERR(t_alg);
34620b2730d8SKim Phillips 				if (err == -ENOTSUPP)
346379b3a418SLee Nipper 					continue;
34649c4a7965SKim Phillips 				goto err_out;
34659c4a7965SKim Phillips 			}
34669c4a7965SKim Phillips 
3467acbf7c62SLee Nipper 			switch (t_alg->algt.type) {
3468acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_ABLKCIPHER:
3469acbf7c62SLee Nipper 				err = crypto_register_alg(
3470acbf7c62SLee Nipper 						&t_alg->algt.alg.crypto);
3471aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.crypto;
3472acbf7c62SLee Nipper 				break;
3473aeb4c132SHerbert Xu 
3474aeb4c132SHerbert Xu 			case CRYPTO_ALG_TYPE_AEAD:
3475aeb4c132SHerbert Xu 				err = crypto_register_aead(
3476aeb4c132SHerbert Xu 					&t_alg->algt.alg.aead);
3477aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.aead.base;
3478aeb4c132SHerbert Xu 				break;
3479aeb4c132SHerbert Xu 
3480acbf7c62SLee Nipper 			case CRYPTO_ALG_TYPE_AHASH:
3481acbf7c62SLee Nipper 				err = crypto_register_ahash(
3482acbf7c62SLee Nipper 						&t_alg->algt.alg.hash);
3483aeb4c132SHerbert Xu 				alg = &t_alg->algt.alg.hash.halg.base;
3484acbf7c62SLee Nipper 				break;
3485acbf7c62SLee Nipper 			}
34869c4a7965SKim Phillips 			if (err) {
34879c4a7965SKim Phillips 				dev_err(dev, "%s alg registration failed\n",
3488aeb4c132SHerbert Xu 					alg->cra_driver_name);
348924b92ff2SLEROY Christophe 				devm_kfree(dev, t_alg);
3490991155baSHoria Geanta 			} else
34919c4a7965SKim Phillips 				list_add_tail(&t_alg->entry, &priv->alg_list);
34929c4a7965SKim Phillips 		}
34939c4a7965SKim Phillips 	}
34945b859b6eSKim Phillips 	if (!list_empty(&priv->alg_list))
34955b859b6eSKim Phillips 		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
34965b859b6eSKim Phillips 			 (char *)of_get_property(np, "compatible", NULL));
34979c4a7965SKim Phillips 
34989c4a7965SKim Phillips 	return 0;
34999c4a7965SKim Phillips 
35009c4a7965SKim Phillips err_out:
35019c4a7965SKim Phillips 	talitos_remove(ofdev);
35029c4a7965SKim Phillips 
35039c4a7965SKim Phillips 	return err;
35049c4a7965SKim Phillips }
35059c4a7965SKim Phillips 
35066c3f975aSMárton Németh static const struct of_device_id talitos_match[] = {
35070635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS1
35080635b7dbSLEROY Christophe 	{
35090635b7dbSLEROY Christophe 		.compatible = "fsl,sec1.0",
35100635b7dbSLEROY Christophe 	},
35110635b7dbSLEROY Christophe #endif
35120635b7dbSLEROY Christophe #ifdef CONFIG_CRYPTO_DEV_TALITOS2
35139c4a7965SKim Phillips 	{
35149c4a7965SKim Phillips 		.compatible = "fsl,sec2.0",
35159c4a7965SKim Phillips 	},
35160635b7dbSLEROY Christophe #endif
35179c4a7965SKim Phillips 	{},
35189c4a7965SKim Phillips };
35199c4a7965SKim Phillips MODULE_DEVICE_TABLE(of, talitos_match);
35209c4a7965SKim Phillips 
35211c48a5c9SGrant Likely static struct platform_driver talitos_driver = {
35224018294bSGrant Likely 	.driver = {
35239c4a7965SKim Phillips 		.name = "talitos",
35244018294bSGrant Likely 		.of_match_table = talitos_match,
35254018294bSGrant Likely 	},
35269c4a7965SKim Phillips 	.probe = talitos_probe,
3527596f1034SAl Viro 	.remove = talitos_remove,
35289c4a7965SKim Phillips };
35299c4a7965SKim Phillips 
3530741e8c2dSAxel Lin module_platform_driver(talitos_driver);
35319c4a7965SKim Phillips 
35329c4a7965SKim Phillips MODULE_LICENSE("GPL");
35339c4a7965SKim Phillips MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
35349c4a7965SKim Phillips MODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3535