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