xref: /linux/drivers/crypto/ti/dthev2-common.c (revision 68a052239fc4b351e961f698b824f7654a346091)
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 static int dthe_dma_init(struct dthe_data *dev_data)
52 {
53 	int ret;
54 	struct dma_slave_config cfg;
55 
56 	dev_data->dma_aes_rx = NULL;
57 	dev_data->dma_aes_tx = NULL;
58 	dev_data->dma_sha_tx = NULL;
59 
60 	dev_data->dma_aes_rx = dma_request_chan(dev_data->dev, "rx");
61 	if (IS_ERR(dev_data->dma_aes_rx)) {
62 		return dev_err_probe(dev_data->dev, PTR_ERR(dev_data->dma_aes_rx),
63 				     "Unable to request rx DMA channel\n");
64 	}
65 
66 	dev_data->dma_aes_tx = dma_request_chan(dev_data->dev, "tx1");
67 	if (IS_ERR(dev_data->dma_aes_tx)) {
68 		ret = dev_err_probe(dev_data->dev, PTR_ERR(dev_data->dma_aes_tx),
69 				    "Unable to request tx1 DMA channel\n");
70 		goto err_dma_aes_tx;
71 	}
72 
73 	dev_data->dma_sha_tx = dma_request_chan(dev_data->dev, "tx2");
74 	if (IS_ERR(dev_data->dma_sha_tx)) {
75 		ret = dev_err_probe(dev_data->dev, PTR_ERR(dev_data->dma_sha_tx),
76 				    "Unable to request tx2 DMA channel\n");
77 		goto err_dma_sha_tx;
78 	}
79 
80 	memzero_explicit(&cfg, sizeof(cfg));
81 
82 	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
83 	cfg.src_maxburst = 4;
84 
85 	ret = dmaengine_slave_config(dev_data->dma_aes_rx, &cfg);
86 	if (ret) {
87 		dev_err(dev_data->dev, "Can't configure IN dmaengine slave: %d\n", ret);
88 		goto err_dma_config;
89 	}
90 
91 	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
92 	cfg.dst_maxburst = 4;
93 
94 	ret = dmaengine_slave_config(dev_data->dma_aes_tx, &cfg);
95 	if (ret) {
96 		dev_err(dev_data->dev, "Can't configure OUT dmaengine slave: %d\n", ret);
97 		goto err_dma_config;
98 	}
99 
100 	return 0;
101 
102 err_dma_config:
103 	dma_release_channel(dev_data->dma_sha_tx);
104 err_dma_sha_tx:
105 	dma_release_channel(dev_data->dma_aes_tx);
106 err_dma_aes_tx:
107 	dma_release_channel(dev_data->dma_aes_rx);
108 
109 	return ret;
110 }
111 
112 static int dthe_register_algs(void)
113 {
114 	return dthe_register_aes_algs();
115 }
116 
117 static void dthe_unregister_algs(void)
118 {
119 	dthe_unregister_aes_algs();
120 }
121 
122 static int dthe_probe(struct platform_device *pdev)
123 {
124 	struct device *dev = &pdev->dev;
125 	struct dthe_data *dev_data;
126 	int ret;
127 
128 	dev_data = devm_kzalloc(dev, sizeof(*dev_data), GFP_KERNEL);
129 	if (!dev_data)
130 		return -ENOMEM;
131 
132 	dev_data->dev = dev;
133 	dev_data->regs = devm_platform_ioremap_resource(pdev, 0);
134 	if (IS_ERR(dev_data->regs))
135 		return PTR_ERR(dev_data->regs);
136 
137 	platform_set_drvdata(pdev, dev_data);
138 
139 	spin_lock(&dthe_dev_list.lock);
140 	list_add(&dev_data->list, &dthe_dev_list.dev_list);
141 	spin_unlock(&dthe_dev_list.lock);
142 
143 	ret = dthe_dma_init(dev_data);
144 	if (ret)
145 		goto probe_dma_err;
146 
147 	dev_data->engine = crypto_engine_alloc_init(dev, 1);
148 	if (!dev_data->engine) {
149 		ret = -ENOMEM;
150 		goto probe_engine_err;
151 	}
152 
153 	ret = crypto_engine_start(dev_data->engine);
154 	if (ret) {
155 		dev_err(dev, "Failed to start crypto engine\n");
156 		goto probe_engine_start_err;
157 	}
158 
159 	ret = dthe_register_algs();
160 	if (ret) {
161 		dev_err(dev, "Failed to register algs\n");
162 		goto probe_engine_start_err;
163 	}
164 
165 	return 0;
166 
167 probe_engine_start_err:
168 	crypto_engine_exit(dev_data->engine);
169 probe_engine_err:
170 	dma_release_channel(dev_data->dma_aes_rx);
171 	dma_release_channel(dev_data->dma_aes_tx);
172 	dma_release_channel(dev_data->dma_sha_tx);
173 probe_dma_err:
174 	spin_lock(&dthe_dev_list.lock);
175 	list_del(&dev_data->list);
176 	spin_unlock(&dthe_dev_list.lock);
177 
178 	return ret;
179 }
180 
181 static void dthe_remove(struct platform_device *pdev)
182 {
183 	struct dthe_data *dev_data = platform_get_drvdata(pdev);
184 
185 	spin_lock(&dthe_dev_list.lock);
186 	list_del(&dev_data->list);
187 	spin_unlock(&dthe_dev_list.lock);
188 
189 	dthe_unregister_algs();
190 
191 	crypto_engine_exit(dev_data->engine);
192 
193 	dma_release_channel(dev_data->dma_aes_rx);
194 	dma_release_channel(dev_data->dma_aes_tx);
195 	dma_release_channel(dev_data->dma_sha_tx);
196 }
197 
198 static const struct of_device_id dthe_of_match[] = {
199 	{ .compatible = "ti,am62l-dthev2", },
200 	{},
201 };
202 MODULE_DEVICE_TABLE(of, dthe_of_match);
203 
204 static struct platform_driver dthe_driver = {
205 	.probe	= dthe_probe,
206 	.remove	= dthe_remove,
207 	.driver = {
208 		.name		= DRIVER_NAME,
209 		.of_match_table	= dthe_of_match,
210 	},
211 };
212 
213 module_platform_driver(dthe_driver);
214 
215 MODULE_AUTHOR("T Pratham <t-pratham@ti.com>");
216 MODULE_DESCRIPTION("Texas Instruments DTHE V2 driver");
217 MODULE_LICENSE("GPL");
218