1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * (c) 2021 Jorge Ramirez <jorge@foundries.io>, Foundries Ltd. 4 */ 5 6 #include <arm.h> 7 #include <crypto/crypto.h> 8 #include <initcall.h> 9 #include <io.h> 10 #include <kernel/boot.h> 11 #include <kernel/delay.h> 12 #include <kernel/dt.h> 13 #include <kernel/panic.h> 14 #include <libfdt.h> 15 #include <mm/core_memprot.h> 16 #include <mm/core_mmu.h> 17 #include <platform_config.h> 18 #include <rng_support.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <tee/tee_cryp_utl.h> 22 #include <trace.h> 23 #include <util.h> 24 25 #define RNG_VER 0x00 26 #define RNG_CMD 0x04 27 #define RNG_CR 0x08 28 #define RNG_SR 0x0C 29 #define RNG_ESR 0x10 30 #define RNG_OUT 0x14 31 32 #define RNG_CMD_CLR_INT BIT(4) 33 #define RNG_CMD_CLR_ERR BIT(5) 34 35 #define RNG_CR_AR BIT(4) 36 #define RNG_CR_MASK_DONE BIT(5) 37 #define RNG_CR_MASK_ERROR BIT(6) 38 39 #define RNG_SR_ST_DONE BIT(4) 40 #define RNG_SR_SEED_DONE BIT(5) 41 #define RNG_SR_ERROR BIT(16) 42 #define RNG_SR_FIFO_LEVEL_SHIFT 8 43 #define RNG_SR_FIFO_LEVEL_MASK GENMASK_32(11, RNG_SR_FIFO_LEVEL_SHIFT) 44 45 #define RNG_VER_TYPE_SHIFT 28 46 #define RNG_VER_TYPE_MASK GENMASK_32(31, RNG_VER_TYPE_SHIFT) 47 48 #define RNG_ESR_STATUS_STAT_ERR BIT(3) 49 50 #define RNG_TYPE_RNGA 0 51 #define RNG_TYPE_RNGB 1 52 #define RNG_TYPE_RNGC 2 53 54 #define SEED_TIMEOUT 2000000 55 #define IRQ_TIMEOUT 1000000 56 57 #define WORDS_IN_FIFO(__rng_sr) \ 58 (((__rng_sr) & RNG_SR_FIFO_LEVEL_MASK) >> RNG_SR_FIFO_LEVEL_SHIFT) 59 60 #define RNG_TYPE(__rng_vr) \ 61 (((__rng_vr) & RNG_VER_TYPE_MASK) >> RNG_VER_TYPE_SHIFT) 62 63 static struct imx_rng { 64 struct io_pa_va base; 65 size_t size; 66 bool ready; 67 uint32_t error; 68 } rngb = { 69 .base.pa = RNGB_BASE, 70 .size = 0x4000, 71 }; 72 73 static void wait_for_irq(struct imx_rng *rng) 74 { 75 uint64_t tref = timeout_init_us(IRQ_TIMEOUT); 76 uint32_t status = 0; 77 78 do { 79 rng->error = io_read32(rng->base.va + RNG_ESR); 80 status = io_read32(rng->base.va + RNG_SR); 81 82 if (timeout_elapsed(tref)) 83 panic(); 84 85 } while ((status & (RNG_SR_SEED_DONE | RNG_SR_ST_DONE)) == 0); 86 } 87 88 static void irq_clear(struct imx_rng *rng) 89 { 90 io_setbits32(rng->base.va + RNG_CR, 91 RNG_CR_MASK_DONE | RNG_CR_MASK_ERROR); 92 io_setbits32(rng->base.va + RNG_CMD, 93 RNG_CMD_CLR_INT | RNG_CMD_CLR_ERR); 94 } 95 96 static void irq_unmask(struct imx_rng *rng) 97 { 98 io_clrbits32(rng->base.va + RNG_CR, 99 RNG_CR_MASK_DONE | RNG_CR_MASK_ERROR); 100 } 101 102 static void rng_seed(struct imx_rng *rng) 103 { 104 uint64_t tref = timeout_init_us(SEED_TIMEOUT); 105 106 irq_clear(rng); 107 do { 108 irq_unmask(rng); 109 /* configure continuous auto-reseed */ 110 io_setbits32(rng->base.va + RNG_CR, RNG_CR_AR); 111 wait_for_irq(rng); 112 irq_clear(rng); 113 114 if (timeout_elapsed(tref)) 115 panic(); 116 } while (rng->error); 117 } 118 119 static TEE_Result map_controller_static(void) 120 { 121 rngb.base.va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, 122 rngb.base.pa, rngb.size); 123 if (!rngb.base.va) 124 return TEE_ERROR_GENERIC; 125 126 return TEE_SUCCESS; 127 } 128 129 #if !defined(CFG_DT) 130 static TEE_Result map_controller(void) 131 { 132 return map_controller_static(); 133 } 134 #else 135 static const char *const rng_match_table[] = { 136 "fsl,imx25-rngb", 137 }; 138 139 static TEE_Result map_controller(void) 140 { 141 void *fdt = get_dt(); 142 unsigned int i = 0; 143 int off = -1; 144 145 if (!fdt) 146 return map_controller_static(); 147 148 for (i = 0; i < ARRAY_SIZE(rng_match_table); i++) { 149 off = fdt_node_offset_by_compatible(fdt, 0, rng_match_table[i]); 150 if (off >= 0) 151 break; 152 } 153 154 if (off < 0) 155 return map_controller_static(); 156 157 if (dt_enable_secure_status(fdt, off)) 158 return TEE_ERROR_NOT_SUPPORTED; 159 160 if (dt_map_dev(fdt, off, &rngb.base.va, &rngb.size, DT_MAP_AUTO) < 0) 161 return TEE_ERROR_NOT_SUPPORTED; 162 163 rngb.base.pa = virt_to_phys((void *)rngb.base.va); 164 165 return TEE_SUCCESS; 166 } 167 #endif 168 169 TEE_Result hw_get_random_bytes(void *buf, size_t len) 170 { 171 uint32_t *rngbuf = buf; 172 uint32_t status = 0; 173 uint32_t val = 0; 174 175 if (!rngb.ready) 176 return TEE_ERROR_BAD_STATE; 177 178 while (len) { 179 status = io_read32(rngb.base.va + RNG_SR); 180 if (status & RNG_SR_ERROR) 181 return TEE_ERROR_BAD_STATE; 182 183 if (WORDS_IN_FIFO(status)) { 184 val = io_read32(rngb.base.va + RNG_OUT); 185 if (len > sizeof(uint32_t)) { 186 len = len - sizeof(uint32_t); 187 memcpy(rngbuf, &val, sizeof(uint32_t)); 188 rngbuf++; 189 } else { 190 memcpy(rngbuf, &val, len); 191 len = 0; 192 } 193 } 194 } 195 196 return TEE_SUCCESS; 197 } 198 199 void plat_rng_init(void) 200 { 201 } 202 203 static TEE_Result rngb_init(void) 204 { 205 uint32_t type = 0; 206 207 if (map_controller()) 208 panic(); 209 210 type = RNG_TYPE(io_read32(rngb.base.va + RNG_VER)); 211 if (type != RNG_TYPE_RNGB && type != RNG_TYPE_RNGC) 212 panic(); 213 214 rng_seed(&rngb); 215 rngb.ready = true; 216 217 return TEE_SUCCESS; 218 } 219 220 driver_init(rngb_init); 221