18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * talitos - Freescale Integrated Security Engine (SEC) device driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Scatterlist Crypto API glue code copied from files with the following:
88c2ecf20Sopenharmony_ci * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Crypto algorithm registration code copied from hifn driver:
118c2ecf20Sopenharmony_ci * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
128c2ecf20Sopenharmony_ci * All rights reserved.
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <linux/kernel.h>
168c2ecf20Sopenharmony_ci#include <linux/module.h>
178c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
188c2ecf20Sopenharmony_ci#include <linux/device.h>
198c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
208c2ecf20Sopenharmony_ci#include <linux/crypto.h>
218c2ecf20Sopenharmony_ci#include <linux/hw_random.h>
228c2ecf20Sopenharmony_ci#include <linux/of_address.h>
238c2ecf20Sopenharmony_ci#include <linux/of_irq.h>
248c2ecf20Sopenharmony_ci#include <linux/of_platform.h>
258c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
268c2ecf20Sopenharmony_ci#include <linux/io.h>
278c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
288c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h>
298c2ecf20Sopenharmony_ci#include <linux/slab.h>
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#include <crypto/algapi.h>
328c2ecf20Sopenharmony_ci#include <crypto/aes.h>
338c2ecf20Sopenharmony_ci#include <crypto/internal/des.h>
348c2ecf20Sopenharmony_ci#include <crypto/sha.h>
358c2ecf20Sopenharmony_ci#include <crypto/md5.h>
368c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h>
378c2ecf20Sopenharmony_ci#include <crypto/authenc.h>
388c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h>
398c2ecf20Sopenharmony_ci#include <crypto/hash.h>
408c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h>
418c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h>
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#include "talitos.h"
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
468c2ecf20Sopenharmony_ci			   unsigned int len, bool is_sec1)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
498c2ecf20Sopenharmony_ci	if (is_sec1) {
508c2ecf20Sopenharmony_ci		ptr->len1 = cpu_to_be16(len);
518c2ecf20Sopenharmony_ci	} else {
528c2ecf20Sopenharmony_ci		ptr->len = cpu_to_be16(len);
538c2ecf20Sopenharmony_ci		ptr->eptr = upper_32_bits(dma_addr);
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
588c2ecf20Sopenharmony_ci			     struct talitos_ptr *src_ptr, bool is_sec1)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	dst_ptr->ptr = src_ptr->ptr;
618c2ecf20Sopenharmony_ci	if (is_sec1) {
628c2ecf20Sopenharmony_ci		dst_ptr->len1 = src_ptr->len1;
638c2ecf20Sopenharmony_ci	} else {
648c2ecf20Sopenharmony_ci		dst_ptr->len = src_ptr->len;
658c2ecf20Sopenharmony_ci		dst_ptr->eptr = src_ptr->eptr;
668c2ecf20Sopenharmony_ci	}
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
708c2ecf20Sopenharmony_ci					   bool is_sec1)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	if (is_sec1)
738c2ecf20Sopenharmony_ci		return be16_to_cpu(ptr->len1);
748c2ecf20Sopenharmony_ci	else
758c2ecf20Sopenharmony_ci		return be16_to_cpu(ptr->len);
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
798c2ecf20Sopenharmony_ci				   bool is_sec1)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	if (!is_sec1)
828c2ecf20Sopenharmony_ci		ptr->j_extent = val;
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistatic void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	if (!is_sec1)
888c2ecf20Sopenharmony_ci		ptr->j_extent |= val;
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci/*
928c2ecf20Sopenharmony_ci * map virtual single (contiguous) pointer to h/w descriptor pointer
938c2ecf20Sopenharmony_ci */
948c2ecf20Sopenharmony_cistatic void __map_single_talitos_ptr(struct device *dev,
958c2ecf20Sopenharmony_ci				     struct talitos_ptr *ptr,
968c2ecf20Sopenharmony_ci				     unsigned int len, void *data,
978c2ecf20Sopenharmony_ci				     enum dma_data_direction dir,
988c2ecf20Sopenharmony_ci				     unsigned long attrs)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	dma_addr_t dma_addr = dma_map_single_attrs(dev, data, len, dir, attrs);
1018c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
1028c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	to_talitos_ptr(ptr, dma_addr, len, is_sec1);
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic void map_single_talitos_ptr(struct device *dev,
1088c2ecf20Sopenharmony_ci				   struct talitos_ptr *ptr,
1098c2ecf20Sopenharmony_ci				   unsigned int len, void *data,
1108c2ecf20Sopenharmony_ci				   enum dma_data_direction dir)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	__map_single_talitos_ptr(dev, ptr, len, data, dir, 0);
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic void map_single_talitos_ptr_nosync(struct device *dev,
1168c2ecf20Sopenharmony_ci					  struct talitos_ptr *ptr,
1178c2ecf20Sopenharmony_ci					  unsigned int len, void *data,
1188c2ecf20Sopenharmony_ci					  enum dma_data_direction dir)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	__map_single_talitos_ptr(dev, ptr, len, data, dir,
1218c2ecf20Sopenharmony_ci				 DMA_ATTR_SKIP_CPU_SYNC);
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci/*
1258c2ecf20Sopenharmony_ci * unmap bus single (contiguous) h/w descriptor pointer
1268c2ecf20Sopenharmony_ci */
1278c2ecf20Sopenharmony_cistatic void unmap_single_talitos_ptr(struct device *dev,
1288c2ecf20Sopenharmony_ci				     struct talitos_ptr *ptr,
1298c2ecf20Sopenharmony_ci				     enum dma_data_direction dir)
1308c2ecf20Sopenharmony_ci{
1318c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
1328c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
1358c2ecf20Sopenharmony_ci			 from_talitos_ptr_len(ptr, is_sec1), dir);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic int reset_channel(struct device *dev, int ch)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
1418c2ecf20Sopenharmony_ci	unsigned int timeout = TALITOS_TIMEOUT;
1428c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	if (is_sec1) {
1458c2ecf20Sopenharmony_ci		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
1468c2ecf20Sopenharmony_ci			  TALITOS1_CCCR_LO_RESET);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
1498c2ecf20Sopenharmony_ci			TALITOS1_CCCR_LO_RESET) && --timeout)
1508c2ecf20Sopenharmony_ci			cpu_relax();
1518c2ecf20Sopenharmony_ci	} else {
1528c2ecf20Sopenharmony_ci		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
1538c2ecf20Sopenharmony_ci			  TALITOS2_CCCR_RESET);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
1568c2ecf20Sopenharmony_ci			TALITOS2_CCCR_RESET) && --timeout)
1578c2ecf20Sopenharmony_ci			cpu_relax();
1588c2ecf20Sopenharmony_ci	}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	if (timeout == 0) {
1618c2ecf20Sopenharmony_ci		dev_err(dev, "failed to reset channel %d\n", ch);
1628c2ecf20Sopenharmony_ci		return -EIO;
1638c2ecf20Sopenharmony_ci	}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	/* set 36-bit addressing, done writeback enable and done IRQ enable */
1668c2ecf20Sopenharmony_ci	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
1678c2ecf20Sopenharmony_ci		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
1688c2ecf20Sopenharmony_ci	/* enable chaining descriptors */
1698c2ecf20Sopenharmony_ci	if (is_sec1)
1708c2ecf20Sopenharmony_ci		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
1718c2ecf20Sopenharmony_ci			  TALITOS_CCCR_LO_NE);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	/* and ICCR writeback, if available */
1748c2ecf20Sopenharmony_ci	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
1758c2ecf20Sopenharmony_ci		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
1768c2ecf20Sopenharmony_ci		          TALITOS_CCCR_LO_IWSE);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	return 0;
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cistatic int reset_device(struct device *dev)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
1848c2ecf20Sopenharmony_ci	unsigned int timeout = TALITOS_TIMEOUT;
1858c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
1868c2ecf20Sopenharmony_ci	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	setbits32(priv->reg + TALITOS_MCR, mcr);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
1918c2ecf20Sopenharmony_ci	       && --timeout)
1928c2ecf20Sopenharmony_ci		cpu_relax();
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	if (priv->irq[1]) {
1958c2ecf20Sopenharmony_ci		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
1968c2ecf20Sopenharmony_ci		setbits32(priv->reg + TALITOS_MCR, mcr);
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	if (timeout == 0) {
2008c2ecf20Sopenharmony_ci		dev_err(dev, "failed to reset device\n");
2018c2ecf20Sopenharmony_ci		return -EIO;
2028c2ecf20Sopenharmony_ci	}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	return 0;
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci/*
2088c2ecf20Sopenharmony_ci * Reset and initialize the device
2098c2ecf20Sopenharmony_ci */
2108c2ecf20Sopenharmony_cistatic int init_device(struct device *dev)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
2138c2ecf20Sopenharmony_ci	int ch, err;
2148c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	/*
2178c2ecf20Sopenharmony_ci	 * Master reset
2188c2ecf20Sopenharmony_ci	 * errata documentation: warning: certain SEC interrupts
2198c2ecf20Sopenharmony_ci	 * are not fully cleared by writing the MCR:SWR bit,
2208c2ecf20Sopenharmony_ci	 * set bit twice to completely reset
2218c2ecf20Sopenharmony_ci	 */
2228c2ecf20Sopenharmony_ci	err = reset_device(dev);
2238c2ecf20Sopenharmony_ci	if (err)
2248c2ecf20Sopenharmony_ci		return err;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	err = reset_device(dev);
2278c2ecf20Sopenharmony_ci	if (err)
2288c2ecf20Sopenharmony_ci		return err;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/* reset channels */
2318c2ecf20Sopenharmony_ci	for (ch = 0; ch < priv->num_channels; ch++) {
2328c2ecf20Sopenharmony_ci		err = reset_channel(dev, ch);
2338c2ecf20Sopenharmony_ci		if (err)
2348c2ecf20Sopenharmony_ci			return err;
2358c2ecf20Sopenharmony_ci	}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	/* enable channel done and error interrupts */
2388c2ecf20Sopenharmony_ci	if (is_sec1) {
2398c2ecf20Sopenharmony_ci		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
2408c2ecf20Sopenharmony_ci		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
2418c2ecf20Sopenharmony_ci		/* disable parity error check in DEU (erroneous? test vect.) */
2428c2ecf20Sopenharmony_ci		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
2438c2ecf20Sopenharmony_ci	} else {
2448c2ecf20Sopenharmony_ci		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
2458c2ecf20Sopenharmony_ci		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	/* disable integrity check error interrupts (use writeback instead) */
2498c2ecf20Sopenharmony_ci	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
2508c2ecf20Sopenharmony_ci		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
2518c2ecf20Sopenharmony_ci		          TALITOS_MDEUICR_LO_ICE);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	return 0;
2548c2ecf20Sopenharmony_ci}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci/**
2578c2ecf20Sopenharmony_ci * talitos_submit - submits a descriptor to the device for processing
2588c2ecf20Sopenharmony_ci * @dev:	the SEC device to be used
2598c2ecf20Sopenharmony_ci * @ch:		the SEC device channel to be used
2608c2ecf20Sopenharmony_ci * @desc:	the descriptor to be processed by the device
2618c2ecf20Sopenharmony_ci * @callback:	whom to call when processing is complete
2628c2ecf20Sopenharmony_ci * @context:	a handle for use by caller (optional)
2638c2ecf20Sopenharmony_ci *
2648c2ecf20Sopenharmony_ci * desc must contain valid dma-mapped (bus physical) address pointers.
2658c2ecf20Sopenharmony_ci * callback must check err and feedback in descriptor header
2668c2ecf20Sopenharmony_ci * for device processing status.
2678c2ecf20Sopenharmony_ci */
2688c2ecf20Sopenharmony_cistatic int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
2698c2ecf20Sopenharmony_ci			  void (*callback)(struct device *dev,
2708c2ecf20Sopenharmony_ci					   struct talitos_desc *desc,
2718c2ecf20Sopenharmony_ci					   void *context, int error),
2728c2ecf20Sopenharmony_ci			  void *context)
2738c2ecf20Sopenharmony_ci{
2748c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
2758c2ecf20Sopenharmony_ci	struct talitos_request *request;
2768c2ecf20Sopenharmony_ci	unsigned long flags;
2778c2ecf20Sopenharmony_ci	int head;
2788c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
2838c2ecf20Sopenharmony_ci		/* h/w fifo is full */
2848c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
2858c2ecf20Sopenharmony_ci		return -EAGAIN;
2868c2ecf20Sopenharmony_ci	}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	head = priv->chan[ch].head;
2898c2ecf20Sopenharmony_ci	request = &priv->chan[ch].fifo[head];
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	/* map descriptor and save caller data */
2928c2ecf20Sopenharmony_ci	if (is_sec1) {
2938c2ecf20Sopenharmony_ci		desc->hdr1 = desc->hdr;
2948c2ecf20Sopenharmony_ci		request->dma_desc = dma_map_single(dev, &desc->hdr1,
2958c2ecf20Sopenharmony_ci						   TALITOS_DESC_SIZE,
2968c2ecf20Sopenharmony_ci						   DMA_BIDIRECTIONAL);
2978c2ecf20Sopenharmony_ci	} else {
2988c2ecf20Sopenharmony_ci		request->dma_desc = dma_map_single(dev, desc,
2998c2ecf20Sopenharmony_ci						   TALITOS_DESC_SIZE,
3008c2ecf20Sopenharmony_ci						   DMA_BIDIRECTIONAL);
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci	request->callback = callback;
3038c2ecf20Sopenharmony_ci	request->context = context;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	/* increment fifo head */
3068c2ecf20Sopenharmony_ci	priv->chan[ch].head = (priv->chan[ch].head + 1) & (priv->fifo_len - 1);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	smp_wmb();
3098c2ecf20Sopenharmony_ci	request->desc = desc;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	/* GO! */
3128c2ecf20Sopenharmony_ci	wmb();
3138c2ecf20Sopenharmony_ci	out_be32(priv->chan[ch].reg + TALITOS_FF,
3148c2ecf20Sopenharmony_ci		 upper_32_bits(request->dma_desc));
3158c2ecf20Sopenharmony_ci	out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
3168c2ecf20Sopenharmony_ci		 lower_32_bits(request->dma_desc));
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	return -EINPROGRESS;
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cistatic __be32 get_request_hdr(struct talitos_request *request, bool is_sec1)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	if (!is_sec1)
3288c2ecf20Sopenharmony_ci		return request->desc->hdr;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	if (!request->desc->next_desc)
3318c2ecf20Sopenharmony_ci		return request->desc->hdr1;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	edesc = container_of(request->desc, struct talitos_edesc, desc);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1;
3368c2ecf20Sopenharmony_ci}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci/*
3398c2ecf20Sopenharmony_ci * process what was done, notify callback of error if not
3408c2ecf20Sopenharmony_ci */
3418c2ecf20Sopenharmony_cistatic void flush_channel(struct device *dev, int ch, int error, int reset_ch)
3428c2ecf20Sopenharmony_ci{
3438c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
3448c2ecf20Sopenharmony_ci	struct talitos_request *request, saved_req;
3458c2ecf20Sopenharmony_ci	unsigned long flags;
3468c2ecf20Sopenharmony_ci	int tail, status;
3478c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	tail = priv->chan[ch].tail;
3528c2ecf20Sopenharmony_ci	while (priv->chan[ch].fifo[tail].desc) {
3538c2ecf20Sopenharmony_ci		__be32 hdr;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci		request = &priv->chan[ch].fifo[tail];
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci		/* descriptors with their done bits set don't get the error */
3588c2ecf20Sopenharmony_ci		rmb();
3598c2ecf20Sopenharmony_ci		hdr = get_request_hdr(request, is_sec1);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
3628c2ecf20Sopenharmony_ci			status = 0;
3638c2ecf20Sopenharmony_ci		else
3648c2ecf20Sopenharmony_ci			if (!error)
3658c2ecf20Sopenharmony_ci				break;
3668c2ecf20Sopenharmony_ci			else
3678c2ecf20Sopenharmony_ci				status = error;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci		dma_unmap_single(dev, request->dma_desc,
3708c2ecf20Sopenharmony_ci				 TALITOS_DESC_SIZE,
3718c2ecf20Sopenharmony_ci				 DMA_BIDIRECTIONAL);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci		/* copy entries so we can call callback outside lock */
3748c2ecf20Sopenharmony_ci		saved_req.desc = request->desc;
3758c2ecf20Sopenharmony_ci		saved_req.callback = request->callback;
3768c2ecf20Sopenharmony_ci		saved_req.context = request->context;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci		/* release request entry in fifo */
3798c2ecf20Sopenharmony_ci		smp_wmb();
3808c2ecf20Sopenharmony_ci		request->desc = NULL;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci		/* increment fifo tail */
3838c2ecf20Sopenharmony_ci		priv->chan[ch].tail = (tail + 1) & (priv->fifo_len - 1);
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci		atomic_dec(&priv->chan[ch].submit_count);
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci		saved_req.callback(dev, saved_req.desc, saved_req.context,
3908c2ecf20Sopenharmony_ci				   status);
3918c2ecf20Sopenharmony_ci		/* channel may resume processing in single desc error case */
3928c2ecf20Sopenharmony_ci		if (error && !reset_ch && status == error)
3938c2ecf20Sopenharmony_ci			return;
3948c2ecf20Sopenharmony_ci		spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
3958c2ecf20Sopenharmony_ci		tail = priv->chan[ch].tail;
3968c2ecf20Sopenharmony_ci	}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->chan[ch].tail_lock, flags);
3998c2ecf20Sopenharmony_ci}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci/*
4028c2ecf20Sopenharmony_ci * process completed requests for channels that have done status
4038c2ecf20Sopenharmony_ci */
4048c2ecf20Sopenharmony_ci#define DEF_TALITOS1_DONE(name, ch_done_mask)				\
4058c2ecf20Sopenharmony_cistatic void talitos1_done_##name(unsigned long data)			\
4068c2ecf20Sopenharmony_ci{									\
4078c2ecf20Sopenharmony_ci	struct device *dev = (struct device *)data;			\
4088c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);		\
4098c2ecf20Sopenharmony_ci	unsigned long flags;						\
4108c2ecf20Sopenharmony_ci									\
4118c2ecf20Sopenharmony_ci	if (ch_done_mask & 0x10000000)					\
4128c2ecf20Sopenharmony_ci		flush_channel(dev, 0, 0, 0);			\
4138c2ecf20Sopenharmony_ci	if (ch_done_mask & 0x40000000)					\
4148c2ecf20Sopenharmony_ci		flush_channel(dev, 1, 0, 0);			\
4158c2ecf20Sopenharmony_ci	if (ch_done_mask & 0x00010000)					\
4168c2ecf20Sopenharmony_ci		flush_channel(dev, 2, 0, 0);			\
4178c2ecf20Sopenharmony_ci	if (ch_done_mask & 0x00040000)					\
4188c2ecf20Sopenharmony_ci		flush_channel(dev, 3, 0, 0);			\
4198c2ecf20Sopenharmony_ci									\
4208c2ecf20Sopenharmony_ci	/* At this point, all completed channels have been processed */	\
4218c2ecf20Sopenharmony_ci	/* Unmask done interrupts for channels completed later on. */	\
4228c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->reg_lock, flags);			\
4238c2ecf20Sopenharmony_ci	clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
4248c2ecf20Sopenharmony_ci	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);	\
4258c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4268c2ecf20Sopenharmony_ci}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ciDEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
4298c2ecf20Sopenharmony_ciDEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci#define DEF_TALITOS2_DONE(name, ch_done_mask)				\
4328c2ecf20Sopenharmony_cistatic void talitos2_done_##name(unsigned long data)			\
4338c2ecf20Sopenharmony_ci{									\
4348c2ecf20Sopenharmony_ci	struct device *dev = (struct device *)data;			\
4358c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);		\
4368c2ecf20Sopenharmony_ci	unsigned long flags;						\
4378c2ecf20Sopenharmony_ci									\
4388c2ecf20Sopenharmony_ci	if (ch_done_mask & 1)						\
4398c2ecf20Sopenharmony_ci		flush_channel(dev, 0, 0, 0);				\
4408c2ecf20Sopenharmony_ci	if (ch_done_mask & (1 << 2))					\
4418c2ecf20Sopenharmony_ci		flush_channel(dev, 1, 0, 0);				\
4428c2ecf20Sopenharmony_ci	if (ch_done_mask & (1 << 4))					\
4438c2ecf20Sopenharmony_ci		flush_channel(dev, 2, 0, 0);				\
4448c2ecf20Sopenharmony_ci	if (ch_done_mask & (1 << 6))					\
4458c2ecf20Sopenharmony_ci		flush_channel(dev, 3, 0, 0);				\
4468c2ecf20Sopenharmony_ci									\
4478c2ecf20Sopenharmony_ci	/* At this point, all completed channels have been processed */	\
4488c2ecf20Sopenharmony_ci	/* Unmask done interrupts for channels completed later on. */	\
4498c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->reg_lock, flags);			\
4508c2ecf20Sopenharmony_ci	setbits32(priv->reg + TALITOS_IMR, ch_done_mask);		\
4518c2ecf20Sopenharmony_ci	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);	\
4528c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->reg_lock, flags);			\
4538c2ecf20Sopenharmony_ci}
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ciDEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
4568c2ecf20Sopenharmony_ciDEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
4578c2ecf20Sopenharmony_ciDEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
4588c2ecf20Sopenharmony_ciDEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci/*
4618c2ecf20Sopenharmony_ci * locate current (offending) descriptor
4628c2ecf20Sopenharmony_ci */
4638c2ecf20Sopenharmony_cistatic __be32 current_desc_hdr(struct device *dev, int ch)
4648c2ecf20Sopenharmony_ci{
4658c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
4668c2ecf20Sopenharmony_ci	int tail, iter;
4678c2ecf20Sopenharmony_ci	dma_addr_t cur_desc;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
4708c2ecf20Sopenharmony_ci	cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	if (!cur_desc) {
4738c2ecf20Sopenharmony_ci		dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
4748c2ecf20Sopenharmony_ci		return 0;
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	tail = priv->chan[ch].tail;
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	iter = tail;
4808c2ecf20Sopenharmony_ci	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc &&
4818c2ecf20Sopenharmony_ci	       priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) {
4828c2ecf20Sopenharmony_ci		iter = (iter + 1) & (priv->fifo_len - 1);
4838c2ecf20Sopenharmony_ci		if (iter == tail) {
4848c2ecf20Sopenharmony_ci			dev_err(dev, "couldn't locate current descriptor\n");
4858c2ecf20Sopenharmony_ci			return 0;
4868c2ecf20Sopenharmony_ci		}
4878c2ecf20Sopenharmony_ci	}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) {
4908c2ecf20Sopenharmony_ci		struct talitos_edesc *edesc;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci		edesc = container_of(priv->chan[ch].fifo[iter].desc,
4938c2ecf20Sopenharmony_ci				     struct talitos_edesc, desc);
4948c2ecf20Sopenharmony_ci		return ((struct talitos_desc *)
4958c2ecf20Sopenharmony_ci			(edesc->buf + edesc->dma_len))->hdr;
4968c2ecf20Sopenharmony_ci	}
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	return priv->chan[ch].fifo[iter].desc->hdr;
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci/*
5028c2ecf20Sopenharmony_ci * user diagnostics; report root cause of error based on execution unit status
5038c2ecf20Sopenharmony_ci */
5048c2ecf20Sopenharmony_cistatic void report_eu_error(struct device *dev, int ch, __be32 desc_hdr)
5058c2ecf20Sopenharmony_ci{
5068c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
5078c2ecf20Sopenharmony_ci	int i;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	if (!desc_hdr)
5108c2ecf20Sopenharmony_ci		desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF));
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
5138c2ecf20Sopenharmony_ci	case DESC_HDR_SEL0_AFEU:
5148c2ecf20Sopenharmony_ci		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
5158c2ecf20Sopenharmony_ci			in_be32(priv->reg_afeu + TALITOS_EUISR),
5168c2ecf20Sopenharmony_ci			in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
5178c2ecf20Sopenharmony_ci		break;
5188c2ecf20Sopenharmony_ci	case DESC_HDR_SEL0_DEU:
5198c2ecf20Sopenharmony_ci		dev_err(dev, "DEUISR 0x%08x_%08x\n",
5208c2ecf20Sopenharmony_ci			in_be32(priv->reg_deu + TALITOS_EUISR),
5218c2ecf20Sopenharmony_ci			in_be32(priv->reg_deu + TALITOS_EUISR_LO));
5228c2ecf20Sopenharmony_ci		break;
5238c2ecf20Sopenharmony_ci	case DESC_HDR_SEL0_MDEUA:
5248c2ecf20Sopenharmony_ci	case DESC_HDR_SEL0_MDEUB:
5258c2ecf20Sopenharmony_ci		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5268c2ecf20Sopenharmony_ci			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5278c2ecf20Sopenharmony_ci			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5288c2ecf20Sopenharmony_ci		break;
5298c2ecf20Sopenharmony_ci	case DESC_HDR_SEL0_RNG:
5308c2ecf20Sopenharmony_ci		dev_err(dev, "RNGUISR 0x%08x_%08x\n",
5318c2ecf20Sopenharmony_ci			in_be32(priv->reg_rngu + TALITOS_ISR),
5328c2ecf20Sopenharmony_ci			in_be32(priv->reg_rngu + TALITOS_ISR_LO));
5338c2ecf20Sopenharmony_ci		break;
5348c2ecf20Sopenharmony_ci	case DESC_HDR_SEL0_PKEU:
5358c2ecf20Sopenharmony_ci		dev_err(dev, "PKEUISR 0x%08x_%08x\n",
5368c2ecf20Sopenharmony_ci			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5378c2ecf20Sopenharmony_ci			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5388c2ecf20Sopenharmony_ci		break;
5398c2ecf20Sopenharmony_ci	case DESC_HDR_SEL0_AESU:
5408c2ecf20Sopenharmony_ci		dev_err(dev, "AESUISR 0x%08x_%08x\n",
5418c2ecf20Sopenharmony_ci			in_be32(priv->reg_aesu + TALITOS_EUISR),
5428c2ecf20Sopenharmony_ci			in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
5438c2ecf20Sopenharmony_ci		break;
5448c2ecf20Sopenharmony_ci	case DESC_HDR_SEL0_CRCU:
5458c2ecf20Sopenharmony_ci		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5468c2ecf20Sopenharmony_ci			in_be32(priv->reg_crcu + TALITOS_EUISR),
5478c2ecf20Sopenharmony_ci			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5488c2ecf20Sopenharmony_ci		break;
5498c2ecf20Sopenharmony_ci	case DESC_HDR_SEL0_KEU:
5508c2ecf20Sopenharmony_ci		dev_err(dev, "KEUISR 0x%08x_%08x\n",
5518c2ecf20Sopenharmony_ci			in_be32(priv->reg_pkeu + TALITOS_EUISR),
5528c2ecf20Sopenharmony_ci			in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
5538c2ecf20Sopenharmony_ci		break;
5548c2ecf20Sopenharmony_ci	}
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
5578c2ecf20Sopenharmony_ci	case DESC_HDR_SEL1_MDEUA:
5588c2ecf20Sopenharmony_ci	case DESC_HDR_SEL1_MDEUB:
5598c2ecf20Sopenharmony_ci		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
5608c2ecf20Sopenharmony_ci			in_be32(priv->reg_mdeu + TALITOS_EUISR),
5618c2ecf20Sopenharmony_ci			in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
5628c2ecf20Sopenharmony_ci		break;
5638c2ecf20Sopenharmony_ci	case DESC_HDR_SEL1_CRCU:
5648c2ecf20Sopenharmony_ci		dev_err(dev, "CRCUISR 0x%08x_%08x\n",
5658c2ecf20Sopenharmony_ci			in_be32(priv->reg_crcu + TALITOS_EUISR),
5668c2ecf20Sopenharmony_ci			in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
5678c2ecf20Sopenharmony_ci		break;
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++)
5718c2ecf20Sopenharmony_ci		dev_err(dev, "DESCBUF 0x%08x_%08x\n",
5728c2ecf20Sopenharmony_ci			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
5738c2ecf20Sopenharmony_ci			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
5748c2ecf20Sopenharmony_ci}
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci/*
5778c2ecf20Sopenharmony_ci * recover from error interrupts
5788c2ecf20Sopenharmony_ci */
5798c2ecf20Sopenharmony_cistatic void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
5808c2ecf20Sopenharmony_ci{
5818c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
5828c2ecf20Sopenharmony_ci	unsigned int timeout = TALITOS_TIMEOUT;
5838c2ecf20Sopenharmony_ci	int ch, error, reset_dev = 0;
5848c2ecf20Sopenharmony_ci	u32 v_lo;
5858c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
5868c2ecf20Sopenharmony_ci	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	for (ch = 0; ch < priv->num_channels; ch++) {
5898c2ecf20Sopenharmony_ci		/* skip channels without errors */
5908c2ecf20Sopenharmony_ci		if (is_sec1) {
5918c2ecf20Sopenharmony_ci			/* bits 29, 31, 17, 19 */
5928c2ecf20Sopenharmony_ci			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
5938c2ecf20Sopenharmony_ci				continue;
5948c2ecf20Sopenharmony_ci		} else {
5958c2ecf20Sopenharmony_ci			if (!(isr & (1 << (ch * 2 + 1))))
5968c2ecf20Sopenharmony_ci				continue;
5978c2ecf20Sopenharmony_ci		}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci		error = -EINVAL;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_DOF) {
6048c2ecf20Sopenharmony_ci			dev_err(dev, "double fetch fifo overflow error\n");
6058c2ecf20Sopenharmony_ci			error = -EAGAIN;
6068c2ecf20Sopenharmony_ci			reset_ch = 1;
6078c2ecf20Sopenharmony_ci		}
6088c2ecf20Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_SOF) {
6098c2ecf20Sopenharmony_ci			/* h/w dropped descriptor */
6108c2ecf20Sopenharmony_ci			dev_err(dev, "single fetch fifo overflow error\n");
6118c2ecf20Sopenharmony_ci			error = -EAGAIN;
6128c2ecf20Sopenharmony_ci		}
6138c2ecf20Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_MDTE)
6148c2ecf20Sopenharmony_ci			dev_err(dev, "master data transfer error\n");
6158c2ecf20Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
6168c2ecf20Sopenharmony_ci			dev_err(dev, is_sec1 ? "pointer not complete error\n"
6178c2ecf20Sopenharmony_ci					     : "s/g data length zero error\n");
6188c2ecf20Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_FPZ)
6198c2ecf20Sopenharmony_ci			dev_err(dev, is_sec1 ? "parity error\n"
6208c2ecf20Sopenharmony_ci					     : "fetch pointer zero error\n");
6218c2ecf20Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_IDH)
6228c2ecf20Sopenharmony_ci			dev_err(dev, "illegal descriptor header error\n");
6238c2ecf20Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_IEU)
6248c2ecf20Sopenharmony_ci			dev_err(dev, is_sec1 ? "static assignment error\n"
6258c2ecf20Sopenharmony_ci					     : "invalid exec unit error\n");
6268c2ecf20Sopenharmony_ci		if (v_lo & TALITOS_CCPSR_LO_EU)
6278c2ecf20Sopenharmony_ci			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
6288c2ecf20Sopenharmony_ci		if (!is_sec1) {
6298c2ecf20Sopenharmony_ci			if (v_lo & TALITOS_CCPSR_LO_GB)
6308c2ecf20Sopenharmony_ci				dev_err(dev, "gather boundary error\n");
6318c2ecf20Sopenharmony_ci			if (v_lo & TALITOS_CCPSR_LO_GRL)
6328c2ecf20Sopenharmony_ci				dev_err(dev, "gather return/length error\n");
6338c2ecf20Sopenharmony_ci			if (v_lo & TALITOS_CCPSR_LO_SB)
6348c2ecf20Sopenharmony_ci				dev_err(dev, "scatter boundary error\n");
6358c2ecf20Sopenharmony_ci			if (v_lo & TALITOS_CCPSR_LO_SRL)
6368c2ecf20Sopenharmony_ci				dev_err(dev, "scatter return/length error\n");
6378c2ecf20Sopenharmony_ci		}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci		flush_channel(dev, ch, error, reset_ch);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci		if (reset_ch) {
6428c2ecf20Sopenharmony_ci			reset_channel(dev, ch);
6438c2ecf20Sopenharmony_ci		} else {
6448c2ecf20Sopenharmony_ci			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
6458c2ecf20Sopenharmony_ci				  TALITOS2_CCCR_CONT);
6468c2ecf20Sopenharmony_ci			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
6478c2ecf20Sopenharmony_ci			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
6488c2ecf20Sopenharmony_ci			       TALITOS2_CCCR_CONT) && --timeout)
6498c2ecf20Sopenharmony_ci				cpu_relax();
6508c2ecf20Sopenharmony_ci			if (timeout == 0) {
6518c2ecf20Sopenharmony_ci				dev_err(dev, "failed to restart channel %d\n",
6528c2ecf20Sopenharmony_ci					ch);
6538c2ecf20Sopenharmony_ci				reset_dev = 1;
6548c2ecf20Sopenharmony_ci			}
6558c2ecf20Sopenharmony_ci		}
6568c2ecf20Sopenharmony_ci	}
6578c2ecf20Sopenharmony_ci	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
6588c2ecf20Sopenharmony_ci	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
6598c2ecf20Sopenharmony_ci		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
6608c2ecf20Sopenharmony_ci			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
6618c2ecf20Sopenharmony_ci				isr, isr_lo);
6628c2ecf20Sopenharmony_ci		else
6638c2ecf20Sopenharmony_ci			dev_err(dev, "done overflow, internal time out, or "
6648c2ecf20Sopenharmony_ci				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci		/* purge request queues */
6678c2ecf20Sopenharmony_ci		for (ch = 0; ch < priv->num_channels; ch++)
6688c2ecf20Sopenharmony_ci			flush_channel(dev, ch, -EIO, 1);
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci		/* reset and reinitialize the device */
6718c2ecf20Sopenharmony_ci		init_device(dev);
6728c2ecf20Sopenharmony_ci	}
6738c2ecf20Sopenharmony_ci}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci#define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
6768c2ecf20Sopenharmony_cistatic irqreturn_t talitos1_interrupt_##name(int irq, void *data)	       \
6778c2ecf20Sopenharmony_ci{									       \
6788c2ecf20Sopenharmony_ci	struct device *dev = data;					       \
6798c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);		       \
6808c2ecf20Sopenharmony_ci	u32 isr, isr_lo;						       \
6818c2ecf20Sopenharmony_ci	unsigned long flags;						       \
6828c2ecf20Sopenharmony_ci									       \
6838c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->reg_lock, flags);			       \
6848c2ecf20Sopenharmony_ci	isr = in_be32(priv->reg + TALITOS_ISR);				       \
6858c2ecf20Sopenharmony_ci	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
6868c2ecf20Sopenharmony_ci	/* Acknowledge interrupt */					       \
6878c2ecf20Sopenharmony_ci	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
6888c2ecf20Sopenharmony_ci	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
6898c2ecf20Sopenharmony_ci									       \
6908c2ecf20Sopenharmony_ci	if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) {    \
6918c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
6928c2ecf20Sopenharmony_ci		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
6938c2ecf20Sopenharmony_ci	}								       \
6948c2ecf20Sopenharmony_ci	else {								       \
6958c2ecf20Sopenharmony_ci		if (likely(isr & ch_done_mask)) {			       \
6968c2ecf20Sopenharmony_ci			/* mask further done interrupts. */		       \
6978c2ecf20Sopenharmony_ci			setbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
6988c2ecf20Sopenharmony_ci			/* done_task will unmask done interrupts at exit */    \
6998c2ecf20Sopenharmony_ci			tasklet_schedule(&priv->done_task[tlet]);	       \
7008c2ecf20Sopenharmony_ci		}							       \
7018c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
7028c2ecf20Sopenharmony_ci	}								       \
7038c2ecf20Sopenharmony_ci									       \
7048c2ecf20Sopenharmony_ci	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
7058c2ecf20Sopenharmony_ci								IRQ_NONE;      \
7068c2ecf20Sopenharmony_ci}
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ciDEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci#define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)	       \
7118c2ecf20Sopenharmony_cistatic irqreturn_t talitos2_interrupt_##name(int irq, void *data)	       \
7128c2ecf20Sopenharmony_ci{									       \
7138c2ecf20Sopenharmony_ci	struct device *dev = data;					       \
7148c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);		       \
7158c2ecf20Sopenharmony_ci	u32 isr, isr_lo;						       \
7168c2ecf20Sopenharmony_ci	unsigned long flags;						       \
7178c2ecf20Sopenharmony_ci									       \
7188c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->reg_lock, flags);			       \
7198c2ecf20Sopenharmony_ci	isr = in_be32(priv->reg + TALITOS_ISR);				       \
7208c2ecf20Sopenharmony_ci	isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);			       \
7218c2ecf20Sopenharmony_ci	/* Acknowledge interrupt */					       \
7228c2ecf20Sopenharmony_ci	out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
7238c2ecf20Sopenharmony_ci	out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);			       \
7248c2ecf20Sopenharmony_ci									       \
7258c2ecf20Sopenharmony_ci	if (unlikely(isr & ch_err_mask || isr_lo)) {			       \
7268c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
7278c2ecf20Sopenharmony_ci		talitos_error(dev, isr & ch_err_mask, isr_lo);		       \
7288c2ecf20Sopenharmony_ci	}								       \
7298c2ecf20Sopenharmony_ci	else {								       \
7308c2ecf20Sopenharmony_ci		if (likely(isr & ch_done_mask)) {			       \
7318c2ecf20Sopenharmony_ci			/* mask further done interrupts. */		       \
7328c2ecf20Sopenharmony_ci			clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
7338c2ecf20Sopenharmony_ci			/* done_task will unmask done interrupts at exit */    \
7348c2ecf20Sopenharmony_ci			tasklet_schedule(&priv->done_task[tlet]);	       \
7358c2ecf20Sopenharmony_ci		}							       \
7368c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&priv->reg_lock, flags);		       \
7378c2ecf20Sopenharmony_ci	}								       \
7388c2ecf20Sopenharmony_ci									       \
7398c2ecf20Sopenharmony_ci	return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
7408c2ecf20Sopenharmony_ci								IRQ_NONE;      \
7418c2ecf20Sopenharmony_ci}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ciDEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
7448c2ecf20Sopenharmony_ciDEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
7458c2ecf20Sopenharmony_ci		       0)
7468c2ecf20Sopenharmony_ciDEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
7478c2ecf20Sopenharmony_ci		       1)
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci/*
7508c2ecf20Sopenharmony_ci * hwrng
7518c2ecf20Sopenharmony_ci */
7528c2ecf20Sopenharmony_cistatic int talitos_rng_data_present(struct hwrng *rng, int wait)
7538c2ecf20Sopenharmony_ci{
7548c2ecf20Sopenharmony_ci	struct device *dev = (struct device *)rng->priv;
7558c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
7568c2ecf20Sopenharmony_ci	u32 ofl;
7578c2ecf20Sopenharmony_ci	int i;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	for (i = 0; i < 20; i++) {
7608c2ecf20Sopenharmony_ci		ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
7618c2ecf20Sopenharmony_ci		      TALITOS_RNGUSR_LO_OFL;
7628c2ecf20Sopenharmony_ci		if (ofl || !wait)
7638c2ecf20Sopenharmony_ci			break;
7648c2ecf20Sopenharmony_ci		udelay(10);
7658c2ecf20Sopenharmony_ci	}
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	return !!ofl;
7688c2ecf20Sopenharmony_ci}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_cistatic int talitos_rng_data_read(struct hwrng *rng, u32 *data)
7718c2ecf20Sopenharmony_ci{
7728c2ecf20Sopenharmony_ci	struct device *dev = (struct device *)rng->priv;
7738c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	/* rng fifo requires 64-bit accesses */
7768c2ecf20Sopenharmony_ci	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
7778c2ecf20Sopenharmony_ci	*data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	return sizeof(u32);
7808c2ecf20Sopenharmony_ci}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_cistatic int talitos_rng_init(struct hwrng *rng)
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	struct device *dev = (struct device *)rng->priv;
7858c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
7868c2ecf20Sopenharmony_ci	unsigned int timeout = TALITOS_TIMEOUT;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
7898c2ecf20Sopenharmony_ci	while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
7908c2ecf20Sopenharmony_ci		 & TALITOS_RNGUSR_LO_RD)
7918c2ecf20Sopenharmony_ci	       && --timeout)
7928c2ecf20Sopenharmony_ci		cpu_relax();
7938c2ecf20Sopenharmony_ci	if (timeout == 0) {
7948c2ecf20Sopenharmony_ci		dev_err(dev, "failed to reset rng hw\n");
7958c2ecf20Sopenharmony_ci		return -ENODEV;
7968c2ecf20Sopenharmony_ci	}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	/* start generating */
7998c2ecf20Sopenharmony_ci	setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	return 0;
8028c2ecf20Sopenharmony_ci}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_cistatic int talitos_register_rng(struct device *dev)
8058c2ecf20Sopenharmony_ci{
8068c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
8078c2ecf20Sopenharmony_ci	int err;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	priv->rng.name		= dev_driver_string(dev);
8108c2ecf20Sopenharmony_ci	priv->rng.init		= talitos_rng_init;
8118c2ecf20Sopenharmony_ci	priv->rng.data_present	= talitos_rng_data_present;
8128c2ecf20Sopenharmony_ci	priv->rng.data_read	= talitos_rng_data_read;
8138c2ecf20Sopenharmony_ci	priv->rng.priv		= (unsigned long)dev;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	err = hwrng_register(&priv->rng);
8168c2ecf20Sopenharmony_ci	if (!err)
8178c2ecf20Sopenharmony_ci		priv->rng_registered = true;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	return err;
8208c2ecf20Sopenharmony_ci}
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_cistatic void talitos_unregister_rng(struct device *dev)
8238c2ecf20Sopenharmony_ci{
8248c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	if (!priv->rng_registered)
8278c2ecf20Sopenharmony_ci		return;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	hwrng_unregister(&priv->rng);
8308c2ecf20Sopenharmony_ci	priv->rng_registered = false;
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci/*
8348c2ecf20Sopenharmony_ci * crypto alg
8358c2ecf20Sopenharmony_ci */
8368c2ecf20Sopenharmony_ci#define TALITOS_CRA_PRIORITY		3000
8378c2ecf20Sopenharmony_ci/*
8388c2ecf20Sopenharmony_ci * Defines a priority for doing AEAD with descriptors type
8398c2ecf20Sopenharmony_ci * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
8408c2ecf20Sopenharmony_ci */
8418c2ecf20Sopenharmony_ci#define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
8428c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS2
8438c2ecf20Sopenharmony_ci#define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
8448c2ecf20Sopenharmony_ci#else
8458c2ecf20Sopenharmony_ci#define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE)
8468c2ecf20Sopenharmony_ci#endif
8478c2ecf20Sopenharmony_ci#define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_cistruct talitos_ctx {
8508c2ecf20Sopenharmony_ci	struct device *dev;
8518c2ecf20Sopenharmony_ci	int ch;
8528c2ecf20Sopenharmony_ci	__be32 desc_hdr_template;
8538c2ecf20Sopenharmony_ci	u8 key[TALITOS_MAX_KEY_SIZE];
8548c2ecf20Sopenharmony_ci	u8 iv[TALITOS_MAX_IV_LENGTH];
8558c2ecf20Sopenharmony_ci	dma_addr_t dma_key;
8568c2ecf20Sopenharmony_ci	unsigned int keylen;
8578c2ecf20Sopenharmony_ci	unsigned int enckeylen;
8588c2ecf20Sopenharmony_ci	unsigned int authkeylen;
8598c2ecf20Sopenharmony_ci};
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci#define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
8628c2ecf20Sopenharmony_ci#define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_cistruct talitos_ahash_req_ctx {
8658c2ecf20Sopenharmony_ci	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8668c2ecf20Sopenharmony_ci	unsigned int hw_context_size;
8678c2ecf20Sopenharmony_ci	u8 buf[2][HASH_MAX_BLOCK_SIZE];
8688c2ecf20Sopenharmony_ci	int buf_idx;
8698c2ecf20Sopenharmony_ci	unsigned int swinit;
8708c2ecf20Sopenharmony_ci	unsigned int first;
8718c2ecf20Sopenharmony_ci	unsigned int last;
8728c2ecf20Sopenharmony_ci	unsigned int to_hash_later;
8738c2ecf20Sopenharmony_ci	unsigned int nbuf;
8748c2ecf20Sopenharmony_ci	struct scatterlist bufsl[2];
8758c2ecf20Sopenharmony_ci	struct scatterlist *psrc;
8768c2ecf20Sopenharmony_ci};
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_cistruct talitos_export_state {
8798c2ecf20Sopenharmony_ci	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
8808c2ecf20Sopenharmony_ci	u8 buf[HASH_MAX_BLOCK_SIZE];
8818c2ecf20Sopenharmony_ci	unsigned int swinit;
8828c2ecf20Sopenharmony_ci	unsigned int first;
8838c2ecf20Sopenharmony_ci	unsigned int last;
8848c2ecf20Sopenharmony_ci	unsigned int to_hash_later;
8858c2ecf20Sopenharmony_ci	unsigned int nbuf;
8868c2ecf20Sopenharmony_ci};
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_cistatic int aead_setkey(struct crypto_aead *authenc,
8898c2ecf20Sopenharmony_ci		       const u8 *key, unsigned int keylen)
8908c2ecf20Sopenharmony_ci{
8918c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
8928c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
8938c2ecf20Sopenharmony_ci	struct crypto_authenc_keys keys;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
8968c2ecf20Sopenharmony_ci		goto badkey;
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
8998c2ecf20Sopenharmony_ci		goto badkey;
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	if (ctx->keylen)
9028c2ecf20Sopenharmony_ci		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci	memcpy(ctx->key, keys.authkey, keys.authkeylen);
9058c2ecf20Sopenharmony_ci	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	ctx->keylen = keys.authkeylen + keys.enckeylen;
9088c2ecf20Sopenharmony_ci	ctx->enckeylen = keys.enckeylen;
9098c2ecf20Sopenharmony_ci	ctx->authkeylen = keys.authkeylen;
9108c2ecf20Sopenharmony_ci	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
9118c2ecf20Sopenharmony_ci				      DMA_TO_DEVICE);
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
9148c2ecf20Sopenharmony_ci	return 0;
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_cibadkey:
9178c2ecf20Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
9188c2ecf20Sopenharmony_ci	return -EINVAL;
9198c2ecf20Sopenharmony_ci}
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_cistatic int aead_des3_setkey(struct crypto_aead *authenc,
9228c2ecf20Sopenharmony_ci			    const u8 *key, unsigned int keylen)
9238c2ecf20Sopenharmony_ci{
9248c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
9258c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
9268c2ecf20Sopenharmony_ci	struct crypto_authenc_keys keys;
9278c2ecf20Sopenharmony_ci	int err;
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	err = crypto_authenc_extractkeys(&keys, key, keylen);
9308c2ecf20Sopenharmony_ci	if (unlikely(err))
9318c2ecf20Sopenharmony_ci		goto out;
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	err = -EINVAL;
9348c2ecf20Sopenharmony_ci	if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
9358c2ecf20Sopenharmony_ci		goto out;
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci	err = verify_aead_des3_key(authenc, keys.enckey, keys.enckeylen);
9388c2ecf20Sopenharmony_ci	if (err)
9398c2ecf20Sopenharmony_ci		goto out;
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	if (ctx->keylen)
9428c2ecf20Sopenharmony_ci		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	memcpy(ctx->key, keys.authkey, keys.authkeylen);
9458c2ecf20Sopenharmony_ci	memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	ctx->keylen = keys.authkeylen + keys.enckeylen;
9488c2ecf20Sopenharmony_ci	ctx->enckeylen = keys.enckeylen;
9498c2ecf20Sopenharmony_ci	ctx->authkeylen = keys.authkeylen;
9508c2ecf20Sopenharmony_ci	ctx->dma_key = dma_map_single(dev, ctx->key, ctx->keylen,
9518c2ecf20Sopenharmony_ci				      DMA_TO_DEVICE);
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ciout:
9548c2ecf20Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
9558c2ecf20Sopenharmony_ci	return err;
9568c2ecf20Sopenharmony_ci}
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_cistatic void talitos_sg_unmap(struct device *dev,
9598c2ecf20Sopenharmony_ci			     struct talitos_edesc *edesc,
9608c2ecf20Sopenharmony_ci			     struct scatterlist *src,
9618c2ecf20Sopenharmony_ci			     struct scatterlist *dst,
9628c2ecf20Sopenharmony_ci			     unsigned int len, unsigned int offset)
9638c2ecf20Sopenharmony_ci{
9648c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
9658c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
9668c2ecf20Sopenharmony_ci	unsigned int src_nents = edesc->src_nents ? : 1;
9678c2ecf20Sopenharmony_ci	unsigned int dst_nents = edesc->dst_nents ? : 1;
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	if (is_sec1 && dst && dst_nents > 1) {
9708c2ecf20Sopenharmony_ci		dma_sync_single_for_device(dev, edesc->dma_link_tbl + offset,
9718c2ecf20Sopenharmony_ci					   len, DMA_FROM_DEVICE);
9728c2ecf20Sopenharmony_ci		sg_pcopy_from_buffer(dst, dst_nents, edesc->buf + offset, len,
9738c2ecf20Sopenharmony_ci				     offset);
9748c2ecf20Sopenharmony_ci	}
9758c2ecf20Sopenharmony_ci	if (src != dst) {
9768c2ecf20Sopenharmony_ci		if (src_nents == 1 || !is_sec1)
9778c2ecf20Sopenharmony_ci			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci		if (dst && (dst_nents == 1 || !is_sec1))
9808c2ecf20Sopenharmony_ci			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
9818c2ecf20Sopenharmony_ci	} else if (src_nents == 1 || !is_sec1) {
9828c2ecf20Sopenharmony_ci		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
9838c2ecf20Sopenharmony_ci	}
9848c2ecf20Sopenharmony_ci}
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_cistatic void ipsec_esp_unmap(struct device *dev,
9878c2ecf20Sopenharmony_ci			    struct talitos_edesc *edesc,
9888c2ecf20Sopenharmony_ci			    struct aead_request *areq, bool encrypt)
9898c2ecf20Sopenharmony_ci{
9908c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
9918c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
9928c2ecf20Sopenharmony_ci	unsigned int ivsize = crypto_aead_ivsize(aead);
9938c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(aead);
9948c2ecf20Sopenharmony_ci	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
9958c2ecf20Sopenharmony_ci	bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
9968c2ecf20Sopenharmony_ci	struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	if (is_ipsec_esp)
9998c2ecf20Sopenharmony_ci		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
10008c2ecf20Sopenharmony_ci					 DMA_FROM_DEVICE);
10018c2ecf20Sopenharmony_ci	unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	talitos_sg_unmap(dev, edesc, areq->src, areq->dst,
10048c2ecf20Sopenharmony_ci			 cryptlen + authsize, areq->assoclen);
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	if (edesc->dma_len)
10078c2ecf20Sopenharmony_ci		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
10088c2ecf20Sopenharmony_ci				 DMA_BIDIRECTIONAL);
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	if (!is_ipsec_esp) {
10118c2ecf20Sopenharmony_ci		unsigned int dst_nents = edesc->dst_nents ? : 1;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci		sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
10148c2ecf20Sopenharmony_ci				   areq->assoclen + cryptlen - ivsize);
10158c2ecf20Sopenharmony_ci	}
10168c2ecf20Sopenharmony_ci}
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci/*
10198c2ecf20Sopenharmony_ci * ipsec_esp descriptor callbacks
10208c2ecf20Sopenharmony_ci */
10218c2ecf20Sopenharmony_cistatic void ipsec_esp_encrypt_done(struct device *dev,
10228c2ecf20Sopenharmony_ci				   struct talitos_desc *desc, void *context,
10238c2ecf20Sopenharmony_ci				   int err)
10248c2ecf20Sopenharmony_ci{
10258c2ecf20Sopenharmony_ci	struct aead_request *areq = context;
10268c2ecf20Sopenharmony_ci	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
10278c2ecf20Sopenharmony_ci	unsigned int ivsize = crypto_aead_ivsize(authenc);
10288c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci	edesc = container_of(desc, struct talitos_edesc, desc);
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	ipsec_esp_unmap(dev, edesc, areq, true);
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci	kfree(edesc);
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	aead_request_complete(areq, err);
10398c2ecf20Sopenharmony_ci}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_cistatic void ipsec_esp_decrypt_swauth_done(struct device *dev,
10428c2ecf20Sopenharmony_ci					  struct talitos_desc *desc,
10438c2ecf20Sopenharmony_ci					  void *context, int err)
10448c2ecf20Sopenharmony_ci{
10458c2ecf20Sopenharmony_ci	struct aead_request *req = context;
10468c2ecf20Sopenharmony_ci	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
10478c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(authenc);
10488c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
10498c2ecf20Sopenharmony_ci	char *oicv, *icv;
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci	edesc = container_of(desc, struct talitos_edesc, desc);
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	ipsec_esp_unmap(dev, edesc, req, false);
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	if (!err) {
10568c2ecf20Sopenharmony_ci		/* auth check */
10578c2ecf20Sopenharmony_ci		oicv = edesc->buf + edesc->dma_len;
10588c2ecf20Sopenharmony_ci		icv = oicv - authsize;
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci		err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
10618c2ecf20Sopenharmony_ci	}
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	kfree(edesc);
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci	aead_request_complete(req, err);
10668c2ecf20Sopenharmony_ci}
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_cistatic void ipsec_esp_decrypt_hwauth_done(struct device *dev,
10698c2ecf20Sopenharmony_ci					  struct talitos_desc *desc,
10708c2ecf20Sopenharmony_ci					  void *context, int err)
10718c2ecf20Sopenharmony_ci{
10728c2ecf20Sopenharmony_ci	struct aead_request *req = context;
10738c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	edesc = container_of(desc, struct talitos_edesc, desc);
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci	ipsec_esp_unmap(dev, edesc, req, false);
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	/* check ICV auth status */
10808c2ecf20Sopenharmony_ci	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
10818c2ecf20Sopenharmony_ci		     DESC_HDR_LO_ICCR1_PASS))
10828c2ecf20Sopenharmony_ci		err = -EBADMSG;
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	kfree(edesc);
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	aead_request_complete(req, err);
10878c2ecf20Sopenharmony_ci}
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci/*
10908c2ecf20Sopenharmony_ci * convert scatterlist to SEC h/w link table format
10918c2ecf20Sopenharmony_ci * stop at cryptlen bytes
10928c2ecf20Sopenharmony_ci */
10938c2ecf20Sopenharmony_cistatic int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
10948c2ecf20Sopenharmony_ci				 unsigned int offset, int datalen, int elen,
10958c2ecf20Sopenharmony_ci				 struct talitos_ptr *link_tbl_ptr, int align)
10968c2ecf20Sopenharmony_ci{
10978c2ecf20Sopenharmony_ci	int n_sg = elen ? sg_count + 1 : sg_count;
10988c2ecf20Sopenharmony_ci	int count = 0;
10998c2ecf20Sopenharmony_ci	int cryptlen = datalen + elen;
11008c2ecf20Sopenharmony_ci	int padding = ALIGN(cryptlen, align) - cryptlen;
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	while (cryptlen && sg && n_sg--) {
11038c2ecf20Sopenharmony_ci		unsigned int len = sg_dma_len(sg);
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci		if (offset >= len) {
11068c2ecf20Sopenharmony_ci			offset -= len;
11078c2ecf20Sopenharmony_ci			goto next;
11088c2ecf20Sopenharmony_ci		}
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci		len -= offset;
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci		if (len > cryptlen)
11138c2ecf20Sopenharmony_ci			len = cryptlen;
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci		if (datalen > 0 && len > datalen) {
11168c2ecf20Sopenharmony_ci			to_talitos_ptr(link_tbl_ptr + count,
11178c2ecf20Sopenharmony_ci				       sg_dma_address(sg) + offset, datalen, 0);
11188c2ecf20Sopenharmony_ci			to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
11198c2ecf20Sopenharmony_ci			count++;
11208c2ecf20Sopenharmony_ci			len -= datalen;
11218c2ecf20Sopenharmony_ci			offset += datalen;
11228c2ecf20Sopenharmony_ci		}
11238c2ecf20Sopenharmony_ci		to_talitos_ptr(link_tbl_ptr + count,
11248c2ecf20Sopenharmony_ci			       sg_dma_address(sg) + offset, sg_next(sg) ? len : len + padding, 0);
11258c2ecf20Sopenharmony_ci		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
11268c2ecf20Sopenharmony_ci		count++;
11278c2ecf20Sopenharmony_ci		cryptlen -= len;
11288c2ecf20Sopenharmony_ci		datalen -= len;
11298c2ecf20Sopenharmony_ci		offset = 0;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_cinext:
11328c2ecf20Sopenharmony_ci		sg = sg_next(sg);
11338c2ecf20Sopenharmony_ci	}
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	/* tag end of link table */
11368c2ecf20Sopenharmony_ci	if (count > 0)
11378c2ecf20Sopenharmony_ci		to_talitos_ptr_ext_set(link_tbl_ptr + count - 1,
11388c2ecf20Sopenharmony_ci				       DESC_PTR_LNKTBL_RET, 0);
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci	return count;
11418c2ecf20Sopenharmony_ci}
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_cistatic int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
11448c2ecf20Sopenharmony_ci			      unsigned int len, struct talitos_edesc *edesc,
11458c2ecf20Sopenharmony_ci			      struct talitos_ptr *ptr, int sg_count,
11468c2ecf20Sopenharmony_ci			      unsigned int offset, int tbl_off, int elen,
11478c2ecf20Sopenharmony_ci			      bool force, int align)
11488c2ecf20Sopenharmony_ci{
11498c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
11508c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
11518c2ecf20Sopenharmony_ci	int aligned_len = ALIGN(len, align);
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	if (!src) {
11548c2ecf20Sopenharmony_ci		to_talitos_ptr(ptr, 0, 0, is_sec1);
11558c2ecf20Sopenharmony_ci		return 1;
11568c2ecf20Sopenharmony_ci	}
11578c2ecf20Sopenharmony_ci	to_talitos_ptr_ext_set(ptr, elen, is_sec1);
11588c2ecf20Sopenharmony_ci	if (sg_count == 1 && !force) {
11598c2ecf20Sopenharmony_ci		to_talitos_ptr(ptr, sg_dma_address(src) + offset, aligned_len, is_sec1);
11608c2ecf20Sopenharmony_ci		return sg_count;
11618c2ecf20Sopenharmony_ci	}
11628c2ecf20Sopenharmony_ci	if (is_sec1) {
11638c2ecf20Sopenharmony_ci		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, aligned_len, is_sec1);
11648c2ecf20Sopenharmony_ci		return sg_count;
11658c2ecf20Sopenharmony_ci	}
11668c2ecf20Sopenharmony_ci	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen,
11678c2ecf20Sopenharmony_ci					 &edesc->link_tbl[tbl_off], align);
11688c2ecf20Sopenharmony_ci	if (sg_count == 1 && !force) {
11698c2ecf20Sopenharmony_ci		/* Only one segment now, so no link tbl needed*/
11708c2ecf20Sopenharmony_ci		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
11718c2ecf20Sopenharmony_ci		return sg_count;
11728c2ecf20Sopenharmony_ci	}
11738c2ecf20Sopenharmony_ci	to_talitos_ptr(ptr, edesc->dma_link_tbl +
11748c2ecf20Sopenharmony_ci			    tbl_off * sizeof(struct talitos_ptr), aligned_len, is_sec1);
11758c2ecf20Sopenharmony_ci	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci	return sg_count;
11788c2ecf20Sopenharmony_ci}
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_cistatic int talitos_sg_map(struct device *dev, struct scatterlist *src,
11818c2ecf20Sopenharmony_ci			  unsigned int len, struct talitos_edesc *edesc,
11828c2ecf20Sopenharmony_ci			  struct talitos_ptr *ptr, int sg_count,
11838c2ecf20Sopenharmony_ci			  unsigned int offset, int tbl_off)
11848c2ecf20Sopenharmony_ci{
11858c2ecf20Sopenharmony_ci	return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset,
11868c2ecf20Sopenharmony_ci				  tbl_off, 0, false, 1);
11878c2ecf20Sopenharmony_ci}
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci/*
11908c2ecf20Sopenharmony_ci * fill in and submit ipsec_esp descriptor
11918c2ecf20Sopenharmony_ci */
11928c2ecf20Sopenharmony_cistatic int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
11938c2ecf20Sopenharmony_ci		     bool encrypt,
11948c2ecf20Sopenharmony_ci		     void (*callback)(struct device *dev,
11958c2ecf20Sopenharmony_ci				      struct talitos_desc *desc,
11968c2ecf20Sopenharmony_ci				      void *context, int error))
11978c2ecf20Sopenharmony_ci{
11988c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
11998c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(aead);
12008c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
12018c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
12028c2ecf20Sopenharmony_ci	struct talitos_desc *desc = &edesc->desc;
12038c2ecf20Sopenharmony_ci	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
12048c2ecf20Sopenharmony_ci	unsigned int ivsize = crypto_aead_ivsize(aead);
12058c2ecf20Sopenharmony_ci	int tbl_off = 0;
12068c2ecf20Sopenharmony_ci	int sg_count, ret;
12078c2ecf20Sopenharmony_ci	int elen = 0;
12088c2ecf20Sopenharmony_ci	bool sync_needed = false;
12098c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
12108c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
12118c2ecf20Sopenharmony_ci	bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
12128c2ecf20Sopenharmony_ci	struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
12138c2ecf20Sopenharmony_ci	struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
12148c2ecf20Sopenharmony_ci	dma_addr_t dma_icv = edesc->dma_link_tbl + edesc->dma_len - authsize;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	/* hmac key */
12178c2ecf20Sopenharmony_ci	to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen, is_sec1);
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	sg_count = edesc->src_nents ?: 1;
12208c2ecf20Sopenharmony_ci	if (is_sec1 && sg_count > 1)
12218c2ecf20Sopenharmony_ci		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
12228c2ecf20Sopenharmony_ci				  areq->assoclen + cryptlen);
12238c2ecf20Sopenharmony_ci	else
12248c2ecf20Sopenharmony_ci		sg_count = dma_map_sg(dev, areq->src, sg_count,
12258c2ecf20Sopenharmony_ci				      (areq->src == areq->dst) ?
12268c2ecf20Sopenharmony_ci				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	/* hmac data */
12298c2ecf20Sopenharmony_ci	ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
12308c2ecf20Sopenharmony_ci			     &desc->ptr[1], sg_count, 0, tbl_off);
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	if (ret > 1) {
12338c2ecf20Sopenharmony_ci		tbl_off += ret;
12348c2ecf20Sopenharmony_ci		sync_needed = true;
12358c2ecf20Sopenharmony_ci	}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	/* cipher iv */
12388c2ecf20Sopenharmony_ci	to_talitos_ptr(civ_ptr, edesc->iv_dma, ivsize, is_sec1);
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci	/* cipher key */
12418c2ecf20Sopenharmony_ci	to_talitos_ptr(ckey_ptr, ctx->dma_key  + ctx->authkeylen,
12428c2ecf20Sopenharmony_ci		       ctx->enckeylen, is_sec1);
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	/*
12458c2ecf20Sopenharmony_ci	 * cipher in
12468c2ecf20Sopenharmony_ci	 * map and adjust cipher len to aead request cryptlen.
12478c2ecf20Sopenharmony_ci	 * extent is bytes of HMAC postpended to ciphertext,
12488c2ecf20Sopenharmony_ci	 * typically 12 for ipsec
12498c2ecf20Sopenharmony_ci	 */
12508c2ecf20Sopenharmony_ci	if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV))
12518c2ecf20Sopenharmony_ci		elen = authsize;
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci	ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4],
12548c2ecf20Sopenharmony_ci				 sg_count, areq->assoclen, tbl_off, elen,
12558c2ecf20Sopenharmony_ci				 false, 1);
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	if (ret > 1) {
12588c2ecf20Sopenharmony_ci		tbl_off += ret;
12598c2ecf20Sopenharmony_ci		sync_needed = true;
12608c2ecf20Sopenharmony_ci	}
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci	/* cipher out */
12638c2ecf20Sopenharmony_ci	if (areq->src != areq->dst) {
12648c2ecf20Sopenharmony_ci		sg_count = edesc->dst_nents ? : 1;
12658c2ecf20Sopenharmony_ci		if (!is_sec1 || sg_count == 1)
12668c2ecf20Sopenharmony_ci			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
12678c2ecf20Sopenharmony_ci	}
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	if (is_ipsec_esp && encrypt)
12708c2ecf20Sopenharmony_ci		elen = authsize;
12718c2ecf20Sopenharmony_ci	else
12728c2ecf20Sopenharmony_ci		elen = 0;
12738c2ecf20Sopenharmony_ci	ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
12748c2ecf20Sopenharmony_ci				 sg_count, areq->assoclen, tbl_off, elen,
12758c2ecf20Sopenharmony_ci				 is_ipsec_esp && !encrypt, 1);
12768c2ecf20Sopenharmony_ci	tbl_off += ret;
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	if (!encrypt && is_ipsec_esp) {
12798c2ecf20Sopenharmony_ci		struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci		/* Add an entry to the link table for ICV data */
12828c2ecf20Sopenharmony_ci		to_talitos_ptr_ext_set(tbl_ptr - 1, 0, is_sec1);
12838c2ecf20Sopenharmony_ci		to_talitos_ptr_ext_set(tbl_ptr, DESC_PTR_LNKTBL_RET, is_sec1);
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci		/* icv data follows link tables */
12868c2ecf20Sopenharmony_ci		to_talitos_ptr(tbl_ptr, dma_icv, authsize, is_sec1);
12878c2ecf20Sopenharmony_ci		to_talitos_ptr_ext_or(&desc->ptr[5], authsize, is_sec1);
12888c2ecf20Sopenharmony_ci		sync_needed = true;
12898c2ecf20Sopenharmony_ci	} else if (!encrypt) {
12908c2ecf20Sopenharmony_ci		to_talitos_ptr(&desc->ptr[6], dma_icv, authsize, is_sec1);
12918c2ecf20Sopenharmony_ci		sync_needed = true;
12928c2ecf20Sopenharmony_ci	} else if (!is_ipsec_esp) {
12938c2ecf20Sopenharmony_ci		talitos_sg_map(dev, areq->dst, authsize, edesc, &desc->ptr[6],
12948c2ecf20Sopenharmony_ci			       sg_count, areq->assoclen + cryptlen, tbl_off);
12958c2ecf20Sopenharmony_ci	}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	/* iv out */
12988c2ecf20Sopenharmony_ci	if (is_ipsec_esp)
12998c2ecf20Sopenharmony_ci		map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
13008c2ecf20Sopenharmony_ci				       DMA_FROM_DEVICE);
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	if (sync_needed)
13038c2ecf20Sopenharmony_ci		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
13048c2ecf20Sopenharmony_ci					   edesc->dma_len,
13058c2ecf20Sopenharmony_ci					   DMA_BIDIRECTIONAL);
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
13088c2ecf20Sopenharmony_ci	if (ret != -EINPROGRESS) {
13098c2ecf20Sopenharmony_ci		ipsec_esp_unmap(dev, edesc, areq, encrypt);
13108c2ecf20Sopenharmony_ci		kfree(edesc);
13118c2ecf20Sopenharmony_ci	}
13128c2ecf20Sopenharmony_ci	return ret;
13138c2ecf20Sopenharmony_ci}
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci/*
13168c2ecf20Sopenharmony_ci * allocate and map the extended descriptor
13178c2ecf20Sopenharmony_ci */
13188c2ecf20Sopenharmony_cistatic struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13198c2ecf20Sopenharmony_ci						 struct scatterlist *src,
13208c2ecf20Sopenharmony_ci						 struct scatterlist *dst,
13218c2ecf20Sopenharmony_ci						 u8 *iv,
13228c2ecf20Sopenharmony_ci						 unsigned int assoclen,
13238c2ecf20Sopenharmony_ci						 unsigned int cryptlen,
13248c2ecf20Sopenharmony_ci						 unsigned int authsize,
13258c2ecf20Sopenharmony_ci						 unsigned int ivsize,
13268c2ecf20Sopenharmony_ci						 int icv_stashing,
13278c2ecf20Sopenharmony_ci						 u32 cryptoflags,
13288c2ecf20Sopenharmony_ci						 bool encrypt)
13298c2ecf20Sopenharmony_ci{
13308c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
13318c2ecf20Sopenharmony_ci	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
13328c2ecf20Sopenharmony_ci	dma_addr_t iv_dma = 0;
13338c2ecf20Sopenharmony_ci	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
13348c2ecf20Sopenharmony_ci		      GFP_ATOMIC;
13358c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
13368c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
13378c2ecf20Sopenharmony_ci	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci	if (cryptlen + authsize > max_len) {
13408c2ecf20Sopenharmony_ci		dev_err(dev, "length exceeds h/w max limit\n");
13418c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
13428c2ecf20Sopenharmony_ci	}
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	if (!dst || dst == src) {
13458c2ecf20Sopenharmony_ci		src_len = assoclen + cryptlen + authsize;
13468c2ecf20Sopenharmony_ci		src_nents = sg_nents_for_len(src, src_len);
13478c2ecf20Sopenharmony_ci		if (src_nents < 0) {
13488c2ecf20Sopenharmony_ci			dev_err(dev, "Invalid number of src SG.\n");
13498c2ecf20Sopenharmony_ci			return ERR_PTR(-EINVAL);
13508c2ecf20Sopenharmony_ci		}
13518c2ecf20Sopenharmony_ci		src_nents = (src_nents == 1) ? 0 : src_nents;
13528c2ecf20Sopenharmony_ci		dst_nents = dst ? src_nents : 0;
13538c2ecf20Sopenharmony_ci		dst_len = 0;
13548c2ecf20Sopenharmony_ci	} else { /* dst && dst != src*/
13558c2ecf20Sopenharmony_ci		src_len = assoclen + cryptlen + (encrypt ? 0 : authsize);
13568c2ecf20Sopenharmony_ci		src_nents = sg_nents_for_len(src, src_len);
13578c2ecf20Sopenharmony_ci		if (src_nents < 0) {
13588c2ecf20Sopenharmony_ci			dev_err(dev, "Invalid number of src SG.\n");
13598c2ecf20Sopenharmony_ci			return ERR_PTR(-EINVAL);
13608c2ecf20Sopenharmony_ci		}
13618c2ecf20Sopenharmony_ci		src_nents = (src_nents == 1) ? 0 : src_nents;
13628c2ecf20Sopenharmony_ci		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
13638c2ecf20Sopenharmony_ci		dst_nents = sg_nents_for_len(dst, dst_len);
13648c2ecf20Sopenharmony_ci		if (dst_nents < 0) {
13658c2ecf20Sopenharmony_ci			dev_err(dev, "Invalid number of dst SG.\n");
13668c2ecf20Sopenharmony_ci			return ERR_PTR(-EINVAL);
13678c2ecf20Sopenharmony_ci		}
13688c2ecf20Sopenharmony_ci		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
13698c2ecf20Sopenharmony_ci	}
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	/*
13728c2ecf20Sopenharmony_ci	 * allocate space for base edesc plus the link tables,
13738c2ecf20Sopenharmony_ci	 * allowing for two separate entries for AD and generated ICV (+ 2),
13748c2ecf20Sopenharmony_ci	 * and space for two sets of ICVs (stashed and generated)
13758c2ecf20Sopenharmony_ci	 */
13768c2ecf20Sopenharmony_ci	alloc_len = sizeof(struct talitos_edesc);
13778c2ecf20Sopenharmony_ci	if (src_nents || dst_nents || !encrypt) {
13788c2ecf20Sopenharmony_ci		if (is_sec1)
13798c2ecf20Sopenharmony_ci			dma_len = (src_nents ? src_len : 0) +
13808c2ecf20Sopenharmony_ci				  (dst_nents ? dst_len : 0) + authsize;
13818c2ecf20Sopenharmony_ci		else
13828c2ecf20Sopenharmony_ci			dma_len = (src_nents + dst_nents + 2) *
13838c2ecf20Sopenharmony_ci				  sizeof(struct talitos_ptr) + authsize;
13848c2ecf20Sopenharmony_ci		alloc_len += dma_len;
13858c2ecf20Sopenharmony_ci	} else {
13868c2ecf20Sopenharmony_ci		dma_len = 0;
13878c2ecf20Sopenharmony_ci	}
13888c2ecf20Sopenharmony_ci	alloc_len += icv_stashing ? authsize : 0;
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci	/* if its a ahash, add space for a second desc next to the first one */
13918c2ecf20Sopenharmony_ci	if (is_sec1 && !dst)
13928c2ecf20Sopenharmony_ci		alloc_len += sizeof(struct talitos_desc);
13938c2ecf20Sopenharmony_ci	alloc_len += ivsize;
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	edesc = kmalloc(alloc_len, GFP_DMA | flags);
13968c2ecf20Sopenharmony_ci	if (!edesc)
13978c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
13988c2ecf20Sopenharmony_ci	if (ivsize) {
13998c2ecf20Sopenharmony_ci		iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
14008c2ecf20Sopenharmony_ci		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
14018c2ecf20Sopenharmony_ci	}
14028c2ecf20Sopenharmony_ci	memset(&edesc->desc, 0, sizeof(edesc->desc));
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	edesc->src_nents = src_nents;
14058c2ecf20Sopenharmony_ci	edesc->dst_nents = dst_nents;
14068c2ecf20Sopenharmony_ci	edesc->iv_dma = iv_dma;
14078c2ecf20Sopenharmony_ci	edesc->dma_len = dma_len;
14088c2ecf20Sopenharmony_ci	if (dma_len)
14098c2ecf20Sopenharmony_ci		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
14108c2ecf20Sopenharmony_ci						     edesc->dma_len,
14118c2ecf20Sopenharmony_ci						     DMA_BIDIRECTIONAL);
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci	return edesc;
14148c2ecf20Sopenharmony_ci}
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_cistatic struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
14178c2ecf20Sopenharmony_ci					      int icv_stashing, bool encrypt)
14188c2ecf20Sopenharmony_ci{
14198c2ecf20Sopenharmony_ci	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
14208c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(authenc);
14218c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
14228c2ecf20Sopenharmony_ci	unsigned int ivsize = crypto_aead_ivsize(authenc);
14238c2ecf20Sopenharmony_ci	unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
14268c2ecf20Sopenharmony_ci				   iv, areq->assoclen, cryptlen,
14278c2ecf20Sopenharmony_ci				   authsize, ivsize, icv_stashing,
14288c2ecf20Sopenharmony_ci				   areq->base.flags, encrypt);
14298c2ecf20Sopenharmony_ci}
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_cistatic int aead_encrypt(struct aead_request *req)
14328c2ecf20Sopenharmony_ci{
14338c2ecf20Sopenharmony_ci	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14348c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
14358c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci	/* allocate extended descriptor */
14388c2ecf20Sopenharmony_ci	edesc = aead_edesc_alloc(req, req->iv, 0, true);
14398c2ecf20Sopenharmony_ci	if (IS_ERR(edesc))
14408c2ecf20Sopenharmony_ci		return PTR_ERR(edesc);
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	/* set encrypt */
14438c2ecf20Sopenharmony_ci	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci	return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done);
14468c2ecf20Sopenharmony_ci}
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_cistatic int aead_decrypt(struct aead_request *req)
14498c2ecf20Sopenharmony_ci{
14508c2ecf20Sopenharmony_ci	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
14518c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(authenc);
14528c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
14538c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
14548c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
14558c2ecf20Sopenharmony_ci	void *icvdata;
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	/* allocate extended descriptor */
14588c2ecf20Sopenharmony_ci	edesc = aead_edesc_alloc(req, req->iv, 1, false);
14598c2ecf20Sopenharmony_ci	if (IS_ERR(edesc))
14608c2ecf20Sopenharmony_ci		return PTR_ERR(edesc);
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_ci	if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) &&
14638c2ecf20Sopenharmony_ci	    (priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
14648c2ecf20Sopenharmony_ci	    ((!edesc->src_nents && !edesc->dst_nents) ||
14658c2ecf20Sopenharmony_ci	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci		/* decrypt and check the ICV */
14688c2ecf20Sopenharmony_ci		edesc->desc.hdr = ctx->desc_hdr_template |
14698c2ecf20Sopenharmony_ci				  DESC_HDR_DIR_INBOUND |
14708c2ecf20Sopenharmony_ci				  DESC_HDR_MODE1_MDEU_CICV;
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci		/* reset integrity check result bits */
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci		return ipsec_esp(edesc, req, false,
14758c2ecf20Sopenharmony_ci				 ipsec_esp_decrypt_hwauth_done);
14768c2ecf20Sopenharmony_ci	}
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci	/* Have to check the ICV with software */
14798c2ecf20Sopenharmony_ci	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
14808c2ecf20Sopenharmony_ci
14818c2ecf20Sopenharmony_ci	/* stash incoming ICV for later cmp with ICV generated by the h/w */
14828c2ecf20Sopenharmony_ci	icvdata = edesc->buf + edesc->dma_len;
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize,
14858c2ecf20Sopenharmony_ci			   req->assoclen + req->cryptlen - authsize);
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	return ipsec_esp(edesc, req, false, ipsec_esp_decrypt_swauth_done);
14888c2ecf20Sopenharmony_ci}
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_cistatic int skcipher_setkey(struct crypto_skcipher *cipher,
14918c2ecf20Sopenharmony_ci			     const u8 *key, unsigned int keylen)
14928c2ecf20Sopenharmony_ci{
14938c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
14948c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci	if (ctx->keylen)
14978c2ecf20Sopenharmony_ci		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci	memcpy(&ctx->key, key, keylen);
15008c2ecf20Sopenharmony_ci	ctx->keylen = keylen;
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci	ctx->dma_key = dma_map_single(dev, ctx->key, keylen, DMA_TO_DEVICE);
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	return 0;
15058c2ecf20Sopenharmony_ci}
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_cistatic int skcipher_des_setkey(struct crypto_skcipher *cipher,
15088c2ecf20Sopenharmony_ci				 const u8 *key, unsigned int keylen)
15098c2ecf20Sopenharmony_ci{
15108c2ecf20Sopenharmony_ci	return verify_skcipher_des_key(cipher, key) ?:
15118c2ecf20Sopenharmony_ci	       skcipher_setkey(cipher, key, keylen);
15128c2ecf20Sopenharmony_ci}
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_cistatic int skcipher_des3_setkey(struct crypto_skcipher *cipher,
15158c2ecf20Sopenharmony_ci				  const u8 *key, unsigned int keylen)
15168c2ecf20Sopenharmony_ci{
15178c2ecf20Sopenharmony_ci	return verify_skcipher_des3_key(cipher, key) ?:
15188c2ecf20Sopenharmony_ci	       skcipher_setkey(cipher, key, keylen);
15198c2ecf20Sopenharmony_ci}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_cistatic int skcipher_aes_setkey(struct crypto_skcipher *cipher,
15228c2ecf20Sopenharmony_ci				  const u8 *key, unsigned int keylen)
15238c2ecf20Sopenharmony_ci{
15248c2ecf20Sopenharmony_ci	if (keylen == AES_KEYSIZE_128 || keylen == AES_KEYSIZE_192 ||
15258c2ecf20Sopenharmony_ci	    keylen == AES_KEYSIZE_256)
15268c2ecf20Sopenharmony_ci		return skcipher_setkey(cipher, key, keylen);
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci	return -EINVAL;
15298c2ecf20Sopenharmony_ci}
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_cistatic void common_nonsnoop_unmap(struct device *dev,
15328c2ecf20Sopenharmony_ci				  struct talitos_edesc *edesc,
15338c2ecf20Sopenharmony_ci				  struct skcipher_request *areq)
15348c2ecf20Sopenharmony_ci{
15358c2ecf20Sopenharmony_ci	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci	talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, 0);
15388c2ecf20Sopenharmony_ci	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	if (edesc->dma_len)
15418c2ecf20Sopenharmony_ci		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
15428c2ecf20Sopenharmony_ci				 DMA_BIDIRECTIONAL);
15438c2ecf20Sopenharmony_ci}
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_cistatic void skcipher_done(struct device *dev,
15468c2ecf20Sopenharmony_ci			    struct talitos_desc *desc, void *context,
15478c2ecf20Sopenharmony_ci			    int err)
15488c2ecf20Sopenharmony_ci{
15498c2ecf20Sopenharmony_ci	struct skcipher_request *areq = context;
15508c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
15518c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
15528c2ecf20Sopenharmony_ci	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
15538c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_ci	edesc = container_of(desc, struct talitos_edesc, desc);
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci	common_nonsnoop_unmap(dev, edesc, areq);
15588c2ecf20Sopenharmony_ci	memcpy(areq->iv, ctx->iv, ivsize);
15598c2ecf20Sopenharmony_ci
15608c2ecf20Sopenharmony_ci	kfree(edesc);
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci	areq->base.complete(&areq->base, err);
15638c2ecf20Sopenharmony_ci}
15648c2ecf20Sopenharmony_ci
15658c2ecf20Sopenharmony_cistatic int common_nonsnoop(struct talitos_edesc *edesc,
15668c2ecf20Sopenharmony_ci			   struct skcipher_request *areq,
15678c2ecf20Sopenharmony_ci			   void (*callback) (struct device *dev,
15688c2ecf20Sopenharmony_ci					     struct talitos_desc *desc,
15698c2ecf20Sopenharmony_ci					     void *context, int error))
15708c2ecf20Sopenharmony_ci{
15718c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
15728c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
15738c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
15748c2ecf20Sopenharmony_ci	struct talitos_desc *desc = &edesc->desc;
15758c2ecf20Sopenharmony_ci	unsigned int cryptlen = areq->cryptlen;
15768c2ecf20Sopenharmony_ci	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
15778c2ecf20Sopenharmony_ci	int sg_count, ret;
15788c2ecf20Sopenharmony_ci	bool sync_needed = false;
15798c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
15808c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
15818c2ecf20Sopenharmony_ci	bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU &&
15828c2ecf20Sopenharmony_ci		      (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR;
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_ci	/* first DWORD empty */
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	/* cipher iv */
15878c2ecf20Sopenharmony_ci	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize, is_sec1);
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	/* cipher key */
15908c2ecf20Sopenharmony_ci	to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen, is_sec1);
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci	sg_count = edesc->src_nents ?: 1;
15938c2ecf20Sopenharmony_ci	if (is_sec1 && sg_count > 1)
15948c2ecf20Sopenharmony_ci		sg_copy_to_buffer(areq->src, sg_count, edesc->buf,
15958c2ecf20Sopenharmony_ci				  cryptlen);
15968c2ecf20Sopenharmony_ci	else
15978c2ecf20Sopenharmony_ci		sg_count = dma_map_sg(dev, areq->src, sg_count,
15988c2ecf20Sopenharmony_ci				      (areq->src == areq->dst) ?
15998c2ecf20Sopenharmony_ci				      DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
16008c2ecf20Sopenharmony_ci	/*
16018c2ecf20Sopenharmony_ci	 * cipher in
16028c2ecf20Sopenharmony_ci	 */
16038c2ecf20Sopenharmony_ci	sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3],
16048c2ecf20Sopenharmony_ci				      sg_count, 0, 0, 0, false, is_ctr ? 16 : 1);
16058c2ecf20Sopenharmony_ci	if (sg_count > 1)
16068c2ecf20Sopenharmony_ci		sync_needed = true;
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci	/* cipher out */
16098c2ecf20Sopenharmony_ci	if (areq->src != areq->dst) {
16108c2ecf20Sopenharmony_ci		sg_count = edesc->dst_nents ? : 1;
16118c2ecf20Sopenharmony_ci		if (!is_sec1 || sg_count == 1)
16128c2ecf20Sopenharmony_ci			dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
16138c2ecf20Sopenharmony_ci	}
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci	ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
16168c2ecf20Sopenharmony_ci			     sg_count, 0, (edesc->src_nents + 1));
16178c2ecf20Sopenharmony_ci	if (ret > 1)
16188c2ecf20Sopenharmony_ci		sync_needed = true;
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_ci	/* iv out */
16218c2ecf20Sopenharmony_ci	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
16228c2ecf20Sopenharmony_ci			       DMA_FROM_DEVICE);
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	/* last DWORD empty */
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci	if (sync_needed)
16278c2ecf20Sopenharmony_ci		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
16288c2ecf20Sopenharmony_ci					   edesc->dma_len, DMA_BIDIRECTIONAL);
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
16318c2ecf20Sopenharmony_ci	if (ret != -EINPROGRESS) {
16328c2ecf20Sopenharmony_ci		common_nonsnoop_unmap(dev, edesc, areq);
16338c2ecf20Sopenharmony_ci		kfree(edesc);
16348c2ecf20Sopenharmony_ci	}
16358c2ecf20Sopenharmony_ci	return ret;
16368c2ecf20Sopenharmony_ci}
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_cistatic struct talitos_edesc *skcipher_edesc_alloc(struct skcipher_request *
16398c2ecf20Sopenharmony_ci						    areq, bool encrypt)
16408c2ecf20Sopenharmony_ci{
16418c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
16428c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
16438c2ecf20Sopenharmony_ci	unsigned int ivsize = crypto_skcipher_ivsize(cipher);
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ci	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
16468c2ecf20Sopenharmony_ci				   areq->iv, 0, areq->cryptlen, 0, ivsize, 0,
16478c2ecf20Sopenharmony_ci				   areq->base.flags, encrypt);
16488c2ecf20Sopenharmony_ci}
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_cistatic int skcipher_encrypt(struct skcipher_request *areq)
16518c2ecf20Sopenharmony_ci{
16528c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
16538c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
16548c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
16558c2ecf20Sopenharmony_ci	unsigned int blocksize =
16568c2ecf20Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher));
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci	if (!areq->cryptlen)
16598c2ecf20Sopenharmony_ci		return 0;
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	if (areq->cryptlen % blocksize)
16628c2ecf20Sopenharmony_ci		return -EINVAL;
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci	/* allocate extended descriptor */
16658c2ecf20Sopenharmony_ci	edesc = skcipher_edesc_alloc(areq, true);
16668c2ecf20Sopenharmony_ci	if (IS_ERR(edesc))
16678c2ecf20Sopenharmony_ci		return PTR_ERR(edesc);
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	/* set encrypt */
16708c2ecf20Sopenharmony_ci	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	return common_nonsnoop(edesc, areq, skcipher_done);
16738c2ecf20Sopenharmony_ci}
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_cistatic int skcipher_decrypt(struct skcipher_request *areq)
16768c2ecf20Sopenharmony_ci{
16778c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(areq);
16788c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(cipher);
16798c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
16808c2ecf20Sopenharmony_ci	unsigned int blocksize =
16818c2ecf20Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_skcipher_tfm(cipher));
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci	if (!areq->cryptlen)
16848c2ecf20Sopenharmony_ci		return 0;
16858c2ecf20Sopenharmony_ci
16868c2ecf20Sopenharmony_ci	if (areq->cryptlen % blocksize)
16878c2ecf20Sopenharmony_ci		return -EINVAL;
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci	/* allocate extended descriptor */
16908c2ecf20Sopenharmony_ci	edesc = skcipher_edesc_alloc(areq, false);
16918c2ecf20Sopenharmony_ci	if (IS_ERR(edesc))
16928c2ecf20Sopenharmony_ci		return PTR_ERR(edesc);
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
16958c2ecf20Sopenharmony_ci
16968c2ecf20Sopenharmony_ci	return common_nonsnoop(edesc, areq, skcipher_done);
16978c2ecf20Sopenharmony_ci}
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_cistatic void common_nonsnoop_hash_unmap(struct device *dev,
17008c2ecf20Sopenharmony_ci				       struct talitos_edesc *edesc,
17018c2ecf20Sopenharmony_ci				       struct ahash_request *areq)
17028c2ecf20Sopenharmony_ci{
17038c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
17048c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
17058c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
17068c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
17078c2ecf20Sopenharmony_ci	struct talitos_desc *desc = &edesc->desc;
17088c2ecf20Sopenharmony_ci	struct talitos_desc *desc2 = (struct talitos_desc *)
17098c2ecf20Sopenharmony_ci				     (edesc->buf + edesc->dma_len);
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_ci	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
17128c2ecf20Sopenharmony_ci	if (desc->next_desc &&
17138c2ecf20Sopenharmony_ci	    desc->ptr[5].ptr != desc2->ptr[5].ptr)
17148c2ecf20Sopenharmony_ci		unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
17158c2ecf20Sopenharmony_ci	if (req_ctx->last)
17168c2ecf20Sopenharmony_ci		memcpy(areq->result, req_ctx->hw_context,
17178c2ecf20Sopenharmony_ci		       crypto_ahash_digestsize(tfm));
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci	if (req_ctx->psrc)
17208c2ecf20Sopenharmony_ci		talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_ci	/* When using hashctx-in, must unmap it. */
17238c2ecf20Sopenharmony_ci	if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1))
17248c2ecf20Sopenharmony_ci		unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1],
17258c2ecf20Sopenharmony_ci					 DMA_TO_DEVICE);
17268c2ecf20Sopenharmony_ci	else if (desc->next_desc)
17278c2ecf20Sopenharmony_ci		unmap_single_talitos_ptr(dev, &desc2->ptr[1],
17288c2ecf20Sopenharmony_ci					 DMA_TO_DEVICE);
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci	if (is_sec1 && req_ctx->nbuf)
17318c2ecf20Sopenharmony_ci		unmap_single_talitos_ptr(dev, &desc->ptr[3],
17328c2ecf20Sopenharmony_ci					 DMA_TO_DEVICE);
17338c2ecf20Sopenharmony_ci
17348c2ecf20Sopenharmony_ci	if (edesc->dma_len)
17358c2ecf20Sopenharmony_ci		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
17368c2ecf20Sopenharmony_ci				 DMA_BIDIRECTIONAL);
17378c2ecf20Sopenharmony_ci
17388c2ecf20Sopenharmony_ci	if (edesc->desc.next_desc)
17398c2ecf20Sopenharmony_ci		dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc),
17408c2ecf20Sopenharmony_ci				 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
17418c2ecf20Sopenharmony_ci}
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_cistatic void ahash_done(struct device *dev,
17448c2ecf20Sopenharmony_ci		       struct talitos_desc *desc, void *context,
17458c2ecf20Sopenharmony_ci		       int err)
17468c2ecf20Sopenharmony_ci{
17478c2ecf20Sopenharmony_ci	struct ahash_request *areq = context;
17488c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc =
17498c2ecf20Sopenharmony_ci		 container_of(desc, struct talitos_edesc, desc);
17508c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
17518c2ecf20Sopenharmony_ci
17528c2ecf20Sopenharmony_ci	if (!req_ctx->last && req_ctx->to_hash_later) {
17538c2ecf20Sopenharmony_ci		/* Position any partial block for next update/final/finup */
17548c2ecf20Sopenharmony_ci		req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
17558c2ecf20Sopenharmony_ci		req_ctx->nbuf = req_ctx->to_hash_later;
17568c2ecf20Sopenharmony_ci	}
17578c2ecf20Sopenharmony_ci	common_nonsnoop_hash_unmap(dev, edesc, areq);
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	kfree(edesc);
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_ci	areq->base.complete(&areq->base, err);
17628c2ecf20Sopenharmony_ci}
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci/*
17658c2ecf20Sopenharmony_ci * SEC1 doesn't like hashing of 0 sized message, so we do the padding
17668c2ecf20Sopenharmony_ci * ourself and submit a padded block
17678c2ecf20Sopenharmony_ci */
17688c2ecf20Sopenharmony_cistatic void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
17698c2ecf20Sopenharmony_ci			       struct talitos_edesc *edesc,
17708c2ecf20Sopenharmony_ci			       struct talitos_ptr *ptr)
17718c2ecf20Sopenharmony_ci{
17728c2ecf20Sopenharmony_ci	static u8 padded_hash[64] = {
17738c2ecf20Sopenharmony_ci		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17748c2ecf20Sopenharmony_ci		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17758c2ecf20Sopenharmony_ci		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17768c2ecf20Sopenharmony_ci		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17778c2ecf20Sopenharmony_ci	};
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci	pr_err_once("Bug in SEC1, padding ourself\n");
17808c2ecf20Sopenharmony_ci	edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
17818c2ecf20Sopenharmony_ci	map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
17828c2ecf20Sopenharmony_ci			       (char *)padded_hash, DMA_TO_DEVICE);
17838c2ecf20Sopenharmony_ci}
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_cistatic int common_nonsnoop_hash(struct talitos_edesc *edesc,
17868c2ecf20Sopenharmony_ci				struct ahash_request *areq, unsigned int length,
17878c2ecf20Sopenharmony_ci				void (*callback) (struct device *dev,
17888c2ecf20Sopenharmony_ci						  struct talitos_desc *desc,
17898c2ecf20Sopenharmony_ci						  void *context, int error))
17908c2ecf20Sopenharmony_ci{
17918c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
17928c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
17938c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
17948c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
17958c2ecf20Sopenharmony_ci	struct talitos_desc *desc = &edesc->desc;
17968c2ecf20Sopenharmony_ci	int ret;
17978c2ecf20Sopenharmony_ci	bool sync_needed = false;
17988c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
17998c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
18008c2ecf20Sopenharmony_ci	int sg_count;
18018c2ecf20Sopenharmony_ci
18028c2ecf20Sopenharmony_ci	/* first DWORD empty */
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	/* hash context in */
18058c2ecf20Sopenharmony_ci	if (!req_ctx->first || req_ctx->swinit) {
18068c2ecf20Sopenharmony_ci		map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
18078c2ecf20Sopenharmony_ci					      req_ctx->hw_context_size,
18088c2ecf20Sopenharmony_ci					      req_ctx->hw_context,
18098c2ecf20Sopenharmony_ci					      DMA_TO_DEVICE);
18108c2ecf20Sopenharmony_ci		req_ctx->swinit = 0;
18118c2ecf20Sopenharmony_ci	}
18128c2ecf20Sopenharmony_ci	/* Indicate next op is not the first. */
18138c2ecf20Sopenharmony_ci	req_ctx->first = 0;
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	/* HMAC key */
18168c2ecf20Sopenharmony_ci	if (ctx->keylen)
18178c2ecf20Sopenharmony_ci		to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
18188c2ecf20Sopenharmony_ci			       is_sec1);
18198c2ecf20Sopenharmony_ci
18208c2ecf20Sopenharmony_ci	if (is_sec1 && req_ctx->nbuf)
18218c2ecf20Sopenharmony_ci		length -= req_ctx->nbuf;
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	sg_count = edesc->src_nents ?: 1;
18248c2ecf20Sopenharmony_ci	if (is_sec1 && sg_count > 1)
18258c2ecf20Sopenharmony_ci		sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
18268c2ecf20Sopenharmony_ci	else if (length)
18278c2ecf20Sopenharmony_ci		sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
18288c2ecf20Sopenharmony_ci				      DMA_TO_DEVICE);
18298c2ecf20Sopenharmony_ci	/*
18308c2ecf20Sopenharmony_ci	 * data in
18318c2ecf20Sopenharmony_ci	 */
18328c2ecf20Sopenharmony_ci	if (is_sec1 && req_ctx->nbuf) {
18338c2ecf20Sopenharmony_ci		map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
18348c2ecf20Sopenharmony_ci				       req_ctx->buf[req_ctx->buf_idx],
18358c2ecf20Sopenharmony_ci				       DMA_TO_DEVICE);
18368c2ecf20Sopenharmony_ci	} else {
18378c2ecf20Sopenharmony_ci		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
18388c2ecf20Sopenharmony_ci					  &desc->ptr[3], sg_count, 0, 0);
18398c2ecf20Sopenharmony_ci		if (sg_count > 1)
18408c2ecf20Sopenharmony_ci			sync_needed = true;
18418c2ecf20Sopenharmony_ci	}
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci	/* fifth DWORD empty */
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci	/* hash/HMAC out -or- hash context out */
18468c2ecf20Sopenharmony_ci	if (req_ctx->last)
18478c2ecf20Sopenharmony_ci		map_single_talitos_ptr(dev, &desc->ptr[5],
18488c2ecf20Sopenharmony_ci				       crypto_ahash_digestsize(tfm),
18498c2ecf20Sopenharmony_ci				       req_ctx->hw_context, DMA_FROM_DEVICE);
18508c2ecf20Sopenharmony_ci	else
18518c2ecf20Sopenharmony_ci		map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
18528c2ecf20Sopenharmony_ci					      req_ctx->hw_context_size,
18538c2ecf20Sopenharmony_ci					      req_ctx->hw_context,
18548c2ecf20Sopenharmony_ci					      DMA_FROM_DEVICE);
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ci	/* last DWORD empty */
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
18598c2ecf20Sopenharmony_ci		talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci	if (is_sec1 && req_ctx->nbuf && length) {
18628c2ecf20Sopenharmony_ci		struct talitos_desc *desc2 = (struct talitos_desc *)
18638c2ecf20Sopenharmony_ci					     (edesc->buf + edesc->dma_len);
18648c2ecf20Sopenharmony_ci		dma_addr_t next_desc;
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci		memset(desc2, 0, sizeof(*desc2));
18678c2ecf20Sopenharmony_ci		desc2->hdr = desc->hdr;
18688c2ecf20Sopenharmony_ci		desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
18698c2ecf20Sopenharmony_ci		desc2->hdr1 = desc2->hdr;
18708c2ecf20Sopenharmony_ci		desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
18718c2ecf20Sopenharmony_ci		desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
18728c2ecf20Sopenharmony_ci		desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci		if (desc->ptr[1].ptr)
18758c2ecf20Sopenharmony_ci			copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
18768c2ecf20Sopenharmony_ci					 is_sec1);
18778c2ecf20Sopenharmony_ci		else
18788c2ecf20Sopenharmony_ci			map_single_talitos_ptr_nosync(dev, &desc2->ptr[1],
18798c2ecf20Sopenharmony_ci						      req_ctx->hw_context_size,
18808c2ecf20Sopenharmony_ci						      req_ctx->hw_context,
18818c2ecf20Sopenharmony_ci						      DMA_TO_DEVICE);
18828c2ecf20Sopenharmony_ci		copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
18838c2ecf20Sopenharmony_ci		sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
18848c2ecf20Sopenharmony_ci					  &desc2->ptr[3], sg_count, 0, 0);
18858c2ecf20Sopenharmony_ci		if (sg_count > 1)
18868c2ecf20Sopenharmony_ci			sync_needed = true;
18878c2ecf20Sopenharmony_ci		copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
18888c2ecf20Sopenharmony_ci		if (req_ctx->last)
18898c2ecf20Sopenharmony_ci			map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
18908c2ecf20Sopenharmony_ci						      req_ctx->hw_context_size,
18918c2ecf20Sopenharmony_ci						      req_ctx->hw_context,
18928c2ecf20Sopenharmony_ci						      DMA_FROM_DEVICE);
18938c2ecf20Sopenharmony_ci
18948c2ecf20Sopenharmony_ci		next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE,
18958c2ecf20Sopenharmony_ci					   DMA_BIDIRECTIONAL);
18968c2ecf20Sopenharmony_ci		desc->next_desc = cpu_to_be32(next_desc);
18978c2ecf20Sopenharmony_ci	}
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_ci	if (sync_needed)
19008c2ecf20Sopenharmony_ci		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
19018c2ecf20Sopenharmony_ci					   edesc->dma_len, DMA_BIDIRECTIONAL);
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
19048c2ecf20Sopenharmony_ci	if (ret != -EINPROGRESS) {
19058c2ecf20Sopenharmony_ci		common_nonsnoop_hash_unmap(dev, edesc, areq);
19068c2ecf20Sopenharmony_ci		kfree(edesc);
19078c2ecf20Sopenharmony_ci	}
19088c2ecf20Sopenharmony_ci	return ret;
19098c2ecf20Sopenharmony_ci}
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_cistatic struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
19128c2ecf20Sopenharmony_ci					       unsigned int nbytes)
19138c2ecf20Sopenharmony_ci{
19148c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
19158c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
19168c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
19178c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
19188c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci	if (is_sec1)
19218c2ecf20Sopenharmony_ci		nbytes -= req_ctx->nbuf;
19228c2ecf20Sopenharmony_ci
19238c2ecf20Sopenharmony_ci	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
19248c2ecf20Sopenharmony_ci				   nbytes, 0, 0, 0, areq->base.flags, false);
19258c2ecf20Sopenharmony_ci}
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_cistatic int ahash_init(struct ahash_request *areq)
19288c2ecf20Sopenharmony_ci{
19298c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
19308c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
19318c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
19328c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
19338c2ecf20Sopenharmony_ci	unsigned int size;
19348c2ecf20Sopenharmony_ci	dma_addr_t dma;
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	/* Initialize the context */
19378c2ecf20Sopenharmony_ci	req_ctx->buf_idx = 0;
19388c2ecf20Sopenharmony_ci	req_ctx->nbuf = 0;
19398c2ecf20Sopenharmony_ci	req_ctx->first = 1; /* first indicates h/w must init its context */
19408c2ecf20Sopenharmony_ci	req_ctx->swinit = 0; /* assume h/w init of context */
19418c2ecf20Sopenharmony_ci	size =	(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
19428c2ecf20Sopenharmony_ci			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
19438c2ecf20Sopenharmony_ci			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
19448c2ecf20Sopenharmony_ci	req_ctx->hw_context_size = size;
19458c2ecf20Sopenharmony_ci
19468c2ecf20Sopenharmony_ci	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
19478c2ecf20Sopenharmony_ci			     DMA_TO_DEVICE);
19488c2ecf20Sopenharmony_ci	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci	return 0;
19518c2ecf20Sopenharmony_ci}
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_ci/*
19548c2ecf20Sopenharmony_ci * on h/w without explicit sha224 support, we initialize h/w context
19558c2ecf20Sopenharmony_ci * manually with sha224 constants, and tell it to run sha256.
19568c2ecf20Sopenharmony_ci */
19578c2ecf20Sopenharmony_cistatic int ahash_init_sha224_swinit(struct ahash_request *areq)
19588c2ecf20Sopenharmony_ci{
19598c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ci	req_ctx->hw_context[0] = SHA224_H0;
19628c2ecf20Sopenharmony_ci	req_ctx->hw_context[1] = SHA224_H1;
19638c2ecf20Sopenharmony_ci	req_ctx->hw_context[2] = SHA224_H2;
19648c2ecf20Sopenharmony_ci	req_ctx->hw_context[3] = SHA224_H3;
19658c2ecf20Sopenharmony_ci	req_ctx->hw_context[4] = SHA224_H4;
19668c2ecf20Sopenharmony_ci	req_ctx->hw_context[5] = SHA224_H5;
19678c2ecf20Sopenharmony_ci	req_ctx->hw_context[6] = SHA224_H6;
19688c2ecf20Sopenharmony_ci	req_ctx->hw_context[7] = SHA224_H7;
19698c2ecf20Sopenharmony_ci
19708c2ecf20Sopenharmony_ci	/* init 64-bit count */
19718c2ecf20Sopenharmony_ci	req_ctx->hw_context[8] = 0;
19728c2ecf20Sopenharmony_ci	req_ctx->hw_context[9] = 0;
19738c2ecf20Sopenharmony_ci
19748c2ecf20Sopenharmony_ci	ahash_init(areq);
19758c2ecf20Sopenharmony_ci	req_ctx->swinit = 1;/* prevent h/w initting context with sha256 values*/
19768c2ecf20Sopenharmony_ci
19778c2ecf20Sopenharmony_ci	return 0;
19788c2ecf20Sopenharmony_ci}
19798c2ecf20Sopenharmony_ci
19808c2ecf20Sopenharmony_cistatic int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
19818c2ecf20Sopenharmony_ci{
19828c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
19838c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
19848c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
19858c2ecf20Sopenharmony_ci	struct talitos_edesc *edesc;
19868c2ecf20Sopenharmony_ci	unsigned int blocksize =
19878c2ecf20Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
19888c2ecf20Sopenharmony_ci	unsigned int nbytes_to_hash;
19898c2ecf20Sopenharmony_ci	unsigned int to_hash_later;
19908c2ecf20Sopenharmony_ci	unsigned int nsg;
19918c2ecf20Sopenharmony_ci	int nents;
19928c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
19938c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
19948c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
19958c2ecf20Sopenharmony_ci	u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
19968c2ecf20Sopenharmony_ci
19978c2ecf20Sopenharmony_ci	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
19988c2ecf20Sopenharmony_ci		/* Buffer up to one whole block */
19998c2ecf20Sopenharmony_ci		nents = sg_nents_for_len(areq->src, nbytes);
20008c2ecf20Sopenharmony_ci		if (nents < 0) {
20018c2ecf20Sopenharmony_ci			dev_err(ctx->dev, "Invalid number of src SG.\n");
20028c2ecf20Sopenharmony_ci			return nents;
20038c2ecf20Sopenharmony_ci		}
20048c2ecf20Sopenharmony_ci		sg_copy_to_buffer(areq->src, nents,
20058c2ecf20Sopenharmony_ci				  ctx_buf + req_ctx->nbuf, nbytes);
20068c2ecf20Sopenharmony_ci		req_ctx->nbuf += nbytes;
20078c2ecf20Sopenharmony_ci		return 0;
20088c2ecf20Sopenharmony_ci	}
20098c2ecf20Sopenharmony_ci
20108c2ecf20Sopenharmony_ci	/* At least (blocksize + 1) bytes are available to hash */
20118c2ecf20Sopenharmony_ci	nbytes_to_hash = nbytes + req_ctx->nbuf;
20128c2ecf20Sopenharmony_ci	to_hash_later = nbytes_to_hash & (blocksize - 1);
20138c2ecf20Sopenharmony_ci
20148c2ecf20Sopenharmony_ci	if (req_ctx->last)
20158c2ecf20Sopenharmony_ci		to_hash_later = 0;
20168c2ecf20Sopenharmony_ci	else if (to_hash_later)
20178c2ecf20Sopenharmony_ci		/* There is a partial block. Hash the full block(s) now */
20188c2ecf20Sopenharmony_ci		nbytes_to_hash -= to_hash_later;
20198c2ecf20Sopenharmony_ci	else {
20208c2ecf20Sopenharmony_ci		/* Keep one block buffered */
20218c2ecf20Sopenharmony_ci		nbytes_to_hash -= blocksize;
20228c2ecf20Sopenharmony_ci		to_hash_later = blocksize;
20238c2ecf20Sopenharmony_ci	}
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci	/* Chain in any previously buffered data */
20268c2ecf20Sopenharmony_ci	if (!is_sec1 && req_ctx->nbuf) {
20278c2ecf20Sopenharmony_ci		nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
20288c2ecf20Sopenharmony_ci		sg_init_table(req_ctx->bufsl, nsg);
20298c2ecf20Sopenharmony_ci		sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
20308c2ecf20Sopenharmony_ci		if (nsg > 1)
20318c2ecf20Sopenharmony_ci			sg_chain(req_ctx->bufsl, 2, areq->src);
20328c2ecf20Sopenharmony_ci		req_ctx->psrc = req_ctx->bufsl;
20338c2ecf20Sopenharmony_ci	} else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
20348c2ecf20Sopenharmony_ci		int offset;
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci		if (nbytes_to_hash > blocksize)
20378c2ecf20Sopenharmony_ci			offset = blocksize - req_ctx->nbuf;
20388c2ecf20Sopenharmony_ci		else
20398c2ecf20Sopenharmony_ci			offset = nbytes_to_hash - req_ctx->nbuf;
20408c2ecf20Sopenharmony_ci		nents = sg_nents_for_len(areq->src, offset);
20418c2ecf20Sopenharmony_ci		if (nents < 0) {
20428c2ecf20Sopenharmony_ci			dev_err(ctx->dev, "Invalid number of src SG.\n");
20438c2ecf20Sopenharmony_ci			return nents;
20448c2ecf20Sopenharmony_ci		}
20458c2ecf20Sopenharmony_ci		sg_copy_to_buffer(areq->src, nents,
20468c2ecf20Sopenharmony_ci				  ctx_buf + req_ctx->nbuf, offset);
20478c2ecf20Sopenharmony_ci		req_ctx->nbuf += offset;
20488c2ecf20Sopenharmony_ci		req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, areq->src,
20498c2ecf20Sopenharmony_ci						 offset);
20508c2ecf20Sopenharmony_ci	} else
20518c2ecf20Sopenharmony_ci		req_ctx->psrc = areq->src;
20528c2ecf20Sopenharmony_ci
20538c2ecf20Sopenharmony_ci	if (to_hash_later) {
20548c2ecf20Sopenharmony_ci		nents = sg_nents_for_len(areq->src, nbytes);
20558c2ecf20Sopenharmony_ci		if (nents < 0) {
20568c2ecf20Sopenharmony_ci			dev_err(ctx->dev, "Invalid number of src SG.\n");
20578c2ecf20Sopenharmony_ci			return nents;
20588c2ecf20Sopenharmony_ci		}
20598c2ecf20Sopenharmony_ci		sg_pcopy_to_buffer(areq->src, nents,
20608c2ecf20Sopenharmony_ci				   req_ctx->buf[(req_ctx->buf_idx + 1) & 1],
20618c2ecf20Sopenharmony_ci				      to_hash_later,
20628c2ecf20Sopenharmony_ci				      nbytes - to_hash_later);
20638c2ecf20Sopenharmony_ci	}
20648c2ecf20Sopenharmony_ci	req_ctx->to_hash_later = to_hash_later;
20658c2ecf20Sopenharmony_ci
20668c2ecf20Sopenharmony_ci	/* Allocate extended descriptor */
20678c2ecf20Sopenharmony_ci	edesc = ahash_edesc_alloc(areq, nbytes_to_hash);
20688c2ecf20Sopenharmony_ci	if (IS_ERR(edesc))
20698c2ecf20Sopenharmony_ci		return PTR_ERR(edesc);
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_ci	edesc->desc.hdr = ctx->desc_hdr_template;
20728c2ecf20Sopenharmony_ci
20738c2ecf20Sopenharmony_ci	/* On last one, request SEC to pad; otherwise continue */
20748c2ecf20Sopenharmony_ci	if (req_ctx->last)
20758c2ecf20Sopenharmony_ci		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
20768c2ecf20Sopenharmony_ci	else
20778c2ecf20Sopenharmony_ci		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
20788c2ecf20Sopenharmony_ci
20798c2ecf20Sopenharmony_ci	/* request SEC to INIT hash. */
20808c2ecf20Sopenharmony_ci	if (req_ctx->first && !req_ctx->swinit)
20818c2ecf20Sopenharmony_ci		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_ci	/* When the tfm context has a keylen, it's an HMAC.
20848c2ecf20Sopenharmony_ci	 * A first or last (ie. not middle) descriptor must request HMAC.
20858c2ecf20Sopenharmony_ci	 */
20868c2ecf20Sopenharmony_ci	if (ctx->keylen && (req_ctx->first || req_ctx->last))
20878c2ecf20Sopenharmony_ci		edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_ci	return common_nonsnoop_hash(edesc, areq, nbytes_to_hash, ahash_done);
20908c2ecf20Sopenharmony_ci}
20918c2ecf20Sopenharmony_ci
20928c2ecf20Sopenharmony_cistatic int ahash_update(struct ahash_request *areq)
20938c2ecf20Sopenharmony_ci{
20948c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci	req_ctx->last = 0;
20978c2ecf20Sopenharmony_ci
20988c2ecf20Sopenharmony_ci	return ahash_process_req(areq, areq->nbytes);
20998c2ecf20Sopenharmony_ci}
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_cistatic int ahash_final(struct ahash_request *areq)
21028c2ecf20Sopenharmony_ci{
21038c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ci	req_ctx->last = 1;
21068c2ecf20Sopenharmony_ci
21078c2ecf20Sopenharmony_ci	return ahash_process_req(areq, 0);
21088c2ecf20Sopenharmony_ci}
21098c2ecf20Sopenharmony_ci
21108c2ecf20Sopenharmony_cistatic int ahash_finup(struct ahash_request *areq)
21118c2ecf20Sopenharmony_ci{
21128c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_ci	req_ctx->last = 1;
21158c2ecf20Sopenharmony_ci
21168c2ecf20Sopenharmony_ci	return ahash_process_req(areq, areq->nbytes);
21178c2ecf20Sopenharmony_ci}
21188c2ecf20Sopenharmony_ci
21198c2ecf20Sopenharmony_cistatic int ahash_digest(struct ahash_request *areq)
21208c2ecf20Sopenharmony_ci{
21218c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21228c2ecf20Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(areq);
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci	ahash->init(areq);
21258c2ecf20Sopenharmony_ci	req_ctx->last = 1;
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_ci	return ahash_process_req(areq, areq->nbytes);
21288c2ecf20Sopenharmony_ci}
21298c2ecf20Sopenharmony_ci
21308c2ecf20Sopenharmony_cistatic int ahash_export(struct ahash_request *areq, void *out)
21318c2ecf20Sopenharmony_ci{
21328c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21338c2ecf20Sopenharmony_ci	struct talitos_export_state *export = out;
21348c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
21358c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
21368c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
21378c2ecf20Sopenharmony_ci	dma_addr_t dma;
21388c2ecf20Sopenharmony_ci
21398c2ecf20Sopenharmony_ci	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
21408c2ecf20Sopenharmony_ci			     DMA_FROM_DEVICE);
21418c2ecf20Sopenharmony_ci	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_FROM_DEVICE);
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci	memcpy(export->hw_context, req_ctx->hw_context,
21448c2ecf20Sopenharmony_ci	       req_ctx->hw_context_size);
21458c2ecf20Sopenharmony_ci	memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf);
21468c2ecf20Sopenharmony_ci	export->swinit = req_ctx->swinit;
21478c2ecf20Sopenharmony_ci	export->first = req_ctx->first;
21488c2ecf20Sopenharmony_ci	export->last = req_ctx->last;
21498c2ecf20Sopenharmony_ci	export->to_hash_later = req_ctx->to_hash_later;
21508c2ecf20Sopenharmony_ci	export->nbuf = req_ctx->nbuf;
21518c2ecf20Sopenharmony_ci
21528c2ecf20Sopenharmony_ci	return 0;
21538c2ecf20Sopenharmony_ci}
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_cistatic int ahash_import(struct ahash_request *areq, const void *in)
21568c2ecf20Sopenharmony_ci{
21578c2ecf20Sopenharmony_ci	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
21588c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
21598c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
21608c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
21618c2ecf20Sopenharmony_ci	const struct talitos_export_state *export = in;
21628c2ecf20Sopenharmony_ci	unsigned int size;
21638c2ecf20Sopenharmony_ci	dma_addr_t dma;
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci	memset(req_ctx, 0, sizeof(*req_ctx));
21668c2ecf20Sopenharmony_ci	size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
21678c2ecf20Sopenharmony_ci			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
21688c2ecf20Sopenharmony_ci			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
21698c2ecf20Sopenharmony_ci	req_ctx->hw_context_size = size;
21708c2ecf20Sopenharmony_ci	memcpy(req_ctx->hw_context, export->hw_context, size);
21718c2ecf20Sopenharmony_ci	memcpy(req_ctx->buf[0], export->buf, export->nbuf);
21728c2ecf20Sopenharmony_ci	req_ctx->swinit = export->swinit;
21738c2ecf20Sopenharmony_ci	req_ctx->first = export->first;
21748c2ecf20Sopenharmony_ci	req_ctx->last = export->last;
21758c2ecf20Sopenharmony_ci	req_ctx->to_hash_later = export->to_hash_later;
21768c2ecf20Sopenharmony_ci	req_ctx->nbuf = export->nbuf;
21778c2ecf20Sopenharmony_ci
21788c2ecf20Sopenharmony_ci	dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
21798c2ecf20Sopenharmony_ci			     DMA_TO_DEVICE);
21808c2ecf20Sopenharmony_ci	dma_unmap_single(dev, dma, req_ctx->hw_context_size, DMA_TO_DEVICE);
21818c2ecf20Sopenharmony_ci
21828c2ecf20Sopenharmony_ci	return 0;
21838c2ecf20Sopenharmony_ci}
21848c2ecf20Sopenharmony_ci
21858c2ecf20Sopenharmony_cistatic int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
21868c2ecf20Sopenharmony_ci		   u8 *hash)
21878c2ecf20Sopenharmony_ci{
21888c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci	struct scatterlist sg[1];
21918c2ecf20Sopenharmony_ci	struct ahash_request *req;
21928c2ecf20Sopenharmony_ci	struct crypto_wait wait;
21938c2ecf20Sopenharmony_ci	int ret;
21948c2ecf20Sopenharmony_ci
21958c2ecf20Sopenharmony_ci	crypto_init_wait(&wait);
21968c2ecf20Sopenharmony_ci
21978c2ecf20Sopenharmony_ci	req = ahash_request_alloc(tfm, GFP_KERNEL);
21988c2ecf20Sopenharmony_ci	if (!req)
21998c2ecf20Sopenharmony_ci		return -ENOMEM;
22008c2ecf20Sopenharmony_ci
22018c2ecf20Sopenharmony_ci	/* Keep tfm keylen == 0 during hash of the long key */
22028c2ecf20Sopenharmony_ci	ctx->keylen = 0;
22038c2ecf20Sopenharmony_ci	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
22048c2ecf20Sopenharmony_ci				   crypto_req_done, &wait);
22058c2ecf20Sopenharmony_ci
22068c2ecf20Sopenharmony_ci	sg_init_one(&sg[0], key, keylen);
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_ci	ahash_request_set_crypt(req, sg, hash, keylen);
22098c2ecf20Sopenharmony_ci	ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
22108c2ecf20Sopenharmony_ci
22118c2ecf20Sopenharmony_ci	ahash_request_free(req);
22128c2ecf20Sopenharmony_ci
22138c2ecf20Sopenharmony_ci	return ret;
22148c2ecf20Sopenharmony_ci}
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_cistatic int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
22178c2ecf20Sopenharmony_ci			unsigned int keylen)
22188c2ecf20Sopenharmony_ci{
22198c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
22208c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
22218c2ecf20Sopenharmony_ci	unsigned int blocksize =
22228c2ecf20Sopenharmony_ci			crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
22238c2ecf20Sopenharmony_ci	unsigned int digestsize = crypto_ahash_digestsize(tfm);
22248c2ecf20Sopenharmony_ci	unsigned int keysize = keylen;
22258c2ecf20Sopenharmony_ci	u8 hash[SHA512_DIGEST_SIZE];
22268c2ecf20Sopenharmony_ci	int ret;
22278c2ecf20Sopenharmony_ci
22288c2ecf20Sopenharmony_ci	if (keylen <= blocksize)
22298c2ecf20Sopenharmony_ci		memcpy(ctx->key, key, keysize);
22308c2ecf20Sopenharmony_ci	else {
22318c2ecf20Sopenharmony_ci		/* Must get the hash of the long key */
22328c2ecf20Sopenharmony_ci		ret = keyhash(tfm, key, keylen, hash);
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_ci		if (ret)
22358c2ecf20Sopenharmony_ci			return -EINVAL;
22368c2ecf20Sopenharmony_ci
22378c2ecf20Sopenharmony_ci		keysize = digestsize;
22388c2ecf20Sopenharmony_ci		memcpy(ctx->key, hash, digestsize);
22398c2ecf20Sopenharmony_ci	}
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci	if (ctx->keylen)
22428c2ecf20Sopenharmony_ci		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
22438c2ecf20Sopenharmony_ci
22448c2ecf20Sopenharmony_ci	ctx->keylen = keysize;
22458c2ecf20Sopenharmony_ci	ctx->dma_key = dma_map_single(dev, ctx->key, keysize, DMA_TO_DEVICE);
22468c2ecf20Sopenharmony_ci
22478c2ecf20Sopenharmony_ci	return 0;
22488c2ecf20Sopenharmony_ci}
22498c2ecf20Sopenharmony_ci
22508c2ecf20Sopenharmony_ci
22518c2ecf20Sopenharmony_cistruct talitos_alg_template {
22528c2ecf20Sopenharmony_ci	u32 type;
22538c2ecf20Sopenharmony_ci	u32 priority;
22548c2ecf20Sopenharmony_ci	union {
22558c2ecf20Sopenharmony_ci		struct skcipher_alg skcipher;
22568c2ecf20Sopenharmony_ci		struct ahash_alg hash;
22578c2ecf20Sopenharmony_ci		struct aead_alg aead;
22588c2ecf20Sopenharmony_ci	} alg;
22598c2ecf20Sopenharmony_ci	__be32 desc_hdr_template;
22608c2ecf20Sopenharmony_ci};
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_cistatic struct talitos_alg_template driver_algs[] = {
22638c2ecf20Sopenharmony_ci	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
22648c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
22658c2ecf20Sopenharmony_ci		.alg.aead = {
22668c2ecf20Sopenharmony_ci			.base = {
22678c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),cbc(aes))",
22688c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha1-"
22698c2ecf20Sopenharmony_ci						   "cbc-aes-talitos",
22708c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
22718c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
22728c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
22738c2ecf20Sopenharmony_ci			},
22748c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
22758c2ecf20Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
22768c2ecf20Sopenharmony_ci		},
22778c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
22788c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_AESU |
22798c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_AESU_CBC |
22808c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
22818c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
22828c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
22838c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
22848c2ecf20Sopenharmony_ci	},
22858c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
22868c2ecf20Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
22878c2ecf20Sopenharmony_ci		.alg.aead = {
22888c2ecf20Sopenharmony_ci			.base = {
22898c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),cbc(aes))",
22908c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha1-"
22918c2ecf20Sopenharmony_ci						   "cbc-aes-talitos-hsna",
22928c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
22938c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
22948c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
22958c2ecf20Sopenharmony_ci			},
22968c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
22978c2ecf20Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
22988c2ecf20Sopenharmony_ci		},
22998c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23008c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
23018c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC |
23028c2ecf20Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
23038c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
23048c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
23058c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23068c2ecf20Sopenharmony_ci	},
23078c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
23088c2ecf20Sopenharmony_ci		.alg.aead = {
23098c2ecf20Sopenharmony_ci			.base = {
23108c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),"
23118c2ecf20Sopenharmony_ci					    "cbc(des3_ede))",
23128c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha1-"
23138c2ecf20Sopenharmony_ci						   "cbc-3des-talitos",
23148c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
23158c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
23168c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
23178c2ecf20Sopenharmony_ci			},
23188c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
23198c2ecf20Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
23208c2ecf20Sopenharmony_ci			.setkey = aead_des3_setkey,
23218c2ecf20Sopenharmony_ci		},
23228c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23238c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
23248c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
23258c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
23268c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
23278c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
23288c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
23298c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23308c2ecf20Sopenharmony_ci	},
23318c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
23328c2ecf20Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23338c2ecf20Sopenharmony_ci		.alg.aead = {
23348c2ecf20Sopenharmony_ci			.base = {
23358c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),"
23368c2ecf20Sopenharmony_ci					    "cbc(des3_ede))",
23378c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha1-"
23388c2ecf20Sopenharmony_ci						   "cbc-3des-talitos-hsna",
23398c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
23408c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
23418c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
23428c2ecf20Sopenharmony_ci			},
23438c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
23448c2ecf20Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
23458c2ecf20Sopenharmony_ci			.setkey = aead_des3_setkey,
23468c2ecf20Sopenharmony_ci		},
23478c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23488c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
23498c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_DEU_CBC |
23508c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_DEU_3DES |
23518c2ecf20Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
23528c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
23538c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
23548c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
23558c2ecf20Sopenharmony_ci	},
23568c2ecf20Sopenharmony_ci	{       .type = CRYPTO_ALG_TYPE_AEAD,
23578c2ecf20Sopenharmony_ci		.alg.aead = {
23588c2ecf20Sopenharmony_ci			.base = {
23598c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),cbc(aes))",
23608c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha224-"
23618c2ecf20Sopenharmony_ci						   "cbc-aes-talitos",
23628c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
23638c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
23648c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
23658c2ecf20Sopenharmony_ci			},
23668c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
23678c2ecf20Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
23688c2ecf20Sopenharmony_ci		},
23698c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
23708c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
23718c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC |
23728c2ecf20Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
23738c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
23748c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
23758c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
23768c2ecf20Sopenharmony_ci	},
23778c2ecf20Sopenharmony_ci	{       .type = CRYPTO_ALG_TYPE_AEAD,
23788c2ecf20Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
23798c2ecf20Sopenharmony_ci		.alg.aead = {
23808c2ecf20Sopenharmony_ci			.base = {
23818c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),cbc(aes))",
23828c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha224-"
23838c2ecf20Sopenharmony_ci						   "cbc-aes-talitos-hsna",
23848c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
23858c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
23868c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
23878c2ecf20Sopenharmony_ci			},
23888c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
23898c2ecf20Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
23908c2ecf20Sopenharmony_ci		},
23918c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
23928c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
23938c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC |
23948c2ecf20Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
23958c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
23968c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
23978c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
23988c2ecf20Sopenharmony_ci	},
23998c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
24008c2ecf20Sopenharmony_ci		.alg.aead = {
24018c2ecf20Sopenharmony_ci			.base = {
24028c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),"
24038c2ecf20Sopenharmony_ci					    "cbc(des3_ede))",
24048c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha224-"
24058c2ecf20Sopenharmony_ci						   "cbc-3des-talitos",
24068c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24078c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
24088c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
24098c2ecf20Sopenharmony_ci			},
24108c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
24118c2ecf20Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
24128c2ecf20Sopenharmony_ci			.setkey = aead_des3_setkey,
24138c2ecf20Sopenharmony_ci		},
24148c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24158c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
24168c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
24178c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
24188c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
24198c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
24208c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
24218c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
24228c2ecf20Sopenharmony_ci	},
24238c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
24248c2ecf20Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24258c2ecf20Sopenharmony_ci		.alg.aead = {
24268c2ecf20Sopenharmony_ci			.base = {
24278c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha224),"
24288c2ecf20Sopenharmony_ci					    "cbc(des3_ede))",
24298c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha224-"
24308c2ecf20Sopenharmony_ci						   "cbc-3des-talitos-hsna",
24318c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24328c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
24338c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
24348c2ecf20Sopenharmony_ci			},
24358c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
24368c2ecf20Sopenharmony_ci			.maxauthsize = SHA224_DIGEST_SIZE,
24378c2ecf20Sopenharmony_ci			.setkey = aead_des3_setkey,
24388c2ecf20Sopenharmony_ci		},
24398c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24408c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
24418c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_DEU_CBC |
24428c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_DEU_3DES |
24438c2ecf20Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
24448c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
24458c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
24468c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
24478c2ecf20Sopenharmony_ci	},
24488c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
24498c2ecf20Sopenharmony_ci		.alg.aead = {
24508c2ecf20Sopenharmony_ci			.base = {
24518c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),cbc(aes))",
24528c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha256-"
24538c2ecf20Sopenharmony_ci						   "cbc-aes-talitos",
24548c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
24558c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
24568c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
24578c2ecf20Sopenharmony_ci			},
24588c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
24598c2ecf20Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
24608c2ecf20Sopenharmony_ci		},
24618c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
24628c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_AESU |
24638c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_AESU_CBC |
24648c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
24658c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
24668c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
24678c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24688c2ecf20Sopenharmony_ci	},
24698c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
24708c2ecf20Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
24718c2ecf20Sopenharmony_ci		.alg.aead = {
24728c2ecf20Sopenharmony_ci			.base = {
24738c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),cbc(aes))",
24748c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha256-"
24758c2ecf20Sopenharmony_ci						   "cbc-aes-talitos-hsna",
24768c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
24778c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
24788c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
24798c2ecf20Sopenharmony_ci			},
24808c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
24818c2ecf20Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
24828c2ecf20Sopenharmony_ci		},
24838c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
24848c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
24858c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC |
24868c2ecf20Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
24878c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
24888c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
24898c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
24908c2ecf20Sopenharmony_ci	},
24918c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
24928c2ecf20Sopenharmony_ci		.alg.aead = {
24938c2ecf20Sopenharmony_ci			.base = {
24948c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),"
24958c2ecf20Sopenharmony_ci					    "cbc(des3_ede))",
24968c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha256-"
24978c2ecf20Sopenharmony_ci						   "cbc-3des-talitos",
24988c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
24998c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
25008c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
25018c2ecf20Sopenharmony_ci			},
25028c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
25038c2ecf20Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
25048c2ecf20Sopenharmony_ci			.setkey = aead_des3_setkey,
25058c2ecf20Sopenharmony_ci		},
25068c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25078c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
25088c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
25098c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
25108c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
25118c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
25128c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
25138c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25148c2ecf20Sopenharmony_ci	},
25158c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
25168c2ecf20Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
25178c2ecf20Sopenharmony_ci		.alg.aead = {
25188c2ecf20Sopenharmony_ci			.base = {
25198c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),"
25208c2ecf20Sopenharmony_ci					    "cbc(des3_ede))",
25218c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha256-"
25228c2ecf20Sopenharmony_ci						   "cbc-3des-talitos-hsna",
25238c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
25248c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
25258c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
25268c2ecf20Sopenharmony_ci			},
25278c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
25288c2ecf20Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
25298c2ecf20Sopenharmony_ci			.setkey = aead_des3_setkey,
25308c2ecf20Sopenharmony_ci		},
25318c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
25328c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
25338c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_DEU_CBC |
25348c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_DEU_3DES |
25358c2ecf20Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
25368c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
25378c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
25388c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
25398c2ecf20Sopenharmony_ci	},
25408c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
25418c2ecf20Sopenharmony_ci		.alg.aead = {
25428c2ecf20Sopenharmony_ci			.base = {
25438c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha384),cbc(aes))",
25448c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha384-"
25458c2ecf20Sopenharmony_ci						   "cbc-aes-talitos",
25468c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
25478c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
25488c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
25498c2ecf20Sopenharmony_ci			},
25508c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
25518c2ecf20Sopenharmony_ci			.maxauthsize = SHA384_DIGEST_SIZE,
25528c2ecf20Sopenharmony_ci		},
25538c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25548c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_AESU |
25558c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_AESU_CBC |
25568c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUB |
25578c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
25588c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
25598c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
25608c2ecf20Sopenharmony_ci	},
25618c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
25628c2ecf20Sopenharmony_ci		.alg.aead = {
25638c2ecf20Sopenharmony_ci			.base = {
25648c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha384),"
25658c2ecf20Sopenharmony_ci					    "cbc(des3_ede))",
25668c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha384-"
25678c2ecf20Sopenharmony_ci						   "cbc-3des-talitos",
25688c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
25698c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
25708c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
25718c2ecf20Sopenharmony_ci			},
25728c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
25738c2ecf20Sopenharmony_ci			.maxauthsize = SHA384_DIGEST_SIZE,
25748c2ecf20Sopenharmony_ci			.setkey = aead_des3_setkey,
25758c2ecf20Sopenharmony_ci		},
25768c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25778c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
25788c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
25798c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
25808c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUB |
25818c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
25828c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
25838c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
25848c2ecf20Sopenharmony_ci	},
25858c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
25868c2ecf20Sopenharmony_ci		.alg.aead = {
25878c2ecf20Sopenharmony_ci			.base = {
25888c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha512),cbc(aes))",
25898c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha512-"
25908c2ecf20Sopenharmony_ci						   "cbc-aes-talitos",
25918c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
25928c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
25938c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
25948c2ecf20Sopenharmony_ci			},
25958c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
25968c2ecf20Sopenharmony_ci			.maxauthsize = SHA512_DIGEST_SIZE,
25978c2ecf20Sopenharmony_ci		},
25988c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
25998c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_AESU |
26008c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_AESU_CBC |
26018c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUB |
26028c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
26038c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
26048c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
26058c2ecf20Sopenharmony_ci	},
26068c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
26078c2ecf20Sopenharmony_ci		.alg.aead = {
26088c2ecf20Sopenharmony_ci			.base = {
26098c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha512),"
26108c2ecf20Sopenharmony_ci					    "cbc(des3_ede))",
26118c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha512-"
26128c2ecf20Sopenharmony_ci						   "cbc-3des-talitos",
26138c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26148c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
26158c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
26168c2ecf20Sopenharmony_ci			},
26178c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
26188c2ecf20Sopenharmony_ci			.maxauthsize = SHA512_DIGEST_SIZE,
26198c2ecf20Sopenharmony_ci			.setkey = aead_des3_setkey,
26208c2ecf20Sopenharmony_ci		},
26218c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26228c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
26238c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
26248c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
26258c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUB |
26268c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
26278c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
26288c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
26298c2ecf20Sopenharmony_ci	},
26308c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
26318c2ecf20Sopenharmony_ci		.alg.aead = {
26328c2ecf20Sopenharmony_ci			.base = {
26338c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(md5),cbc(aes))",
26348c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-md5-"
26358c2ecf20Sopenharmony_ci						   "cbc-aes-talitos",
26368c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
26378c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
26388c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
26398c2ecf20Sopenharmony_ci			},
26408c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
26418c2ecf20Sopenharmony_ci			.maxauthsize = MD5_DIGEST_SIZE,
26428c2ecf20Sopenharmony_ci		},
26438c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26448c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_AESU |
26458c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_AESU_CBC |
26468c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
26478c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
26488c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
26498c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26508c2ecf20Sopenharmony_ci	},
26518c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
26528c2ecf20Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26538c2ecf20Sopenharmony_ci		.alg.aead = {
26548c2ecf20Sopenharmony_ci			.base = {
26558c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(md5),cbc(aes))",
26568c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-md5-"
26578c2ecf20Sopenharmony_ci						   "cbc-aes-talitos-hsna",
26588c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
26598c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
26608c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
26618c2ecf20Sopenharmony_ci			},
26628c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
26638c2ecf20Sopenharmony_ci			.maxauthsize = MD5_DIGEST_SIZE,
26648c2ecf20Sopenharmony_ci		},
26658c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
26668c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
26678c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC |
26688c2ecf20Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
26698c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
26708c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
26718c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26728c2ecf20Sopenharmony_ci	},
26738c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
26748c2ecf20Sopenharmony_ci		.alg.aead = {
26758c2ecf20Sopenharmony_ci			.base = {
26768c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
26778c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-md5-"
26788c2ecf20Sopenharmony_ci						   "cbc-3des-talitos",
26798c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
26808c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
26818c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
26828c2ecf20Sopenharmony_ci			},
26838c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
26848c2ecf20Sopenharmony_ci			.maxauthsize = MD5_DIGEST_SIZE,
26858c2ecf20Sopenharmony_ci			.setkey = aead_des3_setkey,
26868c2ecf20Sopenharmony_ci		},
26878c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
26888c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
26898c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
26908c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES |
26918c2ecf20Sopenharmony_ci		                     DESC_HDR_SEL1_MDEUA |
26928c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_INIT |
26938c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_PAD |
26948c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
26958c2ecf20Sopenharmony_ci	},
26968c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AEAD,
26978c2ecf20Sopenharmony_ci		.priority = TALITOS_CRA_PRIORITY_AEAD_HSNA,
26988c2ecf20Sopenharmony_ci		.alg.aead = {
26998c2ecf20Sopenharmony_ci			.base = {
27008c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
27018c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-md5-"
27028c2ecf20Sopenharmony_ci						   "cbc-3des-talitos-hsna",
27038c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
27048c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
27058c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
27068c2ecf20Sopenharmony_ci			},
27078c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
27088c2ecf20Sopenharmony_ci			.maxauthsize = MD5_DIGEST_SIZE,
27098c2ecf20Sopenharmony_ci			.setkey = aead_des3_setkey,
27108c2ecf20Sopenharmony_ci		},
27118c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_HMAC_SNOOP_NO_AFEU |
27128c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
27138c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_DEU_CBC |
27148c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_DEU_3DES |
27158c2ecf20Sopenharmony_ci				     DESC_HDR_SEL1_MDEUA |
27168c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_INIT |
27178c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_PAD |
27188c2ecf20Sopenharmony_ci				     DESC_HDR_MODE1_MDEU_MD5_HMAC,
27198c2ecf20Sopenharmony_ci	},
27208c2ecf20Sopenharmony_ci	/* SKCIPHER algorithms. */
27218c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
27228c2ecf20Sopenharmony_ci		.alg.skcipher = {
27238c2ecf20Sopenharmony_ci			.base.cra_name = "ecb(aes)",
27248c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ecb-aes-talitos",
27258c2ecf20Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
27268c2ecf20Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
27278c2ecf20Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
27288c2ecf20Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
27298c2ecf20Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
27308c2ecf20Sopenharmony_ci			.setkey = skcipher_aes_setkey,
27318c2ecf20Sopenharmony_ci		},
27328c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27338c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_AESU,
27348c2ecf20Sopenharmony_ci	},
27358c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
27368c2ecf20Sopenharmony_ci		.alg.skcipher = {
27378c2ecf20Sopenharmony_ci			.base.cra_name = "cbc(aes)",
27388c2ecf20Sopenharmony_ci			.base.cra_driver_name = "cbc-aes-talitos",
27398c2ecf20Sopenharmony_ci			.base.cra_blocksize = AES_BLOCK_SIZE,
27408c2ecf20Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
27418c2ecf20Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
27428c2ecf20Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
27438c2ecf20Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
27448c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
27458c2ecf20Sopenharmony_ci			.setkey = skcipher_aes_setkey,
27468c2ecf20Sopenharmony_ci		},
27478c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27488c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
27498c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CBC,
27508c2ecf20Sopenharmony_ci	},
27518c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
27528c2ecf20Sopenharmony_ci		.alg.skcipher = {
27538c2ecf20Sopenharmony_ci			.base.cra_name = "ctr(aes)",
27548c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ctr-aes-talitos",
27558c2ecf20Sopenharmony_ci			.base.cra_blocksize = 1,
27568c2ecf20Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
27578c2ecf20Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
27588c2ecf20Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
27598c2ecf20Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
27608c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
27618c2ecf20Sopenharmony_ci			.setkey = skcipher_aes_setkey,
27628c2ecf20Sopenharmony_ci		},
27638c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_AESU_CTR_NONSNOOP |
27648c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
27658c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CTR,
27668c2ecf20Sopenharmony_ci	},
27678c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
27688c2ecf20Sopenharmony_ci		.alg.skcipher = {
27698c2ecf20Sopenharmony_ci			.base.cra_name = "ctr(aes)",
27708c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ctr-aes-talitos",
27718c2ecf20Sopenharmony_ci			.base.cra_blocksize = 1,
27728c2ecf20Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
27738c2ecf20Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
27748c2ecf20Sopenharmony_ci			.min_keysize = AES_MIN_KEY_SIZE,
27758c2ecf20Sopenharmony_ci			.max_keysize = AES_MAX_KEY_SIZE,
27768c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
27778c2ecf20Sopenharmony_ci			.setkey = skcipher_aes_setkey,
27788c2ecf20Sopenharmony_ci		},
27798c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27808c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_AESU |
27818c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_AESU_CTR,
27828c2ecf20Sopenharmony_ci	},
27838c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
27848c2ecf20Sopenharmony_ci		.alg.skcipher = {
27858c2ecf20Sopenharmony_ci			.base.cra_name = "ecb(des)",
27868c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ecb-des-talitos",
27878c2ecf20Sopenharmony_ci			.base.cra_blocksize = DES_BLOCK_SIZE,
27888c2ecf20Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
27898c2ecf20Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
27908c2ecf20Sopenharmony_ci			.min_keysize = DES_KEY_SIZE,
27918c2ecf20Sopenharmony_ci			.max_keysize = DES_KEY_SIZE,
27928c2ecf20Sopenharmony_ci			.setkey = skcipher_des_setkey,
27938c2ecf20Sopenharmony_ci		},
27948c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
27958c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_DEU,
27968c2ecf20Sopenharmony_ci	},
27978c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
27988c2ecf20Sopenharmony_ci		.alg.skcipher = {
27998c2ecf20Sopenharmony_ci			.base.cra_name = "cbc(des)",
28008c2ecf20Sopenharmony_ci			.base.cra_driver_name = "cbc-des-talitos",
28018c2ecf20Sopenharmony_ci			.base.cra_blocksize = DES_BLOCK_SIZE,
28028c2ecf20Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
28038c2ecf20Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
28048c2ecf20Sopenharmony_ci			.min_keysize = DES_KEY_SIZE,
28058c2ecf20Sopenharmony_ci			.max_keysize = DES_KEY_SIZE,
28068c2ecf20Sopenharmony_ci			.ivsize = DES_BLOCK_SIZE,
28078c2ecf20Sopenharmony_ci			.setkey = skcipher_des_setkey,
28088c2ecf20Sopenharmony_ci		},
28098c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28108c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
28118c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_DEU_CBC,
28128c2ecf20Sopenharmony_ci	},
28138c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
28148c2ecf20Sopenharmony_ci		.alg.skcipher = {
28158c2ecf20Sopenharmony_ci			.base.cra_name = "ecb(des3_ede)",
28168c2ecf20Sopenharmony_ci			.base.cra_driver_name = "ecb-3des-talitos",
28178c2ecf20Sopenharmony_ci			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
28188c2ecf20Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
28198c2ecf20Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
28208c2ecf20Sopenharmony_ci			.min_keysize = DES3_EDE_KEY_SIZE,
28218c2ecf20Sopenharmony_ci			.max_keysize = DES3_EDE_KEY_SIZE,
28228c2ecf20Sopenharmony_ci			.setkey = skcipher_des3_setkey,
28238c2ecf20Sopenharmony_ci		},
28248c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28258c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_DEU |
28268c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_DEU_3DES,
28278c2ecf20Sopenharmony_ci	},
28288c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_SKCIPHER,
28298c2ecf20Sopenharmony_ci		.alg.skcipher = {
28308c2ecf20Sopenharmony_ci			.base.cra_name = "cbc(des3_ede)",
28318c2ecf20Sopenharmony_ci			.base.cra_driver_name = "cbc-3des-talitos",
28328c2ecf20Sopenharmony_ci			.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
28338c2ecf20Sopenharmony_ci			.base.cra_flags = CRYPTO_ALG_ASYNC |
28348c2ecf20Sopenharmony_ci					  CRYPTO_ALG_ALLOCATES_MEMORY,
28358c2ecf20Sopenharmony_ci			.min_keysize = DES3_EDE_KEY_SIZE,
28368c2ecf20Sopenharmony_ci			.max_keysize = DES3_EDE_KEY_SIZE,
28378c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
28388c2ecf20Sopenharmony_ci			.setkey = skcipher_des3_setkey,
28398c2ecf20Sopenharmony_ci		},
28408c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28418c2ecf20Sopenharmony_ci			             DESC_HDR_SEL0_DEU |
28428c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_CBC |
28438c2ecf20Sopenharmony_ci		                     DESC_HDR_MODE0_DEU_3DES,
28448c2ecf20Sopenharmony_ci	},
28458c2ecf20Sopenharmony_ci	/* AHASH algorithms. */
28468c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
28478c2ecf20Sopenharmony_ci		.alg.hash = {
28488c2ecf20Sopenharmony_ci			.halg.digestsize = MD5_DIGEST_SIZE,
28498c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
28508c2ecf20Sopenharmony_ci			.halg.base = {
28518c2ecf20Sopenharmony_ci				.cra_name = "md5",
28528c2ecf20Sopenharmony_ci				.cra_driver_name = "md5-talitos",
28538c2ecf20Sopenharmony_ci				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
28548c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
28558c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
28568c2ecf20Sopenharmony_ci			}
28578c2ecf20Sopenharmony_ci		},
28588c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28598c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
28608c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_MD5,
28618c2ecf20Sopenharmony_ci	},
28628c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
28638c2ecf20Sopenharmony_ci		.alg.hash = {
28648c2ecf20Sopenharmony_ci			.halg.digestsize = SHA1_DIGEST_SIZE,
28658c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
28668c2ecf20Sopenharmony_ci			.halg.base = {
28678c2ecf20Sopenharmony_ci				.cra_name = "sha1",
28688c2ecf20Sopenharmony_ci				.cra_driver_name = "sha1-talitos",
28698c2ecf20Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
28708c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
28718c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
28728c2ecf20Sopenharmony_ci			}
28738c2ecf20Sopenharmony_ci		},
28748c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28758c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
28768c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA1,
28778c2ecf20Sopenharmony_ci	},
28788c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
28798c2ecf20Sopenharmony_ci		.alg.hash = {
28808c2ecf20Sopenharmony_ci			.halg.digestsize = SHA224_DIGEST_SIZE,
28818c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
28828c2ecf20Sopenharmony_ci			.halg.base = {
28838c2ecf20Sopenharmony_ci				.cra_name = "sha224",
28848c2ecf20Sopenharmony_ci				.cra_driver_name = "sha224-talitos",
28858c2ecf20Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
28868c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
28878c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
28888c2ecf20Sopenharmony_ci			}
28898c2ecf20Sopenharmony_ci		},
28908c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
28918c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
28928c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA224,
28938c2ecf20Sopenharmony_ci	},
28948c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
28958c2ecf20Sopenharmony_ci		.alg.hash = {
28968c2ecf20Sopenharmony_ci			.halg.digestsize = SHA256_DIGEST_SIZE,
28978c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
28988c2ecf20Sopenharmony_ci			.halg.base = {
28998c2ecf20Sopenharmony_ci				.cra_name = "sha256",
29008c2ecf20Sopenharmony_ci				.cra_driver_name = "sha256-talitos",
29018c2ecf20Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
29028c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
29038c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
29048c2ecf20Sopenharmony_ci			}
29058c2ecf20Sopenharmony_ci		},
29068c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
29078c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
29088c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA256,
29098c2ecf20Sopenharmony_ci	},
29108c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
29118c2ecf20Sopenharmony_ci		.alg.hash = {
29128c2ecf20Sopenharmony_ci			.halg.digestsize = SHA384_DIGEST_SIZE,
29138c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
29148c2ecf20Sopenharmony_ci			.halg.base = {
29158c2ecf20Sopenharmony_ci				.cra_name = "sha384",
29168c2ecf20Sopenharmony_ci				.cra_driver_name = "sha384-talitos",
29178c2ecf20Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
29188c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
29198c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
29208c2ecf20Sopenharmony_ci			}
29218c2ecf20Sopenharmony_ci		},
29228c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
29238c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUB |
29248c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEUB_SHA384,
29258c2ecf20Sopenharmony_ci	},
29268c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
29278c2ecf20Sopenharmony_ci		.alg.hash = {
29288c2ecf20Sopenharmony_ci			.halg.digestsize = SHA512_DIGEST_SIZE,
29298c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
29308c2ecf20Sopenharmony_ci			.halg.base = {
29318c2ecf20Sopenharmony_ci				.cra_name = "sha512",
29328c2ecf20Sopenharmony_ci				.cra_driver_name = "sha512-talitos",
29338c2ecf20Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
29348c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
29358c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
29368c2ecf20Sopenharmony_ci			}
29378c2ecf20Sopenharmony_ci		},
29388c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
29398c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUB |
29408c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEUB_SHA512,
29418c2ecf20Sopenharmony_ci	},
29428c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
29438c2ecf20Sopenharmony_ci		.alg.hash = {
29448c2ecf20Sopenharmony_ci			.halg.digestsize = MD5_DIGEST_SIZE,
29458c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
29468c2ecf20Sopenharmony_ci			.halg.base = {
29478c2ecf20Sopenharmony_ci				.cra_name = "hmac(md5)",
29488c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-md5-talitos",
29498c2ecf20Sopenharmony_ci				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
29508c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
29518c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
29528c2ecf20Sopenharmony_ci			}
29538c2ecf20Sopenharmony_ci		},
29548c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
29558c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
29568c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_MD5,
29578c2ecf20Sopenharmony_ci	},
29588c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
29598c2ecf20Sopenharmony_ci		.alg.hash = {
29608c2ecf20Sopenharmony_ci			.halg.digestsize = SHA1_DIGEST_SIZE,
29618c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
29628c2ecf20Sopenharmony_ci			.halg.base = {
29638c2ecf20Sopenharmony_ci				.cra_name = "hmac(sha1)",
29648c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-sha1-talitos",
29658c2ecf20Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
29668c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
29678c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
29688c2ecf20Sopenharmony_ci			}
29698c2ecf20Sopenharmony_ci		},
29708c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
29718c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
29728c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA1,
29738c2ecf20Sopenharmony_ci	},
29748c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
29758c2ecf20Sopenharmony_ci		.alg.hash = {
29768c2ecf20Sopenharmony_ci			.halg.digestsize = SHA224_DIGEST_SIZE,
29778c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
29788c2ecf20Sopenharmony_ci			.halg.base = {
29798c2ecf20Sopenharmony_ci				.cra_name = "hmac(sha224)",
29808c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-sha224-talitos",
29818c2ecf20Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
29828c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
29838c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
29848c2ecf20Sopenharmony_ci			}
29858c2ecf20Sopenharmony_ci		},
29868c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
29878c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
29888c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA224,
29898c2ecf20Sopenharmony_ci	},
29908c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
29918c2ecf20Sopenharmony_ci		.alg.hash = {
29928c2ecf20Sopenharmony_ci			.halg.digestsize = SHA256_DIGEST_SIZE,
29938c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
29948c2ecf20Sopenharmony_ci			.halg.base = {
29958c2ecf20Sopenharmony_ci				.cra_name = "hmac(sha256)",
29968c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-sha256-talitos",
29978c2ecf20Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
29988c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
29998c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
30008c2ecf20Sopenharmony_ci			}
30018c2ecf20Sopenharmony_ci		},
30028c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
30038c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUA |
30048c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEU_SHA256,
30058c2ecf20Sopenharmony_ci	},
30068c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
30078c2ecf20Sopenharmony_ci		.alg.hash = {
30088c2ecf20Sopenharmony_ci			.halg.digestsize = SHA384_DIGEST_SIZE,
30098c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
30108c2ecf20Sopenharmony_ci			.halg.base = {
30118c2ecf20Sopenharmony_ci				.cra_name = "hmac(sha384)",
30128c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-sha384-talitos",
30138c2ecf20Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
30148c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
30158c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
30168c2ecf20Sopenharmony_ci			}
30178c2ecf20Sopenharmony_ci		},
30188c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
30198c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUB |
30208c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEUB_SHA384,
30218c2ecf20Sopenharmony_ci	},
30228c2ecf20Sopenharmony_ci	{	.type = CRYPTO_ALG_TYPE_AHASH,
30238c2ecf20Sopenharmony_ci		.alg.hash = {
30248c2ecf20Sopenharmony_ci			.halg.digestsize = SHA512_DIGEST_SIZE,
30258c2ecf20Sopenharmony_ci			.halg.statesize = sizeof(struct talitos_export_state),
30268c2ecf20Sopenharmony_ci			.halg.base = {
30278c2ecf20Sopenharmony_ci				.cra_name = "hmac(sha512)",
30288c2ecf20Sopenharmony_ci				.cra_driver_name = "hmac-sha512-talitos",
30298c2ecf20Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
30308c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
30318c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY,
30328c2ecf20Sopenharmony_ci			}
30338c2ecf20Sopenharmony_ci		},
30348c2ecf20Sopenharmony_ci		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
30358c2ecf20Sopenharmony_ci				     DESC_HDR_SEL0_MDEUB |
30368c2ecf20Sopenharmony_ci				     DESC_HDR_MODE0_MDEUB_SHA512,
30378c2ecf20Sopenharmony_ci	}
30388c2ecf20Sopenharmony_ci};
30398c2ecf20Sopenharmony_ci
30408c2ecf20Sopenharmony_cistruct talitos_crypto_alg {
30418c2ecf20Sopenharmony_ci	struct list_head entry;
30428c2ecf20Sopenharmony_ci	struct device *dev;
30438c2ecf20Sopenharmony_ci	struct talitos_alg_template algt;
30448c2ecf20Sopenharmony_ci};
30458c2ecf20Sopenharmony_ci
30468c2ecf20Sopenharmony_cistatic int talitos_init_common(struct talitos_ctx *ctx,
30478c2ecf20Sopenharmony_ci			       struct talitos_crypto_alg *talitos_alg)
30488c2ecf20Sopenharmony_ci{
30498c2ecf20Sopenharmony_ci	struct talitos_private *priv;
30508c2ecf20Sopenharmony_ci
30518c2ecf20Sopenharmony_ci	/* update context with ptr to dev */
30528c2ecf20Sopenharmony_ci	ctx->dev = talitos_alg->dev;
30538c2ecf20Sopenharmony_ci
30548c2ecf20Sopenharmony_ci	/* assign SEC channel to tfm in round-robin fashion */
30558c2ecf20Sopenharmony_ci	priv = dev_get_drvdata(ctx->dev);
30568c2ecf20Sopenharmony_ci	ctx->ch = atomic_inc_return(&priv->last_chan) &
30578c2ecf20Sopenharmony_ci		  (priv->num_channels - 1);
30588c2ecf20Sopenharmony_ci
30598c2ecf20Sopenharmony_ci	/* copy descriptor header template value */
30608c2ecf20Sopenharmony_ci	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
30618c2ecf20Sopenharmony_ci
30628c2ecf20Sopenharmony_ci	/* select done notification */
30638c2ecf20Sopenharmony_ci	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
30648c2ecf20Sopenharmony_ci
30658c2ecf20Sopenharmony_ci	return 0;
30668c2ecf20Sopenharmony_ci}
30678c2ecf20Sopenharmony_ci
30688c2ecf20Sopenharmony_cistatic int talitos_cra_init_aead(struct crypto_aead *tfm)
30698c2ecf20Sopenharmony_ci{
30708c2ecf20Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(tfm);
30718c2ecf20Sopenharmony_ci	struct talitos_crypto_alg *talitos_alg;
30728c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_aead_ctx(tfm);
30738c2ecf20Sopenharmony_ci
30748c2ecf20Sopenharmony_ci	talitos_alg = container_of(alg, struct talitos_crypto_alg,
30758c2ecf20Sopenharmony_ci				   algt.alg.aead);
30768c2ecf20Sopenharmony_ci
30778c2ecf20Sopenharmony_ci	return talitos_init_common(ctx, talitos_alg);
30788c2ecf20Sopenharmony_ci}
30798c2ecf20Sopenharmony_ci
30808c2ecf20Sopenharmony_cistatic int talitos_cra_init_skcipher(struct crypto_skcipher *tfm)
30818c2ecf20Sopenharmony_ci{
30828c2ecf20Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
30838c2ecf20Sopenharmony_ci	struct talitos_crypto_alg *talitos_alg;
30848c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_skcipher_ctx(tfm);
30858c2ecf20Sopenharmony_ci
30868c2ecf20Sopenharmony_ci	talitos_alg = container_of(alg, struct talitos_crypto_alg,
30878c2ecf20Sopenharmony_ci				   algt.alg.skcipher);
30888c2ecf20Sopenharmony_ci
30898c2ecf20Sopenharmony_ci	return talitos_init_common(ctx, talitos_alg);
30908c2ecf20Sopenharmony_ci}
30918c2ecf20Sopenharmony_ci
30928c2ecf20Sopenharmony_cistatic int talitos_cra_init_ahash(struct crypto_tfm *tfm)
30938c2ecf20Sopenharmony_ci{
30948c2ecf20Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
30958c2ecf20Sopenharmony_ci	struct talitos_crypto_alg *talitos_alg;
30968c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
30978c2ecf20Sopenharmony_ci
30988c2ecf20Sopenharmony_ci	talitos_alg = container_of(__crypto_ahash_alg(alg),
30998c2ecf20Sopenharmony_ci				   struct talitos_crypto_alg,
31008c2ecf20Sopenharmony_ci				   algt.alg.hash);
31018c2ecf20Sopenharmony_ci
31028c2ecf20Sopenharmony_ci	ctx->keylen = 0;
31038c2ecf20Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
31048c2ecf20Sopenharmony_ci				 sizeof(struct talitos_ahash_req_ctx));
31058c2ecf20Sopenharmony_ci
31068c2ecf20Sopenharmony_ci	return talitos_init_common(ctx, talitos_alg);
31078c2ecf20Sopenharmony_ci}
31088c2ecf20Sopenharmony_ci
31098c2ecf20Sopenharmony_cistatic void talitos_cra_exit(struct crypto_tfm *tfm)
31108c2ecf20Sopenharmony_ci{
31118c2ecf20Sopenharmony_ci	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
31128c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
31138c2ecf20Sopenharmony_ci
31148c2ecf20Sopenharmony_ci	if (ctx->keylen)
31158c2ecf20Sopenharmony_ci		dma_unmap_single(dev, ctx->dma_key, ctx->keylen, DMA_TO_DEVICE);
31168c2ecf20Sopenharmony_ci}
31178c2ecf20Sopenharmony_ci
31188c2ecf20Sopenharmony_ci/*
31198c2ecf20Sopenharmony_ci * given the alg's descriptor header template, determine whether descriptor
31208c2ecf20Sopenharmony_ci * type and primary/secondary execution units required match the hw
31218c2ecf20Sopenharmony_ci * capabilities description provided in the device tree node.
31228c2ecf20Sopenharmony_ci */
31238c2ecf20Sopenharmony_cistatic int hw_supports(struct device *dev, __be32 desc_hdr_template)
31248c2ecf20Sopenharmony_ci{
31258c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
31268c2ecf20Sopenharmony_ci	int ret;
31278c2ecf20Sopenharmony_ci
31288c2ecf20Sopenharmony_ci	ret = (1 << DESC_TYPE(desc_hdr_template) & priv->desc_types) &&
31298c2ecf20Sopenharmony_ci	      (1 << PRIMARY_EU(desc_hdr_template) & priv->exec_units);
31308c2ecf20Sopenharmony_ci
31318c2ecf20Sopenharmony_ci	if (SECONDARY_EU(desc_hdr_template))
31328c2ecf20Sopenharmony_ci		ret = ret && (1 << SECONDARY_EU(desc_hdr_template)
31338c2ecf20Sopenharmony_ci		              & priv->exec_units);
31348c2ecf20Sopenharmony_ci
31358c2ecf20Sopenharmony_ci	return ret;
31368c2ecf20Sopenharmony_ci}
31378c2ecf20Sopenharmony_ci
31388c2ecf20Sopenharmony_cistatic int talitos_remove(struct platform_device *ofdev)
31398c2ecf20Sopenharmony_ci{
31408c2ecf20Sopenharmony_ci	struct device *dev = &ofdev->dev;
31418c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
31428c2ecf20Sopenharmony_ci	struct talitos_crypto_alg *t_alg, *n;
31438c2ecf20Sopenharmony_ci	int i;
31448c2ecf20Sopenharmony_ci
31458c2ecf20Sopenharmony_ci	list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
31468c2ecf20Sopenharmony_ci		switch (t_alg->algt.type) {
31478c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_SKCIPHER:
31488c2ecf20Sopenharmony_ci			crypto_unregister_skcipher(&t_alg->algt.alg.skcipher);
31498c2ecf20Sopenharmony_ci			break;
31508c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AEAD:
31518c2ecf20Sopenharmony_ci			crypto_unregister_aead(&t_alg->algt.alg.aead);
31528c2ecf20Sopenharmony_ci			break;
31538c2ecf20Sopenharmony_ci		case CRYPTO_ALG_TYPE_AHASH:
31548c2ecf20Sopenharmony_ci			crypto_unregister_ahash(&t_alg->algt.alg.hash);
31558c2ecf20Sopenharmony_ci			break;
31568c2ecf20Sopenharmony_ci		}
31578c2ecf20Sopenharmony_ci		list_del(&t_alg->entry);
31588c2ecf20Sopenharmony_ci	}
31598c2ecf20Sopenharmony_ci
31608c2ecf20Sopenharmony_ci	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
31618c2ecf20Sopenharmony_ci		talitos_unregister_rng(dev);
31628c2ecf20Sopenharmony_ci
31638c2ecf20Sopenharmony_ci	for (i = 0; i < 2; i++)
31648c2ecf20Sopenharmony_ci		if (priv->irq[i]) {
31658c2ecf20Sopenharmony_ci			free_irq(priv->irq[i], dev);
31668c2ecf20Sopenharmony_ci			irq_dispose_mapping(priv->irq[i]);
31678c2ecf20Sopenharmony_ci		}
31688c2ecf20Sopenharmony_ci
31698c2ecf20Sopenharmony_ci	tasklet_kill(&priv->done_task[0]);
31708c2ecf20Sopenharmony_ci	if (priv->irq[1])
31718c2ecf20Sopenharmony_ci		tasklet_kill(&priv->done_task[1]);
31728c2ecf20Sopenharmony_ci
31738c2ecf20Sopenharmony_ci	return 0;
31748c2ecf20Sopenharmony_ci}
31758c2ecf20Sopenharmony_ci
31768c2ecf20Sopenharmony_cistatic struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
31778c2ecf20Sopenharmony_ci						    struct talitos_alg_template
31788c2ecf20Sopenharmony_ci						           *template)
31798c2ecf20Sopenharmony_ci{
31808c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
31818c2ecf20Sopenharmony_ci	struct talitos_crypto_alg *t_alg;
31828c2ecf20Sopenharmony_ci	struct crypto_alg *alg;
31838c2ecf20Sopenharmony_ci
31848c2ecf20Sopenharmony_ci	t_alg = devm_kzalloc(dev, sizeof(struct talitos_crypto_alg),
31858c2ecf20Sopenharmony_ci			     GFP_KERNEL);
31868c2ecf20Sopenharmony_ci	if (!t_alg)
31878c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
31888c2ecf20Sopenharmony_ci
31898c2ecf20Sopenharmony_ci	t_alg->algt = *template;
31908c2ecf20Sopenharmony_ci
31918c2ecf20Sopenharmony_ci	switch (t_alg->algt.type) {
31928c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
31938c2ecf20Sopenharmony_ci		alg = &t_alg->algt.alg.skcipher.base;
31948c2ecf20Sopenharmony_ci		alg->cra_exit = talitos_cra_exit;
31958c2ecf20Sopenharmony_ci		t_alg->algt.alg.skcipher.init = talitos_cra_init_skcipher;
31968c2ecf20Sopenharmony_ci		t_alg->algt.alg.skcipher.setkey =
31978c2ecf20Sopenharmony_ci			t_alg->algt.alg.skcipher.setkey ?: skcipher_setkey;
31988c2ecf20Sopenharmony_ci		t_alg->algt.alg.skcipher.encrypt = skcipher_encrypt;
31998c2ecf20Sopenharmony_ci		t_alg->algt.alg.skcipher.decrypt = skcipher_decrypt;
32008c2ecf20Sopenharmony_ci		if (!strcmp(alg->cra_name, "ctr(aes)") && !has_ftr_sec1(priv) &&
32018c2ecf20Sopenharmony_ci		    DESC_TYPE(t_alg->algt.desc_hdr_template) !=
32028c2ecf20Sopenharmony_ci		    DESC_TYPE(DESC_HDR_TYPE_AESU_CTR_NONSNOOP)) {
32038c2ecf20Sopenharmony_ci			devm_kfree(dev, t_alg);
32048c2ecf20Sopenharmony_ci			return ERR_PTR(-ENOTSUPP);
32058c2ecf20Sopenharmony_ci		}
32068c2ecf20Sopenharmony_ci		break;
32078c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
32088c2ecf20Sopenharmony_ci		alg = &t_alg->algt.alg.aead.base;
32098c2ecf20Sopenharmony_ci		alg->cra_exit = talitos_cra_exit;
32108c2ecf20Sopenharmony_ci		t_alg->algt.alg.aead.init = talitos_cra_init_aead;
32118c2ecf20Sopenharmony_ci		t_alg->algt.alg.aead.setkey = t_alg->algt.alg.aead.setkey ?:
32128c2ecf20Sopenharmony_ci					      aead_setkey;
32138c2ecf20Sopenharmony_ci		t_alg->algt.alg.aead.encrypt = aead_encrypt;
32148c2ecf20Sopenharmony_ci		t_alg->algt.alg.aead.decrypt = aead_decrypt;
32158c2ecf20Sopenharmony_ci		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
32168c2ecf20Sopenharmony_ci		    !strncmp(alg->cra_name, "authenc(hmac(sha224)", 20)) {
32178c2ecf20Sopenharmony_ci			devm_kfree(dev, t_alg);
32188c2ecf20Sopenharmony_ci			return ERR_PTR(-ENOTSUPP);
32198c2ecf20Sopenharmony_ci		}
32208c2ecf20Sopenharmony_ci		break;
32218c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_AHASH:
32228c2ecf20Sopenharmony_ci		alg = &t_alg->algt.alg.hash.halg.base;
32238c2ecf20Sopenharmony_ci		alg->cra_init = talitos_cra_init_ahash;
32248c2ecf20Sopenharmony_ci		alg->cra_exit = talitos_cra_exit;
32258c2ecf20Sopenharmony_ci		t_alg->algt.alg.hash.init = ahash_init;
32268c2ecf20Sopenharmony_ci		t_alg->algt.alg.hash.update = ahash_update;
32278c2ecf20Sopenharmony_ci		t_alg->algt.alg.hash.final = ahash_final;
32288c2ecf20Sopenharmony_ci		t_alg->algt.alg.hash.finup = ahash_finup;
32298c2ecf20Sopenharmony_ci		t_alg->algt.alg.hash.digest = ahash_digest;
32308c2ecf20Sopenharmony_ci		if (!strncmp(alg->cra_name, "hmac", 4))
32318c2ecf20Sopenharmony_ci			t_alg->algt.alg.hash.setkey = ahash_setkey;
32328c2ecf20Sopenharmony_ci		t_alg->algt.alg.hash.import = ahash_import;
32338c2ecf20Sopenharmony_ci		t_alg->algt.alg.hash.export = ahash_export;
32348c2ecf20Sopenharmony_ci
32358c2ecf20Sopenharmony_ci		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
32368c2ecf20Sopenharmony_ci		    !strncmp(alg->cra_name, "hmac", 4)) {
32378c2ecf20Sopenharmony_ci			devm_kfree(dev, t_alg);
32388c2ecf20Sopenharmony_ci			return ERR_PTR(-ENOTSUPP);
32398c2ecf20Sopenharmony_ci		}
32408c2ecf20Sopenharmony_ci		if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
32418c2ecf20Sopenharmony_ci		    (!strcmp(alg->cra_name, "sha224") ||
32428c2ecf20Sopenharmony_ci		     !strcmp(alg->cra_name, "hmac(sha224)"))) {
32438c2ecf20Sopenharmony_ci			t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
32448c2ecf20Sopenharmony_ci			t_alg->algt.desc_hdr_template =
32458c2ecf20Sopenharmony_ci					DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
32468c2ecf20Sopenharmony_ci					DESC_HDR_SEL0_MDEUA |
32478c2ecf20Sopenharmony_ci					DESC_HDR_MODE0_MDEU_SHA256;
32488c2ecf20Sopenharmony_ci		}
32498c2ecf20Sopenharmony_ci		break;
32508c2ecf20Sopenharmony_ci	default:
32518c2ecf20Sopenharmony_ci		dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type);
32528c2ecf20Sopenharmony_ci		devm_kfree(dev, t_alg);
32538c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
32548c2ecf20Sopenharmony_ci	}
32558c2ecf20Sopenharmony_ci
32568c2ecf20Sopenharmony_ci	alg->cra_module = THIS_MODULE;
32578c2ecf20Sopenharmony_ci	if (t_alg->algt.priority)
32588c2ecf20Sopenharmony_ci		alg->cra_priority = t_alg->algt.priority;
32598c2ecf20Sopenharmony_ci	else
32608c2ecf20Sopenharmony_ci		alg->cra_priority = TALITOS_CRA_PRIORITY;
32618c2ecf20Sopenharmony_ci	if (has_ftr_sec1(priv))
32628c2ecf20Sopenharmony_ci		alg->cra_alignmask = 3;
32638c2ecf20Sopenharmony_ci	else
32648c2ecf20Sopenharmony_ci		alg->cra_alignmask = 0;
32658c2ecf20Sopenharmony_ci	alg->cra_ctxsize = sizeof(struct talitos_ctx);
32668c2ecf20Sopenharmony_ci	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
32678c2ecf20Sopenharmony_ci
32688c2ecf20Sopenharmony_ci	t_alg->dev = dev;
32698c2ecf20Sopenharmony_ci
32708c2ecf20Sopenharmony_ci	return t_alg;
32718c2ecf20Sopenharmony_ci}
32728c2ecf20Sopenharmony_ci
32738c2ecf20Sopenharmony_cistatic int talitos_probe_irq(struct platform_device *ofdev)
32748c2ecf20Sopenharmony_ci{
32758c2ecf20Sopenharmony_ci	struct device *dev = &ofdev->dev;
32768c2ecf20Sopenharmony_ci	struct device_node *np = ofdev->dev.of_node;
32778c2ecf20Sopenharmony_ci	struct talitos_private *priv = dev_get_drvdata(dev);
32788c2ecf20Sopenharmony_ci	int err;
32798c2ecf20Sopenharmony_ci	bool is_sec1 = has_ftr_sec1(priv);
32808c2ecf20Sopenharmony_ci
32818c2ecf20Sopenharmony_ci	priv->irq[0] = irq_of_parse_and_map(np, 0);
32828c2ecf20Sopenharmony_ci	if (!priv->irq[0]) {
32838c2ecf20Sopenharmony_ci		dev_err(dev, "failed to map irq\n");
32848c2ecf20Sopenharmony_ci		return -EINVAL;
32858c2ecf20Sopenharmony_ci	}
32868c2ecf20Sopenharmony_ci	if (is_sec1) {
32878c2ecf20Sopenharmony_ci		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
32888c2ecf20Sopenharmony_ci				  dev_driver_string(dev), dev);
32898c2ecf20Sopenharmony_ci		goto primary_out;
32908c2ecf20Sopenharmony_ci	}
32918c2ecf20Sopenharmony_ci
32928c2ecf20Sopenharmony_ci	priv->irq[1] = irq_of_parse_and_map(np, 1);
32938c2ecf20Sopenharmony_ci
32948c2ecf20Sopenharmony_ci	/* get the primary irq line */
32958c2ecf20Sopenharmony_ci	if (!priv->irq[1]) {
32968c2ecf20Sopenharmony_ci		err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0,
32978c2ecf20Sopenharmony_ci				  dev_driver_string(dev), dev);
32988c2ecf20Sopenharmony_ci		goto primary_out;
32998c2ecf20Sopenharmony_ci	}
33008c2ecf20Sopenharmony_ci
33018c2ecf20Sopenharmony_ci	err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0,
33028c2ecf20Sopenharmony_ci			  dev_driver_string(dev), dev);
33038c2ecf20Sopenharmony_ci	if (err)
33048c2ecf20Sopenharmony_ci		goto primary_out;
33058c2ecf20Sopenharmony_ci
33068c2ecf20Sopenharmony_ci	/* get the secondary irq line */
33078c2ecf20Sopenharmony_ci	err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0,
33088c2ecf20Sopenharmony_ci			  dev_driver_string(dev), dev);
33098c2ecf20Sopenharmony_ci	if (err) {
33108c2ecf20Sopenharmony_ci		dev_err(dev, "failed to request secondary irq\n");
33118c2ecf20Sopenharmony_ci		irq_dispose_mapping(priv->irq[1]);
33128c2ecf20Sopenharmony_ci		priv->irq[1] = 0;
33138c2ecf20Sopenharmony_ci	}
33148c2ecf20Sopenharmony_ci
33158c2ecf20Sopenharmony_ci	return err;
33168c2ecf20Sopenharmony_ci
33178c2ecf20Sopenharmony_ciprimary_out:
33188c2ecf20Sopenharmony_ci	if (err) {
33198c2ecf20Sopenharmony_ci		dev_err(dev, "failed to request primary irq\n");
33208c2ecf20Sopenharmony_ci		irq_dispose_mapping(priv->irq[0]);
33218c2ecf20Sopenharmony_ci		priv->irq[0] = 0;
33228c2ecf20Sopenharmony_ci	}
33238c2ecf20Sopenharmony_ci
33248c2ecf20Sopenharmony_ci	return err;
33258c2ecf20Sopenharmony_ci}
33268c2ecf20Sopenharmony_ci
33278c2ecf20Sopenharmony_cistatic int talitos_probe(struct platform_device *ofdev)
33288c2ecf20Sopenharmony_ci{
33298c2ecf20Sopenharmony_ci	struct device *dev = &ofdev->dev;
33308c2ecf20Sopenharmony_ci	struct device_node *np = ofdev->dev.of_node;
33318c2ecf20Sopenharmony_ci	struct talitos_private *priv;
33328c2ecf20Sopenharmony_ci	int i, err;
33338c2ecf20Sopenharmony_ci	int stride;
33348c2ecf20Sopenharmony_ci	struct resource *res;
33358c2ecf20Sopenharmony_ci
33368c2ecf20Sopenharmony_ci	priv = devm_kzalloc(dev, sizeof(struct talitos_private), GFP_KERNEL);
33378c2ecf20Sopenharmony_ci	if (!priv)
33388c2ecf20Sopenharmony_ci		return -ENOMEM;
33398c2ecf20Sopenharmony_ci
33408c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&priv->alg_list);
33418c2ecf20Sopenharmony_ci
33428c2ecf20Sopenharmony_ci	dev_set_drvdata(dev, priv);
33438c2ecf20Sopenharmony_ci
33448c2ecf20Sopenharmony_ci	priv->ofdev = ofdev;
33458c2ecf20Sopenharmony_ci
33468c2ecf20Sopenharmony_ci	spin_lock_init(&priv->reg_lock);
33478c2ecf20Sopenharmony_ci
33488c2ecf20Sopenharmony_ci	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
33498c2ecf20Sopenharmony_ci	if (!res)
33508c2ecf20Sopenharmony_ci		return -ENXIO;
33518c2ecf20Sopenharmony_ci	priv->reg = devm_ioremap(dev, res->start, resource_size(res));
33528c2ecf20Sopenharmony_ci	if (!priv->reg) {
33538c2ecf20Sopenharmony_ci		dev_err(dev, "failed to of_iomap\n");
33548c2ecf20Sopenharmony_ci		err = -ENOMEM;
33558c2ecf20Sopenharmony_ci		goto err_out;
33568c2ecf20Sopenharmony_ci	}
33578c2ecf20Sopenharmony_ci
33588c2ecf20Sopenharmony_ci	/* get SEC version capabilities from device tree */
33598c2ecf20Sopenharmony_ci	of_property_read_u32(np, "fsl,num-channels", &priv->num_channels);
33608c2ecf20Sopenharmony_ci	of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len);
33618c2ecf20Sopenharmony_ci	of_property_read_u32(np, "fsl,exec-units-mask", &priv->exec_units);
33628c2ecf20Sopenharmony_ci	of_property_read_u32(np, "fsl,descriptor-types-mask",
33638c2ecf20Sopenharmony_ci			     &priv->desc_types);
33648c2ecf20Sopenharmony_ci
33658c2ecf20Sopenharmony_ci	if (!is_power_of_2(priv->num_channels) || !priv->chfifo_len ||
33668c2ecf20Sopenharmony_ci	    !priv->exec_units || !priv->desc_types) {
33678c2ecf20Sopenharmony_ci		dev_err(dev, "invalid property data in device tree node\n");
33688c2ecf20Sopenharmony_ci		err = -EINVAL;
33698c2ecf20Sopenharmony_ci		goto err_out;
33708c2ecf20Sopenharmony_ci	}
33718c2ecf20Sopenharmony_ci
33728c2ecf20Sopenharmony_ci	if (of_device_is_compatible(np, "fsl,sec3.0"))
33738c2ecf20Sopenharmony_ci		priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
33748c2ecf20Sopenharmony_ci
33758c2ecf20Sopenharmony_ci	if (of_device_is_compatible(np, "fsl,sec2.1"))
33768c2ecf20Sopenharmony_ci		priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
33778c2ecf20Sopenharmony_ci				  TALITOS_FTR_SHA224_HWINIT |
33788c2ecf20Sopenharmony_ci				  TALITOS_FTR_HMAC_OK;
33798c2ecf20Sopenharmony_ci
33808c2ecf20Sopenharmony_ci	if (of_device_is_compatible(np, "fsl,sec1.0"))
33818c2ecf20Sopenharmony_ci		priv->features |= TALITOS_FTR_SEC1;
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_ci	if (of_device_is_compatible(np, "fsl,sec1.2")) {
33848c2ecf20Sopenharmony_ci		priv->reg_deu = priv->reg + TALITOS12_DEU;
33858c2ecf20Sopenharmony_ci		priv->reg_aesu = priv->reg + TALITOS12_AESU;
33868c2ecf20Sopenharmony_ci		priv->reg_mdeu = priv->reg + TALITOS12_MDEU;
33878c2ecf20Sopenharmony_ci		stride = TALITOS1_CH_STRIDE;
33888c2ecf20Sopenharmony_ci	} else if (of_device_is_compatible(np, "fsl,sec1.0")) {
33898c2ecf20Sopenharmony_ci		priv->reg_deu = priv->reg + TALITOS10_DEU;
33908c2ecf20Sopenharmony_ci		priv->reg_aesu = priv->reg + TALITOS10_AESU;
33918c2ecf20Sopenharmony_ci		priv->reg_mdeu = priv->reg + TALITOS10_MDEU;
33928c2ecf20Sopenharmony_ci		priv->reg_afeu = priv->reg + TALITOS10_AFEU;
33938c2ecf20Sopenharmony_ci		priv->reg_rngu = priv->reg + TALITOS10_RNGU;
33948c2ecf20Sopenharmony_ci		priv->reg_pkeu = priv->reg + TALITOS10_PKEU;
33958c2ecf20Sopenharmony_ci		stride = TALITOS1_CH_STRIDE;
33968c2ecf20Sopenharmony_ci	} else {
33978c2ecf20Sopenharmony_ci		priv->reg_deu = priv->reg + TALITOS2_DEU;
33988c2ecf20Sopenharmony_ci		priv->reg_aesu = priv->reg + TALITOS2_AESU;
33998c2ecf20Sopenharmony_ci		priv->reg_mdeu = priv->reg + TALITOS2_MDEU;
34008c2ecf20Sopenharmony_ci		priv->reg_afeu = priv->reg + TALITOS2_AFEU;
34018c2ecf20Sopenharmony_ci		priv->reg_rngu = priv->reg + TALITOS2_RNGU;
34028c2ecf20Sopenharmony_ci		priv->reg_pkeu = priv->reg + TALITOS2_PKEU;
34038c2ecf20Sopenharmony_ci		priv->reg_keu = priv->reg + TALITOS2_KEU;
34048c2ecf20Sopenharmony_ci		priv->reg_crcu = priv->reg + TALITOS2_CRCU;
34058c2ecf20Sopenharmony_ci		stride = TALITOS2_CH_STRIDE;
34068c2ecf20Sopenharmony_ci	}
34078c2ecf20Sopenharmony_ci
34088c2ecf20Sopenharmony_ci	err = talitos_probe_irq(ofdev);
34098c2ecf20Sopenharmony_ci	if (err)
34108c2ecf20Sopenharmony_ci		goto err_out;
34118c2ecf20Sopenharmony_ci
34128c2ecf20Sopenharmony_ci	if (has_ftr_sec1(priv)) {
34138c2ecf20Sopenharmony_ci		if (priv->num_channels == 1)
34148c2ecf20Sopenharmony_ci			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
34158c2ecf20Sopenharmony_ci				     (unsigned long)dev);
34168c2ecf20Sopenharmony_ci		else
34178c2ecf20Sopenharmony_ci			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
34188c2ecf20Sopenharmony_ci				     (unsigned long)dev);
34198c2ecf20Sopenharmony_ci	} else {
34208c2ecf20Sopenharmony_ci		if (priv->irq[1]) {
34218c2ecf20Sopenharmony_ci			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
34228c2ecf20Sopenharmony_ci				     (unsigned long)dev);
34238c2ecf20Sopenharmony_ci			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
34248c2ecf20Sopenharmony_ci				     (unsigned long)dev);
34258c2ecf20Sopenharmony_ci		} else if (priv->num_channels == 1) {
34268c2ecf20Sopenharmony_ci			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
34278c2ecf20Sopenharmony_ci				     (unsigned long)dev);
34288c2ecf20Sopenharmony_ci		} else {
34298c2ecf20Sopenharmony_ci			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
34308c2ecf20Sopenharmony_ci				     (unsigned long)dev);
34318c2ecf20Sopenharmony_ci		}
34328c2ecf20Sopenharmony_ci	}
34338c2ecf20Sopenharmony_ci
34348c2ecf20Sopenharmony_ci	priv->chan = devm_kcalloc(dev,
34358c2ecf20Sopenharmony_ci				  priv->num_channels,
34368c2ecf20Sopenharmony_ci				  sizeof(struct talitos_channel),
34378c2ecf20Sopenharmony_ci				  GFP_KERNEL);
34388c2ecf20Sopenharmony_ci	if (!priv->chan) {
34398c2ecf20Sopenharmony_ci		dev_err(dev, "failed to allocate channel management space\n");
34408c2ecf20Sopenharmony_ci		err = -ENOMEM;
34418c2ecf20Sopenharmony_ci		goto err_out;
34428c2ecf20Sopenharmony_ci	}
34438c2ecf20Sopenharmony_ci
34448c2ecf20Sopenharmony_ci	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
34458c2ecf20Sopenharmony_ci
34468c2ecf20Sopenharmony_ci	for (i = 0; i < priv->num_channels; i++) {
34478c2ecf20Sopenharmony_ci		priv->chan[i].reg = priv->reg + stride * (i + 1);
34488c2ecf20Sopenharmony_ci		if (!priv->irq[1] || !(i & 1))
34498c2ecf20Sopenharmony_ci			priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
34508c2ecf20Sopenharmony_ci
34518c2ecf20Sopenharmony_ci		spin_lock_init(&priv->chan[i].head_lock);
34528c2ecf20Sopenharmony_ci		spin_lock_init(&priv->chan[i].tail_lock);
34538c2ecf20Sopenharmony_ci
34548c2ecf20Sopenharmony_ci		priv->chan[i].fifo = devm_kcalloc(dev,
34558c2ecf20Sopenharmony_ci						priv->fifo_len,
34568c2ecf20Sopenharmony_ci						sizeof(struct talitos_request),
34578c2ecf20Sopenharmony_ci						GFP_KERNEL);
34588c2ecf20Sopenharmony_ci		if (!priv->chan[i].fifo) {
34598c2ecf20Sopenharmony_ci			dev_err(dev, "failed to allocate request fifo %d\n", i);
34608c2ecf20Sopenharmony_ci			err = -ENOMEM;
34618c2ecf20Sopenharmony_ci			goto err_out;
34628c2ecf20Sopenharmony_ci		}
34638c2ecf20Sopenharmony_ci
34648c2ecf20Sopenharmony_ci		atomic_set(&priv->chan[i].submit_count,
34658c2ecf20Sopenharmony_ci			   -(priv->chfifo_len - 1));
34668c2ecf20Sopenharmony_ci	}
34678c2ecf20Sopenharmony_ci
34688c2ecf20Sopenharmony_ci	dma_set_mask(dev, DMA_BIT_MASK(36));
34698c2ecf20Sopenharmony_ci
34708c2ecf20Sopenharmony_ci	/* reset and initialize the h/w */
34718c2ecf20Sopenharmony_ci	err = init_device(dev);
34728c2ecf20Sopenharmony_ci	if (err) {
34738c2ecf20Sopenharmony_ci		dev_err(dev, "failed to initialize device\n");
34748c2ecf20Sopenharmony_ci		goto err_out;
34758c2ecf20Sopenharmony_ci	}
34768c2ecf20Sopenharmony_ci
34778c2ecf20Sopenharmony_ci	/* register the RNG, if available */
34788c2ecf20Sopenharmony_ci	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
34798c2ecf20Sopenharmony_ci		err = talitos_register_rng(dev);
34808c2ecf20Sopenharmony_ci		if (err) {
34818c2ecf20Sopenharmony_ci			dev_err(dev, "failed to register hwrng: %d\n", err);
34828c2ecf20Sopenharmony_ci			goto err_out;
34838c2ecf20Sopenharmony_ci		} else
34848c2ecf20Sopenharmony_ci			dev_info(dev, "hwrng\n");
34858c2ecf20Sopenharmony_ci	}
34868c2ecf20Sopenharmony_ci
34878c2ecf20Sopenharmony_ci	/* register crypto algorithms the device supports */
34888c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
34898c2ecf20Sopenharmony_ci		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
34908c2ecf20Sopenharmony_ci			struct talitos_crypto_alg *t_alg;
34918c2ecf20Sopenharmony_ci			struct crypto_alg *alg = NULL;
34928c2ecf20Sopenharmony_ci
34938c2ecf20Sopenharmony_ci			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
34948c2ecf20Sopenharmony_ci			if (IS_ERR(t_alg)) {
34958c2ecf20Sopenharmony_ci				err = PTR_ERR(t_alg);
34968c2ecf20Sopenharmony_ci				if (err == -ENOTSUPP)
34978c2ecf20Sopenharmony_ci					continue;
34988c2ecf20Sopenharmony_ci				goto err_out;
34998c2ecf20Sopenharmony_ci			}
35008c2ecf20Sopenharmony_ci
35018c2ecf20Sopenharmony_ci			switch (t_alg->algt.type) {
35028c2ecf20Sopenharmony_ci			case CRYPTO_ALG_TYPE_SKCIPHER:
35038c2ecf20Sopenharmony_ci				err = crypto_register_skcipher(
35048c2ecf20Sopenharmony_ci						&t_alg->algt.alg.skcipher);
35058c2ecf20Sopenharmony_ci				alg = &t_alg->algt.alg.skcipher.base;
35068c2ecf20Sopenharmony_ci				break;
35078c2ecf20Sopenharmony_ci
35088c2ecf20Sopenharmony_ci			case CRYPTO_ALG_TYPE_AEAD:
35098c2ecf20Sopenharmony_ci				err = crypto_register_aead(
35108c2ecf20Sopenharmony_ci					&t_alg->algt.alg.aead);
35118c2ecf20Sopenharmony_ci				alg = &t_alg->algt.alg.aead.base;
35128c2ecf20Sopenharmony_ci				break;
35138c2ecf20Sopenharmony_ci
35148c2ecf20Sopenharmony_ci			case CRYPTO_ALG_TYPE_AHASH:
35158c2ecf20Sopenharmony_ci				err = crypto_register_ahash(
35168c2ecf20Sopenharmony_ci						&t_alg->algt.alg.hash);
35178c2ecf20Sopenharmony_ci				alg = &t_alg->algt.alg.hash.halg.base;
35188c2ecf20Sopenharmony_ci				break;
35198c2ecf20Sopenharmony_ci			}
35208c2ecf20Sopenharmony_ci			if (err) {
35218c2ecf20Sopenharmony_ci				dev_err(dev, "%s alg registration failed\n",
35228c2ecf20Sopenharmony_ci					alg->cra_driver_name);
35238c2ecf20Sopenharmony_ci				devm_kfree(dev, t_alg);
35248c2ecf20Sopenharmony_ci			} else
35258c2ecf20Sopenharmony_ci				list_add_tail(&t_alg->entry, &priv->alg_list);
35268c2ecf20Sopenharmony_ci		}
35278c2ecf20Sopenharmony_ci	}
35288c2ecf20Sopenharmony_ci	if (!list_empty(&priv->alg_list))
35298c2ecf20Sopenharmony_ci		dev_info(dev, "%s algorithms registered in /proc/crypto\n",
35308c2ecf20Sopenharmony_ci			 (char *)of_get_property(np, "compatible", NULL));
35318c2ecf20Sopenharmony_ci
35328c2ecf20Sopenharmony_ci	return 0;
35338c2ecf20Sopenharmony_ci
35348c2ecf20Sopenharmony_cierr_out:
35358c2ecf20Sopenharmony_ci	talitos_remove(ofdev);
35368c2ecf20Sopenharmony_ci
35378c2ecf20Sopenharmony_ci	return err;
35388c2ecf20Sopenharmony_ci}
35398c2ecf20Sopenharmony_ci
35408c2ecf20Sopenharmony_cistatic const struct of_device_id talitos_match[] = {
35418c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS1
35428c2ecf20Sopenharmony_ci	{
35438c2ecf20Sopenharmony_ci		.compatible = "fsl,sec1.0",
35448c2ecf20Sopenharmony_ci	},
35458c2ecf20Sopenharmony_ci#endif
35468c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_TALITOS2
35478c2ecf20Sopenharmony_ci	{
35488c2ecf20Sopenharmony_ci		.compatible = "fsl,sec2.0",
35498c2ecf20Sopenharmony_ci	},
35508c2ecf20Sopenharmony_ci#endif
35518c2ecf20Sopenharmony_ci	{},
35528c2ecf20Sopenharmony_ci};
35538c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, talitos_match);
35548c2ecf20Sopenharmony_ci
35558c2ecf20Sopenharmony_cistatic struct platform_driver talitos_driver = {
35568c2ecf20Sopenharmony_ci	.driver = {
35578c2ecf20Sopenharmony_ci		.name = "talitos",
35588c2ecf20Sopenharmony_ci		.of_match_table = talitos_match,
35598c2ecf20Sopenharmony_ci	},
35608c2ecf20Sopenharmony_ci	.probe = talitos_probe,
35618c2ecf20Sopenharmony_ci	.remove = talitos_remove,
35628c2ecf20Sopenharmony_ci};
35638c2ecf20Sopenharmony_ci
35648c2ecf20Sopenharmony_cimodule_platform_driver(talitos_driver);
35658c2ecf20Sopenharmony_ci
35668c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
35678c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
35688c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Freescale integrated security engine (SEC) driver");
3569