Author: kevans
Date: Fri Jan 12 21:44:53 2018
New Revision: 327893
URL: https://svnweb.freebsd.org/changeset/base/327893

Log:
  Import dtc 1.4.6

Added:
  vendor/dtc/dist/fdtoverlay.c   (contents, props changed)
  vendor/dtc/dist/pylibfdt/
  vendor/dtc/dist/pylibfdt/Makefile.pylibfdt   (contents, props changed)
  vendor/dtc/dist/pylibfdt/libfdt.i
  vendor/dtc/dist/pylibfdt/setup.py   (contents, props changed)
  vendor/dtc/dist/tests/bad-chosen.dts   (contents, props changed)
  vendor/dtc/dist/tests/bad-gpio.dts   (contents, props changed)
  vendor/dtc/dist/tests/bad-interrupt-cells.dts   (contents, props changed)
  vendor/dtc/dist/tests/bad-phandle-cells.dts   (contents, props changed)
  vendor/dtc/dist/tests/fdtoverlay-runtest.sh   (contents, props changed)
  vendor/dtc/dist/tests/pci-bridge-bad1.dts   (contents, props changed)
  vendor/dtc/dist/tests/pci-bridge-bad2.dts   (contents, props changed)
  vendor/dtc/dist/tests/pci-bridge-ok.dts   (contents, props changed)
  vendor/dtc/dist/tests/pylibfdt_tests.py   (contents, props changed)
  vendor/dtc/dist/tests/stacked_overlay_bar.dts   (contents, props changed)
  vendor/dtc/dist/tests/stacked_overlay_base.dts   (contents, props changed)
  vendor/dtc/dist/tests/stacked_overlay_baz.dts   (contents, props changed)
  vendor/dtc/dist/tests/unit-addr-leading-0s.dts   (contents, props changed)
  vendor/dtc/dist/tests/unit-addr-leading-0x.dts   (contents, props changed)
Modified:
  vendor/dtc/dist/Documentation/manual.txt
  vendor/dtc/dist/Makefile
  vendor/dtc/dist/Makefile.utils
  vendor/dtc/dist/README
  vendor/dtc/dist/checks.c
  vendor/dtc/dist/convert-dtsv0-lexer.l
  vendor/dtc/dist/data.c
  vendor/dtc/dist/dtc-lexer.l
  vendor/dtc/dist/dtc-parser.y
  vendor/dtc/dist/dtc.c
  vendor/dtc/dist/dtc.h
  vendor/dtc/dist/fdtdump.c
  vendor/dtc/dist/fdtget.c
  vendor/dtc/dist/fdtput.c
  vendor/dtc/dist/flattree.c
  vendor/dtc/dist/libfdt/fdt.c
  vendor/dtc/dist/libfdt/fdt.h
  vendor/dtc/dist/libfdt/fdt_empty_tree.c
  vendor/dtc/dist/libfdt/fdt_overlay.c
  vendor/dtc/dist/libfdt/fdt_ro.c
  vendor/dtc/dist/libfdt/fdt_rw.c
  vendor/dtc/dist/libfdt/fdt_sw.c
  vendor/dtc/dist/libfdt/fdt_wip.c
  vendor/dtc/dist/libfdt/libfdt.h
  vendor/dtc/dist/libfdt/libfdt_env.h
  vendor/dtc/dist/libfdt/libfdt_internal.h
  vendor/dtc/dist/libfdt/version.lds
  vendor/dtc/dist/livetree.c
  vendor/dtc/dist/srcpos.h
  vendor/dtc/dist/tests/Makefile.tests
  vendor/dtc/dist/tests/bad-string-props.dts
  vendor/dtc/dist/tests/char_literal.c
  vendor/dtc/dist/tests/dtbs_equal_ordered.c
  vendor/dtc/dist/tests/dtbs_equal_unordered.c
  vendor/dtc/dist/tests/dumptrees.c
  vendor/dtc/dist/tests/include7.dts
  vendor/dtc/dist/tests/integer-expressions.c
  vendor/dtc/dist/tests/node_check_compatible.c
  vendor/dtc/dist/tests/node_offset_by_prop_value.c
  vendor/dtc/dist/tests/nopulate.c
  vendor/dtc/dist/tests/path-references.c
  vendor/dtc/dist/tests/path-references.dts
  vendor/dtc/dist/tests/property_iterate.c
  vendor/dtc/dist/tests/references.c
  vendor/dtc/dist/tests/run_tests.sh
  vendor/dtc/dist/tests/sized_cells.c
  vendor/dtc/dist/tests/stringlist.c
  vendor/dtc/dist/tests/subnode_iterate.c
  vendor/dtc/dist/tests/sw_tree1.c
  vendor/dtc/dist/tests/test_tree1.dts
  vendor/dtc/dist/tests/test_tree1_label_noderef.dts
  vendor/dtc/dist/tests/testdata.h
  vendor/dtc/dist/tests/tests.h
  vendor/dtc/dist/tests/tests.sh
  vendor/dtc/dist/tests/trees.S
  vendor/dtc/dist/tests/truncated_property.c
  vendor/dtc/dist/tests/value-labels.c
  vendor/dtc/dist/treesource.c
  vendor/dtc/dist/util.c
  vendor/dtc/dist/util.h

Modified: vendor/dtc/dist/Documentation/manual.txt
==============================================================================
--- vendor/dtc/dist/Documentation/manual.txt    Fri Jan 12 20:40:27 2018        
(r327892)
+++ vendor/dtc/dist/Documentation/manual.txt    Fri Jan 12 21:44:53 2018        
(r327893)
@@ -674,4 +674,22 @@ The fdtdump program prints a readable version of a fla
 
 The syntax of the fdtdump command line is:
 
-    fdtdump <DTB-file-name>
+    fdtdump [options] <DTB-file-name>
+
+Where options are:
+    -d,--debug          Dump debug information while decoding the file
+    -s,--scan           Scan for an embedded fdt in given file
+
+3) fdtoverlay -- Flat Device Tree overlay applicator
+
+The fdtoverlay applies an arbitrary number of FDT overlays to a base FDT blob
+to a given output file.
+
+The syntax of the fdtoverlay command line is:
+
+    fdtoverlay -i <base-blob> -o <output-blob> <overlay-blob0> 
[<overlay-blob1> ...]
+
+Where options are:
+    -i, --input         Input base DT blob
+    -o, --output        Output DT blob
+    -v, --verbose       Verbose message output

Modified: vendor/dtc/dist/Makefile
==============================================================================
--- vendor/dtc/dist/Makefile    Fri Jan 12 20:40:27 2018        (r327892)
+++ vendor/dtc/dist/Makefile    Fri Jan 12 21:44:53 2018        (r327893)
@@ -10,7 +10,7 @@
 #
 VERSION = 1
 PATCHLEVEL = 4
-SUBLEVEL = 3
+SUBLEVEL = 6
 EXTRAVERSION =
 LOCAL_VERSION =
 CONFIG_LOCALVERSION =
@@ -18,10 +18,12 @@ CONFIG_LOCALVERSION =
 CPPFLAGS = -I libfdt -I .
 WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
        -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
-CFLAGS = -g -Os -fPIC -Werror $(WARNINGS)
+CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS)
 
 BISON = bison
 LEX = flex
+SWIG = swig
+PKG_CONFIG ?= pkg-config
 
 INSTALL = /usr/bin/install
 DESTDIR =
@@ -31,14 +33,20 @@ LIBDIR = $(PREFIX)/lib
 INCLUDEDIR = $(PREFIX)/include
 
 HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
-           sed -e 's/\(cygwin\).*/cygwin/')
+           sed -e 's/\(cygwin\|msys\).*/\1/')
 
 ifeq ($(HOSTOS),darwin)
-SHAREDLIB_EXT=dylib
-SHAREDLIB_LINK_OPTIONS=-dynamiclib -Wl,-install_name -Wl,
+SHAREDLIB_EXT     = dylib
+SHAREDLIB_CFLAGS  = -fPIC
+SHAREDLIB_LDFLAGS = -fPIC -dynamiclib -Wl,-install_name -Wl,
+else ifeq ($(HOSTOS),$(filter $(HOSTOS),msys cygwin))
+SHAREDLIB_EXT     = so
+SHAREDLIB_CFLAGS  =
+SHAREDLIB_LDFLAGS = -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
 else
-SHAREDLIB_EXT=so
-SHAREDLIB_LINK_OPTIONS=-shared -Wl,--version-script=$(LIBFDT_version) 
-Wl,-soname,
+SHAREDLIB_EXT     = so
+SHAREDLIB_CFLAGS  = -fPIC
+SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,--version-script=$(LIBFDT_version) 
-Wl,-soname,
 endif
 
 #
@@ -112,18 +120,38 @@ BIN += dtc
 BIN += fdtdump
 BIN += fdtget
 BIN += fdtput
+BIN += fdtoverlay
 
 SCRIPTS = dtdiff
 
 all: $(BIN) libfdt
 
+# We need both Python and swig to build pylibfdt.
+.PHONY: maybe_pylibfdt
+maybe_pylibfdt: FORCE
+       if $(PKG_CONFIG) --cflags python2 >/dev/null 2>&1; then \
+               if which swig >/dev/null 2>&1; then \
+                       can_build=yes; \
+               fi; \
+       fi; \
+       if [ "$$can_build" = "yes" ]; then \
+               $(MAKE) pylibfdt; \
+       else \
+               echo "## Skipping pylibfdt (install python dev and swig to 
build)"; \
+       fi
 
+ifeq ($(NO_PYTHON),)
+all: maybe_pylibfdt
+endif
+
+
 ifneq ($(DEPTARGETS),)
 -include $(DTC_OBJS:%.o=%.d)
 -include $(CONVERT_OBJS:%.o=%.d)
 -include $(FDTDUMP_OBJS:%.o=%.d)
 -include $(FDTGET_OBJS:%.o=%.d)
 -include $(FDTPUT_OBJS:%.o=%.d)
+-include $(FDTOVERLAY_OBJS:%.o=%.d)
 endif
 
 
@@ -180,6 +208,10 @@ install-includes:
 
 install: install-bin install-lib install-includes
 
+ifeq ($(NO_PYTHON),)
+install: install_pylibfdt
+endif
+
 $(VERSION_FILE): Makefile FORCE
        $(call filechk,version)
 
@@ -196,13 +228,31 @@ fdtget:   $(FDTGET_OBJS) $(LIBFDT_archive)
 
 fdtput:        $(FDTPUT_OBJS) $(LIBFDT_archive)
 
+fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_archive)
+
 dist:
        git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
                > ../dtc-$(dtc_version).tar
        cat ../dtc-$(dtc_version).tar | \
                gzip -9 > ../dtc-$(dtc_version).tar.gz
 
+
 #
+# Rules for pylibfdt
+#
+PYLIBFDT_srcdir = pylibfdt
+PYLIBFDT_objdir = pylibfdt
+
+include $(PYLIBFDT_srcdir)/Makefile.pylibfdt
+
+.PHONY: pylibfdt
+pylibfdt: $(PYLIBFDT_objdir)/_libfdt.so
+
+pylibfdt_clean:
+       @$(VECHO) CLEAN "(pylibfdt)"
+       rm -f $(addprefix $(PYLIBFDT_objdir)/,$(PYLIBFDT_cleanfiles))
+
+#
 # Release signing and uploading
 # This is for maintainer convenience, don't try this at home.
 #
@@ -234,6 +284,10 @@ TESTS_BIN += convert-dtsv0
 TESTS_BIN += fdtput
 TESTS_BIN += fdtget
 TESTS_BIN += fdtdump
+TESTS_BIN += fdtoverlay
+ifeq ($(NO_PYTHON),)
+TESTS_PYLIBFDT += maybe_pylibfdt
+endif
 
 include tests/Makefile.tests
 
@@ -243,7 +297,7 @@ include tests/Makefile.tests
 STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* 
\
        *.tab.[ch] *.lex.c *.output
 
-clean: libfdt_clean tests_clean
+clean: libfdt_clean pylibfdt_clean tests_clean
        @$(VECHO) CLEAN
        rm -f $(STD_CLEANFILES)
        rm -f $(VERSION_FILE)
@@ -287,7 +341,7 @@ clean: libfdt_clean tests_clean
 
 $(LIBFDT_lib):
        @$(VECHO) LD $@
-       $(CC) $(LDFLAGS) -fPIC $(SHAREDLIB_LINK_OPTIONS)$(LIBFDT_soname) -o 
$(LIBFDT_lib) $^
+       $(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) 
$^
 
 %.lex.c: %.l
        @$(VECHO) LEX $@

Modified: vendor/dtc/dist/Makefile.utils
==============================================================================
--- vendor/dtc/dist/Makefile.utils      Fri Jan 12 20:40:27 2018        
(r327892)
+++ vendor/dtc/dist/Makefile.utils      Fri Jan 12 21:44:53 2018        
(r327893)
@@ -22,3 +22,9 @@ FDTPUT_SRCS = \
        util.c
 
 FDTPUT_OBJS = $(FDTPUT_SRCS:%.c=%.o)
+
+FDTOVERLAY_SRCS = \
+       fdtoverlay.c \
+       util.c
+
+FDTOVERLAY_OBJS = $(FDTOVERLAY_SRCS:%.c=%.o)

Modified: vendor/dtc/dist/README
==============================================================================
--- vendor/dtc/dist/README      Fri Jan 12 20:40:27 2018        (r327892)
+++ vendor/dtc/dist/README      Fri Jan 12 21:44:53 2018        (r327893)
@@ -7,6 +7,83 @@ DTC and LIBFDT are maintained by:
 David Gibson <da...@gibson.dropbear.id.au>
 Jon Loeliger <j...@jdl.com>
 
+
+Python library
+--------------
+
+A Python library is also available. To build this you will need to install
+swig and Python development files. On Debian distributions:
+
+   sudo apt-get install swig python-dev
+
+The library provides an Fdt class which you can use like this:
+
+$ PYTHONPATH=../pylibfdt python
+>>> import libfdt
+>>> fdt = libfdt.Fdt(open('test_tree1.dtb').read())
+>>> node = fdt.path_offset('/subnode@1')
+>>> print node
+124
+>>> prop_offset = fdt.first_property_offset(node)
+>>> prop = fdt.get_property_by_offset(prop_offset)
+>>> print '%s=%r' % (prop.name, prop.value)
+compatible=bytearray(b'subnode1\x00')
+>>> print '%s=%s' % (prop.name, prop.value)
+compatible=subnode1
+>>> node2 = fdt.path_offset('/')
+>>> print fdt.getprop(node2, 'compatible')
+test_tree1
+
+You will find tests in tests/pylibfdt_tests.py showing how to use each
+method. Help is available using the Python help command, e.g.:
+
+    $ cd pylibfdt
+    $ python -c "import libfdt; help(libfdt)"
+
+If you add new features, please check code coverage:
+
+    $ sudo apt-get install python-pip python-pytest
+    $ sudo pip install coverage
+    $ cd tests
+    $ coverage run pylibfdt_tests.py
+    $ coverage html
+    # Open 'htmlcov/index.html' in your browser
+
+
+To install the library via the normal setup.py method, use:
+
+    ./pylibfdt/setup.py [--prefix=/path/to/install_dir]
+
+If --prefix is not provided, the default prefix is used, typically '/usr'
+or '/usr/local'. See Python's distutils documentation for details. You can
+also install via the Makefile if you like, but the above is more common.
+
+To install both libfdt and pylibfdt you can use:
+
+    make install [SETUP_PREFIX=/path/to/install_dir] \
+            [PREFIX=/path/to/install_dir]
+
+To disable building the python library, even if swig and Python are available,
+use:
+
+    make NO_PYTHON=1
+
+
+More work remains to support all of libfdt, including access to numeric
+values.
+
+
+Tests
+-----
+
+Test files are kept in the tests/ directory. Use 'make check' to build and run
+all tests.
+
+If you want to adjust a test file, be aware that tree_tree1.dts is compiled
+and checked against a binary tree from assembler macros in trees.S. So
+if you change that file you must change tree.S also.
+
+
 Mailing list
 ------------
 The following list is for discussion about dtc and libfdt implementation

Modified: vendor/dtc/dist/checks.c
==============================================================================
--- vendor/dtc/dist/checks.c    Fri Jan 12 20:40:27 2018        (r327892)
+++ vendor/dtc/dist/checks.c    Fri Jan 12 21:44:53 2018        (r327893)
@@ -53,31 +53,27 @@ struct check {
        struct check **prereq;
 };
 
-#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...)        \
-       static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \
-       static struct check _nm = { \
-               .name = #_nm, \
-               .fn = (_fn), \
-               .data = (_d), \
-               .warn = (_w), \
-               .error = (_e), \
+#define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...)        \
+       static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \
+       static struct check nm_ = { \
+               .name = #nm_, \
+               .fn = (fn_), \
+               .data = (d_), \
+               .warn = (w_), \
+               .error = (e_), \
                .status = UNCHECKED, \
-               .num_prereqs = ARRAY_SIZE(_nm##_prereqs), \
-               .prereq = _nm##_prereqs, \
+               .num_prereqs = ARRAY_SIZE(nm_##_prereqs), \
+               .prereq = nm_##_prereqs, \
        };
-#define WARNING(_nm, _fn, _d, ...) \
-       CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__)
-#define ERROR(_nm, _fn, _d, ...) \
-       CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__)
-#define CHECK(_nm, _fn, _d, ...) \
-       CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__)
+#define WARNING(nm_, fn_, d_, ...) \
+       CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__)
+#define ERROR(nm_, fn_, d_, ...) \
+       CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__)
+#define CHECK(nm_, fn_, d_, ...) \
+       CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__)
 
-#ifdef __GNUC__
-static inline void check_msg(struct check *c, struct dt_info *dti,
-                            const char *fmt, ...) __attribute__((format 
(printf, 3, 4)));
-#endif
-static inline void check_msg(struct check *c, struct dt_info *dti,
-                            const char *fmt, ...)
+static inline void  PRINTF(3, 4) check_msg(struct check *c, struct dt_info 
*dti,
+                                          const char *fmt, ...)
 {
        va_list ap;
        va_start(ap, fmt);
@@ -183,6 +179,36 @@ static void check_is_string(struct check *c, struct dt
 #define ERROR_IF_NOT_STRING(nm, propname) \
        ERROR(nm, check_is_string, (propname))
 
+static void check_is_string_list(struct check *c, struct dt_info *dti,
+                                struct node *node)
+{
+       int rem, l;
+       struct property *prop;
+       char *propname = c->data;
+       char *str;
+
+       prop = get_property(node, propname);
+       if (!prop)
+               return; /* Not present, assumed ok */
+
+       str = prop->val.val;
+       rem = prop->val.len;
+       while (rem > 0) {
+               l = strnlen(str, rem);
+               if (l == rem) {
+                       FAIL(c, dti, "\"%s\" property in %s is not a string 
list",
+                            propname, node->fullpath);
+                       break;
+               }
+               rem -= l + 1;
+               str += l + 1;
+       }
+}
+#define WARNING_IF_NOT_STRING_LIST(nm, propname) \
+       WARNING(nm, check_is_string_list, (propname))
+#define ERROR_IF_NOT_STRING_LIST(nm, propname) \
+       ERROR(nm, check_is_string_list, (propname))
+
 static void check_is_cell(struct check *c, struct dt_info *dti,
                          struct node *node)
 {
@@ -538,13 +564,13 @@ static void fixup_phandle_references(struct check *c, 
                                        FAIL(c, dti, "Reference to non-existent 
node or "
                                                        "label \"%s\"\n", 
m->ref);
                                else /* mark the entry as unresolved */
-                                       *((cell_t *)(prop->val.val + 
m->offset)) =
+                                       *((fdt32_t *)(prop->val.val + 
m->offset)) =
                                                cpu_to_fdt32(0xffffffff);
                                continue;
                        }
 
                        phandle = get_node_phandle(dt, refnode);
-                       *((cell_t *)(prop->val.val + m->offset)) = 
cpu_to_fdt32(phandle);
+                       *((fdt32_t *)(prop->val.val + m->offset)) = 
cpu_to_fdt32(phandle);
                }
        }
 }
@@ -590,7 +616,48 @@ WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interru
 WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
 WARNING_IF_NOT_STRING(model_is_string, "model");
 WARNING_IF_NOT_STRING(status_is_string, "status");
+WARNING_IF_NOT_STRING(label_is_string, "label");
 
+WARNING_IF_NOT_STRING_LIST(compatible_is_string_list, "compatible");
+
+static void check_names_is_string_list(struct check *c, struct dt_info *dti,
+                                      struct node *node)
+{
+       struct property *prop;
+
+       for_each_property(node, prop) {
+               const char *s = strrchr(prop->name, '-');
+               if (!s || !streq(s, "-names"))
+                       continue;
+
+               c->data = prop->name;
+               check_is_string_list(c, dti, node);
+       }
+}
+WARNING(names_is_string_list, check_names_is_string_list, NULL);
+
+static void check_alias_paths(struct check *c, struct dt_info *dti,
+                                   struct node *node)
+{
+       struct property *prop;
+
+       if (!streq(node->name, "aliases"))
+               return;
+
+       for_each_property(node, prop) {
+               if (!prop->val.val || !get_node_by_path(dti->dt, 
prop->val.val)) {
+                       FAIL(c, dti, "aliases property '%s' is not a valid node 
(%s)",
+                            prop->name, prop->val.val);
+                       continue;
+               }
+               if (strspn(prop->name, LOWERCASE DIGITS "-") != 
strlen(prop->name))
+                       FAIL(c, dti, "aliases property name '%s' is not valid",
+                            prop->name);
+
+       }
+}
+WARNING(alias_paths, check_alias_paths, NULL);
+
 static void fixup_addr_size_cells(struct check *c, struct dt_info *dti,
                                  struct node *node)
 {
@@ -685,6 +752,229 @@ static void check_ranges_format(struct check *c, struc
 }
 WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
 
+static const struct bus_type pci_bus = {
+       .name = "PCI",
+};
+
+static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node 
*node)
+{
+       struct property *prop;
+       cell_t *cells;
+
+       prop = get_property(node, "device_type");
+       if (!prop || !streq(prop->val.val, "pci"))
+               return;
+
+       node->bus = &pci_bus;
+
+       if (!strprefixeq(node->name, node->basenamelen, "pci") &&
+           !strprefixeq(node->name, node->basenamelen, "pcie"))
+               FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"",
+                            node->fullpath);
+
+       prop = get_property(node, "ranges");
+       if (!prop)
+               FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a 
bridge)",
+                            node->fullpath);
+
+       if (node_addr_cells(node) != 3)
+               FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge",
+                            node->fullpath);
+       if (node_size_cells(node) != 2)
+               FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge",
+                            node->fullpath);
+
+       prop = get_property(node, "bus-range");
+       if (!prop) {
+               FAIL(c, dti, "Node %s missing bus-range for PCI bridge",
+                            node->fullpath);
+               return;
+       }
+       if (prop->val.len != (sizeof(cell_t) * 2)) {
+               FAIL(c, dti, "Node %s bus-range must be 2 cells",
+                            node->fullpath);
+               return;
+       }
+       cells = (cell_t *)prop->val.val;
+       if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
+               FAIL(c, dti, "Node %s bus-range 1st cell must be less than or 
equal to 2nd cell",
+                            node->fullpath);
+       if (fdt32_to_cpu(cells[1]) > 0xff)
+               FAIL(c, dti, "Node %s bus-range maximum bus number must be less 
than 256",
+                            node->fullpath);
+}
+WARNING(pci_bridge, check_pci_bridge, NULL,
+       &device_type_is_string, &addr_size_cells);
+
+static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, 
struct node *node)
+{
+       struct property *prop;
+       unsigned int bus_num, min_bus, max_bus;
+       cell_t *cells;
+
+       if (!node->parent || (node->parent->bus != &pci_bus))
+               return;
+
+       prop = get_property(node, "reg");
+       if (!prop)
+               return;
+
+       cells = (cell_t *)prop->val.val;
+       bus_num = (fdt32_to_cpu(cells[0]) & 0x00ff0000) >> 16;
+
+       prop = get_property(node->parent, "bus-range");
+       if (!prop) {
+               min_bus = max_bus = 0;
+       } else {
+               cells = (cell_t *)prop->val.val;
+               min_bus = fdt32_to_cpu(cells[0]);
+               max_bus = fdt32_to_cpu(cells[0]);
+       }
+       if ((bus_num < min_bus) || (bus_num > max_bus))
+               FAIL(c, dti, "Node %s PCI bus number %d out of range, expected 
(%d - %d)",
+                    node->fullpath, bus_num, min_bus, max_bus);
+}
+WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, &reg_format, 
&pci_bridge);
+
+static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct 
node *node)
+{
+       struct property *prop;
+       const char *unitname = get_unitname(node);
+       char unit_addr[5];
+       unsigned int dev, func, reg;
+       cell_t *cells;
+
+       if (!node->parent || (node->parent->bus != &pci_bus))
+               return;
+
+       prop = get_property(node, "reg");
+       if (!prop) {
+               FAIL(c, dti, "Node %s missing PCI reg property", 
node->fullpath);
+               return;
+       }
+
+       cells = (cell_t *)prop->val.val;
+       if (cells[1] || cells[2])
+               FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 
3 must be 0",
+                            node->fullpath);
+
+       reg = fdt32_to_cpu(cells[0]);
+       dev = (reg & 0xf800) >> 11;
+       func = (reg & 0x700) >> 8;
+
+       if (reg & 0xff000000)
+               FAIL(c, dti, "Node %s PCI reg address is not configuration 
space",
+                            node->fullpath);
+       if (reg & 0x000000ff)
+               FAIL(c, dti, "Node %s PCI reg config space address register 
number must be 0",
+                            node->fullpath);
+
+       if (func == 0) {
+               snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
+               if (streq(unitname, unit_addr))
+                       return;
+       }
+
+       snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func);
+       if (streq(unitname, unit_addr))
+               return;
+
+       FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"",
+            node->fullpath, unit_addr);
+}
+WARNING(pci_device_reg, check_pci_device_reg, NULL, &reg_format, &pci_bridge);
+
+static const struct bus_type simple_bus = {
+       .name = "simple-bus",
+};
+
+static bool node_is_compatible(struct node *node, const char *compat)
+{
+       struct property *prop;
+       const char *str, *end;
+
+       prop = get_property(node, "compatible");
+       if (!prop)
+               return false;
+
+       for (str = prop->val.val, end = str + prop->val.len; str < end;
+            str += strnlen(str, end - str) + 1) {
+               if (strprefixeq(str, end - str, compat))
+                       return true;
+       }
+       return false;
+}
+
+static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, 
struct node *node)
+{
+       if (node_is_compatible(node, "simple-bus"))
+               node->bus = &simple_bus;
+}
+WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells);
+
+static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct 
node *node)
+{
+       struct property *prop;
+       const char *unitname = get_unitname(node);
+       char unit_addr[17];
+       unsigned int size;
+       uint64_t reg = 0;
+       cell_t *cells = NULL;
+
+       if (!node->parent || (node->parent->bus != &simple_bus))
+               return;
+
+       prop = get_property(node, "reg");
+       if (prop)
+               cells = (cell_t *)prop->val.val;
+       else {
+               prop = get_property(node, "ranges");
+               if (prop && prop->val.len)
+                       /* skip of child address */
+                       cells = ((cell_t *)prop->val.val) + 
node_addr_cells(node);
+       }
+
+       if (!cells) {
+               if (node->parent->parent && !(node->bus == &simple_bus))
+                       FAIL(c, dti, "Node %s missing or empty reg/ranges 
property", node->fullpath);
+               return;
+       }
+
+       size = node_addr_cells(node->parent);
+       while (size--)
+               reg = (reg << 32) | fdt32_to_cpu(*(cells++));
+
+       snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg);
+       if (!streq(unitname, unit_addr))
+               FAIL(c, dti, "Node %s simple-bus unit address format error, 
expected \"%s\"",
+                    node->fullpath, unit_addr);
+}
+WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, 
&simple_bus_bridge);
+
+static void check_unit_address_format(struct check *c, struct dt_info *dti,
+                                     struct node *node)
+{
+       const char *unitname = get_unitname(node);
+
+       if (node->parent && node->parent->bus)
+               return;
+
+       if (!unitname[0])
+               return;
+
+       if (!strncmp(unitname, "0x", 2)) {
+               FAIL(c, dti, "Node %s unit name should not have leading \"0x\"",
+                   node->fullpath);
+               /* skip over 0x for next test */
+               unitname += 2;
+       }
+       if (unitname[0] == '0' && isxdigit(unitname[1]))
+               FAIL(c, dti, "Node %s unit name should not have leading 0s",
+                   node->fullpath);
+}
+WARNING(unit_address_format, check_unit_address_format, NULL,
+       &node_name_format, &pci_bridge, &simple_bus_bridge);
+
 /*
  * Style checks
  */
@@ -713,6 +1003,31 @@ static void check_avoid_default_addr_size(struct check
 WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
        &addr_size_cells);
 
+static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info 
*dti,
+                                             struct node *node)
+{
+       struct property *prop;
+       struct node *child;
+       bool has_reg = false;
+
+       if (!node->parent || node->addr_cells < 0 || node->size_cells < 0)
+               return;
+
+       if (get_property(node, "ranges") || !node->children)
+               return;
+
+       for_each_child(node, child) {
+               prop = get_property(child, "reg");
+               if (prop)
+                       has_reg = true;
+       }
+
+       if (!has_reg)
+               FAIL(c, dti, "unnecessary #address-cells/#size-cells without 
\"ranges\" or child \"reg\" property in %s",
+                    node->fullpath);
+}
+WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, 
&avoid_default_addr_size);
+
 static void check_obsolete_chosen_interrupt_controller(struct check *c,
                                                       struct dt_info *dti,
                                                       struct node *node)
@@ -737,6 +1052,324 @@ static void check_obsolete_chosen_interrupt_controller
 WARNING(obsolete_chosen_interrupt_controller,
        check_obsolete_chosen_interrupt_controller, NULL);
 
+static void check_chosen_node_is_root(struct check *c, struct dt_info *dti,
+                                     struct node *node)
+{
+       if (!streq(node->name, "chosen"))
+               return;
+
+       if (node->parent != dti->dt)
+               FAIL(c, dti, "chosen node '%s' must be at root node",
+                    node->fullpath);
+}
+WARNING(chosen_node_is_root, check_chosen_node_is_root, NULL);
+
+static void check_chosen_node_bootargs(struct check *c, struct dt_info *dti,
+                                      struct node *node)
+{
+       struct property *prop;
+
+       if (!streq(node->name, "chosen"))
+               return;
+
+       prop = get_property(node, "bootargs");
+       if (!prop)
+               return;
+
+       c->data = prop->name;
+       check_is_string(c, dti, node);
+}
+WARNING(chosen_node_bootargs, check_chosen_node_bootargs, NULL);
+
+static void check_chosen_node_stdout_path(struct check *c, struct dt_info *dti,
+                                         struct node *node)
+{
+       struct property *prop;
+
+       if (!streq(node->name, "chosen"))
+               return;
+
+       prop = get_property(node, "stdout-path");
+       if (!prop) {
+               prop = get_property(node, "linux,stdout-path");
+               if (!prop)
+                       return;
+               FAIL(c, dti, "Use 'stdout-path' instead of 
'linux,stdout-path'");
+       }
+
+       c->data = prop->name;
+       check_is_string(c, dti, node);
+}
+WARNING(chosen_node_stdout_path, check_chosen_node_stdout_path, NULL);
+
+struct provider {
+       const char *prop_name;
+       const char *cell_name;
+       bool optional;
+};
+
+static void check_property_phandle_args(struct check *c,
+                                         struct dt_info *dti,
+                                         struct node *node,
+                                         struct property *prop,
+                                         const struct provider *provider)
+{
+       struct node *root = dti->dt;
+       int cell, cellsize = 0;
+
+       if (prop->val.len % sizeof(cell_t)) {
+               FAIL(c, dti, "property '%s' size (%d) is invalid, expected 
multiple of %zu in node %s",
+                    prop->name, prop->val.len, sizeof(cell_t), node->fullpath);
+               return;
+       }
+
+       for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize 
+ 1) {
+               struct node *provider_node;
+               struct property *cellprop;
+               int phandle;
+
+               phandle = propval_cell_n(prop, cell);
+               /*
+                * Some bindings use a cell value 0 or -1 to skip over optional
+                * entries when each index position has a specific definition.
+                */
+               if (phandle == 0 || phandle == -1) {
+                       /* Give up if this is an overlay with external 
references */
+                       if (dti->dtsflags & DTSF_PLUGIN)
+                               break;
+
+                       cellsize = 0;
+                       continue;
+               }
+
+               /* If we have markers, verify the current cell is a phandle */
+               if (prop->val.markers) {
+                       struct marker *m = prop->val.markers;
+                       for_each_marker_of_type(m, REF_PHANDLE) {
+                               if (m->offset == (cell * sizeof(cell_t)))
+                                       break;
+                       }
+                       if (!m)
+                               FAIL(c, dti, "Property '%s', cell %d is not a 
phandle reference in %s",
+                                    prop->name, cell, node->fullpath);
+               }
+
+               provider_node = get_node_by_phandle(root, phandle);
+               if (!provider_node) {
+                       FAIL(c, dti, "Could not get phandle node for %s:%s(cell 
%d)",
+                            node->fullpath, prop->name, cell);
+                       break;
+               }
+
+               cellprop = get_property(provider_node, provider->cell_name);
+               if (cellprop) {
+                       cellsize = propval_cell(cellprop);
+               } else if (provider->optional) {
+                       cellsize = 0;
+               } else {
+                       FAIL(c, dti, "Missing property '%s' in node %s or bad 
phandle (referred from %s:%s[%d])",
+                            provider->cell_name,
+                            provider_node->fullpath,
+                            node->fullpath, prop->name, cell);
+                       break;
+               }
+
+               if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
+                       FAIL(c, dti, "%s property size (%d) too small for cell 
size %d in %s",
+                            prop->name, prop->val.len, cellsize, 
node->fullpath);
+               }
+       }
+}
+
+static void check_provider_cells_property(struct check *c,
+                                         struct dt_info *dti,
+                                         struct node *node)
+{
+       struct provider *provider = c->data;
+       struct property *prop;
+
+       prop = get_property(node, provider->prop_name);
+       if (!prop)
+               return;
+
+       check_property_phandle_args(c, dti, node, prop, provider);
+}
+#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
+       static struct provider nm##_provider = { (propname), (cells_name), 
__VA_ARGS__ }; \
+       WARNING(nm##_property, check_provider_cells_property, &nm##_provider, 
&phandle_references);
+
+WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", 
"#cooling-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", 
"#interrupt-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", 
"#io-channel-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true);
+WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", 
"#mux-control-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", 
"#power-domain-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", 
"#thermal-sensor-cells");
+
+static bool prop_is_gpio(struct property *prop)
+{
+       char *str;
+
+       /*
+        * *-gpios and *-gpio can appear in property names,
+        * so skip over any false matches (only one known ATM)
+        */
+       if (strstr(prop->name, "nr-gpio"))
+               return false;
+
+       str = strrchr(prop->name, '-');
+       if (str)
+               str++;
+       else
+               str = prop->name;
+       if (!(streq(str, "gpios") || streq(str, "gpio")))
+               return false;
+
+       return true;
+}
+
+static void check_gpios_property(struct check *c,
+                                         struct dt_info *dti,
+                                         struct node *node)
+{
+       struct property *prop;
+
+       /* Skip GPIO hog nodes which have 'gpios' property */
+       if (get_property(node, "gpio-hog"))
+               return;
+
+       for_each_property(node, prop) {
+               struct provider provider;
+
+               if (!prop_is_gpio(prop))
+                       continue;
+
+               provider.prop_name = prop->name;
+               provider.cell_name = "#gpio-cells";
+               provider.optional = false;
+               check_property_phandle_args(c, dti, node, prop, &provider);
+       }
+
+}
+WARNING(gpios_property, check_gpios_property, NULL, &phandle_references);
+
+static void check_deprecated_gpio_property(struct check *c,
+                                          struct dt_info *dti,
+                                          struct node *node)
+{
+       struct property *prop;
+
+       for_each_property(node, prop) {
+               char *str;
+
+               if (!prop_is_gpio(prop))
+                       continue;
+
+               str = strstr(prop->name, "gpio");
+               if (!streq(str, "gpio"))
+                       continue;
+
+               FAIL(c, dti, "'[*-]gpio' is deprecated, use '[*-]gpios' instead 
for %s:%s",
+                    node->fullpath, prop->name);
+       }
+
+}
+CHECK(deprecated_gpio_property, check_deprecated_gpio_property, NULL);
+
+static bool node_is_interrupt_provider(struct node *node)
+{
+       struct property *prop;
+
+       prop = get_property(node, "interrupt-controller");
+       if (prop)
+               return true;
+
+       prop = get_property(node, "interrupt-map");
+       if (prop)
+               return true;
+
+       return false;
+}
+static void check_interrupts_property(struct check *c,
+                                     struct dt_info *dti,
+                                     struct node *node)
+{
+       struct node *root = dti->dt;
+       struct node *irq_node = NULL, *parent = node;
+       struct property *irq_prop, *prop = NULL;
+       int irq_cells, phandle;
+
+       irq_prop = get_property(node, "interrupts");
+       if (!irq_prop)
+               return;
+
+       if (irq_prop->val.len % sizeof(cell_t))
+               FAIL(c, dti, "property '%s' size (%d) is invalid, expected 
multiple of %zu in node %s",
+                    irq_prop->name, irq_prop->val.len, sizeof(cell_t),
+                    node->fullpath);
+
+       while (parent && !prop) {
+               if (parent != node && node_is_interrupt_provider(parent)) {
+                       irq_node = parent;
+                       break;
+               }
+
+               prop = get_property(parent, "interrupt-parent");
+               if (prop) {
+                       phandle = propval_cell(prop);
+                       /* Give up if this is an overlay with external 
references */
+                       if ((phandle == 0 || phandle == -1) &&
+                           (dti->dtsflags & DTSF_PLUGIN))
+                                       return;
+
+                       irq_node = get_node_by_phandle(root, phandle);
+                       if (!irq_node) {
+                               FAIL(c, dti, "Bad interrupt-parent phandle for 
%s",
+                                    node->fullpath);
+                               return;
+                       }
+                       if (!node_is_interrupt_provider(irq_node))
+                               FAIL(c, dti,
+                                    "Missing interrupt-controller or 
interrupt-map property in %s",
+                                    irq_node->fullpath);
+
+                       break;
+               }
+
+               parent = parent->parent;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to