blob: 786a710f5fb6f1f76cf86d20e8dd2c9e40a518de [file] [log] [blame]
Michael Walleb258eb22020-06-27 22:58:53 +02001// 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
9#include <asm/cache.h>
Michael Walleb258eb22020-06-27 22:58:53 +020010#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
18#define CAAM_RNG_MAX_FIFO_STORE_SIZE 16
19#define CAAM_RNG_DESC_LEN (3 * CAAM_CMD_SZ + CAAM_PTR_SZ)
20
21struct caam_rng_priv {
22 u32 desc[CAAM_RNG_DESC_LEN / 4];
23 u8 data[CAAM_RNG_MAX_FIFO_STORE_SIZE] __aligned(ARCH_DMA_MINALIGN);
24};
25
26static int caam_rng_read_one(struct caam_rng_priv *priv)
27{
28 int size = ALIGN(CAAM_RNG_MAX_FIFO_STORE_SIZE, ARCH_DMA_MINALIGN);
29 int ret;
30
31 ret = run_descriptor_jr(priv->desc);
32 if (ret < 0)
33 return -EIO;
34
35 invalidate_dcache_range((unsigned long)priv->data,
36 (unsigned long)priv->data + size);
37
38 return 0;
39}
40
41static int caam_rng_read(struct udevice *dev, void *data, size_t len)
42{
43 struct caam_rng_priv *priv = dev_get_priv(dev);
44 u8 *buffer = data;
45 size_t size;
46 int ret;
47
48 while (len) {
49 ret = caam_rng_read_one(priv);
50 if (ret)
51 return ret;
52
53 size = min(len, (size_t)CAAM_RNG_MAX_FIFO_STORE_SIZE);
54
55 memcpy(buffer, priv->data, size);
56 buffer += size;
57 len -= size;
58 }
59
60 return 0;
61}
62
63static int caam_rng_probe(struct udevice *dev)
64{
65 struct caam_rng_priv *priv = dev_get_priv(dev);
66 ulong size = ALIGN(CAAM_RNG_DESC_LEN, ARCH_DMA_MINALIGN);
67
68 inline_cnstr_jobdesc_rng(priv->desc, priv->data,
69 CAAM_RNG_MAX_FIFO_STORE_SIZE);
70 flush_dcache_range((unsigned long)priv->desc,
71 (unsigned long)priv->desc + size);
72
73 return 0;
74}
75
76static const struct dm_rng_ops caam_rng_ops = {
77 .read = caam_rng_read,
78};
79
80U_BOOT_DRIVER(caam_rng) = {
81 .name = "caam-rng",
82 .id = UCLASS_RNG,
83 .ops = &caam_rng_ops,
84 .probe = caam_rng_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -070085 .priv_auto = sizeof(struct caam_rng_priv),
Michael Walleb258eb22020-06-27 22:58:53 +020086 .flags = DM_FLAG_ALLOC_PRIV_DMA,
87};