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