From 979ab02473e578b81ad8ef7c3a844b789b48c40d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:47 -0600 Subject: dtoc: Adjust Node to record its parent We need to be able to search back up the tree for #address-cells and #size-cells. Record the parent of each node to make this easier. Signed-off-by: Simon Glass Reviewed-by: Philipp Tomsich Tested-by: Philipp Tomsich Tested-by: Kever Yang --- tools/dtoc/fdt.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index 63a32ea2d7b..49409a62ec2 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -174,8 +174,9 @@ class Node: props: A dict of properties for this node, each a Prop object. Keyed by property name """ - def __init__(self, fdt, offset, name, path): + def __init__(self, fdt, parent, offset, name, path): self._fdt = fdt + self.parent = parent self._offset = offset self.name = name self.path = path @@ -217,7 +218,7 @@ class Node: sep = '' if self.path[-1] == '/' else '/' name = self._fdt._fdt_obj.get_name(offset) path = self.path + sep + name - node = Node(self._fdt, offset, name, path) + node = Node(self._fdt, self, offset, name, path) self.subnodes.append(node) node.Scan() @@ -279,7 +280,7 @@ class Fdt: TODO(sjg@chromium.org): Implement the 'root' parameter """ - self._root = self.Node(self, 0, '/', '/') + self._root = self.Node(self, None, 0, '/', '/') self._root.Scan() def GetRoot(self): @@ -386,7 +387,7 @@ class Fdt: return libfdt.fdt_off_dt_struct(self._fdt) + offset @classmethod - def Node(self, fdt, offset, name, path): + def Node(self, fdt, parent, offset, name, path): """Create a new node This is used by Fdt.Scan() to create a new node using the correct @@ -394,11 +395,12 @@ class Fdt: Args: fdt: Fdt object + parent: Parent node, or None if this is the root node offset: Offset of node name: Node name path: Full path to node """ - node = Node(fdt, offset, name, path) + node = Node(fdt, parent, offset, name, path) return node def FdtScan(fname): -- cgit v1.3.1 From fbdfd228fb7bcdd16ddca3e081b1cc1d8205702b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:48 -0600 Subject: dtoc: Add a 64-bit type and a way to convert cells into 64 bits When dealing with multi-cell values we need a type that can hold this value. Add this and a function to process it from a list of cell values. Signed-off-by: Simon Glass Reviewed-by: Philipp Tomsich Tested-by: Philipp Tomsich Tested-by: Kever Yang --- tools/dtoc/dtb_platdata.py | 3 +++ tools/dtoc/fdt.py | 2 +- tools/dtoc/fdt_util.py | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 041a33188ff..4a1162a9fae 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -38,6 +38,7 @@ TYPE_NAMES = { fdt.TYPE_BYTE: 'unsigned char', fdt.TYPE_STRING: 'const char *', fdt.TYPE_BOOL: 'bool', + fdt.TYPE_INT64: 'fdt64_t', } STRUCT_PREFIX = 'dtd_' @@ -95,6 +96,8 @@ def get_value(ftype, value): return '"%s"' % value elif ftype == fdt.TYPE_BOOL: return 'true' + elif ftype == fdt.TYPE_INT64: + return '%#x' % value def get_compat_name(node): """Get a node's first compatible string as a C identifier diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index 49409a62ec2..ffd42ce541d 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -21,7 +21,7 @@ import libfdt # so it is fairly efficient. # A list of types we support -(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4) +(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, TYPE_INT64) = range(5) def CheckErr(errnum, msg): if errnum: diff --git a/tools/dtoc/fdt_util.py b/tools/dtoc/fdt_util.py index b9dfae8d0e7..bec6ee947a8 100644 --- a/tools/dtoc/fdt_util.py +++ b/tools/dtoc/fdt_util.py @@ -29,6 +29,20 @@ def fdt32_to_cpu(val): val = val.encode('raw_unicode_escape') return struct.unpack('>I', val)[0] +def fdt_cells_to_cpu(val, cells): + """Convert one or two cells to a long integer + + Args: + Value to convert (array of one or more 4-character strings) + + Return: + A native-endian long value + """ + out = long(fdt32_to_cpu(val[0])) + if cells == 2: + out = out << 32 | fdt32_to_cpu(val[1]) + return out + def EnsureCompiled(fname): """Compile an fdt .dts source file into a .dtb binary blob if needed. -- cgit v1.3.1 From 21d54ac353d76d46848cb7fae14a07775cc3bacf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:49 -0600 Subject: dtoc: Avoid very long lines in output Large arrays can result in lines with hundreds or thousands of characters which is not very editor-friendly. To avoid this, addjust the tool to group values 8 per line. Signed-off-by: Simon Glass Tested-by: Kever Yang --- tools/dtoc/dtb_platdata.py | 7 ++++++- tools/dtoc/test_dtoc.py | 6 ++++-- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 4a1162a9fae..3243bccfe8e 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -385,7 +385,12 @@ class DtbPlatdata(object): else: for val in prop.value: vals.append(get_value(prop.type, val)) - self.buf(', '.join(vals)) + + # Put 8 values per line to avoid very long lines. + for i in xrange(0, len(vals), 8): + if i: + self.buf(',\n\t\t') + self.buf(', '.join(vals[i:i + 8])) self.buf('}') else: self.buf(get_value(prop.type, prop.value)) diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 8b95c4124f0..5040f233255 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -146,7 +146,8 @@ static struct dtd_sandbox_spl_test dtv_spl_test = { \t.bytearray\t\t= {0x6, 0x0, 0x0}, \t.byteval\t\t= 0x5, \t.intval\t\t\t= 0x1, -\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11}, +\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, +\t\t0x11}, \t.stringval\t\t= "message", \t.boolval\t\t= true, \t.intarray\t\t= {0x2, 0x3, 0x4, 0x0}, @@ -162,7 +163,8 @@ static struct dtd_sandbox_spl_test dtv_spl_test2 = { \t.bytearray\t\t= {0x1, 0x23, 0x34}, \t.byteval\t\t= 0x8, \t.intval\t\t\t= 0x3, -\t.longbytearray\t\t= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, +\t.longbytearray\t\t= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +\t\t0x0}, \t.stringval\t\t= "message2", \t.intarray\t\t= {0x5, 0x0, 0x0, 0x0}, \t.stringarray\t\t= {"another", "multi-word", "message"}, -- cgit v1.3.1 From c20ee0ed070953600b54b16c8b48725348abead5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:50 -0600 Subject: dtoc: Add support for 32 or 64-bit addresses When using 32-bit addresses dtoc works correctly. For 64-bit addresses it does not since it ignores the #address-cells and #size-cells properties. Update the tool to use fdt64_t as the element type for reg properties when either the address or size is larger than one cell. Use the correct value so that C code can obtain the information from the device tree easily. Alos create a new type, fdt_val_t, which is defined to either fdt32_t or fdt64_t depending on the word size of the machine. This type corresponds to fdt_addr_t and fdt_size_t. Unfortunately we cannot just use those types since they are defined to phys_addr_t and phys_size_t which use 'unsigned long' in the 32-bit case, rather than 'unsigned int'. Add tests for the four combinations of address and size values (32/32, 64/64, 32/64, 64/32). Also update existing uses for rk3399 and rk3368 which now need to use the new fdt_val_t type. Signed-off-by: Simon Glass Suggested-by: Heiko Stuebner Reported-by: Kever Yang Reviewed-by: Philipp Tomsich Tested-by: Kever Yang --- drivers/clk/rockchip/clk_rk3368.c | 2 +- drivers/clk/rockchip/clk_rk3399.c | 4 +- drivers/core/regmap.c | 2 +- include/fdtdec.h | 2 + include/regmap.h | 2 +- include/syscon.h | 6 +- tools/dtoc/dtb_platdata.py | 61 +++++++++++ tools/dtoc/dtoc_test_addr32.dts | 27 +++++ tools/dtoc/dtoc_test_addr32_64.dts | 33 ++++++ tools/dtoc/dtoc_test_addr64.dts | 33 ++++++ tools/dtoc/dtoc_test_addr64_32.dts | 33 ++++++ tools/dtoc/fdt_util.py | 2 + tools/dtoc/test_dtoc.py | 212 +++++++++++++++++++++++++++++++++++++ 13 files changed, 413 insertions(+), 6 deletions(-) create mode 100644 tools/dtoc/dtoc_test_addr32.dts create mode 100644 tools/dtoc/dtoc_test_addr32_64.dts create mode 100644 tools/dtoc/dtoc_test_addr64.dts create mode 100644 tools/dtoc/dtoc_test_addr64_32.dts (limited to 'tools') diff --git a/drivers/clk/rockchip/clk_rk3368.c b/drivers/clk/rockchip/clk_rk3368.c index 2be1f572d72..0160d50c038 100644 --- a/drivers/clk/rockchip/clk_rk3368.c +++ b/drivers/clk/rockchip/clk_rk3368.c @@ -471,7 +471,7 @@ static int rk3368_clk_probe(struct udevice *dev) #if CONFIG_IS_ENABLED(OF_PLATDATA) struct rk3368_clk_plat *plat = dev_get_platdata(dev); - priv->cru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]); + priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]); #endif #if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) rkclk_init(priv->cru); diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c index 3edafea1400..72328067241 100644 --- a/drivers/clk/rockchip/clk_rk3399.c +++ b/drivers/clk/rockchip/clk_rk3399.c @@ -963,7 +963,7 @@ static int rk3399_clk_probe(struct udevice *dev) #if CONFIG_IS_ENABLED(OF_PLATDATA) struct rk3399_clk_plat *plat = dev_get_platdata(dev); - priv->cru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]); + priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]); #endif rkclk_init(priv->cru); #endif @@ -1145,7 +1145,7 @@ static int rk3399_pmuclk_probe(struct udevice *dev) #if CONFIG_IS_ENABLED(OF_PLATDATA) struct rk3399_pmuclk_plat *plat = dev_get_platdata(dev); - priv->pmucru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]); + priv->pmucru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]); #endif #ifndef CONFIG_SPL_BUILD diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index d4e16a27ef3..0f1d30820c6 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -40,7 +40,7 @@ static struct regmap *regmap_alloc_count(int count) } #if CONFIG_IS_ENABLED(OF_PLATDATA) -int regmap_init_mem_platdata(struct udevice *dev, u32 *reg, int count, +int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count, struct regmap **mapp) { struct regmap_range *range; diff --git a/include/fdtdec.h b/include/fdtdec.h index 4a0947c6266..1ba02be8e1b 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -27,10 +27,12 @@ typedef phys_size_t fdt_size_t; #define FDT_ADDR_T_NONE (-1ULL) #define fdt_addr_to_cpu(reg) be64_to_cpu(reg) #define fdt_size_to_cpu(reg) be64_to_cpu(reg) +typedef fdt64_t fdt_val_t; #else #define FDT_ADDR_T_NONE (-1U) #define fdt_addr_to_cpu(reg) be32_to_cpu(reg) #define fdt_size_to_cpu(reg) be32_to_cpu(reg) +typedef fdt32_t fdt_val_t; #endif /* Information obtained about memory from the FDT */ diff --git a/include/regmap.h b/include/regmap.h index 1eed94e47a3..493a5d8eff8 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -69,7 +69,7 @@ int regmap_init_mem(struct udevice *dev, struct regmap **mapp); * @count: Number of pairs (e.g. 1 if the regmap has a single entry) * @mapp: Returns allocated map */ -int regmap_init_mem_platdata(struct udevice *dev, u32 *reg, int count, +int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count, struct regmap **mapp); /** diff --git a/include/syscon.h b/include/syscon.h index 34842aa4705..5d52b1cc3c3 100644 --- a/include/syscon.h +++ b/include/syscon.h @@ -8,6 +8,8 @@ #ifndef __SYSCON_H #define __SYSCON_H +#include + /** * struct syscon_uc_info - Information stored by the syscon UCLASS_UCLASS * @@ -28,9 +30,11 @@ struct syscon_ops { * We don't support 64-bit machines. If they are so resource-contrained that * they need to use OF_PLATDATA, something is horribly wrong with the * education of our hardware engineers. + * + * Update: 64-bit is now supported and we have an education crisis. */ struct syscon_base_platdata { - u32 reg[2]; + fdt_val_t reg[2]; }; #endif diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 3243bccfe8e..0c719310b10 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -242,6 +242,66 @@ class DtbPlatdata(object): self._valid_nodes = [] return self.scan_node(self._fdt.GetRoot()) + @staticmethod + def get_num_cells(node): + """Get the number of cells in addresses and sizes for this node + + Args: + node: Node to check + + Returns: + Tuple: + Number of address cells for this node + Number of size cells for this node + """ + parent = node.parent + na, ns = 2, 2 + if parent: + na_prop = parent.props.get('#address-cells') + ns_prop = parent.props.get('#size-cells') + if na_prop: + na = fdt_util.fdt32_to_cpu(na_prop.value) + if ns_prop: + ns = fdt_util.fdt32_to_cpu(ns_prop.value) + return na, ns + + def scan_reg_sizes(self): + """Scan for 64-bit 'reg' properties and update the values + + This finds 'reg' properties with 64-bit data and converts the value to + an array of 64-values. This allows it to be output in a way that the + C code can read. + """ + for node in self._valid_nodes: + reg = node.props.get('reg') + if not reg: + continue + na, ns = self.get_num_cells(node) + total = na + ns + + if reg.type != fdt.TYPE_INT: + raise ValueError("Node '%s' reg property is not an int") + if len(reg.value) % total: + raise ValueError("Node '%s' reg property has %d cells " + 'which is not a multiple of na + ns = %d + %d)' % + (node.name, len(reg.value), na, ns)) + reg.na = na + reg.ns = ns + if na != 1 or ns != 1: + reg.type = fdt.TYPE_INT64 + i = 0 + new_value = [] + val = reg.value + if not isinstance(val, list): + val = [val] + while i < len(val): + addr = fdt_util.fdt_cells_to_cpu(val[i:], reg.na) + i += na + size = fdt_util.fdt_cells_to_cpu(val[i:], reg.ns) + i += ns + new_value += [addr, size] + reg.value = new_value + def scan_structs(self): """Scan the device tree building up the C structures we will use. @@ -450,6 +510,7 @@ def run_steps(args, dtb_file, include_disabled, output): plat = DtbPlatdata(dtb_file, include_disabled) plat.scan_dtb() plat.scan_tree() + plat.scan_reg_sizes() plat.setup_output(output) structs = plat.scan_structs() plat.scan_phandles() diff --git a/tools/dtoc/dtoc_test_addr32.dts b/tools/dtoc/dtoc_test_addr32.dts new file mode 100644 index 00000000000..bcfdcae10b5 --- /dev/null +++ b/tools/dtoc/dtoc_test_addr32.dts @@ -0,0 +1,27 @@ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + test1 { + u-boot,dm-pre-reloc; + compatible = "test1"; + reg = <0x1234 0x5678>; + }; + + test2 { + u-boot,dm-pre-reloc; + compatible = "test2"; + reg = <0x12345678 0x98765432 2 3>; + }; + +}; diff --git a/tools/dtoc/dtoc_test_addr32_64.dts b/tools/dtoc/dtoc_test_addr32_64.dts new file mode 100644 index 00000000000..1c962433103 --- /dev/null +++ b/tools/dtoc/dtoc_test_addr32_64.dts @@ -0,0 +1,33 @@ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <2>; + + test1 { + u-boot,dm-pre-reloc; + compatible = "test1"; + reg = <0x1234 0x5678 0x0>; + }; + + test2 { + u-boot,dm-pre-reloc; + compatible = "test2"; + reg = <0x12345678 0x98765432 0x10987654>; + }; + + test3 { + u-boot,dm-pre-reloc; + compatible = "test3"; + reg = <0x12345678 0x98765432 0x10987654 2 0 3>; + }; + +}; diff --git a/tools/dtoc/dtoc_test_addr64.dts b/tools/dtoc/dtoc_test_addr64.dts new file mode 100644 index 00000000000..4c0ad0ec360 --- /dev/null +++ b/tools/dtoc/dtoc_test_addr64.dts @@ -0,0 +1,33 @@ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + + test1 { + u-boot,dm-pre-reloc; + compatible = "test1"; + reg = /bits/ 64 <0x1234 0x5678>; + }; + + test2 { + u-boot,dm-pre-reloc; + compatible = "test2"; + reg = /bits/ 64 <0x1234567890123456 0x9876543210987654>; + }; + + test3 { + u-boot,dm-pre-reloc; + compatible = "test3"; + reg = /bits/ 64 <0x1234567890123456 0x9876543210987654 2 3>; + }; + +}; diff --git a/tools/dtoc/dtoc_test_addr64_32.dts b/tools/dtoc/dtoc_test_addr64_32.dts new file mode 100644 index 00000000000..c36f6b726e1 --- /dev/null +++ b/tools/dtoc/dtoc_test_addr64_32.dts @@ -0,0 +1,33 @@ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <1>; + + test1 { + u-boot,dm-pre-reloc; + compatible = "test1"; + reg = <0x1234 0x0 0x5678>; + }; + + test2 { + u-boot,dm-pre-reloc; + compatible = "test2"; + reg = <0x12345678 0x90123456 0x98765432>; + }; + + test3 { + u-boot,dm-pre-reloc; + compatible = "test3"; + reg = <0x12345678 0x90123456 0x98765432 0 2 3>; + }; + +}; diff --git a/tools/dtoc/fdt_util.py b/tools/dtoc/fdt_util.py index bec6ee947a8..338d47a5e14 100644 --- a/tools/dtoc/fdt_util.py +++ b/tools/dtoc/fdt_util.py @@ -38,6 +38,8 @@ def fdt_cells_to_cpu(val, cells): Return: A native-endian long value """ + if not cells: + return 0 out = long(fdt32_to_cpu(val[0])) if cells == 2: out = out << 32 | fdt32_to_cpu(val[1]) diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 5040f233255..09cfddaaaa3 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -270,4 +270,216 @@ U_BOOT_DEVICE(spl_test) = { \t.platdata_size\t= sizeof(dtv_spl_test), }; +''', data) + + def test_addresses64(self): + """Test output from a node with a 'reg' property with na=2, ns=2""" + dtb_file = get_dtb_file('dtoc_test_addr64.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['struct'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +struct dtd_test1 { +\tfdt64_t\t\treg[2]; +}; +struct dtd_test2 { +\tfdt64_t\t\treg[2]; +}; +struct dtd_test3 { +\tfdt64_t\t\treg[4]; +}; +''', data) + + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +#include + +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), +}; + +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), +}; + +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), +}; + +''', data) + + def test_addresses32(self): + """Test output from a node with a 'reg' property with na=1, ns=1""" + dtb_file = get_dtb_file('dtoc_test_addr32.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['struct'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +struct dtd_test1 { +\tfdt32_t\t\treg[2]; +}; +struct dtd_test2 { +\tfdt32_t\t\treg[4]; +}; +''', data) + + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +#include + +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), +}; + +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), +}; + +''', data) + + def test_addresses64_32(self): + """Test output from a node with a 'reg' property with na=2, ns=1""" + dtb_file = get_dtb_file('dtoc_test_addr64_32.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['struct'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +struct dtd_test1 { +\tfdt64_t\t\treg[2]; +}; +struct dtd_test2 { +\tfdt64_t\t\treg[2]; +}; +struct dtd_test3 { +\tfdt64_t\t\treg[4]; +}; +''', data) + + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +#include + +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), +}; + +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), +}; + +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), +}; + +''', data) + + def test_addresses32_64(self): + """Test output from a node with a 'reg' property with na=1, ns=2""" + dtb_file = get_dtb_file('dtoc_test_addr32_64.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['struct'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +struct dtd_test1 { +\tfdt64_t\t\treg[2]; +}; +struct dtd_test2 { +\tfdt64_t\t\treg[2]; +}; +struct dtd_test3 { +\tfdt64_t\t\treg[4]; +}; +''', data) + + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +#include + +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), +}; + +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), +}; + +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), +}; + ''', data) -- cgit v1.3.1 From 5ec741fd84ec2c080a6c400feaaa7f335f5cb62f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:51 -0600 Subject: dtoc: Handle 'reg' properties with unusual sizes At present dtoc assumes that all 'reg' properties have both an address and a size. For I2C devices we do not have this. Adjust dtoc to cope. Reported-by: Philipp Tomsich Signed-off-by: Simon Glass Tested-by: Kever Yang --- tools/dtoc/dtoc_test_simple.dts | 14 ++++++++++++++ tools/dtoc/test_dtoc.py | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+) (limited to 'tools') diff --git a/tools/dtoc/dtoc_test_simple.dts b/tools/dtoc/dtoc_test_simple.dts index c7366862637..6afe674b1f5 100644 --- a/tools/dtoc/dtoc_test_simple.dts +++ b/tools/dtoc/dtoc_test_simple.dts @@ -9,6 +9,8 @@ /dts-v1/; / { + #address-cells = <1>; + #size-cells = <1>; spl-test { u-boot,dm-pre-reloc; compatible = "sandbox,spl-test"; @@ -45,4 +47,16 @@ compatible = "sandbox,spl-test.2"; }; + i2c@0 { + compatible = "sandbox,i2c-test"; + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <0>; + pmic@9 { + compatible = "sandbox,pmic-test"; + u-boot,dm-pre-reloc; + reg = <9>; + low-power; + }; + }; }; diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 09cfddaaaa3..62460acb7c5 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -121,6 +121,12 @@ class TestDtoc(unittest.TestCase): data = infile.read() self.assertEqual('''#include #include +struct dtd_sandbox_i2c_test { +}; +struct dtd_sandbox_pmic_test { +\tbool\t\tlow_power; +\tfdt64_t\t\treg[2]; +}; struct dtd_sandbox_spl_test { \tbool\t\tboolval; \tunsigned char\tbytearray[3]; @@ -192,6 +198,24 @@ U_BOOT_DEVICE(spl_test4) = { \t.platdata_size\t= sizeof(dtv_spl_test4), }; +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), +}; + +static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = { +\t.low_power\t\t= true, +\t.reg\t\t\t= {0x9, 0x0}, +}; +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), +}; + ''', data) def test_phandle(self): -- cgit v1.3.1 From 09264e04330479fbe5bdb647619be4fd90735bfc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:52 -0600 Subject: dtoc: Update the Fdt class to record phandles Add a map from phandles to nodes. This can be used by clients of the the class instead of maintaining this themselves. Signed-off-by: Simon Glass Tested-by: Kever Yang --- tools/dtoc/fdt.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'tools') diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index ffd42ce541d..dbc338653bc 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -212,6 +212,10 @@ class Node: searching into subnodes so that the entire tree is built. """ self.props = self._fdt.GetProps(self) + phandle = self.props.get('phandle') + if phandle: + val = fdt_util.fdt32_to_cpu(phandle.value) + self._fdt.phandle_to_node[val] = self offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.Offset()) while offset >= 0: @@ -263,6 +267,7 @@ class Fdt: def __init__(self, fname): self._fname = fname self._cached_offsets = False + self.phandle_to_node = {} if self._fname: self._fname = fdt_util.EnsureCompiled(self._fname) -- cgit v1.3.1 From 72ab7c5e384f415b66dc9bef41db928cfc11c310 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:53 -0600 Subject: dtoc: Use the Fdt's class's phandle map Now that the Fdt class can map phandles to the associated nodes, use that instead of a separate implementation. Signed-off-by: Simon Glass Tested-by: Kever Yang --- tools/dtoc/dtb_platdata.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'tools') diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 0c719310b10..705ab27c861 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -144,17 +144,14 @@ class DtbPlatdata(object): _dtb_fname: Filename of the input device tree binary file _valid_nodes: A list of Node object with compatible strings _include_disabled: true to include nodes marked status = "disabled" - _phandle_nodes: A dict of nodes indexed by phandle number (1, 2...) _outfile: The current output file (sys.stdout or a real file) _lines: Stashed list of output lines for outputting in the future - _phandle_nodes: A dict of Nodes indexed by phandle (an integer) """ def __init__(self, dtb_fname, include_disabled): self._fdt = None self._dtb_fname = dtb_fname self._valid_nodes = None self._include_disabled = include_disabled - self._phandle_nodes = {} self._outfile = None self._lines = [] self._aliases = {} @@ -210,8 +207,7 @@ class DtbPlatdata(object): def scan_node(self, root): """Scan a node and subnodes to build a tree of node and phandle info - This adds each node to self._valid_nodes and each phandle to - self._phandle_nodes. + This adds each node to self._valid_nodes. Args: root: Root node for scan @@ -222,10 +218,6 @@ class DtbPlatdata(object): if (not self._include_disabled and not status or status.value != 'disabled'): self._valid_nodes.append(node) - phandle_prop = node.props.get('phandle') - if phandle_prop: - phandle = phandle_prop.GetPhandle() - self._phandle_nodes[phandle] = node # recurse to handle any subnodes self.scan_node(node) @@ -234,11 +226,9 @@ class DtbPlatdata(object): """Scan the device tree for useful information This fills in the following properties: - _phandle_nodes: A dict of Nodes indexed by phandle (an integer) _valid_nodes: A list of nodes we wish to consider include in the platform data """ - self._phandle_nodes = {} self._valid_nodes = [] return self.scan_node(self._fdt.GetRoot()) @@ -374,7 +364,7 @@ class DtbPlatdata(object): value_it = iter(prop.value) for phandle_cell, _ in zip(value_it, value_it): phandle = fdt_util.fdt32_to_cpu(phandle_cell) - target_node = self._phandle_nodes[phandle] + target_node = self._fdt.phandle_to_node[phandle] node.phandles.add(target_node) @@ -439,7 +429,7 @@ class DtbPlatdata(object): for phandle_cell, id_cell in zip(value_it, value_it): phandle = fdt_util.fdt32_to_cpu(phandle_cell) id_num = fdt_util.fdt32_to_cpu(id_cell) - target_node = self._phandle_nodes[phandle] + target_node = self._fdt.phandle_to_node[phandle] name = conv_name_to_c(target_node.name) vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id_num)) else: -- cgit v1.3.1 From 2925c26bb2b5450349c2080cac764c18e15a052e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:54 -0600 Subject: dtoc: Make is_phandle() a member function This function will need to have access to class members once we enhance it to support multiple phandle values. In preparation for that, move it into the class. Signed-off-by: Simon Glass Tested-by: Kever Yang --- tools/dtoc/dtb_platdata.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'tools') diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 705ab27c861..a483d6c8757 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -116,21 +116,6 @@ def get_compat_name(node): compat, aliases = compat[0], compat[1:] return conv_name_to_c(compat), [conv_name_to_c(a) for a in aliases] -def is_phandle(prop): - """Check if a node contains phandles - - We have no reliable way of detecting whether a node uses a phandle - or not. As an interim measure, use a list of known property names. - - Args: - prop: Prop object to check - Return: - True if the object value contains phandles, else False - """ - if prop.name in ['clocks']: - return True - return False - class DtbPlatdata(object): """Provide a means to convert device tree binary data to platform data @@ -196,6 +181,21 @@ class DtbPlatdata(object): self._lines = [] return lines + def is_phandle(self, prop): + """Check if a node contains phandles + + We have no reliable way of detecting whether a node uses a phandle + or not. As an interim measure, use a list of known property names. + + Args: + prop: Prop object to check + Return: + True if the object value contains phandles, else False + """ + if prop.name in ['clocks']: + return True + return False + def scan_dtb(self): """Scan the device tree to obtain a tree of nodes and properties @@ -359,7 +359,7 @@ class DtbPlatdata(object): if pname in PROP_IGNORE_LIST or pname[0] == '#': continue if isinstance(prop.value, list): - if is_phandle(prop): + if self.is_phandle(prop): # Process the list as pairs of (phandle, id) value_it = iter(prop.value) for phandle_cell, _ in zip(value_it, value_it): @@ -383,7 +383,7 @@ class DtbPlatdata(object): self.out('struct %s%s {\n' % (STRUCT_PREFIX, name)) for pname in sorted(structs[name]): prop = structs[name][pname] - if is_phandle(prop): + if self.is_phandle(prop): # For phandles, include a reference to the target self.out('\t%s%s[%d]' % (tab_to(2, 'struct phandle_2_cell'), conv_name_to_c(prop.name), @@ -423,7 +423,7 @@ class DtbPlatdata(object): vals = [] # For phandles, output a reference to the platform data # of the target node. - if is_phandle(prop): + if self.is_phandle(prop): # Process the list as pairs of (phandle, id) value_it = iter(prop.value) for phandle_cell, id_cell in zip(value_it, value_it): -- cgit v1.3.1 From 8fed2eb20c2ef95d69f9683ab07f0ea869616713 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:55 -0600 Subject: dtoc: Rename is_phandle() and adjust it to return more detail Update this function to return more detail about a property that contains phandles. This will allow (in a future commit) more accurate handling of these properties. Signed-off-by: Simon Glass Tested-by: Kever Yang --- tools/dtoc/dtb_platdata.py | 79 +++++++++++++++++++++++++++++----------- tools/dtoc/dtoc_test_phandle.dts | 1 + 2 files changed, 58 insertions(+), 22 deletions(-) (limited to 'tools') diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index a483d6c8757..001bc4ea668 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -12,6 +12,7 @@ This supports converting device tree data to C structures definitions and static data. """ +import collections import copy import sys @@ -44,6 +45,14 @@ TYPE_NAMES = { STRUCT_PREFIX = 'dtd_' VAL_PREFIX = 'dtv_' +# This holds information about a property which includes phandles. +# +# max_args: integer: Maximum number or arguments that any phandle uses (int). +# args: Number of args for each phandle in the property. The total number of +# phandles is len(args). This is a list of integers. +PhandleInfo = collections.namedtuple('PhandleInfo', ['max_args', 'args']) + + def conv_name_to_c(name): """Convert a device-tree name to a C identifier @@ -181,20 +190,42 @@ class DtbPlatdata(object): self._lines = [] return lines - def is_phandle(self, prop): - """Check if a node contains phandles + def get_phandle_argc(self, prop, node_name): + """Check if a node contains phandles - We have no reliable way of detecting whether a node uses a phandle - or not. As an interim measure, use a list of known property names. + We have no reliable way of detecting whether a node uses a phandle + or not. As an interim measure, use a list of known property names. - Args: - prop: Prop object to check - Return: - True if the object value contains phandles, else False - """ - if prop.name in ['clocks']: - return True - return False + Args: + prop: Prop object to check + Return: + Number of argument cells is this is a phandle, else None + """ + if prop.name in ['clocks']: + val = prop.value + if not isinstance(val, list): + val = [val] + i = 0 + + max_args = 0 + args = [] + while i < len(val): + phandle = fdt_util.fdt32_to_cpu(val[i]) + target = self._fdt.phandle_to_node.get(phandle) + 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) + if not cells: + raise ValueError("Node '%s' has no '%s' property" % + (target.name, prop_name)) + num_args = fdt_util.fdt32_to_cpu(cells.value) + max_args = max(max_args, num_args) + args.append(num_args) + i += 1 + num_args + return PhandleInfo(max_args, args) + return None def scan_dtb(self): """Scan the device tree to obtain a tree of nodes and properties @@ -358,14 +389,16 @@ class DtbPlatdata(object): for pname, prop in node.props.items(): if pname in PROP_IGNORE_LIST or pname[0] == '#': continue - if isinstance(prop.value, list): - if self.is_phandle(prop): - # Process the list as pairs of (phandle, id) - value_it = iter(prop.value) - for phandle_cell, _ in zip(value_it, value_it): - phandle = fdt_util.fdt32_to_cpu(phandle_cell) - target_node = self._fdt.phandle_to_node[phandle] - node.phandles.add(target_node) + info = self.get_phandle_argc(prop, node.name) + if info: + if not isinstance(prop.value, list): + prop.value = [prop.value] + # Process the list as pairs of (phandle, id) + value_it = iter(prop.value) + for phandle_cell, _ in zip(value_it, value_it): + phandle = fdt_util.fdt32_to_cpu(phandle_cell) + target_node = self._fdt.phandle_to_node[phandle] + node.phandles.add(target_node) def generate_structs(self, structs): @@ -383,7 +416,8 @@ class DtbPlatdata(object): self.out('struct %s%s {\n' % (STRUCT_PREFIX, name)) for pname in sorted(structs[name]): prop = structs[name][pname] - if self.is_phandle(prop): + info = self.get_phandle_argc(prop, structs[name]) + if info: # For phandles, include a reference to the target self.out('\t%s%s[%d]' % (tab_to(2, 'struct phandle_2_cell'), conv_name_to_c(prop.name), @@ -423,7 +457,8 @@ class DtbPlatdata(object): vals = [] # For phandles, output a reference to the platform data # of the target node. - if self.is_phandle(prop): + info = self.get_phandle_argc(prop, node.name) + if info: # Process the list as pairs of (phandle, id) value_it = iter(prop.value) for phandle_cell, id_cell in zip(value_it, value_it): diff --git a/tools/dtoc/dtoc_test_phandle.dts b/tools/dtoc/dtoc_test_phandle.dts index e9828a695b5..c0a602f2967 100644 --- a/tools/dtoc/dtoc_test_phandle.dts +++ b/tools/dtoc/dtoc_test_phandle.dts @@ -13,6 +13,7 @@ u-boot,dm-pre-reloc; compatible = "target"; intval = <1>; + #clock-cells = <1>; }; phandle-source { -- cgit v1.3.1 From 0d15463c0537806f70ea2359e32e4deb8c4766c2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:56 -0600 Subject: dtoc: Rename the phandle struct Rather than naming the phandle struct according to the number of cells it uses (e.g. struct phandle_2_cell) name it according to the number of arguments it has (e.g. struct phandle_1_arg). This is a more intuitive naming. Signed-off-by: Simon Glass Tested-by: Kever Yang --- doc/driver-model/of-plat.txt | 2 +- drivers/clk/clk-uclass.c | 2 +- include/clk.h | 4 ++-- include/dt-structs.h | 7 ++++++- tools/dtoc/dtb_platdata.py | 3 ++- tools/dtoc/test_dtoc.py | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/doc/driver-model/of-plat.txt b/doc/driver-model/of-plat.txt index 3ed8c759d69..732bc34f067 100644 --- a/doc/driver-model/of-plat.txt +++ b/doc/driver-model/of-plat.txt @@ -111,7 +111,7 @@ struct dtd_rockchip_rk3288_dw_mshc { bool cap_sd_highspeed; fdt32_t card_detect_delay; fdt32_t clock_freq_min_max[2]; - struct phandle_2_cell clocks[4]; + struct phandle_1_arg clocks[4]; bool disable_wp; fdt32_t fifo_depth; fdt32_t interrupts[3]; diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index e68d9279b96..8b40326efa2 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -23,7 +23,7 @@ static inline 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_2_cell *cells, struct clk *clk) + struct phandle_1_arg *cells, struct clk *clk) { int ret; diff --git a/include/clk.h b/include/clk.h index c5988f78a8f..e7ce3e85768 100644 --- a/include/clk.h +++ b/include/clk.h @@ -61,9 +61,9 @@ struct clk { }; #if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(CLK) -struct phandle_2_cell; +struct phandle_1_arg; int clk_get_by_index_platdata(struct udevice *dev, int index, - struct phandle_2_cell *cells, struct clk *clk); + struct phandle_1_arg *cells, struct clk *clk); /** * clock_get_by_index - Get/request a clock by integer index. diff --git a/include/dt-structs.h b/include/dt-structs.h index 0732c442ff8..2ed997115ae 100644 --- a/include/dt-structs.h +++ b/include/dt-structs.h @@ -9,7 +9,12 @@ /* These structures may only be used in SPL */ #if CONFIG_IS_ENABLED(OF_PLATDATA) -struct phandle_2_cell { +struct phandle_0_arg { + const void *node; + int id[0]; +}; + +struct phandle_1_arg { const void *node; int id; }; diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 001bc4ea668..0234f71b767 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -419,7 +419,8 @@ class DtbPlatdata(object): info = self.get_phandle_argc(prop, structs[name]) if info: # For phandles, include a reference to the target - self.out('\t%s%s[%d]' % (tab_to(2, 'struct phandle_2_cell'), + struct_name = 'struct phandle_%d_arg' % info.max_args + self.out('\t%s%s[%d]' % (tab_to(2, struct_name), conv_name_to_c(prop.name), len(prop.value) / 2)) else: diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 62460acb7c5..23c4439ed91 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -228,7 +228,7 @@ U_BOOT_DEVICE(pmic_at_9) = { self.assertEqual('''#include #include struct dtd_source { -\tstruct phandle_2_cell clocks[1]; +\tstruct phandle_1_arg clocks[1]; }; struct dtd_target { \tfdt32_t\t\tintval; -- cgit v1.3.1 From 35d503700f294b6f5dd930e2c1b0dd841f1b58fb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:57 -0600 Subject: dtoc: Put each phandle on a separate line When writing values from properties which contain phandles, dtoc currently writes 8 phandles per line. Change this to write one phandle per line. This helps reduce line length, since phandles are generally longer and may have arguments. Signed-off-by: Simon Glass Tested-by: Kever Yang --- tools/dtoc/dtb_platdata.py | 12 +++++++----- tools/dtoc/test_dtoc.py | 3 ++- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 0234f71b767..c0a3ae692bc 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -468,15 +468,17 @@ class DtbPlatdata(object): target_node = self._fdt.phandle_to_node[phandle] name = conv_name_to_c(target_node.name) vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id_num)) + for val in vals: + self.buf('\n\t\t%s,' % val) else: for val in prop.value: vals.append(get_value(prop.type, val)) - # Put 8 values per line to avoid very long lines. - for i in xrange(0, len(vals), 8): - if i: - self.buf(',\n\t\t') - self.buf(', '.join(vals[i:i + 8])) + # Put 8 values per line to avoid very long lines. + for i in xrange(0, len(vals), 8): + if i: + self.buf(',\n\t\t') + self.buf(', '.join(vals[i:i + 8])) self.buf('}') else: self.buf(get_value(prop.type, prop.value)) diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 23c4439ed91..aa617a649c8 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -252,7 +252,8 @@ U_BOOT_DEVICE(phandle_target) = { }; static struct dtd_source dtv_phandle_source = { -\t.clocks\t\t\t= {{&dtv_phandle_target, 1}}, +\t.clocks\t\t\t= { +\t\t{&dtv_phandle_target, 1},}, }; U_BOOT_DEVICE(phandle_source) = { \t.name\t\t= "source", -- cgit v1.3.1 From bc79617fdfeb4afabb94774885447dd64d7bea6c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:58 -0600 Subject: dtoc: Put phandle args in an array We want to support more than one phandle argument. It makes sense to use an array for this rather than discrete struct members. Adjust the code to support this. Rename the member to 'arg' instead of 'id'. Signed-off-by: Simon Glass Tested-by: Kever Yang --- drivers/clk/clk-uclass.c | 2 +- include/dt-structs.h | 4 ++-- tools/dtoc/dtb_platdata.py | 2 +- tools/dtoc/test_dtoc.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 8b40326efa2..83ba13374c7 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -32,7 +32,7 @@ int clk_get_by_index_platdata(struct udevice *dev, int index, ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev); if (ret) return ret; - clk->id = cells[0].id; + clk->id = cells[0].arg[0]; return 0; } diff --git a/include/dt-structs.h b/include/dt-structs.h index 2ed997115ae..9ab4e2524d1 100644 --- a/include/dt-structs.h +++ b/include/dt-structs.h @@ -11,12 +11,12 @@ #if CONFIG_IS_ENABLED(OF_PLATDATA) struct phandle_0_arg { const void *node; - int id[0]; + int arg[0]; }; struct phandle_1_arg { const void *node; - int id; + int arg[1]; }; #include #endif diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index c0a3ae692bc..1920a59f821 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -467,7 +467,7 @@ class DtbPlatdata(object): id_num = fdt_util.fdt32_to_cpu(id_cell) target_node = self._fdt.phandle_to_node[phandle] name = conv_name_to_c(target_node.name) - vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id_num)) + vals.append('{&%s%s, {%d}}' % (VAL_PREFIX, name, id_num)) for val in vals: self.buf('\n\t\t%s,' % val) else: diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index aa617a649c8..fbae927cf8f 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -253,7 +253,7 @@ U_BOOT_DEVICE(phandle_target) = { static struct dtd_source dtv_phandle_source = { \t.clocks\t\t\t= { -\t\t{&dtv_phandle_target, 1},}, +\t\t{&dtv_phandle_target, {1}},}, }; U_BOOT_DEVICE(phandle_source) = { \t.name\t\t= "source", -- cgit v1.3.1 From 634eba4be060af3bcba51cba2d57d217df897f31 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:15:59 -0600 Subject: dtoc: Support properties containing multiple phandle values At present dtoc has a very simplistic view of phandles. It assumes that a property has only a single phandle with a single argument (i.e. two cells per property). This is not true in many cases. Enhance the implementation to scan all phandles in a property and to use the correct number of arguments (which can be 0, 1, 2 or more) when generating the C code. For the struct definitions, use a struct which can hold the maximum number of arguments used by the property. Signed-off-by: Simon Glass Tested-by: Kever Yang --- include/dt-structs.h | 5 +++++ tools/dtoc/dtb_platdata.py | 21 ++++++++++++++------- tools/dtoc/dtoc_test_phandle.dts | 17 +++++++++++++++-- tools/dtoc/test_dtoc.py | 27 ++++++++++++++++++++++++--- 4 files changed, 58 insertions(+), 12 deletions(-) (limited to 'tools') diff --git a/include/dt-structs.h b/include/dt-structs.h index 9ab4e2524d1..76979e73e17 100644 --- a/include/dt-structs.h +++ b/include/dt-structs.h @@ -18,6 +18,11 @@ struct phandle_1_arg { const void *node; int arg[1]; }; + +struct phandle_2_arg { + const void *node; + int arg[2]; +}; #include #endif diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 1920a59f821..cfca45b0ac9 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -394,11 +394,13 @@ class DtbPlatdata(object): if not isinstance(prop.value, list): prop.value = [prop.value] # Process the list as pairs of (phandle, id) - value_it = iter(prop.value) - for phandle_cell, _ in zip(value_it, value_it): + pos = 0 + for args in info.args: + phandle_cell = prop.value[pos] phandle = fdt_util.fdt32_to_cpu(phandle_cell) target_node = self._fdt.phandle_to_node[phandle] node.phandles.add(target_node) + pos += 1 + args def generate_structs(self, structs): @@ -422,7 +424,7 @@ class DtbPlatdata(object): struct_name = 'struct phandle_%d_arg' % info.max_args self.out('\t%s%s[%d]' % (tab_to(2, struct_name), conv_name_to_c(prop.name), - len(prop.value) / 2)) + len(info.args))) else: ptype = TYPE_NAMES[prop.type] self.out('\t%s%s' % (tab_to(2, ptype), @@ -461,13 +463,18 @@ class DtbPlatdata(object): info = self.get_phandle_argc(prop, node.name) if info: # Process the list as pairs of (phandle, id) - value_it = iter(prop.value) - for phandle_cell, id_cell in zip(value_it, value_it): + pos = 0 + for args in info.args: + phandle_cell = prop.value[pos] phandle = fdt_util.fdt32_to_cpu(phandle_cell) - id_num = fdt_util.fdt32_to_cpu(id_cell) target_node = self._fdt.phandle_to_node[phandle] name = conv_name_to_c(target_node.name) - vals.append('{&%s%s, {%d}}' % (VAL_PREFIX, name, id_num)) + arg_values = [] + 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))) for val in vals: self.buf('\n\t\t%s,' % val) else: diff --git a/tools/dtoc/dtoc_test_phandle.dts b/tools/dtoc/dtoc_test_phandle.dts index c0a602f2967..ba12b0fe65e 100644 --- a/tools/dtoc/dtoc_test_phandle.dts +++ b/tools/dtoc/dtoc_test_phandle.dts @@ -10,15 +10,28 @@ / { phandle: phandle-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <0>; + #clock-cells = <0>; + }; + + phandle_1: phandle2-target { u-boot,dm-pre-reloc; compatible = "target"; intval = <1>; - #clock-cells = <1>; + #clock-cells = <1>; + }; + phandle_2: phandle3-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <2>; + #clock-cells = <2>; }; phandle-source { u-boot,dm-pre-reloc; compatible = "source"; - clocks = <&phandle 1>; + clocks = <&phandle &phandle_1 11 &phandle_2 12 13 &phandle>; }; }; diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index fbae927cf8f..cc009b2a256 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -228,7 +228,7 @@ U_BOOT_DEVICE(pmic_at_9) = { self.assertEqual('''#include #include struct dtd_source { -\tstruct phandle_1_arg clocks[1]; +\tstruct phandle_2_arg clocks[4]; }; struct dtd_target { \tfdt32_t\t\tintval; @@ -243,7 +243,7 @@ struct dtd_target { #include static struct dtd_target dtv_phandle_target = { -\t.intval\t\t\t= 0x1, +\t.intval\t\t\t= 0x0, }; U_BOOT_DEVICE(phandle_target) = { \t.name\t\t= "target", @@ -251,9 +251,30 @@ U_BOOT_DEVICE(phandle_target) = { \t.platdata_size\t= sizeof(dtv_phandle_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), +}; + +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), +}; + static struct dtd_source dtv_phandle_source = { \t.clocks\t\t\t= { -\t\t{&dtv_phandle_target, {1}},}, +\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, {}},}, }; U_BOOT_DEVICE(phandle_source) = { \t.name\t\t= "source", -- cgit v1.3.1 From d503114c66a76b5ceb9d72da2c9b5231eb6743b8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Aug 2017 14:16:01 -0600 Subject: dtoc: Add a header to the generated files Add a header that indicates that the files generated by dtoc should not be modified. Signed-off-by: Simon Glass Tested-by: Kever Yang --- tools/dtoc/dtb_platdata.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'tools') diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index cfca45b0ac9..dc9c0d9f458 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -190,6 +190,16 @@ class DtbPlatdata(object): self._lines = [] return lines + def out_header(self): + """Output a message indicating that this is an auto-generated file""" + self.out('''/* + * DO NOT MODIFY + * + * This file was generated by dtoc from a .dtb (device tree binary) file. + */ + +''') + def get_phandle_argc(self, prop, node_name): """Check if a node contains phandles @@ -410,6 +420,7 @@ class DtbPlatdata(object): definitions for node in self._valid_nodes. See the documentation in README.of-plat for more information. """ + self.out_header() self.out('#include \n') self.out('#include \n') @@ -512,6 +523,7 @@ class DtbPlatdata(object): See the documentation in doc/driver-model/of-plat.txt for more information. """ + self.out_header() self.out('#include \n') self.out('#include \n') self.out('#include \n') -- cgit v1.3.1