1 // SPDX-License-Identifier: GPL-2.0-only
2 // SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 * Crypto driver for NVIDIA Security Engine in Tegra Chips
8 #include <linux/dma-mapping.h>
9 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/mod_devicetable.h>
13 #include <crypto/engine.h>
17 static struct host1x_bo *tegra_se_cmdbuf_get(struct host1x_bo *host_bo)
19 struct tegra_se_cmdbuf *cmdbuf = container_of(host_bo, struct tegra_se_cmdbuf, bo);
21 kref_get(&cmdbuf->ref);
26 static void tegra_se_cmdbuf_release(struct kref *ref)
28 struct tegra_se_cmdbuf *cmdbuf = container_of(ref, struct tegra_se_cmdbuf, ref);
30 dma_free_attrs(cmdbuf->dev, cmdbuf->size, cmdbuf->addr,
36 static void tegra_se_cmdbuf_put(struct host1x_bo *host_bo)
38 struct tegra_se_cmdbuf *cmdbuf = container_of(host_bo, struct tegra_se_cmdbuf, bo);
40 kref_put(&cmdbuf->ref, tegra_se_cmdbuf_release);
43 static struct host1x_bo_mapping *
44 tegra_se_cmdbuf_pin(struct device *dev, struct host1x_bo *bo, enum dma_data_direction direction)
46 struct tegra_se_cmdbuf *cmdbuf = container_of(bo, struct tegra_se_cmdbuf, bo);
47 struct host1x_bo_mapping *map;
50 map = kzalloc(sizeof(*map), GFP_KERNEL);
52 return ERR_PTR(-ENOMEM);
55 map->bo = host1x_bo_get(bo);
56 map->direction = direction;
59 map->sgt = kzalloc(sizeof(*map->sgt), GFP_KERNEL);
65 err = dma_get_sgtable(dev, map->sgt, cmdbuf->addr,
66 cmdbuf->iova, cmdbuf->words * 4);
70 err = dma_map_sgtable(dev, map->sgt, direction, 0);
74 map->phys = sg_dma_address(map->sgt->sgl);
75 map->size = cmdbuf->words * 4;
81 sg_free_table(map->sgt);
88 static void tegra_se_cmdbuf_unpin(struct host1x_bo_mapping *map)
93 dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0);
94 sg_free_table(map->sgt);
96 host1x_bo_put(map->bo);
101 static void *tegra_se_cmdbuf_mmap(struct host1x_bo *host_bo)
103 struct tegra_se_cmdbuf *cmdbuf = container_of(host_bo, struct tegra_se_cmdbuf, bo);
108 static void tegra_se_cmdbuf_munmap(struct host1x_bo *host_bo, void *addr)
112 static const struct host1x_bo_ops tegra_se_cmdbuf_ops = {
113 .get = tegra_se_cmdbuf_get,
114 .put = tegra_se_cmdbuf_put,
115 .pin = tegra_se_cmdbuf_pin,
116 .unpin = tegra_se_cmdbuf_unpin,
117 .mmap = tegra_se_cmdbuf_mmap,
118 .munmap = tegra_se_cmdbuf_munmap,
121 static struct tegra_se_cmdbuf *tegra_se_host1x_bo_alloc(struct tegra_se *se, ssize_t size)
123 struct tegra_se_cmdbuf *cmdbuf;
124 struct device *dev = se->dev->parent;
126 cmdbuf = kzalloc(sizeof(*cmdbuf), GFP_KERNEL);
130 cmdbuf->addr = dma_alloc_attrs(dev, size, &cmdbuf->iova,
138 host1x_bo_init(&cmdbuf->bo, &tegra_se_cmdbuf_ops);
139 kref_init(&cmdbuf->ref);
144 int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
146 struct host1x_job *job;
149 job = host1x_job_alloc(se->channel, 1, 0, true);
151 dev_err(se->dev, "failed to allocate host1x job\n");
155 job->syncpt = host1x_syncpt_get(se->syncpt);
156 job->syncpt_incrs = 1;
157 job->client = &se->client;
158 job->class = se->client.class;
159 job->serialize = true;
160 job->engine_fallback_streamid = se->stream_id;
161 job->engine_streamid_offset = SE_STREAM_ID;
163 se->cmdbuf->words = size;
165 host1x_job_add_gather(job, &se->cmdbuf->bo, size, 0);
167 ret = host1x_job_pin(job, se->dev);
169 dev_err(se->dev, "failed to pin host1x job\n");
173 ret = host1x_job_submit(job);
175 dev_err(se->dev, "failed to submit host1x job\n");
179 ret = host1x_syncpt_wait(job->syncpt, job->syncpt_end,
180 MAX_SCHEDULE_TIMEOUT, NULL);
182 dev_err(se->dev, "host1x job timed out\n");
190 host1x_job_unpin(job);
197 static int tegra_se_client_init(struct host1x_client *client)
199 struct tegra_se *se = container_of(client, struct tegra_se, client);
202 se->channel = host1x_channel_request(&se->client);
204 dev_err(se->dev, "host1x channel map failed\n");
208 se->syncpt = host1x_syncpt_request(&se->client, 0);
210 dev_err(se->dev, "host1x syncpt allocation failed\n");
215 se->syncpt_id = host1x_syncpt_id(se->syncpt);
217 se->cmdbuf = tegra_se_host1x_bo_alloc(se, SZ_4K);
223 ret = se->hw->init_alg(se);
225 dev_err(se->dev, "failed to register algorithms\n");
232 tegra_se_cmdbuf_put(&se->cmdbuf->bo);
234 host1x_syncpt_put(se->syncpt);
236 host1x_channel_put(se->channel);
241 static int tegra_se_client_deinit(struct host1x_client *client)
243 struct tegra_se *se = container_of(client, struct tegra_se, client);
245 se->hw->deinit_alg(se);
246 tegra_se_cmdbuf_put(&se->cmdbuf->bo);
247 host1x_syncpt_put(se->syncpt);
248 host1x_channel_put(se->channel);
253 static const struct host1x_client_ops tegra_se_client_ops = {
254 .init = tegra_se_client_init,
255 .exit = tegra_se_client_deinit,
258 static int tegra_se_host1x_register(struct tegra_se *se)
260 INIT_LIST_HEAD(&se->client.list);
261 se->client.dev = se->dev;
262 se->client.ops = &tegra_se_client_ops;
263 se->client.class = se->hw->host1x_class;
264 se->client.num_syncpts = 1;
266 host1x_client_register(&se->client);
271 static int tegra_se_probe(struct platform_device *pdev)
273 struct device *dev = &pdev->dev;
277 se = devm_kzalloc(dev, sizeof(*se), GFP_KERNEL);
282 se->owner = TEGRA_GPSE_ID;
283 se->hw = device_get_match_data(&pdev->dev);
285 se->base = devm_platform_ioremap_resource(pdev, 0);
286 if (IS_ERR(se->base))
287 return PTR_ERR(se->base);
289 dma_set_mask_and_coherent(dev, DMA_BIT_MASK(39));
290 platform_set_drvdata(pdev, se);
292 se->clk = devm_clk_get_enabled(se->dev, NULL);
294 return dev_err_probe(dev, PTR_ERR(se->clk),
295 "failed to enable clocks\n");
297 if (!tegra_dev_iommu_get_stream_id(dev, &se->stream_id))
298 return dev_err_probe(dev, -ENODEV,
299 "failed to get IOMMU stream ID\n");
301 writel(se->stream_id, se->base + SE_STREAM_ID);
303 se->engine = crypto_engine_alloc_init(dev, 0);
305 return dev_err_probe(dev, -ENOMEM, "failed to init crypto engine\n");
307 ret = crypto_engine_start(se->engine);
309 crypto_engine_exit(se->engine);
310 return dev_err_probe(dev, ret, "failed to start crypto engine\n");
313 ret = tegra_se_host1x_register(se);
315 crypto_engine_stop(se->engine);
316 crypto_engine_exit(se->engine);
317 return dev_err_probe(dev, ret, "failed to init host1x params\n");
323 static void tegra_se_remove(struct platform_device *pdev)
325 struct tegra_se *se = platform_get_drvdata(pdev);
327 crypto_engine_stop(se->engine);
328 crypto_engine_exit(se->engine);
329 host1x_client_unregister(&se->client);
332 static const struct tegra_se_regs tegra234_aes1_regs = {
333 .config = SE_AES1_CFG,
334 .op = SE_AES1_OPERATION,
335 .last_blk = SE_AES1_LAST_BLOCK,
336 .linear_ctr = SE_AES1_LINEAR_CTR,
337 .aad_len = SE_AES1_AAD_LEN,
338 .cryp_msg_len = SE_AES1_CRYPTO_MSG_LEN,
339 .manifest = SE_AES1_KEYMANIFEST,
340 .key_addr = SE_AES1_KEY_ADDR,
341 .key_data = SE_AES1_KEY_DATA,
342 .key_dst = SE_AES1_KEY_DST,
343 .result = SE_AES1_CMAC_RESULT,
346 static const struct tegra_se_regs tegra234_hash_regs = {
347 .config = SE_SHA_CFG,
348 .op = SE_SHA_OPERATION,
349 .manifest = SE_SHA_KEYMANIFEST,
350 .key_addr = SE_SHA_KEY_ADDR,
351 .key_data = SE_SHA_KEY_DATA,
352 .key_dst = SE_SHA_KEY_DST,
353 .result = SE_SHA_HASH_RESULT,
356 static const struct tegra_se_hw tegra234_aes_hw = {
357 .regs = &tegra234_aes1_regs,
359 .host1x_class = 0x3b,
360 .init_alg = tegra_init_aes,
361 .deinit_alg = tegra_deinit_aes,
364 static const struct tegra_se_hw tegra234_hash_hw = {
365 .regs = &tegra234_hash_regs,
367 .host1x_class = 0x3d,
368 .init_alg = tegra_init_hash,
369 .deinit_alg = tegra_deinit_hash,
372 static const struct of_device_id tegra_se_of_match[] = {
374 .compatible = "nvidia,tegra234-se-aes",
375 .data = &tegra234_aes_hw
377 .compatible = "nvidia,tegra234-se-hash",
378 .data = &tegra234_hash_hw,
382 MODULE_DEVICE_TABLE(of, tegra_se_of_match);
384 static struct platform_driver tegra_se_driver = {
387 .of_match_table = tegra_se_of_match,
389 .probe = tegra_se_probe,
390 .remove_new = tegra_se_remove,
393 static int tegra_se_host1x_probe(struct host1x_device *dev)
395 return host1x_device_init(dev);
398 static int tegra_se_host1x_remove(struct host1x_device *dev)
400 host1x_device_exit(dev);
405 static struct host1x_driver tegra_se_host1x_driver = {
407 .name = "tegra-se-host1x",
409 .probe = tegra_se_host1x_probe,
410 .remove = tegra_se_host1x_remove,
411 .subdevs = tegra_se_of_match,
414 static int __init tegra_se_module_init(void)
418 ret = host1x_driver_register(&tegra_se_host1x_driver);
422 return platform_driver_register(&tegra_se_driver);
425 static void __exit tegra_se_module_exit(void)
427 host1x_driver_unregister(&tegra_se_host1x_driver);
428 platform_driver_unregister(&tegra_se_driver);
431 module_init(tegra_se_module_init);
432 module_exit(tegra_se_module_exit);
434 MODULE_DESCRIPTION("NVIDIA Tegra Security Engine Driver");
436 MODULE_LICENSE("GPL");