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