]>
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 = { | |
35d50370 | 255 | \t.clocks\t\t\t= { |
bc79617f | 256 | \t\t{&dtv_phandle_target, {1}},}, |
c0791928 SG |
257 | }; |
258 | U_BOOT_DEVICE(phandle_source) = { | |
259 | \t.name\t\t= "source", | |
260 | \t.platdata\t= &dtv_phandle_source, | |
261 | \t.platdata_size\t= sizeof(dtv_phandle_source), | |
262 | }; | |
263 | ||
264 | ''', data) | |
265 | ||
266 | def test_aliases(self): | |
267 | """Test output from a node with multiple compatible strings""" | |
268 | dtb_file = get_dtb_file('dtoc_test_aliases.dts') | |
269 | output = tools.GetOutputFilename('output') | |
270 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
271 | with open(output) as infile: | |
272 | data = infile.read() | |
273 | self.assertEqual('''#include <stdbool.h> | |
274 | #include <libfdt.h> | |
275 | struct dtd_compat1 { | |
276 | \tfdt32_t\t\tintval; | |
277 | }; | |
278 | #define dtd_compat2_1_fred dtd_compat1 | |
279 | #define dtd_compat3 dtd_compat1 | |
280 | ''', data) | |
281 | ||
282 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
283 | with open(output) as infile: | |
284 | data = infile.read() | |
285 | self.assertEqual('''#include <common.h> | |
286 | #include <dm.h> | |
287 | #include <dt-structs.h> | |
288 | ||
289 | static struct dtd_compat1 dtv_spl_test = { | |
290 | \t.intval\t\t\t= 0x1, | |
291 | }; | |
292 | U_BOOT_DEVICE(spl_test) = { | |
293 | \t.name\t\t= "compat1", | |
294 | \t.platdata\t= &dtv_spl_test, | |
295 | \t.platdata_size\t= sizeof(dtv_spl_test), | |
296 | }; | |
297 | ||
c20ee0ed SG |
298 | ''', data) |
299 | ||
300 | def test_addresses64(self): | |
301 | """Test output from a node with a 'reg' property with na=2, ns=2""" | |
302 | dtb_file = get_dtb_file('dtoc_test_addr64.dts') | |
303 | output = tools.GetOutputFilename('output') | |
304 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
305 | with open(output) as infile: | |
306 | data = infile.read() | |
307 | self.assertEqual('''#include <stdbool.h> | |
308 | #include <libfdt.h> | |
309 | struct dtd_test1 { | |
310 | \tfdt64_t\t\treg[2]; | |
311 | }; | |
312 | struct dtd_test2 { | |
313 | \tfdt64_t\t\treg[2]; | |
314 | }; | |
315 | struct dtd_test3 { | |
316 | \tfdt64_t\t\treg[4]; | |
317 | }; | |
318 | ''', data) | |
319 | ||
320 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
321 | with open(output) as infile: | |
322 | data = infile.read() | |
323 | self.assertEqual('''#include <common.h> | |
324 | #include <dm.h> | |
325 | #include <dt-structs.h> | |
326 | ||
327 | static struct dtd_test1 dtv_test1 = { | |
328 | \t.reg\t\t\t= {0x1234, 0x5678}, | |
329 | }; | |
330 | U_BOOT_DEVICE(test1) = { | |
331 | \t.name\t\t= "test1", | |
332 | \t.platdata\t= &dtv_test1, | |
333 | \t.platdata_size\t= sizeof(dtv_test1), | |
334 | }; | |
335 | ||
336 | static struct dtd_test2 dtv_test2 = { | |
337 | \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654}, | |
338 | }; | |
339 | U_BOOT_DEVICE(test2) = { | |
340 | \t.name\t\t= "test2", | |
341 | \t.platdata\t= &dtv_test2, | |
342 | \t.platdata_size\t= sizeof(dtv_test2), | |
343 | }; | |
344 | ||
345 | static struct dtd_test3 dtv_test3 = { | |
346 | \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3}, | |
347 | }; | |
348 | U_BOOT_DEVICE(test3) = { | |
349 | \t.name\t\t= "test3", | |
350 | \t.platdata\t= &dtv_test3, | |
351 | \t.platdata_size\t= sizeof(dtv_test3), | |
352 | }; | |
353 | ||
354 | ''', data) | |
355 | ||
356 | def test_addresses32(self): | |
357 | """Test output from a node with a 'reg' property with na=1, ns=1""" | |
358 | dtb_file = get_dtb_file('dtoc_test_addr32.dts') | |
359 | output = tools.GetOutputFilename('output') | |
360 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
361 | with open(output) as infile: | |
362 | data = infile.read() | |
363 | self.assertEqual('''#include <stdbool.h> | |
364 | #include <libfdt.h> | |
365 | struct dtd_test1 { | |
366 | \tfdt32_t\t\treg[2]; | |
367 | }; | |
368 | struct dtd_test2 { | |
369 | \tfdt32_t\t\treg[4]; | |
370 | }; | |
371 | ''', data) | |
372 | ||
373 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
374 | with open(output) as infile: | |
375 | data = infile.read() | |
376 | self.assertEqual('''#include <common.h> | |
377 | #include <dm.h> | |
378 | #include <dt-structs.h> | |
379 | ||
380 | static struct dtd_test1 dtv_test1 = { | |
381 | \t.reg\t\t\t= {0x1234, 0x5678}, | |
382 | }; | |
383 | U_BOOT_DEVICE(test1) = { | |
384 | \t.name\t\t= "test1", | |
385 | \t.platdata\t= &dtv_test1, | |
386 | \t.platdata_size\t= sizeof(dtv_test1), | |
387 | }; | |
388 | ||
389 | static struct dtd_test2 dtv_test2 = { | |
390 | \t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3}, | |
391 | }; | |
392 | U_BOOT_DEVICE(test2) = { | |
393 | \t.name\t\t= "test2", | |
394 | \t.platdata\t= &dtv_test2, | |
395 | \t.platdata_size\t= sizeof(dtv_test2), | |
396 | }; | |
397 | ||
398 | ''', data) | |
399 | ||
400 | def test_addresses64_32(self): | |
401 | """Test output from a node with a 'reg' property with na=2, ns=1""" | |
402 | dtb_file = get_dtb_file('dtoc_test_addr64_32.dts') | |
403 | output = tools.GetOutputFilename('output') | |
404 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
405 | with open(output) as infile: | |
406 | data = infile.read() | |
407 | self.assertEqual('''#include <stdbool.h> | |
408 | #include <libfdt.h> | |
409 | struct dtd_test1 { | |
410 | \tfdt64_t\t\treg[2]; | |
411 | }; | |
412 | struct dtd_test2 { | |
413 | \tfdt64_t\t\treg[2]; | |
414 | }; | |
415 | struct dtd_test3 { | |
416 | \tfdt64_t\t\treg[4]; | |
417 | }; | |
418 | ''', data) | |
419 | ||
420 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
421 | with open(output) as infile: | |
422 | data = infile.read() | |
423 | self.assertEqual('''#include <common.h> | |
424 | #include <dm.h> | |
425 | #include <dt-structs.h> | |
426 | ||
427 | static struct dtd_test1 dtv_test1 = { | |
428 | \t.reg\t\t\t= {0x123400000000, 0x5678}, | |
429 | }; | |
430 | U_BOOT_DEVICE(test1) = { | |
431 | \t.name\t\t= "test1", | |
432 | \t.platdata\t= &dtv_test1, | |
433 | \t.platdata_size\t= sizeof(dtv_test1), | |
434 | }; | |
435 | ||
436 | static struct dtd_test2 dtv_test2 = { | |
437 | \t.reg\t\t\t= {0x1234567890123456, 0x98765432}, | |
438 | }; | |
439 | U_BOOT_DEVICE(test2) = { | |
440 | \t.name\t\t= "test2", | |
441 | \t.platdata\t= &dtv_test2, | |
442 | \t.platdata_size\t= sizeof(dtv_test2), | |
443 | }; | |
444 | ||
445 | static struct dtd_test3 dtv_test3 = { | |
446 | \t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3}, | |
447 | }; | |
448 | U_BOOT_DEVICE(test3) = { | |
449 | \t.name\t\t= "test3", | |
450 | \t.platdata\t= &dtv_test3, | |
451 | \t.platdata_size\t= sizeof(dtv_test3), | |
452 | }; | |
453 | ||
454 | ''', data) | |
455 | ||
456 | def test_addresses32_64(self): | |
457 | """Test output from a node with a 'reg' property with na=1, ns=2""" | |
458 | dtb_file = get_dtb_file('dtoc_test_addr32_64.dts') | |
459 | output = tools.GetOutputFilename('output') | |
460 | dtb_platdata.run_steps(['struct'], dtb_file, False, output) | |
461 | with open(output) as infile: | |
462 | data = infile.read() | |
463 | self.assertEqual('''#include <stdbool.h> | |
464 | #include <libfdt.h> | |
465 | struct dtd_test1 { | |
466 | \tfdt64_t\t\treg[2]; | |
467 | }; | |
468 | struct dtd_test2 { | |
469 | \tfdt64_t\t\treg[2]; | |
470 | }; | |
471 | struct dtd_test3 { | |
472 | \tfdt64_t\t\treg[4]; | |
473 | }; | |
474 | ''', data) | |
475 | ||
476 | dtb_platdata.run_steps(['platdata'], dtb_file, False, output) | |
477 | with open(output) as infile: | |
478 | data = infile.read() | |
479 | self.assertEqual('''#include <common.h> | |
480 | #include <dm.h> | |
481 | #include <dt-structs.h> | |
482 | ||
483 | static struct dtd_test1 dtv_test1 = { | |
484 | \t.reg\t\t\t= {0x1234, 0x567800000000}, | |
485 | }; | |
486 | U_BOOT_DEVICE(test1) = { | |
487 | \t.name\t\t= "test1", | |
488 | \t.platdata\t= &dtv_test1, | |
489 | \t.platdata_size\t= sizeof(dtv_test1), | |
490 | }; | |
491 | ||
492 | static struct dtd_test2 dtv_test2 = { | |
493 | \t.reg\t\t\t= {0x12345678, 0x9876543210987654}, | |
494 | }; | |
495 | U_BOOT_DEVICE(test2) = { | |
496 | \t.name\t\t= "test2", | |
497 | \t.platdata\t= &dtv_test2, | |
498 | \t.platdata_size\t= sizeof(dtv_test2), | |
499 | }; | |
500 | ||
501 | static struct dtd_test3 dtv_test3 = { | |
502 | \t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3}, | |
503 | }; | |
504 | U_BOOT_DEVICE(test3) = { | |
505 | \t.name\t\t= "test3", | |
506 | \t.platdata\t= &dtv_test3, | |
507 | \t.platdata_size\t= sizeof(dtv_test3), | |
508 | }; | |
509 | ||
c0791928 | 510 | ''', data) |