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