Blame view

drivers/of/base.c 53.8 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
3482f2c52   Grant Likely   of: Create of_con...
18
  #include <linux/console.h>
611cad720   Shawn Guo   dt: add of_alias_...
19
  #include <linux/ctype.h>
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
20
  #include <linux/cpu.h>
97e873e5c   Stephen Rothwell   Start split out o...
21
22
  #include <linux/module.h>
  #include <linux/of.h>
5fa23530d   Sudeep Holla   of: base: add sup...
23
  #include <linux/of_device.h>
fd9fdb78a   Philipp Zabel   [media] of: move ...
24
  #include <linux/of_graph.h>
581b605a8   Stephen Rothwell   Consolidate of_fi...
25
  #include <linux/spinlock.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
26
  #include <linux/slab.h>
75b57ecf9   Grant Likely   of: Make device n...
27
  #include <linux/string.h>
a9f2f63a6   Jeremy Kerr   of: include linux...
28
  #include <linux/proc_fs.h>
581b605a8   Stephen Rothwell   Consolidate of_fi...
29

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

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

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

8a2b22a25   Grant Likely   of: Make devicetr...
41
  struct kset *of_kset;
75b57ecf9   Grant Likely   of: Make device n...
42
43
  
  /*
8a2b22a25   Grant Likely   of: Make devicetr...
44
45
46
47
   * 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...
48
   */
c05aba2bd   Pantelis Antoniou   of: rename of_ali...
49
  DEFINE_MUTEX(of_mutex);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
50

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

f42b0e18f   Rob Herring   of: add node name...
56
57
58
59
60
61
62
63
64
65
66
67
68
  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);
  }
1db5dec2d   Rob Herring   of: Add missing e...
69
  EXPORT_SYMBOL(of_node_name_eq);
f42b0e18f   Rob Herring   of: add node name...
70
71
72
73
74
75
76
77
  
  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;
  }
1db5dec2d   Rob Herring   of: Add missing e...
78
  EXPORT_SYMBOL(of_node_name_prefix);
f42b0e18f   Rob Herring   of: add node name...
79

97e873e5c   Stephen Rothwell   Start split out o...
80
81
  int of_n_addr_cells(struct device_node *np)
  {
8832963d8   Sergei Shtylyov   of: base: use of_...
82
  	u32 cells;
97e873e5c   Stephen Rothwell   Start split out o...
83
84
85
86
  
  	do {
  		if (np->parent)
  			np = np->parent;
8832963d8   Sergei Shtylyov   of: base: use of_...
87
88
  		if (!of_property_read_u32(np, "#address-cells", &cells))
  			return cells;
97e873e5c   Stephen Rothwell   Start split out o...
89
90
91
92
93
94
95
96
  	} while (np->parent);
  	/* No #address-cells property for the root node */
  	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
  }
  EXPORT_SYMBOL(of_n_addr_cells);
  
  int of_n_size_cells(struct device_node *np)
  {
8832963d8   Sergei Shtylyov   of: base: use of_...
97
  	u32 cells;
97e873e5c   Stephen Rothwell   Start split out o...
98
99
100
101
  
  	do {
  		if (np->parent)
  			np = np->parent;
8832963d8   Sergei Shtylyov   of: base: use of_...
102
103
  		if (!of_property_read_u32(np, "#size-cells", &cells))
  			return cells;
97e873e5c   Stephen Rothwell   Start split out o...
104
105
106
107
108
  	} while (np->parent);
  	/* No #size-cells property for the root node */
  	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
  }
  EXPORT_SYMBOL(of_n_size_cells);
0c3f061c1   Rob Herring   of: implement of_...
109
110
111
  #ifdef CONFIG_NUMA
  int __weak of_node_to_nid(struct device_node *np)
  {
c8fff7bc5   Konstantin Khlebnikov   of: return NUMA_N...
112
  	return NUMA_NO_NODE;
0c3f061c1   Rob Herring   of: implement of_...
113
114
  }
  #endif
0b3ce78e9   Frank Rowand   of: cache phandle...
115
116
117
118
119
120
121
122
  /*
   * Assumptions behind phandle_cache implementation:
   *   - phandle property values are in a contiguous range of 1..n
   *
   * If the assumptions do not hold, then
   *   - the phandle lookup overhead reduction provided by the cache
   *     will likely be less
   */
1cb5a0333   Frank Rowand   of: of_node_get()...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  
  static struct device_node **phandle_cache;
  static u32 phandle_cache_mask;
  
  /*
   * Caller must hold devtree_lock.
   */
  static void __of_free_phandle_cache(void)
  {
  	u32 cache_entries = phandle_cache_mask + 1;
  	u32 k;
  
  	if (!phandle_cache)
  		return;
  
  	for (k = 0; k < cache_entries; k++)
  		of_node_put(phandle_cache[k]);
  
  	kfree(phandle_cache);
  	phandle_cache = NULL;
  }
  
  int of_free_phandle_cache(void)
  {
  	unsigned long flags;
  
  	raw_spin_lock_irqsave(&devtree_lock, flags);
  
  	__of_free_phandle_cache();
  
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
  
  	return 0;
  }
  #if !defined(CONFIG_MODULES)
  late_initcall_sync(of_free_phandle_cache);
  #endif
8dbea6442   Frank Rowand   of: __of_detach_n...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  /*
   * Caller must hold devtree_lock.
   */
  void __of_free_phandle_cache_entry(phandle handle)
  {
  	phandle masked_handle;
  	struct device_node *np;
  
  	if (!handle)
  		return;
  
  	masked_handle = handle & phandle_cache_mask;
  
  	if (phandle_cache) {
  		np = phandle_cache[masked_handle];
  		if (np && handle == np->phandle) {
  			of_node_put(np);
  			phandle_cache[masked_handle] = NULL;
  		}
  	}
  }
b9952b521   Frank Rowand   of: overlay: upda...
181
  void of_populate_phandle_cache(void)
0b3ce78e9   Frank Rowand   of: cache phandle...
182
183
184
185
186
187
188
  {
  	unsigned long flags;
  	u32 cache_entries;
  	struct device_node *np;
  	u32 phandles = 0;
  
  	raw_spin_lock_irqsave(&devtree_lock, flags);
1cb5a0333   Frank Rowand   of: of_node_get()...
189
  	__of_free_phandle_cache();
0b3ce78e9   Frank Rowand   of: cache phandle...
190
191
192
193
  
  	for_each_of_allnodes(np)
  		if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)
  			phandles++;
e54192b48   Rob Herring   of: fix phandle c...
194
195
  	if (!phandles)
  		goto out;
0b3ce78e9   Frank Rowand   of: cache phandle...
196
197
198
199
200
201
202
203
204
  	cache_entries = roundup_pow_of_two(phandles);
  	phandle_cache_mask = cache_entries - 1;
  
  	phandle_cache = kcalloc(cache_entries, sizeof(*phandle_cache),
  				GFP_ATOMIC);
  	if (!phandle_cache)
  		goto out;
  
  	for_each_of_allnodes(np)
1cb5a0333   Frank Rowand   of: of_node_get()...
205
206
  		if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL) {
  			of_node_get(np);
0b3ce78e9   Frank Rowand   of: cache phandle...
207
  			phandle_cache[np->phandle & phandle_cache_mask] = np;
1cb5a0333   Frank Rowand   of: of_node_get()...
208
  		}
0b3ce78e9   Frank Rowand   of: cache phandle...
209
210
211
212
  
  out:
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
  }
194ec9368   Sudeep Holla   drivers: of/base:...
213
  void __init of_core_init(void)
75b57ecf9   Grant Likely   of: Make device n...
214
215
  {
  	struct device_node *np;
0b3ce78e9   Frank Rowand   of: cache phandle...
216
  	of_populate_phandle_cache();
75b57ecf9   Grant Likely   of: Make device n...
217
  	/* Create the kset, and register existing nodes */
c05aba2bd   Pantelis Antoniou   of: rename of_ali...
218
  	mutex_lock(&of_mutex);
75b57ecf9   Grant Likely   of: Make device n...
219
220
  	of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
  	if (!of_kset) {
c05aba2bd   Pantelis Antoniou   of: rename of_ali...
221
  		mutex_unlock(&of_mutex);
606ad42aa   Rob Herring   of: use pr_fmt pr...
222
223
  		pr_err("failed to register existing nodes
  ");
194ec9368   Sudeep Holla   drivers: of/base:...
224
  		return;
75b57ecf9   Grant Likely   of: Make device n...
225
226
  	}
  	for_each_of_allnodes(np)
8a2b22a25   Grant Likely   of: Make devicetr...
227
  		__of_attach_node_sysfs(np);
c05aba2bd   Pantelis Antoniou   of: rename of_ali...
228
  	mutex_unlock(&of_mutex);
75b57ecf9   Grant Likely   of: Make device n...
229

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

28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
235
236
  static struct property *__of_find_property(const struct device_node *np,
  					   const char *name, int *lenp)
581b605a8   Stephen Rothwell   Consolidate of_fi...
237
238
  {
  	struct property *pp;
64e4566f6   Timur Tabi   [POWERPC] Add nul...
239
240
  	if (!np)
  		return NULL;
a3a7cab17   Sachin Kamat   of: Fix null poin...
241
  	for (pp = np->properties; pp; pp = pp->next) {
581b605a8   Stephen Rothwell   Consolidate of_fi...
242
  		if (of_prop_cmp(pp->name, name) == 0) {
a3a7cab17   Sachin Kamat   of: Fix null poin...
243
  			if (lenp)
581b605a8   Stephen Rothwell   Consolidate of_fi...
244
245
246
247
  				*lenp = pp->length;
  			break;
  		}
  	}
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
248
249
250
251
252
253
254
255
256
  
  	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...
257
  	unsigned long flags;
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
258

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
259
  	raw_spin_lock_irqsave(&devtree_lock, flags);
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
260
  	pp = __of_find_property(np, name, lenp);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
261
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
581b605a8   Stephen Rothwell   Consolidate of_fi...
262
263
264
265
  
  	return pp;
  }
  EXPORT_SYMBOL(of_find_property);
5063e25a3   Grant Likely   of: Eliminate of_...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  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...
282
283
284
285
286
287
288
289
290
291
292
  /**
   * 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...
293
  	unsigned long flags;
e91edcf5a   Grant Likely   of: merge of_find...
294

d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
295
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
296
297
  	np = __of_find_all_nodes(prev);
  	of_node_get(np);
e91edcf5a   Grant Likely   of: merge of_find...
298
  	of_node_put(prev);
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
299
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
e91edcf5a   Grant Likely   of: merge of_find...
300
301
302
  	return np;
  }
  EXPORT_SYMBOL(of_find_all_nodes);
97e873e5c   Stephen Rothwell   Start split out o...
303
304
305
306
  /*
   * Find a property with a given name for a given node
   * and return the value.
   */
a25095d45   Grant Likely   of: Move dynamic ...
307
308
  const void *__of_get_property(const struct device_node *np,
  			      const char *name, int *lenp)
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
309
310
311
312
313
314
315
316
317
318
  {
  	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...
319
  const void *of_get_property(const struct device_node *np, const char *name,
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
320
  			    int *lenp)
97e873e5c   Stephen Rothwell   Start split out o...
321
322
323
324
325
326
  {
  	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...
327

183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  /*
   * 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);
f3cea45a7   Grant Likely   of: Fix iteration...
361
  	if (!cell || !ac)
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
362
  		return false;
f3cea45a7   Grant Likely   of: Fix iteration...
363
  	prop_len /= sizeof(*cell) * ac;
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
364
365
366
367
368
369
370
371
372
373
374
  	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...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
  /*
   * 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...
393
  	return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread);
d1cb9d1af   David Miller   of: Make cpu node...
394
  }
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  /**
   * 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...
411
412
   * 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...
413
414
415
   */
  struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
  {
d1cb9d1af   David Miller   of: Make cpu node...
416
  	struct device_node *cpun;
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
417

d1cb9d1af   David Miller   of: Make cpu node...
418
419
  	for_each_node_by_type(cpun, "cpu") {
  		if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread))
183912d35   Sudeep KarkadaNagesha   of: move of_get_c...
420
421
422
423
424
  			return cpun;
  	}
  	return NULL;
  }
  EXPORT_SYMBOL(of_get_cpu_node);
215a14cfa   Kevin Hao   of: reimplement t...
425
  /**
a0e71cd9b   Suzuki K Poulose   of: Add helper fo...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
   * 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);
  
  /**
215a14cfa   Kevin Hao   of: reimplement t...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
   * __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...
480
   */
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
481
  static int __of_device_is_compatible(const struct device_node *device,
215a14cfa   Kevin Hao   of: reimplement t...
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
  				     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...
501

215a14cfa   Kevin Hao   of: reimplement t...
502
503
504
505
506
  	/* Matching type is better than matching name */
  	if (type && type[0]) {
  		if (!device->type || of_node_cmp(type, device->type))
  			return 0;
  		score += 2;
0081cbc37   Stephen Rothwell   Consolidate of_de...
507
  	}
215a14cfa   Kevin Hao   of: reimplement t...
508
509
510
511
512
513
514
515
  	/* Matching name is a bit better than not */
  	if (name && name[0]) {
  		if (!device->name || of_node_cmp(name, device->name))
  			return 0;
  		score++;
  	}
  
  	return score;
0081cbc37   Stephen Rothwell   Consolidate of_de...
516
  }
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
517
518
519
520
521
522
523
  
  /** 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...
524
  	unsigned long flags;
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
525
  	int res;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
526
  	raw_spin_lock_irqsave(&devtree_lock, flags);
215a14cfa   Kevin Hao   of: reimplement t...
527
  	res = __of_device_is_compatible(device, compat, NULL, NULL);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
528
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
529
530
  	return res;
  }
0081cbc37   Stephen Rothwell   Consolidate of_de...
531
  EXPORT_SYMBOL(of_device_is_compatible);
e679c5f44   Stephen Rothwell   Consolidate of_ge...
532

b9c13fe32   Benjamin Herrenschmidt   dt: Add of_device...
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
  /** 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...
554
  /**
71a157e8e   Grant Likely   of: add 'of_' pre...
555
   * of_machine_is_compatible - Test root of device tree for a given compatible value
1f43cfb94   Grant Likely   of: merge machine...
556
557
   * @compat: compatible string to look for in root node's compatible property.
   *
25c7a1de6   Kevin Cernekee   of: Fix of_device...
558
   * Returns a positive integer if the root node has the given value in its
1f43cfb94   Grant Likely   of: merge machine...
559
560
   * compatible property.
   */
71a157e8e   Grant Likely   of: add 'of_' pre...
561
  int of_machine_is_compatible(const char *compat)
1f43cfb94   Grant Likely   of: merge machine...
562
563
564
565
566
567
568
569
570
571
572
  {
  	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...
573
  EXPORT_SYMBOL(of_machine_is_compatible);
1f43cfb94   Grant Likely   of: merge machine...
574
575
  
  /**
c31a0c052   Stephen Warren   of: fix recursive...
576
   *  __of_device_is_available - check if a device is available for use
834d97d45   Josh Boyer   [POWERPC] Add of_...
577
   *
c31a0c052   Stephen Warren   of: fix recursive...
578
   *  @device: Node to check for availability, with locks already held
834d97d45   Josh Boyer   [POWERPC] Add of_...
579
   *
53a4ab96c   Kevin Cernekee   of: Change of_dev...
580
581
   *  Returns true if the status property is absent or set to "okay" or "ok",
   *  false otherwise
834d97d45   Josh Boyer   [POWERPC] Add of_...
582
   */
53a4ab96c   Kevin Cernekee   of: Change of_dev...
583
  static bool __of_device_is_available(const struct device_node *device)
834d97d45   Josh Boyer   [POWERPC] Add of_...
584
585
586
  {
  	const char *status;
  	int statlen;
42ccd781b   Xiubo Li   of: Fix __of_devi...
587
  	if (!device)
53a4ab96c   Kevin Cernekee   of: Change of_dev...
588
  		return false;
42ccd781b   Xiubo Li   of: Fix __of_devi...
589

c31a0c052   Stephen Warren   of: fix recursive...
590
  	status = __of_get_property(device, "status", &statlen);
834d97d45   Josh Boyer   [POWERPC] Add of_...
591
  	if (status == NULL)
53a4ab96c   Kevin Cernekee   of: Change of_dev...
592
  		return true;
834d97d45   Josh Boyer   [POWERPC] Add of_...
593
594
595
  
  	if (statlen > 0) {
  		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
53a4ab96c   Kevin Cernekee   of: Change of_dev...
596
  			return true;
834d97d45   Josh Boyer   [POWERPC] Add of_...
597
  	}
53a4ab96c   Kevin Cernekee   of: Change of_dev...
598
  	return false;
834d97d45   Josh Boyer   [POWERPC] Add of_...
599
  }
c31a0c052   Stephen Warren   of: fix recursive...
600
601
602
603
604
605
  
  /**
   *  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...
606
607
   *  Returns true if the status property is absent or set to "okay" or "ok",
   *  false otherwise
c31a0c052   Stephen Warren   of: fix recursive...
608
   */
53a4ab96c   Kevin Cernekee   of: Change of_dev...
609
  bool of_device_is_available(const struct device_node *device)
c31a0c052   Stephen Warren   of: fix recursive...
610
611
  {
  	unsigned long flags;
53a4ab96c   Kevin Cernekee   of: Change of_dev...
612
  	bool res;
c31a0c052   Stephen Warren   of: fix recursive...
613
614
615
616
617
618
619
  
  	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_...
620
621
622
  EXPORT_SYMBOL(of_device_is_available);
  
  /**
37786c7fe   Kevin Cernekee   of: Add helper fu...
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
   *  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...
646
647
648
649
650
651
652
653
654
   *	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...
655
  	unsigned long flags;
e679c5f44   Stephen Rothwell   Consolidate of_ge...
656
657
658
  
  	if (!node)
  		return NULL;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
659
  	raw_spin_lock_irqsave(&devtree_lock, flags);
e679c5f44   Stephen Rothwell   Consolidate of_ge...
660
  	np = of_node_get(node->parent);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
661
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
e679c5f44   Stephen Rothwell   Consolidate of_ge...
662
663
664
  	return np;
  }
  EXPORT_SYMBOL(of_get_parent);
d1cd355a5   Stephen Rothwell   Consolidate of_ge...
665
666
  
  /**
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
667
668
669
   *	of_get_next_parent - Iterate to a node's parent
   *	@node:	Node to get parent of
   *
c0e848d8b   Geert Uytterhoeven   of: Remove spaces...
670
671
672
   *	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_...
673
674
675
676
677
678
679
   *
   *	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...
680
  	unsigned long flags;
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
681
682
683
  
  	if (!node)
  		return NULL;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
684
  	raw_spin_lock_irqsave(&devtree_lock, flags);
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
685
686
  	parent = of_node_get(node->parent);
  	of_node_put(node);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
687
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
688
689
  	return parent;
  }
6695be686   Guennadi Liakhovetski   [media] DT: expor...
690
  EXPORT_SYMBOL(of_get_next_parent);
f4eb01070   Michael Ellerman   [POWERPC] Add of_...
691

0d0e02d60   Grant Likely   of: Create unlock...
692
693
694
695
  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...
696
697
  	if (!node)
  		return NULL;
0d0e02d60   Grant Likely   of: Create unlock...
698
699
700
701
702
703
704
705
706
707
  	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_...
708
  /**
d1cd355a5   Stephen Rothwell   Consolidate of_ge...
709
710
711
712
   *	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...
713
714
715
   *	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...
716
717
718
719
720
   */
  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...
721
  	unsigned long flags;
d1cd355a5   Stephen Rothwell   Consolidate of_ge...
722

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
723
  	raw_spin_lock_irqsave(&devtree_lock, flags);
0d0e02d60   Grant Likely   of: Create unlock...
724
  	next = __of_get_next_child(node, prev);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
725
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
d1cd355a5   Stephen Rothwell   Consolidate of_ge...
726
727
728
  	return next;
  }
  EXPORT_SYMBOL(of_get_next_child);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
729
730
  
  /**
3296193d1   Timur Tabi   dt: introduce for...
731
732
733
734
735
736
737
738
739
740
741
   *	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...
742
  	unsigned long flags;
3296193d1   Timur Tabi   dt: introduce for...
743

43cb43678   Florian Fainelli   of: handle NULL n...
744
745
  	if (!node)
  		return NULL;
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
746
  	raw_spin_lock_irqsave(&devtree_lock, flags);
3296193d1   Timur Tabi   dt: introduce for...
747
748
  	next = prev ? prev->sibling : node->child;
  	for (; next; next = next->sibling) {
c31a0c052   Stephen Warren   of: fix recursive...
749
  		if (!__of_device_is_available(next))
3296193d1   Timur Tabi   dt: introduce for...
750
751
752
753
754
  			continue;
  		if (of_node_get(next))
  			break;
  	}
  	of_node_put(prev);
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
755
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
3296193d1   Timur Tabi   dt: introduce for...
756
757
758
759
760
  	return next;
  }
  EXPORT_SYMBOL(of_get_next_available_child);
  
  /**
36156f924   Johan Hovold   of: add helper to...
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
   * 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_...
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
   *	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)
  		if (child->name && (of_node_cmp(child->name, name) == 0))
  			break;
  	return child;
  }
  EXPORT_SYMBOL(of_get_child_by_name);
e0a58f3e0   Frank Rowand   of: overlay: remo...
807
  struct device_node *__of_find_node_by_path(struct device_node *parent,
c22e650e6   Grant Likely   of: Make of_find_...
808
809
810
  						const char *path)
  {
  	struct device_node *child;
106937e8c   Leif Lindholm   of: fix handling ...
811
  	int len;
c22e650e6   Grant Likely   of: Make of_find_...
812

721a09e95   Brian Norris   of: handle both '...
813
  	len = strcspn(path, "/:");
c22e650e6   Grant Likely   of: Make of_find_...
814
815
816
817
  	if (!len)
  		return NULL;
  
  	__for_each_child_of_node(parent, child) {
95e6b1fa3   Rob Herring   of: use kbasename...
818
  		const char *name = kbasename(child->full_name);
c22e650e6   Grant Likely   of: Make of_find_...
819
820
821
822
823
  		if (strncmp(path, name, len) == 0 && (strlen(name) == len))
  			return child;
  	}
  	return NULL;
  }
27497e11b   Rob Herring   of: find_node_by_...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
  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_...
841
  /**
75c28c09a   Leif Lindholm   of: add optional ...
842
   *	of_find_node_opts_by_path - Find a node matching a full OF path
c22e650e6   Grant Likely   of: Make of_find_...
843
844
845
846
   *	@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 ...
847
848
849
   *	@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_...
850
851
852
853
854
   *
   *	Valid paths:
   *		/foo/bar	Full path
   *		foo		Valid alias
   *		foo/bar		Valid alias + relative path
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
855
856
857
858
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.
   */
75c28c09a   Leif Lindholm   of: add optional ...
859
  struct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
860
  {
c22e650e6   Grant Likely   of: Make of_find_...
861
862
  	struct device_node *np = NULL;
  	struct property *pp;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
863
  	unsigned long flags;
75c28c09a   Leif Lindholm   of: add optional ...
864
865
866
867
  	const char *separator = strchr(path, ':');
  
  	if (opts)
  		*opts = separator ? separator + 1 : NULL;
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
868

c22e650e6   Grant Likely   of: Make of_find_...
869
  	if (strcmp(path, "/") == 0)
5063e25a3   Grant Likely   of: Eliminate of_...
870
  		return of_node_get(of_root);
c22e650e6   Grant Likely   of: Make of_find_...
871
872
873
  
  	/* The path could begin with an alias */
  	if (*path != '/') {
106937e8c   Leif Lindholm   of: fix handling ...
874
875
876
877
878
879
  		int len;
  		const char *p = separator;
  
  		if (!p)
  			p = strchrnul(path, '/');
  		len = p - path;
c22e650e6   Grant Likely   of: Make of_find_...
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
  
  		/* 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...
897
  	raw_spin_lock_irqsave(&devtree_lock, flags);
c22e650e6   Grant Likely   of: Make of_find_...
898
  	if (!np)
5063e25a3   Grant Likely   of: Eliminate of_...
899
  		np = of_node_get(of_root);
27497e11b   Rob Herring   of: find_node_by_...
900
  	np = __of_find_node_by_full_path(np, path);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
901
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
902
903
  	return np;
  }
75c28c09a   Leif Lindholm   of: add optional ...
904
  EXPORT_SYMBOL(of_find_node_opts_by_path);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
905
906
907
  
  /**
   *	of_find_node_by_name - Find a node by its "name" property
02a876b50   Stephen Boyd   of: Document exac...
908
   *	@from:	The node to start searching from or NULL; the node
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
909
   *		you pass will not be searched, only the next one
02a876b50   Stephen Boyd   of: Document exac...
910
911
   *		will. Typically, you pass what the previous call
   *		returned. of_node_put() will be called on @from.
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
912
913
914
915
916
917
918
919
920
   *	@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...
921
  	unsigned long flags;
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
922

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
923
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
924
  	for_each_of_allnodes_from(from, np)
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
925
926
927
928
  		if (np->name && (of_node_cmp(np->name, name) == 0)
  		    && of_node_get(np))
  			break;
  	of_node_put(from);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
929
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
  	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...
950
  	unsigned long flags;
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
951

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
952
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
953
  	for_each_of_allnodes_from(from, np)
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
954
955
956
957
  		if (np->type && (of_node_cmp(np->type, type) == 0)
  		    && of_node_get(np))
  			break;
  	of_node_put(from);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
958
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
  	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...
981
  	unsigned long flags;
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
982

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
983
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
984
  	for_each_of_allnodes_from(from, np)
215a14cfa   Kevin Hao   of: reimplement t...
985
  		if (__of_device_is_compatible(np, compatible, type, NULL) &&
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
986
  		    of_node_get(np))
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
987
  			break;
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
988
  	of_node_put(from);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
989
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1ef4d4242   Stephen Rothwell   Consolidate of_fi...
990
991
992
  	return np;
  }
  EXPORT_SYMBOL(of_find_compatible_node);
283029d16   Grant Likely   [POWERPC] Add of_...
993
994
  
  /**
1e291b14c   Michael Ellerman   of: Add helpers f...
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
   *	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...
1011
  	unsigned long flags;
1e291b14c   Michael Ellerman   of: Add helpers f...
1012

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1013
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
1014
  	for_each_of_allnodes_from(from, np) {
a3a7cab17   Sachin Kamat   of: Fix null poin...
1015
  		for (pp = np->properties; pp; pp = pp->next) {
1e291b14c   Michael Ellerman   of: Add helpers f...
1016
1017
1018
1019
1020
1021
1022
1023
  			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...
1024
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1e291b14c   Michael Ellerman   of: Add helpers f...
1025
1026
1027
  	return np;
  }
  EXPORT_SYMBOL(of_find_node_with_property);
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1028
1029
1030
  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_...
1031
  {
215a14cfa   Kevin Hao   of: reimplement t...
1032
1033
  	const struct of_device_id *best_match = NULL;
  	int score, best_score = 0;
a52f07ecd   Grant Likely   dt: protect again...
1034
1035
  	if (!matches)
  		return NULL;
215a14cfa   Kevin Hao   of: reimplement t...
1036
1037
1038
1039
1040
1041
1042
  	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:...
1043
  	}
215a14cfa   Kevin Hao   of: reimplement t...
1044
1045
  
  	return best_match;
283029d16   Grant Likely   [POWERPC] Add of_...
1046
  }
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1047
1048
  
  /**
c50949d32   Geert Uytterhoeven   of: Grammar s/an/a/
1049
   * of_match_node - Tell if a device_node has a matching of_match structure
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1050
1051
1052
   *	@matches:	array of of device match structures to search in
   *	@node:		the of device structure to match against
   *
71c5498ee   Kevin Hao   Revert "of: searc...
1053
   *	Low level utility function used by device matching.
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1054
1055
1056
1057
1058
   */
  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...
1059
  	unsigned long flags;
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1060

d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1061
  	raw_spin_lock_irqsave(&devtree_lock, flags);
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1062
  	match = __of_match_node(matches, node);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1063
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1064
1065
  	return match;
  }
283029d16   Grant Likely   [POWERPC] Add of_...
1066
1067
1068
  EXPORT_SYMBOL(of_match_node);
  
  /**
50c8af4cf   Stephen Warren   of: introduce for...
1069
1070
   *	of_find_matching_node_and_match - Find a node based on an of_device_id
   *					  match table.
283029d16   Grant Likely   [POWERPC] Add of_...
1071
1072
1073
1074
1075
   *	@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...
1076
   *	@match		Updated to point at the matches entry which matched
283029d16   Grant Likely   [POWERPC] Add of_...
1077
1078
1079
1080
   *
   *	Returns a node pointer with refcount incremented, use
   *	of_node_put() on it when done.
   */
50c8af4cf   Stephen Warren   of: introduce for...
1081
1082
1083
  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_...
1084
1085
  {
  	struct device_node *np;
dc71bcf1b   Thomas Abraham   of: fix incorrect...
1086
  	const struct of_device_id *m;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1087
  	unsigned long flags;
283029d16   Grant Likely   [POWERPC] Add of_...
1088

50c8af4cf   Stephen Warren   of: introduce for...
1089
1090
  	if (match)
  		*match = NULL;
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1091
  	raw_spin_lock_irqsave(&devtree_lock, flags);
5063e25a3   Grant Likely   of: Eliminate of_...
1092
  	for_each_of_allnodes_from(from, np) {
28d0e36bf   Thomas Gleixner   OF: Fixup resursi...
1093
  		m = __of_match_node(matches, np);
dc71bcf1b   Thomas Abraham   of: fix incorrect...
1094
  		if (m && of_node_get(np)) {
50c8af4cf   Stephen Warren   of: introduce for...
1095
  			if (match)
dc71bcf1b   Thomas Abraham   of: fix incorrect...
1096
  				*match = m;
283029d16   Grant Likely   [POWERPC] Add of_...
1097
  			break;
50c8af4cf   Stephen Warren   of: introduce for...
1098
  		}
283029d16   Grant Likely   [POWERPC] Add of_...
1099
1100
  	}
  	of_node_put(from);
d6d3c4e65   Thomas Gleixner   OF: convert devtr...
1101
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
283029d16   Grant Likely   [POWERPC] Add of_...
1102
1103
  	return np;
  }
80c2022e5   Grant Likely   of: Fix export of...
1104
  EXPORT_SYMBOL(of_find_matching_node_and_match);
3f07af494   Grant Likely   of: adapt of_find...
1105
1106
  
  /**
3f07af494   Grant Likely   of: adapt of_find...
1107
1108
1109
1110
1111
   * 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...
1112
1113
1114
1115
   * 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...
1116
   *
2ffe8c5f3   Grant Likely   of: refactor of_m...
1117
   * This routine returns 0 on success, <0 on failure.
3f07af494   Grant Likely   of: adapt of_find...
1118
1119
1120
   */
  int of_modalias_node(struct device_node *node, char *modalias, int len)
  {
2ffe8c5f3   Grant Likely   of: refactor of_m...
1121
1122
  	const char *compatible, *p;
  	int cplen;
3f07af494   Grant Likely   of: adapt of_find...
1123
1124
  
  	compatible = of_get_property(node, "compatible", &cplen);
2ffe8c5f3   Grant Likely   of: refactor of_m...
1125
  	if (!compatible || strlen(compatible) > cplen)
3f07af494   Grant Likely   of: adapt of_find...
1126
  		return -ENODEV;
3f07af494   Grant Likely   of: adapt of_find...
1127
  	p = strchr(compatible, ',');
2ffe8c5f3   Grant Likely   of: refactor of_m...
1128
  	strlcpy(modalias, p ? p + 1 : compatible, len);
3f07af494   Grant Likely   of: adapt of_find...
1129
1130
1131
  	return 0;
  }
  EXPORT_SYMBOL_GPL(of_modalias_node);
64b60e096   Anton Vorontsov   of: Add new helpe...
1132
  /**
89751a7cb   Jeremy Kerr   of: merge of_find...
1133
1134
1135
1136
1137
1138
1139
1140
   * 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...
1141
  	struct device_node *np = NULL;
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
1142
  	unsigned long flags;
0b3ce78e9   Frank Rowand   of: cache phandle...
1143
  	phandle masked_handle;
89751a7cb   Jeremy Kerr   of: merge of_find...
1144

fc59b4479   Grant Likely   of: Don't try to ...
1145
1146
  	if (!handle)
  		return NULL;
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
1147
  	raw_spin_lock_irqsave(&devtree_lock, flags);
0b3ce78e9   Frank Rowand   of: cache phandle...
1148
1149
1150
1151
1152
1153
1154
  
  	masked_handle = handle & phandle_cache_mask;
  
  	if (phandle_cache) {
  		if (phandle_cache[masked_handle] &&
  		    handle == phandle_cache[masked_handle]->phandle)
  			np = phandle_cache[masked_handle];
8dbea6442   Frank Rowand   of: __of_detach_n...
1155
1156
1157
1158
1159
1160
  		if (np && of_node_check_flag(np, OF_DETACHED)) {
  			WARN_ON(1); /* did not uncache np on node removal */
  			of_node_put(np);
  			phandle_cache[masked_handle] = NULL;
  			np = NULL;
  		}
0b3ce78e9   Frank Rowand   of: cache phandle...
1161
1162
1163
1164
  	}
  
  	if (!np) {
  		for_each_of_allnodes(np)
8dbea6442   Frank Rowand   of: __of_detach_n...
1165
1166
  			if (np->phandle == handle &&
  			    !of_node_check_flag(np, OF_DETACHED)) {
1cb5a0333   Frank Rowand   of: of_node_get()...
1167
1168
1169
  				if (phandle_cache) {
  					/* will put when removed from cache */
  					of_node_get(np);
0b3ce78e9   Frank Rowand   of: cache phandle...
1170
  					phandle_cache[masked_handle] = np;
1cb5a0333   Frank Rowand   of: of_node_get()...
1171
  				}
0b3ce78e9   Frank Rowand   of: cache phandle...
1172
1173
1174
  				break;
  			}
  	}
89751a7cb   Jeremy Kerr   of: merge of_find...
1175
  	of_node_get(np);
d25d86949   Benjamin Herrenschmidt   of: Fix locking v...
1176
  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
89751a7cb   Jeremy Kerr   of: merge of_find...
1177
1178
1179
  	return np;
  }
  EXPORT_SYMBOL(of_find_node_by_phandle);
624cfca53   Grant Likely   of: Add helper fo...
1180
1181
1182
  void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
  {
  	int i;
0d638a07d   Rob Herring   of: Convert to us...
1183
  	printk("%s %pOF", msg, args->np);
4aa663444   Marcin Nowakowski   drivers/of: fix m...
1184
1185
1186
1187
1188
1189
1190
  	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...
1191
  }
74e1fbb13   Joerg Roedel   of: Introduce str...
1192
1193
1194
1195
1196
  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...
1197
  {
74e1fbb13   Joerg Roedel   of: Introduce str...
1198
1199
1200
1201
  	const __be32 *list;
  	int size;
  
  	memset(it, 0, sizeof(*it));
64b60e096   Anton Vorontsov   of: Add new helpe...
1202
1203
  
  	list = of_get_property(np, list_name, &size);
15c9a0acc   Grant Likely   of: create of_pha...
1204
  	if (!list)
1af4c7f18   Alexandre Courbot   of: return -ENOEN...
1205
  		return -ENOENT;
64b60e096   Anton Vorontsov   of: Add new helpe...
1206

74e1fbb13   Joerg Roedel   of: Introduce str...
1207
1208
1209
1210
1211
1212
1213
1214
1215
  	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 ...
1216
  EXPORT_SYMBOL_GPL(of_phandle_iterator_init);
74e1fbb13   Joerg Roedel   of: Introduce str...
1217

cd209b412   Joerg Roedel   of: Move phandle ...
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
  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...
1236

15c9a0acc   Grant Likely   of: create of_pha...
1237
  		/*
cd209b412   Joerg Roedel   of: Move phandle ...
1238
1239
  		 * Find the provider node and parse the #*-cells property to
  		 * determine the argument length.
15c9a0acc   Grant Likely   of: create of_pha...
1240
  		 */
cd209b412   Joerg Roedel   of: Move phandle ...
1241
  		it->node = of_find_node_by_phandle(it->phandle);
035fd9482   Stephen Warren   of: introduce of_...
1242

cd209b412   Joerg Roedel   of: Move phandle ...
1243
1244
  		if (it->cells_name) {
  			if (!it->node) {
0d638a07d   Rob Herring   of: Convert to us...
1245
1246
1247
  				pr_err("%pOF: could not find phandle
  ",
  				       it->parent);
cd209b412   Joerg Roedel   of: Move phandle ...
1248
  				goto err;
15c9a0acc   Grant Likely   of: create of_pha...
1249
  			}
64b60e096   Anton Vorontsov   of: Add new helpe...
1250

cd209b412   Joerg Roedel   of: Move phandle ...
1251
1252
  			if (of_property_read_u32(it->node, it->cells_name,
  						 &count)) {
0d638a07d   Rob Herring   of: Convert to us...
1253
1254
1255
  				pr_err("%pOF: could not get %s for %pOF
  ",
  				       it->parent,
cd209b412   Joerg Roedel   of: Move phandle ...
1256
  				       it->cells_name,
0d638a07d   Rob Herring   of: Convert to us...
1257
  				       it->node);
23ce04c07   Grant Likely   of/base: Clean up...
1258
  				goto err;
15c9a0acc   Grant Likely   of: create of_pha...
1259
  			}
cd209b412   Joerg Roedel   of: Move phandle ...
1260
1261
  		} else {
  			count = it->cell_count;
64b60e096   Anton Vorontsov   of: Add new helpe...
1262
  		}
15c9a0acc   Grant Likely   of: create of_pha...
1263
  		/*
cd209b412   Joerg Roedel   of: Move phandle ...
1264
1265
1266
1267
  		 * Make sure that the arguments actually fit in the remaining
  		 * property data length
  		 */
  		if (it->cur + count > it->list_end) {
0d638a07d   Rob Herring   of: Convert to us...
1268
1269
1270
  			pr_err("%pOF: arguments longer than property
  ",
  			       it->parent);
cd209b412   Joerg Roedel   of: Move phandle ...
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
  			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 ...
1288
  EXPORT_SYMBOL_GPL(of_phandle_iterator_next);
cd209b412   Joerg Roedel   of: Move phandle ...
1289

abdaa77b1   Joerg Roedel   of: Introduce of_...
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
  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...
1306
1307
  static int __of_parse_phandle_with_args(const struct device_node *np,
  					const char *list_name,
035fd9482   Stephen Warren   of: introduce of_...
1308
1309
  					const char *cells_name,
  					int cell_count, int index,
bd69f73f2   Grant Likely   of: Create functi...
1310
  					struct of_phandle_args *out_args)
64b60e096   Anton Vorontsov   of: Add new helpe...
1311
  {
74e1fbb13   Joerg Roedel   of: Introduce str...
1312
1313
  	struct of_phandle_iterator it;
  	int rc, cur_index = 0;
64b60e096   Anton Vorontsov   of: Add new helpe...
1314

15c9a0acc   Grant Likely   of: create of_pha...
1315
  	/* Loop over the phandles until all the requested entry is found */
f623ce95a   Joerg Roedel   of: Introduce of_...
1316
  	of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) {
15c9a0acc   Grant Likely   of: create of_pha...
1317
  		/*
cd209b412   Joerg Roedel   of: Move phandle ...
1318
  		 * All of the error cases bail out of the loop, so at
15c9a0acc   Grant Likely   of: create of_pha...
1319
1320
1321
1322
  		 * 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...
1323
  		rc = -ENOENT;
15c9a0acc   Grant Likely   of: create of_pha...
1324
  		if (cur_index == index) {
74e1fbb13   Joerg Roedel   of: Introduce str...
1325
  			if (!it.phandle)
23ce04c07   Grant Likely   of/base: Clean up...
1326
  				goto err;
15c9a0acc   Grant Likely   of: create of_pha...
1327
1328
  
  			if (out_args) {
abdaa77b1   Joerg Roedel   of: Introduce of_...
1329
1330
1331
1332
1333
  				int c;
  
  				c = of_phandle_iterator_args(&it,
  							     out_args->args,
  							     MAX_PHANDLE_ARGS);
74e1fbb13   Joerg Roedel   of: Introduce str...
1334
  				out_args->np = it.node;
abdaa77b1   Joerg Roedel   of: Introduce of_...
1335
  				out_args->args_count = c;
b855f16b0   Tang Yuantian   of/base: release ...
1336
  			} else {
74e1fbb13   Joerg Roedel   of: Introduce str...
1337
  				of_node_put(it.node);
15c9a0acc   Grant Likely   of: create of_pha...
1338
  			}
23ce04c07   Grant Likely   of/base: Clean up...
1339
1340
  
  			/* Found it! return success */
15c9a0acc   Grant Likely   of: create of_pha...
1341
  			return 0;
64b60e096   Anton Vorontsov   of: Add new helpe...
1342
  		}
64b60e096   Anton Vorontsov   of: Add new helpe...
1343

64b60e096   Anton Vorontsov   of: Add new helpe...
1344
1345
  		cur_index++;
  	}
23ce04c07   Grant Likely   of/base: Clean up...
1346
1347
1348
1349
1350
  	/*
  	 * 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 ...
1351

23ce04c07   Grant Likely   of/base: Clean up...
1352
   err:
beab47d55   Markus Elfring   of: Delete an unn...
1353
  	of_node_put(it.node);
23ce04c07   Grant Likely   of/base: Clean up...
1354
  	return rc;
64b60e096   Anton Vorontsov   of: Add new helpe...
1355
  }
bd69f73f2   Grant Likely   of: Create functi...
1356

eded9dd40   Stephen Warren   of: move document...
1357
  /**
5fba49e3a   Stephen Warren   of: move of_parse...
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
   * 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...
1370
1371
1372
1373
  	struct of_phandle_args args;
  
  	if (index < 0)
  		return NULL;
5fba49e3a   Stephen Warren   of: move of_parse...
1374

91d9942c2   Stephen Warren   of: call __of_par...
1375
1376
  	if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0,
  					 index, &args))
5fba49e3a   Stephen Warren   of: move of_parse...
1377
  		return NULL;
91d9942c2   Stephen Warren   of: call __of_par...
1378
  	return args.np;
5fba49e3a   Stephen Warren   of: move of_parse...
1379
1380
1381
1382
  }
  EXPORT_SYMBOL(of_parse_phandle);
  
  /**
eded9dd40   Stephen Warren   of: move document...
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
   * 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...
1394
   * Caller is responsible to call of_node_put() on the returned out_args->np
eded9dd40   Stephen Warren   of: move document...
1395
1396
1397
1398
1399
   * pointer.
   *
   * Example:
   *
   * phandle1: node1 {
c0e848d8b   Geert Uytterhoeven   of: Remove spaces...
1400
   *	#list-cells = <2>;
eded9dd40   Stephen Warren   of: move document...
1401
1402
1403
   * }
   *
   * phandle2: node2 {
c0e848d8b   Geert Uytterhoeven   of: Remove spaces...
1404
   *	#list-cells = <1>;
eded9dd40   Stephen Warren   of: move document...
1405
1406
1407
   * }
   *
   * node3 {
c0e848d8b   Geert Uytterhoeven   of: Remove spaces...
1408
   *	list = <&phandle1 1 2 &phandle2 3>;
eded9dd40   Stephen Warren   of: move document...
1409
1410
1411
1412
1413
   * }
   *
   * 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...
1414
1415
1416
1417
1418
1419
  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)
  {
  	if (index < 0)
  		return -EINVAL;
035fd9482   Stephen Warren   of: introduce of_...
1420
1421
  	return __of_parse_phandle_with_args(np, list_name, cells_name, 0,
  					    index, out_args);
bd69f73f2   Grant Likely   of: Create functi...
1422
  }
15c9a0acc   Grant Likely   of: create of_pha...
1423
  EXPORT_SYMBOL(of_parse_phandle_with_args);
02af11b03   Grant Likely   of: merge prom_{a...
1424

bd69f73f2   Grant Likely   of: Create functi...
1425
  /**
bd6f2fd5a   Stephen Boyd   of: Support parsi...
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
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
1532
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
   * 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;
  
  	ret = __of_parse_phandle_with_args(np, list_name, cells_name, 0, index,
  					   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_...
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
   * 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...
1621
   * Caller is responsible to call of_node_put() on the returned out_args->np
035fd9482   Stephen Warren   of: introduce of_...
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
   * pointer.
   *
   * Example:
   *
   * phandle1: node1 {
   * }
   *
   * phandle2: node2 {
   * }
   *
   * node3 {
c0e848d8b   Geert Uytterhoeven   of: Remove spaces...
1633
   *	list = <&phandle1 0 2 &phandle2 2 3>;
035fd9482   Stephen Warren   of: introduce of_...
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
   * }
   *
   * 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...
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
   * 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...
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
  	struct of_phandle_iterator it;
  	int rc, cur_index = 0;
  
  	rc = of_phandle_iterator_init(&it, np, list_name, cells_name, 0);
  	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...
1682
1683
  }
  EXPORT_SYMBOL(of_count_phandle_with_args);
02af11b03   Grant Likely   of: merge prom_{a...
1684
  /**
62664f677   Xiubo Li   of: add __of_add_...
1685
1686
   * __of_add_property - Add a property to a node without lock operations
   */
d8c500884   Pantelis Antoniou   of: Create unlock...
1687
  int __of_add_property(struct device_node *np, struct property *prop)
62664f677   Xiubo Li   of: add __of_add_...
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
  {
  	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...
1706
   * of_add_property - Add a property to a node
02af11b03   Grant Likely   of: merge prom_{a...
1707
   */
79d1c7129   Nathan Fontenot   powerpc+of: Renam...
1708
  int of_add_property(struct device_node *np, struct property *prop)
02af11b03   Grant Likely   of: merge prom_{a...
1709
  {
02af11b03   Grant Likely   of: merge prom_{a...
1710
  	unsigned long flags;
1cf3d8b3d   Nathan Fontenot   powerpc+of: Add o...
1711
  	int rc;
8a2b22a25   Grant Likely   of: Make devicetr...
1712
  	mutex_lock(&of_mutex);
02af11b03   Grant Likely   of: merge prom_{a...
1713

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

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

8a2b22a25   Grant Likely   of: Make devicetr...
1721
  	mutex_unlock(&of_mutex);
259092a35   Grant Likely   of: Reorder devic...
1722
1723
  	if (!rc)
  		of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL);
62664f677   Xiubo Li   of: add __of_add_...
1724
  	return rc;
02af11b03   Grant Likely   of: merge prom_{a...
1725
  }
d8c500884   Pantelis Antoniou   of: Create unlock...
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
  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...
1744
  /**
79d1c7129   Nathan Fontenot   powerpc+of: Renam...
1745
   * of_remove_property - Remove a property from a node.
02af11b03   Grant Likely   of: merge prom_{a...
1746
1747
1748
1749
1750
1751
   *
   * 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...
1752
  int of_remove_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;
201b3fe58   Suraj Jitindar Singh   drivers/of: Add c...
1756
1757
  	if (!prop)
  		return -ENODEV;
8a2b22a25   Grant Likely   of: Make devicetr...
1758
  	mutex_lock(&of_mutex);
02af11b03   Grant Likely   of: merge prom_{a...
1759

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

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

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

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

8a2b22a25   Grant Likely   of: Make devicetr...
1772
  	return rc;
02af11b03   Grant Likely   of: merge prom_{a...
1773
  }
d8c500884   Pantelis Antoniou   of: Create unlock...
1774
1775
  int __of_update_property(struct device_node *np, struct property *newprop,
  		struct property **oldpropp)
02af11b03   Grant Likely   of: merge prom_{a...
1776
  {
475d00942   Dong Aisheng   of: Improve prom_...
1777
  	struct property **next, *oldprop;
02af11b03   Grant Likely   of: merge prom_{a...
1778

d8c500884   Pantelis Antoniou   of: Create unlock...
1779
1780
1781
1782
1783
  	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_...
1784

d8c500884   Pantelis Antoniou   of: Create unlock...
1785
  	if (oldprop) {
947fdaad0   Xiubo Li   of: fix race betw...
1786
  		/* replace the node */
d8c500884   Pantelis Antoniou   of: Create unlock...
1787
1788
1789
1790
1791
1792
1793
1794
  		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...
1795
  	}
75b57ecf9   Grant Likely   of: Make device n...
1796

d8c500884   Pantelis Antoniou   of: Create unlock...
1797
1798
  	return 0;
  }
fcdeb7fed   Grant Likely   of: merge of_atta...
1799
  /*
79d1c7129   Nathan Fontenot   powerpc+of: Renam...
1800
   * of_update_property - Update a property in a node, if the property does
475d00942   Dong Aisheng   of: Improve prom_...
1801
   * not exist, add it.
fcdeb7fed   Grant Likely   of: merge of_atta...
1802
   *
02af11b03   Grant Likely   of: merge prom_{a...
1803
1804
1805
1806
   * 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...
1807
   */
79d1c7129   Nathan Fontenot   powerpc+of: Renam...
1808
  int of_update_property(struct device_node *np, struct property *newprop)
fcdeb7fed   Grant Likely   of: merge of_atta...
1809
  {
d8c500884   Pantelis Antoniou   of: Create unlock...
1810
  	struct property *oldprop;
fcdeb7fed   Grant Likely   of: merge of_atta...
1811
  	unsigned long flags;
1cf3d8b3d   Nathan Fontenot   powerpc+of: Add o...
1812
  	int rc;
d8c500884   Pantelis Antoniou   of: Create unlock...
1813
1814
  	if (!newprop->name)
  		return -EINVAL;
1cf3d8b3d   Nathan Fontenot   powerpc+of: Add o...
1815

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

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

8a2b22a25   Grant Likely   of: Make devicetr...
1822
1823
  	if (!rc)
  		__of_update_property_sysfs(np, newprop, oldprop);
fcdeb7fed   Grant Likely   of: merge of_atta...
1824

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

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

1cf3d8b3d   Nathan Fontenot   powerpc+of: Add o...
1830
  	return rc;
fcdeb7fed   Grant Likely   of: merge of_atta...
1831
  }
fcdeb7fed   Grant Likely   of: merge of_atta...
1832

611cad720   Shawn Guo   dt: add of_alias_...
1833
1834
1835
1836
1837
1838
1839
1840
  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...
1841
1842
1843
  	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_...
1844
  }
e1a87ff45   Haibo Chen   MLK-17621-2 mmc: ...
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
  /*
   * of_alias_max_index() - get the maximum index for a given alias stem
   * @stem:   The alias stem for which the maximum index is searched for
   *
   * Given an alias stem (the alias without the number) this function
   * returns the maximum number for which an alias exists.
   *
   * Return: The maximum existing alias index or -ENODEV if no alias
   *         exists for this stem.
   */
  int of_alias_max_index(const char *stem)
  {
  	struct alias_prop *app;
  	int max = -ENODEV;
  
  	mutex_lock(&of_mutex);
  
  	list_for_each_entry(app, &aliases_lookup, link) {
  		if (strcmp(app->stem, stem))
  			continue;
  		if (app->id > max)
  			max = app->id;
  	}
  
  	mutex_unlock(&of_mutex);
  
  	return max;
  }
  EXPORT_SYMBOL_GPL(of_alias_max_index);
611cad720   Shawn Guo   dt: add of_alias_...
1874
  /**
1821dda4a   Geert Uytterhoeven   of: Improve gramm...
1875
   * of_alias_scan - Scan all properties of the 'aliases' node
611cad720   Shawn Guo   dt: add of_alias_...
1876
   *
1821dda4a   Geert Uytterhoeven   of: Improve gramm...
1877
1878
1879
   * 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_...
1880
1881
   *
   * @dt_alloc:	An allocator that provides a virtual address to memory
1821dda4a   Geert Uytterhoeven   of: Improve gramm...
1882
   *		for storing the resulting tree
611cad720   Shawn Guo   dt: add of_alias_...
1883
1884
1885
1886
   */
  void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
  {
  	struct property *pp;
7dbe5849f   Laurentiu Tudor   of: make sure of_...
1887
  	of_aliases = of_find_node_by_path("/aliases");
611cad720   Shawn Guo   dt: add of_alias_...
1888
1889
1890
  	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...
1891
1892
  
  	if (of_chosen) {
a752ee56a   Grant Likely   tty: Update hyper...
1893
  		/* linux,stdout-path and /aliases/stdout are for legacy compatibility */
b0d9d92f9   Sergei Shtylyov   of: base: use of_...
1894
1895
1896
1897
1898
  		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...
1899
  		if (IS_ENABLED(CONFIG_PPC) && !name)
b0d9d92f9   Sergei Shtylyov   of: base: use of_...
1900
  			of_property_read_string(of_aliases, "stdout", &name);
f64255b50   Peter Hurley   Revert "of: Fix p...
1901
  		if (name)
7914a7c56   Leif Lindholm   of: support passi...
1902
  			of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
5c19e9521   Sascha Hauer   OF: Add helper fo...
1903
  	}
611cad720   Shawn Guo   dt: add of_alias_...
1904
1905
  	if (!of_aliases)
  		return;
8af0da93d   Dong Aisheng   dt: reform for_ea...
1906
  	for_each_property_of_node(of_aliases, pp) {
611cad720   Shawn Guo   dt: add of_alias_...
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
  		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...
1933
  		ap = dt_alloc(sizeof(*ap) + len + 1, __alignof__(*ap));
611cad720   Shawn Guo   dt: add of_alias_...
1934
1935
  		if (!ap)
  			continue;
0640332e0   Grant Likely   of: Fix missing m...
1936
  		memset(ap, 0, sizeof(*ap) + len + 1);
611cad720   Shawn Guo   dt: add of_alias_...
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
  		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...
1947
1948
   * 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_...
1949
1950
1951
1952
1953
   */
  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...
1954
  	mutex_lock(&of_mutex);
611cad720   Shawn Guo   dt: add of_alias_...
1955
1956
1957
1958
1959
1960
1961
1962
1963
  	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...
1964
  	mutex_unlock(&of_mutex);
611cad720   Shawn Guo   dt: add of_alias_...
1965
1966
1967
1968
  
  	return id;
  }
  EXPORT_SYMBOL_GPL(of_alias_get_id);
c541adc63   Stephen Warren   dt: add property ...
1969

351d224f6   Wolfram Sang   of: base: add fun...
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
  /**
   * 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...
1995
  /**
3482f2c52   Grant Likely   of: Create of_con...
1996
1997
1998
1999
2000
2001
2002
2003
   * 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...
2004
   */
3482f2c52   Grant Likely   of: Create of_con...
2005
  bool of_console_check(struct device_node *dn, char *name, int index)
5c19e9521   Sascha Hauer   OF: Add helper fo...
2006
  {
3482f2c52   Grant Likely   of: Create of_con...
2007
  	if (!dn || dn != of_stdout || console_set_on_cmdline)
5c19e9521   Sascha Hauer   OF: Add helper fo...
2008
  		return false;
db179e0d0   Sergey Senozhatsky   of: do not leak c...
2009
2010
2011
2012
2013
2014
  
  	/*
  	 * 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...
2015
  }
3482f2c52   Grant Likely   of: Create of_con...
2016
  EXPORT_SYMBOL_GPL(of_console_check);
a3e31b458   Sudeep KarkadaNagesha   of: Move definiti...
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
  
  /**
   *	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...
2028
  	struct device_node *child, *cache_node;
a3e31b458   Sudeep KarkadaNagesha   of: Move definiti...
2029

91d967497   Rob Herring   of: fix sparse wa...
2030
2031
2032
  	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...
2033

91d967497   Rob Herring   of: fix sparse wa...
2034
2035
  	if (cache_node)
  		return cache_node;
a3e31b458   Sudeep KarkadaNagesha   of: Move definiti...
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
  
  	/* OF on pmac has nodes instead of properties named "l2-cache"
  	 * beneath CPU nodes.
  	 */
  	if (!strcmp(np->type, "cpu"))
  		for_each_child_of_node(np, child)
  			if (!strcmp(child->type, "cache"))
  				return child;
  
  	return NULL;
  }
fd9fdb78a   Philipp Zabel   [media] of: move ...
2047
2048
  
  /**
5fa23530d   Sudeep Holla   of: base: add sup...
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
   * 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;
  }