Blame view

drivers/of/base.c 59.4 KB
af6074fc9   Rob Herring   of: Use SPDX lice...
1
  // SPDX-License-Identifier: GPL-2.0+
97e873e5c   Stephen Rothwell   Start split out o...
2
3
4
5
6
7
8
9
10
11
12
  /*
   * Procedures for creating, accessing and interpreting the device tree.
   *
   * Paul Mackerras	August 1996.
   * Copyright (C) 1996-2005 Paul Mackerras.
   *
   *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
   *    {engebret|bergner}@us.ibm.com
   *
   *  Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
   *
e91edcf5a   Grant Likely   of: merge of_find...
13
14
   *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
   *  Grant Likely.
97e873e5c   Stephen Rothwell   Start split out o...
15
   */
606ad42aa   Rob Herring   of: use pr_fmt pr...
16
17
  
  #define pr_fmt(fmt)	"OF: " fmt
b1078c355   Michal Simek   of: base: Introdu...
18
  #include <linux/bitmap.h>
3482f2c52   Grant Likely   of: Create of_con...
19
  #include <linux/console.h>
611cad720   Shawn Guo   dt: add of_alias_...
20
  #include <linux/ctype.h>
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
21
  #include <linux/cpu.h>
97e873e5c   Stephen Rothwell   Start split out o...
22
23
  #include <linux/module.h>
  #include <linux/of.h>
5fa23530d   Sudeep Holla   of: base: add sup...
24
  #include <linux/of_device.h>
fd9fdb78a   Philipp Zabel   [media] of: move ...
25
  #include <linux/of_graph.h>
581b605a8   Stephen Rothwell   Consolidate of_fi...
26
  #include <linux/spinlock.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
27
  #include <linux/slab.h>
75b57ecf9   Grant Likely   of: Make device n...
28
  #include <linux/string.h>
a9f2f63a6   Jeremy Kerr   of: include linux...
29
  #include <linux/proc_fs.h>
581b605a8   Stephen Rothwell   Consolidate of_fi...
30

ced4eec90   Stepan Moskovchenko   of: Output device...
31
  #include "of_private.h"
611cad720   Shawn Guo   dt: add of_alias_...
32

ced4eec90   Stepan Moskovchenko   of: Output device...
33
  LIST_HEAD(aliases_lookup);
611cad720   Shawn Guo   dt: add of_alias_...
34

5063e25a3   Grant Likely   of: Eliminate of_...
35
36
  struct device_node *of_root;
  EXPORT_SYMBOL(of_root);
fc0bdae49   Grant Likely   of: move definiti...
37
  struct device_node *of_chosen;
611cad720   Shawn Guo   dt: add of_alias_...
38
  struct device_node *of_aliases;
a752ee56a   Grant Likely   tty: Update hyper...
39
  struct device_node *of_stdout;
7914a7c56   Leif Lindholm   of: support passi...
40
  static const char *of_stdout_options;
611cad720   Shawn Guo   dt: add of_alias_...
41

8a2b22a25   Grant Likely   of: Make devicetr...
42
  struct kset *of_kset;
75b57ecf9   Grant Likely   of: Make device n...
43
44
  
  /*
8a2b22a25   Grant Likely   of: Make devicetr...
45
46
47
48
   * Used to protect the of_aliases, to hold off addition of nodes to sysfs.
   * This mutex must be held whenever modifications are being made to the
   * device tree. The of_{attach,detach}_node() and
   * of_{add,remove,update}_property() helpers make sure this happens.
75b57ecf9   Grant Likely   of: Make device n...
49
   */
c05aba2bd   Pantelis Antoniou   of: rename of_ali...
50
  DEFINE_MUTEX(of_mutex);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
51

5063e25a3   Grant Likely   of: Eliminate of_...
52
  /* use when traversing tree through the child, sibling,
581b605a8   Stephen Rothwell   Consolidate of_fi...
53
54
   * or parent members of struct device_node.
   */
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
55
  DEFINE_RAW_SPINLOCK(devtree_lock);
97e873e5c   Stephen Rothwell   Start split out o...
56

f42b0e18f   Rob Herring   of: add node name...
57
58
59
60
61
62
63
64
65
66
67
68
69
  bool of_node_name_eq(const struct device_node *np, const char *name)
  {
  	const char *node_name;
  	size_t len;
  
  	if (!np)
  		return false;
  
  	node_name = kbasename(np->full_name);
  	len = strchrnul(node_name, '@') - node_name;
  
  	return (strlen(name) == len) && (strncmp(node_name, name, len) == 0);
  }
173ee3962   Rob Herring   of: Add missing e...
70
  EXPORT_SYMBOL(of_node_name_eq);
f42b0e18f   Rob Herring   of: add node name...
71
72
73
74
75
76
77
78
  
  bool of_node_name_prefix(const struct device_node *np, const char *prefix)
  {
  	if (!np)
  		return false;
  
  	return strncmp(kbasename(np->full_name), prefix, strlen(prefix)) == 0;
  }
173ee3962   Rob Herring   of: Add missing e...
79
  EXPORT_SYMBOL(of_node_name_prefix);
f42b0e18f   Rob Herring   of: add node name...
80

e8b1dee21   Rob Herring   of: Use device_ty...
81
82
83
84
85
86
  static bool __of_node_is_type(const struct device_node *np, const char *type)
  {
  	const char *match = __of_get_property(np, "device_type", NULL);
  
  	return np && match && type && !strcmp(match, type);
  }
b68ac8dc2   Robin Murphy   of: Factor out #{...
87
  int of_bus_n_addr_cells(struct device_node *np)
97e873e5c   Stephen Rothwell   Start split out o...
88
  {
8832963d8   Sergei Shtylyov   of: base: use of_...
89
  	u32 cells;
97e873e5c   Stephen Rothwell   Start split out o...
90

b68ac8dc2   Robin Murphy   of: Factor out #{...
91
  	for (; np; np = np->parent)
8832963d8   Sergei Shtylyov   of: base: use of_...
92
93
  		if (!of_property_read_u32(np, "#address-cells", &cells))
  			return cells;
b68ac8dc2   Robin Murphy   of: Factor out #{...
94

97e873e5c   Stephen Rothwell   Start split out o...
95
96
97
  	/* No #address-cells property for the root node */
  	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
  }
b68ac8dc2   Robin Murphy   of: Factor out #{...
98
99
100
101
102
103
104
105
  
  int of_n_addr_cells(struct device_node *np)
  {
  	if (np->parent)
  		np = np->parent;
  
  	return of_bus_n_addr_cells(np);
  }
97e873e5c   Stephen Rothwell   Start split out o...
106
  EXPORT_SYMBOL(of_n_addr_cells);
b68ac8dc2   Robin Murphy   of: Factor out #{...
107
  int of_bus_n_size_cells(struct device_node *np)
97e873e5c   Stephen Rothwell   Start split out o...
108
  {
8832963d8   Sergei Shtylyov   of: base: use of_...
109
  	u32 cells;
97e873e5c   Stephen Rothwell   Start split out o...
110

b68ac8dc2   Robin Murphy   of: Factor out #{...
111
  	for (; np; np = np->parent)
8832963d8   Sergei Shtylyov   of: base: use of_...
112
113
  		if (!of_property_read_u32(np, "#size-cells", &cells))
  			return cells;
b68ac8dc2   Robin Murphy   of: Factor out #{...
114

97e873e5c   Stephen Rothwell   Start split out o...
115
116
117
  	/* No #size-cells property for the root node */
  	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
  }
b68ac8dc2   Robin Murphy   of: Factor out #{...
118
119
120
121
122
123
124
125
  
  int of_n_size_cells(struct device_node *np)
  {
  	if (np->parent)
  		np = np->parent;
  
  	return of_bus_n_size_cells(np);
  }
97e873e5c   Stephen Rothwell   Start split out o...
126
  EXPORT_SYMBOL(of_n_size_cells);
0c3f061c1   Rob Herring   of: implement of_...
127
128
129
  #ifdef CONFIG_NUMA
  int __weak of_node_to_nid(struct device_node *np)
  {
c8fff7bc5   Konstantin Khlebnikov   of: return NUMA_N...
130
  	return NUMA_NO_NODE;
0c3f061c1   Rob Herring   of: implement of_...
131
132
  }
  #endif
90dc0d1ce   Rob Herring   of: Rework and si...
133
134
  #define OF_PHANDLE_CACHE_BITS	7
  #define OF_PHANDLE_CACHE_SZ	BIT(OF_PHANDLE_CACHE_BITS)
b8a9ac1a5   Frank Rowand   of: of_node_get()...
135

90dc0d1ce   Rob Herring   of: Rework and si...
136
  static struct device_node *phandle_cache[OF_PHANDLE_CACHE_SZ];
b8a9ac1a5   Frank Rowand   of: of_node_get()...
137

90dc0d1ce   Rob Herring   of: Rework and si...
138
  static u32 of_phandle_cache_hash(phandle handle)
b8a9ac1a5   Frank Rowand   of: of_node_get()...
139
  {
90dc0d1ce   Rob Herring   of: Rework and si...
140
  	return hash_32(handle, OF_PHANDLE_CACHE_BITS);
b8a9ac1a5   Frank Rowand   of: of_node_get()...
141
  }
5801169a2   Frank Rowand   of: __of_detach_n...
142
143
144
  /*
   * Caller must hold devtree_lock.
   */
90dc0d1ce   Rob Herring   of: Rework and si...
145
  void __of_phandle_cache_inv_entry(phandle handle)
5801169a2   Frank Rowand   of: __of_detach_n...
146
  {
90dc0d1ce   Rob Herring   of: Rework and si...
147
  	u32 handle_hash;
5801169a2   Frank Rowand   of: __of_detach_n...
148
149
150
151
  	struct device_node *np;
  
  	if (!handle)
  		return;
90dc0d1ce   Rob Herring   of: Rework and si...
152
  	handle_hash = of_phandle_cache_hash(handle);
5801169a2   Frank Rowand   of: __of_detach_n...
153

90dc0d1ce   Rob Herring   of: Rework and si...
154
155
156
  	np = phandle_cache[handle_hash];
  	if (np && handle == np->phandle)
  		phandle_cache[handle_hash] = NULL;
0b3ce78e9   Frank Rowand   of: cache phandle...
157
  }
194ec9368   Sudeep Holla   drivers: of/base:...
158
  void __init of_core_init(void)
75b57ecf9   Grant Likely   of: Make device n...
159
160
  {
  	struct device_node *np;
0b3ce78e9   Frank Rowand   of: cache phandle...
161

75b57ecf9   Grant Likely   of: Make device n...
162
  	/* Create the kset, and register existing nodes */
c05aba2bd   Pantelis Antoniou   of: rename of_ali...
163
  	mutex_lock(&of_mutex);
75b57ecf9   Grant Likely   of: Make device n...
164
165
  	of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
  	if (!of_kset) {
c05aba2bd   Pantelis Antoniou   of: rename of_ali...
166
  		mutex_unlock(&of_mutex);
606ad42aa   Rob Herring   of: use pr_fmt pr...
167
168
  		pr_err("failed to register existing nodes
  ");
194ec9368   Sudeep Holla   drivers: of/base:...
169
  		return;
75b57ecf9   Grant Likely   of: Make device n...
170
  	}
90dc0d1ce   Rob Herring   of: Rework and si...
171
  	for_each_of_allnodes(np) {
8a2b22a25   Grant Likely   of: Make devicetr...
172
  		__of_attach_node_sysfs(np);
90dc0d1ce   Rob Herring   of: Rework and si...
173
174
175
  		if (np->phandle && !phandle_cache[of_phandle_cache_hash(np->phandle)])
  			phandle_cache[of_phandle_cache_hash(np->phandle)] = np;
  	}
c05aba2bd   Pantelis Antoniou   of: rename of_ali...
176
  	mutex_unlock(&of_mutex);
75b57ecf9   Grant Likely   of: Make device n...
177

8357041a6   Grant Likely   of: remove /proc/...
178
  	/* Symlink in /proc as required by userspace ABI */
5063e25a3   Grant Likely   of: Eliminate of_...
179
  	if (of_root)
75b57ecf9   Grant Likely   of: Make device n...
180
  		proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
75b57ecf9   Grant Likely   of: Make device n...
181
  }
75b57ecf9   Grant Likely   of: Make device n...
182

28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
183
184
  static struct property *__of_find_property(const struct device_node *np,
  					   const char *name, int *lenp)
581b605a8   Stephen Rothwell   Consolidate of_fi...
185
186
  {
  	struct property *pp;
64e4566f6   Timur Tabi   [POWERPC] Add nul...
187
188
  	if (!np)
  		return NULL;
a3a7cab17   Sachin Kamat   of: Fix null poin...
189
  	for (pp = np->properties; pp; pp = pp->next) {
581b605a8   Stephen Rothwell   Consolidate of_fi...
190
  		if (of_prop_cmp(pp->name, name) == 0) {
a3a7cab17   Sachin Kamat   of: Fix null poin...
191
  			if (lenp)
581b605a8   Stephen Rothwell   Consolidate of_fi...
192
193
194
195
  				*lenp = pp->length;
  			break;
  		}
  	}
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
196
197
198
199
200
201
202
203
204
  
  	return pp;
  }
  
  struct property *of_find_property(const struct device_node *np,
  				  const char *name,
  				  int *lenp)
  {
  	struct property *pp;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
205
  	unsigned long flags;
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
206

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
207
  	raw_spin_lock_irqsave(&devtree_lock, flags);
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
208
  	pp = __of_find_property(np, name, lenp);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
209
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
581b605a8   Stephen Rothwell   Consolidate of_fi...
210
211
212
213
  
  	return pp;
  }
  EXPORT_SYMBOL(of_find_property);
5063e25a3   Grant Likely   of: Eliminate of_...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  struct device_node *__of_find_all_nodes(struct device_node *prev)
  {
  	struct device_node *np;
  	if (!prev) {
  		np = of_root;
  	} else if (prev->child) {
  		np = prev->child;
  	} else {
  		/* Walk back up looking for a sibling, or the end of the structure */
  		np = prev;
  		while (np->parent && !np->sibling)
  			np = np->parent;
  		np = np->sibling; /* Might be null at the end of the tree */
  	}
  	return np;
  }
e91edcf5a   Grant Likely   of: merge of_find...
230
231
232
233
234
235
236
237
238
239
240
  /**
   * of_find_all_nodes - Get next node in global list
   * @prev:	Previous node or NULL to start iteration
   *		of_node_put() will be called on it
   *
   * Returns a node pointer with refcount incremented, use
   * of_node_put() on it when done.
   */
  struct device_node *of_find_all_nodes(struct device_node *prev)
  {
  	struct device_node *np;
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
241
  	unsigned long flags;
e91edcf5a   Grant Likely   of: merge of_find...
242

d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
243
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
244
245
  	np = __of_find_all_nodes(prev);
  	of_node_get(np);
e91edcf5a   Grant Likely   of: merge of_find...
246
  	of_node_put(prev);
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
247
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
e91edcf5a   Grant Likely   of: merge of_find...
248
249
250
  	return np;
  }
  EXPORT_SYMBOL(of_find_all_nodes);
97e873e5c   Stephen Rothwell   Start split out o...
251
252
253
254
  /*
   * Find a property with a given name for a given node
   * and return the value.
   */
a25095d45   Grant Likely   of: Move dynamic ...
255
256
  const void *__of_get_property(const struct device_node *np,
  			      const char *name, int *lenp)
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
257
258
259
260
261
262
263
264
265
266
  {
  	struct property *pp = __of_find_property(np, name, lenp);
  
  	return pp ? pp->value : NULL;
  }
  
  /*
   * Find a property with a given name for a given node
   * and return the value.
   */
97e873e5c   Stephen Rothwell   Start split out o...
267
  const void *of_get_property(const struct device_node *np, const char *name,
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
268
  			    int *lenp)
97e873e5c   Stephen Rothwell   Start split out o...
269
270
271
272
273
274
  {
  	struct property *pp = of_find_property(np, name, lenp);
  
  	return pp ? pp->value : NULL;
  }
  EXPORT_SYMBOL(of_get_property);
0081cbc37   Stephen Rothwell   Consolidate of_de...
275

183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  /*
   * arch_match_cpu_phys_id - Match the given logical CPU and physical id
   *
   * @cpu: logical cpu index of a core/thread
   * @phys_id: physical identifier of a core/thread
   *
   * CPU logical to physical index mapping is architecture specific.
   * However this __weak function provides a default match of physical
   * id to logical cpu index. phys_id provided here is usually values read
   * from the device tree which must match the hardware internal registers.
   *
   * Returns true if the physical identifier and the logical cpu index
   * correspond to the same core/thread, false otherwise.
   */
  bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id)
  {
  	return (u32)phys_id == cpu;
  }
  
  /**
   * Checks if the given "prop_name" property holds the physical id of the
   * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not
   * NULL, local thread number within the core is returned in it.
   */
  static bool __of_find_n_match_cpu_property(struct device_node *cpun,
  			const char *prop_name, int cpu, unsigned int *thread)
  {
  	const __be32 *cell;
  	int ac, prop_len, tid;
  	u64 hwid;
  
  	ac = of_n_addr_cells(cpun);
  	cell = of_get_property(cpun, prop_name, &prop_len);
6487c15f1   Rob Herring   of: Support match...
309
310
  	if (!cell && !ac && arch_match_cpu_phys_id(cpu, 0))
  		return true;
f3cea45a7   Grant Likely   of: Fix iteration...
311
  	if (!cell || !ac)
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
312
  		return false;
f3cea45a7   Grant Likely   of: Fix iteration...
313
  	prop_len /= sizeof(*cell) * ac;
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
314
315
316
317
318
319
320
321
322
323
324
  	for (tid = 0; tid < prop_len; tid++) {
  		hwid = of_read_number(cell, ac);
  		if (arch_match_cpu_phys_id(cpu, hwid)) {
  			if (thread)
  				*thread = tid;
  			return true;
  		}
  		cell += ac;
  	}
  	return false;
  }
d1cb9d1af   David Miller   of: Make cpu node...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  /*
   * arch_find_n_match_cpu_physical_id - See if the given device node is
   * for the cpu corresponding to logical cpu 'cpu'.  Return true if so,
   * else false.  If 'thread' is non-NULL, the local thread number within the
   * core is returned in it.
   */
  bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,
  					      int cpu, unsigned int *thread)
  {
  	/* Check for non-standard "ibm,ppc-interrupt-server#s" property
  	 * for thread ids on PowerPC. If it doesn't exist fallback to
  	 * standard "reg" property.
  	 */
  	if (IS_ENABLED(CONFIG_PPC) &&
  	    __of_find_n_match_cpu_property(cpun,
  					   "ibm,ppc-interrupt-server#s",
  					   cpu, thread))
  		return true;
510bd068d   Masahiro Yamada   of: simplify arch...
343
  	return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread);
d1cb9d1af   David Miller   of: Make cpu node...
344
  }
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  /**
   * of_get_cpu_node - Get device node associated with the given logical CPU
   *
   * @cpu: CPU number(logical index) for which device node is required
   * @thread: if not NULL, local thread number within the physical core is
   *          returned
   *
   * The main purpose of this function is to retrieve the device node for the
   * given logical CPU index. It should be used to initialize the of_node in
   * cpu device. Once of_node in cpu device is populated, all the further
   * references can use that instead.
   *
   * CPU logical to physical index mapping is architecture specific and is built
   * before booting secondary cores. This function uses arch_match_cpu_phys_id
   * which can be overridden by architecture specific implementation.
   *
1c986e364   Masahiro Yamada   of: document refc...
361
362
   * Returns a node pointer for the logical cpu with refcount incremented, use
   * of_node_put() on it when done. Returns NULL if not found.
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
363
364
365
   */
  struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
  {
d1cb9d1af   David Miller   of: Make cpu node...
366
  	struct device_node *cpun;
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
367

651d44f96   Rob Herring   of: use for_each_...
368
  	for_each_of_cpu_node(cpun) {
d1cb9d1af   David Miller   of: Make cpu node...
369
  		if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread))
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
370
371
372
373
374
  			return cpun;
  	}
  	return NULL;
  }
  EXPORT_SYMBOL(of_get_cpu_node);
215a14cfa   Kevin Hao   of: reimplement t...
375
  /**
a0e71cd9b   Suzuki K Poulose   of: Add helper fo...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
   * of_cpu_node_to_id: Get the logical CPU number for a given device_node
   *
   * @cpu_node: Pointer to the device_node for CPU.
   *
   * Returns the logical CPU number of the given CPU device_node.
   * Returns -ENODEV if the CPU is not found.
   */
  int of_cpu_node_to_id(struct device_node *cpu_node)
  {
  	int cpu;
  	bool found = false;
  	struct device_node *np;
  
  	for_each_possible_cpu(cpu) {
  		np = of_cpu_device_node_get(cpu);
  		found = (cpu_node == np);
  		of_node_put(np);
  		if (found)
  			return cpu;
  	}
  
  	return -ENODEV;
  }
  EXPORT_SYMBOL(of_cpu_node_to_id);
  
  /**
b9f8c26af   Ulf Hansson   of: base: Add of_...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
   * of_get_cpu_state_node - Get CPU's idle state node at the given index
   *
   * @cpu_node: The device node for the CPU
   * @index: The index in the list of the idle states
   *
   * Two generic methods can be used to describe a CPU's idle states, either via
   * a flattened description through the "cpu-idle-states" binding or via the
   * hierarchical layout, using the "power-domains" and the "domain-idle-states"
   * bindings. This function check for both and returns the idle state node for
   * the requested index.
   *
   * In case an idle state node is found at @index, the refcount is incremented
   * for it, so call of_node_put() on it when done. Returns NULL if not found.
   */
  struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
  					  int index)
  {
  	struct of_phandle_args args;
  	int err;
  
  	err = of_parse_phandle_with_args(cpu_node, "power-domains",
  					"#power-domain-cells", 0, &args);
  	if (!err) {
  		struct device_node *state_node =
  			of_parse_phandle(args.np, "domain-idle-states", index);
  
  		of_node_put(args.np);
  		if (state_node)
  			return state_node;
  	}
  
  	return of_parse_phandle(cpu_node, "cpu-idle-states", index);
  }
  EXPORT_SYMBOL(of_get_cpu_state_node);
  
  /**
215a14cfa   Kevin Hao   of: reimplement t...
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
   * __of_device_is_compatible() - Check if the node matches given constraints
   * @device: pointer to node
   * @compat: required compatible string, NULL or "" for any match
   * @type: required device_type value, NULL or "" for any match
   * @name: required node name, NULL or "" for any match
   *
   * Checks if the given @compat, @type and @name strings match the
   * properties of the given @device. A constraints can be skipped by
   * passing NULL or an empty string as the constraint.
   *
   * Returns 0 for no match, and a positive integer on match. The return
   * value is a relative score with larger values indicating better
   * matches. The score is weighted for the most specific compatible value
   * to get the highest score. Matching type is next, followed by matching
   * name. Practically speaking, this results in the following priority
   * order for matches:
   *
   * 1. specific compatible && type && name
   * 2. specific compatible && type
   * 3. specific compatible && name
   * 4. specific compatible
   * 5. general compatible && type && name
   * 6. general compatible && type
   * 7. general compatible && name
   * 8. general compatible
   * 9. type && name
   * 10. type
   * 11. name
0081cbc37   Stephen Rothwell   Consolidate of_de...
466
   */
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
467
  static int __of_device_is_compatible(const struct device_node *device,
215a14cfa   Kevin Hao   of: reimplement t...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
  				     const char *compat, const char *type, const char *name)
  {
  	struct property *prop;
  	const char *cp;
  	int index = 0, score = 0;
  
  	/* Compatible match has highest priority */
  	if (compat && compat[0]) {
  		prop = __of_find_property(device, "compatible", NULL);
  		for (cp = of_prop_next_string(prop, NULL); cp;
  		     cp = of_prop_next_string(prop, cp), index++) {
  			if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
  				score = INT_MAX/2 - (index << 2);
  				break;
  			}
  		}
  		if (!score)
  			return 0;
  	}
0081cbc37   Stephen Rothwell   Consolidate of_de...
487

215a14cfa   Kevin Hao   of: reimplement t...
488
489
  	/* Matching type is better than matching name */
  	if (type && type[0]) {
e8b1dee21   Rob Herring   of: Use device_ty...
490
  		if (!__of_node_is_type(device, type))
215a14cfa   Kevin Hao   of: reimplement t...
491
492
  			return 0;
  		score += 2;
0081cbc37   Stephen Rothwell   Consolidate of_de...
493
  	}
215a14cfa   Kevin Hao   of: reimplement t...
494
495
  	/* Matching name is a bit better than not */
  	if (name && name[0]) {
b3e46d1a0   Rob Herring   of: Use of_node_n...
496
  		if (!of_node_name_eq(device, name))
215a14cfa   Kevin Hao   of: reimplement t...
497
498
499
500
501
  			return 0;
  		score++;
  	}
  
  	return score;
0081cbc37   Stephen Rothwell   Consolidate of_de...
502
  }
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
503
504
505
506
507
508
509
  
  /** Checks if the given "compat" string matches one of the strings in
   * the device's "compatible" property
   */
  int of_device_is_compatible(const struct device_node *device,
  		const char *compat)
  {
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
510
  	unsigned long flags;
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
511
  	int res;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
512
  	raw_spin_lock_irqsave(&devtree_lock, flags);
215a14cfa   Kevin Hao   of: reimplement t...
513
  	res = __of_device_is_compatible(device, compat, NULL, NULL);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
514
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
515
516
  	return res;
  }
0081cbc37   Stephen Rothwell   Consolidate of_de...
517
  EXPORT_SYMBOL(of_device_is_compatible);
e679c5f44   Stephen Rothwell   Consolidate of_ge...
518

b9c13fe32   Benjamin Herrenschmidt   dt: Add of_device...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
  /** Checks if the device is compatible with any of the entries in
   *  a NULL terminated array of strings. Returns the best match
   *  score or 0.
   */
  int of_device_compatible_match(struct device_node *device,
  			       const char *const *compat)
  {
  	unsigned int tmp, score = 0;
  
  	if (!compat)
  		return 0;
  
  	while (*compat) {
  		tmp = of_device_is_compatible(device, *compat);
  		if (tmp > score)
  			score = tmp;
  		compat++;
  	}
  
  	return score;
  }
e679c5f44   Stephen Rothwell   Consolidate of_ge...
540
  /**
71a157e8e   Grant Likely   of: add 'of_' pre...
541
   * of_machine_is_compatible - Test root of device tree for a given compatible value
1f43cfb94   Grant Likely   of: merge machine...
542
543
   * @compat: compatible string to look for in root node's compatible property.
   *
25c7a1de6   Kevin Cernekee   of: Fix of_device...
544
   * Returns a positive integer if the root node has the given value in its
1f43cfb94   Grant Likely   of: merge machine...
545
546
   * compatible property.
   */
71a157e8e   Grant Likely   of: add 'of_' pre...
547
  int of_machine_is_compatible(const char *compat)
1f43cfb94   Grant Likely   of: merge machine...
548
549
550
551
552
553
554
555
556
557
558
  {
  	struct device_node *root;
  	int rc = 0;
  
  	root = of_find_node_by_path("/");
  	if (root) {
  		rc = of_device_is_compatible(root, compat);
  		of_node_put(root);
  	}
  	return rc;
  }
71a157e8e   Grant Likely   of: add 'of_' pre...
559
  EXPORT_SYMBOL(of_machine_is_compatible);
1f43cfb94   Grant Likely   of: merge machine...
560
561
  
  /**
c31a0c052   Stephen Warren   of: fix recursive...
562
   *  __of_device_is_available - check if a device is available for use
834d97d45   Josh Boyer   [POWERPC] Add of_...
563
   *
c31a0c052   Stephen Warren   of: fix recursive...
564
   *  @device: Node to check for availability, with locks already held
834d97d45   Josh Boyer   [POWERPC] Add of_...
565
   *
53a4ab96c   Kevin Cernekee   of: Change of_dev...
566
567
   *  Returns true if the status property is absent or set to "okay" or "ok",
   *  false otherwise
834d97d45   Josh Boyer   [POWERPC] Add of_...
568
   */
53a4ab96c   Kevin Cernekee   of: Change of_dev...
569
  static bool __of_device_is_available(const struct device_node *device)
834d97d45   Josh Boyer   [POWERPC] Add of_...
570
571
572
  {
  	const char *status;
  	int statlen;
42ccd781b   Xiubo Li   of: Fix __of_devi...
573
  	if (!device)
53a4ab96c   Kevin Cernekee   of: Change of_dev...
574
  		return false;
42ccd781b   Xiubo Li   of: Fix __of_devi...
575

c31a0c052   Stephen Warren   of: fix recursive...
576
  	status = __of_get_property(device, "status", &statlen);
834d97d45   Josh Boyer   [POWERPC] Add of_...
577
  	if (status == NULL)
53a4ab96c   Kevin Cernekee   of: Change of_dev...
578
  		return true;
834d97d45   Josh Boyer   [POWERPC] Add of_...
579
580
581
  
  	if (statlen > 0) {
  		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
53a4ab96c   Kevin Cernekee   of: Change of_dev...
582
  			return true;
834d97d45   Josh Boyer   [POWERPC] Add of_...
583
  	}
53a4ab96c   Kevin Cernekee   of: Change of_dev...
584
  	return false;
834d97d45   Josh Boyer   [POWERPC] Add of_...
585
  }
c31a0c052   Stephen Warren   of: fix recursive...
586
587
588
589
590
591
  
  /**
   *  of_device_is_available - check if a device is available for use
   *
   *  @device: Node to check for availability
   *
53a4ab96c   Kevin Cernekee   of: Change of_dev...
592
593
   *  Returns true if the status property is absent or set to "okay" or "ok",
   *  false otherwise
c31a0c052   Stephen Warren   of: fix recursive...
594
   */
53a4ab96c   Kevin Cernekee   of: Change of_dev...
595
  bool of_device_is_available(const struct device_node *device)
c31a0c052   Stephen Warren   of: fix recursive...
596
597
  {
  	unsigned long flags;
53a4ab96c   Kevin Cernekee   of: Change of_dev...
598
  	bool res;
c31a0c052   Stephen Warren   of: fix recursive...
599
600
601
602
603
604
605
  
  	raw_spin_lock_irqsave(&devtree_lock, flags);
  	res = __of_device_is_available(device);
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
  	return res;
  
  }
834d97d45   Josh Boyer   [POWERPC] Add of_...
606
607
608
  EXPORT_SYMBOL(of_device_is_available);
  
  /**
37786c7fe   Kevin Cernekee   of: Add helper fu...
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
   *  of_device_is_big_endian - check if a device has BE registers
   *
   *  @device: Node to check for endianness
   *
   *  Returns true if the device has a "big-endian" property, or if the kernel
   *  was compiled for BE *and* the device has a "native-endian" property.
   *  Returns false otherwise.
   *
   *  Callers would nominally use ioread32be/iowrite32be if
   *  of_device_is_big_endian() == true, or readl/writel otherwise.
   */
  bool of_device_is_big_endian(const struct device_node *device)
  {
  	if (of_property_read_bool(device, "big-endian"))
  		return true;
  	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
  	    of_property_read_bool(device, "native-endian"))
  		return true;
  	return false;
  }
  EXPORT_SYMBOL(of_device_is_big_endian);
  
  /**
e679c5f44   Stephen Rothwell   Consolidate of_ge...
632
633
634
635
636
637
638
639
640
   *	of_get_parent - Get a node's parent if any
   *	@node:	Node to get parent
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.
   */
  struct device_node *of_get_parent(const struct device_node *node)
  {
  	struct device_node *np;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
641
  	unsigned long flags;
e679c5f44   Stephen Rothwell   Consolidate of_ge...
642
643
644
  
  	if (!node)
  		return NULL;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
645
  	raw_spin_lock_irqsave(&devtree_lock, flags);
e679c5f44   Stephen Rothwell   Consolidate of_ge...
646
  	np = of_node_get(node->parent);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
647
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
e679c5f44   Stephen Rothwell   Consolidate of_ge...
648
649
650
  	return np;
  }
  EXPORT_SYMBOL(of_get_parent);
d1cd355a5   Stephen Rothwell   Consolidate of_ge...
651
652
  
  /**
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
653
654
655
   *	of_get_next_parent - Iterate to a node's parent
   *	@node:	Node to get parent of
   *
c0e848d8b   Geert Uytterhoeven   of: Remove spaces...
656
657
658
   *	This is like of_get_parent() except that it drops the
   *	refcount on the passed node, making it suitable for iterating
   *	through a node's parents.
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
659
660
661
662
663
664
665
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.
   */
  struct device_node *of_get_next_parent(struct device_node *node)
  {
  	struct device_node *parent;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
666
  	unsigned long flags;
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
667
668
669
  
  	if (!node)
  		return NULL;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
670
  	raw_spin_lock_irqsave(&devtree_lock, flags);
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
671
672
  	parent = of_node_get(node->parent);
  	of_node_put(node);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
673
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
674
675
  	return parent;
  }
6695be686   Guennadi Liakhovetski   [media] DT: expor...
676
  EXPORT_SYMBOL(of_get_next_parent);
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
677

0d0e02d60   Grant Likely   of: Create unlock...
678
679
680
681
  static struct device_node *__of_get_next_child(const struct device_node *node,
  						struct device_node *prev)
  {
  	struct device_node *next;
43cb43678   Florian Fainelli   of: handle NULL n...
682
683
  	if (!node)
  		return NULL;
0d0e02d60   Grant Likely   of: Create unlock...
684
685
686
687
688
689
690
691
692
693
  	next = prev ? prev->sibling : node->child;
  	for (; next; next = next->sibling)
  		if (of_node_get(next))
  			break;
  	of_node_put(prev);
  	return next;
  }
  #define __for_each_child_of_node(parent, child) \
  	for (child = __of_get_next_child(parent, NULL); child != NULL; \
  	     child = __of_get_next_child(parent, child))
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
694
  /**
d1cd355a5   Stephen Rothwell   Consolidate of_ge...
695
696
697
698
   *	of_get_next_child - Iterate a node childs
   *	@node:	parent node
   *	@prev:	previous child of the parent node, or NULL to get first
   *
648082735   Baruch Siach   of: base: improve...
699
700
701
   *	Returns a node pointer with refcount incremented, use of_node_put() on
   *	it when done. Returns NULL when prev is the last child. Decrements the
   *	refcount of prev.
d1cd355a5   Stephen Rothwell   Consolidate of_ge...
702
703
704
705
706
   */
  struct device_node *of_get_next_child(const struct device_node *node,
  	struct device_node *prev)
  {
  	struct device_node *next;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
707
  	unsigned long flags;
d1cd355a5   Stephen Rothwell   Consolidate of_ge...
708

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
709
  	raw_spin_lock_irqsave(&devtree_lock, flags);
0d0e02d60   Grant Likely   of: Create unlock...
710
  	next = __of_get_next_child(node, prev);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
711
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
d1cd355a5   Stephen Rothwell   Consolidate of_ge...
712
713
714
  	return next;
  }
  EXPORT_SYMBOL(of_get_next_child);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
715
716
  
  /**
3296193d1   Timur Tabi   dt: introduce for...
717
718
719
720
721
722
723
724
725
726
727
   *	of_get_next_available_child - Find the next available child node
   *	@node:	parent node
   *	@prev:	previous child of the parent node, or NULL to get first
   *
   *      This function is like of_get_next_child(), except that it
   *      automatically skips any disabled nodes (i.e. status = "disabled").
   */
  struct device_node *of_get_next_available_child(const struct device_node *node,
  	struct device_node *prev)
  {
  	struct device_node *next;
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
728
  	unsigned long flags;
3296193d1   Timur Tabi   dt: introduce for...
729

43cb43678   Florian Fainelli   of: handle NULL n...
730
731
  	if (!node)
  		return NULL;
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
732
  	raw_spin_lock_irqsave(&devtree_lock, flags);
3296193d1   Timur Tabi   dt: introduce for...
733
734
  	next = prev ? prev->sibling : node->child;
  	for (; next; next = next->sibling) {
c31a0c052   Stephen Warren   of: fix recursive...
735
  		if (!__of_device_is_available(next))
3296193d1   Timur Tabi   dt: introduce for...
736
737
738
739
740
  			continue;
  		if (of_node_get(next))
  			break;
  	}
  	of_node_put(prev);
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
741
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
3296193d1   Timur Tabi   dt: introduce for...
742
743
744
745
746
  	return next;
  }
  EXPORT_SYMBOL(of_get_next_available_child);
  
  /**
f1f207e43   Rob Herring   of: Add cpu node ...
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
   *	of_get_next_cpu_node - Iterate on cpu nodes
   *	@prev:	previous child of the /cpus node, or NULL to get first
   *
   *	Returns a cpu node pointer with refcount incremented, use of_node_put()
   *	on it when done. Returns NULL when prev is the last child. Decrements
   *	the refcount of prev.
   */
  struct device_node *of_get_next_cpu_node(struct device_node *prev)
  {
  	struct device_node *next = NULL;
  	unsigned long flags;
  	struct device_node *node;
  
  	if (!prev)
  		node = of_find_node_by_path("/cpus");
  
  	raw_spin_lock_irqsave(&devtree_lock, flags);
  	if (prev)
  		next = prev->sibling;
  	else if (node) {
  		next = node->child;
  		of_node_put(node);
  	}
  	for (; next; next = next->sibling) {
  		if (!(of_node_name_eq(next, "cpu") ||
e8b1dee21   Rob Herring   of: Use device_ty...
772
  		      __of_node_is_type(next, "cpu")))
f1f207e43   Rob Herring   of: Add cpu node ...
773
  			continue;
f1f207e43   Rob Herring   of: Add cpu node ...
774
775
776
777
778
779
780
781
782
783
  		if (of_node_get(next))
  			break;
  	}
  	of_node_put(prev);
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
  	return next;
  }
  EXPORT_SYMBOL(of_get_next_cpu_node);
  
  /**
36156f924   Johan Hovold   of: add helper to...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
   * of_get_compatible_child - Find compatible child node
   * @parent:	parent node
   * @compatible:	compatible string
   *
   * Lookup child node whose compatible property contains the given compatible
   * string.
   *
   * Returns a node pointer with refcount incremented, use of_node_put() on it
   * when done; or NULL if not found.
   */
  struct device_node *of_get_compatible_child(const struct device_node *parent,
  				const char *compatible)
  {
  	struct device_node *child;
  
  	for_each_child_of_node(parent, child) {
  		if (of_device_is_compatible(child, compatible))
  			break;
  	}
  
  	return child;
  }
  EXPORT_SYMBOL(of_get_compatible_child);
  
  /**
9c19761a7   Srinivas Kandagatla   dt: introduce of_...
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
   *	of_get_child_by_name - Find the child node by name for a given parent
   *	@node:	parent node
   *	@name:	child name to look for.
   *
   *      This function looks for child node for given matching name
   *
   *	Returns a node pointer if found, with refcount incremented, use
   *	of_node_put() on it when done.
   *	Returns NULL if node is not found.
   */
  struct device_node *of_get_child_by_name(const struct device_node *node,
  				const char *name)
  {
  	struct device_node *child;
  
  	for_each_child_of_node(node, child)
b3e46d1a0   Rob Herring   of: Use of_node_n...
825
  		if (of_node_name_eq(child, name))
9c19761a7   Srinivas Kandagatla   dt: introduce of_...
826
827
828
829
  			break;
  	return child;
  }
  EXPORT_SYMBOL(of_get_child_by_name);
e0a58f3e0   Frank Rowand   of: overlay: remo...
830
  struct device_node *__of_find_node_by_path(struct device_node *parent,
c22e650e6   Grant Likely   of: Make of_find_...
831
832
833
  						const char *path)
  {
  	struct device_node *child;
106937e8c   Leif Lindholm   of: fix handling ...
834
  	int len;
c22e650e6   Grant Likely   of: Make of_find_...
835

721a09e95   Brian Norris   of: handle both '...
836
  	len = strcspn(path, "/:");
c22e650e6   Grant Likely   of: Make of_find_...
837
838
839
840
  	if (!len)
  		return NULL;
  
  	__for_each_child_of_node(parent, child) {
95e6b1fa3   Rob Herring   of: use kbasename...
841
  		const char *name = kbasename(child->full_name);
c22e650e6   Grant Likely   of: Make of_find_...
842
843
844
845
846
  		if (strncmp(path, name, len) == 0 && (strlen(name) == len))
  			return child;
  	}
  	return NULL;
  }
27497e11b   Rob Herring   of: find_node_by_...
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
  struct device_node *__of_find_node_by_full_path(struct device_node *node,
  						const char *path)
  {
  	const char *separator = strchr(path, ':');
  
  	while (node && *path == '/') {
  		struct device_node *tmp = node;
  
  		path++; /* Increment past '/' delimiter */
  		node = __of_find_node_by_path(node, path);
  		of_node_put(tmp);
  		path = strchrnul(path, '/');
  		if (separator && separator < path)
  			break;
  	}
  	return node;
  }
9c19761a7   Srinivas Kandagatla   dt: introduce of_...
864
  /**
75c28c09a   Leif Lindholm   of: add optional ...
865
   *	of_find_node_opts_by_path - Find a node matching a full OF path
c22e650e6   Grant Likely   of: Make of_find_...
866
867
868
869
   *	@path: Either the full path to match, or if the path does not
   *	       start with '/', the name of a property of the /aliases
   *	       node (an alias).  In the case of an alias, the node
   *	       matching the alias' value will be returned.
75c28c09a   Leif Lindholm   of: add optional ...
870
871
872
   *	@opts: Address of a pointer into which to store the start of
   *	       an options string appended to the end of the path with
   *	       a ':' separator.
c22e650e6   Grant Likely   of: Make of_find_...
873
874
875
876
877
   *
   *	Valid paths:
   *		/foo/bar	Full path
   *		foo		Valid alias
   *		foo/bar		Valid alias + relative path
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
878
879
880
881
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.
   */
75c28c09a   Leif Lindholm   of: add optional ...
882
  struct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
883
  {
c22e650e6   Grant Likely   of: Make of_find_...
884
885
  	struct device_node *np = NULL;
  	struct property *pp;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
886
  	unsigned long flags;
75c28c09a   Leif Lindholm   of: add optional ...
887
888
889
890
  	const char *separator = strchr(path, ':');
  
  	if (opts)
  		*opts = separator ? separator + 1 : NULL;
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
891

c22e650e6   Grant Likely   of: Make of_find_...
892
  	if (strcmp(path, "/") == 0)
5063e25a3   Grant Likely   of: Eliminate of_...
893
  		return of_node_get(of_root);
c22e650e6   Grant Likely   of: Make of_find_...
894
895
896
  
  	/* The path could begin with an alias */
  	if (*path != '/') {
106937e8c   Leif Lindholm   of: fix handling ...
897
898
899
900
901
902
  		int len;
  		const char *p = separator;
  
  		if (!p)
  			p = strchrnul(path, '/');
  		len = p - path;
c22e650e6   Grant Likely   of: Make of_find_...
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
  
  		/* of_aliases must not be NULL */
  		if (!of_aliases)
  			return NULL;
  
  		for_each_property_of_node(of_aliases, pp) {
  			if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {
  				np = of_find_node_by_path(pp->value);
  				break;
  			}
  		}
  		if (!np)
  			return NULL;
  		path = p;
  	}
  
  	/* Step down the tree matching path components */
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
920
  	raw_spin_lock_irqsave(&devtree_lock, flags);
c22e650e6   Grant Likely   of: Make of_find_...
921
  	if (!np)
5063e25a3   Grant Likely   of: Eliminate of_...
922
  		np = of_node_get(of_root);
27497e11b   Rob Herring   of: find_node_by_...
923
  	np = __of_find_node_by_full_path(np, path);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
924
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
925
926
  	return np;
  }
75c28c09a   Leif Lindholm   of: add optional ...
927
  EXPORT_SYMBOL(of_find_node_opts_by_path);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
928
929
930
  
  /**
   *	of_find_node_by_name - Find a node by its "name" property
02a876b50   Stephen Boyd   of: Document exac...
931
   *	@from:	The node to start searching from or NULL; the node
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
932
   *		you pass will not be searched, only the next one
02a876b50   Stephen Boyd   of: Document exac...
933
934
   *		will. Typically, you pass what the previous call
   *		returned. of_node_put() will be called on @from.
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
935
936
937
938
939
940
941
942
943
   *	@name:	The name string to match against
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.
   */
  struct device_node *of_find_node_by_name(struct device_node *from,
  	const char *name)
  {
  	struct device_node *np;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
944
  	unsigned long flags;
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
945

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
946
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
947
  	for_each_of_allnodes_from(from, np)
b3e46d1a0   Rob Herring   of: Use of_node_n...
948
  		if (of_node_name_eq(np, name) && of_node_get(np))
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
949
950
  			break;
  	of_node_put(from);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
951
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
  	return np;
  }
  EXPORT_SYMBOL(of_find_node_by_name);
  
  /**
   *	of_find_node_by_type - Find a node by its "device_type" property
   *	@from:	The node to start searching from, or NULL to start searching
   *		the entire device tree. The node you pass will not be
   *		searched, only the next one will; typically, you pass
   *		what the previous call returned. of_node_put() will be
   *		called on from for you.
   *	@type:	The type string to match against
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.
   */
  struct device_node *of_find_node_by_type(struct device_node *from,
  	const char *type)
  {
  	struct device_node *np;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
972
  	unsigned long flags;
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
973

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
974
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
975
  	for_each_of_allnodes_from(from, np)
e8b1dee21   Rob Herring   of: Use device_ty...
976
  		if (__of_node_is_type(np, type) && of_node_get(np))
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
977
978
  			break;
  	of_node_put(from);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
979
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
  	return np;
  }
  EXPORT_SYMBOL(of_find_node_by_type);
  
  /**
   *	of_find_compatible_node - Find a node based on type and one of the
   *                                tokens in its "compatible" property
   *	@from:		The node to start searching from or NULL, the node
   *			you pass will not be searched, only the next one
   *			will; typically, you pass what the previous call
   *			returned. of_node_put() will be called on it
   *	@type:		The type string to match "device_type" or NULL to ignore
   *	@compatible:	The string to match to one of the tokens in the device
   *			"compatible" list.
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.
   */
  struct device_node *of_find_compatible_node(struct device_node *from,
  	const char *type, const char *compatible)
  {
  	struct device_node *np;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1002
  	unsigned long flags;
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
1003

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1004
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
1005
  	for_each_of_allnodes_from(from, np)
215a14cfa   Kevin Hao   of: reimplement t...
1006
  		if (__of_device_is_compatible(np, compatible, type, NULL) &&
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1007
  		    of_node_get(np))
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
1008
  			break;
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
1009
  	of_node_put(from);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1010
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
1011
1012
1013
  	return np;
  }
  EXPORT_SYMBOL(of_find_compatible_node);
283029d16   Grant Likely   [POWERPC] Add of_...
1014
1015
  
  /**
1e291b14c   Michael Ellerman   of: Add helpers f...
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
   *	of_find_node_with_property - Find a node which has a property with
   *                                   the given name.
   *	@from:		The node to start searching from or NULL, the node
   *			you pass will not be searched, only the next one
   *			will; typically, you pass what the previous call
   *			returned. of_node_put() will be called on it
   *	@prop_name:	The name of the property to look for.
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.
   */
  struct device_node *of_find_node_with_property(struct device_node *from,
  	const char *prop_name)
  {
  	struct device_node *np;
  	struct property *pp;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1032
  	unsigned long flags;
1e291b14c   Michael Ellerman   of: Add helpers f...
1033

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1034
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
1035
  	for_each_of_allnodes_from(from, np) {
a3a7cab17   Sachin Kamat   of: Fix null poin...
1036
  		for (pp = np->properties; pp; pp = pp->next) {
1e291b14c   Michael Ellerman   of: Add helpers f...
1037
1038
1039
1040
1041
1042
1043
1044
  			if (of_prop_cmp(pp->name, prop_name) == 0) {
  				of_node_get(np);
  				goto out;
  			}
  		}
  	}
  out:
  	of_node_put(from);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1045
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1e291b14c   Michael Ellerman   of: Add helpers f...
1046
1047
1048
  	return np;
  }
  EXPORT_SYMBOL(of_find_node_with_property);
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1049
1050
1051
  static
  const struct of_device_id *__of_match_node(const struct of_device_id *matches,
  					   const struct device_node *node)
283029d16   Grant Likely   [POWERPC] Add of_...
1052
  {
215a14cfa   Kevin Hao   of: reimplement t...
1053
1054
  	const struct of_device_id *best_match = NULL;
  	int score, best_score = 0;
a52f07ecd   Grant Likely   dt: protect again...
1055
1056
  	if (!matches)
  		return NULL;
215a14cfa   Kevin Hao   of: reimplement t...
1057
1058
1059
1060
1061
1062
1063
  	for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
  		score = __of_device_is_compatible(node, matches->compatible,
  						  matches->type, matches->name);
  		if (score > best_score) {
  			best_match = matches;
  			best_score = score;
  		}
4e8ca6ee3   Kevin Hao   Revert "OF: base:...
1064
  	}
215a14cfa   Kevin Hao   of: reimplement t...
1065
1066
  
  	return best_match;
283029d16   Grant Likely   [POWERPC] Add of_...
1067
  }
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1068
1069
  
  /**
c50949d32   Geert Uytterhoeven   of: Grammar s/an/a/
1070
   * of_match_node - Tell if a device_node has a matching of_match structure
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1071
1072
1073
   *	@matches:	array of of device match structures to search in
   *	@node:		the of device structure to match against
   *
71c5498ee   Kevin Hao   Revert "of: searc...
1074
   *	Low level utility function used by device matching.
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1075
1076
1077
1078
1079
   */
  const struct of_device_id *of_match_node(const struct of_device_id *matches,
  					 const struct device_node *node)
  {
  	const struct of_device_id *match;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1080
  	unsigned long flags;
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1081

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1082
  	raw_spin_lock_irqsave(&devtree_lock, flags);
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1083
  	match = __of_match_node(matches, node);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1084
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1085
1086
  	return match;
  }
283029d16   Grant Likely   [POWERPC] Add of_...
1087
1088
1089
  EXPORT_SYMBOL(of_match_node);
  
  /**
50c8af4cf   Stephen Warren   of: introduce for...
1090
1091
   *	of_find_matching_node_and_match - Find a node based on an of_device_id
   *					  match table.
283029d16   Grant Likely   [POWERPC] Add of_...
1092
1093
1094
1095
1096
   *	@from:		The node to start searching from or NULL, the node
   *			you pass will not be searched, only the next one
   *			will; typically, you pass what the previous call
   *			returned. of_node_put() will be called on it
   *	@matches:	array of of device match structures to search in
50c8af4cf   Stephen Warren   of: introduce for...
1097
   *	@match		Updated to point at the matches entry which matched
283029d16   Grant Likely   [POWERPC] Add of_...
1098
1099
1100
1101
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.
   */
50c8af4cf   Stephen Warren   of: introduce for...
1102
1103
1104
  struct device_node *of_find_matching_node_and_match(struct device_node *from,
  					const struct of_device_id *matches,
  					const struct of_device_id **match)
283029d16   Grant Likely   [POWERPC] Add of_...
1105
1106
  {
  	struct device_node *np;
dc71bcf1b   Thomas Abraham   of: fix incorrect...
1107
  	const struct of_device_id *m;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1108
  	unsigned long flags;
283029d16   Grant Likely   [POWERPC] Add of_...
1109

50c8af4cf   Stephen Warren   of: introduce for...
1110
1111
  	if (match)
  		*match = NULL;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1112
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
1113
  	for_each_of_allnodes_from(from, np) {
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1114
  		m = __of_match_node(matches, np);
dc71bcf1b   Thomas Abraham   of: fix incorrect...
1115
  		if (m && of_node_get(np)) {
50c8af4cf   Stephen Warren   of: introduce for...
1116
  			if (match)
dc71bcf1b   Thomas Abraham   of: fix incorrect...
1117
  				*match = m;
283029d16   Grant Likely   [POWERPC] Add of_...
1118
  			break;
50c8af4cf   Stephen Warren   of: introduce for...
1119
  		}
283029d16   Grant Likely   [POWERPC] Add of_...
1120
1121
  	}
  	of_node_put(from);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1122
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
283029d16   Grant Likely   [POWERPC] Add of_...
1123
1124
  	return np;
  }
80c2022e5   Grant Likely   of: Fix export of...
1125
  EXPORT_SYMBOL(of_find_matching_node_and_match);
3f07af494   Grant Likely   of: adapt of_find...
1126
1127
  
  /**
3f07af494   Grant Likely   of: adapt of_find...
1128
1129
1130
1131
1132
   * of_modalias_node - Lookup appropriate modalias for a device node
   * @node:	pointer to a device tree node
   * @modalias:	Pointer to buffer that modalias value will be copied into
   * @len:	Length of modalias value
   *
2ffe8c5f3   Grant Likely   of: refactor of_m...
1133
1134
1135
1136
   * Based on the value of the compatible property, this routine will attempt
   * to choose an appropriate modalias value for a particular device tree node.
   * It does this by stripping the manufacturer prefix (as delimited by a ',')
   * from the first entry in the compatible list property.
3f07af494   Grant Likely   of: adapt of_find...
1137
   *
2ffe8c5f3   Grant Likely   of: refactor of_m...
1138
   * This routine returns 0 on success, <0 on failure.
3f07af494   Grant Likely   of: adapt of_find...
1139
1140
1141
   */
  int of_modalias_node(struct device_node *node, char *modalias, int len)
  {
2ffe8c5f3   Grant Likely   of: refactor of_m...
1142
1143
  	const char *compatible, *p;
  	int cplen;
3f07af494   Grant Likely   of: adapt of_find...
1144
1145
  
  	compatible = of_get_property(node, "compatible", &cplen);
2ffe8c5f3   Grant Likely   of: refactor of_m...
1146
  	if (!compatible || strlen(compatible) > cplen)
3f07af494   Grant Likely   of: adapt of_find...
1147
  		return -ENODEV;
3f07af494   Grant Likely   of: adapt of_find...
1148
  	p = strchr(compatible, ',');
2ffe8c5f3   Grant Likely   of: refactor of_m...
1149
  	strlcpy(modalias, p ? p + 1 : compatible, len);
3f07af494   Grant Likely   of: adapt of_find...
1150
1151
1152
  	return 0;
  }
  EXPORT_SYMBOL_GPL(of_modalias_node);
64b60e096   Anton Vorontsov   of: Add new helpe...
1153
  /**
89751a7cb   Jeremy Kerr   of: merge of_find...
1154
1155
1156
1157
1158
1159
1160
1161
   * of_find_node_by_phandle - Find a node given a phandle
   * @handle:	phandle of the node to find
   *
   * Returns a node pointer with refcount incremented, use
   * of_node_put() on it when done.
   */
  struct device_node *of_find_node_by_phandle(phandle handle)
  {
0b3ce78e9   Frank Rowand   of: cache phandle...
1162
  	struct device_node *np = NULL;
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
1163
  	unsigned long flags;
90dc0d1ce   Rob Herring   of: Rework and si...
1164
  	u32 handle_hash;
89751a7cb   Jeremy Kerr   of: merge of_find...
1165

fc59b4479   Grant Likely   of: Don't try to ...
1166
1167
  	if (!handle)
  		return NULL;
90dc0d1ce   Rob Herring   of: Rework and si...
1168
  	handle_hash = of_phandle_cache_hash(handle);
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
1169
  	raw_spin_lock_irqsave(&devtree_lock, flags);
0b3ce78e9   Frank Rowand   of: cache phandle...
1170

90dc0d1ce   Rob Herring   of: Rework and si...
1171
1172
1173
  	if (phandle_cache[handle_hash] &&
  	    handle == phandle_cache[handle_hash]->phandle)
  		np = phandle_cache[handle_hash];
0b3ce78e9   Frank Rowand   of: cache phandle...
1174
1175
1176
  
  	if (!np) {
  		for_each_of_allnodes(np)
5801169a2   Frank Rowand   of: __of_detach_n...
1177
1178
  			if (np->phandle == handle &&
  			    !of_node_check_flag(np, OF_DETACHED)) {
90dc0d1ce   Rob Herring   of: Rework and si...
1179
  				phandle_cache[handle_hash] = np;
0b3ce78e9   Frank Rowand   of: cache phandle...
1180
1181
1182
  				break;
  			}
  	}
89751a7cb   Jeremy Kerr   of: merge of_find...
1183
  	of_node_get(np);
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
1184
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
89751a7cb   Jeremy Kerr   of: merge of_find...
1185
1186
1187
  	return np;
  }
  EXPORT_SYMBOL(of_find_node_by_phandle);
624cfca53   Grant Likely   of: Add helper fo...
1188
1189
1190
  void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
  {
  	int i;
0d638a07d   Rob Herring   of: Convert to us...
1191
  	printk("%s %pOF", msg, args->np);
4aa663444   Marcin Nowakowski   drivers/of: fix m...
1192
1193
1194
1195
1196
1197
1198
  	for (i = 0; i < args->args_count; i++) {
  		const char delim = i ? ',' : ':';
  
  		pr_cont("%c%08x", delim, args->args[i]);
  	}
  	pr_cont("
  ");
624cfca53   Grant Likely   of: Add helper fo...
1199
  }
74e1fbb13   Joerg Roedel   of: Introduce str...
1200
1201
1202
1203
1204
  int of_phandle_iterator_init(struct of_phandle_iterator *it,
  		const struct device_node *np,
  		const char *list_name,
  		const char *cells_name,
  		int cell_count)
64b60e096   Anton Vorontsov   of: Add new helpe...
1205
  {
74e1fbb13   Joerg Roedel   of: Introduce str...
1206
1207
1208
1209
  	const __be32 *list;
  	int size;
  
  	memset(it, 0, sizeof(*it));
64b60e096   Anton Vorontsov   of: Add new helpe...
1210

59e9fcf87   Uwe Kleine-König   of: restore old h...
1211
1212
1213
1214
1215
1216
  	/*
  	 * one of cell_count or cells_name must be provided to determine the
  	 * argument length.
  	 */
  	if (cell_count < 0 && !cells_name)
  		return -EINVAL;
64b60e096   Anton Vorontsov   of: Add new helpe...
1217
  	list = of_get_property(np, list_name, &size);
15c9a0acc   Grant Likely   of: create of_pha...
1218
  	if (!list)
1af4c7f18   Alexandre Courbot   of: return -ENOEN...
1219
  		return -ENOENT;
64b60e096   Anton Vorontsov   of: Add new helpe...
1220

74e1fbb13   Joerg Roedel   of: Introduce str...
1221
1222
1223
1224
1225
1226
1227
1228
1229
  	it->cells_name = cells_name;
  	it->cell_count = cell_count;
  	it->parent = np;
  	it->list_end = list + size / sizeof(*list);
  	it->phandle_end = list;
  	it->cur = list;
  
  	return 0;
  }
00bab23f7   Kuninori Morimoto   of-graph: export ...
1230
  EXPORT_SYMBOL_GPL(of_phandle_iterator_init);
74e1fbb13   Joerg Roedel   of: Introduce str...
1231

cd209b412   Joerg Roedel   of: Move phandle ...
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
  int of_phandle_iterator_next(struct of_phandle_iterator *it)
  {
  	uint32_t count = 0;
  
  	if (it->node) {
  		of_node_put(it->node);
  		it->node = NULL;
  	}
  
  	if (!it->cur || it->phandle_end >= it->list_end)
  		return -ENOENT;
  
  	it->cur = it->phandle_end;
  
  	/* If phandle is 0, then it is an empty entry with no arguments. */
  	it->phandle = be32_to_cpup(it->cur++);
  
  	if (it->phandle) {
64b60e096   Anton Vorontsov   of: Add new helpe...
1250

15c9a0acc   Grant Likely   of: create of_pha...
1251
  		/*
cd209b412   Joerg Roedel   of: Move phandle ...
1252
1253
  		 * Find the provider node and parse the #*-cells property to
  		 * determine the argument length.
15c9a0acc   Grant Likely   of: create of_pha...
1254
  		 */
cd209b412   Joerg Roedel   of: Move phandle ...
1255
  		it->node = of_find_node_by_phandle(it->phandle);
035fd9482   Stephen Warren   of: introduce of_...
1256

cd209b412   Joerg Roedel   of: Move phandle ...
1257
1258
  		if (it->cells_name) {
  			if (!it->node) {
0d638a07d   Rob Herring   of: Convert to us...
1259
1260
1261
  				pr_err("%pOF: could not find phandle
  ",
  				       it->parent);
cd209b412   Joerg Roedel   of: Move phandle ...
1262
  				goto err;
15c9a0acc   Grant Likely   of: create of_pha...
1263
  			}
64b60e096   Anton Vorontsov   of: Add new helpe...
1264

cd209b412   Joerg Roedel   of: Move phandle ...
1265
1266
  			if (of_property_read_u32(it->node, it->cells_name,
  						 &count)) {
e42ee6101   Uwe Kleine-König   of: Let of_for_ea...
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
  				/*
  				 * If both cell_count and cells_name is given,
  				 * fall back to cell_count in absence
  				 * of the cells_name property
  				 */
  				if (it->cell_count >= 0) {
  					count = it->cell_count;
  				} else {
  					pr_err("%pOF: could not get %s for %pOF
  ",
  					       it->parent,
  					       it->cells_name,
  					       it->node);
  					goto err;
  				}
15c9a0acc   Grant Likely   of: create of_pha...
1282
  			}
cd209b412   Joerg Roedel   of: Move phandle ...
1283
1284
  		} else {
  			count = it->cell_count;
64b60e096   Anton Vorontsov   of: Add new helpe...
1285
  		}
15c9a0acc   Grant Likely   of: create of_pha...
1286
  		/*
cd209b412   Joerg Roedel   of: Move phandle ...
1287
1288
1289
1290
  		 * Make sure that the arguments actually fit in the remaining
  		 * property data length
  		 */
  		if (it->cur + count > it->list_end) {
af3be70a3   Florian Fainelli   of: Improve of_ph...
1291
1292
1293
1294
  			pr_err("%pOF: %s = %d found %d
  ",
  			       it->parent, it->cells_name,
  			       count, it->cell_count);
cd209b412   Joerg Roedel   of: Move phandle ...
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
  			goto err;
  		}
  	}
  
  	it->phandle_end = it->cur + count;
  	it->cur_count = count;
  
  	return 0;
  
  err:
  	if (it->node) {
  		of_node_put(it->node);
  		it->node = NULL;
  	}
  
  	return -EINVAL;
  }
00bab23f7   Kuninori Morimoto   of-graph: export ...
1312
  EXPORT_SYMBOL_GPL(of_phandle_iterator_next);
cd209b412   Joerg Roedel   of: Move phandle ...
1313

abdaa77b1   Joerg Roedel   of: Introduce of_...
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
  int of_phandle_iterator_args(struct of_phandle_iterator *it,
  			     uint32_t *args,
  			     int size)
  {
  	int i, count;
  
  	count = it->cur_count;
  
  	if (WARN_ON(size < count))
  		count = size;
  
  	for (i = 0; i < count; i++)
  		args[i] = be32_to_cpup(it->cur++);
  
  	return count;
  }
bd69f73f2   Grant Likely   of: Create functi...
1330
1331
  static int __of_parse_phandle_with_args(const struct device_node *np,
  					const char *list_name,
035fd9482   Stephen Warren   of: introduce of_...
1332
1333
  					const char *cells_name,
  					int cell_count, int index,
bd69f73f2   Grant Likely   of: Create functi...
1334
  					struct of_phandle_args *out_args)
64b60e096   Anton Vorontsov   of: Add new helpe...
1335
  {
74e1fbb13   Joerg Roedel   of: Introduce str...
1336
1337
  	struct of_phandle_iterator it;
  	int rc, cur_index = 0;
64b60e096   Anton Vorontsov   of: Add new helpe...
1338

15c9a0acc   Grant Likely   of: create of_pha...
1339
  	/* Loop over the phandles until all the requested entry is found */
f623ce95a   Joerg Roedel   of: Introduce of_...
1340
  	of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) {
15c9a0acc   Grant Likely   of: create of_pha...
1341
  		/*
cd209b412   Joerg Roedel   of: Move phandle ...
1342
  		 * All of the error cases bail out of the loop, so at
15c9a0acc   Grant Likely   of: create of_pha...
1343
1344
1345
1346
  		 * this point, the parsing is successful. If the requested
  		 * index matches, then fill the out_args structure and return,
  		 * or return -ENOENT for an empty entry.
  		 */
23ce04c07   Grant Likely   of/base: Clean up...
1347
  		rc = -ENOENT;
15c9a0acc   Grant Likely   of: create of_pha...
1348
  		if (cur_index == index) {
74e1fbb13   Joerg Roedel   of: Introduce str...
1349
  			if (!it.phandle)
23ce04c07   Grant Likely   of/base: Clean up...
1350
  				goto err;
15c9a0acc   Grant Likely   of: create of_pha...
1351
1352
  
  			if (out_args) {
abdaa77b1   Joerg Roedel   of: Introduce of_...
1353
1354
1355
1356
1357
  				int c;
  
  				c = of_phandle_iterator_args(&it,
  							     out_args->args,
  							     MAX_PHANDLE_ARGS);
74e1fbb13   Joerg Roedel   of: Introduce str...
1358
  				out_args->np = it.node;
abdaa77b1   Joerg Roedel   of: Introduce of_...
1359
  				out_args->args_count = c;
b855f16b0   Tang Yuantian   of/base: release ...
1360
  			} else {
74e1fbb13   Joerg Roedel   of: Introduce str...
1361
  				of_node_put(it.node);
15c9a0acc   Grant Likely   of: create of_pha...
1362
  			}
23ce04c07   Grant Likely   of/base: Clean up...
1363
1364
  
  			/* Found it! return success */
15c9a0acc   Grant Likely   of: create of_pha...
1365
  			return 0;
64b60e096   Anton Vorontsov   of: Add new helpe...
1366
  		}
64b60e096   Anton Vorontsov   of: Add new helpe...
1367

64b60e096   Anton Vorontsov   of: Add new helpe...
1368
1369
  		cur_index++;
  	}
23ce04c07   Grant Likely   of/base: Clean up...
1370
1371
1372
1373
1374
  	/*
  	 * Unlock node before returning result; will be one of:
  	 * -ENOENT : index is for empty phandle
  	 * -EINVAL : parsing error on data
  	 */
cd209b412   Joerg Roedel   of: Move phandle ...
1375

23ce04c07   Grant Likely   of/base: Clean up...
1376
   err:
beab47d55   Markus Elfring   of: Delete an unn...
1377
  	of_node_put(it.node);
23ce04c07   Grant Likely   of/base: Clean up...
1378
  	return rc;
64b60e096   Anton Vorontsov   of: Add new helpe...
1379
  }
bd69f73f2   Grant Likely   of: Create functi...
1380

eded9dd40   Stephen Warren   of: move document...
1381
  /**
5fba49e3a   Stephen Warren   of: move of_parse...
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
   * of_parse_phandle - Resolve a phandle property to a device_node pointer
   * @np: Pointer to device node holding phandle property
   * @phandle_name: Name of property holding a phandle value
   * @index: For properties holding a table of phandles, this is the index into
   *         the table
   *
   * Returns the device_node pointer with refcount incremented.  Use
   * of_node_put() on it when done.
   */
  struct device_node *of_parse_phandle(const struct device_node *np,
  				     const char *phandle_name, int index)
  {
91d9942c2   Stephen Warren   of: call __of_par...
1394
1395
1396
1397
  	struct of_phandle_args args;
  
  	if (index < 0)
  		return NULL;
5fba49e3a   Stephen Warren   of: move of_parse...
1398

91d9942c2   Stephen Warren   of: call __of_par...
1399
1400
  	if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0,
  					 index, &args))
5fba49e3a   Stephen Warren   of: move of_parse...
1401
  		return NULL;
91d9942c2   Stephen Warren   of: call __of_par...
1402
  	return args.np;
5fba49e3a   Stephen Warren   of: move of_parse...
1403
1404
1405
1406
  }
  EXPORT_SYMBOL(of_parse_phandle);
  
  /**
eded9dd40   Stephen Warren   of: move document...
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
   * of_parse_phandle_with_args() - Find a node pointed by phandle in a list
   * @np:		pointer to a device tree node containing a list
   * @list_name:	property name that contains a list
   * @cells_name:	property name that specifies phandles' arguments count
   * @index:	index of a phandle to parse out
   * @out_args:	optional pointer to output arguments structure (will be filled)
   *
   * This function is useful to parse lists of phandles and their arguments.
   * Returns 0 on success and fills out_args, on error returns appropriate
   * errno value.
   *
d94a75c13   Geert Uytterhoeven   of: Correct of_ph...
1418
   * Caller is responsible to call of_node_put() on the returned out_args->np
eded9dd40   Stephen Warren   of: move document...
1419
1420
1421
1422
1423
   * pointer.
   *
   * Example:
   *
   * phandle1: node1 {
c0e848d8b   Geert Uytterhoeven   of: Remove spaces...
1424
   *	#list-cells = <2>;
eded9dd40   Stephen Warren   of: move document...
1425
1426
1427
   * }
   *
   * phandle2: node2 {
c0e848d8b   Geert Uytterhoeven   of: Remove spaces...
1428
   *	#list-cells = <1>;
eded9dd40   Stephen Warren   of: move document...
1429
1430
1431
   * }
   *
   * node3 {
c0e848d8b   Geert Uytterhoeven   of: Remove spaces...
1432
   *	list = <&phandle1 1 2 &phandle2 3>;
eded9dd40   Stephen Warren   of: move document...
1433
1434
1435
1436
1437
   * }
   *
   * To get a device_node of the `node2' node you may call this:
   * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
   */
bd69f73f2   Grant Likely   of: Create functi...
1438
1439
1440
1441
  int of_parse_phandle_with_args(const struct device_node *np, const char *list_name,
  				const char *cells_name, int index,
  				struct of_phandle_args *out_args)
  {
59e9fcf87   Uwe Kleine-König   of: restore old h...
1442
  	int cell_count = -1;
bd69f73f2   Grant Likely   of: Create functi...
1443
1444
  	if (index < 0)
  		return -EINVAL;
59e9fcf87   Uwe Kleine-König   of: restore old h...
1445
1446
1447
1448
1449
1450
1451
  
  	/* If cells_name is NULL we assume a cell count of 0 */
  	if (!cells_name)
  		cell_count = 0;
  
  	return __of_parse_phandle_with_args(np, list_name, cells_name,
  					    cell_count, index, out_args);
bd69f73f2   Grant Likely   of: Create functi...
1452
  }
15c9a0acc   Grant Likely   of: create of_pha...
1453
  EXPORT_SYMBOL(of_parse_phandle_with_args);
02af11b03   Grant Likely   of: merge prom_{a...
1454

bd69f73f2   Grant Likely   of: Create functi...
1455
  /**
bd6f2fd5a   Stephen Boyd   of: Support parsi...
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
   * of_parse_phandle_with_args_map() - Find a node pointed by phandle in a list and remap it
   * @np:		pointer to a device tree node containing a list
   * @list_name:	property name that contains a list
   * @stem_name:	stem of property names that specify phandles' arguments count
   * @index:	index of a phandle to parse out
   * @out_args:	optional pointer to output arguments structure (will be filled)
   *
   * This function is useful to parse lists of phandles and their arguments.
   * Returns 0 on success and fills out_args, on error returns appropriate errno
   * value. The difference between this function and of_parse_phandle_with_args()
   * is that this API remaps a phandle if the node the phandle points to has
   * a <@stem_name>-map property.
   *
   * Caller is responsible to call of_node_put() on the returned out_args->np
   * pointer.
   *
   * Example:
   *
   * phandle1: node1 {
   *	#list-cells = <2>;
   * }
   *
   * phandle2: node2 {
   *	#list-cells = <1>;
   * }
   *
   * phandle3: node3 {
   * 	#list-cells = <1>;
   * 	list-map = <0 &phandle2 3>,
   * 		   <1 &phandle2 2>,
   * 		   <2 &phandle1 5 1>;
   *	list-map-mask = <0x3>;
   * };
   *
   * node4 {
   *	list = <&phandle1 1 2 &phandle3 0>;
   * }
   *
   * To get a device_node of the `node2' node you may call this:
   * of_parse_phandle_with_args(node4, "list", "list", 1, &args);
   */
  int of_parse_phandle_with_args_map(const struct device_node *np,
  				   const char *list_name,
  				   const char *stem_name,
  				   int index, struct of_phandle_args *out_args)
  {
  	char *cells_name, *map_name = NULL, *mask_name = NULL;
  	char *pass_name = NULL;
  	struct device_node *cur, *new = NULL;
  	const __be32 *map, *mask, *pass;
  	static const __be32 dummy_mask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
  	static const __be32 dummy_pass[] = { [0 ... MAX_PHANDLE_ARGS] = 0 };
  	__be32 initial_match_array[MAX_PHANDLE_ARGS];
  	const __be32 *match_array = initial_match_array;
  	int i, ret, map_len, match;
  	u32 list_size, new_size;
  
  	if (index < 0)
  		return -EINVAL;
  
  	cells_name = kasprintf(GFP_KERNEL, "#%s-cells", stem_name);
  	if (!cells_name)
  		return -ENOMEM;
  
  	ret = -ENOMEM;
  	map_name = kasprintf(GFP_KERNEL, "%s-map", stem_name);
  	if (!map_name)
  		goto free;
  
  	mask_name = kasprintf(GFP_KERNEL, "%s-map-mask", stem_name);
  	if (!mask_name)
  		goto free;
  
  	pass_name = kasprintf(GFP_KERNEL, "%s-map-pass-thru", stem_name);
  	if (!pass_name)
  		goto free;
e42ee6101   Uwe Kleine-König   of: Let of_for_ea...
1532
  	ret = __of_parse_phandle_with_args(np, list_name, cells_name, -1, index,
bd6f2fd5a   Stephen Boyd   of: Support parsi...
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
  					   out_args);
  	if (ret)
  		goto free;
  
  	/* Get the #<list>-cells property */
  	cur = out_args->np;
  	ret = of_property_read_u32(cur, cells_name, &list_size);
  	if (ret < 0)
  		goto put;
  
  	/* Precalculate the match array - this simplifies match loop */
  	for (i = 0; i < list_size; i++)
  		initial_match_array[i] = cpu_to_be32(out_args->args[i]);
  
  	ret = -EINVAL;
  	while (cur) {
  		/* Get the <list>-map property */
  		map = of_get_property(cur, map_name, &map_len);
  		if (!map) {
  			ret = 0;
  			goto free;
  		}
  		map_len /= sizeof(u32);
  
  		/* Get the <list>-map-mask property (optional) */
  		mask = of_get_property(cur, mask_name, NULL);
  		if (!mask)
  			mask = dummy_mask;
  		/* Iterate through <list>-map property */
  		match = 0;
  		while (map_len > (list_size + 1) && !match) {
  			/* Compare specifiers */
  			match = 1;
  			for (i = 0; i < list_size; i++, map_len--)
  				match &= !((match_array[i] ^ *map++) & mask[i]);
  
  			of_node_put(new);
  			new = of_find_node_by_phandle(be32_to_cpup(map));
  			map++;
  			map_len--;
  
  			/* Check if not found */
  			if (!new)
  				goto put;
  
  			if (!of_device_is_available(new))
  				match = 0;
  
  			ret = of_property_read_u32(new, cells_name, &new_size);
  			if (ret)
  				goto put;
  
  			/* Check for malformed properties */
  			if (WARN_ON(new_size > MAX_PHANDLE_ARGS))
  				goto put;
  			if (map_len < new_size)
  				goto put;
  
  			/* Move forward by new node's #<list>-cells amount */
  			map += new_size;
  			map_len -= new_size;
  		}
  		if (!match)
  			goto put;
  
  		/* Get the <list>-map-pass-thru property (optional) */
  		pass = of_get_property(cur, pass_name, NULL);
  		if (!pass)
  			pass = dummy_pass;
  
  		/*
  		 * Successfully parsed a <list>-map translation; copy new
  		 * specifier into the out_args structure, keeping the
  		 * bits specified in <list>-map-pass-thru.
  		 */
  		match_array = map - new_size;
  		for (i = 0; i < new_size; i++) {
  			__be32 val = *(map - new_size + i);
  
  			if (i < list_size) {
  				val &= ~pass[i];
  				val |= cpu_to_be32(out_args->args[i]) & pass[i];
  			}
  
  			out_args->args[i] = be32_to_cpu(val);
  		}
  		out_args->args_count = list_size = new_size;
  		/* Iterate again with new provider */
  		out_args->np = new;
  		of_node_put(cur);
  		cur = new;
  	}
  put:
  	of_node_put(cur);
  	of_node_put(new);
  free:
  	kfree(mask_name);
  	kfree(map_name);
  	kfree(cells_name);
  	kfree(pass_name);
  
  	return ret;
  }
  EXPORT_SYMBOL(of_parse_phandle_with_args_map);
  
  /**
035fd9482   Stephen Warren   of: introduce of_...
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
   * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list
   * @np:		pointer to a device tree node containing a list
   * @list_name:	property name that contains a list
   * @cell_count: number of argument cells following the phandle
   * @index:	index of a phandle to parse out
   * @out_args:	optional pointer to output arguments structure (will be filled)
   *
   * This function is useful to parse lists of phandles and their arguments.
   * Returns 0 on success and fills out_args, on error returns appropriate
   * errno value.
   *
d94a75c13   Geert Uytterhoeven   of: Correct of_ph...
1650
   * Caller is responsible to call of_node_put() on the returned out_args->np
035fd9482   Stephen Warren   of: introduce of_...
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
   * pointer.
   *
   * Example:
   *
   * phandle1: node1 {
   * }
   *
   * phandle2: node2 {
   * }
   *
   * node3 {
c0e848d8b   Geert Uytterhoeven   of: Remove spaces...
1662
   *	list = <&phandle1 0 2 &phandle2 2 3>;
035fd9482   Stephen Warren   of: introduce of_...
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
   * }
   *
   * To get a device_node of the `node2' node you may call this:
   * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args);
   */
  int of_parse_phandle_with_fixed_args(const struct device_node *np,
  				const char *list_name, int cell_count,
  				int index, struct of_phandle_args *out_args)
  {
  	if (index < 0)
  		return -EINVAL;
  	return __of_parse_phandle_with_args(np, list_name, NULL, cell_count,
  					   index, out_args);
  }
  EXPORT_SYMBOL(of_parse_phandle_with_fixed_args);
  
  /**
bd69f73f2   Grant Likely   of: Create functi...
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
   * of_count_phandle_with_args() - Find the number of phandles references in a property
   * @np:		pointer to a device tree node containing a list
   * @list_name:	property name that contains a list
   * @cells_name:	property name that specifies phandles' arguments count
   *
   * Returns the number of phandle + argument tuples within a property. It
   * is a typical pattern to encode a list of phandle and variable
   * arguments into a single property. The number of arguments is encoded
   * by a property in the phandle-target node. For example, a gpios
   * property would contain a list of GPIO specifies consisting of a
   * phandle and 1 or more arguments. The number of arguments are
   * determined by the #gpio-cells property in the node pointed to by the
   * phandle.
   */
  int of_count_phandle_with_args(const struct device_node *np, const char *list_name,
  				const char *cells_name)
  {
2021bd01f   Joerg Roedel   of: Remove counti...
1697
1698
  	struct of_phandle_iterator it;
  	int rc, cur_index = 0;
59e9fcf87   Uwe Kleine-König   of: restore old h...
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
  	/*
  	 * If cells_name is NULL we assume a cell count of 0. This makes
  	 * counting the phandles trivial as each 32bit word in the list is a
  	 * phandle and no arguments are to consider. So we don't iterate through
  	 * the list but just use the length to determine the phandle count.
  	 */
  	if (!cells_name) {
  		const __be32 *list;
  		int size;
  
  		list = of_get_property(np, list_name, &size);
  		if (!list)
  			return -ENOENT;
  
  		return size / sizeof(*list);
  	}
e42ee6101   Uwe Kleine-König   of: Let of_for_ea...
1715
  	rc = of_phandle_iterator_init(&it, np, list_name, cells_name, -1);
2021bd01f   Joerg Roedel   of: Remove counti...
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
  	if (rc)
  		return rc;
  
  	while ((rc = of_phandle_iterator_next(&it)) == 0)
  		cur_index += 1;
  
  	if (rc != -ENOENT)
  		return rc;
  
  	return cur_index;
bd69f73f2   Grant Likely   of: Create functi...
1726
1727
  }
  EXPORT_SYMBOL(of_count_phandle_with_args);
02af11b03   Grant Likely   of: merge prom_{a...
1728
  /**
62664f677   Xiubo Li   of: add __of_add_...
1729
1730
   * __of_add_property - Add a property to a node without lock operations
   */
d8c500884   Pantelis Antoniou   of: Create unlock...
1731
  int __of_add_property(struct device_node *np, struct property *prop)
62664f677   Xiubo Li   of: add __of_add_...
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
  {
  	struct property **next;
  
  	prop->next = NULL;
  	next = &np->properties;
  	while (*next) {
  		if (strcmp(prop->name, (*next)->name) == 0)
  			/* duplicate ! don't insert it */
  			return -EEXIST;
  
  		next = &(*next)->next;
  	}
  	*next = prop;
  
  	return 0;
  }
  
  /**
79d1c7129   Nathan Fontenot   powerpc+of: Renam...
1750
   * of_add_property - Add a property to a node
02af11b03   Grant Likely   of: merge prom_{a...
1751
   */
79d1c7129   Nathan Fontenot   powerpc+of: Renam...
1752
  int of_add_property(struct device_node *np, struct property *prop)
02af11b03   Grant Likely   of: merge prom_{a...
1753
  {
02af11b03   Grant Likely   of: merge prom_{a...
1754
  	unsigned long flags;
1cf3d8b3d   Nathan Fontenot   powerpc+of: Add o...
1755
  	int rc;
8a2b22a25   Grant Likely   of: Make devicetr...
1756
  	mutex_lock(&of_mutex);
02af11b03   Grant Likely   of: merge prom_{a...
1757

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1758
  	raw_spin_lock_irqsave(&devtree_lock, flags);
62664f677   Xiubo Li   of: add __of_add_...
1759
  	rc = __of_add_property(np, prop);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1760
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
02af11b03   Grant Likely   of: merge prom_{a...
1761

8a2b22a25   Grant Likely   of: Make devicetr...
1762
  	if (!rc)
0829f6d1f   Pantelis Antoniou   of: device_node k...
1763
  		__of_add_property_sysfs(np, prop);
02af11b03   Grant Likely   of: merge prom_{a...
1764

8a2b22a25   Grant Likely   of: Make devicetr...
1765
  	mutex_unlock(&of_mutex);
259092a35   Grant Likely   of: Reorder devic...
1766
1767
  	if (!rc)
  		of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL);
62664f677   Xiubo Li   of: add __of_add_...
1768
  	return rc;
02af11b03   Grant Likely   of: merge prom_{a...
1769
  }
d8c500884   Pantelis Antoniou   of: Create unlock...
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
  int __of_remove_property(struct device_node *np, struct property *prop)
  {
  	struct property **next;
  
  	for (next = &np->properties; *next; next = &(*next)->next) {
  		if (*next == prop)
  			break;
  	}
  	if (*next == NULL)
  		return -ENODEV;
  
  	/* found the node */
  	*next = prop->next;
  	prop->next = np->deadprops;
  	np->deadprops = prop;
  
  	return 0;
  }
02af11b03   Grant Likely   of: merge prom_{a...
1788
  /**
79d1c7129   Nathan Fontenot   powerpc+of: Renam...
1789
   * of_remove_property - Remove a property from a node.
02af11b03   Grant Likely   of: merge prom_{a...
1790
1791
1792
1793
1794
1795
   *
   * Note that we don't actually remove it, since we have given out
   * who-knows-how-many pointers to the data using get-property.
   * Instead we just move the property to the "dead properties"
   * list, so it won't be found any more.
   */
79d1c7129   Nathan Fontenot   powerpc+of: Renam...
1796
  int of_remove_property(struct device_node *np, struct property *prop)
02af11b03   Grant Likely   of: merge prom_{a...
1797
  {
02af11b03   Grant Likely   of: merge prom_{a...
1798
  	unsigned long flags;
1cf3d8b3d   Nathan Fontenot   powerpc+of: Add o...
1799
  	int rc;
201b3fe58   Suraj Jitindar Singh   drivers/of: Add c...
1800
1801
  	if (!prop)
  		return -ENODEV;
8a2b22a25   Grant Likely   of: Make devicetr...
1802
  	mutex_lock(&of_mutex);
02af11b03   Grant Likely   of: merge prom_{a...
1803

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1804
  	raw_spin_lock_irqsave(&devtree_lock, flags);
d8c500884   Pantelis Antoniou   of: Create unlock...
1805
  	rc = __of_remove_property(np, prop);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1806
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
02af11b03   Grant Likely   of: merge prom_{a...
1807

8a2b22a25   Grant Likely   of: Make devicetr...
1808
1809
  	if (!rc)
  		__of_remove_property_sysfs(np, prop);
02af11b03   Grant Likely   of: merge prom_{a...
1810

8a2b22a25   Grant Likely   of: Make devicetr...
1811
  	mutex_unlock(&of_mutex);
75b57ecf9   Grant Likely   of: Make device n...
1812

259092a35   Grant Likely   of: Reorder devic...
1813
1814
  	if (!rc)
  		of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL);
02af11b03   Grant Likely   of: merge prom_{a...
1815

8a2b22a25   Grant Likely   of: Make devicetr...
1816
  	return rc;
02af11b03   Grant Likely   of: merge prom_{a...
1817
  }
0f7c5317b   Florian Fainelli   of: Export of_rem...
1818
  EXPORT_SYMBOL_GPL(of_remove_property);
02af11b03   Grant Likely   of: merge prom_{a...
1819

d8c500884   Pantelis Antoniou   of: Create unlock...
1820
1821
  int __of_update_property(struct device_node *np, struct property *newprop,
  		struct property **oldpropp)
02af11b03   Grant Likely   of: merge prom_{a...
1822
  {
475d00942   Dong Aisheng   of: Improve prom_...
1823
  	struct property **next, *oldprop;
02af11b03   Grant Likely   of: merge prom_{a...
1824

d8c500884   Pantelis Antoniou   of: Create unlock...
1825
1826
1827
1828
1829
  	for (next = &np->properties; *next; next = &(*next)->next) {
  		if (of_prop_cmp((*next)->name, newprop->name) == 0)
  			break;
  	}
  	*oldpropp = oldprop = *next;
475d00942   Dong Aisheng   of: Improve prom_...
1830

d8c500884   Pantelis Antoniou   of: Create unlock...
1831
  	if (oldprop) {
947fdaad0   Xiubo Li   of: fix race betw...
1832
  		/* replace the node */
d8c500884   Pantelis Antoniou   of: Create unlock...
1833
1834
1835
1836
1837
1838
1839
1840
  		newprop->next = oldprop->next;
  		*next = newprop;
  		oldprop->next = np->deadprops;
  		np->deadprops = oldprop;
  	} else {
  		/* new node */
  		newprop->next = NULL;
  		*next = newprop;
02af11b03   Grant Likely   of: merge prom_{a...
1841
  	}
75b57ecf9   Grant Likely   of: Make device n...
1842

d8c500884   Pantelis Antoniou   of: Create unlock...
1843
1844
  	return 0;
  }
fcdeb7fed   Grant Likely   of: merge of_atta...
1845
  /*
79d1c7129   Nathan Fontenot   powerpc+of: Renam...
1846
   * of_update_property - Update a property in a node, if the property does
475d00942   Dong Aisheng   of: Improve prom_...
1847
   * not exist, add it.
fcdeb7fed   Grant Likely   of: merge of_atta...
1848
   *
02af11b03   Grant Likely   of: merge prom_{a...
1849
1850
1851
1852
   * Note that we don't actually remove it, since we have given out
   * who-knows-how-many pointers to the data using get-property.
   * Instead we just move the property to the "dead properties" list,
   * and add the new property to the property list
fcdeb7fed   Grant Likely   of: merge of_atta...
1853
   */
79d1c7129   Nathan Fontenot   powerpc+of: Renam...
1854
  int of_update_property(struct device_node *np, struct property *newprop)
fcdeb7fed   Grant Likely   of: merge of_atta...
1855
  {
d8c500884   Pantelis Antoniou   of: Create unlock...
1856
  	struct property *oldprop;
fcdeb7fed   Grant Likely   of: merge of_atta...
1857
  	unsigned long flags;
1cf3d8b3d   Nathan Fontenot   powerpc+of: Add o...
1858
  	int rc;
d8c500884   Pantelis Antoniou   of: Create unlock...
1859
1860
  	if (!newprop->name)
  		return -EINVAL;
1cf3d8b3d   Nathan Fontenot   powerpc+of: Add o...
1861

8a2b22a25   Grant Likely   of: Make devicetr...
1862
  	mutex_lock(&of_mutex);
fcdeb7fed   Grant Likely   of: merge of_atta...
1863

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1864
  	raw_spin_lock_irqsave(&devtree_lock, flags);
d8c500884   Pantelis Antoniou   of: Create unlock...
1865
  	rc = __of_update_property(np, newprop, &oldprop);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1866
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
fcdeb7fed   Grant Likely   of: merge of_atta...
1867

8a2b22a25   Grant Likely   of: Make devicetr...
1868
1869
  	if (!rc)
  		__of_update_property_sysfs(np, newprop, oldprop);
fcdeb7fed   Grant Likely   of: merge of_atta...
1870

8a2b22a25   Grant Likely   of: Make devicetr...
1871
  	mutex_unlock(&of_mutex);
fcdeb7fed   Grant Likely   of: merge of_atta...
1872

259092a35   Grant Likely   of: Reorder devic...
1873
1874
  	if (!rc)
  		of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop);
e81b3295b   Nathan Fontenot   powerpc+of: Add /...
1875

1cf3d8b3d   Nathan Fontenot   powerpc+of: Add o...
1876
  	return rc;
fcdeb7fed   Grant Likely   of: merge of_atta...
1877
  }
fcdeb7fed   Grant Likely   of: merge of_atta...
1878

611cad720   Shawn Guo   dt: add of_alias_...
1879
1880
1881
1882
1883
1884
1885
1886
  static void of_alias_add(struct alias_prop *ap, struct device_node *np,
  			 int id, const char *stem, int stem_len)
  {
  	ap->np = np;
  	ap->id = id;
  	strncpy(ap->stem, stem, stem_len);
  	ap->stem[stem_len] = 0;
  	list_add_tail(&ap->link, &aliases_lookup);
0d638a07d   Rob Herring   of: Convert to us...
1887
1888
1889
  	pr_debug("adding DT alias:%s: stem=%s id=%i node=%pOF
  ",
  		 ap->alias, ap->stem, ap->id, np);
611cad720   Shawn Guo   dt: add of_alias_...
1890
1891
1892
  }
  
  /**
1821dda4a   Geert Uytterhoeven   of: Improve gramm...
1893
   * of_alias_scan - Scan all properties of the 'aliases' node
611cad720   Shawn Guo   dt: add of_alias_...
1894
   *
1821dda4a   Geert Uytterhoeven   of: Improve gramm...
1895
1896
1897
   * The function scans all the properties of the 'aliases' node and populates
   * the global lookup table with the properties.  It returns the
   * number of alias properties found, or an error code in case of failure.
611cad720   Shawn Guo   dt: add of_alias_...
1898
1899
   *
   * @dt_alloc:	An allocator that provides a virtual address to memory
1821dda4a   Geert Uytterhoeven   of: Improve gramm...
1900
   *		for storing the resulting tree
611cad720   Shawn Guo   dt: add of_alias_...
1901
1902
1903
1904
   */
  void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
  {
  	struct property *pp;
7dbe5849f   Laurentiu Tudor   of: make sure of_...
1905
  	of_aliases = of_find_node_by_path("/aliases");
611cad720   Shawn Guo   dt: add of_alias_...
1906
1907
1908
  	of_chosen = of_find_node_by_path("/chosen");
  	if (of_chosen == NULL)
  		of_chosen = of_find_node_by_path("/chosen@0");
5c19e9521   Sascha Hauer   OF: Add helper fo...
1909
1910
  
  	if (of_chosen) {
a752ee56a   Grant Likely   tty: Update hyper...
1911
  		/* linux,stdout-path and /aliases/stdout are for legacy compatibility */
b0d9d92f9   Sergei Shtylyov   of: base: use of_...
1912
1913
1914
1915
1916
  		const char *name = NULL;
  
  		if (of_property_read_string(of_chosen, "stdout-path", &name))
  			of_property_read_string(of_chosen, "linux,stdout-path",
  						&name);
a752ee56a   Grant Likely   tty: Update hyper...
1917
  		if (IS_ENABLED(CONFIG_PPC) && !name)
b0d9d92f9   Sergei Shtylyov   of: base: use of_...
1918
  			of_property_read_string(of_aliases, "stdout", &name);
f64255b50   Peter Hurley   Revert "of: Fix p...
1919
  		if (name)
7914a7c56   Leif Lindholm   of: support passi...
1920
  			of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
5c19e9521   Sascha Hauer   OF: Add helper fo...
1921
  	}
611cad720   Shawn Guo   dt: add of_alias_...
1922
1923
  	if (!of_aliases)
  		return;
8af0da93d   Dong Aisheng   dt: reform for_ea...
1924
  	for_each_property_of_node(of_aliases, pp) {
611cad720   Shawn Guo   dt: add of_alias_...
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
  		const char *start = pp->name;
  		const char *end = start + strlen(start);
  		struct device_node *np;
  		struct alias_prop *ap;
  		int id, len;
  
  		/* Skip those we do not want to proceed */
  		if (!strcmp(pp->name, "name") ||
  		    !strcmp(pp->name, "phandle") ||
  		    !strcmp(pp->name, "linux,phandle"))
  			continue;
  
  		np = of_find_node_by_path(pp->value);
  		if (!np)
  			continue;
  
  		/* walk the alias backwards to extract the id and work out
  		 * the 'stem' string */
  		while (isdigit(*(end-1)) && end > start)
  			end--;
  		len = end - start;
  
  		if (kstrtoint(end, 10, &id) < 0)
  			continue;
  
  		/* Allocate an alias_prop with enough space for the stem */
de96ec2a7   Paul Burton   OF: Prevent unali...
1951
  		ap = dt_alloc(sizeof(*ap) + len + 1, __alignof__(*ap));
611cad720   Shawn Guo   dt: add of_alias_...
1952
1953
  		if (!ap)
  			continue;
0640332e0   Grant Likely   of: Fix missing m...
1954
  		memset(ap, 0, sizeof(*ap) + len + 1);
611cad720   Shawn Guo   dt: add of_alias_...
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
  		ap->alias = start;
  		of_alias_add(ap, np, id, start, len);
  	}
  }
  
  /**
   * of_alias_get_id - Get alias id for the given device_node
   * @np:		Pointer to the given device_node
   * @stem:	Alias stem of the given device_node
   *
5a53a07f1   Geert Uytterhoeven   of: Improve gramm...
1965
1966
   * The function travels the lookup table to get the alias id for the given
   * device_node and alias stem.  It returns the alias id if found.
611cad720   Shawn Guo   dt: add of_alias_...
1967
1968
1969
1970
1971
   */
  int of_alias_get_id(struct device_node *np, const char *stem)
  {
  	struct alias_prop *app;
  	int id = -ENODEV;
c05aba2bd   Pantelis Antoniou   of: rename of_ali...
1972
  	mutex_lock(&of_mutex);
611cad720   Shawn Guo   dt: add of_alias_...
1973
1974
1975
1976
1977
1978
1979
1980
1981
  	list_for_each_entry(app, &aliases_lookup, link) {
  		if (strcmp(app->stem, stem) != 0)
  			continue;
  
  		if (np == app->np) {
  			id = app->id;
  			break;
  		}
  	}
c05aba2bd   Pantelis Antoniou   of: rename of_ali...
1982
  	mutex_unlock(&of_mutex);
611cad720   Shawn Guo   dt: add of_alias_...
1983
1984
1985
1986
  
  	return id;
  }
  EXPORT_SYMBOL_GPL(of_alias_get_id);
c541adc63   Stephen Warren   dt: add property ...
1987

351d224f6   Wolfram Sang   of: base: add fun...
1988
  /**
b1078c355   Michal Simek   of: base: Introdu...
1989
1990
1991
1992
   * of_alias_get_alias_list - Get alias list for the given device driver
   * @matches:	Array of OF device match structures to search in
   * @stem:	Alias stem of the given device_node
   * @bitmap:	Bitmap field pointer
7acf79b6b   Michal Simek   of: base: Fix eng...
1993
   * @nbits:	Maximum number of alias IDs which can be recorded in bitmap
b1078c355   Michal Simek   of: base: Introdu...
1994
1995
1996
1997
   *
   * The function travels the lookup table to record alias ids for the given
   * device match structures and alias stem.
   *
59eaeba63   Michal Simek   of: base: Change ...
1998
1999
   * Return:	0 or -ENOSYS when !CONFIG_OF or
   *		-EOVERFLOW if alias ID is greater then allocated nbits
b1078c355   Michal Simek   of: base: Introdu...
2000
2001
2002
2003
2004
2005
   */
  int of_alias_get_alias_list(const struct of_device_id *matches,
  			     const char *stem, unsigned long *bitmap,
  			     unsigned int nbits)
  {
  	struct alias_prop *app;
59eaeba63   Michal Simek   of: base: Change ...
2006
  	int ret = 0;
b1078c355   Michal Simek   of: base: Introdu...
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
  
  	/* Zero bitmap field to make sure that all the time it is clean */
  	bitmap_zero(bitmap, nbits);
  
  	mutex_lock(&of_mutex);
  	pr_debug("%s: Looking for stem: %s
  ", __func__, stem);
  	list_for_each_entry(app, &aliases_lookup, link) {
  		pr_debug("%s: stem: %s, id: %d
  ",
  			 __func__, app->stem, app->id);
  
  		if (strcmp(app->stem, stem) != 0) {
7acf79b6b   Michal Simek   of: base: Fix eng...
2020
2021
  			pr_debug("%s: stem comparison didn't pass %s
  ",
b1078c355   Michal Simek   of: base: Introdu...
2022
2023
2024
  				 __func__, app->stem);
  			continue;
  		}
b1078c355   Michal Simek   of: base: Introdu...
2025
2026
2027
  		if (of_match_node(matches, app->np)) {
  			pr_debug("%s: Allocated ID %d
  ", __func__, app->id);
59eaeba63   Michal Simek   of: base: Change ...
2028
2029
2030
2031
2032
2033
2034
2035
2036
  
  			if (app->id >= nbits) {
  				pr_warn("%s: ID %d >= than bitmap field %d
  ",
  					__func__, app->id, nbits);
  				ret = -EOVERFLOW;
  			} else {
  				set_bit(app->id, bitmap);
  			}
b1078c355   Michal Simek   of: base: Introdu...
2037
  		}
b1078c355   Michal Simek   of: base: Introdu...
2038
2039
  	}
  	mutex_unlock(&of_mutex);
59eaeba63   Michal Simek   of: base: Change ...
2040
  	return ret;
b1078c355   Michal Simek   of: base: Introdu...
2041
2042
2043
2044
  }
  EXPORT_SYMBOL_GPL(of_alias_get_alias_list);
  
  /**
351d224f6   Wolfram Sang   of: base: add fun...
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
   * of_alias_get_highest_id - Get highest alias id for the given stem
   * @stem:	Alias stem to be examined
   *
   * The function travels the lookup table to get the highest alias id for the
   * given alias stem.  It returns the alias id if found.
   */
  int of_alias_get_highest_id(const char *stem)
  {
  	struct alias_prop *app;
  	int id = -ENODEV;
  
  	mutex_lock(&of_mutex);
  	list_for_each_entry(app, &aliases_lookup, link) {
  		if (strcmp(app->stem, stem) != 0)
  			continue;
  
  		if (app->id > id)
  			id = app->id;
  	}
  	mutex_unlock(&of_mutex);
  
  	return id;
  }
  EXPORT_SYMBOL_GPL(of_alias_get_highest_id);
5c19e9521   Sascha Hauer   OF: Add helper fo...
2069
  /**
3482f2c52   Grant Likely   of: Create of_con...
2070
2071
2072
2073
2074
2075
2076
2077
   * of_console_check() - Test and setup console for DT setup
   * @dn - Pointer to device node
   * @name - Name to use for preferred console without index. ex. "ttyS"
   * @index - Index to use for preferred console.
   *
   * Check if the given device node matches the stdout-path property in the
   * /chosen node. If it does then register it as the preferred console and return
   * TRUE. Otherwise return FALSE.
5c19e9521   Sascha Hauer   OF: Add helper fo...
2078
   */
3482f2c52   Grant Likely   of: Create of_con...
2079
  bool of_console_check(struct device_node *dn, char *name, int index)
5c19e9521   Sascha Hauer   OF: Add helper fo...
2080
  {
3482f2c52   Grant Likely   of: Create of_con...
2081
  	if (!dn || dn != of_stdout || console_set_on_cmdline)
5c19e9521   Sascha Hauer   OF: Add helper fo...
2082
  		return false;
db179e0d0   Sergey Senozhatsky   of: do not leak c...
2083
2084
2085
2086
2087
2088
  
  	/*
  	 * XXX: cast `options' to char pointer to suppress complication
  	 * warnings: printk, UART and console drivers expect char pointer.
  	 */
  	return !add_preferred_console(name, index, (char *)of_stdout_options);
5c19e9521   Sascha Hauer   OF: Add helper fo...
2089
  }
3482f2c52   Grant Likely   of: Create of_con...
2090
  EXPORT_SYMBOL_GPL(of_console_check);
a3e31b458   Sudeep KarkadaNagesha   of: Move definiti...
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
  
  /**
   *	of_find_next_cache_node - Find a node's subsidiary cache
   *	@np:	node of type "cpu" or "cache"
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.  Caller should hold a reference
   *	to np.
   */
  struct device_node *of_find_next_cache_node(const struct device_node *np)
  {
91d967497   Rob Herring   of: fix sparse wa...
2102
  	struct device_node *child, *cache_node;
a3e31b458   Sudeep KarkadaNagesha   of: Move definiti...
2103

91d967497   Rob Herring   of: fix sparse wa...
2104
2105
2106
  	cache_node = of_parse_phandle(np, "l2-cache", 0);
  	if (!cache_node)
  		cache_node = of_parse_phandle(np, "next-level-cache", 0);
a3e31b458   Sudeep KarkadaNagesha   of: Move definiti...
2107

91d967497   Rob Herring   of: fix sparse wa...
2108
2109
  	if (cache_node)
  		return cache_node;
a3e31b458   Sudeep KarkadaNagesha   of: Move definiti...
2110
2111
2112
2113
  
  	/* OF on pmac has nodes instead of properties named "l2-cache"
  	 * beneath CPU nodes.
  	 */
e8b1dee21   Rob Herring   of: Use device_ty...
2114
  	if (IS_ENABLED(CONFIG_PPC_PMAC) && of_node_is_type(np, "cpu"))
a3e31b458   Sudeep KarkadaNagesha   of: Move definiti...
2115
  		for_each_child_of_node(np, child)
e8b1dee21   Rob Herring   of: Use device_ty...
2116
  			if (of_node_is_type(child, "cache"))
a3e31b458   Sudeep KarkadaNagesha   of: Move definiti...
2117
2118
2119
2120
  				return child;
  
  	return NULL;
  }
fd9fdb78a   Philipp Zabel   [media] of: move ...
2121
2122
  
  /**
5fa23530d   Sudeep Holla   of: base: add sup...
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
   * of_find_last_cache_level - Find the level at which the last cache is
   * 		present for the given logical cpu
   *
   * @cpu: cpu number(logical index) for which the last cache level is needed
   *
   * Returns the the level at which the last cache is present. It is exactly
   * same as  the total number of cache levels for the given logical cpu.
   */
  int of_find_last_cache_level(unsigned int cpu)
  {
  	u32 cache_level = 0;
  	struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu);
  
  	while (np) {
  		prev = np;
  		of_node_put(np);
  		np = of_find_next_cache_node(np);
  	}
  
  	of_property_read_u32(prev, "cache-level", &cache_level);
  
  	return cache_level;
  }
2a6db719c   Nipun Gupta   iommu/of: make of...
2146
2147
  
  /**
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2148
   * of_map_id - Translate an ID through a downstream mapping.
2a6db719c   Nipun Gupta   iommu/of: make of...
2149
   * @np: root complex device node.
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2150
   * @id: device ID to map.
2a6db719c   Nipun Gupta   iommu/of: make of...
2151
2152
2153
2154
2155
   * @map_name: property name of the map to use.
   * @map_mask_name: optional property name of the mask to use.
   * @target: optional pointer to a target device node.
   * @id_out: optional pointer to receive the translated ID.
   *
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2156
   * Given a device ID, look up the appropriate implementation-defined
2a6db719c   Nipun Gupta   iommu/of: make of...
2157
2158
2159
2160
2161
2162
2163
2164
2165
   * platform ID and/or the target device which receives transactions on that
   * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
   * @id_out may be NULL if only the other is required. If @target points to
   * a non-NULL device node pointer, only entries targeting that node will be
   * matched; if it points to a NULL value, it will receive the device node of
   * the first matching target phandle, with a reference held.
   *
   * Return: 0 on success or a standard error code on failure.
   */
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2166
  int of_map_id(struct device_node *np, u32 id,
2a6db719c   Nipun Gupta   iommu/of: make of...
2167
2168
2169
  	       const char *map_name, const char *map_mask_name,
  	       struct device_node **target, u32 *id_out)
  {
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2170
  	u32 map_mask, masked_id;
2a6db719c   Nipun Gupta   iommu/of: make of...
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
  	int map_len;
  	const __be32 *map = NULL;
  
  	if (!np || !map_name || (!target && !id_out))
  		return -EINVAL;
  
  	map = of_get_property(np, map_name, &map_len);
  	if (!map) {
  		if (target)
  			return -ENODEV;
  		/* Otherwise, no map implies no translation */
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2182
  		*id_out = id;
2a6db719c   Nipun Gupta   iommu/of: make of...
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
  		return 0;
  	}
  
  	if (!map_len || map_len % (4 * sizeof(*map))) {
  		pr_err("%pOF: Error: Bad %s length: %d
  ", np,
  			map_name, map_len);
  		return -EINVAL;
  	}
  
  	/* The default is to select all bits. */
  	map_mask = 0xffffffff;
  
  	/*
  	 * Can be overridden by "{iommu,msi}-map-mask" property.
  	 * If of_property_read_u32() fails, the default is used.
  	 */
  	if (map_mask_name)
  		of_property_read_u32(np, map_mask_name, &map_mask);
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2202
  	masked_id = map_mask & id;
2a6db719c   Nipun Gupta   iommu/of: make of...
2203
2204
  	for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
  		struct device_node *phandle_node;
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2205
  		u32 id_base = be32_to_cpup(map + 0);
2a6db719c   Nipun Gupta   iommu/of: make of...
2206
2207
  		u32 phandle = be32_to_cpup(map + 1);
  		u32 out_base = be32_to_cpup(map + 2);
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2208
  		u32 id_len = be32_to_cpup(map + 3);
2a6db719c   Nipun Gupta   iommu/of: make of...
2209

746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2210
2211
2212
  		if (id_base & ~map_mask) {
  			pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores id-base (0x%x)
  ",
2a6db719c   Nipun Gupta   iommu/of: make of...
2213
  				np, map_name, map_name,
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2214
  				map_mask, id_base);
2a6db719c   Nipun Gupta   iommu/of: make of...
2215
2216
  			return -EFAULT;
  		}
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2217
  		if (masked_id < id_base || masked_id >= id_base + id_len)
2a6db719c   Nipun Gupta   iommu/of: make of...
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
  			continue;
  
  		phandle_node = of_find_node_by_phandle(phandle);
  		if (!phandle_node)
  			return -ENODEV;
  
  		if (target) {
  			if (*target)
  				of_node_put(phandle_node);
  			else
  				*target = phandle_node;
  
  			if (*target != phandle_node)
  				continue;
  		}
  
  		if (id_out)
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2235
  			*id_out = masked_id - id_base + out_base;
2a6db719c   Nipun Gupta   iommu/of: make of...
2236

746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2237
2238
2239
2240
  		pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x
  ",
  			np, map_name, map_mask, id_base, out_base,
  			id_len, id, masked_id - id_base + out_base);
2a6db719c   Nipun Gupta   iommu/of: make of...
2241
2242
  		return 0;
  	}
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2243
2244
2245
  	pr_info("%pOF: no %s translation for id 0x%x on %pOF
  ", np, map_name,
  		id, target && *target ? *target : NULL);
fb709b5e1   Jean-Philippe Brucker   of: Allow the iom...
2246
2247
2248
  
  	/* Bypasses translation */
  	if (id_out)
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2249
  		*id_out = id;
fb709b5e1   Jean-Philippe Brucker   of: Allow the iom...
2250
  	return 0;
2a6db719c   Nipun Gupta   iommu/of: make of...
2251
  }
746a71d02   Lorenzo Pieralisi   of/iommu: Make of...
2252
  EXPORT_SYMBOL_GPL(of_map_id);