xref: /optee_os/core/drivers/hi16xx_rng.c (revision 6c9c7a3f3763de86facb5f86b35a63dff8a38f9e)
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>
10*6c9c7a3fSJerome 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 
353de7021fSJerome Forissier register_phys_mem(MEM_AREA_IO_SEC, ALG_SC_BASE, ALG_SC_REG_SIZE);
363de7021fSJerome Forissier register_phys_mem(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE);
373de7021fSJerome Forissier 
38*6c9c7a3fSJerome Forissier static unsigned int rng_lock = SPINLOCK_UNLOCK;
393de7021fSJerome Forissier 
403de7021fSJerome Forissier static TEE_Result hi16xx_rng_init(void)
413de7021fSJerome Forissier {
423de7021fSJerome Forissier 	vaddr_t alg = (vaddr_t)phys_to_virt(ALG_SC_BASE, MEM_AREA_IO_SEC);
433de7021fSJerome Forissier 	vaddr_t rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC);
443de7021fSJerome Forissier 	TEE_Time time;
453de7021fSJerome Forissier 
463de7021fSJerome Forissier 	/* ALG sub-controller must allow RNG out of reset */
473de7021fSJerome Forissier 	write32(ALG_SC_SRST_DREQ_RNG, alg + ALG_SC_RNG_RESET_DREQ);
483de7021fSJerome Forissier 
493de7021fSJerome Forissier 	/* Set initial seed */
503de7021fSJerome Forissier 	tee_time_get_sys_time(&time);
513de7021fSJerome Forissier 	write32(time.seconds * 1000 + time.millis, rng + RNG_SEED);
523de7021fSJerome Forissier 
533de7021fSJerome Forissier 	/*
543de7021fSJerome Forissier 	 * Enable RNG and configure it to re-seed automatically from the
553de7021fSJerome Forissier 	 * internal ring oscillator
563de7021fSJerome Forissier 	 */
573de7021fSJerome Forissier 	write32(RNG_EN | RNG_RING_EN | RNG_SEED_SEL, rng + RNG_CTRL);
583de7021fSJerome Forissier 
593de7021fSJerome Forissier 	IMSG("Hi16xx RNG initialized");
603de7021fSJerome Forissier 	return TEE_SUCCESS;
613de7021fSJerome Forissier }
623de7021fSJerome Forissier 
633de7021fSJerome Forissier uint8_t hw_get_random_byte(void)
643de7021fSJerome Forissier {
653de7021fSJerome Forissier 	static vaddr_t r;
663de7021fSJerome Forissier 	static int pos;
673de7021fSJerome Forissier 	static union {
683de7021fSJerome Forissier 		uint32_t val;
693de7021fSJerome Forissier 		uint8_t byte[4];
703de7021fSJerome Forissier 	} random;
713de7021fSJerome Forissier 	uint8_t ret;
72*6c9c7a3fSJerome Forissier 	uint32_t exceptions;
733de7021fSJerome Forissier 
74*6c9c7a3fSJerome Forissier 	exceptions = cpu_spin_lock_xsave(&rng_lock);
753de7021fSJerome Forissier 
763de7021fSJerome Forissier 	if (!r)
773de7021fSJerome Forissier 		r = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC) + RNG_NUM;
783de7021fSJerome Forissier 
793de7021fSJerome Forissier 	if (!pos)
803de7021fSJerome Forissier 		random.val = read32(r);
813de7021fSJerome Forissier 
823de7021fSJerome Forissier 	ret = random.byte[pos++];
833de7021fSJerome Forissier 
843de7021fSJerome Forissier 	if (pos == 4)
853de7021fSJerome Forissier 		pos = 0;
863de7021fSJerome Forissier 
87*6c9c7a3fSJerome Forissier 	cpu_spin_unlock_xrestore(&rng_lock, exceptions);
883de7021fSJerome Forissier 
893de7021fSJerome Forissier 	return ret;
903de7021fSJerome Forissier }
913de7021fSJerome Forissier 
923de7021fSJerome Forissier driver_init(hi16xx_rng_init);
93