File Index
Files and directories
Sign in
FILE

dthev2-common.c

File preview with syntax highlighting.

linux-6.19.14/drivers/crypto/ti/dthev2-common.c C
  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
 30static 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
 35struct 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
 51static 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
102err_dma_config:
103	dma_release_channel(dev_data->dma_sha_tx);
104err_dma_sha_tx:
105	dma_release_channel(dev_data->dma_aes_tx);
106err_dma_aes_tx:
107	dma_release_channel(dev_data->dma_aes_rx);
108
109	return ret;
110}
111
112static int dthe_register_algs(void)
113{
114	return dthe_register_aes_algs();
115}
116
117static void dthe_unregister_algs(void)
118{
119	dthe_unregister_aes_algs();
120}
121
122static 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
167probe_engine_start_err:
168	crypto_engine_exit(dev_data->engine);
169probe_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);
173probe_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
181static 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
198static const struct of_device_id dthe_of_match[] = {
199	{ .compatible = "ti,am62l-dthev2", },
200	{},
201};
202MODULE_DEVICE_TABLE(of, dthe_of_match);
203
204static 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
213module_platform_driver(dthe_driver);
214
215MODULE_AUTHOR("T Pratham <t-pratham@ti.com>");
216MODULE_DESCRIPTION("Texas Instruments DTHE V2 driver");
217MODULE_LICENSE("GPL");
~/ Read-only file preview.