From patchwork Thu Jun 25 04:10:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Lozano X-Patchwork-Id: 1316718 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=collabora.com Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49smm51JCzz9sRW for ; Thu, 25 Jun 2020 14:11:17 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id EA303820E5; Thu, 25 Jun 2020 06:11:09 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 6B8DE820F7; Thu, 25 Jun 2020 06:11:02 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_PASS, UNPARSEABLE_RELAY,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 8744F820E5 for ; Thu, 25 Jun 2020 06:10:55 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=walter.lozano@collabora.com Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: wlozano) with ESMTPSA id A71502A4FF0 From: Walter Lozano To: u-boot@lists.denx.de, Simon Glass Cc: Walter Lozano , Heinrich Schuchardt Subject: [PATCH v4 04/14] dtoc: add support to scan drivers Date: Thu, 25 Jun 2020 01:10:07 -0300 Message-Id: <20200625041017.26204-5-walter.lozano@collabora.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200625041017.26204-1-walter.lozano@collabora.com> References: <20200625041017.26204-1-walter.lozano@collabora.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean Currently dtoc scans dtbs to convert them to struct platdata and to generate U_BOOT_DEVICE entries. These entries need to be filled with the driver name, but at this moment the information used is the compatible name present in the dtb. This causes that only nodes with a compatible name that matches a driver name generate a working entry. In order to improve this behaviour, this patch adds to dtoc the capability of scan drivers source code to generate a list of valid driver names and aliases. This allows to generate U_BOOT_DEVICE entries using valid driver names and rise a warning in the case a name is not valid. Signed-off-by: Walter Lozano Reviewed-by: Simon Glass --- tools/dtoc/dtb_platdata.py | 91 ++++++++++++++++++++++++++++++++++++-- tools/dtoc/test_dtoc.py | 33 ++++++++++++++ 2 files changed, 120 insertions(+), 4 deletions(-) diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index bc0de426a9..ae8674d85c 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -13,6 +13,8 @@ static data. import collections import copy +import os +import re import sys from dtoc import fdt @@ -143,6 +145,11 @@ class DtbPlatdata(object): _aliases: Dict that hold aliases for compatible strings key: First compatible string declared in a node value: List of additional compatible strings declared in a node + _drivers: List of valid driver names found in drivers/ + _driver_aliases: Dict that holds aliases for driver names + key: Driver alias declared with + U_BOOT_DRIVER_ALIAS(driver_alias, driver_name) + value: Driver name declared with U_BOOT_DRIVER(driver_name) """ def __init__(self, dtb_fname, include_disabled): self._fdt = None @@ -152,6 +159,38 @@ class DtbPlatdata(object): self._outfile = None self._lines = [] self._aliases = {} + self._drivers = [] + self._driver_aliases = {} + + def get_normalized_compat_name(self, node): + """Get a node's normalized compat name + + Returns a valid driver name by retrieving node's first compatible + string as a C identifier and performing a check against _drivers + and a lookup in driver_aliases printing a warning in case of failure. + + Args: + node: Node object to check + Return: + Tuple: + Driver name associated with the first compatible string + List of C identifiers for all the other compatible strings + (possibly empty) + In case of no match found, the return will be the same as + get_compat_name() + """ + compat_c, aliases_c = get_compat_name(node) + if compat_c not in self._drivers: + compat_c_old = compat_c + compat_c = self._driver_aliases.get(compat_c) + if not compat_c: + print('WARNING: the driver %s was not found in the driver list' + % (compat_c_old)) + compat_c = compat_c_old + else: + aliases_c = [compat_c_old] + aliases_c + + return compat_c, aliases_c def setup_output(self, fname): """Set up the output destination @@ -246,6 +285,49 @@ class DtbPlatdata(object): return PhandleInfo(max_args, args) return None + def scan_driver(self, fn): + """Scan a driver file to build a list of driver names and aliases + + This procedure will populate self._drivers and self._driver_aliases + + Args + fn: Driver filename to scan + """ + with open(fn) as fd: + buff = fd.read() + + # The following re will search for driver names declared as + # U_BOOT_DRIVER(driver_name) + drivers = re.findall('U_BOOT_DRIVER\((.*)\)', buff) + + for driver in drivers: + self._drivers.append(driver) + + # The following re will search for driver aliases declared as + # U_BOOT_DRIVER_ALIAS(alias, driver_name) + driver_aliases = re.findall('U_BOOT_DRIVER_ALIAS\(\s*(\w+)\s*,\s*(\w+)\s*\)', + buff) + + for alias in driver_aliases: # pragma: no cover + if len(alias) != 2: + continue + self._driver_aliases[alias[1]] = alias[0] + + def scan_drivers(self): + """Scan the driver folders to build a list of driver names and aliases + + This procedure will populate self._drivers and self._driver_aliases + + """ + basedir = sys.argv[0].replace('tools/dtoc/dtoc', '') + if basedir == '': + basedir = './' + for (dirpath, dirnames, filenames) in os.walk(basedir): + for fn in filenames: + if not fn.endswith('.c'): + continue + self.scan_driver(dirpath + '/' + fn) + def scan_dtb(self): """Scan the device tree to obtain a tree of nodes and properties @@ -356,7 +438,7 @@ class DtbPlatdata(object): """ structs = {} for node in self._valid_nodes: - node_name, _ = get_compat_name(node) + node_name, _ = self.get_normalized_compat_name(node) fields = {} # Get a list of all the valid properties in this node. @@ -380,14 +462,14 @@ class DtbPlatdata(object): upto = 0 for node in self._valid_nodes: - node_name, _ = get_compat_name(node) + node_name, _ = self.get_normalized_compat_name(node) struct = structs[node_name] for name, prop in node.props.items(): if name not in PROP_IGNORE_LIST and name[0] != '#': prop.Widen(struct[name]) upto += 1 - struct_name, aliases = get_compat_name(node) + struct_name, aliases = self.get_normalized_compat_name(node) for alias in aliases: self._aliases[alias] = struct_name @@ -464,7 +546,7 @@ class DtbPlatdata(object): Args: node: node to output """ - struct_name, _ = get_compat_name(node) + struct_name, _ = self.get_normalized_compat_name(node) var_name = conv_name_to_c(node.name) self.buf('static const struct %s%s %s%s = {\n' % (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) @@ -565,6 +647,7 @@ def run_steps(args, dtb_file, include_disabled, output): raise ValueError('Please specify a command: struct, platdata') plat = DtbPlatdata(dtb_file, include_disabled) + plat.scan_drivers() plat.scan_dtb() plat.scan_tree() plat.scan_reg_sizes() diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 8498e8303c..91fc9d77f3 100755 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -266,6 +266,39 @@ U_BOOT_DEVICE(pmic_at_9) = { \t.platdata_size\t= sizeof(dtv_pmic_at_9), }; +''', data) + + def test_driver_alias(self): + """Test output from a device tree file with a driver alias""" + dtb_file = get_dtb_file('dtoc_test_driver_alias.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['struct'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self._CheckStrings(HEADER + ''' +struct dtd_sandbox_gpio { +\tconst char *\tgpio_bank_name; +\tbool\t\tgpio_controller; +\tfdt32_t\t\tsandbox_gpio_count; +}; +#define dtd_sandbox_gpio_alias dtd_sandbox_gpio +''', data) + + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self._CheckStrings(C_HEADER + ''' +static const struct dtd_sandbox_gpio dtv_gpios_at_0 = { +\t.gpio_bank_name\t\t= "a", +\t.gpio_controller\t= true, +\t.sandbox_gpio_count\t= 0x14, +}; +U_BOOT_DEVICE(gpios_at_0) = { +\t.name\t\t= "sandbox_gpio", +\t.platdata\t= &dtv_gpios_at_0, +\t.platdata_size\t= sizeof(dtv_gpios_at_0), +}; + ''', data) def test_phandle(self):