| 1 | |
| 2 | |
| 3 | * drivers/of/property.c - Procedures for accessing and interpreting
|
| 4 | * Devicetree properties and graphs.
|
| 5 | *
|
| 6 | * Initially created by copying procedures from drivers/of/base.c. This
|
| 7 | * file contains the OF property as well as the OF graph interface
|
| 8 | * functions.
|
| 9 | *
|
| 10 | * Paul Mackerras August 1996.
|
| 11 | * Copyright (C) 1996-2005 Paul Mackerras.
|
| 12 | *
|
| 13 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
|
| 14 | * {engebret|bergner}@us.ibm.com
|
| 15 | *
|
| 16 | * Adapted for sparc and sparc64 by David S. Miller [email protected]
|
| 17 | *
|
| 18 | * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
|
| 19 | * Grant Likely.
|
| 20 |
|
| 21 |
|
| 22 | #define pr_fmt(fmt) "OF: " fmt
|
| 23 |
|
| 24 | #include <linux/ctype.h>
|
| 25 | #include <linux/of.h>
|
| 26 | #include <linux/of_address.h>
|
| 27 | #include <linux/of_device.h>
|
| 28 | #include <linux/of_graph.h>
|
| 29 | #include <linux/of_irq.h>
|
| 30 | #include <linux/string.h>
|
| 31 | #include <linux/moduleparam.h>
|
| 32 |
|
| 33 | #include "of_private.h"
|
| 34 |
|
| 35 | |
| 36 | * of_property_read_bool - Find a property
|
| 37 | * @np: device node from which the property value is to be read.
|
| 38 | * @propname: name of the property to be searched.
|
| 39 | *
|
| 40 | * Search for a boolean property in a device node. Usage on non-boolean
|
| 41 | * property types is deprecated.
|
| 42 | *
|
| 43 | * Return: true if the property exists false otherwise.
|
| 44 |
|
| 45 | bool of_property_read_bool(const struct device_node *np, const char *propname)
|
| 46 | {
|
| 47 | struct property *prop = of_find_property(np, propname, NULL);
|
| 48 |
|
| 49 | |
| 50 | * Boolean properties should not have a value. Testing for property
|
| 51 | * presence should either use of_property_present() or just read the
|
| 52 | * property value and check the returned error code.
|
| 53 |
|
| 54 | if (prop && prop->length)
|
| 55 | pr_warn("%pOF: Read of boolean property '%s' with a value.\n", np, propname);
|
| 56 |
|
| 57 | return prop ? true : false;
|
| 58 | }
|
| 59 | EXPORT_SYMBOL(of_property_read_bool);
|
| 60 |
|
| 61 | |
| 62 | * of_graph_is_present() - check graph's presence
|
| 63 | * @node: pointer to device_node containing graph port
|
| 64 | *
|
| 65 | * Return: True if @node has a port or ports (with a port) sub-node,
|
| 66 | * false otherwise.
|
| 67 |
|
| 68 | bool of_graph_is_present(const struct device_node *node)
|
| 69 | {
|
| 70 | struct device_node *ports __free(device_node) = of_get_child_by_name(node, "ports");
|
| 71 |
|
| 72 | if (ports)
|
| 73 | node = ports;
|
| 74 |
|
| 75 | struct device_node *port __free(device_node) = of_get_child_by_name(node, "port");
|
| 76 |
|
| 77 | return !!port;
|
| 78 | }
|
| 79 | EXPORT_SYMBOL(of_graph_is_present);
|
| 80 |
|
| 81 | |
| 82 | * of_property_count_elems_of_size - Count the number of elements in a property
|
| 83 | *
|
| 84 | * @np: device node from which the property value is to be read.
|
| 85 | * @propname: name of the property to be searched.
|
| 86 | * @elem_size: size of the individual element
|
| 87 | *
|
| 88 | * Search for a property in a device node and count the number of elements of
|
| 89 | * size elem_size in it.
|
| 90 | *
|
| 91 | * Return: The number of elements on success, -EINVAL if the property does not
|
| 92 | * exist or its length does not match a multiple of elem_size and -ENODATA if
|
| 93 | * the property does not have a value.
|
| 94 |
|
| 95 | int of_property_count_elems_of_size(const struct device_node *np,
|
| 96 | const char *propname, int elem_size)
|
| 97 | {
|
| 98 | const struct property *prop = of_find_property(np, propname, NULL);
|
| 99 |
|
| 100 | if (!prop)
|
| 101 | return -EINVAL;
|
| 102 | if (!prop->value)
|
| 103 | return -ENODATA;
|
| 104 |
|
| 105 | if (prop->length % elem_size != 0) {
|
| 106 | pr_err("size of %s in node %pOF is not a multiple of %d\n",
|
| 107 | propname, np, elem_size);
|
| 108 | return -EINVAL;
|
| 109 | }
|
| 110 |
|
| 111 | return prop->length / elem_size;
|
| 112 | }
|
| 113 | EXPORT_SYMBOL_GPL(of_property_count_elems_of_size);
|
| 114 |
|
| 115 | |
| 116 | * of_find_property_value_of_size
|
| 117 | *
|
| 118 | * @np: device node from which the property value is to be read.
|
| 119 | * @propname: name of the property to be searched.
|
| 120 | * @min: minimum allowed length of property value
|
| 121 | * @max: maximum allowed length of property value (0 means unlimited)
|
| 122 | * @len: if !=NULL, actual length is written to here
|
| 123 | *
|
| 124 | * Search for a property in a device node and valid the requested size.
|
| 125 | *
|
| 126 | * Return: The property value on success, -EINVAL if the property does not
|
| 127 | * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
|
| 128 | * property data is too small or too large.
|
| 129 | *
|
| 130 |
|
| 131 | static void *of_find_property_value_of_size(const struct device_node *np,
|
| 132 | const char *propname, u32 min, u32 max, size_t *len)
|
| 133 | {
|
| 134 | const struct property *prop = of_find_property(np, propname, NULL);
|
| 135 |
|
| 136 | if (!prop)
|
| 137 | return ERR_PTR(-EINVAL);
|
| 138 | if (!prop->value)
|
| 139 | return ERR_PTR(-ENODATA);
|
| 140 | if (prop->length < min)
|
| 141 | return ERR_PTR(-EOVERFLOW);
|
| 142 | if (max && prop->length > max)
|
| 143 | return ERR_PTR(-EOVERFLOW);
|
| 144 |
|
| 145 | if (len)
|
| 146 | *len = prop->length;
|
| 147 |
|
| 148 | return prop->value;
|
| 149 | }
|
| 150 |
|
| 151 | |
| 152 | * of_property_read_u8_index - Find and read a u8 from a multi-value property.
|
| 153 | *
|
| 154 | * @np: device node from which the property value is to be read.
|
| 155 | * @propname: name of the property to be searched.
|
| 156 | * @index: index of the u8 in the list of values
|
| 157 | * @out_value: pointer to return value, modified only if no error.
|
| 158 | *
|
| 159 | * Search for a property in a device node and read nth 8-bit value from
|
| 160 | * it.
|
| 161 | *
|
| 162 | * Return: 0 on success, -EINVAL if the property does not exist,
|
| 163 | * -ENODATA if property does not have a value, and -EOVERFLOW if the
|
| 164 | * property data isn't large enough.
|
| 165 | *
|
| 166 | * The out_value is modified only if a valid u8 value can be decoded.
|
| 167 |
|
| 168 | int of_property_read_u8_index(const struct device_node *np,
|
| 169 | const char *propname,
|
| 170 | u32 index, u8 *out_value)
|
| 171 | {
|
| 172 | const u8 *val = of_find_property_value_of_size(np, propname,
|
| 173 | ((index + 1) * sizeof(*out_value)),
|
| 174 | 0, NULL);
|
| 175 |
|
| 176 | if (IS_ERR(val))
|
| 177 | return PTR_ERR(val);
|
| 178 |
|
| 179 | *out_value = val[index];
|
| 180 | return 0;
|
| 181 | }
|
| 182 | EXPORT_SYMBOL_GPL(of_property_read_u8_index);
|
| 183 |
|
| 184 | |
| 185 | * of_property_read_u16_index - Find and read a u16 from a multi-value property.
|
| 186 | *
|
| 187 | * @np: device node from which the property value is to be read.
|
| 188 | * @propname: name of the property to be searched.
|
| 189 | * @index: index of the u16 in the list of values
|
| 190 | * @out_value: pointer to return value, modified only if no error.
|
| 191 | *
|
| 192 | * Search for a property in a device node and read nth 16-bit value from
|
| 193 | * it.
|
| 194 | *
|
| 195 | * Return: 0 on success, -EINVAL if the property does not exist,
|
| 196 | * -ENODATA if property does not have a value, and -EOVERFLOW if the
|
| 197 | * property data isn't large enough.
|
| 198 | *
|
| 199 | * The out_value is modified only if a valid u16 value can be decoded.
|
| 200 |
|
| 201 | int of_property_read_u16_index(const struct device_node *np,
|
| 202 | const char *propname,
|
| 203 | u32 index, u16 *out_value)
|
| 204 | {
|
| 205 | const u16 *val = of_find_property_value_of_size(np, propname,
|
| 206 | ((index + 1) * sizeof(*out_value)),
|
| 207 | 0, NULL);
|
| 208 |
|
| 209 | if (IS_ERR(val))
|
| 210 | return PTR_ERR(val);
|
| 211 |
|
| 212 | *out_value = be16_to_cpup(((__be16 *)val) + index);
|
| 213 | return 0;
|
| 214 | }
|
| 215 | EXPORT_SYMBOL_GPL(of_property_read_u16_index);
|
| 216 |
|
| 217 | |
| 218 | * of_property_read_u32_index - Find and read a u32 from a multi-value property.
|
| 219 | *
|
| 220 | * @np: device node from which the property value is to be read.
|
| 221 | * @propname: name of the property to be searched.
|
| 222 | * @index: index of the u32 in the list of values
|
| 223 | * @out_value: pointer to return value, modified only if no error.
|
| 224 | *
|
| 225 | * Search for a property in a device node and read nth 32-bit value from
|
| 226 | * it.
|
| 227 | *
|
| 228 | * Return: 0 on success, -EINVAL if the property does not exist,
|
| 229 | * -ENODATA if property does not have a value, and -EOVERFLOW if the
|
| 230 | * property data isn't large enough.
|
| 231 | *
|
| 232 | * The out_value is modified only if a valid u32 value can be decoded.
|
| 233 |
|
| 234 | int of_property_read_u32_index(const struct device_node *np,
|
| 235 | const char *propname,
|
| 236 | u32 index, u32 *out_value)
|
| 237 | {
|
| 238 | const u32 *val = of_find_property_value_of_size(np, propname,
|
| 239 | ((index + 1) * sizeof(*out_value)),
|
| 240 | 0,
|
| 241 | NULL);
|
| 242 |
|
| 243 | if (IS_ERR(val))
|
| 244 | return PTR_ERR(val);
|
| 245 |
|
| 246 | *out_value = be32_to_cpup(((__be32 *)val) + index);
|
| 247 | return 0;
|
| 248 | }
|
| 249 | EXPORT_SYMBOL_GPL(of_property_read_u32_index);
|
| 250 |
|
| 251 | |
| 252 | * of_property_read_u64_index - Find and read a u64 from a multi-value property.
|
| 253 | *
|
| 254 | * @np: device node from which the property value is to be read.
|
| 255 | * @propname: name of the property to be searched.
|
| 256 | * @index: index of the u64 in the list of values
|
| 257 | * @out_value: pointer to return value, modified only if no error.
|
| 258 | *
|
| 259 | * Search for a property in a device node and read nth 64-bit value from
|
| 260 | * it.
|
| 261 | *
|
| 262 | * Return: 0 on success, -EINVAL if the property does not exist,
|
| 263 | * -ENODATA if property does not have a value, and -EOVERFLOW if the
|
| 264 | * property data isn't large enough.
|
| 265 | *
|
| 266 | * The out_value is modified only if a valid u64 value can be decoded.
|
| 267 |
|
| 268 | int of_property_read_u64_index(const struct device_node *np,
|
| 269 | const char *propname,
|
| 270 | u32 index, u64 *out_value)
|
| 271 | {
|
| 272 | const u64 *val = of_find_property_value_of_size(np, propname,
|
| 273 | ((index + 1) * sizeof(*out_value)),
|
| 274 | 0, NULL);
|
| 275 |
|
| 276 | if (IS_ERR(val))
|
| 277 | return PTR_ERR(val);
|
| 278 |
|
| 279 | *out_value = be64_to_cpup(((__be64 *)val) + index);
|
| 280 | return 0;
|
| 281 | }
|
| 282 | EXPORT_SYMBOL_GPL(of_property_read_u64_index);
|
| 283 |
|
| 284 | |
| 285 | * of_property_read_variable_u8_array - Find and read an array of u8 from a
|
| 286 | * property, with bounds on the minimum and maximum array size.
|
| 287 | *
|
| 288 | * @np: device node from which the property value is to be read.
|
| 289 | * @propname: name of the property to be searched.
|
| 290 | * @out_values: pointer to found values.
|
| 291 | * @sz_min: minimum number of array elements to read
|
| 292 | * @sz_max: maximum number of array elements to read, if zero there is no
|
| 293 | * upper limit on the number of elements in the dts entry but only
|
| 294 | * sz_min will be read.
|
| 295 | *
|
| 296 | * Search for a property in a device node and read 8-bit value(s) from
|
| 297 | * it.
|
| 298 | *
|
| 299 | * dts entry of array should be like:
|
| 300 | * ``property = /bits/ 8 <0x50 0x60 0x70>;``
|
| 301 | *
|
| 302 | * Return: The number of elements read on success, -EINVAL if the property
|
| 303 | * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
|
| 304 | * if the property data is smaller than sz_min or longer than sz_max.
|
| 305 | *
|
| 306 | * The out_values is modified only if a valid u8 value can be decoded.
|
| 307 |
|
| 308 | int of_property_read_variable_u8_array(const struct device_node *np,
|
| 309 | const char *propname, u8 *out_values,
|
| 310 | size_t sz_min, size_t sz_max)
|
| 311 | {
|
| 312 | size_t sz, count;
|
| 313 | const u8 *val = of_find_property_value_of_size(np, propname,
|
| 314 | (sz_min * sizeof(*out_values)),
|
| 315 | (sz_max * sizeof(*out_values)),
|
| 316 | &sz);
|
| 317 |
|
| 318 | if (IS_ERR(val))
|
| 319 | return PTR_ERR(val);
|
| 320 |
|
| 321 | if (!sz_max)
|
| 322 | sz = sz_min;
|
| 323 | else
|
| 324 | sz /= sizeof(*out_values);
|
| 325 |
|
| 326 | count = sz;
|
| 327 | while (count--)
|
| 328 | *out_values++ = *val++;
|
| 329 |
|
| 330 | return sz;
|
| 331 | }
|
| 332 | EXPORT_SYMBOL_GPL(of_property_read_variable_u8_array);
|
| 333 |
|
| 334 | |
| 335 | * of_property_read_variable_u16_array - Find and read an array of u16 from a
|
| 336 | * property, with bounds on the minimum and maximum array size.
|
| 337 | *
|
| 338 | * @np: device node from which the property value is to be read.
|
| 339 | * @propname: name of the property to be searched.
|
| 340 | * @out_values: pointer to found values.
|
| 341 | * @sz_min: minimum number of array elements to read
|
| 342 | * @sz_max: maximum number of array elements to read, if zero there is no
|
| 343 | * upper limit on the number of elements in the dts entry but only
|
| 344 | * sz_min will be read.
|
| 345 | *
|
| 346 | * Search for a property in a device node and read 16-bit value(s) from
|
| 347 | * it.
|
| 348 | *
|
| 349 | * dts entry of array should be like:
|
| 350 | * ``property = /bits/ 16 <0x5000 0x6000 0x7000>;``
|
| 351 | *
|
| 352 | * Return: The number of elements read on success, -EINVAL if the property
|
| 353 | * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
|
| 354 | * if the property data is smaller than sz_min or longer than sz_max.
|
| 355 | *
|
| 356 | * The out_values is modified only if a valid u16 value can be decoded.
|
| 357 |
|
| 358 | int of_property_read_variable_u16_array(const struct device_node *np,
|
| 359 | const char *propname, u16 *out_values,
|
| 360 | size_t sz_min, size_t sz_max)
|
| 361 | {
|
| 362 | size_t sz, count;
|
| 363 | const __be16 *val = of_find_property_value_of_size(np, propname,
|
| 364 | (sz_min * sizeof(*out_values)),
|
| 365 | (sz_max * sizeof(*out_values)),
|
| 366 | &sz);
|
| 367 |
|
| 368 | if (IS_ERR(val))
|
| 369 | return PTR_ERR(val);
|
| 370 |
|
| 371 | if (!sz_max)
|
| 372 | sz = sz_min;
|
| 373 | else
|
| 374 | sz /= sizeof(*out_values);
|
| 375 |
|
| 376 | count = sz;
|
| 377 | while (count--)
|
| 378 | *out_values++ = be16_to_cpup(val++);
|
| 379 |
|
| 380 | return sz;
|
| 381 | }
|
| 382 | EXPORT_SYMBOL_GPL(of_property_read_variable_u16_array);
|
| 383 |
|
| 384 | |
| 385 | * of_property_read_variable_u32_array - Find and read an array of 32 bit
|
| 386 | * integers from a property, with bounds on the minimum and maximum array size.
|
| 387 | *
|
| 388 | * @np: device node from which the property value is to be read.
|
| 389 | * @propname: name of the property to be searched.
|
| 390 | * @out_values: pointer to return found values.
|
| 391 | * @sz_min: minimum number of array elements to read
|
| 392 | * @sz_max: maximum number of array elements to read, if zero there is no
|
| 393 | * upper limit on the number of elements in the dts entry but only
|
| 394 | * sz_min will be read.
|
| 395 | *
|
| 396 | * Search for a property in a device node and read 32-bit value(s) from
|
| 397 | * it.
|
| 398 | *
|
| 399 | * Return: The number of elements read on success, -EINVAL if the property
|
| 400 | * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
|
| 401 | * if the property data is smaller than sz_min or longer than sz_max.
|
| 402 | *
|
| 403 | * The out_values is modified only if a valid u32 value can be decoded.
|
| 404 |
|
| 405 | int of_property_read_variable_u32_array(const struct device_node *np,
|
| 406 | const char *propname, u32 *out_values,
|
| 407 | size_t sz_min, size_t sz_max)
|
| 408 | {
|
| 409 | size_t sz, count;
|
| 410 | const __be32 *val = of_find_property_value_of_size(np, propname,
|
| 411 | (sz_min * sizeof(*out_values)),
|
| 412 | (sz_max * sizeof(*out_values)),
|
| 413 | &sz);
|
| 414 |
|
| 415 | if (IS_ERR(val))
|
| 416 | return PTR_ERR(val);
|
| 417 |
|
| 418 | if (!sz_max)
|
| 419 | sz = sz_min;
|
| 420 | else
|
| 421 | sz /= sizeof(*out_values);
|
| 422 |
|
| 423 | count = sz;
|
| 424 | while (count--)
|
| 425 | *out_values++ = be32_to_cpup(val++);
|
| 426 |
|
| 427 | return sz;
|
| 428 | }
|
| 429 | EXPORT_SYMBOL_GPL(of_property_read_variable_u32_array);
|
| 430 |
|
| 431 | |
| 432 | * of_property_read_u64 - Find and read a 64 bit integer from a property
|
| 433 | * @np: device node from which the property value is to be read.
|
| 434 | * @propname: name of the property to be searched.
|
| 435 | * @out_value: pointer to return value, modified only if return value is 0.
|
| 436 | *
|
| 437 | * Search for a property in a device node and read a 64-bit value from
|
| 438 | * it.
|
| 439 | *
|
| 440 | * Return: 0 on success, -EINVAL if the property does not exist,
|
| 441 | * -ENODATA if property does not have a value, and -EOVERFLOW if the
|
| 442 | * property data isn't large enough.
|
| 443 | *
|
| 444 | * The out_value is modified only if a valid u64 value can be decoded.
|
| 445 |
|
| 446 | int of_property_read_u64(const struct device_node *np, const char *propname,
|
| 447 | u64 *out_value)
|
| 448 | {
|
| 449 | const __be32 *val = of_find_property_value_of_size(np, propname,
|
| 450 | sizeof(*out_value),
|
| 451 | 0,
|
| 452 | NULL);
|
| 453 |
|
| 454 | if (IS_ERR(val))
|
| 455 | return PTR_ERR(val);
|
| 456 |
|
| 457 | *out_value = of_read_number(val, 2);
|
| 458 | return 0;
|
| 459 | }
|
| 460 | EXPORT_SYMBOL_GPL(of_property_read_u64);
|
| 461 |
|
| 462 | |
| 463 | * of_property_read_variable_u64_array - Find and read an array of 64 bit
|
| 464 | * integers from a property, with bounds on the minimum and maximum array size.
|
| 465 | *
|
| 466 | * @np: device node from which the property value is to be read.
|
| 467 | * @propname: name of the property to be searched.
|
| 468 | * @out_values: pointer to found values.
|
| 469 | * @sz_min: minimum number of array elements to read
|
| 470 | * @sz_max: maximum number of array elements to read, if zero there is no
|
| 471 | * upper limit on the number of elements in the dts entry but only
|
| 472 | * sz_min will be read.
|
| 473 | *
|
| 474 | * Search for a property in a device node and read 64-bit value(s) from
|
| 475 | * it.
|
| 476 | *
|
| 477 | * Return: The number of elements read on success, -EINVAL if the property
|
| 478 | * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
|
| 479 | * if the property data is smaller than sz_min or longer than sz_max.
|
| 480 | *
|
| 481 | * The out_values is modified only if a valid u64 value can be decoded.
|
| 482 |
|
| 483 | int of_property_read_variable_u64_array(const struct device_node *np,
|
| 484 | const char *propname, u64 *out_values,
|
| 485 | size_t sz_min, size_t sz_max)
|
| 486 | {
|
| 487 | size_t sz, count;
|
| 488 | const __be32 *val = of_find_property_value_of_size(np, propname,
|
| 489 | (sz_min * sizeof(*out_values)),
|
| 490 | (sz_max * sizeof(*out_values)),
|
| 491 | &sz);
|
| 492 |
|
| 493 | if (IS_ERR(val))
|
| 494 | return PTR_ERR(val);
|
| 495 |
|
| 496 | if (!sz_max)
|
| 497 | sz = sz_min;
|
| 498 | else
|
| 499 | sz /= sizeof(*out_values);
|
| 500 |
|
| 501 | count = sz;
|
| 502 | while (count--) {
|
| 503 | *out_values++ = of_read_number(val, 2);
|
| 504 | val += 2;
|
| 505 | }
|
| 506 |
|
| 507 | return sz;
|
| 508 | }
|
| 509 | EXPORT_SYMBOL_GPL(of_property_read_variable_u64_array);
|
| 510 |
|
| 511 | |
| 512 | * of_property_read_string - Find and read a string from a property
|
| 513 | * @np: device node from which the property value is to be read.
|
| 514 | * @propname: name of the property to be searched.
|
| 515 | * @out_string: pointer to null terminated return string, modified only if
|
| 516 | * return value is 0.
|
| 517 | *
|
| 518 | * Search for a property in a device tree node and retrieve a null
|
| 519 | * terminated string value (pointer to data, not a copy).
|
| 520 | *
|
| 521 | * Return: 0 on success, -EINVAL if the property does not exist, -ENODATA if
|
| 522 | * property does not have a value, and -EILSEQ if the string is not
|
| 523 | * null-terminated within the length of the property data.
|
| 524 | *
|
| 525 | * Note that the empty string "" has length of 1, thus -ENODATA cannot
|
| 526 | * be interpreted as an empty string.
|
| 527 | *
|
| 528 | * The out_string pointer is modified only if a valid string can be decoded.
|
| 529 |
|
| 530 | int of_property_read_string(const struct device_node *np, const char *propname,
|
| 531 | const char **out_string)
|
| 532 | {
|
| 533 | const struct property *prop = of_find_property(np, propname, NULL);
|
| 534 |
|
| 535 | if (!prop)
|
| 536 | return -EINVAL;
|
| 537 | if (!prop->length)
|
| 538 | return -ENODATA;
|
| 539 | if (strnlen(prop->value, prop->length) >= prop->length)
|
| 540 | return -EILSEQ;
|
| 541 | *out_string = prop->value;
|
| 542 | return 0;
|
| 543 | }
|
| 544 | EXPORT_SYMBOL_GPL(of_property_read_string);
|
| 545 |
|
| 546 | |
| 547 | * of_property_match_string() - Find string in a list and return index
|
| 548 | * @np: pointer to the node containing the string list property
|
| 549 | * @propname: string list property name
|
| 550 | * @string: pointer to the string to search for in the string list
|
| 551 | *
|
| 552 | * Search for an exact match of string in a device node property which is a
|
| 553 | * string of lists.
|
| 554 | *
|
| 555 | * Return: the index of the first occurrence of the string on success, -EINVAL
|
| 556 | * if the property does not exist, -ENODATA if the property does not have a
|
| 557 | * value, and -EILSEQ if the string is not null-terminated within the length of
|
| 558 | * the property data.
|
| 559 |
|
| 560 | int of_property_match_string(const struct device_node *np, const char *propname,
|
| 561 | const char *string)
|
| 562 | {
|
| 563 | const struct property *prop = of_find_property(np, propname, NULL);
|
| 564 | size_t l;
|
| 565 | int i;
|
| 566 | const char *p, *end;
|
| 567 |
|
| 568 | if (!prop)
|
| 569 | return -EINVAL;
|
| 570 | if (!prop->value)
|
| 571 | return -ENODATA;
|
| 572 |
|
| 573 | p = prop->value;
|
| 574 | end = p + prop->length;
|
| 575 |
|
| 576 | for (i = 0; p < end; i++, p += l) {
|
| 577 | l = strnlen(p, end - p) + 1;
|
| 578 | if (p + l > end)
|
| 579 | return -EILSEQ;
|
| 580 | pr_debug("comparing %s with %s\n", string, p);
|
| 581 | if (strcmp(string, p) == 0)
|
| 582 | return i;
|
| 583 | }
|
| 584 | return -ENODATA;
|
| 585 | }
|
| 586 | EXPORT_SYMBOL_GPL(of_property_match_string);
|
| 587 |
|
| 588 | |
| 589 | * of_property_read_string_helper() - Utility helper for parsing string properties
|
| 590 | * @np: device node from which the property value is to be read.
|
| 591 | * @propname: name of the property to be searched.
|
| 592 | * @out_strs: output array of string pointers.
|
| 593 | * @sz: number of array elements to read.
|
| 594 | * @skip: Number of strings to skip over at beginning of list.
|
| 595 | *
|
| 596 | * Don't call this function directly. It is a utility helper for the
|
| 597 | * of_property_read_string*() family of functions.
|
| 598 |
|
| 599 | int of_property_read_string_helper(const struct device_node *np,
|
| 600 | const char *propname, const char **out_strs,
|
| 601 | size_t sz, int skip)
|
| 602 | {
|
| 603 | const struct property *prop = of_find_property(np, propname, NULL);
|
| 604 | int l = 0, i = 0;
|
| 605 | const char *p, *end;
|
| 606 |
|
| 607 | if (!prop)
|
| 608 | return -EINVAL;
|
| 609 | if (!prop->value)
|
| 610 | return -ENODATA;
|
| 611 | p = prop->value;
|
| 612 | end = p + prop->length;
|
| 613 |
|
| 614 | for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) {
|
| 615 | l = strnlen(p, end - p) + 1;
|
| 616 | if (p + l > end)
|
| 617 | return -EILSEQ;
|
| 618 | if (out_strs && i >= skip)
|
| 619 | *out_strs++ = p;
|
| 620 | }
|
| 621 | i -= skip;
|
| 622 | return i <= 0 ? -ENODATA : i;
|
| 623 | }
|
| 624 | EXPORT_SYMBOL_GPL(of_property_read_string_helper);
|
| 625 |
|
| 626 | const __be32 *of_prop_next_u32(const struct property *prop, const __be32 *cur,
|
| 627 | u32 *pu)
|
| 628 | {
|
| 629 | const void *curv = cur;
|
| 630 |
|
| 631 | if (!prop)
|
| 632 | return NULL;
|
| 633 |
|
| 634 | if (!cur) {
|
| 635 | curv = prop->value;
|
| 636 | goto out_val;
|
| 637 | }
|
| 638 |
|
| 639 | curv += sizeof(*cur);
|
| 640 | if (curv >= prop->value + prop->length)
|
| 641 | return NULL;
|
| 642 |
|
| 643 | out_val:
|
| 644 | *pu = be32_to_cpup(curv);
|
| 645 | return curv;
|
| 646 | }
|
| 647 | EXPORT_SYMBOL_GPL(of_prop_next_u32);
|
| 648 |
|
| 649 | const char *of_prop_next_string(const struct property *prop, const char *cur)
|
| 650 | {
|
| 651 | const char *curv;
|
| 652 | const char *end;
|
| 653 | size_t len;
|
| 654 |
|
| 655 | if (!prop || !prop->value || !prop->length)
|
| 656 | return NULL;
|
| 657 |
|
| 658 | curv = cur ? cur : prop->value;
|
| 659 | end = prop->value + prop->length;
|
| 660 |
|
| 661 | if (curv < (const char *)prop->value || curv >= end)
|
| 662 | return NULL;
|
| 663 |
|
| 664 | if (cur) {
|
| 665 | len = strnlen(curv, end - curv);
|
| 666 | if (len >= end - curv)
|
| 667 | return NULL;
|
| 668 |
|
| 669 | curv += len + 1;
|
| 670 | if (curv >= end)
|
| 671 | return NULL;
|
| 672 | }
|
| 673 |
|
| 674 | len = strnlen(curv, end - curv);
|
| 675 | if (len >= end - curv)
|
| 676 | return NULL;
|
| 677 |
|
| 678 | return curv;
|
| 679 | }
|
| 680 | EXPORT_SYMBOL_GPL(of_prop_next_string);
|
| 681 |
|
| 682 | |
| 683 | * of_graph_parse_endpoint() - parse common endpoint node properties
|
| 684 | * @node: pointer to endpoint device_node
|
| 685 | * @endpoint: pointer to the OF endpoint data structure
|
| 686 | *
|
| 687 | * The caller should hold a reference to @node.
|
| 688 |
|
| 689 | int of_graph_parse_endpoint(const struct device_node *node,
|
| 690 | struct of_endpoint *endpoint)
|
| 691 | {
|
| 692 | struct device_node *port_node __free(device_node) =
|
| 693 | of_get_parent(node);
|
| 694 |
|
| 695 | WARN_ONCE(!port_node, "%s(): endpoint %pOF has no parent node\n",
|
| 696 | __func__, node);
|
| 697 |
|
| 698 | memset(endpoint, 0, sizeof(*endpoint));
|
| 699 |
|
| 700 | endpoint->local_node = node;
|
| 701 | |
| 702 | * It doesn't matter whether the two calls below succeed.
|
| 703 | * If they don't then the default value 0 is used.
|
| 704 |
|
| 705 | of_property_read_u32(port_node, "reg", &endpoint->port);
|
| 706 | of_property_read_u32(node, "reg", &endpoint->id);
|
| 707 |
|
| 708 | return 0;
|
| 709 | }
|
| 710 | EXPORT_SYMBOL(of_graph_parse_endpoint);
|
| 711 |
|
| 712 | |
| 713 | * of_graph_get_port_by_id() - get the port matching a given id
|
| 714 | * @parent: pointer to the parent device node
|
| 715 | * @id: id of the port
|
| 716 | *
|
| 717 | * Return: A 'port' node pointer with refcount incremented. The caller
|
| 718 | * has to use of_node_put() on it when done.
|
| 719 |
|
| 720 | struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id)
|
| 721 | {
|
| 722 | struct device_node *node __free(device_node) = of_get_child_by_name(parent, "ports");
|
| 723 |
|
| 724 | if (node)
|
| 725 | parent = node;
|
| 726 |
|
| 727 | for_each_child_of_node_scoped(parent, port) {
|
| 728 | u32 port_id = 0;
|
| 729 |
|
| 730 | if (!of_node_name_eq(port, "port"))
|
| 731 | continue;
|
| 732 | of_property_read_u32(port, "reg", &port_id);
|
| 733 | if (id == port_id)
|
| 734 | return_ptr(port);
|
| 735 | }
|
| 736 |
|
| 737 | return NULL;
|
| 738 | }
|
| 739 | EXPORT_SYMBOL(of_graph_get_port_by_id);
|
| 740 |
|
| 741 | |
| 742 | * of_graph_get_next_port() - get next port node.
|
| 743 | * @parent: pointer to the parent device node, or parent ports node
|
| 744 | * @prev: previous port node, or NULL to get first
|
| 745 | *
|
| 746 | * Parent device node can be used as @parent whether device node has ports node
|
| 747 | * or not. It will work same as ports@0 node.
|
| 748 | *
|
| 749 | * Return: A 'port' node pointer with refcount incremented. Refcount
|
| 750 | * of the passed @prev node is decremented.
|
| 751 |
|
| 752 | struct device_node *of_graph_get_next_port(const struct device_node *parent,
|
| 753 | struct device_node *prev)
|
| 754 | {
|
| 755 | if (!parent)
|
| 756 | return NULL;
|
| 757 |
|
| 758 | if (!prev) {
|
| 759 | struct device_node *node __free(device_node) =
|
| 760 | of_get_child_by_name(parent, "ports");
|
| 761 |
|
| 762 | if (node)
|
| 763 | parent = node;
|
| 764 |
|
| 765 | return of_get_child_by_name(parent, "port");
|
| 766 | }
|
| 767 |
|
| 768 | do {
|
| 769 | prev = of_get_next_child(parent, prev);
|
| 770 | if (!prev)
|
| 771 | break;
|
| 772 | } while (!of_node_name_eq(prev, "port"));
|
| 773 |
|
| 774 | return prev;
|
| 775 | }
|
| 776 | EXPORT_SYMBOL(of_graph_get_next_port);
|
| 777 |
|
| 778 | |
| 779 | * of_graph_get_next_port_endpoint() - get next endpoint node in port.
|
| 780 | * If it reached to end of the port, it will return NULL.
|
| 781 | * @port: pointer to the target port node
|
| 782 | * @prev: previous endpoint node, or NULL to get first
|
| 783 | *
|
| 784 | * Return: An 'endpoint' node pointer with refcount incremented. Refcount
|
| 785 | * of the passed @prev node is decremented.
|
| 786 |
|
| 787 | struct device_node *of_graph_get_next_port_endpoint(const struct device_node *port,
|
| 788 | struct device_node *prev)
|
| 789 | {
|
| 790 | while (1) {
|
| 791 | prev = of_get_next_child(port, prev);
|
| 792 | if (!prev)
|
| 793 | break;
|
| 794 | if (WARN(!of_node_name_eq(prev, "endpoint"),
|
| 795 | "non endpoint node is used (%pOF)", prev))
|
| 796 | continue;
|
| 797 |
|
| 798 | break;
|
| 799 | }
|
| 800 |
|
| 801 | return prev;
|
| 802 | }
|
| 803 | EXPORT_SYMBOL(of_graph_get_next_port_endpoint);
|
| 804 |
|
| 805 | |
| 806 | * of_graph_get_next_endpoint() - get next endpoint node
|
| 807 | * @parent: pointer to the parent device node
|
| 808 | * @prev: previous endpoint node, or NULL to get first
|
| 809 | *
|
| 810 | * Return: An 'endpoint' node pointer with refcount incremented. Refcount
|
| 811 | * of the passed @prev node is decremented.
|
| 812 |
|
| 813 | struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
|
| 814 | struct device_node *prev)
|
| 815 | {
|
| 816 | struct device_node *endpoint;
|
| 817 | struct device_node *port;
|
| 818 |
|
| 819 | if (!parent)
|
| 820 | return NULL;
|
| 821 |
|
| 822 | |
| 823 | * Start by locating the port node. If no previous endpoint is specified
|
| 824 | * search for the first port node, otherwise get the previous endpoint
|
| 825 | * parent port node.
|
| 826 |
|
| 827 | if (!prev) {
|
| 828 | port = of_graph_get_next_port(parent, NULL);
|
| 829 | if (!port) {
|
| 830 | pr_debug("graph: no port node found in %pOF\n", parent);
|
| 831 | return NULL;
|
| 832 | }
|
| 833 | } else {
|
| 834 | port = of_get_parent(prev);
|
| 835 | if (WARN_ONCE(!port, "%s(): endpoint %pOF has no parent node\n",
|
| 836 | __func__, prev))
|
| 837 | return NULL;
|
| 838 | }
|
| 839 |
|
| 840 | while (1) {
|
| 841 | |
| 842 | * Now that we have a port node, get the next endpoint by
|
| 843 | * getting the next child. If the previous endpoint is NULL this
|
| 844 | * will return the first child.
|
| 845 |
|
| 846 | endpoint = of_graph_get_next_port_endpoint(port, prev);
|
| 847 | if (endpoint) {
|
| 848 | of_node_put(port);
|
| 849 | return endpoint;
|
| 850 | }
|
| 851 |
|
| 852 |
|
| 853 | prev = NULL;
|
| 854 |
|
| 855 | port = of_graph_get_next_port(parent, port);
|
| 856 | if (!port)
|
| 857 | return NULL;
|
| 858 | }
|
| 859 | }
|
| 860 | EXPORT_SYMBOL(of_graph_get_next_endpoint);
|
| 861 |
|
| 862 | |
| 863 | * of_graph_get_endpoint_by_regs() - get endpoint node of specific identifiers
|
| 864 | * @parent: pointer to the parent device node
|
| 865 | * @port_reg: identifier (value of reg property) of the parent port node
|
| 866 | * @reg: identifier (value of reg property) of the endpoint node
|
| 867 | *
|
| 868 | * Return: An 'endpoint' node pointer which is identified by reg and at the same
|
| 869 | * is the child of a port node identified by port_reg. reg and port_reg are
|
| 870 | * ignored when they are -1. Use of_node_put() on the pointer when done.
|
| 871 |
|
| 872 | struct device_node *of_graph_get_endpoint_by_regs(
|
| 873 | const struct device_node *parent, int port_reg, int reg)
|
| 874 | {
|
| 875 | struct of_endpoint endpoint;
|
| 876 | struct device_node *node = NULL;
|
| 877 |
|
| 878 | for_each_endpoint_of_node(parent, node) {
|
| 879 | of_graph_parse_endpoint(node, &endpoint);
|
| 880 | if (((port_reg == -1) || (endpoint.port == port_reg)) &&
|
| 881 | ((reg == -1) || (endpoint.id == reg)))
|
| 882 | return node;
|
| 883 | }
|
| 884 |
|
| 885 | return NULL;
|
| 886 | }
|
| 887 | EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);
|
| 888 |
|
| 889 | |
| 890 | * of_graph_get_remote_endpoint() - get remote endpoint node
|
| 891 | * @node: pointer to a local endpoint device_node
|
| 892 | *
|
| 893 | * Return: Remote endpoint node associated with remote endpoint node linked
|
| 894 | * to @node. Use of_node_put() on it when done.
|
| 895 |
|
| 896 | struct device_node *of_graph_get_remote_endpoint(const struct device_node *node)
|
| 897 | {
|
| 898 |
|
| 899 | return of_parse_phandle(node, "remote-endpoint", 0);
|
| 900 | }
|
| 901 | EXPORT_SYMBOL(of_graph_get_remote_endpoint);
|
| 902 |
|
| 903 | |
| 904 | * of_graph_get_port_parent() - get port's parent node
|
| 905 | * @node: pointer to a local endpoint device_node
|
| 906 | *
|
| 907 | * Return: device node associated with endpoint node linked
|
| 908 | * to @node. Use of_node_put() on it when done.
|
| 909 |
|
| 910 | struct device_node *of_graph_get_port_parent(struct device_node *node)
|
| 911 | {
|
| 912 | unsigned int depth;
|
| 913 |
|
| 914 | if (!node)
|
| 915 | return NULL;
|
| 916 |
|
| 917 | |
| 918 | * Preserve usecount for passed in node as of_get_next_parent()
|
| 919 | * will do of_node_put() on it.
|
| 920 |
|
| 921 | of_node_get(node);
|
| 922 |
|
| 923 |
|
| 924 | for (depth = 3; depth && node; depth--) {
|
| 925 | node = of_get_next_parent(node);
|
| 926 | if (depth == 2 && !of_node_name_eq(node, "ports") &&
|
| 927 | !of_node_name_eq(node, "in-ports") &&
|
| 928 | !of_node_name_eq(node, "out-ports"))
|
| 929 | break;
|
| 930 | }
|
| 931 | return node;
|
| 932 | }
|
| 933 | EXPORT_SYMBOL(of_graph_get_port_parent);
|
| 934 |
|
| 935 | |
| 936 | * of_graph_get_remote_port_parent() - get remote port's parent node
|
| 937 | * @node: pointer to a local endpoint device_node
|
| 938 | *
|
| 939 | * Return: Remote device node associated with remote endpoint node linked
|
| 940 | * to @node. Use of_node_put() on it when done.
|
| 941 |
|
| 942 | struct device_node *of_graph_get_remote_port_parent(
|
| 943 | const struct device_node *node)
|
| 944 | {
|
| 945 |
|
| 946 | struct device_node *np __free(device_node) =
|
| 947 | of_graph_get_remote_endpoint(node);
|
| 948 |
|
| 949 | return of_graph_get_port_parent(np);
|
| 950 | }
|
| 951 | EXPORT_SYMBOL(of_graph_get_remote_port_parent);
|
| 952 |
|
| 953 | |
| 954 | * of_graph_get_remote_port() - get remote port node
|
| 955 | * @node: pointer to a local endpoint device_node
|
| 956 | *
|
| 957 | * Return: Remote port node associated with remote endpoint node linked
|
| 958 | * to @node. Use of_node_put() on it when done.
|
| 959 |
|
| 960 | struct device_node *of_graph_get_remote_port(const struct device_node *node)
|
| 961 | {
|
| 962 | struct device_node *np;
|
| 963 |
|
| 964 |
|
| 965 | np = of_graph_get_remote_endpoint(node);
|
| 966 | if (!np)
|
| 967 | return NULL;
|
| 968 | return of_get_next_parent(np);
|
| 969 | }
|
| 970 | EXPORT_SYMBOL(of_graph_get_remote_port);
|
| 971 |
|
| 972 | |
| 973 | * of_graph_get_endpoint_count() - get the number of endpoints in a device node
|
| 974 | * @np: parent device node containing ports and endpoints
|
| 975 | *
|
| 976 | * Return: count of endpoint of this device node
|
| 977 |
|
| 978 | unsigned int of_graph_get_endpoint_count(const struct device_node *np)
|
| 979 | {
|
| 980 | struct device_node *endpoint;
|
| 981 | unsigned int num = 0;
|
| 982 |
|
| 983 | for_each_endpoint_of_node(np, endpoint)
|
| 984 | num++;
|
| 985 |
|
| 986 | return num;
|
| 987 | }
|
| 988 | EXPORT_SYMBOL(of_graph_get_endpoint_count);
|
| 989 |
|
| 990 | |
| 991 | * of_graph_get_port_count() - get the number of port in a device or ports node
|
| 992 | * @np: pointer to the device or ports node
|
| 993 | *
|
| 994 | * Return: count of port of this device or ports node
|
| 995 |
|
| 996 | unsigned int of_graph_get_port_count(struct device_node *np)
|
| 997 | {
|
| 998 | unsigned int num = 0;
|
| 999 |
|
| 1000 | for_each_of_graph_port(np, port)
|
| 1001 | num++;
|
| 1002 |
|
| 1003 | return num;
|
| 1004 | }
|
| 1005 | EXPORT_SYMBOL(of_graph_get_port_count);
|
| 1006 |
|
| 1007 | |
| 1008 | * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint
|
| 1009 | * @node: pointer to parent device_node containing graph port/endpoint
|
| 1010 | * @port: identifier (value of reg property) of the parent port node
|
| 1011 | * @endpoint: identifier (value of reg property) of the endpoint node
|
| 1012 | *
|
| 1013 | * Return: Remote device node associated with remote endpoint node linked
|
| 1014 | * to @node. Use of_node_put() on it when done.
|
| 1015 |
|
| 1016 | struct device_node *of_graph_get_remote_node(const struct device_node *node,
|
| 1017 | u32 port, u32 endpoint)
|
| 1018 | {
|
| 1019 | struct device_node *endpoint_node, *remote;
|
| 1020 |
|
| 1021 | endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
|
| 1022 | if (!endpoint_node) {
|
| 1023 | pr_debug("no valid endpoint (%d, %d) for node %pOF\n",
|
| 1024 | port, endpoint, node);
|
| 1025 | return NULL;
|
| 1026 | }
|
| 1027 |
|
| 1028 | remote = of_graph_get_remote_port_parent(endpoint_node);
|
| 1029 | of_node_put(endpoint_node);
|
| 1030 | if (!remote) {
|
| 1031 | pr_debug("no valid remote node\n");
|
| 1032 | return NULL;
|
| 1033 | }
|
| 1034 |
|
| 1035 | if (!of_device_is_available(remote)) {
|
| 1036 | pr_debug("not available for remote node\n");
|
| 1037 | of_node_put(remote);
|
| 1038 | return NULL;
|
| 1039 | }
|
| 1040 |
|
| 1041 | return remote;
|
| 1042 | }
|
| 1043 | EXPORT_SYMBOL(of_graph_get_remote_node);
|
| 1044 |
|
| 1045 | static struct fwnode_handle *of_fwnode_get(struct fwnode_handle *fwnode)
|
| 1046 | {
|
| 1047 | return of_fwnode_handle(of_node_get(to_of_node(fwnode)));
|
| 1048 | }
|
| 1049 |
|
| 1050 | static void of_fwnode_put(struct fwnode_handle *fwnode)
|
| 1051 | {
|
| 1052 | of_node_put(to_of_node(fwnode));
|
| 1053 | }
|
| 1054 |
|
| 1055 | static bool of_fwnode_device_is_available(const struct fwnode_handle *fwnode)
|
| 1056 | {
|
| 1057 | return of_device_is_available(to_of_node(fwnode));
|
| 1058 | }
|
| 1059 |
|
| 1060 | static bool of_fwnode_device_dma_supported(const struct fwnode_handle *fwnode)
|
| 1061 | {
|
| 1062 | return true;
|
| 1063 | }
|
| 1064 |
|
| 1065 | static enum dev_dma_attr
|
| 1066 | of_fwnode_device_get_dma_attr(const struct fwnode_handle *fwnode)
|
| 1067 | {
|
| 1068 | if (of_dma_is_coherent(to_of_node(fwnode)))
|
| 1069 | return DEV_DMA_COHERENT;
|
| 1070 | else
|
| 1071 | return DEV_DMA_NON_COHERENT;
|
| 1072 | }
|
| 1073 |
|
| 1074 | static bool of_fwnode_property_present(const struct fwnode_handle *fwnode,
|
| 1075 | const char *propname)
|
| 1076 | {
|
| 1077 | return of_property_present(to_of_node(fwnode), propname);
|
| 1078 | }
|
| 1079 |
|
| 1080 | static bool of_fwnode_property_read_bool(const struct fwnode_handle *fwnode,
|
| 1081 | const char *propname)
|
| 1082 | {
|
| 1083 | return of_property_read_bool(to_of_node(fwnode), propname);
|
| 1084 | }
|
| 1085 |
|
| 1086 | static int of_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
|
| 1087 | const char *propname,
|
| 1088 | unsigned int elem_size, void *val,
|
| 1089 | size_t nval)
|
| 1090 | {
|
| 1091 | const struct device_node *node = to_of_node(fwnode);
|
| 1092 |
|
| 1093 | if (!val)
|
| 1094 | return of_property_count_elems_of_size(node, propname,
|
| 1095 | elem_size);
|
| 1096 |
|
| 1097 | switch (elem_size) {
|
| 1098 | case sizeof(u8):
|
| 1099 | return of_property_read_u8_array(node, propname, val, nval);
|
| 1100 | case sizeof(u16):
|
| 1101 | return of_property_read_u16_array(node, propname, val, nval);
|
| 1102 | case sizeof(u32):
|
| 1103 | return of_property_read_u32_array(node, propname, val, nval);
|
| 1104 | case sizeof(u64):
|
| 1105 | return of_property_read_u64_array(node, propname, val, nval);
|
| 1106 | }
|
| 1107 |
|
| 1108 | return -ENXIO;
|
| 1109 | }
|
| 1110 |
|
| 1111 | static int
|
| 1112 | of_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
|
| 1113 | const char *propname, const char **val,
|
| 1114 | size_t nval)
|
| 1115 | {
|
| 1116 | const struct device_node *node = to_of_node(fwnode);
|
| 1117 |
|
| 1118 | return val ?
|
| 1119 | of_property_read_string_array(node, propname, val, nval) :
|
| 1120 | of_property_count_strings(node, propname);
|
| 1121 | }
|
| 1122 |
|
| 1123 | static const char *of_fwnode_get_name(const struct fwnode_handle *fwnode)
|
| 1124 | {
|
| 1125 | return kbasename(to_of_node(fwnode)->full_name);
|
| 1126 | }
|
| 1127 |
|
| 1128 | static const char *of_fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
|
| 1129 | {
|
| 1130 |
|
| 1131 | if (!to_of_node(fwnode)->parent)
|
| 1132 | return "";
|
| 1133 |
|
| 1134 | return "/";
|
| 1135 | }
|
| 1136 |
|
| 1137 | static struct fwnode_handle *
|
| 1138 | of_fwnode_get_parent(const struct fwnode_handle *fwnode)
|
| 1139 | {
|
| 1140 | return of_fwnode_handle(of_get_parent(to_of_node(fwnode)));
|
| 1141 | }
|
| 1142 |
|
| 1143 | static struct fwnode_handle *
|
| 1144 | of_fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
|
| 1145 | struct fwnode_handle *child)
|
| 1146 | {
|
| 1147 | return of_fwnode_handle(of_get_next_available_child(to_of_node(fwnode),
|
| 1148 | to_of_node(child)));
|
| 1149 | }
|
| 1150 |
|
| 1151 | static struct fwnode_handle *
|
| 1152 | of_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
|
| 1153 | const char *childname)
|
| 1154 | {
|
| 1155 | const struct device_node *node = to_of_node(fwnode);
|
| 1156 | struct device_node *child;
|
| 1157 |
|
| 1158 | for_each_available_child_of_node(node, child)
|
| 1159 | if (of_node_name_eq(child, childname))
|
| 1160 | return of_fwnode_handle(child);
|
| 1161 |
|
| 1162 | return NULL;
|
| 1163 | }
|
| 1164 |
|
| 1165 | static int
|
| 1166 | of_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
|
| 1167 | const char *prop, const char *nargs_prop,
|
| 1168 | unsigned int nargs, unsigned int index,
|
| 1169 | struct fwnode_reference_args *args)
|
| 1170 | {
|
| 1171 | struct of_phandle_args of_args;
|
| 1172 | unsigned int i;
|
| 1173 | int ret;
|
| 1174 |
|
| 1175 | |
| 1176 | * This function should return -ENOENT for out of bound indexes,
|
| 1177 | * but the OF API uses signed indexes and consider negative indexes
|
| 1178 | * as invalid. Catch them here to correctly implement the fwnode API.
|
| 1179 |
|
| 1180 | if ((int)index < 0)
|
| 1181 | return -ENOENT;
|
| 1182 |
|
| 1183 | if (nargs_prop)
|
| 1184 | ret = of_parse_phandle_with_args(to_of_node(fwnode), prop,
|
| 1185 | nargs_prop, index, &of_args);
|
| 1186 | else
|
| 1187 | ret = of_parse_phandle_with_fixed_args(to_of_node(fwnode), prop,
|
| 1188 | nargs, index, &of_args);
|
| 1189 | if (ret < 0)
|
| 1190 | return ret;
|
| 1191 | if (!args) {
|
| 1192 | of_node_put(of_args.np);
|
| 1193 | return 0;
|
| 1194 | }
|
| 1195 |
|
| 1196 | args->nargs = of_args.args_count;
|
| 1197 | args->fwnode = of_fwnode_handle(of_args.np);
|
| 1198 |
|
| 1199 | for (i = 0; i < NR_FWNODE_REFERENCE_ARGS; i++)
|
| 1200 | args->args[i] = i < of_args.args_count ? of_args.args[i] : 0;
|
| 1201 |
|
| 1202 | return 0;
|
| 1203 | }
|
| 1204 |
|
| 1205 | static struct fwnode_handle *
|
| 1206 | of_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
|
| 1207 | struct fwnode_handle *prev)
|
| 1208 | {
|
| 1209 | return of_fwnode_handle(of_graph_get_next_endpoint(to_of_node(fwnode),
|
| 1210 | to_of_node(prev)));
|
| 1211 | }
|
| 1212 |
|
| 1213 | static struct fwnode_handle *
|
| 1214 | of_fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
|
| 1215 | {
|
| 1216 | return of_fwnode_handle(
|
| 1217 | of_graph_get_remote_endpoint(to_of_node(fwnode)));
|
| 1218 | }
|
| 1219 |
|
| 1220 | static struct fwnode_handle *
|
| 1221 | of_fwnode_graph_get_port_parent(struct fwnode_handle *fwnode)
|
| 1222 | {
|
| 1223 | struct device_node *np;
|
| 1224 |
|
| 1225 |
|
| 1226 | np = of_get_parent(to_of_node(fwnode));
|
| 1227 | if (!np)
|
| 1228 | return NULL;
|
| 1229 |
|
| 1230 |
|
| 1231 | if (!of_node_name_eq(np, "ports"))
|
| 1232 | return of_fwnode_handle(np);
|
| 1233 |
|
| 1234 | return of_fwnode_handle(of_get_next_parent(np));
|
| 1235 | }
|
| 1236 |
|
| 1237 | static int of_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
|
| 1238 | struct fwnode_endpoint *endpoint)
|
| 1239 | {
|
| 1240 | const struct device_node *node = to_of_node(fwnode);
|
| 1241 | struct device_node *port_node __free(device_node) = of_get_parent(node);
|
| 1242 |
|
| 1243 | endpoint->local_fwnode = fwnode;
|
| 1244 |
|
| 1245 | of_property_read_u32(port_node, "reg", &endpoint->port);
|
| 1246 | of_property_read_u32(node, "reg", &endpoint->id);
|
| 1247 |
|
| 1248 | return 0;
|
| 1249 | }
|
| 1250 |
|
| 1251 | static const void *
|
| 1252 | of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
|
| 1253 | const struct device *dev)
|
| 1254 | {
|
| 1255 | return of_device_get_match_data(dev);
|
| 1256 | }
|
| 1257 |
|
| 1258 | static void of_link_to_phandle(struct device_node *con_np,
|
| 1259 | struct device_node *sup_np,
|
| 1260 | u8 flags)
|
| 1261 | {
|
| 1262 | struct device_node *tmp_np __free(device_node) = of_node_get(sup_np);
|
| 1263 |
|
| 1264 |
|
| 1265 | while (tmp_np) {
|
| 1266 | if (of_fwnode_handle(tmp_np)->dev)
|
| 1267 | break;
|
| 1268 |
|
| 1269 | if (!of_device_is_available(tmp_np))
|
| 1270 | return;
|
| 1271 |
|
| 1272 | tmp_np = of_get_next_parent(tmp_np);
|
| 1273 | }
|
| 1274 |
|
| 1275 | fwnode_link_add(of_fwnode_handle(con_np), of_fwnode_handle(sup_np), flags);
|
| 1276 | }
|
| 1277 |
|
| 1278 | |
| 1279 | * parse_prop_cells - Property parsing function for suppliers
|
| 1280 | *
|
| 1281 | * @np: Pointer to device tree node containing a list
|
| 1282 | * @prop_name: Name of property to be parsed. Expected to hold phandle values
|
| 1283 | * @index: For properties holding a list of phandles, this is the index
|
| 1284 | * into the list.
|
| 1285 | * @list_name: Property name that is known to contain list of phandle(s) to
|
| 1286 | * supplier(s)
|
| 1287 | * @cells_name: property name that specifies phandles' arguments count
|
| 1288 | *
|
| 1289 | * This is a helper function to parse properties that have a known fixed name
|
| 1290 | * and are a list of phandles and phandle arguments.
|
| 1291 | *
|
| 1292 | * Returns:
|
| 1293 | * - phandle node pointer with refcount incremented. Caller must of_node_put()
|
| 1294 | * on it when done.
|
| 1295 | * - NULL if no phandle found at index
|
| 1296 |
|
| 1297 | static struct device_node *parse_prop_cells(struct device_node *np,
|
| 1298 | const char *prop_name, int index,
|
| 1299 | const char *list_name,
|
| 1300 | const char *cells_name)
|
| 1301 | {
|
| 1302 | struct of_phandle_args sup_args;
|
| 1303 |
|
| 1304 | if (strcmp(prop_name, list_name))
|
| 1305 | return NULL;
|
| 1306 |
|
| 1307 | if (__of_parse_phandle_with_args(np, list_name, cells_name, 0, index,
|
| 1308 | &sup_args))
|
| 1309 | return NULL;
|
| 1310 |
|
| 1311 | return sup_args.np;
|
| 1312 | }
|
| 1313 |
|
| 1314 | #define DEFINE_SIMPLE_PROP(fname, name, cells) \
|
| 1315 | static struct device_node *parse_##fname(struct device_node *np, \
|
| 1316 | const char *prop_name, int index) \
|
| 1317 | { \
|
| 1318 | return parse_prop_cells(np, prop_name, index, name, cells); \
|
| 1319 | }
|
| 1320 |
|
| 1321 | |
| 1322 | * parse_suffix_prop_cells - Suffix property parsing function for suppliers
|
| 1323 | *
|
| 1324 | * @np: Pointer to device tree node containing a list
|
| 1325 | * @prop_name: Name of property to be parsed. Expected to hold phandle values
|
| 1326 | * @index: For properties holding a list of phandles, this is the index
|
| 1327 | * into the list.
|
| 1328 | * @suffix: Property suffix that is known to contain list of phandle(s) to
|
| 1329 | * supplier(s)
|
| 1330 | * @cells_name: property name that specifies phandles' arguments count
|
| 1331 | *
|
| 1332 | * This is a helper function to parse properties that have a known fixed suffix
|
| 1333 | * and are a list of phandles and phandle arguments.
|
| 1334 | *
|
| 1335 | * Returns:
|
| 1336 | * - phandle node pointer with refcount incremented. Caller must of_node_put()
|
| 1337 | * on it when done.
|
| 1338 | * - NULL if no phandle found at index
|
| 1339 |
|
| 1340 | static struct device_node *parse_suffix_prop_cells(struct device_node *np,
|
| 1341 | const char *prop_name, int index,
|
| 1342 | const char *suffix,
|
| 1343 | const char *cells_name)
|
| 1344 | {
|
| 1345 | struct of_phandle_args sup_args;
|
| 1346 |
|
| 1347 | if (!strends(prop_name, suffix))
|
| 1348 | return NULL;
|
| 1349 |
|
| 1350 | if (of_parse_phandle_with_args(np, prop_name, cells_name, index,
|
| 1351 | &sup_args))
|
| 1352 | return NULL;
|
| 1353 |
|
| 1354 | return sup_args.np;
|
| 1355 | }
|
| 1356 |
|
| 1357 | #define DEFINE_SUFFIX_PROP(fname, suffix, cells) \
|
| 1358 | static struct device_node *parse_##fname(struct device_node *np, \
|
| 1359 | const char *prop_name, int index) \
|
| 1360 | { \
|
| 1361 | return parse_suffix_prop_cells(np, prop_name, index, suffix, cells); \
|
| 1362 | }
|
| 1363 |
|
| 1364 | |
| 1365 | * struct supplier_bindings - Property parsing functions for suppliers
|
| 1366 | *
|
| 1367 | * @parse_prop: function name
|
| 1368 | * parse_prop() finds the node corresponding to a supplier phandle
|
| 1369 | * parse_prop.np: Pointer to device node holding supplier phandle property
|
| 1370 | * parse_prop.prop_name: Name of property holding a phandle value
|
| 1371 | * parse_prop.index: For properties holding a list of phandles, this is the
|
| 1372 | * index into the list
|
| 1373 | * @get_con_dev: If the consumer node containing the property is never converted
|
| 1374 | * to a struct device, implement this ops so fw_devlink can use it
|
| 1375 | * to find the true consumer.
|
| 1376 | * @optional: Describes whether a supplier is mandatory or not
|
| 1377 | * @fwlink_flags: Optional fwnode link flags to use when creating a fwnode link
|
| 1378 | * for this property.
|
| 1379 | *
|
| 1380 | * Returns:
|
| 1381 | * parse_prop() return values are
|
| 1382 | * - phandle node pointer with refcount incremented. Caller must of_node_put()
|
| 1383 | * on it when done.
|
| 1384 | * - NULL if no phandle found at index
|
| 1385 |
|
| 1386 | struct supplier_bindings {
|
| 1387 | struct device_node *(*parse_prop)(struct device_node *np,
|
| 1388 | const char *prop_name, int index);
|
| 1389 | struct device_node *(*get_con_dev)(struct device_node *np);
|
| 1390 | bool optional;
|
| 1391 | u8 fwlink_flags;
|
| 1392 | };
|
| 1393 |
|
| 1394 | DEFINE_SIMPLE_PROP(clocks, "clocks", "#clock-cells")
|
| 1395 | DEFINE_SIMPLE_PROP(interconnects, "interconnects", "#interconnect-cells")
|
| 1396 | DEFINE_SIMPLE_PROP(iommus, "iommus", "#iommu-cells")
|
| 1397 | DEFINE_SIMPLE_PROP(mboxes, "mboxes", "#mbox-cells")
|
| 1398 | DEFINE_SIMPLE_PROP(io_channels, "io-channels", "#io-channel-cells")
|
| 1399 | DEFINE_SIMPLE_PROP(io_backends, "io-backends", "#io-backend-cells")
|
| 1400 | DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-cells")
|
| 1401 | DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells")
|
| 1402 | DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells")
|
| 1403 | DEFINE_SIMPLE_PROP(extcon, "extcon", NULL)
|
| 1404 | DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", "#nvmem-cell-cells")
|
| 1405 | DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells")
|
| 1406 | DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL)
|
| 1407 | DEFINE_SIMPLE_PROP(pwms, "pwms", "#pwm-cells")
|
| 1408 | DEFINE_SIMPLE_PROP(resets, "resets", "#reset-cells")
|
| 1409 | DEFINE_SIMPLE_PROP(leds, "leds", NULL)
|
| 1410 | DEFINE_SIMPLE_PROP(backlight, "backlight", NULL)
|
| 1411 | DEFINE_SIMPLE_PROP(panel, "panel", NULL)
|
| 1412 | DEFINE_SIMPLE_PROP(msi_parent, "msi-parent", "#msi-cells")
|
| 1413 | DEFINE_SIMPLE_PROP(post_init_providers, "post-init-providers", NULL)
|
| 1414 | DEFINE_SIMPLE_PROP(access_controllers, "access-controllers", "#access-controller-cells")
|
| 1415 | DEFINE_SIMPLE_PROP(pses, "pses", "#pse-cells")
|
| 1416 | DEFINE_SIMPLE_PROP(power_supplies, "power-supplies", NULL)
|
| 1417 | DEFINE_SIMPLE_PROP(mmc_pwrseq, "mmc-pwrseq", NULL)
|
| 1418 | DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
|
| 1419 | DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
|
| 1420 |
|
| 1421 | static struct device_node *parse_pinctrl_n(struct device_node *np,
|
| 1422 | const char *prop_name, int index)
|
| 1423 | {
|
| 1424 | if (!strstarts(prop_name, "pinctrl-"))
|
| 1425 | return NULL;
|
| 1426 |
|
| 1427 | if (!isdigit(prop_name[strlen("pinctrl-")]))
|
| 1428 | return NULL;
|
| 1429 |
|
| 1430 | return of_parse_phandle(np, prop_name, index);
|
| 1431 | }
|
| 1432 |
|
| 1433 | static struct device_node *parse_gpios(struct device_node *np,
|
| 1434 | const char *prop_name, int index)
|
| 1435 | {
|
| 1436 | if (strends(prop_name, ",nr-gpios"))
|
| 1437 | return NULL;
|
| 1438 |
|
| 1439 | return parse_suffix_prop_cells(np, prop_name, index, "-gpios",
|
| 1440 | "#gpio-cells");
|
| 1441 | }
|
| 1442 |
|
| 1443 | static struct device_node *parse_iommu_maps(struct device_node *np,
|
| 1444 | const char *prop_name, int index)
|
| 1445 | {
|
| 1446 | if (strcmp(prop_name, "iommu-map"))
|
| 1447 | return NULL;
|
| 1448 |
|
| 1449 | return of_parse_phandle(np, prop_name, (index * 4) + 1);
|
| 1450 | }
|
| 1451 |
|
| 1452 | static struct device_node *parse_gpio_compat(struct device_node *np,
|
| 1453 | const char *prop_name, int index)
|
| 1454 | {
|
| 1455 | struct of_phandle_args sup_args;
|
| 1456 |
|
| 1457 | if (strcmp(prop_name, "gpio") && strcmp(prop_name, "gpios"))
|
| 1458 | return NULL;
|
| 1459 |
|
| 1460 | |
| 1461 | * Ignore node with gpio-hog property since its gpios are all provided
|
| 1462 | * by its parent.
|
| 1463 |
|
| 1464 | if (of_property_read_bool(np, "gpio-hog"))
|
| 1465 | return NULL;
|
| 1466 |
|
| 1467 | if (of_parse_phandle_with_args(np, prop_name, "#gpio-cells", index,
|
| 1468 | &sup_args))
|
| 1469 | return NULL;
|
| 1470 |
|
| 1471 | return sup_args.np;
|
| 1472 | }
|
| 1473 |
|
| 1474 | static struct device_node *parse_interrupts(struct device_node *np,
|
| 1475 | const char *prop_name, int index)
|
| 1476 | {
|
| 1477 | struct of_phandle_args sup_args;
|
| 1478 |
|
| 1479 | if (!IS_ENABLED(CONFIG_OF_IRQ) || IS_ENABLED(CONFIG_PPC))
|
| 1480 | return NULL;
|
| 1481 |
|
| 1482 | if (strcmp(prop_name, "interrupts") &&
|
| 1483 | strcmp(prop_name, "interrupts-extended"))
|
| 1484 | return NULL;
|
| 1485 |
|
| 1486 | return of_irq_parse_one(np, index, &sup_args) ? NULL : sup_args.np;
|
| 1487 | }
|
| 1488 |
|
| 1489 | static struct device_node *parse_interrupt_map(struct device_node *np,
|
| 1490 | const char *prop_name, int index)
|
| 1491 | {
|
| 1492 | const __be32 *imap, *imap_end;
|
| 1493 | struct of_phandle_args sup_args;
|
| 1494 | u32 addrcells, intcells;
|
| 1495 | int imaplen;
|
| 1496 |
|
| 1497 | if (!IS_ENABLED(CONFIG_OF_IRQ))
|
| 1498 | return NULL;
|
| 1499 |
|
| 1500 | if (strcmp(prop_name, "interrupt-map"))
|
| 1501 | return NULL;
|
| 1502 |
|
| 1503 | if (of_property_read_u32(np, "#interrupt-cells", &intcells))
|
| 1504 | return NULL;
|
| 1505 | addrcells = of_bus_n_addr_cells(np);
|
| 1506 |
|
| 1507 | imap = of_get_property(np, "interrupt-map", &imaplen);
|
| 1508 | if (!imap)
|
| 1509 | return NULL;
|
| 1510 | imaplen /= sizeof(*imap);
|
| 1511 |
|
| 1512 | imap_end = imap + imaplen;
|
| 1513 |
|
| 1514 | for (int i = 0; imap + addrcells + intcells + 1 < imap_end; i++) {
|
| 1515 | imap += addrcells + intcells;
|
| 1516 |
|
| 1517 | imap = of_irq_parse_imap_parent(imap, imap_end - imap, &sup_args);
|
| 1518 | if (!imap)
|
| 1519 | return NULL;
|
| 1520 |
|
| 1521 | if (i == index)
|
| 1522 | return sup_args.np;
|
| 1523 |
|
| 1524 | of_node_put(sup_args.np);
|
| 1525 | }
|
| 1526 |
|
| 1527 | return NULL;
|
| 1528 | }
|
| 1529 |
|
| 1530 | static struct device_node *parse_remote_endpoint(struct device_node *np,
|
| 1531 | const char *prop_name,
|
| 1532 | int index)
|
| 1533 | {
|
| 1534 |
|
| 1535 | if (index > 0 || strcmp(prop_name, "remote-endpoint"))
|
| 1536 | return NULL;
|
| 1537 |
|
| 1538 | return of_graph_get_remote_port_parent(np);
|
| 1539 | }
|
| 1540 |
|
| 1541 | static const struct supplier_bindings of_supplier_bindings[] = {
|
| 1542 | { .parse_prop = parse_clocks, },
|
| 1543 | { .parse_prop = parse_interconnects, },
|
| 1544 | { .parse_prop = parse_iommus, .optional = true, },
|
| 1545 | { .parse_prop = parse_iommu_maps, .optional = true, },
|
| 1546 | { .parse_prop = parse_mboxes, },
|
| 1547 | { .parse_prop = parse_io_channels, },
|
| 1548 | { .parse_prop = parse_io_backends, },
|
| 1549 | { .parse_prop = parse_dmas, .optional = true, },
|
| 1550 | { .parse_prop = parse_power_domains, },
|
| 1551 | { .parse_prop = parse_hwlocks, },
|
| 1552 | { .parse_prop = parse_extcon, },
|
| 1553 | { .parse_prop = parse_nvmem_cells, },
|
| 1554 | { .parse_prop = parse_phys, },
|
| 1555 | { .parse_prop = parse_wakeup_parent, },
|
| 1556 | { .parse_prop = parse_pinctrl_n, },
|
| 1557 | {
|
| 1558 | .parse_prop = parse_remote_endpoint,
|
| 1559 | .get_con_dev = of_graph_get_port_parent,
|
| 1560 | },
|
| 1561 | { .parse_prop = parse_pwms, },
|
| 1562 | { .parse_prop = parse_resets, },
|
| 1563 | { .parse_prop = parse_leds, },
|
| 1564 | { .parse_prop = parse_backlight, },
|
| 1565 | { .parse_prop = parse_panel, },
|
| 1566 | { .parse_prop = parse_msi_parent, },
|
| 1567 | { .parse_prop = parse_pses, },
|
| 1568 | { .parse_prop = parse_power_supplies, },
|
| 1569 | { .parse_prop = parse_mmc_pwrseq, },
|
| 1570 | { .parse_prop = parse_gpio_compat, },
|
| 1571 | { .parse_prop = parse_interrupts, },
|
| 1572 | { .parse_prop = parse_interrupt_map, },
|
| 1573 | { .parse_prop = parse_access_controllers, },
|
| 1574 | { .parse_prop = parse_regulators, },
|
| 1575 | { .parse_prop = parse_gpio, },
|
| 1576 | { .parse_prop = parse_gpios, },
|
| 1577 | {
|
| 1578 | .parse_prop = parse_post_init_providers,
|
| 1579 | .fwlink_flags = FWLINK_FLAG_IGNORE,
|
| 1580 | },
|
| 1581 | {}
|
| 1582 | };
|
| 1583 |
|
| 1584 | |
| 1585 | * of_link_property - Create device links to suppliers listed in a property
|
| 1586 | * @con_np: The consumer device tree node which contains the property
|
| 1587 | * @prop_name: Name of property to be parsed
|
| 1588 | *
|
| 1589 | * This function checks if the property @prop_name that is present in the
|
| 1590 | * @con_np device tree node is one of the known common device tree bindings
|
| 1591 | * that list phandles to suppliers. If @prop_name isn't one, this function
|
| 1592 | * doesn't do anything.
|
| 1593 | *
|
| 1594 | * If @prop_name is one, this function attempts to create fwnode links from the
|
| 1595 | * consumer device tree node @con_np to all the suppliers device tree nodes
|
| 1596 | * listed in @prop_name.
|
| 1597 | *
|
| 1598 | * Any failed attempt to create a fwnode link will NOT result in an immediate
|
| 1599 | * return. of_link_property() must create links to all the available supplier
|
| 1600 | * device tree nodes even when attempts to create a link to one or more
|
| 1601 | * suppliers fail.
|
| 1602 |
|
| 1603 | static int of_link_property(struct device_node *con_np, const char *prop_name)
|
| 1604 | {
|
| 1605 | struct device_node *phandle;
|
| 1606 | const struct supplier_bindings *s = of_supplier_bindings;
|
| 1607 | unsigned int i = 0;
|
| 1608 | bool matched = false;
|
| 1609 |
|
| 1610 |
|
| 1611 | while (!matched && s->parse_prop) {
|
| 1612 | if (s->optional && !fw_devlink_is_strict()) {
|
| 1613 | s++;
|
| 1614 | continue;
|
| 1615 | }
|
| 1616 |
|
| 1617 | while ((phandle = s->parse_prop(con_np, prop_name, i))) {
|
| 1618 | struct device_node *con_dev_np __free(device_node) =
|
| 1619 | s->get_con_dev ? s->get_con_dev(con_np) : of_node_get(con_np);
|
| 1620 |
|
| 1621 | matched = true;
|
| 1622 | i++;
|
| 1623 | of_link_to_phandle(con_dev_np, phandle, s->fwlink_flags);
|
| 1624 | of_node_put(phandle);
|
| 1625 | }
|
| 1626 | s++;
|
| 1627 | }
|
| 1628 | return 0;
|
| 1629 | }
|
| 1630 |
|
| 1631 | static void __iomem *of_fwnode_iomap(struct fwnode_handle *fwnode, int index)
|
| 1632 | {
|
| 1633 | #ifdef CONFIG_OF_ADDRESS
|
| 1634 | return of_iomap(to_of_node(fwnode), index);
|
| 1635 | #else
|
| 1636 | return NULL;
|
| 1637 | #endif
|
| 1638 | }
|
| 1639 |
|
| 1640 | static int of_fwnode_irq_get(const struct fwnode_handle *fwnode,
|
| 1641 | unsigned int index)
|
| 1642 | {
|
| 1643 | return of_irq_get(to_of_node(fwnode), index);
|
| 1644 | }
|
| 1645 |
|
| 1646 | static int match_property_by_path(const char *node_path, const char *prop_name,
|
| 1647 | const char *value)
|
| 1648 | {
|
| 1649 | struct device_node *np __free(device_node) = of_find_node_by_path(node_path);
|
| 1650 |
|
| 1651 | return of_property_match_string(np, prop_name, value);
|
| 1652 | }
|
| 1653 |
|
| 1654 | static bool of_is_fwnode_add_links_supported(void)
|
| 1655 | {
|
| 1656 | static int is_supported = -1;
|
| 1657 |
|
| 1658 | if (!IS_ENABLED(CONFIG_X86))
|
| 1659 | return true;
|
| 1660 |
|
| 1661 | if (is_supported != -1)
|
| 1662 | return !!is_supported;
|
| 1663 |
|
| 1664 | is_supported = !((match_property_by_path("/soc", "compatible", "intel,ce4100-cp") >= 0) ||
|
| 1665 | (match_property_by_path("/", "architecture", "OLPC") >= 0));
|
| 1666 |
|
| 1667 | return !!is_supported;
|
| 1668 | }
|
| 1669 |
|
| 1670 | static int of_fwnode_add_links(struct fwnode_handle *fwnode)
|
| 1671 | {
|
| 1672 | const struct property *p;
|
| 1673 | struct device_node *con_np = to_of_node(fwnode);
|
| 1674 |
|
| 1675 | if (!of_is_fwnode_add_links_supported())
|
| 1676 | return 0;
|
| 1677 |
|
| 1678 | if (!con_np)
|
| 1679 | return -EINVAL;
|
| 1680 |
|
| 1681 | for_each_property_of_node(con_np, p)
|
| 1682 | of_link_property(con_np, p->name);
|
| 1683 |
|
| 1684 | return 0;
|
| 1685 | }
|
| 1686 |
|
| 1687 | const struct fwnode_operations of_fwnode_ops = {
|
| 1688 | .get = of_fwnode_get,
|
| 1689 | .put = of_fwnode_put,
|
| 1690 | .device_is_available = of_fwnode_device_is_available,
|
| 1691 | .device_get_match_data = of_fwnode_device_get_match_data,
|
| 1692 | .device_dma_supported = of_fwnode_device_dma_supported,
|
| 1693 | .device_get_dma_attr = of_fwnode_device_get_dma_attr,
|
| 1694 | .property_present = of_fwnode_property_present,
|
| 1695 | .property_read_bool = of_fwnode_property_read_bool,
|
| 1696 | .property_read_int_array = of_fwnode_property_read_int_array,
|
| 1697 | .property_read_string_array = of_fwnode_property_read_string_array,
|
| 1698 | .get_name = of_fwnode_get_name,
|
| 1699 | .get_name_prefix = of_fwnode_get_name_prefix,
|
| 1700 | .get_parent = of_fwnode_get_parent,
|
| 1701 | .get_next_child_node = of_fwnode_get_next_child_node,
|
| 1702 | .get_named_child_node = of_fwnode_get_named_child_node,
|
| 1703 | .get_reference_args = of_fwnode_get_reference_args,
|
| 1704 | .graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint,
|
| 1705 | .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint,
|
| 1706 | .graph_get_port_parent = of_fwnode_graph_get_port_parent,
|
| 1707 | .graph_parse_endpoint = of_fwnode_graph_parse_endpoint,
|
| 1708 | .iomap = of_fwnode_iomap,
|
| 1709 | .irq_get = of_fwnode_irq_get,
|
| 1710 | .add_links = of_fwnode_add_links,
|
| 1711 | };
|
| 1712 | EXPORT_SYMBOL_GPL(of_fwnode_ops);
|