xref: /optee_os/core/drivers/hi16xx_rng.c (revision 3de7021fc55c570e52cbfa5a9c27b56b3b26e910)
1*3de7021fSJerome Forissier /*
2*3de7021fSJerome Forissier  * Copyright (c) 2016, Linaro Limited
3*3de7021fSJerome Forissier  * All rights reserved.
4*3de7021fSJerome Forissier  *
5*3de7021fSJerome Forissier  * Redistribution and use in source and binary forms, with or without
6*3de7021fSJerome Forissier  * modification, are permitted provided that the following conditions are met:
7*3de7021fSJerome Forissier  *
8*3de7021fSJerome Forissier  * 1. Redistributions of source code must retain the above copyright notice,
9*3de7021fSJerome Forissier  * this list of conditions and the following disclaimer.
10*3de7021fSJerome Forissier  *
11*3de7021fSJerome Forissier  * 2. Redistributions in binary form must reproduce the above copyright notice,
12*3de7021fSJerome Forissier  * this list of conditions and the following disclaimer in the documentation
13*3de7021fSJerome Forissier  * and/or other materials provided with the distribution.
14*3de7021fSJerome Forissier  *
15*3de7021fSJerome Forissier  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16*3de7021fSJerome Forissier  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*3de7021fSJerome Forissier  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*3de7021fSJerome Forissier  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19*3de7021fSJerome Forissier  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*3de7021fSJerome Forissier  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*3de7021fSJerome Forissier  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*3de7021fSJerome Forissier  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*3de7021fSJerome Forissier  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*3de7021fSJerome Forissier  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*3de7021fSJerome Forissier  * POSSIBILITY OF SUCH DAMAGE.
26*3de7021fSJerome Forissier  */
27*3de7021fSJerome Forissier 
28*3de7021fSJerome Forissier /* Driver for the internal Random Number Generator of HiSilicon P660/Hi16xx */
29*3de7021fSJerome Forissier 
30*3de7021fSJerome Forissier #include <initcall.h>
31*3de7021fSJerome Forissier #include <io.h>
32*3de7021fSJerome Forissier #include <kernel/mutex.h>
33*3de7021fSJerome Forissier #include <kernel/tee_time.h>
34*3de7021fSJerome Forissier #include <mm/core_memprot.h>
35*3de7021fSJerome Forissier #include <mm/core_mmu.h>
36*3de7021fSJerome Forissier #include <platform_config.h>
37*3de7021fSJerome Forissier #include <rng_support.h>
38*3de7021fSJerome Forissier #include <trace.h>
39*3de7021fSJerome Forissier #include <types_ext.h>
40*3de7021fSJerome Forissier #include <util.h>
41*3de7021fSJerome Forissier 
42*3de7021fSJerome Forissier /* ALG sub-controller registers */
43*3de7021fSJerome Forissier 
44*3de7021fSJerome Forissier #define ALG_SC_RNG_RESET_DREQ	0xAB4	/* RNG reset cancel */
45*3de7021fSJerome Forissier #  define ALG_SC_SRST_DREQ_RNG	BIT(0)
46*3de7021fSJerome Forissier 
47*3de7021fSJerome Forissier /* RNG registers */
48*3de7021fSJerome Forissier 
49*3de7021fSJerome Forissier #define	RNG_SEED	0x0	/* Initial seed */
50*3de7021fSJerome Forissier #define RNG_CTRL	0x4	/* Control register */
51*3de7021fSJerome Forissier #  define RNG_SEED_SEL	BIT(2)	/* Re-seed source: 1: ring osc., 0: LFSR */
52*3de7021fSJerome Forissier #  define RNG_RING_EN	BIT(1)	/* Enable ring oscillator */
53*3de7021fSJerome Forissier #  define RNG_EN	BIT(0)	/* Enable RNG */
54*3de7021fSJerome Forissier #define RNG_NUM		0x10	/* Random number output */
55*3de7021fSJerome Forissier #define RNG_PHY_SEED	0x14	/* Ring oscillator output */
56*3de7021fSJerome Forissier 
57*3de7021fSJerome Forissier register_phys_mem(MEM_AREA_IO_SEC, ALG_SC_BASE, ALG_SC_REG_SIZE);
58*3de7021fSJerome Forissier register_phys_mem(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE);
59*3de7021fSJerome Forissier 
60*3de7021fSJerome Forissier static struct mutex rng_mutex = MUTEX_INITIALIZER;
61*3de7021fSJerome Forissier 
62*3de7021fSJerome Forissier static TEE_Result hi16xx_rng_init(void)
63*3de7021fSJerome Forissier {
64*3de7021fSJerome Forissier 	vaddr_t alg = (vaddr_t)phys_to_virt(ALG_SC_BASE, MEM_AREA_IO_SEC);
65*3de7021fSJerome Forissier 	vaddr_t rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC);
66*3de7021fSJerome Forissier 	TEE_Time time;
67*3de7021fSJerome Forissier 
68*3de7021fSJerome Forissier 	/* ALG sub-controller must allow RNG out of reset */
69*3de7021fSJerome Forissier 	write32(ALG_SC_SRST_DREQ_RNG, alg + ALG_SC_RNG_RESET_DREQ);
70*3de7021fSJerome Forissier 
71*3de7021fSJerome Forissier 	/* Set initial seed */
72*3de7021fSJerome Forissier 	tee_time_get_sys_time(&time);
73*3de7021fSJerome Forissier 	write32(time.seconds * 1000 + time.millis, rng + RNG_SEED);
74*3de7021fSJerome Forissier 
75*3de7021fSJerome Forissier 	/*
76*3de7021fSJerome Forissier 	 * Enable RNG and configure it to re-seed automatically from the
77*3de7021fSJerome Forissier 	 * internal ring oscillator
78*3de7021fSJerome Forissier 	 */
79*3de7021fSJerome Forissier 	write32(RNG_EN | RNG_RING_EN | RNG_SEED_SEL, rng + RNG_CTRL);
80*3de7021fSJerome Forissier 
81*3de7021fSJerome Forissier 	IMSG("Hi16xx RNG initialized");
82*3de7021fSJerome Forissier 	return TEE_SUCCESS;
83*3de7021fSJerome Forissier }
84*3de7021fSJerome Forissier 
85*3de7021fSJerome Forissier uint8_t hw_get_random_byte(void)
86*3de7021fSJerome Forissier {
87*3de7021fSJerome Forissier 	static vaddr_t r;
88*3de7021fSJerome Forissier 	static int pos;
89*3de7021fSJerome Forissier 	static union {
90*3de7021fSJerome Forissier 		uint32_t val;
91*3de7021fSJerome Forissier 		uint8_t byte[4];
92*3de7021fSJerome Forissier 	} random;
93*3de7021fSJerome Forissier 	uint8_t ret;
94*3de7021fSJerome Forissier 
95*3de7021fSJerome Forissier 	mutex_lock(&rng_mutex);
96*3de7021fSJerome Forissier 
97*3de7021fSJerome Forissier 	if (!r)
98*3de7021fSJerome Forissier 		r = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC) + RNG_NUM;
99*3de7021fSJerome Forissier 
100*3de7021fSJerome Forissier 	if (!pos)
101*3de7021fSJerome Forissier 		random.val = read32(r);
102*3de7021fSJerome Forissier 
103*3de7021fSJerome Forissier 	ret = random.byte[pos++];
104*3de7021fSJerome Forissier 
105*3de7021fSJerome Forissier 	if (pos == 4)
106*3de7021fSJerome Forissier 		pos = 0;
107*3de7021fSJerome Forissier 
108*3de7021fSJerome Forissier 	mutex_unlock(&rng_mutex);
109*3de7021fSJerome Forissier 
110*3de7021fSJerome Forissier 	return ret;
111*3de7021fSJerome Forissier }
112*3de7021fSJerome Forissier 
113*3de7021fSJerome Forissier driver_init(hi16xx_rng_init);
114