162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * sun8i-ss.h - hardware cryptographic offloader for 462306a36Sopenharmony_ci * Allwinner A80/A83T SoC 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2016-2019 Corentin LABBE <clabbe.montjoie@gmail.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#include <crypto/aes.h> 962306a36Sopenharmony_ci#include <crypto/des.h> 1062306a36Sopenharmony_ci#include <crypto/engine.h> 1162306a36Sopenharmony_ci#include <crypto/rng.h> 1262306a36Sopenharmony_ci#include <crypto/skcipher.h> 1362306a36Sopenharmony_ci#include <linux/atomic.h> 1462306a36Sopenharmony_ci#include <linux/debugfs.h> 1562306a36Sopenharmony_ci#include <linux/crypto.h> 1662306a36Sopenharmony_ci#include <crypto/internal/hash.h> 1762306a36Sopenharmony_ci#include <crypto/md5.h> 1862306a36Sopenharmony_ci#include <crypto/sha1.h> 1962306a36Sopenharmony_ci#include <crypto/sha2.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define SS_START 1 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define SS_ENCRYPTION 0 2462306a36Sopenharmony_ci#define SS_DECRYPTION BIT(6) 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define SS_ALG_AES 0 2762306a36Sopenharmony_ci#define SS_ALG_DES (1 << 2) 2862306a36Sopenharmony_ci#define SS_ALG_3DES (2 << 2) 2962306a36Sopenharmony_ci#define SS_ALG_MD5 (3 << 2) 3062306a36Sopenharmony_ci#define SS_ALG_PRNG (4 << 2) 3162306a36Sopenharmony_ci#define SS_ALG_SHA1 (6 << 2) 3262306a36Sopenharmony_ci#define SS_ALG_SHA224 (7 << 2) 3362306a36Sopenharmony_ci#define SS_ALG_SHA256 (8 << 2) 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define SS_CTL_REG 0x00 3662306a36Sopenharmony_ci#define SS_INT_CTL_REG 0x04 3762306a36Sopenharmony_ci#define SS_INT_STA_REG 0x08 3862306a36Sopenharmony_ci#define SS_KEY_ADR_REG 0x10 3962306a36Sopenharmony_ci#define SS_IV_ADR_REG 0x18 4062306a36Sopenharmony_ci#define SS_SRC_ADR_REG 0x20 4162306a36Sopenharmony_ci#define SS_DST_ADR_REG 0x28 4262306a36Sopenharmony_ci#define SS_LEN_ADR_REG 0x30 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define SS_ID_NOTSUPP 0xFF 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define SS_ID_CIPHER_AES 0 4762306a36Sopenharmony_ci#define SS_ID_CIPHER_DES 1 4862306a36Sopenharmony_ci#define SS_ID_CIPHER_DES3 2 4962306a36Sopenharmony_ci#define SS_ID_CIPHER_MAX 3 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define SS_ID_OP_ECB 0 5262306a36Sopenharmony_ci#define SS_ID_OP_CBC 1 5362306a36Sopenharmony_ci#define SS_ID_OP_MAX 2 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define SS_AES_128BITS 0 5662306a36Sopenharmony_ci#define SS_AES_192BITS 1 5762306a36Sopenharmony_ci#define SS_AES_256BITS 2 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define SS_OP_ECB 0 6062306a36Sopenharmony_ci#define SS_OP_CBC (1 << 13) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define SS_ID_HASH_MD5 0 6362306a36Sopenharmony_ci#define SS_ID_HASH_SHA1 1 6462306a36Sopenharmony_ci#define SS_ID_HASH_SHA224 2 6562306a36Sopenharmony_ci#define SS_ID_HASH_SHA256 3 6662306a36Sopenharmony_ci#define SS_ID_HASH_MAX 4 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#define SS_FLOW0 BIT(30) 6962306a36Sopenharmony_ci#define SS_FLOW1 BIT(31) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define SS_PRNG_CONTINUE BIT(18) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define MAX_SG 8 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#define MAXFLOW 2 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define SS_MAX_CLOCKS 2 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci#define SS_DIE_ID_SHIFT 20 8062306a36Sopenharmony_ci#define SS_DIE_ID_MASK 0x07 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#define PRNG_DATA_SIZE (160 / 8) 8362306a36Sopenharmony_ci#define PRNG_SEED_SIZE DIV_ROUND_UP(175, 8) 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define MAX_PAD_SIZE 4096 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* 8862306a36Sopenharmony_ci * struct ss_clock - Describe clocks used by sun8i-ss 8962306a36Sopenharmony_ci * @name: Name of clock needed by this variant 9062306a36Sopenharmony_ci * @freq: Frequency to set for each clock 9162306a36Sopenharmony_ci * @max_freq: Maximum frequency for each clock 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_cistruct ss_clock { 9462306a36Sopenharmony_ci const char *name; 9562306a36Sopenharmony_ci unsigned long freq; 9662306a36Sopenharmony_ci unsigned long max_freq; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/* 10062306a36Sopenharmony_ci * struct ss_variant - Describe SS capability for each variant hardware 10162306a36Sopenharmony_ci * @alg_cipher: list of supported ciphers. for each SS_ID_ this will give the 10262306a36Sopenharmony_ci * coresponding SS_ALG_XXX value 10362306a36Sopenharmony_ci * @alg_hash: list of supported hashes. for each SS_ID_ this will give the 10462306a36Sopenharmony_ci * corresponding SS_ALG_XXX value 10562306a36Sopenharmony_ci * @op_mode: list of supported block modes 10662306a36Sopenharmony_ci * @ss_clks: list of clock needed by this variant 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_cistruct ss_variant { 10962306a36Sopenharmony_ci char alg_cipher[SS_ID_CIPHER_MAX]; 11062306a36Sopenharmony_ci char alg_hash[SS_ID_HASH_MAX]; 11162306a36Sopenharmony_ci u32 op_mode[SS_ID_OP_MAX]; 11262306a36Sopenharmony_ci struct ss_clock ss_clks[SS_MAX_CLOCKS]; 11362306a36Sopenharmony_ci}; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistruct sginfo { 11662306a36Sopenharmony_ci u32 addr; 11762306a36Sopenharmony_ci u32 len; 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* 12162306a36Sopenharmony_ci * struct sun8i_ss_flow - Information used by each flow 12262306a36Sopenharmony_ci * @engine: ptr to the crypto_engine for this flow 12362306a36Sopenharmony_ci * @complete: completion for the current task on this flow 12462306a36Sopenharmony_ci * @status: set to 1 by interrupt if task is done 12562306a36Sopenharmony_ci * @stat_req: number of request done by this flow 12662306a36Sopenharmony_ci * @iv: list of IV to use for each step 12762306a36Sopenharmony_ci * @biv: buffer which contain the backuped IV 12862306a36Sopenharmony_ci * @pad: padding buffer for hash operations 12962306a36Sopenharmony_ci * @result: buffer for storing the result of hash operations 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_cistruct sun8i_ss_flow { 13262306a36Sopenharmony_ci struct crypto_engine *engine; 13362306a36Sopenharmony_ci struct completion complete; 13462306a36Sopenharmony_ci int status; 13562306a36Sopenharmony_ci u8 *iv[MAX_SG]; 13662306a36Sopenharmony_ci u8 *biv; 13762306a36Sopenharmony_ci void *pad; 13862306a36Sopenharmony_ci void *result; 13962306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG 14062306a36Sopenharmony_ci unsigned long stat_req; 14162306a36Sopenharmony_ci#endif 14262306a36Sopenharmony_ci}; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci/* 14562306a36Sopenharmony_ci * struct sun8i_ss_dev - main container for all this driver information 14662306a36Sopenharmony_ci * @base: base address of SS 14762306a36Sopenharmony_ci * @ssclks: clocks used by SS 14862306a36Sopenharmony_ci * @reset: pointer to reset controller 14962306a36Sopenharmony_ci * @dev: the platform device 15062306a36Sopenharmony_ci * @mlock: Control access to device registers 15162306a36Sopenharmony_ci * @flows: array of all flow 15262306a36Sopenharmony_ci * @flow: flow to use in next request 15362306a36Sopenharmony_ci * @variant: pointer to variant specific data 15462306a36Sopenharmony_ci * @dbgfs_dir: Debugfs dentry for statistic directory 15562306a36Sopenharmony_ci * @dbgfs_stats: Debugfs dentry for statistic counters 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_cistruct sun8i_ss_dev { 15862306a36Sopenharmony_ci void __iomem *base; 15962306a36Sopenharmony_ci struct clk *ssclks[SS_MAX_CLOCKS]; 16062306a36Sopenharmony_ci struct reset_control *reset; 16162306a36Sopenharmony_ci struct device *dev; 16262306a36Sopenharmony_ci struct mutex mlock; 16362306a36Sopenharmony_ci struct sun8i_ss_flow *flows; 16462306a36Sopenharmony_ci atomic_t flow; 16562306a36Sopenharmony_ci const struct ss_variant *variant; 16662306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG 16762306a36Sopenharmony_ci struct dentry *dbgfs_dir; 16862306a36Sopenharmony_ci struct dentry *dbgfs_stats; 16962306a36Sopenharmony_ci#endif 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci/* 17362306a36Sopenharmony_ci * struct sun8i_cipher_req_ctx - context for a skcipher request 17462306a36Sopenharmony_ci * @t_src: list of mapped SGs with their size 17562306a36Sopenharmony_ci * @t_dst: list of mapped SGs with their size 17662306a36Sopenharmony_ci * @p_key: DMA address of the key 17762306a36Sopenharmony_ci * @p_iv: DMA address of the IVs 17862306a36Sopenharmony_ci * @niv: Number of IVs DMA mapped 17962306a36Sopenharmony_ci * @method: current algorithm for this request 18062306a36Sopenharmony_ci * @op_mode: op_mode for this request 18162306a36Sopenharmony_ci * @op_dir: direction (encrypt vs decrypt) for this request 18262306a36Sopenharmony_ci * @flow: the flow to use for this request 18362306a36Sopenharmony_ci * @ivlen: size of IVs 18462306a36Sopenharmony_ci * @keylen: keylen for this request 18562306a36Sopenharmony_ci * @fallback_req: request struct for invoking the fallback skcipher TFM 18662306a36Sopenharmony_ci */ 18762306a36Sopenharmony_cistruct sun8i_cipher_req_ctx { 18862306a36Sopenharmony_ci struct sginfo t_src[MAX_SG]; 18962306a36Sopenharmony_ci struct sginfo t_dst[MAX_SG]; 19062306a36Sopenharmony_ci u32 p_key; 19162306a36Sopenharmony_ci u32 p_iv[MAX_SG]; 19262306a36Sopenharmony_ci int niv; 19362306a36Sopenharmony_ci u32 method; 19462306a36Sopenharmony_ci u32 op_mode; 19562306a36Sopenharmony_ci u32 op_dir; 19662306a36Sopenharmony_ci int flow; 19762306a36Sopenharmony_ci unsigned int ivlen; 19862306a36Sopenharmony_ci unsigned int keylen; 19962306a36Sopenharmony_ci struct skcipher_request fallback_req; // keep at the end 20062306a36Sopenharmony_ci}; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/* 20362306a36Sopenharmony_ci * struct sun8i_cipher_tfm_ctx - context for a skcipher TFM 20462306a36Sopenharmony_ci * @key: pointer to key data 20562306a36Sopenharmony_ci * @keylen: len of the key 20662306a36Sopenharmony_ci * @ss: pointer to the private data of driver handling this TFM 20762306a36Sopenharmony_ci * @fallback_tfm: pointer to the fallback TFM 20862306a36Sopenharmony_ci */ 20962306a36Sopenharmony_cistruct sun8i_cipher_tfm_ctx { 21062306a36Sopenharmony_ci u32 *key; 21162306a36Sopenharmony_ci u32 keylen; 21262306a36Sopenharmony_ci struct sun8i_ss_dev *ss; 21362306a36Sopenharmony_ci struct crypto_skcipher *fallback_tfm; 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci/* 21762306a36Sopenharmony_ci * struct sun8i_ss_prng_ctx - context for PRNG TFM 21862306a36Sopenharmony_ci * @seed: The seed to use 21962306a36Sopenharmony_ci * @slen: The size of the seed 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_cistruct sun8i_ss_rng_tfm_ctx { 22262306a36Sopenharmony_ci void *seed; 22362306a36Sopenharmony_ci unsigned int slen; 22462306a36Sopenharmony_ci}; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci/* 22762306a36Sopenharmony_ci * struct sun8i_ss_hash_tfm_ctx - context for an ahash TFM 22862306a36Sopenharmony_ci * @fallback_tfm: pointer to the fallback TFM 22962306a36Sopenharmony_ci * @ss: pointer to the private data of driver handling this TFM 23062306a36Sopenharmony_ci */ 23162306a36Sopenharmony_cistruct sun8i_ss_hash_tfm_ctx { 23262306a36Sopenharmony_ci struct crypto_ahash *fallback_tfm; 23362306a36Sopenharmony_ci struct sun8i_ss_dev *ss; 23462306a36Sopenharmony_ci u8 *ipad; 23562306a36Sopenharmony_ci u8 *opad; 23662306a36Sopenharmony_ci u8 key[SHA256_BLOCK_SIZE]; 23762306a36Sopenharmony_ci int keylen; 23862306a36Sopenharmony_ci}; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci/* 24162306a36Sopenharmony_ci * struct sun8i_ss_hash_reqctx - context for an ahash request 24262306a36Sopenharmony_ci * @t_src: list of DMA address and size for source SGs 24362306a36Sopenharmony_ci * @t_dst: list of DMA address and size for destination SGs 24462306a36Sopenharmony_ci * @fallback_req: pre-allocated fallback request 24562306a36Sopenharmony_ci * @method: the register value for the algorithm used by this request 24662306a36Sopenharmony_ci * @flow: the flow to use for this request 24762306a36Sopenharmony_ci */ 24862306a36Sopenharmony_cistruct sun8i_ss_hash_reqctx { 24962306a36Sopenharmony_ci struct sginfo t_src[MAX_SG]; 25062306a36Sopenharmony_ci struct sginfo t_dst[MAX_SG]; 25162306a36Sopenharmony_ci struct ahash_request fallback_req; 25262306a36Sopenharmony_ci u32 method; 25362306a36Sopenharmony_ci int flow; 25462306a36Sopenharmony_ci}; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci/* 25762306a36Sopenharmony_ci * struct sun8i_ss_alg_template - crypto_alg template 25862306a36Sopenharmony_ci * @type: the CRYPTO_ALG_TYPE for this template 25962306a36Sopenharmony_ci * @ss_algo_id: the SS_ID for this template 26062306a36Sopenharmony_ci * @ss_blockmode: the type of block operation SS_ID 26162306a36Sopenharmony_ci * @ss: pointer to the sun8i_ss_dev structure associated with 26262306a36Sopenharmony_ci * this template 26362306a36Sopenharmony_ci * @alg: one of sub struct must be used 26462306a36Sopenharmony_ci * @stat_req: number of request done on this template 26562306a36Sopenharmony_ci * @stat_fb: number of request which has fallbacked 26662306a36Sopenharmony_ci * @stat_bytes: total data size done by this template 26762306a36Sopenharmony_ci */ 26862306a36Sopenharmony_cistruct sun8i_ss_alg_template { 26962306a36Sopenharmony_ci u32 type; 27062306a36Sopenharmony_ci u32 ss_algo_id; 27162306a36Sopenharmony_ci u32 ss_blockmode; 27262306a36Sopenharmony_ci struct sun8i_ss_dev *ss; 27362306a36Sopenharmony_ci union { 27462306a36Sopenharmony_ci struct skcipher_engine_alg skcipher; 27562306a36Sopenharmony_ci struct rng_alg rng; 27662306a36Sopenharmony_ci struct ahash_engine_alg hash; 27762306a36Sopenharmony_ci } alg; 27862306a36Sopenharmony_ci unsigned long stat_req; 27962306a36Sopenharmony_ci unsigned long stat_fb; 28062306a36Sopenharmony_ci unsigned long stat_bytes; 28162306a36Sopenharmony_ci unsigned long stat_fb_len; 28262306a36Sopenharmony_ci unsigned long stat_fb_sglen; 28362306a36Sopenharmony_ci unsigned long stat_fb_align; 28462306a36Sopenharmony_ci unsigned long stat_fb_sgnum; 28562306a36Sopenharmony_ci char fbname[CRYPTO_MAX_ALG_NAME]; 28662306a36Sopenharmony_ci}; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ciint sun8i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, 28962306a36Sopenharmony_ci unsigned int keylen); 29062306a36Sopenharmony_ciint sun8i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key, 29162306a36Sopenharmony_ci unsigned int keylen); 29262306a36Sopenharmony_ciint sun8i_ss_cipher_init(struct crypto_tfm *tfm); 29362306a36Sopenharmony_civoid sun8i_ss_cipher_exit(struct crypto_tfm *tfm); 29462306a36Sopenharmony_ciint sun8i_ss_handle_cipher_request(struct crypto_engine *engine, void *areq); 29562306a36Sopenharmony_ciint sun8i_ss_skdecrypt(struct skcipher_request *areq); 29662306a36Sopenharmony_ciint sun8i_ss_skencrypt(struct skcipher_request *areq); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ciint sun8i_ss_get_engine_number(struct sun8i_ss_dev *ss); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ciint sun8i_ss_run_task(struct sun8i_ss_dev *ss, struct sun8i_cipher_req_ctx *rctx, const char *name); 30162306a36Sopenharmony_ciint sun8i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, 30262306a36Sopenharmony_ci unsigned int slen, u8 *dst, unsigned int dlen); 30362306a36Sopenharmony_ciint sun8i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen); 30462306a36Sopenharmony_ciint sun8i_ss_prng_init(struct crypto_tfm *tfm); 30562306a36Sopenharmony_civoid sun8i_ss_prng_exit(struct crypto_tfm *tfm); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ciint sun8i_ss_hash_init_tfm(struct crypto_ahash *tfm); 30862306a36Sopenharmony_civoid sun8i_ss_hash_exit_tfm(struct crypto_ahash *tfm); 30962306a36Sopenharmony_ciint sun8i_ss_hash_init(struct ahash_request *areq); 31062306a36Sopenharmony_ciint sun8i_ss_hash_export(struct ahash_request *areq, void *out); 31162306a36Sopenharmony_ciint sun8i_ss_hash_import(struct ahash_request *areq, const void *in); 31262306a36Sopenharmony_ciint sun8i_ss_hash_final(struct ahash_request *areq); 31362306a36Sopenharmony_ciint sun8i_ss_hash_update(struct ahash_request *areq); 31462306a36Sopenharmony_ciint sun8i_ss_hash_finup(struct ahash_request *areq); 31562306a36Sopenharmony_ciint sun8i_ss_hash_digest(struct ahash_request *areq); 31662306a36Sopenharmony_ciint sun8i_ss_hash_run(struct crypto_engine *engine, void *breq); 31762306a36Sopenharmony_ciint sun8i_ss_hmac_setkey(struct crypto_ahash *ahash, const u8 *key, 31862306a36Sopenharmony_ci unsigned int keylen); 319