blob: b6bf0052a95b69bf69b0cfbeac8cb4ad5c037a46 [file] [log] [blame]
Antonio Nino Diaz12f73ff2018-07-13 09:27:16 +01001/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
Antonio Nino Diaz12f73ff2018-07-13 09:27:16 +01008#include <string.h>
9
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010#include <lib/mmio.h>
11
Andre Przywarabb6ef152019-07-09 11:44:14 +010012#include <rpi_hw.h>
Antonio Nino Diaz12f73ff2018-07-13 09:27:16 +010013
14/* Initial amount of values to discard */
15#define RNG_WARMUP_COUNT U(0x40000)
16
17static void rpi3_rng_initialize(void)
18{
19 uint32_t int_mask, ctrl;
20
21 /* Return if it is already enabled */
22 ctrl = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET);
23 if ((ctrl & RPI3_RNG_CTRL_ENABLE) != 0U) {
24 return;
25 }
26
27 /* Mask interrupts */
28 int_mask = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET);
29 int_mask |= RPI3_RNG_INT_MASK_DISABLE;
30 mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET, int_mask);
31
32 /* Discard several values when initializing to give it time to warmup */
33 mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET, RNG_WARMUP_COUNT);
34
35 mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET,
36 RPI3_RNG_CTRL_ENABLE);
37}
38
39static uint32_t rpi3_rng_get_word(void)
40{
41 size_t nwords;
42
43 do {
44 /* Get number of available words to read */
45 nwords = (mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET)
46 >> RPI3_RNG_STATUS_NUM_WORDS_SHIFT)
47 & RPI3_RNG_STATUS_NUM_WORDS_MASK;
48 } while (nwords == 0U);
49
50 return mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_DATA_OFFSET);
51}
52
53void rpi3_rng_read(void *buf, size_t len)
54{
55 uint32_t data;
56 size_t left = len;
57 uint32_t *dst = buf;
58
59 assert(buf != NULL);
60 assert(len != 0U);
61 assert(check_uptr_overflow((uintptr_t) buf, (uintptr_t) len) == 0);
62
63 rpi3_rng_initialize();
64
65 while (left >= sizeof(uint32_t)) {
66 data = rpi3_rng_get_word();
67 *dst++ = data;
68 left -= sizeof(uint32_t);
69 }
70
71 if (left > 0U) {
72 data = rpi3_rng_get_word();
73 memcpy(dst, &data, left);
74 }
75}