Blame view

drivers/base/property.c 32 KB
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
1
2
3
4
5
6
7
8
9
10
11
  /*
   * property.c - Unified device property interface.
   *
   * Copyright (C) 2014, Intel Corporation
   * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
   *          Mika Westerberg <mika.westerberg@linux.intel.com>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
12
  #include <linux/acpi.h>
16ba08d5c   Rafael J. Wysocki   device property: ...
13
14
  #include <linux/export.h>
  #include <linux/kernel.h>
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
15
  #include <linux/of.h>
05ca55600   Suthikulpanit, Suravee   device property: ...
16
  #include <linux/of_address.h>
16ba08d5c   Rafael J. Wysocki   device property: ...
17
  #include <linux/property.h>
4c96b7dc0   Jeremy Linton   Add a matching se...
18
19
  #include <linux/etherdevice.h>
  #include <linux/phy.h>
16ba08d5c   Rafael J. Wysocki   device property: ...
20

f4d052660   Heikki Krogerus   device property: ...
21
22
23
24
  struct property_set {
  	struct fwnode_handle fwnode;
  	struct property_entry *properties;
  };
61f5e294b   Andy Shevchenko   device property: ...
25
  static inline bool is_pset_node(struct fwnode_handle *fwnode)
16ba08d5c   Rafael J. Wysocki   device property: ...
26
  {
0224a4a30   Heikki Krogerus   device property: ...
27
  	return !IS_ERR_OR_NULL(fwnode) && fwnode->type == FWNODE_PDATA;
16ba08d5c   Rafael J. Wysocki   device property: ...
28
  }
61f5e294b   Andy Shevchenko   device property: ...
29
  static inline struct property_set *to_pset_node(struct fwnode_handle *fwnode)
16ba08d5c   Rafael J. Wysocki   device property: ...
30
  {
61f5e294b   Andy Shevchenko   device property: ...
31
  	return is_pset_node(fwnode) ?
16ba08d5c   Rafael J. Wysocki   device property: ...
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  		container_of(fwnode, struct property_set, fwnode) : NULL;
  }
  
  static struct property_entry *pset_prop_get(struct property_set *pset,
  					    const char *name)
  {
  	struct property_entry *prop;
  
  	if (!pset || !pset->properties)
  		return NULL;
  
  	for (prop = pset->properties; prop->name; prop++)
  		if (!strcmp(name, prop->name))
  			return prop;
  
  	return NULL;
  }
318a19718   Andy Shevchenko   device property: ...
49
50
  static void *pset_prop_find(struct property_set *pset, const char *propname,
  			    size_t length)
16ba08d5c   Rafael J. Wysocki   device property: ...
51
52
  {
  	struct property_entry *prop;
318a19718   Andy Shevchenko   device property: ...
53
  	void *pointer;
16ba08d5c   Rafael J. Wysocki   device property: ...
54

318a19718   Andy Shevchenko   device property: ...
55
56
57
  	prop = pset_prop_get(pset, propname);
  	if (!prop)
  		return ERR_PTR(-EINVAL);
66586baba   Andy Shevchenko   device property: ...
58
59
60
61
  	if (prop->is_array)
  		pointer = prop->pointer.raw_data;
  	else
  		pointer = &prop->value.raw_data;
318a19718   Andy Shevchenko   device property: ...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  	if (!pointer)
  		return ERR_PTR(-ENODATA);
  	if (length > prop->length)
  		return ERR_PTR(-EOVERFLOW);
  	return pointer;
  }
  
  static int pset_prop_read_u8_array(struct property_set *pset,
  				   const char *propname,
  				   u8 *values, size_t nval)
  {
  	void *pointer;
  	size_t length = nval * sizeof(*values);
  
  	pointer = pset_prop_find(pset, propname, length);
  	if (IS_ERR(pointer))
  		return PTR_ERR(pointer);
  
  	memcpy(values, pointer, length);
  	return 0;
  }
  
  static int pset_prop_read_u16_array(struct property_set *pset,
  				    const char *propname,
  				    u16 *values, size_t nval)
  {
  	void *pointer;
  	size_t length = nval * sizeof(*values);
  
  	pointer = pset_prop_find(pset, propname, length);
  	if (IS_ERR(pointer))
  		return PTR_ERR(pointer);
  
  	memcpy(values, pointer, length);
  	return 0;
  }
  
  static int pset_prop_read_u32_array(struct property_set *pset,
  				    const char *propname,
  				    u32 *values, size_t nval)
  {
  	void *pointer;
  	size_t length = nval * sizeof(*values);
  
  	pointer = pset_prop_find(pset, propname, length);
  	if (IS_ERR(pointer))
  		return PTR_ERR(pointer);
  
  	memcpy(values, pointer, length);
  	return 0;
  }
  
  static int pset_prop_read_u64_array(struct property_set *pset,
  				    const char *propname,
  				    u64 *values, size_t nval)
  {
  	void *pointer;
  	size_t length = nval * sizeof(*values);
  
  	pointer = pset_prop_find(pset, propname, length);
  	if (IS_ERR(pointer))
  		return PTR_ERR(pointer);
  
  	memcpy(values, pointer, length);
  	return 0;
  }
  
  static int pset_prop_count_elems_of_size(struct property_set *pset,
  					 const char *propname, size_t length)
  {
  	struct property_entry *prop;
  
  	prop = pset_prop_get(pset, propname);
16ba08d5c   Rafael J. Wysocki   device property: ...
135
  	if (!prop)
16ba08d5c   Rafael J. Wysocki   device property: ...
136
  		return -EINVAL;
318a19718   Andy Shevchenko   device property: ...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  
  	return prop->length / length;
  }
  
  static int pset_prop_read_string_array(struct property_set *pset,
  				       const char *propname,
  				       const char **strings, size_t nval)
  {
  	void *pointer;
  	size_t length = nval * sizeof(*strings);
  
  	pointer = pset_prop_find(pset, propname, length);
  	if (IS_ERR(pointer))
  		return PTR_ERR(pointer);
  
  	memcpy(strings, pointer, length);
16ba08d5c   Rafael J. Wysocki   device property: ...
153
154
  	return 0;
  }
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
155

66586baba   Andy Shevchenko   device property: ...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  static int pset_prop_read_string(struct property_set *pset,
  				 const char *propname, const char **strings)
  {
  	struct property_entry *prop;
  	const char **pointer;
  
  	prop = pset_prop_get(pset, propname);
  	if (!prop)
  		return -EINVAL;
  	if (!prop->is_string)
  		return -EILSEQ;
  	if (prop->is_array) {
  		pointer = prop->pointer.str;
  		if (!pointer)
  			return -ENODATA;
  	} else {
  		pointer = &prop->value.str;
  		if (*pointer && strnlen(*pointer, prop->length) >= prop->length)
  			return -EILSEQ;
  	}
  
  	*strings = *pointer;
  	return 0;
  }
9017f2525   Rafael J. Wysocki   driver core: Impl...
180
181
182
183
184
  static inline struct fwnode_handle *dev_fwnode(struct device *dev)
  {
  	return IS_ENABLED(CONFIG_OF) && dev->of_node ?
  		&dev->of_node->fwnode : dev->fwnode;
  }
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
185
186
187
188
189
190
191
192
193
194
  
  /**
   * device_property_present - check if a property of a device is present
   * @dev: Device whose property is being checked
   * @propname: Name of the property
   *
   * Check if property @propname is present in the device firmware description.
   */
  bool device_property_present(struct device *dev, const char *propname)
  {
9017f2525   Rafael J. Wysocki   driver core: Impl...
195
  	return fwnode_property_present(dev_fwnode(dev), propname);
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
196
197
  }
  EXPORT_SYMBOL_GPL(device_property_present);
362c0b302   Andy Shevchenko   device property: ...
198
199
  static bool __fwnode_property_present(struct fwnode_handle *fwnode,
  				      const char *propname)
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
200
201
  {
  	if (is_of_node(fwnode))
c181fb3e7   Alexander Sverdlin   ACPI / OF: Rename...
202
  		return of_property_read_bool(to_of_node(fwnode), propname);
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
203
  	else if (is_acpi_node(fwnode))
3a7a2ab83   Rafael J. Wysocki   ACPI / property: ...
204
  		return !acpi_node_prop_get(fwnode, propname, NULL);
61f5e294b   Andy Shevchenko   device property: ...
205
206
  	else if (is_pset_node(fwnode))
  		return !!pset_prop_get(to_pset_node(fwnode), propname);
e3f9e299b   Andy Shevchenko   device property: ...
207
  	return false;
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
208
  }
362c0b302   Andy Shevchenko   device property: ...
209
210
211
212
213
214
215
216
217
218
219
  
  /**
   * fwnode_property_present - check if a property of a firmware node is present
   * @fwnode: Firmware node whose property to check
   * @propname: Name of the property
   */
  bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
  {
  	bool ret;
  
  	ret = __fwnode_property_present(fwnode, propname);
0d67e0fa1   Heikki Krogerus   device property: ...
220
221
  	if (ret == false && !IS_ERR_OR_NULL(fwnode) &&
  	    !IS_ERR_OR_NULL(fwnode->secondary))
362c0b302   Andy Shevchenko   device property: ...
222
223
224
  		ret = __fwnode_property_present(fwnode->secondary, propname);
  	return ret;
  }
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
225
  EXPORT_SYMBOL_GPL(fwnode_property_present);
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
226
227
228
229
  /**
   * device_property_read_u8_array - return a u8 array property of a device
   * @dev: Device to get the property of
   * @propname: Name of the property
5c0acf3b4   Adrian Hunter   driver core: Add ...
230
   * @val: The values are stored here or %NULL to return the number of values
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
231
232
233
234
235
   * @nval: Size of the @val array
   *
   * Function reads an array of u8 properties with @propname from the device
   * firmware description and stores them to @val if found.
   *
5c0acf3b4   Adrian Hunter   driver core: Add ...
236
237
   * Return: number of values if @val was %NULL,
   *         %0 if the property was found (success),
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
238
239
240
241
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of numbers,
   *	   %-EOVERFLOW if the size of the property is not as expected.
4fa7508e9   Guenter Roeck   device property: ...
242
   *	   %-ENXIO if no suitable firmware interface is present.
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
243
244
245
246
   */
  int device_property_read_u8_array(struct device *dev, const char *propname,
  				  u8 *val, size_t nval)
  {
9017f2525   Rafael J. Wysocki   driver core: Impl...
247
  	return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval);
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
248
249
250
251
252
253
254
  }
  EXPORT_SYMBOL_GPL(device_property_read_u8_array);
  
  /**
   * device_property_read_u16_array - return a u16 array property of a device
   * @dev: Device to get the property of
   * @propname: Name of the property
5c0acf3b4   Adrian Hunter   driver core: Add ...
255
   * @val: The values are stored here or %NULL to return the number of values
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
256
257
258
259
260
   * @nval: Size of the @val array
   *
   * Function reads an array of u16 properties with @propname from the device
   * firmware description and stores them to @val if found.
   *
5c0acf3b4   Adrian Hunter   driver core: Add ...
261
262
   * Return: number of values if @val was %NULL,
   *         %0 if the property was found (success),
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
263
264
265
266
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of numbers,
   *	   %-EOVERFLOW if the size of the property is not as expected.
4fa7508e9   Guenter Roeck   device property: ...
267
   *	   %-ENXIO if no suitable firmware interface is present.
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
268
269
270
271
   */
  int device_property_read_u16_array(struct device *dev, const char *propname,
  				   u16 *val, size_t nval)
  {
9017f2525   Rafael J. Wysocki   driver core: Impl...
272
  	return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval);
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
273
274
275
276
277
278
279
  }
  EXPORT_SYMBOL_GPL(device_property_read_u16_array);
  
  /**
   * device_property_read_u32_array - return a u32 array property of a device
   * @dev: Device to get the property of
   * @propname: Name of the property
5c0acf3b4   Adrian Hunter   driver core: Add ...
280
   * @val: The values are stored here or %NULL to return the number of values
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
281
282
283
284
285
   * @nval: Size of the @val array
   *
   * Function reads an array of u32 properties with @propname from the device
   * firmware description and stores them to @val if found.
   *
5c0acf3b4   Adrian Hunter   driver core: Add ...
286
287
   * Return: number of values if @val was %NULL,
   *         %0 if the property was found (success),
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
288
289
290
291
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of numbers,
   *	   %-EOVERFLOW if the size of the property is not as expected.
4fa7508e9   Guenter Roeck   device property: ...
292
   *	   %-ENXIO if no suitable firmware interface is present.
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
293
294
295
296
   */
  int device_property_read_u32_array(struct device *dev, const char *propname,
  				   u32 *val, size_t nval)
  {
9017f2525   Rafael J. Wysocki   driver core: Impl...
297
  	return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval);
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
298
299
300
301
302
303
304
  }
  EXPORT_SYMBOL_GPL(device_property_read_u32_array);
  
  /**
   * device_property_read_u64_array - return a u64 array property of a device
   * @dev: Device to get the property of
   * @propname: Name of the property
5c0acf3b4   Adrian Hunter   driver core: Add ...
305
   * @val: The values are stored here or %NULL to return the number of values
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
306
307
308
309
310
   * @nval: Size of the @val array
   *
   * Function reads an array of u64 properties with @propname from the device
   * firmware description and stores them to @val if found.
   *
5c0acf3b4   Adrian Hunter   driver core: Add ...
311
312
   * Return: number of values if @val was %NULL,
   *         %0 if the property was found (success),
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
313
314
315
316
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of numbers,
   *	   %-EOVERFLOW if the size of the property is not as expected.
4fa7508e9   Guenter Roeck   device property: ...
317
   *	   %-ENXIO if no suitable firmware interface is present.
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
318
319
320
321
   */
  int device_property_read_u64_array(struct device *dev, const char *propname,
  				   u64 *val, size_t nval)
  {
9017f2525   Rafael J. Wysocki   driver core: Impl...
322
  	return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval);
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
323
324
325
326
327
328
329
  }
  EXPORT_SYMBOL_GPL(device_property_read_u64_array);
  
  /**
   * device_property_read_string_array - return a string array property of device
   * @dev: Device to get the property of
   * @propname: Name of the property
5c0acf3b4   Adrian Hunter   driver core: Add ...
330
   * @val: The values are stored here or %NULL to return the number of values
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
331
332
333
334
335
   * @nval: Size of the @val array
   *
   * Function reads an array of string properties with @propname from the device
   * firmware description and stores them to @val if found.
   *
5c0acf3b4   Adrian Hunter   driver core: Add ...
336
337
   * Return: number of values if @val was %NULL,
   *         %0 if the property was found (success),
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
338
339
340
341
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO or %-EILSEQ if the property is not an array of strings,
   *	   %-EOVERFLOW if the size of the property is not as expected.
4fa7508e9   Guenter Roeck   device property: ...
342
   *	   %-ENXIO if no suitable firmware interface is present.
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
343
344
345
346
   */
  int device_property_read_string_array(struct device *dev, const char *propname,
  				      const char **val, size_t nval)
  {
9017f2525   Rafael J. Wysocki   driver core: Impl...
347
  	return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval);
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  }
  EXPORT_SYMBOL_GPL(device_property_read_string_array);
  
  /**
   * device_property_read_string - return a string property of a device
   * @dev: Device to get the property of
   * @propname: Name of the property
   * @val: The value is stored here
   *
   * Function reads property @propname from the device firmware description and
   * stores the value into @val if found. The value is checked to be a string.
   *
   * Return: %0 if the property was found (success),
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO or %-EILSEQ if the property type is not a string.
4fa7508e9   Guenter Roeck   device property: ...
364
   *	   %-ENXIO if no suitable firmware interface is present.
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
365
366
367
368
   */
  int device_property_read_string(struct device *dev, const char *propname,
  				const char **val)
  {
9017f2525   Rafael J. Wysocki   driver core: Impl...
369
  	return fwnode_property_read_string(dev_fwnode(dev), propname, val);
b31384fa5   Rafael J. Wysocki   Driver core: Unif...
370
371
  }
  EXPORT_SYMBOL_GPL(device_property_read_string);
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
372

3f5c8d318   Mika Westerberg   device property: ...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
  /**
   * device_property_match_string - find a string in an array and return index
   * @dev: Device to get the property of
   * @propname: Name of the property holding the array
   * @string: String to look for
   *
   * Find a given string in a string array and if it is found return the
   * index back.
   *
   * Return: %0 if the property was found (success),
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of strings,
   *	   %-ENXIO if no suitable firmware interface is present.
   */
  int device_property_match_string(struct device *dev, const char *propname,
  				 const char *string)
  {
  	return fwnode_property_match_string(dev_fwnode(dev), propname, string);
  }
  EXPORT_SYMBOL_GPL(device_property_match_string);
1d656fb75   Andy Shevchenko   device property: ...
394
395
  #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval)				\
  	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval))	\
9017f2525   Rafael J. Wysocki   driver core: Impl...
396
  	      : of_property_count_elems_of_size((node), (propname), sizeof(type))
318a19718   Andy Shevchenko   device property: ...
397
398
399
  #define PSET_PROP_READ_ARRAY(node, propname, type, val, nval)				\
  	(val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval))	\
  	      : pset_prop_count_elems_of_size((node), (propname), sizeof(type))
362c0b302   Andy Shevchenko   device property: ...
400
  #define FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_)	\
1d656fb75   Andy Shevchenko   device property: ...
401
402
403
404
405
406
407
408
  ({											\
  	int _ret_;									\
  	if (is_of_node(_fwnode_))							\
  		_ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_,	\
  					       _type_, _val_, _nval_);			\
  	else if (is_acpi_node(_fwnode_))						\
  		_ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_,		\
  					    _val_, _nval_);				\
61f5e294b   Andy Shevchenko   device property: ...
409
  	else if (is_pset_node(_fwnode_)) 						\
318a19718   Andy Shevchenko   device property: ...
410
411
  		_ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_,	\
  					     _type_, _val_, _nval_);			\
1d656fb75   Andy Shevchenko   device property: ...
412
413
414
  	else										\
  		_ret_ = -ENXIO;								\
  	_ret_;										\
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
415
  })
362c0b302   Andy Shevchenko   device property: ...
416
417
418
419
420
  #define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_)	\
  ({											\
  	int _ret_;									\
  	_ret_ = FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_,		\
  				 _val_, _nval_);					\
0d67e0fa1   Heikki Krogerus   device property: ...
421
422
  	if (_ret_ == -EINVAL && !IS_ERR_OR_NULL(_fwnode_) &&				\
  	    !IS_ERR_OR_NULL(_fwnode_->secondary))					\
362c0b302   Andy Shevchenko   device property: ...
423
424
425
426
  		_ret_ = FWNODE_PROP_READ(_fwnode_->secondary, _propname_, _type_,	\
  				_proptype_, _val_, _nval_);				\
  	_ret_;										\
  })
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
427
428
429
430
  /**
   * fwnode_property_read_u8_array - return a u8 array property of firmware node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
5c0acf3b4   Adrian Hunter   driver core: Add ...
431
   * @val: The values are stored here or %NULL to return the number of values
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
432
433
434
435
436
   * @nval: Size of the @val array
   *
   * Read an array of u8 properties with @propname from @fwnode and stores them to
   * @val if found.
   *
5c0acf3b4   Adrian Hunter   driver core: Add ...
437
438
   * Return: number of values if @val was %NULL,
   *         %0 if the property was found (success),
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of numbers,
   *	   %-EOVERFLOW if the size of the property is not as expected,
   *	   %-ENXIO if no suitable firmware interface is present.
   */
  int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
  				  const char *propname, u8 *val, size_t nval)
  {
  	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8,
  				      val, nval);
  }
  EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
  
  /**
   * fwnode_property_read_u16_array - return a u16 array property of firmware node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
5c0acf3b4   Adrian Hunter   driver core: Add ...
457
   * @val: The values are stored here or %NULL to return the number of values
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
458
459
460
461
462
   * @nval: Size of the @val array
   *
   * Read an array of u16 properties with @propname from @fwnode and store them to
   * @val if found.
   *
5c0acf3b4   Adrian Hunter   driver core: Add ...
463
464
   * Return: number of values if @val was %NULL,
   *         %0 if the property was found (success),
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of numbers,
   *	   %-EOVERFLOW if the size of the property is not as expected,
   *	   %-ENXIO if no suitable firmware interface is present.
   */
  int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
  				   const char *propname, u16 *val, size_t nval)
  {
  	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16,
  				      val, nval);
  }
  EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
  
  /**
   * fwnode_property_read_u32_array - return a u32 array property of firmware node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
5c0acf3b4   Adrian Hunter   driver core: Add ...
483
   * @val: The values are stored here or %NULL to return the number of values
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
484
485
486
487
488
   * @nval: Size of the @val array
   *
   * Read an array of u32 properties with @propname from @fwnode store them to
   * @val if found.
   *
5c0acf3b4   Adrian Hunter   driver core: Add ...
489
490
   * Return: number of values if @val was %NULL,
   *         %0 if the property was found (success),
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of numbers,
   *	   %-EOVERFLOW if the size of the property is not as expected,
   *	   %-ENXIO if no suitable firmware interface is present.
   */
  int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
  				   const char *propname, u32 *val, size_t nval)
  {
  	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32,
  				      val, nval);
  }
  EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
  
  /**
   * fwnode_property_read_u64_array - return a u64 array property firmware node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
5c0acf3b4   Adrian Hunter   driver core: Add ...
509
   * @val: The values are stored here or %NULL to return the number of values
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
510
511
512
513
514
   * @nval: Size of the @val array
   *
   * Read an array of u64 properties with @propname from @fwnode and store them to
   * @val if found.
   *
5c0acf3b4   Adrian Hunter   driver core: Add ...
515
516
   * Return: number of values if @val was %NULL,
   *         %0 if the property was found (success),
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
517
518
519
520
521
522
523
524
525
526
527
528
529
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of numbers,
   *	   %-EOVERFLOW if the size of the property is not as expected,
   *	   %-ENXIO if no suitable firmware interface is present.
   */
  int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
  				   const char *propname, u64 *val, size_t nval)
  {
  	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64,
  				      val, nval);
  }
  EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
362c0b302   Andy Shevchenko   device property: ...
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
  static int __fwnode_property_read_string_array(struct fwnode_handle *fwnode,
  					       const char *propname,
  					       const char **val, size_t nval)
  {
  	if (is_of_node(fwnode))
  		return val ?
  			of_property_read_string_array(to_of_node(fwnode),
  						      propname, val, nval) :
  			of_property_count_strings(to_of_node(fwnode), propname);
  	else if (is_acpi_node(fwnode))
  		return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
  					   val, nval);
  	else if (is_pset_node(fwnode))
  		return val ?
  			pset_prop_read_string_array(to_pset_node(fwnode),
  						    propname, val, nval) :
  			pset_prop_count_elems_of_size(to_pset_node(fwnode),
  						      propname,
  						      sizeof(const char *));
  	return -ENXIO;
  }
  
  static int __fwnode_property_read_string(struct fwnode_handle *fwnode,
  					 const char *propname, const char **val)
  {
  	if (is_of_node(fwnode))
  		return of_property_read_string(to_of_node(fwnode), propname, val);
  	else if (is_acpi_node(fwnode))
  		return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
  					   val, 1);
  	else if (is_pset_node(fwnode))
  		return pset_prop_read_string(to_pset_node(fwnode), propname, val);
  	return -ENXIO;
  }
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
564
565
566
567
  /**
   * fwnode_property_read_string_array - return string array property of a node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
5c0acf3b4   Adrian Hunter   driver core: Add ...
568
   * @val: The values are stored here or %NULL to return the number of values
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
569
570
571
572
573
   * @nval: Size of the @val array
   *
   * Read an string list property @propname from the given firmware node and store
   * them to @val if found.
   *
5c0acf3b4   Adrian Hunter   driver core: Add ...
574
575
   * Return: number of values if @val was %NULL,
   *         %0 if the property was found (success),
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
576
577
578
579
580
581
582
583
584
585
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of strings,
   *	   %-EOVERFLOW if the size of the property is not as expected,
   *	   %-ENXIO if no suitable firmware interface is present.
   */
  int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
  				      const char *propname, const char **val,
  				      size_t nval)
  {
362c0b302   Andy Shevchenko   device property: ...
586
587
588
  	int ret;
  
  	ret = __fwnode_property_read_string_array(fwnode, propname, val, nval);
0d67e0fa1   Heikki Krogerus   device property: ...
589
590
  	if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
  	    !IS_ERR_OR_NULL(fwnode->secondary))
362c0b302   Andy Shevchenko   device property: ...
591
592
593
  		ret = __fwnode_property_read_string_array(fwnode->secondary,
  							  propname, val, nval);
  	return ret;
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
  }
  EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
  
  /**
   * fwnode_property_read_string - return a string property of a firmware node
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property
   * @val: The value is stored here
   *
   * Read property @propname from the given firmware node and store the value into
   * @val if found.  The value is checked to be a string.
   *
   * Return: %0 if the property was found (success),
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO or %-EILSEQ if the property is not a string,
   *	   %-ENXIO if no suitable firmware interface is present.
   */
  int fwnode_property_read_string(struct fwnode_handle *fwnode,
  				const char *propname, const char **val)
  {
362c0b302   Andy Shevchenko   device property: ...
615
616
617
  	int ret;
  
  	ret = __fwnode_property_read_string(fwnode, propname, val);
0d67e0fa1   Heikki Krogerus   device property: ...
618
619
  	if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
  	    !IS_ERR_OR_NULL(fwnode->secondary))
362c0b302   Andy Shevchenko   device property: ...
620
621
622
  		ret = __fwnode_property_read_string(fwnode->secondary,
  						    propname, val);
  	return ret;
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
623
624
625
626
  }
  EXPORT_SYMBOL_GPL(fwnode_property_read_string);
  
  /**
3f5c8d318   Mika Westerberg   device property: ...
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
   * fwnode_property_match_string - find a string in an array and return index
   * @fwnode: Firmware node to get the property of
   * @propname: Name of the property holding the array
   * @string: String to look for
   *
   * Find a given string in a string array and if it is found return the
   * index back.
   *
   * Return: %0 if the property was found (success),
   *	   %-EINVAL if given arguments are not valid,
   *	   %-ENODATA if the property does not have a value,
   *	   %-EPROTO if the property is not an array of strings,
   *	   %-ENXIO if no suitable firmware interface is present.
   */
  int fwnode_property_match_string(struct fwnode_handle *fwnode,
  	const char *propname, const char *string)
  {
  	const char **values;
a7c1d0a98   Andy Shevchenko   device property: ...
645
  	int nval, ret;
3f5c8d318   Mika Westerberg   device property: ...
646
647
648
649
  
  	nval = fwnode_property_read_string_array(fwnode, propname, NULL, 0);
  	if (nval < 0)
  		return nval;
f6740c189   Andy Shevchenko   device property: ...
650
651
  	if (nval == 0)
  		return -ENODATA;
3f5c8d318   Mika Westerberg   device property: ...
652
653
654
655
656
657
658
  	values = kcalloc(nval, sizeof(*values), GFP_KERNEL);
  	if (!values)
  		return -ENOMEM;
  
  	ret = fwnode_property_read_string_array(fwnode, propname, values, nval);
  	if (ret < 0)
  		goto out;
a7c1d0a98   Andy Shevchenko   device property: ...
659
660
661
  	ret = match_string(values, nval, string);
  	if (ret < 0)
  		ret = -ENODATA;
3f5c8d318   Mika Westerberg   device property: ...
662
663
664
665
666
667
668
  out:
  	kfree(values);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(fwnode_property_match_string);
  
  /**
13141e1cb   Mika Westerberg   device property: ...
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
   * pset_free_set - releases memory allocated for copied property set
   * @pset: Property set to release
   *
   * Function takes previously copied property set and releases all the
   * memory allocated to it.
   */
  static void pset_free_set(struct property_set *pset)
  {
  	const struct property_entry *prop;
  	size_t i, nval;
  
  	if (!pset)
  		return;
  
  	for (prop = pset->properties; prop->name; prop++) {
  		if (prop->is_array) {
  			if (prop->is_string && prop->pointer.str) {
  				nval = prop->length / sizeof(const char *);
  				for (i = 0; i < nval; i++)
  					kfree(prop->pointer.str[i]);
  			}
  			kfree(prop->pointer.raw_data);
  		} else if (prop->is_string) {
  			kfree(prop->value.str);
  		}
  		kfree(prop->name);
  	}
  
  	kfree(pset->properties);
  	kfree(pset);
  }
  
  static int pset_copy_entry(struct property_entry *dst,
  			   const struct property_entry *src)
  {
  	const char **d, **s;
  	size_t i, nval;
  
  	dst->name = kstrdup(src->name, GFP_KERNEL);
  	if (!dst->name)
  		return -ENOMEM;
  
  	if (src->is_array) {
f6740c189   Andy Shevchenko   device property: ...
712
713
  		if (!src->length)
  			return -ENODATA;
13141e1cb   Mika Westerberg   device property: ...
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
  		if (src->is_string) {
  			nval = src->length / sizeof(const char *);
  			dst->pointer.str = kcalloc(nval, sizeof(const char *),
  						   GFP_KERNEL);
  			if (!dst->pointer.str)
  				return -ENOMEM;
  
  			d = dst->pointer.str;
  			s = src->pointer.str;
  			for (i = 0; i < nval; i++) {
  				d[i] = kstrdup(s[i], GFP_KERNEL);
  				if (!d[i] && s[i])
  					return -ENOMEM;
  			}
  		} else {
  			dst->pointer.raw_data = kmemdup(src->pointer.raw_data,
  							src->length, GFP_KERNEL);
  			if (!dst->pointer.raw_data)
  				return -ENOMEM;
  		}
  	} else if (src->is_string) {
  		dst->value.str = kstrdup(src->value.str, GFP_KERNEL);
  		if (!dst->value.str && src->value.str)
  			return -ENOMEM;
  	} else {
  		dst->value.raw_data = src->value.raw_data;
  	}
  
  	dst->length = src->length;
  	dst->is_array = src->is_array;
  	dst->is_string = src->is_string;
  
  	return 0;
  }
  
  /**
   * pset_copy_set - copies property set
   * @pset: Property set to copy
   *
   * This function takes a deep copy of the given property set and returns
   * pointer to the copy. Call device_free_property_set() to free resources
   * allocated in this function.
   *
   * Return: Pointer to the new property set or error pointer.
   */
  static struct property_set *pset_copy_set(const struct property_set *pset)
  {
  	const struct property_entry *entry;
  	struct property_set *p;
  	size_t i, n = 0;
  
  	p = kzalloc(sizeof(*p), GFP_KERNEL);
  	if (!p)
  		return ERR_PTR(-ENOMEM);
  
  	while (pset->properties[n].name)
  		n++;
  
  	p->properties = kcalloc(n + 1, sizeof(*entry), GFP_KERNEL);
  	if (!p->properties) {
  		kfree(p);
  		return ERR_PTR(-ENOMEM);
  	}
  
  	for (i = 0; i < n; i++) {
  		int ret = pset_copy_entry(&p->properties[i],
  					  &pset->properties[i]);
  		if (ret) {
  			pset_free_set(p);
  			return ERR_PTR(ret);
  		}
  	}
  
  	return p;
  }
  
  /**
f4d052660   Heikki Krogerus   device property: ...
791
   * device_remove_properties - Remove properties from a device object.
13141e1cb   Mika Westerberg   device property: ...
792
793
794
   * @dev: Device whose properties to remove.
   *
   * The function removes properties previously associated to the device
f4d052660   Heikki Krogerus   device property: ...
795
   * secondary firmware node with device_add_properties(). Memory allocated
13141e1cb   Mika Westerberg   device property: ...
796
797
   * to the properties will also be released.
   */
f4d052660   Heikki Krogerus   device property: ...
798
  void device_remove_properties(struct device *dev)
13141e1cb   Mika Westerberg   device property: ...
799
800
801
802
803
804
805
806
807
808
809
  {
  	struct fwnode_handle *fwnode;
  
  	fwnode = dev_fwnode(dev);
  	if (!fwnode)
  		return;
  	/*
  	 * Pick either primary or secondary node depending which one holds
  	 * the pset. If there is no real firmware node (ACPI/DT) primary
  	 * will hold the pset.
  	 */
0d67e0fa1   Heikki Krogerus   device property: ...
810
811
  	if (is_pset_node(fwnode)) {
  		set_primary_fwnode(dev, NULL);
13141e1cb   Mika Westerberg   device property: ...
812
  		pset_free_set(to_pset_node(fwnode));
0d67e0fa1   Heikki Krogerus   device property: ...
813
814
815
816
817
818
819
  	} else {
  		fwnode = fwnode->secondary;
  		if (!IS_ERR(fwnode) && is_pset_node(fwnode)) {
  			set_secondary_fwnode(dev, NULL);
  			pset_free_set(to_pset_node(fwnode));
  		}
  	}
13141e1cb   Mika Westerberg   device property: ...
820
  }
f4d052660   Heikki Krogerus   device property: ...
821
  EXPORT_SYMBOL_GPL(device_remove_properties);
13141e1cb   Mika Westerberg   device property: ...
822
823
  
  /**
f4d052660   Heikki Krogerus   device property: ...
824
   * device_add_properties - Add a collection of properties to a device object.
13141e1cb   Mika Westerberg   device property: ...
825
   * @dev: Device to add properties to.
f4d052660   Heikki Krogerus   device property: ...
826
   * @properties: Collection of properties to add.
13141e1cb   Mika Westerberg   device property: ...
827
   *
f4d052660   Heikki Krogerus   device property: ...
828
829
830
   * Associate a collection of device properties represented by @properties with
   * @dev as its secondary firmware node. The function takes a copy of
   * @properties.
13141e1cb   Mika Westerberg   device property: ...
831
   */
f4d052660   Heikki Krogerus   device property: ...
832
  int device_add_properties(struct device *dev, struct property_entry *properties)
13141e1cb   Mika Westerberg   device property: ...
833
  {
f4d052660   Heikki Krogerus   device property: ...
834
  	struct property_set *p, pset;
13141e1cb   Mika Westerberg   device property: ...
835

f4d052660   Heikki Krogerus   device property: ...
836
  	if (!properties)
13141e1cb   Mika Westerberg   device property: ...
837
  		return -EINVAL;
f4d052660   Heikki Krogerus   device property: ...
838
839
840
  	pset.properties = properties;
  
  	p = pset_copy_set(&pset);
13141e1cb   Mika Westerberg   device property: ...
841
842
843
844
845
846
847
  	if (IS_ERR(p))
  		return PTR_ERR(p);
  
  	p->fwnode.type = FWNODE_PDATA;
  	set_secondary_fwnode(dev, &p->fwnode);
  	return 0;
  }
f4d052660   Heikki Krogerus   device property: ...
848
  EXPORT_SYMBOL_GPL(device_add_properties);
13141e1cb   Mika Westerberg   device property: ...
849
850
  
  /**
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
851
852
853
854
855
856
857
858
859
   * device_get_next_child_node - Return the next child node handle for a device
   * @dev: Device to find the next child node for.
   * @child: Handle to one of the device's child nodes or a null handle.
   */
  struct fwnode_handle *device_get_next_child_node(struct device *dev,
  						 struct fwnode_handle *child)
  {
  	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
  		struct device_node *node;
c181fb3e7   Alexander Sverdlin   ACPI / OF: Rename...
860
  		node = of_get_next_available_child(dev->of_node, to_of_node(child));
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
861
862
863
  		if (node)
  			return &node->fwnode;
  	} else if (IS_ENABLED(CONFIG_ACPI)) {
504a33749   Rafael J. Wysocki   ACPI / property: ...
864
  		return acpi_get_next_subnode(dev, child);
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
865
866
867
868
869
870
  	}
  	return NULL;
  }
  EXPORT_SYMBOL_GPL(device_get_next_child_node);
  
  /**
613e97218   Adam Thomson   device property: ...
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
   * device_get_named_child_node - Return first matching named child node handle
   * @dev: Device to find the named child node for.
   * @childname: String to match child node name against.
   */
  struct fwnode_handle *device_get_named_child_node(struct device *dev,
  						  const char *childname)
  {
  	struct fwnode_handle *child;
  
  	/*
  	 * Find first matching named child node of this device.
  	 * For ACPI this will be a data only sub-node.
  	 */
  	device_for_each_child_node(dev, child) {
  		if (is_of_node(child)) {
  			if (!of_node_cmp(to_of_node(child)->name, childname))
  				return child;
  		} else if (is_acpi_data_node(child)) {
  			if (acpi_data_node_match(child, childname))
  				return child;
  		}
  	}
  
  	return NULL;
  }
  EXPORT_SYMBOL_GPL(device_get_named_child_node);
  
  /**
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
899
900
901
902
903
904
905
906
907
908
   * fwnode_handle_put - Drop reference to a device node
   * @fwnode: Pointer to the device node to drop the reference to.
   *
   * This has to be used when terminating device_for_each_child_node() iteration
   * with break or return to prevent stale device node references from being left
   * behind.
   */
  void fwnode_handle_put(struct fwnode_handle *fwnode)
  {
  	if (is_of_node(fwnode))
c181fb3e7   Alexander Sverdlin   ACPI / OF: Rename...
909
  		of_node_put(to_of_node(fwnode));
8a0662d9e   Rafael J. Wysocki   Driver core: Unif...
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
  }
  EXPORT_SYMBOL_GPL(fwnode_handle_put);
  
  /**
   * device_get_child_node_count - return the number of child nodes for device
   * @dev: Device to cound the child nodes for
   */
  unsigned int device_get_child_node_count(struct device *dev)
  {
  	struct fwnode_handle *child;
  	unsigned int count = 0;
  
  	device_for_each_child_node(dev, child)
  		count++;
  
  	return count;
  }
  EXPORT_SYMBOL_GPL(device_get_child_node_count);
05ca55600   Suthikulpanit, Suravee   device property: ...
928

e5e558644   Suthikulpanit, Suravee   device property: ...
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
  bool device_dma_supported(struct device *dev)
  {
  	/* For DT, this is always supported.
  	 * For ACPI, this depends on CCA, which
  	 * is determined by the acpi_dma_supported().
  	 */
  	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
  		return true;
  
  	return acpi_dma_supported(ACPI_COMPANION(dev));
  }
  EXPORT_SYMBOL_GPL(device_dma_supported);
  
  enum dev_dma_attr device_get_dma_attr(struct device *dev)
  {
  	enum dev_dma_attr attr = DEV_DMA_NOT_SUPPORTED;
  
  	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
  		if (of_dma_is_coherent(dev->of_node))
  			attr = DEV_DMA_COHERENT;
  		else
  			attr = DEV_DMA_NON_COHERENT;
  	} else
  		attr = acpi_get_dma_attr(ACPI_COMPANION(dev));
  
  	return attr;
  }
  EXPORT_SYMBOL_GPL(device_get_dma_attr);
4c96b7dc0   Jeremy Linton   Add a matching se...
957
  /**
2f710a3a8   Jeremy Linton   device property: ...
958
   * device_get_phy_mode - Get phy mode for given device
4c96b7dc0   Jeremy Linton   Add a matching se...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
   * @dev:	Pointer to the given device
   *
   * The function gets phy interface string from property 'phy-mode' or
   * 'phy-connection-type', and return its index in phy_modes table, or errno in
   * error case.
   */
  int device_get_phy_mode(struct device *dev)
  {
  	const char *pm;
  	int err, i;
  
  	err = device_property_read_string(dev, "phy-mode", &pm);
  	if (err < 0)
  		err = device_property_read_string(dev,
  						  "phy-connection-type", &pm);
  	if (err < 0)
  		return err;
  
  	for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
  		if (!strcasecmp(pm, phy_modes(i)))
  			return i;
  
  	return -ENODEV;
  }
  EXPORT_SYMBOL_GPL(device_get_phy_mode);
  
  static void *device_get_mac_addr(struct device *dev,
  				 const char *name, char *addr,
  				 int alen)
  {
  	int ret = device_property_read_u8_array(dev, name, addr, alen);
2f710a3a8   Jeremy Linton   device property: ...
990
  	if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
4c96b7dc0   Jeremy Linton   Add a matching se...
991
992
993
994
995
  		return addr;
  	return NULL;
  }
  
  /**
2f710a3a8   Jeremy Linton   device property: ...
996
997
998
999
1000
1001
   * device_get_mac_address - Get the MAC for a given device
   * @dev:	Pointer to the device
   * @addr:	Address of buffer to store the MAC in
   * @alen:	Length of the buffer pointed to by addr, should be ETH_ALEN
   *
   * Search the firmware node for the best MAC address to use.  'mac-address' is
4c96b7dc0   Jeremy Linton   Add a matching se...
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
   * checked first, because that is supposed to contain to "most recent" MAC
   * address. If that isn't set, then 'local-mac-address' is checked next,
   * because that is the default address.  If that isn't set, then the obsolete
   * 'address' is checked, just in case we're using an old device tree.
   *
   * Note that the 'address' property is supposed to contain a virtual address of
   * the register set, but some DTS files have redefined that property to be the
   * MAC address.
   *
   * All-zero MAC addresses are rejected, because those could be properties that
2f710a3a8   Jeremy Linton   device property: ...
1012
1013
1014
1015
1016
   * exist in the firmware tables, but were not updated by the firmware.  For
   * example, the DTS could define 'mac-address' and 'local-mac-address', with
   * zero MAC addresses.  Some older U-Boots only initialized 'local-mac-address'.
   * In this case, the real MAC is in 'local-mac-address', and 'mac-address'
   * exists but is all zeros.
4c96b7dc0   Jeremy Linton   Add a matching se...
1017
1018
1019
  */
  void *device_get_mac_address(struct device *dev, char *addr, int alen)
  {
5b902d6f9   Julien Grall   device property: ...
1020
  	char *res;
4c96b7dc0   Jeremy Linton   Add a matching se...
1021

5b902d6f9   Julien Grall   device property: ...
1022
1023
1024
1025
1026
1027
1028
  	res = device_get_mac_addr(dev, "mac-address", addr, alen);
  	if (res)
  		return res;
  
  	res = device_get_mac_addr(dev, "local-mac-address", addr, alen);
  	if (res)
  		return res;
4c96b7dc0   Jeremy Linton   Add a matching se...
1029
1030
1031
1032
  
  	return device_get_mac_addr(dev, "address", addr, alen);
  }
  EXPORT_SYMBOL(device_get_mac_address);