1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2022, Linaro Limited
4 *
5 * Tests introduce dummy test drivers and assiciated devices defined in
6 * dt_driver_test.dtsi file with device resource dependencies.
7 */
8
9 #include <assert.h>
10 #include <config.h>
11 #include <crypto/crypto.h>
12 #include <drivers/clk.h>
13 #include <drivers/clk_dt.h>
14 #include <drivers/rstctrl.h>
15 #include <initcall.h>
16 #include <kernel/dt.h>
17 #include <kernel/dt_driver.h>
18 #include <libfdt.h>
19 #include <malloc.h>
20 #include <sys/queue.h>
21 #include <tee_api_defines_extensions.h>
22 #include <tee_api_types.h>
23
24 #define DT_TEST_MSG(...) FMSG("(dt-driver-test) " __VA_ARGS__)
25
26 /* Test state IDs */
27 enum dt_test_sid { DEFAULT = 0, IN_PROGRESS, SUCCESS, FAILED };
28
29 /*
30 * DT tests state to be reported from PTA_INVOKE_TESTS_CMD_DT_TEST_STATUS
31 * possibly printed to console. A test can be skipped (DEFAULT) or be
32 * successful (SUCCESS) orthewise it has failed (IN_PROGRESS, FAILED).
33 */
34 struct dt_test_state {
35 enum dt_test_sid probe_deferral;
36 enum dt_test_sid probe_clocks;
37 enum dt_test_sid probe_resets;
38 enum dt_test_sid crypto_dependencies;
39 };
40
41 /*
42 * References allocated from heap to be free once test completed
43 * dt_test_alloc(), dt_test_free(), dt_test_free_all()
44 */
45 struct dt_test_free_ref {
46 void *p;
47 SLIST_ENTRY(dt_test_free_ref) link;
48 };
49
50 static struct dt_test_state dt_test_state;
51
52 static const char __maybe_unused * const dt_test_str_sid[] = {
53 [DEFAULT] = "not passed",
54 [IN_PROGRESS] = "in-progress",
55 [SUCCESS] = "successful",
56 [FAILED] = "failed",
57 };
58
59 /* Reference allocations during test for release_init_resource initcall level */
60 static SLIST_HEAD(dt_test_free_refs, dt_test_free_ref) dt_test_free_list =
61 SLIST_HEAD_INITIALIZER(dt_test_free_list);
62
dt_test_alloc(size_t size)63 static void __maybe_unused *dt_test_alloc(size_t size)
64 {
65 struct dt_test_free_ref *ref = NULL;
66
67 ref = calloc(1, sizeof(*ref) + size);
68 if (!ref)
69 return NULL;
70
71 ref->p = ref + 1;
72 SLIST_INSERT_HEAD(&dt_test_free_list, ref, link);
73
74 return ref->p;
75 }
76
dt_test_free(void * p)77 static void __maybe_unused dt_test_free(void *p)
78 {
79 struct dt_test_free_ref *ref = NULL;
80 struct dt_test_free_ref *t_ref = NULL;
81
82 if (!p)
83 return;
84
85 SLIST_FOREACH_SAFE(ref, &dt_test_free_list, link, t_ref) {
86 if (ref->p == p) {
87 SLIST_REMOVE(&dt_test_free_list, ref,
88 dt_test_free_ref, link);
89 free(ref);
90 return;
91 }
92 }
93
94 panic();
95 }
96
dt_test_free_all(void)97 static void dt_test_free_all(void)
98 {
99 while (!SLIST_EMPTY(&dt_test_free_list)) {
100 struct dt_test_free_ref *ref = SLIST_FIRST(&dt_test_free_list);
101
102 SLIST_REMOVE(&dt_test_free_list, ref, dt_test_free_ref, link);
103 free(ref);
104 }
105 }
106
dt_test_release(void)107 static TEE_Result dt_test_release(void)
108 {
109 dt_test_free_all();
110
111 DT_TEST_MSG("Probe deferral: %s",
112 dt_test_str_sid[dt_test_state.probe_deferral]);
113 DT_TEST_MSG("Clocks probe: %s",
114 dt_test_str_sid[dt_test_state.probe_clocks]);
115 DT_TEST_MSG("Reset ctrl probe: %s",
116 dt_test_str_sid[dt_test_state.probe_resets]);
117 DT_TEST_MSG("Crypto deps.: %s",
118 dt_test_str_sid[dt_test_state.crypto_dependencies]);
119
120 return dt_driver_test_status();
121 }
122
123 release_init_resource(dt_test_release);
124
dt_driver_test_status(void)125 TEE_Result dt_driver_test_status(void)
126 {
127 TEE_Result res = TEE_SUCCESS;
128
129 if (dt_test_state.probe_deferral != SUCCESS) {
130 EMSG("Probe deferral test failed");
131 res = TEE_ERROR_GENERIC;
132 }
133 if (IS_ENABLED(CFG_DRIVERS_CLK) &&
134 dt_test_state.probe_clocks != SUCCESS) {
135 EMSG("Clocks probing test failed");
136 res = TEE_ERROR_GENERIC;
137 }
138 if (IS_ENABLED(CFG_DRIVERS_RSTCTRL) &&
139 dt_test_state.probe_resets != SUCCESS) {
140 EMSG("Reset controllers probing test failed");
141 res = TEE_ERROR_GENERIC;
142 }
143 if (dt_test_state.crypto_dependencies != SUCCESS) {
144 EMSG("Probe deferral on crypto dependencies test failed");
145 res = TEE_ERROR_GENERIC;
146 }
147
148 return res;
149 }
150
151 /*
152 * Consumer test driver: instance probed from the compatible
153 * node parsed in the DT. It consumes emulated resource obtained
154 * from DT references. Probe shall succeed only once all resources
155 * are found.
156 */
dt_test_consumer_probe(const void * fdt,int node,const void * compat_data __unused)157 static TEE_Result dt_test_consumer_probe(const void *fdt, int node,
158 const void *compat_data __unused)
159 {
160 TEE_Result res = TEE_ERROR_GENERIC;
161
162 if (IS_ENABLED(CFG_DRIVERS_CLK)) {
163 struct clk *clk0 = NULL;
164 struct clk *clk1 = NULL;
165 struct clk *clk = NULL;
166
167 DT_TEST_MSG("Probe clocks");
168
169 res = clk_dt_get_by_index(fdt, node, 0, &clk0);
170 if (res)
171 goto err_probe;
172 res = clk_dt_get_by_index(fdt, node, 1, &clk1);
173 if (res)
174 goto err_probe;
175
176 DT_TEST_MSG("Check valid clock references");
177
178 if (clk_enable(clk0)) {
179 DT_TEST_MSG("Can't enable %s", clk_get_name(clk0));
180 return TEE_ERROR_GENERIC;
181 }
182 clk_disable(clk0);
183
184 res = clk_dt_get_by_name(fdt, node, "clk0", &clk);
185 if (res || clk != clk0) {
186 DT_TEST_MSG("Unexpected clock reference");
187 return TEE_ERROR_GENERIC;
188 }
189
190 res = clk_dt_get_by_name(fdt, node, "clk1", &clk);
191 if (res || clk != clk1) {
192 DT_TEST_MSG("Unexpected clock reference");
193 return TEE_ERROR_GENERIC;
194 }
195
196 DT_TEST_MSG("Bad clock reference");
197
198 res = clk_dt_get_by_index(fdt, node, 3, &clk);
199 if (!res) {
200 DT_TEST_MSG("Unexpected clock found on invalid index");
201 return TEE_ERROR_GENERIC;
202 }
203
204 res = clk_dt_get_by_name(fdt, node, "clk2", &clk);
205 if (!res) {
206 DT_TEST_MSG("Unexpected clock found on invalid name");
207 return TEE_ERROR_GENERIC;
208 }
209
210 dt_test_state.probe_clocks = SUCCESS;
211 }
212
213 if (IS_ENABLED(CFG_DRIVERS_RSTCTRL)) {
214 struct rstctrl *rstctrl0 = NULL;
215 struct rstctrl *rstctrl1 = NULL;
216 struct rstctrl *rstctrl = NULL;
217
218 DT_TEST_MSG("Probe reset controllers");
219
220 res = rstctrl_dt_get_by_index(fdt, node, 0, &rstctrl0);
221 if (res)
222 goto err_probe;
223
224 DT_TEST_MSG("Check valid reset controller");
225
226 if (rstctrl_assert(rstctrl0)) {
227 EMSG("Can't assert rstctrl %s", rstctrl_name(rstctrl0));
228 return TEE_ERROR_GENERIC;
229 }
230
231 res = rstctrl_dt_get_by_name(fdt, node, "rst0", &rstctrl);
232 if (res)
233 return res;
234
235 if (rstctrl != rstctrl0) {
236 EMSG("Unexpected reset controller reference");
237 return TEE_ERROR_GENERIC;
238 }
239
240 res = rstctrl_dt_get_by_name(fdt, node, "rst1", &rstctrl1);
241 if (res)
242 goto err_probe;
243
244 if (!rstctrl1 || rstctrl1 == rstctrl0) {
245 EMSG("Unexpected reset controller reference");
246 return TEE_ERROR_GENERIC;
247 }
248
249 dt_test_state.probe_resets = SUCCESS;
250 }
251
252 if (dt_test_state.probe_deferral != IN_PROGRESS) {
253 dt_test_state.probe_deferral = FAILED;
254 return TEE_ERROR_GENERIC;
255 }
256
257 dt_test_state.probe_deferral = SUCCESS;
258
259 return TEE_SUCCESS;
260
261 err_probe:
262 assert(res);
263
264 if (res == TEE_ERROR_DEFER_DRIVER_INIT &&
265 dt_test_state.probe_deferral == DEFAULT) {
266 /* We expect at least a probe deferral */
267 dt_test_state.probe_deferral = IN_PROGRESS;
268 }
269
270 return res;
271 }
272
273 static const struct dt_device_match dt_test_consumer_match_table[] = {
274 { .compatible = "linaro,dt-test-consumer", },
275 { }
276 };
277
278 DEFINE_DT_DRIVER(dt_test_consumer_driver) = {
279 .name = "dt-test-consumer",
280 .match_table = dt_test_consumer_match_table,
281 .probe = dt_test_consumer_probe,
282 };
283
dt_test_crypt_consumer_probe(const void * fdt __unused,int node __unused,const void * compat_data __unused)284 static TEE_Result dt_test_crypt_consumer_probe(const void *fdt __unused,
285 int node __unused,
286 const void *compat_data __unused)
287 {
288 TEE_Result res = dt_driver_get_crypto();
289 uint8_t __maybe_unused byte = 0;
290
291 if (res == TEE_ERROR_DEFER_DRIVER_INIT &&
292 dt_test_state.crypto_dependencies == DEFAULT) {
293 /* We expect to be deferred */
294 dt_test_state.crypto_dependencies = IN_PROGRESS;
295 }
296
297 if (res)
298 return res;
299
300 if (dt_test_state.crypto_dependencies == DEFAULT) {
301 EMSG("Test expects at least a driver probe deferral");
302 dt_test_state.crypto_dependencies = FAILED;
303 return TEE_ERROR_GENERIC;
304 }
305
306 if (crypto_rng_read(&byte, sizeof(byte))) {
307 dt_test_state.crypto_dependencies = FAILED;
308 return TEE_ERROR_GENERIC;
309 }
310
311 dt_test_state.crypto_dependencies = SUCCESS;
312 return TEE_SUCCESS;
313 }
314
315 static const struct dt_device_match dt_test_crypt_consumer_match_table[] = {
316 { .compatible = "linaro,dt-test-crypt-consumer", },
317 { }
318 };
319
320 DEFINE_DT_DRIVER(dt_test_consumer_driver) = {
321 .name = "dt-test-crypt-consumer",
322 .match_table = dt_test_crypt_consumer_match_table,
323 .probe = dt_test_crypt_consumer_probe,
324 };
325
326 #ifdef CFG_DRIVERS_CLK
327 #define DT_TEST_CLK_COUNT 2
328
329 #define DT_TEST_CLK0_BINDING_ID 3
330 #define DT_TEST_CLK1_BINDING_ID 7
331
332 static const char *dt_test_clk_name[DT_TEST_CLK_COUNT] = {
333 "dt_test-clk3",
334 "dt_test-clk7",
335 };
336
337 /* Emulating a clock does not require operators */
338 static const struct clk_ops dt_test_clock_provider_ops;
339
dt_test_get_clk(struct dt_driver_phandle_args * args,void * data,TEE_Result * res)340 static struct clk *dt_test_get_clk(struct dt_driver_phandle_args *args,
341 void *data, TEE_Result *res)
342 {
343 struct clk *clk_ref = data;
344 struct clk *clk = NULL;
345
346 if (args->args_count != 1) {
347 *res = TEE_ERROR_BAD_PARAMETERS;
348 return NULL;
349 }
350
351 switch (args->args[0]) {
352 case DT_TEST_CLK0_BINDING_ID:
353 clk = clk_ref;
354 break;
355 case DT_TEST_CLK1_BINDING_ID:
356 clk = clk_ref + 1;
357 break;
358 default:
359 EMSG("Unexpected binding ID %"PRIu32, args->args[0]);
360 *res = TEE_ERROR_BAD_PARAMETERS;
361 return NULL;
362 }
363
364 DT_TEST_MSG("Providing clock %s", clk_get_name(clk));
365
366 *res = TEE_SUCCESS;
367 return clk;
368 }
369
dt_test_clock_provider_probe(const void * fdt,int node,const void * compat_data __unused)370 static TEE_Result dt_test_clock_provider_probe(const void *fdt, int node,
371 const void *compat_data __unused)
372 {
373 TEE_Result res = TEE_ERROR_GENERIC;
374 struct clk *clk = NULL;
375 size_t n = 0;
376
377 DT_TEST_MSG("Register clocks");
378
379 clk = dt_test_alloc(DT_TEST_CLK_COUNT * sizeof(*clk));
380 if (!clk)
381 return TEE_ERROR_OUT_OF_MEMORY;
382
383 for (n = 0; n < DT_TEST_CLK_COUNT; n++) {
384 clk[n].ops = &dt_test_clock_provider_ops;
385 clk[n].name = dt_test_clk_name[n];
386
387 res = clk_register(clk + n);
388 if (res)
389 goto err;
390 }
391
392 res = clk_dt_register_clk_provider(fdt, node, dt_test_get_clk, clk);
393 if (res)
394 goto err;
395
396 return TEE_SUCCESS;
397
398 err:
399 dt_test_free(clk);
400 return res;
401 }
402
403 CLK_DT_DECLARE(dt_test_clock_provider, "linaro,dt-test-provider",
404 dt_test_clock_provider_probe);
405 #endif /* CFG_DRIVERS_CLK */
406
407 #ifdef CFG_DRIVERS_RSTCTRL
408 #define DT_TEST_RSTCTRL_COUNT 2
409
410 #define DT_TEST_RSTCTRL0_BINDING_ID 5
411 #define DT_TEST_RSTCTRL1_BINDING_ID 35
412
413 struct dt_test_rstctrl {
414 unsigned int dt_binding;
415 struct rstctrl rstctrl;
416 };
417
to_test_rstctrl(struct rstctrl * rstctrl)418 static struct dt_test_rstctrl *to_test_rstctrl(struct rstctrl *rstctrl)
419 {
420 return container_of(rstctrl, struct dt_test_rstctrl, rstctrl);
421 }
422
dt_test_rstctrl_stub(struct rstctrl * rstctrl __maybe_unused,unsigned int to_us __unused)423 static TEE_Result dt_test_rstctrl_stub(struct rstctrl *rstctrl __maybe_unused,
424 unsigned int to_us __unused)
425 {
426 struct dt_test_rstctrl *dev = to_test_rstctrl(rstctrl);
427
428 switch (dev->dt_binding) {
429 case DT_TEST_RSTCTRL0_BINDING_ID:
430 case DT_TEST_RSTCTRL1_BINDING_ID:
431 return TEE_SUCCESS;
432 default:
433 EMSG("Unexpected rstctrl reference");
434 return TEE_ERROR_GENERIC;
435 }
436 }
437
dt_test_rstctrl_name(struct rstctrl * rstctrl __maybe_unused)438 static const char *dt_test_rstctrl_name(struct rstctrl *rstctrl __maybe_unused)
439 {
440 static const char *rstctrl_name[DT_TEST_RSTCTRL_COUNT] = {
441 "dt_test-rstctrl5",
442 "dt_test-rstctrl35",
443 };
444 struct dt_test_rstctrl *dev = to_test_rstctrl(rstctrl);
445
446 switch (dev->dt_binding) {
447 case DT_TEST_RSTCTRL0_BINDING_ID:
448 return rstctrl_name[0];
449 case DT_TEST_RSTCTRL1_BINDING_ID:
450 return rstctrl_name[1];
451 default:
452 EMSG("Unexpected rstctrl reference");
453 return NULL;
454 }
455 }
456
457 const struct rstctrl_ops dt_test_rstctrl_ops = {
458 .assert_level = dt_test_rstctrl_stub,
459 .deassert_level = dt_test_rstctrl_stub,
460 .get_name = dt_test_rstctrl_name,
461 };
462
dt_test_get_rstctrl(struct dt_driver_phandle_args * args,void * data,TEE_Result * res)463 static struct rstctrl *dt_test_get_rstctrl(struct dt_driver_phandle_args *args,
464 void *data, TEE_Result *res)
465 {
466 struct dt_test_rstctrl *ref = data;
467 struct rstctrl *rstctrl = NULL;
468
469 if (args->args_count != 1) {
470 *res = TEE_ERROR_BAD_PARAMETERS;
471 return NULL;
472 }
473
474 switch (args->args[0]) {
475 case DT_TEST_RSTCTRL0_BINDING_ID:
476 rstctrl = &ref[0].rstctrl;
477 break;
478 case DT_TEST_RSTCTRL1_BINDING_ID:
479 rstctrl = &ref[1].rstctrl;
480 break;
481 default:
482 EMSG("Unexpected binding ID %"PRIu32, args->args[0]);
483 *res = TEE_ERROR_BAD_PARAMETERS;
484 return NULL;
485 }
486
487 DT_TEST_MSG("Providing reset controller %s", rstctrl_name(rstctrl));
488
489 *res = TEE_SUCCESS;
490 return rstctrl;
491 }
492
dt_test_rstctrl_provider_probe(const void * fdt,int offs,const void * data __unused)493 static TEE_Result dt_test_rstctrl_provider_probe(const void *fdt, int offs,
494 const void *data __unused)
495 {
496 TEE_Result res = TEE_ERROR_GENERIC;
497 struct dt_test_rstctrl *devices = NULL;
498
499 DT_TEST_MSG("Register reset controllers");
500
501 assert(rstctrl_ops_is_valid(&dt_test_rstctrl_ops));
502
503 devices = dt_test_alloc(DT_TEST_RSTCTRL_COUNT * sizeof(*devices));
504 if (!devices)
505 return TEE_ERROR_OUT_OF_MEMORY;
506
507 devices[0].rstctrl.ops = &dt_test_rstctrl_ops;
508 devices[0].dt_binding = DT_TEST_RSTCTRL0_BINDING_ID;
509
510 devices[1].rstctrl.ops = &dt_test_rstctrl_ops;
511 devices[1].dt_binding = DT_TEST_RSTCTRL1_BINDING_ID;
512
513 res = rstctrl_register_provider(fdt, offs, dt_test_get_rstctrl,
514 devices);
515 if (res) {
516 dt_test_free(devices);
517 return res;
518 }
519
520 return TEE_SUCCESS;
521 }
522
523 RSTCTRL_DT_DECLARE(dt_test_rstctrl_provider, "linaro,dt-test-provider",
524 dt_test_rstctrl_provider_probe);
525 #endif /* CFG_DRIVERS_RSTCTRL */
526