tegra-se-main.c 9.7 KB

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