11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
23de7021fSJerome Forissier /*
33de7021fSJerome Forissier * Copyright (c) 2016, Linaro Limited
43de7021fSJerome Forissier */
53de7021fSJerome Forissier
63de7021fSJerome Forissier /* Driver for the internal Random Number Generator of HiSilicon P660/Hi16xx */
73de7021fSJerome Forissier
83de7021fSJerome Forissier #include <initcall.h>
93de7021fSJerome Forissier #include <io.h>
106c9c7a3fSJerome Forissier #include <kernel/spinlock.h>
113de7021fSJerome Forissier #include <kernel/tee_time.h>
123de7021fSJerome Forissier #include <mm/core_memprot.h>
133de7021fSJerome Forissier #include <mm/core_mmu.h>
143de7021fSJerome Forissier #include <platform_config.h>
153de7021fSJerome Forissier #include <rng_support.h>
163de7021fSJerome Forissier #include <trace.h>
173de7021fSJerome Forissier #include <types_ext.h>
183de7021fSJerome Forissier #include <util.h>
193de7021fSJerome Forissier
203de7021fSJerome Forissier /* ALG sub-controller registers */
213de7021fSJerome Forissier
223de7021fSJerome Forissier #define ALG_SC_RNG_RESET_DREQ 0xAB4 /* RNG reset cancel */
233de7021fSJerome Forissier # define ALG_SC_SRST_DREQ_RNG BIT(0)
243de7021fSJerome Forissier
253de7021fSJerome Forissier /* RNG registers */
263de7021fSJerome Forissier
273de7021fSJerome Forissier #define RNG_SEED 0x0 /* Initial seed */
283de7021fSJerome Forissier #define RNG_CTRL 0x4 /* Control register */
293de7021fSJerome Forissier # define RNG_SEED_SEL BIT(2) /* Re-seed source: 1: ring osc., 0: LFSR */
303de7021fSJerome Forissier # define RNG_RING_EN BIT(1) /* Enable ring oscillator */
313de7021fSJerome Forissier # define RNG_EN BIT(0) /* Enable RNG */
323de7021fSJerome Forissier #define RNG_NUM 0x10 /* Random number output */
333de7021fSJerome Forissier #define RNG_PHY_SEED 0x14 /* Ring oscillator output */
343de7021fSJerome Forissier
35a5e82dc7SJerome Forissier register_phys_mem_pgdir(MEM_AREA_IO_SEC, ALG_SC_BASE, ALG_SC_REG_SIZE);
36a5e82dc7SJerome Forissier register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE);
373de7021fSJerome Forissier
386c9c7a3fSJerome Forissier static unsigned int rng_lock = SPINLOCK_UNLOCK;
393de7021fSJerome Forissier
hi16xx_rng_init(void)403de7021fSJerome Forissier static TEE_Result hi16xx_rng_init(void)
413de7021fSJerome Forissier {
42c2e4eb43SAnton Rybakov vaddr_t alg = (vaddr_t)phys_to_virt(ALG_SC_BASE, MEM_AREA_IO_SEC,
43c2e4eb43SAnton Rybakov ALG_SC_REG_SIZE);
44c2e4eb43SAnton Rybakov vaddr_t rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC,
45c2e4eb43SAnton Rybakov RNG_REG_SIZE);
463de7021fSJerome Forissier TEE_Time time;
473de7021fSJerome Forissier
483de7021fSJerome Forissier /* ALG sub-controller must allow RNG out of reset */
49918bb3a5SEtienne Carriere io_write32(alg + ALG_SC_RNG_RESET_DREQ, ALG_SC_SRST_DREQ_RNG);
503de7021fSJerome Forissier
513de7021fSJerome Forissier /* Set initial seed */
523de7021fSJerome Forissier tee_time_get_sys_time(&time);
53918bb3a5SEtienne Carriere io_write32(rng + RNG_SEED, time.seconds * 1000 + time.millis);
543de7021fSJerome Forissier
553de7021fSJerome Forissier /*
563de7021fSJerome Forissier * Enable RNG and configure it to re-seed automatically from the
573de7021fSJerome Forissier * internal ring oscillator
583de7021fSJerome Forissier */
59918bb3a5SEtienne Carriere io_write32(rng + RNG_CTRL, RNG_EN | RNG_RING_EN | RNG_SEED_SEL);
603de7021fSJerome Forissier
613de7021fSJerome Forissier IMSG("Hi16xx RNG initialized");
623de7021fSJerome Forissier return TEE_SUCCESS;
633de7021fSJerome Forissier }
643de7021fSJerome Forissier
hw_get_random_bytes(void * buf,size_t len)65*830d8c4cSAndrew Davis TEE_Result hw_get_random_bytes(void *buf, size_t len)
663de7021fSJerome Forissier {
673de7021fSJerome Forissier static vaddr_t r;
683de7021fSJerome Forissier static int pos;
693de7021fSJerome Forissier static union {
703de7021fSJerome Forissier uint32_t val;
713de7021fSJerome Forissier uint8_t byte[4];
723de7021fSJerome Forissier } random;
73*830d8c4cSAndrew Davis size_t buffer_pos = 0;
74*830d8c4cSAndrew Davis uint8_t *buffer = buf;
756c9c7a3fSJerome Forissier uint32_t exceptions;
763de7021fSJerome Forissier
776c9c7a3fSJerome Forissier exceptions = cpu_spin_lock_xsave(&rng_lock);
783de7021fSJerome Forissier if (!r)
79c2e4eb43SAnton Rybakov r = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, 1) +
80c2e4eb43SAnton Rybakov RNG_NUM;
81*830d8c4cSAndrew Davis cpu_spin_unlock_xrestore(&rng_lock, exceptions);
823de7021fSJerome Forissier
83*830d8c4cSAndrew Davis while (buffer_pos < len) {
84*830d8c4cSAndrew Davis exceptions = cpu_spin_lock_xsave(&rng_lock);
85*830d8c4cSAndrew Davis
86*830d8c4cSAndrew Davis /* Refill our FIFO */
87*830d8c4cSAndrew Davis if (pos == 0)
88918bb3a5SEtienne Carriere random.val = io_read32(r);
893de7021fSJerome Forissier
90*830d8c4cSAndrew Davis buffer[buffer_pos++] = random.byte[pos++];
913de7021fSJerome Forissier if (pos == 4)
923de7021fSJerome Forissier pos = 0;
933de7021fSJerome Forissier
946c9c7a3fSJerome Forissier cpu_spin_unlock_xrestore(&rng_lock, exceptions);
95*830d8c4cSAndrew Davis }
963de7021fSJerome Forissier
97*830d8c4cSAndrew Davis return TEE_SUCCESS;
983de7021fSJerome Forissier }
993de7021fSJerome Forissier
1003de7021fSJerome Forissier driver_init(hi16xx_rng_init);
101