18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2010-2011 Picochip Ltd., Jamie Iles
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h>
68c2ecf20Sopenharmony_ci#include <crypto/aes.h>
78c2ecf20Sopenharmony_ci#include <crypto/algapi.h>
88c2ecf20Sopenharmony_ci#include <crypto/authenc.h>
98c2ecf20Sopenharmony_ci#include <crypto/internal/des.h>
108c2ecf20Sopenharmony_ci#include <crypto/md5.h>
118c2ecf20Sopenharmony_ci#include <crypto/sha.h>
128c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h>
138c2ecf20Sopenharmony_ci#include <linux/clk.h>
148c2ecf20Sopenharmony_ci#include <linux/crypto.h>
158c2ecf20Sopenharmony_ci#include <linux/delay.h>
168c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
178c2ecf20Sopenharmony_ci#include <linux/dmapool.h>
188c2ecf20Sopenharmony_ci#include <linux/err.h>
198c2ecf20Sopenharmony_ci#include <linux/init.h>
208c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
218c2ecf20Sopenharmony_ci#include <linux/io.h>
228c2ecf20Sopenharmony_ci#include <linux/list.h>
238c2ecf20Sopenharmony_ci#include <linux/module.h>
248c2ecf20Sopenharmony_ci#include <linux/of.h>
258c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
268c2ecf20Sopenharmony_ci#include <linux/pm.h>
278c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h>
288c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
298c2ecf20Sopenharmony_ci#include <linux/sched.h>
308c2ecf20Sopenharmony_ci#include <linux/sizes.h>
318c2ecf20Sopenharmony_ci#include <linux/slab.h>
328c2ecf20Sopenharmony_ci#include <linux/timer.h>
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#include "picoxcell_crypto_regs.h"
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/*
378c2ecf20Sopenharmony_ci * The threshold for the number of entries in the CMD FIFO available before
388c2ecf20Sopenharmony_ci * the CMD0_CNT interrupt is raised. Increasing this value will reduce the
398c2ecf20Sopenharmony_ci * number of interrupts raised to the CPU.
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_ci#define CMD0_IRQ_THRESHOLD   1
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/*
448c2ecf20Sopenharmony_ci * The timeout period (in jiffies) for a PDU. When the the number of PDUs in
458c2ecf20Sopenharmony_ci * flight is greater than the STAT_IRQ_THRESHOLD or 0 the timer is disabled.
468c2ecf20Sopenharmony_ci * When there are packets in flight but lower than the threshold, we enable
478c2ecf20Sopenharmony_ci * the timer and at expiry, attempt to remove any processed packets from the
488c2ecf20Sopenharmony_ci * queue and if there are still packets left, schedule the timer again.
498c2ecf20Sopenharmony_ci */
508c2ecf20Sopenharmony_ci#define PACKET_TIMEOUT	    1
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* The priority to register each algorithm with. */
538c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_ALG_PRIORITY	10000
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_KASUMI_F8_KEY_LEN	16
568c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ 64
578c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_IPSEC_HASH_PG_SZ	64
588c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_IPSEC_MAX_CTXS	32
598c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_IPSEC_FIFO_SZ	32
608c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_L2_CIPHER_PG_SZ	64
618c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_L2_HASH_PG_SZ	64
628c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_L2_MAX_CTXS	128
638c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_L2_FIFO_SZ		128
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci#define MAX_DDT_LEN			16
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci/* DDT format. This must match the hardware DDT format exactly. */
688c2ecf20Sopenharmony_cistruct spacc_ddt {
698c2ecf20Sopenharmony_ci	dma_addr_t	p;
708c2ecf20Sopenharmony_ci	u32		len;
718c2ecf20Sopenharmony_ci};
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/*
748c2ecf20Sopenharmony_ci * Asynchronous crypto request structure.
758c2ecf20Sopenharmony_ci *
768c2ecf20Sopenharmony_ci * This structure defines a request that is either queued for processing or
778c2ecf20Sopenharmony_ci * being processed.
788c2ecf20Sopenharmony_ci */
798c2ecf20Sopenharmony_cistruct spacc_req {
808c2ecf20Sopenharmony_ci	struct list_head		list;
818c2ecf20Sopenharmony_ci	struct spacc_engine		*engine;
828c2ecf20Sopenharmony_ci	struct crypto_async_request	*req;
838c2ecf20Sopenharmony_ci	int				result;
848c2ecf20Sopenharmony_ci	bool				is_encrypt;
858c2ecf20Sopenharmony_ci	unsigned			ctx_id;
868c2ecf20Sopenharmony_ci	dma_addr_t			src_addr, dst_addr;
878c2ecf20Sopenharmony_ci	struct spacc_ddt		*src_ddt, *dst_ddt;
888c2ecf20Sopenharmony_ci	void				(*complete)(struct spacc_req *req);
898c2ecf20Sopenharmony_ci	struct skcipher_request		fallback_req;	// keep at the end
908c2ecf20Sopenharmony_ci};
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistruct spacc_aead {
938c2ecf20Sopenharmony_ci	unsigned long			ctrl_default;
948c2ecf20Sopenharmony_ci	unsigned long			type;
958c2ecf20Sopenharmony_ci	struct aead_alg			alg;
968c2ecf20Sopenharmony_ci	struct spacc_engine		*engine;
978c2ecf20Sopenharmony_ci	struct list_head		entry;
988c2ecf20Sopenharmony_ci	int				key_offs;
998c2ecf20Sopenharmony_ci	int				iv_offs;
1008c2ecf20Sopenharmony_ci};
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistruct spacc_engine {
1038c2ecf20Sopenharmony_ci	void __iomem			*regs;
1048c2ecf20Sopenharmony_ci	struct list_head		pending;
1058c2ecf20Sopenharmony_ci	int				next_ctx;
1068c2ecf20Sopenharmony_ci	spinlock_t			hw_lock;
1078c2ecf20Sopenharmony_ci	int				in_flight;
1088c2ecf20Sopenharmony_ci	struct list_head		completed;
1098c2ecf20Sopenharmony_ci	struct list_head		in_progress;
1108c2ecf20Sopenharmony_ci	struct tasklet_struct		complete;
1118c2ecf20Sopenharmony_ci	unsigned long			fifo_sz;
1128c2ecf20Sopenharmony_ci	void __iomem			*cipher_ctx_base;
1138c2ecf20Sopenharmony_ci	void __iomem			*hash_key_base;
1148c2ecf20Sopenharmony_ci	struct spacc_alg		*algs;
1158c2ecf20Sopenharmony_ci	unsigned			num_algs;
1168c2ecf20Sopenharmony_ci	struct list_head		registered_algs;
1178c2ecf20Sopenharmony_ci	struct spacc_aead		*aeads;
1188c2ecf20Sopenharmony_ci	unsigned			num_aeads;
1198c2ecf20Sopenharmony_ci	struct list_head		registered_aeads;
1208c2ecf20Sopenharmony_ci	size_t				cipher_pg_sz;
1218c2ecf20Sopenharmony_ci	size_t				hash_pg_sz;
1228c2ecf20Sopenharmony_ci	const char			*name;
1238c2ecf20Sopenharmony_ci	struct clk			*clk;
1248c2ecf20Sopenharmony_ci	struct device			*dev;
1258c2ecf20Sopenharmony_ci	unsigned			max_ctxs;
1268c2ecf20Sopenharmony_ci	struct timer_list		packet_timeout;
1278c2ecf20Sopenharmony_ci	unsigned			stat_irq_thresh;
1288c2ecf20Sopenharmony_ci	struct dma_pool			*req_pool;
1298c2ecf20Sopenharmony_ci};
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci/* Algorithm type mask. */
1328c2ecf20Sopenharmony_ci#define SPACC_CRYPTO_ALG_MASK		0x7
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci/* SPACC definition of a crypto algorithm. */
1358c2ecf20Sopenharmony_cistruct spacc_alg {
1368c2ecf20Sopenharmony_ci	unsigned long			ctrl_default;
1378c2ecf20Sopenharmony_ci	unsigned long			type;
1388c2ecf20Sopenharmony_ci	struct skcipher_alg		alg;
1398c2ecf20Sopenharmony_ci	struct spacc_engine		*engine;
1408c2ecf20Sopenharmony_ci	struct list_head		entry;
1418c2ecf20Sopenharmony_ci	int				key_offs;
1428c2ecf20Sopenharmony_ci	int				iv_offs;
1438c2ecf20Sopenharmony_ci};
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci/* Generic context structure for any algorithm type. */
1468c2ecf20Sopenharmony_cistruct spacc_generic_ctx {
1478c2ecf20Sopenharmony_ci	struct spacc_engine		*engine;
1488c2ecf20Sopenharmony_ci	int				flags;
1498c2ecf20Sopenharmony_ci	int				key_offs;
1508c2ecf20Sopenharmony_ci	int				iv_offs;
1518c2ecf20Sopenharmony_ci};
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci/* Block cipher context. */
1548c2ecf20Sopenharmony_cistruct spacc_ablk_ctx {
1558c2ecf20Sopenharmony_ci	struct spacc_generic_ctx	generic;
1568c2ecf20Sopenharmony_ci	u8				key[AES_MAX_KEY_SIZE];
1578c2ecf20Sopenharmony_ci	u8				key_len;
1588c2ecf20Sopenharmony_ci	/*
1598c2ecf20Sopenharmony_ci	 * The fallback cipher. If the operation can't be done in hardware,
1608c2ecf20Sopenharmony_ci	 * fallback to a software version.
1618c2ecf20Sopenharmony_ci	 */
1628c2ecf20Sopenharmony_ci	struct crypto_skcipher		*sw_cipher;
1638c2ecf20Sopenharmony_ci};
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci/* AEAD cipher context. */
1668c2ecf20Sopenharmony_cistruct spacc_aead_ctx {
1678c2ecf20Sopenharmony_ci	struct spacc_generic_ctx	generic;
1688c2ecf20Sopenharmony_ci	u8				cipher_key[AES_MAX_KEY_SIZE];
1698c2ecf20Sopenharmony_ci	u8				hash_ctx[SPACC_CRYPTO_IPSEC_HASH_PG_SZ];
1708c2ecf20Sopenharmony_ci	u8				cipher_key_len;
1718c2ecf20Sopenharmony_ci	u8				hash_key_len;
1728c2ecf20Sopenharmony_ci	struct crypto_aead		*sw_cipher;
1738c2ecf20Sopenharmony_ci};
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cistatic int spacc_ablk_submit(struct spacc_req *req);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic inline struct spacc_alg *to_spacc_skcipher(struct skcipher_alg *alg)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	return alg ? container_of(alg, struct spacc_alg, alg) : NULL;
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic inline struct spacc_aead *to_spacc_aead(struct aead_alg *alg)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	return container_of(alg, struct spacc_aead, alg);
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic inline int spacc_fifo_cmd_full(struct spacc_engine *engine)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	u32 fifo_stat = readl(engine->regs + SPA_FIFO_STAT_REG_OFFSET);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	return fifo_stat & SPA_FIFO_CMD_FULL;
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci/*
1958c2ecf20Sopenharmony_ci * Given a cipher context, and a context number, get the base address of the
1968c2ecf20Sopenharmony_ci * context page.
1978c2ecf20Sopenharmony_ci *
1988c2ecf20Sopenharmony_ci * Returns the address of the context page where the key/context may
1998c2ecf20Sopenharmony_ci * be written.
2008c2ecf20Sopenharmony_ci */
2018c2ecf20Sopenharmony_cistatic inline void __iomem *spacc_ctx_page_addr(struct spacc_generic_ctx *ctx,
2028c2ecf20Sopenharmony_ci						unsigned indx,
2038c2ecf20Sopenharmony_ci						bool is_cipher_ctx)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	return is_cipher_ctx ? ctx->engine->cipher_ctx_base +
2068c2ecf20Sopenharmony_ci			(indx * ctx->engine->cipher_pg_sz) :
2078c2ecf20Sopenharmony_ci		ctx->engine->hash_key_base + (indx * ctx->engine->hash_pg_sz);
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci/* The context pages can only be written with 32-bit accesses. */
2118c2ecf20Sopenharmony_cistatic inline void memcpy_toio32(u32 __iomem *dst, const void *src,
2128c2ecf20Sopenharmony_ci				 unsigned count)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	const u32 *src32 = (const u32 *) src;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	while (count--)
2178c2ecf20Sopenharmony_ci		writel(*src32++, dst++);
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic void spacc_cipher_write_ctx(struct spacc_generic_ctx *ctx,
2218c2ecf20Sopenharmony_ci				   void __iomem *page_addr, const u8 *key,
2228c2ecf20Sopenharmony_ci				   size_t key_len, const u8 *iv, size_t iv_len)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	void __iomem *key_ptr = page_addr + ctx->key_offs;
2258c2ecf20Sopenharmony_ci	void __iomem *iv_ptr = page_addr + ctx->iv_offs;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	memcpy_toio32(key_ptr, key, key_len / 4);
2288c2ecf20Sopenharmony_ci	memcpy_toio32(iv_ptr, iv, iv_len / 4);
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci/*
2328c2ecf20Sopenharmony_ci * Load a context into the engines context memory.
2338c2ecf20Sopenharmony_ci *
2348c2ecf20Sopenharmony_ci * Returns the index of the context page where the context was loaded.
2358c2ecf20Sopenharmony_ci */
2368c2ecf20Sopenharmony_cistatic unsigned spacc_load_ctx(struct spacc_generic_ctx *ctx,
2378c2ecf20Sopenharmony_ci			       const u8 *ciph_key, size_t ciph_len,
2388c2ecf20Sopenharmony_ci			       const u8 *iv, size_t ivlen, const u8 *hash_key,
2398c2ecf20Sopenharmony_ci			       size_t hash_len)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	unsigned indx = ctx->engine->next_ctx++;
2428c2ecf20Sopenharmony_ci	void __iomem *ciph_page_addr, *hash_page_addr;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	ciph_page_addr = spacc_ctx_page_addr(ctx, indx, 1);
2458c2ecf20Sopenharmony_ci	hash_page_addr = spacc_ctx_page_addr(ctx, indx, 0);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	ctx->engine->next_ctx &= ctx->engine->fifo_sz - 1;
2488c2ecf20Sopenharmony_ci	spacc_cipher_write_ctx(ctx, ciph_page_addr, ciph_key, ciph_len, iv,
2498c2ecf20Sopenharmony_ci			       ivlen);
2508c2ecf20Sopenharmony_ci	writel(ciph_len | (indx << SPA_KEY_SZ_CTX_INDEX_OFFSET) |
2518c2ecf20Sopenharmony_ci	       (1 << SPA_KEY_SZ_CIPHER_OFFSET),
2528c2ecf20Sopenharmony_ci	       ctx->engine->regs + SPA_KEY_SZ_REG_OFFSET);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	if (hash_key) {
2558c2ecf20Sopenharmony_ci		memcpy_toio32(hash_page_addr, hash_key, hash_len / 4);
2568c2ecf20Sopenharmony_ci		writel(hash_len | (indx << SPA_KEY_SZ_CTX_INDEX_OFFSET),
2578c2ecf20Sopenharmony_ci		       ctx->engine->regs + SPA_KEY_SZ_REG_OFFSET);
2588c2ecf20Sopenharmony_ci	}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	return indx;
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistatic inline void ddt_set(struct spacc_ddt *ddt, dma_addr_t phys, size_t len)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	ddt->p = phys;
2668c2ecf20Sopenharmony_ci	ddt->len = len;
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci/*
2708c2ecf20Sopenharmony_ci * Take a crypto request and scatterlists for the data and turn them into DDTs
2718c2ecf20Sopenharmony_ci * for passing to the crypto engines. This also DMA maps the data so that the
2728c2ecf20Sopenharmony_ci * crypto engines can DMA to/from them.
2738c2ecf20Sopenharmony_ci */
2748c2ecf20Sopenharmony_cistatic struct spacc_ddt *spacc_sg_to_ddt(struct spacc_engine *engine,
2758c2ecf20Sopenharmony_ci					 struct scatterlist *payload,
2768c2ecf20Sopenharmony_ci					 unsigned nbytes,
2778c2ecf20Sopenharmony_ci					 enum dma_data_direction dir,
2788c2ecf20Sopenharmony_ci					 dma_addr_t *ddt_phys)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	unsigned mapped_ents;
2818c2ecf20Sopenharmony_ci	struct scatterlist *cur;
2828c2ecf20Sopenharmony_ci	struct spacc_ddt *ddt;
2838c2ecf20Sopenharmony_ci	int i;
2848c2ecf20Sopenharmony_ci	int nents;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	nents = sg_nents_for_len(payload, nbytes);
2878c2ecf20Sopenharmony_ci	if (nents < 0) {
2888c2ecf20Sopenharmony_ci		dev_err(engine->dev, "Invalid numbers of SG.\n");
2898c2ecf20Sopenharmony_ci		return NULL;
2908c2ecf20Sopenharmony_ci	}
2918c2ecf20Sopenharmony_ci	mapped_ents = dma_map_sg(engine->dev, payload, nents, dir);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	if (mapped_ents + 1 > MAX_DDT_LEN)
2948c2ecf20Sopenharmony_ci		goto out;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, ddt_phys);
2978c2ecf20Sopenharmony_ci	if (!ddt)
2988c2ecf20Sopenharmony_ci		goto out;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	for_each_sg(payload, cur, mapped_ents, i)
3018c2ecf20Sopenharmony_ci		ddt_set(&ddt[i], sg_dma_address(cur), sg_dma_len(cur));
3028c2ecf20Sopenharmony_ci	ddt_set(&ddt[mapped_ents], 0, 0);
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	return ddt;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ciout:
3078c2ecf20Sopenharmony_ci	dma_unmap_sg(engine->dev, payload, nents, dir);
3088c2ecf20Sopenharmony_ci	return NULL;
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_cistatic int spacc_aead_make_ddts(struct aead_request *areq)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
3148c2ecf20Sopenharmony_ci	struct spacc_req *req = aead_request_ctx(areq);
3158c2ecf20Sopenharmony_ci	struct spacc_engine *engine = req->engine;
3168c2ecf20Sopenharmony_ci	struct spacc_ddt *src_ddt, *dst_ddt;
3178c2ecf20Sopenharmony_ci	unsigned total;
3188c2ecf20Sopenharmony_ci	int src_nents, dst_nents;
3198c2ecf20Sopenharmony_ci	struct scatterlist *cur;
3208c2ecf20Sopenharmony_ci	int i, dst_ents, src_ents;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	total = areq->assoclen + areq->cryptlen;
3238c2ecf20Sopenharmony_ci	if (req->is_encrypt)
3248c2ecf20Sopenharmony_ci		total += crypto_aead_authsize(aead);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	src_nents = sg_nents_for_len(areq->src, total);
3278c2ecf20Sopenharmony_ci	if (src_nents < 0) {
3288c2ecf20Sopenharmony_ci		dev_err(engine->dev, "Invalid numbers of src SG.\n");
3298c2ecf20Sopenharmony_ci		return src_nents;
3308c2ecf20Sopenharmony_ci	}
3318c2ecf20Sopenharmony_ci	if (src_nents + 1 > MAX_DDT_LEN)
3328c2ecf20Sopenharmony_ci		return -E2BIG;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	dst_nents = 0;
3358c2ecf20Sopenharmony_ci	if (areq->src != areq->dst) {
3368c2ecf20Sopenharmony_ci		dst_nents = sg_nents_for_len(areq->dst, total);
3378c2ecf20Sopenharmony_ci		if (dst_nents < 0) {
3388c2ecf20Sopenharmony_ci			dev_err(engine->dev, "Invalid numbers of dst SG.\n");
3398c2ecf20Sopenharmony_ci			return dst_nents;
3408c2ecf20Sopenharmony_ci		}
3418c2ecf20Sopenharmony_ci		if (src_nents + 1 > MAX_DDT_LEN)
3428c2ecf20Sopenharmony_ci			return -E2BIG;
3438c2ecf20Sopenharmony_ci	}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	src_ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, &req->src_addr);
3468c2ecf20Sopenharmony_ci	if (!src_ddt)
3478c2ecf20Sopenharmony_ci		goto err;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	dst_ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, &req->dst_addr);
3508c2ecf20Sopenharmony_ci	if (!dst_ddt)
3518c2ecf20Sopenharmony_ci		goto err_free_src;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	req->src_ddt = src_ddt;
3548c2ecf20Sopenharmony_ci	req->dst_ddt = dst_ddt;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	if (dst_nents) {
3578c2ecf20Sopenharmony_ci		src_ents = dma_map_sg(engine->dev, areq->src, src_nents,
3588c2ecf20Sopenharmony_ci				      DMA_TO_DEVICE);
3598c2ecf20Sopenharmony_ci		if (!src_ents)
3608c2ecf20Sopenharmony_ci			goto err_free_dst;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci		dst_ents = dma_map_sg(engine->dev, areq->dst, dst_nents,
3638c2ecf20Sopenharmony_ci				      DMA_FROM_DEVICE);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci		if (!dst_ents) {
3668c2ecf20Sopenharmony_ci			dma_unmap_sg(engine->dev, areq->src, src_nents,
3678c2ecf20Sopenharmony_ci				     DMA_TO_DEVICE);
3688c2ecf20Sopenharmony_ci			goto err_free_dst;
3698c2ecf20Sopenharmony_ci		}
3708c2ecf20Sopenharmony_ci	} else {
3718c2ecf20Sopenharmony_ci		src_ents = dma_map_sg(engine->dev, areq->src, src_nents,
3728c2ecf20Sopenharmony_ci				      DMA_BIDIRECTIONAL);
3738c2ecf20Sopenharmony_ci		if (!src_ents)
3748c2ecf20Sopenharmony_ci			goto err_free_dst;
3758c2ecf20Sopenharmony_ci		dst_ents = src_ents;
3768c2ecf20Sopenharmony_ci	}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	/*
3798c2ecf20Sopenharmony_ci	 * Now map in the payload for the source and destination and terminate
3808c2ecf20Sopenharmony_ci	 * with the NULL pointers.
3818c2ecf20Sopenharmony_ci	 */
3828c2ecf20Sopenharmony_ci	for_each_sg(areq->src, cur, src_ents, i)
3838c2ecf20Sopenharmony_ci		ddt_set(src_ddt++, sg_dma_address(cur), sg_dma_len(cur));
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	/* For decryption we need to skip the associated data. */
3868c2ecf20Sopenharmony_ci	total = req->is_encrypt ? 0 : areq->assoclen;
3878c2ecf20Sopenharmony_ci	for_each_sg(areq->dst, cur, dst_ents, i) {
3888c2ecf20Sopenharmony_ci		unsigned len = sg_dma_len(cur);
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci		if (len <= total) {
3918c2ecf20Sopenharmony_ci			total -= len;
3928c2ecf20Sopenharmony_ci			continue;
3938c2ecf20Sopenharmony_ci		}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci		ddt_set(dst_ddt++, sg_dma_address(cur) + total, len - total);
3968c2ecf20Sopenharmony_ci	}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	ddt_set(src_ddt, 0, 0);
3998c2ecf20Sopenharmony_ci	ddt_set(dst_ddt, 0, 0);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	return 0;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_cierr_free_dst:
4048c2ecf20Sopenharmony_ci	dma_pool_free(engine->req_pool, dst_ddt, req->dst_addr);
4058c2ecf20Sopenharmony_cierr_free_src:
4068c2ecf20Sopenharmony_ci	dma_pool_free(engine->req_pool, src_ddt, req->src_addr);
4078c2ecf20Sopenharmony_cierr:
4088c2ecf20Sopenharmony_ci	return -ENOMEM;
4098c2ecf20Sopenharmony_ci}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_cistatic void spacc_aead_free_ddts(struct spacc_req *req)
4128c2ecf20Sopenharmony_ci{
4138c2ecf20Sopenharmony_ci	struct aead_request *areq = container_of(req->req, struct aead_request,
4148c2ecf20Sopenharmony_ci						 base);
4158c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
4168c2ecf20Sopenharmony_ci	unsigned total = areq->assoclen + areq->cryptlen +
4178c2ecf20Sopenharmony_ci			 (req->is_encrypt ? crypto_aead_authsize(aead) : 0);
4188c2ecf20Sopenharmony_ci	struct spacc_aead_ctx *aead_ctx = crypto_aead_ctx(aead);
4198c2ecf20Sopenharmony_ci	struct spacc_engine *engine = aead_ctx->generic.engine;
4208c2ecf20Sopenharmony_ci	int nents = sg_nents_for_len(areq->src, total);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	/* sg_nents_for_len should not fail since it works when mapping sg */
4238c2ecf20Sopenharmony_ci	if (unlikely(nents < 0)) {
4248c2ecf20Sopenharmony_ci		dev_err(engine->dev, "Invalid numbers of src SG.\n");
4258c2ecf20Sopenharmony_ci		return;
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	if (areq->src != areq->dst) {
4298c2ecf20Sopenharmony_ci		dma_unmap_sg(engine->dev, areq->src, nents, DMA_TO_DEVICE);
4308c2ecf20Sopenharmony_ci		nents = sg_nents_for_len(areq->dst, total);
4318c2ecf20Sopenharmony_ci		if (unlikely(nents < 0)) {
4328c2ecf20Sopenharmony_ci			dev_err(engine->dev, "Invalid numbers of dst SG.\n");
4338c2ecf20Sopenharmony_ci			return;
4348c2ecf20Sopenharmony_ci		}
4358c2ecf20Sopenharmony_ci		dma_unmap_sg(engine->dev, areq->dst, nents, DMA_FROM_DEVICE);
4368c2ecf20Sopenharmony_ci	} else
4378c2ecf20Sopenharmony_ci		dma_unmap_sg(engine->dev, areq->src, nents, DMA_BIDIRECTIONAL);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	dma_pool_free(engine->req_pool, req->src_ddt, req->src_addr);
4408c2ecf20Sopenharmony_ci	dma_pool_free(engine->req_pool, req->dst_ddt, req->dst_addr);
4418c2ecf20Sopenharmony_ci}
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_cistatic void spacc_free_ddt(struct spacc_req *req, struct spacc_ddt *ddt,
4448c2ecf20Sopenharmony_ci			   dma_addr_t ddt_addr, struct scatterlist *payload,
4458c2ecf20Sopenharmony_ci			   unsigned nbytes, enum dma_data_direction dir)
4468c2ecf20Sopenharmony_ci{
4478c2ecf20Sopenharmony_ci	int nents = sg_nents_for_len(payload, nbytes);
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	if (nents < 0) {
4508c2ecf20Sopenharmony_ci		dev_err(req->engine->dev, "Invalid numbers of SG.\n");
4518c2ecf20Sopenharmony_ci		return;
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	dma_unmap_sg(req->engine->dev, payload, nents, dir);
4558c2ecf20Sopenharmony_ci	dma_pool_free(req->engine->req_pool, ddt, ddt_addr);
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic int spacc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
4598c2ecf20Sopenharmony_ci			     unsigned int keylen)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
4628c2ecf20Sopenharmony_ci	struct crypto_authenc_keys keys;
4638c2ecf20Sopenharmony_ci	int err;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	crypto_aead_clear_flags(ctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
4668c2ecf20Sopenharmony_ci	crypto_aead_set_flags(ctx->sw_cipher, crypto_aead_get_flags(tfm) &
4678c2ecf20Sopenharmony_ci					      CRYPTO_TFM_REQ_MASK);
4688c2ecf20Sopenharmony_ci	err = crypto_aead_setkey(ctx->sw_cipher, key, keylen);
4698c2ecf20Sopenharmony_ci	if (err)
4708c2ecf20Sopenharmony_ci		return err;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
4738c2ecf20Sopenharmony_ci		goto badkey;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	if (keys.enckeylen > AES_MAX_KEY_SIZE)
4768c2ecf20Sopenharmony_ci		goto badkey;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	if (keys.authkeylen > sizeof(ctx->hash_ctx))
4798c2ecf20Sopenharmony_ci		goto badkey;
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	memcpy(ctx->cipher_key, keys.enckey, keys.enckeylen);
4828c2ecf20Sopenharmony_ci	ctx->cipher_key_len = keys.enckeylen;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	memcpy(ctx->hash_ctx, keys.authkey, keys.authkeylen);
4858c2ecf20Sopenharmony_ci	ctx->hash_key_len = keys.authkeylen;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
4888c2ecf20Sopenharmony_ci	return 0;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_cibadkey:
4918c2ecf20Sopenharmony_ci	memzero_explicit(&keys, sizeof(keys));
4928c2ecf20Sopenharmony_ci	return -EINVAL;
4938c2ecf20Sopenharmony_ci}
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_cistatic int spacc_aead_setauthsize(struct crypto_aead *tfm,
4968c2ecf20Sopenharmony_ci				  unsigned int authsize)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(crypto_aead_tfm(tfm));
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	return crypto_aead_setauthsize(ctx->sw_cipher, authsize);
5018c2ecf20Sopenharmony_ci}
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci/*
5048c2ecf20Sopenharmony_ci * Check if an AEAD request requires a fallback operation. Some requests can't
5058c2ecf20Sopenharmony_ci * be completed in hardware because the hardware may not support certain key
5068c2ecf20Sopenharmony_ci * sizes. In these cases we need to complete the request in software.
5078c2ecf20Sopenharmony_ci */
5088c2ecf20Sopenharmony_cistatic int spacc_aead_need_fallback(struct aead_request *aead_req)
5098c2ecf20Sopenharmony_ci{
5108c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(aead_req);
5118c2ecf20Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(aead);
5128c2ecf20Sopenharmony_ci	struct spacc_aead *spacc_alg = to_spacc_aead(alg);
5138c2ecf20Sopenharmony_ci	struct spacc_aead_ctx *ctx = crypto_aead_ctx(aead);
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	/*
5168c2ecf20Sopenharmony_ci	 * If we have a non-supported key-length, then we need to do a
5178c2ecf20Sopenharmony_ci	 * software fallback.
5188c2ecf20Sopenharmony_ci	 */
5198c2ecf20Sopenharmony_ci	if ((spacc_alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
5208c2ecf20Sopenharmony_ci	    SPA_CTRL_CIPH_ALG_AES &&
5218c2ecf20Sopenharmony_ci	    ctx->cipher_key_len != AES_KEYSIZE_128 &&
5228c2ecf20Sopenharmony_ci	    ctx->cipher_key_len != AES_KEYSIZE_256)
5238c2ecf20Sopenharmony_ci		return 1;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	return 0;
5268c2ecf20Sopenharmony_ci}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_cistatic int spacc_aead_do_fallback(struct aead_request *req, unsigned alg_type,
5298c2ecf20Sopenharmony_ci				  bool is_encrypt)
5308c2ecf20Sopenharmony_ci{
5318c2ecf20Sopenharmony_ci	struct crypto_tfm *old_tfm = crypto_aead_tfm(crypto_aead_reqtfm(req));
5328c2ecf20Sopenharmony_ci	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(old_tfm);
5338c2ecf20Sopenharmony_ci	struct aead_request *subreq = aead_request_ctx(req);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	aead_request_set_tfm(subreq, ctx->sw_cipher);
5368c2ecf20Sopenharmony_ci	aead_request_set_callback(subreq, req->base.flags,
5378c2ecf20Sopenharmony_ci				  req->base.complete, req->base.data);
5388c2ecf20Sopenharmony_ci	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
5398c2ecf20Sopenharmony_ci			       req->iv);
5408c2ecf20Sopenharmony_ci	aead_request_set_ad(subreq, req->assoclen);
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	return is_encrypt ? crypto_aead_encrypt(subreq) :
5438c2ecf20Sopenharmony_ci			    crypto_aead_decrypt(subreq);
5448c2ecf20Sopenharmony_ci}
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_cistatic void spacc_aead_complete(struct spacc_req *req)
5478c2ecf20Sopenharmony_ci{
5488c2ecf20Sopenharmony_ci	spacc_aead_free_ddts(req);
5498c2ecf20Sopenharmony_ci	req->req->complete(req->req, req->result);
5508c2ecf20Sopenharmony_ci}
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_cistatic int spacc_aead_submit(struct spacc_req *req)
5538c2ecf20Sopenharmony_ci{
5548c2ecf20Sopenharmony_ci	struct aead_request *aead_req =
5558c2ecf20Sopenharmony_ci		container_of(req->req, struct aead_request, base);
5568c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(aead_req);
5578c2ecf20Sopenharmony_ci	unsigned int authsize = crypto_aead_authsize(aead);
5588c2ecf20Sopenharmony_ci	struct spacc_aead_ctx *ctx = crypto_aead_ctx(aead);
5598c2ecf20Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(aead);
5608c2ecf20Sopenharmony_ci	struct spacc_aead *spacc_alg = to_spacc_aead(alg);
5618c2ecf20Sopenharmony_ci	struct spacc_engine *engine = ctx->generic.engine;
5628c2ecf20Sopenharmony_ci	u32 ctrl, proc_len, assoc_len;
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	req->result = -EINPROGRESS;
5658c2ecf20Sopenharmony_ci	req->ctx_id = spacc_load_ctx(&ctx->generic, ctx->cipher_key,
5668c2ecf20Sopenharmony_ci		ctx->cipher_key_len, aead_req->iv, crypto_aead_ivsize(aead),
5678c2ecf20Sopenharmony_ci		ctx->hash_ctx, ctx->hash_key_len);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	/* Set the source and destination DDT pointers. */
5708c2ecf20Sopenharmony_ci	writel(req->src_addr, engine->regs + SPA_SRC_PTR_REG_OFFSET);
5718c2ecf20Sopenharmony_ci	writel(req->dst_addr, engine->regs + SPA_DST_PTR_REG_OFFSET);
5728c2ecf20Sopenharmony_ci	writel(0, engine->regs + SPA_OFFSET_REG_OFFSET);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	assoc_len = aead_req->assoclen;
5758c2ecf20Sopenharmony_ci	proc_len = aead_req->cryptlen + assoc_len;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	/*
5788c2ecf20Sopenharmony_ci	 * If we are decrypting, we need to take the length of the ICV out of
5798c2ecf20Sopenharmony_ci	 * the processing length.
5808c2ecf20Sopenharmony_ci	 */
5818c2ecf20Sopenharmony_ci	if (!req->is_encrypt)
5828c2ecf20Sopenharmony_ci		proc_len -= authsize;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	writel(proc_len, engine->regs + SPA_PROC_LEN_REG_OFFSET);
5858c2ecf20Sopenharmony_ci	writel(assoc_len, engine->regs + SPA_AAD_LEN_REG_OFFSET);
5868c2ecf20Sopenharmony_ci	writel(authsize, engine->regs + SPA_ICV_LEN_REG_OFFSET);
5878c2ecf20Sopenharmony_ci	writel(0, engine->regs + SPA_ICV_OFFSET_REG_OFFSET);
5888c2ecf20Sopenharmony_ci	writel(0, engine->regs + SPA_AUX_INFO_REG_OFFSET);
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	ctrl = spacc_alg->ctrl_default | (req->ctx_id << SPA_CTRL_CTX_IDX) |
5918c2ecf20Sopenharmony_ci		(1 << SPA_CTRL_ICV_APPEND);
5928c2ecf20Sopenharmony_ci	if (req->is_encrypt)
5938c2ecf20Sopenharmony_ci		ctrl |= (1 << SPA_CTRL_ENCRYPT_IDX) | (1 << SPA_CTRL_AAD_COPY);
5948c2ecf20Sopenharmony_ci	else
5958c2ecf20Sopenharmony_ci		ctrl |= (1 << SPA_CTRL_KEY_EXP);
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	writel(ctrl, engine->regs + SPA_CTRL_REG_OFFSET);
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	return -EINPROGRESS;
6028c2ecf20Sopenharmony_ci}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_cistatic int spacc_req_submit(struct spacc_req *req);
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_cistatic void spacc_push(struct spacc_engine *engine)
6078c2ecf20Sopenharmony_ci{
6088c2ecf20Sopenharmony_ci	struct spacc_req *req;
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	while (!list_empty(&engine->pending) &&
6118c2ecf20Sopenharmony_ci	       engine->in_flight + 1 <= engine->fifo_sz) {
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci		++engine->in_flight;
6148c2ecf20Sopenharmony_ci		req = list_first_entry(&engine->pending, struct spacc_req,
6158c2ecf20Sopenharmony_ci				       list);
6168c2ecf20Sopenharmony_ci		list_move_tail(&req->list, &engine->in_progress);
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci		req->result = spacc_req_submit(req);
6198c2ecf20Sopenharmony_ci	}
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci/*
6238c2ecf20Sopenharmony_ci * Setup an AEAD request for processing. This will configure the engine, load
6248c2ecf20Sopenharmony_ci * the context and then start the packet processing.
6258c2ecf20Sopenharmony_ci */
6268c2ecf20Sopenharmony_cistatic int spacc_aead_setup(struct aead_request *req,
6278c2ecf20Sopenharmony_ci			    unsigned alg_type, bool is_encrypt)
6288c2ecf20Sopenharmony_ci{
6298c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
6308c2ecf20Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(aead);
6318c2ecf20Sopenharmony_ci	struct spacc_engine *engine = to_spacc_aead(alg)->engine;
6328c2ecf20Sopenharmony_ci	struct spacc_req *dev_req = aead_request_ctx(req);
6338c2ecf20Sopenharmony_ci	int err;
6348c2ecf20Sopenharmony_ci	unsigned long flags;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	dev_req->req		= &req->base;
6378c2ecf20Sopenharmony_ci	dev_req->is_encrypt	= is_encrypt;
6388c2ecf20Sopenharmony_ci	dev_req->result		= -EBUSY;
6398c2ecf20Sopenharmony_ci	dev_req->engine		= engine;
6408c2ecf20Sopenharmony_ci	dev_req->complete	= spacc_aead_complete;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	if (unlikely(spacc_aead_need_fallback(req) ||
6438c2ecf20Sopenharmony_ci		     ((err = spacc_aead_make_ddts(req)) == -E2BIG)))
6448c2ecf20Sopenharmony_ci		return spacc_aead_do_fallback(req, alg_type, is_encrypt);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	if (err)
6478c2ecf20Sopenharmony_ci		goto out;
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	err = -EINPROGRESS;
6508c2ecf20Sopenharmony_ci	spin_lock_irqsave(&engine->hw_lock, flags);
6518c2ecf20Sopenharmony_ci	if (unlikely(spacc_fifo_cmd_full(engine)) ||
6528c2ecf20Sopenharmony_ci	    engine->in_flight + 1 > engine->fifo_sz) {
6538c2ecf20Sopenharmony_ci		if (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
6548c2ecf20Sopenharmony_ci			err = -EBUSY;
6558c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&engine->hw_lock, flags);
6568c2ecf20Sopenharmony_ci			goto out_free_ddts;
6578c2ecf20Sopenharmony_ci		}
6588c2ecf20Sopenharmony_ci		list_add_tail(&dev_req->list, &engine->pending);
6598c2ecf20Sopenharmony_ci	} else {
6608c2ecf20Sopenharmony_ci		list_add_tail(&dev_req->list, &engine->pending);
6618c2ecf20Sopenharmony_ci		spacc_push(engine);
6628c2ecf20Sopenharmony_ci	}
6638c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&engine->hw_lock, flags);
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	goto out;
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ciout_free_ddts:
6688c2ecf20Sopenharmony_ci	spacc_aead_free_ddts(dev_req);
6698c2ecf20Sopenharmony_ciout:
6708c2ecf20Sopenharmony_ci	return err;
6718c2ecf20Sopenharmony_ci}
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_cistatic int spacc_aead_encrypt(struct aead_request *req)
6748c2ecf20Sopenharmony_ci{
6758c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
6768c2ecf20Sopenharmony_ci	struct spacc_aead *alg = to_spacc_aead(crypto_aead_alg(aead));
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	return spacc_aead_setup(req, alg->type, 1);
6798c2ecf20Sopenharmony_ci}
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_cistatic int spacc_aead_decrypt(struct aead_request *req)
6828c2ecf20Sopenharmony_ci{
6838c2ecf20Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
6848c2ecf20Sopenharmony_ci	struct spacc_aead  *alg = to_spacc_aead(crypto_aead_alg(aead));
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	return spacc_aead_setup(req, alg->type, 0);
6878c2ecf20Sopenharmony_ci}
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci/*
6908c2ecf20Sopenharmony_ci * Initialise a new AEAD context. This is responsible for allocating the
6918c2ecf20Sopenharmony_ci * fallback cipher and initialising the context.
6928c2ecf20Sopenharmony_ci */
6938c2ecf20Sopenharmony_cistatic int spacc_aead_cra_init(struct crypto_aead *tfm)
6948c2ecf20Sopenharmony_ci{
6958c2ecf20Sopenharmony_ci	struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
6968c2ecf20Sopenharmony_ci	struct aead_alg *alg = crypto_aead_alg(tfm);
6978c2ecf20Sopenharmony_ci	struct spacc_aead *spacc_alg = to_spacc_aead(alg);
6988c2ecf20Sopenharmony_ci	struct spacc_engine *engine = spacc_alg->engine;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	ctx->generic.flags = spacc_alg->type;
7018c2ecf20Sopenharmony_ci	ctx->generic.engine = engine;
7028c2ecf20Sopenharmony_ci	ctx->sw_cipher = crypto_alloc_aead(alg->base.cra_name, 0,
7038c2ecf20Sopenharmony_ci					   CRYPTO_ALG_NEED_FALLBACK);
7048c2ecf20Sopenharmony_ci	if (IS_ERR(ctx->sw_cipher))
7058c2ecf20Sopenharmony_ci		return PTR_ERR(ctx->sw_cipher);
7068c2ecf20Sopenharmony_ci	ctx->generic.key_offs = spacc_alg->key_offs;
7078c2ecf20Sopenharmony_ci	ctx->generic.iv_offs = spacc_alg->iv_offs;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	crypto_aead_set_reqsize(
7108c2ecf20Sopenharmony_ci		tfm,
7118c2ecf20Sopenharmony_ci		max(sizeof(struct spacc_req),
7128c2ecf20Sopenharmony_ci		    sizeof(struct aead_request) +
7138c2ecf20Sopenharmony_ci		    crypto_aead_reqsize(ctx->sw_cipher)));
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	return 0;
7168c2ecf20Sopenharmony_ci}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci/*
7198c2ecf20Sopenharmony_ci * Destructor for an AEAD context. This is called when the transform is freed
7208c2ecf20Sopenharmony_ci * and must free the fallback cipher.
7218c2ecf20Sopenharmony_ci */
7228c2ecf20Sopenharmony_cistatic void spacc_aead_cra_exit(struct crypto_aead *tfm)
7238c2ecf20Sopenharmony_ci{
7248c2ecf20Sopenharmony_ci	struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	crypto_free_aead(ctx->sw_cipher);
7278c2ecf20Sopenharmony_ci}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci/*
7308c2ecf20Sopenharmony_ci * Set the DES key for a block cipher transform. This also performs weak key
7318c2ecf20Sopenharmony_ci * checking if the transform has requested it.
7328c2ecf20Sopenharmony_ci */
7338c2ecf20Sopenharmony_cistatic int spacc_des_setkey(struct crypto_skcipher *cipher, const u8 *key,
7348c2ecf20Sopenharmony_ci			    unsigned int len)
7358c2ecf20Sopenharmony_ci{
7368c2ecf20Sopenharmony_ci	struct spacc_ablk_ctx *ctx = crypto_skcipher_ctx(cipher);
7378c2ecf20Sopenharmony_ci	int err;
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	err = verify_skcipher_des_key(cipher, key);
7408c2ecf20Sopenharmony_ci	if (err)
7418c2ecf20Sopenharmony_ci		return err;
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	memcpy(ctx->key, key, len);
7448c2ecf20Sopenharmony_ci	ctx->key_len = len;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	return 0;
7478c2ecf20Sopenharmony_ci}
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci/*
7508c2ecf20Sopenharmony_ci * Set the 3DES key for a block cipher transform. This also performs weak key
7518c2ecf20Sopenharmony_ci * checking if the transform has requested it.
7528c2ecf20Sopenharmony_ci */
7538c2ecf20Sopenharmony_cistatic int spacc_des3_setkey(struct crypto_skcipher *cipher, const u8 *key,
7548c2ecf20Sopenharmony_ci			     unsigned int len)
7558c2ecf20Sopenharmony_ci{
7568c2ecf20Sopenharmony_ci	struct spacc_ablk_ctx *ctx = crypto_skcipher_ctx(cipher);
7578c2ecf20Sopenharmony_ci	int err;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	err = verify_skcipher_des3_key(cipher, key);
7608c2ecf20Sopenharmony_ci	if (err)
7618c2ecf20Sopenharmony_ci		return err;
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	memcpy(ctx->key, key, len);
7648c2ecf20Sopenharmony_ci	ctx->key_len = len;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	return 0;
7678c2ecf20Sopenharmony_ci}
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci/*
7708c2ecf20Sopenharmony_ci * Set the key for an AES block cipher. Some key lengths are not supported in
7718c2ecf20Sopenharmony_ci * hardware so this must also check whether a fallback is needed.
7728c2ecf20Sopenharmony_ci */
7738c2ecf20Sopenharmony_cistatic int spacc_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
7748c2ecf20Sopenharmony_ci			    unsigned int len)
7758c2ecf20Sopenharmony_ci{
7768c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
7778c2ecf20Sopenharmony_ci	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
7788c2ecf20Sopenharmony_ci	int err = 0;
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	if (len > AES_MAX_KEY_SIZE)
7818c2ecf20Sopenharmony_ci		return -EINVAL;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	/*
7848c2ecf20Sopenharmony_ci	 * IPSec engine only supports 128 and 256 bit AES keys. If we get a
7858c2ecf20Sopenharmony_ci	 * request for any other size (192 bits) then we need to do a software
7868c2ecf20Sopenharmony_ci	 * fallback.
7878c2ecf20Sopenharmony_ci	 */
7888c2ecf20Sopenharmony_ci	if (len != AES_KEYSIZE_128 && len != AES_KEYSIZE_256) {
7898c2ecf20Sopenharmony_ci		if (!ctx->sw_cipher)
7908c2ecf20Sopenharmony_ci			return -EINVAL;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci		/*
7938c2ecf20Sopenharmony_ci		 * Set the fallback transform to use the same request flags as
7948c2ecf20Sopenharmony_ci		 * the hardware transform.
7958c2ecf20Sopenharmony_ci		 */
7968c2ecf20Sopenharmony_ci		crypto_skcipher_clear_flags(ctx->sw_cipher,
7978c2ecf20Sopenharmony_ci					    CRYPTO_TFM_REQ_MASK);
7988c2ecf20Sopenharmony_ci		crypto_skcipher_set_flags(ctx->sw_cipher,
7998c2ecf20Sopenharmony_ci					  cipher->base.crt_flags &
8008c2ecf20Sopenharmony_ci					  CRYPTO_TFM_REQ_MASK);
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci		err = crypto_skcipher_setkey(ctx->sw_cipher, key, len);
8038c2ecf20Sopenharmony_ci		if (err)
8048c2ecf20Sopenharmony_ci			goto sw_setkey_failed;
8058c2ecf20Sopenharmony_ci	}
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	memcpy(ctx->key, key, len);
8088c2ecf20Sopenharmony_ci	ctx->key_len = len;
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_cisw_setkey_failed:
8118c2ecf20Sopenharmony_ci	return err;
8128c2ecf20Sopenharmony_ci}
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_cistatic int spacc_kasumi_f8_setkey(struct crypto_skcipher *cipher,
8158c2ecf20Sopenharmony_ci				  const u8 *key, unsigned int len)
8168c2ecf20Sopenharmony_ci{
8178c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
8188c2ecf20Sopenharmony_ci	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
8198c2ecf20Sopenharmony_ci	int err = 0;
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	if (len > AES_MAX_KEY_SIZE) {
8228c2ecf20Sopenharmony_ci		err = -EINVAL;
8238c2ecf20Sopenharmony_ci		goto out;
8248c2ecf20Sopenharmony_ci	}
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	memcpy(ctx->key, key, len);
8278c2ecf20Sopenharmony_ci	ctx->key_len = len;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ciout:
8308c2ecf20Sopenharmony_ci	return err;
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_cistatic int spacc_ablk_need_fallback(struct spacc_req *req)
8348c2ecf20Sopenharmony_ci{
8358c2ecf20Sopenharmony_ci	struct skcipher_request *ablk_req = skcipher_request_cast(req->req);
8368c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(ablk_req);
8378c2ecf20Sopenharmony_ci	struct spacc_alg *spacc_alg = to_spacc_skcipher(crypto_skcipher_alg(tfm));
8388c2ecf20Sopenharmony_ci	struct spacc_ablk_ctx *ctx;
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	ctx = crypto_skcipher_ctx(tfm);
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	return (spacc_alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
8438c2ecf20Sopenharmony_ci			SPA_CTRL_CIPH_ALG_AES &&
8448c2ecf20Sopenharmony_ci			ctx->key_len != AES_KEYSIZE_128 &&
8458c2ecf20Sopenharmony_ci			ctx->key_len != AES_KEYSIZE_256;
8468c2ecf20Sopenharmony_ci}
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_cistatic void spacc_ablk_complete(struct spacc_req *req)
8498c2ecf20Sopenharmony_ci{
8508c2ecf20Sopenharmony_ci	struct skcipher_request *ablk_req = skcipher_request_cast(req->req);
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	if (ablk_req->src != ablk_req->dst) {
8538c2ecf20Sopenharmony_ci		spacc_free_ddt(req, req->src_ddt, req->src_addr, ablk_req->src,
8548c2ecf20Sopenharmony_ci			       ablk_req->cryptlen, DMA_TO_DEVICE);
8558c2ecf20Sopenharmony_ci		spacc_free_ddt(req, req->dst_ddt, req->dst_addr, ablk_req->dst,
8568c2ecf20Sopenharmony_ci			       ablk_req->cryptlen, DMA_FROM_DEVICE);
8578c2ecf20Sopenharmony_ci	} else
8588c2ecf20Sopenharmony_ci		spacc_free_ddt(req, req->dst_ddt, req->dst_addr, ablk_req->dst,
8598c2ecf20Sopenharmony_ci			       ablk_req->cryptlen, DMA_BIDIRECTIONAL);
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	req->req->complete(req->req, req->result);
8628c2ecf20Sopenharmony_ci}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_cistatic int spacc_ablk_submit(struct spacc_req *req)
8658c2ecf20Sopenharmony_ci{
8668c2ecf20Sopenharmony_ci	struct skcipher_request *ablk_req = skcipher_request_cast(req->req);
8678c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(ablk_req);
8688c2ecf20Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
8698c2ecf20Sopenharmony_ci	struct spacc_alg *spacc_alg = to_spacc_skcipher(alg);
8708c2ecf20Sopenharmony_ci	struct spacc_ablk_ctx *ctx = crypto_skcipher_ctx(tfm);
8718c2ecf20Sopenharmony_ci	struct spacc_engine *engine = ctx->generic.engine;
8728c2ecf20Sopenharmony_ci	u32 ctrl;
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci	req->ctx_id = spacc_load_ctx(&ctx->generic, ctx->key,
8758c2ecf20Sopenharmony_ci		ctx->key_len, ablk_req->iv, alg->ivsize,
8768c2ecf20Sopenharmony_ci		NULL, 0);
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	writel(req->src_addr, engine->regs + SPA_SRC_PTR_REG_OFFSET);
8798c2ecf20Sopenharmony_ci	writel(req->dst_addr, engine->regs + SPA_DST_PTR_REG_OFFSET);
8808c2ecf20Sopenharmony_ci	writel(0, engine->regs + SPA_OFFSET_REG_OFFSET);
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	writel(ablk_req->cryptlen, engine->regs + SPA_PROC_LEN_REG_OFFSET);
8838c2ecf20Sopenharmony_ci	writel(0, engine->regs + SPA_ICV_OFFSET_REG_OFFSET);
8848c2ecf20Sopenharmony_ci	writel(0, engine->regs + SPA_AUX_INFO_REG_OFFSET);
8858c2ecf20Sopenharmony_ci	writel(0, engine->regs + SPA_AAD_LEN_REG_OFFSET);
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	ctrl = spacc_alg->ctrl_default | (req->ctx_id << SPA_CTRL_CTX_IDX) |
8888c2ecf20Sopenharmony_ci		(req->is_encrypt ? (1 << SPA_CTRL_ENCRYPT_IDX) :
8898c2ecf20Sopenharmony_ci		 (1 << SPA_CTRL_KEY_EXP));
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci	mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	writel(ctrl, engine->regs + SPA_CTRL_REG_OFFSET);
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	return -EINPROGRESS;
8968c2ecf20Sopenharmony_ci}
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_cistatic int spacc_ablk_do_fallback(struct skcipher_request *req,
8998c2ecf20Sopenharmony_ci				  unsigned alg_type, bool is_encrypt)
9008c2ecf20Sopenharmony_ci{
9018c2ecf20Sopenharmony_ci	struct crypto_tfm *old_tfm =
9028c2ecf20Sopenharmony_ci	    crypto_skcipher_tfm(crypto_skcipher_reqtfm(req));
9038c2ecf20Sopenharmony_ci	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(old_tfm);
9048c2ecf20Sopenharmony_ci	struct spacc_req *dev_req = skcipher_request_ctx(req);
9058c2ecf20Sopenharmony_ci	int err;
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	/*
9088c2ecf20Sopenharmony_ci	 * Change the request to use the software fallback transform, and once
9098c2ecf20Sopenharmony_ci	 * the ciphering has completed, put the old transform back into the
9108c2ecf20Sopenharmony_ci	 * request.
9118c2ecf20Sopenharmony_ci	 */
9128c2ecf20Sopenharmony_ci	skcipher_request_set_tfm(&dev_req->fallback_req, ctx->sw_cipher);
9138c2ecf20Sopenharmony_ci	skcipher_request_set_callback(&dev_req->fallback_req, req->base.flags,
9148c2ecf20Sopenharmony_ci				      req->base.complete, req->base.data);
9158c2ecf20Sopenharmony_ci	skcipher_request_set_crypt(&dev_req->fallback_req, req->src, req->dst,
9168c2ecf20Sopenharmony_ci				   req->cryptlen, req->iv);
9178c2ecf20Sopenharmony_ci	err = is_encrypt ? crypto_skcipher_encrypt(&dev_req->fallback_req) :
9188c2ecf20Sopenharmony_ci			   crypto_skcipher_decrypt(&dev_req->fallback_req);
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	return err;
9218c2ecf20Sopenharmony_ci}
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_cistatic int spacc_ablk_setup(struct skcipher_request *req, unsigned alg_type,
9248c2ecf20Sopenharmony_ci			    bool is_encrypt)
9258c2ecf20Sopenharmony_ci{
9268c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
9278c2ecf20Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
9288c2ecf20Sopenharmony_ci	struct spacc_engine *engine = to_spacc_skcipher(alg)->engine;
9298c2ecf20Sopenharmony_ci	struct spacc_req *dev_req = skcipher_request_ctx(req);
9308c2ecf20Sopenharmony_ci	unsigned long flags;
9318c2ecf20Sopenharmony_ci	int err = -ENOMEM;
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	dev_req->req		= &req->base;
9348c2ecf20Sopenharmony_ci	dev_req->is_encrypt	= is_encrypt;
9358c2ecf20Sopenharmony_ci	dev_req->engine		= engine;
9368c2ecf20Sopenharmony_ci	dev_req->complete	= spacc_ablk_complete;
9378c2ecf20Sopenharmony_ci	dev_req->result		= -EINPROGRESS;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	if (unlikely(spacc_ablk_need_fallback(dev_req)))
9408c2ecf20Sopenharmony_ci		return spacc_ablk_do_fallback(req, alg_type, is_encrypt);
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	/*
9438c2ecf20Sopenharmony_ci	 * Create the DDT's for the engine. If we share the same source and
9448c2ecf20Sopenharmony_ci	 * destination then we can optimize by reusing the DDT's.
9458c2ecf20Sopenharmony_ci	 */
9468c2ecf20Sopenharmony_ci	if (req->src != req->dst) {
9478c2ecf20Sopenharmony_ci		dev_req->src_ddt = spacc_sg_to_ddt(engine, req->src,
9488c2ecf20Sopenharmony_ci			req->cryptlen, DMA_TO_DEVICE, &dev_req->src_addr);
9498c2ecf20Sopenharmony_ci		if (!dev_req->src_ddt)
9508c2ecf20Sopenharmony_ci			goto out;
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci		dev_req->dst_ddt = spacc_sg_to_ddt(engine, req->dst,
9538c2ecf20Sopenharmony_ci			req->cryptlen, DMA_FROM_DEVICE, &dev_req->dst_addr);
9548c2ecf20Sopenharmony_ci		if (!dev_req->dst_ddt)
9558c2ecf20Sopenharmony_ci			goto out_free_src;
9568c2ecf20Sopenharmony_ci	} else {
9578c2ecf20Sopenharmony_ci		dev_req->dst_ddt = spacc_sg_to_ddt(engine, req->dst,
9588c2ecf20Sopenharmony_ci			req->cryptlen, DMA_BIDIRECTIONAL, &dev_req->dst_addr);
9598c2ecf20Sopenharmony_ci		if (!dev_req->dst_ddt)
9608c2ecf20Sopenharmony_ci			goto out;
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci		dev_req->src_ddt = NULL;
9638c2ecf20Sopenharmony_ci		dev_req->src_addr = dev_req->dst_addr;
9648c2ecf20Sopenharmony_ci	}
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	err = -EINPROGRESS;
9678c2ecf20Sopenharmony_ci	spin_lock_irqsave(&engine->hw_lock, flags);
9688c2ecf20Sopenharmony_ci	/*
9698c2ecf20Sopenharmony_ci	 * Check if the engine will accept the operation now. If it won't then
9708c2ecf20Sopenharmony_ci	 * we either stick it on the end of a pending list if we can backlog,
9718c2ecf20Sopenharmony_ci	 * or bailout with an error if not.
9728c2ecf20Sopenharmony_ci	 */
9738c2ecf20Sopenharmony_ci	if (unlikely(spacc_fifo_cmd_full(engine)) ||
9748c2ecf20Sopenharmony_ci	    engine->in_flight + 1 > engine->fifo_sz) {
9758c2ecf20Sopenharmony_ci		if (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
9768c2ecf20Sopenharmony_ci			err = -EBUSY;
9778c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&engine->hw_lock, flags);
9788c2ecf20Sopenharmony_ci			goto out_free_ddts;
9798c2ecf20Sopenharmony_ci		}
9808c2ecf20Sopenharmony_ci		list_add_tail(&dev_req->list, &engine->pending);
9818c2ecf20Sopenharmony_ci	} else {
9828c2ecf20Sopenharmony_ci		list_add_tail(&dev_req->list, &engine->pending);
9838c2ecf20Sopenharmony_ci		spacc_push(engine);
9848c2ecf20Sopenharmony_ci	}
9858c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&engine->hw_lock, flags);
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	goto out;
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ciout_free_ddts:
9908c2ecf20Sopenharmony_ci	spacc_free_ddt(dev_req, dev_req->dst_ddt, dev_req->dst_addr, req->dst,
9918c2ecf20Sopenharmony_ci		       req->cryptlen, req->src == req->dst ?
9928c2ecf20Sopenharmony_ci		       DMA_BIDIRECTIONAL : DMA_FROM_DEVICE);
9938c2ecf20Sopenharmony_ciout_free_src:
9948c2ecf20Sopenharmony_ci	if (req->src != req->dst)
9958c2ecf20Sopenharmony_ci		spacc_free_ddt(dev_req, dev_req->src_ddt, dev_req->src_addr,
9968c2ecf20Sopenharmony_ci			       req->src, req->cryptlen, DMA_TO_DEVICE);
9978c2ecf20Sopenharmony_ciout:
9988c2ecf20Sopenharmony_ci	return err;
9998c2ecf20Sopenharmony_ci}
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_cistatic int spacc_ablk_init_tfm(struct crypto_skcipher *tfm)
10028c2ecf20Sopenharmony_ci{
10038c2ecf20Sopenharmony_ci	struct spacc_ablk_ctx *ctx = crypto_skcipher_ctx(tfm);
10048c2ecf20Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
10058c2ecf20Sopenharmony_ci	struct spacc_alg *spacc_alg = to_spacc_skcipher(alg);
10068c2ecf20Sopenharmony_ci	struct spacc_engine *engine = spacc_alg->engine;
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	ctx->generic.flags = spacc_alg->type;
10098c2ecf20Sopenharmony_ci	ctx->generic.engine = engine;
10108c2ecf20Sopenharmony_ci	if (alg->base.cra_flags & CRYPTO_ALG_NEED_FALLBACK) {
10118c2ecf20Sopenharmony_ci		ctx->sw_cipher = crypto_alloc_skcipher(alg->base.cra_name, 0,
10128c2ecf20Sopenharmony_ci						       CRYPTO_ALG_NEED_FALLBACK);
10138c2ecf20Sopenharmony_ci		if (IS_ERR(ctx->sw_cipher)) {
10148c2ecf20Sopenharmony_ci			dev_warn(engine->dev, "failed to allocate fallback for %s\n",
10158c2ecf20Sopenharmony_ci				 alg->base.cra_name);
10168c2ecf20Sopenharmony_ci			return PTR_ERR(ctx->sw_cipher);
10178c2ecf20Sopenharmony_ci		}
10188c2ecf20Sopenharmony_ci		crypto_skcipher_set_reqsize(tfm, sizeof(struct spacc_req) +
10198c2ecf20Sopenharmony_ci						 crypto_skcipher_reqsize(ctx->sw_cipher));
10208c2ecf20Sopenharmony_ci	} else {
10218c2ecf20Sopenharmony_ci		/* take the size without the fallback skcipher_request at the end */
10228c2ecf20Sopenharmony_ci		crypto_skcipher_set_reqsize(tfm, offsetof(struct spacc_req,
10238c2ecf20Sopenharmony_ci							  fallback_req));
10248c2ecf20Sopenharmony_ci	}
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	ctx->generic.key_offs = spacc_alg->key_offs;
10278c2ecf20Sopenharmony_ci	ctx->generic.iv_offs = spacc_alg->iv_offs;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	return 0;
10308c2ecf20Sopenharmony_ci}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_cistatic void spacc_ablk_exit_tfm(struct crypto_skcipher *tfm)
10338c2ecf20Sopenharmony_ci{
10348c2ecf20Sopenharmony_ci	struct spacc_ablk_ctx *ctx = crypto_skcipher_ctx(tfm);
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci	crypto_free_skcipher(ctx->sw_cipher);
10378c2ecf20Sopenharmony_ci}
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_cistatic int spacc_ablk_encrypt(struct skcipher_request *req)
10408c2ecf20Sopenharmony_ci{
10418c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
10428c2ecf20Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(cipher);
10438c2ecf20Sopenharmony_ci	struct spacc_alg *spacc_alg = to_spacc_skcipher(alg);
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	return spacc_ablk_setup(req, spacc_alg->type, 1);
10468c2ecf20Sopenharmony_ci}
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_cistatic int spacc_ablk_decrypt(struct skcipher_request *req)
10498c2ecf20Sopenharmony_ci{
10508c2ecf20Sopenharmony_ci	struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
10518c2ecf20Sopenharmony_ci	struct skcipher_alg *alg = crypto_skcipher_alg(cipher);
10528c2ecf20Sopenharmony_ci	struct spacc_alg *spacc_alg = to_spacc_skcipher(alg);
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	return spacc_ablk_setup(req, spacc_alg->type, 0);
10558c2ecf20Sopenharmony_ci}
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_cistatic inline int spacc_fifo_stat_empty(struct spacc_engine *engine)
10588c2ecf20Sopenharmony_ci{
10598c2ecf20Sopenharmony_ci	return readl(engine->regs + SPA_FIFO_STAT_REG_OFFSET) &
10608c2ecf20Sopenharmony_ci		SPA_FIFO_STAT_EMPTY;
10618c2ecf20Sopenharmony_ci}
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_cistatic void spacc_process_done(struct spacc_engine *engine)
10648c2ecf20Sopenharmony_ci{
10658c2ecf20Sopenharmony_ci	struct spacc_req *req;
10668c2ecf20Sopenharmony_ci	unsigned long flags;
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci	spin_lock_irqsave(&engine->hw_lock, flags);
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	while (!spacc_fifo_stat_empty(engine)) {
10718c2ecf20Sopenharmony_ci		req = list_first_entry(&engine->in_progress, struct spacc_req,
10728c2ecf20Sopenharmony_ci				       list);
10738c2ecf20Sopenharmony_ci		list_move_tail(&req->list, &engine->completed);
10748c2ecf20Sopenharmony_ci		--engine->in_flight;
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci		/* POP the status register. */
10778c2ecf20Sopenharmony_ci		writel(~0, engine->regs + SPA_STAT_POP_REG_OFFSET);
10788c2ecf20Sopenharmony_ci		req->result = (readl(engine->regs + SPA_STATUS_REG_OFFSET) &
10798c2ecf20Sopenharmony_ci		     SPA_STATUS_RES_CODE_MASK) >> SPA_STATUS_RES_CODE_OFFSET;
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci		/*
10828c2ecf20Sopenharmony_ci		 * Convert the SPAcc error status into the standard POSIX error
10838c2ecf20Sopenharmony_ci		 * codes.
10848c2ecf20Sopenharmony_ci		 */
10858c2ecf20Sopenharmony_ci		if (unlikely(req->result)) {
10868c2ecf20Sopenharmony_ci			switch (req->result) {
10878c2ecf20Sopenharmony_ci			case SPA_STATUS_ICV_FAIL:
10888c2ecf20Sopenharmony_ci				req->result = -EBADMSG;
10898c2ecf20Sopenharmony_ci				break;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci			case SPA_STATUS_MEMORY_ERROR:
10928c2ecf20Sopenharmony_ci				dev_warn(engine->dev,
10938c2ecf20Sopenharmony_ci					 "memory error triggered\n");
10948c2ecf20Sopenharmony_ci				req->result = -EFAULT;
10958c2ecf20Sopenharmony_ci				break;
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci			case SPA_STATUS_BLOCK_ERROR:
10988c2ecf20Sopenharmony_ci				dev_warn(engine->dev,
10998c2ecf20Sopenharmony_ci					 "block error triggered\n");
11008c2ecf20Sopenharmony_ci				req->result = -EIO;
11018c2ecf20Sopenharmony_ci				break;
11028c2ecf20Sopenharmony_ci			}
11038c2ecf20Sopenharmony_ci		}
11048c2ecf20Sopenharmony_ci	}
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci	tasklet_schedule(&engine->complete);
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&engine->hw_lock, flags);
11098c2ecf20Sopenharmony_ci}
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_cistatic irqreturn_t spacc_spacc_irq(int irq, void *dev)
11128c2ecf20Sopenharmony_ci{
11138c2ecf20Sopenharmony_ci	struct spacc_engine *engine = (struct spacc_engine *)dev;
11148c2ecf20Sopenharmony_ci	u32 spacc_irq_stat = readl(engine->regs + SPA_IRQ_STAT_REG_OFFSET);
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	writel(spacc_irq_stat, engine->regs + SPA_IRQ_STAT_REG_OFFSET);
11178c2ecf20Sopenharmony_ci	spacc_process_done(engine);
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
11208c2ecf20Sopenharmony_ci}
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_cistatic void spacc_packet_timeout(struct timer_list *t)
11238c2ecf20Sopenharmony_ci{
11248c2ecf20Sopenharmony_ci	struct spacc_engine *engine = from_timer(engine, t, packet_timeout);
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	spacc_process_done(engine);
11278c2ecf20Sopenharmony_ci}
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_cistatic int spacc_req_submit(struct spacc_req *req)
11308c2ecf20Sopenharmony_ci{
11318c2ecf20Sopenharmony_ci	struct crypto_alg *alg = req->req->tfm->__crt_alg;
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	if (CRYPTO_ALG_TYPE_AEAD == (CRYPTO_ALG_TYPE_MASK & alg->cra_flags))
11348c2ecf20Sopenharmony_ci		return spacc_aead_submit(req);
11358c2ecf20Sopenharmony_ci	else
11368c2ecf20Sopenharmony_ci		return spacc_ablk_submit(req);
11378c2ecf20Sopenharmony_ci}
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_cistatic void spacc_spacc_complete(unsigned long data)
11408c2ecf20Sopenharmony_ci{
11418c2ecf20Sopenharmony_ci	struct spacc_engine *engine = (struct spacc_engine *)data;
11428c2ecf20Sopenharmony_ci	struct spacc_req *req, *tmp;
11438c2ecf20Sopenharmony_ci	unsigned long flags;
11448c2ecf20Sopenharmony_ci	LIST_HEAD(completed);
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	spin_lock_irqsave(&engine->hw_lock, flags);
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	list_splice_init(&engine->completed, &completed);
11498c2ecf20Sopenharmony_ci	spacc_push(engine);
11508c2ecf20Sopenharmony_ci	if (engine->in_flight)
11518c2ecf20Sopenharmony_ci		mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&engine->hw_lock, flags);
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	list_for_each_entry_safe(req, tmp, &completed, list) {
11568c2ecf20Sopenharmony_ci		list_del(&req->list);
11578c2ecf20Sopenharmony_ci		req->complete(req);
11588c2ecf20Sopenharmony_ci	}
11598c2ecf20Sopenharmony_ci}
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
11628c2ecf20Sopenharmony_cistatic int spacc_suspend(struct device *dev)
11638c2ecf20Sopenharmony_ci{
11648c2ecf20Sopenharmony_ci	struct spacc_engine *engine = dev_get_drvdata(dev);
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	/*
11678c2ecf20Sopenharmony_ci	 * We only support standby mode. All we have to do is gate the clock to
11688c2ecf20Sopenharmony_ci	 * the spacc. The hardware will preserve state until we turn it back
11698c2ecf20Sopenharmony_ci	 * on again.
11708c2ecf20Sopenharmony_ci	 */
11718c2ecf20Sopenharmony_ci	clk_disable(engine->clk);
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	return 0;
11748c2ecf20Sopenharmony_ci}
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_cistatic int spacc_resume(struct device *dev)
11778c2ecf20Sopenharmony_ci{
11788c2ecf20Sopenharmony_ci	struct spacc_engine *engine = dev_get_drvdata(dev);
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	return clk_enable(engine->clk);
11818c2ecf20Sopenharmony_ci}
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_cistatic const struct dev_pm_ops spacc_pm_ops = {
11848c2ecf20Sopenharmony_ci	.suspend	= spacc_suspend,
11858c2ecf20Sopenharmony_ci	.resume		= spacc_resume,
11868c2ecf20Sopenharmony_ci};
11878c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_cistatic inline struct spacc_engine *spacc_dev_to_engine(struct device *dev)
11908c2ecf20Sopenharmony_ci{
11918c2ecf20Sopenharmony_ci	return dev ? dev_get_drvdata(dev) : NULL;
11928c2ecf20Sopenharmony_ci}
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_cistatic ssize_t spacc_stat_irq_thresh_show(struct device *dev,
11958c2ecf20Sopenharmony_ci					  struct device_attribute *attr,
11968c2ecf20Sopenharmony_ci					  char *buf)
11978c2ecf20Sopenharmony_ci{
11988c2ecf20Sopenharmony_ci	struct spacc_engine *engine = spacc_dev_to_engine(dev);
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%u\n", engine->stat_irq_thresh);
12018c2ecf20Sopenharmony_ci}
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_cistatic ssize_t spacc_stat_irq_thresh_store(struct device *dev,
12048c2ecf20Sopenharmony_ci					   struct device_attribute *attr,
12058c2ecf20Sopenharmony_ci					   const char *buf, size_t len)
12068c2ecf20Sopenharmony_ci{
12078c2ecf20Sopenharmony_ci	struct spacc_engine *engine = spacc_dev_to_engine(dev);
12088c2ecf20Sopenharmony_ci	unsigned long thresh;
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	if (kstrtoul(buf, 0, &thresh))
12118c2ecf20Sopenharmony_ci		return -EINVAL;
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	thresh = clamp(thresh, 1UL, engine->fifo_sz - 1);
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	engine->stat_irq_thresh = thresh;
12168c2ecf20Sopenharmony_ci	writel(engine->stat_irq_thresh << SPA_IRQ_CTRL_STAT_CNT_OFFSET,
12178c2ecf20Sopenharmony_ci	       engine->regs + SPA_IRQ_CTRL_REG_OFFSET);
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	return len;
12208c2ecf20Sopenharmony_ci}
12218c2ecf20Sopenharmony_cistatic DEVICE_ATTR(stat_irq_thresh, 0644, spacc_stat_irq_thresh_show,
12228c2ecf20Sopenharmony_ci		   spacc_stat_irq_thresh_store);
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_cistatic struct spacc_alg ipsec_engine_algs[] = {
12258c2ecf20Sopenharmony_ci	{
12268c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC,
12278c2ecf20Sopenharmony_ci		.key_offs = 0,
12288c2ecf20Sopenharmony_ci		.iv_offs = AES_MAX_KEY_SIZE,
12298c2ecf20Sopenharmony_ci		.alg = {
12308c2ecf20Sopenharmony_ci			.base.cra_name		= "cbc(aes)",
12318c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "cbc-aes-picoxcell",
12328c2ecf20Sopenharmony_ci			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
12338c2ecf20Sopenharmony_ci			.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
12348c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ASYNC |
12358c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ALLOCATES_MEMORY |
12368c2ecf20Sopenharmony_ci						  CRYPTO_ALG_NEED_FALLBACK,
12378c2ecf20Sopenharmony_ci			.base.cra_blocksize	= AES_BLOCK_SIZE,
12388c2ecf20Sopenharmony_ci			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
12398c2ecf20Sopenharmony_ci			.base.cra_module	= THIS_MODULE,
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci			.setkey			= spacc_aes_setkey,
12428c2ecf20Sopenharmony_ci			.encrypt 		= spacc_ablk_encrypt,
12438c2ecf20Sopenharmony_ci			.decrypt 		= spacc_ablk_decrypt,
12448c2ecf20Sopenharmony_ci			.min_keysize 		= AES_MIN_KEY_SIZE,
12458c2ecf20Sopenharmony_ci			.max_keysize 		= AES_MAX_KEY_SIZE,
12468c2ecf20Sopenharmony_ci			.ivsize			= AES_BLOCK_SIZE,
12478c2ecf20Sopenharmony_ci			.init			= spacc_ablk_init_tfm,
12488c2ecf20Sopenharmony_ci			.exit			= spacc_ablk_exit_tfm,
12498c2ecf20Sopenharmony_ci		},
12508c2ecf20Sopenharmony_ci	},
12518c2ecf20Sopenharmony_ci	{
12528c2ecf20Sopenharmony_ci		.key_offs = 0,
12538c2ecf20Sopenharmony_ci		.iv_offs = AES_MAX_KEY_SIZE,
12548c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_ECB,
12558c2ecf20Sopenharmony_ci		.alg = {
12568c2ecf20Sopenharmony_ci			.base.cra_name		= "ecb(aes)",
12578c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "ecb-aes-picoxcell",
12588c2ecf20Sopenharmony_ci			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
12598c2ecf20Sopenharmony_ci			.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
12608c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ASYNC |
12618c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ALLOCATES_MEMORY |
12628c2ecf20Sopenharmony_ci						  CRYPTO_ALG_NEED_FALLBACK,
12638c2ecf20Sopenharmony_ci			.base.cra_blocksize	= AES_BLOCK_SIZE,
12648c2ecf20Sopenharmony_ci			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
12658c2ecf20Sopenharmony_ci			.base.cra_module	= THIS_MODULE,
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci			.setkey			= spacc_aes_setkey,
12688c2ecf20Sopenharmony_ci			.encrypt 		= spacc_ablk_encrypt,
12698c2ecf20Sopenharmony_ci			.decrypt 		= spacc_ablk_decrypt,
12708c2ecf20Sopenharmony_ci			.min_keysize 		= AES_MIN_KEY_SIZE,
12718c2ecf20Sopenharmony_ci			.max_keysize 		= AES_MAX_KEY_SIZE,
12728c2ecf20Sopenharmony_ci			.init			= spacc_ablk_init_tfm,
12738c2ecf20Sopenharmony_ci			.exit			= spacc_ablk_exit_tfm,
12748c2ecf20Sopenharmony_ci		},
12758c2ecf20Sopenharmony_ci	},
12768c2ecf20Sopenharmony_ci	{
12778c2ecf20Sopenharmony_ci		.key_offs = DES_BLOCK_SIZE,
12788c2ecf20Sopenharmony_ci		.iv_offs = 0,
12798c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC,
12808c2ecf20Sopenharmony_ci		.alg = {
12818c2ecf20Sopenharmony_ci			.base.cra_name		= "cbc(des)",
12828c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "cbc-des-picoxcell",
12838c2ecf20Sopenharmony_ci			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
12848c2ecf20Sopenharmony_ci			.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
12858c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ASYNC |
12868c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ALLOCATES_MEMORY,
12878c2ecf20Sopenharmony_ci			.base.cra_blocksize	= DES_BLOCK_SIZE,
12888c2ecf20Sopenharmony_ci			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
12898c2ecf20Sopenharmony_ci			.base.cra_module	= THIS_MODULE,
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_ci			.setkey			= spacc_des_setkey,
12928c2ecf20Sopenharmony_ci			.encrypt		= spacc_ablk_encrypt,
12938c2ecf20Sopenharmony_ci			.decrypt		= spacc_ablk_decrypt,
12948c2ecf20Sopenharmony_ci			.min_keysize		= DES_KEY_SIZE,
12958c2ecf20Sopenharmony_ci			.max_keysize		= DES_KEY_SIZE,
12968c2ecf20Sopenharmony_ci			.ivsize			= DES_BLOCK_SIZE,
12978c2ecf20Sopenharmony_ci			.init			= spacc_ablk_init_tfm,
12988c2ecf20Sopenharmony_ci			.exit			= spacc_ablk_exit_tfm,
12998c2ecf20Sopenharmony_ci		},
13008c2ecf20Sopenharmony_ci	},
13018c2ecf20Sopenharmony_ci	{
13028c2ecf20Sopenharmony_ci		.key_offs = DES_BLOCK_SIZE,
13038c2ecf20Sopenharmony_ci		.iv_offs = 0,
13048c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_ECB,
13058c2ecf20Sopenharmony_ci		.alg = {
13068c2ecf20Sopenharmony_ci			.base.cra_name		= "ecb(des)",
13078c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "ecb-des-picoxcell",
13088c2ecf20Sopenharmony_ci			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
13098c2ecf20Sopenharmony_ci			.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
13108c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ASYNC |
13118c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ALLOCATES_MEMORY,
13128c2ecf20Sopenharmony_ci			.base.cra_blocksize	= DES_BLOCK_SIZE,
13138c2ecf20Sopenharmony_ci			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
13148c2ecf20Sopenharmony_ci			.base.cra_module	= THIS_MODULE,
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci			.setkey			= spacc_des_setkey,
13178c2ecf20Sopenharmony_ci			.encrypt		= spacc_ablk_encrypt,
13188c2ecf20Sopenharmony_ci			.decrypt		= spacc_ablk_decrypt,
13198c2ecf20Sopenharmony_ci			.min_keysize		= DES_KEY_SIZE,
13208c2ecf20Sopenharmony_ci			.max_keysize		= DES_KEY_SIZE,
13218c2ecf20Sopenharmony_ci			.init			= spacc_ablk_init_tfm,
13228c2ecf20Sopenharmony_ci			.exit			= spacc_ablk_exit_tfm,
13238c2ecf20Sopenharmony_ci		},
13248c2ecf20Sopenharmony_ci	},
13258c2ecf20Sopenharmony_ci	{
13268c2ecf20Sopenharmony_ci		.key_offs = DES_BLOCK_SIZE,
13278c2ecf20Sopenharmony_ci		.iv_offs = 0,
13288c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC,
13298c2ecf20Sopenharmony_ci		.alg = {
13308c2ecf20Sopenharmony_ci			.base.cra_name		= "cbc(des3_ede)",
13318c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "cbc-des3-ede-picoxcell",
13328c2ecf20Sopenharmony_ci			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
13338c2ecf20Sopenharmony_ci			.base.cra_flags		= CRYPTO_ALG_ASYNC |
13348c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ALLOCATES_MEMORY |
13358c2ecf20Sopenharmony_ci						  CRYPTO_ALG_KERN_DRIVER_ONLY,
13368c2ecf20Sopenharmony_ci			.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
13378c2ecf20Sopenharmony_ci			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
13388c2ecf20Sopenharmony_ci			.base.cra_module	= THIS_MODULE,
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci			.setkey			= spacc_des3_setkey,
13418c2ecf20Sopenharmony_ci			.encrypt		= spacc_ablk_encrypt,
13428c2ecf20Sopenharmony_ci			.decrypt		= spacc_ablk_decrypt,
13438c2ecf20Sopenharmony_ci			.min_keysize		= DES3_EDE_KEY_SIZE,
13448c2ecf20Sopenharmony_ci			.max_keysize		= DES3_EDE_KEY_SIZE,
13458c2ecf20Sopenharmony_ci			.ivsize			= DES3_EDE_BLOCK_SIZE,
13468c2ecf20Sopenharmony_ci			.init			= spacc_ablk_init_tfm,
13478c2ecf20Sopenharmony_ci			.exit			= spacc_ablk_exit_tfm,
13488c2ecf20Sopenharmony_ci		},
13498c2ecf20Sopenharmony_ci	},
13508c2ecf20Sopenharmony_ci	{
13518c2ecf20Sopenharmony_ci		.key_offs = DES_BLOCK_SIZE,
13528c2ecf20Sopenharmony_ci		.iv_offs = 0,
13538c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_ECB,
13548c2ecf20Sopenharmony_ci		.alg = {
13558c2ecf20Sopenharmony_ci			.base.cra_name		= "ecb(des3_ede)",
13568c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "ecb-des3-ede-picoxcell",
13578c2ecf20Sopenharmony_ci			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
13588c2ecf20Sopenharmony_ci			.base.cra_flags		= CRYPTO_ALG_ASYNC |
13598c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ALLOCATES_MEMORY |
13608c2ecf20Sopenharmony_ci						  CRYPTO_ALG_KERN_DRIVER_ONLY,
13618c2ecf20Sopenharmony_ci			.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
13628c2ecf20Sopenharmony_ci			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
13638c2ecf20Sopenharmony_ci			.base.cra_module	= THIS_MODULE,
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci			.setkey			= spacc_des3_setkey,
13668c2ecf20Sopenharmony_ci			.encrypt		= spacc_ablk_encrypt,
13678c2ecf20Sopenharmony_ci			.decrypt		= spacc_ablk_decrypt,
13688c2ecf20Sopenharmony_ci			.min_keysize		= DES3_EDE_KEY_SIZE,
13698c2ecf20Sopenharmony_ci			.max_keysize		= DES3_EDE_KEY_SIZE,
13708c2ecf20Sopenharmony_ci			.init			= spacc_ablk_init_tfm,
13718c2ecf20Sopenharmony_ci			.exit			= spacc_ablk_exit_tfm,
13728c2ecf20Sopenharmony_ci		},
13738c2ecf20Sopenharmony_ci	},
13748c2ecf20Sopenharmony_ci};
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_cistatic struct spacc_aead ipsec_engine_aeads[] = {
13778c2ecf20Sopenharmony_ci	{
13788c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_AES |
13798c2ecf20Sopenharmony_ci				SPA_CTRL_CIPH_MODE_CBC |
13808c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_ALG_SHA |
13818c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_MODE_HMAC,
13828c2ecf20Sopenharmony_ci		.key_offs = 0,
13838c2ecf20Sopenharmony_ci		.iv_offs = AES_MAX_KEY_SIZE,
13848c2ecf20Sopenharmony_ci		.alg = {
13858c2ecf20Sopenharmony_ci			.base = {
13868c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),cbc(aes))",
13878c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha1-"
13888c2ecf20Sopenharmony_ci						   "cbc-aes-picoxcell",
13898c2ecf20Sopenharmony_ci				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
13908c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
13918c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
13928c2ecf20Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK |
13938c2ecf20Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
13948c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
13958c2ecf20Sopenharmony_ci				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
13968c2ecf20Sopenharmony_ci				.cra_module = THIS_MODULE,
13978c2ecf20Sopenharmony_ci			},
13988c2ecf20Sopenharmony_ci			.setkey = spacc_aead_setkey,
13998c2ecf20Sopenharmony_ci			.setauthsize = spacc_aead_setauthsize,
14008c2ecf20Sopenharmony_ci			.encrypt = spacc_aead_encrypt,
14018c2ecf20Sopenharmony_ci			.decrypt = spacc_aead_decrypt,
14028c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
14038c2ecf20Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
14048c2ecf20Sopenharmony_ci			.init = spacc_aead_cra_init,
14058c2ecf20Sopenharmony_ci			.exit = spacc_aead_cra_exit,
14068c2ecf20Sopenharmony_ci		},
14078c2ecf20Sopenharmony_ci	},
14088c2ecf20Sopenharmony_ci	{
14098c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_AES |
14108c2ecf20Sopenharmony_ci				SPA_CTRL_CIPH_MODE_CBC |
14118c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_ALG_SHA256 |
14128c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_MODE_HMAC,
14138c2ecf20Sopenharmony_ci		.key_offs = 0,
14148c2ecf20Sopenharmony_ci		.iv_offs = AES_MAX_KEY_SIZE,
14158c2ecf20Sopenharmony_ci		.alg = {
14168c2ecf20Sopenharmony_ci			.base = {
14178c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),cbc(aes))",
14188c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha256-"
14198c2ecf20Sopenharmony_ci						   "cbc-aes-picoxcell",
14208c2ecf20Sopenharmony_ci				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
14218c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
14228c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
14238c2ecf20Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK |
14248c2ecf20Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
14258c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
14268c2ecf20Sopenharmony_ci				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
14278c2ecf20Sopenharmony_ci				.cra_module = THIS_MODULE,
14288c2ecf20Sopenharmony_ci			},
14298c2ecf20Sopenharmony_ci			.setkey = spacc_aead_setkey,
14308c2ecf20Sopenharmony_ci			.setauthsize = spacc_aead_setauthsize,
14318c2ecf20Sopenharmony_ci			.encrypt = spacc_aead_encrypt,
14328c2ecf20Sopenharmony_ci			.decrypt = spacc_aead_decrypt,
14338c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
14348c2ecf20Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
14358c2ecf20Sopenharmony_ci			.init = spacc_aead_cra_init,
14368c2ecf20Sopenharmony_ci			.exit = spacc_aead_cra_exit,
14378c2ecf20Sopenharmony_ci		},
14388c2ecf20Sopenharmony_ci	},
14398c2ecf20Sopenharmony_ci	{
14408c2ecf20Sopenharmony_ci		.key_offs = 0,
14418c2ecf20Sopenharmony_ci		.iv_offs = AES_MAX_KEY_SIZE,
14428c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_AES |
14438c2ecf20Sopenharmony_ci				SPA_CTRL_CIPH_MODE_CBC |
14448c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_ALG_MD5 |
14458c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_MODE_HMAC,
14468c2ecf20Sopenharmony_ci		.alg = {
14478c2ecf20Sopenharmony_ci			.base = {
14488c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(md5),cbc(aes))",
14498c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-md5-"
14508c2ecf20Sopenharmony_ci						   "cbc-aes-picoxcell",
14518c2ecf20Sopenharmony_ci				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
14528c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
14538c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
14548c2ecf20Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK |
14558c2ecf20Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
14568c2ecf20Sopenharmony_ci				.cra_blocksize = AES_BLOCK_SIZE,
14578c2ecf20Sopenharmony_ci				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
14588c2ecf20Sopenharmony_ci				.cra_module = THIS_MODULE,
14598c2ecf20Sopenharmony_ci			},
14608c2ecf20Sopenharmony_ci			.setkey = spacc_aead_setkey,
14618c2ecf20Sopenharmony_ci			.setauthsize = spacc_aead_setauthsize,
14628c2ecf20Sopenharmony_ci			.encrypt = spacc_aead_encrypt,
14638c2ecf20Sopenharmony_ci			.decrypt = spacc_aead_decrypt,
14648c2ecf20Sopenharmony_ci			.ivsize = AES_BLOCK_SIZE,
14658c2ecf20Sopenharmony_ci			.maxauthsize = MD5_DIGEST_SIZE,
14668c2ecf20Sopenharmony_ci			.init = spacc_aead_cra_init,
14678c2ecf20Sopenharmony_ci			.exit = spacc_aead_cra_exit,
14688c2ecf20Sopenharmony_ci		},
14698c2ecf20Sopenharmony_ci	},
14708c2ecf20Sopenharmony_ci	{
14718c2ecf20Sopenharmony_ci		.key_offs = DES_BLOCK_SIZE,
14728c2ecf20Sopenharmony_ci		.iv_offs = 0,
14738c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_DES |
14748c2ecf20Sopenharmony_ci				SPA_CTRL_CIPH_MODE_CBC |
14758c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_ALG_SHA |
14768c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_MODE_HMAC,
14778c2ecf20Sopenharmony_ci		.alg = {
14788c2ecf20Sopenharmony_ci			.base = {
14798c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
14808c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha1-"
14818c2ecf20Sopenharmony_ci						   "cbc-3des-picoxcell",
14828c2ecf20Sopenharmony_ci				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
14838c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
14848c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
14858c2ecf20Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK |
14868c2ecf20Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
14878c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
14888c2ecf20Sopenharmony_ci				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
14898c2ecf20Sopenharmony_ci				.cra_module = THIS_MODULE,
14908c2ecf20Sopenharmony_ci			},
14918c2ecf20Sopenharmony_ci			.setkey = spacc_aead_setkey,
14928c2ecf20Sopenharmony_ci			.setauthsize = spacc_aead_setauthsize,
14938c2ecf20Sopenharmony_ci			.encrypt = spacc_aead_encrypt,
14948c2ecf20Sopenharmony_ci			.decrypt = spacc_aead_decrypt,
14958c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
14968c2ecf20Sopenharmony_ci			.maxauthsize = SHA1_DIGEST_SIZE,
14978c2ecf20Sopenharmony_ci			.init = spacc_aead_cra_init,
14988c2ecf20Sopenharmony_ci			.exit = spacc_aead_cra_exit,
14998c2ecf20Sopenharmony_ci		},
15008c2ecf20Sopenharmony_ci	},
15018c2ecf20Sopenharmony_ci	{
15028c2ecf20Sopenharmony_ci		.key_offs = DES_BLOCK_SIZE,
15038c2ecf20Sopenharmony_ci		.iv_offs = 0,
15048c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_AES |
15058c2ecf20Sopenharmony_ci				SPA_CTRL_CIPH_MODE_CBC |
15068c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_ALG_SHA256 |
15078c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_MODE_HMAC,
15088c2ecf20Sopenharmony_ci		.alg = {
15098c2ecf20Sopenharmony_ci			.base = {
15108c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(sha256),"
15118c2ecf20Sopenharmony_ci					    "cbc(des3_ede))",
15128c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-sha256-"
15138c2ecf20Sopenharmony_ci						   "cbc-3des-picoxcell",
15148c2ecf20Sopenharmony_ci				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
15158c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
15168c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
15178c2ecf20Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK |
15188c2ecf20Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
15198c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
15208c2ecf20Sopenharmony_ci				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
15218c2ecf20Sopenharmony_ci				.cra_module = THIS_MODULE,
15228c2ecf20Sopenharmony_ci			},
15238c2ecf20Sopenharmony_ci			.setkey = spacc_aead_setkey,
15248c2ecf20Sopenharmony_ci			.setauthsize = spacc_aead_setauthsize,
15258c2ecf20Sopenharmony_ci			.encrypt = spacc_aead_encrypt,
15268c2ecf20Sopenharmony_ci			.decrypt = spacc_aead_decrypt,
15278c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
15288c2ecf20Sopenharmony_ci			.maxauthsize = SHA256_DIGEST_SIZE,
15298c2ecf20Sopenharmony_ci			.init = spacc_aead_cra_init,
15308c2ecf20Sopenharmony_ci			.exit = spacc_aead_cra_exit,
15318c2ecf20Sopenharmony_ci		},
15328c2ecf20Sopenharmony_ci	},
15338c2ecf20Sopenharmony_ci	{
15348c2ecf20Sopenharmony_ci		.key_offs = DES_BLOCK_SIZE,
15358c2ecf20Sopenharmony_ci		.iv_offs = 0,
15368c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_DES |
15378c2ecf20Sopenharmony_ci				SPA_CTRL_CIPH_MODE_CBC |
15388c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_ALG_MD5 |
15398c2ecf20Sopenharmony_ci				SPA_CTRL_HASH_MODE_HMAC,
15408c2ecf20Sopenharmony_ci		.alg = {
15418c2ecf20Sopenharmony_ci			.base = {
15428c2ecf20Sopenharmony_ci				.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
15438c2ecf20Sopenharmony_ci				.cra_driver_name = "authenc-hmac-md5-"
15448c2ecf20Sopenharmony_ci						   "cbc-3des-picoxcell",
15458c2ecf20Sopenharmony_ci				.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
15468c2ecf20Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
15478c2ecf20Sopenharmony_ci					     CRYPTO_ALG_ALLOCATES_MEMORY |
15488c2ecf20Sopenharmony_ci					     CRYPTO_ALG_NEED_FALLBACK |
15498c2ecf20Sopenharmony_ci					     CRYPTO_ALG_KERN_DRIVER_ONLY,
15508c2ecf20Sopenharmony_ci				.cra_blocksize = DES3_EDE_BLOCK_SIZE,
15518c2ecf20Sopenharmony_ci				.cra_ctxsize = sizeof(struct spacc_aead_ctx),
15528c2ecf20Sopenharmony_ci				.cra_module = THIS_MODULE,
15538c2ecf20Sopenharmony_ci			},
15548c2ecf20Sopenharmony_ci			.setkey = spacc_aead_setkey,
15558c2ecf20Sopenharmony_ci			.setauthsize = spacc_aead_setauthsize,
15568c2ecf20Sopenharmony_ci			.encrypt = spacc_aead_encrypt,
15578c2ecf20Sopenharmony_ci			.decrypt = spacc_aead_decrypt,
15588c2ecf20Sopenharmony_ci			.ivsize = DES3_EDE_BLOCK_SIZE,
15598c2ecf20Sopenharmony_ci			.maxauthsize = MD5_DIGEST_SIZE,
15608c2ecf20Sopenharmony_ci			.init = spacc_aead_cra_init,
15618c2ecf20Sopenharmony_ci			.exit = spacc_aead_cra_exit,
15628c2ecf20Sopenharmony_ci		},
15638c2ecf20Sopenharmony_ci	},
15648c2ecf20Sopenharmony_ci};
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_cistatic struct spacc_alg l2_engine_algs[] = {
15678c2ecf20Sopenharmony_ci	{
15688c2ecf20Sopenharmony_ci		.key_offs = 0,
15698c2ecf20Sopenharmony_ci		.iv_offs = SPACC_CRYPTO_KASUMI_F8_KEY_LEN,
15708c2ecf20Sopenharmony_ci		.ctrl_default = SPA_CTRL_CIPH_ALG_KASUMI |
15718c2ecf20Sopenharmony_ci				SPA_CTRL_CIPH_MODE_F8,
15728c2ecf20Sopenharmony_ci		.alg = {
15738c2ecf20Sopenharmony_ci			.base.cra_name		= "f8(kasumi)",
15748c2ecf20Sopenharmony_ci			.base.cra_driver_name	= "f8-kasumi-picoxcell",
15758c2ecf20Sopenharmony_ci			.base.cra_priority	= SPACC_CRYPTO_ALG_PRIORITY,
15768c2ecf20Sopenharmony_ci			.base.cra_flags		= CRYPTO_ALG_ASYNC |
15778c2ecf20Sopenharmony_ci						  CRYPTO_ALG_ALLOCATES_MEMORY |
15788c2ecf20Sopenharmony_ci						  CRYPTO_ALG_KERN_DRIVER_ONLY,
15798c2ecf20Sopenharmony_ci			.base.cra_blocksize	= 8,
15808c2ecf20Sopenharmony_ci			.base.cra_ctxsize	= sizeof(struct spacc_ablk_ctx),
15818c2ecf20Sopenharmony_ci			.base.cra_module	= THIS_MODULE,
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci			.setkey			= spacc_kasumi_f8_setkey,
15848c2ecf20Sopenharmony_ci			.encrypt		= spacc_ablk_encrypt,
15858c2ecf20Sopenharmony_ci			.decrypt		= spacc_ablk_decrypt,
15868c2ecf20Sopenharmony_ci			.min_keysize		= 16,
15878c2ecf20Sopenharmony_ci			.max_keysize		= 16,
15888c2ecf20Sopenharmony_ci			.ivsize			= 8,
15898c2ecf20Sopenharmony_ci			.init			= spacc_ablk_init_tfm,
15908c2ecf20Sopenharmony_ci			.exit			= spacc_ablk_exit_tfm,
15918c2ecf20Sopenharmony_ci		},
15928c2ecf20Sopenharmony_ci	},
15938c2ecf20Sopenharmony_ci};
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
15968c2ecf20Sopenharmony_cistatic const struct of_device_id spacc_of_id_table[] = {
15978c2ecf20Sopenharmony_ci	{ .compatible = "picochip,spacc-ipsec" },
15988c2ecf20Sopenharmony_ci	{ .compatible = "picochip,spacc-l2" },
15998c2ecf20Sopenharmony_ci	{}
16008c2ecf20Sopenharmony_ci};
16018c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, spacc_of_id_table);
16028c2ecf20Sopenharmony_ci#endif /* CONFIG_OF */
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_cistatic void spacc_tasklet_kill(void *data)
16058c2ecf20Sopenharmony_ci{
16068c2ecf20Sopenharmony_ci	tasklet_kill(data);
16078c2ecf20Sopenharmony_ci}
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_cistatic int spacc_probe(struct platform_device *pdev)
16108c2ecf20Sopenharmony_ci{
16118c2ecf20Sopenharmony_ci	int i, err, ret;
16128c2ecf20Sopenharmony_ci	struct resource *irq;
16138c2ecf20Sopenharmony_ci	struct device_node *np = pdev->dev.of_node;
16148c2ecf20Sopenharmony_ci	struct spacc_engine *engine = devm_kzalloc(&pdev->dev, sizeof(*engine),
16158c2ecf20Sopenharmony_ci						   GFP_KERNEL);
16168c2ecf20Sopenharmony_ci	if (!engine)
16178c2ecf20Sopenharmony_ci		return -ENOMEM;
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	if (of_device_is_compatible(np, "picochip,spacc-ipsec")) {
16208c2ecf20Sopenharmony_ci		engine->max_ctxs	= SPACC_CRYPTO_IPSEC_MAX_CTXS;
16218c2ecf20Sopenharmony_ci		engine->cipher_pg_sz	= SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ;
16228c2ecf20Sopenharmony_ci		engine->hash_pg_sz	= SPACC_CRYPTO_IPSEC_HASH_PG_SZ;
16238c2ecf20Sopenharmony_ci		engine->fifo_sz		= SPACC_CRYPTO_IPSEC_FIFO_SZ;
16248c2ecf20Sopenharmony_ci		engine->algs		= ipsec_engine_algs;
16258c2ecf20Sopenharmony_ci		engine->num_algs	= ARRAY_SIZE(ipsec_engine_algs);
16268c2ecf20Sopenharmony_ci		engine->aeads		= ipsec_engine_aeads;
16278c2ecf20Sopenharmony_ci		engine->num_aeads	= ARRAY_SIZE(ipsec_engine_aeads);
16288c2ecf20Sopenharmony_ci	} else if (of_device_is_compatible(np, "picochip,spacc-l2")) {
16298c2ecf20Sopenharmony_ci		engine->max_ctxs	= SPACC_CRYPTO_L2_MAX_CTXS;
16308c2ecf20Sopenharmony_ci		engine->cipher_pg_sz	= SPACC_CRYPTO_L2_CIPHER_PG_SZ;
16318c2ecf20Sopenharmony_ci		engine->hash_pg_sz	= SPACC_CRYPTO_L2_HASH_PG_SZ;
16328c2ecf20Sopenharmony_ci		engine->fifo_sz		= SPACC_CRYPTO_L2_FIFO_SZ;
16338c2ecf20Sopenharmony_ci		engine->algs		= l2_engine_algs;
16348c2ecf20Sopenharmony_ci		engine->num_algs	= ARRAY_SIZE(l2_engine_algs);
16358c2ecf20Sopenharmony_ci	} else {
16368c2ecf20Sopenharmony_ci		return -EINVAL;
16378c2ecf20Sopenharmony_ci	}
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	engine->name = dev_name(&pdev->dev);
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	engine->regs = devm_platform_ioremap_resource(pdev, 0);
16428c2ecf20Sopenharmony_ci	if (IS_ERR(engine->regs))
16438c2ecf20Sopenharmony_ci		return PTR_ERR(engine->regs);
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ci	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
16468c2ecf20Sopenharmony_ci	if (!irq) {
16478c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "no memory/irq resource for engine\n");
16488c2ecf20Sopenharmony_ci		return -ENXIO;
16498c2ecf20Sopenharmony_ci	}
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	tasklet_init(&engine->complete, spacc_spacc_complete,
16528c2ecf20Sopenharmony_ci		     (unsigned long)engine);
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci	ret = devm_add_action(&pdev->dev, spacc_tasklet_kill,
16558c2ecf20Sopenharmony_ci			      &engine->complete);
16568c2ecf20Sopenharmony_ci	if (ret)
16578c2ecf20Sopenharmony_ci		return ret;
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci	if (devm_request_irq(&pdev->dev, irq->start, spacc_spacc_irq, 0,
16608c2ecf20Sopenharmony_ci			     engine->name, engine)) {
16618c2ecf20Sopenharmony_ci		dev_err(engine->dev, "failed to request IRQ\n");
16628c2ecf20Sopenharmony_ci		return -EBUSY;
16638c2ecf20Sopenharmony_ci	}
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	engine->dev		= &pdev->dev;
16668c2ecf20Sopenharmony_ci	engine->cipher_ctx_base = engine->regs + SPA_CIPH_KEY_BASE_REG_OFFSET;
16678c2ecf20Sopenharmony_ci	engine->hash_key_base	= engine->regs + SPA_HASH_KEY_BASE_REG_OFFSET;
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	engine->req_pool = dmam_pool_create(engine->name, engine->dev,
16708c2ecf20Sopenharmony_ci		MAX_DDT_LEN * sizeof(struct spacc_ddt), 8, SZ_64K);
16718c2ecf20Sopenharmony_ci	if (!engine->req_pool)
16728c2ecf20Sopenharmony_ci		return -ENOMEM;
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	spin_lock_init(&engine->hw_lock);
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_ci	engine->clk = clk_get(&pdev->dev, "ref");
16778c2ecf20Sopenharmony_ci	if (IS_ERR(engine->clk)) {
16788c2ecf20Sopenharmony_ci		dev_info(&pdev->dev, "clk unavailable\n");
16798c2ecf20Sopenharmony_ci		return PTR_ERR(engine->clk);
16808c2ecf20Sopenharmony_ci	}
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_ci	if (clk_prepare_enable(engine->clk)) {
16838c2ecf20Sopenharmony_ci		dev_info(&pdev->dev, "unable to prepare/enable clk\n");
16848c2ecf20Sopenharmony_ci		ret = -EIO;
16858c2ecf20Sopenharmony_ci		goto err_clk_put;
16868c2ecf20Sopenharmony_ci	}
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci	/*
16898c2ecf20Sopenharmony_ci	 * Use an IRQ threshold of 50% as a default. This seems to be a
16908c2ecf20Sopenharmony_ci	 * reasonable trade off of latency against throughput but can be
16918c2ecf20Sopenharmony_ci	 * changed at runtime.
16928c2ecf20Sopenharmony_ci	 */
16938c2ecf20Sopenharmony_ci	engine->stat_irq_thresh = (engine->fifo_sz / 2);
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci	ret = device_create_file(&pdev->dev, &dev_attr_stat_irq_thresh);
16968c2ecf20Sopenharmony_ci	if (ret)
16978c2ecf20Sopenharmony_ci		goto err_clk_disable;
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	/*
17008c2ecf20Sopenharmony_ci	 * Configure the interrupts. We only use the STAT_CNT interrupt as we
17018c2ecf20Sopenharmony_ci	 * only submit a new packet for processing when we complete another in
17028c2ecf20Sopenharmony_ci	 * the queue. This minimizes time spent in the interrupt handler.
17038c2ecf20Sopenharmony_ci	 */
17048c2ecf20Sopenharmony_ci	writel(engine->stat_irq_thresh << SPA_IRQ_CTRL_STAT_CNT_OFFSET,
17058c2ecf20Sopenharmony_ci	       engine->regs + SPA_IRQ_CTRL_REG_OFFSET);
17068c2ecf20Sopenharmony_ci	writel(SPA_IRQ_EN_STAT_EN | SPA_IRQ_EN_GLBL_EN,
17078c2ecf20Sopenharmony_ci	       engine->regs + SPA_IRQ_EN_REG_OFFSET);
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_ci	timer_setup(&engine->packet_timeout, spacc_packet_timeout, 0);
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&engine->pending);
17128c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&engine->completed);
17138c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&engine->in_progress);
17148c2ecf20Sopenharmony_ci	engine->in_flight = 0;
17158c2ecf20Sopenharmony_ci
17168c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, engine);
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	ret = -EINVAL;
17198c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&engine->registered_algs);
17208c2ecf20Sopenharmony_ci	for (i = 0; i < engine->num_algs; ++i) {
17218c2ecf20Sopenharmony_ci		engine->algs[i].engine = engine;
17228c2ecf20Sopenharmony_ci		err = crypto_register_skcipher(&engine->algs[i].alg);
17238c2ecf20Sopenharmony_ci		if (!err) {
17248c2ecf20Sopenharmony_ci			list_add_tail(&engine->algs[i].entry,
17258c2ecf20Sopenharmony_ci				      &engine->registered_algs);
17268c2ecf20Sopenharmony_ci			ret = 0;
17278c2ecf20Sopenharmony_ci		}
17288c2ecf20Sopenharmony_ci		if (err)
17298c2ecf20Sopenharmony_ci			dev_err(engine->dev, "failed to register alg \"%s\"\n",
17308c2ecf20Sopenharmony_ci				engine->algs[i].alg.base.cra_name);
17318c2ecf20Sopenharmony_ci		else
17328c2ecf20Sopenharmony_ci			dev_dbg(engine->dev, "registered alg \"%s\"\n",
17338c2ecf20Sopenharmony_ci				engine->algs[i].alg.base.cra_name);
17348c2ecf20Sopenharmony_ci	}
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&engine->registered_aeads);
17378c2ecf20Sopenharmony_ci	for (i = 0; i < engine->num_aeads; ++i) {
17388c2ecf20Sopenharmony_ci		engine->aeads[i].engine = engine;
17398c2ecf20Sopenharmony_ci		err = crypto_register_aead(&engine->aeads[i].alg);
17408c2ecf20Sopenharmony_ci		if (!err) {
17418c2ecf20Sopenharmony_ci			list_add_tail(&engine->aeads[i].entry,
17428c2ecf20Sopenharmony_ci				      &engine->registered_aeads);
17438c2ecf20Sopenharmony_ci			ret = 0;
17448c2ecf20Sopenharmony_ci		}
17458c2ecf20Sopenharmony_ci		if (err)
17468c2ecf20Sopenharmony_ci			dev_err(engine->dev, "failed to register alg \"%s\"\n",
17478c2ecf20Sopenharmony_ci				engine->aeads[i].alg.base.cra_name);
17488c2ecf20Sopenharmony_ci		else
17498c2ecf20Sopenharmony_ci			dev_dbg(engine->dev, "registered alg \"%s\"\n",
17508c2ecf20Sopenharmony_ci				engine->aeads[i].alg.base.cra_name);
17518c2ecf20Sopenharmony_ci	}
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci	if (!ret)
17548c2ecf20Sopenharmony_ci		return 0;
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ci	del_timer_sync(&engine->packet_timeout);
17578c2ecf20Sopenharmony_ci	device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
17588c2ecf20Sopenharmony_cierr_clk_disable:
17598c2ecf20Sopenharmony_ci	clk_disable_unprepare(engine->clk);
17608c2ecf20Sopenharmony_cierr_clk_put:
17618c2ecf20Sopenharmony_ci	clk_put(engine->clk);
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci	return ret;
17648c2ecf20Sopenharmony_ci}
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_cistatic int spacc_remove(struct platform_device *pdev)
17678c2ecf20Sopenharmony_ci{
17688c2ecf20Sopenharmony_ci	struct spacc_aead *aead, *an;
17698c2ecf20Sopenharmony_ci	struct spacc_alg *alg, *next;
17708c2ecf20Sopenharmony_ci	struct spacc_engine *engine = platform_get_drvdata(pdev);
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_ci	del_timer_sync(&engine->packet_timeout);
17738c2ecf20Sopenharmony_ci	device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	list_for_each_entry_safe(aead, an, &engine->registered_aeads, entry) {
17768c2ecf20Sopenharmony_ci		list_del(&aead->entry);
17778c2ecf20Sopenharmony_ci		crypto_unregister_aead(&aead->alg);
17788c2ecf20Sopenharmony_ci	}
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	list_for_each_entry_safe(alg, next, &engine->registered_algs, entry) {
17818c2ecf20Sopenharmony_ci		list_del(&alg->entry);
17828c2ecf20Sopenharmony_ci		crypto_unregister_skcipher(&alg->alg);
17838c2ecf20Sopenharmony_ci	}
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci	clk_disable_unprepare(engine->clk);
17868c2ecf20Sopenharmony_ci	clk_put(engine->clk);
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	return 0;
17898c2ecf20Sopenharmony_ci}
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_cistatic struct platform_driver spacc_driver = {
17928c2ecf20Sopenharmony_ci	.probe		= spacc_probe,
17938c2ecf20Sopenharmony_ci	.remove		= spacc_remove,
17948c2ecf20Sopenharmony_ci	.driver		= {
17958c2ecf20Sopenharmony_ci		.name	= "picochip,spacc",
17968c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
17978c2ecf20Sopenharmony_ci		.pm	= &spacc_pm_ops,
17988c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */
17998c2ecf20Sopenharmony_ci		.of_match_table	= of_match_ptr(spacc_of_id_table),
18008c2ecf20Sopenharmony_ci	},
18018c2ecf20Sopenharmony_ci};
18028c2ecf20Sopenharmony_ci
18038c2ecf20Sopenharmony_cimodule_platform_driver(spacc_driver);
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
18068c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jamie Iles");
1807