162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * AMD Cryptographic Coprocessor (CCP) driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2013,2017 Advanced Micro Devices, Inc.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: Tom Lendacky <thomas.lendacky@amd.com>
862306a36Sopenharmony_ci * Author: Gary R Hook <gary.hook@amd.com>
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#ifndef __CCP_DEV_H__
1262306a36Sopenharmony_ci#define __CCP_DEV_H__
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/device.h>
1562306a36Sopenharmony_ci#include <linux/spinlock.h>
1662306a36Sopenharmony_ci#include <linux/mutex.h>
1762306a36Sopenharmony_ci#include <linux/list.h>
1862306a36Sopenharmony_ci#include <linux/wait.h>
1962306a36Sopenharmony_ci#include <linux/dma-direction.h>
2062306a36Sopenharmony_ci#include <linux/dmapool.h>
2162306a36Sopenharmony_ci#include <linux/hw_random.h>
2262306a36Sopenharmony_ci#include <linux/bitops.h>
2362306a36Sopenharmony_ci#include <linux/interrupt.h>
2462306a36Sopenharmony_ci#include <linux/irqreturn.h>
2562306a36Sopenharmony_ci#include <linux/dmaengine.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include "sp-dev.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define MAX_CCP_NAME_LEN		16
3062306a36Sopenharmony_ci#define MAX_DMAPOOL_NAME_LEN		32
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define MAX_HW_QUEUES			5
3362306a36Sopenharmony_ci#define MAX_CMD_QLEN			100
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define TRNG_RETRIES			10
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define CACHE_NONE			0x00
3862306a36Sopenharmony_ci#define CACHE_WB_NO_ALLOC		0xb7
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/****** Register Mappings ******/
4162306a36Sopenharmony_ci#define Q_MASK_REG			0x000
4262306a36Sopenharmony_ci#define TRNG_OUT_REG			0x00c
4362306a36Sopenharmony_ci#define IRQ_MASK_REG			0x040
4462306a36Sopenharmony_ci#define IRQ_STATUS_REG			0x200
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#define DEL_CMD_Q_JOB			0x124
4762306a36Sopenharmony_ci#define DEL_Q_ACTIVE			0x00000200
4862306a36Sopenharmony_ci#define DEL_Q_ID_SHIFT			6
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#define CMD_REQ0			0x180
5162306a36Sopenharmony_ci#define CMD_REQ_INCR			0x04
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define CMD_Q_STATUS_BASE		0x210
5462306a36Sopenharmony_ci#define CMD_Q_INT_STATUS_BASE		0x214
5562306a36Sopenharmony_ci#define CMD_Q_STATUS_INCR		0x20
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define CMD_Q_CACHE_BASE		0x228
5862306a36Sopenharmony_ci#define CMD_Q_CACHE_INC			0x20
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define CMD_Q_ERROR(__qs)		((__qs) & 0x0000003f)
6162306a36Sopenharmony_ci#define CMD_Q_DEPTH(__qs)		(((__qs) >> 12) & 0x0000000f)
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/* ------------------------ CCP Version 5 Specifics ------------------------ */
6462306a36Sopenharmony_ci#define CMD5_QUEUE_MASK_OFFSET		0x00
6562306a36Sopenharmony_ci#define	CMD5_QUEUE_PRIO_OFFSET		0x04
6662306a36Sopenharmony_ci#define CMD5_REQID_CONFIG_OFFSET	0x08
6762306a36Sopenharmony_ci#define	CMD5_CMD_TIMEOUT_OFFSET		0x10
6862306a36Sopenharmony_ci#define LSB_PUBLIC_MASK_LO_OFFSET	0x18
6962306a36Sopenharmony_ci#define LSB_PUBLIC_MASK_HI_OFFSET	0x1C
7062306a36Sopenharmony_ci#define LSB_PRIVATE_MASK_LO_OFFSET	0x20
7162306a36Sopenharmony_ci#define LSB_PRIVATE_MASK_HI_OFFSET	0x24
7262306a36Sopenharmony_ci#define CMD5_PSP_CCP_VERSION		0x100
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci#define CMD5_Q_CONTROL_BASE		0x0000
7562306a36Sopenharmony_ci#define CMD5_Q_TAIL_LO_BASE		0x0004
7662306a36Sopenharmony_ci#define CMD5_Q_HEAD_LO_BASE		0x0008
7762306a36Sopenharmony_ci#define CMD5_Q_INT_ENABLE_BASE		0x000C
7862306a36Sopenharmony_ci#define CMD5_Q_INTERRUPT_STATUS_BASE	0x0010
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#define CMD5_Q_STATUS_BASE		0x0100
8162306a36Sopenharmony_ci#define CMD5_Q_INT_STATUS_BASE		0x0104
8262306a36Sopenharmony_ci#define CMD5_Q_DMA_STATUS_BASE		0x0108
8362306a36Sopenharmony_ci#define CMD5_Q_DMA_READ_STATUS_BASE	0x010C
8462306a36Sopenharmony_ci#define CMD5_Q_DMA_WRITE_STATUS_BASE	0x0110
8562306a36Sopenharmony_ci#define CMD5_Q_ABORT_BASE		0x0114
8662306a36Sopenharmony_ci#define CMD5_Q_AX_CACHE_BASE		0x0118
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci#define	CMD5_CONFIG_0_OFFSET		0x6000
8962306a36Sopenharmony_ci#define	CMD5_TRNG_CTL_OFFSET		0x6008
9062306a36Sopenharmony_ci#define	CMD5_AES_MASK_OFFSET		0x6010
9162306a36Sopenharmony_ci#define	CMD5_CLK_GATE_CTL_OFFSET	0x603C
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci/* Address offset between two virtual queue registers */
9462306a36Sopenharmony_ci#define CMD5_Q_STATUS_INCR		0x1000
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* Bit masks */
9762306a36Sopenharmony_ci#define CMD5_Q_RUN			0x1
9862306a36Sopenharmony_ci#define CMD5_Q_HALT			0x2
9962306a36Sopenharmony_ci#define CMD5_Q_MEM_LOCATION		0x4
10062306a36Sopenharmony_ci#define CMD5_Q_SIZE			0x1F
10162306a36Sopenharmony_ci#define CMD5_Q_SHIFT			3
10262306a36Sopenharmony_ci#define COMMANDS_PER_QUEUE		16
10362306a36Sopenharmony_ci#define QUEUE_SIZE_VAL			((ffs(COMMANDS_PER_QUEUE) - 2) & \
10462306a36Sopenharmony_ci					  CMD5_Q_SIZE)
10562306a36Sopenharmony_ci#define Q_PTR_MASK			(2 << (QUEUE_SIZE_VAL + 5) - 1)
10662306a36Sopenharmony_ci#define Q_DESC_SIZE			sizeof(struct ccp5_desc)
10762306a36Sopenharmony_ci#define Q_SIZE(n)			(COMMANDS_PER_QUEUE*(n))
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci#define INT_COMPLETION			0x1
11062306a36Sopenharmony_ci#define INT_ERROR			0x2
11162306a36Sopenharmony_ci#define INT_QUEUE_STOPPED		0x4
11262306a36Sopenharmony_ci#define	INT_EMPTY_QUEUE			0x8
11362306a36Sopenharmony_ci#define SUPPORTED_INTERRUPTS		(INT_COMPLETION | INT_ERROR)
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci#define LSB_REGION_WIDTH		5
11662306a36Sopenharmony_ci#define MAX_LSB_CNT			8
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci#define LSB_SIZE			16
11962306a36Sopenharmony_ci#define LSB_ITEM_SIZE			32
12062306a36Sopenharmony_ci#define PLSB_MAP_SIZE			(LSB_SIZE)
12162306a36Sopenharmony_ci#define SLSB_MAP_SIZE			(MAX_LSB_CNT * LSB_SIZE)
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci#define LSB_ENTRY_NUMBER(LSB_ADDR)	(LSB_ADDR / LSB_ITEM_SIZE)
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci/* ------------------------ CCP Version 3 Specifics ------------------------ */
12662306a36Sopenharmony_ci#define REQ0_WAIT_FOR_WRITE		0x00000004
12762306a36Sopenharmony_ci#define REQ0_INT_ON_COMPLETE		0x00000002
12862306a36Sopenharmony_ci#define REQ0_STOP_ON_COMPLETE		0x00000001
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci#define REQ0_CMD_Q_SHIFT		9
13162306a36Sopenharmony_ci#define REQ0_JOBID_SHIFT		3
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci/****** REQ1 Related Values ******/
13462306a36Sopenharmony_ci#define REQ1_PROTECT_SHIFT		27
13562306a36Sopenharmony_ci#define REQ1_ENGINE_SHIFT		23
13662306a36Sopenharmony_ci#define REQ1_KEY_KSB_SHIFT		2
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci#define REQ1_EOM			0x00000002
13962306a36Sopenharmony_ci#define REQ1_INIT			0x00000001
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci/* AES Related Values */
14262306a36Sopenharmony_ci#define REQ1_AES_TYPE_SHIFT		21
14362306a36Sopenharmony_ci#define REQ1_AES_MODE_SHIFT		18
14462306a36Sopenharmony_ci#define REQ1_AES_ACTION_SHIFT		17
14562306a36Sopenharmony_ci#define REQ1_AES_CFB_SIZE_SHIFT		10
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci/* XTS-AES Related Values */
14862306a36Sopenharmony_ci#define REQ1_XTS_AES_SIZE_SHIFT		10
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci/* SHA Related Values */
15162306a36Sopenharmony_ci#define REQ1_SHA_TYPE_SHIFT		21
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci/* RSA Related Values */
15462306a36Sopenharmony_ci#define REQ1_RSA_MOD_SIZE_SHIFT		10
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci/* Pass-Through Related Values */
15762306a36Sopenharmony_ci#define REQ1_PT_BW_SHIFT		12
15862306a36Sopenharmony_ci#define REQ1_PT_BS_SHIFT		10
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci/* ECC Related Values */
16162306a36Sopenharmony_ci#define REQ1_ECC_AFFINE_CONVERT		0x00200000
16262306a36Sopenharmony_ci#define REQ1_ECC_FUNCTION_SHIFT		18
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci/****** REQ4 Related Values ******/
16562306a36Sopenharmony_ci#define REQ4_KSB_SHIFT			18
16662306a36Sopenharmony_ci#define REQ4_MEMTYPE_SHIFT		16
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci/****** REQ6 Related Values ******/
16962306a36Sopenharmony_ci#define REQ6_MEMTYPE_SHIFT		16
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci/****** Key Storage Block ******/
17262306a36Sopenharmony_ci#define KSB_START			77
17362306a36Sopenharmony_ci#define KSB_END				127
17462306a36Sopenharmony_ci#define KSB_COUNT			(KSB_END - KSB_START + 1)
17562306a36Sopenharmony_ci#define CCP_SB_BITS			256
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci#define CCP_JOBID_MASK			0x0000003f
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci/* ------------------------ General CCP Defines ------------------------ */
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci#define	CCP_DMA_DFLT			0x0
18262306a36Sopenharmony_ci#define	CCP_DMA_PRIV			0x1
18362306a36Sopenharmony_ci#define	CCP_DMA_PUB			0x2
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci#define CCP_DMAPOOL_MAX_SIZE		64
18662306a36Sopenharmony_ci#define CCP_DMAPOOL_ALIGN		BIT(5)
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci#define CCP_REVERSE_BUF_SIZE		64
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci#define CCP_AES_KEY_SB_COUNT		1
19162306a36Sopenharmony_ci#define CCP_AES_CTX_SB_COUNT		1
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci#define CCP_XTS_AES_KEY_SB_COUNT	1
19462306a36Sopenharmony_ci#define CCP5_XTS_AES_KEY_SB_COUNT	2
19562306a36Sopenharmony_ci#define CCP_XTS_AES_CTX_SB_COUNT	1
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci#define CCP_DES3_KEY_SB_COUNT		1
19862306a36Sopenharmony_ci#define CCP_DES3_CTX_SB_COUNT		1
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci#define CCP_SHA_SB_COUNT		1
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci#define CCP_RSA_MAX_WIDTH		4096
20362306a36Sopenharmony_ci#define CCP5_RSA_MAX_WIDTH		16384
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci#define CCP_PASSTHRU_BLOCKSIZE		256
20662306a36Sopenharmony_ci#define CCP_PASSTHRU_MASKSIZE		32
20762306a36Sopenharmony_ci#define CCP_PASSTHRU_SB_COUNT		1
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci#define CCP_ECC_MODULUS_BYTES		48      /* 384-bits */
21062306a36Sopenharmony_ci#define CCP_ECC_MAX_OPERANDS		6
21162306a36Sopenharmony_ci#define CCP_ECC_MAX_OUTPUTS		3
21262306a36Sopenharmony_ci#define CCP_ECC_SRC_BUF_SIZE		448
21362306a36Sopenharmony_ci#define CCP_ECC_DST_BUF_SIZE		192
21462306a36Sopenharmony_ci#define CCP_ECC_OPERAND_SIZE		64
21562306a36Sopenharmony_ci#define CCP_ECC_OUTPUT_SIZE		64
21662306a36Sopenharmony_ci#define CCP_ECC_RESULT_OFFSET		60
21762306a36Sopenharmony_ci#define CCP_ECC_RESULT_SUCCESS		0x0001
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci#define CCP_SB_BYTES			32
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistruct ccp_op;
22262306a36Sopenharmony_cistruct ccp_device;
22362306a36Sopenharmony_cistruct ccp_cmd;
22462306a36Sopenharmony_cistruct ccp_fns;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistruct ccp_dma_cmd {
22762306a36Sopenharmony_ci	struct list_head entry;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	struct ccp_cmd ccp_cmd;
23062306a36Sopenharmony_ci};
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistruct ccp_dma_desc {
23362306a36Sopenharmony_ci	struct list_head entry;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	struct ccp_device *ccp;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	struct list_head pending;
23862306a36Sopenharmony_ci	struct list_head active;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	enum dma_status status;
24162306a36Sopenharmony_ci	struct dma_async_tx_descriptor tx_desc;
24262306a36Sopenharmony_ci	size_t len;
24362306a36Sopenharmony_ci};
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_cistruct ccp_dma_chan {
24662306a36Sopenharmony_ci	struct ccp_device *ccp;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	spinlock_t lock;
24962306a36Sopenharmony_ci	struct list_head created;
25062306a36Sopenharmony_ci	struct list_head pending;
25162306a36Sopenharmony_ci	struct list_head active;
25262306a36Sopenharmony_ci	struct list_head complete;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	struct tasklet_struct cleanup_tasklet;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	enum dma_status status;
25762306a36Sopenharmony_ci	struct dma_chan dma_chan;
25862306a36Sopenharmony_ci};
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistruct ccp_cmd_queue {
26162306a36Sopenharmony_ci	struct ccp_device *ccp;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	/* Queue identifier */
26462306a36Sopenharmony_ci	u32 id;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	/* Queue dma pool */
26762306a36Sopenharmony_ci	struct dma_pool *dma_pool;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	/* Queue base address (not neccessarily aligned)*/
27062306a36Sopenharmony_ci	struct ccp5_desc *qbase;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	/* Aligned queue start address (per requirement) */
27362306a36Sopenharmony_ci	struct mutex q_mutex ____cacheline_aligned;
27462306a36Sopenharmony_ci	unsigned int qidx;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	/* Version 5 has different requirements for queue memory */
27762306a36Sopenharmony_ci	unsigned int qsize;
27862306a36Sopenharmony_ci	dma_addr_t qbase_dma;
27962306a36Sopenharmony_ci	dma_addr_t qdma_tail;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	/* Per-queue reserved storage block(s) */
28262306a36Sopenharmony_ci	u32 sb_key;
28362306a36Sopenharmony_ci	u32 sb_ctx;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	/* Bitmap of LSBs that can be accessed by this queue */
28662306a36Sopenharmony_ci	DECLARE_BITMAP(lsbmask, MAX_LSB_CNT);
28762306a36Sopenharmony_ci	/* Private LSB that is assigned to this queue, or -1 if none.
28862306a36Sopenharmony_ci	 * Bitmap for my private LSB, unused otherwise
28962306a36Sopenharmony_ci	 */
29062306a36Sopenharmony_ci	int lsb;
29162306a36Sopenharmony_ci	DECLARE_BITMAP(lsbmap, PLSB_MAP_SIZE);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	/* Queue processing thread */
29462306a36Sopenharmony_ci	struct task_struct *kthread;
29562306a36Sopenharmony_ci	unsigned int active;
29662306a36Sopenharmony_ci	unsigned int suspended;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	/* Number of free command slots available */
29962306a36Sopenharmony_ci	unsigned int free_slots;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	/* Interrupt masks */
30262306a36Sopenharmony_ci	u32 int_ok;
30362306a36Sopenharmony_ci	u32 int_err;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	/* Register addresses for queue */
30662306a36Sopenharmony_ci	void __iomem *reg_control;
30762306a36Sopenharmony_ci	void __iomem *reg_tail_lo;
30862306a36Sopenharmony_ci	void __iomem *reg_head_lo;
30962306a36Sopenharmony_ci	void __iomem *reg_int_enable;
31062306a36Sopenharmony_ci	void __iomem *reg_interrupt_status;
31162306a36Sopenharmony_ci	void __iomem *reg_status;
31262306a36Sopenharmony_ci	void __iomem *reg_int_status;
31362306a36Sopenharmony_ci	void __iomem *reg_dma_status;
31462306a36Sopenharmony_ci	void __iomem *reg_dma_read_status;
31562306a36Sopenharmony_ci	void __iomem *reg_dma_write_status;
31662306a36Sopenharmony_ci	u32 qcontrol; /* Cached control register */
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	/* Status values from job */
31962306a36Sopenharmony_ci	u32 int_status;
32062306a36Sopenharmony_ci	u32 q_status;
32162306a36Sopenharmony_ci	u32 q_int_status;
32262306a36Sopenharmony_ci	u32 cmd_error;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	/* Interrupt wait queue */
32562306a36Sopenharmony_ci	wait_queue_head_t int_queue;
32662306a36Sopenharmony_ci	unsigned int int_rcvd;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	/* Per-queue Statistics */
32962306a36Sopenharmony_ci	unsigned long total_ops;
33062306a36Sopenharmony_ci	unsigned long total_aes_ops;
33162306a36Sopenharmony_ci	unsigned long total_xts_aes_ops;
33262306a36Sopenharmony_ci	unsigned long total_3des_ops;
33362306a36Sopenharmony_ci	unsigned long total_sha_ops;
33462306a36Sopenharmony_ci	unsigned long total_rsa_ops;
33562306a36Sopenharmony_ci	unsigned long total_pt_ops;
33662306a36Sopenharmony_ci	unsigned long total_ecc_ops;
33762306a36Sopenharmony_ci} ____cacheline_aligned;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_cistruct ccp_device {
34062306a36Sopenharmony_ci	struct list_head entry;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	struct ccp_vdata *vdata;
34362306a36Sopenharmony_ci	unsigned int ord;
34462306a36Sopenharmony_ci	char name[MAX_CCP_NAME_LEN];
34562306a36Sopenharmony_ci	char rngname[MAX_CCP_NAME_LEN];
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	struct device *dev;
34862306a36Sopenharmony_ci	struct sp_device *sp;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	/* Bus specific device information
35162306a36Sopenharmony_ci	 */
35262306a36Sopenharmony_ci	void *dev_specific;
35362306a36Sopenharmony_ci	unsigned int qim;
35462306a36Sopenharmony_ci	unsigned int irq;
35562306a36Sopenharmony_ci	bool use_tasklet;
35662306a36Sopenharmony_ci	struct tasklet_struct irq_tasklet;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	/* I/O area used for device communication. The register mapping
35962306a36Sopenharmony_ci	 * starts at an offset into the mapped bar.
36062306a36Sopenharmony_ci	 *   The CMD_REQx registers and the Delete_Cmd_Queue_Job register
36162306a36Sopenharmony_ci	 *   need to be protected while a command queue thread is accessing
36262306a36Sopenharmony_ci	 *   them.
36362306a36Sopenharmony_ci	 */
36462306a36Sopenharmony_ci	struct mutex req_mutex ____cacheline_aligned;
36562306a36Sopenharmony_ci	void __iomem *io_regs;
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	/* Master lists that all cmds are queued on. Because there can be
36862306a36Sopenharmony_ci	 * more than one CCP command queue that can process a cmd a separate
36962306a36Sopenharmony_ci	 * backlog list is needed so that the backlog completion call
37062306a36Sopenharmony_ci	 * completes before the cmd is available for execution.
37162306a36Sopenharmony_ci	 */
37262306a36Sopenharmony_ci	spinlock_t cmd_lock ____cacheline_aligned;
37362306a36Sopenharmony_ci	unsigned int cmd_count;
37462306a36Sopenharmony_ci	struct list_head cmd;
37562306a36Sopenharmony_ci	struct list_head backlog;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	/* The command queues. These represent the queues available on the
37862306a36Sopenharmony_ci	 * CCP that are available for processing cmds
37962306a36Sopenharmony_ci	 */
38062306a36Sopenharmony_ci	struct ccp_cmd_queue cmd_q[MAX_HW_QUEUES];
38162306a36Sopenharmony_ci	unsigned int cmd_q_count;
38262306a36Sopenharmony_ci	unsigned int max_q_count;
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	/* Support for the CCP True RNG
38562306a36Sopenharmony_ci	 */
38662306a36Sopenharmony_ci	struct hwrng hwrng;
38762306a36Sopenharmony_ci	unsigned int hwrng_retries;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	/* Support for the CCP DMA capabilities
39062306a36Sopenharmony_ci	 */
39162306a36Sopenharmony_ci	struct dma_device dma_dev;
39262306a36Sopenharmony_ci	struct ccp_dma_chan *ccp_dma_chan;
39362306a36Sopenharmony_ci	struct kmem_cache *dma_cmd_cache;
39462306a36Sopenharmony_ci	struct kmem_cache *dma_desc_cache;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	/* A counter used to generate job-ids for cmds submitted to the CCP
39762306a36Sopenharmony_ci	 */
39862306a36Sopenharmony_ci	atomic_t current_id ____cacheline_aligned;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	/* The v3 CCP uses key storage blocks (SB) to maintain context for
40162306a36Sopenharmony_ci	 * certain operations. To prevent multiple cmds from using the same
40262306a36Sopenharmony_ci	 * SB range a command queue reserves an SB range for the duration of
40362306a36Sopenharmony_ci	 * the cmd. Each queue, will however, reserve 2 SB blocks for
40462306a36Sopenharmony_ci	 * operations that only require single SB entries (eg. AES context/iv
40562306a36Sopenharmony_ci	 * and key) in order to avoid allocation contention.  This will reserve
40662306a36Sopenharmony_ci	 * at most 10 SB entries, leaving 40 SB entries available for dynamic
40762306a36Sopenharmony_ci	 * allocation.
40862306a36Sopenharmony_ci	 *
40962306a36Sopenharmony_ci	 * The v5 CCP Local Storage Block (LSB) is broken up into 8
41062306a36Sopenharmony_ci	 * memrory ranges, each of which can be enabled for access by one
41162306a36Sopenharmony_ci	 * or more queues. Device initialization takes this into account,
41262306a36Sopenharmony_ci	 * and attempts to assign one region for exclusive use by each
41362306a36Sopenharmony_ci	 * available queue; the rest are then aggregated as "public" use.
41462306a36Sopenharmony_ci	 * If there are fewer regions than queues, all regions are shared
41562306a36Sopenharmony_ci	 * amongst all queues.
41662306a36Sopenharmony_ci	 */
41762306a36Sopenharmony_ci	struct mutex sb_mutex ____cacheline_aligned;
41862306a36Sopenharmony_ci	DECLARE_BITMAP(sb, KSB_COUNT);
41962306a36Sopenharmony_ci	wait_queue_head_t sb_queue;
42062306a36Sopenharmony_ci	unsigned int sb_avail;
42162306a36Sopenharmony_ci	unsigned int sb_count;
42262306a36Sopenharmony_ci	u32 sb_start;
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	/* Bitmap of shared LSBs, if any */
42562306a36Sopenharmony_ci	DECLARE_BITMAP(lsbmap, SLSB_MAP_SIZE);
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	/* Suspend support */
42862306a36Sopenharmony_ci	unsigned int suspending;
42962306a36Sopenharmony_ci	wait_queue_head_t suspend_queue;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	/* DMA caching attribute support */
43262306a36Sopenharmony_ci	unsigned int axcache;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	/* Device Statistics */
43562306a36Sopenharmony_ci	unsigned long total_interrupts;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	/* DebugFS info */
43862306a36Sopenharmony_ci	struct dentry *debugfs_instance;
43962306a36Sopenharmony_ci};
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_cienum ccp_memtype {
44262306a36Sopenharmony_ci	CCP_MEMTYPE_SYSTEM = 0,
44362306a36Sopenharmony_ci	CCP_MEMTYPE_SB,
44462306a36Sopenharmony_ci	CCP_MEMTYPE_LOCAL,
44562306a36Sopenharmony_ci	CCP_MEMTYPE__LAST,
44662306a36Sopenharmony_ci};
44762306a36Sopenharmony_ci#define	CCP_MEMTYPE_LSB	CCP_MEMTYPE_KSB
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_cistruct ccp_dma_info {
45162306a36Sopenharmony_ci	dma_addr_t address;
45262306a36Sopenharmony_ci	unsigned int offset;
45362306a36Sopenharmony_ci	unsigned int length;
45462306a36Sopenharmony_ci	enum dma_data_direction dir;
45562306a36Sopenharmony_ci} __packed __aligned(4);
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_cistruct ccp_dm_workarea {
45862306a36Sopenharmony_ci	struct device *dev;
45962306a36Sopenharmony_ci	struct dma_pool *dma_pool;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	u8 *address;
46262306a36Sopenharmony_ci	struct ccp_dma_info dma;
46362306a36Sopenharmony_ci	unsigned int length;
46462306a36Sopenharmony_ci};
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_cistruct ccp_sg_workarea {
46762306a36Sopenharmony_ci	struct scatterlist *sg;
46862306a36Sopenharmony_ci	int nents;
46962306a36Sopenharmony_ci	unsigned int sg_used;
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	struct scatterlist *dma_sg;
47262306a36Sopenharmony_ci	struct scatterlist *dma_sg_head;
47362306a36Sopenharmony_ci	struct device *dma_dev;
47462306a36Sopenharmony_ci	unsigned int dma_count;
47562306a36Sopenharmony_ci	enum dma_data_direction dma_dir;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	u64 bytes_left;
47862306a36Sopenharmony_ci};
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_cistruct ccp_data {
48162306a36Sopenharmony_ci	struct ccp_sg_workarea sg_wa;
48262306a36Sopenharmony_ci	struct ccp_dm_workarea dm_wa;
48362306a36Sopenharmony_ci};
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistruct ccp_mem {
48662306a36Sopenharmony_ci	enum ccp_memtype type;
48762306a36Sopenharmony_ci	union {
48862306a36Sopenharmony_ci		struct ccp_dma_info dma;
48962306a36Sopenharmony_ci		u32 sb;
49062306a36Sopenharmony_ci	} u;
49162306a36Sopenharmony_ci};
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistruct ccp_aes_op {
49462306a36Sopenharmony_ci	enum ccp_aes_type type;
49562306a36Sopenharmony_ci	enum ccp_aes_mode mode;
49662306a36Sopenharmony_ci	enum ccp_aes_action action;
49762306a36Sopenharmony_ci	unsigned int size;
49862306a36Sopenharmony_ci};
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_cistruct ccp_xts_aes_op {
50162306a36Sopenharmony_ci	enum ccp_aes_type type;
50262306a36Sopenharmony_ci	enum ccp_aes_action action;
50362306a36Sopenharmony_ci	enum ccp_xts_aes_unit_size unit_size;
50462306a36Sopenharmony_ci};
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_cistruct ccp_des3_op {
50762306a36Sopenharmony_ci	enum ccp_des3_type type;
50862306a36Sopenharmony_ci	enum ccp_des3_mode mode;
50962306a36Sopenharmony_ci	enum ccp_des3_action action;
51062306a36Sopenharmony_ci};
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_cistruct ccp_sha_op {
51362306a36Sopenharmony_ci	enum ccp_sha_type type;
51462306a36Sopenharmony_ci	u64 msg_bits;
51562306a36Sopenharmony_ci};
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_cistruct ccp_rsa_op {
51862306a36Sopenharmony_ci	u32 mod_size;
51962306a36Sopenharmony_ci	u32 input_len;
52062306a36Sopenharmony_ci};
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_cistruct ccp_passthru_op {
52362306a36Sopenharmony_ci	enum ccp_passthru_bitwise bit_mod;
52462306a36Sopenharmony_ci	enum ccp_passthru_byteswap byte_swap;
52562306a36Sopenharmony_ci};
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_cistruct ccp_ecc_op {
52862306a36Sopenharmony_ci	enum ccp_ecc_function function;
52962306a36Sopenharmony_ci};
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_cistruct ccp_op {
53262306a36Sopenharmony_ci	struct ccp_cmd_queue *cmd_q;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	u32 jobid;
53562306a36Sopenharmony_ci	u32 ioc;
53662306a36Sopenharmony_ci	u32 soc;
53762306a36Sopenharmony_ci	u32 sb_key;
53862306a36Sopenharmony_ci	u32 sb_ctx;
53962306a36Sopenharmony_ci	u32 init;
54062306a36Sopenharmony_ci	u32 eom;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	struct ccp_mem src;
54362306a36Sopenharmony_ci	struct ccp_mem dst;
54462306a36Sopenharmony_ci	struct ccp_mem exp;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	union {
54762306a36Sopenharmony_ci		struct ccp_aes_op aes;
54862306a36Sopenharmony_ci		struct ccp_xts_aes_op xts;
54962306a36Sopenharmony_ci		struct ccp_des3_op des3;
55062306a36Sopenharmony_ci		struct ccp_sha_op sha;
55162306a36Sopenharmony_ci		struct ccp_rsa_op rsa;
55262306a36Sopenharmony_ci		struct ccp_passthru_op passthru;
55362306a36Sopenharmony_ci		struct ccp_ecc_op ecc;
55462306a36Sopenharmony_ci	} u;
55562306a36Sopenharmony_ci};
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_cistatic inline u32 ccp_addr_lo(struct ccp_dma_info *info)
55862306a36Sopenharmony_ci{
55962306a36Sopenharmony_ci	return lower_32_bits(info->address + info->offset);
56062306a36Sopenharmony_ci}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_cistatic inline u32 ccp_addr_hi(struct ccp_dma_info *info)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	return upper_32_bits(info->address + info->offset) & 0x0000ffff;
56562306a36Sopenharmony_ci}
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci/**
56862306a36Sopenharmony_ci * descriptor for version 5 CPP commands
56962306a36Sopenharmony_ci * 8 32-bit words:
57062306a36Sopenharmony_ci * word 0: function; engine; control bits
57162306a36Sopenharmony_ci * word 1: length of source data
57262306a36Sopenharmony_ci * word 2: low 32 bits of source pointer
57362306a36Sopenharmony_ci * word 3: upper 16 bits of source pointer; source memory type
57462306a36Sopenharmony_ci * word 4: low 32 bits of destination pointer
57562306a36Sopenharmony_ci * word 5: upper 16 bits of destination pointer; destination memory type
57662306a36Sopenharmony_ci * word 6: low 32 bits of key pointer
57762306a36Sopenharmony_ci * word 7: upper 16 bits of key pointer; key memory type
57862306a36Sopenharmony_ci */
57962306a36Sopenharmony_cistruct dword0 {
58062306a36Sopenharmony_ci	unsigned int soc:1;
58162306a36Sopenharmony_ci	unsigned int ioc:1;
58262306a36Sopenharmony_ci	unsigned int rsvd1:1;
58362306a36Sopenharmony_ci	unsigned int init:1;
58462306a36Sopenharmony_ci	unsigned int eom:1;		/* AES/SHA only */
58562306a36Sopenharmony_ci	unsigned int function:15;
58662306a36Sopenharmony_ci	unsigned int engine:4;
58762306a36Sopenharmony_ci	unsigned int prot:1;
58862306a36Sopenharmony_ci	unsigned int rsvd2:7;
58962306a36Sopenharmony_ci};
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_cistruct dword3 {
59262306a36Sopenharmony_ci	unsigned int  src_hi:16;
59362306a36Sopenharmony_ci	unsigned int  src_mem:2;
59462306a36Sopenharmony_ci	unsigned int  lsb_cxt_id:8;
59562306a36Sopenharmony_ci	unsigned int  rsvd1:5;
59662306a36Sopenharmony_ci	unsigned int  fixed:1;
59762306a36Sopenharmony_ci};
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ciunion dword4 {
60062306a36Sopenharmony_ci	u32 dst_lo;		/* NON-SHA	*/
60162306a36Sopenharmony_ci	u32 sha_len_lo;		/* SHA		*/
60262306a36Sopenharmony_ci};
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ciunion dword5 {
60562306a36Sopenharmony_ci	struct {
60662306a36Sopenharmony_ci		unsigned int  dst_hi:16;
60762306a36Sopenharmony_ci		unsigned int  dst_mem:2;
60862306a36Sopenharmony_ci		unsigned int  rsvd1:13;
60962306a36Sopenharmony_ci		unsigned int  fixed:1;
61062306a36Sopenharmony_ci	} fields;
61162306a36Sopenharmony_ci	u32 sha_len_hi;
61262306a36Sopenharmony_ci};
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_cistruct dword7 {
61562306a36Sopenharmony_ci	unsigned int  key_hi:16;
61662306a36Sopenharmony_ci	unsigned int  key_mem:2;
61762306a36Sopenharmony_ci	unsigned int  rsvd1:14;
61862306a36Sopenharmony_ci};
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_cistruct ccp5_desc {
62162306a36Sopenharmony_ci	struct dword0 dw0;
62262306a36Sopenharmony_ci	u32 length;
62362306a36Sopenharmony_ci	u32 src_lo;
62462306a36Sopenharmony_ci	struct dword3 dw3;
62562306a36Sopenharmony_ci	union dword4 dw4;
62662306a36Sopenharmony_ci	union dword5 dw5;
62762306a36Sopenharmony_ci	u32 key_lo;
62862306a36Sopenharmony_ci	struct dword7 dw7;
62962306a36Sopenharmony_ci};
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_civoid ccp_add_device(struct ccp_device *ccp);
63262306a36Sopenharmony_civoid ccp_del_device(struct ccp_device *ccp);
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ciextern void ccp_log_error(struct ccp_device *, unsigned int);
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cistruct ccp_device *ccp_alloc_struct(struct sp_device *sp);
63762306a36Sopenharmony_cibool ccp_queues_suspended(struct ccp_device *ccp);
63862306a36Sopenharmony_ciint ccp_cmd_queue_thread(void *data);
63962306a36Sopenharmony_ciint ccp_trng_read(struct hwrng *rng, void *data, size_t max, bool wait);
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ciint ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd);
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ciint ccp_register_rng(struct ccp_device *ccp);
64462306a36Sopenharmony_civoid ccp_unregister_rng(struct ccp_device *ccp);
64562306a36Sopenharmony_ciint ccp_dmaengine_register(struct ccp_device *ccp);
64662306a36Sopenharmony_civoid ccp_dmaengine_unregister(struct ccp_device *ccp);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_civoid ccp5_debugfs_setup(struct ccp_device *ccp);
64962306a36Sopenharmony_civoid ccp5_debugfs_destroy(void);
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci/* Structure for computation functions that are device-specific */
65262306a36Sopenharmony_cistruct ccp_actions {
65362306a36Sopenharmony_ci	int (*aes)(struct ccp_op *);
65462306a36Sopenharmony_ci	int (*xts_aes)(struct ccp_op *);
65562306a36Sopenharmony_ci	int (*des3)(struct ccp_op *);
65662306a36Sopenharmony_ci	int (*sha)(struct ccp_op *);
65762306a36Sopenharmony_ci	int (*rsa)(struct ccp_op *);
65862306a36Sopenharmony_ci	int (*passthru)(struct ccp_op *);
65962306a36Sopenharmony_ci	int (*ecc)(struct ccp_op *);
66062306a36Sopenharmony_ci	u32 (*sballoc)(struct ccp_cmd_queue *, unsigned int);
66162306a36Sopenharmony_ci	void (*sbfree)(struct ccp_cmd_queue *, unsigned int, unsigned int);
66262306a36Sopenharmony_ci	unsigned int (*get_free_slots)(struct ccp_cmd_queue *);
66362306a36Sopenharmony_ci	int (*init)(struct ccp_device *);
66462306a36Sopenharmony_ci	void (*destroy)(struct ccp_device *);
66562306a36Sopenharmony_ci	irqreturn_t (*irqhandler)(int, void *);
66662306a36Sopenharmony_ci};
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ciextern const struct ccp_vdata ccpv3_platform;
66962306a36Sopenharmony_ciextern const struct ccp_vdata ccpv3;
67062306a36Sopenharmony_ciextern const struct ccp_vdata ccpv5a;
67162306a36Sopenharmony_ciextern const struct ccp_vdata ccpv5b;
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci#endif
674