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