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