aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-15 14:49:41 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-15 14:49:41 -0500
commit6df8b74b1720db1133ace0861cb6721bfe57819a (patch)
tree9bf00c9a75cd52a0917bbd6ff5ff4a693b3b8f0a
parent57d64e6f5fac7b47dd03487f5f2670a7f0c67335 (diff)
parent61eb3a04f9789c5e4f7498a2f171b82a567cea6b (diff)
Merge tag 'devicetree-for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull DeviceTree updates from Rob Herring: - add various vendor prefixes. - fix NUMA node handling when "numa=off" is passed on kernel command line. - coding style Clean-up of overlay handling code. - DocBook fixes in DT platform driver code - Altera SoCFPGA binding addtions for freeze bridge, arria10 FPGA manager and FPGA bridges. - a couple of printk message fixes. * tag 'devicetree-for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (33 commits) dt: pwm: bcm2835: fix typo in clocks property name devicetree: add vendor prefix for National Instruments Revert "of: base: add support to get machine model name" of: Fix issue where code would fall through to error case. drivers/of: fix missing pr_cont()s in of_print_phandle_args devicetree: bindings: Add vendor prefix for Oki devicetree: bindings: Add vendor prefix for Andes Technology Corporation dt-bindings: add MYIR Tech hardware vendor prefix add bindings document for altera freeze bridge ARM: socfpga: add bindings doc for arria10 fpga manager ARM: socfpga: add bindings document for fpga bridge drivers of: base: add support to get machine model name of/platform: clarify of_find_device_by_node refcounting of/platform: fix of_platform_device_destroy comment of: Remove unused variable overlay_symbols of: Move setting of pointer to beside test for non-null of: Add back an error message, restructured of: Update comments to reflect changes and increase clarity of: Remove redundant size check of: Update structure of code to be clearer, also remove BUG_ON() ...
-rw-r--r--Documentation/devicetree/bindings/arm/arm-boards3
-rw-r--r--Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt16
-rw-r--r--Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt23
-rw-r--r--Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt39
-rw-r--r--Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt19
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt2
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt11
-rw-r--r--drivers/of/base.c9
-rw-r--r--drivers/of/of_numa.c7
-rw-r--r--drivers/of/platform.c6
-rw-r--r--drivers/of/resolver.c358
11 files changed, 278 insertions, 215 deletions
diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards
index ab318a56fca2..b6e810c2781a 100644
--- a/Documentation/devicetree/bindings/arm/arm-boards
+++ b/Documentation/devicetree/bindings/arm/arm-boards
@@ -148,11 +148,12 @@ Example:
148 148
149/dts-v1/; 149/dts-v1/;
150#include <dt-bindings/interrupt-controller/irq.h> 150#include <dt-bindings/interrupt-controller/irq.h>
151#include "skeleton.dtsi"
152 151
153/ { 152/ {
154 model = "ARM RealView PB1176 with device tree"; 153 model = "ARM RealView PB1176 with device tree";
155 compatible = "arm,realview-pb1176"; 154 compatible = "arm,realview-pb1176";
155 #address-cells = <1>;
156 #size-cells = <1>;
156 157
157 soc { 158 soc {
158 #address-cells = <1>; 159 #address-cells = <1>;
diff --git a/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt b/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt
new file mode 100644
index 000000000000..817a8d4bf903
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt
@@ -0,0 +1,16 @@
1Altera FPGA To SDRAM Bridge Driver
2
3Required properties:
4- compatible : Should contain "altr,socfpga-fpga2sdram-bridge"
5
6Optional properties:
7- bridge-enable : 0 if driver should disable bridge at startup
8 1 if driver should enable bridge at startup
9 Default is to leave bridge in current state.
10
11Example:
12 fpga_bridge3: fpga-bridge@ffc25080 {
13 compatible = "altr,socfpga-fpga2sdram-bridge";
14 reg = <0xffc25080 0x4>;
15 bridge-enable = <0>;
16 };
diff --git a/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt b/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt
new file mode 100644
index 000000000000..f8e288c71b2d
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt
@@ -0,0 +1,23 @@
1Altera Freeze Bridge Controller Driver
2
3The Altera Freeze Bridge Controller manages one or more freeze bridges.
4The controller can freeze/disable the bridges which prevents signal
5changes from passing through the bridge. The controller can also
6unfreeze/enable the bridges which allows traffic to pass through the
7bridge normally.
8
9Required properties:
10- compatible : Should contain "altr,freeze-bridge-controller"
11- regs : base address and size for freeze bridge module
12
13Optional properties:
14- bridge-enable : 0 if driver should disable bridge at startup
15 1 if driver should enable bridge at startup
16 Default is to leave bridge in current state.
17
18Example:
19 freeze-controller@100000450 {
20 compatible = "altr,freeze-bridge-controller";
21 regs = <0x1000 0x10>;
22 bridge-enable = <0>;
23 };
diff --git a/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt b/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt
new file mode 100644
index 000000000000..6406f9337eeb
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt
@@ -0,0 +1,39 @@
1Altera FPGA/HPS Bridge Driver
2
3Required properties:
4- regs : base address and size for AXI bridge module
5- compatible : Should contain one of:
6 "altr,socfpga-lwhps2fpga-bridge",
7 "altr,socfpga-hps2fpga-bridge", or
8 "altr,socfpga-fpga2hps-bridge"
9- resets : Phandle and reset specifier for this bridge's reset
10- clocks : Clocks used by this module.
11
12Optional properties:
13- bridge-enable : 0 if driver should disable bridge at startup.
14 1 if driver should enable bridge at startup.
15 Default is to leave bridge in its current state.
16
17Example:
18 fpga_bridge0: fpga-bridge@ff400000 {
19 compatible = "altr,socfpga-lwhps2fpga-bridge";
20 reg = <0xff400000 0x100000>;
21 resets = <&rst LWHPS2FPGA_RESET>;
22 clocks = <&l4_main_clk>;
23 bridge-enable = <0>;
24 };
25
26 fpga_bridge1: fpga-bridge@ff500000 {
27 compatible = "altr,socfpga-hps2fpga-bridge";
28 reg = <0xff500000 0x10000>;
29 resets = <&rst HPS2FPGA_RESET>;
30 clocks = <&l4_main_clk>;
31 bridge-enable = <1>;
32 };
33
34 fpga_bridge2: fpga-bridge@ff600000 {
35 compatible = "altr,socfpga-fpga2hps-bridge";
36 reg = <0xff600000 0x100000>;
37 resets = <&rst FPGA2HPS_RESET>;
38 clocks = <&l4_main_clk>;
39 };
diff --git a/Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt
new file mode 100644
index 000000000000..2fd8e7a84734
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt
@@ -0,0 +1,19 @@
1Altera SOCFPGA Arria10 FPGA Manager
2
3Required properties:
4- compatible : should contain "altr,socfpga-a10-fpga-mgr"
5- reg : base address and size for memory mapped io.
6 - The first index is for FPGA manager register access.
7 - The second index is for writing FPGA configuration data.
8- resets : Phandle and reset specifier for the device's reset.
9- clocks : Clocks used by the device.
10
11Example:
12
13 fpga_mgr: fpga-mgr@ffd03000 {
14 compatible = "altr,socfpga-a10-fpga-mgr";
15 reg = <0xffd03000 0x100
16 0xffcfe400 0x20>;
17 clocks = <&l4_mp_clk>;
18 resets = <&rst FPGAMGR_RESET>;
19 };
diff --git a/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt b/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt
index fb6fb31bc4c4..cf573e85b11d 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt
@@ -3,7 +3,7 @@ BCM2835 PWM controller (Raspberry Pi controller)
3Required properties: 3Required properties:
4- compatible: should be "brcm,bcm2835-pwm" 4- compatible: should be "brcm,bcm2835-pwm"
5- reg: physical base address and length of the controller's registers 5- reg: physical base address and length of the controller's registers
6- clock: This clock defines the base clock frequency of the PWM hardware 6- clocks: This clock defines the base clock frequency of the PWM hardware
7 system, the period and the duty_cycle of the PWM signal is a multiple of 7 system, the period and the duty_cycle of the PWM signal is a multiple of
8 the base period. 8 the base period.
9- #pwm-cells: Should be 2. See pwm.txt in this directory for a description of 9- #pwm-cells: Should be 2. See pwm.txt in this directory for a description of
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 078834a5fd85..6e25c912a5c2 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -24,9 +24,11 @@ ampire Ampire Co., Ltd.
24ams AMS AG 24ams AMS AG
25amstaos AMS-Taos Inc. 25amstaos AMS-Taos Inc.
26analogix Analogix Semiconductor, Inc. 26analogix Analogix Semiconductor, Inc.
27andestech Andes Technology Corporation
27apm Applied Micro Circuits Corporation (APM) 28apm Applied Micro Circuits Corporation (APM)
28aptina Aptina Imaging 29aptina Aptina Imaging
29arasan Arasan Chip Systems 30arasan Arasan Chip Systems
31aries Aries Embedded GmbH
30arm ARM Ltd. 32arm ARM Ltd.
31armadeus ARMadeus Systems SARL 33armadeus ARMadeus Systems SARL
32arrow Arrow Electronics 34arrow Arrow Electronics
@@ -161,6 +163,7 @@ lg LG Corporation
161linux Linux-specific binding 163linux Linux-specific binding
162lltc Linear Technology Corporation 164lltc Linear Technology Corporation
163lsi LSI Corp. (LSI Logic) 165lsi LSI Corp. (LSI Logic)
166macnica Macnica Americas
164marvell Marvell Technology Group Ltd. 167marvell Marvell Technology Group Ltd.
165maxim Maxim Integrated Products 168maxim Maxim Integrated Products
166mcube mCube 169mcube mCube
@@ -186,6 +189,7 @@ mti Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
186mundoreader Mundo Reader S.L. 189mundoreader Mundo Reader S.L.
187murata Murata Manufacturing Co., Ltd. 190murata Murata Manufacturing Co., Ltd.
188mxicy Macronix International Co., Ltd. 191mxicy Macronix International Co., Ltd.
192myir MYIR Tech Limited
189national National Semiconductor 193national National Semiconductor
190nec NEC LCD Technologies, Ltd. 194nec NEC LCD Technologies, Ltd.
191neonode Neonode Inc. 195neonode Neonode Inc.
@@ -193,13 +197,15 @@ netgear NETGEAR
193netlogic Broadcom Corporation (formerly NetLogic Microsystems) 197netlogic Broadcom Corporation (formerly NetLogic Microsystems)
194netxeon Shenzhen Netxeon Technology CO., LTD 198netxeon Shenzhen Netxeon Technology CO., LTD
195newhaven Newhaven Display International 199newhaven Newhaven Display International
196nvd New Vision Display 200ni National Instruments
197nintendo Nintendo 201nintendo Nintendo
198nokia Nokia 202nokia Nokia
199nuvoton Nuvoton Technology Corporation 203nuvoton Nuvoton Technology Corporation
204nvd New Vision Display
200nvidia NVIDIA 205nvidia NVIDIA
201nxp NXP Semiconductors 206nxp NXP Semiconductors
202okaya Okaya Electric America, Inc. 207okaya Okaya Electric America, Inc.
208oki Oki Electric Industry Co., Ltd.
203olimex OLIMEX Ltd. 209olimex OLIMEX Ltd.
204onion Onion Corporation 210onion Onion Corporation
205onnn ON Semiconductor Corp. 211onnn ON Semiconductor Corp.
@@ -238,6 +244,7 @@ richtek Richtek Technology Corporation
238ricoh Ricoh Co. Ltd. 244ricoh Ricoh Co. Ltd.
239rockchip Fuzhou Rockchip Electronics Co., Ltd 245rockchip Fuzhou Rockchip Electronics Co., Ltd
240samsung Samsung Semiconductor 246samsung Samsung Semiconductor
247samtec Samtec/Softing company
241sandisk Sandisk Corporation 248sandisk Sandisk Corporation
242sbs Smart Battery System 249sbs Smart Battery System
243schindler Schindler 250schindler Schindler
@@ -282,6 +289,7 @@ tcg Trusted Computing Group
282tcl Toby Churchill Ltd. 289tcl Toby Churchill Ltd.
283technexion TechNexion 290technexion TechNexion
284technologic Technologic Systems 291technologic Technologic Systems
292terasic Terasic Inc.
285thine THine Electronics, Inc. 293thine THine Electronics, Inc.
286ti Texas Instruments 294ti Texas Instruments
287tlm Trusted Logic Mobility 295tlm Trusted Logic Mobility
@@ -296,6 +304,7 @@ tronfy Tronfy
296tronsmart Tronsmart 304tronsmart Tronsmart
297truly Truly Semiconductors Limited 305truly Truly Semiconductors Limited
298tyan Tyan Computer Corporation 306tyan Tyan Computer Corporation
307udoo Udoo
299uniwest United Western Technologies Corp (UniWest) 308uniwest United Western Technologies Corp (UniWest)
300upisemi uPI Semiconductor Corp. 309upisemi uPI Semiconductor Corp.
301urt United Radiant Technology Corporation 310urt United Radiant Technology Corporation
diff --git a/drivers/of/base.c b/drivers/of/base.c
index a0bccb54a9bd..d4bea3c797d6 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1534,9 +1534,12 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
1534{ 1534{
1535 int i; 1535 int i;
1536 printk("%s %s", msg, of_node_full_name(args->np)); 1536 printk("%s %s", msg, of_node_full_name(args->np));
1537 for (i = 0; i < args->args_count; i++) 1537 for (i = 0; i < args->args_count; i++) {
1538 printk(i ? ",%08x" : ":%08x", args->args[i]); 1538 const char delim = i ? ',' : ':';
1539 printk("\n"); 1539
1540 pr_cont("%c%08x", delim, args->args[i]);
1541 }
1542 pr_cont("\n");
1540} 1543}
1541 1544
1542int of_phandle_iterator_init(struct of_phandle_iterator *it, 1545int of_phandle_iterator_init(struct of_phandle_iterator *it,
diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
index f63d4b0deff0..a53982a330ea 100644
--- a/drivers/of/of_numa.c
+++ b/drivers/of/of_numa.c
@@ -176,7 +176,12 @@ int of_node_to_nid(struct device_node *device)
176 np->name); 176 np->name);
177 of_node_put(np); 177 of_node_put(np);
178 178
179 if (!r) 179 /*
180 * If numa=off passed on command line, or with a defective
181 * device tree, the nid may not be in the set of possible
182 * nodes. Check for this case and return NUMA_NO_NODE.
183 */
184 if (!r && nid < MAX_NUMNODES && node_possible(nid))
180 return nid; 185 return nid;
181 186
182 return NUMA_NO_NODE; 187 return NUMA_NO_NODE;
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index e4bf07d20f9b..b8064bc2b6eb 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -45,6 +45,9 @@ static int of_dev_node_match(struct device *dev, void *data)
45 * of_find_device_by_node - Find the platform_device associated with a node 45 * of_find_device_by_node - Find the platform_device associated with a node
46 * @np: Pointer to device tree node 46 * @np: Pointer to device tree node
47 * 47 *
48 * Takes a reference to the embedded struct device which needs to be dropped
49 * after use.
50 *
48 * Returns platform_device pointer, or NULL if not found 51 * Returns platform_device pointer, or NULL if not found
49 */ 52 */
50struct platform_device *of_find_device_by_node(struct device_node *np) 53struct platform_device *of_find_device_by_node(struct device_node *np)
@@ -558,9 +561,6 @@ static int of_platform_device_destroy(struct device *dev, void *data)
558 * of the given device (and, recurrently, their children) that have been 561 * of the given device (and, recurrently, their children) that have been
559 * created from their respective device tree nodes (and only those, 562 * created from their respective device tree nodes (and only those,
560 * leaving others - eg. manually created - unharmed). 563 * leaving others - eg. manually created - unharmed).
561 *
562 * Returns 0 when all children devices have been removed or
563 * -EBUSY when some children remained.
564 */ 564 */
565void of_platform_depopulate(struct device *parent) 565void of_platform_depopulate(struct device *parent)
566{ 566{
diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
index 46325d6394cf..8bf12e904fd2 100644
--- a/drivers/of/resolver.c
+++ b/drivers/of/resolver.c
@@ -28,20 +28,19 @@
28 * Find a node with the give full name by recursively following any of 28 * Find a node with the give full name by recursively following any of
29 * the child node links. 29 * the child node links.
30 */ 30 */
31static struct device_node *__of_find_node_by_full_name(struct device_node *node, 31static struct device_node *find_node_by_full_name(struct device_node *node,
32 const char *full_name) 32 const char *full_name)
33{ 33{
34 struct device_node *child, *found; 34 struct device_node *child, *found;
35 35
36 if (node == NULL) 36 if (!node)
37 return NULL; 37 return NULL;
38 38
39 /* check */ 39 if (!of_node_cmp(node->full_name, full_name))
40 if (of_node_cmp(node->full_name, full_name) == 0)
41 return of_node_get(node); 40 return of_node_get(node);
42 41
43 for_each_child_of_node(node, child) { 42 for_each_child_of_node(node, child) {
44 found = __of_find_node_by_full_name(child, full_name); 43 found = find_node_by_full_name(child, full_name);
45 if (found != NULL) { 44 if (found != NULL) {
46 of_node_put(child); 45 of_node_put(child);
47 return found; 46 return found;
@@ -51,16 +50,12 @@ static struct device_node *__of_find_node_by_full_name(struct device_node *node,
51 return NULL; 50 return NULL;
52} 51}
53 52
54/* 53static phandle live_tree_max_phandle(void)
55 * Find live tree's maximum phandle value.
56 */
57static phandle of_get_tree_max_phandle(void)
58{ 54{
59 struct device_node *node; 55 struct device_node *node;
60 phandle phandle; 56 phandle phandle;
61 unsigned long flags; 57 unsigned long flags;
62 58
63 /* now search recursively */
64 raw_spin_lock_irqsave(&devtree_lock, flags); 59 raw_spin_lock_irqsave(&devtree_lock, flags);
65 phandle = 0; 60 phandle = 0;
66 for_each_of_allnodes(node) { 61 for_each_of_allnodes(node) {
@@ -73,131 +68,102 @@ static phandle of_get_tree_max_phandle(void)
73 return phandle; 68 return phandle;
74} 69}
75 70
76/* 71static void adjust_overlay_phandles(struct device_node *overlay,
77 * Adjust a subtree's phandle values by a given delta.
78 * Makes sure not to just adjust the device node's phandle value,
79 * but modify the phandle properties values as well.
80 */
81static void __of_adjust_tree_phandles(struct device_node *node,
82 int phandle_delta) 72 int phandle_delta)
83{ 73{
84 struct device_node *child; 74 struct device_node *child;
85 struct property *prop; 75 struct property *prop;
86 phandle phandle; 76 phandle phandle;
87 77
88 /* first adjust the node's phandle direct value */ 78 /* adjust node's phandle in node */
89 if (node->phandle != 0 && node->phandle != OF_PHANDLE_ILLEGAL) 79 if (overlay->phandle != 0 && overlay->phandle != OF_PHANDLE_ILLEGAL)
90 node->phandle += phandle_delta; 80 overlay->phandle += phandle_delta;
91 81
92 /* now adjust phandle & linux,phandle values */ 82 /* copy adjusted phandle into *phandle properties */
93 for_each_property_of_node(node, prop) { 83 for_each_property_of_node(overlay, prop) {
94 84
95 /* only look for these two */ 85 if (of_prop_cmp(prop->name, "phandle") &&
96 if (of_prop_cmp(prop->name, "phandle") != 0 && 86 of_prop_cmp(prop->name, "linux,phandle"))
97 of_prop_cmp(prop->name, "linux,phandle") != 0)
98 continue; 87 continue;
99 88
100 /* must be big enough */
101 if (prop->length < 4) 89 if (prop->length < 4)
102 continue; 90 continue;
103 91
104 /* read phandle value */
105 phandle = be32_to_cpup(prop->value); 92 phandle = be32_to_cpup(prop->value);
106 if (phandle == OF_PHANDLE_ILLEGAL) /* unresolved */ 93 if (phandle == OF_PHANDLE_ILLEGAL)
107 continue; 94 continue;
108 95
109 /* adjust */ 96 *(uint32_t *)prop->value = cpu_to_be32(overlay->phandle);
110 *(uint32_t *)prop->value = cpu_to_be32(node->phandle);
111 } 97 }
112 98
113 /* now do the children recursively */ 99 for_each_child_of_node(overlay, child)
114 for_each_child_of_node(node, child) 100 adjust_overlay_phandles(child, phandle_delta);
115 __of_adjust_tree_phandles(child, phandle_delta);
116} 101}
117 102
118static int __of_adjust_phandle_ref(struct device_node *node, 103static int update_usages_of_a_phandle_reference(struct device_node *overlay,
119 struct property *rprop, int value) 104 struct property *prop_fixup, phandle phandle)
120{ 105{
121 phandle phandle;
122 struct device_node *refnode; 106 struct device_node *refnode;
123 struct property *sprop; 107 struct property *prop;
124 char *propval, *propcur, *propend, *nodestr, *propstr, *s; 108 char *value, *cur, *end, *node_path, *prop_name, *s;
125 int offset, propcurlen; 109 int offset, len;
126 int err = 0; 110 int err = 0;
127 111
128 /* make a copy */ 112 value = kmalloc(prop_fixup->length, GFP_KERNEL);
129 propval = kmalloc(rprop->length, GFP_KERNEL); 113 if (!value)
130 if (!propval) {
131 pr_err("%s: Could not copy value of '%s'\n",
132 __func__, rprop->name);
133 return -ENOMEM; 114 return -ENOMEM;
134 } 115 memcpy(value, prop_fixup->value, prop_fixup->length);
135 memcpy(propval, rprop->value, rprop->length);
136 116
137 propend = propval + rprop->length; 117 /* prop_fixup contains a list of tuples of path:property_name:offset */
138 for (propcur = propval; propcur < propend; propcur += propcurlen + 1) { 118 end = value + prop_fixup->length;
139 propcurlen = strlen(propcur); 119 for (cur = value; cur < end; cur += len + 1) {
120 len = strlen(cur);
140 121
141 nodestr = propcur; 122 node_path = cur;
142 s = strchr(propcur, ':'); 123 s = strchr(cur, ':');
143 if (!s) { 124 if (!s) {
144 pr_err("%s: Illegal symbol entry '%s' (1)\n",
145 __func__, propcur);
146 err = -EINVAL; 125 err = -EINVAL;
147 goto err_fail; 126 goto err_fail;
148 } 127 }
149 *s++ = '\0'; 128 *s++ = '\0';
150 129
151 propstr = s; 130 prop_name = s;
152 s = strchr(s, ':'); 131 s = strchr(s, ':');
153 if (!s) { 132 if (!s) {
154 pr_err("%s: Illegal symbol entry '%s' (2)\n",
155 __func__, (char *)rprop->value);
156 err = -EINVAL; 133 err = -EINVAL;
157 goto err_fail; 134 goto err_fail;
158 } 135 }
159
160 *s++ = '\0'; 136 *s++ = '\0';
137
161 err = kstrtoint(s, 10, &offset); 138 err = kstrtoint(s, 10, &offset);
162 if (err != 0) { 139 if (err)
163 pr_err("%s: Could get offset '%s'\n",
164 __func__, (char *)rprop->value);
165 goto err_fail; 140 goto err_fail;
166 }
167 141
168 /* look into the resolve node for the full path */ 142 refnode = find_node_by_full_name(overlay, node_path);
169 refnode = __of_find_node_by_full_name(node, nodestr); 143 if (!refnode)
170 if (!refnode) {
171 pr_warn("%s: Could not find refnode '%s'\n",
172 __func__, (char *)rprop->value);
173 continue; 144 continue;
174 }
175 145
176 /* now find the property */ 146 for_each_property_of_node(refnode, prop) {
177 for_each_property_of_node(refnode, sprop) { 147 if (!of_prop_cmp(prop->name, prop_name))
178 if (of_prop_cmp(sprop->name, propstr) == 0)
179 break; 148 break;
180 } 149 }
181 of_node_put(refnode); 150 of_node_put(refnode);
182 151
183 if (!sprop) { 152 if (!prop) {
184 pr_err("%s: Could not find property '%s'\n",
185 __func__, (char *)rprop->value);
186 err = -ENOENT; 153 err = -ENOENT;
187 goto err_fail; 154 goto err_fail;
188 } 155 }
189 156
190 phandle = value; 157 *(__be32 *)(prop->value + offset) = cpu_to_be32(phandle);
191 *(__be32 *)(sprop->value + offset) = cpu_to_be32(phandle);
192 } 158 }
193 159
194err_fail: 160err_fail:
195 kfree(propval); 161 kfree(value);
196 return err; 162 return err;
197} 163}
198 164
199/* compare nodes taking into account that 'name' strips out the @ part */ 165/* compare nodes taking into account that 'name' strips out the @ part */
200static int __of_node_name_cmp(const struct device_node *dn1, 166static int node_name_cmp(const struct device_node *dn1,
201 const struct device_node *dn2) 167 const struct device_node *dn2)
202{ 168{
203 const char *n1 = strrchr(dn1->full_name, '/') ? : "/"; 169 const char *n1 = strrchr(dn1->full_name, '/') ? : "/";
@@ -208,85 +174,77 @@ static int __of_node_name_cmp(const struct device_node *dn1,
208 174
209/* 175/*
210 * Adjust the local phandle references by the given phandle delta. 176 * Adjust the local phandle references by the given phandle delta.
211 * Assumes the existances of a __local_fixups__ node at the root. 177 *
212 * Assumes that __of_verify_tree_phandle_references has been called. 178 * Subtree @local_fixups, which is overlay node __local_fixups__,
213 * Does not take any devtree locks so make sure you call this on a tree 179 * mirrors the fragment node structure at the root of the overlay.
214 * which is at the detached state. 180 *
181 * For each property in the fragments that contains a phandle reference,
182 * @local_fixups has a property of the same name that contains a list
183 * of offsets of the phandle reference(s) within the respective property
184 * value(s). The values at these offsets will be fixed up.
215 */ 185 */
216static int __of_adjust_tree_phandle_references(struct device_node *node, 186static int adjust_local_phandle_references(struct device_node *local_fixups,
217 struct device_node *target, int phandle_delta) 187 struct device_node *overlay, int phandle_delta)
218{ 188{
219 struct device_node *child, *childtarget; 189 struct device_node *child, *overlay_child;
220 struct property *rprop, *sprop; 190 struct property *prop_fix, *prop;
221 int err, i, count; 191 int err, i, count;
222 unsigned int off; 192 unsigned int off;
223 phandle phandle; 193 phandle phandle;
224 194
225 if (node == NULL) 195 if (!local_fixups)
226 return 0; 196 return 0;
227 197
228 for_each_property_of_node(node, rprop) { 198 for_each_property_of_node(local_fixups, prop_fix) {
229 199
230 /* skip properties added automatically */ 200 /* skip properties added automatically */
231 if (of_prop_cmp(rprop->name, "name") == 0 || 201 if (!of_prop_cmp(prop_fix->name, "name") ||
232 of_prop_cmp(rprop->name, "phandle") == 0 || 202 !of_prop_cmp(prop_fix->name, "phandle") ||
233 of_prop_cmp(rprop->name, "linux,phandle") == 0) 203 !of_prop_cmp(prop_fix->name, "linux,phandle"))
234 continue; 204 continue;
235 205
236 if ((rprop->length % 4) != 0 || rprop->length == 0) { 206 if ((prop_fix->length % 4) != 0 || prop_fix->length == 0)
237 pr_err("%s: Illegal property (size) '%s' @%s\n",
238 __func__, rprop->name, node->full_name);
239 return -EINVAL; 207 return -EINVAL;
240 } 208 count = prop_fix->length / sizeof(__be32);
241 count = rprop->length / sizeof(__be32);
242 209
243 /* now find the target property */ 210 for_each_property_of_node(overlay, prop) {
244 for_each_property_of_node(target, sprop) { 211 if (!of_prop_cmp(prop->name, prop_fix->name))
245 if (of_prop_cmp(sprop->name, rprop->name) == 0)
246 break; 212 break;
247 } 213 }
248 214
249 if (sprop == NULL) { 215 if (!prop)
250 pr_err("%s: Could not find target property '%s' @%s\n",
251 __func__, rprop->name, node->full_name);
252 return -EINVAL; 216 return -EINVAL;
253 }
254 217
255 for (i = 0; i < count; i++) { 218 for (i = 0; i < count; i++) {
256 off = be32_to_cpu(((__be32 *)rprop->value)[i]); 219 off = be32_to_cpu(((__be32 *)prop_fix->value)[i]);
257 /* make sure the offset doesn't overstep (even wrap) */ 220 if ((off + 4) > prop->length)
258 if (off >= sprop->length ||
259 (off + 4) > sprop->length) {
260 pr_err("%s: Illegal property '%s' @%s\n",
261 __func__, rprop->name,
262 node->full_name);
263 return -EINVAL; 221 return -EINVAL;
264 } 222
265 223 phandle = be32_to_cpu(*(__be32 *)(prop->value + off));
266 if (phandle_delta) { 224 phandle += phandle_delta;
267 /* adjust */ 225 *(__be32 *)(prop->value + off) = cpu_to_be32(phandle);
268 phandle = be32_to_cpu(*(__be32 *)(sprop->value + off));
269 phandle += phandle_delta;
270 *(__be32 *)(sprop->value + off) = cpu_to_be32(phandle);
271 }
272 } 226 }
273 } 227 }
274 228
275 for_each_child_of_node(node, child) { 229 /*
276 230 * These nested loops recurse down two subtrees in parallel, where the
277 for_each_child_of_node(target, childtarget) 231 * node names in the two subtrees match.
278 if (__of_node_name_cmp(child, childtarget) == 0) 232 *
233 * The roots of the subtrees are the overlay's __local_fixups__ node
234 * and the overlay's root node.
235 */
236 for_each_child_of_node(local_fixups, child) {
237
238 for_each_child_of_node(overlay, overlay_child)
239 if (!node_name_cmp(child, overlay_child))
279 break; 240 break;
280 241
281 if (!childtarget) { 242 if (!overlay_child)
282 pr_err("%s: Could not find target child '%s' @%s\n",
283 __func__, child->name, node->full_name);
284 return -EINVAL; 243 return -EINVAL;
285 }
286 244
287 err = __of_adjust_tree_phandle_references(child, childtarget, 245 err = adjust_local_phandle_references(child, overlay_child,
288 phandle_delta); 246 phandle_delta);
289 if (err != 0) 247 if (err)
290 return err; 248 return err;
291 } 249 }
292 250
@@ -294,111 +252,103 @@ static int __of_adjust_tree_phandle_references(struct device_node *node,
294} 252}
295 253
296/** 254/**
297 * of_resolve - Resolve the given node against the live tree. 255 * of_resolve_phandles - Relocate and resolve overlay against live tree
298 * 256 *
299 * @resolve: Node to resolve 257 * @overlay: Pointer to devicetree overlay to relocate and resolve
300 * 258 *
301 * Perform dynamic Device Tree resolution against the live tree 259 * Modify (relocate) values of local phandles in @overlay to a range that
302 * to the given node to resolve. This depends on the live tree 260 * does not conflict with the live expanded devicetree. Update references
303 * having a __symbols__ node, and the resolve node the __fixups__ & 261 * to the local phandles in @overlay. Update (resolve) phandle references
304 * __local_fixups__ nodes (if needed). 262 * in @overlay that refer to the live expanded devicetree.
305 * The result of the operation is a resolve node that it's contents 263 *
306 * are fit to be inserted or operate upon the live tree. 264 * Phandle values in the live tree are in the range of
307 * Returns 0 on success or a negative error value on error. 265 * 1 .. live_tree_max_phandle(). The range of phandle values in the overlay
266 * also begin with at 1. Adjust the phandle values in the overlay to begin
267 * at live_tree_max_phandle() + 1. Update references to the phandles to
268 * the adjusted phandle values.
269 *
270 * The name of each property in the "__fixups__" node in the overlay matches
271 * the name of a symbol (a label) in the live tree. The values of each
272 * property in the "__fixups__" node is a list of the property values in the
273 * overlay that need to be updated to contain the phandle reference
274 * corresponding to that symbol in the live tree. Update the references in
275 * the overlay with the phandle values in the live tree.
276 *
277 * @overlay must be detached.
278 *
279 * Resolving and applying @overlay to the live expanded devicetree must be
280 * protected by a mechanism to ensure that multiple overlays are processed
281 * in a single threaded manner so that multiple overlays will not relocate
282 * phandles to overlapping ranges. The mechanism to enforce this is not
283 * yet implemented.
284 *
285 * Return: %0 on success or a negative error value on error.
308 */ 286 */
309int of_resolve_phandles(struct device_node *resolve) 287int of_resolve_phandles(struct device_node *overlay)
310{ 288{
311 struct device_node *child, *childroot, *refnode; 289 struct device_node *child, *local_fixups, *refnode;
312 struct device_node *root_sym, *resolve_sym, *resolve_fix; 290 struct device_node *tree_symbols, *overlay_fixups;
313 struct property *rprop; 291 struct property *prop;
314 const char *refpath; 292 const char *refpath;
315 phandle phandle, phandle_delta; 293 phandle phandle, phandle_delta;
316 int err; 294 int err;
317 295
318 if (!resolve) 296 tree_symbols = NULL;
319 pr_err("%s: null node\n", __func__);
320 if (resolve && !of_node_check_flag(resolve, OF_DETACHED))
321 pr_err("%s: node %s not detached\n", __func__,
322 resolve->full_name);
323 /* the resolve node must exist, and be detached */
324 if (!resolve || !of_node_check_flag(resolve, OF_DETACHED))
325 return -EINVAL;
326
327 /* first we need to adjust the phandles */
328 phandle_delta = of_get_tree_max_phandle() + 1;
329 __of_adjust_tree_phandles(resolve, phandle_delta);
330
331 /* locate the local fixups */
332 childroot = NULL;
333 for_each_child_of_node(resolve, childroot)
334 if (of_node_cmp(childroot->name, "__local_fixups__") == 0)
335 break;
336
337 if (childroot != NULL) {
338 /* resolve root is guaranteed to be the '/' */
339 err = __of_adjust_tree_phandle_references(childroot,
340 resolve, 0);
341 if (err != 0)
342 return err;
343 297
344 BUG_ON(__of_adjust_tree_phandle_references(childroot, 298 if (!overlay) {
345 resolve, phandle_delta)); 299 pr_err("null overlay\n");
300 err = -EINVAL;
301 goto out;
302 }
303 if (!of_node_check_flag(overlay, OF_DETACHED)) {
304 pr_err("overlay not detached\n");
305 err = -EINVAL;
306 goto out;
346 } 307 }
347 308
348 root_sym = NULL; 309 phandle_delta = live_tree_max_phandle() + 1;
349 resolve_sym = NULL; 310 adjust_overlay_phandles(overlay, phandle_delta);
350 resolve_fix = NULL;
351
352 /* this may fail (if no fixups are required) */
353 root_sym = of_find_node_by_path("/__symbols__");
354 311
355 /* locate the symbols & fixups nodes on resolve */ 312 for_each_child_of_node(overlay, local_fixups)
356 for_each_child_of_node(resolve, child) { 313 if (!of_node_cmp(local_fixups->name, "__local_fixups__"))
314 break;
357 315
358 if (!resolve_sym && 316 err = adjust_local_phandle_references(local_fixups, overlay, phandle_delta);
359 of_node_cmp(child->name, "__symbols__") == 0) 317 if (err)
360 resolve_sym = child; 318 goto out;
361 319
362 if (!resolve_fix && 320 overlay_fixups = NULL;
363 of_node_cmp(child->name, "__fixups__") == 0)
364 resolve_fix = child;
365 321
366 /* both found, don't bother anymore */ 322 for_each_child_of_node(overlay, child) {
367 if (resolve_sym && resolve_fix) 323 if (!of_node_cmp(child->name, "__fixups__"))
368 break; 324 overlay_fixups = child;
369 } 325 }
370 326
371 /* we do allow for the case where no fixups are needed */ 327 if (!overlay_fixups) {
372 if (!resolve_fix) { 328 err = 0;
373 err = 0; /* no error */
374 goto out; 329 goto out;
375 } 330 }
376 331
377 /* we need to fixup, but no root symbols... */ 332 tree_symbols = of_find_node_by_path("/__symbols__");
378 if (!root_sym) { 333 if (!tree_symbols) {
379 pr_err("%s: no symbols in root of device tree.\n", __func__); 334 pr_err("no symbols in root of device tree.\n");
380 err = -EINVAL; 335 err = -EINVAL;
381 goto out; 336 goto out;
382 } 337 }
383 338
384 for_each_property_of_node(resolve_fix, rprop) { 339 for_each_property_of_node(overlay_fixups, prop) {
385 340
386 /* skip properties added automatically */ 341 /* skip properties added automatically */
387 if (of_prop_cmp(rprop->name, "name") == 0) 342 if (!of_prop_cmp(prop->name, "name"))
388 continue; 343 continue;
389 344
390 err = of_property_read_string(root_sym, 345 err = of_property_read_string(tree_symbols,
391 rprop->name, &refpath); 346 prop->name, &refpath);
392 if (err != 0) { 347 if (err)
393 pr_err("%s: Could not find symbol '%s'\n",
394 __func__, rprop->name);
395 goto out; 348 goto out;
396 }
397 349
398 refnode = of_find_node_by_path(refpath); 350 refnode = of_find_node_by_path(refpath);
399 if (!refnode) { 351 if (!refnode) {
400 pr_err("%s: Could not find node by path '%s'\n",
401 __func__, refpath);
402 err = -ENOENT; 352 err = -ENOENT;
403 goto out; 353 goto out;
404 } 354 }
@@ -406,17 +356,15 @@ int of_resolve_phandles(struct device_node *resolve)
406 phandle = refnode->phandle; 356 phandle = refnode->phandle;
407 of_node_put(refnode); 357 of_node_put(refnode);
408 358
409 pr_debug("%s: %s phandle is 0x%08x\n", 359 err = update_usages_of_a_phandle_reference(overlay, prop, phandle);
410 __func__, rprop->name, phandle);
411
412 err = __of_adjust_phandle_ref(resolve, rprop, phandle);
413 if (err) 360 if (err)
414 break; 361 break;
415 } 362 }
416 363
417out: 364out:
418 /* NULL is handled by of_node_put as NOP */ 365 if (err)
419 of_node_put(root_sym); 366 pr_err("overlay phandle fixup failed: %d\n", err);
367 of_node_put(tree_symbols);
420 368
421 return err; 369 return err;
422} 370}