xref: /OK3568_Linux_fs/kernel/drivers/crypto/rockchip/rk3288_crypto.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Crypto acceleration support for Rockchip RK3288
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Author: Zain Wang <zain.wang@rock-chips.com>
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * Some ideas are from marvell-cesa.c and s5p-sss.c driver.
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include "rk3288_crypto.h"
13*4882a593Smuzhiyun #include <linux/dma-mapping.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/of.h>
17*4882a593Smuzhiyun #include <linux/clk.h>
18*4882a593Smuzhiyun #include <linux/crypto.h>
19*4882a593Smuzhiyun #include <linux/reset.h>
20*4882a593Smuzhiyun 
rk_crypto_enable_clk(struct rk_crypto_info * dev)21*4882a593Smuzhiyun static int rk_crypto_enable_clk(struct rk_crypto_info *dev)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun 	int err;
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun 	err = clk_prepare_enable(dev->sclk);
26*4882a593Smuzhiyun 	if (err) {
27*4882a593Smuzhiyun 		dev_err(dev->dev, "[%s:%d], Couldn't enable clock sclk\n",
28*4882a593Smuzhiyun 			__func__, __LINE__);
29*4882a593Smuzhiyun 		goto err_return;
30*4882a593Smuzhiyun 	}
31*4882a593Smuzhiyun 	err = clk_prepare_enable(dev->aclk);
32*4882a593Smuzhiyun 	if (err) {
33*4882a593Smuzhiyun 		dev_err(dev->dev, "[%s:%d], Couldn't enable clock aclk\n",
34*4882a593Smuzhiyun 			__func__, __LINE__);
35*4882a593Smuzhiyun 		goto err_aclk;
36*4882a593Smuzhiyun 	}
37*4882a593Smuzhiyun 	err = clk_prepare_enable(dev->hclk);
38*4882a593Smuzhiyun 	if (err) {
39*4882a593Smuzhiyun 		dev_err(dev->dev, "[%s:%d], Couldn't enable clock hclk\n",
40*4882a593Smuzhiyun 			__func__, __LINE__);
41*4882a593Smuzhiyun 		goto err_hclk;
42*4882a593Smuzhiyun 	}
43*4882a593Smuzhiyun 	err = clk_prepare_enable(dev->dmaclk);
44*4882a593Smuzhiyun 	if (err) {
45*4882a593Smuzhiyun 		dev_err(dev->dev, "[%s:%d], Couldn't enable clock dmaclk\n",
46*4882a593Smuzhiyun 			__func__, __LINE__);
47*4882a593Smuzhiyun 		goto err_dmaclk;
48*4882a593Smuzhiyun 	}
49*4882a593Smuzhiyun 	return err;
50*4882a593Smuzhiyun err_dmaclk:
51*4882a593Smuzhiyun 	clk_disable_unprepare(dev->hclk);
52*4882a593Smuzhiyun err_hclk:
53*4882a593Smuzhiyun 	clk_disable_unprepare(dev->aclk);
54*4882a593Smuzhiyun err_aclk:
55*4882a593Smuzhiyun 	clk_disable_unprepare(dev->sclk);
56*4882a593Smuzhiyun err_return:
57*4882a593Smuzhiyun 	return err;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
rk_crypto_disable_clk(struct rk_crypto_info * dev)60*4882a593Smuzhiyun static void rk_crypto_disable_clk(struct rk_crypto_info *dev)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	clk_disable_unprepare(dev->dmaclk);
63*4882a593Smuzhiyun 	clk_disable_unprepare(dev->hclk);
64*4882a593Smuzhiyun 	clk_disable_unprepare(dev->aclk);
65*4882a593Smuzhiyun 	clk_disable_unprepare(dev->sclk);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
check_alignment(struct scatterlist * sg_src,struct scatterlist * sg_dst,int align_mask)68*4882a593Smuzhiyun static int check_alignment(struct scatterlist *sg_src,
69*4882a593Smuzhiyun 			   struct scatterlist *sg_dst,
70*4882a593Smuzhiyun 			   int align_mask)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun 	int in, out, align;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	in = IS_ALIGNED((uint32_t)sg_src->offset, 4) &&
75*4882a593Smuzhiyun 	     IS_ALIGNED((uint32_t)sg_src->length, align_mask);
76*4882a593Smuzhiyun 	if (!sg_dst)
77*4882a593Smuzhiyun 		return in;
78*4882a593Smuzhiyun 	out = IS_ALIGNED((uint32_t)sg_dst->offset, 4) &&
79*4882a593Smuzhiyun 	      IS_ALIGNED((uint32_t)sg_dst->length, align_mask);
80*4882a593Smuzhiyun 	align = in && out;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	return (align && (sg_src->length == sg_dst->length));
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
rk_load_data(struct rk_crypto_info * dev,struct scatterlist * sg_src,struct scatterlist * sg_dst)85*4882a593Smuzhiyun static int rk_load_data(struct rk_crypto_info *dev,
86*4882a593Smuzhiyun 			struct scatterlist *sg_src,
87*4882a593Smuzhiyun 			struct scatterlist *sg_dst)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun 	unsigned int count;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	dev->aligned = dev->aligned ?
92*4882a593Smuzhiyun 		check_alignment(sg_src, sg_dst, dev->align_size) :
93*4882a593Smuzhiyun 		dev->aligned;
94*4882a593Smuzhiyun 	if (dev->aligned) {
95*4882a593Smuzhiyun 		count = min(dev->left_bytes, sg_src->length);
96*4882a593Smuzhiyun 		dev->left_bytes -= count;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 		if (!dma_map_sg(dev->dev, sg_src, 1, DMA_TO_DEVICE)) {
99*4882a593Smuzhiyun 			dev_err(dev->dev, "[%s:%d] dma_map_sg(src)  error\n",
100*4882a593Smuzhiyun 				__func__, __LINE__);
101*4882a593Smuzhiyun 			return -EINVAL;
102*4882a593Smuzhiyun 		}
103*4882a593Smuzhiyun 		dev->addr_in = sg_dma_address(sg_src);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 		if (sg_dst) {
106*4882a593Smuzhiyun 			if (!dma_map_sg(dev->dev, sg_dst, 1, DMA_FROM_DEVICE)) {
107*4882a593Smuzhiyun 				dev_err(dev->dev,
108*4882a593Smuzhiyun 					"[%s:%d] dma_map_sg(dst)  error\n",
109*4882a593Smuzhiyun 					__func__, __LINE__);
110*4882a593Smuzhiyun 				dma_unmap_sg(dev->dev, sg_src, 1,
111*4882a593Smuzhiyun 					     DMA_TO_DEVICE);
112*4882a593Smuzhiyun 				return -EINVAL;
113*4882a593Smuzhiyun 			}
114*4882a593Smuzhiyun 			dev->addr_out = sg_dma_address(sg_dst);
115*4882a593Smuzhiyun 		}
116*4882a593Smuzhiyun 	} else {
117*4882a593Smuzhiyun 		count = (dev->left_bytes > PAGE_SIZE) ?
118*4882a593Smuzhiyun 			PAGE_SIZE : dev->left_bytes;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 		if (!sg_pcopy_to_buffer(dev->first, dev->src_nents,
121*4882a593Smuzhiyun 					dev->addr_vir, count,
122*4882a593Smuzhiyun 					dev->total - dev->left_bytes)) {
123*4882a593Smuzhiyun 			dev_err(dev->dev, "[%s:%d] pcopy err\n",
124*4882a593Smuzhiyun 				__func__, __LINE__);
125*4882a593Smuzhiyun 			return -EINVAL;
126*4882a593Smuzhiyun 		}
127*4882a593Smuzhiyun 		dev->left_bytes -= count;
128*4882a593Smuzhiyun 		sg_init_one(&dev->sg_tmp, dev->addr_vir, count);
129*4882a593Smuzhiyun 		if (!dma_map_sg(dev->dev, &dev->sg_tmp, 1, DMA_TO_DEVICE)) {
130*4882a593Smuzhiyun 			dev_err(dev->dev, "[%s:%d] dma_map_sg(sg_tmp)  error\n",
131*4882a593Smuzhiyun 				__func__, __LINE__);
132*4882a593Smuzhiyun 			return -ENOMEM;
133*4882a593Smuzhiyun 		}
134*4882a593Smuzhiyun 		dev->addr_in = sg_dma_address(&dev->sg_tmp);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 		if (sg_dst) {
137*4882a593Smuzhiyun 			if (!dma_map_sg(dev->dev, &dev->sg_tmp, 1,
138*4882a593Smuzhiyun 					DMA_FROM_DEVICE)) {
139*4882a593Smuzhiyun 				dev_err(dev->dev,
140*4882a593Smuzhiyun 					"[%s:%d] dma_map_sg(sg_tmp)  error\n",
141*4882a593Smuzhiyun 					__func__, __LINE__);
142*4882a593Smuzhiyun 				dma_unmap_sg(dev->dev, &dev->sg_tmp, 1,
143*4882a593Smuzhiyun 					     DMA_TO_DEVICE);
144*4882a593Smuzhiyun 				return -ENOMEM;
145*4882a593Smuzhiyun 			}
146*4882a593Smuzhiyun 			dev->addr_out = sg_dma_address(&dev->sg_tmp);
147*4882a593Smuzhiyun 		}
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 	dev->count = count;
150*4882a593Smuzhiyun 	return 0;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
rk_unload_data(struct rk_crypto_info * dev)153*4882a593Smuzhiyun static void rk_unload_data(struct rk_crypto_info *dev)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	struct scatterlist *sg_in, *sg_out;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	sg_in = dev->aligned ? dev->sg_src : &dev->sg_tmp;
158*4882a593Smuzhiyun 	dma_unmap_sg(dev->dev, sg_in, 1, DMA_TO_DEVICE);
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	if (dev->sg_dst) {
161*4882a593Smuzhiyun 		sg_out = dev->aligned ? dev->sg_dst : &dev->sg_tmp;
162*4882a593Smuzhiyun 		dma_unmap_sg(dev->dev, sg_out, 1, DMA_FROM_DEVICE);
163*4882a593Smuzhiyun 	}
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun 
rk_crypto_irq_handle(int irq,void * dev_id)166*4882a593Smuzhiyun static irqreturn_t rk_crypto_irq_handle(int irq, void *dev_id)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	struct rk_crypto_info *dev  = platform_get_drvdata(dev_id);
169*4882a593Smuzhiyun 	u32 interrupt_status;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	spin_lock(&dev->lock);
172*4882a593Smuzhiyun 	interrupt_status = CRYPTO_READ(dev, RK_CRYPTO_INTSTS);
173*4882a593Smuzhiyun 	CRYPTO_WRITE(dev, RK_CRYPTO_INTSTS, interrupt_status);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	if (interrupt_status & 0x0a) {
176*4882a593Smuzhiyun 		dev_warn(dev->dev, "DMA Error\n");
177*4882a593Smuzhiyun 		dev->err = -EFAULT;
178*4882a593Smuzhiyun 	}
179*4882a593Smuzhiyun 	tasklet_schedule(&dev->done_task);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	spin_unlock(&dev->lock);
182*4882a593Smuzhiyun 	return IRQ_HANDLED;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
rk_crypto_enqueue(struct rk_crypto_info * dev,struct crypto_async_request * async_req)185*4882a593Smuzhiyun static int rk_crypto_enqueue(struct rk_crypto_info *dev,
186*4882a593Smuzhiyun 			      struct crypto_async_request *async_req)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	unsigned long flags;
189*4882a593Smuzhiyun 	int ret;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	spin_lock_irqsave(&dev->lock, flags);
192*4882a593Smuzhiyun 	ret = crypto_enqueue_request(&dev->queue, async_req);
193*4882a593Smuzhiyun 	if (dev->busy) {
194*4882a593Smuzhiyun 		spin_unlock_irqrestore(&dev->lock, flags);
195*4882a593Smuzhiyun 		return ret;
196*4882a593Smuzhiyun 	}
197*4882a593Smuzhiyun 	dev->busy = true;
198*4882a593Smuzhiyun 	spin_unlock_irqrestore(&dev->lock, flags);
199*4882a593Smuzhiyun 	tasklet_schedule(&dev->queue_task);
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	return ret;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun 
rk_crypto_queue_task_cb(unsigned long data)204*4882a593Smuzhiyun static void rk_crypto_queue_task_cb(unsigned long data)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	struct rk_crypto_info *dev = (struct rk_crypto_info *)data;
207*4882a593Smuzhiyun 	struct crypto_async_request *async_req, *backlog;
208*4882a593Smuzhiyun 	unsigned long flags;
209*4882a593Smuzhiyun 	int err = 0;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	dev->err = 0;
212*4882a593Smuzhiyun 	spin_lock_irqsave(&dev->lock, flags);
213*4882a593Smuzhiyun 	backlog   = crypto_get_backlog(&dev->queue);
214*4882a593Smuzhiyun 	async_req = crypto_dequeue_request(&dev->queue);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	if (!async_req) {
217*4882a593Smuzhiyun 		dev->busy = false;
218*4882a593Smuzhiyun 		spin_unlock_irqrestore(&dev->lock, flags);
219*4882a593Smuzhiyun 		return;
220*4882a593Smuzhiyun 	}
221*4882a593Smuzhiyun 	spin_unlock_irqrestore(&dev->lock, flags);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	if (backlog) {
224*4882a593Smuzhiyun 		backlog->complete(backlog, -EINPROGRESS);
225*4882a593Smuzhiyun 		backlog = NULL;
226*4882a593Smuzhiyun 	}
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	dev->async_req = async_req;
229*4882a593Smuzhiyun 	err = dev->start(dev);
230*4882a593Smuzhiyun 	if (err)
231*4882a593Smuzhiyun 		dev->complete(dev->async_req, err);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
rk_crypto_done_task_cb(unsigned long data)234*4882a593Smuzhiyun static void rk_crypto_done_task_cb(unsigned long data)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun 	struct rk_crypto_info *dev = (struct rk_crypto_info *)data;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	if (dev->err) {
239*4882a593Smuzhiyun 		dev->complete(dev->async_req, dev->err);
240*4882a593Smuzhiyun 		return;
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	dev->err = dev->update(dev);
244*4882a593Smuzhiyun 	if (dev->err)
245*4882a593Smuzhiyun 		dev->complete(dev->async_req, dev->err);
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun static struct rk_crypto_tmp *rk_cipher_algs[] = {
249*4882a593Smuzhiyun 	&rk_ecb_aes_alg,
250*4882a593Smuzhiyun 	&rk_cbc_aes_alg,
251*4882a593Smuzhiyun 	&rk_ecb_des_alg,
252*4882a593Smuzhiyun 	&rk_cbc_des_alg,
253*4882a593Smuzhiyun 	&rk_ecb_des3_ede_alg,
254*4882a593Smuzhiyun 	&rk_cbc_des3_ede_alg,
255*4882a593Smuzhiyun 	&rk_ahash_sha1,
256*4882a593Smuzhiyun 	&rk_ahash_sha256,
257*4882a593Smuzhiyun 	&rk_ahash_md5,
258*4882a593Smuzhiyun };
259*4882a593Smuzhiyun 
rk_crypto_register(struct rk_crypto_info * crypto_info)260*4882a593Smuzhiyun static int rk_crypto_register(struct rk_crypto_info *crypto_info)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun 	unsigned int i, k;
263*4882a593Smuzhiyun 	int err = 0;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rk_cipher_algs); i++) {
266*4882a593Smuzhiyun 		rk_cipher_algs[i]->dev = crypto_info;
267*4882a593Smuzhiyun 		if (rk_cipher_algs[i]->type == ALG_TYPE_CIPHER)
268*4882a593Smuzhiyun 			err = crypto_register_skcipher(
269*4882a593Smuzhiyun 					&rk_cipher_algs[i]->alg.skcipher);
270*4882a593Smuzhiyun 		else
271*4882a593Smuzhiyun 			err = crypto_register_ahash(
272*4882a593Smuzhiyun 					&rk_cipher_algs[i]->alg.hash);
273*4882a593Smuzhiyun 		if (err)
274*4882a593Smuzhiyun 			goto err_cipher_algs;
275*4882a593Smuzhiyun 	}
276*4882a593Smuzhiyun 	return 0;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun err_cipher_algs:
279*4882a593Smuzhiyun 	for (k = 0; k < i; k++) {
280*4882a593Smuzhiyun 		if (rk_cipher_algs[i]->type == ALG_TYPE_CIPHER)
281*4882a593Smuzhiyun 			crypto_unregister_skcipher(&rk_cipher_algs[k]->alg.skcipher);
282*4882a593Smuzhiyun 		else
283*4882a593Smuzhiyun 			crypto_unregister_ahash(&rk_cipher_algs[i]->alg.hash);
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 	return err;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun 
rk_crypto_unregister(void)288*4882a593Smuzhiyun static void rk_crypto_unregister(void)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun 	unsigned int i;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rk_cipher_algs); i++) {
293*4882a593Smuzhiyun 		if (rk_cipher_algs[i]->type == ALG_TYPE_CIPHER)
294*4882a593Smuzhiyun 			crypto_unregister_skcipher(&rk_cipher_algs[i]->alg.skcipher);
295*4882a593Smuzhiyun 		else
296*4882a593Smuzhiyun 			crypto_unregister_ahash(&rk_cipher_algs[i]->alg.hash);
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
rk_crypto_action(void * data)300*4882a593Smuzhiyun static void rk_crypto_action(void *data)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	struct rk_crypto_info *crypto_info = data;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	reset_control_assert(crypto_info->rst);
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun static const struct of_device_id crypto_of_id_table[] = {
308*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3288-crypto" },
309*4882a593Smuzhiyun 	{}
310*4882a593Smuzhiyun };
311*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, crypto_of_id_table);
312*4882a593Smuzhiyun 
rk_crypto_probe(struct platform_device * pdev)313*4882a593Smuzhiyun static int rk_crypto_probe(struct platform_device *pdev)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
316*4882a593Smuzhiyun 	struct rk_crypto_info *crypto_info;
317*4882a593Smuzhiyun 	int err = 0;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	crypto_info = devm_kzalloc(&pdev->dev,
320*4882a593Smuzhiyun 				   sizeof(*crypto_info), GFP_KERNEL);
321*4882a593Smuzhiyun 	if (!crypto_info) {
322*4882a593Smuzhiyun 		err = -ENOMEM;
323*4882a593Smuzhiyun 		goto err_crypto;
324*4882a593Smuzhiyun 	}
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	crypto_info->rst = devm_reset_control_get(dev, "crypto-rst");
327*4882a593Smuzhiyun 	if (IS_ERR(crypto_info->rst)) {
328*4882a593Smuzhiyun 		err = PTR_ERR(crypto_info->rst);
329*4882a593Smuzhiyun 		goto err_crypto;
330*4882a593Smuzhiyun 	}
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	reset_control_assert(crypto_info->rst);
333*4882a593Smuzhiyun 	usleep_range(10, 20);
334*4882a593Smuzhiyun 	reset_control_deassert(crypto_info->rst);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	err = devm_add_action_or_reset(dev, rk_crypto_action, crypto_info);
337*4882a593Smuzhiyun 	if (err)
338*4882a593Smuzhiyun 		goto err_crypto;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	spin_lock_init(&crypto_info->lock);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	crypto_info->reg = devm_platform_ioremap_resource(pdev, 0);
343*4882a593Smuzhiyun 	if (IS_ERR(crypto_info->reg)) {
344*4882a593Smuzhiyun 		err = PTR_ERR(crypto_info->reg);
345*4882a593Smuzhiyun 		goto err_crypto;
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	crypto_info->aclk = devm_clk_get(&pdev->dev, "aclk");
349*4882a593Smuzhiyun 	if (IS_ERR(crypto_info->aclk)) {
350*4882a593Smuzhiyun 		err = PTR_ERR(crypto_info->aclk);
351*4882a593Smuzhiyun 		goto err_crypto;
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	crypto_info->hclk = devm_clk_get(&pdev->dev, "hclk");
355*4882a593Smuzhiyun 	if (IS_ERR(crypto_info->hclk)) {
356*4882a593Smuzhiyun 		err = PTR_ERR(crypto_info->hclk);
357*4882a593Smuzhiyun 		goto err_crypto;
358*4882a593Smuzhiyun 	}
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	crypto_info->sclk = devm_clk_get(&pdev->dev, "sclk");
361*4882a593Smuzhiyun 	if (IS_ERR(crypto_info->sclk)) {
362*4882a593Smuzhiyun 		err = PTR_ERR(crypto_info->sclk);
363*4882a593Smuzhiyun 		goto err_crypto;
364*4882a593Smuzhiyun 	}
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	crypto_info->dmaclk = devm_clk_get(&pdev->dev, "apb_pclk");
367*4882a593Smuzhiyun 	if (IS_ERR(crypto_info->dmaclk)) {
368*4882a593Smuzhiyun 		err = PTR_ERR(crypto_info->dmaclk);
369*4882a593Smuzhiyun 		goto err_crypto;
370*4882a593Smuzhiyun 	}
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	crypto_info->irq = platform_get_irq(pdev, 0);
373*4882a593Smuzhiyun 	if (crypto_info->irq < 0) {
374*4882a593Smuzhiyun 		dev_warn(crypto_info->dev,
375*4882a593Smuzhiyun 			 "control Interrupt is not available.\n");
376*4882a593Smuzhiyun 		err = crypto_info->irq;
377*4882a593Smuzhiyun 		goto err_crypto;
378*4882a593Smuzhiyun 	}
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	err = devm_request_irq(&pdev->dev, crypto_info->irq,
381*4882a593Smuzhiyun 			       rk_crypto_irq_handle, IRQF_SHARED,
382*4882a593Smuzhiyun 			       "rk-crypto", pdev);
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	if (err) {
385*4882a593Smuzhiyun 		dev_err(crypto_info->dev, "irq request failed.\n");
386*4882a593Smuzhiyun 		goto err_crypto;
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	crypto_info->dev = &pdev->dev;
390*4882a593Smuzhiyun 	platform_set_drvdata(pdev, crypto_info);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	tasklet_init(&crypto_info->queue_task,
393*4882a593Smuzhiyun 		     rk_crypto_queue_task_cb, (unsigned long)crypto_info);
394*4882a593Smuzhiyun 	tasklet_init(&crypto_info->done_task,
395*4882a593Smuzhiyun 		     rk_crypto_done_task_cb, (unsigned long)crypto_info);
396*4882a593Smuzhiyun 	crypto_init_queue(&crypto_info->queue, 50);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	crypto_info->enable_clk = rk_crypto_enable_clk;
399*4882a593Smuzhiyun 	crypto_info->disable_clk = rk_crypto_disable_clk;
400*4882a593Smuzhiyun 	crypto_info->load_data = rk_load_data;
401*4882a593Smuzhiyun 	crypto_info->unload_data = rk_unload_data;
402*4882a593Smuzhiyun 	crypto_info->enqueue = rk_crypto_enqueue;
403*4882a593Smuzhiyun 	crypto_info->busy = false;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	err = rk_crypto_register(crypto_info);
406*4882a593Smuzhiyun 	if (err) {
407*4882a593Smuzhiyun 		dev_err(dev, "err in register alg");
408*4882a593Smuzhiyun 		goto err_register_alg;
409*4882a593Smuzhiyun 	}
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	dev_info(dev, "Crypto Accelerator successfully registered\n");
412*4882a593Smuzhiyun 	return 0;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun err_register_alg:
415*4882a593Smuzhiyun 	tasklet_kill(&crypto_info->queue_task);
416*4882a593Smuzhiyun 	tasklet_kill(&crypto_info->done_task);
417*4882a593Smuzhiyun err_crypto:
418*4882a593Smuzhiyun 	return err;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun 
rk_crypto_remove(struct platform_device * pdev)421*4882a593Smuzhiyun static int rk_crypto_remove(struct platform_device *pdev)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun 	struct rk_crypto_info *crypto_tmp = platform_get_drvdata(pdev);
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	rk_crypto_unregister();
426*4882a593Smuzhiyun 	tasklet_kill(&crypto_tmp->done_task);
427*4882a593Smuzhiyun 	tasklet_kill(&crypto_tmp->queue_task);
428*4882a593Smuzhiyun 	return 0;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun static struct platform_driver crypto_driver = {
432*4882a593Smuzhiyun 	.probe		= rk_crypto_probe,
433*4882a593Smuzhiyun 	.remove		= rk_crypto_remove,
434*4882a593Smuzhiyun 	.driver		= {
435*4882a593Smuzhiyun 		.name	= "rk3288-crypto",
436*4882a593Smuzhiyun 		.of_match_table	= crypto_of_id_table,
437*4882a593Smuzhiyun 	},
438*4882a593Smuzhiyun };
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun module_platform_driver(crypto_driver);
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun MODULE_AUTHOR("Zain Wang <zain.wang@rock-chips.com>");
443*4882a593Smuzhiyun MODULE_DESCRIPTION("Support for Rockchip's cryptographic engine");
444*4882a593Smuzhiyun MODULE_LICENSE("GPL");
445