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