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