162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2021 Aspeed Technology Inc. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#include <crypto/engine.h> 662306a36Sopenharmony_ci#include <crypto/internal/akcipher.h> 762306a36Sopenharmony_ci#include <crypto/internal/rsa.h> 862306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 962306a36Sopenharmony_ci#include <linux/clk.h> 1062306a36Sopenharmony_ci#include <linux/count_zeros.h> 1162306a36Sopenharmony_ci#include <linux/dma-mapping.h> 1262306a36Sopenharmony_ci#include <linux/err.h> 1362306a36Sopenharmony_ci#include <linux/interrupt.h> 1462306a36Sopenharmony_ci#include <linux/kernel.h> 1562306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/of.h> 1862306a36Sopenharmony_ci#include <linux/platform_device.h> 1962306a36Sopenharmony_ci#include <linux/regmap.h> 2062306a36Sopenharmony_ci#include <linux/slab.h> 2162306a36Sopenharmony_ci#include <linux/string.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_ASPEED_DEBUG 2462306a36Sopenharmony_ci#define ACRY_DBG(d, fmt, ...) \ 2562306a36Sopenharmony_ci dev_info((d)->dev, "%s() " fmt, __func__, ##__VA_ARGS__) 2662306a36Sopenharmony_ci#else 2762306a36Sopenharmony_ci#define ACRY_DBG(d, fmt, ...) \ 2862306a36Sopenharmony_ci dev_dbg((d)->dev, "%s() " fmt, __func__, ##__VA_ARGS__) 2962306a36Sopenharmony_ci#endif 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/***************************** 3262306a36Sopenharmony_ci * * 3362306a36Sopenharmony_ci * ACRY register definitions * 3462306a36Sopenharmony_ci * * 3562306a36Sopenharmony_ci * ***************************/ 3662306a36Sopenharmony_ci#define ASPEED_ACRY_TRIGGER 0x000 /* ACRY Engine Control: trigger */ 3762306a36Sopenharmony_ci#define ASPEED_ACRY_DMA_CMD 0x048 /* ACRY Engine Control: Command */ 3862306a36Sopenharmony_ci#define ASPEED_ACRY_DMA_SRC_BASE 0x04C /* ACRY DRAM base address for DMA */ 3962306a36Sopenharmony_ci#define ASPEED_ACRY_DMA_LEN 0x050 /* ACRY Data Length of DMA */ 4062306a36Sopenharmony_ci#define ASPEED_ACRY_RSA_KEY_LEN 0x058 /* ACRY RSA Exp/Mod Key Length (Bits) */ 4162306a36Sopenharmony_ci#define ASPEED_ACRY_INT_MASK 0x3F8 /* ACRY Interrupt Mask */ 4262306a36Sopenharmony_ci#define ASPEED_ACRY_STATUS 0x3FC /* ACRY Interrupt Status */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* rsa trigger */ 4562306a36Sopenharmony_ci#define ACRY_CMD_RSA_TRIGGER BIT(0) 4662306a36Sopenharmony_ci#define ACRY_CMD_DMA_RSA_TRIGGER BIT(1) 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* rsa dma cmd */ 4962306a36Sopenharmony_ci#define ACRY_CMD_DMA_SRAM_MODE_RSA (0x3 << 4) 5062306a36Sopenharmony_ci#define ACRY_CMD_DMEM_AHB BIT(8) 5162306a36Sopenharmony_ci#define ACRY_CMD_DMA_SRAM_AHB_ENGINE 0 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* rsa key len */ 5462306a36Sopenharmony_ci#define RSA_E_BITS_LEN(x) ((x) << 16) 5562306a36Sopenharmony_ci#define RSA_M_BITS_LEN(x) (x) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* acry isr */ 5862306a36Sopenharmony_ci#define ACRY_RSA_ISR BIT(1) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define ASPEED_ACRY_BUFF_SIZE 0x1800 /* DMA buffer size */ 6162306a36Sopenharmony_ci#define ASPEED_ACRY_SRAM_MAX_LEN 2048 /* ACRY SRAM maximum length (Bytes) */ 6262306a36Sopenharmony_ci#define ASPEED_ACRY_RSA_MAX_KEY_LEN 512 /* ACRY RSA maximum key length (Bytes) */ 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#define CRYPTO_FLAGS_BUSY BIT(1) 6562306a36Sopenharmony_ci#define BYTES_PER_DWORD 4 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/***************************** 6862306a36Sopenharmony_ci * * 6962306a36Sopenharmony_ci * AHBC register definitions * 7062306a36Sopenharmony_ci * * 7162306a36Sopenharmony_ci * ***************************/ 7262306a36Sopenharmony_ci#define AHBC_REGION_PROT 0x240 7362306a36Sopenharmony_ci#define REGION_ACRYM BIT(23) 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#define ast_acry_write(acry, val, offset) \ 7662306a36Sopenharmony_ci writel((val), (acry)->regs + (offset)) 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define ast_acry_read(acry, offset) \ 7962306a36Sopenharmony_ci readl((acry)->regs + (offset)) 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistruct aspeed_acry_dev; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_citypedef int (*aspeed_acry_fn_t)(struct aspeed_acry_dev *); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistruct aspeed_acry_dev { 8662306a36Sopenharmony_ci void __iomem *regs; 8762306a36Sopenharmony_ci struct device *dev; 8862306a36Sopenharmony_ci int irq; 8962306a36Sopenharmony_ci struct clk *clk; 9062306a36Sopenharmony_ci struct regmap *ahbc; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci struct akcipher_request *req; 9362306a36Sopenharmony_ci struct tasklet_struct done_task; 9462306a36Sopenharmony_ci aspeed_acry_fn_t resume; 9562306a36Sopenharmony_ci unsigned long flags; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* ACRY output SRAM buffer */ 9862306a36Sopenharmony_ci void __iomem *acry_sram; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* ACRY input DMA buffer */ 10162306a36Sopenharmony_ci void *buf_addr; 10262306a36Sopenharmony_ci dma_addr_t buf_dma_addr; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci struct crypto_engine *crypt_engine_rsa; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci /* ACRY SRAM memory mapped */ 10762306a36Sopenharmony_ci int exp_dw_mapping[ASPEED_ACRY_RSA_MAX_KEY_LEN]; 10862306a36Sopenharmony_ci int mod_dw_mapping[ASPEED_ACRY_RSA_MAX_KEY_LEN]; 10962306a36Sopenharmony_ci int data_byte_mapping[ASPEED_ACRY_SRAM_MAX_LEN]; 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistruct aspeed_acry_ctx { 11362306a36Sopenharmony_ci struct aspeed_acry_dev *acry_dev; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci struct rsa_key key; 11662306a36Sopenharmony_ci int enc; 11762306a36Sopenharmony_ci u8 *n; 11862306a36Sopenharmony_ci u8 *e; 11962306a36Sopenharmony_ci u8 *d; 12062306a36Sopenharmony_ci size_t n_sz; 12162306a36Sopenharmony_ci size_t e_sz; 12262306a36Sopenharmony_ci size_t d_sz; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci aspeed_acry_fn_t trigger; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci struct crypto_akcipher *fallback_tfm; 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistruct aspeed_acry_alg { 13062306a36Sopenharmony_ci struct aspeed_acry_dev *acry_dev; 13162306a36Sopenharmony_ci struct akcipher_engine_alg akcipher; 13262306a36Sopenharmony_ci}; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cienum aspeed_rsa_key_mode { 13562306a36Sopenharmony_ci ASPEED_RSA_EXP_MODE = 0, 13662306a36Sopenharmony_ci ASPEED_RSA_MOD_MODE, 13762306a36Sopenharmony_ci ASPEED_RSA_DATA_MODE, 13862306a36Sopenharmony_ci}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic inline struct akcipher_request * 14162306a36Sopenharmony_ci akcipher_request_cast(struct crypto_async_request *req) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci return container_of(req, struct akcipher_request, base); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic int aspeed_acry_do_fallback(struct akcipher_request *req) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci struct crypto_akcipher *cipher = crypto_akcipher_reqtfm(req); 14962306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(cipher); 15062306a36Sopenharmony_ci int err; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci akcipher_request_set_tfm(req, ctx->fallback_tfm); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if (ctx->enc) 15562306a36Sopenharmony_ci err = crypto_akcipher_encrypt(req); 15662306a36Sopenharmony_ci else 15762306a36Sopenharmony_ci err = crypto_akcipher_decrypt(req); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci akcipher_request_set_tfm(req, cipher); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci return err; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic bool aspeed_acry_need_fallback(struct akcipher_request *req) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci struct crypto_akcipher *cipher = crypto_akcipher_reqtfm(req); 16762306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(cipher); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci return ctx->key.n_sz > ASPEED_ACRY_RSA_MAX_KEY_LEN; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic int aspeed_acry_handle_queue(struct aspeed_acry_dev *acry_dev, 17362306a36Sopenharmony_ci struct akcipher_request *req) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci if (aspeed_acry_need_fallback(req)) { 17662306a36Sopenharmony_ci ACRY_DBG(acry_dev, "SW fallback\n"); 17762306a36Sopenharmony_ci return aspeed_acry_do_fallback(req); 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return crypto_transfer_akcipher_request_to_engine(acry_dev->crypt_engine_rsa, req); 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic int aspeed_acry_do_request(struct crypto_engine *engine, void *areq) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct akcipher_request *req = akcipher_request_cast(areq); 18662306a36Sopenharmony_ci struct crypto_akcipher *cipher = crypto_akcipher_reqtfm(req); 18762306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(cipher); 18862306a36Sopenharmony_ci struct aspeed_acry_dev *acry_dev = ctx->acry_dev; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci acry_dev->req = req; 19162306a36Sopenharmony_ci acry_dev->flags |= CRYPTO_FLAGS_BUSY; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci return ctx->trigger(acry_dev); 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic int aspeed_acry_complete(struct aspeed_acry_dev *acry_dev, int err) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct akcipher_request *req = acry_dev->req; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci acry_dev->flags &= ~CRYPTO_FLAGS_BUSY; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci crypto_finalize_akcipher_request(acry_dev->crypt_engine_rsa, req, err); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci return err; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/* 20862306a36Sopenharmony_ci * Copy Data to DMA buffer for engine used. 20962306a36Sopenharmony_ci */ 21062306a36Sopenharmony_cistatic void aspeed_acry_rsa_sg_copy_to_buffer(struct aspeed_acry_dev *acry_dev, 21162306a36Sopenharmony_ci u8 *buf, struct scatterlist *src, 21262306a36Sopenharmony_ci size_t nbytes) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci static u8 dram_buffer[ASPEED_ACRY_SRAM_MAX_LEN]; 21562306a36Sopenharmony_ci int i = 0, j; 21662306a36Sopenharmony_ci int data_idx; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci ACRY_DBG(acry_dev, "\n"); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci scatterwalk_map_and_copy(dram_buffer, src, 0, nbytes, 0); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci for (j = nbytes - 1; j >= 0; j--) { 22362306a36Sopenharmony_ci data_idx = acry_dev->data_byte_mapping[i]; 22462306a36Sopenharmony_ci buf[data_idx] = dram_buffer[j]; 22562306a36Sopenharmony_ci i++; 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci for (; i < ASPEED_ACRY_SRAM_MAX_LEN; i++) { 22962306a36Sopenharmony_ci data_idx = acry_dev->data_byte_mapping[i]; 23062306a36Sopenharmony_ci buf[data_idx] = 0; 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci/* 23562306a36Sopenharmony_ci * Copy Exp/Mod to DMA buffer for engine used. 23662306a36Sopenharmony_ci * 23762306a36Sopenharmony_ci * Params: 23862306a36Sopenharmony_ci * - mode 0 : Exponential 23962306a36Sopenharmony_ci * - mode 1 : Modulus 24062306a36Sopenharmony_ci * 24162306a36Sopenharmony_ci * Example: 24262306a36Sopenharmony_ci * - DRAM memory layout: 24362306a36Sopenharmony_ci * D[0], D[4], D[8], D[12] 24462306a36Sopenharmony_ci * - ACRY SRAM memory layout should reverse the order of source data: 24562306a36Sopenharmony_ci * D[12], D[8], D[4], D[0] 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_cistatic int aspeed_acry_rsa_ctx_copy(struct aspeed_acry_dev *acry_dev, void *buf, 24862306a36Sopenharmony_ci const void *xbuf, size_t nbytes, 24962306a36Sopenharmony_ci enum aspeed_rsa_key_mode mode) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci const u8 *src = xbuf; 25262306a36Sopenharmony_ci __le32 *dw_buf = buf; 25362306a36Sopenharmony_ci int nbits, ndw; 25462306a36Sopenharmony_ci int i, j, idx; 25562306a36Sopenharmony_ci u32 data = 0; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci ACRY_DBG(acry_dev, "nbytes:%zu, mode:%d\n", nbytes, mode); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (nbytes > ASPEED_ACRY_RSA_MAX_KEY_LEN) 26062306a36Sopenharmony_ci return -ENOMEM; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* Remove the leading zeros */ 26362306a36Sopenharmony_ci while (nbytes > 0 && src[0] == 0) { 26462306a36Sopenharmony_ci src++; 26562306a36Sopenharmony_ci nbytes--; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci nbits = nbytes * 8; 26962306a36Sopenharmony_ci if (nbytes > 0) 27062306a36Sopenharmony_ci nbits -= count_leading_zeros(src[0]) - (BITS_PER_LONG - 8); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci /* double-world alignment */ 27362306a36Sopenharmony_ci ndw = DIV_ROUND_UP(nbytes, BYTES_PER_DWORD); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (nbytes > 0) { 27662306a36Sopenharmony_ci i = BYTES_PER_DWORD - nbytes % BYTES_PER_DWORD; 27762306a36Sopenharmony_ci i %= BYTES_PER_DWORD; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci for (j = ndw; j > 0; j--) { 28062306a36Sopenharmony_ci for (; i < BYTES_PER_DWORD; i++) { 28162306a36Sopenharmony_ci data <<= 8; 28262306a36Sopenharmony_ci data |= *src++; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci i = 0; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (mode == ASPEED_RSA_EXP_MODE) 28862306a36Sopenharmony_ci idx = acry_dev->exp_dw_mapping[j - 1]; 28962306a36Sopenharmony_ci else /* mode == ASPEED_RSA_MOD_MODE */ 29062306a36Sopenharmony_ci idx = acry_dev->mod_dw_mapping[j - 1]; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci dw_buf[idx] = cpu_to_le32(data); 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci return nbits; 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic int aspeed_acry_rsa_transfer(struct aspeed_acry_dev *acry_dev) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct akcipher_request *req = acry_dev->req; 30262306a36Sopenharmony_ci u8 __iomem *sram_buffer = acry_dev->acry_sram; 30362306a36Sopenharmony_ci struct scatterlist *out_sg = req->dst; 30462306a36Sopenharmony_ci static u8 dram_buffer[ASPEED_ACRY_SRAM_MAX_LEN]; 30562306a36Sopenharmony_ci int leading_zero = 1; 30662306a36Sopenharmony_ci int result_nbytes; 30762306a36Sopenharmony_ci int i = 0, j; 30862306a36Sopenharmony_ci int data_idx; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci /* Set Data Memory to AHB(CPU) Access Mode */ 31162306a36Sopenharmony_ci ast_acry_write(acry_dev, ACRY_CMD_DMEM_AHB, ASPEED_ACRY_DMA_CMD); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* Disable ACRY SRAM protection */ 31462306a36Sopenharmony_ci regmap_update_bits(acry_dev->ahbc, AHBC_REGION_PROT, 31562306a36Sopenharmony_ci REGION_ACRYM, 0); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci result_nbytes = ASPEED_ACRY_SRAM_MAX_LEN; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci for (j = ASPEED_ACRY_SRAM_MAX_LEN - 1; j >= 0; j--) { 32062306a36Sopenharmony_ci data_idx = acry_dev->data_byte_mapping[j]; 32162306a36Sopenharmony_ci if (readb(sram_buffer + data_idx) == 0 && leading_zero) { 32262306a36Sopenharmony_ci result_nbytes--; 32362306a36Sopenharmony_ci } else { 32462306a36Sopenharmony_ci leading_zero = 0; 32562306a36Sopenharmony_ci dram_buffer[i] = readb(sram_buffer + data_idx); 32662306a36Sopenharmony_ci i++; 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci ACRY_DBG(acry_dev, "result_nbytes:%d, req->dst_len:%d\n", 33162306a36Sopenharmony_ci result_nbytes, req->dst_len); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (result_nbytes <= req->dst_len) { 33462306a36Sopenharmony_ci scatterwalk_map_and_copy(dram_buffer, out_sg, 0, result_nbytes, 33562306a36Sopenharmony_ci 1); 33662306a36Sopenharmony_ci req->dst_len = result_nbytes; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci } else { 33962306a36Sopenharmony_ci dev_err(acry_dev->dev, "RSA engine error!\n"); 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci memzero_explicit(acry_dev->buf_addr, ASPEED_ACRY_BUFF_SIZE); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci return aspeed_acry_complete(acry_dev, 0); 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic int aspeed_acry_rsa_trigger(struct aspeed_acry_dev *acry_dev) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci struct akcipher_request *req = acry_dev->req; 35062306a36Sopenharmony_ci struct crypto_akcipher *cipher = crypto_akcipher_reqtfm(req); 35162306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(cipher); 35262306a36Sopenharmony_ci int ne, nm; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci if (!ctx->n || !ctx->n_sz) { 35562306a36Sopenharmony_ci dev_err(acry_dev->dev, "%s: key n is not set\n", __func__); 35662306a36Sopenharmony_ci return -EINVAL; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci memzero_explicit(acry_dev->buf_addr, ASPEED_ACRY_BUFF_SIZE); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci /* Copy source data to DMA buffer */ 36262306a36Sopenharmony_ci aspeed_acry_rsa_sg_copy_to_buffer(acry_dev, acry_dev->buf_addr, 36362306a36Sopenharmony_ci req->src, req->src_len); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci nm = aspeed_acry_rsa_ctx_copy(acry_dev, acry_dev->buf_addr, ctx->n, 36662306a36Sopenharmony_ci ctx->n_sz, ASPEED_RSA_MOD_MODE); 36762306a36Sopenharmony_ci if (ctx->enc) { 36862306a36Sopenharmony_ci if (!ctx->e || !ctx->e_sz) { 36962306a36Sopenharmony_ci dev_err(acry_dev->dev, "%s: key e is not set\n", 37062306a36Sopenharmony_ci __func__); 37162306a36Sopenharmony_ci return -EINVAL; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci /* Copy key e to DMA buffer */ 37462306a36Sopenharmony_ci ne = aspeed_acry_rsa_ctx_copy(acry_dev, acry_dev->buf_addr, 37562306a36Sopenharmony_ci ctx->e, ctx->e_sz, 37662306a36Sopenharmony_ci ASPEED_RSA_EXP_MODE); 37762306a36Sopenharmony_ci } else { 37862306a36Sopenharmony_ci if (!ctx->d || !ctx->d_sz) { 37962306a36Sopenharmony_ci dev_err(acry_dev->dev, "%s: key d is not set\n", 38062306a36Sopenharmony_ci __func__); 38162306a36Sopenharmony_ci return -EINVAL; 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci /* Copy key d to DMA buffer */ 38462306a36Sopenharmony_ci ne = aspeed_acry_rsa_ctx_copy(acry_dev, acry_dev->buf_addr, 38562306a36Sopenharmony_ci ctx->key.d, ctx->key.d_sz, 38662306a36Sopenharmony_ci ASPEED_RSA_EXP_MODE); 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci ast_acry_write(acry_dev, acry_dev->buf_dma_addr, 39062306a36Sopenharmony_ci ASPEED_ACRY_DMA_SRC_BASE); 39162306a36Sopenharmony_ci ast_acry_write(acry_dev, (ne << 16) + nm, 39262306a36Sopenharmony_ci ASPEED_ACRY_RSA_KEY_LEN); 39362306a36Sopenharmony_ci ast_acry_write(acry_dev, ASPEED_ACRY_BUFF_SIZE, 39462306a36Sopenharmony_ci ASPEED_ACRY_DMA_LEN); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci acry_dev->resume = aspeed_acry_rsa_transfer; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci /* Enable ACRY SRAM protection */ 39962306a36Sopenharmony_ci regmap_update_bits(acry_dev->ahbc, AHBC_REGION_PROT, 40062306a36Sopenharmony_ci REGION_ACRYM, REGION_ACRYM); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci ast_acry_write(acry_dev, ACRY_RSA_ISR, ASPEED_ACRY_INT_MASK); 40362306a36Sopenharmony_ci ast_acry_write(acry_dev, ACRY_CMD_DMA_SRAM_MODE_RSA | 40462306a36Sopenharmony_ci ACRY_CMD_DMA_SRAM_AHB_ENGINE, ASPEED_ACRY_DMA_CMD); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci /* Trigger RSA engines */ 40762306a36Sopenharmony_ci ast_acry_write(acry_dev, ACRY_CMD_RSA_TRIGGER | 40862306a36Sopenharmony_ci ACRY_CMD_DMA_RSA_TRIGGER, ASPEED_ACRY_TRIGGER); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci return 0; 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_cistatic int aspeed_acry_rsa_enc(struct akcipher_request *req) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci struct crypto_akcipher *cipher = crypto_akcipher_reqtfm(req); 41662306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(cipher); 41762306a36Sopenharmony_ci struct aspeed_acry_dev *acry_dev = ctx->acry_dev; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci ctx->trigger = aspeed_acry_rsa_trigger; 42062306a36Sopenharmony_ci ctx->enc = 1; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci return aspeed_acry_handle_queue(acry_dev, req); 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic int aspeed_acry_rsa_dec(struct akcipher_request *req) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci struct crypto_akcipher *cipher = crypto_akcipher_reqtfm(req); 42862306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(cipher); 42962306a36Sopenharmony_ci struct aspeed_acry_dev *acry_dev = ctx->acry_dev; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci ctx->trigger = aspeed_acry_rsa_trigger; 43262306a36Sopenharmony_ci ctx->enc = 0; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci return aspeed_acry_handle_queue(acry_dev, req); 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic u8 *aspeed_rsa_key_copy(u8 *src, size_t len) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci return kmemdup(src, len, GFP_KERNEL); 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic int aspeed_rsa_set_n(struct aspeed_acry_ctx *ctx, u8 *value, 44362306a36Sopenharmony_ci size_t len) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci ctx->n_sz = len; 44662306a36Sopenharmony_ci ctx->n = aspeed_rsa_key_copy(value, len); 44762306a36Sopenharmony_ci if (!ctx->n) 44862306a36Sopenharmony_ci return -ENOMEM; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci return 0; 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_cistatic int aspeed_rsa_set_e(struct aspeed_acry_ctx *ctx, u8 *value, 45462306a36Sopenharmony_ci size_t len) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci ctx->e_sz = len; 45762306a36Sopenharmony_ci ctx->e = aspeed_rsa_key_copy(value, len); 45862306a36Sopenharmony_ci if (!ctx->e) 45962306a36Sopenharmony_ci return -ENOMEM; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci return 0; 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistatic int aspeed_rsa_set_d(struct aspeed_acry_ctx *ctx, u8 *value, 46562306a36Sopenharmony_ci size_t len) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci ctx->d_sz = len; 46862306a36Sopenharmony_ci ctx->d = aspeed_rsa_key_copy(value, len); 46962306a36Sopenharmony_ci if (!ctx->d) 47062306a36Sopenharmony_ci return -ENOMEM; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci return 0; 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic void aspeed_rsa_key_free(struct aspeed_acry_ctx *ctx) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci kfree_sensitive(ctx->n); 47862306a36Sopenharmony_ci kfree_sensitive(ctx->e); 47962306a36Sopenharmony_ci kfree_sensitive(ctx->d); 48062306a36Sopenharmony_ci ctx->n_sz = 0; 48162306a36Sopenharmony_ci ctx->e_sz = 0; 48262306a36Sopenharmony_ci ctx->d_sz = 0; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic int aspeed_acry_rsa_setkey(struct crypto_akcipher *tfm, const void *key, 48662306a36Sopenharmony_ci unsigned int keylen, int priv) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(tfm); 48962306a36Sopenharmony_ci struct aspeed_acry_dev *acry_dev = ctx->acry_dev; 49062306a36Sopenharmony_ci int ret; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci if (priv) 49362306a36Sopenharmony_ci ret = rsa_parse_priv_key(&ctx->key, key, keylen); 49462306a36Sopenharmony_ci else 49562306a36Sopenharmony_ci ret = rsa_parse_pub_key(&ctx->key, key, keylen); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci if (ret) { 49862306a36Sopenharmony_ci dev_err(acry_dev->dev, "rsa parse key failed, ret:0x%x\n", 49962306a36Sopenharmony_ci ret); 50062306a36Sopenharmony_ci return ret; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci /* Aspeed engine supports up to 4096 bits, 50462306a36Sopenharmony_ci * Use software fallback instead. 50562306a36Sopenharmony_ci */ 50662306a36Sopenharmony_ci if (ctx->key.n_sz > ASPEED_ACRY_RSA_MAX_KEY_LEN) 50762306a36Sopenharmony_ci return 0; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci ret = aspeed_rsa_set_n(ctx, (u8 *)ctx->key.n, ctx->key.n_sz); 51062306a36Sopenharmony_ci if (ret) 51162306a36Sopenharmony_ci goto err; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci ret = aspeed_rsa_set_e(ctx, (u8 *)ctx->key.e, ctx->key.e_sz); 51462306a36Sopenharmony_ci if (ret) 51562306a36Sopenharmony_ci goto err; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci if (priv) { 51862306a36Sopenharmony_ci ret = aspeed_rsa_set_d(ctx, (u8 *)ctx->key.d, ctx->key.d_sz); 51962306a36Sopenharmony_ci if (ret) 52062306a36Sopenharmony_ci goto err; 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci return 0; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_cierr: 52662306a36Sopenharmony_ci dev_err(acry_dev->dev, "rsa set key failed\n"); 52762306a36Sopenharmony_ci aspeed_rsa_key_free(ctx); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci return ret; 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_cistatic int aspeed_acry_rsa_set_pub_key(struct crypto_akcipher *tfm, 53362306a36Sopenharmony_ci const void *key, 53462306a36Sopenharmony_ci unsigned int keylen) 53562306a36Sopenharmony_ci{ 53662306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(tfm); 53762306a36Sopenharmony_ci int ret; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci ret = crypto_akcipher_set_pub_key(ctx->fallback_tfm, key, keylen); 54062306a36Sopenharmony_ci if (ret) 54162306a36Sopenharmony_ci return ret; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci return aspeed_acry_rsa_setkey(tfm, key, keylen, 0); 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic int aspeed_acry_rsa_set_priv_key(struct crypto_akcipher *tfm, 54762306a36Sopenharmony_ci const void *key, 54862306a36Sopenharmony_ci unsigned int keylen) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(tfm); 55162306a36Sopenharmony_ci int ret; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci ret = crypto_akcipher_set_priv_key(ctx->fallback_tfm, key, keylen); 55462306a36Sopenharmony_ci if (ret) 55562306a36Sopenharmony_ci return ret; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci return aspeed_acry_rsa_setkey(tfm, key, keylen, 1); 55862306a36Sopenharmony_ci} 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_cistatic unsigned int aspeed_acry_rsa_max_size(struct crypto_akcipher *tfm) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(tfm); 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci if (ctx->key.n_sz > ASPEED_ACRY_RSA_MAX_KEY_LEN) 56562306a36Sopenharmony_ci return crypto_akcipher_maxsize(ctx->fallback_tfm); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci return ctx->n_sz; 56862306a36Sopenharmony_ci} 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_cistatic int aspeed_acry_rsa_init_tfm(struct crypto_akcipher *tfm) 57162306a36Sopenharmony_ci{ 57262306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(tfm); 57362306a36Sopenharmony_ci struct akcipher_alg *alg = crypto_akcipher_alg(tfm); 57462306a36Sopenharmony_ci const char *name = crypto_tfm_alg_name(&tfm->base); 57562306a36Sopenharmony_ci struct aspeed_acry_alg *acry_alg; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci acry_alg = container_of(alg, struct aspeed_acry_alg, akcipher.base); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci ctx->acry_dev = acry_alg->acry_dev; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci ctx->fallback_tfm = crypto_alloc_akcipher(name, 0, CRYPTO_ALG_ASYNC | 58262306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 58362306a36Sopenharmony_ci if (IS_ERR(ctx->fallback_tfm)) { 58462306a36Sopenharmony_ci dev_err(ctx->acry_dev->dev, "ERROR: Cannot allocate fallback for %s %ld\n", 58562306a36Sopenharmony_ci name, PTR_ERR(ctx->fallback_tfm)); 58662306a36Sopenharmony_ci return PTR_ERR(ctx->fallback_tfm); 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci return 0; 59062306a36Sopenharmony_ci} 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_cistatic void aspeed_acry_rsa_exit_tfm(struct crypto_akcipher *tfm) 59362306a36Sopenharmony_ci{ 59462306a36Sopenharmony_ci struct aspeed_acry_ctx *ctx = akcipher_tfm_ctx(tfm); 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci crypto_free_akcipher(ctx->fallback_tfm); 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic struct aspeed_acry_alg aspeed_acry_akcipher_algs[] = { 60062306a36Sopenharmony_ci { 60162306a36Sopenharmony_ci .akcipher.base = { 60262306a36Sopenharmony_ci .encrypt = aspeed_acry_rsa_enc, 60362306a36Sopenharmony_ci .decrypt = aspeed_acry_rsa_dec, 60462306a36Sopenharmony_ci .sign = aspeed_acry_rsa_dec, 60562306a36Sopenharmony_ci .verify = aspeed_acry_rsa_enc, 60662306a36Sopenharmony_ci .set_pub_key = aspeed_acry_rsa_set_pub_key, 60762306a36Sopenharmony_ci .set_priv_key = aspeed_acry_rsa_set_priv_key, 60862306a36Sopenharmony_ci .max_size = aspeed_acry_rsa_max_size, 60962306a36Sopenharmony_ci .init = aspeed_acry_rsa_init_tfm, 61062306a36Sopenharmony_ci .exit = aspeed_acry_rsa_exit_tfm, 61162306a36Sopenharmony_ci .base = { 61262306a36Sopenharmony_ci .cra_name = "rsa", 61362306a36Sopenharmony_ci .cra_driver_name = "aspeed-rsa", 61462306a36Sopenharmony_ci .cra_priority = 300, 61562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_AKCIPHER | 61662306a36Sopenharmony_ci CRYPTO_ALG_ASYNC | 61762306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 61862306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 61962306a36Sopenharmony_ci .cra_module = THIS_MODULE, 62062306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct aspeed_acry_ctx), 62162306a36Sopenharmony_ci }, 62262306a36Sopenharmony_ci }, 62362306a36Sopenharmony_ci .akcipher.op = { 62462306a36Sopenharmony_ci .do_one_request = aspeed_acry_do_request, 62562306a36Sopenharmony_ci }, 62662306a36Sopenharmony_ci }, 62762306a36Sopenharmony_ci}; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cistatic void aspeed_acry_register(struct aspeed_acry_dev *acry_dev) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci int i, rc; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(aspeed_acry_akcipher_algs); i++) { 63462306a36Sopenharmony_ci aspeed_acry_akcipher_algs[i].acry_dev = acry_dev; 63562306a36Sopenharmony_ci rc = crypto_engine_register_akcipher(&aspeed_acry_akcipher_algs[i].akcipher); 63662306a36Sopenharmony_ci if (rc) { 63762306a36Sopenharmony_ci ACRY_DBG(acry_dev, "Failed to register %s\n", 63862306a36Sopenharmony_ci aspeed_acry_akcipher_algs[i].akcipher.base.base.cra_name); 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic void aspeed_acry_unregister(struct aspeed_acry_dev *acry_dev) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci int i; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(aspeed_acry_akcipher_algs); i++) 64862306a36Sopenharmony_ci crypto_engine_unregister_akcipher(&aspeed_acry_akcipher_algs[i].akcipher); 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci/* ACRY interrupt service routine. */ 65262306a36Sopenharmony_cistatic irqreturn_t aspeed_acry_irq(int irq, void *dev) 65362306a36Sopenharmony_ci{ 65462306a36Sopenharmony_ci struct aspeed_acry_dev *acry_dev = (struct aspeed_acry_dev *)dev; 65562306a36Sopenharmony_ci u32 sts; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci sts = ast_acry_read(acry_dev, ASPEED_ACRY_STATUS); 65862306a36Sopenharmony_ci ast_acry_write(acry_dev, sts, ASPEED_ACRY_STATUS); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci ACRY_DBG(acry_dev, "irq sts:0x%x\n", sts); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci if (sts & ACRY_RSA_ISR) { 66362306a36Sopenharmony_ci /* Stop RSA engine */ 66462306a36Sopenharmony_ci ast_acry_write(acry_dev, 0, ASPEED_ACRY_TRIGGER); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci if (acry_dev->flags & CRYPTO_FLAGS_BUSY) 66762306a36Sopenharmony_ci tasklet_schedule(&acry_dev->done_task); 66862306a36Sopenharmony_ci else 66962306a36Sopenharmony_ci dev_err(acry_dev->dev, "RSA no active requests.\n"); 67062306a36Sopenharmony_ci } 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci return IRQ_HANDLED; 67362306a36Sopenharmony_ci} 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci/* 67662306a36Sopenharmony_ci * ACRY SRAM has its own memory layout. 67762306a36Sopenharmony_ci * Set the DRAM to SRAM indexing for future used. 67862306a36Sopenharmony_ci */ 67962306a36Sopenharmony_cistatic void aspeed_acry_sram_mapping(struct aspeed_acry_dev *acry_dev) 68062306a36Sopenharmony_ci{ 68162306a36Sopenharmony_ci int i, j = 0; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci for (i = 0; i < (ASPEED_ACRY_SRAM_MAX_LEN / BYTES_PER_DWORD); i++) { 68462306a36Sopenharmony_ci acry_dev->exp_dw_mapping[i] = j; 68562306a36Sopenharmony_ci acry_dev->mod_dw_mapping[i] = j + 4; 68662306a36Sopenharmony_ci acry_dev->data_byte_mapping[(i * 4)] = (j + 8) * 4; 68762306a36Sopenharmony_ci acry_dev->data_byte_mapping[(i * 4) + 1] = (j + 8) * 4 + 1; 68862306a36Sopenharmony_ci acry_dev->data_byte_mapping[(i * 4) + 2] = (j + 8) * 4 + 2; 68962306a36Sopenharmony_ci acry_dev->data_byte_mapping[(i * 4) + 3] = (j + 8) * 4 + 3; 69062306a36Sopenharmony_ci j++; 69162306a36Sopenharmony_ci j = j % 4 ? j : j + 8; 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci} 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_cistatic void aspeed_acry_done_task(unsigned long data) 69662306a36Sopenharmony_ci{ 69762306a36Sopenharmony_ci struct aspeed_acry_dev *acry_dev = (struct aspeed_acry_dev *)data; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci (void)acry_dev->resume(acry_dev); 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_cistatic const struct of_device_id aspeed_acry_of_matches[] = { 70362306a36Sopenharmony_ci { .compatible = "aspeed,ast2600-acry", }, 70462306a36Sopenharmony_ci {}, 70562306a36Sopenharmony_ci}; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_cistatic int aspeed_acry_probe(struct platform_device *pdev) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci struct aspeed_acry_dev *acry_dev; 71062306a36Sopenharmony_ci struct device *dev = &pdev->dev; 71162306a36Sopenharmony_ci int rc; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci acry_dev = devm_kzalloc(dev, sizeof(struct aspeed_acry_dev), 71462306a36Sopenharmony_ci GFP_KERNEL); 71562306a36Sopenharmony_ci if (!acry_dev) 71662306a36Sopenharmony_ci return -ENOMEM; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci acry_dev->dev = dev; 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci platform_set_drvdata(pdev, acry_dev); 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci acry_dev->regs = devm_platform_ioremap_resource(pdev, 0); 72362306a36Sopenharmony_ci if (IS_ERR(acry_dev->regs)) 72462306a36Sopenharmony_ci return PTR_ERR(acry_dev->regs); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci acry_dev->acry_sram = devm_platform_ioremap_resource(pdev, 1); 72762306a36Sopenharmony_ci if (IS_ERR(acry_dev->acry_sram)) 72862306a36Sopenharmony_ci return PTR_ERR(acry_dev->acry_sram); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci /* Get irq number and register it */ 73162306a36Sopenharmony_ci acry_dev->irq = platform_get_irq(pdev, 0); 73262306a36Sopenharmony_ci if (acry_dev->irq < 0) 73362306a36Sopenharmony_ci return -ENXIO; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci rc = devm_request_irq(dev, acry_dev->irq, aspeed_acry_irq, 0, 73662306a36Sopenharmony_ci dev_name(dev), acry_dev); 73762306a36Sopenharmony_ci if (rc) { 73862306a36Sopenharmony_ci dev_err(dev, "Failed to request irq.\n"); 73962306a36Sopenharmony_ci return rc; 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci acry_dev->clk = devm_clk_get_enabled(dev, NULL); 74362306a36Sopenharmony_ci if (IS_ERR(acry_dev->clk)) { 74462306a36Sopenharmony_ci dev_err(dev, "Failed to get acry clk\n"); 74562306a36Sopenharmony_ci return PTR_ERR(acry_dev->clk); 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci acry_dev->ahbc = syscon_regmap_lookup_by_phandle(dev->of_node, 74962306a36Sopenharmony_ci "aspeed,ahbc"); 75062306a36Sopenharmony_ci if (IS_ERR(acry_dev->ahbc)) { 75162306a36Sopenharmony_ci dev_err(dev, "Failed to get AHBC regmap\n"); 75262306a36Sopenharmony_ci return -ENODEV; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci /* Initialize crypto hardware engine structure for RSA */ 75662306a36Sopenharmony_ci acry_dev->crypt_engine_rsa = crypto_engine_alloc_init(dev, true); 75762306a36Sopenharmony_ci if (!acry_dev->crypt_engine_rsa) { 75862306a36Sopenharmony_ci rc = -ENOMEM; 75962306a36Sopenharmony_ci goto clk_exit; 76062306a36Sopenharmony_ci } 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci rc = crypto_engine_start(acry_dev->crypt_engine_rsa); 76362306a36Sopenharmony_ci if (rc) 76462306a36Sopenharmony_ci goto err_engine_rsa_start; 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci tasklet_init(&acry_dev->done_task, aspeed_acry_done_task, 76762306a36Sopenharmony_ci (unsigned long)acry_dev); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci /* Set Data Memory to AHB(CPU) Access Mode */ 77062306a36Sopenharmony_ci ast_acry_write(acry_dev, ACRY_CMD_DMEM_AHB, ASPEED_ACRY_DMA_CMD); 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci /* Initialize ACRY SRAM index */ 77362306a36Sopenharmony_ci aspeed_acry_sram_mapping(acry_dev); 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci acry_dev->buf_addr = dmam_alloc_coherent(dev, ASPEED_ACRY_BUFF_SIZE, 77662306a36Sopenharmony_ci &acry_dev->buf_dma_addr, 77762306a36Sopenharmony_ci GFP_KERNEL); 77862306a36Sopenharmony_ci if (!acry_dev->buf_addr) { 77962306a36Sopenharmony_ci rc = -ENOMEM; 78062306a36Sopenharmony_ci goto err_engine_rsa_start; 78162306a36Sopenharmony_ci } 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci aspeed_acry_register(acry_dev); 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci dev_info(dev, "Aspeed ACRY Accelerator successfully registered\n"); 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci return 0; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_cierr_engine_rsa_start: 79062306a36Sopenharmony_ci crypto_engine_exit(acry_dev->crypt_engine_rsa); 79162306a36Sopenharmony_ciclk_exit: 79262306a36Sopenharmony_ci clk_disable_unprepare(acry_dev->clk); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci return rc; 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic int aspeed_acry_remove(struct platform_device *pdev) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci struct aspeed_acry_dev *acry_dev = platform_get_drvdata(pdev); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci aspeed_acry_unregister(acry_dev); 80262306a36Sopenharmony_ci crypto_engine_exit(acry_dev->crypt_engine_rsa); 80362306a36Sopenharmony_ci tasklet_kill(&acry_dev->done_task); 80462306a36Sopenharmony_ci clk_disable_unprepare(acry_dev->clk); 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci return 0; 80762306a36Sopenharmony_ci} 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, aspeed_acry_of_matches); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_cistatic struct platform_driver aspeed_acry_driver = { 81262306a36Sopenharmony_ci .probe = aspeed_acry_probe, 81362306a36Sopenharmony_ci .remove = aspeed_acry_remove, 81462306a36Sopenharmony_ci .driver = { 81562306a36Sopenharmony_ci .name = KBUILD_MODNAME, 81662306a36Sopenharmony_ci .of_match_table = aspeed_acry_of_matches, 81762306a36Sopenharmony_ci }, 81862306a36Sopenharmony_ci}; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_cimodule_platform_driver(aspeed_acry_driver); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ciMODULE_AUTHOR("Neal Liu <neal_liu@aspeedtech.com>"); 82362306a36Sopenharmony_ciMODULE_DESCRIPTION("ASPEED ACRY driver for hardware RSA Engine"); 82462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 825