]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
dtoc: Support tracking the phase of U-Boot
authorSimon Glass <sjg@chromium.org>
Wed, 3 Feb 2021 13:01:02 +0000 (06:01 -0700)
committerSimon Glass <sjg@chromium.org>
Mon, 22 Mar 2021 06:23:27 +0000 (19:23 +1300)
U-Boot operates in several phases, typically TPL, SPL and U-Boot proper.
The latter does not use dtoc.

In some rare cases different drivers are used for two phases. For example,
in TPL it may not be necessary to use the full PCI subsystem, so a simple
driver can be used instead.

This works in the build system simply by compiling in one driver or the
other (e.g. PCI driver + uclass for SPL; simple_bus for TPL). But dtoc has
no way of knowing which code is compiled in for which phase, since it does
not inspect Makefiles or dependency graphs.

So to make this work for dtoc, we need to be able to explicitly mark
drivers with their phase. This is done by adding an empty macro to the
driver. Add support for this in dtoc.

Signed-off-by: Simon Glass <sjg@chromium.org>
include/dm/device.h
tools/dtoc/dtb_platdata.py
tools/dtoc/main.py
tools/dtoc/src_scan.py
tools/dtoc/test_dtoc.py
tools/dtoc/test_src_scan.py

index bb9faa0ed93471a56623cf84cd6707dce6d78978..84df5b9e95a5fc4f34bdebc1f71de08996806760 100644 (file)
@@ -369,6 +369,22 @@ struct driver {
  */
 #define DM_DRIVER_ALIAS(__name, __alias)
 
+/**
+ * Declare a macro to indicate which phase of U-Boot this driver is fore.
+ *
+ *
+ * This macro produces no code but its information will be parsed by dtoc. The
+ * macro can be only be used once in a driver. Put it within the U_BOOT_DRIVER()
+ * declaration, e.g.:
+ *
+ * U_BOOT_DRIVER(cpu) = {
+ *     .name = ...
+ *     ...
+ *     DM_PHASE(tpl)
+ * };
+ */
+#define DM_PHASE(_phase)
+
 /**
  * dev_get_plat() - Get the platform data for a device
  *
index 28669f3121784e7e270efce5a4ad05be1c7122b9..ef0454c8904b87ff8d3d985bbec60ff703eb3cce 100644 (file)
@@ -733,7 +733,7 @@ OUTPUT_FILES = {
     }
 
 
-def run_steps(args, dtb_file, include_disabled, output, output_dirs,
+def run_steps(args, dtb_file, include_disabled, output, output_dirs, phase,
               warning_disabled=False, drivers_additional=None, basedir=None,
               scan=None):
     """Run all the steps of the dtoc tool
@@ -746,6 +746,8 @@ def run_steps(args, dtb_file, include_disabled, output, output_dirs,
         output_dirs (tuple of str):
             Directory to put C output files
             Directory to put H output files
+        phase: The phase of U-Boot that we are generating data for, e.g. 'spl'
+             or 'tpl'. None if not known
         warning_disabled (bool): True to avoid showing warnings about missing
             drivers
         drivers_additional (list): List of additional drivers to use during
@@ -764,7 +766,8 @@ def run_steps(args, dtb_file, include_disabled, output, output_dirs,
         raise ValueError('Must specify either output or output_dirs, not both')
 
     if not scan:
-        scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional)
+        scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional,
+                                phase)
         scan.scan_drivers()
         do_process = True
     else:
index 355b1e62773228cc2931706aa71dcc9199ddb832..15a8ff167a9e0a40c48d60d5dc924b8dac5647f8 100755 (executable)
@@ -85,6 +85,8 @@ parser.add_option('--include-disabled', action='store_true',
                   help='Include disabled nodes')
 parser.add_option('-o', '--output', action='store',
                   help='Select output filename')
+parser.add_option('-p', '--phase', type=str,
+                  help='set phase of U-Boot this invocation is for (spl/tpl)')
 parser.add_option('-P', '--processes', type=int,
                   help='set number of processes to use for running tests')
 parser.add_option('-t', '--test', action='store_true', dest='test',
@@ -104,4 +106,5 @@ elif options.test_coverage:
 else:
     dtb_platdata.run_steps(args, options.dtb_file, options.include_disabled,
                            options.output,
-                           [options.c_output_dir, options.h_output_dir])
+                           [options.c_output_dir, options.h_output_dir],
+                           phase=options.phase)
index 1a02d41063f4c2f1a08de3b3527d4d85a788de0f..2699153016c0308b33469d54823a517be6175dcf 100644 (file)
@@ -67,6 +67,7 @@ class Driver:
         child_plat (str): struct name of the per_child_plat_auto member,
             e.g. 'pci_child_plat'
         used (bool): True if the driver is used by the structs being output
+        phase (str): Which phase of U-Boot to use this driver
     """
     def __init__(self, name, fname):
         self.name = name
@@ -78,6 +79,7 @@ class Driver:
         self.child_priv = ''
         self.child_plat = ''
         self.used = False
+        self.phase = ''
 
     def __eq__(self, other):
         return (self.name == other.name and
@@ -173,8 +175,10 @@ class Scanner:
         _structs: Dict of all structs found in U-Boot:
             key: Name of struct
             value: Struct object
+        _phase: The phase of U-Boot that we are generating data for, e.g. 'spl'
+             or 'tpl'. None if not known
     """
-    def __init__(self, basedir, warning_disabled, drivers_additional):
+    def __init__(self, basedir, warning_disabled, drivers_additional, phase=''):
         """Set up a new Scanner
         """
         if not basedir:
@@ -190,6 +194,7 @@ class Scanner:
         self._compat_to_driver = {}
         self._uclass = {}
         self._structs = {}
+        self._phase = phase
 
     def get_driver(self, name):
         """Get a driver given its name
@@ -428,6 +433,8 @@ class Scanner:
         re_of_match = re.compile(
             r'\.of_match\s*=\s*(of_match_ptr\()?([a-z0-9_]+)(\))?,')
 
+        re_phase = re.compile('^\s*DM_PHASE\((.*)\).*$')
+
         # Matches the struct name for priv, plat
         re_priv = self._get_re_for_member('priv_auto')
         re_plat = self._get_re_for_member('plat_auto')
@@ -454,6 +461,7 @@ class Scanner:
                 m_plat = re_plat.match(line)
                 m_cplat = re_child_plat.match(line)
                 m_cpriv = re_child_priv.match(line)
+                m_phase = re_phase.match(line)
                 if m_priv:
                     driver.priv = m_priv.group(1)
                 elif m_plat:
@@ -466,6 +474,8 @@ class Scanner:
                     driver.uclass_id = m_id.group(1)
                 elif m_of_match:
                     compat = m_of_match.group(2)
+                elif m_phase:
+                    driver.phase = m_phase.group(1)
                 elif '};' in line:
                     if driver.uclass_id and compat:
                         if compat not in of_match:
index d90ece205d7cde01dadecd228c969f84a2b8a80d..c1fafb656fb5417a1b326df049dfff2bbaf71456 100755 (executable)
@@ -138,8 +138,8 @@ class TestDtoc(unittest.TestCase):
             dtb_file (str): Filename of .dtb file
             output (str): Filename of output file
         """
-        dtb_platdata.run_steps(args, dtb_file, False, output, [], True,
-                               None, None, scan=copy_scan())
+        dtb_platdata.run_steps(args, dtb_file, False, output, [], None,
+                               warning_disabled=True, scan=copy_scan())
 
     def test_name(self):
         """Test conversion of device tree names to C identifiers"""
@@ -365,7 +365,7 @@ U_BOOT_DRVINFO(gpios_at_0) = {
         output = tools.GetOutputFilename('output')
         with test_util.capture_sys_output() as _:
             dtb_platdata.run_steps(['struct'], dtb_file, False, output, [],
-                                   scan=copy_scan())
+                                   None, scan=copy_scan())
         with open(output) as infile:
             data = infile.read()
         self._check_strings(HEADER + '''
@@ -375,7 +375,7 @@ struct dtd_invalid {
 
         with test_util.capture_sys_output() as _:
             dtb_platdata.run_steps(['platdata'], dtb_file, False, output, [],
-                                   scan=copy_scan())
+                                   None, scan=copy_scan())
         with open(output) as infile:
             data = infile.read()
         self._check_strings(C_HEADER + '''
@@ -927,8 +927,8 @@ U_BOOT_DRVINFO(spl_test2) = {
     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,
-                                   scan=copy_scan())
+            dtb_platdata.run_steps(['all'], None, False, 'out', ['cdir'], None,
+                                   warning_disabled=True, scan=copy_scan())
         self.assertIn("Must specify either output or output_dirs, not both",
                       str(exc.exception))
 
@@ -944,8 +944,8 @@ 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,
-                               scan=copy_scan())
+        dtb_platdata.run_steps(['all'], dtb_file, False, None, [outdir], None,
+                               warning_disabled=True, scan=copy_scan())
         fnames = glob.glob(outdir + '/*')
         self.assertEqual(4, len(fnames))
 
index ebdc12abc87c46b0d804d2ff13823c2ac85e640b..8d35b33c28a5ff52cc41debac45a1f547366cd90 100644 (file)
@@ -233,6 +233,7 @@ U_BOOT_DRIVER(i2c_tegra) = {
         self.assertIn('i2c_tegra', scan._drivers)
         drv = scan._drivers['i2c_tegra']
         self.assertEqual('i2c_tegra', drv.name)
+        self.assertEqual('', drv.phase)
 
     def test_priv(self):
         """Test collection of struct info from drivers"""
@@ -250,6 +251,7 @@ U_BOOT_DRIVER(testing) = {
        .plat_auto = sizeof(struct some_plat),
        .per_child_auto = sizeof(struct some_cpriv),
        .per_child_plat_auto = sizeof(struct some_cplat),
+       DM_PHASE(tpl)
 };
 '''
         scan = src_scan.Scanner(None, False, None)
@@ -264,6 +266,7 @@ U_BOOT_DRIVER(testing) = {
         self.assertEqual('some_plat', drv.plat)
         self.assertEqual('some_cpriv', drv.child_priv)
         self.assertEqual('some_cplat', drv.child_plat)
+        self.assertEqual('tpl', drv.phase)
         self.assertEqual(1, len(scan._drivers))
 
     def test_uclass_scan(self):