imx-rngc.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * RNG driver for Freescale RNGC
  4. *
  5. * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
  6. * Copyright (C) 2017 Martin Kaiser <[email protected]>
  7. */
  8. #include <linux/module.h>
  9. #include <linux/mod_devicetable.h>
  10. #include <linux/init.h>
  11. #include <linux/kernel.h>
  12. #include <linux/clk.h>
  13. #include <linux/err.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/hw_random.h>
  17. #include <linux/completion.h>
  18. #include <linux/io.h>
  19. #define RNGC_VER_ID 0x0000
  20. #define RNGC_COMMAND 0x0004
  21. #define RNGC_CONTROL 0x0008
  22. #define RNGC_STATUS 0x000C
  23. #define RNGC_ERROR 0x0010
  24. #define RNGC_FIFO 0x0014
  25. /* the fields in the ver id register */
  26. #define RNGC_TYPE_SHIFT 28
  27. #define RNGC_VER_MAJ_SHIFT 8
  28. /* the rng_type field */
  29. #define RNGC_TYPE_RNGB 0x1
  30. #define RNGC_TYPE_RNGC 0x2
  31. #define RNGC_CMD_CLR_ERR 0x00000020
  32. #define RNGC_CMD_CLR_INT 0x00000010
  33. #define RNGC_CMD_SEED 0x00000002
  34. #define RNGC_CMD_SELF_TEST 0x00000001
  35. #define RNGC_CTRL_MASK_ERROR 0x00000040
  36. #define RNGC_CTRL_MASK_DONE 0x00000020
  37. #define RNGC_CTRL_AUTO_SEED 0x00000010
  38. #define RNGC_STATUS_ERROR 0x00010000
  39. #define RNGC_STATUS_FIFO_LEVEL_MASK 0x00000f00
  40. #define RNGC_STATUS_FIFO_LEVEL_SHIFT 8
  41. #define RNGC_STATUS_SEED_DONE 0x00000020
  42. #define RNGC_STATUS_ST_DONE 0x00000010
  43. #define RNGC_ERROR_STATUS_STAT_ERR 0x00000008
  44. #define RNGC_TIMEOUT 3000 /* 3 sec */
  45. static bool self_test = true;
  46. module_param(self_test, bool, 0);
  47. struct imx_rngc {
  48. struct device *dev;
  49. struct clk *clk;
  50. void __iomem *base;
  51. struct hwrng rng;
  52. struct completion rng_op_done;
  53. /*
  54. * err_reg is written only by the irq handler and read only
  55. * when interrupts are masked, we need no spinlock
  56. */
  57. u32 err_reg;
  58. };
  59. static inline void imx_rngc_irq_mask_clear(struct imx_rngc *rngc)
  60. {
  61. u32 ctrl, cmd;
  62. /* mask interrupts */
  63. ctrl = readl(rngc->base + RNGC_CONTROL);
  64. ctrl |= RNGC_CTRL_MASK_DONE | RNGC_CTRL_MASK_ERROR;
  65. writel(ctrl, rngc->base + RNGC_CONTROL);
  66. /*
  67. * CLR_INT clears the interrupt only if there's no error
  68. * CLR_ERR clear the interrupt and the error register if there
  69. * is an error
  70. */
  71. cmd = readl(rngc->base + RNGC_COMMAND);
  72. cmd |= RNGC_CMD_CLR_INT | RNGC_CMD_CLR_ERR;
  73. writel(cmd, rngc->base + RNGC_COMMAND);
  74. }
  75. static inline void imx_rngc_irq_unmask(struct imx_rngc *rngc)
  76. {
  77. u32 ctrl;
  78. ctrl = readl(rngc->base + RNGC_CONTROL);
  79. ctrl &= ~(RNGC_CTRL_MASK_DONE | RNGC_CTRL_MASK_ERROR);
  80. writel(ctrl, rngc->base + RNGC_CONTROL);
  81. }
  82. static int imx_rngc_self_test(struct imx_rngc *rngc)
  83. {
  84. u32 cmd;
  85. int ret;
  86. imx_rngc_irq_unmask(rngc);
  87. /* run self test */
  88. cmd = readl(rngc->base + RNGC_COMMAND);
  89. writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND);
  90. ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT));
  91. imx_rngc_irq_mask_clear(rngc);
  92. if (!ret)
  93. return -ETIMEDOUT;
  94. return rngc->err_reg ? -EIO : 0;
  95. }
  96. static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait)
  97. {
  98. struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
  99. unsigned int status;
  100. unsigned int level;
  101. int retval = 0;
  102. while (max >= sizeof(u32)) {
  103. status = readl(rngc->base + RNGC_STATUS);
  104. /* is there some error while reading this random number? */
  105. if (status & RNGC_STATUS_ERROR)
  106. break;
  107. /* how many random numbers are in FIFO? [0-16] */
  108. level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >>
  109. RNGC_STATUS_FIFO_LEVEL_SHIFT;
  110. if (level) {
  111. /* retrieve a random number from FIFO */
  112. *(u32 *)data = readl(rngc->base + RNGC_FIFO);
  113. retval += sizeof(u32);
  114. data += sizeof(u32);
  115. max -= sizeof(u32);
  116. }
  117. }
  118. return retval ? retval : -EIO;
  119. }
  120. static irqreturn_t imx_rngc_irq(int irq, void *priv)
  121. {
  122. struct imx_rngc *rngc = (struct imx_rngc *)priv;
  123. u32 status;
  124. /*
  125. * clearing the interrupt will also clear the error register
  126. * read error and status before clearing
  127. */
  128. status = readl(rngc->base + RNGC_STATUS);
  129. rngc->err_reg = readl(rngc->base + RNGC_ERROR);
  130. imx_rngc_irq_mask_clear(rngc);
  131. if (status & (RNGC_STATUS_SEED_DONE | RNGC_STATUS_ST_DONE))
  132. complete(&rngc->rng_op_done);
  133. return IRQ_HANDLED;
  134. }
  135. static int imx_rngc_init(struct hwrng *rng)
  136. {
  137. struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
  138. u32 cmd, ctrl;
  139. int ret;
  140. /* clear error */
  141. cmd = readl(rngc->base + RNGC_COMMAND);
  142. writel(cmd | RNGC_CMD_CLR_ERR, rngc->base + RNGC_COMMAND);
  143. imx_rngc_irq_unmask(rngc);
  144. /* create seed, repeat while there is some statistical error */
  145. do {
  146. /* seed creation */
  147. cmd = readl(rngc->base + RNGC_COMMAND);
  148. writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND);
  149. ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT));
  150. if (!ret) {
  151. ret = -ETIMEDOUT;
  152. goto err;
  153. }
  154. } while (rngc->err_reg == RNGC_ERROR_STATUS_STAT_ERR);
  155. if (rngc->err_reg) {
  156. ret = -EIO;
  157. goto err;
  158. }
  159. /*
  160. * enable automatic seeding, the rngc creates a new seed automatically
  161. * after serving 2^20 random 160-bit words
  162. */
  163. ctrl = readl(rngc->base + RNGC_CONTROL);
  164. ctrl |= RNGC_CTRL_AUTO_SEED;
  165. writel(ctrl, rngc->base + RNGC_CONTROL);
  166. /*
  167. * if initialisation was successful, we keep the interrupt
  168. * unmasked until imx_rngc_cleanup is called
  169. * we mask the interrupt ourselves if we return an error
  170. */
  171. return 0;
  172. err:
  173. imx_rngc_irq_mask_clear(rngc);
  174. return ret;
  175. }
  176. static void imx_rngc_cleanup(struct hwrng *rng)
  177. {
  178. struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
  179. imx_rngc_irq_mask_clear(rngc);
  180. }
  181. static int imx_rngc_probe(struct platform_device *pdev)
  182. {
  183. struct imx_rngc *rngc;
  184. int ret;
  185. int irq;
  186. u32 ver_id;
  187. u8 rng_type;
  188. rngc = devm_kzalloc(&pdev->dev, sizeof(*rngc), GFP_KERNEL);
  189. if (!rngc)
  190. return -ENOMEM;
  191. rngc->base = devm_platform_ioremap_resource(pdev, 0);
  192. if (IS_ERR(rngc->base))
  193. return PTR_ERR(rngc->base);
  194. rngc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
  195. if (IS_ERR(rngc->clk)) {
  196. dev_err(&pdev->dev, "Can not get rng_clk\n");
  197. return PTR_ERR(rngc->clk);
  198. }
  199. irq = platform_get_irq(pdev, 0);
  200. if (irq < 0)
  201. return irq;
  202. ver_id = readl(rngc->base + RNGC_VER_ID);
  203. rng_type = ver_id >> RNGC_TYPE_SHIFT;
  204. /*
  205. * This driver supports only RNGC and RNGB. (There's a different
  206. * driver for RNGA.)
  207. */
  208. if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB)
  209. return -ENODEV;
  210. init_completion(&rngc->rng_op_done);
  211. rngc->rng.name = pdev->name;
  212. rngc->rng.init = imx_rngc_init;
  213. rngc->rng.read = imx_rngc_read;
  214. rngc->rng.cleanup = imx_rngc_cleanup;
  215. rngc->rng.quality = 19;
  216. rngc->dev = &pdev->dev;
  217. platform_set_drvdata(pdev, rngc);
  218. imx_rngc_irq_mask_clear(rngc);
  219. ret = devm_request_irq(&pdev->dev,
  220. irq, imx_rngc_irq, 0, pdev->name, (void *)rngc);
  221. if (ret) {
  222. dev_err(rngc->dev, "Can't get interrupt working.\n");
  223. return ret;
  224. }
  225. if (self_test) {
  226. ret = imx_rngc_self_test(rngc);
  227. if (ret) {
  228. dev_err(rngc->dev, "self test failed\n");
  229. return ret;
  230. }
  231. }
  232. ret = devm_hwrng_register(&pdev->dev, &rngc->rng);
  233. if (ret) {
  234. dev_err(&pdev->dev, "hwrng registration failed\n");
  235. return ret;
  236. }
  237. dev_info(&pdev->dev,
  238. "Freescale RNG%c registered (HW revision %d.%02d)\n",
  239. rng_type == RNGC_TYPE_RNGB ? 'B' : 'C',
  240. (ver_id >> RNGC_VER_MAJ_SHIFT) & 0xff, ver_id & 0xff);
  241. return 0;
  242. }
  243. static int __maybe_unused imx_rngc_suspend(struct device *dev)
  244. {
  245. struct imx_rngc *rngc = dev_get_drvdata(dev);
  246. clk_disable_unprepare(rngc->clk);
  247. return 0;
  248. }
  249. static int __maybe_unused imx_rngc_resume(struct device *dev)
  250. {
  251. struct imx_rngc *rngc = dev_get_drvdata(dev);
  252. clk_prepare_enable(rngc->clk);
  253. return 0;
  254. }
  255. static SIMPLE_DEV_PM_OPS(imx_rngc_pm_ops, imx_rngc_suspend, imx_rngc_resume);
  256. static const struct of_device_id imx_rngc_dt_ids[] = {
  257. { .compatible = "fsl,imx25-rngb", .data = NULL, },
  258. { /* sentinel */ }
  259. };
  260. MODULE_DEVICE_TABLE(of, imx_rngc_dt_ids);
  261. static struct platform_driver imx_rngc_driver = {
  262. .driver = {
  263. .name = KBUILD_MODNAME,
  264. .pm = &imx_rngc_pm_ops,
  265. .of_match_table = imx_rngc_dt_ids,
  266. },
  267. };
  268. module_platform_driver_probe(imx_rngc_driver, imx_rngc_probe);
  269. MODULE_AUTHOR("Freescale Semiconductor, Inc.");
  270. MODULE_DESCRIPTION("H/W RNGC driver for i.MX");
  271. MODULE_LICENSE("GPL");