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