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