1 // SPDX-License-Identifier: GPL-2.0-only 2 // SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 /* 4 * Crypto driver for NVIDIA Security Engine in Tegra Chips 5 */ 6 7 #include <linux/clk.h> 8 #include <linux/dma-mapping.h> 9 #include <linux/module.h> 10 #include <linux/platform_device.h> 11 #include <linux/mod_devicetable.h> 12 13 #include <crypto/engine.h> 14 15 #include "tegra-se.h" 16 17 static struct host1x_bo *tegra_se_cmdbuf_get(struct host1x_bo *host_bo) 18 { 19 struct tegra_se_cmdbuf *cmdbuf = container_of(host_bo, struct tegra_se_cmdbuf, bo); 20 21 kref_get(&cmdbuf->ref); 22 23 return host_bo; 24 } 25 26 static void tegra_se_cmdbuf_release(struct kref *ref) 27 { 28 struct tegra_se_cmdbuf *cmdbuf = container_of(ref, struct tegra_se_cmdbuf, ref); 29 30 dma_free_attrs(cmdbuf->dev, cmdbuf->size, cmdbuf->addr, 31 cmdbuf->iova, 0); 32 33 kfree(cmdbuf); 34 } 35 36 static void tegra_se_cmdbuf_put(struct host1x_bo *host_bo) 37 { 38 struct tegra_se_cmdbuf *cmdbuf = container_of(host_bo, struct tegra_se_cmdbuf, bo); 39 40 kref_put(&cmdbuf->ref, tegra_se_cmdbuf_release); 41 } 42 43 static struct host1x_bo_mapping * 44 tegra_se_cmdbuf_pin(struct device *dev, struct host1x_bo *bo, enum dma_data_direction direction) 45 { 46 struct tegra_se_cmdbuf *cmdbuf = container_of(bo, struct tegra_se_cmdbuf, bo); 47 struct host1x_bo_mapping *map; 48 int err; 49 50 map = kzalloc_obj(*map); 51 if (!map) 52 return ERR_PTR(-ENOMEM); 53 54 kref_init(&map->ref); 55 map->bo = bo; 56 map->direction = direction; 57 map->dev = dev; 58 59 map->sgt = kzalloc_obj(*map->sgt); 60 if (!map->sgt) { 61 err = -ENOMEM; 62 goto free; 63 } 64 65 err = dma_get_sgtable(dev, map->sgt, cmdbuf->addr, 66 cmdbuf->iova, cmdbuf->words * 4); 67 if (err) 68 goto free_sgt; 69 70 err = dma_map_sgtable(dev, map->sgt, direction, 0); 71 if (err) 72 goto free_sgt; 73 74 map->phys = sg_dma_address(map->sgt->sgl); 75 map->size = cmdbuf->words * 4; 76 map->chunks = err; 77 78 return map; 79 80 free_sgt: 81 sg_free_table(map->sgt); 82 kfree(map->sgt); 83 free: 84 kfree(map); 85 return ERR_PTR(err); 86 } 87 88 static void tegra_se_cmdbuf_unpin(struct host1x_bo_mapping *map) 89 { 90 if (!map) 91 return; 92 93 dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0); 94 sg_free_table(map->sgt); 95 kfree(map->sgt); 96 97 kfree(map); 98 } 99 100 static void *tegra_se_cmdbuf_mmap(struct host1x_bo *host_bo) 101 { 102 struct tegra_se_cmdbuf *cmdbuf = container_of(host_bo, struct tegra_se_cmdbuf, bo); 103 104 return cmdbuf->addr; 105 } 106 107 static void tegra_se_cmdbuf_munmap(struct host1x_bo *host_bo, void *addr) 108 { 109 } 110 111 static const struct host1x_bo_ops tegra_se_cmdbuf_ops = { 112 .get = tegra_se_cmdbuf_get, 113 .put = tegra_se_cmdbuf_put, 114 .pin = tegra_se_cmdbuf_pin, 115 .unpin = tegra_se_cmdbuf_unpin, 116 .mmap = tegra_se_cmdbuf_mmap, 117 .munmap = tegra_se_cmdbuf_munmap, 118 }; 119 120 static struct tegra_se_cmdbuf *tegra_se_host1x_bo_alloc(struct tegra_se *se, ssize_t size) 121 { 122 struct tegra_se_cmdbuf *cmdbuf; 123 struct device *dev = se->dev->parent; 124 125 cmdbuf = kzalloc_obj(*cmdbuf); 126 if (!cmdbuf) 127 return NULL; 128 129 cmdbuf->addr = dma_alloc_attrs(dev, size, &cmdbuf->iova, 130 GFP_KERNEL, 0); 131 if (!cmdbuf->addr) 132 return NULL; 133 134 cmdbuf->size = size; 135 cmdbuf->dev = dev; 136 137 host1x_bo_init(&cmdbuf->bo, &tegra_se_cmdbuf_ops); 138 kref_init(&cmdbuf->ref); 139 140 return cmdbuf; 141 } 142 143 int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size) 144 { 145 struct host1x_job *job; 146 int ret; 147 148 job = host1x_job_alloc(se->channel, 1, 0, true); 149 if (!job) { 150 dev_err(se->dev, "failed to allocate host1x job\n"); 151 return -ENOMEM; 152 } 153 154 job->syncpt = host1x_syncpt_get(se->syncpt); 155 job->syncpt_incrs = 1; 156 job->client = &se->client; 157 job->class = se->client.class; 158 job->serialize = true; 159 job->engine_fallback_streamid = se->stream_id; 160 job->engine_streamid_offset = SE_STREAM_ID; 161 162 cmdbuf->words = size; 163 164 host1x_job_add_gather(job, &cmdbuf->bo, size, 0); 165 166 ret = host1x_job_pin(job, se->dev); 167 if (ret) { 168 dev_err(se->dev, "failed to pin host1x job\n"); 169 goto job_put; 170 } 171 172 ret = host1x_job_submit(job); 173 if (ret) { 174 dev_err(se->dev, "failed to submit host1x job\n"); 175 goto job_unpin; 176 } 177 178 ret = host1x_syncpt_wait(job->syncpt, job->syncpt_end, 179 MAX_SCHEDULE_TIMEOUT, NULL); 180 if (ret) { 181 dev_err(se->dev, "host1x job timed out\n"); 182 goto job_put; 183 } 184 185 host1x_job_put(job); 186 return 0; 187 188 job_unpin: 189 host1x_job_unpin(job); 190 job_put: 191 host1x_job_put(job); 192 193 return ret; 194 } 195 196 static int tegra_se_client_init(struct host1x_client *client) 197 { 198 struct tegra_se *se = container_of(client, struct tegra_se, client); 199 int ret; 200 201 se->channel = host1x_channel_request(&se->client); 202 if (!se->channel) { 203 dev_err(se->dev, "host1x channel map failed\n"); 204 return -ENODEV; 205 } 206 207 se->syncpt = host1x_syncpt_request(&se->client, 0); 208 if (!se->syncpt) { 209 dev_err(se->dev, "host1x syncpt allocation failed\n"); 210 ret = -EINVAL; 211 goto channel_put; 212 } 213 214 se->syncpt_id = host1x_syncpt_id(se->syncpt); 215 216 se->cmdbuf = tegra_se_host1x_bo_alloc(se, SZ_4K); 217 if (!se->cmdbuf) { 218 ret = -ENOMEM; 219 goto syncpt_put; 220 } 221 222 se->keybuf = tegra_se_host1x_bo_alloc(se, SZ_4K); 223 if (!se->keybuf) { 224 ret = -ENOMEM; 225 goto cmdbuf_put; 226 } 227 228 ret = se->hw->init_alg(se); 229 if (ret) { 230 dev_err(se->dev, "failed to register algorithms\n"); 231 goto keybuf_put; 232 } 233 234 return 0; 235 236 keybuf_put: 237 tegra_se_cmdbuf_put(&se->keybuf->bo); 238 cmdbuf_put: 239 tegra_se_cmdbuf_put(&se->cmdbuf->bo); 240 syncpt_put: 241 host1x_syncpt_put(se->syncpt); 242 channel_put: 243 host1x_channel_put(se->channel); 244 245 return ret; 246 } 247 248 static int tegra_se_client_deinit(struct host1x_client *client) 249 { 250 struct tegra_se *se = container_of(client, struct tegra_se, client); 251 252 se->hw->deinit_alg(se); 253 tegra_se_cmdbuf_put(&se->cmdbuf->bo); 254 host1x_syncpt_put(se->syncpt); 255 host1x_channel_put(se->channel); 256 257 return 0; 258 } 259 260 static const struct host1x_client_ops tegra_se_client_ops = { 261 .init = tegra_se_client_init, 262 .exit = tegra_se_client_deinit, 263 }; 264 265 static int tegra_se_host1x_register(struct tegra_se *se) 266 { 267 INIT_LIST_HEAD(&se->client.list); 268 se->client.dev = se->dev; 269 se->client.ops = &tegra_se_client_ops; 270 se->client.class = se->hw->host1x_class; 271 se->client.num_syncpts = 1; 272 273 host1x_client_register(&se->client); 274 275 return 0; 276 } 277 278 static int tegra_se_probe(struct platform_device *pdev) 279 { 280 struct device *dev = &pdev->dev; 281 struct tegra_se *se; 282 int ret; 283 284 se = devm_kzalloc(dev, sizeof(*se), GFP_KERNEL); 285 if (!se) 286 return -ENOMEM; 287 288 se->dev = dev; 289 se->owner = TEGRA_GPSE_ID; 290 se->hw = device_get_match_data(&pdev->dev); 291 292 se->base = devm_platform_ioremap_resource(pdev, 0); 293 if (IS_ERR(se->base)) 294 return PTR_ERR(se->base); 295 296 dma_set_mask_and_coherent(dev, DMA_BIT_MASK(39)); 297 platform_set_drvdata(pdev, se); 298 299 se->clk = devm_clk_get_enabled(se->dev, NULL); 300 if (IS_ERR(se->clk)) 301 return dev_err_probe(dev, PTR_ERR(se->clk), 302 "failed to enable clocks\n"); 303 304 if (!tegra_dev_iommu_get_stream_id(dev, &se->stream_id)) 305 return dev_err_probe(dev, -ENODEV, 306 "failed to get IOMMU stream ID\n"); 307 308 writel(se->stream_id, se->base + SE_STREAM_ID); 309 310 se->engine = crypto_engine_alloc_init(dev, 0); 311 if (!se->engine) 312 return -ENOMEM; 313 314 ret = crypto_engine_start(se->engine); 315 if (ret) { 316 crypto_engine_exit(se->engine); 317 return dev_err_probe(dev, ret, "failed to start crypto engine\n"); 318 } 319 320 ret = tegra_se_host1x_register(se); 321 if (ret) { 322 crypto_engine_exit(se->engine); 323 return dev_err_probe(dev, ret, "failed to init host1x params\n"); 324 } 325 326 return 0; 327 } 328 329 static void tegra_se_remove(struct platform_device *pdev) 330 { 331 struct tegra_se *se = platform_get_drvdata(pdev); 332 333 crypto_engine_exit(se->engine); 334 host1x_client_unregister(&se->client); 335 } 336 337 static const struct tegra_se_regs tegra234_aes1_regs = { 338 .config = SE_AES1_CFG, 339 .op = SE_AES1_OPERATION, 340 .last_blk = SE_AES1_LAST_BLOCK, 341 .linear_ctr = SE_AES1_LINEAR_CTR, 342 .aad_len = SE_AES1_AAD_LEN, 343 .cryp_msg_len = SE_AES1_CRYPTO_MSG_LEN, 344 .manifest = SE_AES1_KEYMANIFEST, 345 .key_addr = SE_AES1_KEY_ADDR, 346 .key_data = SE_AES1_KEY_DATA, 347 .key_dst = SE_AES1_KEY_DST, 348 .result = SE_AES1_CMAC_RESULT, 349 }; 350 351 static const struct tegra_se_regs tegra234_hash_regs = { 352 .config = SE_SHA_CFG, 353 .op = SE_SHA_OPERATION, 354 .manifest = SE_SHA_KEYMANIFEST, 355 .key_addr = SE_SHA_KEY_ADDR, 356 .key_data = SE_SHA_KEY_DATA, 357 .key_dst = SE_SHA_KEY_DST, 358 .result = SE_SHA_HASH_RESULT, 359 }; 360 361 static const struct tegra_se_hw tegra234_aes_hw = { 362 .regs = &tegra234_aes1_regs, 363 .kac_ver = 1, 364 .host1x_class = 0x3b, 365 .init_alg = tegra_init_aes, 366 .deinit_alg = tegra_deinit_aes, 367 }; 368 369 static const struct tegra_se_hw tegra234_hash_hw = { 370 .regs = &tegra234_hash_regs, 371 .kac_ver = 1, 372 .host1x_class = 0x3d, 373 .init_alg = tegra_init_hash, 374 .deinit_alg = tegra_deinit_hash, 375 }; 376 377 static const struct of_device_id tegra_se_of_match[] = { 378 { 379 .compatible = "nvidia,tegra234-se-aes", 380 .data = &tegra234_aes_hw 381 }, { 382 .compatible = "nvidia,tegra234-se-hash", 383 .data = &tegra234_hash_hw, 384 }, 385 { }, 386 }; 387 MODULE_DEVICE_TABLE(of, tegra_se_of_match); 388 389 static struct platform_driver tegra_se_driver = { 390 .driver = { 391 .name = "tegra-se", 392 .of_match_table = tegra_se_of_match, 393 }, 394 .probe = tegra_se_probe, 395 .remove = tegra_se_remove, 396 }; 397 398 static int tegra_se_host1x_probe(struct host1x_device *dev) 399 { 400 return host1x_device_init(dev); 401 } 402 403 static void tegra_se_host1x_remove(struct host1x_device *dev) 404 { 405 host1x_device_exit(dev); 406 } 407 408 static struct host1x_driver tegra_se_host1x_driver = { 409 .driver = { 410 .name = "tegra-se-host1x", 411 }, 412 .probe = tegra_se_host1x_probe, 413 .remove = tegra_se_host1x_remove, 414 .subdevs = tegra_se_of_match, 415 }; 416 417 static int __init tegra_se_module_init(void) 418 { 419 int ret; 420 421 ret = host1x_driver_register(&tegra_se_host1x_driver); 422 if (ret) 423 return ret; 424 425 return platform_driver_register(&tegra_se_driver); 426 } 427 428 static void __exit tegra_se_module_exit(void) 429 { 430 host1x_driver_unregister(&tegra_se_host1x_driver); 431 platform_driver_unregister(&tegra_se_driver); 432 } 433 434 module_init(tegra_se_module_init); 435 module_exit(tegra_se_module_exit); 436 437 MODULE_DESCRIPTION("NVIDIA Tegra Security Engine Driver"); 438 MODULE_AUTHOR("Akhil R <akhilrajeev@nvidia.com>"); 439 MODULE_LICENSE("GPL"); 440