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