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