175a6faf6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2bfd927ffSZain Wang /*
3bfd927ffSZain Wang  * Crypto acceleration support for Rockchip RK3288
4bfd927ffSZain Wang  *
5bfd927ffSZain Wang  * Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd
6bfd927ffSZain Wang  *
7bfd927ffSZain Wang  * Author: Zain Wang <zain.wang@rock-chips.com>
8bfd927ffSZain Wang  *
9bfd927ffSZain Wang  * Some ideas are from marvell/cesa.c and s5p-sss.c driver.
10bfd927ffSZain Wang  */
111a15d26cSHerbert Xu 
1257d67c6eSCorentin Labbe #include <asm/unaligned.h>
131a15d26cSHerbert Xu #include <crypto/internal/hash.h>
141a15d26cSHerbert Xu #include <linux/device.h>
151a15d26cSHerbert Xu #include <linux/err.h>
1637bc2215SCorentin Labbe #include <linux/iopoll.h>
171a15d26cSHerbert Xu #include <linux/kernel.h>
181a15d26cSHerbert Xu #include <linux/module.h>
191a15d26cSHerbert Xu #include <linux/string.h>
20bfd927ffSZain Wang #include "rk3288_crypto.h"
21bfd927ffSZain Wang 
22bfd927ffSZain Wang /*
23bfd927ffSZain Wang  * IC can not process zero message hash,
24bfd927ffSZain Wang  * so we put the fixed hash out when met zero message.
25bfd927ffSZain Wang  */
26bfd927ffSZain Wang 
rk_ahash_need_fallback(struct ahash_request * req)2781660048SCorentin Labbe static bool rk_ahash_need_fallback(struct ahash_request *req)
2881660048SCorentin Labbe {
2981660048SCorentin Labbe 	struct scatterlist *sg;
3081660048SCorentin Labbe 
3181660048SCorentin Labbe 	sg = req->src;
3281660048SCorentin Labbe 	while (sg) {
3381660048SCorentin Labbe 		if (!IS_ALIGNED(sg->offset, sizeof(u32))) {
3481660048SCorentin Labbe 			return true;
3581660048SCorentin Labbe 		}
3681660048SCorentin Labbe 		if (sg->length % 4) {
3781660048SCorentin Labbe 			return true;
3881660048SCorentin Labbe 		}
3981660048SCorentin Labbe 		sg = sg_next(sg);
4081660048SCorentin Labbe 	}
4181660048SCorentin Labbe 	return false;
4281660048SCorentin Labbe }
4381660048SCorentin Labbe 
rk_ahash_digest_fb(struct ahash_request * areq)4481660048SCorentin Labbe static int rk_ahash_digest_fb(struct ahash_request *areq)
4581660048SCorentin Labbe {
4681660048SCorentin Labbe 	struct rk_ahash_rctx *rctx = ahash_request_ctx(areq);
4781660048SCorentin Labbe 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
4881660048SCorentin Labbe 	struct rk_ahash_ctx *tfmctx = crypto_ahash_ctx(tfm);
491a15d26cSHerbert Xu 	struct ahash_alg *alg = crypto_ahash_alg(tfm);
501a15d26cSHerbert Xu 	struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash.base);
5148d904d4SCorentin Labbe 
5248d904d4SCorentin Labbe 	algt->stat_fb++;
5381660048SCorentin Labbe 
5481660048SCorentin Labbe 	ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm);
5581660048SCorentin Labbe 	rctx->fallback_req.base.flags = areq->base.flags &
5681660048SCorentin Labbe 					CRYPTO_TFM_REQ_MAY_SLEEP;
5781660048SCorentin Labbe 
5881660048SCorentin Labbe 	rctx->fallback_req.nbytes = areq->nbytes;
5981660048SCorentin Labbe 	rctx->fallback_req.src = areq->src;
6081660048SCorentin Labbe 	rctx->fallback_req.result = areq->result;
6181660048SCorentin Labbe 
6281660048SCorentin Labbe 	return crypto_ahash_digest(&rctx->fallback_req);
6381660048SCorentin Labbe }
6481660048SCorentin Labbe 
zero_message_process(struct ahash_request * req)65bfd927ffSZain Wang static int zero_message_process(struct ahash_request *req)
66bfd927ffSZain Wang {
67bfd927ffSZain Wang 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
68bfd927ffSZain Wang 	int rk_digest_size = crypto_ahash_digestsize(tfm);
69bfd927ffSZain Wang 
70bfd927ffSZain Wang 	switch (rk_digest_size) {
71bfd927ffSZain Wang 	case SHA1_DIGEST_SIZE:
72bfd927ffSZain Wang 		memcpy(req->result, sha1_zero_message_hash, rk_digest_size);
73bfd927ffSZain Wang 		break;
74bfd927ffSZain Wang 	case SHA256_DIGEST_SIZE:
75bfd927ffSZain Wang 		memcpy(req->result, sha256_zero_message_hash, rk_digest_size);
76bfd927ffSZain Wang 		break;
77bfd927ffSZain Wang 	case MD5_DIGEST_SIZE:
78bfd927ffSZain Wang 		memcpy(req->result, md5_zero_message_hash, rk_digest_size);
79bfd927ffSZain Wang 		break;
80bfd927ffSZain Wang 	default:
81bfd927ffSZain Wang 		return -EINVAL;
82bfd927ffSZain Wang 	}
83bfd927ffSZain Wang 
84bfd927ffSZain Wang 	return 0;
85bfd927ffSZain Wang }
86bfd927ffSZain Wang 
rk_ahash_reg_init(struct ahash_request * req,struct rk_crypto_info * dev)870d31b14cSCorentin Labbe static void rk_ahash_reg_init(struct ahash_request *req,
880d31b14cSCorentin Labbe 			      struct rk_crypto_info *dev)
89bfd927ffSZain Wang {
905a7801f6SZain Wang 	struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
913d8c5f5aSKai Ye 	int reg_status;
92bfd927ffSZain Wang 
93bfd927ffSZain Wang 	reg_status = CRYPTO_READ(dev, RK_CRYPTO_CTRL) |
94bfd927ffSZain Wang 		     RK_CRYPTO_HASH_FLUSH | _SBF(0xffff, 16);
95bfd927ffSZain Wang 	CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, reg_status);
96bfd927ffSZain Wang 
97bfd927ffSZain Wang 	reg_status = CRYPTO_READ(dev, RK_CRYPTO_CTRL);
98bfd927ffSZain Wang 	reg_status &= (~RK_CRYPTO_HASH_FLUSH);
99bfd927ffSZain Wang 	reg_status |= _SBF(0xffff, 16);
100bfd927ffSZain Wang 	CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, reg_status);
101bfd927ffSZain Wang 
102bfd927ffSZain Wang 	memset_io(dev->reg + RK_CRYPTO_HASH_DOUT_0, 0, 32);
103bfd927ffSZain Wang 
104bfd927ffSZain Wang 	CRYPTO_WRITE(dev, RK_CRYPTO_INTENA, RK_CRYPTO_HRDMA_ERR_ENA |
105bfd927ffSZain Wang 					    RK_CRYPTO_HRDMA_DONE_ENA);
106bfd927ffSZain Wang 
107bfd927ffSZain Wang 	CRYPTO_WRITE(dev, RK_CRYPTO_INTSTS, RK_CRYPTO_HRDMA_ERR_INT |
108bfd927ffSZain Wang 					    RK_CRYPTO_HRDMA_DONE_INT);
109bfd927ffSZain Wang 
1105a7801f6SZain Wang 	CRYPTO_WRITE(dev, RK_CRYPTO_HASH_CTRL, rctx->mode |
111bfd927ffSZain Wang 					       RK_CRYPTO_HASH_SWAP_DO);
112bfd927ffSZain Wang 
113bfd927ffSZain Wang 	CRYPTO_WRITE(dev, RK_CRYPTO_CONF, RK_CRYPTO_BYTESWAP_HRFIFO |
114bfd927ffSZain Wang 					  RK_CRYPTO_BYTESWAP_BRFIFO |
115bfd927ffSZain Wang 					  RK_CRYPTO_BYTESWAP_BTFIFO);
116bfd927ffSZain Wang 
11757d67c6eSCorentin Labbe 	CRYPTO_WRITE(dev, RK_CRYPTO_HASH_MSG_LEN, req->nbytes);
118bfd927ffSZain Wang }
119bfd927ffSZain Wang 
rk_ahash_init(struct ahash_request * req)120bfd927ffSZain Wang static int rk_ahash_init(struct ahash_request *req)
121bfd927ffSZain Wang {
122bfd927ffSZain Wang 	struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
123bfd927ffSZain Wang 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
124bfd927ffSZain Wang 	struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
125bfd927ffSZain Wang 
126bfd927ffSZain Wang 	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
127bfd927ffSZain Wang 	rctx->fallback_req.base.flags = req->base.flags &
128bfd927ffSZain Wang 					CRYPTO_TFM_REQ_MAY_SLEEP;
129bfd927ffSZain Wang 
130bfd927ffSZain Wang 	return crypto_ahash_init(&rctx->fallback_req);
131bfd927ffSZain Wang }
132bfd927ffSZain Wang 
rk_ahash_update(struct ahash_request * req)133bfd927ffSZain Wang static int rk_ahash_update(struct ahash_request *req)
134bfd927ffSZain Wang {
135bfd927ffSZain Wang 	struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
136bfd927ffSZain Wang 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
137bfd927ffSZain Wang 	struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
138bfd927ffSZain Wang 
139bfd927ffSZain Wang 	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
140bfd927ffSZain Wang 	rctx->fallback_req.base.flags = req->base.flags &
141bfd927ffSZain Wang 					CRYPTO_TFM_REQ_MAY_SLEEP;
142bfd927ffSZain Wang 	rctx->fallback_req.nbytes = req->nbytes;
143bfd927ffSZain Wang 	rctx->fallback_req.src = req->src;
144bfd927ffSZain Wang 
145bfd927ffSZain Wang 	return crypto_ahash_update(&rctx->fallback_req);
146bfd927ffSZain Wang }
147bfd927ffSZain Wang 
rk_ahash_final(struct ahash_request * req)148bfd927ffSZain Wang static int rk_ahash_final(struct ahash_request *req)
149bfd927ffSZain Wang {
150bfd927ffSZain Wang 	struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
151bfd927ffSZain Wang 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
152bfd927ffSZain Wang 	struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
153bfd927ffSZain Wang 
154bfd927ffSZain Wang 	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
155bfd927ffSZain Wang 	rctx->fallback_req.base.flags = req->base.flags &
156bfd927ffSZain Wang 					CRYPTO_TFM_REQ_MAY_SLEEP;
157bfd927ffSZain Wang 	rctx->fallback_req.result = req->result;
158bfd927ffSZain Wang 
159bfd927ffSZain Wang 	return crypto_ahash_final(&rctx->fallback_req);
160bfd927ffSZain Wang }
161bfd927ffSZain Wang 
rk_ahash_finup(struct ahash_request * req)162bfd927ffSZain Wang static int rk_ahash_finup(struct ahash_request *req)
163bfd927ffSZain Wang {
164bfd927ffSZain Wang 	struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
165bfd927ffSZain Wang 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
166bfd927ffSZain Wang 	struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
167bfd927ffSZain Wang 
168bfd927ffSZain Wang 	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
169bfd927ffSZain Wang 	rctx->fallback_req.base.flags = req->base.flags &
170bfd927ffSZain Wang 					CRYPTO_TFM_REQ_MAY_SLEEP;
171bfd927ffSZain Wang 
172bfd927ffSZain Wang 	rctx->fallback_req.nbytes = req->nbytes;
173bfd927ffSZain Wang 	rctx->fallback_req.src = req->src;
174bfd927ffSZain Wang 	rctx->fallback_req.result = req->result;
175bfd927ffSZain Wang 
176bfd927ffSZain Wang 	return crypto_ahash_finup(&rctx->fallback_req);
177bfd927ffSZain Wang }
178bfd927ffSZain Wang 
rk_ahash_import(struct ahash_request * req,const void * in)179bfd927ffSZain Wang static int rk_ahash_import(struct ahash_request *req, const void *in)
180bfd927ffSZain Wang {
181bfd927ffSZain Wang 	struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
182bfd927ffSZain Wang 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
183bfd927ffSZain Wang 	struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
184bfd927ffSZain Wang 
185bfd927ffSZain Wang 	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
186bfd927ffSZain Wang 	rctx->fallback_req.base.flags = req->base.flags &
187bfd927ffSZain Wang 					CRYPTO_TFM_REQ_MAY_SLEEP;
188bfd927ffSZain Wang 
189bfd927ffSZain Wang 	return crypto_ahash_import(&rctx->fallback_req, in);
190bfd927ffSZain Wang }
191bfd927ffSZain Wang 
rk_ahash_export(struct ahash_request * req,void * out)192bfd927ffSZain Wang static int rk_ahash_export(struct ahash_request *req, void *out)
193bfd927ffSZain Wang {
194bfd927ffSZain Wang 	struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
195bfd927ffSZain Wang 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
196bfd927ffSZain Wang 	struct rk_ahash_ctx *ctx = crypto_ahash_ctx(tfm);
197bfd927ffSZain Wang 
198bfd927ffSZain Wang 	ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
199bfd927ffSZain Wang 	rctx->fallback_req.base.flags = req->base.flags &
200bfd927ffSZain Wang 					CRYPTO_TFM_REQ_MAY_SLEEP;
201bfd927ffSZain Wang 
202bfd927ffSZain Wang 	return crypto_ahash_export(&rctx->fallback_req, out);
203bfd927ffSZain Wang }
204bfd927ffSZain Wang 
rk_ahash_digest(struct ahash_request * req)205bfd927ffSZain Wang static int rk_ahash_digest(struct ahash_request *req)
206bfd927ffSZain Wang {
2072d3c756aSCorentin Labbe 	struct rk_ahash_rctx *rctx = ahash_request_ctx(req);
2089dcd71c8SCorentin Labbe 	struct rk_crypto_info *dev;
2099dcd71c8SCorentin Labbe 	struct crypto_engine *engine;
210bfd927ffSZain Wang 
21181660048SCorentin Labbe 	if (rk_ahash_need_fallback(req))
21281660048SCorentin Labbe 		return rk_ahash_digest_fb(req);
21381660048SCorentin Labbe 
214bfd927ffSZain Wang 	if (!req->nbytes)
215bfd927ffSZain Wang 		return zero_message_process(req);
21657d67c6eSCorentin Labbe 
2179dcd71c8SCorentin Labbe 	dev = get_rk_crypto();
2182d3c756aSCorentin Labbe 
2199dcd71c8SCorentin Labbe 	rctx->dev = dev;
2209dcd71c8SCorentin Labbe 	engine = dev->engine;
2219dcd71c8SCorentin Labbe 
2229dcd71c8SCorentin Labbe 	return crypto_transfer_hash_request_to_engine(engine, req);
223bfd927ffSZain Wang }
224bfd927ffSZain Wang 
crypto_ahash_dma_start(struct rk_crypto_info * dev,struct scatterlist * sg)22557d67c6eSCorentin Labbe static void crypto_ahash_dma_start(struct rk_crypto_info *dev, struct scatterlist *sg)
226bfd927ffSZain Wang {
22757d67c6eSCorentin Labbe 	CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAS, sg_dma_address(sg));
22857d67c6eSCorentin Labbe 	CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAL, sg_dma_len(sg) / 4);
229bfd927ffSZain Wang 	CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, RK_CRYPTO_HASH_START |
230bfd927ffSZain Wang 					  (RK_CRYPTO_HASH_START << 16));
231bfd927ffSZain Wang }
232bfd927ffSZain Wang 
rk_hash_prepare(struct crypto_engine * engine,void * breq)23357d67c6eSCorentin Labbe static int rk_hash_prepare(struct crypto_engine *engine, void *breq)
234bfd927ffSZain Wang {
23557d67c6eSCorentin Labbe 	struct ahash_request *areq = container_of(breq, struct ahash_request, base);
23657d67c6eSCorentin Labbe 	struct rk_ahash_rctx *rctx = ahash_request_ctx(areq);
2372d3c756aSCorentin Labbe 	struct rk_crypto_info *rkc = rctx->dev;
23857d67c6eSCorentin Labbe 	int ret;
239bfd927ffSZain Wang 
240c018c7a9SCorentin Labbe 	ret = dma_map_sg(rkc->dev, areq->src, sg_nents(areq->src), DMA_TO_DEVICE);
24157d67c6eSCorentin Labbe 	if (ret <= 0)
24257d67c6eSCorentin Labbe 		return -EINVAL;
24357d67c6eSCorentin Labbe 
24457d67c6eSCorentin Labbe 	rctx->nrsg = ret;
24557d67c6eSCorentin Labbe 
24657d67c6eSCorentin Labbe 	return 0;
247bfd927ffSZain Wang }
248bfd927ffSZain Wang 
rk_hash_unprepare(struct crypto_engine * engine,void * breq)249c66c17a0SHerbert Xu static void rk_hash_unprepare(struct crypto_engine *engine, void *breq)
250bfd927ffSZain Wang {
25157d67c6eSCorentin Labbe 	struct ahash_request *areq = container_of(breq, struct ahash_request, base);
25257d67c6eSCorentin Labbe 	struct rk_ahash_rctx *rctx = ahash_request_ctx(areq);
2532d3c756aSCorentin Labbe 	struct rk_crypto_info *rkc = rctx->dev;
2545a7801f6SZain Wang 
255c018c7a9SCorentin Labbe 	dma_unmap_sg(rkc->dev, areq->src, rctx->nrsg, DMA_TO_DEVICE);
25657d67c6eSCorentin Labbe }
25757d67c6eSCorentin Labbe 
rk_hash_run(struct crypto_engine * engine,void * breq)25857d67c6eSCorentin Labbe static int rk_hash_run(struct crypto_engine *engine, void *breq)
25957d67c6eSCorentin Labbe {
26057d67c6eSCorentin Labbe 	struct ahash_request *areq = container_of(breq, struct ahash_request, base);
26157d67c6eSCorentin Labbe 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
26257d67c6eSCorentin Labbe 	struct rk_ahash_rctx *rctx = ahash_request_ctx(areq);
2631a15d26cSHerbert Xu 	struct ahash_alg *alg = crypto_ahash_alg(tfm);
2641a15d26cSHerbert Xu 	struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash.base);
26557d67c6eSCorentin Labbe 	struct scatterlist *sg = areq->src;
2662d3c756aSCorentin Labbe 	struct rk_crypto_info *rkc = rctx->dev;
267c66c17a0SHerbert Xu 	int err;
26857d67c6eSCorentin Labbe 	int i;
26957d67c6eSCorentin Labbe 	u32 v;
27057d67c6eSCorentin Labbe 
2719dcd71c8SCorentin Labbe 	err = pm_runtime_resume_and_get(rkc->dev);
2729dcd71c8SCorentin Labbe 	if (err)
2739dcd71c8SCorentin Labbe 		return err;
2749dcd71c8SCorentin Labbe 
275c66c17a0SHerbert Xu 	err = rk_hash_prepare(engine, breq);
276c66c17a0SHerbert Xu 	if (err)
277c66c17a0SHerbert Xu 		goto theend;
278c66c17a0SHerbert Xu 
2795a7801f6SZain Wang 	rctx->mode = 0;
2805a7801f6SZain Wang 
28148d904d4SCorentin Labbe 	algt->stat_req++;
2829dcd71c8SCorentin Labbe 	rkc->nreq++;
28348d904d4SCorentin Labbe 
2845a7801f6SZain Wang 	switch (crypto_ahash_digestsize(tfm)) {
2855a7801f6SZain Wang 	case SHA1_DIGEST_SIZE:
2865a7801f6SZain Wang 		rctx->mode = RK_CRYPTO_HASH_SHA1;
2875a7801f6SZain Wang 		break;
2885a7801f6SZain Wang 	case SHA256_DIGEST_SIZE:
2895a7801f6SZain Wang 		rctx->mode = RK_CRYPTO_HASH_SHA256;
2905a7801f6SZain Wang 		break;
2915a7801f6SZain Wang 	case MD5_DIGEST_SIZE:
2925a7801f6SZain Wang 		rctx->mode = RK_CRYPTO_HASH_MD5;
2935a7801f6SZain Wang 		break;
2945a7801f6SZain Wang 	default:
29557d67c6eSCorentin Labbe 		err =  -EINVAL;
29657d67c6eSCorentin Labbe 		goto theend;
2975a7801f6SZain Wang 	}
2985a7801f6SZain Wang 
2990d31b14cSCorentin Labbe 	rk_ahash_reg_init(areq, rkc);
30057d67c6eSCorentin Labbe 
30157d67c6eSCorentin Labbe 	while (sg) {
302c018c7a9SCorentin Labbe 		reinit_completion(&rkc->complete);
303c018c7a9SCorentin Labbe 		rkc->status = 0;
304c018c7a9SCorentin Labbe 		crypto_ahash_dma_start(rkc, sg);
305c018c7a9SCorentin Labbe 		wait_for_completion_interruptible_timeout(&rkc->complete,
30657d67c6eSCorentin Labbe 							  msecs_to_jiffies(2000));
307c018c7a9SCorentin Labbe 		if (!rkc->status) {
308c018c7a9SCorentin Labbe 			dev_err(rkc->dev, "DMA timeout\n");
30957d67c6eSCorentin Labbe 			err = -EFAULT;
31057d67c6eSCorentin Labbe 			goto theend;
31157d67c6eSCorentin Labbe 		}
31257d67c6eSCorentin Labbe 		sg = sg_next(sg);
313bfd927ffSZain Wang 	}
314bfd927ffSZain Wang 
3155a7801f6SZain Wang 	/*
3165a7801f6SZain Wang 	 * it will take some time to process date after last dma
3175a7801f6SZain Wang 	 * transmission.
3185a7801f6SZain Wang 	 *
3195a7801f6SZain Wang 	 * waiting time is relative with the last date len,
3205a7801f6SZain Wang 	 * so cannot set a fixed time here.
3215a7801f6SZain Wang 	 * 10us makes system not call here frequently wasting
3225a7801f6SZain Wang 	 * efficiency, and make it response quickly when dma
3235a7801f6SZain Wang 	 * complete.
3245a7801f6SZain Wang 	 */
325c018c7a9SCorentin Labbe 	readl_poll_timeout(rkc->reg + RK_CRYPTO_HASH_STS, v, v == 0, 10, 1000);
3265a7801f6SZain Wang 
32757d67c6eSCorentin Labbe 	for (i = 0; i < crypto_ahash_digestsize(tfm) / 4; i++) {
328c018c7a9SCorentin Labbe 		v = readl(rkc->reg + RK_CRYPTO_HASH_DOUT_0 + i * 4);
32957d67c6eSCorentin Labbe 		put_unaligned_le32(v, areq->result + i * 4);
330bfd927ffSZain Wang 	}
331bfd927ffSZain Wang 
33257d67c6eSCorentin Labbe theend:
3339dcd71c8SCorentin Labbe 	pm_runtime_put_autosuspend(rkc->dev);
3349dcd71c8SCorentin Labbe 
335*c0afb6b8SHerbert Xu 	rk_hash_unprepare(engine, breq);
336*c0afb6b8SHerbert Xu 
33757d67c6eSCorentin Labbe 	local_bh_disable();
33857d67c6eSCorentin Labbe 	crypto_finalize_hash_request(engine, breq, err);
33957d67c6eSCorentin Labbe 	local_bh_enable();
34057d67c6eSCorentin Labbe 
34157d67c6eSCorentin Labbe 	return 0;
342bfd927ffSZain Wang }
343bfd927ffSZain Wang 
rk_hash_init_tfm(struct crypto_ahash * tfm)3441a15d26cSHerbert Xu static int rk_hash_init_tfm(struct crypto_ahash *tfm)
345bfd927ffSZain Wang {
3461a15d26cSHerbert Xu 	struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm);
3471a15d26cSHerbert Xu 	const char *alg_name = crypto_ahash_alg_name(tfm);
3481a15d26cSHerbert Xu 	struct ahash_alg *alg = crypto_ahash_alg(tfm);
3491a15d26cSHerbert Xu 	struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash.base);
350bfd927ffSZain Wang 
351bfd927ffSZain Wang 	/* for fallback */
352bfd927ffSZain Wang 	tctx->fallback_tfm = crypto_alloc_ahash(alg_name, 0,
353bfd927ffSZain Wang 						CRYPTO_ALG_NEED_FALLBACK);
354bfd927ffSZain Wang 	if (IS_ERR(tctx->fallback_tfm)) {
3559dcd71c8SCorentin Labbe 		dev_err(algt->dev->dev, "Could not load fallback driver.\n");
356bfd927ffSZain Wang 		return PTR_ERR(tctx->fallback_tfm);
357bfd927ffSZain Wang 	}
35857d67c6eSCorentin Labbe 
3591a15d26cSHerbert Xu 	crypto_ahash_set_reqsize(tfm,
360bfd927ffSZain Wang 				 sizeof(struct rk_ahash_rctx) +
361bfd927ffSZain Wang 				 crypto_ahash_reqsize(tctx->fallback_tfm));
362bfd927ffSZain Wang 
363c50ef141SCorentin Labbe 	return 0;
364bfd927ffSZain Wang }
365bfd927ffSZain Wang 
rk_hash_exit_tfm(struct crypto_ahash * tfm)3661a15d26cSHerbert Xu static void rk_hash_exit_tfm(struct crypto_ahash *tfm)
367bfd927ffSZain Wang {
3681a15d26cSHerbert Xu 	struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm);
369bfd927ffSZain Wang 
37081660048SCorentin Labbe 	crypto_free_ahash(tctx->fallback_tfm);
371bfd927ffSZain Wang }
372bfd927ffSZain Wang 
373bfd927ffSZain Wang struct rk_crypto_tmp rk_ahash_sha1 = {
3746d55c4a2SCorentin Labbe 	.type = CRYPTO_ALG_TYPE_AHASH,
3751a15d26cSHerbert Xu 	.alg.hash.base = {
376bfd927ffSZain Wang 		.init = rk_ahash_init,
377bfd927ffSZain Wang 		.update = rk_ahash_update,
378bfd927ffSZain Wang 		.final = rk_ahash_final,
379bfd927ffSZain Wang 		.finup = rk_ahash_finup,
380bfd927ffSZain Wang 		.export = rk_ahash_export,
381bfd927ffSZain Wang 		.import = rk_ahash_import,
382bfd927ffSZain Wang 		.digest = rk_ahash_digest,
3831a15d26cSHerbert Xu 		.init_tfm = rk_hash_init_tfm,
3841a15d26cSHerbert Xu 		.exit_tfm = rk_hash_exit_tfm,
385bfd927ffSZain Wang 		.halg = {
386bfd927ffSZain Wang 			 .digestsize = SHA1_DIGEST_SIZE,
387bfd927ffSZain Wang 			 .statesize = sizeof(struct sha1_state),
388bfd927ffSZain Wang 			 .base = {
389bfd927ffSZain Wang 				  .cra_name = "sha1",
390bfd927ffSZain Wang 				  .cra_driver_name = "rk-sha1",
391bfd927ffSZain Wang 				  .cra_priority = 300,
392bfd927ffSZain Wang 				  .cra_flags = CRYPTO_ALG_ASYNC |
393bfd927ffSZain Wang 					       CRYPTO_ALG_NEED_FALLBACK,
394bfd927ffSZain Wang 				  .cra_blocksize = SHA1_BLOCK_SIZE,
395bfd927ffSZain Wang 				  .cra_ctxsize = sizeof(struct rk_ahash_ctx),
396bfd927ffSZain Wang 				  .cra_module = THIS_MODULE,
397bfd927ffSZain Wang 			}
398bfd927ffSZain Wang 		}
3991a15d26cSHerbert Xu 	},
4001a15d26cSHerbert Xu 	.alg.hash.op = {
4011a15d26cSHerbert Xu 		.do_one_request = rk_hash_run,
4021a15d26cSHerbert Xu 	},
403bfd927ffSZain Wang };
404bfd927ffSZain Wang 
405bfd927ffSZain Wang struct rk_crypto_tmp rk_ahash_sha256 = {
4066d55c4a2SCorentin Labbe 	.type = CRYPTO_ALG_TYPE_AHASH,
4071a15d26cSHerbert Xu 	.alg.hash.base = {
408bfd927ffSZain Wang 		.init = rk_ahash_init,
409bfd927ffSZain Wang 		.update = rk_ahash_update,
410bfd927ffSZain Wang 		.final = rk_ahash_final,
411bfd927ffSZain Wang 		.finup = rk_ahash_finup,
412bfd927ffSZain Wang 		.export = rk_ahash_export,
413bfd927ffSZain Wang 		.import = rk_ahash_import,
414bfd927ffSZain Wang 		.digest = rk_ahash_digest,
4151a15d26cSHerbert Xu 		.init_tfm = rk_hash_init_tfm,
4161a15d26cSHerbert Xu 		.exit_tfm = rk_hash_exit_tfm,
417bfd927ffSZain Wang 		.halg = {
418bfd927ffSZain Wang 			 .digestsize = SHA256_DIGEST_SIZE,
419bfd927ffSZain Wang 			 .statesize = sizeof(struct sha256_state),
420bfd927ffSZain Wang 			 .base = {
421bfd927ffSZain Wang 				  .cra_name = "sha256",
422bfd927ffSZain Wang 				  .cra_driver_name = "rk-sha256",
423bfd927ffSZain Wang 				  .cra_priority = 300,
424bfd927ffSZain Wang 				  .cra_flags = CRYPTO_ALG_ASYNC |
425bfd927ffSZain Wang 					       CRYPTO_ALG_NEED_FALLBACK,
426bfd927ffSZain Wang 				  .cra_blocksize = SHA256_BLOCK_SIZE,
427bfd927ffSZain Wang 				  .cra_ctxsize = sizeof(struct rk_ahash_ctx),
428bfd927ffSZain Wang 				  .cra_module = THIS_MODULE,
429bfd927ffSZain Wang 			}
430bfd927ffSZain Wang 		}
4311a15d26cSHerbert Xu 	},
4321a15d26cSHerbert Xu 	.alg.hash.op = {
4331a15d26cSHerbert Xu 		.do_one_request = rk_hash_run,
4341a15d26cSHerbert Xu 	},
435bfd927ffSZain Wang };
436bfd927ffSZain Wang 
437bfd927ffSZain Wang struct rk_crypto_tmp rk_ahash_md5 = {
4386d55c4a2SCorentin Labbe 	.type = CRYPTO_ALG_TYPE_AHASH,
4391a15d26cSHerbert Xu 	.alg.hash.base = {
440bfd927ffSZain Wang 		.init = rk_ahash_init,
441bfd927ffSZain Wang 		.update = rk_ahash_update,
442bfd927ffSZain Wang 		.final = rk_ahash_final,
443bfd927ffSZain Wang 		.finup = rk_ahash_finup,
444bfd927ffSZain Wang 		.export = rk_ahash_export,
445bfd927ffSZain Wang 		.import = rk_ahash_import,
446bfd927ffSZain Wang 		.digest = rk_ahash_digest,
4471a15d26cSHerbert Xu 		.init_tfm = rk_hash_init_tfm,
4481a15d26cSHerbert Xu 		.exit_tfm = rk_hash_exit_tfm,
449bfd927ffSZain Wang 		.halg = {
450bfd927ffSZain Wang 			 .digestsize = MD5_DIGEST_SIZE,
451bfd927ffSZain Wang 			 .statesize = sizeof(struct md5_state),
452bfd927ffSZain Wang 			 .base = {
453bfd927ffSZain Wang 				  .cra_name = "md5",
454bfd927ffSZain Wang 				  .cra_driver_name = "rk-md5",
455bfd927ffSZain Wang 				  .cra_priority = 300,
456bfd927ffSZain Wang 				  .cra_flags = CRYPTO_ALG_ASYNC |
457bfd927ffSZain Wang 					       CRYPTO_ALG_NEED_FALLBACK,
458bfd927ffSZain Wang 				  .cra_blocksize = SHA1_BLOCK_SIZE,
459bfd927ffSZain Wang 				  .cra_ctxsize = sizeof(struct rk_ahash_ctx),
460bfd927ffSZain Wang 				  .cra_module = THIS_MODULE,
461bfd927ffSZain Wang 			}
462bfd927ffSZain Wang 		}
4631a15d26cSHerbert Xu 	},
4641a15d26cSHerbert Xu 	.alg.hash.op = {
4651a15d26cSHerbert Xu 		.do_one_request = rk_hash_run,
4661a15d26cSHerbert Xu 	},
467bfd927ffSZain Wang };
468