...
 
Commits (3)
......@@ -413,6 +413,8 @@ PYTHON3 = python3
DTC ?= $(objtree)/scripts/dtc/dtc
DTOC ?= $(objtree)/tools/dtoc/dtoc
CHECK = sparse
CP = cp
MV = mv
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
-Wbitwise -Wno-return-void -D__CHECK_ENDIAN__ $(CF)
......@@ -1145,7 +1147,6 @@ dtbs: dts/dt.dtb
PHONY += dts/dt.dtb
dts/dt.dtb: tools
$(Q)$(MAKE) $(build)=dts dtbs
$(DTOC) compatible -d dts/dt.dtb -o include/generated/compatible.h
PHONY += compatible
compatible: include/generated/compatible.h
......
......@@ -5,6 +5,10 @@
# This Makefile builds the internal U-Boot fdt if CONFIG_OF_CONTROL is
# enabled. See doc/README.fdt-control for more details.
RM = rm
CP = cp
DTOC = $(objtree)/tools/dtoc/dtoc
DEVICE_TREE ?= $(CONFIG_DEFAULT_DEVICE_TREE:"%"=%)
ifeq ($(DEVICE_TREE),)
DEVICE_TREE := unset
......@@ -16,15 +20,24 @@ else
DTB := arch/$(ARCH)/dts/$(DEVICE_TREE).dtb
endif
$(obj)/dt-spl.dtb: $(DTB) $(objtree)/tools/fdtgrep FORCE
$(obj)/dt-spl.dtb: $(DTB) $(objtree)/tools/fdtgrep $(objtree)/tools/dtoc FORCE
$(call if_changed,fdtgrep)
ifeq ($(CONFIG_OF_DTB_PROPS_REMOVE),y)
$(obj)/dt.dtb: $(DTB) $(objtree)/tools/fdtgrep FORCE
$(RM) $(obj)/dt.dtb
$(call if_changed,fdt_rm_props)
$(CP) $(obj)/dt.dtb $(obj)/dt-full.dtb
$(DTOC) compatible -d $(obj)/dt-full.dtb -o $(obj)/../include/generated/compatible.h
$(DTOC) shrink -d $(obj)/dt-full.dtb -o $(obj)/dt.dtb
else
$(obj)/dt.dtb: $(DTB) FORCE
$(RM) $(obj)/dt.dtb
$(call if_changed,fdt_rm_props)
$(call if_changed,shipped)
$(CP) $(obj)/dt.dtb $(obj)/dt-full.dtb
$(DTOC) compatible -d $(obj)/dt-full.dtb -o $(obj)/../include/generated/compatible.h
$(DTOC) shrink -d $(obj)/dt-full.dtb -o $(obj)/dt.dtb
endif
targets += dt.dtb dt-spl.dtb
......
......@@ -167,6 +167,8 @@ class DtbPlatdata(object):
key: driver name
value: list of struct udevice_id
_dtb_compatible_strings: List of compatible strings found in dtb
_raw_compatible_strings: List of valid raw compatible strings guessed
from drivers/
"""
def __init__(self, dtb_fname, include_disabled, warning_disabled):
self._fdt = None
......@@ -182,6 +184,9 @@ class DtbPlatdata(object):
self._links = []
self._driver_compatible_strings = {}
self._dtb_compatible_strings = []
self._raw_compatible_strings = []
self._configs = []
self._config_file_drivers = {}
def get_normalized_compat_name(self, node):
"""Get a node's normalized compat name
......@@ -346,6 +351,15 @@ class DtbPlatdata(object):
if len(compatible_strings) != 0:
self._driver_compatible_strings[compatible_strings[0][0]] = parse_compatible_strings(compatible_strings)
for comp in compatible_strings:
self._raw_compatible_strings.append(comp[1])
raw_compatible_strings = re.findall('{\s*\.compatible\s*=\s*\"(.+)\"\s*[,}]',
buff)
if len(raw_compatible_strings) != 0:
self._raw_compatible_strings += raw_compatible_strings
def scan_drivers(self):
"""Scan the driver folders to build a list of driver names and aliases
......@@ -361,6 +375,84 @@ class DtbPlatdata(object):
continue
self.scan_driver(dirpath + '/' + fn)
def scan_config(self):
"""Scan the current config file to build a list of options enabled
This procedure will populate self._configs
"""
with open('.config') as f:
buff = f.read()
self._configs = re.findall('(CONFIG_\w*)=y', buff)
if 0:
for conf in self.configs:
print(conf)
def scan_makefile(self, dirpath, fn):
"""Scan a Makefile to build a dictionary of configs and files that
are compiled when this config is enabled
This procedure will populate self._config_file_drivers
"""
with open(dirpath + '/' + fn) as mf:
buff = mf.read()
# Take into account lines broken
buff = buff.replace('\\\n', '')
#Remove tabs
buff = buff.replace('\t', '')
lines = buff.split('\n')
for line in lines:
#Find lines like obj-$(CONFIG_FSL_ESDHC_IMX) += fsl_esdhc_imx.o
#and keep (CONFIG_FSL_ESDHC_IMX, fsl_esdhc_imx.o)
config_file_drivers = re.findall('\((CONFIG_\w*)\)\s*\+=\s*(.*)',
line)
if len(config_file_drivers) == 0:
continue
for cfd in config_file_drivers:
if cfd[1].endswith('/'):
continue
# Split second part as there can be multiple files in a
# line
file_drivers = cfd[1].split(' ')
# Append dirpath to filesnames
file_drivers = [dirpath + '/' + fd for fd in file_drivers]
# Conver to .c source code
file_drivers = [fd.replace('.o', '.c') for fd in file_drivers]
self._config_file_drivers[cfd[0]] = file_drivers
def scan_makefiles(self):
"""Scan all the Makefile in drivers to build a dictionary of configs
and files that are compiled when this config is enabled
This procedure will populate self._config_file_drivers
"""
self.config_drivers = []
self.files_enabled = []
config_drivers = []
for (dirpath, dirnames, filenames) in os.walk('./drivers'):
for fn in filenames:
if fn != 'Makefile':
continue
self.scan_makefile(dirpath, fn)
def scan_drivers_enabled(self):
"""Scan the driver folders to build a list of driver names and aliases,
taking into account only drivers that are enabled
This procedure will populate self._drivers and self._driver_aliases
"""
for conf in self._config_file_drivers.keys():
if conf in self._configs:
fds = self._config_file_drivers[conf]
for fd in fds:
self.scan_driver(fd)
def scan_dtb(self):
"""Scan the device tree to obtain a tree of nodes and properties
......@@ -719,6 +811,32 @@ class DtbPlatdata(object):
for const in constants:
self.out('#define %s\n' % const)
def shrink(self, output):
"""Generate a shrunk version of DTB bases on valid drivers
This function removes nodes from dtb which compatible string is not
found in drivers. The output is saved in a file with suffix name -shrink.dtb
"""
cmd = './tools/fdtgrep '
for comp in self._raw_compatible_strings:
#print(comp)
cmd += ' -c ' + comp
if output != '-':
output = ' -o %s ' % output
else:
output = ''
cmd += ' -O dtb ' + output + self._dtb_fname
if False:
with open('dt_shrink.sh', 'w+') as script:
script.write(cmd)
os.system(cmd)
def run_steps(args, dtb_file, include_disabled, output, warning_disabled=False):
"""Run all the steps of the dtoc tool
......@@ -732,15 +850,23 @@ def run_steps(args, dtb_file, include_disabled, output, warning_disabled=False):
raise ValueError('Please specify a command: struct, platdata')
skip_scan = False
skip_output = False
if args == ['compatible']:
skip_scan = True
if args == ['shrink']:
skip_scan = True
skip_output = True
plat = DtbPlatdata(dtb_file, include_disabled, warning_disabled)
plat.scan_config()
plat.scan_makefiles()
plat.scan_drivers()
plat.scan_dtb()
plat.scan_tree()
plat.scan_reg_sizes()
plat.setup_output(output)
if not skip_output:
plat.setup_output(output)
if not skip_scan:
structs = plat.scan_structs()
plat.scan_phandles()
......@@ -752,6 +878,8 @@ def run_steps(args, dtb_file, include_disabled, output, warning_disabled=False):
plat.generate_tables()
elif cmd == 'compatible':
plat.generate_compatible_strings()
elif cmd == 'shrink':
plat.shrink(output)
else:
raise ValueError("Unknown command '%s': (use: struct, platdata, compatible)" %
raise ValueError("Unknown command '%s': (use: struct, platdata, compatible, shrink)" %
cmd)
// SPDX-License-Identifier: GPL-2.0+
/*
* Test device tree file for dtoc
*
* Copyright 2020 Collabora Ltd.
*/
/dts-v1/;
/ {
gpio_a: gpios@0 {
u-boot,dm-pre-reloc;
gpio-controller;
compatible = "sandbox_gpio_alias";
#gpio-cells = <1>;
gpio-bank-name = "a";
sandbox,gpio-count = <20>;
};
};