diff options
Diffstat (limited to 'tools/dtoc/test_dtoc.py')
-rwxr-xr-x | tools/dtoc/test_dtoc.py | 1023 |
1 files changed, 960 insertions, 63 deletions
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index d961d67..1912a87 100755 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -10,16 +10,19 @@ tool. """ import collections +import copy import glob import os import struct import unittest +from dtb_platdata import Ftype from dtb_platdata import get_value from dtb_platdata import tab_to from dtoc import dtb_platdata from dtoc import fdt from dtoc import fdt_util +from dtoc import src_scan from dtoc.src_scan import conv_name_to_c from dtoc.src_scan import get_compat_name from patman import test_util @@ -38,13 +41,23 @@ HEADER = '''/* #include <stdbool.h> #include <linux/libfdt.h>''' -C_HEADER = '''/* +DECL_HEADER = '''/* + * DO NOT MODIFY + * + * Declares externs for all device/uclass instances. + * This was generated by dtoc from a .dtb (device tree binary) file. + */ +''' + +C_HEADER_PRE = '''/* * DO NOT MODIFY * * Declares the U_BOOT_DRIVER() records and platform data. * This was generated by dtoc from a .dtb (device tree binary) file. */ +''' +C_HEADER = C_HEADER_PRE + ''' /* Allow use of U_BOOT_DRVINFO() in this file */ #define DT_PLAT_C @@ -53,6 +66,21 @@ C_HEADER = '''/* #include <dt-structs.h> ''' +UCLASS_HEADER_COMMON = '''/* + * DO NOT MODIFY + * + * Declares the uclass instances (struct uclass). + * This was generated by dtoc from a .dtb (device tree binary) file. + */ +''' + +UCLASS_HEADER = UCLASS_HEADER_COMMON + ''' +/* This file is not used: --instantiate was not enabled */ +''' + +# Scanner saved from a previous run of the tests (to speed things up) +saved_scan = None + # This is a test so is allowed to access private things in the module it is # testing # pylint: disable=W0212 @@ -67,10 +95,23 @@ def get_dtb_file(dts_fname, capture_stderr=False): Returns: str: Filename of compiled file in output directory """ - return fdt_util.EnsureCompiled(os.path.join(OUR_PATH, dts_fname), + return fdt_util.EnsureCompiled(os.path.join(OUR_PATH, 'test', dts_fname), capture_stderr=capture_stderr) +def setup(): + global saved_scan + + # Disable warnings so that calls to get_normalized_compat_name() will not + # output things. + saved_scan = src_scan.Scanner(None, True, False) + saved_scan.scan_drivers() + +def copy_scan(): + """Get a copy of saved_scan so that each test can start clean""" + return copy.deepcopy(saved_scan) + + class TestDtoc(unittest.TestCase): """Tests for dtoc""" @classmethod @@ -112,15 +153,22 @@ class TestDtoc(unittest.TestCase): self.assertEqual(expected, actual) @staticmethod - def run_test(args, dtb_file, output): + def run_test(args, dtb_file, output, instantiate=False): """Run a test using dtoc Args: args (list of str): List of arguments for dtoc dtb_file (str): Filename of .dtb file output (str): Filename of output file + + Returns: + DtbPlatdata object """ - dtb_platdata.run_steps(args, dtb_file, False, output, [], True) + # Make a copy of the 'scan' object, since it includes uclasses and + # drivers, which get updated during execution. + return dtb_platdata.run_steps( + args, dtb_file, False, output, [], None, instantiate, + warning_disabled=True, scan=copy_scan()) def test_name(self): """Test conversion of device tree names to C identifiers""" @@ -175,7 +223,10 @@ class TestDtoc(unittest.TestCase): """Test output from a device tree file with no nodes""" dtb_file = get_dtb_file('dtoc_test_empty.dts') output = tools.GetOutputFilename('output') - self.run_test(['struct'], dtb_file, output) + + # Run this one without saved_scan to complete test coverage + dtb_platdata.run_steps(['struct'], dtb_file, False, output, [], None, + False) with open(output) as infile: lines = infile.read().splitlines() self.assertEqual(HEADER.splitlines(), lines) @@ -185,10 +236,62 @@ class TestDtoc(unittest.TestCase): lines = infile.read().splitlines() self.assertEqual(C_HEADER.splitlines() + [''], lines) + decl_text = DECL_HEADER + ''' +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> + +/* driver declarations - these allow DM_DRIVER_GET() to be used */ +extern U_BOOT_DRIVER(sandbox_i2c); +extern U_BOOT_DRIVER(sandbox_pmic); +extern U_BOOT_DRIVER(sandbox_spl_test); +extern U_BOOT_DRIVER(sandbox_spl_test); +extern U_BOOT_DRIVER(sandbox_spl_test); + +/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */ +extern UCLASS_DRIVER(i2c); +extern UCLASS_DRIVER(misc); +extern UCLASS_DRIVER(pmic); +''' + decl_text_inst = DECL_HEADER + ''' +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> + +/* driver declarations - these allow DM_DRIVER_GET() to be used */ +extern U_BOOT_DRIVER(sandbox_i2c); +extern U_BOOT_DRIVER(root_driver); +extern U_BOOT_DRIVER(denx_u_boot_test_bus); +extern U_BOOT_DRIVER(sandbox_spl_test); +extern U_BOOT_DRIVER(sandbox_spl_test); +extern U_BOOT_DRIVER(denx_u_boot_fdt_test); +extern U_BOOT_DRIVER(denx_u_boot_fdt_test); + +/* device declarations - these allow DM_DEVICE_REF() to be used */ +extern DM_DEVICE_INST(i2c); +extern DM_DEVICE_INST(root); +extern DM_DEVICE_INST(some_bus); +extern DM_DEVICE_INST(spl_test); +extern DM_DEVICE_INST(spl_test3); +extern DM_DEVICE_INST(test); +extern DM_DEVICE_INST(test0); + +/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */ +extern UCLASS_DRIVER(i2c); +extern UCLASS_DRIVER(misc); +extern UCLASS_DRIVER(root); +extern UCLASS_DRIVER(testbus); +extern UCLASS_DRIVER(testfdt); + +/* uclass declarations - needed for DM_UCLASS_REF() */ +extern DM_UCLASS_INST(i2c); +extern DM_UCLASS_INST(misc); +extern DM_UCLASS_INST(root); +extern DM_UCLASS_INST(testbus); +extern DM_UCLASS_INST(testfdt); +''' struct_text = HEADER + ''' -struct dtd_sandbox_i2c_test { +struct dtd_sandbox_i2c { }; -struct dtd_sandbox_pmic_test { +struct dtd_sandbox_pmic { \tbool\t\tlow_power; \tfdt64_t\t\treg[2]; }; @@ -205,31 +308,52 @@ struct dtd_sandbox_spl_test { \tconst char *\tstringval; }; ''' - platdata_text = C_HEADER + ''' -/* Node /i2c@0 index 0 */ -static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = { +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: i2c_at_0 sandbox_i2c + * 1: pmic_at_9 sandbox_pmic + * 2: spl_test sandbox_spl_test + * 3: spl_test2 sandbox_spl_test + * 4: spl_test3 sandbox_spl_test + * --- -------------------- -------------------- + */ + +/* + * Node /i2c@0 index 0 + * driver sandbox_i2c parent None + */ +static struct dtd_sandbox_i2c dtv_i2c_at_0 = { }; U_BOOT_DRVINFO(i2c_at_0) = { -\t.name\t\t= "sandbox_i2c_test", -\t.plat\t= &dtv_i2c_at_0, +\t.name\t\t= "sandbox_i2c", +\t.plat\t\t= &dtv_i2c_at_0, \t.plat_size\t= sizeof(dtv_i2c_at_0), \t.parent_idx\t= -1, }; -/* Node /i2c@0/pmic@9 index 1 */ -static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = { +/* + * Node /i2c@0/pmic@9 index 1 + * driver sandbox_pmic parent sandbox_i2c + */ +static struct dtd_sandbox_pmic dtv_pmic_at_9 = { \t.low_power\t\t= true, \t.reg\t\t\t= {0x9, 0x0}, }; U_BOOT_DRVINFO(pmic_at_9) = { -\t.name\t\t= "sandbox_pmic_test", -\t.plat\t= &dtv_pmic_at_9, +\t.name\t\t= "sandbox_pmic", +\t.plat\t\t= &dtv_pmic_at_9, \t.plat_size\t= sizeof(dtv_pmic_at_9), \t.parent_idx\t= 0, }; -/* Node /spl-test index 2 */ +/* + * Node /spl-test index 2 + * driver sandbox_spl_test parent None + */ static struct dtd_sandbox_spl_test dtv_spl_test = { \t.boolval\t\t= true, \t.bytearray\t\t= {0x6, 0x0, 0x0}, @@ -244,12 +368,15 @@ static struct dtd_sandbox_spl_test dtv_spl_test = { }; U_BOOT_DRVINFO(spl_test) = { \t.name\t\t= "sandbox_spl_test", -\t.plat\t= &dtv_spl_test, +\t.plat\t\t= &dtv_spl_test, \t.plat_size\t= sizeof(dtv_spl_test), \t.parent_idx\t= -1, }; -/* Node /spl-test2 index 3 */ +/* + * Node /spl-test2 index 3 + * driver sandbox_spl_test parent None + */ static struct dtd_sandbox_spl_test dtv_spl_test2 = { \t.acpi_name\t\t= "\\\\_SB.GPO0", \t.bytearray\t\t= {0x1, 0x23, 0x34}, @@ -263,12 +390,15 @@ static struct dtd_sandbox_spl_test dtv_spl_test2 = { }; U_BOOT_DRVINFO(spl_test2) = { \t.name\t\t= "sandbox_spl_test", -\t.plat\t= &dtv_spl_test2, +\t.plat\t\t= &dtv_spl_test2, \t.plat_size\t= sizeof(dtv_spl_test2), \t.parent_idx\t= -1, }; -/* Node /spl-test3 index 4 */ +/* + * Node /spl-test3 index 4 + * driver sandbox_spl_test parent None + */ static struct dtd_sandbox_spl_test dtv_spl_test3 = { \t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, \t\t0x0}, @@ -276,12 +406,406 @@ static struct dtd_sandbox_spl_test dtv_spl_test3 = { }; U_BOOT_DRVINFO(spl_test3) = { \t.name\t\t= "sandbox_spl_test", -\t.plat\t= &dtv_spl_test3, +\t.plat\t\t= &dtv_spl_test3, \t.plat_size\t= sizeof(dtv_spl_test3), \t.parent_idx\t= -1, }; ''' + uclass_text = UCLASS_HEADER + uclass_text_inst = ''' + +#include <common.h> +#include <dm.h> +#include <dt-structs.h> + +/* + * uclass declarations, ordered by 'struct uclass' linker_list idx: + * 0: i2c + * 1: misc + * 2: root + * 3: testbus + * 4: testfdt + * + * Sequence numbers allocated in each uclass: + * i2c: UCLASS_I2C + * 4: /i2c + * misc: UCLASS_MISC + * 0: /spl-test + * 1: /spl-test3 + * root: UCLASS_ROOT + * 0: / + * testbus: UCLASS_TEST_BUS + * 2: /some-bus + * testfdt: UCLASS_TEST_FDT + * 1: /some-bus/test + * 2: /some-bus/test0 + */ + +struct list_head uclass_head = { + .prev = &DM_UCLASS_REF(testfdt)->sibling_node, + .next = &DM_UCLASS_REF(i2c)->sibling_node, +}; + +DM_UCLASS_INST(i2c) = { + .uc_drv = DM_UCLASS_DRIVER_REF(i2c), + .sibling_node = { + .prev = &uclass_head, + .next = &DM_UCLASS_REF(misc)->sibling_node, + }, + .dev_head = { + .prev = &DM_DEVICE_REF(i2c)->uclass_node, + .next = &DM_DEVICE_REF(i2c)->uclass_node, + }, +}; + +DM_UCLASS_INST(misc) = { + .uc_drv = DM_UCLASS_DRIVER_REF(misc), + .sibling_node = { + .prev = &DM_UCLASS_REF(i2c)->sibling_node, + .next = &DM_UCLASS_REF(root)->sibling_node, + }, + .dev_head = { + .prev = &DM_DEVICE_REF(spl_test3)->uclass_node, + .next = &DM_DEVICE_REF(spl_test)->uclass_node, + }, +}; + +DM_UCLASS_INST(root) = { + .uc_drv = DM_UCLASS_DRIVER_REF(root), + .sibling_node = { + .prev = &DM_UCLASS_REF(misc)->sibling_node, + .next = &DM_UCLASS_REF(testbus)->sibling_node, + }, + .dev_head = { + .prev = &DM_DEVICE_REF(root)->uclass_node, + .next = &DM_DEVICE_REF(root)->uclass_node, + }, +}; + +DM_UCLASS_INST(testbus) = { + .uc_drv = DM_UCLASS_DRIVER_REF(testbus), + .sibling_node = { + .prev = &DM_UCLASS_REF(root)->sibling_node, + .next = &DM_UCLASS_REF(testfdt)->sibling_node, + }, + .dev_head = { + .prev = &DM_DEVICE_REF(some_bus)->uclass_node, + .next = &DM_DEVICE_REF(some_bus)->uclass_node, + }, +}; + +#include <dm/test.h> +u8 _testfdt_priv_[sizeof(struct dm_test_uc_priv)] + __attribute__ ((section (".priv_data"))); +DM_UCLASS_INST(testfdt) = { + .priv_ = _testfdt_priv_, + .uc_drv = DM_UCLASS_DRIVER_REF(testfdt), + .sibling_node = { + .prev = &DM_UCLASS_REF(testbus)->sibling_node, + .next = &uclass_head, + }, + .dev_head = { + .prev = &DM_DEVICE_REF(test0)->uclass_node, + .next = &DM_DEVICE_REF(test)->uclass_node, + }, +}; + +''' + device_text = '''/* + * DO NOT MODIFY + * + * Declares the DM_DEVICE_INST() records. + * This was generated by dtoc from a .dtb (device tree binary) file. + */ + +/* This file is not used: --instantiate was not enabled */ +''' + device_text_inst = '''/* + * DO NOT MODIFY + * + * Declares the DM_DEVICE_INST() records. + * This was generated by dtoc from a .dtb (device tree binary) file. + */ + +#include <common.h> +#include <dm.h> +#include <dt-structs.h> + +/* + * udevice declarations, ordered by 'struct udevice' linker_list position: + * + * idx udevice driver + * --- -------------------- -------------------- + * 0: i2c sandbox_i2c + * 1: root root_driver + * 2: some_bus denx_u_boot_test_bus + * 3: spl_test sandbox_spl_test + * 4: spl_test3 sandbox_spl_test + * 5: test denx_u_boot_fdt_test + * 6: test0 denx_u_boot_fdt_test + * --- -------------------- -------------------- + */ + +/* + * Node /i2c index 0 + * driver sandbox_i2c parent root_driver +*/ +static struct dtd_sandbox_i2c dtv_i2c = { +\t.intval\t\t\t= 0x3, +}; + +#include <asm/i2c.h> +u8 _sandbox_i2c_priv_i2c[sizeof(struct sandbox_i2c_priv)] +\t__attribute__ ((section (".priv_data"))); +#include <i2c.h> +u8 _sandbox_i2c_uc_priv_i2c[sizeof(struct dm_i2c_bus)] +\t__attribute__ ((section (".priv_data"))); + +DM_DEVICE_INST(i2c) = { +\t.driver\t\t= DM_DRIVER_REF(sandbox_i2c), +\t.name\t\t= "sandbox_i2c", +\t.plat_\t\t= &dtv_i2c, +\t.priv_\t\t= _sandbox_i2c_priv_i2c, +\t.uclass\t\t= DM_UCLASS_REF(i2c), +\t.uclass_priv_ = _sandbox_i2c_uc_priv_i2c, +\t.uclass_node\t= { +\t\t.prev = &DM_UCLASS_REF(i2c)->dev_head, +\t\t.next = &DM_UCLASS_REF(i2c)->dev_head, +\t}, +\t.child_head\t= { +\t\t.prev = &DM_DEVICE_REF(i2c)->child_head, +\t\t.next = &DM_DEVICE_REF(i2c)->child_head, +\t}, +\t.sibling_node\t= { +\t\t.prev = &DM_DEVICE_REF(root)->child_head, +\t\t.next = &DM_DEVICE_REF(some_bus)->sibling_node, +\t}, +\t.seq_ = 4, +}; + +/* + * Node / index 1 + * driver root_driver parent None +*/ +static struct dtd_root_driver dtv_root = { +}; + +DM_DEVICE_INST(root) = { +\t.driver\t\t= DM_DRIVER_REF(root_driver), +\t.name\t\t= "root_driver", +\t.plat_\t\t= &dtv_root, +\t.uclass\t\t= DM_UCLASS_REF(root), +\t.uclass_node\t= { +\t\t.prev = &DM_UCLASS_REF(root)->dev_head, +\t\t.next = &DM_UCLASS_REF(root)->dev_head, +\t}, +\t.child_head\t= { +\t\t.prev = &DM_DEVICE_REF(spl_test3)->sibling_node, +\t\t.next = &DM_DEVICE_REF(i2c)->sibling_node, +\t}, +\t.seq_ = 0, +}; + +/* + * Node /some-bus index 2 + * driver denx_u_boot_test_bus parent root_driver +*/ + +#include <dm/test.h> +struct dm_test_pdata __attribute__ ((section (".priv_data"))) +\t_denx_u_boot_test_bus_plat_some_bus = { +\t.dtplat = { +\t\t.ping_add\t\t= 0x4, +\t\t.ping_expect\t\t= 0x4, +\t\t.reg\t\t\t= {0x3, 0x1}, +\t}, +}; +#include <dm/test.h> +u8 _denx_u_boot_test_bus_priv_some_bus[sizeof(struct dm_test_priv)] +\t__attribute__ ((section (".priv_data"))); +#include <dm/test.h> +u8 _denx_u_boot_test_bus_ucplat_some_bus[sizeof(struct dm_test_uclass_priv)] +\t__attribute__ ((section (".priv_data"))); +#include <test.h> + +DM_DEVICE_INST(some_bus) = { +\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_test_bus), +\t.name\t\t= "denx_u_boot_test_bus", +\t.plat_\t\t= &_denx_u_boot_test_bus_plat_some_bus, +\t.uclass_plat_\t= _denx_u_boot_test_bus_ucplat_some_bus, +\t.driver_data\t= DM_TEST_TYPE_FIRST, +\t.priv_\t\t= _denx_u_boot_test_bus_priv_some_bus, +\t.uclass\t\t= DM_UCLASS_REF(testbus), +\t.uclass_node\t= { +\t\t.prev = &DM_UCLASS_REF(testbus)->dev_head, +\t\t.next = &DM_UCLASS_REF(testbus)->dev_head, +\t}, +\t.child_head\t= { +\t\t.prev = &DM_DEVICE_REF(test0)->sibling_node, +\t\t.next = &DM_DEVICE_REF(test)->sibling_node, +\t}, +\t.sibling_node\t= { +\t\t.prev = &DM_DEVICE_REF(i2c)->sibling_node, +\t\t.next = &DM_DEVICE_REF(spl_test)->sibling_node, +\t}, +\t.seq_ = 2, +}; + +/* + * Node /spl-test index 3 + * driver sandbox_spl_test parent root_driver +*/ +static struct dtd_sandbox_spl_test dtv_spl_test = { +\t.boolval\t\t= true, +\t.intval\t\t\t= 0x1, +}; + +DM_DEVICE_INST(spl_test) = { +\t.driver\t\t= DM_DRIVER_REF(sandbox_spl_test), +\t.name\t\t= "sandbox_spl_test", +\t.plat_\t\t= &dtv_spl_test, +\t.uclass\t\t= DM_UCLASS_REF(misc), +\t.uclass_node\t= { +\t\t.prev = &DM_UCLASS_REF(misc)->dev_head, +\t\t.next = &DM_DEVICE_REF(spl_test3)->uclass_node, +\t}, +\t.child_head\t= { +\t\t.prev = &DM_DEVICE_REF(spl_test)->child_head, +\t\t.next = &DM_DEVICE_REF(spl_test)->child_head, +\t}, +\t.sibling_node\t= { +\t\t.prev = &DM_DEVICE_REF(some_bus)->sibling_node, +\t\t.next = &DM_DEVICE_REF(spl_test3)->sibling_node, +\t}, +\t.seq_ = 0, +}; + +/* + * Node /spl-test3 index 4 + * driver sandbox_spl_test parent root_driver +*/ +static struct dtd_sandbox_spl_test dtv_spl_test3 = { +\t.longbytearray\t\t= {0x90a0b0c, 0xd0e0f10}, +\t.stringarray\t\t= "one", +}; + +DM_DEVICE_INST(spl_test3) = { +\t.driver\t\t= DM_DRIVER_REF(sandbox_spl_test), +\t.name\t\t= "sandbox_spl_test", +\t.plat_\t\t= &dtv_spl_test3, +\t.uclass\t\t= DM_UCLASS_REF(misc), +\t.uclass_node\t= { +\t\t.prev = &DM_DEVICE_REF(spl_test)->uclass_node, +\t\t.next = &DM_UCLASS_REF(misc)->dev_head, +\t}, +\t.child_head\t= { +\t\t.prev = &DM_DEVICE_REF(spl_test3)->child_head, +\t\t.next = &DM_DEVICE_REF(spl_test3)->child_head, +\t}, +\t.sibling_node\t= { +\t\t.prev = &DM_DEVICE_REF(spl_test)->sibling_node, +\t\t.next = &DM_DEVICE_REF(root)->child_head, +\t}, +\t.seq_ = 1, +}; + +/* + * Node /some-bus/test index 5 + * driver denx_u_boot_fdt_test parent denx_u_boot_test_bus +*/ + +#include <dm/test.h> +struct dm_test_pdata __attribute__ ((section (".priv_data"))) +\t_denx_u_boot_fdt_test_plat_test = { +\t.dtplat = { +\t\t.ping_add\t\t= 0x5, +\t\t.ping_expect\t\t= 0x5, +\t\t.reg\t\t\t= {0x5, 0x0}, +\t}, +}; +#include <dm/test.h> +u8 _denx_u_boot_fdt_test_priv_test[sizeof(struct dm_test_priv)] +\t__attribute__ ((section (".priv_data"))); +#include <dm/test.h> +u8 _denx_u_boot_fdt_test_parent_plat_test[sizeof(struct dm_test_parent_plat)] +\t__attribute__ ((section (".priv_data"))); +#include <dm/test.h> +u8 _denx_u_boot_fdt_test_parent_priv_test[sizeof(struct dm_test_parent_data)] +\t__attribute__ ((section (".priv_data"))); + +DM_DEVICE_INST(test) = { +\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_fdt_test), +\t.name\t\t= "denx_u_boot_fdt_test", +\t.plat_\t\t= &_denx_u_boot_fdt_test_plat_test, +\t.parent_plat_\t= _denx_u_boot_fdt_test_parent_plat_test, +\t.driver_data\t= DM_TEST_TYPE_FIRST, +\t.parent\t\t= DM_DEVICE_REF(some_bus), +\t.priv_\t\t= _denx_u_boot_fdt_test_priv_test, +\t.uclass\t\t= DM_UCLASS_REF(testfdt), +\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test, +\t.uclass_node\t= { +\t\t.prev = &DM_UCLASS_REF(testfdt)->dev_head, +\t\t.next = &DM_DEVICE_REF(test0)->uclass_node, +\t}, +\t.child_head\t= { +\t\t.prev = &DM_DEVICE_REF(test)->child_head, +\t\t.next = &DM_DEVICE_REF(test)->child_head, +\t}, +\t.sibling_node\t= { +\t\t.prev = &DM_DEVICE_REF(some_bus)->child_head, +\t\t.next = &DM_DEVICE_REF(test0)->sibling_node, +\t}, +\t.seq_ = 1, +}; + +/* + * Node /some-bus/test0 index 6 + * driver denx_u_boot_fdt_test parent denx_u_boot_test_bus +*/ + +#include <dm/test.h> +struct dm_test_pdata __attribute__ ((section (".priv_data"))) +\t_denx_u_boot_fdt_test_plat_test0 = { +\t.dtplat = { +\t}, +}; +#include <dm/test.h> +u8 _denx_u_boot_fdt_test_priv_test0[sizeof(struct dm_test_priv)] +\t__attribute__ ((section (".priv_data"))); +#include <dm/test.h> +u8 _denx_u_boot_fdt_test_parent_plat_test0[sizeof(struct dm_test_parent_plat)] +\t__attribute__ ((section (".priv_data"))); +#include <dm/test.h> +u8 _denx_u_boot_fdt_test_parent_priv_test0[sizeof(struct dm_test_parent_data)] +\t__attribute__ ((section (".priv_data"))); + +DM_DEVICE_INST(test0) = { +\t.driver\t\t= DM_DRIVER_REF(denx_u_boot_fdt_test), +\t.name\t\t= "denx_u_boot_fdt_test", +\t.plat_\t\t= &_denx_u_boot_fdt_test_plat_test0, +\t.parent_plat_\t= _denx_u_boot_fdt_test_parent_plat_test0, +\t.driver_data\t= DM_TEST_TYPE_SECOND, +\t.parent\t\t= DM_DEVICE_REF(some_bus), +\t.priv_\t\t= _denx_u_boot_fdt_test_priv_test0, +\t.uclass\t\t= DM_UCLASS_REF(testfdt), +\t.parent_priv_\t= _denx_u_boot_fdt_test_parent_priv_test0, +\t.uclass_node\t= { +\t\t.prev = &DM_DEVICE_REF(test)->uclass_node, +\t\t.next = &DM_UCLASS_REF(testfdt)->dev_head, +\t}, +\t.child_head\t= { +\t\t.prev = &DM_DEVICE_REF(test0)->child_head, +\t\t.next = &DM_DEVICE_REF(test0)->child_head, +\t}, +\t.sibling_node\t= { +\t\t.prev = &DM_DEVICE_REF(test)->sibling_node, +\t\t.next = &DM_DEVICE_REF(some_bus)->child_head, +\t}, +\t.seq_ = 2, +}; + +''' def test_simple(self): """Test output from some simple nodes with various types of data""" @@ -299,10 +823,18 @@ U_BOOT_DRVINFO(spl_test3) = { self._check_strings(self.platdata_text, data) + self.run_test(['decl'], dtb_file, output) + with open(output) as infile: + data = infile.read() + + self._check_strings(self.decl_text, data) + # Try the 'all' command self.run_test(['all'], dtb_file, output) data = tools.ReadFile(output, binary=False) - self._check_strings(self.platdata_text + self.struct_text, data) + self._check_strings( + self.decl_text + self.device_text + self.platdata_text + + self.struct_text + self.uclass_text, data) def test_driver_alias(self): """Test output from a device tree file with a driver alias""" @@ -323,7 +855,19 @@ struct dtd_sandbox_gpio { with open(output) as infile: data = infile.read() self._check_strings(C_HEADER + ''' -/* Node /gpios@0 index 0 */ +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: gpios_at_0 sandbox_gpio + * --- -------------------- -------------------- + */ + +/* + * Node /gpios@0 index 0 + * driver sandbox_gpio parent None + */ static struct dtd_sandbox_gpio dtv_gpios_at_0 = { \t.gpio_bank_name\t\t= "a", \t.gpio_controller\t= true, @@ -331,7 +875,7 @@ static struct dtd_sandbox_gpio dtv_gpios_at_0 = { }; U_BOOT_DRVINFO(gpios_at_0) = { \t.name\t\t= "sandbox_gpio", -\t.plat\t= &dtv_gpios_at_0, +\t.plat\t\t= &dtv_gpios_at_0, \t.plat_size\t= sizeof(dtv_gpios_at_0), \t.parent_idx\t= -1, }; @@ -343,7 +887,9 @@ U_BOOT_DRVINFO(gpios_at_0) = { dtb_file = get_dtb_file('dtoc_test_invalid_driver.dts') output = tools.GetOutputFilename('output') with test_util.capture_sys_output() as _: - dtb_platdata.run_steps(['struct'], dtb_file, False, output, []) + dtb_platdata.run_steps( + ['struct'], dtb_file, False, output, [], None, False, + scan=copy_scan()) with open(output) as infile: data = infile.read() self._check_strings(HEADER + ''' @@ -352,16 +898,27 @@ struct dtd_invalid { ''', data) with test_util.capture_sys_output() as _: - dtb_platdata.run_steps(['platdata'], dtb_file, False, output, []) + dtb_platdata.run_steps( + ['platdata'], dtb_file, False, output, [], None, False, + scan=copy_scan()) with open(output) as infile: data = infile.read() self._check_strings(C_HEADER + ''' +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: spl_test invalid + * --- -------------------- -------------------- + */ + /* Node /spl-test index 0 */ static struct dtd_invalid dtv_spl_test = { }; U_BOOT_DRVINFO(spl_test) = { \t.name\t\t= "invalid", -\t.plat\t= &dtv_spl_test, +\t.plat\t\t= &dtv_spl_test, \t.plat_size\t= sizeof(dtv_spl_test), \t.parent_idx\t= -1, }; @@ -388,13 +945,26 @@ struct dtd_target { with open(output) as infile: data = infile.read() self._check_strings(C_HEADER + ''' +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: phandle2_target target + * 1: phandle3_target target + * 2: phandle_source source + * 3: phandle_source2 source + * 4: phandle_target target + * --- -------------------- -------------------- + */ + /* Node /phandle2-target index 0 */ static struct dtd_target dtv_phandle2_target = { \t.intval\t\t\t= 0x1, }; U_BOOT_DRVINFO(phandle2_target) = { \t.name\t\t= "target", -\t.plat\t= &dtv_phandle2_target, +\t.plat\t\t= &dtv_phandle2_target, \t.plat_size\t= sizeof(dtv_phandle2_target), \t.parent_idx\t= -1, }; @@ -405,7 +975,7 @@ static struct dtd_target dtv_phandle3_target = { }; U_BOOT_DRVINFO(phandle3_target) = { \t.name\t\t= "target", -\t.plat\t= &dtv_phandle3_target, +\t.plat\t\t= &dtv_phandle3_target, \t.plat_size\t= sizeof(dtv_phandle3_target), \t.parent_idx\t= -1, }; @@ -420,7 +990,7 @@ static struct dtd_source dtv_phandle_source = { }; U_BOOT_DRVINFO(phandle_source) = { \t.name\t\t= "source", -\t.plat\t= &dtv_phandle_source, +\t.plat\t\t= &dtv_phandle_source, \t.plat_size\t= sizeof(dtv_phandle_source), \t.parent_idx\t= -1, }; @@ -432,7 +1002,7 @@ static struct dtd_source dtv_phandle_source2 = { }; U_BOOT_DRVINFO(phandle_source2) = { \t.name\t\t= "source", -\t.plat\t= &dtv_phandle_source2, +\t.plat\t\t= &dtv_phandle_source2, \t.plat_size\t= sizeof(dtv_phandle_source2), \t.parent_idx\t= -1, }; @@ -443,7 +1013,7 @@ static struct dtd_target dtv_phandle_target = { }; U_BOOT_DRVINFO(phandle_target) = { \t.name\t\t= "target", -\t.plat\t= &dtv_phandle_target, +\t.plat\t\t= &dtv_phandle_target, \t.plat_size\t= sizeof(dtv_phandle_target), \t.parent_idx\t= -1, }; @@ -474,6 +1044,16 @@ struct dtd_target { with open(output) as infile: data = infile.read() self._check_strings(C_HEADER + ''' +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: phandle_source2 source + * 1: phandle_target target + * --- -------------------- -------------------- + */ + /* Node /phandle-source2 index 0 */ static struct dtd_source dtv_phandle_source2 = { \t.clocks\t\t\t= { @@ -481,7 +1061,7 @@ static struct dtd_source dtv_phandle_source2 = { }; U_BOOT_DRVINFO(phandle_source2) = { \t.name\t\t= "source", -\t.plat\t= &dtv_phandle_source2, +\t.plat\t\t= &dtv_phandle_source2, \t.plat_size\t= sizeof(dtv_phandle_source2), \t.parent_idx\t= -1, }; @@ -491,7 +1071,7 @@ static struct dtd_target dtv_phandle_target = { }; U_BOOT_DRVINFO(phandle_target) = { \t.name\t\t= "target", -\t.plat\t= &dtv_phandle_target, +\t.plat\t\t= &dtv_phandle_target, \t.plat_size\t= sizeof(dtv_phandle_target), \t.parent_idx\t= -1, }; @@ -502,17 +1082,32 @@ U_BOOT_DRVINFO(phandle_target) = { """Test that phandle targets are generated when unsing cd-gpios""" dtb_file = get_dtb_file('dtoc_test_phandle_cd_gpios.dts') output = tools.GetOutputFilename('output') - dtb_platdata.run_steps(['platdata'], dtb_file, False, output, [], True) + dtb_platdata.run_steps( + ['platdata'], dtb_file, False, output, [], None, False, + warning_disabled=True, scan=copy_scan()) with open(output) as infile: data = infile.read() self._check_strings(C_HEADER + ''' +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: phandle2_target target + * 1: phandle3_target target + * 2: phandle_source source + * 3: phandle_source2 source + * 4: phandle_target target + * --- -------------------- -------------------- + */ + /* Node /phandle2-target index 0 */ static struct dtd_target dtv_phandle2_target = { \t.intval\t\t\t= 0x1, }; U_BOOT_DRVINFO(phandle2_target) = { \t.name\t\t= "target", -\t.plat\t= &dtv_phandle2_target, +\t.plat\t\t= &dtv_phandle2_target, \t.plat_size\t= sizeof(dtv_phandle2_target), \t.parent_idx\t= -1, }; @@ -523,7 +1118,7 @@ static struct dtd_target dtv_phandle3_target = { }; U_BOOT_DRVINFO(phandle3_target) = { \t.name\t\t= "target", -\t.plat\t= &dtv_phandle3_target, +\t.plat\t\t= &dtv_phandle3_target, \t.plat_size\t= sizeof(dtv_phandle3_target), \t.parent_idx\t= -1, }; @@ -538,7 +1133,7 @@ static struct dtd_source dtv_phandle_source = { }; U_BOOT_DRVINFO(phandle_source) = { \t.name\t\t= "source", -\t.plat\t= &dtv_phandle_source, +\t.plat\t\t= &dtv_phandle_source, \t.plat_size\t= sizeof(dtv_phandle_source), \t.parent_idx\t= -1, }; @@ -550,7 +1145,7 @@ static struct dtd_source dtv_phandle_source2 = { }; U_BOOT_DRVINFO(phandle_source2) = { \t.name\t\t= "source", -\t.plat\t= &dtv_phandle_source2, +\t.plat\t\t= &dtv_phandle_source2, \t.plat_size\t= sizeof(dtv_phandle_source2), \t.parent_idx\t= -1, }; @@ -561,7 +1156,7 @@ static struct dtd_target dtv_phandle_target = { }; U_BOOT_DRVINFO(phandle_target) = { \t.name\t\t= "target", -\t.plat\t= &dtv_phandle_target, +\t.plat\t\t= &dtv_phandle_target, \t.plat_size\t= sizeof(dtv_phandle_target), \t.parent_idx\t= -1, }; @@ -611,13 +1206,24 @@ struct dtd_test3 { with open(output) as infile: data = infile.read() self._check_strings(C_HEADER + ''' +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: test1 test1 + * 1: test2 test2 + * 2: test3 test3 + * --- -------------------- -------------------- + */ + /* Node /test1 index 0 */ static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x1234, 0x5678}, }; U_BOOT_DRVINFO(test1) = { \t.name\t\t= "test1", -\t.plat\t= &dtv_test1, +\t.plat\t\t= &dtv_test1, \t.plat_size\t= sizeof(dtv_test1), \t.parent_idx\t= -1, }; @@ -628,7 +1234,7 @@ static struct dtd_test2 dtv_test2 = { }; U_BOOT_DRVINFO(test2) = { \t.name\t\t= "test2", -\t.plat\t= &dtv_test2, +\t.plat\t\t= &dtv_test2, \t.plat_size\t= sizeof(dtv_test2), \t.parent_idx\t= -1, }; @@ -639,7 +1245,7 @@ static struct dtd_test3 dtv_test3 = { }; U_BOOT_DRVINFO(test3) = { \t.name\t\t= "test3", -\t.plat\t= &dtv_test3, +\t.plat\t\t= &dtv_test3, \t.plat_size\t= sizeof(dtv_test3), \t.parent_idx\t= -1, }; @@ -666,13 +1272,23 @@ struct dtd_test2 { with open(output) as infile: data = infile.read() self._check_strings(C_HEADER + ''' +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: test1 test1 + * 1: test2 test2 + * --- -------------------- -------------------- + */ + /* Node /test1 index 0 */ static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x1234, 0x5678}, }; U_BOOT_DRVINFO(test1) = { \t.name\t\t= "test1", -\t.plat\t= &dtv_test1, +\t.plat\t\t= &dtv_test1, \t.plat_size\t= sizeof(dtv_test1), \t.parent_idx\t= -1, }; @@ -683,7 +1299,7 @@ static struct dtd_test2 dtv_test2 = { }; U_BOOT_DRVINFO(test2) = { \t.name\t\t= "test2", -\t.plat\t= &dtv_test2, +\t.plat\t\t= &dtv_test2, \t.plat_size\t= sizeof(dtv_test2), \t.parent_idx\t= -1, }; @@ -713,13 +1329,24 @@ struct dtd_test3 { with open(output) as infile: data = infile.read() self._check_strings(C_HEADER + ''' +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: test1 test1 + * 1: test2 test2 + * 2: test3 test3 + * --- -------------------- -------------------- + */ + /* Node /test1 index 0 */ static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x123400000000, 0x5678}, }; U_BOOT_DRVINFO(test1) = { \t.name\t\t= "test1", -\t.plat\t= &dtv_test1, +\t.plat\t\t= &dtv_test1, \t.plat_size\t= sizeof(dtv_test1), \t.parent_idx\t= -1, }; @@ -730,7 +1357,7 @@ static struct dtd_test2 dtv_test2 = { }; U_BOOT_DRVINFO(test2) = { \t.name\t\t= "test2", -\t.plat\t= &dtv_test2, +\t.plat\t\t= &dtv_test2, \t.plat_size\t= sizeof(dtv_test2), \t.parent_idx\t= -1, }; @@ -741,7 +1368,7 @@ static struct dtd_test3 dtv_test3 = { }; U_BOOT_DRVINFO(test3) = { \t.name\t\t= "test3", -\t.plat\t= &dtv_test3, +\t.plat\t\t= &dtv_test3, \t.plat_size\t= sizeof(dtv_test3), \t.parent_idx\t= -1, }; @@ -771,13 +1398,24 @@ struct dtd_test3 { with open(output) as infile: data = infile.read() self._check_strings(C_HEADER + ''' +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: test1 test1 + * 1: test2 test2 + * 2: test3 test3 + * --- -------------------- -------------------- + */ + /* Node /test1 index 0 */ static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x1234, 0x567800000000}, }; U_BOOT_DRVINFO(test1) = { \t.name\t\t= "test1", -\t.plat\t= &dtv_test1, +\t.plat\t\t= &dtv_test1, \t.plat_size\t= sizeof(dtv_test1), \t.parent_idx\t= -1, }; @@ -788,7 +1426,7 @@ static struct dtd_test2 dtv_test2 = { }; U_BOOT_DRVINFO(test2) = { \t.name\t\t= "test2", -\t.plat\t= &dtv_test2, +\t.plat\t\t= &dtv_test2, \t.plat_size\t= sizeof(dtv_test2), \t.parent_idx\t= -1, }; @@ -799,7 +1437,7 @@ static struct dtd_test3 dtv_test3 = { }; U_BOOT_DRVINFO(test3) = { \t.name\t\t= "test3", -\t.plat\t= &dtv_test3, +\t.plat\t\t= &dtv_test3, \t.plat_size\t= sizeof(dtv_test3), \t.parent_idx\t= -1, }; @@ -845,24 +1483,40 @@ struct dtd_sandbox_spl_test { with open(output) as infile: data = infile.read() self._check_strings(C_HEADER + ''' -/* Node /spl-test index 0 */ +/* + * driver_info declarations, ordered by 'struct driver_info' linker_list idx: + * + * idx driver_info driver + * --- -------------------- -------------------- + * 0: spl_test sandbox_spl_test + * 1: spl_test2 sandbox_spl_test + * --- -------------------- -------------------- + */ + +/* + * Node /spl-test index 0 + * driver sandbox_spl_test parent None + */ static struct dtd_sandbox_spl_test dtv_spl_test = { \t.intval\t\t\t= 0x1, }; U_BOOT_DRVINFO(spl_test) = { \t.name\t\t= "sandbox_spl_test", -\t.plat\t= &dtv_spl_test, +\t.plat\t\t= &dtv_spl_test, \t.plat_size\t= sizeof(dtv_spl_test), \t.parent_idx\t= -1, }; -/* Node /spl-test2 index 1 */ +/* + * Node /spl-test2 index 1 + * driver sandbox_spl_test parent None + */ static struct dtd_sandbox_spl_test dtv_spl_test2 = { \t.intarray\t\t= 0x5, }; U_BOOT_DRVINFO(spl_test2) = { \t.name\t\t= "sandbox_spl_test", -\t.plat\t= &dtv_spl_test2, +\t.plat\t\t= &dtv_spl_test2, \t.plat_size\t= sizeof(dtv_spl_test2), \t.parent_idx\t= -1, }; @@ -882,7 +1536,9 @@ U_BOOT_DRVINFO(spl_test2) = { output = tools.GetOutputFilename('output') self.run_test(['all'], dtb_file, output) data = tools.ReadFile(output, binary=False) - self._check_strings(self.platdata_text + self.struct_text, data) + self._check_strings( + self.decl_text + self.device_text + self.platdata_text + + self.struct_text + self.uclass_text, data) def test_no_command(self): """Test running dtoc without a command""" @@ -897,13 +1553,16 @@ U_BOOT_DRVINFO(spl_test2) = { output = tools.GetOutputFilename('output') with self.assertRaises(ValueError) as exc: self.run_test(['invalid-cmd'], dtb_file, output) - self.assertIn("Unknown command 'invalid-cmd': (use: platdata, struct)", - str(exc.exception)) + self.assertIn( + "Unknown command 'invalid-cmd': (use: decl, device, platdata, struct, uclass)", + str(exc.exception)) def test_output_conflict(self): """Test a conflict between and output dirs and output file""" with self.assertRaises(ValueError) as exc: - dtb_platdata.run_steps(['all'], None, False, 'out', ['cdir'], True) + dtb_platdata.run_steps( + ['all'], None, False, 'out', ['cdir'], None, False, + warning_disabled=True, scan=copy_scan()) self.assertIn("Must specify either output or output_dirs, not both", str(exc.exception)) @@ -919,11 +1578,249 @@ U_BOOT_DRVINFO(spl_test2) = { fnames = glob.glob(outdir + '/*') self.assertEqual(2, len(fnames)) - dtb_platdata.run_steps(['all'], dtb_file, False, None, [outdir], True) + dtb_platdata.run_steps( + ['all'], dtb_file, False, None, [outdir], None, False, + warning_disabled=True, scan=copy_scan()) fnames = glob.glob(outdir + '/*') - self.assertEqual(4, len(fnames)) + self.assertEqual(7, len(fnames)) leafs = set(os.path.basename(fname) for fname in fnames) self.assertEqual( - {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb'}, + {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb', + 'dt-uclass.c', 'dt-decl.h', 'dt-device.c'}, leafs) + + def setup_process_test(self): + """Set up a test of process_nodes() + + This uses saved_scan but returns a deep copy of it, so it is safe to + modify it in these tests + + Returns: + tuple: + DtbPlatdata: object to test + Scanner: scanner to use + """ + dtb_file = get_dtb_file('dtoc_test_simple.dts') + output = tools.GetOutputFilename('output') + + # Take a copy before messing with it + scan = copy_scan() + plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False) + plat.scan_dtb() + plat.scan_tree(False) + plat.prepare_nodes() + return plat, scan + + def test_process_nodes(self): + """Test processing nodes to add various info""" + plat, scan = self.setup_process_test() + plat.process_nodes(True) + + i2c_node = plat._fdt.GetNode('/i2c@0') + pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9') + pmic = scan._drivers['sandbox_pmic'] + i2c = scan._drivers['sandbox_i2c'] + self.assertEqual('DM_DEVICE_REF(pmic_at_9)', pmic_node.dev_ref) + self.assertEqual(pmic, pmic_node.driver) + self.assertEqual(i2c_node, pmic_node.parent) + self.assertEqual(i2c, pmic_node.parent_driver) + + # The pmic is the only child + self.assertEqual(pmic_node.parent_seq, 0) + self.assertEqual([pmic_node], i2c_node.child_devs) + + # Start and end of the list should be the child_head + ref = '&DM_DEVICE_REF(i2c_at_0)->child_head' + self.assertEqual( + {-1: ref, 0: '&DM_DEVICE_REF(pmic_at_9)->sibling_node', 1: ref}, + i2c_node.child_refs) + + def test_process_nodes_bad_parent(self): + # Pretend that i2c has a parent (the pmic) and delete that driver + plat, scan = self.setup_process_test() + + i2c_node = plat._fdt.GetNode('/i2c@0') + pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9') + del scan._drivers['sandbox_pmic'] + i2c_node.parent = pmic_node + + # Process twice, the second time to generate an exception + plat.process_nodes(False) + with self.assertRaises(ValueError) as exc: + plat.process_nodes(True) + self.assertIn( + "Cannot parse/find parent driver 'sandbox_pmic' for 'sandbox_i2c", + str(exc.exception)) + + def test_process_nodes_bad_node(self): + plat, scan = self.setup_process_test() + + # Now remove the pmic driver + del scan._drivers['sandbox_pmic'] + + # Process twice, the second time to generate an exception + plat.process_nodes(False) + with self.assertRaises(ValueError) as exc: + plat.process_nodes(True) + self.assertIn("Cannot parse/find driver for 'sandbox_pmic", + str(exc.exception)) + + def test_process_nodes_bad_uclass(self): + plat, scan = self.setup_process_test() + + self.assertIn('UCLASS_I2C', scan._uclass) + del scan._uclass['UCLASS_I2C'] + with self.assertRaises(ValueError) as exc: + plat.process_nodes(True) + self.assertIn("Cannot parse/find uclass 'UCLASS_I2C' for driver 'sandbox_i2c'", + str(exc.exception)) + + def test_process_nodes_used(self): + """Test processing nodes to add various info""" + plat, scan = self.setup_process_test() + plat.process_nodes(True) + + pmic = scan._drivers['sandbox_pmic'] + self.assertTrue(pmic.used) + + gpio = scan._drivers['sandbox_gpio'] + self.assertFalse(gpio.used) + + def test_alias_read(self): + """Test obtaining aliases""" + dtb_file = get_dtb_file('dtoc_test_inst.dts') + output = tools.GetOutputFilename('output') + plat = self.run_test(['struct'], dtb_file, output) + + scan = plat._scan + testfdt_node = plat._fdt.GetNode('/some-bus/test') + test0_node = plat._fdt.GetNode('/some-bus/test0') + self.assertIn('UCLASS_TEST_FDT', scan._uclass) + uc = scan._uclass['UCLASS_TEST_FDT'] + self.assertEqual({1: testfdt_node, 2: test0_node}, + uc.alias_num_to_node) + self.assertEqual({'/some-bus/test': 1, '/some-bus/test0': 2}, + uc.alias_path_to_num) + + # Try adding an alias that doesn't exist + self.assertFalse(scan.add_uclass_alias('fred', 3, None)) + + # Try adding an alias for a missing node + self.assertIsNone(scan.add_uclass_alias('testfdt', 3, None)) + + def test_alias_read_bad(self): + """Test invalid alias property name""" + dtb_file = get_dtb_file('dtoc_test_alias_bad.dts') + output = tools.GetOutputFilename('output') + with self.assertRaises(ValueError) as exc: + plat = self.run_test(['struct'], dtb_file, output) + self.assertIn("Cannot decode alias 'i2c4-'", str(exc.exception)) + + def test_alias_read_bad_path(self): + """Test alias pointing to a non-existent node""" + # This line may produce a warning, so capture it: + # Warning (alias_paths): /aliases:i2c4: aliases property is not a valid + # node (/does/not/exist) + dtb_file = get_dtb_file('dtoc_test_alias_bad_path.dts', True) + + output = tools.GetOutputFilename('output') + with self.assertRaises(ValueError) as exc: + plat = self.run_test(['struct'], dtb_file, output) + self.assertIn("Alias 'i2c4' path '/does/not/exist' not found", + str(exc.exception)) + + def test_alias_read_bad_uclass(self): + """Test alias for a uclass that doesn't exist""" + dtb_file = get_dtb_file('dtoc_test_alias_bad_uc.dts') + output = tools.GetOutputFilename('output') + with test_util.capture_sys_output() as (stdout, _): + plat = self.run_test(['struct'], dtb_file, output) + self.assertEqual("Could not find uclass for alias 'other1'", + stdout.getvalue().strip()) + + def test_sequence(self): + """Test assignment of sequence numnbers""" + dtb_file = get_dtb_file('dtoc_test_inst.dts') + output = tools.GetOutputFilename('output') + plat = self.run_test(['struct'], dtb_file, output) + + scan = plat._scan + testfdt = plat._fdt.GetNode('/some-bus/test') + self.assertEqual(1, testfdt.seq) + i2c = plat._fdt.GetNode('/i2c') + + # For now this uclass is not compiled in, so no sequence is assigned + self.assertEqual(4, i2c.seq) + spl = plat._fdt.GetNode('/spl-test') + self.assertEqual(0, spl.seq) + + def test_process_root(self): + """Test assignment of sequence numnbers""" + dtb_file = get_dtb_file('dtoc_test_simple.dts') + output = tools.GetOutputFilename('output') + + # Take a copy before messing with it + scan = copy_scan() + plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False) + plat.scan_dtb() + root = plat._fdt.GetRoot() + + plat.scan_tree(False) + self.assertNotIn(root, plat._valid_nodes) + + plat.scan_tree(True) + self.assertIn(root, plat._valid_nodes) + self.assertEqual('root_driver', + scan.get_normalized_compat_name(root)[0]) + + def test_simple_inst(self): + """Test output from some simple nodes with instantiate enabled""" + dtb_file = get_dtb_file('dtoc_test_inst.dts') + output = tools.GetOutputFilename('output') + + self.run_test(['decl'], dtb_file, output, True) + with open(output) as infile: + data = infile.read() + + self._check_strings(self.decl_text_inst, data) + + self.run_test(['platdata'], dtb_file, output, True) + with open(output) as infile: + data = infile.read() + + self._check_strings(C_HEADER_PRE + ''' +/* This file is not used: --instantiate was enabled */ +''', data) + + self.run_test(['uclass'], dtb_file, output, True) + with open(output) as infile: + data = infile.read() + + self._check_strings(UCLASS_HEADER_COMMON + self.uclass_text_inst, data) + + self.run_test(['device'], dtb_file, output, True) + with open(output) as infile: + data = infile.read() + + self._check_strings(self.device_text_inst, data) + + def test_inst_no_hdr(self): + """Test dealing with a struct tsssshat has no header""" + dtb_file = get_dtb_file('dtoc_test_inst.dts') + output = tools.GetOutputFilename('output') + + # Run it once to set everything up + plat = self.run_test(['decl'], dtb_file, output, True) + scan = plat._scan + + # Restart the output file and delete any record of the uclass' struct + plat.setup_output(Ftype.SOURCE, output) + del scan._structs['dm_test_uc_priv'] + + # Now generate the uclasses, which should provide a warning + with test_util.capture_sys_output() as (stdout, _): + plat.generate_uclasses() + self.assertEqual( + 'Warning: Cannot find header file for struct dm_test_uc_priv', + stdout.getvalue().strip()) |