]>
Commit | Line | Data |
---|---|---|
242d1cd6 FL |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright 2019-2020 NXP. | |
4 | */ | |
5 | ||
6 | /* | |
7 | * Configuration of the Tamper pins in different mode: | |
8 | * - default (no tamper pins): _default_ | |
9 | * - passive mode expecting VCC on the line: "_passive_vcc_" | |
10 | * - passive mode expecting VCC on the line: "_passive_gnd_" | |
11 | * - active mode: "_active_" | |
12 | */ | |
13 | ||
14 | #include <command.h> | |
15 | #include <log.h> | |
16 | #include <stddef.h> | |
17 | #include <common.h> | |
18 | #include <asm/arch/sci/sci.h> | |
19 | #include <asm/arch-imx8/imx8-pins.h> | |
20 | #include <asm/arch-imx8/snvs_security_sc.h> | |
21 | ||
22 | /* Access to gd */ | |
23 | DECLARE_GLOBAL_DATA_PTR; | |
24 | ||
25 | #define SC_WRITE_CONF 1 | |
26 | ||
27 | #define PGD_HEX_VALUE 0x41736166 | |
28 | #define SRTC_EN 0x1 | |
29 | #define DP_EN BIT(5) | |
30 | ||
31 | struct snvs_security_sc_conf { | |
32 | struct snvs_hp_conf { | |
33 | u32 lock; /* HPLR - HP Lock */ | |
34 | u32 __cmd; /* HPCOMR - HP Command */ | |
35 | u32 __ctl; /* HPCR - HP Control */ | |
36 | u32 secvio_intcfg; /* HPSICR - Security Violation Int | |
37 | * Config | |
38 | */ | |
39 | u32 secvio_ctl; /* HPSVCR - Security Violation Control*/ | |
40 | u32 status; /* HPSR - HP Status */ | |
41 | u32 secvio_status; /* HPSVSR - Security Violation Status */ | |
42 | u32 __ha_counteriv; /* High Assurance Counter IV */ | |
43 | u32 __ha_counter; /* High Assurance Counter */ | |
44 | u32 __rtc_msb; /* Real Time Clock/Counter MSB */ | |
45 | u32 __rtc_lsb; /* Real Time Counter LSB */ | |
46 | u32 __time_alarm_msb; /* Time Alarm MSB */ | |
47 | u32 __time_alarm_lsb; /* Time Alarm LSB */ | |
48 | } hp; | |
49 | struct snvs_lp_conf { | |
50 | u32 lock; | |
51 | u32 __ctl; | |
52 | u32 __mstr_key_ctl; /* Master Key Control */ | |
53 | u32 secvio_ctl; /* Security Violation Control */ | |
54 | u32 tamper_filt_cfg; /* Tamper Glitch Filters Configuration*/ | |
55 | u32 tamper_det_cfg; /* Tamper Detectors Configuration */ | |
56 | u32 status; | |
57 | u32 __srtc_msb; /* Secure Real Time Clock/Counter MSB */ | |
58 | u32 __srtc_lsb; /* Secure Real Time Clock/Counter LSB */ | |
59 | u32 __time_alarm; /* Time Alarm */ | |
60 | u32 __smc_msb; /* Secure Monotonic Counter MSB */ | |
61 | u32 __smc_lsb; /* Secure Monotonic Counter LSB */ | |
62 | u32 __pwr_glitch_det; /* Power Glitch Detector */ | |
63 | u32 __gen_purpose; | |
64 | u8 __zmk[32]; /* Zeroizable Master Key */ | |
65 | u32 __rsvd0; | |
66 | u32 __gen_purposes[4]; /* gp0_30 to gp0_33 */ | |
67 | u32 tamper_det_cfg2; /* Tamper Detectors Configuration2 */ | |
68 | u32 tamper_det_status; /* Tamper Detectors status */ | |
69 | u32 tamper_filt1_cfg; /* Tamper Glitch Filter1 Configuration*/ | |
70 | u32 tamper_filt2_cfg; /* Tamper Glitch Filter2 Configuration*/ | |
71 | u32 __rsvd1[4]; | |
72 | u32 act_tamper1_cfg; /* Active Tamper1 Configuration */ | |
73 | u32 act_tamper2_cfg; /* Active Tamper2 Configuration */ | |
74 | u32 act_tamper3_cfg; /* Active Tamper3 Configuration */ | |
75 | u32 act_tamper4_cfg; /* Active Tamper4 Configuration */ | |
76 | u32 act_tamper5_cfg; /* Active Tamper5 Configuration */ | |
77 | u32 __rsvd2[3]; | |
78 | u32 act_tamper_ctl; /* Active Tamper Control */ | |
79 | u32 act_tamper_clk_ctl; /* Active Tamper Clock Control */ | |
80 | u32 act_tamper_routing_ctl1;/* Active Tamper Routing Control1 */ | |
81 | u32 act_tamper_routing_ctl2;/* Active Tamper Routing Control2 */ | |
82 | } lp; | |
83 | }; | |
84 | ||
85 | static struct snvs_security_sc_conf snvs_default_config = { | |
86 | .hp = { | |
87 | .lock = 0x1f0703ff, | |
88 | .secvio_ctl = 0x3000007f, | |
89 | }, | |
90 | .lp = { | |
91 | .lock = 0x1f0003ff, | |
92 | .secvio_ctl = 0x36, | |
93 | .tamper_filt_cfg = 0, | |
94 | .tamper_det_cfg = 0x76, /* analogic tampers | |
95 | * + rollover tampers | |
96 | */ | |
97 | .tamper_det_cfg2 = 0, | |
98 | .tamper_filt1_cfg = 0, | |
99 | .tamper_filt2_cfg = 0, | |
100 | .act_tamper1_cfg = 0, | |
101 | .act_tamper2_cfg = 0, | |
102 | .act_tamper3_cfg = 0, | |
103 | .act_tamper4_cfg = 0, | |
104 | .act_tamper5_cfg = 0, | |
105 | .act_tamper_ctl = 0, | |
106 | .act_tamper_clk_ctl = 0, | |
107 | .act_tamper_routing_ctl1 = 0, | |
108 | .act_tamper_routing_ctl2 = 0, | |
109 | } | |
110 | }; | |
111 | ||
112 | static struct snvs_security_sc_conf snvs_passive_vcc_config = { | |
113 | .hp = { | |
114 | .lock = 0x1f0703ff, | |
115 | .secvio_ctl = 0x3000007f, | |
116 | }, | |
117 | .lp = { | |
118 | .lock = 0x1f0003ff, | |
119 | .secvio_ctl = 0x36, | |
120 | .tamper_filt_cfg = 0, | |
121 | .tamper_det_cfg = 0x276, /* ET1 will trig on line at GND | |
122 | * + analogic tampers | |
123 | * + rollover tampers | |
124 | */ | |
125 | .tamper_det_cfg2 = 0, | |
126 | .tamper_filt1_cfg = 0, | |
127 | .tamper_filt2_cfg = 0, | |
128 | .act_tamper1_cfg = 0, | |
129 | .act_tamper2_cfg = 0, | |
130 | .act_tamper3_cfg = 0, | |
131 | .act_tamper4_cfg = 0, | |
132 | .act_tamper5_cfg = 0, | |
133 | .act_tamper_ctl = 0, | |
134 | .act_tamper_clk_ctl = 0, | |
135 | .act_tamper_routing_ctl1 = 0, | |
136 | .act_tamper_routing_ctl2 = 0, | |
137 | } | |
138 | }; | |
139 | ||
140 | static struct snvs_security_sc_conf snvs_passive_gnd_config = { | |
141 | .hp = { | |
142 | .lock = 0x1f0703ff, | |
143 | .secvio_ctl = 0x3000007f, | |
144 | }, | |
145 | .lp = { | |
146 | .lock = 0x1f0003ff, | |
147 | .secvio_ctl = 0x36, | |
148 | .tamper_filt_cfg = 0, | |
149 | .tamper_det_cfg = 0xa76, /* ET1 will trig on line at VCC | |
150 | * + analogic tampers | |
151 | * + rollover tampers | |
152 | */ | |
153 | .tamper_det_cfg2 = 0, | |
154 | .tamper_filt1_cfg = 0, | |
155 | .tamper_filt2_cfg = 0, | |
156 | .act_tamper1_cfg = 0, | |
157 | .act_tamper2_cfg = 0, | |
158 | .act_tamper3_cfg = 0, | |
159 | .act_tamper4_cfg = 0, | |
160 | .act_tamper5_cfg = 0, | |
161 | .act_tamper_ctl = 0, | |
162 | .act_tamper_clk_ctl = 0, | |
163 | .act_tamper_routing_ctl1 = 0, | |
164 | .act_tamper_routing_ctl2 = 0, | |
165 | } | |
166 | }; | |
167 | ||
168 | static struct snvs_security_sc_conf snvs_active_config = { | |
169 | .hp = { | |
170 | .lock = 0x1f0703ff, | |
171 | .secvio_ctl = 0x3000007f, | |
172 | }, | |
173 | .lp = { | |
174 | .lock = 0x1f0003ff, | |
175 | .secvio_ctl = 0x36, | |
176 | .tamper_filt_cfg = 0x00800000, /* Enable filtering */ | |
177 | .tamper_det_cfg = 0x276, /* ET1 enabled + analogic tampers | |
178 | * + rollover tampers | |
179 | */ | |
180 | .tamper_det_cfg2 = 0, | |
181 | .tamper_filt1_cfg = 0, | |
182 | .tamper_filt2_cfg = 0, | |
183 | .act_tamper1_cfg = 0x84001111, | |
184 | .act_tamper2_cfg = 0, | |
185 | .act_tamper3_cfg = 0, | |
186 | .act_tamper4_cfg = 0, | |
187 | .act_tamper5_cfg = 0, | |
188 | .act_tamper_ctl = 0x00010001, | |
189 | .act_tamper_clk_ctl = 0, | |
190 | .act_tamper_routing_ctl1 = 0x1, | |
191 | .act_tamper_routing_ctl2 = 0, | |
192 | } | |
193 | }; | |
194 | ||
195 | static struct snvs_security_sc_conf *get_snvs_config(void) | |
196 | { | |
197 | return &snvs_default_config; | |
198 | } | |
199 | ||
200 | struct snvs_dgo_conf { | |
201 | u32 tamper_offset_ctl; | |
202 | u32 tamper_pull_ctl; | |
203 | u32 tamper_ana_test_ctl; | |
204 | u32 tamper_sensor_trim_ctl; | |
205 | u32 tamper_misc_ctl; | |
206 | u32 tamper_core_volt_mon_ctl; | |
207 | }; | |
208 | ||
209 | static struct snvs_dgo_conf snvs_dgo_default_config = { | |
210 | .tamper_misc_ctl = 0x80000000, /* Lock the DGO */ | |
211 | }; | |
212 | ||
213 | static struct snvs_dgo_conf snvs_dgo_passive_vcc_config = { | |
214 | .tamper_misc_ctl = 0x80000000, /* Lock the DGO */ | |
215 | .tamper_pull_ctl = 0x00000001, /* Pull down ET1 */ | |
216 | .tamper_ana_test_ctl = 0x20000000, /* Enable tamper */ | |
217 | }; | |
218 | ||
219 | static struct snvs_dgo_conf snvs_dgo_passive_gnd_config = { | |
220 | .tamper_misc_ctl = 0x80000000, /* Lock the DGO */ | |
221 | .tamper_pull_ctl = 0x00000401, /* Pull up ET1 */ | |
222 | .tamper_ana_test_ctl = 0x20000000, /* Enable tamper */ | |
223 | }; | |
224 | ||
225 | static struct snvs_dgo_conf snvs_dgo_active_config = { | |
226 | .tamper_misc_ctl = 0x80000000, /* Lock the DGO */ | |
227 | .tamper_ana_test_ctl = 0x20000000, /* Enable tamper */ | |
228 | }; | |
229 | ||
230 | static struct snvs_dgo_conf *get_snvs_dgo_config(void) | |
231 | { | |
232 | return &snvs_dgo_default_config; | |
233 | } | |
234 | ||
235 | struct tamper_pin_cfg { | |
236 | u32 pad; | |
237 | u32 mux_conf; | |
238 | }; | |
239 | ||
240 | static struct tamper_pin_cfg tamper_pin_list_default_config[] = { | |
241 | {SC_P_CSI_D00, 0}, /* Tamp_Out0 */ | |
242 | {SC_P_CSI_D01, 0}, /* Tamp_Out1 */ | |
243 | {SC_P_CSI_D02, 0}, /* Tamp_Out2 */ | |
244 | {SC_P_CSI_D03, 0}, /* Tamp_Out3 */ | |
245 | {SC_P_CSI_D04, 0}, /* Tamp_Out4 */ | |
246 | {SC_P_CSI_D05, 0}, /* Tamp_In0 */ | |
247 | {SC_P_CSI_D06, 0}, /* Tamp_In1 */ | |
248 | {SC_P_CSI_D07, 0}, /* Tamp_In2 */ | |
249 | {SC_P_CSI_HSYNC, 0}, /* Tamp_In3 */ | |
250 | {SC_P_CSI_VSYNC, 0}, /* Tamp_In4 */ | |
251 | }; | |
252 | ||
253 | static struct tamper_pin_cfg tamper_pin_list_passive_vcc_config[] = { | |
254 | {SC_P_CSI_D05, 0x1c000060}, /* Tamp_In0 */ /* Sel tamper + OD input */ | |
255 | }; | |
256 | ||
257 | static struct tamper_pin_cfg tamper_pin_list_passive_gnd_config[] = { | |
258 | {SC_P_CSI_D05, 0x1c000060}, /* Tamp_In0 */ /* Sel tamper + OD input */ | |
259 | }; | |
260 | ||
261 | static struct tamper_pin_cfg tamper_pin_list_active_config[] = { | |
262 | {SC_P_CSI_D00, 0x1a000060}, /* Tamp_Out0 */ /* Sel tamper + OD */ | |
263 | {SC_P_CSI_D05, 0x1c000060}, /* Tamp_In0 */ /* Sel tamper + OD input */ | |
264 | }; | |
265 | ||
266 | #define TAMPER_PIN_LIST_CHOSEN tamper_pin_list_default_config | |
267 | ||
268 | static struct tamper_pin_cfg *get_tamper_pin_cfg_list(u32 *size) | |
269 | { | |
270 | *size = sizeof(TAMPER_PIN_LIST_CHOSEN) / | |
271 | sizeof(TAMPER_PIN_LIST_CHOSEN[0]); | |
272 | ||
273 | return TAMPER_PIN_LIST_CHOSEN; | |
274 | } | |
275 | ||
276 | #define SC_CONF_OFFSET_OF(_field) \ | |
277 | (offsetof(struct snvs_security_sc_conf, _field)) | |
278 | ||
279 | static u32 ptr_value(u32 *_p) | |
280 | { | |
281 | return (_p) ? *_p : 0xdeadbeef; | |
282 | } | |
283 | ||
284 | static int check_write_secvio_config(u32 id, u32 *_p1, u32 *_p2, | |
285 | u32 *_p3, u32 *_p4, u32 *_p5, | |
286 | u32 _cnt) | |
287 | { | |
288 | int scierr = 0; | |
289 | u32 d1 = ptr_value(_p1); | |
290 | u32 d2 = ptr_value(_p2); | |
291 | u32 d3 = ptr_value(_p3); | |
292 | u32 d4 = ptr_value(_p4); | |
293 | u32 d5 = ptr_value(_p5); | |
294 | ||
295 | scierr = sc_seco_secvio_config(-1, id, SC_WRITE_CONF, &d1, &d2, &d3, | |
296 | &d4, &d4, _cnt); | |
297 | if (scierr != SC_ERR_NONE) { | |
298 | printf("Failed to set secvio configuration\n"); | |
299 | debug("Failed to set conf id 0x%x with values ", id); | |
300 | debug("0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x (cnt: %d)\n", | |
301 | d1, d2, d3, d4, d5, _cnt); | |
302 | goto exit; | |
303 | } | |
304 | ||
305 | if (_p1) | |
306 | *(u32 *)_p1 = d1; | |
307 | if (_p2) | |
308 | *(u32 *)_p2 = d2; | |
309 | if (_p3) | |
310 | *(u32 *)_p3 = d3; | |
311 | if (_p4) | |
312 | *(u32 *)_p4 = d4; | |
313 | if (_p5) | |
314 | *(u32 *)_p5 = d5; | |
315 | ||
316 | exit: | |
317 | return scierr; | |
318 | } | |
319 | ||
320 | #define SC_CHECK_WRITE1(id, _p1) \ | |
321 | check_write_secvio_config(id, _p1, NULL, NULL, NULL, NULL, 1) | |
322 | ||
323 | static int apply_snvs_config(struct snvs_security_sc_conf *cnf) | |
324 | { | |
325 | int scierr = 0; | |
326 | ||
327 | debug("%s\n", __func__); | |
328 | ||
329 | debug("Applying config:\n" | |
330 | "\thp.lock = 0x%.8x\n" | |
331 | "\thp.secvio_ctl = 0x%.8x\n" | |
332 | "\tlp.lock = 0x%.8x\n" | |
333 | "\tlp.secvio_ctl = 0x%.8x\n" | |
334 | "\tlp.tamper_filt_cfg = 0x%.8x\n" | |
335 | "\tlp.tamper_det_cfg = 0x%.8x\n" | |
336 | "\tlp.tamper_det_cfg2 = 0x%.8x\n" | |
337 | "\tlp.tamper_filt1_cfg = 0x%.8x\n" | |
338 | "\tlp.tamper_filt2_cfg = 0x%.8x\n" | |
339 | "\tlp.act_tamper1_cfg = 0x%.8x\n" | |
340 | "\tlp.act_tamper2_cfg = 0x%.8x\n" | |
341 | "\tlp.act_tamper3_cfg = 0x%.8x\n" | |
342 | "\tlp.act_tamper4_cfg = 0x%.8x\n" | |
343 | "\tlp.act_tamper5_cfg = 0x%.8x\n" | |
344 | "\tlp.act_tamper_ctl = 0x%.8x\n" | |
345 | "\tlp.act_tamper_clk_ctl = 0x%.8x\n" | |
346 | "\tlp.act_tamper_routing_ctl1 = 0x%.8x\n" | |
347 | "\tlp.act_tamper_routing_ctl2 = 0x%.8x\n", | |
348 | cnf->hp.lock, | |
349 | cnf->hp.secvio_ctl, | |
350 | cnf->lp.lock, | |
351 | cnf->lp.secvio_ctl, | |
352 | cnf->lp.tamper_filt_cfg, | |
353 | cnf->lp.tamper_det_cfg, | |
354 | cnf->lp.tamper_det_cfg2, | |
355 | cnf->lp.tamper_filt1_cfg, | |
356 | cnf->lp.tamper_filt2_cfg, | |
357 | cnf->lp.act_tamper1_cfg, | |
358 | cnf->lp.act_tamper2_cfg, | |
359 | cnf->lp.act_tamper3_cfg, | |
360 | cnf->lp.act_tamper4_cfg, | |
361 | cnf->lp.act_tamper5_cfg, | |
362 | cnf->lp.act_tamper_ctl, | |
363 | cnf->lp.act_tamper_clk_ctl, | |
364 | cnf->lp.act_tamper_routing_ctl1, | |
365 | cnf->lp.act_tamper_routing_ctl2); | |
366 | ||
367 | scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.tamper_filt_cfg), | |
368 | &cnf->lp.tamper_filt_cfg, | |
369 | &cnf->lp.tamper_filt1_cfg, | |
370 | &cnf->lp.tamper_filt2_cfg, NULL, | |
371 | NULL, 3); | |
372 | if (scierr != SC_ERR_NONE) | |
373 | goto exit; | |
374 | ||
375 | /* Configure AT */ | |
376 | scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.act_tamper1_cfg), | |
377 | &cnf->lp.act_tamper1_cfg, | |
378 | &cnf->lp.act_tamper2_cfg, | |
379 | &cnf->lp.act_tamper2_cfg, | |
380 | &cnf->lp.act_tamper2_cfg, | |
381 | &cnf->lp.act_tamper2_cfg, 5); | |
382 | if (scierr != SC_ERR_NONE) | |
383 | goto exit; | |
384 | ||
385 | /* Configure AT routing */ | |
386 | scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.act_tamper_routing_ctl1), | |
387 | &cnf->lp.act_tamper_routing_ctl1, | |
388 | &cnf->lp.act_tamper_routing_ctl2, | |
389 | NULL, NULL, NULL, 2); | |
390 | if (scierr != SC_ERR_NONE) | |
391 | goto exit; | |
392 | ||
393 | /* Configure AT frequency */ | |
394 | scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.act_tamper_clk_ctl), | |
395 | &cnf->lp.act_tamper_clk_ctl); | |
396 | if (scierr != SC_ERR_NONE) | |
397 | goto exit; | |
398 | ||
399 | /* Activate the ATs */ | |
400 | scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.act_tamper_ctl), | |
401 | &cnf->lp.act_tamper_ctl); | |
402 | if (scierr != SC_ERR_NONE) | |
403 | goto exit; | |
404 | ||
405 | /* Activate the detectors */ | |
406 | scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.tamper_det_cfg), | |
407 | &cnf->lp.tamper_det_cfg, | |
408 | &cnf->lp.tamper_det_cfg2, NULL, NULL, | |
409 | NULL, 2); | |
410 | if (scierr != SC_ERR_NONE) | |
411 | goto exit; | |
412 | ||
413 | /* Configure LP secvio */ | |
414 | scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.secvio_ctl), | |
415 | &cnf->lp.secvio_ctl); | |
416 | if (scierr != SC_ERR_NONE) | |
417 | goto exit; | |
418 | ||
419 | /* Configure HP secvio */ | |
420 | scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(hp.secvio_ctl), | |
421 | &cnf->hp.secvio_ctl); | |
422 | if (scierr != SC_ERR_NONE) | |
423 | goto exit; | |
424 | ||
425 | /* Lock access */ | |
426 | scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(hp.lock), &cnf->hp.lock); | |
427 | if (scierr != SC_ERR_NONE) | |
428 | goto exit; | |
429 | ||
430 | scierr = SC_CHECK_WRITE1(SC_CONF_OFFSET_OF(lp.lock), &cnf->lp.lock); | |
431 | if (scierr != SC_ERR_NONE) | |
432 | goto exit; | |
433 | ||
434 | exit: | |
435 | return (scierr == SC_ERR_NONE) ? 0 : -EIO; | |
436 | } | |
437 | ||
438 | static int dgo_write(u32 _id, u8 _access, u32 *_pdata) | |
439 | { | |
440 | int scierr = sc_seco_secvio_dgo_config(-1, _id, _access, _pdata); | |
441 | ||
442 | if (scierr != SC_ERR_NONE) { | |
443 | printf("Failed to set dgo configuration\n"); | |
444 | debug("Failed to set conf id 0x%x : 0x%.8x", _id, *_pdata); | |
445 | } | |
446 | ||
447 | return scierr; | |
448 | } | |
449 | ||
450 | static int apply_snvs_dgo_config(struct snvs_dgo_conf *cnf) | |
451 | { | |
452 | int scierr = 0; | |
453 | ||
454 | debug("%s\n", __func__); | |
455 | ||
456 | debug("Applying config:\n" | |
457 | "\ttamper_offset_ctl = 0x%.8x\n" | |
458 | "\ttamper_pull_ctl = 0x%.8x\n" | |
459 | "\ttamper_ana_test_ctl = 0x%.8x\n" | |
460 | "\ttamper_sensor_trim_ctl = 0x%.8x\n" | |
461 | "\ttamper_misc_ctl = 0x%.8x\n" | |
462 | "\ttamper_core_volt_mon_ctl = 0x%.8x\n", | |
463 | cnf->tamper_offset_ctl, | |
464 | cnf->tamper_pull_ctl, | |
465 | cnf->tamper_ana_test_ctl, | |
466 | cnf->tamper_sensor_trim_ctl, | |
467 | cnf->tamper_misc_ctl, | |
468 | cnf->tamper_core_volt_mon_ctl); | |
469 | ||
470 | dgo_write(0x04, 1, &cnf->tamper_offset_ctl); | |
471 | if (scierr != SC_ERR_NONE) | |
472 | goto exit; | |
473 | ||
474 | dgo_write(0x14, 1, &cnf->tamper_pull_ctl); | |
475 | if (scierr != SC_ERR_NONE) | |
476 | goto exit; | |
477 | ||
478 | dgo_write(0x24, 1, &cnf->tamper_ana_test_ctl); | |
479 | if (scierr != SC_ERR_NONE) | |
480 | goto exit; | |
481 | ||
482 | dgo_write(0x34, 1, &cnf->tamper_sensor_trim_ctl); | |
483 | if (scierr != SC_ERR_NONE) | |
484 | goto exit; | |
485 | ||
486 | dgo_write(0x54, 1, &cnf->tamper_core_volt_mon_ctl); | |
487 | if (scierr != SC_ERR_NONE) | |
488 | goto exit; | |
489 | ||
490 | /* Last as it could lock the writes */ | |
491 | dgo_write(0x44, 1, &cnf->tamper_misc_ctl); | |
492 | if (scierr != SC_ERR_NONE) | |
493 | goto exit; | |
494 | ||
495 | exit: | |
496 | return (scierr == SC_ERR_NONE) ? 0 : -EIO; | |
497 | } | |
498 | ||
499 | static int pad_write(u32 _pad, u32 _value) | |
500 | { | |
501 | int scierr = sc_pad_set(-1, _pad, _value); | |
502 | ||
503 | if (scierr != SC_ERR_NONE) { | |
504 | printf("Failed to set pad configuration\n"); | |
505 | debug("Failed to set conf pad 0x%x : 0x%.8x", _pad, _value); | |
506 | } | |
507 | ||
508 | return scierr; | |
509 | } | |
510 | ||
511 | static int apply_tamper_pin_list_config(struct tamper_pin_cfg *confs, u32 size) | |
512 | { | |
513 | int scierr = 0; | |
514 | u32 idx; | |
515 | ||
516 | debug("%s\n", __func__); | |
517 | ||
518 | for (idx = 0; idx < size; idx++) { | |
519 | debug("\t idx %d: pad %d: 0x%.8x\n", idx, confs[idx].pad, | |
520 | confs[idx].mux_conf); | |
521 | pad_write(confs[idx].pad, 3 << 30 | confs[idx].mux_conf); | |
522 | if (scierr != SC_ERR_NONE) | |
523 | goto exit; | |
524 | } | |
525 | ||
526 | exit: | |
527 | return (scierr == SC_ERR_NONE) ? 0 : -EIO; | |
528 | } | |
529 | ||
530 | int examples(void) | |
531 | { | |
532 | u32 size; | |
533 | struct snvs_security_sc_conf *snvs_conf; | |
534 | struct snvs_dgo_conf *snvs_dgo_conf; | |
535 | struct tamper_pin_cfg *tamper_pin_conf; | |
536 | ||
537 | /* Caller */ | |
538 | snvs_conf = get_snvs_config(); | |
539 | snvs_dgo_conf = get_snvs_dgo_config(); | |
540 | tamper_pin_conf = get_tamper_pin_cfg_list(&size); | |
541 | ||
542 | /* Default */ | |
543 | snvs_conf = &snvs_default_config; | |
544 | snvs_dgo_conf = &snvs_dgo_default_config; | |
545 | tamper_pin_conf = tamper_pin_list_default_config; | |
546 | ||
547 | /* Passive tamper expecting VCC on the line */ | |
548 | snvs_conf = &snvs_passive_vcc_config; | |
549 | snvs_dgo_conf = &snvs_dgo_passive_vcc_config; | |
550 | tamper_pin_conf = tamper_pin_list_passive_vcc_config; | |
551 | ||
552 | /* Passive tamper expecting GND on the line */ | |
553 | snvs_conf = &snvs_passive_gnd_config; | |
554 | snvs_dgo_conf = &snvs_dgo_passive_gnd_config; | |
555 | tamper_pin_conf = tamper_pin_list_passive_gnd_config; | |
556 | ||
557 | /* Active tamper */ | |
558 | snvs_conf = &snvs_active_config; | |
559 | snvs_dgo_conf = &snvs_dgo_active_config; | |
560 | tamper_pin_conf = tamper_pin_list_active_config; | |
561 | ||
562 | return !snvs_conf + !snvs_dgo_conf + !tamper_pin_conf; | |
563 | } | |
564 | ||
565 | #ifdef CONFIG_IMX_SNVS_SEC_SC_AUTO | |
566 | int snvs_security_sc_init(void) | |
567 | { | |
568 | int err = 0; | |
569 | ||
570 | struct snvs_security_sc_conf *snvs_conf; | |
571 | struct snvs_dgo_conf *snvs_dgo_conf; | |
572 | struct tamper_pin_cfg *tamper_pin_conf; | |
573 | u32 size; | |
574 | ||
575 | debug("%s\n", __func__); | |
576 | ||
577 | snvs_conf = get_snvs_config(); | |
578 | snvs_dgo_conf = get_snvs_dgo_config(); | |
579 | ||
580 | tamper_pin_conf = get_tamper_pin_cfg_list(&size); | |
581 | ||
582 | err = apply_tamper_pin_list_config(tamper_pin_conf, size); | |
583 | if (err) { | |
584 | debug("Failed to set pins\n"); | |
585 | goto exit; | |
586 | } | |
587 | ||
588 | err = apply_snvs_dgo_config(snvs_dgo_conf); | |
589 | if (err) { | |
590 | debug("Failed to set dgo\n"); | |
591 | goto exit; | |
592 | } | |
593 | ||
594 | err = apply_snvs_config(snvs_conf); | |
595 | if (err) { | |
596 | debug("Failed to set snvs\n"); | |
597 | goto exit; | |
598 | } | |
599 | ||
600 | exit: | |
601 | return err; | |
602 | } | |
603 | #endif /* CONFIG_IMX_SNVS_SEC_SC_AUTO */ | |
604 | ||
605 | static char snvs_cfg_help_text[] = | |
606 | "snvs_cfg\n" | |
607 | "\thp.lock\n" | |
608 | "\thp.secvio_ctl\n" | |
609 | "\tlp.lock\n" | |
610 | "\tlp.secvio_ctl\n" | |
611 | "\tlp.tamper_filt_cfg\n" | |
612 | "\tlp.tamper_det_cfg\n" | |
613 | "\tlp.tamper_det_cfg2\n" | |
614 | "\tlp.tamper_filt1_cfg\n" | |
615 | "\tlp.tamper_filt2_cfg\n" | |
616 | "\tlp.act_tamper1_cfg\n" | |
617 | "\tlp.act_tamper2_cfg\n" | |
618 | "\tlp.act_tamper3_cfg\n" | |
619 | "\tlp.act_tamper4_cfg\n" | |
620 | "\tlp.act_tamper5_cfg\n" | |
621 | "\tlp.act_tamper_ctl\n" | |
622 | "\tlp.act_tamper_clk_ctl\n" | |
623 | "\tlp.act_tamper_routing_ctl1\n" | |
624 | "\tlp.act_tamper_routing_ctl2\n" | |
625 | "\n" | |
626 | "ALL values should be in hexadecimal format"; | |
627 | ||
628 | #define NB_REGISTERS 18 | |
09140113 SG |
629 | static int do_snvs_cfg(struct cmd_tbl *cmdtp, int flag, int argc, |
630 | char *const argv[]) | |
242d1cd6 FL |
631 | { |
632 | int err = 0; | |
633 | u32 idx = 0; | |
634 | ||
635 | struct snvs_security_sc_conf conf = {0}; | |
636 | ||
637 | if (argc != (NB_REGISTERS + 1)) | |
638 | return CMD_RET_USAGE; | |
639 | ||
640 | conf.hp.lock = simple_strtoul(argv[++idx], NULL, 16); | |
641 | conf.hp.secvio_ctl = simple_strtoul(argv[++idx], NULL, 16); | |
642 | conf.lp.lock = simple_strtoul(argv[++idx], NULL, 16); | |
643 | conf.lp.secvio_ctl = simple_strtoul(argv[++idx], NULL, 16); | |
644 | conf.lp.tamper_filt_cfg = simple_strtoul(argv[++idx], NULL, 16); | |
645 | conf.lp.tamper_det_cfg = simple_strtoul(argv[++idx], NULL, 16); | |
646 | conf.lp.tamper_det_cfg2 = simple_strtoul(argv[++idx], NULL, 16); | |
647 | conf.lp.tamper_filt1_cfg = simple_strtoul(argv[++idx], NULL, 16); | |
648 | conf.lp.tamper_filt2_cfg = simple_strtoul(argv[++idx], NULL, 16); | |
649 | conf.lp.act_tamper1_cfg = simple_strtoul(argv[++idx], NULL, 16); | |
650 | conf.lp.act_tamper2_cfg = simple_strtoul(argv[++idx], NULL, 16); | |
651 | conf.lp.act_tamper3_cfg = simple_strtoul(argv[++idx], NULL, 16); | |
652 | conf.lp.act_tamper4_cfg = simple_strtoul(argv[++idx], NULL, 16); | |
653 | conf.lp.act_tamper5_cfg = simple_strtoul(argv[++idx], NULL, 16); | |
654 | conf.lp.act_tamper_ctl = simple_strtoul(argv[++idx], NULL, 16); | |
655 | conf.lp.act_tamper_clk_ctl = simple_strtoul(argv[++idx], NULL, 16); | |
656 | conf.lp.act_tamper_routing_ctl1 = simple_strtoul(argv[++idx], NULL, 16); | |
657 | conf.lp.act_tamper_routing_ctl2 = simple_strtoul(argv[++idx], NULL, 16); | |
658 | ||
659 | err = apply_snvs_config(&conf); | |
660 | ||
661 | return err; | |
662 | } | |
663 | ||
664 | U_BOOT_CMD(snvs_cfg, | |
665 | NB_REGISTERS + 1, 1, do_snvs_cfg, | |
666 | "Security violation configuration", | |
667 | snvs_cfg_help_text | |
668 | ); | |
669 | ||
670 | static char snvs_dgo_cfg_help_text[] = | |
671 | "snvs_dgo_cfg\n" | |
672 | "\ttamper_offset_ctl\n" | |
673 | "\ttamper_pull_ctl\n" | |
674 | "\ttamper_ana_test_ctl\n" | |
675 | "\ttamper_sensor_trim_ctl\n" | |
676 | "\ttamper_misc_ctl\n" | |
677 | "\ttamper_core_volt_mon_ctl\n" | |
678 | "\n" | |
679 | "ALL values should be in hexadecimal format"; | |
680 | ||
09140113 | 681 | static int do_snvs_dgo_cfg(struct cmd_tbl *cmdtp, int flag, int argc, |
242d1cd6 FL |
682 | char *const argv[]) |
683 | { | |
684 | int err = 0; | |
685 | u32 idx = 0; | |
686 | ||
687 | struct snvs_dgo_conf conf = {0}; | |
688 | ||
689 | if (argc != (6 + 1)) | |
690 | return CMD_RET_USAGE; | |
691 | ||
692 | conf.tamper_offset_ctl = simple_strtoul(argv[++idx], NULL, 16); | |
693 | conf.tamper_pull_ctl = simple_strtoul(argv[++idx], NULL, 16); | |
694 | conf.tamper_ana_test_ctl = simple_strtoul(argv[++idx], NULL, 16); | |
695 | conf.tamper_sensor_trim_ctl = simple_strtoul(argv[++idx], NULL, 16); | |
696 | conf.tamper_misc_ctl = simple_strtoul(argv[++idx], NULL, 16); | |
697 | conf.tamper_core_volt_mon_ctl = simple_strtoul(argv[++idx], NULL, 16); | |
698 | ||
699 | err = apply_snvs_dgo_config(&conf); | |
700 | ||
701 | return err; | |
702 | } | |
703 | ||
704 | U_BOOT_CMD(snvs_dgo_cfg, | |
705 | 7, 1, do_snvs_dgo_cfg, | |
706 | "SNVS DGO configuration", | |
707 | snvs_dgo_cfg_help_text | |
708 | ); | |
709 | ||
710 | static char tamper_pin_cfg_help_text[] = | |
711 | "snvs_dgo_cfg\n" | |
712 | "\tpad\n" | |
713 | "\tvalue\n" | |
714 | "\n" | |
715 | "ALL values should be in hexadecimal format"; | |
716 | ||
09140113 | 717 | static int do_tamper_pin_cfg(struct cmd_tbl *cmdtp, int flag, int argc, |
242d1cd6 FL |
718 | char *const argv[]) |
719 | { | |
720 | int err = 0; | |
721 | u32 idx = 0; | |
722 | ||
723 | struct tamper_pin_cfg conf = {0}; | |
724 | ||
725 | if (argc != (2 + 1)) | |
726 | return CMD_RET_USAGE; | |
727 | ||
728 | conf.pad = simple_strtoul(argv[++idx], NULL, 10); | |
729 | conf.mux_conf = simple_strtoul(argv[++idx], NULL, 16); | |
730 | ||
731 | err = apply_tamper_pin_list_config(&conf, 1); | |
732 | ||
733 | return err; | |
734 | } | |
735 | ||
736 | U_BOOT_CMD(tamper_pin_cfg, | |
737 | 3, 1, do_tamper_pin_cfg, | |
738 | "tamper pin configuration", | |
739 | tamper_pin_cfg_help_text | |
740 | ); | |
741 | ||
742 | static char snvs_clear_status_help_text[] = | |
743 | "snvs_clear_status\n" | |
744 | "\tHPSR\n" | |
745 | "\tHPSVSR\n" | |
746 | "\tLPSR\n" | |
747 | "\tLPTDSR\n" | |
748 | "\n" | |
749 | "Write the status registers with the value provided," | |
750 | " clearing the status"; | |
751 | ||
09140113 SG |
752 | static int do_snvs_clear_status(struct cmd_tbl *cmdtp, int flag, int argc, |
753 | char *const argv[]) | |
242d1cd6 FL |
754 | { |
755 | int scierr = 0; | |
756 | u32 idx = 0; | |
757 | ||
758 | struct snvs_security_sc_conf conf = {0}; | |
759 | ||
760 | if (argc != (2 + 1)) | |
761 | return CMD_RET_USAGE; | |
762 | ||
763 | conf.lp.status = simple_strtoul(argv[++idx], NULL, 16); | |
764 | conf.lp.tamper_det_status = simple_strtoul(argv[++idx], NULL, 16); | |
765 | ||
766 | scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.status), | |
767 | &conf.lp.status, NULL, NULL, NULL, | |
768 | NULL, 1); | |
769 | if (scierr != SC_ERR_NONE) | |
770 | goto exit; | |
771 | ||
772 | scierr = check_write_secvio_config(SC_CONF_OFFSET_OF(lp.tamper_det_status), | |
773 | &conf.lp.tamper_det_status, NULL, | |
774 | NULL, NULL, NULL, 1); | |
775 | if (scierr != SC_ERR_NONE) | |
776 | goto exit; | |
777 | ||
778 | exit: | |
779 | return (scierr == SC_ERR_NONE) ? 0 : 1; | |
780 | } | |
781 | ||
782 | U_BOOT_CMD(snvs_clear_status, | |
783 | 3, 1, do_snvs_clear_status, | |
784 | "snvs clear status", | |
785 | snvs_clear_status_help_text | |
786 | ); | |
787 | ||
788 | static char snvs_sec_status_help_text[] = | |
789 | "snvs_sec_status\n" | |
790 | "Display information about the security related to tamper and secvio"; | |
791 | ||
09140113 | 792 | static int do_snvs_sec_status(struct cmd_tbl *cmdtp, int flag, int argc, |
242d1cd6 FL |
793 | char *const argv[]) |
794 | { | |
795 | int scierr; | |
796 | u32 idx; | |
797 | ||
798 | u32 data[5]; | |
799 | ||
800 | u32 pads[] = { | |
801 | SC_P_CSI_D00, | |
802 | SC_P_CSI_D01, | |
803 | SC_P_CSI_D02, | |
804 | SC_P_CSI_D03, | |
805 | SC_P_CSI_D04, | |
806 | SC_P_CSI_D05, | |
807 | SC_P_CSI_D06, | |
808 | SC_P_CSI_D07, | |
809 | SC_P_CSI_HSYNC, | |
810 | SC_P_CSI_VSYNC, | |
811 | }; | |
812 | ||
813 | u32 fuses[] = { | |
814 | 14, | |
815 | 30, | |
816 | 31, | |
817 | 260, | |
818 | 261, | |
819 | 262, | |
820 | 263, | |
821 | 768, | |
822 | }; | |
823 | ||
824 | struct snvs_reg { | |
825 | u32 id; | |
826 | u32 nb; | |
827 | } snvs[] = { | |
828 | /* Locks */ | |
829 | {0x0, 1}, | |
830 | {0x34, 1}, | |
831 | /* Security violation */ | |
832 | {0xc, 1}, | |
833 | {0x10, 1}, | |
834 | {0x18, 1}, | |
835 | {0x40, 1}, | |
836 | /* Temper detectors */ | |
837 | {0x48, 2}, | |
838 | {0x4c, 1}, | |
839 | {0xa4, 1}, | |
840 | /* */ | |
841 | {0x44, 3}, | |
842 | {0xe0, 1}, | |
843 | {0xe4, 1}, | |
844 | {0xe8, 2}, | |
845 | /* Misc */ | |
846 | {0x3c, 1}, | |
847 | {0x5c, 2}, | |
848 | {0x64, 1}, | |
849 | {0xf8, 2}, | |
850 | }; | |
851 | ||
852 | u32 dgo[] = { | |
853 | 0x0, | |
854 | 0x10, | |
855 | 0x20, | |
856 | 0x30, | |
857 | 0x40, | |
858 | 0x50, | |
859 | }; | |
860 | ||
861 | /* Pins */ | |
862 | printf("Pins:\n"); | |
863 | for (idx = 0; idx < ARRAY_SIZE(pads); idx++) { | |
864 | u8 pad_id = pads[idx]; | |
865 | ||
866 | scierr = sc_pad_get(-1, pad_id, &data[0]); | |
867 | if (scierr == 0) | |
868 | printf("\t- Pin %d: %.8x\n", pad_id, data[0]); | |
869 | else | |
870 | printf("Failed to read Pin %d\n", pad_id); | |
871 | } | |
872 | ||
873 | /* Fuses */ | |
874 | printf("Fuses:\n"); | |
875 | for (idx = 0; idx < ARRAY_SIZE(fuses); idx++) { | |
876 | u32 fuse_id = fuses[idx]; | |
877 | ||
878 | scierr = sc_misc_otp_fuse_read(-1, fuse_id, &data[0]); | |
879 | if (scierr == 0) | |
880 | printf("\t- Fuse %d: %.8x\n", fuse_id, data[0]); | |
881 | else | |
882 | printf("Failed to read Fuse %d\n", fuse_id); | |
883 | } | |
884 | ||
885 | /* SNVS */ | |
886 | printf("SNVS:\n"); | |
887 | for (idx = 0; idx < ARRAY_SIZE(snvs); idx++) { | |
888 | struct snvs_reg *reg = &snvs[idx]; | |
889 | ||
890 | scierr = sc_seco_secvio_config(-1, reg->id, 0, &data[0], | |
891 | &data[1], &data[2], &data[3], | |
892 | &data[4], reg->nb); | |
893 | if (scierr == 0) { | |
894 | int subidx; | |
895 | ||
896 | printf("\t- SNVS %.2x(%d):", reg->id, reg->nb); | |
897 | for (subidx = 0; subidx < reg->nb; subidx++) | |
898 | printf(" %.8x", data[subidx]); | |
899 | printf("\n"); | |
900 | } else { | |
901 | printf("Failed to read SNVS %d\n", reg->id); | |
902 | } | |
903 | } | |
904 | ||
905 | /* DGO */ | |
906 | printf("DGO:\n"); | |
907 | for (idx = 0; idx < ARRAY_SIZE(dgo); idx++) { | |
908 | u8 dgo_id = dgo[idx]; | |
909 | ||
910 | scierr = sc_seco_secvio_dgo_config(-1, dgo_id, 0, &data[0]); | |
911 | if (scierr == 0) | |
912 | printf("\t- DGO %.2x: %.8x\n", dgo_id, data[0]); | |
913 | else | |
914 | printf("Failed to read DGO %d\n", dgo_id); | |
915 | } | |
916 | ||
917 | return 0; | |
918 | } | |
919 | ||
920 | U_BOOT_CMD(snvs_sec_status, | |
921 | 1, 1, do_snvs_sec_status, | |
922 | "tamper pin configuration", | |
923 | snvs_sec_status_help_text | |
924 | ); |