xref: /linux/drivers/crypto/ti/dthev2-common.c (revision 53597deca0e38c30e6cd4ba2114fa42d2bcd85bb)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * K3 DTHE V2 crypto accelerator driver
4  *
5  * Copyright (C) Texas Instruments 2025 - https://www.ti.com
6  * Author: T Pratham <t-pratham@ti.com>
7  */
8 
9 #include <crypto/aes.h>
10 #include <crypto/algapi.h>
11 #include <crypto/engine.h>
12 #include <crypto/internal/aead.h>
13 #include <crypto/internal/skcipher.h>
14 
15 #include "dthev2-common.h"
16 
17 #include <linux/delay.h>
18 #include <linux/dmaengine.h>
19 #include <linux/dmapool.h>
20 #include <linux/dma-mapping.h>
21 #include <linux/io.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/mod_devicetable.h>
25 #include <linux/platform_device.h>
26 #include <linux/scatterlist.h>
27 
28 #define DRIVER_NAME	"dthev2"
29 
30 static struct dthe_list dthe_dev_list = {
31 	.dev_list = LIST_HEAD_INIT(dthe_dev_list.dev_list),
32 	.lock = __SPIN_LOCK_UNLOCKED(dthe_dev_list.lock),
33 };
34 
35 struct dthe_data *dthe_get_dev(struct dthe_tfm_ctx *ctx)
36 {
37 	struct dthe_data *dev_data;
38 
39 	if (ctx->dev_data)
40 		return ctx->dev_data;
41 
42 	spin_lock_bh(&dthe_dev_list.lock);
43 	dev_data = list_first_entry(&dthe_dev_list.dev_list, struct dthe_data, list);
44 	if (dev_data)
45 		list_move_tail(&dev_data->list, &dthe_dev_list.dev_list);
46 	spin_unlock_bh(&dthe_dev_list.lock);
47 
48 	return dev_data;
49 }
50 
51 struct scatterlist *dthe_copy_sg(struct scatterlist *dst,
52 				 struct scatterlist *src,
53 				 int buflen)
54 {
55 	struct scatterlist *from_sg, *to_sg;
56 	int sglen;
57 
58 	for (to_sg = dst, from_sg = src; buflen && from_sg; buflen -= sglen) {
59 		sglen = from_sg->length;
60 		if (sglen > buflen)
61 			sglen = buflen;
62 		sg_set_buf(to_sg, sg_virt(from_sg), sglen);
63 		from_sg = sg_next(from_sg);
64 		to_sg = sg_next(to_sg);
65 	}
66 
67 	return to_sg;
68 }
69 
70 static int dthe_dma_init(struct dthe_data *dev_data)
71 {
72 	int ret;
73 	struct dma_slave_config cfg;
74 
75 	dev_data->dma_aes_rx = NULL;
76 	dev_data->dma_aes_tx = NULL;
77 	dev_data->dma_sha_tx = NULL;
78 
79 	dev_data->dma_aes_rx = dma_request_chan(dev_data->dev, "rx");
80 	if (IS_ERR(dev_data->dma_aes_rx)) {
81 		return dev_err_probe(dev_data->dev, PTR_ERR(dev_data->dma_aes_rx),
82 				     "Unable to request rx DMA channel\n");
83 	}
84 
85 	dev_data->dma_aes_tx = dma_request_chan(dev_data->dev, "tx1");
86 	if (IS_ERR(dev_data->dma_aes_tx)) {
87 		ret = dev_err_probe(dev_data->dev, PTR_ERR(dev_data->dma_aes_tx),
88 				    "Unable to request tx1 DMA channel\n");
89 		goto err_dma_aes_tx;
90 	}
91 
92 	dev_data->dma_sha_tx = dma_request_chan(dev_data->dev, "tx2");
93 	if (IS_ERR(dev_data->dma_sha_tx)) {
94 		ret = dev_err_probe(dev_data->dev, PTR_ERR(dev_data->dma_sha_tx),
95 				    "Unable to request tx2 DMA channel\n");
96 		goto err_dma_sha_tx;
97 	}
98 
99 	memzero_explicit(&cfg, sizeof(cfg));
100 
101 	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
102 	cfg.src_maxburst = 4;
103 
104 	ret = dmaengine_slave_config(dev_data->dma_aes_rx, &cfg);
105 	if (ret) {
106 		dev_err(dev_data->dev, "Can't configure IN dmaengine slave: %d\n", ret);
107 		goto err_dma_config;
108 	}
109 
110 	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
111 	cfg.dst_maxburst = 4;
112 
113 	ret = dmaengine_slave_config(dev_data->dma_aes_tx, &cfg);
114 	if (ret) {
115 		dev_err(dev_data->dev, "Can't configure OUT dmaengine slave: %d\n", ret);
116 		goto err_dma_config;
117 	}
118 
119 	return 0;
120 
121 err_dma_config:
122 	dma_release_channel(dev_data->dma_sha_tx);
123 err_dma_sha_tx:
124 	dma_release_channel(dev_data->dma_aes_tx);
125 err_dma_aes_tx:
126 	dma_release_channel(dev_data->dma_aes_rx);
127 
128 	return ret;
129 }
130 
131 static int dthe_register_algs(void)
132 {
133 	return dthe_register_aes_algs();
134 }
135 
136 static void dthe_unregister_algs(void)
137 {
138 	dthe_unregister_aes_algs();
139 }
140 
141 static int dthe_probe(struct platform_device *pdev)
142 {
143 	struct device *dev = &pdev->dev;
144 	struct dthe_data *dev_data;
145 	int ret;
146 
147 	dev_data = devm_kzalloc(dev, sizeof(*dev_data), GFP_KERNEL);
148 	if (!dev_data)
149 		return -ENOMEM;
150 
151 	dev_data->dev = dev;
152 	dev_data->regs = devm_platform_ioremap_resource(pdev, 0);
153 	if (IS_ERR(dev_data->regs))
154 		return PTR_ERR(dev_data->regs);
155 
156 	platform_set_drvdata(pdev, dev_data);
157 
158 	spin_lock(&dthe_dev_list.lock);
159 	list_add(&dev_data->list, &dthe_dev_list.dev_list);
160 	spin_unlock(&dthe_dev_list.lock);
161 
162 	ret = dthe_dma_init(dev_data);
163 	if (ret)
164 		goto probe_dma_err;
165 
166 	dev_data->engine = crypto_engine_alloc_init(dev, 1);
167 	if (!dev_data->engine) {
168 		ret = -ENOMEM;
169 		goto probe_engine_err;
170 	}
171 
172 	ret = crypto_engine_start(dev_data->engine);
173 	if (ret) {
174 		dev_err(dev, "Failed to start crypto engine\n");
175 		goto probe_engine_start_err;
176 	}
177 
178 	ret = dthe_register_algs();
179 	if (ret) {
180 		dev_err(dev, "Failed to register algs\n");
181 		goto probe_engine_start_err;
182 	}
183 
184 	return 0;
185 
186 probe_engine_start_err:
187 	crypto_engine_exit(dev_data->engine);
188 probe_engine_err:
189 	dma_release_channel(dev_data->dma_aes_rx);
190 	dma_release_channel(dev_data->dma_aes_tx);
191 	dma_release_channel(dev_data->dma_sha_tx);
192 probe_dma_err:
193 	spin_lock(&dthe_dev_list.lock);
194 	list_del(&dev_data->list);
195 	spin_unlock(&dthe_dev_list.lock);
196 
197 	return ret;
198 }
199 
200 static void dthe_remove(struct platform_device *pdev)
201 {
202 	struct dthe_data *dev_data = platform_get_drvdata(pdev);
203 
204 	spin_lock(&dthe_dev_list.lock);
205 	list_del(&dev_data->list);
206 	spin_unlock(&dthe_dev_list.lock);
207 
208 	dthe_unregister_algs();
209 
210 	crypto_engine_exit(dev_data->engine);
211 
212 	dma_release_channel(dev_data->dma_aes_rx);
213 	dma_release_channel(dev_data->dma_aes_tx);
214 	dma_release_channel(dev_data->dma_sha_tx);
215 }
216 
217 static const struct of_device_id dthe_of_match[] = {
218 	{ .compatible = "ti,am62l-dthev2", },
219 	{},
220 };
221 MODULE_DEVICE_TABLE(of, dthe_of_match);
222 
223 static struct platform_driver dthe_driver = {
224 	.probe	= dthe_probe,
225 	.remove	= dthe_remove,
226 	.driver = {
227 		.name		= DRIVER_NAME,
228 		.of_match_table	= dthe_of_match,
229 	},
230 };
231 
232 module_platform_driver(dthe_driver);
233 
234 MODULE_AUTHOR("T Pratham <t-pratham@ti.com>");
235 MODULE_DESCRIPTION("Texas Instruments DTHE V2 driver");
236 MODULE_LICENSE("GPL");
237