dtoc: Show driver warnings once at the end

At present warnings are shown as soon as they are discovered in the
source scannner. But the function that detects them may be called multiple
times.

Collect all the warnings and show them at the end.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index c9c657c..dd97a6b 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -1194,8 +1194,7 @@
         raise ValueError('Must specify either output or output_dirs, not both')
 
     if not scan:
-        scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional,
-                                phase)
+        scan = src_scan.Scanner(basedir, drivers_additional, phase)
         scan.scan_drivers()
         do_process = True
     else:
@@ -1232,4 +1231,7 @@
         plat.out_header(outfile)
         outfile.method(plat)
     plat.finish_output()
+
+    if not warning_disabled:
+        scan.show_warnings()
     return plat
diff --git a/tools/dtoc/src_scan.py b/tools/dtoc/src_scan.py
index 114212c..2db9688 100644
--- a/tools/dtoc/src_scan.py
+++ b/tools/dtoc/src_scan.py
@@ -188,7 +188,6 @@
             key: Driver alias declared with
                 DM_DRIVER_ALIAS(driver_alias, driver_name)
             value: Driver name declared with U_BOOT_DRIVER(driver_name)
-        _warning_disabled: true to disable warnings about driver names not found
         _drivers_additional (list or str): List of additional drivers to use
             during scanning
         _of_match: Dict holding information about compatible strings
@@ -206,7 +205,7 @@
         _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, phase=''):
+    def __init__(self, basedir, drivers_additional, phase=''):
         """Set up a new Scanner
         """
         if not basedir:
@@ -217,7 +216,7 @@
         self._drivers = {}
         self._driver_aliases = {}
         self._drivers_additional = drivers_additional or []
-        self._warning_disabled = warning_disabled
+        self._missing_drivers = set()
         self._of_match = {}
         self._compat_to_driver = {}
         self._uclass = {}
@@ -268,9 +267,7 @@
                 aliases_c.remove(compat_c)
             return compat_c, aliases_c
 
-        if not self._warning_disabled:
-            print('WARNING: the driver %s was not found in the driver list'
-                  % (compat_list_c[0]))
+        self._missing_drivers.add(compat_list_c[0])
 
         return compat_list_c[0], compat_list_c[1:]
 
@@ -578,6 +575,12 @@
             self._drivers[driver.name] = driver
         self._of_match.update(of_match)
 
+    def show_warnings(self):
+        """Show any warnings that have been collected"""
+        for name in sorted(list(self._missing_drivers)):
+            print('WARNING: the driver %s was not found in the driver list'
+                  % name)
+
     def scan_driver(self, fname):
         """Scan a driver file to build a list of driver names and aliases
 
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index e951283..458d683 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -104,7 +104,7 @@
 
     # Disable warnings so that calls to get_normalized_compat_name() will not
     # output things.
-    saved_scan = src_scan.Scanner(None, True, False)
+    saved_scan = src_scan.Scanner(None, False)
     saved_scan.scan_drivers()
 
 def copy_scan():
diff --git a/tools/dtoc/test_src_scan.py b/tools/dtoc/test_src_scan.py
index 0af86dc..d6da038 100644
--- a/tools/dtoc/test_src_scan.py
+++ b/tools/dtoc/test_src_scan.py
@@ -48,7 +48,7 @@
 
     def test_simple(self):
         """Simple test of scanning drivers"""
-        scan = src_scan.Scanner(None, True, None)
+        scan = src_scan.Scanner(None, None)
         scan.scan_drivers()
         self.assertIn('sandbox_gpio', scan._drivers)
         self.assertIn('sandbox_gpio_alias', scan._driver_aliases)
@@ -59,8 +59,7 @@
     def test_additional(self):
         """Test with additional drivers to scan"""
         scan = src_scan.Scanner(
-            None, True,
-            [None, '', 'tools/dtoc/test/dtoc_test_scan_drivers.cxx'])
+            None, [None, '', 'tools/dtoc/test/dtoc_test_scan_drivers.cxx'])
         scan.scan_drivers()
         self.assertIn('sandbox_gpio_alias2', scan._driver_aliases)
         self.assertEqual('sandbox_gpio',
@@ -77,7 +76,7 @@
         with open(driver_fn, 'wb+') as fout:
             fout.write(b'\x81')
 
-        scan = src_scan.Scanner(None, True, [driver_fn])
+        scan = src_scan.Scanner(None, [driver_fn])
         with test_util.capture_sys_output() as (stdout, _):
             scan.scan_drivers()
         self.assertRegex(stdout.getvalue(),
@@ -126,7 +125,7 @@
             # Mock out scan_driver and check that it is called with the
             # expected files
             with mock.patch.object(src_scan.Scanner, "scan_driver")  as mocked:
-                scan = src_scan.Scanner(indir, True, None)
+                scan = src_scan.Scanner(indir, None)
                 scan.scan_drivers()
             self.assertEqual(2, len(mocked.mock_calls))
             self.assertEqual(mock.call(fname_list[0]),
@@ -141,7 +140,7 @@
         """Test scanning of a driver"""
         fname = os.path.join(OUR_PATH, '..', '..', 'drivers/i2c/tegra_i2c.c')
         buff = tools.ReadFile(fname, False)
-        scan = src_scan.Scanner(None, False, None)
+        scan = src_scan.Scanner(None, None)
         scan._parse_driver(fname, buff)
         self.assertIn('i2c_tegra', scan._drivers)
         drv = scan._drivers['i2c_tegra']
@@ -165,14 +164,15 @@
         # get_normalized_compat_name() uses this to check for root node
         node.parent = FakeNode()
 
-        scan = src_scan.Scanner(None, False, None)
+        scan = src_scan.Scanner(None, None)
         with test_util.capture_sys_output() as (stdout, _):
             name, aliases = scan.get_normalized_compat_name(node)
         self.assertEqual('rockchip_rk3288_grf', name)
         self.assertEqual([], aliases)
-        self.assertEqual(
-            'WARNING: the driver rockchip_rk3288_grf was not found in the driver list',
-            stdout.getvalue().strip())
+        self.assertEqual(1, len(scan._missing_drivers))
+        self.assertEqual({'rockchip_rk3288_grf'}, scan._missing_drivers)
+            #'WARNING: the driver rockchip_rk3288_grf was not found in the driver list',
+            #stdout.getvalue().strip())
 
         i2c = 'I2C_UCLASS'
         compat = {'rockchip,rk3288-grf': 'ROCKCHIP_SYSCON_GRF',
@@ -211,7 +211,7 @@
 	.of_match = tegra_i2c_ids,
 };
 '''
-        scan = src_scan.Scanner(None, False, None)
+        scan = src_scan.Scanner(None, None)
         with self.assertRaises(ValueError) as exc:
             scan._parse_driver('file.c', buff)
         self.assertIn(
@@ -232,7 +232,7 @@
 	.of_match = of_match_ptr(tegra_i2c_ids),
 };
 '''
-        scan = src_scan.Scanner(None, False, None)
+        scan = src_scan.Scanner(None, None)
         scan._parse_driver('file.c', buff)
         self.assertIn('i2c_tegra', scan._drivers)
         drv = scan._drivers['i2c_tegra']
@@ -261,7 +261,7 @@
 	DM_HEADER(<asm/clk.h>)
 };
 '''
-        scan = src_scan.Scanner(None, False, None)
+        scan = src_scan.Scanner(None, None)
         scan._parse_driver('file.c', buff)
         self.assertIn('testing', scan._drivers)
         drv = scan._drivers['testing']
@@ -293,7 +293,7 @@
 };
 
 '''
-        scan = src_scan.Scanner(None, False, None)
+        scan = src_scan.Scanner(None, None)
         scan._parse_uclass_driver('file.c', buff)
         self.assertIn('UCLASS_I2C', scan._uclass)
         drv = scan._uclass['UCLASS_I2C']
@@ -325,7 +325,7 @@
 };
 
 '''
-        scan = src_scan.Scanner(None, False, None)
+        scan = src_scan.Scanner(None, None)
         with self.assertRaises(ValueError) as exc:
             scan._parse_uclass_driver('file.c', buff)
         self.assertIn("file.c: Cannot parse uclass ID in driver 'i2c'",
@@ -340,7 +340,7 @@
 	uint nmsgs;
 };
 '''
-        scan = src_scan.Scanner(None, False, None)
+        scan = src_scan.Scanner(None, None)
         scan._basedir = os.path.join(OUR_PATH, '..', '..')
         scan._parse_structs('arch/arm/include/asm/file.h', buff)
         self.assertIn('some_struct1', scan._structs)
@@ -371,7 +371,7 @@
         output = tools.GetOutputFilename('output.h')
         tools.WriteFile(output, b'struct this is a test \x81 of bad unicode')
 
-        scan = src_scan.Scanner(None, False, None)
+        scan = src_scan.Scanner(None, None)
         with test_util.capture_sys_output() as (stdout, _):
             scan.scan_header(output)
         self.assertIn('due to unicode error', stdout.getvalue())
@@ -411,7 +411,7 @@
 	.of_match = test_ids,
 };
 ''' % name
-        scan = src_scan.Scanner(None, False, None, phase)
+        scan = src_scan.Scanner(None, None, phase)
         scan._parse_driver('file1.c', driver1)
         self.assertIn(name, scan._drivers)
         drv1 = scan._drivers[name]
@@ -476,7 +476,7 @@
 
     def test_sequence(self):
         """Test assignment of sequence numnbers"""
-        scan = src_scan.Scanner(None, False, None, '')
+        scan = src_scan.Scanner(None, None, '')
         node = FakeNode()
         uc = src_scan.UclassDriver('UCLASS_I2C')
         node.uclass = uc