mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 06:31:31 +00:00
dtoc: Support tracking the phase of U-Boot
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>
This commit is contained in:
parent
b9319c4f9b
commit
b00f0066e5
6 changed files with 47 additions and 12 deletions
|
@ -369,6 +369,22 @@ struct driver {
|
||||||
*/
|
*/
|
||||||
#define DM_DRIVER_ALIAS(__name, __alias)
|
#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
|
* dev_get_plat() - Get the platform data for a device
|
||||||
*
|
*
|
||||||
|
|
|
@ -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,
|
warning_disabled=False, drivers_additional=None, basedir=None,
|
||||||
scan=None):
|
scan=None):
|
||||||
"""Run all the steps of the dtoc tool
|
"""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):
|
output_dirs (tuple of str):
|
||||||
Directory to put C output files
|
Directory to put C output files
|
||||||
Directory to put H 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
|
warning_disabled (bool): True to avoid showing warnings about missing
|
||||||
drivers
|
drivers
|
||||||
drivers_additional (list): List of additional drivers to use during
|
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')
|
raise ValueError('Must specify either output or output_dirs, not both')
|
||||||
|
|
||||||
if not scan:
|
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()
|
scan.scan_drivers()
|
||||||
do_process = True
|
do_process = True
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -85,6 +85,8 @@ parser.add_option('--include-disabled', action='store_true',
|
||||||
help='Include disabled nodes')
|
help='Include disabled nodes')
|
||||||
parser.add_option('-o', '--output', action='store',
|
parser.add_option('-o', '--output', action='store',
|
||||||
help='Select output filename')
|
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,
|
parser.add_option('-P', '--processes', type=int,
|
||||||
help='set number of processes to use for running tests')
|
help='set number of processes to use for running tests')
|
||||||
parser.add_option('-t', '--test', action='store_true', dest='test',
|
parser.add_option('-t', '--test', action='store_true', dest='test',
|
||||||
|
@ -104,4 +106,5 @@ elif options.test_coverage:
|
||||||
else:
|
else:
|
||||||
dtb_platdata.run_steps(args, options.dtb_file, options.include_disabled,
|
dtb_platdata.run_steps(args, options.dtb_file, options.include_disabled,
|
||||||
options.output,
|
options.output,
|
||||||
[options.c_output_dir, options.h_output_dir])
|
[options.c_output_dir, options.h_output_dir],
|
||||||
|
phase=options.phase)
|
||||||
|
|
|
@ -67,6 +67,7 @@ class Driver:
|
||||||
child_plat (str): struct name of the per_child_plat_auto member,
|
child_plat (str): struct name of the per_child_plat_auto member,
|
||||||
e.g. 'pci_child_plat'
|
e.g. 'pci_child_plat'
|
||||||
used (bool): True if the driver is used by the structs being output
|
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):
|
def __init__(self, name, fname):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -78,6 +79,7 @@ class Driver:
|
||||||
self.child_priv = ''
|
self.child_priv = ''
|
||||||
self.child_plat = ''
|
self.child_plat = ''
|
||||||
self.used = False
|
self.used = False
|
||||||
|
self.phase = ''
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return (self.name == other.name and
|
return (self.name == other.name and
|
||||||
|
@ -173,8 +175,10 @@ class Scanner:
|
||||||
_structs: Dict of all structs found in U-Boot:
|
_structs: Dict of all structs found in U-Boot:
|
||||||
key: Name of struct
|
key: Name of struct
|
||||||
value: Struct object
|
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
|
"""Set up a new Scanner
|
||||||
"""
|
"""
|
||||||
if not basedir:
|
if not basedir:
|
||||||
|
@ -190,6 +194,7 @@ class Scanner:
|
||||||
self._compat_to_driver = {}
|
self._compat_to_driver = {}
|
||||||
self._uclass = {}
|
self._uclass = {}
|
||||||
self._structs = {}
|
self._structs = {}
|
||||||
|
self._phase = phase
|
||||||
|
|
||||||
def get_driver(self, name):
|
def get_driver(self, name):
|
||||||
"""Get a driver given its name
|
"""Get a driver given its name
|
||||||
|
@ -428,6 +433,8 @@ class Scanner:
|
||||||
re_of_match = re.compile(
|
re_of_match = re.compile(
|
||||||
r'\.of_match\s*=\s*(of_match_ptr\()?([a-z0-9_]+)(\))?,')
|
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
|
# Matches the struct name for priv, plat
|
||||||
re_priv = self._get_re_for_member('priv_auto')
|
re_priv = self._get_re_for_member('priv_auto')
|
||||||
re_plat = self._get_re_for_member('plat_auto')
|
re_plat = self._get_re_for_member('plat_auto')
|
||||||
|
@ -454,6 +461,7 @@ class Scanner:
|
||||||
m_plat = re_plat.match(line)
|
m_plat = re_plat.match(line)
|
||||||
m_cplat = re_child_plat.match(line)
|
m_cplat = re_child_plat.match(line)
|
||||||
m_cpriv = re_child_priv.match(line)
|
m_cpriv = re_child_priv.match(line)
|
||||||
|
m_phase = re_phase.match(line)
|
||||||
if m_priv:
|
if m_priv:
|
||||||
driver.priv = m_priv.group(1)
|
driver.priv = m_priv.group(1)
|
||||||
elif m_plat:
|
elif m_plat:
|
||||||
|
@ -466,6 +474,8 @@ class Scanner:
|
||||||
driver.uclass_id = m_id.group(1)
|
driver.uclass_id = m_id.group(1)
|
||||||
elif m_of_match:
|
elif m_of_match:
|
||||||
compat = m_of_match.group(2)
|
compat = m_of_match.group(2)
|
||||||
|
elif m_phase:
|
||||||
|
driver.phase = m_phase.group(1)
|
||||||
elif '};' in line:
|
elif '};' in line:
|
||||||
if driver.uclass_id and compat:
|
if driver.uclass_id and compat:
|
||||||
if compat not in of_match:
|
if compat not in of_match:
|
||||||
|
|
|
@ -138,8 +138,8 @@ class TestDtoc(unittest.TestCase):
|
||||||
dtb_file (str): Filename of .dtb file
|
dtb_file (str): Filename of .dtb file
|
||||||
output (str): Filename of output file
|
output (str): Filename of output file
|
||||||
"""
|
"""
|
||||||
dtb_platdata.run_steps(args, dtb_file, False, output, [], True,
|
dtb_platdata.run_steps(args, dtb_file, False, output, [], None,
|
||||||
None, None, scan=copy_scan())
|
warning_disabled=True, scan=copy_scan())
|
||||||
|
|
||||||
def test_name(self):
|
def test_name(self):
|
||||||
"""Test conversion of device tree names to C identifiers"""
|
"""Test conversion of device tree names to C identifiers"""
|
||||||
|
@ -365,7 +365,7 @@ U_BOOT_DRVINFO(gpios_at_0) = {
|
||||||
output = tools.GetOutputFilename('output')
|
output = tools.GetOutputFilename('output')
|
||||||
with test_util.capture_sys_output() as _:
|
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, [],
|
||||||
scan=copy_scan())
|
None, scan=copy_scan())
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._check_strings(HEADER + '''
|
self._check_strings(HEADER + '''
|
||||||
|
@ -375,7 +375,7 @@ struct dtd_invalid {
|
||||||
|
|
||||||
with test_util.capture_sys_output() as _:
|
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, [],
|
||||||
scan=copy_scan())
|
None, scan=copy_scan())
|
||||||
with open(output) as infile:
|
with open(output) as infile:
|
||||||
data = infile.read()
|
data = infile.read()
|
||||||
self._check_strings(C_HEADER + '''
|
self._check_strings(C_HEADER + '''
|
||||||
|
@ -927,8 +927,8 @@ U_BOOT_DRVINFO(spl_test2) = {
|
||||||
def test_output_conflict(self):
|
def test_output_conflict(self):
|
||||||
"""Test a conflict between and output dirs and output file"""
|
"""Test a conflict between and output dirs and output file"""
|
||||||
with self.assertRaises(ValueError) as exc:
|
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,
|
||||||
scan=copy_scan())
|
warning_disabled=True, scan=copy_scan())
|
||||||
self.assertIn("Must specify either output or output_dirs, not both",
|
self.assertIn("Must specify either output or output_dirs, not both",
|
||||||
str(exc.exception))
|
str(exc.exception))
|
||||||
|
|
||||||
|
@ -944,8 +944,8 @@ U_BOOT_DRVINFO(spl_test2) = {
|
||||||
fnames = glob.glob(outdir + '/*')
|
fnames = glob.glob(outdir + '/*')
|
||||||
self.assertEqual(2, len(fnames))
|
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,
|
||||||
scan=copy_scan())
|
warning_disabled=True, scan=copy_scan())
|
||||||
fnames = glob.glob(outdir + '/*')
|
fnames = glob.glob(outdir + '/*')
|
||||||
self.assertEqual(4, len(fnames))
|
self.assertEqual(4, len(fnames))
|
||||||
|
|
||||||
|
|
|
@ -233,6 +233,7 @@ U_BOOT_DRIVER(i2c_tegra) = {
|
||||||
self.assertIn('i2c_tegra', scan._drivers)
|
self.assertIn('i2c_tegra', scan._drivers)
|
||||||
drv = scan._drivers['i2c_tegra']
|
drv = scan._drivers['i2c_tegra']
|
||||||
self.assertEqual('i2c_tegra', drv.name)
|
self.assertEqual('i2c_tegra', drv.name)
|
||||||
|
self.assertEqual('', drv.phase)
|
||||||
|
|
||||||
def test_priv(self):
|
def test_priv(self):
|
||||||
"""Test collection of struct info from drivers"""
|
"""Test collection of struct info from drivers"""
|
||||||
|
@ -250,6 +251,7 @@ U_BOOT_DRIVER(testing) = {
|
||||||
.plat_auto = sizeof(struct some_plat),
|
.plat_auto = sizeof(struct some_plat),
|
||||||
.per_child_auto = sizeof(struct some_cpriv),
|
.per_child_auto = sizeof(struct some_cpriv),
|
||||||
.per_child_plat_auto = sizeof(struct some_cplat),
|
.per_child_plat_auto = sizeof(struct some_cplat),
|
||||||
|
DM_PHASE(tpl)
|
||||||
};
|
};
|
||||||
'''
|
'''
|
||||||
scan = src_scan.Scanner(None, False, None)
|
scan = src_scan.Scanner(None, False, None)
|
||||||
|
@ -264,6 +266,7 @@ U_BOOT_DRIVER(testing) = {
|
||||||
self.assertEqual('some_plat', drv.plat)
|
self.assertEqual('some_plat', drv.plat)
|
||||||
self.assertEqual('some_cpriv', drv.child_priv)
|
self.assertEqual('some_cpriv', drv.child_priv)
|
||||||
self.assertEqual('some_cplat', drv.child_plat)
|
self.assertEqual('some_cplat', drv.child_plat)
|
||||||
|
self.assertEqual('tpl', drv.phase)
|
||||||
self.assertEqual(1, len(scan._drivers))
|
self.assertEqual(1, len(scan._drivers))
|
||||||
|
|
||||||
def test_uclass_scan(self):
|
def test_uclass_scan(self):
|
||||||
|
|
Loading…
Add table
Reference in a new issue