[PATCH v2 26/33] dtoc: Add support for decl file

Simon Glass sjg at chromium.org
Wed Feb 3 14:01:14 CET 2021


Add an option to generate the declaration file, which declares all
drivers and uclasses, so references can be used in the code.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

(no changes since v1)

 tools/dtoc/dtb_platdata.py | 36 +++++++++++++++
 tools/dtoc/test_dtoc.py    | 91 +++++++++++++++++++++++++++++++++++---
 2 files changed, 120 insertions(+), 7 deletions(-)

diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 46e2725a86c..040b7246787 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -689,6 +689,39 @@ class DtbPlatdata():
             elif result is False:
                 print("Could not find uclass for alias '%s'" % prop.name)
 
+    def generate_decl(self):
+        nodes_to_output = list(self._valid_nodes)
+
+        self.buf('#include <dm/device-internal.h>\n')
+        self.buf('#include <dm/uclass-internal.h>\n')
+        self.buf('\n')
+        self.buf(
+            '/* driver declarations - these allow DM_DRIVER_GET() to be used */\n')
+        for node in nodes_to_output:
+            self.buf('DM_DRIVER_DECL(%s);\n' % node.struct_name);
+        self.buf('\n')
+
+        if self._instantiate:
+            self.buf(
+                '/* device declarations - these allow DM_DEVICE_REF() to be used */\n')
+            for node in nodes_to_output:
+                self.buf('DM_DEVICE_DECL(%s);\n' % node.var_name)
+            self.buf('\n')
+
+        uclass_list = self._valid_uclasses
+
+        self.buf(
+            '/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */\n')
+        for uclass in uclass_list:
+            self.buf('DM_UCLASS_DRIVER_DECL(%s);\n' % uclass.name)
+
+        if self._instantiate:
+            self.buf('\n')
+            self.buf('/* uclass declarations - needed for DM_UCLASS_REF() */\n')
+            for uclass in uclass_list:
+                self.buf('DM_UCLASS_DECL(%s);\n' % uclass.name)
+        self.out(''.join(self.get_buf()))
+
     def assign_seqs(self):
         """Assign a sequence number to each node"""
         for node in self._valid_nodes_unsorted:
@@ -794,6 +827,9 @@ class DtbPlatdata():
 # key: Command used to generate this file
 # value: OutputFile for this command
 OUTPUT_FILES = {
+    'decl':
+        OutputFile(Ftype.HEADER, 'dt-decl.h', DtbPlatdata.generate_decl,
+                   'Declares externs for all device/uclass instances'),
     'struct':
         OutputFile(Ftype.HEADER, 'dt-structs-gen.h',
                    DtbPlatdata.generate_structs,
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index cbddd62424d..a51a7f301ce 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -40,6 +40,14 @@ HEADER = '''/*
 #include <stdbool.h>
 #include <linux/libfdt.h>'''
 
+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 = '''/*
  * DO NOT MODIFY
  *
@@ -213,6 +221,54 @@ 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 */
+DM_DRIVER_DECL(sandbox_i2c);
+DM_DRIVER_DECL(sandbox_pmic);
+DM_DRIVER_DECL(sandbox_spl_test);
+DM_DRIVER_DECL(sandbox_spl_test);
+DM_DRIVER_DECL(sandbox_spl_test);
+
+/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */
+DM_UCLASS_DRIVER_DECL(i2c);
+DM_UCLASS_DRIVER_DECL(misc);
+DM_UCLASS_DRIVER_DECL(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 */
+DM_DRIVER_DECL(sandbox_i2c);
+DM_DRIVER_DECL(sandbox_pmic);
+DM_DRIVER_DECL(root_driver);
+DM_DRIVER_DECL(sandbox_spl_test);
+DM_DRIVER_DECL(sandbox_spl_test);
+DM_DRIVER_DECL(sandbox_spl_test);
+
+/* device declarations - these allow DM_DEVICE_REF() to be used */
+DM_DEVICE_DECL(i2c_at_0);
+DM_DEVICE_DECL(pmic_at_9);
+DM_DEVICE_DECL(root);
+DM_DEVICE_DECL(spl_test);
+DM_DEVICE_DECL(spl_test2);
+DM_DEVICE_DECL(spl_test3);
+
+/* uclass driver declarations - needed for DM_UCLASS_DRIVER_REF() */
+DM_UCLASS_DRIVER_DECL(i2c);
+DM_UCLASS_DRIVER_DECL(misc);
+DM_UCLASS_DRIVER_DECL(pmic);
+DM_UCLASS_DRIVER_DECL(root);
+
+/* uclass declarations - needed for DM_UCLASS_REF() */
+DM_UCLASS_DECL(i2c);
+DM_UCLASS_DECL(misc);
+DM_UCLASS_DECL(pmic);
+DM_UCLASS_DECL(root);
+'''
     struct_text = HEADER + '''
 struct dtd_sandbox_i2c {
 };
@@ -327,10 +383,17 @@ 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.platdata_text +
+                            self.struct_text, data)
 
     def test_driver_alias(self):
         """Test output from a device tree file with a driver alias"""
@@ -916,7 +979,8 @@ 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.platdata_text +
+                            self.struct_text, data)
 
     def test_no_command(self):
         """Test running dtoc without a command"""
@@ -930,9 +994,10 @@ U_BOOT_DRVINFO(spl_test2) = {
         dtb_file = get_dtb_file('dtoc_test_simple.dts')
         output = tools.GetOutputFilename('output')
         with self.assertRaises(ValueError) as exc:
-            self.run_test(['invalid-cmd'], dtb_file, output, False)
-        self.assertIn("Unknown command 'invalid-cmd': (use: platdata, struct)",
-                      str(exc.exception))
+            self.run_test(['invalid-cmd'], dtb_file, output)
+        self.assertIn(
+            "Unknown command 'invalid-cmd': (use: decl, platdata, struct)",
+            str(exc.exception))
 
     def test_output_conflict(self):
         """Test a conflict between and output dirs and output file"""
@@ -959,11 +1024,12 @@ U_BOOT_DRVINFO(spl_test2) = {
             ['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(5, 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-decl.h'},
             leafs)
 
     def setup_process_test(self):
@@ -1149,3 +1215,14 @@ U_BOOT_DRVINFO(spl_test2) = {
         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_simple.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)
-- 
2.30.0.365.g02bc693789-goog



More information about the U-Boot mailing list