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