162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * talitos - Freescale Integrated Security Engine (SEC) device driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Scatterlist Crypto API glue code copied from files with the following:
862306a36Sopenharmony_ci * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Crypto algorithm registration code copied from hifn driver:
1162306a36Sopenharmony_ci * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1262306a36Sopenharmony_ci * All rights reserved.
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/kernel.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
1862306a36Sopenharmony_ci#include <linux/device.h>
1962306a36Sopenharmony_ci#include <linux/interrupt.h>
2062306a36Sopenharmony_ci#include <linux/crypto.h>
2162306a36Sopenharmony_ci#include <linux/hw_random.h>
2262306a36Sopenharmony_ci#include <linux/of.h>
2362306a36Sopenharmony_ci#include <linux/of_irq.h>
2462306a36Sopenharmony_ci#include <linux/platform_device.h>
2562306a36Sopenharmony_ci#include <linux/dma-mapping.h>
2662306a36Sopenharmony_ci#include <linux/io.h>
2762306a36Sopenharmony_ci#include <linux/spinlock.h>
2862306a36Sopenharmony_ci#include <linux/rtnetlink.h>
2962306a36Sopenharmony_ci#include <linux/slab.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include <crypto/algapi.h>
3262306a36Sopenharmony_ci#include <crypto/aes.h>
3362306a36Sopenharmony_ci#include <crypto/internal/des.h>
3462306a36Sopenharmony_ci#include <crypto/sha1.h>
3562306a36Sopenharmony_ci#include <crypto/sha2.h>
3662306a36Sopenharmony_ci#include <crypto/md5.h>
3762306a36Sopenharmony_ci#include <crypto/internal/aead.h>
3862306a36Sopenharmony_ci#include <crypto/authenc.h>
3962306a36Sopenharmony_ci#include <crypto/internal/skcipher.h>
4062306a36Sopenharmony_ci#include <crypto/hash.h>
4162306a36Sopenharmony_ci#include <crypto/internal/hash.h>
4262306a36Sopenharmony_ci#include <crypto/scatterwalk.h>
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#include "talitos.h"
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
4762306a36Sopenharmony_ci			   unsigned int len, bool is_sec1)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
5062306a36Sopenharmony_ci	if (is_sec1) {
5162306a36Sopenharmony_ci		ptr->len1 = cpu_to_be16(len);
5262306a36Sopenharmony_ci	} else {
5362306a36Sopenharmony_ci		ptr->len = cpu_to_be16(len);
5462306a36Sopenharmony_ci		ptr->eptr = upper_32_bits(dma_addr);
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
5962306a36Sopenharmony_ci			     struct talitos_ptr *src_ptr, bool is_sec1)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	dst_ptr->ptr = src_ptr->ptr;
6262306a36Sopenharmony_ci	if (is_sec1) {
6362306a36Sopenharmony_ci		dst_ptr->len1 = src_ptr->len1;
6462306a36Sopenharmony_ci	} else {
6562306a36Sopenharmony_ci		dst_ptr->len = src_ptr->len;
6662306a36Sopenharmony_ci		dst_ptr->eptr = src_ptr->eptr;
6762306a36Sopenharmony_ci	}
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
7162306a36Sopenharmony_ci					   bool is_sec1)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	if (is_sec1)
7462306a36Sopenharmony_ci		return be16_to_cpu(ptr->len1);
7562306a36Sopenharmony_ci	else
7662306a36Sopenharmony_ci		return be16_to_cpu(ptr->len);
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
8062306a36Sopenharmony_ci				   bool is_sec1)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	if (!is_sec1)
8362306a36Sopenharmony_ci		ptr->j_extent = val;
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	if (!is_sec1)
8962306a36Sopenharmony_ci		ptr->j_extent |= val;
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/*
9362306a36Sopenharmony_ci * map virtual single (contiguous) pointer to h/w descriptor pointer
9462306a36Sopenharmony_ci */
9562306a36Sopenharmony_cistatic void __map_single_talitos_ptr(struct device *dev,
9662306a36Sopenharmony_ci				     struct talitos_ptr *ptr,
9762306a36Sopenharmony_ci				     unsigned int len, void *data,
9862306a36Sopenharmony_ci				     enum dma_data_direction dir,
9962306a36Sopenharmony_ci				     unsigned long attrs)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs);
10262306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
10362306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	to_talitos_ptr(ptr, dma_addr, len, is_sec1);
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistatic void map_single_talitos_ptr(struct device *dev,
10962306a36Sopenharmony_ci				   struct talitos_ptr *ptr,
11062306a36Sopenharmony_ci				   unsigned int len, void *data,
11162306a36Sopenharmony_ci				   enum dma_data_direction dir)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	__map_single_talitos_ptr(dev, ptr, len, data, dir, 0);
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic void map_single_talitos_ptr_nosync(struct device *dev,
11762306a36Sopenharmony_ci					  struct talitos_ptr *ptr,
11862306a36Sopenharmony_ci					  unsigned int len, void *data,
11962306a36Sopenharmony_ci					  enum dma_data_direction dir)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	__map_single_talitos_ptr(dev, ptr, len, data, dir,
12262306a36Sopenharmony_ci				 DMA_ATTR_SKIP_CPU_SYNC);
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci/*
12662306a36Sopenharmony_ci * unmap bus single (contiguous) h/w descriptor pointer
12762306a36Sopenharmony_ci */
12862306a36Sopenharmony_cistatic void unmap_single_talitos_ptr(struct device *dev,
12962306a36Sopenharmony_ci				     struct talitos_ptr *ptr,
13062306a36Sopenharmony_ci				     enum dma_data_direction dir)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
13362306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
13662306a36Sopenharmony_ci			 from_talitos_ptr_len(ptr, is_sec1), dir);
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic int reset_channel(struct device *dev, int ch)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
14262306a36Sopenharmony_ci	unsigned int timeout = TALITOS_TIMEOUT;
14362306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	if (is_sec1) {
14662306a36Sopenharmony_ci		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
14762306a36Sopenharmony_ci			  TALITOS1_CCCR_LO_RESET);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
15062306a36Sopenharmony_ci			TALITOS1_CCCR_LO_RESET) && --timeout)
15162306a36Sopenharmony_ci			cpu_relax();
15262306a36Sopenharmony_ci	} else {
15362306a36Sopenharmony_ci		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
15462306a36Sopenharmony_ci			  TALITOS2_CCCR_RESET);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
15762306a36Sopenharmony_ci			TALITOS2_CCCR_RESET) && --timeout)
15862306a36Sopenharmony_ci			cpu_relax();
15962306a36Sopenharmony_ci	}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	if (timeout == 0) {
16262306a36Sopenharmony_ci		dev_err(dev, "failed to reset channel %d\n", ch);
16362306a36Sopenharmony_ci		return -EIO;
16462306a36Sopenharmony_ci	}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	/* set 36-bit addressing, done writeback enable and done IRQ enable */
16762306a36Sopenharmony_ci	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
16862306a36Sopenharmony_ci		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
16962306a36Sopenharmony_ci	/* enable chaining descriptors */
17062306a36Sopenharmony_ci	if (is_sec1)
17162306a36Sopenharmony_ci		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
17262306a36Sopenharmony_ci			  TALITOS_CCCR_LO_NE);
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	/* and ICCR writeback, if available */
17562306a36Sopenharmony_ci	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
17662306a36Sopenharmony_ci		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
17762306a36Sopenharmony_ci		          TALITOS_CCCR_LO_IWSE);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	return 0;
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic int reset_device(struct device *dev)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
18562306a36Sopenharmony_ci	unsigned int timeout = TALITOS_TIMEOUT;
18662306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
18762306a36Sopenharmony_ci	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	setbits32(priv->reg + TALITOS_MCR, mcr);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
19262306a36Sopenharmony_ci	       && --timeout)
19362306a36Sopenharmony_ci		cpu_relax();
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	if (priv->irq[1]) {
19662306a36Sopenharmony_ci		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
19762306a36Sopenharmony_ci		setbits32(priv->reg + TALITOS_MCR, mcr);
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	if (timeout == 0) {
20162306a36Sopenharmony_ci		dev_err(dev, "failed to reset device\n");
20262306a36Sopenharmony_ci		return -EIO;
20362306a36Sopenharmony_ci	}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	return 0;
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci/*
20962306a36Sopenharmony_ci * Reset and initialize the device
21062306a36Sopenharmony_ci */
21162306a36Sopenharmony_cistatic int init_device(struct device *dev)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
21462306a36Sopenharmony_ci	int ch, err;
21562306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	/*
21862306a36Sopenharmony_ci	 * Master reset
21962306a36Sopenharmony_ci	 * errata documentation: warning: certain SEC interrupts
22062306a36Sopenharmony_ci	 * are not fully cleared by writing the MCR:SWR bit,
22162306a36Sopenharmony_ci	 * set bit twice to completely reset
22262306a36Sopenharmony_ci	 */
22362306a36Sopenharmony_ci	err = reset_device(dev);
22462306a36Sopenharmony_ci	if (err)
22562306a36Sopenharmony_ci		return err;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	err = reset_device(dev);
22862306a36Sopenharmony_ci	if (err)
22962306a36Sopenharmony_ci		return err;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	/* reset channels */
23262306a36Sopenharmony_ci	for (ch = 0; ch < priv->num_channels; ch++) {
23362306a36Sopenharmony_ci		err = reset_channel(dev, ch);
23462306a36Sopenharmony_ci		if (err)
23562306a36Sopenharmony_ci			return err;
23662306a36Sopenharmony_ci	}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	/* enable channel done and error interrupts */
23962306a36Sopenharmony_ci	if (is_sec1) {
24062306a36Sopenharmony_ci		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
24162306a36Sopenharmony_ci		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
24262306a36Sopenharmony_ci		/* disable parity error check in DEU (erroneous? test vect.) */
24362306a36Sopenharmony_ci		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
24462306a36Sopenharmony_ci	} else {
24562306a36Sopenharmony_ci		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
24662306a36Sopenharmony_ci		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	/* disable integrity check error interrupts (use writeback instead) */
25062306a36Sopenharmony_ci	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
25162306a36Sopenharmony_ci		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
25262306a36Sopenharmony_ci		          TALITOS_MDEUICR_LO_ICE);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	return 0;
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci/**
25862306a36Sopenharmony_ci * talitos_submit - submits a descriptor to the device for processing
25962306a36Sopenharmony_ci * @dev:	the SEC device to be used
26062306a36Sopenharmony_ci * @ch:		the SEC device channel to be used
26162306a36Sopenharmony_ci * @desc:	the descriptor to be processed by the device
26262306a36Sopenharmony_ci * @callback:	whom to call when processing is complete
26362306a36Sopenharmony_ci * @context:	a handle for use by caller (optional)
26462306a36Sopenharmony_ci *
26562306a36Sopenharmony_ci * desc must contain valid dma-mapped (bus physical) address pointers.
26662306a36Sopenharmony_ci * callback must check err and feedback in descriptor header
26762306a36Sopenharmony_ci * for device processing status.
26862306a36Sopenharmony_ci */
26962306a36Sopenharmony_cistatic int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
27062306a36Sopenharmony_ci			  void (*callback)(struct device *dev,
27162306a36Sopenharmony_ci					   struct talitos_desc *desc,
27262306a36Sopenharmony_ci					   void *context, int error),
27362306a36Sopenharmony_ci			  void *context)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
27662306a36Sopenharmony_ci	struct talitos_request *request;
27762306a36Sopenharmony_ci	unsigned long flags;
27862306a36Sopenharmony_ci	int head;
27962306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
28462306a36Sopenharmony_ci		/* h/w fifo is full */
28562306a36Sopenharmony_ci		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
28662306a36Sopenharmony_ci		return -EAGAIN;
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	head = priv->chan[ch].head;
29062306a36Sopenharmony_ci	request = &priv->chan[ch].fifo[head];
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	/* map descriptor and save caller data */
29362306a36Sopenharmony_ci	if (is_sec1) {
29462306a36Sopenharmony_ci		desc->hdr1 = desc->hdr;
29562306a36Sopenharmony_ci		request->dma_desc = dma_map_single(dev, &desc->hdr1,
29662306a36Sopenharmony_ci						   TALITOS_DESC_SIZE,
29762306a36Sopenharmony_ci						   DMA_BIDIRECTIONAL);
29862306a36Sopenharmony_ci	} else {
29962306a36Sopenharmony_ci		request->dma_desc = dma_map_single(dev, desc,
30062306a36Sopenharmony_ci						   TALITOS_DESC_SIZE,
30162306a36Sopenharmony_ci						   DMA_BIDIRECTIONAL);
30262306a36Sopenharmony_ci	}
30362306a36Sopenharmony_ci	request->callback = callback;
30462306a36Sopenharmony_ci	request->context = context;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	/* increment fifo head */
30762306a36Sopenharmony_ci	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	smp_wmb();
31062306a36Sopenharmony_ci	request->desc = desc;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	/* GO! */
31362306a36Sopenharmony_ci	wmb();
31462306a36Sopenharmony_ci	out_be32(priv->chan[ch].reg + TALITOS_FF,
31562306a36Sopenharmony_ci		 upper_32_bits(request->dma_desc));
31662306a36Sopenharmony_ci	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
31762306a36Sopenharmony_ci		 lower_32_bits(request->dma_desc));
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	return -EINPROGRESS;
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cistatic __be32 get_request_hdr(struct talitos_request *request, bool is_sec1)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	struct talitos_edesc *edesc;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	if (!is_sec1)
32962306a36Sopenharmony_ci		return request->desc->hdr;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	if (!request->desc->next_desc)
33262306a36Sopenharmony_ci		return request->desc->hdr1;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	edesc = container_of(request->desc, struct talitos_edesc, desc);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1;
33762306a36Sopenharmony_ci}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci/*
34062306a36Sopenharmony_ci * process what was done, notify callback of error if not
34162306a36Sopenharmony_ci */
34262306a36Sopenharmony_cistatic void flush_channel(struct device *dev, int ch, int error, int reset_ch)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
34562306a36Sopenharmony_ci	struct talitos_request *request, saved_req;
34662306a36Sopenharmony_ci	unsigned long flags;
34762306a36Sopenharmony_ci	int tail, status;
34862306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	tail = priv->chan[ch].tail;
35362306a36Sopenharmony_ci	while (priv->chan[ch].fifo[tail].desc) {
35462306a36Sopenharmony_ci		__be32 hdr;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci		request = &priv->chan[ch].fifo[tail];
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci		/* descriptors with their done bits set don't get the error */
35962306a36Sopenharmony_ci		rmb();
36062306a36Sopenharmony_ci		hdr = get_request_hdr(request, is_sec1);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
36362306a36Sopenharmony_ci			status = 0;
36462306a36Sopenharmony_ci		else
36562306a36Sopenharmony_ci			if (!error)
36662306a36Sopenharmony_ci				break;
36762306a36Sopenharmony_ci			else
36862306a36Sopenharmony_ci				status = error;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci		dma_unmap_single(dev, request->dma_desc,
37162306a36Sopenharmony_ci				 TALITOS_DESC_SIZE,
37262306a36Sopenharmony_ci				 DMA_BIDIRECTIONAL);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci		/* copy entries so we can call callback outside lock */
37562306a36Sopenharmony_ci		saved_req.desc = request->desc;
37662306a36Sopenharmony_ci		saved_req.callback = request->callback;
37762306a36Sopenharmony_ci		saved_req.context = request->context;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci		/* release request entry in fifo */
38062306a36Sopenharmony_ci		smp_wmb();
38162306a36Sopenharmony_ci		request->desc = NULL;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci		/* increment fifo tail */
38462306a36Sopenharmony_ci		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci		atomic_dec(&priv->chan[ch].submit_count);
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci		saved_req.callback(dev, saved_req.desc, saved_req.context,
39162306a36Sopenharmony_ci				   status);
39262306a36Sopenharmony_ci		/* channel may resume processing in single desc error case */
39362306a36Sopenharmony_ci		if (error && !reset_ch && status == error)
39462306a36Sopenharmony_ci			return;
39562306a36Sopenharmony_ci		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
39662306a36Sopenharmony_ci		tail = priv->chan[ch].tail;
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
40062306a36Sopenharmony_ci}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci/*
40362306a36Sopenharmony_ci * process completed requests for channels that have done status
40462306a36Sopenharmony_ci */
40562306a36Sopenharmony_ci#define DEF_TALITOS1_DONE(name, ch_done_mask)				\
40662306a36Sopenharmony_cistatic void talitos1_done_##name(unsigned long data)			\
40762306a36Sopenharmony_ci{									\
40862306a36Sopenharmony_ci	struct device *dev = (struct device *)data;			\
40962306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);		\
41062306a36Sopenharmony_ci	unsigned long flags;						\
41162306a36Sopenharmony_ci									\
41262306a36Sopenharmony_ci	if (ch_done_mask & 0x10000000)					\
41362306a36Sopenharmony_ci		flush_channel(dev, 0, 0, 0);			\
41462306a36Sopenharmony_ci	if (ch_done_mask & 0x40000000)					\
41562306a36Sopenharmony_ci		flush_channel(dev, 1, 0, 0);			\
41662306a36Sopenharmony_ci	if (ch_done_mask & 0x00010000)					\
41762306a36Sopenharmony_ci		flush_channel(dev, 2, 0, 0);			\
41862306a36Sopenharmony_ci	if (ch_done_mask & 0x00040000)					\
41962306a36Sopenharmony_ci		flush_channel(dev, 3, 0, 0);			\
42062306a36Sopenharmony_ci									\
42162306a36Sopenharmony_ci	/* At this point, all completed channels have been processed */	\
42262306a36Sopenharmony_ci	/* Unmask done interrupts for channels completed later on. */	\
42362306a36Sopenharmony_ci	spin_lock_irqsave(&priv->reg_lock, flags);			\
42462306a36Sopenharmony_ci	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
42562306a36Sopenharmony_ci	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
42662306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
42762306a36Sopenharmony_ci}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ciDEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
43062306a36Sopenharmony_ciDEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci#define DEF_TALITOS2_DONE(name, ch_done_mask)				\
43362306a36Sopenharmony_cistatic void talitos2_done_##name(unsigned long data)			\
43462306a36Sopenharmony_ci{									\
43562306a36Sopenharmony_ci	struct device *dev = (struct device *)data;			\
43662306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);		\
43762306a36Sopenharmony_ci	unsigned long flags;						\
43862306a36Sopenharmony_ci									\
43962306a36Sopenharmony_ci	if (ch_done_mask & 1)						\
44062306a36Sopenharmony_ci		flush_channel(dev, 0, 0, 0);				\
44162306a36Sopenharmony_ci	if (ch_done_mask & (1 << 2))					\
44262306a36Sopenharmony_ci		flush_channel(dev, 1, 0, 0);				\
44362306a36Sopenharmony_ci	if (ch_done_mask & (1 << 4))					\
44462306a36Sopenharmony_ci		flush_channel(dev, 2, 0, 0);				\
44562306a36Sopenharmony_ci	if (ch_done_mask & (1 << 6))					\
44662306a36Sopenharmony_ci		flush_channel(dev, 3, 0, 0);				\
44762306a36Sopenharmony_ci									\
44862306a36Sopenharmony_ci	/* At this point, all completed channels have been processed */	\
44962306a36Sopenharmony_ci	/* Unmask done interrupts for channels completed later on. */	\
45062306a36Sopenharmony_ci	spin_lock_irqsave(&priv->reg_lock, flags);			\
45162306a36Sopenharmony_ci	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
45262306a36Sopenharmony_ci	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
45362306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
45462306a36Sopenharmony_ci}
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ciDEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
45762306a36Sopenharmony_ciDEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
45862306a36Sopenharmony_ciDEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
45962306a36Sopenharmony_ciDEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci/*
46262306a36Sopenharmony_ci * locate current (offending) descriptor
46362306a36Sopenharmony_ci */
46462306a36Sopenharmony_cistatic __be32 current_desc_hdr(struct device *dev, int ch)
46562306a36Sopenharmony_ci{
46662306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
46762306a36Sopenharmony_ci	int tail, iter;
46862306a36Sopenharmony_ci	dma_addr_t cur_desc;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
47162306a36Sopenharmony_ci	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	if (!cur_desc) {
47462306a36Sopenharmony_ci		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
47562306a36Sopenharmony_ci		return 0;
47662306a36Sopenharmony_ci	}
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	tail = priv->chan[ch].tail;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	iter = tail;
48162306a36Sopenharmony_ci	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc &&
48262306a36Sopenharmony_ci	       priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) {
48362306a36Sopenharmony_ci		iter = (iter + 1) & (priv->fifo_len - 1);
48462306a36Sopenharmony_ci		if (iter == tail) {
48562306a36Sopenharmony_ci			dev_err(dev, "couldn't locate current descriptor\n");
48662306a36Sopenharmony_ci			return 0;
48762306a36Sopenharmony_ci		}
48862306a36Sopenharmony_ci	}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) {
49162306a36Sopenharmony_ci		struct talitos_edesc *edesc;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci		edesc = container_of(priv->chan[ch].fifo[iter].desc,
49462306a36Sopenharmony_ci				     struct talitos_edesc, desc);
49562306a36Sopenharmony_ci		return ((struct talitos_desc *)
49662306a36Sopenharmony_ci			(edesc->buf + edesc->dma_len))->hdr;
49762306a36Sopenharmony_ci	}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	return priv->chan[ch].fifo[iter].desc->hdr;
50062306a36Sopenharmony_ci}
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci/*
50362306a36Sopenharmony_ci * user diagnostics; report root cause of error based on execution unit status
50462306a36Sopenharmony_ci */
50562306a36Sopenharmony_cistatic void report_eu_error(struct device *dev, int ch, __be32 desc_hdr)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
50862306a36Sopenharmony_ci	int i;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	if (!desc_hdr)
51162306a36Sopenharmony_ci		desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF));
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
51462306a36Sopenharmony_ci	case DESC_HDR_SEL0_AFEU:
51562306a36Sopenharmony_ci		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
51662306a36Sopenharmony_ci			in_be32(priv->reg_afeu + TALITOS_EUISR),
51762306a36Sopenharmony_ci			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
51862306a36Sopenharmony_ci		break;
51962306a36Sopenharmony_ci	case DESC_HDR_SEL0_DEU:
52062306a36Sopenharmony_ci		dev_err(dev, "DEUISR 0x%08x_%08x\n",
52162306a36Sopenharmony_ci			in_be32(priv->reg_deu + TALITOS_EUISR),
52262306a36Sopenharmony_ci			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
52362306a36Sopenharmony_ci		break;
52462306a36Sopenharmony_ci	case DESC_HDR_SEL0_MDEUA:
52562306a36Sopenharmony_ci	case DESC_HDR_SEL0_MDEUB:
52662306a36Sopenharmony_ci		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
52762306a36Sopenharmony_ci			in_be32(priv->reg_mdeu + TALITOS_EUISR),
52862306a36Sopenharmony_ci			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
52962306a36Sopenharmony_ci		break;
53062306a36Sopenharmony_ci	case DESC_HDR_SEL0_RNG:
53162306a36Sopenharmony_ci		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
53262306a36Sopenharmony_ci			in_be32(priv->reg_rngu + TALITOS_ISR),
53362306a36Sopenharmony_ci			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
53462306a36Sopenharmony_ci		break;
53562306a36Sopenharmony_ci	case DESC_HDR_SEL0_PKEU:
53662306a36Sopenharmony_ci		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
53762306a36Sopenharmony_ci			in_be32(priv->reg_pkeu + TALITOS_EUISR),
53862306a36Sopenharmony_ci			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
53962306a36Sopenharmony_ci		break;
54062306a36Sopenharmony_ci	case DESC_HDR_SEL0_AESU:
54162306a36Sopenharmony_ci		dev_err(dev, "AESUISR 0x%08x_%08x\n",
54262306a36Sopenharmony_ci			in_be32(priv->reg_aesu + TALITOS_EUISR),
54362306a36Sopenharmony_ci			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
54462306a36Sopenharmony_ci		break;
54562306a36Sopenharmony_ci	case DESC_HDR_SEL0_CRCU:
54662306a36Sopenharmony_ci		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
54762306a36Sopenharmony_ci			in_be32(priv->reg_crcu + TALITOS_EUISR),
54862306a36Sopenharmony_ci			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
54962306a36Sopenharmony_ci		break;
55062306a36Sopenharmony_ci	case DESC_HDR_SEL0_KEU:
55162306a36Sopenharmony_ci		dev_err(dev, "KEUISR 0x%08x_%08x\n",
55262306a36Sopenharmony_ci			in_be32(priv->reg_pkeu + TALITOS_EUISR),
55362306a36Sopenharmony_ci			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
55462306a36Sopenharmony_ci		break;
55562306a36Sopenharmony_ci	}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
55862306a36Sopenharmony_ci	case DESC_HDR_SEL1_MDEUA:
55962306a36Sopenharmony_ci	case DESC_HDR_SEL1_MDEUB:
56062306a36Sopenharmony_ci		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
56162306a36Sopenharmony_ci			in_be32(priv->reg_mdeu + TALITOS_EUISR),
56262306a36Sopenharmony_ci			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
56362306a36Sopenharmony_ci		break;
56462306a36Sopenharmony_ci	case DESC_HDR_SEL1_CRCU:
56562306a36Sopenharmony_ci		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
56662306a36Sopenharmony_ci			in_be32(priv->reg_crcu + TALITOS_EUISR),
56762306a36Sopenharmony_ci			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
56862306a36Sopenharmony_ci		break;
56962306a36Sopenharmony_ci	}
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	for (i = 0; i < 8; i++)
57262306a36Sopenharmony_ci		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
57362306a36Sopenharmony_ci			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
57462306a36Sopenharmony_ci			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci/*
57862306a36Sopenharmony_ci * recover from error interrupts
57962306a36Sopenharmony_ci */
58062306a36Sopenharmony_cistatic void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
58162306a36Sopenharmony_ci{
58262306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
58362306a36Sopenharmony_ci	unsigned int timeout = TALITOS_TIMEOUT;
58462306a36Sopenharmony_ci	int ch, error, reset_dev = 0;
58562306a36Sopenharmony_ci	u32 v_lo;
58662306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
58762306a36Sopenharmony_ci	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	for (ch = 0; ch < priv->num_channels; ch++) {
59062306a36Sopenharmony_ci		/* skip channels without errors */
59162306a36Sopenharmony_ci		if (is_sec1) {
59262306a36Sopenharmony_ci			/* bits 29, 31, 17, 19 */
59362306a36Sopenharmony_ci			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
59462306a36Sopenharmony_ci				continue;
59562306a36Sopenharmony_ci		} else {
59662306a36Sopenharmony_ci			if (!(isr & (1 << (ch * 2 + 1))))
59762306a36Sopenharmony_ci				continue;
59862306a36Sopenharmony_ci		}
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci		error = -EINVAL;
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_DOF) {
60562306a36Sopenharmony_ci			dev_err(dev, "double fetch fifo overflow error\n");
60662306a36Sopenharmony_ci			error = -EAGAIN;
60762306a36Sopenharmony_ci			reset_ch = 1;
60862306a36Sopenharmony_ci		}
60962306a36Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_SOF) {
61062306a36Sopenharmony_ci			/* h/w dropped descriptor */
61162306a36Sopenharmony_ci			dev_err(dev, "single fetch fifo overflow error\n");
61262306a36Sopenharmony_ci			error = -EAGAIN;
61362306a36Sopenharmony_ci		}
61462306a36Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_MDTE)
61562306a36Sopenharmony_ci			dev_err(dev, "master data transfer error\n");
61662306a36Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
61762306a36Sopenharmony_ci			dev_err(dev, is_sec1 ? "pointer not complete error\n"
61862306a36Sopenharmony_ci					     : "s/g data length zero error\n");
61962306a36Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_FPZ)
62062306a36Sopenharmony_ci			dev_err(dev, is_sec1 ? "parity error\n"
62162306a36Sopenharmony_ci					     : "fetch pointer zero error\n");
62262306a36Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_IDH)
62362306a36Sopenharmony_ci			dev_err(dev, "illegal descriptor header error\n");
62462306a36Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_IEU)
62562306a36Sopenharmony_ci			dev_err(dev, is_sec1 ? "static assignment error\n"
62662306a36Sopenharmony_ci					     : "invalid exec unit error\n");
62762306a36Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_EU)
62862306a36Sopenharmony_ci			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
62962306a36Sopenharmony_ci		if (!is_sec1) {
63062306a36Sopenharmony_ci			if (v_lo & TALITOS_CCPSR_LO_GB)
63162306a36Sopenharmony_ci				dev_err(dev, "gather boundary error\n");
63262306a36Sopenharmony_ci			if (v_lo & TALITOS_CCPSR_LO_GRL)
63362306a36Sopenharmony_ci				dev_err(dev, "gather return/length error\n");
63462306a36Sopenharmony_ci			if (v_lo & TALITOS_CCPSR_LO_SB)
63562306a36Sopenharmony_ci				dev_err(dev, "scatter boundary error\n");
63662306a36Sopenharmony_ci			if (v_lo & TALITOS_CCPSR_LO_SRL)
63762306a36Sopenharmony_ci				dev_err(dev, "scatter return/length error\n");
63862306a36Sopenharmony_ci		}
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci		flush_channel(dev, ch, error, reset_ch);
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci		if (reset_ch) {
64362306a36Sopenharmony_ci			reset_channel(dev, ch);
64462306a36Sopenharmony_ci		} else {
64562306a36Sopenharmony_ci			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
64662306a36Sopenharmony_ci				  TALITOS2_CCCR_CONT);
64762306a36Sopenharmony_ci			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
64862306a36Sopenharmony_ci			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
64962306a36Sopenharmony_ci			       TALITOS2_CCCR_CONT) && --timeout)
65062306a36Sopenharmony_ci				cpu_relax();
65162306a36Sopenharmony_ci			if (timeout == 0) {
65262306a36Sopenharmony_ci				dev_err(dev, "failed to restart channel %d\n",
65362306a36Sopenharmony_ci					ch);
65462306a36Sopenharmony_ci				reset_dev = 1;
65562306a36Sopenharmony_ci			}
65662306a36Sopenharmony_ci		}
65762306a36Sopenharmony_ci	}
65862306a36Sopenharmony_ci	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
65962306a36Sopenharmony_ci	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
66062306a36Sopenharmony_ci		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
66162306a36Sopenharmony_ci			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
66262306a36Sopenharmony_ci				isr, isr_lo);
66362306a36Sopenharmony_ci		else
66462306a36Sopenharmony_ci			dev_err(dev, "done overflow, internal time out, or "
66562306a36Sopenharmony_ci				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci		/* purge request queues */
66862306a36Sopenharmony_ci		for (ch = 0; ch < priv->num_channels; ch++)
66962306a36Sopenharmony_ci			flush_channel(dev, ch, -EIO, 1);
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci		/* reset and reinitialize the device */
67262306a36Sopenharmony_ci		init_device(dev);
67362306a36Sopenharmony_ci	}
67462306a36Sopenharmony_ci}
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci#define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
67762306a36Sopenharmony_cistatic irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
67862306a36Sopenharmony_ci{									       \
67962306a36Sopenharmony_ci	struct device *dev = data;					       \
68062306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);		       \
68162306a36Sopenharmony_ci	u32 isr, isr_lo;						       \
68262306a36Sopenharmony_ci	unsigned long flags;						       \
68362306a36Sopenharmony_ci									       \
68462306a36Sopenharmony_ci	spin_lock_irqsave(&priv->reg_lock, flags);			       \
68562306a36Sopenharmony_ci	isr = in_be32(priv->reg + TALITOS_ISR);				       \
68662306a36Sopenharmony_ci	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
68762306a36Sopenharmony_ci	/* Acknowledge interrupt */					       \
68862306a36Sopenharmony_ci	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
68962306a36Sopenharmony_ci	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
69062306a36Sopenharmony_ci									       \
69162306a36Sopenharmony_ci	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
69262306a36Sopenharmony_ci		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
69362306a36Sopenharmony_ci		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
69462306a36Sopenharmony_ci	}								       \
69562306a36Sopenharmony_ci	else {								       \
69662306a36Sopenharmony_ci		if (likely(isr & ch_done_mask)) {			       \
69762306a36Sopenharmony_ci			/* mask further done interrupts. */		       \
69862306a36Sopenharmony_ci			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
69962306a36Sopenharmony_ci			/* done_task will unmask done interrupts at exit */    \
70062306a36Sopenharmony_ci			tasklet_schedule(&priv->done_task[tlet]);	       \
70162306a36Sopenharmony_ci		}							       \
70262306a36Sopenharmony_ci		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
70362306a36Sopenharmony_ci	}								       \
70462306a36Sopenharmony_ci									       \
70562306a36Sopenharmony_ci	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
70662306a36Sopenharmony_ci								IRQ_NONE;      \
70762306a36Sopenharmony_ci}
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ciDEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci#define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
71262306a36Sopenharmony_cistatic irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
71362306a36Sopenharmony_ci{									       \
71462306a36Sopenharmony_ci	struct device *dev = data;					       \
71562306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);		       \
71662306a36Sopenharmony_ci	u32 isr, isr_lo;						       \
71762306a36Sopenharmony_ci	unsigned long flags;						       \
71862306a36Sopenharmony_ci									       \
71962306a36Sopenharmony_ci	spin_lock_irqsave(&priv->reg_lock, flags);			       \
72062306a36Sopenharmony_ci	isr = in_be32(priv->reg + TALITOS_ISR);				       \
72162306a36Sopenharmony_ci	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
72262306a36Sopenharmony_ci	/* Acknowledge interrupt */					       \
72362306a36Sopenharmony_ci	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
72462306a36Sopenharmony_ci	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
72562306a36Sopenharmony_ci									       \
72662306a36Sopenharmony_ci	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
72762306a36Sopenharmony_ci		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
72862306a36Sopenharmony_ci		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
72962306a36Sopenharmony_ci	}								       \
73062306a36Sopenharmony_ci	else {								       \
73162306a36Sopenharmony_ci		if (likely(isr & ch_done_mask)) {			       \
73262306a36Sopenharmony_ci			/* mask further done interrupts. */		       \
73362306a36Sopenharmony_ci			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
73462306a36Sopenharmony_ci			/* done_task will unmask done interrupts at exit */    \
73562306a36Sopenharmony_ci			tasklet_schedule(&priv->done_task[tlet]);	       \
73662306a36Sopenharmony_ci		}							       \
73762306a36Sopenharmony_ci		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
73862306a36Sopenharmony_ci	}								       \
73962306a36Sopenharmony_ci									       \
74062306a36Sopenharmony_ci	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
74162306a36Sopenharmony_ci								IRQ_NONE;      \
74262306a36Sopenharmony_ci}
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ciDEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
74562306a36Sopenharmony_ciDEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
74662306a36Sopenharmony_ci		       0)
74762306a36Sopenharmony_ciDEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
74862306a36Sopenharmony_ci		       1)
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci/*
75162306a36Sopenharmony_ci * hwrng
75262306a36Sopenharmony_ci */
75362306a36Sopenharmony_cistatic int talitos_rng_data_present(struct hwrng *rng, int wait)
75462306a36Sopenharmony_ci{
75562306a36Sopenharmony_ci	struct device *dev = (struct device *)rng->priv;
75662306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
75762306a36Sopenharmony_ci	u32 ofl;
75862306a36Sopenharmony_ci	int i;
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	for (i = 0; i < 20; i++) {
76162306a36Sopenharmony_ci		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
76262306a36Sopenharmony_ci		      TALITOS_RNGUSR_LO_OFL;
76362306a36Sopenharmony_ci		if (ofl || !wait)
76462306a36Sopenharmony_ci			break;
76562306a36Sopenharmony_ci		udelay(10);
76662306a36Sopenharmony_ci	}
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	return !!ofl;
76962306a36Sopenharmony_ci}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_cistatic int talitos_rng_data_read(struct hwrng *rng, u32 *data)
77262306a36Sopenharmony_ci{
77362306a36Sopenharmony_ci	struct device *dev = (struct device *)rng->priv;
77462306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	/* rng fifo requires 64-bit accesses */
77762306a36Sopenharmony_ci	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
77862306a36Sopenharmony_ci	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci	return sizeof(u32);
78162306a36Sopenharmony_ci}
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_cistatic int talitos_rng_init(struct hwrng *rng)
78462306a36Sopenharmony_ci{
78562306a36Sopenharmony_ci	struct device *dev = (struct device *)rng->priv;
78662306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
78762306a36Sopenharmony_ci	unsigned int timeout = TALITOS_TIMEOUT;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
79062306a36Sopenharmony_ci	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
79162306a36Sopenharmony_ci		 & TALITOS_RNGUSR_LO_RD)
79262306a36Sopenharmony_ci	       && --timeout)
79362306a36Sopenharmony_ci		cpu_relax();
79462306a36Sopenharmony_ci	if (timeout == 0) {
79562306a36Sopenharmony_ci		dev_err(dev, "failed to reset rng hw\n");
79662306a36Sopenharmony_ci		return -ENODEV;
79762306a36Sopenharmony_ci	}
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	/* start generating */
80062306a36Sopenharmony_ci	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	return 0;
80362306a36Sopenharmony_ci}
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_cistatic int talitos_register_rng(struct device *dev)
80662306a36Sopenharmony_ci{
80762306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
80862306a36Sopenharmony_ci	int err;
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	priv->rng.name		= dev_driver_string(dev);
81162306a36Sopenharmony_ci	priv->rng.init		= talitos_rng_init;
81262306a36Sopenharmony_ci	priv->rng.data_present	= talitos_rng_data_present;
81362306a36Sopenharmony_ci	priv->rng.data_read	= talitos_rng_data_read;
81462306a36Sopenharmony_ci	priv->rng.priv		= (unsigned long)dev;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	err = hwrng_register(&priv->rng);
81762306a36Sopenharmony_ci	if (!err)
81862306a36Sopenharmony_ci		priv->rng_registered = true;
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	return err;
82162306a36Sopenharmony_ci}
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_cistatic void talitos_unregister_rng(struct device *dev)
82462306a36Sopenharmony_ci{
82562306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	if (!priv->rng_registered)
82862306a36Sopenharmony_ci		return;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	hwrng_unregister(&priv->rng);
83162306a36Sopenharmony_ci	priv->rng_registered = false;
83262306a36Sopenharmony_ci}
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci/*
83562306a36Sopenharmony_ci * crypto alg
83662306a36Sopenharmony_ci */
83762306a36Sopenharmony_ci#define TALITOS_CRA_PRIORITY		3000
83862306a36Sopenharmony_ci/*
83962306a36Sopenharmony_ci * Defines a priority for doing AEAD with descriptors type
84062306a36Sopenharmony_ci * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
84162306a36Sopenharmony_ci */
84262306a36Sopenharmony_ci#define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
84362306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS2
84462306a36Sopenharmony_ci#define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
84562306a36Sopenharmony_ci#else
84662306a36Sopenharmony_ci#define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE)
84762306a36Sopenharmony_ci#endif
84862306a36Sopenharmony_ci#define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_cistruct talitos_ctx {
85162306a36Sopenharmony_ci	struct device *dev;
85262306a36Sopenharmony_ci	int ch;
85362306a36Sopenharmony_ci	__be32 desc_hdr_template;
85462306a36Sopenharmony_ci	u8 key[TALITOS_MAX_KEY_SIZE];
85562306a36Sopenharmony_ci	u8 iv[TALITOS_MAX_IV_LENGTH];
85662306a36Sopenharmony_ci	dma_addr_t dma_key;
85762306a36Sopenharmony_ci	unsigned int keylen;
85862306a36Sopenharmony_ci	unsigned int enckeylen;
85962306a36Sopenharmony_ci	unsigned int authkeylen;
86062306a36Sopenharmony_ci};
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci#define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
86362306a36Sopenharmony_ci#define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_cistruct talitos_ahash_req_ctx {
86662306a36Sopenharmony_ci	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
86762306a36Sopenharmony_ci	unsigned int hw_context_size;
86862306a36Sopenharmony_ci	u8 buf[2][HASH_MAX_BLOCK_SIZE];
86962306a36Sopenharmony_ci	int buf_idx;
87062306a36Sopenharmony_ci	unsigned int swinit;
87162306a36Sopenharmony_ci	unsigned int first;
87262306a36Sopenharmony_ci	unsigned int last;
87362306a36Sopenharmony_ci	unsigned int to_hash_later;
87462306a36Sopenharmony_ci	unsigned int nbuf;
87562306a36Sopenharmony_ci	struct scatterlist bufsl[2];
87662306a36Sopenharmony_ci	struct scatterlist *psrc;
87762306a36Sopenharmony_ci};
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_cistruct talitos_export_state {
88062306a36Sopenharmony_ci	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
88162306a36Sopenharmony_ci	u8 buf[HASH_MAX_BLOCK_SIZE];
88262306a36Sopenharmony_ci	unsigned int swinit;
88362306a36Sopenharmony_ci	unsigned int first;
88462306a36Sopenharmony_ci	unsigned int last;
88562306a36Sopenharmony_ci	unsigned int to_hash_later;
88662306a36Sopenharmony_ci	unsigned int nbuf;
88762306a36Sopenharmony_ci};
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_cistatic int aead_setkey(struct crypto_aead *authenc,
89062306a36Sopenharmony_ci		       const u8 *key, unsigned int keylen)
89162306a36Sopenharmony_ci{
89262306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
89362306a36Sopenharmony_ci	struct device *dev = ctx->dev;
89462306a36Sopenharmony_ci	struct crypto_authenc_keys keys;
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
89762306a36Sopenharmony_ci		goto badkey;
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
90062306a36Sopenharmony_ci		goto badkey;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	if (ctx->keylen)
90362306a36Sopenharmony_ci		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	memcpy(ctx->key, keys.authkey, keys.authkeylen);
90662306a36Sopenharmony_ci	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	ctx->keylen = keys.authkeylen + keys.enckeylen;
90962306a36Sopenharmony_ci	ctx->enckeylen = keys.enckeylen;
91062306a36Sopenharmony_ci	ctx->authkeylen = keys.authkeylen;
91162306a36Sopenharmony_ci	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
91262306a36Sopenharmony_ci				      DMA_TO_DEVICE);
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
91562306a36Sopenharmony_ci	return 0;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_cibadkey:
91862306a36Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
91962306a36Sopenharmony_ci	return -EINVAL;
92062306a36Sopenharmony_ci}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_cistatic int aead_des3_setkey(struct crypto_aead *authenc,
92362306a36Sopenharmony_ci			    const u8 *key, unsigned int keylen)
92462306a36Sopenharmony_ci{
92562306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
92662306a36Sopenharmony_ci	struct device *dev = ctx->dev;
92762306a36Sopenharmony_ci	struct crypto_authenc_keys keys;
92862306a36Sopenharmony_ci	int err;
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	err = crypto_authenc_extractkeys(&keys, key, keylen);
93162306a36Sopenharmony_ci	if (unlikely(err))
93262306a36Sopenharmony_ci		goto out;
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	err = -EINVAL;
93562306a36Sopenharmony_ci	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
93662306a36Sopenharmony_ci		goto out;
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	err = verify_aead_des3_key(authenc, keys.enckey, keys.enckeylen);
93962306a36Sopenharmony_ci	if (err)
94062306a36Sopenharmony_ci		goto out;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	if (ctx->keylen)
94362306a36Sopenharmony_ci		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	memcpy(ctx->key, keys.authkey, keys.authkeylen);
94662306a36Sopenharmony_ci	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	ctx->keylen = keys.authkeylen + keys.enckeylen;
94962306a36Sopenharmony_ci	ctx->enckeylen = keys.enckeylen;
95062306a36Sopenharmony_ci	ctx->authkeylen = keys.authkeylen;
95162306a36Sopenharmony_ci	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
95262306a36Sopenharmony_ci				      DMA_TO_DEVICE);
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_ciout:
95562306a36Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
95662306a36Sopenharmony_ci	return err;
95762306a36Sopenharmony_ci}
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_cistatic void talitos_sg_unmap(struct device *dev,
96062306a36Sopenharmony_ci			     struct talitos_edesc *edesc,
96162306a36Sopenharmony_ci			     struct scatterlist *src,
96262306a36Sopenharmony_ci			     struct scatterlist *dst,
96362306a36Sopenharmony_ci			     unsigned int len, unsigned int offset)
96462306a36Sopenharmony_ci{
96562306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
96662306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
96762306a36Sopenharmony_ci	unsigned int src_nents = edesc->src_nents ? : 1;
96862306a36Sopenharmony_ci	unsigned int dst_nents = edesc->dst_nents ? : 1;
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	if (is_sec1 && dst && dst_nents > 1) {
97162306a36Sopenharmony_ci		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
97262306a36Sopenharmony_ci					   len, DMA_FROM_DEVICE);
97362306a36Sopenharmony_ci		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
97462306a36Sopenharmony_ci				     offset);
97562306a36Sopenharmony_ci	}
97662306a36Sopenharmony_ci	if (src != dst) {
97762306a36Sopenharmony_ci		if (src_nents == 1 || !is_sec1)
97862306a36Sopenharmony_ci			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci		if (dst && (dst_nents == 1 || !is_sec1))
98162306a36Sopenharmony_ci			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
98262306a36Sopenharmony_ci	} else if (src_nents == 1 || !is_sec1) {
98362306a36Sopenharmony_ci		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
98462306a36Sopenharmony_ci	}
98562306a36Sopenharmony_ci}
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_cistatic void ipsec_esp_unmap(struct device *dev,
98862306a36Sopenharmony_ci			    struct talitos_edesc *edesc,
98962306a36Sopenharmony_ci			    struct aead_request *areq, bool encrypt)
99062306a36Sopenharmony_ci{
99162306a36Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
99262306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
99362306a36Sopenharmony_ci	unsigned int ivsize = crypto_aead_ivsize(aead);
99462306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(aead);
99562306a36Sopenharmony_ci	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
99662306a36Sopenharmony_ci	bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
99762306a36Sopenharmony_ci	struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci	if (is_ipsec_esp)
100062306a36Sopenharmony_ci		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
100162306a36Sopenharmony_ci					 DMA_FROM_DEVICE);
100262306a36Sopenharmony_ci	unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	talitos_sg_unmap(dev, edesc, areq->src, areq->dst,
100562306a36Sopenharmony_ci			 cryptlen + authsize, areq->assoclen);
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	if (edesc->dma_len)
100862306a36Sopenharmony_ci		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
100962306a36Sopenharmony_ci				 DMA_BIDIRECTIONAL);
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	if (!is_ipsec_esp) {
101262306a36Sopenharmony_ci		unsigned int dst_nents = edesc->dst_nents ? : 1;
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
101562306a36Sopenharmony_ci				   areq->assoclen + cryptlen - ivsize);
101662306a36Sopenharmony_ci	}
101762306a36Sopenharmony_ci}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci/*
102062306a36Sopenharmony_ci * ipsec_esp descriptor callbacks
102162306a36Sopenharmony_ci */
102262306a36Sopenharmony_cistatic void ipsec_esp_encrypt_done(struct device *dev,
102362306a36Sopenharmony_ci				   struct talitos_desc *desc, void *context,
102462306a36Sopenharmony_ci				   int err)
102562306a36Sopenharmony_ci{
102662306a36Sopenharmony_ci	struct aead_request *areq = context;
102762306a36Sopenharmony_ci	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
102862306a36Sopenharmony_ci	unsigned int ivsize = crypto_aead_ivsize(authenc);
102962306a36Sopenharmony_ci	struct talitos_edesc *edesc;
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	edesc = container_of(desc, struct talitos_edesc, desc);
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	ipsec_esp_unmap(dev, edesc, areq, true);
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	kfree(edesc);
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	aead_request_complete(areq, err);
104062306a36Sopenharmony_ci}
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_cistatic void ipsec_esp_decrypt_swauth_done(struct device *dev,
104362306a36Sopenharmony_ci					  struct talitos_desc *desc,
104462306a36Sopenharmony_ci					  void *context, int err)
104562306a36Sopenharmony_ci{
104662306a36Sopenharmony_ci	struct aead_request *req = context;
104762306a36Sopenharmony_ci	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
104862306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(authenc);
104962306a36Sopenharmony_ci	struct talitos_edesc *edesc;
105062306a36Sopenharmony_ci	char *oicv, *icv;
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	edesc = container_of(desc, struct talitos_edesc, desc);
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	ipsec_esp_unmap(dev, edesc, req, false);
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	if (!err) {
105762306a36Sopenharmony_ci		/* auth check */
105862306a36Sopenharmony_ci		oicv = edesc->buf + edesc->dma_len;
105962306a36Sopenharmony_ci		icv = oicv - authsize;
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
106262306a36Sopenharmony_ci	}
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	kfree(edesc);
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	aead_request_complete(req, err);
106762306a36Sopenharmony_ci}
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_cistatic void ipsec_esp_decrypt_hwauth_done(struct device *dev,
107062306a36Sopenharmony_ci					  struct talitos_desc *desc,
107162306a36Sopenharmony_ci					  void *context, int err)
107262306a36Sopenharmony_ci{
107362306a36Sopenharmony_ci	struct aead_request *req = context;
107462306a36Sopenharmony_ci	struct talitos_edesc *edesc;
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	edesc = container_of(desc, struct talitos_edesc, desc);
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	ipsec_esp_unmap(dev, edesc, req, false);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	/* check ICV auth status */
108162306a36Sopenharmony_ci	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
108262306a36Sopenharmony_ci		     DESC_HDR_LO_ICCR1_PASS))
108362306a36Sopenharmony_ci		err = -EBADMSG;
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	kfree(edesc);
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci	aead_request_complete(req, err);
108862306a36Sopenharmony_ci}
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci/*
109162306a36Sopenharmony_ci * convert scatterlist to SEC h/w link table format
109262306a36Sopenharmony_ci * stop at cryptlen bytes
109362306a36Sopenharmony_ci */
109462306a36Sopenharmony_cistatic int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
109562306a36Sopenharmony_ci				 unsigned int offset, int datalen, int elen,
109662306a36Sopenharmony_ci				 struct talitos_ptr *link_tbl_ptr, int align)
109762306a36Sopenharmony_ci{
109862306a36Sopenharmony_ci	int n_sg = elen ? sg_count + 1 : sg_count;
109962306a36Sopenharmony_ci	int count = 0;
110062306a36Sopenharmony_ci	int cryptlen = datalen + elen;
110162306a36Sopenharmony_ci	int padding = ALIGN(cryptlen, align) - cryptlen;
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	while (cryptlen && sg && n_sg--) {
110462306a36Sopenharmony_ci		unsigned int len = sg_dma_len(sg);
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci		if (offset >= len) {
110762306a36Sopenharmony_ci			offset -= len;
110862306a36Sopenharmony_ci			goto next;
110962306a36Sopenharmony_ci		}
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci		len -= offset;
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci		if (len > cryptlen)
111462306a36Sopenharmony_ci			len = cryptlen;
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci		if (datalen > 0 && len > datalen) {
111762306a36Sopenharmony_ci			to_talitos_ptr(link_tbl_ptr + count,
111862306a36Sopenharmony_ci				       sg_dma_address(sg) + offset, datalen, 0);
111962306a36Sopenharmony_ci			to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
112062306a36Sopenharmony_ci			count++;
112162306a36Sopenharmony_ci			len -= datalen;
112262306a36Sopenharmony_ci			offset += datalen;
112362306a36Sopenharmony_ci		}
112462306a36Sopenharmony_ci		to_talitos_ptr(link_tbl_ptr + count,
112562306a36Sopenharmony_ci			       sg_dma_address(sg) + offset, sg_next(sg) ? len : len + padding, 0);
112662306a36Sopenharmony_ci		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
112762306a36Sopenharmony_ci		count++;
112862306a36Sopenharmony_ci		cryptlen -= len;
112962306a36Sopenharmony_ci		datalen -= len;
113062306a36Sopenharmony_ci		offset = 0;
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_cinext:
113362306a36Sopenharmony_ci		sg = sg_next(sg);
113462306a36Sopenharmony_ci	}
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	/* tag end of link table */
113762306a36Sopenharmony_ci	if (count > 0)
113862306a36Sopenharmony_ci		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
113962306a36Sopenharmony_ci				       DESC_PTR_LNKTBL_RET, 0);
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	return count;
114262306a36Sopenharmony_ci}
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_cistatic int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
114562306a36Sopenharmony_ci			      unsigned int len, struct talitos_edesc *edesc,
114662306a36Sopenharmony_ci			      struct talitos_ptr *ptr, int sg_count,
114762306a36Sopenharmony_ci			      unsigned int offset, int tbl_off, int elen,
114862306a36Sopenharmony_ci			      bool force, int align)
114962306a36Sopenharmony_ci{
115062306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
115162306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
115262306a36Sopenharmony_ci	int aligned_len = ALIGN(len, align);
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	if (!src) {
115562306a36Sopenharmony_ci		to_talitos_ptr(ptr, 0, 0, is_sec1);
115662306a36Sopenharmony_ci		return 1;
115762306a36Sopenharmony_ci	}
115862306a36Sopenharmony_ci	to_talitos_ptr_ext_set(ptr, elen, is_sec1);
115962306a36Sopenharmony_ci	if (sg_count == 1 && !force) {
116062306a36Sopenharmony_ci		to_talitos_ptr(ptr, sg_dma_address(src) + offset, aligned_len, is_sec1);
116162306a36Sopenharmony_ci		return sg_count;
116262306a36Sopenharmony_ci	}
116362306a36Sopenharmony_ci	if (is_sec1) {
116462306a36Sopenharmony_ci		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, aligned_len, is_sec1);
116562306a36Sopenharmony_ci		return sg_count;
116662306a36Sopenharmony_ci	}
116762306a36Sopenharmony_ci	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen,
116862306a36Sopenharmony_ci					 &edesc->link_tbl[tbl_off], align);
116962306a36Sopenharmony_ci	if (sg_count == 1 && !force) {
117062306a36Sopenharmony_ci		/* Only one segment now, so no link tbl needed*/
117162306a36Sopenharmony_ci		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
117262306a36Sopenharmony_ci		return sg_count;
117362306a36Sopenharmony_ci	}
117462306a36Sopenharmony_ci	to_talitos_ptr(ptr, edesc->dma_link_tbl +
117562306a36Sopenharmony_ci			    tbl_off * sizeof(struct talitos_ptr), aligned_len, is_sec1);
117662306a36Sopenharmony_ci	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	return sg_count;
117962306a36Sopenharmony_ci}
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_cistatic int talitos_sg_map(struct device *dev, struct scatterlist *src,
118262306a36Sopenharmony_ci			  unsigned int len, struct talitos_edesc *edesc,
118362306a36Sopenharmony_ci			  struct talitos_ptr *ptr, int sg_count,
118462306a36Sopenharmony_ci			  unsigned int offset, int tbl_off)
118562306a36Sopenharmony_ci{
118662306a36Sopenharmony_ci	return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset,
118762306a36Sopenharmony_ci				  tbl_off, 0, false, 1);
118862306a36Sopenharmony_ci}
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci/*
119162306a36Sopenharmony_ci * fill in and submit ipsec_esp descriptor
119262306a36Sopenharmony_ci */
119362306a36Sopenharmony_cistatic int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
119462306a36Sopenharmony_ci		     bool encrypt,
119562306a36Sopenharmony_ci		     void (*callback)(struct device *dev,
119662306a36Sopenharmony_ci				      struct talitos_desc *desc,
119762306a36Sopenharmony_ci				      void *context, int error))
119862306a36Sopenharmony_ci{
119962306a36Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
120062306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(aead);
120162306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
120262306a36Sopenharmony_ci	struct device *dev = ctx->dev;
120362306a36Sopenharmony_ci	struct talitos_desc *desc = &edesc->desc;
120462306a36Sopenharmony_ci	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
120562306a36Sopenharmony_ci	unsigned int ivsize = crypto_aead_ivsize(aead);
120662306a36Sopenharmony_ci	int tbl_off = 0;
120762306a36Sopenharmony_ci	int sg_count, ret;
120862306a36Sopenharmony_ci	int elen = 0;
120962306a36Sopenharmony_ci	bool sync_needed = false;
121062306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
121162306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
121262306a36Sopenharmony_ci	bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
121362306a36Sopenharmony_ci	struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
121462306a36Sopenharmony_ci	struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
121562306a36Sopenharmony_ci	dma_addr_t dma_icv = edesc->dma_link_tbl + edesc->dma_len - authsize;
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	/* hmac key */
121862306a36Sopenharmony_ci	to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1);
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	sg_count = edesc->src_nents ?: 1;
122162306a36Sopenharmony_ci	if (is_sec1 && sg_count > 1)
122262306a36Sopenharmony_ci		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
122362306a36Sopenharmony_ci				  areq->assoclen + cryptlen);
122462306a36Sopenharmony_ci	else
122562306a36Sopenharmony_ci		sg_count = dma_map_sg(dev, areq->src, sg_count,
122662306a36Sopenharmony_ci				      (areq->src == areq->dst) ?
122762306a36Sopenharmony_ci				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	/* hmac data */
123062306a36Sopenharmony_ci	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
123162306a36Sopenharmony_ci			     &desc->ptr[1], sg_count, 0, tbl_off);
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	if (ret > 1) {
123462306a36Sopenharmony_ci		tbl_off += ret;
123562306a36Sopenharmony_ci		sync_needed = true;
123662306a36Sopenharmony_ci	}
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci	/* cipher iv */
123962306a36Sopenharmony_ci	to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1);
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci	/* cipher key */
124262306a36Sopenharmony_ci	to_talitos_ptr(ckey_ptr, ctx->dma_key  + ctx->authkeylen,
124362306a36Sopenharmony_ci		       ctx->enckeylen, is_sec1);
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	/*
124662306a36Sopenharmony_ci	 * cipher in
124762306a36Sopenharmony_ci	 * map and adjust cipher len to aead request cryptlen.
124862306a36Sopenharmony_ci	 * extent is bytes of HMAC postpended to ciphertext,
124962306a36Sopenharmony_ci	 * typically 12 for ipsec
125062306a36Sopenharmony_ci	 */
125162306a36Sopenharmony_ci	if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV))
125262306a36Sopenharmony_ci		elen = authsize;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4],
125562306a36Sopenharmony_ci				 sg_count, areq->assoclen, tbl_off, elen,
125662306a36Sopenharmony_ci				 false, 1);
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	if (ret > 1) {
125962306a36Sopenharmony_ci		tbl_off += ret;
126062306a36Sopenharmony_ci		sync_needed = true;
126162306a36Sopenharmony_ci	}
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	/* cipher out */
126462306a36Sopenharmony_ci	if (areq->src != areq->dst) {
126562306a36Sopenharmony_ci		sg_count = edesc->dst_nents ? : 1;
126662306a36Sopenharmony_ci		if (!is_sec1 || sg_count == 1)
126762306a36Sopenharmony_ci			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
126862306a36Sopenharmony_ci	}
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci	if (is_ipsec_esp && encrypt)
127162306a36Sopenharmony_ci		elen = authsize;
127262306a36Sopenharmony_ci	else
127362306a36Sopenharmony_ci		elen = 0;
127462306a36Sopenharmony_ci	ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
127562306a36Sopenharmony_ci				 sg_count, areq->assoclen, tbl_off, elen,
127662306a36Sopenharmony_ci				 is_ipsec_esp && !encrypt, 1);
127762306a36Sopenharmony_ci	tbl_off += ret;
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	if (!encrypt && is_ipsec_esp) {
128062306a36Sopenharmony_ci		struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci		/* Add an entry to the link table for ICV data */
128362306a36Sopenharmony_ci		to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
128462306a36Sopenharmony_ci		to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RET, is_sec1);
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci		/* icv data follows link tables */
128762306a36Sopenharmony_ci		to_talitos_ptr(tbl_ptr, dma_icv, authsize, is_sec1);
128862306a36Sopenharmony_ci		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
128962306a36Sopenharmony_ci		sync_needed = true;
129062306a36Sopenharmony_ci	} else if (!encrypt) {
129162306a36Sopenharmony_ci		to_talitos_ptr(&desc->ptr[6], dma_icv, authsize, is_sec1);
129262306a36Sopenharmony_ci		sync_needed = true;
129362306a36Sopenharmony_ci	} else if (!is_ipsec_esp) {
129462306a36Sopenharmony_ci		talitos_sg_map(dev, areq->dst, authsize, edesc, &desc->ptr[6],
129562306a36Sopenharmony_ci			       sg_count, areq->assoclen + cryptlen, tbl_off);
129662306a36Sopenharmony_ci	}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	/* iv out */
129962306a36Sopenharmony_ci	if (is_ipsec_esp)
130062306a36Sopenharmony_ci		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
130162306a36Sopenharmony_ci				       DMA_FROM_DEVICE);
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	if (sync_needed)
130462306a36Sopenharmony_ci		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
130562306a36Sopenharmony_ci					   edesc->dma_len,
130662306a36Sopenharmony_ci					   DMA_BIDIRECTIONAL);
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
130962306a36Sopenharmony_ci	if (ret != -EINPROGRESS) {
131062306a36Sopenharmony_ci		ipsec_esp_unmap(dev, edesc, areq, encrypt);
131162306a36Sopenharmony_ci		kfree(edesc);
131262306a36Sopenharmony_ci	}
131362306a36Sopenharmony_ci	return ret;
131462306a36Sopenharmony_ci}
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci/*
131762306a36Sopenharmony_ci * allocate and map the extended descriptor
131862306a36Sopenharmony_ci */
131962306a36Sopenharmony_cistatic struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
132062306a36Sopenharmony_ci						 struct scatterlist *src,
132162306a36Sopenharmony_ci						 struct scatterlist *dst,
132262306a36Sopenharmony_ci						 u8 *iv,
132362306a36Sopenharmony_ci						 unsigned int assoclen,
132462306a36Sopenharmony_ci						 unsigned int cryptlen,
132562306a36Sopenharmony_ci						 unsigned int authsize,
132662306a36Sopenharmony_ci						 unsigned int ivsize,
132762306a36Sopenharmony_ci						 int icv_stashing,
132862306a36Sopenharmony_ci						 u32 cryptoflags,
132962306a36Sopenharmony_ci						 bool encrypt)
133062306a36Sopenharmony_ci{
133162306a36Sopenharmony_ci	struct talitos_edesc *edesc;
133262306a36Sopenharmony_ci	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
133362306a36Sopenharmony_ci	dma_addr_t iv_dma = 0;
133462306a36Sopenharmony_ci	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
133562306a36Sopenharmony_ci		      GFP_ATOMIC;
133662306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
133762306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
133862306a36Sopenharmony_ci	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	if (cryptlen + authsize > max_len) {
134162306a36Sopenharmony_ci		dev_err(dev, "length exceeds h/w max limit\n");
134262306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
134362306a36Sopenharmony_ci	}
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	if (!dst || dst == src) {
134662306a36Sopenharmony_ci		src_len = assoclen + cryptlen + authsize;
134762306a36Sopenharmony_ci		src_nents = sg_nents_for_len(src, src_len);
134862306a36Sopenharmony_ci		if (src_nents < 0) {
134962306a36Sopenharmony_ci			dev_err(dev, "Invalid number of src SG.\n");
135062306a36Sopenharmony_ci			return ERR_PTR(-EINVAL);
135162306a36Sopenharmony_ci		}
135262306a36Sopenharmony_ci		src_nents = (src_nents == 1) ? 0 : src_nents;
135362306a36Sopenharmony_ci		dst_nents = dst ? src_nents : 0;
135462306a36Sopenharmony_ci		dst_len = 0;
135562306a36Sopenharmony_ci	} else { /* dst && dst != src*/
135662306a36Sopenharmony_ci		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
135762306a36Sopenharmony_ci		src_nents = sg_nents_for_len(src, src_len);
135862306a36Sopenharmony_ci		if (src_nents < 0) {
135962306a36Sopenharmony_ci			dev_err(dev, "Invalid number of src SG.\n");
136062306a36Sopenharmony_ci			return ERR_PTR(-EINVAL);
136162306a36Sopenharmony_ci		}
136262306a36Sopenharmony_ci		src_nents = (src_nents == 1) ? 0 : src_nents;
136362306a36Sopenharmony_ci		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
136462306a36Sopenharmony_ci		dst_nents = sg_nents_for_len(dst, dst_len);
136562306a36Sopenharmony_ci		if (dst_nents < 0) {
136662306a36Sopenharmony_ci			dev_err(dev, "Invalid number of dst SG.\n");
136762306a36Sopenharmony_ci			return ERR_PTR(-EINVAL);
136862306a36Sopenharmony_ci		}
136962306a36Sopenharmony_ci		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
137062306a36Sopenharmony_ci	}
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	/*
137362306a36Sopenharmony_ci	 * allocate space for base edesc plus the link tables,
137462306a36Sopenharmony_ci	 * allowing for two separate entries for AD and generated ICV (+ 2),
137562306a36Sopenharmony_ci	 * and space for two sets of ICVs (stashed and generated)
137662306a36Sopenharmony_ci	 */
137762306a36Sopenharmony_ci	alloc_len = sizeof(struct talitos_edesc);
137862306a36Sopenharmony_ci	if (src_nents || dst_nents || !encrypt) {
137962306a36Sopenharmony_ci		if (is_sec1)
138062306a36Sopenharmony_ci			dma_len = (src_nents ? src_len : 0) +
138162306a36Sopenharmony_ci				  (dst_nents ? dst_len : 0) + authsize;
138262306a36Sopenharmony_ci		else
138362306a36Sopenharmony_ci			dma_len = (src_nents + dst_nents + 2) *
138462306a36Sopenharmony_ci				  sizeof(struct talitos_ptr) + authsize;
138562306a36Sopenharmony_ci		alloc_len += dma_len;
138662306a36Sopenharmony_ci	} else {
138762306a36Sopenharmony_ci		dma_len = 0;
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci	alloc_len += icv_stashing ? authsize : 0;
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci	/* if its a ahash, add space for a second desc next to the first one */
139262306a36Sopenharmony_ci	if (is_sec1 && !dst)
139362306a36Sopenharmony_ci		alloc_len += sizeof(struct talitos_desc);
139462306a36Sopenharmony_ci	alloc_len += ivsize;
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	edesc = kmalloc(ALIGN(alloc_len, dma_get_cache_alignment()), flags);
139762306a36Sopenharmony_ci	if (!edesc)
139862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
139962306a36Sopenharmony_ci	if (ivsize) {
140062306a36Sopenharmony_ci		iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
140162306a36Sopenharmony_ci		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
140262306a36Sopenharmony_ci	}
140362306a36Sopenharmony_ci	memset(&edesc->desc, 0, sizeof(edesc->desc));
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	edesc->src_nents = src_nents;
140662306a36Sopenharmony_ci	edesc->dst_nents = dst_nents;
140762306a36Sopenharmony_ci	edesc->iv_dma = iv_dma;
140862306a36Sopenharmony_ci	edesc->dma_len = dma_len;
140962306a36Sopenharmony_ci	if (dma_len)
141062306a36Sopenharmony_ci		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
141162306a36Sopenharmony_ci						     edesc->dma_len,
141262306a36Sopenharmony_ci						     DMA_BIDIRECTIONAL);
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	return edesc;
141562306a36Sopenharmony_ci}
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_cistatic struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
141862306a36Sopenharmony_ci					      int icv_stashing, bool encrypt)
141962306a36Sopenharmony_ci{
142062306a36Sopenharmony_ci	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
142162306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(authenc);
142262306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
142362306a36Sopenharmony_ci	unsigned int ivsize = crypto_aead_ivsize(authenc);
142462306a36Sopenharmony_ci	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
142762306a36Sopenharmony_ci				   iv, areq->assoclen, cryptlen,
142862306a36Sopenharmony_ci				   authsize, ivsize, icv_stashing,
142962306a36Sopenharmony_ci				   areq->base.flags, encrypt);
143062306a36Sopenharmony_ci}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_cistatic int aead_encrypt(struct aead_request *req)
143362306a36Sopenharmony_ci{
143462306a36Sopenharmony_ci	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
143562306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
143662306a36Sopenharmony_ci	struct talitos_edesc *edesc;
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	/* allocate extended descriptor */
143962306a36Sopenharmony_ci	edesc = aead_edesc_alloc(req, req->iv, 0, true);
144062306a36Sopenharmony_ci	if (IS_ERR(edesc))
144162306a36Sopenharmony_ci		return PTR_ERR(edesc);
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	/* set encrypt */
144462306a36Sopenharmony_ci	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done);
144762306a36Sopenharmony_ci}
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_cistatic int aead_decrypt(struct aead_request *req)
145062306a36Sopenharmony_ci{
145162306a36Sopenharmony_ci	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
145262306a36Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(authenc);
145362306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
145462306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
145562306a36Sopenharmony_ci	struct talitos_edesc *edesc;
145662306a36Sopenharmony_ci	void *icvdata;
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	/* allocate extended descriptor */
145962306a36Sopenharmony_ci	edesc = aead_edesc_alloc(req, req->iv, 1, false);
146062306a36Sopenharmony_ci	if (IS_ERR(edesc))
146162306a36Sopenharmony_ci		return PTR_ERR(edesc);
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) &&
146462306a36Sopenharmony_ci	    (priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
146562306a36Sopenharmony_ci	    ((!edesc->src_nents && !edesc->dst_nents) ||
146662306a36Sopenharmony_ci	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci		/* decrypt and check the ICV */
146962306a36Sopenharmony_ci		edesc->desc.hdr = ctx->desc_hdr_template |
147062306a36Sopenharmony_ci				  DESC_HDR_DIR_INBOUND |
147162306a36Sopenharmony_ci				  DESC_HDR_MODE1_MDEU_CICV;
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci		/* reset integrity check result bits */
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci		return ipsec_esp(edesc, req, false,
147662306a36Sopenharmony_ci				 ipsec_esp_decrypt_hwauth_done);
147762306a36Sopenharmony_ci	}
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	/* Have to check the ICV with software */
148062306a36Sopenharmony_ci	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci	/* stash incoming ICV for later cmp with ICV generated by the h/w */
148362306a36Sopenharmony_ci	icvdata = edesc->buf + edesc->dma_len;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize,
148662306a36Sopenharmony_ci			   req->assoclen + req->cryptlen - authsize);
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci	return ipsec_esp(edesc, req, false, ipsec_esp_decrypt_swauth_done);
148962306a36Sopenharmony_ci}
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_cistatic int skcipher_setkey(struct crypto_skcipher *cipher,
149262306a36Sopenharmony_ci			     const u8 *key, unsigned int keylen)
149362306a36Sopenharmony_ci{
149462306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
149562306a36Sopenharmony_ci	struct device *dev = ctx->dev;
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	if (ctx->keylen)
149862306a36Sopenharmony_ci		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	memcpy(&ctx->key, key, keylen);
150162306a36Sopenharmony_ci	ctx->keylen = keylen;
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE);
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	return 0;
150662306a36Sopenharmony_ci}
150762306a36Sopenharmony_ci
150862306a36Sopenharmony_cistatic int skcipher_des_setkey(struct crypto_skcipher *cipher,
150962306a36Sopenharmony_ci				 const u8 *key, unsigned int keylen)
151062306a36Sopenharmony_ci{
151162306a36Sopenharmony_ci	return verify_skcipher_des_key(cipher, key) ?:
151262306a36Sopenharmony_ci	       skcipher_setkey(cipher, key, keylen);
151362306a36Sopenharmony_ci}
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_cistatic int skcipher_des3_setkey(struct crypto_skcipher *cipher,
151662306a36Sopenharmony_ci				  const u8 *key, unsigned int keylen)
151762306a36Sopenharmony_ci{
151862306a36Sopenharmony_ci	return verify_skcipher_des3_key(cipher, key) ?:
151962306a36Sopenharmony_ci	       skcipher_setkey(cipher, key, keylen);
152062306a36Sopenharmony_ci}
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_cistatic int skcipher_aes_setkey(struct crypto_skcipher *cipher,
152362306a36Sopenharmony_ci				  const u8 *key, unsigned int keylen)
152462306a36Sopenharmony_ci{
152562306a36Sopenharmony_ci	if (keylen == AES_KEYSIZE_128 || keylen == AES_KEYSIZE_192 ||
152662306a36Sopenharmony_ci	    keylen == AES_KEYSIZE_256)
152762306a36Sopenharmony_ci		return skcipher_setkey(cipher, key, keylen);
152862306a36Sopenharmony_ci
152962306a36Sopenharmony_ci	return -EINVAL;
153062306a36Sopenharmony_ci}
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_cistatic void common_nonsnoop_unmap(struct device *dev,
153362306a36Sopenharmony_ci				  struct talitos_edesc *edesc,
153462306a36Sopenharmony_ci				  struct skcipher_request *areq)
153562306a36Sopenharmony_ci{
153662306a36Sopenharmony_ci	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, 0);
153962306a36Sopenharmony_ci	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	if (edesc->dma_len)
154262306a36Sopenharmony_ci		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
154362306a36Sopenharmony_ci				 DMA_BIDIRECTIONAL);
154462306a36Sopenharmony_ci}
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_cistatic void skcipher_done(struct device *dev,
154762306a36Sopenharmony_ci			    struct talitos_desc *desc, void *context,
154862306a36Sopenharmony_ci			    int err)
154962306a36Sopenharmony_ci{
155062306a36Sopenharmony_ci	struct skcipher_request *areq = context;
155162306a36Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
155262306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
155362306a36Sopenharmony_ci	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
155462306a36Sopenharmony_ci	struct talitos_edesc *edesc;
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	edesc = container_of(desc, struct talitos_edesc, desc);
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci	common_nonsnoop_unmap(dev, edesc, areq);
155962306a36Sopenharmony_ci	memcpy(areq->iv, ctx->iv, ivsize);
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci	kfree(edesc);
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci	skcipher_request_complete(areq, err);
156462306a36Sopenharmony_ci}
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_cistatic int common_nonsnoop(struct talitos_edesc *edesc,
156762306a36Sopenharmony_ci			   struct skcipher_request *areq,
156862306a36Sopenharmony_ci			   void (*callback) (struct device *dev,
156962306a36Sopenharmony_ci					     struct talitos_desc *desc,
157062306a36Sopenharmony_ci					     void *context, int error))
157162306a36Sopenharmony_ci{
157262306a36Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
157362306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
157462306a36Sopenharmony_ci	struct device *dev = ctx->dev;
157562306a36Sopenharmony_ci	struct talitos_desc *desc = &edesc->desc;
157662306a36Sopenharmony_ci	unsigned int cryptlen = areq->cryptlen;
157762306a36Sopenharmony_ci	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
157862306a36Sopenharmony_ci	int sg_count, ret;
157962306a36Sopenharmony_ci	bool sync_needed = false;
158062306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
158162306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
158262306a36Sopenharmony_ci	bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU &&
158362306a36Sopenharmony_ci		      (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR;
158462306a36Sopenharmony_ci
158562306a36Sopenharmony_ci	/* first DWORD empty */
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci	/* cipher iv */
158862306a36Sopenharmony_ci	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1);
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_ci	/* cipher key */
159162306a36Sopenharmony_ci	to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1);
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	sg_count = edesc->src_nents ?: 1;
159462306a36Sopenharmony_ci	if (is_sec1 && sg_count > 1)
159562306a36Sopenharmony_ci		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
159662306a36Sopenharmony_ci				  cryptlen);
159762306a36Sopenharmony_ci	else
159862306a36Sopenharmony_ci		sg_count = dma_map_sg(dev, areq->src, sg_count,
159962306a36Sopenharmony_ci				      (areq->src == areq->dst) ?
160062306a36Sopenharmony_ci				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
160162306a36Sopenharmony_ci	/*
160262306a36Sopenharmony_ci	 * cipher in
160362306a36Sopenharmony_ci	 */
160462306a36Sopenharmony_ci	sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3],
160562306a36Sopenharmony_ci				      sg_count, 0, 0, 0, false, is_ctr ? 16 : 1);
160662306a36Sopenharmony_ci	if (sg_count > 1)
160762306a36Sopenharmony_ci		sync_needed = true;
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	/* cipher out */
161062306a36Sopenharmony_ci	if (areq->src != areq->dst) {
161162306a36Sopenharmony_ci		sg_count = edesc->dst_nents ? : 1;
161262306a36Sopenharmony_ci		if (!is_sec1 || sg_count == 1)
161362306a36Sopenharmony_ci			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
161462306a36Sopenharmony_ci	}
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_ci	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
161762306a36Sopenharmony_ci			     sg_count, 0, (edesc->src_nents + 1));
161862306a36Sopenharmony_ci	if (ret > 1)
161962306a36Sopenharmony_ci		sync_needed = true;
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci	/* iv out */
162262306a36Sopenharmony_ci	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
162362306a36Sopenharmony_ci			       DMA_FROM_DEVICE);
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci	/* last DWORD empty */
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci	if (sync_needed)
162862306a36Sopenharmony_ci		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
162962306a36Sopenharmony_ci					   edesc->dma_len, DMA_BIDIRECTIONAL);
163062306a36Sopenharmony_ci
163162306a36Sopenharmony_ci	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
163262306a36Sopenharmony_ci	if (ret != -EINPROGRESS) {
163362306a36Sopenharmony_ci		common_nonsnoop_unmap(dev, edesc, areq);
163462306a36Sopenharmony_ci		kfree(edesc);
163562306a36Sopenharmony_ci	}
163662306a36Sopenharmony_ci	return ret;
163762306a36Sopenharmony_ci}
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_cistatic struct talitos_edesc *skcipher_edesc_alloc(struct skcipher_request *
164062306a36Sopenharmony_ci						    areq, bool encrypt)
164162306a36Sopenharmony_ci{
164262306a36Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
164362306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
164462306a36Sopenharmony_ci	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
164762306a36Sopenharmony_ci				   areq->iv, 0, areq->cryptlen, 0, ivsize, 0,
164862306a36Sopenharmony_ci				   areq->base.flags, encrypt);
164962306a36Sopenharmony_ci}
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_cistatic int skcipher_encrypt(struct skcipher_request *areq)
165262306a36Sopenharmony_ci{
165362306a36Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
165462306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
165562306a36Sopenharmony_ci	struct talitos_edesc *edesc;
165662306a36Sopenharmony_ci	unsigned int blocksize =
165762306a36Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher));
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_ci	if (!areq->cryptlen)
166062306a36Sopenharmony_ci		return 0;
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci	if (areq->cryptlen % blocksize)
166362306a36Sopenharmony_ci		return -EINVAL;
166462306a36Sopenharmony_ci
166562306a36Sopenharmony_ci	/* allocate extended descriptor */
166662306a36Sopenharmony_ci	edesc = skcipher_edesc_alloc(areq, true);
166762306a36Sopenharmony_ci	if (IS_ERR(edesc))
166862306a36Sopenharmony_ci		return PTR_ERR(edesc);
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	/* set encrypt */
167162306a36Sopenharmony_ci	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	return common_nonsnoop(edesc, areq, skcipher_done);
167462306a36Sopenharmony_ci}
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_cistatic int skcipher_decrypt(struct skcipher_request *areq)
167762306a36Sopenharmony_ci{
167862306a36Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
167962306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
168062306a36Sopenharmony_ci	struct talitos_edesc *edesc;
168162306a36Sopenharmony_ci	unsigned int blocksize =
168262306a36Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher));
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	if (!areq->cryptlen)
168562306a36Sopenharmony_ci		return 0;
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_ci	if (areq->cryptlen % blocksize)
168862306a36Sopenharmony_ci		return -EINVAL;
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci	/* allocate extended descriptor */
169162306a36Sopenharmony_ci	edesc = skcipher_edesc_alloc(areq, false);
169262306a36Sopenharmony_ci	if (IS_ERR(edesc))
169362306a36Sopenharmony_ci		return PTR_ERR(edesc);
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_ci	return common_nonsnoop(edesc, areq, skcipher_done);
169862306a36Sopenharmony_ci}
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_cistatic void common_nonsnoop_hash_unmap(struct device *dev,
170162306a36Sopenharmony_ci				       struct talitos_edesc *edesc,
170262306a36Sopenharmony_ci				       struct ahash_request *areq)
170362306a36Sopenharmony_ci{
170462306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
170562306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
170662306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
170762306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
170862306a36Sopenharmony_ci	struct talitos_desc *desc = &edesc->desc;
170962306a36Sopenharmony_ci	struct talitos_desc *desc2 = (struct talitos_desc *)
171062306a36Sopenharmony_ci				     (edesc->buf + edesc->dma_len);
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE);
171362306a36Sopenharmony_ci	if (desc->next_desc &&
171462306a36Sopenharmony_ci	    desc->ptr[5].ptr != desc2->ptr[5].ptr)
171562306a36Sopenharmony_ci		unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
171662306a36Sopenharmony_ci	if (req_ctx->last)
171762306a36Sopenharmony_ci		memcpy(areq->result, req_ctx->hw_context,
171862306a36Sopenharmony_ci		       crypto_ahash_digestsize(tfm));
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	if (req_ctx->psrc)
172162306a36Sopenharmony_ci		talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci	/* When using hashctx-in, must unmap it. */
172462306a36Sopenharmony_ci	if (from_talitos_ptr_len(&desc->ptr[1], is_sec1))
172562306a36Sopenharmony_ci		unmap_single_talitos_ptr(dev, &desc->ptr[1],
172662306a36Sopenharmony_ci					 DMA_TO_DEVICE);
172762306a36Sopenharmony_ci	else if (desc->next_desc)
172862306a36Sopenharmony_ci		unmap_single_talitos_ptr(dev, &desc2->ptr[1],
172962306a36Sopenharmony_ci					 DMA_TO_DEVICE);
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	if (is_sec1 && req_ctx->nbuf)
173262306a36Sopenharmony_ci		unmap_single_talitos_ptr(dev, &desc->ptr[3],
173362306a36Sopenharmony_ci					 DMA_TO_DEVICE);
173462306a36Sopenharmony_ci
173562306a36Sopenharmony_ci	if (edesc->dma_len)
173662306a36Sopenharmony_ci		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
173762306a36Sopenharmony_ci				 DMA_BIDIRECTIONAL);
173862306a36Sopenharmony_ci
173962306a36Sopenharmony_ci	if (desc->next_desc)
174062306a36Sopenharmony_ci		dma_unmap_single(dev, be32_to_cpu(desc->next_desc),
174162306a36Sopenharmony_ci				 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
174262306a36Sopenharmony_ci}
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_cistatic void ahash_done(struct device *dev,
174562306a36Sopenharmony_ci		       struct talitos_desc *desc, void *context,
174662306a36Sopenharmony_ci		       int err)
174762306a36Sopenharmony_ci{
174862306a36Sopenharmony_ci	struct ahash_request *areq = context;
174962306a36Sopenharmony_ci	struct talitos_edesc *edesc =
175062306a36Sopenharmony_ci		 container_of(desc, struct talitos_edesc, desc);
175162306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	if (!req_ctx->last && req_ctx->to_hash_later) {
175462306a36Sopenharmony_ci		/* Position any partial block for next update/final/finup */
175562306a36Sopenharmony_ci		req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
175662306a36Sopenharmony_ci		req_ctx->nbuf = req_ctx->to_hash_later;
175762306a36Sopenharmony_ci	}
175862306a36Sopenharmony_ci	common_nonsnoop_hash_unmap(dev, edesc, areq);
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	kfree(edesc);
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_ci	ahash_request_complete(areq, err);
176362306a36Sopenharmony_ci}
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci/*
176662306a36Sopenharmony_ci * SEC1 doesn't like hashing of 0 sized message, so we do the padding
176762306a36Sopenharmony_ci * ourself and submit a padded block
176862306a36Sopenharmony_ci */
176962306a36Sopenharmony_cistatic void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
177062306a36Sopenharmony_ci			       struct talitos_edesc *edesc,
177162306a36Sopenharmony_ci			       struct talitos_ptr *ptr)
177262306a36Sopenharmony_ci{
177362306a36Sopenharmony_ci	static u8 padded_hash[64] = {
177462306a36Sopenharmony_ci		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177562306a36Sopenharmony_ci		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177662306a36Sopenharmony_ci		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177762306a36Sopenharmony_ci		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177862306a36Sopenharmony_ci	};
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci	pr_err_once("Bug in SEC1, padding ourself\n");
178162306a36Sopenharmony_ci	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
178262306a36Sopenharmony_ci	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
178362306a36Sopenharmony_ci			       (char *)padded_hash, DMA_TO_DEVICE);
178462306a36Sopenharmony_ci}
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_cistatic int common_nonsnoop_hash(struct talitos_edesc *edesc,
178762306a36Sopenharmony_ci				struct ahash_request *areq, unsigned int length,
178862306a36Sopenharmony_ci				void (*callback) (struct device *dev,
178962306a36Sopenharmony_ci						  struct talitos_desc *desc,
179062306a36Sopenharmony_ci						  void *context, int error))
179162306a36Sopenharmony_ci{
179262306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
179362306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
179462306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
179562306a36Sopenharmony_ci	struct device *dev = ctx->dev;
179662306a36Sopenharmony_ci	struct talitos_desc *desc = &edesc->desc;
179762306a36Sopenharmony_ci	int ret;
179862306a36Sopenharmony_ci	bool sync_needed = false;
179962306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
180062306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
180162306a36Sopenharmony_ci	int sg_count;
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci	/* first DWORD empty */
180462306a36Sopenharmony_ci
180562306a36Sopenharmony_ci	/* hash context in */
180662306a36Sopenharmony_ci	if (!req_ctx->first || req_ctx->swinit) {
180762306a36Sopenharmony_ci		map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
180862306a36Sopenharmony_ci					      req_ctx->hw_context_size,
180962306a36Sopenharmony_ci					      req_ctx->hw_context,
181062306a36Sopenharmony_ci					      DMA_TO_DEVICE);
181162306a36Sopenharmony_ci		req_ctx->swinit = 0;
181262306a36Sopenharmony_ci	}
181362306a36Sopenharmony_ci	/* Indicate next op is not the first. */
181462306a36Sopenharmony_ci	req_ctx->first = 0;
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	/* HMAC key */
181762306a36Sopenharmony_ci	if (ctx->keylen)
181862306a36Sopenharmony_ci		to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
181962306a36Sopenharmony_ci			       is_sec1);
182062306a36Sopenharmony_ci
182162306a36Sopenharmony_ci	if (is_sec1 && req_ctx->nbuf)
182262306a36Sopenharmony_ci		length -= req_ctx->nbuf;
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci	sg_count = edesc->src_nents ?: 1;
182562306a36Sopenharmony_ci	if (is_sec1 && sg_count > 1)
182662306a36Sopenharmony_ci		sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
182762306a36Sopenharmony_ci	else if (length)
182862306a36Sopenharmony_ci		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
182962306a36Sopenharmony_ci				      DMA_TO_DEVICE);
183062306a36Sopenharmony_ci	/*
183162306a36Sopenharmony_ci	 * data in
183262306a36Sopenharmony_ci	 */
183362306a36Sopenharmony_ci	if (is_sec1 && req_ctx->nbuf) {
183462306a36Sopenharmony_ci		map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
183562306a36Sopenharmony_ci				       req_ctx->buf[req_ctx->buf_idx],
183662306a36Sopenharmony_ci				       DMA_TO_DEVICE);
183762306a36Sopenharmony_ci	} else {
183862306a36Sopenharmony_ci		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
183962306a36Sopenharmony_ci					  &desc->ptr[3], sg_count, 0, 0);
184062306a36Sopenharmony_ci		if (sg_count > 1)
184162306a36Sopenharmony_ci			sync_needed = true;
184262306a36Sopenharmony_ci	}
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci	/* fifth DWORD empty */
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci	/* hash/HMAC out -or- hash context out */
184762306a36Sopenharmony_ci	if (req_ctx->last)
184862306a36Sopenharmony_ci		map_single_talitos_ptr(dev, &desc->ptr[5],
184962306a36Sopenharmony_ci				       crypto_ahash_digestsize(tfm),
185062306a36Sopenharmony_ci				       req_ctx->hw_context, DMA_FROM_DEVICE);
185162306a36Sopenharmony_ci	else
185262306a36Sopenharmony_ci		map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
185362306a36Sopenharmony_ci					      req_ctx->hw_context_size,
185462306a36Sopenharmony_ci					      req_ctx->hw_context,
185562306a36Sopenharmony_ci					      DMA_FROM_DEVICE);
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci	/* last DWORD empty */
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
186062306a36Sopenharmony_ci		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_ci	if (is_sec1 && req_ctx->nbuf && length) {
186362306a36Sopenharmony_ci		struct talitos_desc *desc2 = (struct talitos_desc *)
186462306a36Sopenharmony_ci					     (edesc->buf + edesc->dma_len);
186562306a36Sopenharmony_ci		dma_addr_t next_desc;
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci		memset(desc2, 0, sizeof(*desc2));
186862306a36Sopenharmony_ci		desc2->hdr = desc->hdr;
186962306a36Sopenharmony_ci		desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
187062306a36Sopenharmony_ci		desc2->hdr1 = desc2->hdr;
187162306a36Sopenharmony_ci		desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
187262306a36Sopenharmony_ci		desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
187362306a36Sopenharmony_ci		desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci		if (desc->ptr[1].ptr)
187662306a36Sopenharmony_ci			copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
187762306a36Sopenharmony_ci					 is_sec1);
187862306a36Sopenharmony_ci		else
187962306a36Sopenharmony_ci			map_single_talitos_ptr_nosync(dev, &desc2->ptr[1],
188062306a36Sopenharmony_ci						      req_ctx->hw_context_size,
188162306a36Sopenharmony_ci						      req_ctx->hw_context,
188262306a36Sopenharmony_ci						      DMA_TO_DEVICE);
188362306a36Sopenharmony_ci		copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
188462306a36Sopenharmony_ci		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
188562306a36Sopenharmony_ci					  &desc2->ptr[3], sg_count, 0, 0);
188662306a36Sopenharmony_ci		if (sg_count > 1)
188762306a36Sopenharmony_ci			sync_needed = true;
188862306a36Sopenharmony_ci		copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
188962306a36Sopenharmony_ci		if (req_ctx->last)
189062306a36Sopenharmony_ci			map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
189162306a36Sopenharmony_ci						      req_ctx->hw_context_size,
189262306a36Sopenharmony_ci						      req_ctx->hw_context,
189362306a36Sopenharmony_ci						      DMA_FROM_DEVICE);
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci		next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE,
189662306a36Sopenharmony_ci					   DMA_BIDIRECTIONAL);
189762306a36Sopenharmony_ci		desc->next_desc = cpu_to_be32(next_desc);
189862306a36Sopenharmony_ci	}
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_ci	if (sync_needed)
190162306a36Sopenharmony_ci		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
190262306a36Sopenharmony_ci					   edesc->dma_len, DMA_BIDIRECTIONAL);
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
190562306a36Sopenharmony_ci	if (ret != -EINPROGRESS) {
190662306a36Sopenharmony_ci		common_nonsnoop_hash_unmap(dev, edesc, areq);
190762306a36Sopenharmony_ci		kfree(edesc);
190862306a36Sopenharmony_ci	}
190962306a36Sopenharmony_ci	return ret;
191062306a36Sopenharmony_ci}
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_cistatic struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
191362306a36Sopenharmony_ci					       unsigned int nbytes)
191462306a36Sopenharmony_ci{
191562306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
191662306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
191762306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
191862306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
191962306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
192062306a36Sopenharmony_ci
192162306a36Sopenharmony_ci	if (is_sec1)
192262306a36Sopenharmony_ci		nbytes -= req_ctx->nbuf;
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
192562306a36Sopenharmony_ci				   nbytes, 0, 0, 0, areq->base.flags, false);
192662306a36Sopenharmony_ci}
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_cistatic int ahash_init(struct ahash_request *areq)
192962306a36Sopenharmony_ci{
193062306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
193162306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
193262306a36Sopenharmony_ci	struct device *dev = ctx->dev;
193362306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
193462306a36Sopenharmony_ci	unsigned int size;
193562306a36Sopenharmony_ci	dma_addr_t dma;
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	/* Initialize the context */
193862306a36Sopenharmony_ci	req_ctx->buf_idx = 0;
193962306a36Sopenharmony_ci	req_ctx->nbuf = 0;
194062306a36Sopenharmony_ci	req_ctx->first = 1; /* first indicates h/w must init its context */
194162306a36Sopenharmony_ci	req_ctx->swinit = 0; /* assume h/w init of context */
194262306a36Sopenharmony_ci	size =	(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
194362306a36Sopenharmony_ci			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
194462306a36Sopenharmony_ci			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
194562306a36Sopenharmony_ci	req_ctx->hw_context_size = size;
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
194862306a36Sopenharmony_ci			     DMA_TO_DEVICE);
194962306a36Sopenharmony_ci	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_ci	return 0;
195262306a36Sopenharmony_ci}
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_ci/*
195562306a36Sopenharmony_ci * on h/w without explicit sha224 support, we initialize h/w context
195662306a36Sopenharmony_ci * manually with sha224 constants, and tell it to run sha256.
195762306a36Sopenharmony_ci */
195862306a36Sopenharmony_cistatic int ahash_init_sha224_swinit(struct ahash_request *areq)
195962306a36Sopenharmony_ci{
196062306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	req_ctx->hw_context[0] = SHA224_H0;
196362306a36Sopenharmony_ci	req_ctx->hw_context[1] = SHA224_H1;
196462306a36Sopenharmony_ci	req_ctx->hw_context[2] = SHA224_H2;
196562306a36Sopenharmony_ci	req_ctx->hw_context[3] = SHA224_H3;
196662306a36Sopenharmony_ci	req_ctx->hw_context[4] = SHA224_H4;
196762306a36Sopenharmony_ci	req_ctx->hw_context[5] = SHA224_H5;
196862306a36Sopenharmony_ci	req_ctx->hw_context[6] = SHA224_H6;
196962306a36Sopenharmony_ci	req_ctx->hw_context[7] = SHA224_H7;
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci	/* init 64-bit count */
197262306a36Sopenharmony_ci	req_ctx->hw_context[8] = 0;
197362306a36Sopenharmony_ci	req_ctx->hw_context[9] = 0;
197462306a36Sopenharmony_ci
197562306a36Sopenharmony_ci	ahash_init(areq);
197662306a36Sopenharmony_ci	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_ci	return 0;
197962306a36Sopenharmony_ci}
198062306a36Sopenharmony_ci
198162306a36Sopenharmony_cistatic int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
198262306a36Sopenharmony_ci{
198362306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
198462306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
198562306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
198662306a36Sopenharmony_ci	struct talitos_edesc *edesc;
198762306a36Sopenharmony_ci	unsigned int blocksize =
198862306a36Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
198962306a36Sopenharmony_ci	unsigned int nbytes_to_hash;
199062306a36Sopenharmony_ci	unsigned int to_hash_later;
199162306a36Sopenharmony_ci	unsigned int nsg;
199262306a36Sopenharmony_ci	int nents;
199362306a36Sopenharmony_ci	struct device *dev = ctx->dev;
199462306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
199562306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
199662306a36Sopenharmony_ci	u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
199962306a36Sopenharmony_ci		/* Buffer up to one whole block */
200062306a36Sopenharmony_ci		nents = sg_nents_for_len(areq->src, nbytes);
200162306a36Sopenharmony_ci		if (nents < 0) {
200262306a36Sopenharmony_ci			dev_err(dev, "Invalid number of src SG.\n");
200362306a36Sopenharmony_ci			return nents;
200462306a36Sopenharmony_ci		}
200562306a36Sopenharmony_ci		sg_copy_to_buffer(areq->src, nents,
200662306a36Sopenharmony_ci				  ctx_buf + req_ctx->nbuf, nbytes);
200762306a36Sopenharmony_ci		req_ctx->nbuf += nbytes;
200862306a36Sopenharmony_ci		return 0;
200962306a36Sopenharmony_ci	}
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_ci	/* At least (blocksize + 1) bytes are available to hash */
201262306a36Sopenharmony_ci	nbytes_to_hash = nbytes + req_ctx->nbuf;
201362306a36Sopenharmony_ci	to_hash_later = nbytes_to_hash & (blocksize - 1);
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	if (req_ctx->last)
201662306a36Sopenharmony_ci		to_hash_later = 0;
201762306a36Sopenharmony_ci	else if (to_hash_later)
201862306a36Sopenharmony_ci		/* There is a partial block. Hash the full block(s) now */
201962306a36Sopenharmony_ci		nbytes_to_hash -= to_hash_later;
202062306a36Sopenharmony_ci	else {
202162306a36Sopenharmony_ci		/* Keep one block buffered */
202262306a36Sopenharmony_ci		nbytes_to_hash -= blocksize;
202362306a36Sopenharmony_ci		to_hash_later = blocksize;
202462306a36Sopenharmony_ci	}
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_ci	/* Chain in any previously buffered data */
202762306a36Sopenharmony_ci	if (!is_sec1 && req_ctx->nbuf) {
202862306a36Sopenharmony_ci		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
202962306a36Sopenharmony_ci		sg_init_table(req_ctx->bufsl, nsg);
203062306a36Sopenharmony_ci		sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
203162306a36Sopenharmony_ci		if (nsg > 1)
203262306a36Sopenharmony_ci			sg_chain(req_ctx->bufsl, 2, areq->src);
203362306a36Sopenharmony_ci		req_ctx->psrc = req_ctx->bufsl;
203462306a36Sopenharmony_ci	} else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
203562306a36Sopenharmony_ci		int offset;
203662306a36Sopenharmony_ci
203762306a36Sopenharmony_ci		if (nbytes_to_hash > blocksize)
203862306a36Sopenharmony_ci			offset = blocksize - req_ctx->nbuf;
203962306a36Sopenharmony_ci		else
204062306a36Sopenharmony_ci			offset = nbytes_to_hash - req_ctx->nbuf;
204162306a36Sopenharmony_ci		nents = sg_nents_for_len(areq->src, offset);
204262306a36Sopenharmony_ci		if (nents < 0) {
204362306a36Sopenharmony_ci			dev_err(dev, "Invalid number of src SG.\n");
204462306a36Sopenharmony_ci			return nents;
204562306a36Sopenharmony_ci		}
204662306a36Sopenharmony_ci		sg_copy_to_buffer(areq->src, nents,
204762306a36Sopenharmony_ci				  ctx_buf + req_ctx->nbuf, offset);
204862306a36Sopenharmony_ci		req_ctx->nbuf += offset;
204962306a36Sopenharmony_ci		req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, areq->src,
205062306a36Sopenharmony_ci						 offset);
205162306a36Sopenharmony_ci	} else
205262306a36Sopenharmony_ci		req_ctx->psrc = areq->src;
205362306a36Sopenharmony_ci
205462306a36Sopenharmony_ci	if (to_hash_later) {
205562306a36Sopenharmony_ci		nents = sg_nents_for_len(areq->src, nbytes);
205662306a36Sopenharmony_ci		if (nents < 0) {
205762306a36Sopenharmony_ci			dev_err(dev, "Invalid number of src SG.\n");
205862306a36Sopenharmony_ci			return nents;
205962306a36Sopenharmony_ci		}
206062306a36Sopenharmony_ci		sg_pcopy_to_buffer(areq->src, nents,
206162306a36Sopenharmony_ci				   req_ctx->buf[(req_ctx->buf_idx + 1) & 1],
206262306a36Sopenharmony_ci				      to_hash_later,
206362306a36Sopenharmony_ci				      nbytes - to_hash_later);
206462306a36Sopenharmony_ci	}
206562306a36Sopenharmony_ci	req_ctx->to_hash_later = to_hash_later;
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_ci	/* Allocate extended descriptor */
206862306a36Sopenharmony_ci	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
206962306a36Sopenharmony_ci	if (IS_ERR(edesc))
207062306a36Sopenharmony_ci		return PTR_ERR(edesc);
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_ci	edesc->desc.hdr = ctx->desc_hdr_template;
207362306a36Sopenharmony_ci
207462306a36Sopenharmony_ci	/* On last one, request SEC to pad; otherwise continue */
207562306a36Sopenharmony_ci	if (req_ctx->last)
207662306a36Sopenharmony_ci		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
207762306a36Sopenharmony_ci	else
207862306a36Sopenharmony_ci		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
207962306a36Sopenharmony_ci
208062306a36Sopenharmony_ci	/* request SEC to INIT hash. */
208162306a36Sopenharmony_ci	if (req_ctx->first && !req_ctx->swinit)
208262306a36Sopenharmony_ci		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
208362306a36Sopenharmony_ci
208462306a36Sopenharmony_ci	/* When the tfm context has a keylen, it's an HMAC.
208562306a36Sopenharmony_ci	 * A first or last (ie. not middle) descriptor must request HMAC.
208662306a36Sopenharmony_ci	 */
208762306a36Sopenharmony_ci	if (ctx->keylen && (req_ctx->first || req_ctx->last))
208862306a36Sopenharmony_ci		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, ahash_done);
209162306a36Sopenharmony_ci}
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_cistatic int ahash_update(struct ahash_request *areq)
209462306a36Sopenharmony_ci{
209562306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_ci	req_ctx->last = 0;
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci	return ahash_process_req(areq, areq->nbytes);
210062306a36Sopenharmony_ci}
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_cistatic int ahash_final(struct ahash_request *areq)
210362306a36Sopenharmony_ci{
210462306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci	req_ctx->last = 1;
210762306a36Sopenharmony_ci
210862306a36Sopenharmony_ci	return ahash_process_req(areq, 0);
210962306a36Sopenharmony_ci}
211062306a36Sopenharmony_ci
211162306a36Sopenharmony_cistatic int ahash_finup(struct ahash_request *areq)
211262306a36Sopenharmony_ci{
211362306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_ci	req_ctx->last = 1;
211662306a36Sopenharmony_ci
211762306a36Sopenharmony_ci	return ahash_process_req(areq, areq->nbytes);
211862306a36Sopenharmony_ci}
211962306a36Sopenharmony_ci
212062306a36Sopenharmony_cistatic int ahash_digest(struct ahash_request *areq)
212162306a36Sopenharmony_ci{
212262306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
212362306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci	ahash->init(areq);
212662306a36Sopenharmony_ci	req_ctx->last = 1;
212762306a36Sopenharmony_ci
212862306a36Sopenharmony_ci	return ahash_process_req(areq, areq->nbytes);
212962306a36Sopenharmony_ci}
213062306a36Sopenharmony_ci
213162306a36Sopenharmony_cistatic int ahash_export(struct ahash_request *areq, void *out)
213262306a36Sopenharmony_ci{
213362306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
213462306a36Sopenharmony_ci	struct talitos_export_state *export = out;
213562306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
213662306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
213762306a36Sopenharmony_ci	struct device *dev = ctx->dev;
213862306a36Sopenharmony_ci	dma_addr_t dma;
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ci	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
214162306a36Sopenharmony_ci			     DMA_FROM_DEVICE);
214262306a36Sopenharmony_ci	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE);
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci	memcpy(export->hw_context, req_ctx->hw_context,
214562306a36Sopenharmony_ci	       req_ctx->hw_context_size);
214662306a36Sopenharmony_ci	memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf);
214762306a36Sopenharmony_ci	export->swinit = req_ctx->swinit;
214862306a36Sopenharmony_ci	export->first = req_ctx->first;
214962306a36Sopenharmony_ci	export->last = req_ctx->last;
215062306a36Sopenharmony_ci	export->to_hash_later = req_ctx->to_hash_later;
215162306a36Sopenharmony_ci	export->nbuf = req_ctx->nbuf;
215262306a36Sopenharmony_ci
215362306a36Sopenharmony_ci	return 0;
215462306a36Sopenharmony_ci}
215562306a36Sopenharmony_ci
215662306a36Sopenharmony_cistatic int ahash_import(struct ahash_request *areq, const void *in)
215762306a36Sopenharmony_ci{
215862306a36Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
215962306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
216062306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
216162306a36Sopenharmony_ci	struct device *dev = ctx->dev;
216262306a36Sopenharmony_ci	const struct talitos_export_state *export = in;
216362306a36Sopenharmony_ci	unsigned int size;
216462306a36Sopenharmony_ci	dma_addr_t dma;
216562306a36Sopenharmony_ci
216662306a36Sopenharmony_ci	memset(req_ctx, 0, sizeof(*req_ctx));
216762306a36Sopenharmony_ci	size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
216862306a36Sopenharmony_ci			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
216962306a36Sopenharmony_ci			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
217062306a36Sopenharmony_ci	req_ctx->hw_context_size = size;
217162306a36Sopenharmony_ci	memcpy(req_ctx->hw_context, export->hw_context, size);
217262306a36Sopenharmony_ci	memcpy(req_ctx->buf[0], export->buf, export->nbuf);
217362306a36Sopenharmony_ci	req_ctx->swinit = export->swinit;
217462306a36Sopenharmony_ci	req_ctx->first = export->first;
217562306a36Sopenharmony_ci	req_ctx->last = export->last;
217662306a36Sopenharmony_ci	req_ctx->to_hash_later = export->to_hash_later;
217762306a36Sopenharmony_ci	req_ctx->nbuf = export->nbuf;
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
218062306a36Sopenharmony_ci			     DMA_TO_DEVICE);
218162306a36Sopenharmony_ci	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
218262306a36Sopenharmony_ci
218362306a36Sopenharmony_ci	return 0;
218462306a36Sopenharmony_ci}
218562306a36Sopenharmony_ci
218662306a36Sopenharmony_cistatic int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
218762306a36Sopenharmony_ci		   u8 *hash)
218862306a36Sopenharmony_ci{
218962306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci	struct scatterlist sg[1];
219262306a36Sopenharmony_ci	struct ahash_request *req;
219362306a36Sopenharmony_ci	struct crypto_wait wait;
219462306a36Sopenharmony_ci	int ret;
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci	crypto_init_wait(&wait);
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci	req = ahash_request_alloc(tfm, GFP_KERNEL);
219962306a36Sopenharmony_ci	if (!req)
220062306a36Sopenharmony_ci		return -ENOMEM;
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_ci	/* Keep tfm keylen == 0 during hash of the long key */
220362306a36Sopenharmony_ci	ctx->keylen = 0;
220462306a36Sopenharmony_ci	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
220562306a36Sopenharmony_ci				   crypto_req_done, &wait);
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci	sg_init_one(&sg[0], key, keylen);
220862306a36Sopenharmony_ci
220962306a36Sopenharmony_ci	ahash_request_set_crypt(req, sg, hash, keylen);
221062306a36Sopenharmony_ci	ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_ci	ahash_request_free(req);
221362306a36Sopenharmony_ci
221462306a36Sopenharmony_ci	return ret;
221562306a36Sopenharmony_ci}
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_cistatic int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
221862306a36Sopenharmony_ci			unsigned int keylen)
221962306a36Sopenharmony_ci{
222062306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
222162306a36Sopenharmony_ci	struct device *dev = ctx->dev;
222262306a36Sopenharmony_ci	unsigned int blocksize =
222362306a36Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
222462306a36Sopenharmony_ci	unsigned int digestsize = crypto_ahash_digestsize(tfm);
222562306a36Sopenharmony_ci	unsigned int keysize = keylen;
222662306a36Sopenharmony_ci	u8 hash[SHA512_DIGEST_SIZE];
222762306a36Sopenharmony_ci	int ret;
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci	if (keylen <= blocksize)
223062306a36Sopenharmony_ci		memcpy(ctx->key, key, keysize);
223162306a36Sopenharmony_ci	else {
223262306a36Sopenharmony_ci		/* Must get the hash of the long key */
223362306a36Sopenharmony_ci		ret = keyhash(tfm, key, keylen, hash);
223462306a36Sopenharmony_ci
223562306a36Sopenharmony_ci		if (ret)
223662306a36Sopenharmony_ci			return -EINVAL;
223762306a36Sopenharmony_ci
223862306a36Sopenharmony_ci		keysize = digestsize;
223962306a36Sopenharmony_ci		memcpy(ctx->key, hash, digestsize);
224062306a36Sopenharmony_ci	}
224162306a36Sopenharmony_ci
224262306a36Sopenharmony_ci	if (ctx->keylen)
224362306a36Sopenharmony_ci		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_ci	ctx->keylen = keysize;
224662306a36Sopenharmony_ci	ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE);
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	return 0;
224962306a36Sopenharmony_ci}
225062306a36Sopenharmony_ci
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_cistruct talitos_alg_template {
225362306a36Sopenharmony_ci	u32 type;
225462306a36Sopenharmony_ci	u32 priority;
225562306a36Sopenharmony_ci	union {
225662306a36Sopenharmony_ci		struct skcipher_alg skcipher;
225762306a36Sopenharmony_ci		struct ahash_alg hash;
225862306a36Sopenharmony_ci		struct aead_alg aead;
225962306a36Sopenharmony_ci	} alg;
226062306a36Sopenharmony_ci	__be32 desc_hdr_template;
226162306a36Sopenharmony_ci};
226262306a36Sopenharmony_ci
226362306a36Sopenharmony_cistatic struct talitos_alg_template driver_algs[] = {
226462306a36Sopenharmony_ci	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
226562306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
226662306a36Sopenharmony_ci		.alg.aead = {
226762306a36Sopenharmony_ci			.base = {
226862306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),cbc(aes))",
226962306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha1-"
227062306a36Sopenharmony_ci						   "cbc-aes-talitos",
227162306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
227262306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
227362306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
227462306a36Sopenharmony_ci			},
227562306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
227662306a36Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
227762306a36Sopenharmony_ci		},
227862306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
227962306a36Sopenharmony_ci			             DESC_HDR_SEL0_AESU |
228062306a36Sopenharmony_ci		                     DESC_HDR_MODE0_AESU_CBC |
228162306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
228262306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
228362306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
228462306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
228562306a36Sopenharmony_ci	},
228662306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
228762306a36Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
228862306a36Sopenharmony_ci		.alg.aead = {
228962306a36Sopenharmony_ci			.base = {
229062306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),cbc(aes))",
229162306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha1-"
229262306a36Sopenharmony_ci						   "cbc-aes-talitos-hsna",
229362306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
229462306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
229562306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
229662306a36Sopenharmony_ci			},
229762306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
229862306a36Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
229962306a36Sopenharmony_ci		},
230062306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
230162306a36Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
230262306a36Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC |
230362306a36Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
230462306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
230562306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
230662306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
230762306a36Sopenharmony_ci	},
230862306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
230962306a36Sopenharmony_ci		.alg.aead = {
231062306a36Sopenharmony_ci			.base = {
231162306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),"
231262306a36Sopenharmony_ci					    "cbc(des3_ede))",
231362306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha1-"
231462306a36Sopenharmony_ci						   "cbc-3des-talitos",
231562306a36Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
231662306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
231762306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
231862306a36Sopenharmony_ci			},
231962306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
232062306a36Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
232162306a36Sopenharmony_ci			.setkey = aead_des3_setkey,
232262306a36Sopenharmony_ci		},
232362306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
232462306a36Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
232562306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
232662306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
232762306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
232862306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
232962306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
233062306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
233162306a36Sopenharmony_ci	},
233262306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
233362306a36Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
233462306a36Sopenharmony_ci		.alg.aead = {
233562306a36Sopenharmony_ci			.base = {
233662306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),"
233762306a36Sopenharmony_ci					    "cbc(des3_ede))",
233862306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha1-"
233962306a36Sopenharmony_ci						   "cbc-3des-talitos-hsna",
234062306a36Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
234162306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
234262306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
234362306a36Sopenharmony_ci			},
234462306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
234562306a36Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
234662306a36Sopenharmony_ci			.setkey = aead_des3_setkey,
234762306a36Sopenharmony_ci		},
234862306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
234962306a36Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
235062306a36Sopenharmony_ci				     DESC_HDR_MODE0_DEU_CBC |
235162306a36Sopenharmony_ci				     DESC_HDR_MODE0_DEU_3DES |
235262306a36Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
235362306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
235462306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
235562306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
235662306a36Sopenharmony_ci	},
235762306a36Sopenharmony_ci	{       .type = CRYPTO_ALG_TYPE_AEAD,
235862306a36Sopenharmony_ci		.alg.aead = {
235962306a36Sopenharmony_ci			.base = {
236062306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),cbc(aes))",
236162306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha224-"
236262306a36Sopenharmony_ci						   "cbc-aes-talitos",
236362306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
236462306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
236562306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
236662306a36Sopenharmony_ci			},
236762306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
236862306a36Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
236962306a36Sopenharmony_ci		},
237062306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
237162306a36Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
237262306a36Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC |
237362306a36Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
237462306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
237562306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
237662306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
237762306a36Sopenharmony_ci	},
237862306a36Sopenharmony_ci	{       .type = CRYPTO_ALG_TYPE_AEAD,
237962306a36Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
238062306a36Sopenharmony_ci		.alg.aead = {
238162306a36Sopenharmony_ci			.base = {
238262306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),cbc(aes))",
238362306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha224-"
238462306a36Sopenharmony_ci						   "cbc-aes-talitos-hsna",
238562306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
238662306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
238762306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
238862306a36Sopenharmony_ci			},
238962306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
239062306a36Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
239162306a36Sopenharmony_ci		},
239262306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
239362306a36Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
239462306a36Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC |
239562306a36Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
239662306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
239762306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
239862306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
239962306a36Sopenharmony_ci	},
240062306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
240162306a36Sopenharmony_ci		.alg.aead = {
240262306a36Sopenharmony_ci			.base = {
240362306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),"
240462306a36Sopenharmony_ci					    "cbc(des3_ede))",
240562306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha224-"
240662306a36Sopenharmony_ci						   "cbc-3des-talitos",
240762306a36Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
240862306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
240962306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
241062306a36Sopenharmony_ci			},
241162306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
241262306a36Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
241362306a36Sopenharmony_ci			.setkey = aead_des3_setkey,
241462306a36Sopenharmony_ci		},
241562306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
241662306a36Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
241762306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
241862306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
241962306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
242062306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
242162306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
242262306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
242362306a36Sopenharmony_ci	},
242462306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
242562306a36Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
242662306a36Sopenharmony_ci		.alg.aead = {
242762306a36Sopenharmony_ci			.base = {
242862306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),"
242962306a36Sopenharmony_ci					    "cbc(des3_ede))",
243062306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha224-"
243162306a36Sopenharmony_ci						   "cbc-3des-talitos-hsna",
243262306a36Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
243362306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
243462306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
243562306a36Sopenharmony_ci			},
243662306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
243762306a36Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
243862306a36Sopenharmony_ci			.setkey = aead_des3_setkey,
243962306a36Sopenharmony_ci		},
244062306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
244162306a36Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
244262306a36Sopenharmony_ci				     DESC_HDR_MODE0_DEU_CBC |
244362306a36Sopenharmony_ci				     DESC_HDR_MODE0_DEU_3DES |
244462306a36Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
244562306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
244662306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
244762306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
244862306a36Sopenharmony_ci	},
244962306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
245062306a36Sopenharmony_ci		.alg.aead = {
245162306a36Sopenharmony_ci			.base = {
245262306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),cbc(aes))",
245362306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha256-"
245462306a36Sopenharmony_ci						   "cbc-aes-talitos",
245562306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
245662306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
245762306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
245862306a36Sopenharmony_ci			},
245962306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
246062306a36Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
246162306a36Sopenharmony_ci		},
246262306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
246362306a36Sopenharmony_ci			             DESC_HDR_SEL0_AESU |
246462306a36Sopenharmony_ci		                     DESC_HDR_MODE0_AESU_CBC |
246562306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
246662306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
246762306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
246862306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
246962306a36Sopenharmony_ci	},
247062306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
247162306a36Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
247262306a36Sopenharmony_ci		.alg.aead = {
247362306a36Sopenharmony_ci			.base = {
247462306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),cbc(aes))",
247562306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha256-"
247662306a36Sopenharmony_ci						   "cbc-aes-talitos-hsna",
247762306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
247862306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
247962306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
248062306a36Sopenharmony_ci			},
248162306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
248262306a36Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
248362306a36Sopenharmony_ci		},
248462306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
248562306a36Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
248662306a36Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC |
248762306a36Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
248862306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
248962306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
249062306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
249162306a36Sopenharmony_ci	},
249262306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
249362306a36Sopenharmony_ci		.alg.aead = {
249462306a36Sopenharmony_ci			.base = {
249562306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),"
249662306a36Sopenharmony_ci					    "cbc(des3_ede))",
249762306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha256-"
249862306a36Sopenharmony_ci						   "cbc-3des-talitos",
249962306a36Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
250062306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
250162306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
250262306a36Sopenharmony_ci			},
250362306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
250462306a36Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
250562306a36Sopenharmony_ci			.setkey = aead_des3_setkey,
250662306a36Sopenharmony_ci		},
250762306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
250862306a36Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
250962306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
251062306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
251162306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
251262306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
251362306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
251462306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
251562306a36Sopenharmony_ci	},
251662306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
251762306a36Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
251862306a36Sopenharmony_ci		.alg.aead = {
251962306a36Sopenharmony_ci			.base = {
252062306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),"
252162306a36Sopenharmony_ci					    "cbc(des3_ede))",
252262306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha256-"
252362306a36Sopenharmony_ci						   "cbc-3des-talitos-hsna",
252462306a36Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
252562306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
252662306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
252762306a36Sopenharmony_ci			},
252862306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
252962306a36Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
253062306a36Sopenharmony_ci			.setkey = aead_des3_setkey,
253162306a36Sopenharmony_ci		},
253262306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
253362306a36Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
253462306a36Sopenharmony_ci				     DESC_HDR_MODE0_DEU_CBC |
253562306a36Sopenharmony_ci				     DESC_HDR_MODE0_DEU_3DES |
253662306a36Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
253762306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
253862306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
253962306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
254062306a36Sopenharmony_ci	},
254162306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
254262306a36Sopenharmony_ci		.alg.aead = {
254362306a36Sopenharmony_ci			.base = {
254462306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha384),cbc(aes))",
254562306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha384-"
254662306a36Sopenharmony_ci						   "cbc-aes-talitos",
254762306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
254862306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
254962306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
255062306a36Sopenharmony_ci			},
255162306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
255262306a36Sopenharmony_ci			.maxauthsize = SHA384_DIGEST_SIZE,
255362306a36Sopenharmony_ci		},
255462306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
255562306a36Sopenharmony_ci			             DESC_HDR_SEL0_AESU |
255662306a36Sopenharmony_ci		                     DESC_HDR_MODE0_AESU_CBC |
255762306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUB |
255862306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
255962306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
256062306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
256162306a36Sopenharmony_ci	},
256262306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
256362306a36Sopenharmony_ci		.alg.aead = {
256462306a36Sopenharmony_ci			.base = {
256562306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha384),"
256662306a36Sopenharmony_ci					    "cbc(des3_ede))",
256762306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha384-"
256862306a36Sopenharmony_ci						   "cbc-3des-talitos",
256962306a36Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
257062306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
257162306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
257262306a36Sopenharmony_ci			},
257362306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
257462306a36Sopenharmony_ci			.maxauthsize = SHA384_DIGEST_SIZE,
257562306a36Sopenharmony_ci			.setkey = aead_des3_setkey,
257662306a36Sopenharmony_ci		},
257762306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
257862306a36Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
257962306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
258062306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
258162306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUB |
258262306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
258362306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
258462306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
258562306a36Sopenharmony_ci	},
258662306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
258762306a36Sopenharmony_ci		.alg.aead = {
258862306a36Sopenharmony_ci			.base = {
258962306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha512),cbc(aes))",
259062306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha512-"
259162306a36Sopenharmony_ci						   "cbc-aes-talitos",
259262306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
259362306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
259462306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
259562306a36Sopenharmony_ci			},
259662306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
259762306a36Sopenharmony_ci			.maxauthsize = SHA512_DIGEST_SIZE,
259862306a36Sopenharmony_ci		},
259962306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
260062306a36Sopenharmony_ci			             DESC_HDR_SEL0_AESU |
260162306a36Sopenharmony_ci		                     DESC_HDR_MODE0_AESU_CBC |
260262306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUB |
260362306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
260462306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
260562306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
260662306a36Sopenharmony_ci	},
260762306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
260862306a36Sopenharmony_ci		.alg.aead = {
260962306a36Sopenharmony_ci			.base = {
261062306a36Sopenharmony_ci				.cra_name = "authenc(hmac(sha512),"
261162306a36Sopenharmony_ci					    "cbc(des3_ede))",
261262306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha512-"
261362306a36Sopenharmony_ci						   "cbc-3des-talitos",
261462306a36Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
261562306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
261662306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
261762306a36Sopenharmony_ci			},
261862306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
261962306a36Sopenharmony_ci			.maxauthsize = SHA512_DIGEST_SIZE,
262062306a36Sopenharmony_ci			.setkey = aead_des3_setkey,
262162306a36Sopenharmony_ci		},
262262306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
262362306a36Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
262462306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
262562306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
262662306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUB |
262762306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
262862306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
262962306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
263062306a36Sopenharmony_ci	},
263162306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
263262306a36Sopenharmony_ci		.alg.aead = {
263362306a36Sopenharmony_ci			.base = {
263462306a36Sopenharmony_ci				.cra_name = "authenc(hmac(md5),cbc(aes))",
263562306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-md5-"
263662306a36Sopenharmony_ci						   "cbc-aes-talitos",
263762306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
263862306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
263962306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
264062306a36Sopenharmony_ci			},
264162306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
264262306a36Sopenharmony_ci			.maxauthsize = MD5_DIGEST_SIZE,
264362306a36Sopenharmony_ci		},
264462306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
264562306a36Sopenharmony_ci			             DESC_HDR_SEL0_AESU |
264662306a36Sopenharmony_ci		                     DESC_HDR_MODE0_AESU_CBC |
264762306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
264862306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
264962306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
265062306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
265162306a36Sopenharmony_ci	},
265262306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
265362306a36Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
265462306a36Sopenharmony_ci		.alg.aead = {
265562306a36Sopenharmony_ci			.base = {
265662306a36Sopenharmony_ci				.cra_name = "authenc(hmac(md5),cbc(aes))",
265762306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-md5-"
265862306a36Sopenharmony_ci						   "cbc-aes-talitos-hsna",
265962306a36Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
266062306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
266162306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
266262306a36Sopenharmony_ci			},
266362306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
266462306a36Sopenharmony_ci			.maxauthsize = MD5_DIGEST_SIZE,
266562306a36Sopenharmony_ci		},
266662306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
266762306a36Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
266862306a36Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC |
266962306a36Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
267062306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
267162306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
267262306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
267362306a36Sopenharmony_ci	},
267462306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
267562306a36Sopenharmony_ci		.alg.aead = {
267662306a36Sopenharmony_ci			.base = {
267762306a36Sopenharmony_ci				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
267862306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-md5-"
267962306a36Sopenharmony_ci						   "cbc-3des-talitos",
268062306a36Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
268162306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
268262306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
268362306a36Sopenharmony_ci			},
268462306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
268562306a36Sopenharmony_ci			.maxauthsize = MD5_DIGEST_SIZE,
268662306a36Sopenharmony_ci			.setkey = aead_des3_setkey,
268762306a36Sopenharmony_ci		},
268862306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
268962306a36Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
269062306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
269162306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
269262306a36Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
269362306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
269462306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
269562306a36Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
269662306a36Sopenharmony_ci	},
269762306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
269862306a36Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
269962306a36Sopenharmony_ci		.alg.aead = {
270062306a36Sopenharmony_ci			.base = {
270162306a36Sopenharmony_ci				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
270262306a36Sopenharmony_ci				.cra_driver_name = "authenc-hmac-md5-"
270362306a36Sopenharmony_ci						   "cbc-3des-talitos-hsna",
270462306a36Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
270562306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
270662306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
270762306a36Sopenharmony_ci			},
270862306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
270962306a36Sopenharmony_ci			.maxauthsize = MD5_DIGEST_SIZE,
271062306a36Sopenharmony_ci			.setkey = aead_des3_setkey,
271162306a36Sopenharmony_ci		},
271262306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
271362306a36Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
271462306a36Sopenharmony_ci				     DESC_HDR_MODE0_DEU_CBC |
271562306a36Sopenharmony_ci				     DESC_HDR_MODE0_DEU_3DES |
271662306a36Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
271762306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
271862306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
271962306a36Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
272062306a36Sopenharmony_ci	},
272162306a36Sopenharmony_ci	/* SKCIPHER algorithms. */
272262306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
272362306a36Sopenharmony_ci		.alg.skcipher = {
272462306a36Sopenharmony_ci			.base.cra_name = "ecb(aes)",
272562306a36Sopenharmony_ci			.base.cra_driver_name = "ecb-aes-talitos",
272662306a36Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
272762306a36Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
272862306a36Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
272962306a36Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
273062306a36Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
273162306a36Sopenharmony_ci			.setkey = skcipher_aes_setkey,
273262306a36Sopenharmony_ci		},
273362306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
273462306a36Sopenharmony_ci				     DESC_HDR_SEL0_AESU,
273562306a36Sopenharmony_ci	},
273662306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
273762306a36Sopenharmony_ci		.alg.skcipher = {
273862306a36Sopenharmony_ci			.base.cra_name = "cbc(aes)",
273962306a36Sopenharmony_ci			.base.cra_driver_name = "cbc-aes-talitos",
274062306a36Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
274162306a36Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
274262306a36Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
274362306a36Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
274462306a36Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
274562306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
274662306a36Sopenharmony_ci			.setkey = skcipher_aes_setkey,
274762306a36Sopenharmony_ci		},
274862306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
274962306a36Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
275062306a36Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC,
275162306a36Sopenharmony_ci	},
275262306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
275362306a36Sopenharmony_ci		.alg.skcipher = {
275462306a36Sopenharmony_ci			.base.cra_name = "ctr(aes)",
275562306a36Sopenharmony_ci			.base.cra_driver_name = "ctr-aes-talitos",
275662306a36Sopenharmony_ci			.base.cra_blocksize = 1,
275762306a36Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
275862306a36Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
275962306a36Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
276062306a36Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
276162306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
276262306a36Sopenharmony_ci			.setkey = skcipher_aes_setkey,
276362306a36Sopenharmony_ci		},
276462306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
276562306a36Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
276662306a36Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CTR,
276762306a36Sopenharmony_ci	},
276862306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
276962306a36Sopenharmony_ci		.alg.skcipher = {
277062306a36Sopenharmony_ci			.base.cra_name = "ctr(aes)",
277162306a36Sopenharmony_ci			.base.cra_driver_name = "ctr-aes-talitos",
277262306a36Sopenharmony_ci			.base.cra_blocksize = 1,
277362306a36Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
277462306a36Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
277562306a36Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
277662306a36Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
277762306a36Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
277862306a36Sopenharmony_ci			.setkey = skcipher_aes_setkey,
277962306a36Sopenharmony_ci		},
278062306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
278162306a36Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
278262306a36Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CTR,
278362306a36Sopenharmony_ci	},
278462306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
278562306a36Sopenharmony_ci		.alg.skcipher = {
278662306a36Sopenharmony_ci			.base.cra_name = "ecb(des)",
278762306a36Sopenharmony_ci			.base.cra_driver_name = "ecb-des-talitos",
278862306a36Sopenharmony_ci			.base.cra_blocksize = DES_BLOCK_SIZE,
278962306a36Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
279062306a36Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
279162306a36Sopenharmony_ci			.min_keysize = DES_KEY_SIZE,
279262306a36Sopenharmony_ci			.max_keysize = DES_KEY_SIZE,
279362306a36Sopenharmony_ci			.setkey = skcipher_des_setkey,
279462306a36Sopenharmony_ci		},
279562306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
279662306a36Sopenharmony_ci				     DESC_HDR_SEL0_DEU,
279762306a36Sopenharmony_ci	},
279862306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
279962306a36Sopenharmony_ci		.alg.skcipher = {
280062306a36Sopenharmony_ci			.base.cra_name = "cbc(des)",
280162306a36Sopenharmony_ci			.base.cra_driver_name = "cbc-des-talitos",
280262306a36Sopenharmony_ci			.base.cra_blocksize = DES_BLOCK_SIZE,
280362306a36Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
280462306a36Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
280562306a36Sopenharmony_ci			.min_keysize = DES_KEY_SIZE,
280662306a36Sopenharmony_ci			.max_keysize = DES_KEY_SIZE,
280762306a36Sopenharmony_ci			.ivsize = DES_BLOCK_SIZE,
280862306a36Sopenharmony_ci			.setkey = skcipher_des_setkey,
280962306a36Sopenharmony_ci		},
281062306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
281162306a36Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
281262306a36Sopenharmony_ci				     DESC_HDR_MODE0_DEU_CBC,
281362306a36Sopenharmony_ci	},
281462306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
281562306a36Sopenharmony_ci		.alg.skcipher = {
281662306a36Sopenharmony_ci			.base.cra_name = "ecb(des3_ede)",
281762306a36Sopenharmony_ci			.base.cra_driver_name = "ecb-3des-talitos",
281862306a36Sopenharmony_ci			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
281962306a36Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
282062306a36Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
282162306a36Sopenharmony_ci			.min_keysize = DES3_EDE_KEY_SIZE,
282262306a36Sopenharmony_ci			.max_keysize = DES3_EDE_KEY_SIZE,
282362306a36Sopenharmony_ci			.setkey = skcipher_des3_setkey,
282462306a36Sopenharmony_ci		},
282562306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
282662306a36Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
282762306a36Sopenharmony_ci				     DESC_HDR_MODE0_DEU_3DES,
282862306a36Sopenharmony_ci	},
282962306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
283062306a36Sopenharmony_ci		.alg.skcipher = {
283162306a36Sopenharmony_ci			.base.cra_name = "cbc(des3_ede)",
283262306a36Sopenharmony_ci			.base.cra_driver_name = "cbc-3des-talitos",
283362306a36Sopenharmony_ci			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
283462306a36Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
283562306a36Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
283662306a36Sopenharmony_ci			.min_keysize = DES3_EDE_KEY_SIZE,
283762306a36Sopenharmony_ci			.max_keysize = DES3_EDE_KEY_SIZE,
283862306a36Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
283962306a36Sopenharmony_ci			.setkey = skcipher_des3_setkey,
284062306a36Sopenharmony_ci		},
284162306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
284262306a36Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
284362306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
284462306a36Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES,
284562306a36Sopenharmony_ci	},
284662306a36Sopenharmony_ci	/* AHASH algorithms. */
284762306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
284862306a36Sopenharmony_ci		.alg.hash = {
284962306a36Sopenharmony_ci			.halg.digestsize = MD5_DIGEST_SIZE,
285062306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
285162306a36Sopenharmony_ci			.halg.base = {
285262306a36Sopenharmony_ci				.cra_name = "md5",
285362306a36Sopenharmony_ci				.cra_driver_name = "md5-talitos",
285462306a36Sopenharmony_ci				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
285562306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
285662306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
285762306a36Sopenharmony_ci			}
285862306a36Sopenharmony_ci		},
285962306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
286062306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
286162306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_MD5,
286262306a36Sopenharmony_ci	},
286362306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
286462306a36Sopenharmony_ci		.alg.hash = {
286562306a36Sopenharmony_ci			.halg.digestsize = SHA1_DIGEST_SIZE,
286662306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
286762306a36Sopenharmony_ci			.halg.base = {
286862306a36Sopenharmony_ci				.cra_name = "sha1",
286962306a36Sopenharmony_ci				.cra_driver_name = "sha1-talitos",
287062306a36Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
287162306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
287262306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
287362306a36Sopenharmony_ci			}
287462306a36Sopenharmony_ci		},
287562306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
287662306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
287762306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA1,
287862306a36Sopenharmony_ci	},
287962306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
288062306a36Sopenharmony_ci		.alg.hash = {
288162306a36Sopenharmony_ci			.halg.digestsize = SHA224_DIGEST_SIZE,
288262306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
288362306a36Sopenharmony_ci			.halg.base = {
288462306a36Sopenharmony_ci				.cra_name = "sha224",
288562306a36Sopenharmony_ci				.cra_driver_name = "sha224-talitos",
288662306a36Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
288762306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
288862306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
288962306a36Sopenharmony_ci			}
289062306a36Sopenharmony_ci		},
289162306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
289262306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
289362306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA224,
289462306a36Sopenharmony_ci	},
289562306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
289662306a36Sopenharmony_ci		.alg.hash = {
289762306a36Sopenharmony_ci			.halg.digestsize = SHA256_DIGEST_SIZE,
289862306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
289962306a36Sopenharmony_ci			.halg.base = {
290062306a36Sopenharmony_ci				.cra_name = "sha256",
290162306a36Sopenharmony_ci				.cra_driver_name = "sha256-talitos",
290262306a36Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
290362306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
290462306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
290562306a36Sopenharmony_ci			}
290662306a36Sopenharmony_ci		},
290762306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
290862306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
290962306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA256,
291062306a36Sopenharmony_ci	},
291162306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
291262306a36Sopenharmony_ci		.alg.hash = {
291362306a36Sopenharmony_ci			.halg.digestsize = SHA384_DIGEST_SIZE,
291462306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
291562306a36Sopenharmony_ci			.halg.base = {
291662306a36Sopenharmony_ci				.cra_name = "sha384",
291762306a36Sopenharmony_ci				.cra_driver_name = "sha384-talitos",
291862306a36Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
291962306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
292062306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
292162306a36Sopenharmony_ci			}
292262306a36Sopenharmony_ci		},
292362306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
292462306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUB |
292562306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEUB_SHA384,
292662306a36Sopenharmony_ci	},
292762306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
292862306a36Sopenharmony_ci		.alg.hash = {
292962306a36Sopenharmony_ci			.halg.digestsize = SHA512_DIGEST_SIZE,
293062306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
293162306a36Sopenharmony_ci			.halg.base = {
293262306a36Sopenharmony_ci				.cra_name = "sha512",
293362306a36Sopenharmony_ci				.cra_driver_name = "sha512-talitos",
293462306a36Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
293562306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
293662306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
293762306a36Sopenharmony_ci			}
293862306a36Sopenharmony_ci		},
293962306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
294062306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUB |
294162306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEUB_SHA512,
294262306a36Sopenharmony_ci	},
294362306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
294462306a36Sopenharmony_ci		.alg.hash = {
294562306a36Sopenharmony_ci			.halg.digestsize = MD5_DIGEST_SIZE,
294662306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
294762306a36Sopenharmony_ci			.halg.base = {
294862306a36Sopenharmony_ci				.cra_name = "hmac(md5)",
294962306a36Sopenharmony_ci				.cra_driver_name = "hmac-md5-talitos",
295062306a36Sopenharmony_ci				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
295162306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
295262306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
295362306a36Sopenharmony_ci			}
295462306a36Sopenharmony_ci		},
295562306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
295662306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
295762306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_MD5,
295862306a36Sopenharmony_ci	},
295962306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
296062306a36Sopenharmony_ci		.alg.hash = {
296162306a36Sopenharmony_ci			.halg.digestsize = SHA1_DIGEST_SIZE,
296262306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
296362306a36Sopenharmony_ci			.halg.base = {
296462306a36Sopenharmony_ci				.cra_name = "hmac(sha1)",
296562306a36Sopenharmony_ci				.cra_driver_name = "hmac-sha1-talitos",
296662306a36Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
296762306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
296862306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
296962306a36Sopenharmony_ci			}
297062306a36Sopenharmony_ci		},
297162306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
297262306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
297362306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA1,
297462306a36Sopenharmony_ci	},
297562306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
297662306a36Sopenharmony_ci		.alg.hash = {
297762306a36Sopenharmony_ci			.halg.digestsize = SHA224_DIGEST_SIZE,
297862306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
297962306a36Sopenharmony_ci			.halg.base = {
298062306a36Sopenharmony_ci				.cra_name = "hmac(sha224)",
298162306a36Sopenharmony_ci				.cra_driver_name = "hmac-sha224-talitos",
298262306a36Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
298362306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
298462306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
298562306a36Sopenharmony_ci			}
298662306a36Sopenharmony_ci		},
298762306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
298862306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
298962306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA224,
299062306a36Sopenharmony_ci	},
299162306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
299262306a36Sopenharmony_ci		.alg.hash = {
299362306a36Sopenharmony_ci			.halg.digestsize = SHA256_DIGEST_SIZE,
299462306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
299562306a36Sopenharmony_ci			.halg.base = {
299662306a36Sopenharmony_ci				.cra_name = "hmac(sha256)",
299762306a36Sopenharmony_ci				.cra_driver_name = "hmac-sha256-talitos",
299862306a36Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
299962306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
300062306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
300162306a36Sopenharmony_ci			}
300262306a36Sopenharmony_ci		},
300362306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
300462306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
300562306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA256,
300662306a36Sopenharmony_ci	},
300762306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
300862306a36Sopenharmony_ci		.alg.hash = {
300962306a36Sopenharmony_ci			.halg.digestsize = SHA384_DIGEST_SIZE,
301062306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
301162306a36Sopenharmony_ci			.halg.base = {
301262306a36Sopenharmony_ci				.cra_name = "hmac(sha384)",
301362306a36Sopenharmony_ci				.cra_driver_name = "hmac-sha384-talitos",
301462306a36Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
301562306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
301662306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
301762306a36Sopenharmony_ci			}
301862306a36Sopenharmony_ci		},
301962306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
302062306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUB |
302162306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEUB_SHA384,
302262306a36Sopenharmony_ci	},
302362306a36Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
302462306a36Sopenharmony_ci		.alg.hash = {
302562306a36Sopenharmony_ci			.halg.digestsize = SHA512_DIGEST_SIZE,
302662306a36Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
302762306a36Sopenharmony_ci			.halg.base = {
302862306a36Sopenharmony_ci				.cra_name = "hmac(sha512)",
302962306a36Sopenharmony_ci				.cra_driver_name = "hmac-sha512-talitos",
303062306a36Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
303162306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
303262306a36Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
303362306a36Sopenharmony_ci			}
303462306a36Sopenharmony_ci		},
303562306a36Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
303662306a36Sopenharmony_ci				     DESC_HDR_SEL0_MDEUB |
303762306a36Sopenharmony_ci				     DESC_HDR_MODE0_MDEUB_SHA512,
303862306a36Sopenharmony_ci	}
303962306a36Sopenharmony_ci};
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_cistruct talitos_crypto_alg {
304262306a36Sopenharmony_ci	struct list_head entry;
304362306a36Sopenharmony_ci	struct device *dev;
304462306a36Sopenharmony_ci	struct talitos_alg_template algt;
304562306a36Sopenharmony_ci};
304662306a36Sopenharmony_ci
304762306a36Sopenharmony_cistatic int talitos_init_common(struct talitos_ctx *ctx,
304862306a36Sopenharmony_ci			       struct talitos_crypto_alg *talitos_alg)
304962306a36Sopenharmony_ci{
305062306a36Sopenharmony_ci	struct talitos_private *priv;
305162306a36Sopenharmony_ci
305262306a36Sopenharmony_ci	/* update context with ptr to dev */
305362306a36Sopenharmony_ci	ctx->dev = talitos_alg->dev;
305462306a36Sopenharmony_ci
305562306a36Sopenharmony_ci	/* assign SEC channel to tfm in round-robin fashion */
305662306a36Sopenharmony_ci	priv = dev_get_drvdata(ctx->dev);
305762306a36Sopenharmony_ci	ctx->ch = atomic_inc_return(&priv->last_chan) &
305862306a36Sopenharmony_ci		  (priv->num_channels - 1);
305962306a36Sopenharmony_ci
306062306a36Sopenharmony_ci	/* copy descriptor header template value */
306162306a36Sopenharmony_ci	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
306262306a36Sopenharmony_ci
306362306a36Sopenharmony_ci	/* select done notification */
306462306a36Sopenharmony_ci	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
306562306a36Sopenharmony_ci
306662306a36Sopenharmony_ci	return 0;
306762306a36Sopenharmony_ci}
306862306a36Sopenharmony_ci
306962306a36Sopenharmony_cistatic int talitos_cra_init_aead(struct crypto_aead *tfm)
307062306a36Sopenharmony_ci{
307162306a36Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(tfm);
307262306a36Sopenharmony_ci	struct talitos_crypto_alg *talitos_alg;
307362306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
307462306a36Sopenharmony_ci
307562306a36Sopenharmony_ci	talitos_alg = container_of(alg, struct talitos_crypto_alg,
307662306a36Sopenharmony_ci				   algt.alg.aead);
307762306a36Sopenharmony_ci
307862306a36Sopenharmony_ci	return talitos_init_common(ctx, talitos_alg);
307962306a36Sopenharmony_ci}
308062306a36Sopenharmony_ci
308162306a36Sopenharmony_cistatic int talitos_cra_init_skcipher(struct crypto_skcipher *tfm)
308262306a36Sopenharmony_ci{
308362306a36Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
308462306a36Sopenharmony_ci	struct talitos_crypto_alg *talitos_alg;
308562306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(tfm);
308662306a36Sopenharmony_ci
308762306a36Sopenharmony_ci	talitos_alg = container_of(alg, struct talitos_crypto_alg,
308862306a36Sopenharmony_ci				   algt.alg.skcipher);
308962306a36Sopenharmony_ci
309062306a36Sopenharmony_ci	return talitos_init_common(ctx, talitos_alg);
309162306a36Sopenharmony_ci}
309262306a36Sopenharmony_ci
309362306a36Sopenharmony_cistatic int talitos_cra_init_ahash(struct crypto_tfm *tfm)
309462306a36Sopenharmony_ci{
309562306a36Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
309662306a36Sopenharmony_ci	struct talitos_crypto_alg *talitos_alg;
309762306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
309862306a36Sopenharmony_ci
309962306a36Sopenharmony_ci	talitos_alg = container_of(__crypto_ahash_alg(alg),
310062306a36Sopenharmony_ci				   struct talitos_crypto_alg,
310162306a36Sopenharmony_ci				   algt.alg.hash);
310262306a36Sopenharmony_ci
310362306a36Sopenharmony_ci	ctx->keylen = 0;
310462306a36Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
310562306a36Sopenharmony_ci				 sizeof(struct talitos_ahash_req_ctx));
310662306a36Sopenharmony_ci
310762306a36Sopenharmony_ci	return talitos_init_common(ctx, talitos_alg);
310862306a36Sopenharmony_ci}
310962306a36Sopenharmony_ci
311062306a36Sopenharmony_cistatic void talitos_cra_exit(struct crypto_tfm *tfm)
311162306a36Sopenharmony_ci{
311262306a36Sopenharmony_ci	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
311362306a36Sopenharmony_ci	struct device *dev = ctx->dev;
311462306a36Sopenharmony_ci
311562306a36Sopenharmony_ci	if (ctx->keylen)
311662306a36Sopenharmony_ci		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
311762306a36Sopenharmony_ci}
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_ci/*
312062306a36Sopenharmony_ci * given the alg's descriptor header template, determine whether descriptor
312162306a36Sopenharmony_ci * type and primary/secondary execution units required match the hw
312262306a36Sopenharmony_ci * capabilities description provided in the device tree node.
312362306a36Sopenharmony_ci */
312462306a36Sopenharmony_cistatic int hw_supports(struct device *dev, __be32 desc_hdr_template)
312562306a36Sopenharmony_ci{
312662306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
312762306a36Sopenharmony_ci	int ret;
312862306a36Sopenharmony_ci
312962306a36Sopenharmony_ci	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
313062306a36Sopenharmony_ci	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
313162306a36Sopenharmony_ci
313262306a36Sopenharmony_ci	if (SECONDARY_EU(desc_hdr_template))
313362306a36Sopenharmony_ci		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
313462306a36Sopenharmony_ci		              & priv->exec_units);
313562306a36Sopenharmony_ci
313662306a36Sopenharmony_ci	return ret;
313762306a36Sopenharmony_ci}
313862306a36Sopenharmony_ci
313962306a36Sopenharmony_cistatic int talitos_remove(struct platform_device *ofdev)
314062306a36Sopenharmony_ci{
314162306a36Sopenharmony_ci	struct device *dev = &ofdev->dev;
314262306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
314362306a36Sopenharmony_ci	struct talitos_crypto_alg *t_alg, *n;
314462306a36Sopenharmony_ci	int i;
314562306a36Sopenharmony_ci
314662306a36Sopenharmony_ci	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
314762306a36Sopenharmony_ci		switch (t_alg->algt.type) {
314862306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
314962306a36Sopenharmony_ci			crypto_unregister_skcipher(&t_alg->algt.alg.skcipher);
315062306a36Sopenharmony_ci			break;
315162306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
315262306a36Sopenharmony_ci			crypto_unregister_aead(&t_alg->algt.alg.aead);
315362306a36Sopenharmony_ci			break;
315462306a36Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
315562306a36Sopenharmony_ci			crypto_unregister_ahash(&t_alg->algt.alg.hash);
315662306a36Sopenharmony_ci			break;
315762306a36Sopenharmony_ci		}
315862306a36Sopenharmony_ci		list_del(&t_alg->entry);
315962306a36Sopenharmony_ci	}
316062306a36Sopenharmony_ci
316162306a36Sopenharmony_ci	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
316262306a36Sopenharmony_ci		talitos_unregister_rng(dev);
316362306a36Sopenharmony_ci
316462306a36Sopenharmony_ci	for (i = 0; i < 2; i++)
316562306a36Sopenharmony_ci		if (priv->irq[i]) {
316662306a36Sopenharmony_ci			free_irq(priv->irq[i], dev);
316762306a36Sopenharmony_ci			irq_dispose_mapping(priv->irq[i]);
316862306a36Sopenharmony_ci		}
316962306a36Sopenharmony_ci
317062306a36Sopenharmony_ci	tasklet_kill(&priv->done_task[0]);
317162306a36Sopenharmony_ci	if (priv->irq[1])
317262306a36Sopenharmony_ci		tasklet_kill(&priv->done_task[1]);
317362306a36Sopenharmony_ci
317462306a36Sopenharmony_ci	return 0;
317562306a36Sopenharmony_ci}
317662306a36Sopenharmony_ci
317762306a36Sopenharmony_cistatic struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
317862306a36Sopenharmony_ci						    struct talitos_alg_template
317962306a36Sopenharmony_ci						           *template)
318062306a36Sopenharmony_ci{
318162306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
318262306a36Sopenharmony_ci	struct talitos_crypto_alg *t_alg;
318362306a36Sopenharmony_ci	struct crypto_alg *alg;
318462306a36Sopenharmony_ci
318562306a36Sopenharmony_ci	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
318662306a36Sopenharmony_ci			     GFP_KERNEL);
318762306a36Sopenharmony_ci	if (!t_alg)
318862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
318962306a36Sopenharmony_ci
319062306a36Sopenharmony_ci	t_alg->algt = *template;
319162306a36Sopenharmony_ci
319262306a36Sopenharmony_ci	switch (t_alg->algt.type) {
319362306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
319462306a36Sopenharmony_ci		alg = &t_alg->algt.alg.skcipher.base;
319562306a36Sopenharmony_ci		alg->cra_exit = talitos_cra_exit;
319662306a36Sopenharmony_ci		t_alg->algt.alg.skcipher.init = talitos_cra_init_skcipher;
319762306a36Sopenharmony_ci		t_alg->algt.alg.skcipher.setkey =
319862306a36Sopenharmony_ci			t_alg->algt.alg.skcipher.setkey ?: skcipher_setkey;
319962306a36Sopenharmony_ci		t_alg->algt.alg.skcipher.encrypt = skcipher_encrypt;
320062306a36Sopenharmony_ci		t_alg->algt.alg.skcipher.decrypt = skcipher_decrypt;
320162306a36Sopenharmony_ci		if (!strcmp(alg->cra_name, "ctr(aes)") && !has_ftr_sec1(priv) &&
320262306a36Sopenharmony_ci		    DESC_TYPE(t_alg->algt.desc_hdr_template) !=
320362306a36Sopenharmony_ci		    DESC_TYPE(DESC_HDR_TYPE_AESU_CTR_NONSNOOP)) {
320462306a36Sopenharmony_ci			devm_kfree(dev, t_alg);
320562306a36Sopenharmony_ci			return ERR_PTR(-ENOTSUPP);
320662306a36Sopenharmony_ci		}
320762306a36Sopenharmony_ci		break;
320862306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
320962306a36Sopenharmony_ci		alg = &t_alg->algt.alg.aead.base;
321062306a36Sopenharmony_ci		alg->cra_exit = talitos_cra_exit;
321162306a36Sopenharmony_ci		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
321262306a36Sopenharmony_ci		t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?:
321362306a36Sopenharmony_ci					      aead_setkey;
321462306a36Sopenharmony_ci		t_alg->algt.alg.aead.encrypt = aead_encrypt;
321562306a36Sopenharmony_ci		t_alg->algt.alg.aead.decrypt = aead_decrypt;
321662306a36Sopenharmony_ci		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
321762306a36Sopenharmony_ci		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
321862306a36Sopenharmony_ci			devm_kfree(dev, t_alg);
321962306a36Sopenharmony_ci			return ERR_PTR(-ENOTSUPP);
322062306a36Sopenharmony_ci		}
322162306a36Sopenharmony_ci		break;
322262306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_AHASH:
322362306a36Sopenharmony_ci		alg = &t_alg->algt.alg.hash.halg.base;
322462306a36Sopenharmony_ci		alg->cra_init = talitos_cra_init_ahash;
322562306a36Sopenharmony_ci		alg->cra_exit = talitos_cra_exit;
322662306a36Sopenharmony_ci		t_alg->algt.alg.hash.init = ahash_init;
322762306a36Sopenharmony_ci		t_alg->algt.alg.hash.update = ahash_update;
322862306a36Sopenharmony_ci		t_alg->algt.alg.hash.final = ahash_final;
322962306a36Sopenharmony_ci		t_alg->algt.alg.hash.finup = ahash_finup;
323062306a36Sopenharmony_ci		t_alg->algt.alg.hash.digest = ahash_digest;
323162306a36Sopenharmony_ci		if (!strncmp(alg->cra_name, "hmac", 4))
323262306a36Sopenharmony_ci			t_alg->algt.alg.hash.setkey = ahash_setkey;
323362306a36Sopenharmony_ci		t_alg->algt.alg.hash.import = ahash_import;
323462306a36Sopenharmony_ci		t_alg->algt.alg.hash.export = ahash_export;
323562306a36Sopenharmony_ci
323662306a36Sopenharmony_ci		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
323762306a36Sopenharmony_ci		    !strncmp(alg->cra_name, "hmac", 4)) {
323862306a36Sopenharmony_ci			devm_kfree(dev, t_alg);
323962306a36Sopenharmony_ci			return ERR_PTR(-ENOTSUPP);
324062306a36Sopenharmony_ci		}
324162306a36Sopenharmony_ci		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
324262306a36Sopenharmony_ci		    (!strcmp(alg->cra_name, "sha224") ||
324362306a36Sopenharmony_ci		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
324462306a36Sopenharmony_ci			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
324562306a36Sopenharmony_ci			t_alg->algt.desc_hdr_template =
324662306a36Sopenharmony_ci					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
324762306a36Sopenharmony_ci					DESC_HDR_SEL0_MDEUA |
324862306a36Sopenharmony_ci					DESC_HDR_MODE0_MDEU_SHA256;
324962306a36Sopenharmony_ci		}
325062306a36Sopenharmony_ci		break;
325162306a36Sopenharmony_ci	default:
325262306a36Sopenharmony_ci		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
325362306a36Sopenharmony_ci		devm_kfree(dev, t_alg);
325462306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
325562306a36Sopenharmony_ci	}
325662306a36Sopenharmony_ci
325762306a36Sopenharmony_ci	alg->cra_module = THIS_MODULE;
325862306a36Sopenharmony_ci	if (t_alg->algt.priority)
325962306a36Sopenharmony_ci		alg->cra_priority = t_alg->algt.priority;
326062306a36Sopenharmony_ci	else
326162306a36Sopenharmony_ci		alg->cra_priority = TALITOS_CRA_PRIORITY;
326262306a36Sopenharmony_ci	if (has_ftr_sec1(priv))
326362306a36Sopenharmony_ci		alg->cra_alignmask = 3;
326462306a36Sopenharmony_ci	else
326562306a36Sopenharmony_ci		alg->cra_alignmask = 0;
326662306a36Sopenharmony_ci	alg->cra_ctxsize = sizeof(struct talitos_ctx);
326762306a36Sopenharmony_ci	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ci	t_alg->dev = dev;
327062306a36Sopenharmony_ci
327162306a36Sopenharmony_ci	return t_alg;
327262306a36Sopenharmony_ci}
327362306a36Sopenharmony_ci
327462306a36Sopenharmony_cistatic int talitos_probe_irq(struct platform_device *ofdev)
327562306a36Sopenharmony_ci{
327662306a36Sopenharmony_ci	struct device *dev = &ofdev->dev;
327762306a36Sopenharmony_ci	struct device_node *np = ofdev->dev.of_node;
327862306a36Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
327962306a36Sopenharmony_ci	int err;
328062306a36Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
328162306a36Sopenharmony_ci
328262306a36Sopenharmony_ci	priv->irq[0] = irq_of_parse_and_map(np, 0);
328362306a36Sopenharmony_ci	if (!priv->irq[0]) {
328462306a36Sopenharmony_ci		dev_err(dev, "failed to map irq\n");
328562306a36Sopenharmony_ci		return -EINVAL;
328662306a36Sopenharmony_ci	}
328762306a36Sopenharmony_ci	if (is_sec1) {
328862306a36Sopenharmony_ci		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
328962306a36Sopenharmony_ci				  dev_driver_string(dev), dev);
329062306a36Sopenharmony_ci		goto primary_out;
329162306a36Sopenharmony_ci	}
329262306a36Sopenharmony_ci
329362306a36Sopenharmony_ci	priv->irq[1] = irq_of_parse_and_map(np, 1);
329462306a36Sopenharmony_ci
329562306a36Sopenharmony_ci	/* get the primary irq line */
329662306a36Sopenharmony_ci	if (!priv->irq[1]) {
329762306a36Sopenharmony_ci		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
329862306a36Sopenharmony_ci				  dev_driver_string(dev), dev);
329962306a36Sopenharmony_ci		goto primary_out;
330062306a36Sopenharmony_ci	}
330162306a36Sopenharmony_ci
330262306a36Sopenharmony_ci	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
330362306a36Sopenharmony_ci			  dev_driver_string(dev), dev);
330462306a36Sopenharmony_ci	if (err)
330562306a36Sopenharmony_ci		goto primary_out;
330662306a36Sopenharmony_ci
330762306a36Sopenharmony_ci	/* get the secondary irq line */
330862306a36Sopenharmony_ci	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
330962306a36Sopenharmony_ci			  dev_driver_string(dev), dev);
331062306a36Sopenharmony_ci	if (err) {
331162306a36Sopenharmony_ci		dev_err(dev, "failed to request secondary irq\n");
331262306a36Sopenharmony_ci		irq_dispose_mapping(priv->irq[1]);
331362306a36Sopenharmony_ci		priv->irq[1] = 0;
331462306a36Sopenharmony_ci	}
331562306a36Sopenharmony_ci
331662306a36Sopenharmony_ci	return err;
331762306a36Sopenharmony_ci
331862306a36Sopenharmony_ciprimary_out:
331962306a36Sopenharmony_ci	if (err) {
332062306a36Sopenharmony_ci		dev_err(dev, "failed to request primary irq\n");
332162306a36Sopenharmony_ci		irq_dispose_mapping(priv->irq[0]);
332262306a36Sopenharmony_ci		priv->irq[0] = 0;
332362306a36Sopenharmony_ci	}
332462306a36Sopenharmony_ci
332562306a36Sopenharmony_ci	return err;
332662306a36Sopenharmony_ci}
332762306a36Sopenharmony_ci
332862306a36Sopenharmony_cistatic int talitos_probe(struct platform_device *ofdev)
332962306a36Sopenharmony_ci{
333062306a36Sopenharmony_ci	struct device *dev = &ofdev->dev;
333162306a36Sopenharmony_ci	struct device_node *np = ofdev->dev.of_node;
333262306a36Sopenharmony_ci	struct talitos_private *priv;
333362306a36Sopenharmony_ci	int i, err;
333462306a36Sopenharmony_ci	int stride;
333562306a36Sopenharmony_ci	struct resource *res;
333662306a36Sopenharmony_ci
333762306a36Sopenharmony_ci	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
333862306a36Sopenharmony_ci	if (!priv)
333962306a36Sopenharmony_ci		return -ENOMEM;
334062306a36Sopenharmony_ci
334162306a36Sopenharmony_ci	INIT_LIST_HEAD(&priv->alg_list);
334262306a36Sopenharmony_ci
334362306a36Sopenharmony_ci	dev_set_drvdata(dev, priv);
334462306a36Sopenharmony_ci
334562306a36Sopenharmony_ci	priv->ofdev = ofdev;
334662306a36Sopenharmony_ci
334762306a36Sopenharmony_ci	spin_lock_init(&priv->reg_lock);
334862306a36Sopenharmony_ci
334962306a36Sopenharmony_ci	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
335062306a36Sopenharmony_ci	if (!res)
335162306a36Sopenharmony_ci		return -ENXIO;
335262306a36Sopenharmony_ci	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
335362306a36Sopenharmony_ci	if (!priv->reg) {
335462306a36Sopenharmony_ci		dev_err(dev, "failed to of_iomap\n");
335562306a36Sopenharmony_ci		err = -ENOMEM;
335662306a36Sopenharmony_ci		goto err_out;
335762306a36Sopenharmony_ci	}
335862306a36Sopenharmony_ci
335962306a36Sopenharmony_ci	/* get SEC version capabilities from device tree */
336062306a36Sopenharmony_ci	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
336162306a36Sopenharmony_ci	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
336262306a36Sopenharmony_ci	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
336362306a36Sopenharmony_ci	of_property_read_u32(np, "fsl,descriptor-types-mask",
336462306a36Sopenharmony_ci			     &priv->desc_types);
336562306a36Sopenharmony_ci
336662306a36Sopenharmony_ci	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
336762306a36Sopenharmony_ci	    !priv->exec_units || !priv->desc_types) {
336862306a36Sopenharmony_ci		dev_err(dev, "invalid property data in device tree node\n");
336962306a36Sopenharmony_ci		err = -EINVAL;
337062306a36Sopenharmony_ci		goto err_out;
337162306a36Sopenharmony_ci	}
337262306a36Sopenharmony_ci
337362306a36Sopenharmony_ci	if (of_device_is_compatible(np, "fsl,sec3.0"))
337462306a36Sopenharmony_ci		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
337562306a36Sopenharmony_ci
337662306a36Sopenharmony_ci	if (of_device_is_compatible(np, "fsl,sec2.1"))
337762306a36Sopenharmony_ci		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
337862306a36Sopenharmony_ci				  TALITOS_FTR_SHA224_HWINIT |
337962306a36Sopenharmony_ci				  TALITOS_FTR_HMAC_OK;
338062306a36Sopenharmony_ci
338162306a36Sopenharmony_ci	if (of_device_is_compatible(np, "fsl,sec1.0"))
338262306a36Sopenharmony_ci		priv->features |= TALITOS_FTR_SEC1;
338362306a36Sopenharmony_ci
338462306a36Sopenharmony_ci	if (of_device_is_compatible(np, "fsl,sec1.2")) {
338562306a36Sopenharmony_ci		priv->reg_deu = priv->reg + TALITOS12_DEU;
338662306a36Sopenharmony_ci		priv->reg_aesu = priv->reg + TALITOS12_AESU;
338762306a36Sopenharmony_ci		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
338862306a36Sopenharmony_ci		stride = TALITOS1_CH_STRIDE;
338962306a36Sopenharmony_ci	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
339062306a36Sopenharmony_ci		priv->reg_deu = priv->reg + TALITOS10_DEU;
339162306a36Sopenharmony_ci		priv->reg_aesu = priv->reg + TALITOS10_AESU;
339262306a36Sopenharmony_ci		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
339362306a36Sopenharmony_ci		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
339462306a36Sopenharmony_ci		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
339562306a36Sopenharmony_ci		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
339662306a36Sopenharmony_ci		stride = TALITOS1_CH_STRIDE;
339762306a36Sopenharmony_ci	} else {
339862306a36Sopenharmony_ci		priv->reg_deu = priv->reg + TALITOS2_DEU;
339962306a36Sopenharmony_ci		priv->reg_aesu = priv->reg + TALITOS2_AESU;
340062306a36Sopenharmony_ci		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
340162306a36Sopenharmony_ci		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
340262306a36Sopenharmony_ci		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
340362306a36Sopenharmony_ci		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
340462306a36Sopenharmony_ci		priv->reg_keu = priv->reg + TALITOS2_KEU;
340562306a36Sopenharmony_ci		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
340662306a36Sopenharmony_ci		stride = TALITOS2_CH_STRIDE;
340762306a36Sopenharmony_ci	}
340862306a36Sopenharmony_ci
340962306a36Sopenharmony_ci	err = talitos_probe_irq(ofdev);
341062306a36Sopenharmony_ci	if (err)
341162306a36Sopenharmony_ci		goto err_out;
341262306a36Sopenharmony_ci
341362306a36Sopenharmony_ci	if (has_ftr_sec1(priv)) {
341462306a36Sopenharmony_ci		if (priv->num_channels == 1)
341562306a36Sopenharmony_ci			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
341662306a36Sopenharmony_ci				     (unsigned long)dev);
341762306a36Sopenharmony_ci		else
341862306a36Sopenharmony_ci			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
341962306a36Sopenharmony_ci				     (unsigned long)dev);
342062306a36Sopenharmony_ci	} else {
342162306a36Sopenharmony_ci		if (priv->irq[1]) {
342262306a36Sopenharmony_ci			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
342362306a36Sopenharmony_ci				     (unsigned long)dev);
342462306a36Sopenharmony_ci			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
342562306a36Sopenharmony_ci				     (unsigned long)dev);
342662306a36Sopenharmony_ci		} else if (priv->num_channels == 1) {
342762306a36Sopenharmony_ci			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
342862306a36Sopenharmony_ci				     (unsigned long)dev);
342962306a36Sopenharmony_ci		} else {
343062306a36Sopenharmony_ci			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
343162306a36Sopenharmony_ci				     (unsigned long)dev);
343262306a36Sopenharmony_ci		}
343362306a36Sopenharmony_ci	}
343462306a36Sopenharmony_ci
343562306a36Sopenharmony_ci	priv->chan = devm_kcalloc(dev,
343662306a36Sopenharmony_ci				  priv->num_channels,
343762306a36Sopenharmony_ci				  sizeof(struct talitos_channel),
343862306a36Sopenharmony_ci				  GFP_KERNEL);
343962306a36Sopenharmony_ci	if (!priv->chan) {
344062306a36Sopenharmony_ci		dev_err(dev, "failed to allocate channel management space\n");
344162306a36Sopenharmony_ci		err = -ENOMEM;
344262306a36Sopenharmony_ci		goto err_out;
344362306a36Sopenharmony_ci	}
344462306a36Sopenharmony_ci
344562306a36Sopenharmony_ci	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
344662306a36Sopenharmony_ci
344762306a36Sopenharmony_ci	for (i = 0; i < priv->num_channels; i++) {
344862306a36Sopenharmony_ci		priv->chan[i].reg = priv->reg + stride * (i + 1);
344962306a36Sopenharmony_ci		if (!priv->irq[1] || !(i & 1))
345062306a36Sopenharmony_ci			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
345162306a36Sopenharmony_ci
345262306a36Sopenharmony_ci		spin_lock_init(&priv->chan[i].head_lock);
345362306a36Sopenharmony_ci		spin_lock_init(&priv->chan[i].tail_lock);
345462306a36Sopenharmony_ci
345562306a36Sopenharmony_ci		priv->chan[i].fifo = devm_kcalloc(dev,
345662306a36Sopenharmony_ci						priv->fifo_len,
345762306a36Sopenharmony_ci						sizeof(struct talitos_request),
345862306a36Sopenharmony_ci						GFP_KERNEL);
345962306a36Sopenharmony_ci		if (!priv->chan[i].fifo) {
346062306a36Sopenharmony_ci			dev_err(dev, "failed to allocate request fifo %d\n", i);
346162306a36Sopenharmony_ci			err = -ENOMEM;
346262306a36Sopenharmony_ci			goto err_out;
346362306a36Sopenharmony_ci		}
346462306a36Sopenharmony_ci
346562306a36Sopenharmony_ci		atomic_set(&priv->chan[i].submit_count,
346662306a36Sopenharmony_ci			   -(priv->chfifo_len - 1));
346762306a36Sopenharmony_ci	}
346862306a36Sopenharmony_ci
346962306a36Sopenharmony_ci	dma_set_mask(dev, DMA_BIT_MASK(36));
347062306a36Sopenharmony_ci
347162306a36Sopenharmony_ci	/* reset and initialize the h/w */
347262306a36Sopenharmony_ci	err = init_device(dev);
347362306a36Sopenharmony_ci	if (err) {
347462306a36Sopenharmony_ci		dev_err(dev, "failed to initialize device\n");
347562306a36Sopenharmony_ci		goto err_out;
347662306a36Sopenharmony_ci	}
347762306a36Sopenharmony_ci
347862306a36Sopenharmony_ci	/* register the RNG, if available */
347962306a36Sopenharmony_ci	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
348062306a36Sopenharmony_ci		err = talitos_register_rng(dev);
348162306a36Sopenharmony_ci		if (err) {
348262306a36Sopenharmony_ci			dev_err(dev, "failed to register hwrng: %d\n", err);
348362306a36Sopenharmony_ci			goto err_out;
348462306a36Sopenharmony_ci		} else
348562306a36Sopenharmony_ci			dev_info(dev, "hwrng\n");
348662306a36Sopenharmony_ci	}
348762306a36Sopenharmony_ci
348862306a36Sopenharmony_ci	/* register crypto algorithms the device supports */
348962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
349062306a36Sopenharmony_ci		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
349162306a36Sopenharmony_ci			struct talitos_crypto_alg *t_alg;
349262306a36Sopenharmony_ci			struct crypto_alg *alg = NULL;
349362306a36Sopenharmony_ci
349462306a36Sopenharmony_ci			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
349562306a36Sopenharmony_ci			if (IS_ERR(t_alg)) {
349662306a36Sopenharmony_ci				err = PTR_ERR(t_alg);
349762306a36Sopenharmony_ci				if (err == -ENOTSUPP)
349862306a36Sopenharmony_ci					continue;
349962306a36Sopenharmony_ci				goto err_out;
350062306a36Sopenharmony_ci			}
350162306a36Sopenharmony_ci
350262306a36Sopenharmony_ci			switch (t_alg->algt.type) {
350362306a36Sopenharmony_ci			case CRYPTO_ALG_TYPE_SKCIPHER:
350462306a36Sopenharmony_ci				err = crypto_register_skcipher(
350562306a36Sopenharmony_ci						&t_alg->algt.alg.skcipher);
350662306a36Sopenharmony_ci				alg = &t_alg->algt.alg.skcipher.base;
350762306a36Sopenharmony_ci				break;
350862306a36Sopenharmony_ci
350962306a36Sopenharmony_ci			case CRYPTO_ALG_TYPE_AEAD:
351062306a36Sopenharmony_ci				err = crypto_register_aead(
351162306a36Sopenharmony_ci					&t_alg->algt.alg.aead);
351262306a36Sopenharmony_ci				alg = &t_alg->algt.alg.aead.base;
351362306a36Sopenharmony_ci				break;
351462306a36Sopenharmony_ci
351562306a36Sopenharmony_ci			case CRYPTO_ALG_TYPE_AHASH:
351662306a36Sopenharmony_ci				err = crypto_register_ahash(
351762306a36Sopenharmony_ci						&t_alg->algt.alg.hash);
351862306a36Sopenharmony_ci				alg = &t_alg->algt.alg.hash.halg.base;
351962306a36Sopenharmony_ci				break;
352062306a36Sopenharmony_ci			}
352162306a36Sopenharmony_ci			if (err) {
352262306a36Sopenharmony_ci				dev_err(dev, "%s alg registration failed\n",
352362306a36Sopenharmony_ci					alg->cra_driver_name);
352462306a36Sopenharmony_ci				devm_kfree(dev, t_alg);
352562306a36Sopenharmony_ci			} else
352662306a36Sopenharmony_ci				list_add_tail(&t_alg->entry, &priv->alg_list);
352762306a36Sopenharmony_ci		}
352862306a36Sopenharmony_ci	}
352962306a36Sopenharmony_ci	if (!list_empty(&priv->alg_list))
353062306a36Sopenharmony_ci		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
353162306a36Sopenharmony_ci			 (char *)of_get_property(np, "compatible", NULL));
353262306a36Sopenharmony_ci
353362306a36Sopenharmony_ci	return 0;
353462306a36Sopenharmony_ci
353562306a36Sopenharmony_cierr_out:
353662306a36Sopenharmony_ci	talitos_remove(ofdev);
353762306a36Sopenharmony_ci
353862306a36Sopenharmony_ci	return err;
353962306a36Sopenharmony_ci}
354062306a36Sopenharmony_ci
354162306a36Sopenharmony_cistatic const struct of_device_id talitos_match[] = {
354262306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS1
354362306a36Sopenharmony_ci	{
354462306a36Sopenharmony_ci		.compatible = "fsl,sec1.0",
354562306a36Sopenharmony_ci	},
354662306a36Sopenharmony_ci#endif
354762306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS2
354862306a36Sopenharmony_ci	{
354962306a36Sopenharmony_ci		.compatible = "fsl,sec2.0",
355062306a36Sopenharmony_ci	},
355162306a36Sopenharmony_ci#endif
355262306a36Sopenharmony_ci	{},
355362306a36Sopenharmony_ci};
355462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, talitos_match);
355562306a36Sopenharmony_ci
355662306a36Sopenharmony_cistatic struct platform_driver talitos_driver = {
355762306a36Sopenharmony_ci	.driver = {
355862306a36Sopenharmony_ci		.name = "talitos",
355962306a36Sopenharmony_ci		.of_match_table = talitos_match,
356062306a36Sopenharmony_ci	},
356162306a36Sopenharmony_ci	.probe = talitos_probe,
356262306a36Sopenharmony_ci	.remove = talitos_remove,
356362306a36Sopenharmony_ci};
356462306a36Sopenharmony_ci
356562306a36Sopenharmony_cimodule_platform_driver(talitos_driver);
356662306a36Sopenharmony_ci
356762306a36Sopenharmony_ciMODULE_LICENSE("GPL");
356862306a36Sopenharmony_ciMODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
356962306a36Sopenharmony_ciMODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3570