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