1 /*
2  * Copyright (c) 2020, Marvell Technology Group Ltd. All rights reserved.
3  *
4  * Based on Linux kernel omap-rng.c - RNG driver for TI OMAP CPU family
5  *
6  * Author: Deepak Saxena <dsaxena@plexity.net>
7  *
8  * Copyright 2005 (c) MontaVista Software, Inc.
9  *
10  * Mostly based on original driver:
11  *
12  * Copyright (C) 2005 Nokia Corporation
13  * Author: Juha Yrjölä <juha.yrjola@nokia.com>
14  *
15  * SPDX-License-Identifier: BSD-3-Clause
16  */
17 
18 #include <assert.h>
19 #include <errno.h>
20 #include <string.h>
21 
22 #include <common/debug.h>
23 #include <drivers/delay_timer.h>
24 #include <drivers/rambus/trng_ip_76.h>
25 #include <lib/mmio.h>
26 #include <lib/spinlock.h>
27 #include <lib/utils.h>
28 
29 #define RNG_REG_STATUS_RDY			(1 << 0)
30 
31 #define RNG_REG_INTACK_RDY_MASK			(1 << 0)
32 
33 #define RNG_CONTROL_ENABLE_TRNG_MASK		(1 << 10)
34 
35 #define RNG_CONFIG_NOISE_BLOCKS(val)		((0xff & (val)) << 0)
36 #define RNG_CONFIG_NOISE_BLK_VAL		0x5
37 
38 #define RNG_CONFIG_SAMPLE_CYCLES(val)		((0xff & (val)) << 16)
39 #define RNG_CONFIG_SAMPLE_CYCLES_VAL		0x22
40 
41 #define RNG_REG_FRO_ENABLE_MASK			0xffffff
42 #define RNG_REG_FRO_DETUNE_MASK			0x0
43 
44 #define EIP76_RNG_OUTPUT_SIZE			0x10
45 #define EIP76_RNG_WAIT_ROUNDS			10
46 
47 #define RNG_HW_IS_EIP76(ver)			((ver) & (0xff == 0x4C))
48 #define RNG_HW_VER_MAJOR(ver)			(((ver) & (0xf << 24)) >> 24)
49 #define RNG_HW_VER_MINOR(ver)			(((ver) & (0xf << 20)) >> 20)
50 #define RNG_HW_VER_PATCH(ver)			(((ver) & (0xf << 16)) >> 16)
51 
52 
53 enum {
54 	RNG_OUTPUT_0_REG = 0,
55 	RNG_OUTPUT_1_REG,
56 	RNG_OUTPUT_2_REG,
57 	RNG_OUTPUT_3_REG,
58 	RNG_STATUS_REG,
59 	RNG_INTMASK_REG,
60 	RNG_INTACK_REG,
61 	RNG_CONTROL_REG,
62 	RNG_CONFIG_REG,
63 	RNG_ALARMCNT_REG,
64 	RNG_FROENABLE_REG,
65 	RNG_FRODETUNE_REG,
66 	RNG_ALARMMASK_REG,
67 	RNG_ALARMSTOP_REG,
68 	RNG_REV_REG
69 };
70 
71 static uint16_t reg_map_eip76[] = {
72 	[RNG_OUTPUT_0_REG]	= 0x0,
73 	[RNG_OUTPUT_1_REG]	= 0x4,
74 	[RNG_OUTPUT_2_REG]	= 0x8,
75 	[RNG_OUTPUT_3_REG]	= 0xc,
76 	[RNG_STATUS_REG]	= 0x10,
77 	[RNG_INTACK_REG]	= 0x10,
78 	[RNG_CONTROL_REG]	= 0x14,
79 	[RNG_CONFIG_REG]	= 0x18,
80 	[RNG_ALARMCNT_REG]	= 0x1c,
81 	[RNG_FROENABLE_REG]	= 0x20,
82 	[RNG_FRODETUNE_REG]	= 0x24,
83 	[RNG_ALARMMASK_REG]	= 0x28,
84 	[RNG_ALARMSTOP_REG]	= 0x2c,
85 	[RNG_REV_REG]		= 0x7c,
86 };
87 
88 struct eip76_rng_dev {
89 	uintptr_t	base;
90 	uint16_t	*regs;
91 };
92 
93 /* Locals */
94 static struct eip76_rng_dev eip76_dev;
95 static spinlock_t rng_lock;
96 
eip76_rng_read(struct eip76_rng_dev * dev,uint16_t reg)97 static inline uint32_t eip76_rng_read(struct eip76_rng_dev *dev, uint16_t reg)
98 {
99 	return mmio_read_32(dev->base + dev->regs[reg]);
100 }
101 
eip76_rng_write(struct eip76_rng_dev * dev,uint16_t reg,uint32_t val)102 static inline void eip76_rng_write(struct eip76_rng_dev *dev,
103 				   uint16_t reg, uint32_t val)
104 {
105 	mmio_write_32(dev->base + dev->regs[reg], val);
106 }
107 
eip76_rng_init(struct eip76_rng_dev * dev)108 static void eip76_rng_init(struct eip76_rng_dev *dev)
109 {
110 	uint32_t val;
111 
112 	/* Return if RNG is already running. */
113 	if (eip76_rng_read(dev, RNG_CONTROL_REG) &
114 			   RNG_CONTROL_ENABLE_TRNG_MASK) {
115 		return;
116 	}
117 
118 	/*  This field sets the number of 512-bit blocks of raw Noise Source
119 	 * output data that must be processed by either the Conditioning
120 	 * Function or the SP 800-90 DRBG ‘BC_DF’ functionality to yield
121 	 * a ‘full entropy’ output value. As according to [SP 800-90B draft]
122 	 * the amount of entropy input to this functionality must be twice
123 	 * the amount that is output and the 8-bit samples output by the Noise
124 	 * Source are supposed to have one bit of entropy each, the settings
125 	 * for this field are as follows:
126 	 * - SHA-1 Conditioning Function:
127 	 *  generates 160 bits output, requiring 2560 sample bits,
128 	 *  equivalent to 5 blocks of raw Noise Source input.
129 	 * - SHA-256 Conditioning Function:
130 	 *  generates 256 bits output, requiring 4096 sample bits, equivalent
131 	 *  to 8 blocks of raw Noise Source input. Note that two blocks of 256
132 	 *  bits are needed to start or re-seed the SP 800-90 DRBG
133 	 *  (in the EIP-76d-*-SHA2 configurations)
134 	 * - SP 800-90 DRBG ‘BC_DF’ functionality:
135 	 *  generates 384 bits output, requiring 6144 sample bits, equivalent
136 	 *  to 12 blocks of raw Noise Source input.
137 	 *  This field can only be modified when ‘enable_trng’ in TRNG_CONTROL
138 	 *  is ‘0’ or when either of the ‘test_known_noise’ or ‘test_cond_func’
139 	 *  bits in TRNG_TEST is ‘1’. Value 0 in this field selects 256 blocks
140 	 *  of 512 bits to be processed.
141 	 */
142 	val = RNG_CONFIG_NOISE_BLOCKS(RNG_CONFIG_NOISE_BLK_VAL);
143 
144 	/* This field sets the number of FRO samples that are XOR-ed together
145 	 * into one bit to be shifted into the main shift register.
146 	 * This value must be such that there is at least one bit of entropy
147 	 * (in total) in each 8 bits that are shifted.
148 	 * This field can only be modified when ‘enable_trng’ in TRNG_CONTROL
149 	 * is ‘0’ or when either of the ‘test_known_noise’ or ‘test_cond_func’
150 	 * bits in TRNG_TEST is ‘1’. Value 0 in this field selects 65536 FRO
151 	 * samples to be XOR-ed together
152 	 */
153 	val |= RNG_CONFIG_SAMPLE_CYCLES(RNG_CONFIG_SAMPLE_CYCLES_VAL);
154 	eip76_rng_write(dev, RNG_CONFIG_REG, val);
155 
156 	/* Enable all available FROs */
157 	eip76_rng_write(dev, RNG_FRODETUNE_REG, RNG_REG_FRO_DETUNE_MASK);
158 	eip76_rng_write(dev, RNG_FROENABLE_REG, RNG_REG_FRO_ENABLE_MASK);
159 
160 	/* Enable TRNG */
161 	eip76_rng_write(dev, RNG_CONTROL_REG, RNG_CONTROL_ENABLE_TRNG_MASK);
162 }
163 
eip76_rng_read_rand_buf(void * data,bool wait)164 int32_t eip76_rng_read_rand_buf(void *data, bool wait)
165 {
166 	uint32_t i, present;
167 
168 	if (!eip76_dev.base) /* not initialized */
169 		return -1;
170 
171 	for (i = 0; i < EIP76_RNG_WAIT_ROUNDS; i++) {
172 		present = eip76_rng_read(&eip76_dev, RNG_STATUS_REG) &
173 					 RNG_REG_STATUS_RDY;
174 		if (present || !wait) {
175 			break;
176 		}
177 
178 		udelay(10);
179 	}
180 
181 	if (present != 0U) {
182 		return 0;
183 	}
184 
185 	memcpy(data,
186 	       (void *)(eip76_dev.base + eip76_dev.regs[RNG_OUTPUT_0_REG]),
187 	       EIP76_RNG_OUTPUT_SIZE);
188 
189 	eip76_rng_write(&eip76_dev, RNG_INTACK_REG, RNG_REG_INTACK_RDY_MASK);
190 
191 	return EIP76_RNG_OUTPUT_SIZE;
192 }
193 
eip76_rng_probe(uintptr_t base_addr)194 int32_t eip76_rng_probe(uintptr_t base_addr)
195 {
196 	uint32_t ver;
197 
198 	eip76_dev.base = base_addr;
199 	eip76_dev.regs = reg_map_eip76;
200 
201 	eip76_rng_init(&eip76_dev);
202 
203 	ver = eip76_rng_read(&eip76_dev, RNG_REV_REG);
204 
205 	INFO("%s Random Number Generator HW ver. %01x.%01x.%01x\n",
206 	     RNG_HW_IS_EIP76(ver) ? "TRNG-IP-76" : "Unknown",
207 	     RNG_HW_VER_MAJOR(ver), RNG_HW_VER_MINOR(ver),
208 	     RNG_HW_VER_PATCH(ver));
209 
210 	return 0;
211 }
212 
eip76_rng_get_random(uint8_t * data,uint32_t len)213 int32_t eip76_rng_get_random(uint8_t *data, uint32_t len)
214 {
215 	static uint8_t rand[EIP76_RNG_OUTPUT_SIZE];
216 	static uint8_t pos;
217 	uint32_t i;
218 	int32_t ret = 0;
219 
220 	if (!data)
221 		return -1;
222 
223 	spin_lock(&rng_lock);
224 
225 	for (i = 0; i < len; i++) {
226 		if (pos >= EIP76_RNG_OUTPUT_SIZE) {
227 			pos = 0;
228 		}
229 
230 		if (pos != 0U) {
231 			ret = eip76_rng_read_rand_buf(rand, true);
232 		}
233 
234 		/* Only advance FIFO index if it is non zero or
235 		 * the update from TRNG HW was successful
236 		 */
237 		if (pos || ret > 0) {
238 			data[i] = rand[pos++];
239 			ret = 0;
240 		} else {
241 			ret = -1;
242 			break;
243 		}
244 	}
245 
246 	spin_unlock(&rng_lock);
247 
248 	return ret;
249 }
250