]>
Commit | Line | Data |
---|---|---|
c0791928 SG |
1 | # |
2 | # Copyright (c) 2012 The Chromium OS Authors. | |
3 | # | |
4 | # SPDX-License-Identifier: GPL-2.0+ | |
5 | # | |
6 | ||
7 | """Tests for the dtb_platdata module | |
8 | ||
9 | This includes unit tests for some functions and functional tests for | |
10 | """ | |
11 | ||
12 | import collections | |
13 | import os | |
14 | import struct | |
15 | import unittest | |
16 | ||
17 | import dtb_platdata | |
18 | from dtb_platdata import conv_name_to_c | |
19 | from dtb_platdata import get_compat_name | |
20 | from dtb_platdata import get_value | |
21 | from dtb_platdata import tab_to | |
22 | import fdt | |
23 | import fdt_util | |
24 | import tools | |
25 | ||
26 | our_path = os.path.dirname(os.path.realpath(__file__)) | |
27 | ||
28 | ||
29 | def get_dtb_file(dts_fname): | |
30 | """Compile a .dts file to a .dtb | |
31 | ||
32 | Args: | |
33 | dts_fname: Filename of .dts file in the current directory | |
34 | ||
35 | Returns: | |
36 | Filename of compiled file in output directory | |
37 | """ | |
38 | return fdt_util.EnsureCompiled(os.path.join(our_path, dts_fname)) | |
39 | ||
40 | ||
41 | class TestDtoc(unittest.TestCase): | |
42 | """Tests for dtoc""" | |
43 | @classmethod | |
44 | def setUpClass(cls): | |
45 | tools.PrepareOutputDir(None) | |
46 | ||
47 | @classmethod | |
48 | def tearDownClass(cls): | |
49 | tools._RemoveOutputDir() | |
50 | ||
51 | def test_name(self): | |
52 | """Test conversion of device tree names to C identifiers""" | |
53 | self.assertEqual('serial_at_0x12', conv_name_to_c('serial@0x12')) | |
54 | self.assertEqual('vendor_clock_frequency', | |
55 | conv_name_to_c('vendor,clock-frequency')) | |
56 | self.assertEqual('rockchip_rk3399_sdhci_5_1', | |
57 | conv_name_to_c('rockchip,rk3399-sdhci-5.1')) | |
58 | ||
59 | def test_tab_to(self): | |
60 | """Test operation of tab_to() function""" | |
61 | self.assertEqual('fred ', tab_to(0, 'fred')) | |
62 | self.assertEqual('fred\t', tab_to(1, 'fred')) | |
63 | self.assertEqual('fred was here ', tab_to(1, 'fred was here')) | |
64 | self.assertEqual('fred was here\t\t', tab_to(3, 'fred was here')) | |
65 | self.assertEqual('exactly8 ', tab_to(1, 'exactly8')) | |
66 | self.assertEqual('exactly8\t', tab_to(2, 'exactly8')) | |
67 | ||
68 | def test_get_value(self): | |
69 | """Test operation of get_value() function""" | |
70 | self.assertEqual('0x45', | |
71 | get_value(fdt.TYPE_INT, struct.pack('>I', 0x45))) | |
72 | self.assertEqual('0x45', | |
73 | get_value(fdt.TYPE_BYTE, struct.pack('<I', 0x45))) | |
74 | self.assertEqual('0x0', | |
75 | get_value(fdt.TYPE_BYTE, struct.pack('>I', 0x45))) | |
76 | self.assertEqual('"test"', get_value(fdt.TYPE_STRING, 'test')) | |
77 | self.assertEqual('true', get_value(fdt.TYPE_BOOL, None)) | |
78 | ||
79 | def test_get_compat_name(self): | |
80 | """Test operation of get_compat_name() function""" | |
81 | Prop = collections.namedtuple('Prop', ['value']) | |
82 | Node = collections.namedtuple('Node', ['props']) | |
83 | ||
84 | prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1']) | |
85 | node = Node({'compatible': prop}) | |
86 | self.assertEqual(('rockchip_rk3399_sdhci_5_1', ['arasan_sdhci_5_1']), | |
87 | get_compat_name(node)) | |
88 | ||
89 | prop = Prop(['rockchip,rk3399-sdhci-5.1']) | |
90 | node = Node({'compatible': prop}) | |
91 | self.assertEqual(('rockchip_rk3399_sdhci_5_1', []), | |
92 | get_compat_name(node)) | |
93 | ||
94 | prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1', 'third']) | |
95 | node = Node({'compatible': prop}) | |
96 | self.assertEqual(('rockchip_rk3399_sdhci_5_1', | |
97 | ['arasan_sdhci_5_1', 'third']), | |
98 | get_compat_name(node)) | |
99 | ||
100 | def test_empty_file(self): | |
101 | """Test output from a device tree file with no nodes""" | |
102 | dtb_file = get_dtb_file('dtoc_test_empty.dts') | |
103 | output = tools.GetOutputFilename('output') | |
104 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
105 | with open(output) as infile: | |
106 | lines = infile.read().splitlines() | |
107 | self.assertEqual(['#include <stdbool.h>', '#include <libfdt.h>'], lines) | |
108 | ||
109 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
110 | with open(output) as infile: | |
111 | lines = infile.read().splitlines() | |
112 | self.assertEqual(['#include <common.h>', '#include <dm.h>', | |
113 | '#include <dt-structs.h>', ''], lines) | |
114 | ||
115 | def test_simple(self): | |
116 | """Test output from some simple nodes with various types of data""" | |
117 | dtb_file = get_dtb_file('dtoc_test_simple.dts') | |
118 | output = tools.GetOutputFilename('output') | |
119 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
120 | with open(output) as infile: | |
121 | data = infile.read() | |
122 | self.assertEqual('''#include <stdbool.h> | |
123 | #include <libfdt.h> | |
5ec741fd SG |
124 | struct dtd_sandbox_i2c_test { |
125 | }; | |
126 | struct dtd_sandbox_pmic_test { | |
127 | \tbool\t\tlow_power; | |
128 | \tfdt64_t\t\treg[2]; | |
129 | }; | |
c0791928 SG |
130 | struct dtd_sandbox_spl_test { |
131 | \tbool\t\tboolval; | |
132 | \tunsigned char\tbytearray[3]; | |
133 | \tunsigned char\tbyteval; | |
134 | \tfdt32_t\t\tintarray[4]; | |
135 | \tfdt32_t\t\tintval; | |
136 | \tunsigned char\tlongbytearray[9]; | |
137 | \tconst char *\tstringarray[3]; | |
138 | \tconst char *\tstringval; | |
139 | }; | |
140 | struct dtd_sandbox_spl_test_2 { | |
141 | }; | |
142 | ''', data) | |
143 | ||
144 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
145 | with open(output) as infile: | |
146 | data = infile.read() | |
147 | self.assertEqual('''#include <common.h> | |
148 | #include <dm.h> | |
149 | #include <dt-structs.h> | |
150 | ||
151 | static struct dtd_sandbox_spl_test dtv_spl_test = { | |
152 | \t.bytearray\t\t= {0x6, 0x0, 0x0}, | |
153 | \t.byteval\t\t= 0x5, | |
154 | \t.intval\t\t\t= 0x1, | |
21d54ac3 SG |
155 | \t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, |
156 | \t\t0x11}, | |
c0791928 SG |
157 | \t.stringval\t\t= "message", |
158 | \t.boolval\t\t= true, | |
159 | \t.intarray\t\t= {0x2, 0x3, 0x4, 0x0}, | |
160 | \t.stringarray\t\t= {"multi-word", "message", ""}, | |
161 | }; | |
162 | U_BOOT_DEVICE(spl_test) = { | |
163 | \t.name\t\t= "sandbox_spl_test", | |
164 | \t.platdata\t= &dtv_spl_test, | |
165 | \t.platdata_size\t= sizeof(dtv_spl_test), | |
166 | }; | |
167 | ||
168 | static struct dtd_sandbox_spl_test dtv_spl_test2 = { | |
169 | \t.bytearray\t\t= {0x1, 0x23, 0x34}, | |
170 | \t.byteval\t\t= 0x8, | |
171 | \t.intval\t\t\t= 0x3, | |
21d54ac3 SG |
172 | \t.longbytearray\t\t= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
173 | \t\t0x0}, | |
c0791928 SG |
174 | \t.stringval\t\t= "message2", |
175 | \t.intarray\t\t= {0x5, 0x0, 0x0, 0x0}, | |
176 | \t.stringarray\t\t= {"another", "multi-word", "message"}, | |
177 | }; | |
178 | U_BOOT_DEVICE(spl_test2) = { | |
179 | \t.name\t\t= "sandbox_spl_test", | |
180 | \t.platdata\t= &dtv_spl_test2, | |
181 | \t.platdata_size\t= sizeof(dtv_spl_test2), | |
182 | }; | |
183 | ||
184 | static struct dtd_sandbox_spl_test dtv_spl_test3 = { | |
185 | \t.stringarray\t\t= {"one", "", ""}, | |
186 | }; | |
187 | U_BOOT_DEVICE(spl_test3) = { | |
188 | \t.name\t\t= "sandbox_spl_test", | |
189 | \t.platdata\t= &dtv_spl_test3, | |
190 | \t.platdata_size\t= sizeof(dtv_spl_test3), | |
191 | }; | |
192 | ||
193 | static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = { | |
194 | }; | |
195 | U_BOOT_DEVICE(spl_test4) = { | |
196 | \t.name\t\t= "sandbox_spl_test_2", | |
197 | \t.platdata\t= &dtv_spl_test4, | |
198 | \t.platdata_size\t= sizeof(dtv_spl_test4), | |
199 | }; | |
200 | ||
5ec741fd SG |
201 | static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = { |
202 | }; | |
203 | U_BOOT_DEVICE(i2c_at_0) = { | |
204 | \t.name\t\t= "sandbox_i2c_test", | |
205 | \t.platdata\t= &dtv_i2c_at_0, | |
206 | \t.platdata_size\t= sizeof(dtv_i2c_at_0), | |
207 | }; | |
208 | ||
209 | static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = { | |
210 | \t.low_power\t\t= true, | |
211 | \t.reg\t\t\t= {0x9, 0x0}, | |
212 | }; | |
213 | U_BOOT_DEVICE(pmic_at_9) = { | |
214 | \t.name\t\t= "sandbox_pmic_test", | |
215 | \t.platdata\t= &dtv_pmic_at_9, | |
216 | \t.platdata_size\t= sizeof(dtv_pmic_at_9), | |
217 | }; | |
218 | ||
c0791928 SG |
219 | ''', data) |
220 | ||
221 | def test_phandle(self): | |
222 | """Test output from a node containing a phandle reference""" | |
223 | dtb_file = get_dtb_file('dtoc_test_phandle.dts') | |
224 | output = tools.GetOutputFilename('output') | |
225 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
226 | with open(output) as infile: | |
227 | data = infile.read() | |
228 | self.assertEqual('''#include <stdbool.h> | |
229 | #include <libfdt.h> | |
230 | struct dtd_source { | |
0d15463c | 231 | \tstruct phandle_1_arg clocks[1]; |
c0791928 SG |
232 | }; |
233 | struct dtd_target { | |
234 | \tfdt32_t\t\tintval; | |
235 | }; | |
236 | ''', data) | |
237 | ||
238 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
239 | with open(output) as infile: | |
240 | data = infile.read() | |
241 | self.assertEqual('''#include <common.h> | |
242 | #include <dm.h> | |
243 | #include <dt-structs.h> | |
244 | ||
245 | static struct dtd_target dtv_phandle_target = { | |
246 | \t.intval\t\t\t= 0x1, | |
247 | }; | |
248 | U_BOOT_DEVICE(phandle_target) = { | |
249 | \t.name\t\t= "target", | |
250 | \t.platdata\t= &dtv_phandle_target, | |
251 | \t.platdata_size\t= sizeof(dtv_phandle_target), | |
252 | }; | |
253 | ||
254 | static struct dtd_source dtv_phandle_source = { | |
255 | \t.clocks\t\t\t= {{&dtv_phandle_target, 1}}, | |
256 | }; | |
257 | U_BOOT_DEVICE(phandle_source) = { | |
258 | \t.name\t\t= "source", | |
259 | \t.platdata\t= &dtv_phandle_source, | |
260 | \t.platdata_size\t= sizeof(dtv_phandle_source), | |
261 | }; | |
262 | ||
263 | ''', data) | |
264 | ||
265 | def test_aliases(self): | |
266 | """Test output from a node with multiple compatible strings""" | |
267 | dtb_file = get_dtb_file('dtoc_test_aliases.dts') | |
268 | output = tools.GetOutputFilename('output') | |
269 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
270 | with open(output) as infile: | |
271 | data = infile.read() | |
272 | self.assertEqual('''#include <stdbool.h> | |
273 | #include <libfdt.h> | |
274 | struct dtd_compat1 { | |
275 | \tfdt32_t\t\tintval; | |
276 | }; | |
277 | #define dtd_compat2_1_fred dtd_compat1 | |
278 | #define dtd_compat3 dtd_compat1 | |
279 | ''', data) | |
280 | ||
281 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
282 | with open(output) as infile: | |
283 | data = infile.read() | |
284 | self.assertEqual('''#include <common.h> | |
285 | #include <dm.h> | |
286 | #include <dt-structs.h> | |
287 | ||
288 | static struct dtd_compat1 dtv_spl_test = { | |
289 | \t.intval\t\t\t= 0x1, | |
290 | }; | |
291 | U_BOOT_DEVICE(spl_test) = { | |
292 | \t.name\t\t= "compat1", | |
293 | \t.platdata\t= &dtv_spl_test, | |
294 | \t.platdata_size\t= sizeof(dtv_spl_test), | |
295 | }; | |
296 | ||
c20ee0ed SG |
297 | ''', data) |
298 | ||
299 | def test_addresses64(self): | |
300 | """Test output from a node with a 'reg' property with na=2, ns=2""" | |
301 | dtb_file = get_dtb_file('dtoc_test_addr64.dts') | |
302 | output = tools.GetOutputFilename('output') | |
303 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
304 | with open(output) as infile: | |
305 | data = infile.read() | |
306 | self.assertEqual('''#include <stdbool.h> | |
307 | #include <libfdt.h> | |
308 | struct dtd_test1 { | |
309 | \tfdt64_t\t\treg[2]; | |
310 | }; | |
311 | struct dtd_test2 { | |
312 | \tfdt64_t\t\treg[2]; | |
313 | }; | |
314 | struct dtd_test3 { | |
315 | \tfdt64_t\t\treg[4]; | |
316 | }; | |
317 | ''', data) | |
318 | ||
319 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
320 | with open(output) as infile: | |
321 | data = infile.read() | |
322 | self.assertEqual('''#include <common.h> | |
323 | #include <dm.h> | |
324 | #include <dt-structs.h> | |
325 | ||
326 | static struct dtd_test1 dtv_test1 = { | |
327 | \t.reg\t\t\t= {0x1234, 0x5678}, | |
328 | }; | |
329 | U_BOOT_DEVICE(test1) = { | |
330 | \t.name\t\t= "test1", | |
331 | \t.platdata\t= &dtv_test1, | |
332 | \t.platdata_size\t= sizeof(dtv_test1), | |
333 | }; | |
334 | ||
335 | static struct dtd_test2 dtv_test2 = { | |
336 | \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654}, | |
337 | }; | |
338 | U_BOOT_DEVICE(test2) = { | |
339 | \t.name\t\t= "test2", | |
340 | \t.platdata\t= &dtv_test2, | |
341 | \t.platdata_size\t= sizeof(dtv_test2), | |
342 | }; | |
343 | ||
344 | static struct dtd_test3 dtv_test3 = { | |
345 | \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3}, | |
346 | }; | |
347 | U_BOOT_DEVICE(test3) = { | |
348 | \t.name\t\t= "test3", | |
349 | \t.platdata\t= &dtv_test3, | |
350 | \t.platdata_size\t= sizeof(dtv_test3), | |
351 | }; | |
352 | ||
353 | ''', data) | |
354 | ||
355 | def test_addresses32(self): | |
356 | """Test output from a node with a 'reg' property with na=1, ns=1""" | |
357 | dtb_file = get_dtb_file('dtoc_test_addr32.dts') | |
358 | output = tools.GetOutputFilename('output') | |
359 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
360 | with open(output) as infile: | |
361 | data = infile.read() | |
362 | self.assertEqual('''#include <stdbool.h> | |
363 | #include <libfdt.h> | |
364 | struct dtd_test1 { | |
365 | \tfdt32_t\t\treg[2]; | |
366 | }; | |
367 | struct dtd_test2 { | |
368 | \tfdt32_t\t\treg[4]; | |
369 | }; | |
370 | ''', data) | |
371 | ||
372 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
373 | with open(output) as infile: | |
374 | data = infile.read() | |
375 | self.assertEqual('''#include <common.h> | |
376 | #include <dm.h> | |
377 | #include <dt-structs.h> | |
378 | ||
379 | static struct dtd_test1 dtv_test1 = { | |
380 | \t.reg\t\t\t= {0x1234, 0x5678}, | |
381 | }; | |
382 | U_BOOT_DEVICE(test1) = { | |
383 | \t.name\t\t= "test1", | |
384 | \t.platdata\t= &dtv_test1, | |
385 | \t.platdata_size\t= sizeof(dtv_test1), | |
386 | }; | |
387 | ||
388 | static struct dtd_test2 dtv_test2 = { | |
389 | \t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3}, | |
390 | }; | |
391 | U_BOOT_DEVICE(test2) = { | |
392 | \t.name\t\t= "test2", | |
393 | \t.platdata\t= &dtv_test2, | |
394 | \t.platdata_size\t= sizeof(dtv_test2), | |
395 | }; | |
396 | ||
397 | ''', data) | |
398 | ||
399 | def test_addresses64_32(self): | |
400 | """Test output from a node with a 'reg' property with na=2, ns=1""" | |
401 | dtb_file = get_dtb_file('dtoc_test_addr64_32.dts') | |
402 | output = tools.GetOutputFilename('output') | |
403 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
404 | with open(output) as infile: | |
405 | data = infile.read() | |
406 | self.assertEqual('''#include <stdbool.h> | |
407 | #include <libfdt.h> | |
408 | struct dtd_test1 { | |
409 | \tfdt64_t\t\treg[2]; | |
410 | }; | |
411 | struct dtd_test2 { | |
412 | \tfdt64_t\t\treg[2]; | |
413 | }; | |
414 | struct dtd_test3 { | |
415 | \tfdt64_t\t\treg[4]; | |
416 | }; | |
417 | ''', data) | |
418 | ||
419 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
420 | with open(output) as infile: | |
421 | data = infile.read() | |
422 | self.assertEqual('''#include <common.h> | |
423 | #include <dm.h> | |
424 | #include <dt-structs.h> | |
425 | ||
426 | static struct dtd_test1 dtv_test1 = { | |
427 | \t.reg\t\t\t= {0x123400000000, 0x5678}, | |
428 | }; | |
429 | U_BOOT_DEVICE(test1) = { | |
430 | \t.name\t\t= "test1", | |
431 | \t.platdata\t= &dtv_test1, | |
432 | \t.platdata_size\t= sizeof(dtv_test1), | |
433 | }; | |
434 | ||
435 | static struct dtd_test2 dtv_test2 = { | |
436 | \t.reg\t\t\t= {0x1234567890123456, 0x98765432}, | |
437 | }; | |
438 | U_BOOT_DEVICE(test2) = { | |
439 | \t.name\t\t= "test2", | |
440 | \t.platdata\t= &dtv_test2, | |
441 | \t.platdata_size\t= sizeof(dtv_test2), | |
442 | }; | |
443 | ||
444 | static struct dtd_test3 dtv_test3 = { | |
445 | \t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3}, | |
446 | }; | |
447 | U_BOOT_DEVICE(test3) = { | |
448 | \t.name\t\t= "test3", | |
449 | \t.platdata\t= &dtv_test3, | |
450 | \t.platdata_size\t= sizeof(dtv_test3), | |
451 | }; | |
452 | ||
453 | ''', data) | |
454 | ||
455 | def test_addresses32_64(self): | |
456 | """Test output from a node with a 'reg' property with na=1, ns=2""" | |
457 | dtb_file = get_dtb_file('dtoc_test_addr32_64.dts') | |
458 | output = tools.GetOutputFilename('output') | |
459 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
460 | with open(output) as infile: | |
461 | data = infile.read() | |
462 | self.assertEqual('''#include <stdbool.h> | |
463 | #include <libfdt.h> | |
464 | struct dtd_test1 { | |
465 | \tfdt64_t\t\treg[2]; | |
466 | }; | |
467 | struct dtd_test2 { | |
468 | \tfdt64_t\t\treg[2]; | |
469 | }; | |
470 | struct dtd_test3 { | |
471 | \tfdt64_t\t\treg[4]; | |
472 | }; | |
473 | ''', data) | |
474 | ||
475 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
476 | with open(output) as infile: | |
477 | data = infile.read() | |
478 | self.assertEqual('''#include <common.h> | |
479 | #include <dm.h> | |
480 | #include <dt-structs.h> | |
481 | ||
482 | static struct dtd_test1 dtv_test1 = { | |
483 | \t.reg\t\t\t= {0x1234, 0x567800000000}, | |
484 | }; | |
485 | U_BOOT_DEVICE(test1) = { | |
486 | \t.name\t\t= "test1", | |
487 | \t.platdata\t= &dtv_test1, | |
488 | \t.platdata_size\t= sizeof(dtv_test1), | |
489 | }; | |
490 | ||
491 | static struct dtd_test2 dtv_test2 = { | |
492 | \t.reg\t\t\t= {0x12345678, 0x9876543210987654}, | |
493 | }; | |
494 | U_BOOT_DEVICE(test2) = { | |
495 | \t.name\t\t= "test2", | |
496 | \t.platdata\t= &dtv_test2, | |
497 | \t.platdata_size\t= sizeof(dtv_test2), | |
498 | }; | |
499 | ||
500 | static struct dtd_test3 dtv_test3 = { | |
501 | \t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3}, | |
502 | }; | |
503 | U_BOOT_DEVICE(test3) = { | |
504 | \t.name\t\t= "test3", | |
505 | \t.platdata\t= &dtv_test3, | |
506 | \t.platdata_size\t= sizeof(dtv_test3), | |
507 | }; | |
508 | ||
c0791928 | 509 | ''', data) |