[U-Boot] [PATCH 0/3] dtoc: Add support for 64-bit addresses

This series updates dtoc to support 64-bit addresses automatically. These appear in C code as fdt64_t arrays:
struct dtd_test1 { fdt64_t reg[2];
};
static struct dtd_test1 dtv_test1 = { .reg = {0x123400000000, 0x5678}, };
C code can then process these address and size parents easily. This feature is controlled by the #address-cells and #size-cells values of the parent.
Simon Glass (3): dtoc: Adjust Node to record its parent dtoc: Add a 64-bit type and a way to convert cells into 64 bits dtoc: Add support for 32 or 64-bit addresses
tools/dtoc/dtb_platdata.py | 62 +++++++++++ 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.py | 14 +-- tools/dtoc/fdt_util.py | 14 +++ tools/dtoc/test_dtoc.py | 212 +++++++++++++++++++++++++++++++++++++ 8 files changed, 422 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

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 sjg@chromium.org ---
tools/dtoc/fdt.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index 63a32ea2d7..49409a62ec 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):

On Mon, 19 Jun 2017, Simon Glass wrote:
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 sjg@chromium.org
Reviewed-by: Philipp Tomsich philipp.tomsich@theobroma-systems.com Tested-by: Philipp Tomsich philipp.tomsich@theobroma-systems.com

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 sjg@chromium.org ---
tools/dtoc/dtb_platdata.py | 3 +++ tools/dtoc/fdt.py | 2 +- tools/dtoc/fdt_util.py | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 1f85343a9f..f5841cbb88 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 49409a62ec..ffd42ce541 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 b9dfae8d0e..bec6ee947a 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.

On Mon, 19 Jun 2017, Simon Glass wrote:
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 sjg@chromium.org
Reviewed-by: Philipp Tomsich philipp.tomsich@theobroma-systems.com Tested-by: Philipp Tomsich philipp.tomsich@theobroma-systems.com

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.
Add tests for the four combinations of address and size values (32/32, 64/64, 32/64, 64/32).
Signed-off-by: Simon Glass sjg@chromium.org Suggested-by: Heiko Stuebner heiko@sntech.de Reported-by: Kever Yang kever.yang@rock-chips.com ---
tools/dtoc/dtb_platdata.py | 59 +++++++++++ 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/test_dtoc.py | 212 +++++++++++++++++++++++++++++++++++++ 6 files changed, 397 insertions(+) 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
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index f5841cbb88..3de1a20dbd 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -242,6 +242,64 @@ 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 + 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.
@@ -445,6 +503,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 0000000000..bcfdcae10b --- /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 0000000000..1c96243310 --- /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 0000000000..4c0ad0ec36 --- /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 0000000000..c36f6b726e --- /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/test_dtoc.py b/tools/dtoc/test_dtoc.py index 35aa4c9817..d91ff88c85 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -268,4 +268,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 <stdbool.h> +#include <libfdt.h> +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 <common.h> +#include <dm.h> +#include <dt-structs.h> + +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 <stdbool.h> +#include <libfdt.h> +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 <common.h> +#include <dm.h> +#include <dt-structs.h> + +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 <stdbool.h> +#include <libfdt.h> +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 <common.h> +#include <dm.h> +#include <dt-structs.h> + +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 <stdbool.h> +#include <libfdt.h> +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 <common.h> +#include <dm.h> +#include <dt-structs.h> + +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)

On 20 Jun 2017, at 05:34, Simon Glass sjg@chromium.org wrote:
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.
This breaks ‘regmap_init_mem_platdata’, which assumes that it processes 32bit words (i.e. both addr and size are 32bit).
Or did I just miss another changeset?
Add tests for the four combinations of address and size values (32/32, 64/64, 32/64, 64/32).
Signed-off-by: Simon Glass sjg@chromium.org Suggested-by: Heiko Stuebner heiko@sntech.de Reported-by: Kever Yang kever.yang@rock-chips.com
tools/dtoc/dtb_platdata.py | 59 +++++++++++ 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/test_dtoc.py | 212 +++++++++++++++++++++++++++++++++++++ 6 files changed, 397 insertions(+) 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
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index f5841cbb88..3de1a20dbd 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -242,6 +242,64 @@ 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
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.
@@ -445,6 +503,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 0000000000..bcfdcae10b --- /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 0000000000..1c96243310 --- /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 0000000000..4c0ad0ec36 --- /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 0000000000..c36f6b726e --- /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/test_dtoc.py b/tools/dtoc/test_dtoc.py index 35aa4c9817..d91ff88c85 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -268,4 +268,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 <stdbool.h>
+#include <libfdt.h> +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 <common.h>
+#include <dm.h> +#include <dt-structs.h>
+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 <stdbool.h>
+#include <libfdt.h> +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 <common.h>
+#include <dm.h> +#include <dt-structs.h>
+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 <stdbool.h>
+#include <libfdt.h> +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 <common.h>
+#include <dm.h> +#include <dt-structs.h>
+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 <stdbool.h>
+#include <libfdt.h> +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 <common.h>
+#include <dm.h> +#include <dt-structs.h>
+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)
2.13.1.518.g3df882009-goog

On Mon, 19 Jun 2017, Simon Glass wrote:
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.
Add tests for the four combinations of address and size values (32/32, 64/64, 32/64, 64/32).
Signed-off-by: Simon Glass sjg@chromium.org Suggested-by: Heiko Stuebner heiko@sntech.de Reported-by: Kever Yang kever.yang@rock-chips.com
Reviewed-by: Philipp Tomsich philipp.tomsich@theobroma-systems.com Tested-by: Philipp Tomsich philipp.tomsich@theobroma-systems.com
See below for comments.
tools/dtoc/dtb_platdata.py | 59 +++++++++++ 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/test_dtoc.py | 212 +++++++++++++++++++++++++++++++++++++ 6 files changed, 397 insertions(+) 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
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index f5841cbb88..3de1a20dbd 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -242,6 +242,64 @@ 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
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
If there's just a single element in the reg expression (e.g. reg = <1>), as will be the case for I2C or SPI devices, the type of reg.na will be str instead of list... thus causing a failures in fdt_cells_to_cpu.
new_value += [addr, size]
reg.value = new_value
- def scan_structs(self): """Scan the device tree building up the C structures we will use.
@@ -445,6 +503,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 0000000000..bcfdcae10b --- /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 0000000000..1c96243310 --- /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 0000000000..4c0ad0ec36 --- /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 0000000000..c36f6b726e --- /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/test_dtoc.py b/tools/dtoc/test_dtoc.py index 35aa4c9817..d91ff88c85 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -268,4 +268,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 <stdbool.h>
+#include <libfdt.h> +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 <common.h>
+#include <dm.h> +#include <dt-structs.h>
+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 <stdbool.h>
+#include <libfdt.h> +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 <common.h>
+#include <dm.h> +#include <dt-structs.h>
+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 <stdbool.h>
+#include <libfdt.h> +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 <common.h>
+#include <dm.h> +#include <dt-structs.h>
+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 <stdbool.h>
+#include <libfdt.h> +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 <common.h>
+#include <dm.h> +#include <dt-structs.h>
+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)

Simon,
On 20 Jun 2017, at 05:34, Simon Glass sjg@chromium.org wrote:
This series updates dtoc to support 64-bit addresses automatically. These appear in C code as fdt64_t arrays:
struct dtd_test1 { fdt64_t reg[2];
};
static struct dtd_test1 dtv_test1 = { .reg = {0x123400000000, 0x5678}, };
C code can then process these address and size parents easily. This feature is controlled by the #address-cells and #size-cells values of the parent.
Simon Glass (3): dtoc: Adjust Node to record its parent dtoc: Add a 64-bit type and a way to convert cells into 64 bits dtoc: Add support for 32 or 64-bit addresses
tools/dtoc/dtb_platdata.py | 62 +++++++++++ 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.py | 14 +-- tools/dtoc/fdt_util.py | 14 +++ tools/dtoc/test_dtoc.py | 212 +++++++++++++++++++++++++++++++++++++ 8 files changed, 422 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
—
While testing this for the TPL stage of the RK3368, I triggered an error:
Traceback (most recent call last): File "./tools/dtoc/dtoc", line 76, in <module> options.output) File "/hgst-3tb/home/ptomsich/rk3399-spl/u-boot/tools/dtoc/dtb_platdata.py", line 510, in run_steps plat.scan_reg_sizes() File "/hgst-3tb/home/ptomsich/rk3399-spl/u-boot/tools/dtoc/dtb_platdata.py", line 297, in scan_reg_sizes addr = fdt_util.fdt_cells_to_cpu(val[i:], reg.na) File "/hgst-3tb/home/ptomsich/rk3399-spl/u-boot/tools/dtoc/fdt_util.py", line 41, in fdt_cells_to_cpu out = long(fdt32_to_cpu(val[0])) File "/hgst-3tb/home/ptomsich/rk3399-spl/u-boot/tools/dtoc/fdt_util.py", line 30, in fdt32_to_cpu return struct.unpack('>I', val)[0] struct.error: unpack requires a string argument of length 4
with the following DTS snippet:
spi@ff120000 { compatible = "rockchip,rk3368-spi", "rockchip,rk3066-spi"; reg = <0x0 0xff120000 0x0 0x1000>; clocks = <0xb 0x42 0xb 0x153>; clock-names = "spiclk", "apb_pclk"; interrupts = <0x0 0x2d 0x4>; #address-cells = <0x1>; #size-cells = <0x0>; status = "okay"; u-boot,dm-pre-reloc;
w25q32dw@0 { u-boot,dm-pre-reloc; compatible = "spi-flash"; reg = <0x0>; spi-max-frequency = <0x2f34f60>; spi-cpol; spi-cpha; };
};
A bit of debug code shows that the error occurs during the processing of the 'w25q32dw@0’ node.
Note that this is not a showstopper for the RK3368, as OF_PLATDATA is only used for TPL, which performs a return-to-bootrom anyway (and I will be making this more explicit by using the 'dm-spl’ and ‘dm-tpl’ decorators).
Regards, Phil.
participants (3)
-
Dr. Philipp Tomsich
-
Philipp Tomsich
-
Simon Glass