summaryrefslogtreecommitdiff
path: root/tools/dtoc
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2017-08-29 14:15:50 -0600
committerSimon Glass <sjg@chromium.org>2017-09-15 05:27:38 -0600
commitc20ee0ed070953600b54b16c8b48725348abead5 (patch)
tree301cfe10856064ecb02dff25dcbcc856d8a1ea06 /tools/dtoc
parent21d54ac353d76d46848cb7fae14a07775cc3bacf (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.py61
-rw-r--r--tools/dtoc/dtoc_test_addr32.dts27
-rw-r--r--tools/dtoc/dtoc_test_addr32_64.dts33
-rw-r--r--tools/dtoc/dtoc_test_addr64.dts33
-rw-r--r--tools/dtoc/dtoc_test_addr64_32.dts33
-rw-r--r--tools/dtoc/fdt_util.py2
-rw-r--r--tools/dtoc/test_dtoc.py212
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)