162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * caam descriptor construction helper functions
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2008-2012 Freescale Semiconductor, Inc.
662306a36Sopenharmony_ci * Copyright 2019 NXP
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifndef DESC_CONSTR_H
1062306a36Sopenharmony_ci#define DESC_CONSTR_H
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "desc.h"
1362306a36Sopenharmony_ci#include "regs.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define IMMEDIATE (1 << 23)
1662306a36Sopenharmony_ci#define CAAM_CMD_SZ sizeof(u32)
1762306a36Sopenharmony_ci#define CAAM_PTR_SZ caam_ptr_sz
1862306a36Sopenharmony_ci#define CAAM_PTR_SZ_MAX sizeof(dma_addr_t)
1962306a36Sopenharmony_ci#define CAAM_PTR_SZ_MIN sizeof(u32)
2062306a36Sopenharmony_ci#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
2162306a36Sopenharmony_ci#define __DESC_JOB_IO_LEN(n) (CAAM_CMD_SZ * 5 + (n) * 3)
2262306a36Sopenharmony_ci#define DESC_JOB_IO_LEN __DESC_JOB_IO_LEN(CAAM_PTR_SZ)
2362306a36Sopenharmony_ci#define DESC_JOB_IO_LEN_MAX __DESC_JOB_IO_LEN(CAAM_PTR_SZ_MAX)
2462306a36Sopenharmony_ci#define DESC_JOB_IO_LEN_MIN __DESC_JOB_IO_LEN(CAAM_PTR_SZ_MIN)
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/*
2762306a36Sopenharmony_ci * The CAAM QI hardware constructs a job descriptor which points
2862306a36Sopenharmony_ci * to shared descriptor (as pointed by context_a of FQ to CAAM).
2962306a36Sopenharmony_ci * When the job descriptor is executed by deco, the whole job
3062306a36Sopenharmony_ci * descriptor together with shared descriptor gets loaded in
3162306a36Sopenharmony_ci * deco buffer which is 64 words long (each 32-bit).
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci * The job descriptor constructed by QI hardware has layout:
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci *	HEADER		(1 word)
3662306a36Sopenharmony_ci *	Shdesc ptr	(1 or 2 words)
3762306a36Sopenharmony_ci *	SEQ_OUT_PTR	(1 word)
3862306a36Sopenharmony_ci *	Out ptr		(1 or 2 words)
3962306a36Sopenharmony_ci *	Out length	(1 word)
4062306a36Sopenharmony_ci *	SEQ_IN_PTR	(1 word)
4162306a36Sopenharmony_ci *	In ptr		(1 or 2 words)
4262306a36Sopenharmony_ci *	In length	(1 word)
4362306a36Sopenharmony_ci *
4462306a36Sopenharmony_ci * The shdesc ptr is used to fetch shared descriptor contents
4562306a36Sopenharmony_ci * into deco buffer.
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * Apart from shdesc contents, the total number of words that
4862306a36Sopenharmony_ci * get loaded in deco buffer are '8' or '11'. The remaining words
4962306a36Sopenharmony_ci * in deco buffer can be used for storing shared descriptor.
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_ci#define MAX_SDLEN	((CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN_MIN) / CAAM_CMD_SZ)
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#ifdef DEBUG
5462306a36Sopenharmony_ci#define PRINT_POS do { printk(KERN_DEBUG "%02d: %s\n", desc_len(desc),\
5562306a36Sopenharmony_ci			      &__func__[sizeof("append")]); } while (0)
5662306a36Sopenharmony_ci#else
5762306a36Sopenharmony_ci#define PRINT_POS
5862306a36Sopenharmony_ci#endif
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define SET_OK_NO_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
6162306a36Sopenharmony_ci			       LDST_SRCDST_WORD_DECOCTRL | \
6262306a36Sopenharmony_ci			       (LDOFF_CHG_SHARE_OK_NO_PROP << \
6362306a36Sopenharmony_ci				LDST_OFFSET_SHIFT))
6462306a36Sopenharmony_ci#define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
6562306a36Sopenharmony_ci				LDST_SRCDST_WORD_DECOCTRL | \
6662306a36Sopenharmony_ci				(LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
6762306a36Sopenharmony_ci#define ENABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
6862306a36Sopenharmony_ci			       LDST_SRCDST_WORD_DECOCTRL | \
6962306a36Sopenharmony_ci			       (LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ciextern bool caam_little_end;
7262306a36Sopenharmony_ciextern size_t caam_ptr_sz;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/*
7562306a36Sopenharmony_ci * HW fetches 4 S/G table entries at a time, irrespective of how many entries
7662306a36Sopenharmony_ci * are in the table. It's SW's responsibility to make sure these accesses
7762306a36Sopenharmony_ci * do not have side effects.
7862306a36Sopenharmony_ci */
7962306a36Sopenharmony_cistatic inline int pad_sg_nents(int sg_nents)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	return ALIGN(sg_nents, 4);
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic inline int desc_len(u32 * const desc)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	return caam32_to_cpu(*desc) & HDR_DESCLEN_MASK;
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic inline int desc_bytes(void * const desc)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	return desc_len(desc) * CAAM_CMD_SZ;
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic inline u32 *desc_end(u32 * const desc)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	return desc + desc_len(desc);
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic inline void *sh_desc_pdb(u32 * const desc)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	return desc + 1;
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic inline void init_desc(u32 * const desc, u32 options)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	*desc = cpu_to_caam32((options | HDR_ONE) + 1);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic inline void init_sh_desc(u32 * const desc, u32 options)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	PRINT_POS;
11262306a36Sopenharmony_ci	init_desc(desc, CMD_SHARED_DESC_HDR | options);
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic inline void init_sh_desc_pdb(u32 * const desc, u32 options,
11662306a36Sopenharmony_ci				    size_t pdb_bytes)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	init_sh_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT) + pdb_len) |
12162306a36Sopenharmony_ci		     options);
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistatic inline void init_job_desc(u32 * const desc, u32 options)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	init_desc(desc, CMD_DESC_HDR | options);
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic inline void init_job_desc_pdb(u32 * const desc, u32 options,
13062306a36Sopenharmony_ci				     size_t pdb_bytes)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	init_job_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT)) | options);
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic inline void append_ptr(u32 * const desc, dma_addr_t ptr)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	if (caam_ptr_sz == sizeof(dma_addr_t)) {
14062306a36Sopenharmony_ci		dma_addr_t *offset = (dma_addr_t *)desc_end(desc);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci		*offset = cpu_to_caam_dma(ptr);
14362306a36Sopenharmony_ci	} else {
14462306a36Sopenharmony_ci		u32 *offset = (u32 *)desc_end(desc);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci		*offset = cpu_to_caam_dma(ptr);
14762306a36Sopenharmony_ci	}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) +
15062306a36Sopenharmony_ci				CAAM_PTR_SZ / CAAM_CMD_SZ);
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic inline void init_job_desc_shared(u32 * const desc, dma_addr_t ptr,
15462306a36Sopenharmony_ci					int len, u32 options)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	PRINT_POS;
15762306a36Sopenharmony_ci	init_job_desc(desc, HDR_SHARED | options |
15862306a36Sopenharmony_ci		      (len << HDR_START_IDX_SHIFT));
15962306a36Sopenharmony_ci	append_ptr(desc, ptr);
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic inline void append_data(u32 * const desc, const void *data, int len)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	u32 *offset = desc_end(desc);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	/* Avoid gcc warning: memcpy with data == NULL */
16762306a36Sopenharmony_ci	if (!IS_ENABLED(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG) || data)
16862306a36Sopenharmony_ci		memcpy(offset, data, len);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) +
17162306a36Sopenharmony_ci				(len + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ);
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic inline void append_cmd(u32 * const desc, u32 command)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	u32 *cmd = desc_end(desc);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	*cmd = cpu_to_caam32(command);
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 1);
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci#define append_u32 append_cmd
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic inline void append_u64(u32 * const desc, u64 data)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	u32 *offset = desc_end(desc);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	/* Only 32-bit alignment is guaranteed in descriptor buffer */
19062306a36Sopenharmony_ci	if (caam_little_end) {
19162306a36Sopenharmony_ci		*offset = cpu_to_caam32(lower_32_bits(data));
19262306a36Sopenharmony_ci		*(++offset) = cpu_to_caam32(upper_32_bits(data));
19362306a36Sopenharmony_ci	} else {
19462306a36Sopenharmony_ci		*offset = cpu_to_caam32(upper_32_bits(data));
19562306a36Sopenharmony_ci		*(++offset) = cpu_to_caam32(lower_32_bits(data));
19662306a36Sopenharmony_ci	}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + 2);
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci/* Write command without affecting header, and return pointer to next word */
20262306a36Sopenharmony_cistatic inline u32 *write_cmd(u32 * const desc, u32 command)
20362306a36Sopenharmony_ci{
20462306a36Sopenharmony_ci	*desc = cpu_to_caam32(command);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	return desc + 1;
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic inline void append_cmd_ptr(u32 * const desc, dma_addr_t ptr, int len,
21062306a36Sopenharmony_ci				  u32 command)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	append_cmd(desc, command | len);
21362306a36Sopenharmony_ci	append_ptr(desc, ptr);
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci/* Write length after pointer, rather than inside command */
21762306a36Sopenharmony_cistatic inline void append_cmd_ptr_extlen(u32 * const desc, dma_addr_t ptr,
21862306a36Sopenharmony_ci					 unsigned int len, u32 command)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	append_cmd(desc, command);
22162306a36Sopenharmony_ci	if (!(command & (SQIN_RTO | SQIN_PRE)))
22262306a36Sopenharmony_ci		append_ptr(desc, ptr);
22362306a36Sopenharmony_ci	append_cmd(desc, len);
22462306a36Sopenharmony_ci}
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistatic inline void append_cmd_data(u32 * const desc, const void *data, int len,
22762306a36Sopenharmony_ci				   u32 command)
22862306a36Sopenharmony_ci{
22962306a36Sopenharmony_ci	append_cmd(desc, command | IMMEDIATE | len);
23062306a36Sopenharmony_ci	append_data(desc, data, len);
23162306a36Sopenharmony_ci}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci#define APPEND_CMD_RET(cmd, op) \
23462306a36Sopenharmony_cistatic inline u32 *append_##cmd(u32 * const desc, u32 options) \
23562306a36Sopenharmony_ci{ \
23662306a36Sopenharmony_ci	u32 *cmd = desc_end(desc); \
23762306a36Sopenharmony_ci	PRINT_POS; \
23862306a36Sopenharmony_ci	append_cmd(desc, CMD_##op | options); \
23962306a36Sopenharmony_ci	return cmd; \
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ciAPPEND_CMD_RET(jump, JUMP)
24262306a36Sopenharmony_ciAPPEND_CMD_RET(move, MOVE)
24362306a36Sopenharmony_ciAPPEND_CMD_RET(move_len, MOVE_LEN)
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_cistatic inline void set_jump_tgt_here(u32 * const desc, u32 *jump_cmd)
24662306a36Sopenharmony_ci{
24762306a36Sopenharmony_ci	*jump_cmd = cpu_to_caam32(caam32_to_cpu(*jump_cmd) |
24862306a36Sopenharmony_ci				  (desc_len(desc) - (jump_cmd - desc)));
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic inline void set_move_tgt_here(u32 * const desc, u32 *move_cmd)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	u32 val = caam32_to_cpu(*move_cmd);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	val &= ~MOVE_OFFSET_MASK;
25662306a36Sopenharmony_ci	val |= (desc_len(desc) << (MOVE_OFFSET_SHIFT + 2)) & MOVE_OFFSET_MASK;
25762306a36Sopenharmony_ci	*move_cmd = cpu_to_caam32(val);
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci#define APPEND_CMD(cmd, op) \
26162306a36Sopenharmony_cistatic inline void append_##cmd(u32 * const desc, u32 options) \
26262306a36Sopenharmony_ci{ \
26362306a36Sopenharmony_ci	PRINT_POS; \
26462306a36Sopenharmony_ci	append_cmd(desc, CMD_##op | options); \
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ciAPPEND_CMD(operation, OPERATION)
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci#define APPEND_CMD_LEN(cmd, op) \
26962306a36Sopenharmony_cistatic inline void append_##cmd(u32 * const desc, unsigned int len, \
27062306a36Sopenharmony_ci				u32 options) \
27162306a36Sopenharmony_ci{ \
27262306a36Sopenharmony_ci	PRINT_POS; \
27362306a36Sopenharmony_ci	append_cmd(desc, CMD_##op | len | options); \
27462306a36Sopenharmony_ci}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ciAPPEND_CMD_LEN(seq_load, SEQ_LOAD)
27762306a36Sopenharmony_ciAPPEND_CMD_LEN(seq_store, SEQ_STORE)
27862306a36Sopenharmony_ciAPPEND_CMD_LEN(seq_fifo_load, SEQ_FIFO_LOAD)
27962306a36Sopenharmony_ciAPPEND_CMD_LEN(seq_fifo_store, SEQ_FIFO_STORE)
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci#define APPEND_CMD_PTR(cmd, op) \
28262306a36Sopenharmony_cistatic inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
28362306a36Sopenharmony_ci				unsigned int len, u32 options) \
28462306a36Sopenharmony_ci{ \
28562306a36Sopenharmony_ci	PRINT_POS; \
28662306a36Sopenharmony_ci	append_cmd_ptr(desc, ptr, len, CMD_##op | options); \
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ciAPPEND_CMD_PTR(key, KEY)
28962306a36Sopenharmony_ciAPPEND_CMD_PTR(load, LOAD)
29062306a36Sopenharmony_ciAPPEND_CMD_PTR(fifo_load, FIFO_LOAD)
29162306a36Sopenharmony_ciAPPEND_CMD_PTR(fifo_store, FIFO_STORE)
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_cistatic inline void append_store(u32 * const desc, dma_addr_t ptr,
29462306a36Sopenharmony_ci				unsigned int len, u32 options)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	u32 cmd_src;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	cmd_src = options & LDST_SRCDST_MASK;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	append_cmd(desc, CMD_STORE | options | len);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	/* The following options do not require pointer */
30362306a36Sopenharmony_ci	if (!(cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED ||
30462306a36Sopenharmony_ci	      cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB    ||
30562306a36Sopenharmony_ci	      cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB_WE ||
30662306a36Sopenharmony_ci	      cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED_WE))
30762306a36Sopenharmony_ci		append_ptr(desc, ptr);
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci#define APPEND_SEQ_PTR_INTLEN(cmd, op) \
31162306a36Sopenharmony_cistatic inline void append_seq_##cmd##_ptr_intlen(u32 * const desc, \
31262306a36Sopenharmony_ci						 dma_addr_t ptr, \
31362306a36Sopenharmony_ci						 unsigned int len, \
31462306a36Sopenharmony_ci						 u32 options) \
31562306a36Sopenharmony_ci{ \
31662306a36Sopenharmony_ci	PRINT_POS; \
31762306a36Sopenharmony_ci	if (options & (SQIN_RTO | SQIN_PRE)) \
31862306a36Sopenharmony_ci		append_cmd(desc, CMD_SEQ_##op##_PTR | len | options); \
31962306a36Sopenharmony_ci	else \
32062306a36Sopenharmony_ci		append_cmd_ptr(desc, ptr, len, CMD_SEQ_##op##_PTR | options); \
32162306a36Sopenharmony_ci}
32262306a36Sopenharmony_ciAPPEND_SEQ_PTR_INTLEN(in, IN)
32362306a36Sopenharmony_ciAPPEND_SEQ_PTR_INTLEN(out, OUT)
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci#define APPEND_CMD_PTR_TO_IMM(cmd, op) \
32662306a36Sopenharmony_cistatic inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \
32762306a36Sopenharmony_ci					 unsigned int len, u32 options) \
32862306a36Sopenharmony_ci{ \
32962306a36Sopenharmony_ci	PRINT_POS; \
33062306a36Sopenharmony_ci	append_cmd_data(desc, data, len, CMD_##op | options); \
33162306a36Sopenharmony_ci}
33262306a36Sopenharmony_ciAPPEND_CMD_PTR_TO_IMM(load, LOAD);
33362306a36Sopenharmony_ciAPPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD);
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci#define APPEND_CMD_PTR_EXTLEN(cmd, op) \
33662306a36Sopenharmony_cistatic inline void append_##cmd##_extlen(u32 * const desc, dma_addr_t ptr, \
33762306a36Sopenharmony_ci					 unsigned int len, u32 options) \
33862306a36Sopenharmony_ci{ \
33962306a36Sopenharmony_ci	PRINT_POS; \
34062306a36Sopenharmony_ci	append_cmd_ptr_extlen(desc, ptr, len, CMD_##op | SQIN_EXT | options); \
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ciAPPEND_CMD_PTR_EXTLEN(seq_in_ptr, SEQ_IN_PTR)
34362306a36Sopenharmony_ciAPPEND_CMD_PTR_EXTLEN(seq_out_ptr, SEQ_OUT_PTR)
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci/*
34662306a36Sopenharmony_ci * Determine whether to store length internally or externally depending on
34762306a36Sopenharmony_ci * the size of its type
34862306a36Sopenharmony_ci */
34962306a36Sopenharmony_ci#define APPEND_CMD_PTR_LEN(cmd, op, type) \
35062306a36Sopenharmony_cistatic inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
35162306a36Sopenharmony_ci				type len, u32 options) \
35262306a36Sopenharmony_ci{ \
35362306a36Sopenharmony_ci	PRINT_POS; \
35462306a36Sopenharmony_ci	if (sizeof(type) > sizeof(u16)) \
35562306a36Sopenharmony_ci		append_##cmd##_extlen(desc, ptr, len, options); \
35662306a36Sopenharmony_ci	else \
35762306a36Sopenharmony_ci		append_##cmd##_intlen(desc, ptr, len, options); \
35862306a36Sopenharmony_ci}
35962306a36Sopenharmony_ciAPPEND_CMD_PTR_LEN(seq_in_ptr, SEQ_IN_PTR, u32)
36062306a36Sopenharmony_ciAPPEND_CMD_PTR_LEN(seq_out_ptr, SEQ_OUT_PTR, u32)
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci/*
36362306a36Sopenharmony_ci * 2nd variant for commands whose specified immediate length differs
36462306a36Sopenharmony_ci * from length of immediate data provided, e.g., split keys
36562306a36Sopenharmony_ci */
36662306a36Sopenharmony_ci#define APPEND_CMD_PTR_TO_IMM2(cmd, op) \
36762306a36Sopenharmony_cistatic inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \
36862306a36Sopenharmony_ci					 unsigned int data_len, \
36962306a36Sopenharmony_ci					 unsigned int len, u32 options) \
37062306a36Sopenharmony_ci{ \
37162306a36Sopenharmony_ci	PRINT_POS; \
37262306a36Sopenharmony_ci	append_cmd(desc, CMD_##op | IMMEDIATE | len | options); \
37362306a36Sopenharmony_ci	append_data(desc, data, data_len); \
37462306a36Sopenharmony_ci}
37562306a36Sopenharmony_ciAPPEND_CMD_PTR_TO_IMM2(key, KEY);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci#define APPEND_CMD_RAW_IMM(cmd, op, type) \
37862306a36Sopenharmony_cistatic inline void append_##cmd##_imm_##type(u32 * const desc, type immediate, \
37962306a36Sopenharmony_ci					     u32 options) \
38062306a36Sopenharmony_ci{ \
38162306a36Sopenharmony_ci	PRINT_POS; \
38262306a36Sopenharmony_ci	if (options & LDST_LEN_MASK) \
38362306a36Sopenharmony_ci		append_cmd(desc, CMD_##op | IMMEDIATE | options); \
38462306a36Sopenharmony_ci	else \
38562306a36Sopenharmony_ci		append_cmd(desc, CMD_##op | IMMEDIATE | options | \
38662306a36Sopenharmony_ci			   sizeof(type)); \
38762306a36Sopenharmony_ci	append_cmd(desc, immediate); \
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ciAPPEND_CMD_RAW_IMM(load, LOAD, u32);
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci/*
39262306a36Sopenharmony_ci * ee - endianness
39362306a36Sopenharmony_ci * size - size of immediate type in bytes
39462306a36Sopenharmony_ci */
39562306a36Sopenharmony_ci#define APPEND_CMD_RAW_IMM2(cmd, op, ee, size) \
39662306a36Sopenharmony_cistatic inline void append_##cmd##_imm_##ee##size(u32 *desc, \
39762306a36Sopenharmony_ci						   u##size immediate, \
39862306a36Sopenharmony_ci						   u32 options) \
39962306a36Sopenharmony_ci{ \
40062306a36Sopenharmony_ci	__##ee##size data = cpu_to_##ee##size(immediate); \
40162306a36Sopenharmony_ci	PRINT_POS; \
40262306a36Sopenharmony_ci	append_cmd(desc, CMD_##op | IMMEDIATE | options | sizeof(data)); \
40362306a36Sopenharmony_ci	append_data(desc, &data, sizeof(data)); \
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ciAPPEND_CMD_RAW_IMM2(load, LOAD, be, 32);
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci/*
40962306a36Sopenharmony_ci * Append math command. Only the last part of destination and source need to
41062306a36Sopenharmony_ci * be specified
41162306a36Sopenharmony_ci */
41262306a36Sopenharmony_ci#define APPEND_MATH(op, desc, dest, src_0, src_1, len) \
41362306a36Sopenharmony_ciappend_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \
41462306a36Sopenharmony_ci	MATH_SRC0_##src_0 | MATH_SRC1_##src_1 | (u32)len);
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci#define append_math_add(desc, dest, src0, src1, len) \
41762306a36Sopenharmony_ci	APPEND_MATH(ADD, desc, dest, src0, src1, len)
41862306a36Sopenharmony_ci#define append_math_sub(desc, dest, src0, src1, len) \
41962306a36Sopenharmony_ci	APPEND_MATH(SUB, desc, dest, src0, src1, len)
42062306a36Sopenharmony_ci#define append_math_add_c(desc, dest, src0, src1, len) \
42162306a36Sopenharmony_ci	APPEND_MATH(ADDC, desc, dest, src0, src1, len)
42262306a36Sopenharmony_ci#define append_math_sub_b(desc, dest, src0, src1, len) \
42362306a36Sopenharmony_ci	APPEND_MATH(SUBB, desc, dest, src0, src1, len)
42462306a36Sopenharmony_ci#define append_math_and(desc, dest, src0, src1, len) \
42562306a36Sopenharmony_ci	APPEND_MATH(AND, desc, dest, src0, src1, len)
42662306a36Sopenharmony_ci#define append_math_or(desc, dest, src0, src1, len) \
42762306a36Sopenharmony_ci	APPEND_MATH(OR, desc, dest, src0, src1, len)
42862306a36Sopenharmony_ci#define append_math_xor(desc, dest, src0, src1, len) \
42962306a36Sopenharmony_ci	APPEND_MATH(XOR, desc, dest, src0, src1, len)
43062306a36Sopenharmony_ci#define append_math_lshift(desc, dest, src0, src1, len) \
43162306a36Sopenharmony_ci	APPEND_MATH(LSHIFT, desc, dest, src0, src1, len)
43262306a36Sopenharmony_ci#define append_math_rshift(desc, dest, src0, src1, len) \
43362306a36Sopenharmony_ci	APPEND_MATH(RSHIFT, desc, dest, src0, src1, len)
43462306a36Sopenharmony_ci#define append_math_ldshift(desc, dest, src0, src1, len) \
43562306a36Sopenharmony_ci	APPEND_MATH(SHLD, desc, dest, src0, src1, len)
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci/* Exactly one source is IMM. Data is passed in as u32 value */
43862306a36Sopenharmony_ci#define APPEND_MATH_IMM_u32(op, desc, dest, src_0, src_1, data) \
43962306a36Sopenharmony_cido { \
44062306a36Sopenharmony_ci	APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ); \
44162306a36Sopenharmony_ci	append_cmd(desc, data); \
44262306a36Sopenharmony_ci} while (0)
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci#define append_math_add_imm_u32(desc, dest, src0, src1, data) \
44562306a36Sopenharmony_ci	APPEND_MATH_IMM_u32(ADD, desc, dest, src0, src1, data)
44662306a36Sopenharmony_ci#define append_math_sub_imm_u32(desc, dest, src0, src1, data) \
44762306a36Sopenharmony_ci	APPEND_MATH_IMM_u32(SUB, desc, dest, src0, src1, data)
44862306a36Sopenharmony_ci#define append_math_add_c_imm_u32(desc, dest, src0, src1, data) \
44962306a36Sopenharmony_ci	APPEND_MATH_IMM_u32(ADDC, desc, dest, src0, src1, data)
45062306a36Sopenharmony_ci#define append_math_sub_b_imm_u32(desc, dest, src0, src1, data) \
45162306a36Sopenharmony_ci	APPEND_MATH_IMM_u32(SUBB, desc, dest, src0, src1, data)
45262306a36Sopenharmony_ci#define append_math_and_imm_u32(desc, dest, src0, src1, data) \
45362306a36Sopenharmony_ci	APPEND_MATH_IMM_u32(AND, desc, dest, src0, src1, data)
45462306a36Sopenharmony_ci#define append_math_or_imm_u32(desc, dest, src0, src1, data) \
45562306a36Sopenharmony_ci	APPEND_MATH_IMM_u32(OR, desc, dest, src0, src1, data)
45662306a36Sopenharmony_ci#define append_math_xor_imm_u32(desc, dest, src0, src1, data) \
45762306a36Sopenharmony_ci	APPEND_MATH_IMM_u32(XOR, desc, dest, src0, src1, data)
45862306a36Sopenharmony_ci#define append_math_lshift_imm_u32(desc, dest, src0, src1, data) \
45962306a36Sopenharmony_ci	APPEND_MATH_IMM_u32(LSHIFT, desc, dest, src0, src1, data)
46062306a36Sopenharmony_ci#define append_math_rshift_imm_u32(desc, dest, src0, src1, data) \
46162306a36Sopenharmony_ci	APPEND_MATH_IMM_u32(RSHIFT, desc, dest, src0, src1, data)
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci/* Exactly one source is IMM. Data is passed in as u64 value */
46462306a36Sopenharmony_ci#define APPEND_MATH_IMM_u64(op, desc, dest, src_0, src_1, data) \
46562306a36Sopenharmony_cido { \
46662306a36Sopenharmony_ci	u32 upper = (data >> 16) >> 16; \
46762306a36Sopenharmony_ci	APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ * 2 | \
46862306a36Sopenharmony_ci		    (upper ? 0 : MATH_IFB)); \
46962306a36Sopenharmony_ci	if (upper) \
47062306a36Sopenharmony_ci		append_u64(desc, data); \
47162306a36Sopenharmony_ci	else \
47262306a36Sopenharmony_ci		append_u32(desc, lower_32_bits(data)); \
47362306a36Sopenharmony_ci} while (0)
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci#define append_math_add_imm_u64(desc, dest, src0, src1, data) \
47662306a36Sopenharmony_ci	APPEND_MATH_IMM_u64(ADD, desc, dest, src0, src1, data)
47762306a36Sopenharmony_ci#define append_math_sub_imm_u64(desc, dest, src0, src1, data) \
47862306a36Sopenharmony_ci	APPEND_MATH_IMM_u64(SUB, desc, dest, src0, src1, data)
47962306a36Sopenharmony_ci#define append_math_add_c_imm_u64(desc, dest, src0, src1, data) \
48062306a36Sopenharmony_ci	APPEND_MATH_IMM_u64(ADDC, desc, dest, src0, src1, data)
48162306a36Sopenharmony_ci#define append_math_sub_b_imm_u64(desc, dest, src0, src1, data) \
48262306a36Sopenharmony_ci	APPEND_MATH_IMM_u64(SUBB, desc, dest, src0, src1, data)
48362306a36Sopenharmony_ci#define append_math_and_imm_u64(desc, dest, src0, src1, data) \
48462306a36Sopenharmony_ci	APPEND_MATH_IMM_u64(AND, desc, dest, src0, src1, data)
48562306a36Sopenharmony_ci#define append_math_or_imm_u64(desc, dest, src0, src1, data) \
48662306a36Sopenharmony_ci	APPEND_MATH_IMM_u64(OR, desc, dest, src0, src1, data)
48762306a36Sopenharmony_ci#define append_math_xor_imm_u64(desc, dest, src0, src1, data) \
48862306a36Sopenharmony_ci	APPEND_MATH_IMM_u64(XOR, desc, dest, src0, src1, data)
48962306a36Sopenharmony_ci#define append_math_lshift_imm_u64(desc, dest, src0, src1, data) \
49062306a36Sopenharmony_ci	APPEND_MATH_IMM_u64(LSHIFT, desc, dest, src0, src1, data)
49162306a36Sopenharmony_ci#define append_math_rshift_imm_u64(desc, dest, src0, src1, data) \
49262306a36Sopenharmony_ci	APPEND_MATH_IMM_u64(RSHIFT, desc, dest, src0, src1, data)
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci/**
49562306a36Sopenharmony_ci * struct alginfo - Container for algorithm details
49662306a36Sopenharmony_ci * @algtype: algorithm selector; for valid values, see documentation of the
49762306a36Sopenharmony_ci *           functions where it is used.
49862306a36Sopenharmony_ci * @keylen: length of the provided algorithm key, in bytes
49962306a36Sopenharmony_ci * @keylen_pad: padded length of the provided algorithm key, in bytes
50062306a36Sopenharmony_ci * @key_dma: dma (bus) address where algorithm key resides
50162306a36Sopenharmony_ci * @key_virt: virtual address where algorithm key resides
50262306a36Sopenharmony_ci * @key_inline: true - key can be inlined in the descriptor; false - key is
50362306a36Sopenharmony_ci *              referenced by the descriptor
50462306a36Sopenharmony_ci */
50562306a36Sopenharmony_cistruct alginfo {
50662306a36Sopenharmony_ci	u32 algtype;
50762306a36Sopenharmony_ci	unsigned int keylen;
50862306a36Sopenharmony_ci	unsigned int keylen_pad;
50962306a36Sopenharmony_ci	dma_addr_t key_dma;
51062306a36Sopenharmony_ci	const void *key_virt;
51162306a36Sopenharmony_ci	bool key_inline;
51262306a36Sopenharmony_ci};
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci/**
51562306a36Sopenharmony_ci * desc_inline_query() - Provide indications on which data items can be inlined
51662306a36Sopenharmony_ci *                       and which shall be referenced in a shared descriptor.
51762306a36Sopenharmony_ci * @sd_base_len: Shared descriptor base length - bytes consumed by the commands,
51862306a36Sopenharmony_ci *               excluding the data items to be inlined (or corresponding
51962306a36Sopenharmony_ci *               pointer if an item is not inlined). Each cnstr_* function that
52062306a36Sopenharmony_ci *               generates descriptors should have a define mentioning
52162306a36Sopenharmony_ci *               corresponding length.
52262306a36Sopenharmony_ci * @jd_len: Maximum length of the job descriptor(s) that will be used
52362306a36Sopenharmony_ci *          together with the shared descriptor.
52462306a36Sopenharmony_ci * @data_len: Array of lengths of the data items trying to be inlined
52562306a36Sopenharmony_ci * @inl_mask: 32bit mask with bit x = 1 if data item x can be inlined, 0
52662306a36Sopenharmony_ci *            otherwise.
52762306a36Sopenharmony_ci * @count: Number of data items (size of @data_len array); must be <= 32
52862306a36Sopenharmony_ci *
52962306a36Sopenharmony_ci * Return: 0 if data can be inlined / referenced, negative value if not. If 0,
53062306a36Sopenharmony_ci *         check @inl_mask for details.
53162306a36Sopenharmony_ci */
53262306a36Sopenharmony_cistatic inline int desc_inline_query(unsigned int sd_base_len,
53362306a36Sopenharmony_ci				    unsigned int jd_len, unsigned int *data_len,
53462306a36Sopenharmony_ci				    u32 *inl_mask, unsigned int count)
53562306a36Sopenharmony_ci{
53662306a36Sopenharmony_ci	int rem_bytes = (int)(CAAM_DESC_BYTES_MAX - sd_base_len - jd_len);
53762306a36Sopenharmony_ci	unsigned int i;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	*inl_mask = 0;
54062306a36Sopenharmony_ci	for (i = 0; (i < count) && (rem_bytes > 0); i++) {
54162306a36Sopenharmony_ci		if (rem_bytes - (int)(data_len[i] +
54262306a36Sopenharmony_ci			(count - i - 1) * CAAM_PTR_SZ) >= 0) {
54362306a36Sopenharmony_ci			rem_bytes -= data_len[i];
54462306a36Sopenharmony_ci			*inl_mask |= (1 << i);
54562306a36Sopenharmony_ci		} else {
54662306a36Sopenharmony_ci			rem_bytes -= CAAM_PTR_SZ;
54762306a36Sopenharmony_ci		}
54862306a36Sopenharmony_ci	}
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	return (rem_bytes >= 0) ? 0 : -1;
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci/**
55462306a36Sopenharmony_ci * append_proto_dkp - Derived Key Protocol (DKP): key -> split key
55562306a36Sopenharmony_ci * @desc: pointer to buffer used for descriptor construction
55662306a36Sopenharmony_ci * @adata: pointer to authentication transform definitions.
55762306a36Sopenharmony_ci *         keylen should be the length of initial key, while keylen_pad
55862306a36Sopenharmony_ci *         the length of the derived (split) key.
55962306a36Sopenharmony_ci *         Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, SHA224,
56062306a36Sopenharmony_ci *         SHA256, SHA384, SHA512}.
56162306a36Sopenharmony_ci */
56262306a36Sopenharmony_cistatic inline void append_proto_dkp(u32 * const desc, struct alginfo *adata)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	u32 protid;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	/*
56762306a36Sopenharmony_ci	 * Quick & dirty translation from OP_ALG_ALGSEL_{MD5, SHA*}
56862306a36Sopenharmony_ci	 * to OP_PCLID_DKP_{MD5, SHA*}
56962306a36Sopenharmony_ci	 */
57062306a36Sopenharmony_ci	protid = (adata->algtype & OP_ALG_ALGSEL_SUBMASK) |
57162306a36Sopenharmony_ci		 (0x20 << OP_ALG_ALGSEL_SHIFT);
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	if (adata->key_inline) {
57462306a36Sopenharmony_ci		int words;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci		if (adata->keylen > adata->keylen_pad) {
57762306a36Sopenharmony_ci			append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid |
57862306a36Sopenharmony_ci					 OP_PCL_DKP_SRC_PTR |
57962306a36Sopenharmony_ci					 OP_PCL_DKP_DST_IMM | adata->keylen);
58062306a36Sopenharmony_ci			append_ptr(desc, adata->key_dma);
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci			words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) -
58362306a36Sopenharmony_ci				 CAAM_PTR_SZ) / CAAM_CMD_SZ;
58462306a36Sopenharmony_ci		} else {
58562306a36Sopenharmony_ci			append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid |
58662306a36Sopenharmony_ci					 OP_PCL_DKP_SRC_IMM |
58762306a36Sopenharmony_ci					 OP_PCL_DKP_DST_IMM | adata->keylen);
58862306a36Sopenharmony_ci			append_data(desc, adata->key_virt, adata->keylen);
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci			words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) -
59162306a36Sopenharmony_ci				 ALIGN(adata->keylen, CAAM_CMD_SZ)) /
59262306a36Sopenharmony_ci				CAAM_CMD_SZ;
59362306a36Sopenharmony_ci		}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci		/* Reserve space in descriptor buffer for the derived key */
59662306a36Sopenharmony_ci		if (words)
59762306a36Sopenharmony_ci			(*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + words);
59862306a36Sopenharmony_ci	} else {
59962306a36Sopenharmony_ci		append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid |
60062306a36Sopenharmony_ci				 OP_PCL_DKP_SRC_PTR | OP_PCL_DKP_DST_PTR |
60162306a36Sopenharmony_ci				 adata->keylen);
60262306a36Sopenharmony_ci		append_ptr(desc, adata->key_dma);
60362306a36Sopenharmony_ci	}
60462306a36Sopenharmony_ci}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci#endif /* DESC_CONSTR_H */
607