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