/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2017 Conrad Meyer <cem@FreeBSD.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#pragma once

#define CMD_QUEUE_MASK_OFFSET		0x000
#define CMD_QUEUE_PRIO_OFFSET		0x004
#define CMD_REQID_CONFIG_OFFSET		0x008
#define TRNG_OUT_OFFSET			0x00C
#define CMD_CMD_TIMEOUT_OFFSET		0x010
#define LSB_PUBLIC_MASK_LO_OFFSET	0x018
#define LSB_PUBLIC_MASK_HI_OFFSET	0x01C
#define LSB_PRIVATE_MASK_LO_OFFSET	0x020
#define LSB_PRIVATE_MASK_HI_OFFSET	0x024

#define VERSION_REG			0x100
#define VERSION_NUM_MASK		0x3F
#define VERSION_CAP_MASK		0x7FC0
#define VERSION_CAP_AES			(1 << 6)
#define VERSION_CAP_3DES		(1 << 7)
#define VERSION_CAP_SHA			(1 << 8)
#define VERSION_CAP_RSA			(1 << 9)
#define VERSION_CAP_ECC			(1 << 10)
#define VERSION_CAP_ZDE			(1 << 11)
#define VERSION_CAP_ZCE			(1 << 12)
#define VERSION_CAP_TRNG		(1 << 13)
#define VERSION_CAP_ELFC		(1 << 14)
#define VERSION_NUMVQM_SHIFT		15
#define VERSION_NUMVQM_MASK		0xF
#define VERSION_LSBSIZE_SHIFT		19
#define VERSION_LSBSIZE_MASK		0x3FF

#define CMD_Q_CONTROL_BASE		0x000
#define CMD_Q_TAIL_LO_BASE		0x004
#define CMD_Q_HEAD_LO_BASE		0x008
#define CMD_Q_INT_ENABLE_BASE		0x00C
#define CMD_Q_INTERRUPT_STATUS_BASE	0x010

#define CMD_Q_STATUS_BASE		0x100
#define CMD_Q_INT_STATUS_BASE		0x104

#define CMD_Q_STATUS_INCR		0x1000

/* Don't think there's much point in keeping these -- OS can't access: */
#define CMD_CONFIG_0_OFFSET		0x6000
#define CMD_TRNG_CTL_OFFSET		0x6008
#define CMD_AES_MASK_OFFSET		0x6010
#define CMD_CLK_GATE_CTL_OFFSET		0x603C

/* CMD_Q_CONTROL_BASE bits */
#define CMD_Q_RUN			(1 << 0)
#define CMD_Q_HALTED			(1 << 1)
#define CMD_Q_MEM_LOCATION		(1 << 2)
#define CMD_Q_SIZE_SHIFT		3
#define CMD_Q_SIZE_MASK			0x1F
#define CMD_Q_PTR_HI_SHIFT		16
#define CMD_Q_PTR_HI_MASK		0xFFFF

/*
 * The following bits are used for both CMD_Q_INT_ENABLE_BASE and
 * CMD_Q_INTERRUPT_STATUS_BASE.
 */
#define INT_COMPLETION			(1 << 0)
#define INT_ERROR			(1 << 1)
#define INT_QUEUE_STOPPED		(1 << 2)
#define INT_QUEUE_EMPTY			(1 << 3)
#define ALL_INTERRUPTS			(INT_COMPLETION | \
					 INT_ERROR | \
					 INT_QUEUE_STOPPED | \
					 INT_QUEUE_EMPTY)

#define STATUS_ERROR_MASK		0x3F
#define STATUS_JOBSTATUS_SHIFT		7
#define STATUS_JOBSTATUS_MASK		0x7
#define STATUS_ERRORSOURCE_SHIFT	10
#define STATUS_ERRORSOURCE_MASK		0x3
#define STATUS_VLSB_FAULTBLOCK_SHIFT	12
#define STATUS_VLSB_FAULTBLOCK_MASK	0x7

/* From JOBSTATUS field in STATUS register above */
#define JOBSTATUS_IDLE			0
#define JOBSTATUS_ACTIVE_WAITING	1
#define JOBSTATUS_ACTIVE		2
#define JOBSTATUS_WAIT_ABORT		3
#define JOBSTATUS_DYN_ERROR		4
#define JOBSTATUS_PREPARE_HALT		5

/* From ERRORSOURCE field in STATUS register */
#define ERRORSOURCE_INPUT_MEMORY	0
#define ERRORSOURCE_CMD_DESCRIPTOR	1
#define ERRORSOURCE_INPUT_DATA		2
#define ERRORSOURCE_KEY_DATA		3

#define Q_DESC_SIZE			sizeof(struct ccp_desc)

enum ccp_aes_mode {
	CCP_AES_MODE_ECB = 0,
	CCP_AES_MODE_CBC,
	CCP_AES_MODE_OFB,
	CCP_AES_MODE_CFB,
	CCP_AES_MODE_CTR,
	CCP_AES_MODE_CMAC,
	CCP_AES_MODE_GHASH,
	CCP_AES_MODE_GCTR,
	CCP_AES_MODE_IAPM_NIST,
	CCP_AES_MODE_IAPM_IPSEC,

	/* Not a real hardware mode; used as a sentinel value internally. */
	CCP_AES_MODE_XTS,
};

enum ccp_aes_ghash_mode {
	CCP_AES_MODE_GHASH_AAD = 0,
	CCP_AES_MODE_GHASH_FINAL,
};

enum ccp_aes_type {
	CCP_AES_TYPE_128 = 0,
	CCP_AES_TYPE_192,
	CCP_AES_TYPE_256,
};

enum ccp_des_mode {
	CCP_DES_MODE_ECB = 0,
	CCP_DES_MODE_CBC,
	CCP_DES_MODE_CFB,
};

enum ccp_des_type {
	CCP_DES_TYPE_128 = 0,	/* 112 + 16 parity */
	CCP_DES_TYPE_192,	/* 168 + 24 parity */
};

enum ccp_sha_type {
	CCP_SHA_TYPE_1 = 1,
	CCP_SHA_TYPE_224,
	CCP_SHA_TYPE_256,
	CCP_SHA_TYPE_384,
	CCP_SHA_TYPE_512,
	CCP_SHA_TYPE_RSVD1,
	CCP_SHA_TYPE_RSVD2,
	CCP_SHA3_TYPE_224,
	CCP_SHA3_TYPE_256,
	CCP_SHA3_TYPE_384,
	CCP_SHA3_TYPE_512,
};

enum ccp_cipher_algo {
	CCP_CIPHER_ALGO_AES_CBC = 0,
	CCP_CIPHER_ALGO_AES_ECB,
	CCP_CIPHER_ALGO_AES_CTR,
	CCP_CIPHER_ALGO_AES_GCM,
	CCP_CIPHER_ALGO_3DES_CBC,
};

enum ccp_cipher_dir {
	CCP_CIPHER_DIR_DECRYPT = 0,
	CCP_CIPHER_DIR_ENCRYPT = 1,
};

enum ccp_hash_algo {
	CCP_AUTH_ALGO_SHA1 = 0,
	CCP_AUTH_ALGO_SHA1_HMAC,
	CCP_AUTH_ALGO_SHA224,
	CCP_AUTH_ALGO_SHA224_HMAC,
	CCP_AUTH_ALGO_SHA3_224,
	CCP_AUTH_ALGO_SHA3_224_HMAC,
	CCP_AUTH_ALGO_SHA256,
	CCP_AUTH_ALGO_SHA256_HMAC,
	CCP_AUTH_ALGO_SHA3_256,
	CCP_AUTH_ALGO_SHA3_256_HMAC,
	CCP_AUTH_ALGO_SHA384,
	CCP_AUTH_ALGO_SHA384_HMAC,
	CCP_AUTH_ALGO_SHA3_384,
	CCP_AUTH_ALGO_SHA3_384_HMAC,
	CCP_AUTH_ALGO_SHA512,
	CCP_AUTH_ALGO_SHA512_HMAC,
	CCP_AUTH_ALGO_SHA3_512,
	CCP_AUTH_ALGO_SHA3_512_HMAC,
	CCP_AUTH_ALGO_AES_CMAC,
	CCP_AUTH_ALGO_AES_GCM,
};

enum ccp_hash_op {
	CCP_AUTH_OP_GENERATE = 0,
	CCP_AUTH_OP_VERIFY = 1,
};

enum ccp_engine {
	CCP_ENGINE_AES = 0,
	CCP_ENGINE_XTS_AES,
	CCP_ENGINE_3DES,
	CCP_ENGINE_SHA,
	CCP_ENGINE_RSA,
	CCP_ENGINE_PASSTHRU,
	CCP_ENGINE_ZLIB_DECOMPRESS,
	CCP_ENGINE_ECC,
};

enum ccp_xts_unitsize {
	CCP_XTS_AES_UNIT_SIZE_16 = 0,
	CCP_XTS_AES_UNIT_SIZE_512,
	CCP_XTS_AES_UNIT_SIZE_1024,
	CCP_XTS_AES_UNIT_SIZE_2048,
	CCP_XTS_AES_UNIT_SIZE_4096,
};

enum ccp_passthru_bitwise {
	CCP_PASSTHRU_BITWISE_NOOP = 0,
	CCP_PASSTHRU_BITWISE_AND,
	CCP_PASSTHRU_BITWISE_OR,
	CCP_PASSTHRU_BITWISE_XOR,
	CCP_PASSTHRU_BITWISE_MASK,
};

enum ccp_passthru_byteswap {
	CCP_PASSTHRU_BYTESWAP_NOOP = 0,
	CCP_PASSTHRU_BYTESWAP_32BIT,
	CCP_PASSTHRU_BYTESWAP_256BIT,
};

/**
 * descriptor for version 5 CPP commands
 * 8 32-bit words:
 * word 0: function; engine; control bits
 * word 1: length of source data
 * word 2: low 32 bits of source pointer
 * word 3: upper 16 bits of source pointer; source memory type
 * word 4: low 32 bits of destination pointer
 * word 5: upper 16 bits of destination pointer; destination memory
 * type
 * word 6: low 32 bits of key pointer
 * word 7: upper 16 bits of key pointer; key memory type
 */

struct ccp_desc {
	union dword0 {
		struct {
			uint32_t hoc:1;		/* Halt on completion */
			uint32_t ioc:1;		/* Intr. on completion */
			uint32_t reserved_1:1;
			uint32_t som:1;		/* Start of message */
			uint32_t eom:1;		/* End " */
			uint32_t size:7;
			uint32_t encrypt:1;
			uint32_t mode:5;
			uint32_t type:2;
			uint32_t engine:4;
			uint32_t prot:1;
			uint32_t reserved_2:7;
		} aes;
		struct {
			uint32_t hoc:1;		/* Halt on completion */
			uint32_t ioc:1;		/* Intr. on completion */
			uint32_t reserved_1:1;
			uint32_t som:1;		/* Start of message */
			uint32_t eom:1;		/* End " */
			uint32_t size:7;
			uint32_t encrypt:1;
			uint32_t mode:5;
			uint32_t type:2;
			uint32_t engine:4;
			uint32_t prot:1;
			uint32_t reserved_2:7;
		} des;
		struct {
			uint32_t hoc:1;		/* Halt on completion */
			uint32_t ioc:1;		/* Intr. on completion */
			uint32_t reserved_1:1;
			uint32_t som:1;		/* Start of message */
			uint32_t eom:1;		/* End " */
			uint32_t size:7;
			uint32_t encrypt:1;
			uint32_t reserved_2:5;
			uint32_t type:2;
			uint32_t engine:4;
			uint32_t prot:1;
			uint32_t reserved_3:7;
		} aes_xts;
		struct {
			uint32_t hoc:1;		/* Halt on completion */
			uint32_t ioc:1;		/* Intr. on completion */
			uint32_t reserved_1:1;
			uint32_t som:1;		/* Start of message */
			uint32_t eom:1;		/* End " */
			uint32_t reserved_2:10;
			uint32_t type:4;
			uint32_t reserved_3:1;
			uint32_t engine:4;
			uint32_t prot:1;
			uint32_t reserved_4:7;
		} sha;
		struct {
			uint32_t hoc:1;		/* Halt on completion */
			uint32_t ioc:1;		/* Intr. on completion */
			uint32_t reserved_1:1;
			uint32_t som:1;		/* Start of message */
			uint32_t eom:1;		/* End " */
			uint32_t mode:3;
			uint32_t size:12;
			uint32_t engine:4;
			uint32_t prot:1;
			uint32_t reserved_2:7;
		} rsa;
		struct {
			uint32_t hoc:1;		/* Halt on completion */
			uint32_t ioc:1;		/* Intr. on completion */
			uint32_t reserved_1:1;
			uint32_t som:1;		/* Start of message */
			uint32_t eom:1;		/* End " */
			uint32_t byteswap:2;
			uint32_t bitwise:3;
			uint32_t reflect:2;
			uint32_t reserved_2:8;
			uint32_t engine:4;
			uint32_t prot:1;
			uint32_t reserved_3:7;
		} pt;
		struct  {
			uint32_t hoc:1;		/* Halt on completion */
			uint32_t ioc:1;		/* Intr. on completion */
			uint32_t reserved_1:1;
			uint32_t som:1;		/* Start of message */
			uint32_t eom:1;		/* End " */
			uint32_t reserved_2:13;
			uint32_t reserved_3:2;
			uint32_t engine:4;
			uint32_t prot:1;
			uint32_t reserved_4:7;
		} zlib;
		struct {
			uint32_t hoc:1;		/* Halt on completion */
			uint32_t ioc:1;		/* Intr. on completion */
			uint32_t reserved_1:1;
			uint32_t som:1;		/* Start of message */
			uint32_t eom:1;		/* End " */
			uint32_t size:10;
			uint32_t type:2;
			uint32_t mode:3;
			uint32_t engine:4;
			uint32_t prot:1;
			uint32_t reserved_2:7;
		} ecc;
		struct {
			uint32_t hoc:1;		/* Halt on completion */
			uint32_t ioc:1;		/* Intr. on completion */
			uint32_t reserved_1:1;
			uint32_t som:1;		/* Start of message */
			uint32_t eom:1;		/* End " */
			uint32_t function:15;
			uint32_t engine:4;
			uint32_t prot:1;
			uint32_t reserved_2:7;
		} /* generic */;
	};

	uint32_t length;
	uint32_t src_lo;

	struct dword3 {
		uint32_t src_hi:16;
		uint32_t src_mem:2;
		uint32_t lsb_ctx_id:8;
		uint32_t reserved_3:5;
		uint32_t src_fixed:1;
	};

	union dword4 {
		uint32_t dst_lo;	/* NON-SHA */
		uint32_t sha_len_lo;	/* SHA */
	};

	union dword5 {
		struct {
			uint32_t dst_hi:16;
			uint32_t dst_mem:2;
			uint32_t reserved_4:13;
			uint32_t dst_fixed:1;
		};
		uint32_t sha_len_hi;
	};

	uint32_t key_lo;

	struct dword7 {
		uint32_t key_hi:16;
		uint32_t key_mem:2;
		uint32_t reserved_5:14;
	};
};

enum ccp_memtype {
	CCP_MEMTYPE_SYSTEM = 0,
	CCP_MEMTYPE_SB,
	CCP_MEMTYPE_LOCAL,
};

enum ccp_cmd_order {
	CCP_CMD_CIPHER = 0,
	CCP_CMD_AUTH,
	CCP_CMD_CIPHER_HASH,
	CCP_CMD_HASH_CIPHER,
	CCP_CMD_COMBINED,
	CCP_CMD_NOT_SUPPORTED,
};
