rng.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 2020 Michael Walle <michael@walle.cc>
  4. *
  5. * Driver for Freescale Cryptographic Accelerator and Assurance
  6. * Module (CAAM) hardware random number generator.
  7. */
  8. #include <asm/cache.h>
  9. #include <common.h>
  10. #include <cpu_func.h>
  11. #include <dm.h>
  12. #include <rng.h>
  13. #include <linux/kernel.h>
  14. #include "desc_constr.h"
  15. #include "jobdesc.h"
  16. #include "jr.h"
  17. #define CAAM_RNG_MAX_FIFO_STORE_SIZE 16
  18. #define CAAM_RNG_DESC_LEN (3 * CAAM_CMD_SZ + CAAM_PTR_SZ)
  19. struct caam_rng_priv {
  20. u32 desc[CAAM_RNG_DESC_LEN / 4];
  21. u8 data[CAAM_RNG_MAX_FIFO_STORE_SIZE] __aligned(ARCH_DMA_MINALIGN);
  22. };
  23. static int caam_rng_read_one(struct caam_rng_priv *priv)
  24. {
  25. int size = ALIGN(CAAM_RNG_MAX_FIFO_STORE_SIZE, ARCH_DMA_MINALIGN);
  26. int ret;
  27. ret = run_descriptor_jr(priv->desc);
  28. if (ret < 0)
  29. return -EIO;
  30. invalidate_dcache_range((unsigned long)priv->data,
  31. (unsigned long)priv->data + size);
  32. return 0;
  33. }
  34. static int caam_rng_read(struct udevice *dev, void *data, size_t len)
  35. {
  36. struct caam_rng_priv *priv = dev_get_priv(dev);
  37. u8 *buffer = data;
  38. size_t size;
  39. int ret;
  40. while (len) {
  41. ret = caam_rng_read_one(priv);
  42. if (ret)
  43. return ret;
  44. size = min(len, (size_t)CAAM_RNG_MAX_FIFO_STORE_SIZE);
  45. memcpy(buffer, priv->data, size);
  46. buffer += size;
  47. len -= size;
  48. }
  49. return 0;
  50. }
  51. static int caam_rng_probe(struct udevice *dev)
  52. {
  53. struct caam_rng_priv *priv = dev_get_priv(dev);
  54. ulong size = ALIGN(CAAM_RNG_DESC_LEN, ARCH_DMA_MINALIGN);
  55. inline_cnstr_jobdesc_rng(priv->desc, priv->data,
  56. CAAM_RNG_MAX_FIFO_STORE_SIZE);
  57. flush_dcache_range((unsigned long)priv->desc,
  58. (unsigned long)priv->desc + size);
  59. return 0;
  60. }
  61. static const struct dm_rng_ops caam_rng_ops = {
  62. .read = caam_rng_read,
  63. };
  64. U_BOOT_DRIVER(caam_rng) = {
  65. .name = "caam-rng",
  66. .id = UCLASS_RNG,
  67. .ops = &caam_rng_ops,
  68. .probe = caam_rng_probe,
  69. .priv_auto_alloc_size = sizeof(struct caam_rng_priv),
  70. .flags = DM_FLAG_ALLOC_PRIV_DMA,
  71. };