xref: /optee_os/core/drivers/imx_snvs.c (revision 1bb929836182ecb96d2d9d268daa807c67596396)
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