Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 236 lines 5.7 kB view raw
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 51struct 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 70static 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 121err_dma_config: 122 dma_release_channel(dev_data->dma_sha_tx); 123err_dma_sha_tx: 124 dma_release_channel(dev_data->dma_aes_tx); 125err_dma_aes_tx: 126 dma_release_channel(dev_data->dma_aes_rx); 127 128 return ret; 129} 130 131static int dthe_register_algs(void) 132{ 133 return dthe_register_aes_algs(); 134} 135 136static void dthe_unregister_algs(void) 137{ 138 dthe_unregister_aes_algs(); 139} 140 141static 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 186probe_engine_start_err: 187 crypto_engine_exit(dev_data->engine); 188probe_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); 192probe_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 200static 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 217static const struct of_device_id dthe_of_match[] = { 218 { .compatible = "ti,am62l-dthev2", }, 219 {}, 220}; 221MODULE_DEVICE_TABLE(of, dthe_of_match); 222 223static 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 232module_platform_driver(dthe_driver); 233 234MODULE_AUTHOR("T Pratham <t-pratham@ti.com>"); 235MODULE_DESCRIPTION("Texas Instruments DTHE V2 driver"); 236MODULE_LICENSE("GPL");