1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Texas Instruments K3 SA2UL RNG Driver
4  *
5  * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
6  *	Andrew Davis <afd@ti.com>
7  */
8 
9 #include <initcall.h>
10 #include <io.h>
11 #include <keep.h>
12 #include <kernel/interrupt.h>
13 #include <kernel/misc.h>
14 #include <kernel/spinlock.h>
15 #include <mm/core_memprot.h>
16 #include <mm/core_mmu.h>
17 #include <platform_config.h>
18 #include <rng_support.h>
19 
20 #include "sa2ul.h"
21 
22 #define	RNG_OUTPUT_0            0x00
23 #define	RNG_OUTPUT_1            0x04
24 #define	RNG_OUTPUT_2            0x08
25 #define	RNG_OUTPUT_3            0x0C
26 #define	RNG_STATUS              0x10
27 #define RNG_READY               BIT(0)
28 #define SHUTDOWN_OFLO           BIT(1)
29 #define	RNG_INTACK              0x10
30 #define	RNG_CONTROL             0x14
31 #define ENABLE_TRNG             BIT(10)
32 #define	RNG_CONFIG              0x18
33 #define	RNG_ALARMCNT            0x1C
34 #define	RNG_FROENABLE           0x20
35 #define	RNG_FRODETUNE           0x24
36 #define	RNG_ALARMMASK           0x28
37 #define	RNG_ALARMSTOP           0x2C
38 #define	RNG_OPTIONS             0x78
39 #define	RNG_EIP_REV             0x7C
40 
41 #define RNG_CONTROL_STARTUP_CYCLES_SHIFT        16
42 #define RNG_CONTROL_STARTUP_CYCLES_MASK         GENMASK_32(31, 16)
43 
44 #define RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT       16
45 #define RNG_CONFIG_MAX_REFIL_CYCLES_MASK        GENMASK_32(31, 16)
46 #define RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT       0
47 #define RNG_CONFIG_MIN_REFIL_CYCLES_MASK        GENMASK_32(7, 0)
48 
49 #define RNG_ALARMCNT_ALARM_TH_SHIFT             0
50 #define RNG_ALARMCNT_ALARM_TH_MASK              GENMASK_32(7, 0)
51 #define RNG_ALARMCNT_SHUTDOWN_TH_SHIFT          16
52 #define RNG_ALARMCNT_SHUTDOWN_TH_MASK           GENMASK_32(20, 16)
53 
54 #define RNG_CONTROL_STARTUP_CYCLES              0xff
55 #define RNG_CONFIG_MIN_REFIL_CYCLES             0x5
56 #define RNG_CONFIG_MAX_REFIL_CYCLES             0x22
57 #define RNG_ALARM_THRESHOLD                     0xff
58 #define RNG_SHUTDOWN_THRESHOLD                  0x4
59 
60 #define RNG_FRO_MASK    GENMASK_32(23, 0)
61 
62 register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE);
63 
64 static unsigned int rng_lock = SPINLOCK_UNLOCK;
65 static vaddr_t rng;
66 
sa2ul_rng_read128(uint32_t * word0,uint32_t * word1,uint32_t * word2,uint32_t * word3)67 static void sa2ul_rng_read128(uint32_t *word0, uint32_t *word1,
68 			      uint32_t *word2, uint32_t *word3)
69 {
70 	/* Is the result ready (available)? */
71 	while (!(io_read32(rng + RNG_STATUS) & RNG_READY)) {
72 		/* Is the shutdown threshold reached? */
73 		if (io_read32(rng + RNG_STATUS) & SHUTDOWN_OFLO) {
74 			uint32_t alarm = io_read32(rng + RNG_ALARMSTOP);
75 			uint32_t tune = io_read32(rng + RNG_FRODETUNE);
76 
77 			/* Clear the alarm events */
78 			io_write32(rng + RNG_ALARMMASK, 0x0);
79 			io_write32(rng + RNG_ALARMSTOP, 0x0);
80 			/* De-tune offending FROs */
81 			io_write32(rng + RNG_FRODETUNE, tune ^ alarm);
82 			/* Re-enable the shut down FROs */
83 			io_write32(rng + RNG_FROENABLE, RNG_FRO_MASK);
84 			/* Clear the shutdown overflow event */
85 			io_write32(rng + RNG_INTACK, SHUTDOWN_OFLO);
86 
87 			DMSG("Fixed FRO shutdown");
88 		}
89 	}
90 	/* Read random value */
91 	*word0 = io_read32(rng + RNG_OUTPUT_0);
92 	*word1 = io_read32(rng + RNG_OUTPUT_1);
93 	*word2 = io_read32(rng + RNG_OUTPUT_2);
94 	*word3 = io_read32(rng + RNG_OUTPUT_3);
95 	/* Acknowledge read complete */
96 	io_write32(rng + RNG_INTACK, RNG_READY);
97 }
98 
hw_get_random_bytes(void * buf,size_t len)99 TEE_Result hw_get_random_bytes(void *buf, size_t len)
100 {
101 	static union {
102 		uint32_t val[4];
103 		uint8_t byte[16];
104 	} fifo;
105 	static size_t fifo_pos;
106 	uint8_t *buffer = buf;
107 	size_t buffer_pos = 0;
108 
109 	while (buffer_pos < len) {
110 		uint32_t exceptions = cpu_spin_lock_xsave(&rng_lock);
111 
112 		/* Refill our FIFO */
113 		if (fifo_pos == 0)
114 			sa2ul_rng_read128(&fifo.val[0], &fifo.val[1],
115 					  &fifo.val[2], &fifo.val[3]);
116 
117 		buffer[buffer_pos++] = fifo.byte[fifo_pos++];
118 		fifo_pos %= 16;
119 
120 		cpu_spin_unlock_xrestore(&rng_lock, exceptions);
121 	}
122 
123 	return TEE_SUCCESS;
124 }
125 
sa2ul_rng_init(void)126 TEE_Result sa2ul_rng_init(void)
127 {
128 	uint32_t val = 0;
129 
130 	rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_REG_SIZE);
131 
132 	/* Ensure initial latency */
133 	val |= RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT;
134 	val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT;
135 	io_write32(rng + RNG_CONFIG, val);
136 
137 	/* Configure the desired FROs */
138 	io_write32(rng + RNG_FRODETUNE, 0x0);
139 
140 	/* Enable all FROs */
141 	io_write32(rng + RNG_FROENABLE, 0xffffff);
142 
143 	io_write32(rng + RNG_CONTROL, ENABLE_TRNG);
144 
145 	IMSG("SA2UL TRNG initialized");
146 
147 	return TEE_SUCCESS;
148 }
149