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