162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Crypto acceleration support for Rockchip RK3288 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Zain Wang <zain.wang@rock-chips.com> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Some ideas are from marvell/cesa.c and s5p-sss.c driver. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <asm/unaligned.h> 1362306a36Sopenharmony_ci#include <crypto/internal/hash.h> 1462306a36Sopenharmony_ci#include <linux/device.h> 1562306a36Sopenharmony_ci#include <linux/err.h> 1662306a36Sopenharmony_ci#include <linux/iopoll.h> 1762306a36Sopenharmony_ci#include <linux/kernel.h> 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci#include <linux/string.h> 2062306a36Sopenharmony_ci#include "rk3288_crypto.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* 2362306a36Sopenharmony_ci * IC can not process zero message hash, 2462306a36Sopenharmony_ci * so we put the fixed hash out when met zero message. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic bool rk_ahash_need_fallback(struct ahash_request *req) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci struct scatterlist *sg; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci sg = req->src; 3262306a36Sopenharmony_ci while (sg) { 3362306a36Sopenharmony_ci if (!IS_ALIGNED(sg->offset, sizeof(u32))) { 3462306a36Sopenharmony_ci return true; 3562306a36Sopenharmony_ci } 3662306a36Sopenharmony_ci if (sg->length % 4) { 3762306a36Sopenharmony_ci return true; 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci sg = sg_next(sg); 4062306a36Sopenharmony_ci } 4162306a36Sopenharmony_ci return false; 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic int rk_ahash_digest_fb(struct ahash_request *areq) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); 4762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 4862306a36Sopenharmony_ci struct rk_ahash_ctx *tfmctx = crypto_ahash_ctx(tfm); 4962306a36Sopenharmony_ci struct ahash_alg *alg = crypto_ahash_alg(tfm); 5062306a36Sopenharmony_ci struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash.base); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci algt->stat_fb++; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm); 5562306a36Sopenharmony_ci rctx->fallback_req.base.flags = areq->base.flags & 5662306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci rctx->fallback_req.nbytes = areq->nbytes; 5962306a36Sopenharmony_ci rctx->fallback_req.src = areq->src; 6062306a36Sopenharmony_ci rctx->fallback_req.result = areq->result; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci return crypto_ahash_digest(&rctx->fallback_req); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic int zero_message_process(struct ahash_request *req) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 6862306a36Sopenharmony_ci int rk_digest_size = crypto_ahash_digestsize(tfm); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci switch (rk_digest_size) { 7162306a36Sopenharmony_ci case SHA1_DIGEST_SIZE: 7262306a36Sopenharmony_ci memcpy(req->result, sha1_zero_message_hash, rk_digest_size); 7362306a36Sopenharmony_ci break; 7462306a36Sopenharmony_ci case SHA256_DIGEST_SIZE: 7562306a36Sopenharmony_ci memcpy(req->result, sha256_zero_message_hash, rk_digest_size); 7662306a36Sopenharmony_ci break; 7762306a36Sopenharmony_ci case MD5_DIGEST_SIZE: 7862306a36Sopenharmony_ci memcpy(req->result, md5_zero_message_hash, rk_digest_size); 7962306a36Sopenharmony_ci break; 8062306a36Sopenharmony_ci default: 8162306a36Sopenharmony_ci return -EINVAL; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic void rk_ahash_reg_init(struct ahash_request *req, 8862306a36Sopenharmony_ci struct rk_crypto_info *dev) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(req); 9162306a36Sopenharmony_ci int reg_status; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci reg_status = CRYPTO_READ(dev, RK_CRYPTO_CTRL) | 9462306a36Sopenharmony_ci RK_CRYPTO_HASH_FLUSH | _SBF(0xffff, 16); 9562306a36Sopenharmony_ci CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, reg_status); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci reg_status = CRYPTO_READ(dev, RK_CRYPTO_CTRL); 9862306a36Sopenharmony_ci reg_status &= (~RK_CRYPTO_HASH_FLUSH); 9962306a36Sopenharmony_ci reg_status |= _SBF(0xffff, 16); 10062306a36Sopenharmony_ci CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, reg_status); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci memset_io(dev->reg + RK_CRYPTO_HASH_DOUT_0, 0, 32); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci CRYPTO_WRITE(dev, RK_CRYPTO_INTENA, RK_CRYPTO_HRDMA_ERR_ENA | 10562306a36Sopenharmony_ci RK_CRYPTO_HRDMA_DONE_ENA); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci CRYPTO_WRITE(dev, RK_CRYPTO_INTSTS, RK_CRYPTO_HRDMA_ERR_INT | 10862306a36Sopenharmony_ci RK_CRYPTO_HRDMA_DONE_INT); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci CRYPTO_WRITE(dev, RK_CRYPTO_HASH_CTRL, rctx->mode | 11162306a36Sopenharmony_ci RK_CRYPTO_HASH_SWAP_DO); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci CRYPTO_WRITE(dev, RK_CRYPTO_CONF, RK_CRYPTO_BYTESWAP_HRFIFO | 11462306a36Sopenharmony_ci RK_CRYPTO_BYTESWAP_BRFIFO | 11562306a36Sopenharmony_ci RK_CRYPTO_BYTESWAP_BTFIFO); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci CRYPTO_WRITE(dev, RK_CRYPTO_HASH_MSG_LEN, req->nbytes); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic int rk_ahash_init(struct ahash_request *req) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(req); 12362306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 12462306a36Sopenharmony_ci struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); 12762306a36Sopenharmony_ci rctx->fallback_req.base.flags = req->base.flags & 12862306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci return crypto_ahash_init(&rctx->fallback_req); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic int rk_ahash_update(struct ahash_request *req) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(req); 13662306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 13762306a36Sopenharmony_ci struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); 14062306a36Sopenharmony_ci rctx->fallback_req.base.flags = req->base.flags & 14162306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP; 14262306a36Sopenharmony_ci rctx->fallback_req.nbytes = req->nbytes; 14362306a36Sopenharmony_ci rctx->fallback_req.src = req->src; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci return crypto_ahash_update(&rctx->fallback_req); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic int rk_ahash_final(struct ahash_request *req) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(req); 15162306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 15262306a36Sopenharmony_ci struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); 15562306a36Sopenharmony_ci rctx->fallback_req.base.flags = req->base.flags & 15662306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP; 15762306a36Sopenharmony_ci rctx->fallback_req.result = req->result; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci return crypto_ahash_final(&rctx->fallback_req); 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic int rk_ahash_finup(struct ahash_request *req) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(req); 16562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 16662306a36Sopenharmony_ci struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); 16962306a36Sopenharmony_ci rctx->fallback_req.base.flags = req->base.flags & 17062306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci rctx->fallback_req.nbytes = req->nbytes; 17362306a36Sopenharmony_ci rctx->fallback_req.src = req->src; 17462306a36Sopenharmony_ci rctx->fallback_req.result = req->result; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci return crypto_ahash_finup(&rctx->fallback_req); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic int rk_ahash_import(struct ahash_request *req, const void *in) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(req); 18262306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 18362306a36Sopenharmony_ci struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); 18662306a36Sopenharmony_ci rctx->fallback_req.base.flags = req->base.flags & 18762306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci return crypto_ahash_import(&rctx->fallback_req, in); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic int rk_ahash_export(struct ahash_request *req, void *out) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(req); 19562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 19662306a36Sopenharmony_ci struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); 19962306a36Sopenharmony_ci rctx->fallback_req.base.flags = req->base.flags & 20062306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci return crypto_ahash_export(&rctx->fallback_req, out); 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic int rk_ahash_digest(struct ahash_request *req) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(req); 20862306a36Sopenharmony_ci struct rk_crypto_info *dev; 20962306a36Sopenharmony_ci struct crypto_engine *engine; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci if (rk_ahash_need_fallback(req)) 21262306a36Sopenharmony_ci return rk_ahash_digest_fb(req); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (!req->nbytes) 21562306a36Sopenharmony_ci return zero_message_process(req); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci dev = get_rk_crypto(); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci rctx->dev = dev; 22062306a36Sopenharmony_ci engine = dev->engine; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci return crypto_transfer_hash_request_to_engine(engine, req); 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic void crypto_ahash_dma_start(struct rk_crypto_info *dev, struct scatterlist *sg) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAS, sg_dma_address(sg)); 22862306a36Sopenharmony_ci CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAL, sg_dma_len(sg) / 4); 22962306a36Sopenharmony_ci CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, RK_CRYPTO_HASH_START | 23062306a36Sopenharmony_ci (RK_CRYPTO_HASH_START << 16)); 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic int rk_hash_prepare(struct crypto_engine *engine, void *breq) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci struct ahash_request *areq = container_of(breq, struct ahash_request, base); 23662306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); 23762306a36Sopenharmony_ci struct rk_crypto_info *rkc = rctx->dev; 23862306a36Sopenharmony_ci int ret; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci ret = dma_map_sg(rkc->dev, areq->src, sg_nents(areq->src), DMA_TO_DEVICE); 24162306a36Sopenharmony_ci if (ret <= 0) 24262306a36Sopenharmony_ci return -EINVAL; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci rctx->nrsg = ret; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci return 0; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic void rk_hash_unprepare(struct crypto_engine *engine, void *breq) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci struct ahash_request *areq = container_of(breq, struct ahash_request, base); 25262306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); 25362306a36Sopenharmony_ci struct rk_crypto_info *rkc = rctx->dev; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci dma_unmap_sg(rkc->dev, areq->src, rctx->nrsg, DMA_TO_DEVICE); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic int rk_hash_run(struct crypto_engine *engine, void *breq) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci struct ahash_request *areq = container_of(breq, struct ahash_request, base); 26162306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 26262306a36Sopenharmony_ci struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); 26362306a36Sopenharmony_ci struct ahash_alg *alg = crypto_ahash_alg(tfm); 26462306a36Sopenharmony_ci struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash.base); 26562306a36Sopenharmony_ci struct scatterlist *sg = areq->src; 26662306a36Sopenharmony_ci struct rk_crypto_info *rkc = rctx->dev; 26762306a36Sopenharmony_ci int err; 26862306a36Sopenharmony_ci int i; 26962306a36Sopenharmony_ci u32 v; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci err = pm_runtime_resume_and_get(rkc->dev); 27262306a36Sopenharmony_ci if (err) 27362306a36Sopenharmony_ci return err; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci err = rk_hash_prepare(engine, breq); 27662306a36Sopenharmony_ci if (err) 27762306a36Sopenharmony_ci goto theend; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci rctx->mode = 0; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci algt->stat_req++; 28262306a36Sopenharmony_ci rkc->nreq++; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci switch (crypto_ahash_digestsize(tfm)) { 28562306a36Sopenharmony_ci case SHA1_DIGEST_SIZE: 28662306a36Sopenharmony_ci rctx->mode = RK_CRYPTO_HASH_SHA1; 28762306a36Sopenharmony_ci break; 28862306a36Sopenharmony_ci case SHA256_DIGEST_SIZE: 28962306a36Sopenharmony_ci rctx->mode = RK_CRYPTO_HASH_SHA256; 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci case MD5_DIGEST_SIZE: 29262306a36Sopenharmony_ci rctx->mode = RK_CRYPTO_HASH_MD5; 29362306a36Sopenharmony_ci break; 29462306a36Sopenharmony_ci default: 29562306a36Sopenharmony_ci err = -EINVAL; 29662306a36Sopenharmony_ci goto theend; 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci rk_ahash_reg_init(areq, rkc); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci while (sg) { 30262306a36Sopenharmony_ci reinit_completion(&rkc->complete); 30362306a36Sopenharmony_ci rkc->status = 0; 30462306a36Sopenharmony_ci crypto_ahash_dma_start(rkc, sg); 30562306a36Sopenharmony_ci wait_for_completion_interruptible_timeout(&rkc->complete, 30662306a36Sopenharmony_ci msecs_to_jiffies(2000)); 30762306a36Sopenharmony_ci if (!rkc->status) { 30862306a36Sopenharmony_ci dev_err(rkc->dev, "DMA timeout\n"); 30962306a36Sopenharmony_ci err = -EFAULT; 31062306a36Sopenharmony_ci goto theend; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci sg = sg_next(sg); 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* 31662306a36Sopenharmony_ci * it will take some time to process date after last dma 31762306a36Sopenharmony_ci * transmission. 31862306a36Sopenharmony_ci * 31962306a36Sopenharmony_ci * waiting time is relative with the last date len, 32062306a36Sopenharmony_ci * so cannot set a fixed time here. 32162306a36Sopenharmony_ci * 10us makes system not call here frequently wasting 32262306a36Sopenharmony_ci * efficiency, and make it response quickly when dma 32362306a36Sopenharmony_ci * complete. 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_ci readl_poll_timeout(rkc->reg + RK_CRYPTO_HASH_STS, v, v == 0, 10, 1000); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci for (i = 0; i < crypto_ahash_digestsize(tfm) / 4; i++) { 32862306a36Sopenharmony_ci v = readl(rkc->reg + RK_CRYPTO_HASH_DOUT_0 + i * 4); 32962306a36Sopenharmony_ci put_unaligned_le32(v, areq->result + i * 4); 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_citheend: 33362306a36Sopenharmony_ci pm_runtime_put_autosuspend(rkc->dev); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci local_bh_disable(); 33662306a36Sopenharmony_ci crypto_finalize_hash_request(engine, breq, err); 33762306a36Sopenharmony_ci local_bh_enable(); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci rk_hash_unprepare(engine, breq); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci return 0; 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic int rk_hash_init_tfm(struct crypto_ahash *tfm) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); 34762306a36Sopenharmony_ci const char *alg_name = crypto_ahash_alg_name(tfm); 34862306a36Sopenharmony_ci struct ahash_alg *alg = crypto_ahash_alg(tfm); 34962306a36Sopenharmony_ci struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash.base); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* for fallback */ 35262306a36Sopenharmony_ci tctx->fallback_tfm = crypto_alloc_ahash(alg_name, 0, 35362306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 35462306a36Sopenharmony_ci if (IS_ERR(tctx->fallback_tfm)) { 35562306a36Sopenharmony_ci dev_err(algt->dev->dev, "Could not load fallback driver.\n"); 35662306a36Sopenharmony_ci return PTR_ERR(tctx->fallback_tfm); 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci crypto_ahash_set_reqsize(tfm, 36062306a36Sopenharmony_ci sizeof(struct rk_ahash_rctx) + 36162306a36Sopenharmony_ci crypto_ahash_reqsize(tctx->fallback_tfm)); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci return 0; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_cistatic void rk_hash_exit_tfm(struct crypto_ahash *tfm) 36762306a36Sopenharmony_ci{ 36862306a36Sopenharmony_ci struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci crypto_free_ahash(tctx->fallback_tfm); 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistruct rk_crypto_tmp rk_ahash_sha1 = { 37462306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 37562306a36Sopenharmony_ci .alg.hash.base = { 37662306a36Sopenharmony_ci .init = rk_ahash_init, 37762306a36Sopenharmony_ci .update = rk_ahash_update, 37862306a36Sopenharmony_ci .final = rk_ahash_final, 37962306a36Sopenharmony_ci .finup = rk_ahash_finup, 38062306a36Sopenharmony_ci .export = rk_ahash_export, 38162306a36Sopenharmony_ci .import = rk_ahash_import, 38262306a36Sopenharmony_ci .digest = rk_ahash_digest, 38362306a36Sopenharmony_ci .init_tfm = rk_hash_init_tfm, 38462306a36Sopenharmony_ci .exit_tfm = rk_hash_exit_tfm, 38562306a36Sopenharmony_ci .halg = { 38662306a36Sopenharmony_ci .digestsize = SHA1_DIGEST_SIZE, 38762306a36Sopenharmony_ci .statesize = sizeof(struct sha1_state), 38862306a36Sopenharmony_ci .base = { 38962306a36Sopenharmony_ci .cra_name = "sha1", 39062306a36Sopenharmony_ci .cra_driver_name = "rk-sha1", 39162306a36Sopenharmony_ci .cra_priority = 300, 39262306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 39362306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 39462306a36Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 39562306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct rk_ahash_ctx), 39662306a36Sopenharmony_ci .cra_alignmask = 3, 39762306a36Sopenharmony_ci .cra_module = THIS_MODULE, 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci }, 40162306a36Sopenharmony_ci .alg.hash.op = { 40262306a36Sopenharmony_ci .do_one_request = rk_hash_run, 40362306a36Sopenharmony_ci }, 40462306a36Sopenharmony_ci}; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistruct rk_crypto_tmp rk_ahash_sha256 = { 40762306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 40862306a36Sopenharmony_ci .alg.hash.base = { 40962306a36Sopenharmony_ci .init = rk_ahash_init, 41062306a36Sopenharmony_ci .update = rk_ahash_update, 41162306a36Sopenharmony_ci .final = rk_ahash_final, 41262306a36Sopenharmony_ci .finup = rk_ahash_finup, 41362306a36Sopenharmony_ci .export = rk_ahash_export, 41462306a36Sopenharmony_ci .import = rk_ahash_import, 41562306a36Sopenharmony_ci .digest = rk_ahash_digest, 41662306a36Sopenharmony_ci .init_tfm = rk_hash_init_tfm, 41762306a36Sopenharmony_ci .exit_tfm = rk_hash_exit_tfm, 41862306a36Sopenharmony_ci .halg = { 41962306a36Sopenharmony_ci .digestsize = SHA256_DIGEST_SIZE, 42062306a36Sopenharmony_ci .statesize = sizeof(struct sha256_state), 42162306a36Sopenharmony_ci .base = { 42262306a36Sopenharmony_ci .cra_name = "sha256", 42362306a36Sopenharmony_ci .cra_driver_name = "rk-sha256", 42462306a36Sopenharmony_ci .cra_priority = 300, 42562306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 42662306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 42762306a36Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 42862306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct rk_ahash_ctx), 42962306a36Sopenharmony_ci .cra_alignmask = 3, 43062306a36Sopenharmony_ci .cra_module = THIS_MODULE, 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci }, 43462306a36Sopenharmony_ci .alg.hash.op = { 43562306a36Sopenharmony_ci .do_one_request = rk_hash_run, 43662306a36Sopenharmony_ci }, 43762306a36Sopenharmony_ci}; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistruct rk_crypto_tmp rk_ahash_md5 = { 44062306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 44162306a36Sopenharmony_ci .alg.hash.base = { 44262306a36Sopenharmony_ci .init = rk_ahash_init, 44362306a36Sopenharmony_ci .update = rk_ahash_update, 44462306a36Sopenharmony_ci .final = rk_ahash_final, 44562306a36Sopenharmony_ci .finup = rk_ahash_finup, 44662306a36Sopenharmony_ci .export = rk_ahash_export, 44762306a36Sopenharmony_ci .import = rk_ahash_import, 44862306a36Sopenharmony_ci .digest = rk_ahash_digest, 44962306a36Sopenharmony_ci .init_tfm = rk_hash_init_tfm, 45062306a36Sopenharmony_ci .exit_tfm = rk_hash_exit_tfm, 45162306a36Sopenharmony_ci .halg = { 45262306a36Sopenharmony_ci .digestsize = MD5_DIGEST_SIZE, 45362306a36Sopenharmony_ci .statesize = sizeof(struct md5_state), 45462306a36Sopenharmony_ci .base = { 45562306a36Sopenharmony_ci .cra_name = "md5", 45662306a36Sopenharmony_ci .cra_driver_name = "rk-md5", 45762306a36Sopenharmony_ci .cra_priority = 300, 45862306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 45962306a36Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 46062306a36Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 46162306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct rk_ahash_ctx), 46262306a36Sopenharmony_ci .cra_alignmask = 3, 46362306a36Sopenharmony_ci .cra_module = THIS_MODULE, 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci }, 46762306a36Sopenharmony_ci .alg.hash.op = { 46862306a36Sopenharmony_ci .do_one_request = rk_hash_run, 46962306a36Sopenharmony_ci }, 47062306a36Sopenharmony_ci}; 471