162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * sun4i-ss.h - hardware cryptographic accelerator for Allwinner A20 SoC
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Support AES cipher with 128,192,256 bits keysize.
862306a36Sopenharmony_ci * Support MD5 and SHA1 hash algorithms.
962306a36Sopenharmony_ci * Support DES and 3DES
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * You could find the datasheet in Documentation/arch/arm/sunxi.rst
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/clk.h>
1562306a36Sopenharmony_ci#include <linux/crypto.h>
1662306a36Sopenharmony_ci#include <linux/io.h>
1762306a36Sopenharmony_ci#include <linux/module.h>
1862306a36Sopenharmony_ci#include <linux/of.h>
1962306a36Sopenharmony_ci#include <linux/platform_device.h>
2062306a36Sopenharmony_ci#include <linux/reset.h>
2162306a36Sopenharmony_ci#include <crypto/scatterwalk.h>
2262306a36Sopenharmony_ci#include <linux/scatterlist.h>
2362306a36Sopenharmony_ci#include <linux/interrupt.h>
2462306a36Sopenharmony_ci#include <linux/delay.h>
2562306a36Sopenharmony_ci#include <linux/pm_runtime.h>
2662306a36Sopenharmony_ci#include <crypto/md5.h>
2762306a36Sopenharmony_ci#include <crypto/skcipher.h>
2862306a36Sopenharmony_ci#include <crypto/sha1.h>
2962306a36Sopenharmony_ci#include <crypto/hash.h>
3062306a36Sopenharmony_ci#include <crypto/internal/hash.h>
3162306a36Sopenharmony_ci#include <crypto/internal/skcipher.h>
3262306a36Sopenharmony_ci#include <crypto/aes.h>
3362306a36Sopenharmony_ci#include <crypto/internal/des.h>
3462306a36Sopenharmony_ci#include <crypto/internal/rng.h>
3562306a36Sopenharmony_ci#include <crypto/rng.h>
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define SS_CTL            0x00
3862306a36Sopenharmony_ci#define SS_KEY0           0x04
3962306a36Sopenharmony_ci#define SS_KEY1           0x08
4062306a36Sopenharmony_ci#define SS_KEY2           0x0C
4162306a36Sopenharmony_ci#define SS_KEY3           0x10
4262306a36Sopenharmony_ci#define SS_KEY4           0x14
4362306a36Sopenharmony_ci#define SS_KEY5           0x18
4462306a36Sopenharmony_ci#define SS_KEY6           0x1C
4562306a36Sopenharmony_ci#define SS_KEY7           0x20
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define SS_IV0            0x24
4862306a36Sopenharmony_ci#define SS_IV1            0x28
4962306a36Sopenharmony_ci#define SS_IV2            0x2C
5062306a36Sopenharmony_ci#define SS_IV3            0x30
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define SS_FCSR           0x44
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define SS_MD0            0x4C
5562306a36Sopenharmony_ci#define SS_MD1            0x50
5662306a36Sopenharmony_ci#define SS_MD2            0x54
5762306a36Sopenharmony_ci#define SS_MD3            0x58
5862306a36Sopenharmony_ci#define SS_MD4            0x5C
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define SS_RXFIFO         0x200
6162306a36Sopenharmony_ci#define SS_TXFIFO         0x204
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/* SS_CTL configuration values */
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/* PRNG generator mode - bit 15 */
6662306a36Sopenharmony_ci#define SS_PRNG_ONESHOT		(0 << 15)
6762306a36Sopenharmony_ci#define SS_PRNG_CONTINUE	(1 << 15)
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci/* IV mode for hash */
7062306a36Sopenharmony_ci#define SS_IV_ARBITRARY		(1 << 14)
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/* SS operation mode - bits 12-13 */
7362306a36Sopenharmony_ci#define SS_ECB			(0 << 12)
7462306a36Sopenharmony_ci#define SS_CBC			(1 << 12)
7562306a36Sopenharmony_ci#define SS_CTS			(3 << 12)
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/* Counter width for CNT mode - bits 10-11 */
7862306a36Sopenharmony_ci#define SS_CNT_16BITS		(0 << 10)
7962306a36Sopenharmony_ci#define SS_CNT_32BITS		(1 << 10)
8062306a36Sopenharmony_ci#define SS_CNT_64BITS		(2 << 10)
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/* Key size for AES - bits 8-9 */
8362306a36Sopenharmony_ci#define SS_AES_128BITS		(0 << 8)
8462306a36Sopenharmony_ci#define SS_AES_192BITS		(1 << 8)
8562306a36Sopenharmony_ci#define SS_AES_256BITS		(2 << 8)
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/* Operation direction - bit 7 */
8862306a36Sopenharmony_ci#define SS_ENCRYPTION		(0 << 7)
8962306a36Sopenharmony_ci#define SS_DECRYPTION		(1 << 7)
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/* SS Method - bits 4-6 */
9262306a36Sopenharmony_ci#define SS_OP_AES		(0 << 4)
9362306a36Sopenharmony_ci#define SS_OP_DES		(1 << 4)
9462306a36Sopenharmony_ci#define SS_OP_3DES		(2 << 4)
9562306a36Sopenharmony_ci#define SS_OP_SHA1		(3 << 4)
9662306a36Sopenharmony_ci#define SS_OP_MD5		(4 << 4)
9762306a36Sopenharmony_ci#define SS_OP_PRNG		(5 << 4)
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci/* Data end bit - bit 2 */
10062306a36Sopenharmony_ci#define SS_DATA_END		(1 << 2)
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci/* PRNG start bit - bit 1 */
10362306a36Sopenharmony_ci#define SS_PRNG_START		(1 << 1)
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/* SS Enable bit - bit 0 */
10662306a36Sopenharmony_ci#define SS_DISABLED		(0 << 0)
10762306a36Sopenharmony_ci#define SS_ENABLED		(1 << 0)
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/* SS_FCSR configuration values */
11062306a36Sopenharmony_ci/* RX FIFO status - bit 30 */
11162306a36Sopenharmony_ci#define SS_RXFIFO_FREE		(1 << 30)
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci/* RX FIFO empty spaces - bits 24-29 */
11462306a36Sopenharmony_ci#define SS_RXFIFO_SPACES(val)	(((val) >> 24) & 0x3f)
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci/* TX FIFO status - bit 22 */
11762306a36Sopenharmony_ci#define SS_TXFIFO_AVAILABLE	(1 << 22)
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci/* TX FIFO available spaces - bits 16-21 */
12062306a36Sopenharmony_ci#define SS_TXFIFO_SPACES(val)	(((val) >> 16) & 0x3f)
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci#define SS_RX_MAX	32
12362306a36Sopenharmony_ci#define SS_RX_DEFAULT	SS_RX_MAX
12462306a36Sopenharmony_ci#define SS_TX_MAX	33
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci#define SS_RXFIFO_EMP_INT_PENDING	(1 << 10)
12762306a36Sopenharmony_ci#define SS_TXFIFO_AVA_INT_PENDING	(1 << 8)
12862306a36Sopenharmony_ci#define SS_RXFIFO_EMP_INT_ENABLE	(1 << 2)
12962306a36Sopenharmony_ci#define SS_TXFIFO_AVA_INT_ENABLE	(1 << 0)
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci#define SS_SEED_LEN 192
13262306a36Sopenharmony_ci#define SS_DATA_LEN 160
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci/*
13562306a36Sopenharmony_ci * struct ss_variant - Describe SS hardware variant
13662306a36Sopenharmony_ci * @sha1_in_be:		The SHA1 digest is given by SS in BE, and so need to be inverted.
13762306a36Sopenharmony_ci */
13862306a36Sopenharmony_cistruct ss_variant {
13962306a36Sopenharmony_ci	bool sha1_in_be;
14062306a36Sopenharmony_ci};
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistruct sun4i_ss_ctx {
14362306a36Sopenharmony_ci	const struct ss_variant *variant;
14462306a36Sopenharmony_ci	void __iomem *base;
14562306a36Sopenharmony_ci	int irq;
14662306a36Sopenharmony_ci	struct clk *busclk;
14762306a36Sopenharmony_ci	struct clk *ssclk;
14862306a36Sopenharmony_ci	struct reset_control *reset;
14962306a36Sopenharmony_ci	struct device *dev;
15062306a36Sopenharmony_ci	struct resource *res;
15162306a36Sopenharmony_ci	char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */
15262306a36Sopenharmony_ci	char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */
15362306a36Sopenharmony_ci	spinlock_t slock; /* control the use of the device */
15462306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
15562306a36Sopenharmony_ci	u32 seed[SS_SEED_LEN / BITS_PER_LONG];
15662306a36Sopenharmony_ci#endif
15762306a36Sopenharmony_ci	struct dentry *dbgfs_dir;
15862306a36Sopenharmony_ci	struct dentry *dbgfs_stats;
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistruct sun4i_ss_alg_template {
16262306a36Sopenharmony_ci	u32 type;
16362306a36Sopenharmony_ci	u32 mode;
16462306a36Sopenharmony_ci	union {
16562306a36Sopenharmony_ci		struct skcipher_alg crypto;
16662306a36Sopenharmony_ci		struct ahash_alg hash;
16762306a36Sopenharmony_ci		struct rng_alg rng;
16862306a36Sopenharmony_ci	} alg;
16962306a36Sopenharmony_ci	struct sun4i_ss_ctx *ss;
17062306a36Sopenharmony_ci	unsigned long stat_req;
17162306a36Sopenharmony_ci	unsigned long stat_fb;
17262306a36Sopenharmony_ci	unsigned long stat_bytes;
17362306a36Sopenharmony_ci	unsigned long stat_opti;
17462306a36Sopenharmony_ci};
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistruct sun4i_tfm_ctx {
17762306a36Sopenharmony_ci	u32 key[AES_MAX_KEY_SIZE / 4];/* divided by sizeof(u32) */
17862306a36Sopenharmony_ci	u32 keylen;
17962306a36Sopenharmony_ci	u32 keymode;
18062306a36Sopenharmony_ci	struct sun4i_ss_ctx *ss;
18162306a36Sopenharmony_ci	struct crypto_skcipher *fallback_tfm;
18262306a36Sopenharmony_ci};
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistruct sun4i_cipher_req_ctx {
18562306a36Sopenharmony_ci	u32 mode;
18662306a36Sopenharmony_ci	u8 backup_iv[AES_BLOCK_SIZE];
18762306a36Sopenharmony_ci	struct skcipher_request fallback_req;   // keep at the end
18862306a36Sopenharmony_ci};
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistruct sun4i_req_ctx {
19162306a36Sopenharmony_ci	u32 mode;
19262306a36Sopenharmony_ci	u64 byte_count; /* number of bytes "uploaded" to the device */
19362306a36Sopenharmony_ci	u32 hash[5]; /* for storing SS_IVx register */
19462306a36Sopenharmony_ci	char buf[64];
19562306a36Sopenharmony_ci	unsigned int len;
19662306a36Sopenharmony_ci	int flags;
19762306a36Sopenharmony_ci};
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ciint sun4i_hash_crainit(struct crypto_tfm *tfm);
20062306a36Sopenharmony_civoid sun4i_hash_craexit(struct crypto_tfm *tfm);
20162306a36Sopenharmony_ciint sun4i_hash_init(struct ahash_request *areq);
20262306a36Sopenharmony_ciint sun4i_hash_update(struct ahash_request *areq);
20362306a36Sopenharmony_ciint sun4i_hash_final(struct ahash_request *areq);
20462306a36Sopenharmony_ciint sun4i_hash_finup(struct ahash_request *areq);
20562306a36Sopenharmony_ciint sun4i_hash_digest(struct ahash_request *areq);
20662306a36Sopenharmony_ciint sun4i_hash_export_md5(struct ahash_request *areq, void *out);
20762306a36Sopenharmony_ciint sun4i_hash_import_md5(struct ahash_request *areq, const void *in);
20862306a36Sopenharmony_ciint sun4i_hash_export_sha1(struct ahash_request *areq, void *out);
20962306a36Sopenharmony_ciint sun4i_hash_import_sha1(struct ahash_request *areq, const void *in);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ciint sun4i_ss_cbc_aes_encrypt(struct skcipher_request *areq);
21262306a36Sopenharmony_ciint sun4i_ss_cbc_aes_decrypt(struct skcipher_request *areq);
21362306a36Sopenharmony_ciint sun4i_ss_ecb_aes_encrypt(struct skcipher_request *areq);
21462306a36Sopenharmony_ciint sun4i_ss_ecb_aes_decrypt(struct skcipher_request *areq);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ciint sun4i_ss_cbc_des_encrypt(struct skcipher_request *areq);
21762306a36Sopenharmony_ciint sun4i_ss_cbc_des_decrypt(struct skcipher_request *areq);
21862306a36Sopenharmony_ciint sun4i_ss_ecb_des_encrypt(struct skcipher_request *areq);
21962306a36Sopenharmony_ciint sun4i_ss_ecb_des_decrypt(struct skcipher_request *areq);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ciint sun4i_ss_cbc_des3_encrypt(struct skcipher_request *areq);
22262306a36Sopenharmony_ciint sun4i_ss_cbc_des3_decrypt(struct skcipher_request *areq);
22362306a36Sopenharmony_ciint sun4i_ss_ecb_des3_encrypt(struct skcipher_request *areq);
22462306a36Sopenharmony_ciint sun4i_ss_ecb_des3_decrypt(struct skcipher_request *areq);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ciint sun4i_ss_cipher_init(struct crypto_tfm *tfm);
22762306a36Sopenharmony_civoid sun4i_ss_cipher_exit(struct crypto_tfm *tfm);
22862306a36Sopenharmony_ciint sun4i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
22962306a36Sopenharmony_ci			unsigned int keylen);
23062306a36Sopenharmony_ciint sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
23162306a36Sopenharmony_ci			unsigned int keylen);
23262306a36Sopenharmony_ciint sun4i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key,
23362306a36Sopenharmony_ci			 unsigned int keylen);
23462306a36Sopenharmony_ciint sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
23562306a36Sopenharmony_ci			   unsigned int slen, u8 *dst, unsigned int dlen);
23662306a36Sopenharmony_ciint sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen);
237