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