xref: /optee_os/core/drivers/imx_ocotp.c (revision b9ca22051bad8f8c6c853252363858ae7c581766)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2021 NXP
4  */
5 #include <arm.h>
6 #include <initcall.h>
7 #include <mm/core_memprot.h>
8 #include <mm/core_mmu.h>
9 #include <imx.h>
10 #include <io.h>
11 #include <drivers/imx_ocotp.h>
12 #include <kernel/delay_arch.h>
13 #include <kernel/tee_common_otp.h>
14 
15 #define OCOTP_CTRL			0x0
16 #define OCOTP_CTRL_CLR			0x8
17 
18 #if defined(CFG_MX8MP)
19 #define OCOTP_CTRL_ERROR		BIT32(10)
20 #define OCOTP_CTRL_BUSY			BIT32(9)
21 #else
22 #define OCOTP_CTRL_ERROR		BIT32(9)
23 #define OCOTP_CTRL_BUSY			BIT32(8)
24 #endif
25 
26 #if defined(CFG_MX6) || defined(CFG_MX7ULP)
27 #define OCOTP_SHADOW_OFFSET(_b, _w)	((_b) * (0x80) + (_w) * (0x10) + 0x400)
28 #else
29 #define OCOTP_SHADOW_OFFSET(_b, _w)	((_b) * (0x40) + (_w) * (0x10) + 0x400)
30 #endif
31 
32 #define OCOTP_OP_BUSY_TIMEOUT_US	20
33 
34 struct ocotp_instance {
35 	unsigned char nb_banks;
36 	unsigned char nb_words;
37 	TEE_Result (*get_die_id)(uint64_t *ret_uid);
38 };
39 
40 static vaddr_t g_base_addr;
41 static struct mutex fuse_read = MUTEX_INITIALIZER;
42 static const struct ocotp_instance *g_ocotp;
43 
44 #if defined(CFG_MX6)
45 static void ocotp_clock_enable(void)
46 {
47 	vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE);
48 
49 	io_setbits32(va + CCM_CCGR2, BM_CCM_CCGR2_OCOTP_CTRL);
50 }
51 #elif defined(CFG_MX7)
52 static void ocotp_clock_enable(void)
53 {
54 	vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE);
55 
56 	io_setbits32(va + CCM_CCGRx_SET(CCM_CLOCK_DOMAIN_OCOTP),
57 		     CCM_CCGRx_ALWAYS_ON(0));
58 }
59 #elif defined(CFG_MX8M)
60 static void ocotp_clock_enable(void)
61 {
62 	vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE);
63 
64 	io_setbits32(va + CCM_CCGRx_SET(CCM_CCRG_OCOTP),
65 		     CCM_CCGRx_ALWAYS_ON(0));
66 }
67 #elif defined(CFG_MX7ULP)
68 /* The i.MX7ULP has the OCOTP always powered on */
69 static inline void ocotp_clock_enable(void) { }
70 #else
71 #error "Platform not supported"
72 #endif
73 
74 #if defined(CFG_CORE_HAS_GENERIC_TIMER)
75 static TEE_Result ocotp_ctrl_wait_for(uint32_t mask)
76 {
77 	uint32_t val = 0;
78 
79 	assert(g_base_addr);
80 	if (IO_READ32_POLL_TIMEOUT(g_base_addr + OCOTP_CTRL, val,
81 				   !(val & mask), 0, OCOTP_OP_BUSY_TIMEOUT_US))
82 		return TEE_ERROR_BUSY;
83 
84 	return TEE_SUCCESS;
85 }
86 #else
87 static TEE_Result ocotp_ctrl_wait_for(uint32_t mask)
88 {
89 	unsigned int loop = 0;
90 	uint32_t reg = 0;
91 
92 	assert(g_base_addr);
93 
94 	/* 20us delay assuming the CPU clock running at 500MHz */
95 	for (loop = 10000; loop > 0; loop--) {
96 		reg = io_read32(g_base_addr + OCOTP_CTRL) & mask;
97 		if (!reg)
98 			return TEE_SUCCESS;
99 		dsb();
100 		isb();
101 	}
102 
103 	return TEE_ERROR_BUSY;
104 }
105 #endif
106 
107 TEE_Result imx_ocotp_read(unsigned int bank, unsigned int word, uint32_t *val)
108 {
109 	TEE_Result ret = TEE_ERROR_GENERIC;
110 
111 	if (!val)
112 		return TEE_ERROR_BAD_PARAMETERS;
113 
114 	assert(g_base_addr && g_ocotp);
115 
116 	if (bank > g_ocotp->nb_banks || word > g_ocotp->nb_words)
117 		return TEE_ERROR_BAD_PARAMETERS;
118 
119 	mutex_lock(&fuse_read);
120 
121 	ocotp_clock_enable();
122 
123 	/* Clear error bit */
124 	io_write32(g_base_addr + OCOTP_CTRL_CLR, OCOTP_CTRL_ERROR);
125 
126 	/* Wait for busy flag to be cleared */
127 	ret = ocotp_ctrl_wait_for(OCOTP_CTRL_BUSY);
128 	if (ret) {
129 		EMSG("OCOTP is busy");
130 		goto out;
131 	}
132 
133 	/* Read shadow register */
134 	*val = io_read32(g_base_addr + OCOTP_SHADOW_OFFSET(bank, word));
135 
136 	DMSG("OCOTP Bank %d Word %d Fuse 0x%" PRIx32, bank, word, *val);
137 out:
138 	mutex_unlock(&fuse_read);
139 
140 	return ret;
141 }
142 
143 static TEE_Result ocotp_get_die_id_mx7ulp(uint64_t *ret_uid)
144 {
145 	TEE_Result res = TEE_ERROR_GENERIC;
146 	uint32_t val = 0;
147 	uint64_t uid = 0;
148 
149 	res = imx_ocotp_read(1, 6, &val);
150 	if (res)
151 		goto out;
152 	uid = val & GENMASK_32(15, 0);
153 
154 	res = imx_ocotp_read(1, 5, &val);
155 	if (res)
156 		goto out;
157 	uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0));
158 
159 	res = imx_ocotp_read(1, 4, &val);
160 	if (res)
161 		goto out;
162 	uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0));
163 
164 	res = imx_ocotp_read(1, 3, &val);
165 	if (res)
166 		goto out;
167 	uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0));
168 
169 out:
170 	if (res == TEE_SUCCESS)
171 		*ret_uid = uid;
172 
173 	return res;
174 }
175 
176 static TEE_Result ocotp_get_die_id_mx(uint64_t *ret_uid)
177 {
178 	TEE_Result res = TEE_ERROR_GENERIC;
179 	uint32_t val = 0;
180 	uint64_t uid = 0;
181 
182 	res = imx_ocotp_read(0, 2, &val);
183 	if (res)
184 		goto out;
185 	uid = val;
186 
187 	res = imx_ocotp_read(0, 1, &val);
188 	if (res)
189 		goto out;
190 	uid = SHIFT_U64(uid, 32) | val;
191 
192 out:
193 	if (res == TEE_SUCCESS)
194 		*ret_uid = uid;
195 
196 	return res;
197 }
198 
199 static const struct ocotp_instance ocotp_imx6q = {
200 	.nb_banks = 16,
201 	.nb_words = 8,
202 	.get_die_id = ocotp_get_die_id_mx,
203 };
204 
205 static const struct ocotp_instance ocotp_imx6sl = {
206 	.nb_banks = 8,
207 	.nb_words = 8,
208 	.get_die_id = ocotp_get_die_id_mx,
209 };
210 
211 static const struct ocotp_instance ocotp_imx6sll = {
212 	.nb_banks = 16,
213 	.nb_words = 8,
214 	.get_die_id = ocotp_get_die_id_mx,
215 };
216 
217 static const struct ocotp_instance ocotp_imx6sx = {
218 	.nb_banks = 16,
219 	.nb_words = 8,
220 	.get_die_id = ocotp_get_die_id_mx,
221 };
222 
223 static const struct ocotp_instance ocotp_imx6ul = {
224 	.nb_banks = 16,
225 	.nb_words = 8,
226 	.get_die_id = ocotp_get_die_id_mx,
227 };
228 
229 static const struct ocotp_instance ocotp_imx6ull = {
230 	.nb_banks = 8,
231 	.nb_words = 8,
232 	.get_die_id = ocotp_get_die_id_mx,
233 };
234 
235 static const struct ocotp_instance ocotp_imx7d = {
236 	.nb_banks = 8,
237 	.nb_words = 8,
238 	.get_die_id = ocotp_get_die_id_mx,
239 };
240 
241 static const struct ocotp_instance ocotp_imx7ulp = {
242 	.nb_banks = 32,
243 	.nb_words = 8,
244 	.get_die_id = ocotp_get_die_id_mx7ulp,
245 };
246 
247 static const struct ocotp_instance ocotp_imx8m = {
248 	.nb_banks = 32,
249 	.nb_words = 8,
250 	.get_die_id = ocotp_get_die_id_mx,
251 };
252 
253 static const struct ocotp_instance ocotp_imx8mp = {
254 	.nb_banks = 48,
255 	.nb_words = 8,
256 	.get_die_id = ocotp_get_die_id_mx,
257 };
258 
259 int tee_otp_get_die_id(uint8_t *buffer, size_t len)
260 {
261 	size_t max_size_uid = IMX_UID_SIZE;
262 	uint64_t uid = 0;
263 
264 	assert(buffer);
265 	assert(g_base_addr && g_ocotp);
266 
267 	if (g_ocotp->get_die_id(&uid))
268 		goto err;
269 
270 	memcpy(buffer, &uid, MIN(max_size_uid, len));
271 	return 0;
272 
273 err:
274 	EMSG("Error while getting die ID");
275 	return -1;
276 }
277 
278 register_phys_mem_pgdir(MEM_AREA_IO_SEC, OCOTP_BASE, CORE_MMU_PGDIR_SIZE);
279 static TEE_Result imx_ocotp_init(void)
280 {
281 	g_base_addr = core_mmu_get_va(OCOTP_BASE, MEM_AREA_IO_SEC, OCOTP_SIZE);
282 	if (!g_base_addr)
283 		return TEE_ERROR_GENERIC;
284 
285 	if (soc_is_imx6sdl() || soc_is_imx6dq() || soc_is_imx6dqp()) {
286 		g_ocotp = &ocotp_imx6q;
287 	} else if (soc_is_imx6sl()) {
288 		g_ocotp = &ocotp_imx6sl;
289 	} else if (soc_is_imx6sll()) {
290 		g_ocotp = &ocotp_imx6sll;
291 	} else if (soc_is_imx6sx()) {
292 		g_ocotp = &ocotp_imx6sx;
293 	} else if (soc_is_imx6ul()) {
294 		g_ocotp = &ocotp_imx6ul;
295 	} else if (soc_is_imx6ull()) {
296 		g_ocotp = &ocotp_imx6ull;
297 	} else if (soc_is_imx7ds()) {
298 		g_ocotp = &ocotp_imx7d;
299 	} else if (soc_is_imx7ulp()) {
300 		g_ocotp = &ocotp_imx7ulp;
301 	} else if (soc_is_imx8mm() || soc_is_imx8mn() || soc_is_imx8mq()) {
302 		g_ocotp = &ocotp_imx8m;
303 	} else if (soc_is_imx8mp()) {
304 		g_ocotp = &ocotp_imx8mp;
305 	} else {
306 		g_ocotp = NULL;
307 		return TEE_ERROR_NOT_SUPPORTED;
308 	}
309 
310 	return TEE_SUCCESS;
311 }
312 service_init(imx_ocotp_init);
313