rk3288_crypto.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Crypto acceleration support for Rockchip RK3288
  4. *
  5. * Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd
  6. *
  7. * Author: Zain Wang <zain.wang@rock-chips.com>
  8. *
  9. * Some ideas are from marvell-cesa.c and s5p-sss.c driver.
  10. */
  11. #include "rk3288_crypto.h"
  12. #include <crypto/engine.h>
  13. #include <crypto/internal/hash.h>
  14. #include <crypto/internal/skcipher.h>
  15. #include <linux/clk.h>
  16. #include <linux/dma-mapping.h>
  17. #include <linux/debugfs.h>
  18. #include <linux/delay.h>
  19. #include <linux/err.h>
  20. #include <linux/kernel.h>
  21. #include <linux/io.h>
  22. #include <linux/module.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/of.h>
  25. #include <linux/reset.h>
  26. #include <linux/spinlock.h>
  27. static struct rockchip_ip rocklist = {
  28. .dev_list = LIST_HEAD_INIT(rocklist.dev_list),
  29. .lock = __SPIN_LOCK_UNLOCKED(rocklist.lock),
  30. };
  31. struct rk_crypto_info *get_rk_crypto(void)
  32. {
  33. struct rk_crypto_info *first;
  34. spin_lock(&rocklist.lock);
  35. first = list_first_entry_or_null(&rocklist.dev_list,
  36. struct rk_crypto_info, list);
  37. list_rotate_left(&rocklist.dev_list);
  38. spin_unlock(&rocklist.lock);
  39. return first;
  40. }
  41. static const struct rk_variant rk3288_variant = {
  42. .num_clks = 4,
  43. .rkclks = {
  44. { "sclk", 150000000},
  45. }
  46. };
  47. static const struct rk_variant rk3328_variant = {
  48. .num_clks = 3,
  49. };
  50. static const struct rk_variant rk3399_variant = {
  51. .num_clks = 3,
  52. };
  53. static int rk_crypto_get_clks(struct rk_crypto_info *dev)
  54. {
  55. int i, j, err;
  56. unsigned long cr;
  57. dev->num_clks = devm_clk_bulk_get_all(dev->dev, &dev->clks);
  58. if (dev->num_clks < dev->variant->num_clks) {
  59. dev_err(dev->dev, "Missing clocks, got %d instead of %d\n",
  60. dev->num_clks, dev->variant->num_clks);
  61. return -EINVAL;
  62. }
  63. for (i = 0; i < dev->num_clks; i++) {
  64. cr = clk_get_rate(dev->clks[i].clk);
  65. for (j = 0; j < ARRAY_SIZE(dev->variant->rkclks); j++) {
  66. if (dev->variant->rkclks[j].max == 0)
  67. continue;
  68. if (strcmp(dev->variant->rkclks[j].name, dev->clks[i].id))
  69. continue;
  70. if (cr > dev->variant->rkclks[j].max) {
  71. err = clk_set_rate(dev->clks[i].clk,
  72. dev->variant->rkclks[j].max);
  73. if (err)
  74. dev_err(dev->dev, "Fail downclocking %s from %lu to %lu\n",
  75. dev->variant->rkclks[j].name, cr,
  76. dev->variant->rkclks[j].max);
  77. else
  78. dev_info(dev->dev, "Downclocking %s from %lu to %lu\n",
  79. dev->variant->rkclks[j].name, cr,
  80. dev->variant->rkclks[j].max);
  81. }
  82. }
  83. }
  84. return 0;
  85. }
  86. static int rk_crypto_enable_clk(struct rk_crypto_info *dev)
  87. {
  88. int err;
  89. err = clk_bulk_prepare_enable(dev->num_clks, dev->clks);
  90. if (err)
  91. dev_err(dev->dev, "Could not enable clock clks\n");
  92. return err;
  93. }
  94. static void rk_crypto_disable_clk(struct rk_crypto_info *dev)
  95. {
  96. clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
  97. }
  98. /*
  99. * Power management strategy: The device is suspended until a request
  100. * is handled. For avoiding suspend/resume yoyo, the autosuspend is set to 2s.
  101. */
  102. static int rk_crypto_pm_suspend(struct device *dev)
  103. {
  104. struct rk_crypto_info *rkdev = dev_get_drvdata(dev);
  105. rk_crypto_disable_clk(rkdev);
  106. reset_control_assert(rkdev->rst);
  107. return 0;
  108. }
  109. static int rk_crypto_pm_resume(struct device *dev)
  110. {
  111. struct rk_crypto_info *rkdev = dev_get_drvdata(dev);
  112. int ret;
  113. ret = rk_crypto_enable_clk(rkdev);
  114. if (ret)
  115. return ret;
  116. reset_control_deassert(rkdev->rst);
  117. return 0;
  118. }
  119. static const struct dev_pm_ops rk_crypto_pm_ops = {
  120. SET_RUNTIME_PM_OPS(rk_crypto_pm_suspend, rk_crypto_pm_resume, NULL)
  121. };
  122. static int rk_crypto_pm_init(struct rk_crypto_info *rkdev)
  123. {
  124. int err;
  125. pm_runtime_use_autosuspend(rkdev->dev);
  126. pm_runtime_set_autosuspend_delay(rkdev->dev, 2000);
  127. err = pm_runtime_set_suspended(rkdev->dev);
  128. if (err)
  129. return err;
  130. pm_runtime_enable(rkdev->dev);
  131. return err;
  132. }
  133. static void rk_crypto_pm_exit(struct rk_crypto_info *rkdev)
  134. {
  135. pm_runtime_disable(rkdev->dev);
  136. }
  137. static irqreturn_t rk_crypto_irq_handle(int irq, void *dev_id)
  138. {
  139. struct rk_crypto_info *dev = platform_get_drvdata(dev_id);
  140. u32 interrupt_status;
  141. interrupt_status = CRYPTO_READ(dev, RK_CRYPTO_INTSTS);
  142. CRYPTO_WRITE(dev, RK_CRYPTO_INTSTS, interrupt_status);
  143. dev->status = 1;
  144. if (interrupt_status & 0x0a) {
  145. dev_warn(dev->dev, "DMA Error\n");
  146. dev->status = 0;
  147. }
  148. complete(&dev->complete);
  149. return IRQ_HANDLED;
  150. }
  151. static struct rk_crypto_tmp *rk_cipher_algs[] = {
  152. &rk_ecb_aes_alg,
  153. &rk_cbc_aes_alg,
  154. &rk_ecb_des_alg,
  155. &rk_cbc_des_alg,
  156. &rk_ecb_des3_ede_alg,
  157. &rk_cbc_des3_ede_alg,
  158. &rk_ahash_sha1,
  159. &rk_ahash_sha256,
  160. &rk_ahash_md5,
  161. };
  162. static int rk_crypto_debugfs_show(struct seq_file *seq, void *v)
  163. {
  164. struct rk_crypto_info *dd;
  165. unsigned int i;
  166. spin_lock(&rocklist.lock);
  167. list_for_each_entry(dd, &rocklist.dev_list, list) {
  168. seq_printf(seq, "%s %s requests: %lu\n",
  169. dev_driver_string(dd->dev), dev_name(dd->dev),
  170. dd->nreq);
  171. }
  172. spin_unlock(&rocklist.lock);
  173. for (i = 0; i < ARRAY_SIZE(rk_cipher_algs); i++) {
  174. if (!rk_cipher_algs[i]->dev)
  175. continue;
  176. switch (rk_cipher_algs[i]->type) {
  177. case CRYPTO_ALG_TYPE_SKCIPHER:
  178. seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n",
  179. rk_cipher_algs[i]->alg.skcipher.base.base.cra_driver_name,
  180. rk_cipher_algs[i]->alg.skcipher.base.base.cra_name,
  181. rk_cipher_algs[i]->stat_req, rk_cipher_algs[i]->stat_fb);
  182. seq_printf(seq, "\tfallback due to length: %lu\n",
  183. rk_cipher_algs[i]->stat_fb_len);
  184. seq_printf(seq, "\tfallback due to alignment: %lu\n",
  185. rk_cipher_algs[i]->stat_fb_align);
  186. seq_printf(seq, "\tfallback due to SGs: %lu\n",
  187. rk_cipher_algs[i]->stat_fb_sgdiff);
  188. break;
  189. case CRYPTO_ALG_TYPE_AHASH:
  190. seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n",
  191. rk_cipher_algs[i]->alg.hash.base.halg.base.cra_driver_name,
  192. rk_cipher_algs[i]->alg.hash.base.halg.base.cra_name,
  193. rk_cipher_algs[i]->stat_req, rk_cipher_algs[i]->stat_fb);
  194. break;
  195. }
  196. }
  197. return 0;
  198. }
  199. DEFINE_SHOW_ATTRIBUTE(rk_crypto_debugfs);
  200. static void register_debugfs(struct rk_crypto_info *crypto_info)
  201. {
  202. struct dentry *dbgfs_dir __maybe_unused;
  203. struct dentry *dbgfs_stats __maybe_unused;
  204. /* Ignore error of debugfs */
  205. dbgfs_dir = debugfs_create_dir("rk3288_crypto", NULL);
  206. dbgfs_stats = debugfs_create_file("stats", 0444, dbgfs_dir, &rocklist,
  207. &rk_crypto_debugfs_fops);
  208. #ifdef CONFIG_CRYPTO_DEV_ROCKCHIP_DEBUG
  209. rocklist.dbgfs_dir = dbgfs_dir;
  210. rocklist.dbgfs_stats = dbgfs_stats;
  211. #endif
  212. }
  213. static int rk_crypto_register(struct rk_crypto_info *crypto_info)
  214. {
  215. unsigned int i, k;
  216. int err = 0;
  217. for (i = 0; i < ARRAY_SIZE(rk_cipher_algs); i++) {
  218. rk_cipher_algs[i]->dev = crypto_info;
  219. switch (rk_cipher_algs[i]->type) {
  220. case CRYPTO_ALG_TYPE_SKCIPHER:
  221. dev_info(crypto_info->dev, "Register %s as %s\n",
  222. rk_cipher_algs[i]->alg.skcipher.base.base.cra_name,
  223. rk_cipher_algs[i]->alg.skcipher.base.base.cra_driver_name);
  224. err = crypto_engine_register_skcipher(&rk_cipher_algs[i]->alg.skcipher);
  225. break;
  226. case CRYPTO_ALG_TYPE_AHASH:
  227. dev_info(crypto_info->dev, "Register %s as %s\n",
  228. rk_cipher_algs[i]->alg.hash.base.halg.base.cra_name,
  229. rk_cipher_algs[i]->alg.hash.base.halg.base.cra_driver_name);
  230. err = crypto_engine_register_ahash(&rk_cipher_algs[i]->alg.hash);
  231. break;
  232. default:
  233. dev_err(crypto_info->dev, "unknown algorithm\n");
  234. }
  235. if (err)
  236. goto err_cipher_algs;
  237. }
  238. return 0;
  239. err_cipher_algs:
  240. for (k = 0; k < i; k++) {
  241. if (rk_cipher_algs[i]->type == CRYPTO_ALG_TYPE_SKCIPHER)
  242. crypto_engine_unregister_skcipher(&rk_cipher_algs[k]->alg.skcipher);
  243. else
  244. crypto_engine_unregister_ahash(&rk_cipher_algs[i]->alg.hash);
  245. }
  246. return err;
  247. }
  248. static void rk_crypto_unregister(void)
  249. {
  250. unsigned int i;
  251. for (i = 0; i < ARRAY_SIZE(rk_cipher_algs); i++) {
  252. if (rk_cipher_algs[i]->type == CRYPTO_ALG_TYPE_SKCIPHER)
  253. crypto_engine_unregister_skcipher(&rk_cipher_algs[i]->alg.skcipher);
  254. else
  255. crypto_engine_unregister_ahash(&rk_cipher_algs[i]->alg.hash);
  256. }
  257. }
  258. static const struct of_device_id crypto_of_id_table[] = {
  259. { .compatible = "rockchip,rk3288-crypto",
  260. .data = &rk3288_variant,
  261. },
  262. { .compatible = "rockchip,rk3328-crypto",
  263. .data = &rk3328_variant,
  264. },
  265. { .compatible = "rockchip,rk3399-crypto",
  266. .data = &rk3399_variant,
  267. },
  268. {}
  269. };
  270. MODULE_DEVICE_TABLE(of, crypto_of_id_table);
  271. static int rk_crypto_probe(struct platform_device *pdev)
  272. {
  273. struct device *dev = &pdev->dev;
  274. struct rk_crypto_info *crypto_info, *first;
  275. int err = 0;
  276. crypto_info = devm_kzalloc(&pdev->dev,
  277. sizeof(*crypto_info), GFP_KERNEL);
  278. if (!crypto_info) {
  279. err = -ENOMEM;
  280. goto err_crypto;
  281. }
  282. crypto_info->dev = &pdev->dev;
  283. platform_set_drvdata(pdev, crypto_info);
  284. crypto_info->variant = of_device_get_match_data(&pdev->dev);
  285. if (!crypto_info->variant) {
  286. dev_err(&pdev->dev, "Missing variant\n");
  287. return -EINVAL;
  288. }
  289. crypto_info->rst = devm_reset_control_array_get_exclusive(dev);
  290. if (IS_ERR(crypto_info->rst)) {
  291. err = PTR_ERR(crypto_info->rst);
  292. goto err_crypto;
  293. }
  294. reset_control_assert(crypto_info->rst);
  295. usleep_range(10, 20);
  296. reset_control_deassert(crypto_info->rst);
  297. crypto_info->reg = devm_platform_ioremap_resource(pdev, 0);
  298. if (IS_ERR(crypto_info->reg)) {
  299. err = PTR_ERR(crypto_info->reg);
  300. goto err_crypto;
  301. }
  302. err = rk_crypto_get_clks(crypto_info);
  303. if (err)
  304. goto err_crypto;
  305. crypto_info->irq = platform_get_irq(pdev, 0);
  306. if (crypto_info->irq < 0) {
  307. err = crypto_info->irq;
  308. goto err_crypto;
  309. }
  310. err = devm_request_irq(&pdev->dev, crypto_info->irq,
  311. rk_crypto_irq_handle, IRQF_SHARED,
  312. "rk-crypto", pdev);
  313. if (err) {
  314. dev_err(&pdev->dev, "irq request failed.\n");
  315. goto err_crypto;
  316. }
  317. crypto_info->engine = crypto_engine_alloc_init(&pdev->dev, true);
  318. if (!crypto_info->engine) {
  319. err = -ENOMEM;
  320. goto err_crypto;
  321. }
  322. crypto_engine_start(crypto_info->engine);
  323. init_completion(&crypto_info->complete);
  324. err = rk_crypto_pm_init(crypto_info);
  325. if (err)
  326. goto err_pm;
  327. spin_lock(&rocklist.lock);
  328. first = list_first_entry_or_null(&rocklist.dev_list,
  329. struct rk_crypto_info, list);
  330. list_add_tail(&crypto_info->list, &rocklist.dev_list);
  331. spin_unlock(&rocklist.lock);
  332. if (!first) {
  333. err = rk_crypto_register(crypto_info);
  334. if (err) {
  335. dev_err(dev, "Fail to register crypto algorithms");
  336. goto err_register_alg;
  337. }
  338. register_debugfs(crypto_info);
  339. }
  340. return 0;
  341. err_register_alg:
  342. rk_crypto_pm_exit(crypto_info);
  343. err_pm:
  344. crypto_engine_exit(crypto_info->engine);
  345. err_crypto:
  346. dev_err(dev, "Crypto Accelerator not successfully registered\n");
  347. return err;
  348. }
  349. static void rk_crypto_remove(struct platform_device *pdev)
  350. {
  351. struct rk_crypto_info *crypto_tmp = platform_get_drvdata(pdev);
  352. struct rk_crypto_info *first;
  353. spin_lock_bh(&rocklist.lock);
  354. list_del(&crypto_tmp->list);
  355. first = list_first_entry_or_null(&rocklist.dev_list,
  356. struct rk_crypto_info, list);
  357. spin_unlock_bh(&rocklist.lock);
  358. if (!first) {
  359. #ifdef CONFIG_CRYPTO_DEV_ROCKCHIP_DEBUG
  360. debugfs_remove_recursive(rocklist.dbgfs_dir);
  361. #endif
  362. rk_crypto_unregister();
  363. }
  364. rk_crypto_pm_exit(crypto_tmp);
  365. crypto_engine_exit(crypto_tmp->engine);
  366. }
  367. static struct platform_driver crypto_driver = {
  368. .probe = rk_crypto_probe,
  369. .remove_new = rk_crypto_remove,
  370. .driver = {
  371. .name = "rk3288-crypto",
  372. .pm = &rk_crypto_pm_ops,
  373. .of_match_table = crypto_of_id_table,
  374. },
  375. };
  376. module_platform_driver(crypto_driver);
  377. MODULE_AUTHOR("Zain Wang <zain.wang@rock-chips.com>");
  378. MODULE_DESCRIPTION("Support for Rockchip's cryptographic engine");
  379. MODULE_LICENSE("GPL");