@@ -30,6 +30,8 @@ U_BOOT_DRIVER(atmel_at91rm9200_pmc) = {
.of_match = at91_pmc_match,
};
+U_BOOT_DRIVER_ALIAS(atmel_at91rm9200_pmc, atmel_at91sam9260_pmc)
+
/*---------------------------------------------------------*/
int at91_pmc_core_probe(struct udevice *dev)
@@ -309,4 +309,6 @@ U_BOOT_DRIVER(fsl_imx23_gpio) = {
.ofdata_to_platdata = mxs_ofdata_to_platdata,
#endif
};
+
+U_BOOT_DRIVER_ALIAS(fsl_imx23_gpio, fsl_imx28_gpio)
#endif /* DM_GPIO */
@@ -253,6 +253,8 @@ U_BOOT_DRIVER(sandbox_gpio) = {
.ops = &gpio_sandbox_ops,
};
+U_BOOT_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias)
+
/* pincontrol: used only to check GPIO pin configuration (pinmux command) */
struct sb_pinctrl_priv {
@@ -492,3 +492,5 @@ U_BOOT_DRIVER(rockchip_rk3066_i2c) = {
.priv_auto_alloc_size = sizeof(struct rk_i2c),
.ops = &rockchip_i2c_ops,
};
+
+U_BOOT_DRIVER_ALIAS(rockchip_rk3066_i2c, rockchip_rk3288_i2c)
@@ -724,4 +724,5 @@ U_BOOT_DRIVER(fsl_imx23_mmc) = {
.platdata_auto_alloc_size = sizeof(struct mxsmmc_platdata),
};
+U_BOOT_DRIVER_ALIAS(fsl_imx23_mmc, fsl_imx28_mmc)
#endif /* CONFIG_DM_MMC */
@@ -178,6 +178,9 @@ U_BOOT_DRIVER(rockchip_rk3288_dw_mshc) = {
.platdata_auto_alloc_size = sizeof(struct rockchip_mmc_plat),
};
+U_BOOT_DRIVER_ALIAS(rockchip_rk3288_dw_mshc, rockchip_rk3328_dw_mshc)
+U_BOOT_DRIVER_ALIAS(rockchip_rk3288_dw_mshc, rockchip_rk3368_dw_mshc)
+
#ifdef CONFIG_PWRSEQ
static int rockchip_dwmmc_pwrseq_set_power(struct udevice *dev, bool enable)
{
@@ -180,4 +180,6 @@ U_BOOT_DRIVER(jedec_spi_nor) = {
.ops = &spi_flash_std_ops,
};
+U_BOOT_DRIVER_ALIAS(jedec_spi_nor, spansion_m25p16)
+
#endif /* CONFIG_DM_SPI_FLASH */
@@ -190,3 +190,5 @@ U_BOOT_DRIVER(fsl_imx23_pinctrl) = {
.priv_auto_alloc_size = sizeof(struct mxs_pinctrl_priv),
.ops = &mxs_pinctrl_ops,
};
+
+U_BOOT_DRIVER_ALIAS(fsl_imx23_pinctrl, fsl_imx28_pinctrl)
@@ -525,3 +525,5 @@ U_BOOT_DRIVER(atmel_sama5d3_pinctrl) = {
.priv_auto_alloc_size = sizeof(struct at91_pinctrl_priv),
.ops = &at91_pinctrl_ops,
};
+
+U_BOOT_DRIVER_ALIAS(atmel_sama5d3_pinctrl, atmel_at91rm9200_pinctrl)
@@ -193,3 +193,5 @@ U_BOOT_DRIVER(rockchip_rk805) = {
.probe = rk8xx_probe,
.ops = &rk8xx_ops,
};
+
+U_BOOT_DRIVER_ALIAS(rockchip_rk805, rockchip_rk808)
@@ -619,6 +619,10 @@ U_BOOT_DRIVER(ns16550_serial) = {
.flags = DM_FLAG_PRE_RELOC,
#endif
};
+
+U_BOOT_DRIVER_ALIAS(ns16550_serial, rockchip_rk3328_uart)
+U_BOOT_DRIVER_ALIAS(ns16550_serial, rockchip_rk3368_uart)
+U_BOOT_DRIVER_ALIAS(ns16550_serial, ti_da830_uart)
#endif
#endif /* SERIAL_PRESENT */
@@ -618,4 +618,6 @@ U_BOOT_DRIVER(fsl_imx23_spi) = {
.priv_auto_alloc_size = sizeof(struct mxs_spi_priv),
.probe = mxs_spi_probe,
};
+
+U_BOOT_DRIVER_ALIAS(fsl_imx23_spi, fsl_imx28_spi)
#endif
@@ -561,3 +561,5 @@ U_BOOT_DRIVER(rockchip_rk3288_spi) = {
.priv_auto_alloc_size = sizeof(struct rockchip_spi_priv),
.probe = rockchip_spi_probe,
};
+
+U_BOOT_DRIVER_ALIAS(rockchip_rk3288_spi, rockchip_rk3368_spi)
@@ -282,6 +282,13 @@ struct driver {
#define DM_GET_DRIVER(__name) \
ll_entry_get(struct driver, __name, driver)
+/**
+ * Declare a macro to state a alias for a driver name. This macro will
+ * produce no code but its information will be parsed by tools like
+ * dtoc
+ */
+#define U_BOOT_DRIVER_ALIAS(__name, __alias)
+
/**
* dev_get_platdata() - Get the platform data for a device
*
@@ -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,37 @@ 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 +284,48 @@ 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 +436,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 +460,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 +544,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 +645,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()
new file mode 100644
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2020 Collabora Ltd.
+ */
+
+/dts-v1/;
+
+/ {
+ gpio_a: gpios at 0 {
+ u-boot,dm-pre-reloc;
+ gpio-controller;
+ compatible = "sandbox_gpio_alias";
+ #gpio-cells = <1>;
+ gpio-bank-name = "a";
+ sandbox,gpio-count = <20>;
+ };
+
+};
@@ -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):
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. This allows to rise a warning in the case that an U_BOOT_DEVICE entry will try to use a name not valid. Additionally, in order to add more flexibility to the solution, adds the U_BOOT_DRIVER_ALIAS macro, which generates no code at all, but allows an easy way to declare driver name aliases. Thanks to this, dtoc can look for the driver name based on its alias when it populates the U_BOOT_DEVICE entry. Signed-off-by: Walter Lozano <walter.lozano at collabora.com> --- drivers/clk/at91/pmc.c | 2 + drivers/gpio/mxs_gpio.c | 2 + drivers/gpio/sandbox.c | 2 + drivers/i2c/rk_i2c.c | 2 + drivers/mmc/mxsmmc.c | 1 + drivers/mmc/rockchip_dw_mmc.c | 3 + drivers/mtd/spi/sf_probe.c | 2 + drivers/pinctrl/nxp/pinctrl-mxs.c | 2 + drivers/pinctrl/pinctrl-at91.c | 2 + drivers/power/pmic/rk8xx.c | 2 + drivers/serial/ns16550.c | 4 ++ drivers/spi/mxs_spi.c | 2 + drivers/spi/rk_spi.c | 2 + include/dm/device.h | 7 +++ tools/dtoc/dtb_platdata.py | 89 +++++++++++++++++++++++++-- tools/dtoc/dtoc_test_driver_alias.dts | 20 ++++++ tools/dtoc/test_dtoc.py | 33 ++++++++++ 17 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 tools/dtoc/dtoc_test_driver_alias.dts