1*c6ac89bcSPeng Fan /* 2*c6ac89bcSPeng Fan * Copyright 2017 NXP 3*c6ac89bcSPeng Fan * Copyright (c) 2014, 2015 Linaro Limited 4*c6ac89bcSPeng Fan * 5*c6ac89bcSPeng Fan * Peng Fan <peng.fan@nxp.com> 6*c6ac89bcSPeng Fan * 7*c6ac89bcSPeng Fan * Redistribution and use in source and binary forms, with or without 8*c6ac89bcSPeng Fan * modification, are permitted provided that the following conditions are met: 9*c6ac89bcSPeng Fan * 10*c6ac89bcSPeng Fan * 1. Redistributions of source code must retain the above copyright notice, 11*c6ac89bcSPeng Fan * this list of conditions and the following disclaimer. 12*c6ac89bcSPeng Fan * 13*c6ac89bcSPeng Fan * 2. Redistributions in binary form must reproduce the above copyright notice, 14*c6ac89bcSPeng Fan * this list of conditions and the following disclaimer in the documentation 15*c6ac89bcSPeng Fan * and/or other materials provided with the distribution. 16*c6ac89bcSPeng Fan * 17*c6ac89bcSPeng Fan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18*c6ac89bcSPeng Fan * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*c6ac89bcSPeng Fan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*c6ac89bcSPeng Fan * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21*c6ac89bcSPeng Fan * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22*c6ac89bcSPeng Fan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23*c6ac89bcSPeng Fan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24*c6ac89bcSPeng Fan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25*c6ac89bcSPeng Fan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26*c6ac89bcSPeng Fan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27*c6ac89bcSPeng Fan * POSSIBILITY OF SUCH DAMAGE. 28*c6ac89bcSPeng Fan */ 29*c6ac89bcSPeng Fan 30*c6ac89bcSPeng Fan #include <initcall.h> 31*c6ac89bcSPeng Fan #include <io.h> 32*c6ac89bcSPeng Fan #include <drivers/imx_snvs.h> 33*c6ac89bcSPeng Fan #include <kernel/misc.h> 34*c6ac89bcSPeng Fan #include <kernel/tee_time.h> 35*c6ac89bcSPeng Fan #include <kernel/time_source.h> 36*c6ac89bcSPeng Fan #include <mm/core_memprot.h> 37*c6ac89bcSPeng Fan #include <mm/core_mmu.h> 38*c6ac89bcSPeng Fan #include <mpa.h> 39*c6ac89bcSPeng Fan #include <utee_defines.h> 40*c6ac89bcSPeng Fan #include <platform_config.h> 41*c6ac89bcSPeng Fan #include <stdint.h> 42*c6ac89bcSPeng Fan #include <tee/tee_cryp_utl.h> 43*c6ac89bcSPeng Fan #include <types_ext.h> 44*c6ac89bcSPeng Fan #include <trace.h> 45*c6ac89bcSPeng Fan 46*c6ac89bcSPeng Fan #define SNVS_LPLR 0x34 47*c6ac89bcSPeng Fan #define SNVS_LPCR 0x38 48*c6ac89bcSPeng Fan #define SNVS_LPMKCR 0x3C 49*c6ac89bcSPeng Fan #define SNVS_LPSVCR 0x40 50*c6ac89bcSPeng Fan #define SNVS_LPTGFCR 0x44 51*c6ac89bcSPeng Fan #define SNVS_LPTDCR 0x48 52*c6ac89bcSPeng Fan #define SNVS_LPSR 0x4C 53*c6ac89bcSPeng Fan #define SNVS_LPSRTCMR 0x50 54*c6ac89bcSPeng Fan #define SNVS_LPSRTCLR 0x54 55*c6ac89bcSPeng Fan #define SNVS_LPTAR 0x58 56*c6ac89bcSPeng Fan #define SNVS_LPSMCMR 0x5C 57*c6ac89bcSPeng Fan #define SNVS_LPSMCLR 0x60 58*c6ac89bcSPeng Fan #define SNVS_LPPGDR 0x64 59*c6ac89bcSPeng Fan #define SNVS_LPGPR0_A 0x68 60*c6ac89bcSPeng Fan #define SNVS_LPZMKR0 0x6C 61*c6ac89bcSPeng Fan #define SNVS_LPCGR0_30 0x90 62*c6ac89bcSPeng Fan #define SNVS_LPCGR0_31 0x94 63*c6ac89bcSPeng Fan #define SNVS_LPCGR0_32 0x98 64*c6ac89bcSPeng Fan #define SNVS_LPCGR0_33 0x9C 65*c6ac89bcSPeng Fan #define SNVS_LPTDC2R 0xA0 66*c6ac89bcSPeng Fan #define SNVS_LPTDSR 0xA4 67*c6ac89bcSPeng Fan #define SNVS_LPTGF1CR 0xA8 68*c6ac89bcSPeng Fan #define SNVS_LPTGF2CR 0xAC 69*c6ac89bcSPeng Fan #define SNVS_LPAT1CR 0xC0 70*c6ac89bcSPeng Fan #define SNVS_LPAT2CR 0xC4 71*c6ac89bcSPeng Fan #define SNVS_LPAT3CR 0xC8 72*c6ac89bcSPeng Fan #define SNVS_LPAT4CR 0xCC 73*c6ac89bcSPeng Fan #define SNVS_LPAT5CR 0xD0 74*c6ac89bcSPeng Fan #define SNVS_LPATCTLR 0xE0 75*c6ac89bcSPeng Fan #define SNVS_LPATCLKR 0xE4 76*c6ac89bcSPeng Fan #define SNVS_LPATRC1R 0xE8 77*c6ac89bcSPeng Fan #define SNVS_LPATRC2R 0xEC 78*c6ac89bcSPeng Fan 79*c6ac89bcSPeng Fan #define SNVS_LPCR_TOP_MASK BIT(6) 80*c6ac89bcSPeng Fan #define SNVS_LPCR_DP_EN_MASK BIT(5) 81*c6ac89bcSPeng Fan #define SNVS_LPCR_SRTC_ENV_MASK BIT(0) 82*c6ac89bcSPeng Fan 83*c6ac89bcSPeng Fan /* SNVS LP SRTC takes 32K clock as input */ 84*c6ac89bcSPeng Fan #define SNVS_SRTC_FREQ 0x8000 85*c6ac89bcSPeng Fan #define CNT_TO_SECS_SHIFT 15 86*c6ac89bcSPeng Fan #define CNT_TO_SECS_MASK GENMASK_32(14, 0) 87*c6ac89bcSPeng Fan 88*c6ac89bcSPeng Fan static uint64_t snvs_srtc_read_lp_counter(void) 89*c6ac89bcSPeng Fan { 90*c6ac89bcSPeng Fan vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC); 91*c6ac89bcSPeng Fan uint64_t val1, val2; 92*c6ac89bcSPeng Fan uint32_t val; 93*c6ac89bcSPeng Fan 94*c6ac89bcSPeng Fan do { 95*c6ac89bcSPeng Fan val = read32(snvs + SNVS_LPSRTCMR); 96*c6ac89bcSPeng Fan val1 = val; 97*c6ac89bcSPeng Fan val1 <<= 32; 98*c6ac89bcSPeng Fan val = read32(snvs + SNVS_LPSRTCLR); 99*c6ac89bcSPeng Fan val1 |= val; 100*c6ac89bcSPeng Fan 101*c6ac89bcSPeng Fan val = read32(snvs + SNVS_LPSRTCMR); 102*c6ac89bcSPeng Fan val2 = val; 103*c6ac89bcSPeng Fan val2 <<= 32; 104*c6ac89bcSPeng Fan val = read32(snvs + SNVS_LPSRTCLR); 105*c6ac89bcSPeng Fan val2 |= val; 106*c6ac89bcSPeng Fan 107*c6ac89bcSPeng Fan /* 108*c6ac89bcSPeng Fan * When cpu/bus runs at low freq, we may never get same value 109*c6ac89bcSPeng Fan * during two consecutive read, so only compare the second value. 110*c6ac89bcSPeng Fan */ 111*c6ac89bcSPeng Fan } while ((val1 >> CNT_TO_SECS_SHIFT) != (val2 >> CNT_TO_SECS_SHIFT)); 112*c6ac89bcSPeng Fan 113*c6ac89bcSPeng Fan return val2; 114*c6ac89bcSPeng Fan } 115*c6ac89bcSPeng Fan 116*c6ac89bcSPeng Fan static TEE_Result snvs_srtc_get_sys_time(TEE_Time *time) 117*c6ac89bcSPeng Fan { 118*c6ac89bcSPeng Fan uint64_t cnt = snvs_srtc_read_lp_counter(); 119*c6ac89bcSPeng Fan 120*c6ac89bcSPeng Fan time->seconds = cnt >> CNT_TO_SECS_SHIFT; 121*c6ac89bcSPeng Fan time->millis = (cnt & CNT_TO_SECS_MASK) / 122*c6ac89bcSPeng Fan (SNVS_SRTC_FREQ / TEE_TIME_MILLIS_BASE); 123*c6ac89bcSPeng Fan 124*c6ac89bcSPeng Fan return TEE_SUCCESS; 125*c6ac89bcSPeng Fan } 126*c6ac89bcSPeng Fan 127*c6ac89bcSPeng Fan static const struct time_source snvs_srtc_time_source = { 128*c6ac89bcSPeng Fan .name = "snvs srtc", 129*c6ac89bcSPeng Fan .protection_level = 1000, 130*c6ac89bcSPeng Fan .get_sys_time = snvs_srtc_get_sys_time, 131*c6ac89bcSPeng Fan }; 132*c6ac89bcSPeng Fan 133*c6ac89bcSPeng Fan REGISTER_TIME_SOURCE(snvs_srtc_time_source) 134*c6ac89bcSPeng Fan 135*c6ac89bcSPeng Fan /* Needs to be invoked before service_init */ 136*c6ac89bcSPeng Fan TEE_Result snvs_srtc_enable(void) 137*c6ac89bcSPeng Fan { 138*c6ac89bcSPeng Fan vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC); 139*c6ac89bcSPeng Fan int timeout = 2000; 140*c6ac89bcSPeng Fan uint32_t val; 141*c6ac89bcSPeng Fan 142*c6ac89bcSPeng Fan val = read32(snvs + SNVS_LPCR); 143*c6ac89bcSPeng Fan val |= SNVS_LPCR_SRTC_ENV_MASK; 144*c6ac89bcSPeng Fan write32(val, snvs + SNVS_LPCR); 145*c6ac89bcSPeng Fan 146*c6ac89bcSPeng Fan do { 147*c6ac89bcSPeng Fan val = read32(snvs + SNVS_LPCR); 148*c6ac89bcSPeng Fan if (val & SNVS_LPCR_SRTC_ENV_MASK) 149*c6ac89bcSPeng Fan break; 150*c6ac89bcSPeng Fan } while (--timeout); 151*c6ac89bcSPeng Fan 152*c6ac89bcSPeng Fan if (!timeout) 153*c6ac89bcSPeng Fan return TEE_ERROR_GENERIC; 154*c6ac89bcSPeng Fan 155*c6ac89bcSPeng Fan return TEE_SUCCESS; 156*c6ac89bcSPeng Fan } 157*c6ac89bcSPeng Fan 158*c6ac89bcSPeng Fan /* Reused from tee_time_arm_cntpct.c */ 159*c6ac89bcSPeng Fan void plat_prng_add_jitter_entropy(void) 160*c6ac89bcSPeng Fan { 161*c6ac89bcSPeng Fan uint64_t tsc = snvs_srtc_read_lp_counter(); 162*c6ac89bcSPeng Fan int bytes = 0, n; 163*c6ac89bcSPeng Fan static uint8_t first, bits; 164*c6ac89bcSPeng Fan static uint16_t acc; 165*c6ac89bcSPeng Fan 166*c6ac89bcSPeng Fan if (!first) { 167*c6ac89bcSPeng Fan acc = tsc; 168*c6ac89bcSPeng Fan bytes = 2; 169*c6ac89bcSPeng Fan first = 1; 170*c6ac89bcSPeng Fan } else { 171*c6ac89bcSPeng Fan acc = (acc << 2) | ((acc >> 6) & 3); 172*c6ac89bcSPeng Fan for (n = 0; n < 64; n += 2) 173*c6ac89bcSPeng Fan acc ^= (tsc >> n) & 3; 174*c6ac89bcSPeng Fan bits += 2; 175*c6ac89bcSPeng Fan if (bits >= 8) { 176*c6ac89bcSPeng Fan bits = 0; 177*c6ac89bcSPeng Fan bytes = 1; 178*c6ac89bcSPeng Fan } 179*c6ac89bcSPeng Fan } 180*c6ac89bcSPeng Fan if (bytes) { 181*c6ac89bcSPeng Fan FMSG("%s: 0x%02" PRIX16, __func__, 182*c6ac89bcSPeng Fan acc & GENMASK_32(bytes * 8, 0)); 183*c6ac89bcSPeng Fan tee_prng_add_entropy((uint8_t *)&acc, bytes); 184*c6ac89bcSPeng Fan } 185*c6ac89bcSPeng Fan } 186