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_SEED BIT(1) 33 #define RNG_CMD_CLR_INT BIT(4) 34 #define RNG_CMD_CLR_ERR BIT(5) 35 #define RNG_CMD_SOFT_RESET BIT(6) 36 37 #define RNG_CR_AR BIT(4) 38 #define RNG_CR_MASK_DONE BIT(5) 39 #define RNG_CR_MASK_ERROR BIT(6) 40 41 #define RNG_SR_ST_DONE BIT(4) 42 #define RNG_SR_SEED_DONE BIT(5) 43 #define RNG_SR_ERROR BIT(16) 44 #define RNG_SR_FIFO_LEVEL_SHIFT 8 45 #define RNG_SR_FIFO_LEVEL_MASK GENMASK_32(11, RNG_SR_FIFO_LEVEL_SHIFT) 46 47 #define RNG_VER_TYPE_SHIFT 28 48 #define RNG_VER_TYPE_MASK GENMASK_32(31, RNG_VER_TYPE_SHIFT) 49 50 #define RNG_ESR_STATUS_STAT_ERR BIT(3) 51 52 #define RNG_TYPE_RNGA 0 53 #define RNG_TYPE_RNGB 1 54 #define RNG_TYPE_RNGC 2 55 56 #define SEED_TIMEOUT 2000000 57 #define IRQ_TIMEOUT 1000000 58 59 #define WORDS_IN_FIFO(__rng_sr) \ 60 (((__rng_sr) & RNG_SR_FIFO_LEVEL_MASK) >> RNG_SR_FIFO_LEVEL_SHIFT) 61 62 #define RNG_TYPE(__rng_vr) \ 63 (((__rng_vr) & RNG_VER_TYPE_MASK) >> RNG_VER_TYPE_SHIFT) 64 65 static struct imx_rng { 66 struct io_pa_va base; 67 size_t size; 68 bool ready; 69 uint32_t error; 70 } rngb = { 71 .base.pa = RNGB_BASE, 72 .size = 0x4000, 73 }; 74 75 static void wait_for_irq(struct imx_rng *rng) 76 { 77 uint64_t tref = timeout_init_us(IRQ_TIMEOUT); 78 uint32_t status = 0; 79 80 do { 81 rng->error = io_read32(rng->base.va + RNG_ESR); 82 status = io_read32(rng->base.va + RNG_SR); 83 84 if (timeout_elapsed(tref)) 85 panic(); 86 87 } while ((status & (RNG_SR_SEED_DONE | RNG_SR_ST_DONE)) == 0); 88 } 89 90 static void soft_reset(struct imx_rng *rng) 91 { 92 io_setbits32(rng->base.va + RNG_CMD, RNG_CMD_SOFT_RESET); 93 } 94 95 static void irq_clear(struct imx_rng *rng) 96 { 97 io_setbits32(rng->base.va + RNG_CMD, 98 RNG_CMD_CLR_ERR | RNG_CMD_CLR_INT); 99 } 100 101 static void irq_mask(struct imx_rng *rng) 102 { 103 io_setbits32(rng->base.va + RNG_CR, 104 RNG_CR_MASK_DONE | RNG_CR_MASK_ERROR); 105 } 106 107 static void irq_unmask(struct imx_rng *rng) 108 { 109 io_clrbits32(rng->base.va + RNG_CR, 110 RNG_CR_MASK_DONE | RNG_CR_MASK_ERROR); 111 } 112 113 static void rng_seed(struct imx_rng *rng) 114 { 115 uint64_t tref = timeout_init_us(SEED_TIMEOUT); 116 117 irq_clear(rng); 118 irq_mask(rng); 119 do { 120 irq_unmask(rng); 121 /* seed creation */ 122 io_setbits32(rng->base.va + RNG_CMD, RNG_CMD_SEED); 123 wait_for_irq(rng); 124 if (rng->error) 125 soft_reset(rng); 126 else 127 irq_clear(rng); 128 irq_mask(rng); 129 130 if (timeout_elapsed(tref)) 131 panic(); 132 } while (rng->error); 133 134 /* configure continuous auto-reseed */ 135 io_setbits32(rng->base.va + RNG_CR, RNG_CR_AR); 136 } 137 138 static TEE_Result map_controller_static(void) 139 { 140 rngb.base.va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, 141 rngb.base.pa, rngb.size); 142 if (!rngb.base.va) 143 return TEE_ERROR_GENERIC; 144 145 return TEE_SUCCESS; 146 } 147 148 #if !defined(CFG_DT) 149 static TEE_Result map_controller(void) 150 { 151 return map_controller_static(); 152 } 153 #else 154 static const char *const rng_match_table[] = { 155 "fsl,imx25-rngb", 156 }; 157 158 static TEE_Result map_controller(void) 159 { 160 void *fdt = get_dt(); 161 unsigned int i = 0; 162 int off = -1; 163 164 if (!fdt) 165 return map_controller_static(); 166 167 for (i = 0; i < ARRAY_SIZE(rng_match_table); i++) { 168 off = fdt_node_offset_by_compatible(fdt, 0, rng_match_table[i]); 169 if (off >= 0) 170 break; 171 } 172 173 if (off < 0) 174 return map_controller_static(); 175 176 if (dt_enable_secure_status(fdt, off)) 177 return TEE_ERROR_NOT_SUPPORTED; 178 179 if (dt_map_dev(fdt, off, &rngb.base.va, &rngb.size, DT_MAP_AUTO) < 0) 180 return TEE_ERROR_NOT_SUPPORTED; 181 182 rngb.base.pa = virt_to_phys((void *)rngb.base.va); 183 184 return TEE_SUCCESS; 185 } 186 #endif 187 188 TEE_Result hw_get_random_bytes(void *buf, size_t len) 189 { 190 uint32_t *rngbuf = buf; 191 uint32_t status = 0; 192 uint32_t val = 0; 193 194 if (!rngb.ready) 195 return TEE_ERROR_BAD_STATE; 196 197 while (len) { 198 status = io_read32(rngb.base.va + RNG_SR); 199 if (status & RNG_SR_ERROR) 200 return TEE_ERROR_BAD_STATE; 201 202 if (WORDS_IN_FIFO(status)) { 203 val = io_read32(rngb.base.va + RNG_OUT); 204 if (len > sizeof(uint32_t)) { 205 len = len - sizeof(uint32_t); 206 memcpy(rngbuf, &val, sizeof(uint32_t)); 207 rngbuf++; 208 } else { 209 memcpy(rngbuf, &val, len); 210 len = 0; 211 } 212 } 213 } 214 215 return TEE_SUCCESS; 216 } 217 218 void plat_rng_init(void) 219 { 220 } 221 222 static TEE_Result rngb_init(void) 223 { 224 uint32_t type = 0; 225 226 if (map_controller()) 227 panic(); 228 229 type = RNG_TYPE(io_read32(rngb.base.va + RNG_VER)); 230 if (type != RNG_TYPE_RNGB && type != RNG_TYPE_RNGC) 231 panic(); 232 233 rng_seed(&rngb); 234 rngb.ready = true; 235 236 return TEE_SUCCESS; 237 } 238 239 early_init(rngb_init); 240