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