From patchwork Wed May 13 20:13:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Lozano X-Patchwork-Id: 245753 List-Id: U-Boot discussion From: walter.lozano at collabora.com (Walter Lozano) Date: Wed, 13 May 2020 17:13:40 -0300 Subject: [RFC 1/6] dtoc: add support to scan drivers In-Reply-To: <20200513201345.26769-1-walter.lozano@collabora.com> References: <20200513201345.26769-1-walter.lozano@collabora.com> Message-ID: <20200513201345.26769-2-walter.lozano@collabora.com> 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 --- include/dm/device.h | 6 +++++ tools/dtoc/dtb_platdata.py | 53 +++++++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/include/dm/device.h b/include/dm/device.h index 975eec5d0e..d5b3e732c3 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -282,6 +282,12 @@ 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 * diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index ecfe0624d1..3f899a8bac 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -14,6 +14,8 @@ static data. import collections import copy import sys +import os +import re from dtoc import fdt from dtoc import fdt_util @@ -149,6 +151,20 @@ class DtbPlatdata(object): self._outfile = None self._lines = [] self._aliases = {} + self._drivers = [] + self._driver_aliases = {} + + def get_normalized_compat_name(self, node): + compat_c, aliases_c = get_compat_name(node) + if compat_c not in self._drivers: + try: # pragma: no cover + compat_c_old = compat_c + compat_c = self._driver_aliases[compat_c] + aliases_c = [compat_c_old] + aliases + except: + print('WARNING: the driver %s was not found in the driver list' % (compat_c)) + + return compat_c, aliases_c def setup_output(self, fname): """Set up the output destination @@ -243,6 +259,34 @@ class DtbPlatdata(object): return PhandleInfo(max_args, args) return None + def scan_driver(self, fn): + f = open(fn) + + b = f.read() + + drivers = re.findall('U_BOOT_DRIVER\((.*)\)', b) + + for d in drivers: + self._drivers.append(d) + + driver_aliases = re.findall('U_BOOT_DRIVER_ALIAS\(\s*(\w+)\s*,\s*(\w+)\s*\)', b) + + for a in driver_aliases: # pragma: no cover + try: + self._driver_aliases[a[1]] = a[0] + except: + pass + + def scan_drivers(self): + """Scan the driver folders to build a list of driver names and possible + aliases + """ + for (dirpath, dirnames, filenames) in os.walk('./'): + 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 @@ -353,7 +397,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. @@ -377,14 +421,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 @@ -461,7 +505,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)) @@ -562,6 +606,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() From patchwork Wed May 13 20:13:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Lozano X-Patchwork-Id: 245754 List-Id: U-Boot discussion From: walter.lozano at collabora.com (Walter Lozano) Date: Wed, 13 May 2020 17:13:41 -0300 Subject: [RFC 2/6] core: extend struct driver_info to point to device In-Reply-To: <20200513201345.26769-1-walter.lozano@collabora.com> References: <20200513201345.26769-1-walter.lozano@collabora.com> Message-ID: <20200513201345.26769-3-walter.lozano@collabora.com> Currently when creating an U_BOOT_DEVICE entry a struct driver_info is declared, which contains the data needed to instantiate the device. However, the actual device is created at runtime and there is no proper way to get the device based on its struct driver_info. This patch extends struct driver_info adding a pointer to udevice which is populated during the bind process, allowing to generate a set of functions to get the device based on its struct driver_info. Signed-off-by: Walter Lozano --- drivers/core/device.c | 25 +++++++++++++++++++++++-- drivers/core/root.c | 6 +++++- include/dm/device-internal.h | 2 +- include/dm/device.h | 13 +++++++++++++ include/dm/platdata.h | 6 ++++++ 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/drivers/core/device.c b/drivers/core/device.c index 0157bb1fe0..2476f170a5 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -246,10 +246,11 @@ int device_bind_ofnode(struct udevice *parent, const struct driver *drv, } int device_bind_by_name(struct udevice *parent, bool pre_reloc_only, - const struct driver_info *info, struct udevice **devp) + struct driver_info *info, struct udevice **devp) { struct driver *drv; uint platdata_size = 0; + int ret = 0; drv = lists_driver_lookup_name(info->name); if (!drv) @@ -260,9 +261,19 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only, #if CONFIG_IS_ENABLED(OF_PLATDATA) platdata_size = info->platdata_size; #endif - return device_bind_common(parent, drv, info->name, + ret = device_bind_common(parent, drv, info->name, (void *)info->platdata, 0, ofnode_null(), platdata_size, devp); + + if (ret) + return ret; + +#if CONFIG_IS_ENABLED(OF_PLATDATA) + info->dev = *devp; +#endif + + return ret; + } static void *alloc_priv(int size, uint flags) @@ -727,6 +738,16 @@ int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp) return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp); } +#if CONFIG_IS_ENABLED(OF_PLATDATA) +int device_get_by_driver_info(struct driver_info * info, struct udevice **devp) +{ + struct udevice *dev; + + dev = info->dev; + return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp); +} +#endif + int device_find_first_child(const struct udevice *parent, struct udevice **devp) { if (list_empty(&parent->child_head)) { diff --git a/drivers/core/root.c b/drivers/core/root.c index 14df16c280..8f47a6b356 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -25,7 +25,7 @@ DECLARE_GLOBAL_DATA_PTR; -static const struct driver_info root_info = { +static struct driver_info root_info = { .name = "root_driver", }; @@ -346,6 +346,10 @@ int dm_init_and_scan(bool pre_reloc_only) { int ret; +#if CONFIG_IS_ENABLED(OF_PLATDATA) + populate_phandle_data(); +#endif + ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE)); if (ret) { debug("dm_init() failed: %d\n", ret); diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h index 294d6c1810..5145fb4e14 100644 --- a/include/dm/device-internal.h +++ b/include/dm/device-internal.h @@ -81,7 +81,7 @@ int device_bind_with_driver_data(struct udevice *parent, * @return 0 if OK, -ve on error */ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only, - const struct driver_info *info, struct udevice **devp); + struct driver_info *info, struct udevice **devp); /** * device_ofdata_to_platdata() - Read platform data for a device diff --git a/include/dm/device.h b/include/dm/device.h index d5b3e732c3..590c1f99ce 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -537,6 +537,19 @@ int device_find_global_by_ofnode(ofnode node, struct udevice **devp); */ int device_get_global_by_ofnode(ofnode node, struct udevice **devp); +/** + * device_get_by_driver_info() - Get a device based on driver_info + * + * Locates a device by its struct driver_info. + * + * The device is probed to activate it ready for use. + * + * @info: Struct driver_info + * @devp: Returns pointer to device if found, otherwise this is set to NULL + * @return 0 if OK, -ve on error + */ +int device_get_by_driver_info(struct driver_info * info, struct udevice **devp); + /** * device_find_first_child() - Find the first child of a device * diff --git a/include/dm/platdata.h b/include/dm/platdata.h index c972fa6936..17eef7c7a3 100644 --- a/include/dm/platdata.h +++ b/include/dm/platdata.h @@ -28,6 +28,7 @@ struct driver_info { const void *platdata; #if CONFIG_IS_ENABLED(OF_PLATDATA) uint platdata_size; + struct udevice *dev; #endif }; @@ -43,4 +44,9 @@ struct driver_info { #define U_BOOT_DEVICES(__name) \ ll_entry_declare_list(struct driver_info, __name, driver_info) +/* Get a pointer to a given driver */ +#define DM_GET_DEVICE(__name) \ + ll_entry_get(struct driver_info, __name, driver_info) + +void populate_phandle_data(void); #endif From patchwork Wed May 13 20:13:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Lozano X-Patchwork-Id: 245755 List-Id: U-Boot discussion From: walter.lozano at collabora.com (Walter Lozano) Date: Wed, 13 May 2020 17:13:42 -0300 Subject: [RFC 3/6] dtoc: extend dtoc to use struct driver_info when linking nodes In-Reply-To: <20200513201345.26769-1-walter.lozano@collabora.com> References: <20200513201345.26769-1-walter.lozano@collabora.com> Message-ID: <20200513201345.26769-4-walter.lozano@collabora.com> In the current implementation, when dtoc parses a dtb to generate a struct platdata it converts the information related to linked nodes as pointers to struct platdata of destination nodes. By doing this, it makes difficult to get pointer to udevices created based on these information. This patch extends dtoc to use struct driver_info when populating information about linked nodes, which makes it easier to later get the devices created. In this context, reimplement functions like clk_get_by_index_platdata() which made use of the previous approach. Signed-off-by: Walter Lozano --- drivers/clk/clk-uclass.c | 8 +++----- drivers/misc/irq-uclass.c | 4 ++-- drivers/mmc/ftsdc010_mci.c | 2 +- drivers/mmc/rockchip_dw_mmc.c | 2 +- drivers/mmc/rockchip_sdhci.c | 2 +- drivers/ram/rockchip/sdram_rk3399.c | 2 +- drivers/spi/rk_spi.c | 2 +- include/clk.h | 2 +- tools/dtoc/dtb_platdata.py | 17 ++++++++++++++--- 9 files changed, 25 insertions(+), 16 deletions(-) diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 71878474eb..f24008fe00 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -25,14 +25,12 @@ static inline const struct clk_ops *clk_dev_ops(struct udevice *dev) #if CONFIG_IS_ENABLED(OF_CONTROL) # if CONFIG_IS_ENABLED(OF_PLATDATA) -int clk_get_by_index_platdata(struct udevice *dev, int index, - struct phandle_1_arg *cells, struct clk *clk) +int clk_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells, + struct clk *clk) { int ret; - if (index != 0) - return -ENOSYS; - ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev); + ret = device_get_by_driver_info((struct driver_info*) cells[0].node, &clk->dev); if (ret) return ret; clk->id = cells[0].arg[0]; diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c index 61aa10e465..8eaebe6419 100644 --- a/drivers/misc/irq-uclass.c +++ b/drivers/misc/irq-uclass.c @@ -63,14 +63,14 @@ int irq_read_and_clear(struct irq *irq) } #if CONFIG_IS_ENABLED(OF_PLATDATA) -int irq_get_by_index_platdata(struct udevice *dev, int index, +int irq_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells, struct irq *irq) { int ret; if (index != 0) return -ENOSYS; - ret = uclass_get_device(UCLASS_IRQ, 0, &irq->dev); + ret = device_get_by_driver_info(cells[0].node, &irq->dev); if (ret) return ret; irq->id = cells[0].arg[0]; diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c index 9c15eb36d6..efa92d48be 100644 --- a/drivers/mmc/ftsdc010_mci.c +++ b/drivers/mmc/ftsdc010_mci.c @@ -437,7 +437,7 @@ static int ftsdc010_mmc_probe(struct udevice *dev) chip->priv = dev; chip->dev_index = 1; memcpy(priv->minmax, dtplat->clock_freq_min_max, sizeof(priv->minmax)); - ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk); + ret = clk_get_by_driver_info(dev, dtplat->clocks, &priv->clk); if (ret < 0) return ret; #endif diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c index a0e1be8794..7b4479543c 100644 --- a/drivers/mmc/rockchip_dw_mmc.c +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -120,7 +120,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev) priv->minmax[0] = 400000; /* 400 kHz */ priv->minmax[1] = dtplat->max_frequency; - ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk); + ret = clk_get_by_driver_info(dev, dtplat->clocks, &priv->clk); if (ret < 0) return ret; #else diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index b440996b26..b073f1a08d 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -46,7 +46,7 @@ static int arasan_sdhci_probe(struct udevice *dev) host->name = dev->name; host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]); max_frequency = dtplat->max_frequency; - ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &clk); + ret = clk_get_by_driver_info(dev, dtplat->clocks, &clk); #else max_frequency = dev_read_u32_default(dev, "max-frequency", 0); ret = clk_get_by_index(dev, 0, &clk); diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c index d69ef01d08..87ec25f893 100644 --- a/drivers/ram/rockchip/sdram_rk3399.c +++ b/drivers/ram/rockchip/sdram_rk3399.c @@ -3125,7 +3125,7 @@ static int rk3399_dmc_init(struct udevice *dev) priv->cic, priv->pmugrf, priv->pmusgrf, priv->pmucru, priv->pmu); #if CONFIG_IS_ENABLED(OF_PLATDATA) - ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->ddr_clk); + ret = clk_get_by_driver_info(dev, dtplat->clocks, &priv->ddr_clk); #else ret = clk_get_by_index(dev, 0, &priv->ddr_clk); #endif diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c index 95eeb8307a..bd0337272e 100644 --- a/drivers/spi/rk_spi.c +++ b/drivers/spi/rk_spi.c @@ -181,7 +181,7 @@ static int conv_of_platdata(struct udevice *dev) plat->base = dtplat->reg[0]; plat->frequency = 20000000; - ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk); + ret = clk_get_by_driver_info(dev, dtplat->clocks, &priv->clk); if (ret < 0) return ret; dev->req_seq = 0; diff --git a/include/clk.h b/include/clk.h index c6a2713f62..3be379de03 100644 --- a/include/clk.h +++ b/include/clk.h @@ -89,7 +89,7 @@ struct clk_bulk { #if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(CLK) struct phandle_1_arg; -int clk_get_by_index_platdata(struct udevice *dev, int index, +int clk_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells, struct clk *clk); /** diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 3f899a8bac..d30e2af2ec 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -153,6 +153,7 @@ class DtbPlatdata(object): self._aliases = {} self._drivers = [] self._driver_aliases = {} + self._links = [] def get_normalized_compat_name(self, node): compat_c, aliases_c = get_compat_name(node) @@ -507,7 +508,7 @@ class DtbPlatdata(object): """ 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' % + self.buf('static struct %s%s %s%s = {\n' % (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) for pname in sorted(node.props): prop = node.props[pname] @@ -526,6 +527,7 @@ class DtbPlatdata(object): if info: # Process the list as pairs of (phandle, id) pos = 0 + item = 0 for args in info.args: phandle_cell = prop.value[pos] phandle = fdt_util.fdt32_to_cpu(phandle_cell) @@ -535,8 +537,10 @@ class DtbPlatdata(object): for i in range(args): arg_values.append(str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i]))) pos += 1 + args - vals.append('\t{&%s%s, {%s}}' % (VAL_PREFIX, name, - ', '.join(arg_values))) + vals.append('\t{NULL, {%s}}' % (', '.join(arg_values))) + phandle_entry = '%s%s.%s[%d].node = DM_GET_DEVICE(%s)' % (VAL_PREFIX, var_name, member_name, item, name) + self._links.append(phandle_entry) + item += 1 for val in vals: self.buf('\n\t\t%s,' % val) else: @@ -559,6 +563,7 @@ class DtbPlatdata(object): self.buf('\t.name\t\t= "%s",\n' % struct_name) self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name)) self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name)) + self.buf('\t.dev\t\t= NULL,\n') self.buf('};\n') self.buf('\n') @@ -592,6 +597,12 @@ class DtbPlatdata(object): self.output_node(node) nodes_to_output.remove(node) + self.buf('void populate_phandle_data(void) {\n') + for l in self._links: + self.buf(('\t%s;\n' % l)) + self.buf('}\n') + + self.out(''.join(self.get_buf())) def run_steps(args, dtb_file, include_disabled, output): """Run all the steps of the dtoc tool From patchwork Wed May 13 20:13:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Lozano X-Patchwork-Id: 245756 List-Id: U-Boot discussion From: walter.lozano at collabora.com (Walter Lozano) Date: Wed, 13 May 2020 17:13:43 -0300 Subject: [RFC 4/6] dtoc: update tests to match new platdata In-Reply-To: <20200513201345.26769-1-walter.lozano@collabora.com> References: <20200513201345.26769-1-walter.lozano@collabora.com> Message-ID: <20200513201345.26769-5-walter.lozano@collabora.com> After using a new approach to link nodes when OF_PLATDATA is enabled the test cases need to be update. This patch updates the tests based on this new implementation. Signed-off-by: Walter Lozano Reviewed-by: Simon Glass --- tools/dtoc/test_dtoc.py | 123 ++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 42 deletions(-) diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 8498e8303c..7e8947d4af 100755 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -47,7 +47,9 @@ C_HEADER = '''/* #include ''' - +C_EMPTY_POPULATE_PHANDLE_DATA = '''void populate_phandle_data(void) { +} +''' def get_dtb_file(dts_fname, capture_stderr=False): """Compile a .dts file to a .dtb @@ -162,7 +164,7 @@ class TestDtoc(unittest.TestCase): dtb_platdata.run_steps(['platdata'], dtb_file, False, output) with open(output) as infile: lines = infile.read().splitlines() - self.assertEqual(C_HEADER.splitlines() + [''], lines) + self.assertEqual(C_HEADER.splitlines() + [''] + C_EMPTY_POPULATE_PHANDLE_DATA.splitlines(), lines) def test_simple(self): """Test output from some simple nodes with various types of data""" @@ -197,7 +199,7 @@ struct dtd_sandbox_spl_test_2 { with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_sandbox_spl_test dtv_spl_test = { +static struct dtd_sandbox_spl_test dtv_spl_test = { \t.boolval\t\t= true, \t.bytearray\t\t= {0x6, 0x0, 0x0}, \t.byteval\t\t= 0x5, @@ -213,9 +215,10 @@ U_BOOT_DEVICE(spl_test) = { \t.name\t\t= "sandbox_spl_test", \t.platdata\t= &dtv_spl_test, \t.platdata_size\t= sizeof(dtv_spl_test), +\t.dev\t\t= NULL, }; -static const struct dtd_sandbox_spl_test dtv_spl_test2 = { +static struct dtd_sandbox_spl_test dtv_spl_test2 = { \t.bytearray\t\t= {0x1, 0x23, 0x34}, \t.byteval\t\t= 0x8, \t.intarray\t\t= {0x5, 0x0, 0x0, 0x0}, @@ -229,34 +232,38 @@ U_BOOT_DEVICE(spl_test2) = { \t.name\t\t= "sandbox_spl_test", \t.platdata\t= &dtv_spl_test2, \t.platdata_size\t= sizeof(dtv_spl_test2), +\t.dev\t\t= NULL, }; -static const struct dtd_sandbox_spl_test dtv_spl_test3 = { +static struct dtd_sandbox_spl_test dtv_spl_test3 = { \t.stringarray\t\t= {"one", "", ""}, }; U_BOOT_DEVICE(spl_test3) = { \t.name\t\t= "sandbox_spl_test", \t.platdata\t= &dtv_spl_test3, \t.platdata_size\t= sizeof(dtv_spl_test3), +\t.dev\t\t= NULL, }; -static const struct dtd_sandbox_spl_test_2 dtv_spl_test4 = { +static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = { }; U_BOOT_DEVICE(spl_test4) = { \t.name\t\t= "sandbox_spl_test_2", \t.platdata\t= &dtv_spl_test4, \t.platdata_size\t= sizeof(dtv_spl_test4), +\t.dev\t\t= NULL, }; -static const struct dtd_sandbox_i2c_test dtv_i2c_at_0 = { +static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = { }; U_BOOT_DEVICE(i2c_at_0) = { \t.name\t\t= "sandbox_i2c_test", \t.platdata\t= &dtv_i2c_at_0, \t.platdata_size\t= sizeof(dtv_i2c_at_0), +\t.dev\t\t= NULL, }; -static const struct dtd_sandbox_pmic_test dtv_pmic_at_9 = { +static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = { \t.low_power\t\t= true, \t.reg\t\t\t= {0x9, 0x0}, }; @@ -264,9 +271,10 @@ U_BOOT_DEVICE(pmic_at_9) = { \t.name\t\t= "sandbox_pmic_test", \t.platdata\t= &dtv_pmic_at_9, \t.platdata_size\t= sizeof(dtv_pmic_at_9), +\t.dev\t\t= NULL, }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_phandle(self): """Test output from a node containing a phandle reference""" @@ -288,56 +296,68 @@ struct dtd_target { with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_target dtv_phandle_target = { +static struct dtd_target dtv_phandle_target = { \t.intval\t\t\t= 0x0, }; U_BOOT_DEVICE(phandle_target) = { \t.name\t\t= "target", \t.platdata\t= &dtv_phandle_target, \t.platdata_size\t= sizeof(dtv_phandle_target), +\t.dev\t\t= NULL, }; -static const struct dtd_target dtv_phandle2_target = { +static struct dtd_target dtv_phandle2_target = { \t.intval\t\t\t= 0x1, }; U_BOOT_DEVICE(phandle2_target) = { \t.name\t\t= "target", \t.platdata\t= &dtv_phandle2_target, \t.platdata_size\t= sizeof(dtv_phandle2_target), +\t.dev\t\t= NULL, }; -static const struct dtd_target dtv_phandle3_target = { +static struct dtd_target dtv_phandle3_target = { \t.intval\t\t\t= 0x2, }; U_BOOT_DEVICE(phandle3_target) = { \t.name\t\t= "target", \t.platdata\t= &dtv_phandle3_target, \t.platdata_size\t= sizeof(dtv_phandle3_target), +\t.dev\t\t= NULL, }; -static const struct dtd_source dtv_phandle_source = { +static struct dtd_source dtv_phandle_source = { \t.clocks\t\t\t= { -\t\t\t{&dtv_phandle_target, {}}, -\t\t\t{&dtv_phandle2_target, {11}}, -\t\t\t{&dtv_phandle3_target, {12, 13}}, -\t\t\t{&dtv_phandle_target, {}},}, +\t\t\t{NULL, {}}, +\t\t\t{NULL, {11}}, +\t\t\t{NULL, {12, 13}}, +\t\t\t{NULL, {}},}, }; U_BOOT_DEVICE(phandle_source) = { \t.name\t\t= "source", \t.platdata\t= &dtv_phandle_source, \t.platdata_size\t= sizeof(dtv_phandle_source), +\t.dev\t\t= NULL, }; -static const struct dtd_source dtv_phandle_source2 = { +static struct dtd_source dtv_phandle_source2 = { \t.clocks\t\t\t= { -\t\t\t{&dtv_phandle_target, {}},}, +\t\t\t{NULL, {}},}, }; U_BOOT_DEVICE(phandle_source2) = { \t.name\t\t= "source", \t.platdata\t= &dtv_phandle_source2, \t.platdata_size\t= sizeof(dtv_phandle_source2), +\t.dev\t\t= NULL, }; +void populate_phandle_data(void) { +\tdtv_phandle_source.clocks[0].node = DM_GET_DEVICE(phandle_target); +\tdtv_phandle_source.clocks[1].node = DM_GET_DEVICE(phandle2_target); +\tdtv_phandle_source.clocks[2].node = DM_GET_DEVICE(phandle3_target); +\tdtv_phandle_source.clocks[3].node = DM_GET_DEVICE(phandle_target); +\tdtv_phandle_source2.clocks[0].node = DM_GET_DEVICE(phandle_target); +} ''', data) def test_phandle_single(self): @@ -364,24 +384,29 @@ struct dtd_target { with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_target dtv_phandle_target = { +static struct dtd_target dtv_phandle_target = { }; U_BOOT_DEVICE(phandle_target) = { \t.name\t\t= "target", \t.platdata\t= &dtv_phandle_target, \t.platdata_size\t= sizeof(dtv_phandle_target), +\t.dev\t\t= NULL, }; -static const struct dtd_source dtv_phandle_source2 = { +static struct dtd_source dtv_phandle_source2 = { \t.clocks\t\t\t= { -\t\t\t{&dtv_phandle_target, {}},}, +\t\t\t{NULL, {}},}, }; U_BOOT_DEVICE(phandle_source2) = { \t.name\t\t= "source", \t.platdata\t= &dtv_phandle_source2, \t.platdata_size\t= sizeof(dtv_phandle_source2), +\t.dev\t\t= NULL, }; +void populate_phandle_data(void) { +\tdtv_phandle_source2.clocks[0].node = DM_GET_DEVICE(phandle_target); +} ''', data) def test_phandle_bad(self): @@ -423,16 +448,17 @@ struct dtd_compat1 { with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_compat1 dtv_spl_test = { +static struct dtd_compat1 dtv_spl_test = { \t.intval\t\t\t= 0x1, }; U_BOOT_DEVICE(spl_test) = { \t.name\t\t= "compat1", \t.platdata\t= &dtv_spl_test, \t.platdata_size\t= sizeof(dtv_spl_test), +\t.dev\t\t= NULL, }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_addresses64(self): """Test output from a node with a 'reg' property with na=2, ns=2""" @@ -457,34 +483,37 @@ struct dtd_test3 { with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_test1 dtv_test1 = { +static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x1234, 0x5678}, }; U_BOOT_DEVICE(test1) = { \t.name\t\t= "test1", \t.platdata\t= &dtv_test1, \t.platdata_size\t= sizeof(dtv_test1), +\t.dev\t\t= NULL, }; -static const struct dtd_test2 dtv_test2 = { +static struct dtd_test2 dtv_test2 = { \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654}, }; U_BOOT_DEVICE(test2) = { \t.name\t\t= "test2", \t.platdata\t= &dtv_test2, \t.platdata_size\t= sizeof(dtv_test2), +\t.dev\t\t= NULL, }; -static const struct dtd_test3 dtv_test3 = { +static struct dtd_test3 dtv_test3 = { \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3}, }; U_BOOT_DEVICE(test3) = { \t.name\t\t= "test3", \t.platdata\t= &dtv_test3, \t.platdata_size\t= sizeof(dtv_test3), +\t.dev\t\t= NULL, }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_addresses32(self): """Test output from a node with a 'reg' property with na=1, ns=1""" @@ -506,25 +535,27 @@ struct dtd_test2 { with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_test1 dtv_test1 = { +static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x1234, 0x5678}, }; U_BOOT_DEVICE(test1) = { \t.name\t\t= "test1", \t.platdata\t= &dtv_test1, \t.platdata_size\t= sizeof(dtv_test1), +\t.dev\t\t= NULL, }; -static const struct dtd_test2 dtv_test2 = { +static struct dtd_test2 dtv_test2 = { \t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3}, }; U_BOOT_DEVICE(test2) = { \t.name\t\t= "test2", \t.platdata\t= &dtv_test2, \t.platdata_size\t= sizeof(dtv_test2), +\t.dev\t\t= NULL, }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_addresses64_32(self): """Test output from a node with a 'reg' property with na=2, ns=1""" @@ -549,34 +580,37 @@ struct dtd_test3 { with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_test1 dtv_test1 = { +static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x123400000000, 0x5678}, }; U_BOOT_DEVICE(test1) = { \t.name\t\t= "test1", \t.platdata\t= &dtv_test1, \t.platdata_size\t= sizeof(dtv_test1), +\t.dev\t\t= NULL, }; -static const struct dtd_test2 dtv_test2 = { +static struct dtd_test2 dtv_test2 = { \t.reg\t\t\t= {0x1234567890123456, 0x98765432}, }; U_BOOT_DEVICE(test2) = { \t.name\t\t= "test2", \t.platdata\t= &dtv_test2, \t.platdata_size\t= sizeof(dtv_test2), +\t.dev\t\t= NULL, }; -static const struct dtd_test3 dtv_test3 = { +static struct dtd_test3 dtv_test3 = { \t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3}, }; U_BOOT_DEVICE(test3) = { \t.name\t\t= "test3", \t.platdata\t= &dtv_test3, \t.platdata_size\t= sizeof(dtv_test3), +\t.dev\t\t= NULL, }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_addresses32_64(self): """Test output from a node with a 'reg' property with na=1, ns=2""" @@ -601,34 +635,37 @@ struct dtd_test3 { with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_test1 dtv_test1 = { +static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x1234, 0x567800000000}, }; U_BOOT_DEVICE(test1) = { \t.name\t\t= "test1", \t.platdata\t= &dtv_test1, \t.platdata_size\t= sizeof(dtv_test1), +\t.dev\t\t= NULL, }; -static const struct dtd_test2 dtv_test2 = { +static struct dtd_test2 dtv_test2 = { \t.reg\t\t\t= {0x12345678, 0x9876543210987654}, }; U_BOOT_DEVICE(test2) = { \t.name\t\t= "test2", \t.platdata\t= &dtv_test2, \t.platdata_size\t= sizeof(dtv_test2), +\t.dev\t\t= NULL, }; -static const struct dtd_test3 dtv_test3 = { +static struct dtd_test3 dtv_test3 = { \t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3}, }; U_BOOT_DEVICE(test3) = { \t.name\t\t= "test3", \t.platdata\t= &dtv_test3, \t.platdata_size\t= sizeof(dtv_test3), +\t.dev\t\t= NULL, }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_bad_reg(self): """Test that a reg property with an invalid type generates an error""" @@ -668,25 +705,27 @@ struct dtd_sandbox_spl_test { with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_sandbox_spl_test dtv_spl_test = { +static struct dtd_sandbox_spl_test dtv_spl_test = { \t.intval\t\t\t= 0x1, }; U_BOOT_DEVICE(spl_test) = { \t.name\t\t= "sandbox_spl_test", \t.platdata\t= &dtv_spl_test, \t.platdata_size\t= sizeof(dtv_spl_test), +\t.dev\t\t= NULL, }; -static const struct dtd_sandbox_spl_test dtv_spl_test2 = { +static struct dtd_sandbox_spl_test dtv_spl_test2 = { \t.intarray\t\t= 0x5, }; U_BOOT_DEVICE(spl_test2) = { \t.name\t\t= "sandbox_spl_test", \t.platdata\t= &dtv_spl_test2, \t.platdata_size\t= sizeof(dtv_spl_test2), +\t.dev\t\t= NULL, }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def testStdout(self): """Test output to stdout""" From patchwork Wed May 13 20:13:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Lozano X-Patchwork-Id: 245757 List-Id: U-Boot discussion From: walter.lozano at collabora.com (Walter Lozano) Date: Wed, 13 May 2020 17:13:44 -0300 Subject: [RFC 5/6] dtoc: update dtb_platdata to support cd-gpios In-Reply-To: <20200513201345.26769-1-walter.lozano@collabora.com> References: <20200513201345.26769-1-walter.lozano@collabora.com> Message-ID: <20200513201345.26769-6-walter.lozano@collabora.com> Currently dtoc does not support the property cd-gpios used to declare the gpios for card detect in mmc. This patch adds support to cd-gpios property. Signed-off-by: Walter Lozano Reviewed-by: Simon Glass --- tools/dtoc/dtb_platdata.py | 13 ++++++++----- tools/dtoc/test_dtoc.py | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index d30e2af2ec..71a734b408 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -228,7 +228,7 @@ class DtbPlatdata(object): Return: Number of argument cells is this is a phandle, else None """ - if prop.name in ['clocks']: + if prop.name in ['clocks', 'cd-gpios']: if not isinstance(prop.value, list): prop.value = [prop.value] val = prop.value @@ -248,11 +248,14 @@ class DtbPlatdata(object): if not target: raise ValueError("Cannot parse '%s' in node '%s'" % (prop.name, node_name)) - prop_name = '#clock-cells' - cells = target.props.get(prop_name) + cells = None + for prop_name in ['#clock-cells', '#gpio-cells']: + cells = target.props.get(prop_name) + if cells: + break if not cells: - raise ValueError("Node '%s' has no '%s' property" % - (target.name, prop_name)) + raise ValueError("Node '%s' has no cells property" % + (target.name)) num_args = fdt_util.fdt32_to_cpu(cells.value) max_args = max(max_args, num_args) args.append(num_args) diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 7e8947d4af..814988c374 100755 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -426,7 +426,7 @@ void populate_phandle_data(void) { output = tools.GetOutputFilename('output') with self.assertRaises(ValueError) as e: dtb_platdata.run_steps(['struct'], dtb_file, False, output) - self.assertIn("Node 'phandle-target' has no '#clock-cells' property", + self.assertIn("Node 'phandle-target' has no cells property", str(e.exception)) def test_aliases(self): From patchwork Wed May 13 20:13:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Lozano X-Patchwork-Id: 245758 List-Id: U-Boot discussion From: walter.lozano at collabora.com (Walter Lozano) Date: Wed, 13 May 2020 17:13:45 -0300 Subject: [RFC 6/6] dtoc add test for cd-gpios In-Reply-To: <20200513201345.26769-1-walter.lozano@collabora.com> References: <20200513201345.26769-1-walter.lozano@collabora.com> Message-ID: <20200513201345.26769-7-walter.lozano@collabora.com> Add a test for dtoc taking into account the cd-gpios property. Signed-off-by: Walter Lozano Reviewed-by: Simon Glass --- tools/dtoc/dtoc_test_phandle_cd_gpios.dts | 42 +++++++++++++ tools/dtoc/test_dtoc.py | 72 +++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 tools/dtoc/dtoc_test_phandle_cd_gpios.dts diff --git a/tools/dtoc/dtoc_test_phandle_cd_gpios.dts b/tools/dtoc/dtoc_test_phandle_cd_gpios.dts new file mode 100644 index 0000000000..1029ce03b8 --- /dev/null +++ b/tools/dtoc/dtoc_test_phandle_cd_gpios.dts @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + */ + + /dts-v1/; + +/ { + phandle: phandle-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <0>; + #gpio-cells = <0>; + }; + + phandle_1: phandle2-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <1>; + #gpio-cells = <1>; + }; + phandle_2: phandle3-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <2>; + #gpio-cells = <2>; + }; + + phandle-source { + u-boot,dm-pre-reloc; + compatible = "source"; + cd-gpios = <&phandle &phandle_1 11 &phandle_2 12 13 &phandle>; + }; + + phandle-source2 { + u-boot,dm-pre-reloc; + compatible = "source"; + cd-gpios = <&phandle>; + }; +}; diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 814988c374..f3d5e77880 100755 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -407,6 +407,78 @@ U_BOOT_DEVICE(phandle_source2) = { void populate_phandle_data(void) { \tdtv_phandle_source2.clocks[0].node = DM_GET_DEVICE(phandle_target); } +''', data) + + def test_phandle_cd_gpio(self): + """Test that phandle targets are generated when unsing cd-gpios""" + dtb_file = get_dtb_file('dtoc_test_phandle_cd_gpios.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self._CheckStrings(C_HEADER + ''' +static struct dtd_target dtv_phandle_target = { +\t.intval\t\t\t= 0x0, +}; +U_BOOT_DEVICE(phandle_target) = { +\t.name\t\t= "target", +\t.platdata\t= &dtv_phandle_target, +\t.platdata_size\t= sizeof(dtv_phandle_target), +\t.dev\t\t= NULL, +}; + +static struct dtd_target dtv_phandle2_target = { +\t.intval\t\t\t= 0x1, +}; +U_BOOT_DEVICE(phandle2_target) = { +\t.name\t\t= "target", +\t.platdata\t= &dtv_phandle2_target, +\t.platdata_size\t= sizeof(dtv_phandle2_target), +\t.dev\t\t= NULL, +}; + +static struct dtd_target dtv_phandle3_target = { +\t.intval\t\t\t= 0x2, +}; +U_BOOT_DEVICE(phandle3_target) = { +\t.name\t\t= "target", +\t.platdata\t= &dtv_phandle3_target, +\t.platdata_size\t= sizeof(dtv_phandle3_target), +\t.dev\t\t= NULL, +}; + +static struct dtd_source dtv_phandle_source = { +\t.cd_gpios\t\t= { +\t\t\t{NULL, {}}, +\t\t\t{NULL, {11}}, +\t\t\t{NULL, {12, 13}}, +\t\t\t{NULL, {}},}, +}; +U_BOOT_DEVICE(phandle_source) = { +\t.name\t\t= "source", +\t.platdata\t= &dtv_phandle_source, +\t.platdata_size\t= sizeof(dtv_phandle_source), +\t.dev\t\t= NULL, +}; + +static struct dtd_source dtv_phandle_source2 = { +\t.cd_gpios\t\t= { +\t\t\t{NULL, {}},}, +}; +U_BOOT_DEVICE(phandle_source2) = { +\t.name\t\t= "source", +\t.platdata\t= &dtv_phandle_source2, +\t.platdata_size\t= sizeof(dtv_phandle_source2), +\t.dev\t\t= NULL, +}; + +void populate_phandle_data(void) { +\tdtv_phandle_source.cd_gpios[0].node = DM_GET_DEVICE(phandle_target); +\tdtv_phandle_source.cd_gpios[1].node = DM_GET_DEVICE(phandle2_target); +\tdtv_phandle_source.cd_gpios[2].node = DM_GET_DEVICE(phandle3_target); +\tdtv_phandle_source.cd_gpios[3].node = DM_GET_DEVICE(phandle_target); +\tdtv_phandle_source2.cd_gpios[0].node = DM_GET_DEVICE(phandle_target); +} ''', data) def test_phandle_bad(self):