Merge tag 'devicetree-for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux

Pull DeviceTree updates from Rob Herring:

 - new tool 'dtx_diff' to diff DT files

 - sync kernel's dtc/libfdt to current dtc repo master

 - fix for reserved memory regions located in highmem

 - document standard unit suffixes for DT properties

 - various DT binding doc updates

* tag 'devicetree-for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux:
  of: Add vendor prefix for eGalax_eMPIA Technology Inc
  Input: ads7846: Add description how to use internal reference (ADS7846)
  ARM: realview: add EB syscon variants to bindings
  devicetree: bindings: ARM: Use "uV" for micro-volt
  serial: fsl-imx-uart: Fix typo in fsl,dte-mode description
  of: add 'const' for of_property_*_string*() parameter '*np'
  of/unittest: fix infinite loop in of_unittest_destroy_tracked_overlays()
  of: alloc anywhere from memblock if range not specified
  kbuild: Allow using host dtc instead of kernel's copy
  of: resolver: Add missing of_node_get and of_node_put
  of: Add United Radiant Technology Corporation vendor prefix
  dt/bindings: add documentation on standard property unit suffixes
  scripts/dtc: Update to upstream commit b06e55c88b9b
  ARM: boot: Add an implementation of strnlen for libfdt
  scripts/dtc: dtx_diff - add info to error message
  dtc: create tool to diff device trees
diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards
index 1a70997..100db73 100644
--- a/Documentation/devicetree/bindings/arm/arm-boards
+++ b/Documentation/devicetree/bindings/arm/arm-boards
@@ -123,7 +123,9 @@
 
 - syscon: some subnode of the RealView SoC node must be a
   system controller node pointing to the control registers,
-  with the compatible string set to one of these tuples:
+  with the compatible string set to one of these:
+   "arm,realview-eb11mp-revb-syscon", "arm,realview-eb-syscon", "syscon"
+   "arm,realview-eb11mp-revc-syscon", "arm,realview-eb-syscon", "syscon"
    "arm,realview-eb-syscon", "syscon"
    "arm,realview-pb1176-syscon", "syscon"
    "arm,realview-pb11mp-syscon", "syscon"
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index ae9be07..afcf50f 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -250,7 +250,7 @@
 		Usage: optional
 		Value type: <prop-encoded-array>
 		Definition: A u32 value that represents the running time dynamic
-			    power coefficient in units of mW/MHz/uVolt^2. The
+			    power coefficient in units of mW/MHz/uV^2. The
 			    coefficient can either be calculated from power
 			    measurements or derived by analysis.
 
diff --git a/Documentation/devicetree/bindings/input/ads7846.txt b/Documentation/devicetree/bindings/input/ads7846.txt
index 33a1638..c6cfe2e 100644
--- a/Documentation/devicetree/bindings/input/ads7846.txt
+++ b/Documentation/devicetree/bindings/input/ads7846.txt
@@ -29,6 +29,8 @@
 	ti,vref-delay-usecs		vref supply delay in usecs, 0 for
 					external vref (u16).
 	ti,vref-mv			The VREF voltage, in millivolts (u16).
+					Set to 0 to use internal refernce
+					(ADS7846).
 	ti,keep-vref-on			set to keep vref on for differential
 					measurements as well
 	ti,swap-xy			swap x and y axis
diff --git a/Documentation/devicetree/bindings/property-units.txt b/Documentation/devicetree/bindings/property-units.txt
new file mode 100644
index 0000000..12278d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/property-units.txt
@@ -0,0 +1,39 @@
+Standard Unit Suffixes for Property names
+
+Properties which have a unit of measure are recommended to have a unit
+suffix appended to the property name. The list below contains the
+recommended suffixes. Other variations exist in bindings, but should not
+be used in new bindings or added here. The inconsistency in the unit
+prefixes is due to selecting the most commonly used variants.
+
+It is also recommended to use the units listed here and not add additional
+unit prefixes.
+
+Time/Frequency
+----------------------------------------
+-mhz		: megahertz
+-hz		: Hertz (preferred)
+-sec		: seconds
+-ms		: milliseconds
+-us		: microseconds
+-ns		: nanoseconds
+
+Distance
+----------------------------------------
+-mm		: millimeters
+
+Electricity
+----------------------------------------
+-microamp	: micro amps
+-ohms		: Ohms
+-micro-ohms	: micro Ohms
+-microvolt	: micro volts
+
+Temperature
+----------------------------------------
+-celsius	: Degrees Celsius
+-millicelsius	: Degreee milli-Celsius
+
+Pressure
+----------------------------------------
+-kpascal	: kiloPascal
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 156731c..787d422 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -72,6 +72,7 @@
 ea	Embedded Artists AB
 ebv	EBV Elektronik
 edt	Emerging Display Technologies
+eeti	eGalax_eMPIA Technology Inc
 elan	Elan Microelectronic Corp.
 emmicro	EM Microelectronic
 energymicro	Silicon Laboratories (formerly Energy Micro AS)
@@ -247,6 +248,7 @@
 tronfy	Tronfy
 truly	Truly Semiconductors Limited
 upisemi	uPI Semiconductor Corp.
+urt	United Radiant Technology Corporation
 usi	Universal Scientific Industrial Co., Ltd.
 v3	V3 Semiconductor
 variscite	Variscite Ltd.
diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c
index 36e53ef..6894674 100644
--- a/arch/arm/boot/compressed/string.c
+++ b/arch/arm/boot/compressed/string.c
@@ -65,6 +65,15 @@
 	return sc - s;
 }
 
+size_t strnlen(const char *s, size_t count)
+{
+	const char *sc;
+
+	for (sc = s; count-- && *sc != '\0'; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
 int memcmp(const void *cs, const void *ct, size_t count)
 {
 	const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 017dd94..b299de2 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1341,10 +1341,10 @@
  *
  * The out_string pointer is modified only if a valid string can be decoded.
  */
-int of_property_read_string(struct device_node *np, const char *propname,
+int of_property_read_string(const struct device_node *np, const char *propname,
 				const char **out_string)
 {
-	struct property *prop = of_find_property(np, propname, NULL);
+	const struct property *prop = of_find_property(np, propname, NULL);
 	if (!prop)
 		return -EINVAL;
 	if (!prop->value)
@@ -1365,10 +1365,10 @@
  * This function searches a string list property and returns the index
  * of a specific string value.
  */
-int of_property_match_string(struct device_node *np, const char *propname,
+int of_property_match_string(const struct device_node *np, const char *propname,
 			     const char *string)
 {
-	struct property *prop = of_find_property(np, propname, NULL);
+	const struct property *prop = of_find_property(np, propname, NULL);
 	size_t l;
 	int i;
 	const char *p, *end;
@@ -1404,10 +1404,11 @@
  * Don't call this function directly. It is a utility helper for the
  * of_property_read_string*() family of functions.
  */
-int of_property_read_string_helper(struct device_node *np, const char *propname,
-				   const char **out_strs, size_t sz, int skip)
+int of_property_read_string_helper(const struct device_node *np,
+				   const char *propname, const char **out_strs,
+				   size_t sz, int skip)
 {
-	struct property *prop = of_find_property(np, propname, NULL);
+	const struct property *prop = of_find_property(np, propname, NULL);
 	int l = 0, i = 0;
 	const char *p, *end;
 
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 1a3556a..ed01c01 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -32,11 +32,13 @@
 	phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
 	phys_addr_t *res_base)
 {
+	phys_addr_t base;
 	/*
 	 * We use __memblock_alloc_base() because memblock_alloc_base()
 	 * panic()s on allocation failure.
 	 */
-	phys_addr_t base = __memblock_alloc_base(size, align, end);
+	end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end;
+	base = __memblock_alloc_base(size, align, end);
 	if (!base)
 		return -ENOMEM;
 
diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
index 640eb4c..d313d49 100644
--- a/drivers/of/resolver.c
+++ b/drivers/of/resolver.c
@@ -36,12 +36,14 @@
 
 	/* check */
 	if (of_node_cmp(node->full_name, full_name) == 0)
-		return node;
+		return of_node_get(node);
 
 	for_each_child_of_node(node, child) {
 		found = __of_find_node_by_full_name(child, full_name);
-		if (found != NULL)
+		if (found != NULL) {
+			of_node_put(child);
 			return found;
+		}
 	}
 
 	return NULL;
@@ -174,6 +176,7 @@
 			if (of_prop_cmp(sprop->name, propstr) == 0)
 				break;
 		}
+		of_node_put(refnode);
 
 		if (!sprop) {
 			pr_err("%s: Could not find property '%s'\n",
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 979b6e4..e986e6e 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -1165,6 +1165,11 @@
 				continue;
 
 			ret = of_overlay_destroy(id + overlay_first_id);
+			if (ret == -ENODEV) {
+				pr_warn("%s: no overlay to destroy for #%d\n",
+					__func__, id + overlay_first_id);
+				continue;
+			}
 			if (ret != 0) {
 				defers++;
 				pr_warn("%s: overlay destroy failed for #%d\n",
diff --git a/include/linux/of.h b/include/linux/of.h
index dc6e396..7fcb681 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -296,13 +296,13 @@
 				      u64 *out_values,
 				      size_t sz);
 
-extern int of_property_read_string(struct device_node *np,
+extern int of_property_read_string(const struct device_node *np,
 				   const char *propname,
 				   const char **out_string);
-extern int of_property_match_string(struct device_node *np,
+extern int of_property_match_string(const struct device_node *np,
 				    const char *propname,
 				    const char *string);
-extern int of_property_read_string_helper(struct device_node *np,
+extern int of_property_read_string_helper(const struct device_node *np,
 					      const char *propname,
 					      const char **out_strs, size_t sz, int index);
 extern int of_device_is_compatible(const struct device_node *device,
@@ -538,14 +538,14 @@
 	return -ENOSYS;
 }
 
-static inline int of_property_read_string(struct device_node *np,
+static inline int of_property_read_string(const struct device_node *np,
 					  const char *propname,
 					  const char **out_string)
 {
 	return -ENOSYS;
 }
 
-static inline int of_property_read_string_helper(struct device_node *np,
+static inline int of_property_read_string_helper(const struct device_node *np,
 						 const char *propname,
 						 const char **out_strs, size_t sz, int index)
 {
@@ -571,7 +571,7 @@
 	return -ENOSYS;
 }
 
-static inline int of_property_match_string(struct device_node *np,
+static inline int of_property_match_string(const struct device_node *np,
 					   const char *propname,
 					   const char *string)
 {
@@ -773,7 +773,7 @@
  *
  * If @out_strs is NULL, the number of strings in the property is returned.
  */
-static inline int of_property_read_string_array(struct device_node *np,
+static inline int of_property_read_string_array(const struct device_node *np,
 						const char *propname, const char **out_strs,
 						size_t sz)
 {
@@ -792,7 +792,7 @@
  * does not have a value, and -EILSEQ if the string is not null-terminated
  * within the length of the property data.
  */
-static inline int of_property_count_strings(struct device_node *np,
+static inline int of_property_count_strings(const struct device_node *np,
 					    const char *propname)
 {
 	return of_property_read_string_helper(np, propname, NULL, 0, 0);
@@ -816,7 +816,7 @@
  *
  * The out_string pointer is modified only if a valid string can be decoded.
  */
-static inline int of_property_read_string_index(struct device_node *np,
+static inline int of_property_read_string_index(const struct device_node *np,
 						const char *propname,
 						int index, const char **output)
 {
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 2edbcad..ad50d58 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -269,6 +269,7 @@
 
 # DTC
 # ---------------------------------------------------------------------------
+DTC ?= $(objtree)/scripts/dtc/dtc
 
 # Generate an assembly file to wrap the output of the device tree compiler
 quiet_cmd_dt_S_dtb= DTB     $@
@@ -291,7 +292,7 @@
 quiet_cmd_dtc = DTC     $@
 cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
 	$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
-	$(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
+	$(DTC) -O dtb -o $@ -b 0 \
 		-i $(dir $<) $(DTC_FLAGS) \
 		-d $(depfile).dtc.tmp $(dtc-tmp) ; \
 	cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index e81a8c74..0c03ac9 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -560,7 +560,7 @@
 	size_cells = node_size_cells(node->parent);
 	entrylen = (addr_cells + size_cells) * sizeof(cell_t);
 
-	if ((prop->val.len % entrylen) != 0)
+	if (!entrylen || (prop->val.len % entrylen) != 0)
 		FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
 		     "(#address-cells == %d, #size-cells == %d)",
 		     node->fullpath, prop->val.len, addr_cells, size_cells);
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index 0ee1caf03..790fbf6 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -73,24 +73,32 @@
 		}
 
 <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
-			char *line, *tmp, *fn;
+			char *line, *fnstart, *fnend;
+			struct data fn;
 			/* skip text before line # */
 			line = yytext;
 			while (!isdigit((unsigned char)*line))
 				line++;
-			/* skip digits in line # */
-			tmp = line;
-			while (!isspace((unsigned char)*tmp))
-				tmp++;
-			/* "NULL"-terminate line # */
-			*tmp = '\0';
-			/* start of filename */
-			fn = strchr(tmp + 1, '"') + 1;
-			/* strip trailing " from filename */
-			tmp = strchr(fn, '"');
-			*tmp = 0;
+
+			/* regexp ensures that first and list "
+			 * in the whole yytext are those at
+			 * beginning and end of the filename string */
+			fnstart = memchr(yytext, '"', yyleng);
+			for (fnend = yytext + yyleng - 1;
+			     *fnend != '"'; fnend--)
+				;
+			assert(fnstart && fnend && (fnend > fnstart));
+
+			fn = data_copy_escape_string(fnstart + 1,
+						     fnend - fnstart - 1);
+
+			/* Don't allow nuls in filenames */
+			if (memchr(fn.val, '\0', fn.len - 1))
+				lexical_error("nul in line number directive");
+
 			/* -1 since #line is the number of the next line */
-			srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+			srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
+			data_free(fn);
 		}
 
 <*><<EOF>>		{
@@ -153,7 +161,10 @@
 			errno = 0;
 			yylval.integer = strtoull(yytext, &e, 0);
 
-			assert(!(*e) || !e[strspn(e, "UL")]);
+			if (*e && e[strspn(e, "UL")]) {
+				lexical_error("Bad integer literal '%s'",
+					      yytext);
+			}
 
 			if (errno == ERANGE)
 				lexical_error("Integer literal '%s' out of range",
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
index 11cd78e..ba525c2 100644
--- a/scripts/dtc/dtc-lexer.lex.c_shipped
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
@@ -951,31 +951,39 @@
 YY_RULE_SETUP
 #line 75 "dtc-lexer.l"
 {
-			char *line, *tmp, *fn;
+			char *line, *fnstart, *fnend;
+			struct data fn;
 			/* skip text before line # */
 			line = yytext;
 			while (!isdigit((unsigned char)*line))
 				line++;
-			/* skip digits in line # */
-			tmp = line;
-			while (!isspace((unsigned char)*tmp))
-				tmp++;
-			/* "NULL"-terminate line # */
-			*tmp = '\0';
-			/* start of filename */
-			fn = strchr(tmp + 1, '"') + 1;
-			/* strip trailing " from filename */
-			tmp = strchr(fn, '"');
-			*tmp = 0;
+
+			/* regexp ensures that first and list "
+			 * in the whole yytext are those at
+			 * beginning and end of the filename string */
+			fnstart = memchr(yytext, '"', yyleng);
+			for (fnend = yytext + yyleng - 1;
+			     *fnend != '"'; fnend--)
+				;
+			assert(fnstart && fnend && (fnend > fnstart));
+
+			fn = data_copy_escape_string(fnstart + 1,
+						     fnend - fnstart - 1);
+
+			/* Don't allow nuls in filenames */
+			if (memchr(fn.val, '\0', fn.len - 1))
+				lexical_error("nul in line number directive");
+
 			/* -1 since #line is the number of the next line */
-			srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+			srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
+			data_free(fn);
 		}
 	YY_BREAK
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(BYTESTRING):
 case YY_STATE_EOF(PROPNODENAME):
 case YY_STATE_EOF(V1):
-#line 96 "dtc-lexer.l"
+#line 104 "dtc-lexer.l"
 {
 			if (!pop_input_file()) {
 				yyterminate();
@@ -985,7 +993,7 @@
 case 3:
 /* rule 3 can match eol */
 YY_RULE_SETUP
-#line 102 "dtc-lexer.l"
+#line 110 "dtc-lexer.l"
 {
 			DPRINT("String: %s\n", yytext);
 			yylval.data = data_copy_escape_string(yytext+1,
@@ -995,7 +1003,7 @@
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 109 "dtc-lexer.l"
+#line 117 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /dts-v1/\n");
 			dts_version = 1;
@@ -1005,7 +1013,7 @@
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 116 "dtc-lexer.l"
+#line 124 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /memreserve/\n");
 			BEGIN_DEFAULT();
@@ -1014,7 +1022,7 @@
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 122 "dtc-lexer.l"
+#line 130 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /bits/\n");
 			BEGIN_DEFAULT();
@@ -1023,7 +1031,7 @@
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 128 "dtc-lexer.l"
+#line 136 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /delete-property/\n");
 			DPRINT("<PROPNODENAME>\n");
@@ -1033,7 +1041,7 @@
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 135 "dtc-lexer.l"
+#line 143 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /delete-node/\n");
 			DPRINT("<PROPNODENAME>\n");
@@ -1043,7 +1051,7 @@
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 142 "dtc-lexer.l"
+#line 150 "dtc-lexer.l"
 {
 			DPRINT("Label: %s\n", yytext);
 			yylval.labelref = xstrdup(yytext);
@@ -1053,7 +1061,7 @@
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 149 "dtc-lexer.l"
+#line 157 "dtc-lexer.l"
 {
 			char *e;
 			DPRINT("Integer Literal: '%s'\n", yytext);
@@ -1061,7 +1069,10 @@
 			errno = 0;
 			yylval.integer = strtoull(yytext, &e, 0);
 
-			assert(!(*e) || !e[strspn(e, "UL")]);
+			if (*e && e[strspn(e, "UL")]) {
+				lexical_error("Bad integer literal '%s'",
+					      yytext);
+			}
 
 			if (errno == ERANGE)
 				lexical_error("Integer literal '%s' out of range",
@@ -1076,7 +1087,7 @@
 case 11:
 /* rule 11 can match eol */
 YY_RULE_SETUP
-#line 168 "dtc-lexer.l"
+#line 179 "dtc-lexer.l"
 {
 			struct data d;
 			DPRINT("Character literal: %s\n", yytext);
@@ -1100,7 +1111,7 @@
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 189 "dtc-lexer.l"
+#line 200 "dtc-lexer.l"
 {	/* label reference */
 			DPRINT("Ref: %s\n", yytext+1);
 			yylval.labelref = xstrdup(yytext+1);
@@ -1109,7 +1120,7 @@
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 195 "dtc-lexer.l"
+#line 206 "dtc-lexer.l"
 {	/* new-style path reference */
 			yytext[yyleng-1] = '\0';
 			DPRINT("Ref: %s\n", yytext+2);
@@ -1119,7 +1130,7 @@
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 202 "dtc-lexer.l"
+#line 213 "dtc-lexer.l"
 {
 			yylval.byte = strtol(yytext, NULL, 16);
 			DPRINT("Byte: %02x\n", (int)yylval.byte);
@@ -1128,7 +1139,7 @@
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 208 "dtc-lexer.l"
+#line 219 "dtc-lexer.l"
 {
 			DPRINT("/BYTESTRING\n");
 			BEGIN_DEFAULT();
@@ -1137,7 +1148,7 @@
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 214 "dtc-lexer.l"
+#line 225 "dtc-lexer.l"
 {
 			DPRINT("PropNodeName: %s\n", yytext);
 			yylval.propnodename = xstrdup((yytext[0] == '\\') ?
@@ -1148,7 +1159,7 @@
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 222 "dtc-lexer.l"
+#line 233 "dtc-lexer.l"
 {
 			DPRINT("Binary Include\n");
 			return DT_INCBIN;
@@ -1157,64 +1168,64 @@
 case 18:
 /* rule 18 can match eol */
 YY_RULE_SETUP
-#line 227 "dtc-lexer.l"
+#line 238 "dtc-lexer.l"
 /* eat whitespace */
 	YY_BREAK
 case 19:
 /* rule 19 can match eol */
 YY_RULE_SETUP
-#line 228 "dtc-lexer.l"
+#line 239 "dtc-lexer.l"
 /* eat C-style comments */
 	YY_BREAK
 case 20:
 /* rule 20 can match eol */
 YY_RULE_SETUP
-#line 229 "dtc-lexer.l"
+#line 240 "dtc-lexer.l"
 /* eat C++-style comments */
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 231 "dtc-lexer.l"
+#line 242 "dtc-lexer.l"
 { return DT_LSHIFT; };
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 232 "dtc-lexer.l"
+#line 243 "dtc-lexer.l"
 { return DT_RSHIFT; };
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 233 "dtc-lexer.l"
+#line 244 "dtc-lexer.l"
 { return DT_LE; };
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 234 "dtc-lexer.l"
+#line 245 "dtc-lexer.l"
 { return DT_GE; };
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 235 "dtc-lexer.l"
+#line 246 "dtc-lexer.l"
 { return DT_EQ; };
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 236 "dtc-lexer.l"
+#line 247 "dtc-lexer.l"
 { return DT_NE; };
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 237 "dtc-lexer.l"
+#line 248 "dtc-lexer.l"
 { return DT_AND; };
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 238 "dtc-lexer.l"
+#line 249 "dtc-lexer.l"
 { return DT_OR; };
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 240 "dtc-lexer.l"
+#line 251 "dtc-lexer.l"
 {
 			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
 				(unsigned)yytext[0]);
@@ -1232,10 +1243,10 @@
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 255 "dtc-lexer.l"
+#line 266 "dtc-lexer.l"
 ECHO;
 	YY_BREAK
-#line 1239 "dtc-lexer.lex.c"
+#line 1250 "dtc-lexer.lex.c"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -2195,7 +2206,7 @@
 
 #define YYTABLES_NAME "yytables"
 
-#line 254 "dtc-lexer.l"
+#line 265 "dtc-lexer.l"
 
 
 
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
index 116458c..31cec50 100644
--- a/scripts/dtc/dtc-parser.tab.c_shipped
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
@@ -499,9 +499,9 @@
      298,   303,   322,   336,   343,   344,   345,   352,   356,   357,
      361,   362,   366,   367,   371,   372,   376,   377,   381,   382,
      386,   387,   388,   392,   393,   394,   395,   396,   400,   401,
-     402,   406,   407,   408,   412,   413,   414,   415,   419,   420,
-     421,   422,   427,   430,   434,   442,   445,   449,   457,   461,
-     465
+     402,   406,   407,   408,   412,   413,   422,   431,   435,   436,
+     437,   438,   443,   446,   450,   458,   461,   465,   473,   477,
+     481
 };
 #endif
 
@@ -1909,111 +1909,125 @@
     break;
 
   case 65:
-#line 413 "dtc-parser.y" /* yacc.c:1646  */
-    { (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); }
-#line 1915 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 414 "dtc-parser.y" /* yacc.c:1646  */
+    {
+			if ((yyvsp[0].integer) != 0) {
+				(yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer);
+			} else {
+				ERROR(&(yyloc), "Division by zero");
+				(yyval.integer) = 0;
+			}
+		}
+#line 1922 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 66:
-#line 414 "dtc-parser.y" /* yacc.c:1646  */
-    { (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); }
-#line 1921 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 423 "dtc-parser.y" /* yacc.c:1646  */
+    {
+			if ((yyvsp[0].integer) != 0) {
+				(yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer);
+			} else {
+				ERROR(&(yyloc), "Division by zero");
+				(yyval.integer) = 0;
+			}
+		}
+#line 1935 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 69:
-#line 420 "dtc-parser.y" /* yacc.c:1646  */
+#line 436 "dtc-parser.y" /* yacc.c:1646  */
     { (yyval.integer) = -(yyvsp[0].integer); }
-#line 1927 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1941 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 70:
-#line 421 "dtc-parser.y" /* yacc.c:1646  */
+#line 437 "dtc-parser.y" /* yacc.c:1646  */
     { (yyval.integer) = ~(yyvsp[0].integer); }
-#line 1933 "dtc-parser.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 71:
-#line 422 "dtc-parser.y" /* yacc.c:1646  */
-    { (yyval.integer) = !(yyvsp[0].integer); }
-#line 1939 "dtc-parser.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 72:
-#line 427 "dtc-parser.y" /* yacc.c:1646  */
-    {
-			(yyval.data) = empty_data;
-		}
 #line 1947 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
+  case 71:
+#line 438 "dtc-parser.y" /* yacc.c:1646  */
+    { (yyval.integer) = !(yyvsp[0].integer); }
+#line 1953 "dtc-parser.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 72:
+#line 443 "dtc-parser.y" /* yacc.c:1646  */
+    {
+			(yyval.data) = empty_data;
+		}
+#line 1961 "dtc-parser.tab.c" /* yacc.c:1646  */
+    break;
+
   case 73:
-#line 431 "dtc-parser.y" /* yacc.c:1646  */
+#line 447 "dtc-parser.y" /* yacc.c:1646  */
     {
 			(yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte));
 		}
-#line 1955 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1969 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 74:
-#line 435 "dtc-parser.y" /* yacc.c:1646  */
+#line 451 "dtc-parser.y" /* yacc.c:1646  */
     {
 			(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
 		}
-#line 1963 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1977 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 75:
-#line 442 "dtc-parser.y" /* yacc.c:1646  */
+#line 458 "dtc-parser.y" /* yacc.c:1646  */
     {
 			(yyval.nodelist) = NULL;
 		}
-#line 1971 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1985 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 76:
-#line 446 "dtc-parser.y" /* yacc.c:1646  */
+#line 462 "dtc-parser.y" /* yacc.c:1646  */
     {
 			(yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist));
 		}
-#line 1979 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1993 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 77:
-#line 450 "dtc-parser.y" /* yacc.c:1646  */
+#line 466 "dtc-parser.y" /* yacc.c:1646  */
     {
 			ERROR(&(yylsp[0]), "Properties must precede subnodes");
 			YYERROR;
 		}
-#line 1988 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2002 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 78:
-#line 458 "dtc-parser.y" /* yacc.c:1646  */
+#line 474 "dtc-parser.y" /* yacc.c:1646  */
     {
 			(yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename));
 		}
-#line 1996 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2010 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 79:
-#line 462 "dtc-parser.y" /* yacc.c:1646  */
+#line 478 "dtc-parser.y" /* yacc.c:1646  */
     {
 			(yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename));
 		}
-#line 2004 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2018 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 80:
-#line 466 "dtc-parser.y" /* yacc.c:1646  */
+#line 482 "dtc-parser.y" /* yacc.c:1646  */
     {
 			add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref));
 			(yyval.node) = (yyvsp[0].node);
 		}
-#line 2013 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2027 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
 
-#line 2017 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2031 "dtc-parser.tab.c" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -2248,7 +2262,7 @@
 #endif
   return yyresult;
 }
-#line 472 "dtc-parser.y" /* yacc.c:1906  */
+#line 488 "dtc-parser.y" /* yacc.c:1906  */
 
 
 void yyerror(char const *s)
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 5a897e36..000873f 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -410,8 +410,24 @@
 
 integer_mul:
 	  integer_mul '*' integer_unary { $$ = $1 * $3; }
-	| integer_mul '/' integer_unary { $$ = $1 / $3; }
-	| integer_mul '%' integer_unary { $$ = $1 % $3; }
+	| integer_mul '/' integer_unary
+		{
+			if ($3 != 0) {
+				$$ = $1 / $3;
+			} else {
+				ERROR(&@$, "Division by zero");
+				$$ = 0;
+			}
+		}
+	| integer_mul '%' integer_unary
+		{
+			if ($3 != 0) {
+				$$ = $1 % $3;
+			} else {
+				ERROR(&@$, "Division by zero");
+				$$ = 0;
+			}
+		}
 	| integer_unary
 	;
 
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index 8c4add6..5fa23c4 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -18,6 +18,8 @@
  *                                                                   USA
  */
 
+#include <sys/stat.h>
+
 #include "dtc.h"
 #include "srcpos.h"
 
@@ -104,11 +106,56 @@
 	NULL,
 };
 
+static const char *guess_type_by_name(const char *fname, const char *fallback)
+{
+	const char *s;
+
+	s = strrchr(fname, '.');
+	if (s == NULL)
+		return fallback;
+	if (!strcasecmp(s, ".dts"))
+		return "dts";
+	if (!strcasecmp(s, ".dtb"))
+		return "dtb";
+	return fallback;
+}
+
+static const char *guess_input_format(const char *fname, const char *fallback)
+{
+	struct stat statbuf;
+	uint32_t magic;
+	FILE *f;
+
+	if (stat(fname, &statbuf) != 0)
+		return fallback;
+
+	if (S_ISDIR(statbuf.st_mode))
+		return "fs";
+
+	if (!S_ISREG(statbuf.st_mode))
+		return fallback;
+
+	f = fopen(fname, "r");
+	if (f == NULL)
+		return fallback;
+	if (fread(&magic, 4, 1, f) != 1) {
+		fclose(f);
+		return fallback;
+	}
+	fclose(f);
+
+	magic = fdt32_to_cpu(magic);
+	if (magic == FDT_MAGIC)
+		return "dtb";
+
+	return guess_type_by_name(fname, fallback);
+}
+
 int main(int argc, char *argv[])
 {
 	struct boot_info *bi;
-	const char *inform = "dts";
-	const char *outform = "dts";
+	const char *inform = NULL;
+	const char *outform = NULL;
 	const char *outname = "-";
 	const char *depname = NULL;
 	bool force = false, sort = false;
@@ -213,6 +260,17 @@
 		fprintf(depfile, "%s:", outname);
 	}
 
+	if (inform == NULL)
+		inform = guess_input_format(arg, "dts");
+	if (outform == NULL) {
+		outform = guess_type_by_name(outname, NULL);
+		if (outform == NULL) {
+			if (streq(inform, "dts"))
+				outform = "dtb";
+			else
+				outform = "dts";
+		}
+	}
 	if (streq(inform, "dts"))
 		bi = dt_from_source(arg);
 	else if (streq(inform, "fs"))
diff --git a/scripts/dtc/dtx_diff b/scripts/dtc/dtx_diff
new file mode 100755
index 0000000..959ab26
--- /dev/null
+++ b/scripts/dtc/dtx_diff
@@ -0,0 +1,349 @@
+#! /bin/bash
+
+# Copyright (C) 2015 Frank Rowand
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+
+
+usage() {
+
+	# use spaces instead of tabs in the usage message
+	cat >&2 <<eod
+
+Usage:
+
+   `basename $0` DTx
+        decompile DTx
+
+   `basename $0` DTx_1 DTx_2
+        diff DTx_1 and DTx_2
+
+
+       -f           print full dts in diff (--unified=99999)
+       -h           synonym for --help
+       -help        synonym for --help
+      --help        print this message and exit
+       -s SRCTREE   linux kernel source tree is at path SRCTREE
+                        (default is current directory)
+       -S           linux kernel source tree is at root of current git repo
+       -u           unsorted, do not sort DTx
+
+
+Each DTx is processed by the dtc compiler to produce a sorted dts source
+file.  If DTx is a dts source file then it is pre-processed in the same
+manner as done for the compile of the dts source file in the Linux kernel
+build system ('#include' and '/include/' directives are processed).
+
+If two DTx are provided, the resulting dts source files are diffed.
+
+If DTx is a directory, it is treated as a DT subtree, such as
+  /proc/device-tree.
+
+If DTx contains the binary blob magic value in the first four bytes,
+  it is treated as a binary blob (aka .dtb or FDT).
+
+Otherwise DTx is treated as a dts source file (aka .dts).
+
+   If this script is not run from the root of the linux source tree,
+   and DTx utilizes '#include' or '/include/' then the path of the
+   linux source tree can be provided by '-s SRCTREE' or '-S' so that
+   include paths will be set properly.
+
+   The shell variable \${ARCH} must provide the architecture containing
+   the dts source file for include paths to be set properly for '#include'
+   or '/include/' to be processed.
+
+   If DTx_1 and DTx_2 are in different architectures, then this script
+   may not work since \${ARCH} is part of the include path.  Two possible
+   workarounds:
+
+      `basename $0` \\
+          <(ARCH=arch_of_dtx_1 `basename $0` DTx_1) \\
+          <(ARCH=arch_of_dtx_2 `basename $0` DTx_2)
+
+      `basename $0` ARCH=arch_of_dtx_1 DTx_1 >tmp_dtx_1.dts
+      `basename $0` ARCH=arch_of_dtx_2 DTx_2 >tmp_dtx_2.dts
+      `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
+      rm tmp_dtx_1.dts tmp_dtx_2.dts
+
+   If DTx_1 and DTx_2 are in different directories, then this script will
+   add the path of DTx_1 and DTx_2 to the include paths.  If DTx_2 includes
+   a local file that exists in both the path of DTx_1 and DTx_2 then the
+   file in the path of DTx_1 will incorrectly be included.  Possible
+   workaround:
+
+      `basename $0` DTx_1 >tmp_dtx_1.dts
+      `basename $0` DTx_2 >tmp_dtx_2.dts
+      `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
+      rm tmp_dtx_1.dts tmp_dtx_2.dts
+
+eod
+}
+
+
+compile_to_dts() {
+
+	dtx="$1"
+
+	if [ -d "${dtx}" ] ; then
+
+		# -----  input is file tree
+
+		if ( ! ${DTC} -I fs ${dtx} ) ; then
+			exit 3
+		fi
+
+	elif [ -f "${dtx}" ] && [ -r "${dtx}" ] ; then
+
+		magic=`hexdump -n 4 -e '/1 "%02x"' ${dtx}`
+		if [ "${magic}" = "d00dfeed" ] ; then
+
+			# -----  input is FDT (binary blob)
+
+			if ( ! ${DTC} -I dtb ${dtx} ) ; then
+				exit 3
+			fi
+
+			return
+
+		fi
+
+		# -----  input is DTS (source)
+
+		if ( cpp ${cpp_flags} -x assembler-with-cpp ${dtx} \
+			| ${DTC} -I dts ) ; then
+			return
+		fi
+
+		echo ""                                                      >&2
+		echo "Possible hints to resolve the above error:"            >&2
+		echo "  (hints might not fix the problem)"                   >&2
+
+		hint_given=0
+
+		if [ "${ARCH}" = "" ] ; then
+			hint_given=1
+			echo ""                                              >&2
+			echo "  shell variable \$ARCH not set"               >&2
+		fi
+
+		dtx_arch=`echo "/${dtx}" | sed -e 's|.*/arch/||' -e 's|/.*||'`
+
+		if [ "${dtx_arch}" != ""  -a "${dtx_arch}" != "${ARCH}" ] ; then
+			hint_given=1
+			echo ""                                              >&2
+			echo "  architecture ${dtx_arch} is in file path,"   >&2
+			echo "  but does not match shell variable \$ARCH"    >&2
+			echo "  >>\$ARCH<< is: >>${ARCH}<<"                  >&2
+		fi
+
+		if [ ! -d ${srctree}/arch/${ARCH} ] ; then
+			hint_given=1
+			echo ""                                              >&2
+			echo "  ${srctree}/arch/${ARCH}/ does not exist"     >&2
+			echo "  Is \$ARCH='${ARCH}' correct?"                >&2
+			echo "  Possible fix: use '-s' option"               >&2
+
+			git_root=`git rev-parse --show-toplevel 2>/dev/null`
+			if [ -d ${git_root}/arch/ ] ; then
+				echo "  Possible fix: use '-S' option"       >&2
+			fi
+		fi
+
+		if [ $hint_given = 0 ] ; then
+			echo ""                                              >&2
+			echo "  No hints available."                         >&2
+		fi
+
+		echo ""                                                      >&2
+
+		exit 3
+
+	else
+		echo ""                                                     >&2
+		echo "ERROR: ${dtx} does not exist or is not readable"      >&2
+		echo ""                                                     >&2
+		exit 2
+	fi
+
+}
+
+
+# -----  start of script
+
+cmd_diff=0
+diff_flags="-u"
+dtx_file_1=""
+dtx_file_2=""
+dtc_sort="-s"
+help=0
+srctree=""
+
+
+while [ $# -gt 0 ] ; do
+
+	case $1 in
+
+	-f )
+		diff_flags="--unified=999999"
+		shift
+		;;
+
+	-h | -help | --help )
+		help=1
+		shift
+		;;
+
+	-s )
+		srctree="$2"
+		shift 2
+		;;
+
+	-S )
+		git_root=`git rev-parse --show-toplevel 2>/dev/null`
+		srctree="${git_root}"
+		shift
+		;;
+
+	-u )
+		dtc_sort=""
+		shift
+		;;
+
+	*)
+		if [ "${dtx_file_1}"  = "" ] ; then
+			dtx_file_1="$1"
+		elif [ "${dtx_file_2}" = "" ] ; then
+			dtx_file_2="$1"
+		else
+			echo ""                                             >&2
+			echo "ERROR: Unexpected parameter: $1"              >&2
+			echo ""                                             >&2
+			exit 2
+		fi
+		shift
+		;;
+
+	esac
+
+done
+
+if [ "${srctree}" = "" ] ; then
+	srctree="."
+fi
+
+if [ "${dtx_file_2}" != "" ]; then
+	cmd_diff=1
+fi
+
+if (( ${help} )) ; then
+	usage
+	exit 1
+fi
+
+# this must follow check for ${help}
+if [ "${dtx_file_1}" = "" ]; then
+	echo ""                                                             >&2
+	echo "ERROR: parameter DTx required"                                >&2
+	echo ""                                                             >&2
+	exit 2
+fi
+
+
+# -----  prefer dtc from linux kernel, allow fallback to dtc in $PATH
+
+if [ "${KBUILD_OUTPUT:0:2}" = ".." ] ; then
+	__KBUILD_OUTPUT="${srctree}/${KBUILD_OUTPUT}"
+elif [ "${KBUILD_OUTPUT}" = "" ] ; then
+	__KBUILD_OUTPUT="."
+else
+	__KBUILD_OUTPUT="${KBUILD_OUTPUT}"
+fi
+
+DTC="${__KBUILD_OUTPUT}/scripts/dtc/dtc"
+
+if [ ! -x ${DTC} ] ; then
+	__DTC="dtc"
+	if grep -q "^CONFIG_DTC=y" ${__KBUILD_OUTPUT}/.config ; then
+		make_command='
+         make scripts'
+	else
+		make_command='
+         Enable CONFIG_DTC in the kernel configuration
+         make scripts'
+	fi
+	if ( ! which ${__DTC} >/dev/null ) ; then
+
+		# use spaces instead of tabs in the error message
+		cat >&2 <<eod
+
+ERROR: unable to find a 'dtc' program
+
+   Preferred 'dtc' (built from Linux kernel source tree) was not found or
+   is not executable.
+
+      'dtc' is: ${DTC}
+
+      If it does not exist, create it from the root of the Linux source tree:
+${make_command}
+
+      If not at the root of the Linux kernel source tree -s SRCTREE or -S
+      may need to be specified to find 'dtc'.
+
+      If 'O=\${dir}' is specified in your Linux builds, this script requires
+      'export KBUILD_OUTPUT=\${dir}' or add \${dir}/scripts/dtc to \$PATH
+      before running.
+
+      If \${KBUILD_OUTPUT} is a relative path, then '-s SRCDIR', -S, or run
+      this script from the root of the Linux kernel source tree is required.
+
+   Fallback '${__DTC}' was also not in \${PATH} or is not executable.
+
+eod
+		exit 2
+	fi
+	DTC=${__DTC}
+fi
+
+
+# -----  cpp and dtc flags same as for linux source tree build of .dtb files,
+#        plus directories of the dtx file(s)
+
+dtx_path_1_dtc_include="-i `dirname ${dtx_file_1}`"
+
+dtx_path_2_dtc_include=""
+if (( ${cmd_diff} )) ; then
+	dtx_path_2_dtc_include="-i `dirname ${dtx_file_2}`"
+fi
+
+cpp_flags="\
+	-nostdinc                                  \
+	-I${srctree}/arch/${ARCH}/boot/dts         \
+	-I${srctree}/arch/${ARCH}/boot/dts/include \
+	-I${srctree}/drivers/of/testcase-data      \
+	-undef -D__DTS__"
+
+dtc_flags="\
+	-i ${srctree}/arch/${ARCH}/boot/dts/ \
+	-i ${srctree}/kernel/dts             \
+	${dtx_path_1_dtc_include}            \
+	${dtx_path_2_dtc_include}"
+
+DTC="${DTC} ${dtc_flags} -O dts -qq -f ${dtc_sort} -o -"
+
+
+# -----  do the diff or decompile
+
+if (( ${cmd_diff} )) ; then
+
+	diff ${diff_flags} \
+		<(compile_to_dts "${dtx_file_1}") \
+		<(compile_to_dts "${dtx_file_2}")
+
+else
+
+	compile_to_dts "${dtx_file_1}"
+
+fi
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 2ce6a44..22286a1 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -76,18 +76,19 @@
 
 const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
 {
-	const char *p;
+	unsigned absoffset = offset + fdt_off_dt_struct(fdt);
+
+	if ((absoffset < offset)
+	    || ((absoffset + len) < absoffset)
+	    || (absoffset + len) > fdt_totalsize(fdt))
+		return NULL;
 
 	if (fdt_version(fdt) >= 0x11)
 		if (((offset + len) < offset)
 		    || ((offset + len) > fdt_size_dt_struct(fdt)))
 			return NULL;
 
-	p = _fdt_offset_ptr(fdt, offset);
-
-	if (p + len < p)
-		return NULL;
-	return p;
+	return _fdt_offset_ptr(fdt, offset);
 }
 
 uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index a65e4b5..e5b3136 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -538,6 +538,106 @@
 	return 0;
 }
 
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
+{
+	const char *list, *end;
+	int length, count = 0;
+
+	list = fdt_getprop(fdt, nodeoffset, property, &length);
+	if (!list)
+		return -length;
+
+	end = list + length;
+
+	while (list < end) {
+		length = strnlen(list, end - list) + 1;
+
+		/* Abort if the last string isn't properly NUL-terminated. */
+		if (list + length > end)
+			return -FDT_ERR_BADVALUE;
+
+		list += length;
+		count++;
+	}
+
+	return count;
+}
+
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+			  const char *string)
+{
+	int length, len, idx = 0;
+	const char *list, *end;
+
+	list = fdt_getprop(fdt, nodeoffset, property, &length);
+	if (!list)
+		return -length;
+
+	len = strlen(string) + 1;
+	end = list + length;
+
+	while (list < end) {
+		length = strnlen(list, end - list) + 1;
+
+		/* Abort if the last string isn't properly NUL-terminated. */
+		if (list + length > end)
+			return -FDT_ERR_BADVALUE;
+
+		if (length == len && memcmp(list, string, length) == 0)
+			return idx;
+
+		list += length;
+		idx++;
+	}
+
+	return -FDT_ERR_NOTFOUND;
+}
+
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+			       const char *property, int idx,
+			       int *lenp)
+{
+	const char *list, *end;
+	int length;
+
+	list = fdt_getprop(fdt, nodeoffset, property, &length);
+	if (!list) {
+		if (lenp)
+			*lenp = length;
+
+		return NULL;
+	}
+
+	end = list + length;
+
+	while (list < end) {
+		length = strnlen(list, end - list) + 1;
+
+		/* Abort if the last string isn't properly NUL-terminated. */
+		if (list + length > end) {
+			if (lenp)
+				*lenp = -FDT_ERR_BADVALUE;
+
+			return NULL;
+		}
+
+		if (idx == 0) {
+			if (lenp)
+				*lenp = length - 1;
+
+			return list;
+		}
+
+		list += length;
+		idx--;
+	}
+
+	if (lenp)
+		*lenp = -FDT_ERR_NOTFOUND;
+
+	return NULL;
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 			      const char *compatible)
 {
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 70adec6..8be02b1 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -101,6 +101,8 @@
 
 	if (((p + oldlen) < p) || ((p + oldlen) > end))
 		return -FDT_ERR_BADOFFSET;
+	if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
+		return -FDT_ERR_BADOFFSET;
 	if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
 		return -FDT_ERR_NOSPACE;
 	memmove(p + newlen, p + oldlen, end - p - oldlen);
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index ea35ac3..59ca339 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -121,7 +121,12 @@
 	/* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
 	 * or similar property with a bad format or value */
 
-#define FDT_ERR_MAX		14
+#define FDT_ERR_BADVALUE	15
+	/* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
+	 * value. For example: a property expected to contain a string list
+	 * is not NUL-terminated within the length of its value. */
+
+#define FDT_ERR_MAX		15
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -457,8 +462,8 @@
  * @namelen: number of characters of name to consider
  * @lenp: pointer to an integer variable (will be overwritten) or NULL
  *
- * Identical to fdt_get_property_namelen(), but only examine the first
- * namelen characters of name for matching the property name.
+ * Identical to fdt_get_property(), but only examine the first namelen
+ * characters of name for matching the property name.
  */
 const struct fdt_property *fdt_get_property_namelen(const void *fdt,
 						    int nodeoffset,
@@ -868,6 +873,68 @@
  */
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
+/**
+ * fdt_stringlist_count - count the number of strings in a string list
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @return:
+ *   the number of strings in the given property
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist
+ */
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
+
+/**
+ * fdt_stringlist_search - find a string in a string list and return its index
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @string: string to look up in the string list
+ *
+ * Note that it is possible for this function to succeed on property values
+ * that are not NUL-terminated. That's because the function will stop after
+ * finding the first occurrence of @string. This can for example happen with
+ * small-valued cell properties, such as #address-cells, when searching for
+ * the empty string.
+ *
+ * @return:
+ *   the index of the string in the list of strings
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist or does not contain
+ *                     the given string
+ */
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+			  const char *string);
+
+/**
+ * fdt_stringlist_get() - obtain the string at a given index in a string list
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @index: index of the string to return
+ * @lenp: return location for the string length or an error code on failure
+ *
+ * Note that this will successfully extract strings from properties with
+ * non-NUL-terminated values. For example on small-valued cell properties
+ * this function will return the empty string.
+ *
+ * If non-NULL, the length of the string (on success) or a negative error-code
+ * (on failure) will be stored in the integer pointer to by lenp.
+ *
+ * @return:
+ *   A pointer to the string at the given index in the string list or NULL on
+ *   failure. On success the length of the string will be stored in the memory
+ *   location pointed to by the lenp parameter, if non-NULL. On failure one of
+ *   the following negative error codes will be returned in the lenp parameter
+ *   (if non-NULL):
+ *     -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *     -FDT_ERR_NOTFOUND if the property does not exist
+ */
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+			       const char *property, int index,
+			       int *lenp);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index 9d65226..fb124ee 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -152,7 +152,6 @@
 	int	j = *i + 1;
 	char	val;
 
-	assert(c);
 	switch (c) {
 	case 'a':
 		val = '\a';
@@ -349,7 +348,6 @@
 void utilfdt_print_data(const char *data, int len)
 {
 	int i;
-	const char *p = data;
 	const char *s;
 
 	/* no data, don't print */
@@ -376,6 +374,7 @@
 			       i < (len - 1) ? " " : "");
 		printf(">");
 	} else {
+		const unsigned char *p = (const unsigned char *)data;
 		printf(" = [");
 		for (i = 0; i < len; i++)
 			printf("%02x%s", *p++, i < len - 1 ? " " : "");
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
index 5b8c7d5..11d93e6 100644
--- a/scripts/dtc/version_gen.h
+++ b/scripts/dtc/version_gen.h
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.4.1-g9d3649bd"
+#define DTC_VERSION "DTC 1.4.1-gb06e55c8"