diff options
author | Simon Glass <sjg@chromium.org> | 2017-08-29 14:15:50 -0600 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2017-09-15 05:27:38 -0600 |
commit | c20ee0ed070953600b54b16c8b48725348abead5 (patch) | |
tree | 301cfe10856064ecb02dff25dcbcc856d8a1ea06 /tools/dtoc | |
parent | 21d54ac353d76d46848cb7fae14a07775cc3bacf (diff) |
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 <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: Kever Yang <kever.yang@rock-chips.com>
Diffstat (limited to 'tools/dtoc')
-rw-r--r-- | tools/dtoc/dtb_platdata.py | 61 | ||||
-rw-r--r-- | tools/dtoc/dtoc_test_addr32.dts | 27 | ||||
-rw-r--r-- | tools/dtoc/dtoc_test_addr32_64.dts | 33 | ||||
-rw-r--r-- | tools/dtoc/dtoc_test_addr64.dts | 33 | ||||
-rw-r--r-- | tools/dtoc/dtoc_test_addr64_32.dts | 33 | ||||
-rw-r--r-- | tools/dtoc/fdt_util.py | 2 | ||||
-rw-r--r-- | tools/dtoc/test_dtoc.py | 212 |
7 files changed, 401 insertions, 0 deletions
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 3243bccfe8..0c719310b1 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 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/fdt_util.py b/tools/dtoc/fdt_util.py index bec6ee947a..338d47a5e1 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 5040f23325..09cfddaaaa 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -271,3 +271,215 @@ U_BOOT_DEVICE(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) |